@embedpdf/plugin-annotation 1.0.13 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +80 -43
- package/dist/index.js.map +1 -1
- package/dist/lib/helpers.d.ts +8 -2
- package/dist/lib/types.d.ts +44 -6
- package/dist/preact/adapter.d.ts +5 -0
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +267 -7
- package/dist/preact/index.js.map +1 -1
- package/dist/react/adapter.d.ts +5 -0
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +267 -7
- package/dist/react/index.js.map +1 -1
- package/dist/shared-preact/components/annotation-container.d.ts +3 -2
- package/dist/shared-preact/components/annotations/free-text-paint.d.ts +10 -0
- package/dist/shared-preact/components/annotations/free-text.d.ts +13 -0
- package/dist/shared-react/components/annotation-container.d.ts +3 -2
- package/dist/shared-react/components/annotations/free-text-paint.d.ts +10 -0
- package/dist/shared-react/components/annotations/free-text.d.ts +13 -0
- package/package.json +9 -9
package/dist/preact/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { usePlugin, useCapability } from "@embedpdf/core/preact";
|
|
2
|
-
import { AnnotationPlugin, patching, getAnnotationsByPageIndex, getSelectedAnnotationByPageIndex, isInk, isSquare, isCircle, isUnderline, isStrikeout, isSquiggly, isHighlight, isLine, isPolyline, isPolygon,
|
|
2
|
+
import { AnnotationPlugin, patching, getAnnotationsByPageIndex, getSelectedAnnotationByPageIndex, isInk, isSquare, isCircle, isUnderline, isStrikeout, isSquiggly, isHighlight, isLine, isPolyline, isPolygon, isFreeText } from "@embedpdf/plugin-annotation";
|
|
3
3
|
import { jsx, jsxs, Fragment as Fragment$1 } from "preact/jsx-runtime";
|
|
4
|
-
import { restoreOffset, rectEquals, PdfAnnotationBorderStyle, PdfAnnotationSubtype, expandRect, rectFromPoints, blendModeToCss, PdfBlendMode } from "@embedpdf/models";
|
|
4
|
+
import { restoreOffset, rectEquals, PdfAnnotationBorderStyle, PdfAnnotationSubtype, expandRect, rectFromPoints, textAlignmentToCss, standardFontCss, PdfVerticalAlignment, blendModeToCss, PdfBlendMode } from "@embedpdf/models";
|
|
5
5
|
import { usePointerHandlers } from "@embedpdf/plugin-interaction-manager/preact";
|
|
6
6
|
import { useSelectionCapability } from "@embedpdf/plugin-selection/preact";
|
|
7
7
|
import { Fragment } from "preact";
|
|
8
8
|
import { useState, useRef, useEffect, useLayoutEffect, useMemo, useCallback } from "preact/hooks";
|
|
9
9
|
const useAnnotationPlugin = () => usePlugin(AnnotationPlugin.id);
|
|
10
10
|
const useAnnotationCapability = () => useCapability(AnnotationPlugin.id);
|
|
11
|
+
const mapDoubleClick = (handler) => handler ? { onDblClick: handler } : {};
|
|
11
12
|
function getCounterRotation(rect, rotation) {
|
|
12
13
|
const { width: w, height: h } = rect.size;
|
|
13
14
|
switch (rotation % 4) {
|
|
@@ -338,6 +339,7 @@ function AnnotationContainer({
|
|
|
338
339
|
computeVertices,
|
|
339
340
|
computePatch,
|
|
340
341
|
selectionMenu,
|
|
342
|
+
onDoubleClick,
|
|
341
343
|
...props
|
|
342
344
|
}) {
|
|
343
345
|
const { provides: annotationProvides } = useAnnotationCapability();
|
|
@@ -376,6 +378,7 @@ function AnnotationContainer({
|
|
|
376
378
|
"div",
|
|
377
379
|
{
|
|
378
380
|
...rootHandlers,
|
|
381
|
+
...mapDoubleClick(onDoubleClick),
|
|
379
382
|
style: {
|
|
380
383
|
position: "absolute",
|
|
381
384
|
outline: isSelected ? "1px solid #007ACC" : "none",
|
|
@@ -386,6 +389,9 @@ function AnnotationContainer({
|
|
|
386
389
|
height: `${currentRect.size.height * scale}px`,
|
|
387
390
|
pointerEvents: isSelected ? "auto" : "none",
|
|
388
391
|
cursor: isSelected && isDraggable ? "move" : "default",
|
|
392
|
+
...isSelected && {
|
|
393
|
+
zIndex: 3
|
|
394
|
+
},
|
|
389
395
|
...style
|
|
390
396
|
},
|
|
391
397
|
...props,
|
|
@@ -1192,6 +1198,78 @@ const patchPolygon = (orig, ctx) => {
|
|
|
1192
1198
|
vertices: moved
|
|
1193
1199
|
};
|
|
1194
1200
|
};
|
|
1201
|
+
function FreeText({
|
|
1202
|
+
isSelected,
|
|
1203
|
+
isEditing,
|
|
1204
|
+
annotation,
|
|
1205
|
+
pageIndex,
|
|
1206
|
+
scale,
|
|
1207
|
+
onClick
|
|
1208
|
+
}) {
|
|
1209
|
+
const editorRef = useRef(null);
|
|
1210
|
+
const { provides: annotationProvides } = useAnnotationCapability();
|
|
1211
|
+
useEffect(() => {
|
|
1212
|
+
if (isEditing && editorRef.current) {
|
|
1213
|
+
const editor = editorRef.current;
|
|
1214
|
+
editor.focus();
|
|
1215
|
+
const selection = window.getSelection();
|
|
1216
|
+
if (selection) {
|
|
1217
|
+
const range = document.createRange();
|
|
1218
|
+
range.selectNodeContents(editor);
|
|
1219
|
+
range.collapse(false);
|
|
1220
|
+
selection.removeAllRanges();
|
|
1221
|
+
selection.addRange(range);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
}, [isEditing]);
|
|
1225
|
+
const handleBlur = () => {
|
|
1226
|
+
if (!annotationProvides) return;
|
|
1227
|
+
if (!editorRef.current) return;
|
|
1228
|
+
annotationProvides.updateAnnotation(pageIndex, annotation.localId, {
|
|
1229
|
+
contents: editorRef.current.innerText
|
|
1230
|
+
});
|
|
1231
|
+
};
|
|
1232
|
+
return /* @__PURE__ */ jsx(
|
|
1233
|
+
"div",
|
|
1234
|
+
{
|
|
1235
|
+
style: {
|
|
1236
|
+
position: "absolute",
|
|
1237
|
+
width: annotation.object.rect.size.width * scale,
|
|
1238
|
+
height: annotation.object.rect.size.height * scale,
|
|
1239
|
+
cursor: isSelected && !isEditing ? "move" : "default",
|
|
1240
|
+
pointerEvents: isSelected && !isEditing ? "none" : "auto",
|
|
1241
|
+
zIndex: 2
|
|
1242
|
+
},
|
|
1243
|
+
onPointerDown: onClick,
|
|
1244
|
+
children: /* @__PURE__ */ jsx(
|
|
1245
|
+
"span",
|
|
1246
|
+
{
|
|
1247
|
+
ref: editorRef,
|
|
1248
|
+
onBlur: handleBlur,
|
|
1249
|
+
style: {
|
|
1250
|
+
color: annotation.object.fontColor,
|
|
1251
|
+
fontSize: annotation.object.fontSize * scale,
|
|
1252
|
+
fontFamily: standardFontCss(annotation.object.fontFamily),
|
|
1253
|
+
textAlign: textAlignmentToCss(annotation.object.textAlign),
|
|
1254
|
+
flexDirection: "column",
|
|
1255
|
+
justifyContent: annotation.object.verticalAlign === PdfVerticalAlignment.Top ? "flex-start" : annotation.object.verticalAlign === PdfVerticalAlignment.Middle ? "center" : "flex-end",
|
|
1256
|
+
display: "flex",
|
|
1257
|
+
backgroundColor: annotation.object.backgroundColor,
|
|
1258
|
+
opacity: annotation.object.opacity,
|
|
1259
|
+
width: "100%",
|
|
1260
|
+
height: "100%",
|
|
1261
|
+
lineHeight: "1.18",
|
|
1262
|
+
overflow: "hidden",
|
|
1263
|
+
cursor: isEditing ? "text" : "pointer"
|
|
1264
|
+
},
|
|
1265
|
+
contentEditable: isEditing,
|
|
1266
|
+
suppressContentEditableWarning: true,
|
|
1267
|
+
children: annotation.object.contents
|
|
1268
|
+
}
|
|
1269
|
+
)
|
|
1270
|
+
}
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1195
1273
|
function Annotations(annotationsProps) {
|
|
1196
1274
|
const { pageIndex, scale, selectionMenu } = annotationsProps;
|
|
1197
1275
|
const { provides: annotationProvides } = useAnnotationCapability();
|
|
@@ -1199,6 +1277,7 @@ function Annotations(annotationsProps) {
|
|
|
1199
1277
|
const [annotations, setAnnotations] = useState([]);
|
|
1200
1278
|
const { register } = usePointerHandlers({ pageIndex });
|
|
1201
1279
|
const [selectionState, setSelectionState] = useState(null);
|
|
1280
|
+
const [editingId, setEditingId] = useState(null);
|
|
1202
1281
|
useEffect(() => {
|
|
1203
1282
|
if (annotationProvides) {
|
|
1204
1283
|
annotationProvides.onStateChange((state) => {
|
|
@@ -1212,6 +1291,7 @@ function Annotations(annotationsProps) {
|
|
|
1212
1291
|
onPointerDown: (_, pe) => {
|
|
1213
1292
|
if (pe.target === pe.currentTarget && annotationProvides) {
|
|
1214
1293
|
annotationProvides.deselectAnnotation();
|
|
1294
|
+
setEditingId(null);
|
|
1215
1295
|
}
|
|
1216
1296
|
}
|
|
1217
1297
|
}),
|
|
@@ -1223,6 +1303,7 @@ function Annotations(annotationsProps) {
|
|
|
1223
1303
|
if (annotationProvides && selectionProvides) {
|
|
1224
1304
|
annotationProvides.selectAnnotation(pageIndex, annotation.localId);
|
|
1225
1305
|
selectionProvides.clear();
|
|
1306
|
+
setEditingId(null);
|
|
1226
1307
|
}
|
|
1227
1308
|
},
|
|
1228
1309
|
[annotationProvides, selectionProvides, pageIndex]
|
|
@@ -1232,6 +1313,7 @@ function Annotations(annotationsProps) {
|
|
|
1232
1313
|
}, [register, handlers]);
|
|
1233
1314
|
return /* @__PURE__ */ jsx(Fragment$1, { children: annotations.map((annotation) => {
|
|
1234
1315
|
const isSelected = (selectionState == null ? void 0 : selectionState.localId) === annotation.localId;
|
|
1316
|
+
const isEditing = editingId === annotation.localId;
|
|
1235
1317
|
if (isInk(annotation)) {
|
|
1236
1318
|
return /* @__PURE__ */ jsx(
|
|
1237
1319
|
AnnotationContainer,
|
|
@@ -1547,6 +1629,42 @@ function Annotations(annotationsProps) {
|
|
|
1547
1629
|
annotation.localId
|
|
1548
1630
|
);
|
|
1549
1631
|
}
|
|
1632
|
+
if (isFreeText(annotation)) {
|
|
1633
|
+
return /* @__PURE__ */ jsx(
|
|
1634
|
+
AnnotationContainer,
|
|
1635
|
+
{
|
|
1636
|
+
trackedAnnotation: annotation,
|
|
1637
|
+
isSelected,
|
|
1638
|
+
isDraggable: true,
|
|
1639
|
+
isResizable: true,
|
|
1640
|
+
selectionMenu,
|
|
1641
|
+
outlineOffset: 6,
|
|
1642
|
+
onDoubleClick: (e) => {
|
|
1643
|
+
e.stopPropagation();
|
|
1644
|
+
setEditingId(annotation.localId);
|
|
1645
|
+
},
|
|
1646
|
+
style: {
|
|
1647
|
+
mixBlendMode: blendModeToCss(annotation.object.blendMode ?? PdfBlendMode.Normal)
|
|
1648
|
+
},
|
|
1649
|
+
...annotationsProps,
|
|
1650
|
+
children: (object) => /* @__PURE__ */ jsx(
|
|
1651
|
+
FreeText,
|
|
1652
|
+
{
|
|
1653
|
+
isSelected,
|
|
1654
|
+
isEditing,
|
|
1655
|
+
annotation: {
|
|
1656
|
+
...annotation,
|
|
1657
|
+
object
|
|
1658
|
+
},
|
|
1659
|
+
pageIndex,
|
|
1660
|
+
scale,
|
|
1661
|
+
onClick: (e) => handleClick(e, annotation)
|
|
1662
|
+
}
|
|
1663
|
+
)
|
|
1664
|
+
},
|
|
1665
|
+
annotation.localId
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1550
1668
|
return null;
|
|
1551
1669
|
}) });
|
|
1552
1670
|
}
|
|
@@ -1571,8 +1689,9 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
1571
1689
|
return off;
|
|
1572
1690
|
}, [annotationProvides]);
|
|
1573
1691
|
if (!boundingRect) return null;
|
|
1574
|
-
|
|
1575
|
-
|
|
1692
|
+
if (!activeTool.defaults) return null;
|
|
1693
|
+
switch (activeTool.defaults.subtype) {
|
|
1694
|
+
case PdfAnnotationSubtype.UNDERLINE:
|
|
1576
1695
|
return /* @__PURE__ */ jsx(
|
|
1577
1696
|
"div",
|
|
1578
1697
|
{
|
|
@@ -1593,7 +1712,7 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
1593
1712
|
)
|
|
1594
1713
|
}
|
|
1595
1714
|
);
|
|
1596
|
-
case
|
|
1715
|
+
case PdfAnnotationSubtype.HIGHLIGHT:
|
|
1597
1716
|
return /* @__PURE__ */ jsx(
|
|
1598
1717
|
"div",
|
|
1599
1718
|
{
|
|
@@ -1614,7 +1733,7 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
1614
1733
|
)
|
|
1615
1734
|
}
|
|
1616
1735
|
);
|
|
1617
|
-
case
|
|
1736
|
+
case PdfAnnotationSubtype.STRIKEOUT:
|
|
1618
1737
|
return /* @__PURE__ */ jsx(
|
|
1619
1738
|
"div",
|
|
1620
1739
|
{
|
|
@@ -1635,7 +1754,7 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
1635
1754
|
)
|
|
1636
1755
|
}
|
|
1637
1756
|
);
|
|
1638
|
-
case
|
|
1757
|
+
case PdfAnnotationSubtype.SQUIGGLY:
|
|
1639
1758
|
return /* @__PURE__ */ jsx(
|
|
1640
1759
|
"div",
|
|
1641
1760
|
{
|
|
@@ -2537,6 +2656,138 @@ const PolygonPaint = ({
|
|
|
2537
2656
|
}
|
|
2538
2657
|
);
|
|
2539
2658
|
};
|
|
2659
|
+
const FreeTextPaint = ({
|
|
2660
|
+
pageIndex,
|
|
2661
|
+
scale,
|
|
2662
|
+
pageWidth,
|
|
2663
|
+
pageHeight,
|
|
2664
|
+
cursor = "text"
|
|
2665
|
+
}) => {
|
|
2666
|
+
const { provides: annotationProvides } = useAnnotationCapability();
|
|
2667
|
+
const [activeTool, setActiveTool] = useState({ variantKey: null, defaults: null });
|
|
2668
|
+
useEffect(() => annotationProvides == null ? void 0 : annotationProvides.onActiveToolChange(setActiveTool), [annotationProvides]);
|
|
2669
|
+
if (!activeTool.defaults || activeTool.defaults.subtype !== PdfAnnotationSubtype.FREETEXT)
|
|
2670
|
+
return null;
|
|
2671
|
+
const toolFontColor = activeTool.defaults.fontColor ?? "#000000";
|
|
2672
|
+
const toolOpacity = activeTool.defaults.opacity ?? 1;
|
|
2673
|
+
const toolFontSize = activeTool.defaults.fontSize ?? 12;
|
|
2674
|
+
const toolFontFamily = activeTool.defaults.fontFamily;
|
|
2675
|
+
const toolBackgroundColor = activeTool.defaults.backgroundColor ?? "transparent";
|
|
2676
|
+
const toolTextAlign = activeTool.defaults.textAlign;
|
|
2677
|
+
const toolVerticalAlign = activeTool.defaults.verticalAlign;
|
|
2678
|
+
const toolContent = activeTool.defaults.content ?? "Insert text here";
|
|
2679
|
+
const { register } = usePointerHandlers({ modeId: "freeText", pageIndex });
|
|
2680
|
+
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
2681
|
+
const pageWidthPDF = pageWidth / scale;
|
|
2682
|
+
const pageHeightPDF = pageHeight / scale;
|
|
2683
|
+
const [start, setStart] = useState(null);
|
|
2684
|
+
const [current, setCurrent] = useState(null);
|
|
2685
|
+
const commitFreeText = (p1, p2) => {
|
|
2686
|
+
const minX2 = Math.min(p1.x, p2.x);
|
|
2687
|
+
const minY2 = Math.min(p1.y, p2.y);
|
|
2688
|
+
const maxX2 = Math.max(p1.x, p2.x);
|
|
2689
|
+
const maxY2 = Math.max(p1.y, p2.y);
|
|
2690
|
+
const w = maxX2 - minX2;
|
|
2691
|
+
const h = maxY2 - minY2;
|
|
2692
|
+
if (w < 1 || h < 1) return;
|
|
2693
|
+
const rect = {
|
|
2694
|
+
origin: { x: minX2, y: minY2 },
|
|
2695
|
+
size: { width: w, height: h }
|
|
2696
|
+
};
|
|
2697
|
+
const anno = {
|
|
2698
|
+
type: PdfAnnotationSubtype.FREETEXT,
|
|
2699
|
+
rect,
|
|
2700
|
+
contents: toolContent,
|
|
2701
|
+
fontColor: toolFontColor,
|
|
2702
|
+
fontSize: toolFontSize,
|
|
2703
|
+
fontFamily: toolFontFamily,
|
|
2704
|
+
opacity: toolOpacity,
|
|
2705
|
+
backgroundColor: toolBackgroundColor,
|
|
2706
|
+
textAlign: toolTextAlign,
|
|
2707
|
+
verticalAlign: toolVerticalAlign,
|
|
2708
|
+
pageIndex,
|
|
2709
|
+
id: Date.now() + Math.random()
|
|
2710
|
+
};
|
|
2711
|
+
annotationProvides.createAnnotation(pageIndex, anno);
|
|
2712
|
+
annotationProvides.setActiveVariant(null);
|
|
2713
|
+
annotationProvides.selectAnnotation(pageIndex, anno.id);
|
|
2714
|
+
};
|
|
2715
|
+
const handlers = useMemo(
|
|
2716
|
+
() => ({
|
|
2717
|
+
onPointerDown: (pos, evt) => {
|
|
2718
|
+
var _a, _b;
|
|
2719
|
+
const x = clamp(pos.x, 0, pageWidthPDF);
|
|
2720
|
+
const y = clamp(pos.y, 0, pageHeightPDF);
|
|
2721
|
+
setStart({ x, y });
|
|
2722
|
+
setCurrent({ x, y });
|
|
2723
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.setPointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
2724
|
+
},
|
|
2725
|
+
onPointerMove: (pos) => {
|
|
2726
|
+
if (!start) return;
|
|
2727
|
+
const x = clamp(pos.x, 0, pageWidthPDF);
|
|
2728
|
+
const y = clamp(pos.y, 0, pageHeightPDF);
|
|
2729
|
+
setCurrent({ x, y });
|
|
2730
|
+
},
|
|
2731
|
+
onPointerUp: (_, evt) => {
|
|
2732
|
+
var _a, _b;
|
|
2733
|
+
if (start && current && annotationProvides) {
|
|
2734
|
+
commitFreeText(start, current);
|
|
2735
|
+
}
|
|
2736
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.releasePointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
2737
|
+
setStart(null);
|
|
2738
|
+
setCurrent(null);
|
|
2739
|
+
},
|
|
2740
|
+
onPointerCancel: (_, evt) => {
|
|
2741
|
+
var _a, _b;
|
|
2742
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.releasePointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
2743
|
+
setStart(null);
|
|
2744
|
+
setCurrent(null);
|
|
2745
|
+
}
|
|
2746
|
+
}),
|
|
2747
|
+
[start, current, annotationProvides, pageWidthPDF, pageHeightPDF]
|
|
2748
|
+
);
|
|
2749
|
+
useEffect(() => register ? register(handlers) : void 0, [register, handlers]);
|
|
2750
|
+
if (!start || !current) return null;
|
|
2751
|
+
const minX = Math.min(start.x, current.x);
|
|
2752
|
+
const minY = Math.min(start.y, current.y);
|
|
2753
|
+
const maxX = Math.max(start.x, current.x);
|
|
2754
|
+
const maxY = Math.max(start.y, current.y);
|
|
2755
|
+
const dw = maxX - minX;
|
|
2756
|
+
const dh = maxY - minY;
|
|
2757
|
+
return /* @__PURE__ */ jsx(
|
|
2758
|
+
"svg",
|
|
2759
|
+
{
|
|
2760
|
+
style: {
|
|
2761
|
+
position: "absolute",
|
|
2762
|
+
left: minX * scale,
|
|
2763
|
+
top: minY * scale,
|
|
2764
|
+
width: dw * scale,
|
|
2765
|
+
height: dh * scale,
|
|
2766
|
+
pointerEvents: "none",
|
|
2767
|
+
zIndex: 2
|
|
2768
|
+
},
|
|
2769
|
+
width: dw * scale,
|
|
2770
|
+
height: dh * scale,
|
|
2771
|
+
viewBox: `0 0 ${dw} ${dh}`,
|
|
2772
|
+
children: /* @__PURE__ */ jsx(
|
|
2773
|
+
"rect",
|
|
2774
|
+
{
|
|
2775
|
+
x: 0,
|
|
2776
|
+
y: 0,
|
|
2777
|
+
width: dw,
|
|
2778
|
+
height: dh,
|
|
2779
|
+
fill: "transparent",
|
|
2780
|
+
style: {
|
|
2781
|
+
stroke: toolFontColor,
|
|
2782
|
+
strokeWidth: 1,
|
|
2783
|
+
strokeDasharray: "4,4",
|
|
2784
|
+
cursor
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
)
|
|
2788
|
+
}
|
|
2789
|
+
);
|
|
2790
|
+
};
|
|
2540
2791
|
function AnnotationLayer({
|
|
2541
2792
|
pageIndex,
|
|
2542
2793
|
scale,
|
|
@@ -2612,6 +2863,15 @@ function AnnotationLayer({
|
|
|
2612
2863
|
pageWidth,
|
|
2613
2864
|
pageHeight
|
|
2614
2865
|
}
|
|
2866
|
+
),
|
|
2867
|
+
/* @__PURE__ */ jsx(
|
|
2868
|
+
FreeTextPaint,
|
|
2869
|
+
{
|
|
2870
|
+
pageIndex,
|
|
2871
|
+
scale,
|
|
2872
|
+
pageWidth,
|
|
2873
|
+
pageHeight
|
|
2874
|
+
}
|
|
2615
2875
|
)
|
|
2616
2876
|
]
|
|
2617
2877
|
}
|