@pdfme/pdf-lib 1.18.1 → 1.18.4
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/README.md +11 -2
- package/cjs/api/PDFDocument.js +195 -225
- package/cjs/api/PDFDocument.js.map +1 -1
- package/cjs/api/PDFEmbeddedFile.js +30 -33
- package/cjs/api/PDFEmbeddedFile.js.map +1 -1
- package/cjs/api/PDFEmbeddedPage.js +5 -7
- package/cjs/api/PDFEmbeddedPage.js.map +1 -1
- package/cjs/api/PDFFont.js +6 -8
- package/cjs/api/PDFFont.js.map +1 -1
- package/cjs/api/PDFImage.js +14 -16
- package/cjs/api/PDFImage.js.map +1 -1
- package/cjs/api/PDFJavaScript.js +19 -22
- package/cjs/api/PDFJavaScript.js.map +1 -1
- package/cjs/api/PDFPage.d.ts +1 -0
- package/cjs/api/PDFPage.d.ts.map +1 -1
- package/cjs/api/PDFPage.js +30 -17
- package/cjs/api/PDFPage.js.map +1 -1
- package/cjs/api/PDFPageOptions.d.ts +15 -8
- package/cjs/api/PDFPageOptions.d.ts.map +1 -1
- package/cjs/api/PDFPageOptions.js.map +1 -1
- package/cjs/api/form/PDFField.js +1 -1
- package/cjs/api/form/PDFField.js.map +1 -1
- package/cjs/api/form/PDFForm.js +1 -1
- package/cjs/api/form/PDFForm.js.map +1 -1
- package/cjs/api/form/appearances.js +56 -16
- package/cjs/api/form/appearances.js.map +1 -1
- package/cjs/api/operations.d.ts +16 -0
- package/cjs/api/operations.d.ts.map +1 -1
- package/cjs/api/operations.js +53 -5
- package/cjs/api/operations.js.map +1 -1
- package/cjs/api/svg.d.ts +7 -1
- package/cjs/api/svg.d.ts.map +1 -1
- package/cjs/api/svg.js +332 -1016
- package/cjs/api/svg.js.map +1 -1
- package/cjs/core/PDFContext.js +11 -2
- package/cjs/core/PDFContext.js.map +1 -1
- package/cjs/core/embedders/CustomFontEmbedder.js +62 -74
- package/cjs/core/embedders/CustomFontEmbedder.js.map +1 -1
- package/cjs/core/embedders/CustomFontSubsetEmbedder.js +3 -5
- package/cjs/core/embedders/CustomFontSubsetEmbedder.js.map +1 -1
- package/cjs/core/embedders/FileEmbedder.js +30 -32
- package/cjs/core/embedders/FileEmbedder.js.map +1 -1
- package/cjs/core/embedders/JavaScriptEmbedder.js +12 -14
- package/cjs/core/embedders/JavaScriptEmbedder.js.map +1 -1
- package/cjs/core/embedders/JpegEmbedder.js +54 -59
- package/cjs/core/embedders/JpegEmbedder.js.map +1 -1
- package/cjs/core/embedders/PDFPageEmbedder.js +22 -26
- package/cjs/core/embedders/PDFPageEmbedder.js.map +1 -1
- package/cjs/core/embedders/PngEmbedder.js +20 -25
- package/cjs/core/embedders/PngEmbedder.js.map +1 -1
- package/cjs/core/parser/PDFObjectStreamParser.js +15 -17
- package/cjs/core/parser/PDFObjectStreamParser.js.map +1 -1
- package/cjs/core/parser/PDFParser.js +66 -74
- package/cjs/core/parser/PDFParser.js.map +1 -1
- package/cjs/core/writers/PDFStreamWriter.js +53 -55
- package/cjs/core/writers/PDFStreamWriter.js.map +1 -1
- package/cjs/core/writers/PDFWriter.js +62 -66
- package/cjs/core/writers/PDFWriter.js.map +1 -1
- package/cjs/types/index.d.ts +4 -4
- package/cjs/types/index.d.ts.map +1 -1
- package/dist/pdf-lib.esm.js +1153 -2590
- package/dist/pdf-lib.esm.js.map +1 -1
- package/dist/pdf-lib.esm.min.js +1 -15
- package/dist/pdf-lib.esm.min.js.map +1 -1
- package/dist/pdf-lib.js +1153 -2590
- package/dist/pdf-lib.js.map +1 -1
- package/dist/pdf-lib.min.js +1 -15
- package/dist/pdf-lib.min.js.map +1 -1
- package/es/api/PDFDocument.js +195 -226
- package/es/api/PDFDocument.js.map +1 -1
- package/es/api/PDFEmbeddedFile.js +30 -33
- package/es/api/PDFEmbeddedFile.js.map +1 -1
- package/es/api/PDFEmbeddedPage.js +5 -8
- package/es/api/PDFEmbeddedPage.js.map +1 -1
- package/es/api/PDFFont.js +6 -9
- package/es/api/PDFFont.js.map +1 -1
- package/es/api/PDFImage.js +14 -17
- package/es/api/PDFImage.js.map +1 -1
- package/es/api/PDFJavaScript.js +19 -22
- package/es/api/PDFJavaScript.js.map +1 -1
- package/es/api/PDFPage.d.ts +1 -0
- package/es/api/PDFPage.d.ts.map +1 -1
- package/es/api/PDFPage.js +30 -18
- package/es/api/PDFPage.js.map +1 -1
- package/es/api/PDFPageOptions.d.ts +15 -8
- package/es/api/PDFPageOptions.d.ts.map +1 -1
- package/es/api/PDFPageOptions.js.map +1 -1
- package/es/api/form/PDFField.js +1 -1
- package/es/api/form/PDFField.js.map +1 -1
- package/es/api/form/PDFForm.js +1 -1
- package/es/api/form/PDFForm.js.map +1 -1
- package/es/api/form/appearances.js +56 -16
- package/es/api/form/appearances.js.map +1 -1
- package/es/api/operations.d.ts +16 -0
- package/es/api/operations.d.ts.map +1 -1
- package/es/api/operations.js +54 -6
- package/es/api/operations.js.map +1 -1
- package/es/api/svg.d.ts +7 -1
- package/es/api/svg.d.ts.map +1 -1
- package/es/api/svg.js +333 -1017
- package/es/api/svg.js.map +1 -1
- package/es/core/PDFContext.js +11 -2
- package/es/core/PDFContext.js.map +1 -1
- package/es/core/embedders/CustomFontEmbedder.js +62 -75
- package/es/core/embedders/CustomFontEmbedder.js.map +1 -1
- package/es/core/embedders/CustomFontSubsetEmbedder.js +3 -6
- package/es/core/embedders/CustomFontSubsetEmbedder.js.map +1 -1
- package/es/core/embedders/FileEmbedder.js +30 -33
- package/es/core/embedders/FileEmbedder.js.map +1 -1
- package/es/core/embedders/JavaScriptEmbedder.js +12 -15
- package/es/core/embedders/JavaScriptEmbedder.js.map +1 -1
- package/es/core/embedders/JpegEmbedder.js +54 -59
- package/es/core/embedders/JpegEmbedder.js.map +1 -1
- package/es/core/embedders/PDFPageEmbedder.js +22 -27
- package/es/core/embedders/PDFPageEmbedder.js.map +1 -1
- package/es/core/embedders/PngEmbedder.js +20 -25
- package/es/core/embedders/PngEmbedder.js.map +1 -1
- package/es/core/parser/PDFObjectStreamParser.js +15 -18
- package/es/core/parser/PDFObjectStreamParser.js.map +1 -1
- package/es/core/parser/PDFParser.js +66 -75
- package/es/core/parser/PDFParser.js.map +1 -1
- package/es/core/writers/PDFStreamWriter.js +53 -56
- package/es/core/writers/PDFStreamWriter.js.map +1 -1
- package/es/core/writers/PDFWriter.js +62 -67
- package/es/core/writers/PDFWriter.js.map +1 -1
- package/es/types/index.d.ts +4 -4
- package/es/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api/PDFPage.ts +15 -0
- package/src/api/PDFPageOptions.ts +15 -8
- package/src/api/operations.ts +82 -8
- package/src/api/svg.ts +305 -1086
- package/src/types/index.ts +6 -1
- package/ts3.4/cjs/api/PDFPage.d.ts +1 -0
- package/ts3.4/cjs/api/PDFPageOptions.d.ts +15 -8
- package/ts3.4/cjs/api/operations.d.ts +16 -0
- package/ts3.4/cjs/api/svg.d.ts +7 -1
- package/ts3.4/cjs/types/index.d.ts +4 -4
- package/ts3.4/es/api/PDFPage.d.ts +1 -0
- package/ts3.4/es/api/PDFPageOptions.d.ts +15 -8
- package/ts3.4/es/api/operations.d.ts +16 -0
- package/ts3.4/es/api/svg.d.ts +7 -1
- package/ts3.4/es/types/index.d.ts +4 -4
package/dist/pdf-lib.esm.js
CHANGED
|
@@ -16043,13 +16043,22 @@ class PDFContext {
|
|
|
16043
16043
|
return PDFRawStream.of(this.obj(dict), typedArrayFor(contents));
|
|
16044
16044
|
}
|
|
16045
16045
|
flateStream(contents, dict = {}) {
|
|
16046
|
-
return this.stream(pako_1$1.deflate(typedArrayFor(contents)),
|
|
16046
|
+
return this.stream(pako_1$1.deflate(typedArrayFor(contents)), {
|
|
16047
|
+
...dict,
|
|
16048
|
+
Filter: 'FlateDecode',
|
|
16049
|
+
});
|
|
16047
16050
|
}
|
|
16048
16051
|
contentStream(operators, dict = {}) {
|
|
16049
16052
|
return PDFContentStream.of(this.obj(dict), operators);
|
|
16050
16053
|
}
|
|
16051
16054
|
formXObject(operators, dict = {}) {
|
|
16052
|
-
return this.contentStream(operators,
|
|
16055
|
+
return this.contentStream(operators, {
|
|
16056
|
+
BBox: this.obj([0, 0, 0, 0]),
|
|
16057
|
+
Matrix: this.obj([1, 0, 0, 1, 0, 0]),
|
|
16058
|
+
...dict,
|
|
16059
|
+
Type: 'XObject',
|
|
16060
|
+
Subtype: 'Form',
|
|
16061
|
+
});
|
|
16053
16062
|
}
|
|
16054
16063
|
/*
|
|
16055
16064
|
* Reference to PDFContentStream that contains a single PDFOperator: `q`.
|
|
@@ -16384,43 +16393,6 @@ class PDFObjectCopier {
|
|
|
16384
16393
|
}
|
|
16385
16394
|
PDFObjectCopier.for = (src, dest) => new PDFObjectCopier(src, dest);
|
|
16386
16395
|
|
|
16387
|
-
/*! *****************************************************************************
|
|
16388
|
-
Copyright (c) Microsoft Corporation.
|
|
16389
|
-
|
|
16390
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
16391
|
-
purpose with or without fee is hereby granted.
|
|
16392
|
-
|
|
16393
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
16394
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
16395
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
16396
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
16397
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16398
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
16399
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
16400
|
-
***************************************************************************** */
|
|
16401
|
-
|
|
16402
|
-
function __rest(s, e) {
|
|
16403
|
-
var t = {};
|
|
16404
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
16405
|
-
t[p] = s[p];
|
|
16406
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16407
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16408
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
16409
|
-
t[p[i]] = s[p[i]];
|
|
16410
|
-
}
|
|
16411
|
-
return t;
|
|
16412
|
-
}
|
|
16413
|
-
|
|
16414
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
16415
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
16416
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16417
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16418
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16419
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
16420
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
16421
|
-
});
|
|
16422
|
-
}
|
|
16423
|
-
|
|
16424
16396
|
/**
|
|
16425
16397
|
* Entries should be added using the [[addEntry]] and [[addDeletedEntry]]
|
|
16426
16398
|
* methods **in order of ascending object number**.
|
|
@@ -16666,52 +16638,50 @@ class PDFWriter {
|
|
|
16666
16638
|
this.context = context;
|
|
16667
16639
|
this.objectsPerTick = objectsPerTick;
|
|
16668
16640
|
}
|
|
16669
|
-
serializeToBuffer() {
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16674
|
-
|
|
16641
|
+
async serializeToBuffer() {
|
|
16642
|
+
const { size, header, indirectObjects, xref, trailerDict, trailer } = await this.computeBufferSize();
|
|
16643
|
+
let offset = 0;
|
|
16644
|
+
const buffer = new Uint8Array(size);
|
|
16645
|
+
offset += header.copyBytesInto(buffer, offset);
|
|
16646
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16647
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16648
|
+
for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
|
|
16649
|
+
const [ref, object] = indirectObjects[idx];
|
|
16650
|
+
const objectNumber = String(ref.objectNumber);
|
|
16651
|
+
offset += copyStringIntoBuffer(objectNumber, buffer, offset);
|
|
16652
|
+
buffer[offset++] = CharCodes$1.Space;
|
|
16653
|
+
const generationNumber = String(ref.generationNumber);
|
|
16654
|
+
offset += copyStringIntoBuffer(generationNumber, buffer, offset);
|
|
16655
|
+
buffer[offset++] = CharCodes$1.Space;
|
|
16656
|
+
buffer[offset++] = CharCodes$1.o;
|
|
16657
|
+
buffer[offset++] = CharCodes$1.b;
|
|
16658
|
+
buffer[offset++] = CharCodes$1.j;
|
|
16675
16659
|
buffer[offset++] = CharCodes$1.Newline;
|
|
16660
|
+
offset += object.copyBytesInto(buffer, offset);
|
|
16676
16661
|
buffer[offset++] = CharCodes$1.Newline;
|
|
16677
|
-
|
|
16678
|
-
|
|
16679
|
-
|
|
16680
|
-
|
|
16681
|
-
|
|
16682
|
-
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
if (this.shouldWaitForTick(n))
|
|
16701
|
-
yield waitForTick();
|
|
16702
|
-
}
|
|
16703
|
-
if (xref) {
|
|
16704
|
-
offset += xref.copyBytesInto(buffer, offset);
|
|
16705
|
-
buffer[offset++] = CharCodes$1.Newline;
|
|
16706
|
-
}
|
|
16707
|
-
if (trailerDict) {
|
|
16708
|
-
offset += trailerDict.copyBytesInto(buffer, offset);
|
|
16709
|
-
buffer[offset++] = CharCodes$1.Newline;
|
|
16710
|
-
buffer[offset++] = CharCodes$1.Newline;
|
|
16711
|
-
}
|
|
16712
|
-
offset += trailer.copyBytesInto(buffer, offset);
|
|
16713
|
-
return buffer;
|
|
16714
|
-
});
|
|
16662
|
+
buffer[offset++] = CharCodes$1.e;
|
|
16663
|
+
buffer[offset++] = CharCodes$1.n;
|
|
16664
|
+
buffer[offset++] = CharCodes$1.d;
|
|
16665
|
+
buffer[offset++] = CharCodes$1.o;
|
|
16666
|
+
buffer[offset++] = CharCodes$1.b;
|
|
16667
|
+
buffer[offset++] = CharCodes$1.j;
|
|
16668
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16669
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16670
|
+
const n = object instanceof PDFObjectStream ? object.getObjectsCount() : 1;
|
|
16671
|
+
if (this.shouldWaitForTick(n))
|
|
16672
|
+
await waitForTick();
|
|
16673
|
+
}
|
|
16674
|
+
if (xref) {
|
|
16675
|
+
offset += xref.copyBytesInto(buffer, offset);
|
|
16676
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16677
|
+
}
|
|
16678
|
+
if (trailerDict) {
|
|
16679
|
+
offset += trailerDict.copyBytesInto(buffer, offset);
|
|
16680
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16681
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16682
|
+
}
|
|
16683
|
+
offset += trailer.copyBytesInto(buffer, offset);
|
|
16684
|
+
return buffer;
|
|
16715
16685
|
}
|
|
16716
16686
|
computeIndirectObjectSize([ref, object]) {
|
|
16717
16687
|
const refSize = ref.sizeInBytes() + 3; // 'R' -> 'obj\n'
|
|
@@ -16727,28 +16697,26 @@ class PDFWriter {
|
|
|
16727
16697
|
ID: this.context.trailerInfo.ID,
|
|
16728
16698
|
});
|
|
16729
16699
|
}
|
|
16730
|
-
computeBufferSize() {
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
|
|
16740
|
-
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
16749
|
-
|
|
16750
|
-
return { size, header, indirectObjects, xref, trailerDict, trailer };
|
|
16751
|
-
});
|
|
16700
|
+
async computeBufferSize() {
|
|
16701
|
+
const header = PDFHeader.forVersion(1, 7);
|
|
16702
|
+
let size = header.sizeInBytes() + 2;
|
|
16703
|
+
const xref = PDFCrossRefSection.create();
|
|
16704
|
+
const indirectObjects = this.context.enumerateIndirectObjects();
|
|
16705
|
+
for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
|
|
16706
|
+
const indirectObject = indirectObjects[idx];
|
|
16707
|
+
const [ref] = indirectObject;
|
|
16708
|
+
xref.addEntry(ref, size);
|
|
16709
|
+
size += this.computeIndirectObjectSize(indirectObject);
|
|
16710
|
+
if (this.shouldWaitForTick(1))
|
|
16711
|
+
await waitForTick();
|
|
16712
|
+
}
|
|
16713
|
+
const xrefOffset = size;
|
|
16714
|
+
size += xref.sizeInBytes() + 1; // '\n'
|
|
16715
|
+
const trailerDict = PDFTrailerDict.of(this.createTrailerDict());
|
|
16716
|
+
size += trailerDict.sizeInBytes() + 2; // '\n\n'
|
|
16717
|
+
const trailer = PDFTrailer.forLastCrossRefSectionOffset(xrefOffset);
|
|
16718
|
+
size += trailer.sizeInBytes();
|
|
16719
|
+
return { size, header, indirectObjects, xref, trailerDict, trailer };
|
|
16752
16720
|
}
|
|
16753
16721
|
}
|
|
16754
16722
|
PDFWriter.forContext = (context, objectsPerTick) => new PDFWriter(context, objectsPerTick);
|
|
@@ -16953,63 +16921,61 @@ class PDFStreamWriter extends PDFWriter {
|
|
|
16953
16921
|
this.encodeStreams = encodeStreams;
|
|
16954
16922
|
this.objectsPerStream = objectsPerStream;
|
|
16955
16923
|
}
|
|
16956
|
-
computeBufferSize() {
|
|
16957
|
-
|
|
16958
|
-
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
16967
|
-
|
|
16968
|
-
|
|
16969
|
-
|
|
16970
|
-
|
|
16971
|
-
|
|
16972
|
-
|
|
16973
|
-
|
|
16974
|
-
uncompressedObjects.push(indirectObject);
|
|
16975
|
-
xrefStream.addUncompressedEntry(ref, size);
|
|
16976
|
-
size += this.computeIndirectObjectSize(indirectObject);
|
|
16977
|
-
if (this.shouldWaitForTick(1))
|
|
16978
|
-
yield waitForTick();
|
|
16979
|
-
}
|
|
16980
|
-
else {
|
|
16981
|
-
let chunk = last(compressedObjects);
|
|
16982
|
-
let objectStreamRef = last(objectStreamRefs);
|
|
16983
|
-
if (!chunk || chunk.length % this.objectsPerStream === 0) {
|
|
16984
|
-
chunk = [];
|
|
16985
|
-
compressedObjects.push(chunk);
|
|
16986
|
-
objectStreamRef = PDFRef.of(objectNumber++);
|
|
16987
|
-
objectStreamRefs.push(objectStreamRef);
|
|
16988
|
-
}
|
|
16989
|
-
xrefStream.addCompressedEntry(ref, objectStreamRef, chunk.length);
|
|
16990
|
-
chunk.push(indirectObject);
|
|
16991
|
-
}
|
|
16992
|
-
}
|
|
16993
|
-
for (let idx = 0, len = compressedObjects.length; idx < len; idx++) {
|
|
16994
|
-
const chunk = compressedObjects[idx];
|
|
16995
|
-
const ref = objectStreamRefs[idx];
|
|
16996
|
-
const objectStream = PDFObjectStream.withContextAndObjects(this.context, chunk, this.encodeStreams);
|
|
16924
|
+
async computeBufferSize() {
|
|
16925
|
+
let objectNumber = this.context.largestObjectNumber + 1;
|
|
16926
|
+
const header = PDFHeader.forVersion(1, 7);
|
|
16927
|
+
let size = header.sizeInBytes() + 2;
|
|
16928
|
+
const xrefStream = PDFCrossRefStream.create(this.createTrailerDict(), this.encodeStreams);
|
|
16929
|
+
const uncompressedObjects = [];
|
|
16930
|
+
const compressedObjects = [];
|
|
16931
|
+
const objectStreamRefs = [];
|
|
16932
|
+
const indirectObjects = this.context.enumerateIndirectObjects();
|
|
16933
|
+
for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
|
|
16934
|
+
const indirectObject = indirectObjects[idx];
|
|
16935
|
+
const [ref, object] = indirectObject;
|
|
16936
|
+
const shouldNotCompress = ref === this.context.trailerInfo.Encrypt ||
|
|
16937
|
+
object instanceof PDFStream ||
|
|
16938
|
+
object instanceof PDFInvalidObject ||
|
|
16939
|
+
ref.generationNumber !== 0;
|
|
16940
|
+
if (shouldNotCompress) {
|
|
16941
|
+
uncompressedObjects.push(indirectObject);
|
|
16997
16942
|
xrefStream.addUncompressedEntry(ref, size);
|
|
16998
|
-
size += this.computeIndirectObjectSize(
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
|
|
17002
|
-
|
|
17003
|
-
|
|
17004
|
-
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
|
|
17010
|
-
|
|
17011
|
-
|
|
17012
|
-
|
|
16943
|
+
size += this.computeIndirectObjectSize(indirectObject);
|
|
16944
|
+
if (this.shouldWaitForTick(1))
|
|
16945
|
+
await waitForTick();
|
|
16946
|
+
}
|
|
16947
|
+
else {
|
|
16948
|
+
let chunk = last(compressedObjects);
|
|
16949
|
+
let objectStreamRef = last(objectStreamRefs);
|
|
16950
|
+
if (!chunk || chunk.length % this.objectsPerStream === 0) {
|
|
16951
|
+
chunk = [];
|
|
16952
|
+
compressedObjects.push(chunk);
|
|
16953
|
+
objectStreamRef = PDFRef.of(objectNumber++);
|
|
16954
|
+
objectStreamRefs.push(objectStreamRef);
|
|
16955
|
+
}
|
|
16956
|
+
xrefStream.addCompressedEntry(ref, objectStreamRef, chunk.length);
|
|
16957
|
+
chunk.push(indirectObject);
|
|
16958
|
+
}
|
|
16959
|
+
}
|
|
16960
|
+
for (let idx = 0, len = compressedObjects.length; idx < len; idx++) {
|
|
16961
|
+
const chunk = compressedObjects[idx];
|
|
16962
|
+
const ref = objectStreamRefs[idx];
|
|
16963
|
+
const objectStream = PDFObjectStream.withContextAndObjects(this.context, chunk, this.encodeStreams);
|
|
16964
|
+
xrefStream.addUncompressedEntry(ref, size);
|
|
16965
|
+
size += this.computeIndirectObjectSize([ref, objectStream]);
|
|
16966
|
+
uncompressedObjects.push([ref, objectStream]);
|
|
16967
|
+
if (this.shouldWaitForTick(chunk.length))
|
|
16968
|
+
await waitForTick();
|
|
16969
|
+
}
|
|
16970
|
+
const xrefStreamRef = PDFRef.of(objectNumber++);
|
|
16971
|
+
xrefStream.dict.set(PDFName.of('Size'), PDFNumber.of(objectNumber));
|
|
16972
|
+
xrefStream.addUncompressedEntry(xrefStreamRef, size);
|
|
16973
|
+
const xrefOffset = size;
|
|
16974
|
+
size += this.computeIndirectObjectSize([xrefStreamRef, xrefStream]);
|
|
16975
|
+
uncompressedObjects.push([xrefStreamRef, xrefStream]);
|
|
16976
|
+
const trailer = PDFTrailer.forLastCrossRefSectionOffset(xrefOffset);
|
|
16977
|
+
size += trailer.sizeInBytes();
|
|
16978
|
+
return { size, header, indirectObjects: uncompressedObjects, trailer };
|
|
17013
16979
|
}
|
|
17014
16980
|
}
|
|
17015
16981
|
PDFStreamWriter.forContext = (context, objectsPerTick, encodeStreams = true, objectsPerStream = 50) => new PDFStreamWriter(context, objectsPerTick, encodeStreams, objectsPerStream);
|
|
@@ -17380,11 +17346,9 @@ class CustomFontEmbedder {
|
|
|
17380
17346
|
this.baseFontName = '';
|
|
17381
17347
|
this.glyphCache = Cache.populatedBy(this.allGlyphsInFontSortedById);
|
|
17382
17348
|
}
|
|
17383
|
-
static for(fontkit, fontData, customName, fontFeatures) {
|
|
17384
|
-
|
|
17385
|
-
|
|
17386
|
-
return new CustomFontEmbedder(font, fontData, customName, fontFeatures);
|
|
17387
|
-
});
|
|
17349
|
+
static async for(fontkit, fontData, customName, fontFeatures) {
|
|
17350
|
+
const font = await fontkit.create(fontData);
|
|
17351
|
+
return new CustomFontEmbedder(font, fontData, customName, fontFeatures);
|
|
17388
17352
|
}
|
|
17389
17353
|
/**
|
|
17390
17354
|
* Encode the JavaScript string into this font. (JavaScript encodes strings in
|
|
@@ -17430,85 +17394,75 @@ class CustomFontEmbedder {
|
|
|
17430
17394
|
this.customName || context.addRandomSuffix(this.fontName);
|
|
17431
17395
|
return this.embedFontDict(context, ref);
|
|
17432
17396
|
}
|
|
17433
|
-
embedFontDict(context, ref) {
|
|
17434
|
-
|
|
17435
|
-
|
|
17436
|
-
|
|
17437
|
-
|
|
17438
|
-
|
|
17439
|
-
|
|
17440
|
-
|
|
17441
|
-
|
|
17442
|
-
|
|
17443
|
-
ToUnicode: unicodeCMapRef,
|
|
17444
|
-
});
|
|
17445
|
-
if (ref) {
|
|
17446
|
-
context.assign(ref, fontDict);
|
|
17447
|
-
return ref;
|
|
17448
|
-
}
|
|
17449
|
-
else {
|
|
17450
|
-
return context.register(fontDict);
|
|
17451
|
-
}
|
|
17397
|
+
async embedFontDict(context, ref) {
|
|
17398
|
+
const cidFontDictRef = await this.embedCIDFontDict(context);
|
|
17399
|
+
const unicodeCMapRef = this.embedUnicodeCmap(context);
|
|
17400
|
+
const fontDict = context.obj({
|
|
17401
|
+
Type: 'Font',
|
|
17402
|
+
Subtype: 'Type0',
|
|
17403
|
+
BaseFont: this.baseFontName,
|
|
17404
|
+
Encoding: 'Identity-H',
|
|
17405
|
+
DescendantFonts: [cidFontDictRef],
|
|
17406
|
+
ToUnicode: unicodeCMapRef,
|
|
17452
17407
|
});
|
|
17408
|
+
if (ref) {
|
|
17409
|
+
context.assign(ref, fontDict);
|
|
17410
|
+
return ref;
|
|
17411
|
+
}
|
|
17412
|
+
else {
|
|
17413
|
+
return context.register(fontDict);
|
|
17414
|
+
}
|
|
17453
17415
|
}
|
|
17454
17416
|
isCFF() {
|
|
17455
17417
|
return this.font.cff;
|
|
17456
17418
|
}
|
|
17457
|
-
embedCIDFontDict(context) {
|
|
17458
|
-
|
|
17459
|
-
|
|
17460
|
-
|
|
17461
|
-
|
|
17462
|
-
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
|
|
17466
|
-
|
|
17467
|
-
|
|
17468
|
-
|
|
17469
|
-
|
|
17470
|
-
|
|
17471
|
-
W: this.computeWidths(),
|
|
17472
|
-
});
|
|
17473
|
-
return context.register(cidFontDict);
|
|
17419
|
+
async embedCIDFontDict(context) {
|
|
17420
|
+
const fontDescriptorRef = await this.embedFontDescriptor(context);
|
|
17421
|
+
const cidFontDict = context.obj({
|
|
17422
|
+
Type: 'Font',
|
|
17423
|
+
Subtype: this.isCFF() ? 'CIDFontType0' : 'CIDFontType2',
|
|
17424
|
+
CIDToGIDMap: 'Identity',
|
|
17425
|
+
BaseFont: this.baseFontName,
|
|
17426
|
+
CIDSystemInfo: {
|
|
17427
|
+
Registry: PDFString.of('Adobe'),
|
|
17428
|
+
Ordering: PDFString.of('Identity'),
|
|
17429
|
+
Supplement: 0,
|
|
17430
|
+
},
|
|
17431
|
+
FontDescriptor: fontDescriptorRef,
|
|
17432
|
+
W: this.computeWidths(),
|
|
17474
17433
|
});
|
|
17475
|
-
|
|
17476
|
-
|
|
17477
|
-
|
|
17478
|
-
|
|
17479
|
-
|
|
17480
|
-
|
|
17481
|
-
|
|
17482
|
-
|
|
17483
|
-
|
|
17484
|
-
|
|
17485
|
-
|
|
17486
|
-
|
|
17487
|
-
|
|
17488
|
-
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
|
|
17492
|
-
|
|
17493
|
-
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
});
|
|
17497
|
-
return context.register(fontDescriptor);
|
|
17434
|
+
return context.register(cidFontDict);
|
|
17435
|
+
}
|
|
17436
|
+
async embedFontDescriptor(context) {
|
|
17437
|
+
const fontStreamRef = await this.embedFontStream(context);
|
|
17438
|
+
const { scale } = this;
|
|
17439
|
+
const { italicAngle, ascent, descent, capHeight, xHeight } = this.font;
|
|
17440
|
+
const { minX, minY, maxX, maxY } = this.font.bbox;
|
|
17441
|
+
const fontDescriptor = context.obj({
|
|
17442
|
+
Type: 'FontDescriptor',
|
|
17443
|
+
FontName: this.baseFontName,
|
|
17444
|
+
Flags: deriveFontFlags(this.font),
|
|
17445
|
+
FontBBox: [minX * scale, minY * scale, maxX * scale, maxY * scale],
|
|
17446
|
+
ItalicAngle: italicAngle,
|
|
17447
|
+
Ascent: ascent * scale,
|
|
17448
|
+
Descent: descent * scale,
|
|
17449
|
+
CapHeight: (capHeight || ascent) * scale,
|
|
17450
|
+
XHeight: (xHeight || 0) * scale,
|
|
17451
|
+
// Not sure how to compute/find this, nor is anybody else really:
|
|
17452
|
+
// https://stackoverflow.com/questions/35485179/stemv-value-of-the-truetype-font
|
|
17453
|
+
StemV: 0,
|
|
17454
|
+
[this.isCFF() ? 'FontFile3' : 'FontFile2']: fontStreamRef,
|
|
17498
17455
|
});
|
|
17456
|
+
return context.register(fontDescriptor);
|
|
17499
17457
|
}
|
|
17500
|
-
serializeFont() {
|
|
17501
|
-
return
|
|
17502
|
-
return this.fontData;
|
|
17503
|
-
});
|
|
17458
|
+
async serializeFont() {
|
|
17459
|
+
return this.fontData;
|
|
17504
17460
|
}
|
|
17505
|
-
embedFontStream(context) {
|
|
17506
|
-
|
|
17507
|
-
|
|
17508
|
-
Subtype: this.isCFF() ? 'CIDFontType0C' : undefined,
|
|
17509
|
-
});
|
|
17510
|
-
return context.register(fontStream);
|
|
17461
|
+
async embedFontStream(context) {
|
|
17462
|
+
const fontStream = context.flateStream(await this.serializeFont(), {
|
|
17463
|
+
Subtype: this.isCFF() ? 'CIDFontType0C' : undefined,
|
|
17511
17464
|
});
|
|
17465
|
+
return context.register(fontStream);
|
|
17512
17466
|
}
|
|
17513
17467
|
embedUnicodeCmap(context) {
|
|
17514
17468
|
const cmap = createCmap(this.glyphCache.access(), this.glyphId.bind(this));
|
|
@@ -17555,11 +17509,9 @@ class CustomFontSubsetEmbedder extends CustomFontEmbedder {
|
|
|
17555
17509
|
this.glyphCache = Cache.populatedBy(() => this.glyphs);
|
|
17556
17510
|
this.glyphIdMap = new Map();
|
|
17557
17511
|
}
|
|
17558
|
-
static for(fontkit, fontData, customFontName, fontFeatures) {
|
|
17559
|
-
|
|
17560
|
-
|
|
17561
|
-
return new CustomFontSubsetEmbedder(font, fontData, customFontName, fontFeatures);
|
|
17562
|
-
});
|
|
17512
|
+
static async for(fontkit, fontData, customFontName, fontFeatures) {
|
|
17513
|
+
const font = await fontkit.create(fontData);
|
|
17514
|
+
return new CustomFontSubsetEmbedder(font, fontData, customFontName, fontFeatures);
|
|
17563
17515
|
}
|
|
17564
17516
|
encodeText(text) {
|
|
17565
17517
|
const { glyphs } = this.font.layout(text, this.fontFeatures);
|
|
@@ -17630,39 +17582,37 @@ class FileEmbedder {
|
|
|
17630
17582
|
static for(bytes, fileName, options = {}) {
|
|
17631
17583
|
return new FileEmbedder(bytes, fileName, options);
|
|
17632
17584
|
}
|
|
17633
|
-
embedIntoContext(context, ref) {
|
|
17634
|
-
|
|
17635
|
-
|
|
17636
|
-
|
|
17637
|
-
|
|
17638
|
-
|
|
17639
|
-
|
|
17640
|
-
|
|
17641
|
-
|
|
17642
|
-
|
|
17643
|
-
|
|
17644
|
-
|
|
17645
|
-
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
17649
|
-
|
|
17650
|
-
|
|
17651
|
-
|
|
17652
|
-
|
|
17653
|
-
|
|
17654
|
-
|
|
17655
|
-
|
|
17656
|
-
AFRelationship: afRelationship !== null && afRelationship !== void 0 ? afRelationship : undefined,
|
|
17657
|
-
});
|
|
17658
|
-
if (ref) {
|
|
17659
|
-
context.assign(ref, fileSpecDict);
|
|
17660
|
-
return ref;
|
|
17661
|
-
}
|
|
17662
|
-
else {
|
|
17663
|
-
return context.register(fileSpecDict);
|
|
17664
|
-
}
|
|
17585
|
+
async embedIntoContext(context, ref) {
|
|
17586
|
+
const { mimeType, description, creationDate, modificationDate, afRelationship, } = this.options;
|
|
17587
|
+
const embeddedFileStream = context.flateStream(this.fileData, {
|
|
17588
|
+
Type: 'EmbeddedFile',
|
|
17589
|
+
Subtype: mimeType !== null && mimeType !== void 0 ? mimeType : undefined,
|
|
17590
|
+
Params: {
|
|
17591
|
+
Size: this.fileData.length,
|
|
17592
|
+
CreationDate: creationDate
|
|
17593
|
+
? PDFString.fromDate(creationDate)
|
|
17594
|
+
: undefined,
|
|
17595
|
+
ModDate: modificationDate
|
|
17596
|
+
? PDFString.fromDate(modificationDate)
|
|
17597
|
+
: undefined,
|
|
17598
|
+
},
|
|
17599
|
+
});
|
|
17600
|
+
const embeddedFileStreamRef = context.register(embeddedFileStream);
|
|
17601
|
+
const fileSpecDict = context.obj({
|
|
17602
|
+
Type: 'Filespec',
|
|
17603
|
+
F: PDFString.of(this.fileName),
|
|
17604
|
+
UF: PDFHexString.fromText(this.fileName),
|
|
17605
|
+
EF: { F: embeddedFileStreamRef },
|
|
17606
|
+
Desc: description ? PDFHexString.fromText(description) : undefined,
|
|
17607
|
+
AFRelationship: afRelationship !== null && afRelationship !== void 0 ? afRelationship : undefined,
|
|
17665
17608
|
});
|
|
17609
|
+
if (ref) {
|
|
17610
|
+
context.assign(ref, fileSpecDict);
|
|
17611
|
+
return ref;
|
|
17612
|
+
}
|
|
17613
|
+
else {
|
|
17614
|
+
return context.register(fileSpecDict);
|
|
17615
|
+
}
|
|
17666
17616
|
}
|
|
17667
17617
|
}
|
|
17668
17618
|
|
|
@@ -17698,67 +17648,63 @@ class JpegEmbedder {
|
|
|
17698
17648
|
this.height = height;
|
|
17699
17649
|
this.colorSpace = colorSpace;
|
|
17700
17650
|
}
|
|
17701
|
-
static for(imageData) {
|
|
17702
|
-
|
|
17703
|
-
|
|
17704
|
-
|
|
17705
|
-
|
|
17706
|
-
|
|
17707
|
-
|
|
17708
|
-
|
|
17709
|
-
|
|
17710
|
-
marker = dataView.getUint16(pos);
|
|
17711
|
-
pos += 2;
|
|
17712
|
-
if (MARKERS.includes(marker))
|
|
17713
|
-
break;
|
|
17714
|
-
pos += dataView.getUint16(pos);
|
|
17715
|
-
}
|
|
17716
|
-
if (!MARKERS.includes(marker))
|
|
17717
|
-
throw new Error('Invalid JPEG');
|
|
17718
|
-
pos += 2;
|
|
17719
|
-
const bitsPerComponent = dataView.getUint8(pos++);
|
|
17720
|
-
const height = dataView.getUint16(pos);
|
|
17651
|
+
static async for(imageData) {
|
|
17652
|
+
const dataView = new DataView(imageData.buffer);
|
|
17653
|
+
const soi = dataView.getUint16(0);
|
|
17654
|
+
if (soi !== 0xffd8)
|
|
17655
|
+
throw new Error('SOI not found in JPEG');
|
|
17656
|
+
let pos = 2;
|
|
17657
|
+
let marker;
|
|
17658
|
+
while (pos < dataView.byteLength) {
|
|
17659
|
+
marker = dataView.getUint16(pos);
|
|
17721
17660
|
pos += 2;
|
|
17722
|
-
|
|
17723
|
-
|
|
17724
|
-
|
|
17725
|
-
|
|
17726
|
-
|
|
17727
|
-
|
|
17728
|
-
|
|
17729
|
-
|
|
17730
|
-
|
|
17731
|
-
|
|
17732
|
-
|
|
17733
|
-
|
|
17734
|
-
|
|
17735
|
-
|
|
17736
|
-
|
|
17737
|
-
|
|
17738
|
-
|
|
17739
|
-
|
|
17740
|
-
|
|
17741
|
-
|
|
17742
|
-
|
|
17743
|
-
|
|
17744
|
-
|
|
17745
|
-
|
|
17746
|
-
|
|
17747
|
-
|
|
17748
|
-
|
|
17749
|
-
|
|
17750
|
-
|
|
17751
|
-
|
|
17752
|
-
|
|
17753
|
-
|
|
17754
|
-
|
|
17755
|
-
|
|
17756
|
-
|
|
17757
|
-
|
|
17758
|
-
|
|
17759
|
-
|
|
17760
|
-
|
|
17661
|
+
if (MARKERS.includes(marker))
|
|
17662
|
+
break;
|
|
17663
|
+
pos += dataView.getUint16(pos);
|
|
17664
|
+
}
|
|
17665
|
+
if (!MARKERS.includes(marker))
|
|
17666
|
+
throw new Error('Invalid JPEG');
|
|
17667
|
+
pos += 2;
|
|
17668
|
+
const bitsPerComponent = dataView.getUint8(pos++);
|
|
17669
|
+
const height = dataView.getUint16(pos);
|
|
17670
|
+
pos += 2;
|
|
17671
|
+
const width = dataView.getUint16(pos);
|
|
17672
|
+
pos += 2;
|
|
17673
|
+
const channelByte = dataView.getUint8(pos++);
|
|
17674
|
+
const channelName = ChannelToColorSpace[channelByte];
|
|
17675
|
+
if (!channelName)
|
|
17676
|
+
throw new Error('Unknown JPEG channel.');
|
|
17677
|
+
const colorSpace = channelName;
|
|
17678
|
+
return new JpegEmbedder(imageData, bitsPerComponent, width, height, colorSpace);
|
|
17679
|
+
}
|
|
17680
|
+
async embedIntoContext(context, ref) {
|
|
17681
|
+
const xObject = context.stream(this.imageData, {
|
|
17682
|
+
Type: 'XObject',
|
|
17683
|
+
Subtype: 'Image',
|
|
17684
|
+
BitsPerComponent: this.bitsPerComponent,
|
|
17685
|
+
Width: this.width,
|
|
17686
|
+
Height: this.height,
|
|
17687
|
+
ColorSpace: this.colorSpace,
|
|
17688
|
+
Filter: 'DCTDecode',
|
|
17689
|
+
// CMYK JPEG streams in PDF are typically stored complemented,
|
|
17690
|
+
// with 1 as 'off' and 0 as 'on' (PDF 32000-1:2008, 8.6.4.4).
|
|
17691
|
+
//
|
|
17692
|
+
// Standalone CMYK JPEG (usually exported by Photoshop) are
|
|
17693
|
+
// stored inverse, with 0 as 'off' and 1 as 'on', like RGB.
|
|
17694
|
+
//
|
|
17695
|
+
// Applying a swap here as a hedge that most bytes passing
|
|
17696
|
+
// through this method will benefit from it.
|
|
17697
|
+
Decode: this.colorSpace === ColorSpace.DeviceCMYK
|
|
17698
|
+
? [1, 0, 1, 0, 1, 0, 1, 0]
|
|
17699
|
+
: undefined,
|
|
17761
17700
|
});
|
|
17701
|
+
if (ref) {
|
|
17702
|
+
context.assign(ref, xObject);
|
|
17703
|
+
return ref;
|
|
17704
|
+
}
|
|
17705
|
+
else {
|
|
17706
|
+
return context.register(xObject);
|
|
17707
|
+
}
|
|
17762
17708
|
}
|
|
17763
17709
|
}
|
|
17764
17710
|
|
|
@@ -25644,32 +25590,28 @@ class PngEmbedder {
|
|
|
25644
25590
|
this.height = png.height;
|
|
25645
25591
|
this.colorSpace = 'DeviceRGB';
|
|
25646
25592
|
}
|
|
25647
|
-
static for(imageData) {
|
|
25648
|
-
|
|
25649
|
-
|
|
25650
|
-
return new PngEmbedder(png);
|
|
25651
|
-
});
|
|
25593
|
+
static async for(imageData) {
|
|
25594
|
+
const png = PNG.load(imageData);
|
|
25595
|
+
return new PngEmbedder(png);
|
|
25652
25596
|
}
|
|
25653
|
-
embedIntoContext(context, ref) {
|
|
25654
|
-
|
|
25655
|
-
|
|
25656
|
-
|
|
25657
|
-
|
|
25658
|
-
|
|
25659
|
-
|
|
25660
|
-
|
|
25661
|
-
|
|
25662
|
-
|
|
25663
|
-
SMask,
|
|
25664
|
-
});
|
|
25665
|
-
if (ref) {
|
|
25666
|
-
context.assign(ref, xObject);
|
|
25667
|
-
return ref;
|
|
25668
|
-
}
|
|
25669
|
-
else {
|
|
25670
|
-
return context.register(xObject);
|
|
25671
|
-
}
|
|
25597
|
+
async embedIntoContext(context, ref) {
|
|
25598
|
+
const SMask = this.embedAlphaChannel(context);
|
|
25599
|
+
const xObject = context.flateStream(this.image.rgbChannel, {
|
|
25600
|
+
Type: 'XObject',
|
|
25601
|
+
Subtype: 'Image',
|
|
25602
|
+
BitsPerComponent: this.image.bitsPerComponent,
|
|
25603
|
+
Width: this.image.width,
|
|
25604
|
+
Height: this.image.height,
|
|
25605
|
+
ColorSpace: this.colorSpace,
|
|
25606
|
+
SMask,
|
|
25672
25607
|
});
|
|
25608
|
+
if (ref) {
|
|
25609
|
+
context.assign(ref, xObject);
|
|
25610
|
+
return ref;
|
|
25611
|
+
}
|
|
25612
|
+
else {
|
|
25613
|
+
return context.register(xObject);
|
|
25614
|
+
}
|
|
25673
25615
|
}
|
|
25674
25616
|
embedAlphaChannel(context) {
|
|
25675
25617
|
if (!this.image.alphaChannel)
|
|
@@ -26657,34 +26599,30 @@ class PDFPageEmbedder {
|
|
|
26657
26599
|
this.transformationMatrix =
|
|
26658
26600
|
transformationMatrix !== null && transformationMatrix !== void 0 ? transformationMatrix : boundingBoxAdjustedMatrix(bb);
|
|
26659
26601
|
}
|
|
26660
|
-
static for(page, boundingBox, transformationMatrix) {
|
|
26661
|
-
return
|
|
26662
|
-
return new PDFPageEmbedder(page, boundingBox, transformationMatrix);
|
|
26663
|
-
});
|
|
26602
|
+
static async for(page, boundingBox, transformationMatrix) {
|
|
26603
|
+
return new PDFPageEmbedder(page, boundingBox, transformationMatrix);
|
|
26664
26604
|
}
|
|
26665
|
-
embedIntoContext(context, ref) {
|
|
26666
|
-
|
|
26667
|
-
|
|
26668
|
-
|
|
26669
|
-
|
|
26670
|
-
|
|
26671
|
-
|
|
26672
|
-
|
|
26673
|
-
|
|
26674
|
-
|
|
26675
|
-
|
|
26676
|
-
|
|
26677
|
-
|
|
26678
|
-
Resources,
|
|
26679
|
-
});
|
|
26680
|
-
if (ref) {
|
|
26681
|
-
context.assign(ref, xObject);
|
|
26682
|
-
return ref;
|
|
26683
|
-
}
|
|
26684
|
-
else {
|
|
26685
|
-
return context.register(xObject);
|
|
26686
|
-
}
|
|
26605
|
+
async embedIntoContext(context, ref) {
|
|
26606
|
+
const { Contents, Resources } = this.page.normalizedEntries();
|
|
26607
|
+
if (!Contents)
|
|
26608
|
+
throw new MissingPageContentsEmbeddingError();
|
|
26609
|
+
const decodedContents = this.decodeContents(Contents);
|
|
26610
|
+
const { left, bottom, right, top } = this.boundingBox;
|
|
26611
|
+
const xObject = context.flateStream(decodedContents, {
|
|
26612
|
+
Type: 'XObject',
|
|
26613
|
+
Subtype: 'Form',
|
|
26614
|
+
FormType: 1,
|
|
26615
|
+
BBox: [left, bottom, right, top],
|
|
26616
|
+
Matrix: this.transformationMatrix,
|
|
26617
|
+
Resources,
|
|
26687
26618
|
});
|
|
26619
|
+
if (ref) {
|
|
26620
|
+
context.assign(ref, xObject);
|
|
26621
|
+
return ref;
|
|
26622
|
+
}
|
|
26623
|
+
else {
|
|
26624
|
+
return context.register(xObject);
|
|
26625
|
+
}
|
|
26688
26626
|
}
|
|
26689
26627
|
// `contents` is an array of streams which are merged to include them in the XObject.
|
|
26690
26628
|
// This methods extracts each stream and joins them with a newline character.
|
|
@@ -29136,23 +29074,21 @@ class PDFObjectStreamParser extends PDFObjectParser {
|
|
|
29136
29074
|
this.firstOffset = dict.lookup(PDFName.of('First'), PDFNumber).asNumber();
|
|
29137
29075
|
this.objectCount = dict.lookup(PDFName.of('N'), PDFNumber).asNumber();
|
|
29138
29076
|
}
|
|
29139
|
-
parseIntoContext() {
|
|
29140
|
-
|
|
29141
|
-
|
|
29142
|
-
|
|
29143
|
-
|
|
29144
|
-
|
|
29145
|
-
|
|
29146
|
-
|
|
29147
|
-
|
|
29148
|
-
|
|
29149
|
-
|
|
29150
|
-
|
|
29151
|
-
|
|
29152
|
-
|
|
29153
|
-
|
|
29154
|
-
}
|
|
29155
|
-
});
|
|
29077
|
+
async parseIntoContext() {
|
|
29078
|
+
if (this.alreadyParsed) {
|
|
29079
|
+
throw new ReparseError('PDFObjectStreamParser', 'parseIntoContext');
|
|
29080
|
+
}
|
|
29081
|
+
this.alreadyParsed = true;
|
|
29082
|
+
const offsetsAndObjectNumbers = this.parseOffsetsAndObjectNumbers();
|
|
29083
|
+
for (let idx = 0, len = offsetsAndObjectNumbers.length; idx < len; idx++) {
|
|
29084
|
+
const { objectNumber, offset } = offsetsAndObjectNumbers[idx];
|
|
29085
|
+
this.bytes.moveTo(this.firstOffset + offset);
|
|
29086
|
+
const ref = PDFRef.of(objectNumber, 0);
|
|
29087
|
+
const object = this.parseObject(ref);
|
|
29088
|
+
this.context.assign(ref, object);
|
|
29089
|
+
if (this.shouldWaitForTick())
|
|
29090
|
+
await waitForTick();
|
|
29091
|
+
}
|
|
29156
29092
|
}
|
|
29157
29093
|
parseOffsetsAndObjectNumbers() {
|
|
29158
29094
|
const offsetsAndObjectNumbers = [];
|
|
@@ -29260,29 +29196,27 @@ class PDFParser extends PDFObjectParser {
|
|
|
29260
29196
|
this.throwOnInvalidObject = throwOnInvalidObject;
|
|
29261
29197
|
this.context.isDecrypted = !!(cryptoFactory === null || cryptoFactory === void 0 ? void 0 : cryptoFactory.encryptionKey);
|
|
29262
29198
|
}
|
|
29263
|
-
parseDocument() {
|
|
29264
|
-
|
|
29265
|
-
|
|
29266
|
-
|
|
29267
|
-
|
|
29268
|
-
|
|
29269
|
-
|
|
29270
|
-
|
|
29271
|
-
|
|
29272
|
-
|
|
29273
|
-
|
|
29274
|
-
|
|
29275
|
-
throw new StalledParserError(this.bytes.position());
|
|
29276
|
-
}
|
|
29277
|
-
prevOffset = offset;
|
|
29278
|
-
}
|
|
29279
|
-
this.maybeRecoverRoot();
|
|
29280
|
-
if (this.context.lookup(PDFRef.of(0))) {
|
|
29281
|
-
console.warn('Removing parsed object: 0 0 R');
|
|
29282
|
-
this.context.delete(PDFRef.of(0));
|
|
29199
|
+
async parseDocument() {
|
|
29200
|
+
if (this.alreadyParsed) {
|
|
29201
|
+
throw new ReparseError('PDFParser', 'parseDocument');
|
|
29202
|
+
}
|
|
29203
|
+
this.alreadyParsed = true;
|
|
29204
|
+
this.context.header = this.parseHeader();
|
|
29205
|
+
let prevOffset;
|
|
29206
|
+
while (!this.bytes.done()) {
|
|
29207
|
+
await this.parseDocumentSection();
|
|
29208
|
+
const offset = this.bytes.offset();
|
|
29209
|
+
if (offset === prevOffset) {
|
|
29210
|
+
throw new StalledParserError(this.bytes.position());
|
|
29283
29211
|
}
|
|
29284
|
-
|
|
29285
|
-
}
|
|
29212
|
+
prevOffset = offset;
|
|
29213
|
+
}
|
|
29214
|
+
this.maybeRecoverRoot();
|
|
29215
|
+
if (this.context.lookup(PDFRef.of(0))) {
|
|
29216
|
+
console.warn('Removing parsed object: 0 0 R');
|
|
29217
|
+
this.context.delete(PDFRef.of(0));
|
|
29218
|
+
}
|
|
29219
|
+
return this.context;
|
|
29286
29220
|
}
|
|
29287
29221
|
maybeRecoverRoot() {
|
|
29288
29222
|
const isValidCatalog = (obj) => obj instanceof PDFDict &&
|
|
@@ -29334,30 +29268,28 @@ class PDFParser extends PDFObjectParser {
|
|
|
29334
29268
|
return false;
|
|
29335
29269
|
}
|
|
29336
29270
|
}
|
|
29337
|
-
parseIndirectObject() {
|
|
29338
|
-
|
|
29339
|
-
|
|
29340
|
-
|
|
29341
|
-
|
|
29342
|
-
|
|
29343
|
-
|
|
29344
|
-
|
|
29345
|
-
|
|
29346
|
-
|
|
29347
|
-
|
|
29348
|
-
|
|
29349
|
-
|
|
29350
|
-
|
|
29351
|
-
|
|
29352
|
-
|
|
29353
|
-
|
|
29354
|
-
|
|
29355
|
-
|
|
29356
|
-
|
|
29357
|
-
|
|
29358
|
-
|
|
29359
|
-
return ref;
|
|
29360
|
-
});
|
|
29271
|
+
async parseIndirectObject() {
|
|
29272
|
+
const ref = this.parseIndirectObjectHeader();
|
|
29273
|
+
this.skipWhitespaceAndComments();
|
|
29274
|
+
const object = this.parseObject(ref);
|
|
29275
|
+
this.skipWhitespaceAndComments();
|
|
29276
|
+
// if (!this.matchKeyword(Keywords.endobj)) {
|
|
29277
|
+
// throw new MissingKeywordError(this.bytes.position(), Keywords.endobj);
|
|
29278
|
+
// }
|
|
29279
|
+
// TODO: Log a warning if this fails...
|
|
29280
|
+
this.matchKeyword(Keywords.endobj);
|
|
29281
|
+
if (object instanceof PDFRawStream &&
|
|
29282
|
+
object.dict.lookup(PDFName.of('Type')) === PDFName.of('ObjStm')) {
|
|
29283
|
+
await PDFObjectStreamParser.forStream(object, this.shouldWaitForTick).parseIntoContext();
|
|
29284
|
+
}
|
|
29285
|
+
else if (object instanceof PDFRawStream &&
|
|
29286
|
+
object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef')) {
|
|
29287
|
+
PDFXRefStreamParser.forStream(object).parseIntoContext();
|
|
29288
|
+
}
|
|
29289
|
+
else {
|
|
29290
|
+
this.context.assign(ref, object);
|
|
29291
|
+
}
|
|
29292
|
+
return ref;
|
|
29361
29293
|
}
|
|
29362
29294
|
// TODO: Improve and clean this up
|
|
29363
29295
|
tryToParseInvalidIndirectObject() {
|
|
@@ -29386,26 +29318,24 @@ class PDFParser extends PDFObjectParser {
|
|
|
29386
29318
|
this.context.assign(ref, object);
|
|
29387
29319
|
return ref;
|
|
29388
29320
|
}
|
|
29389
|
-
parseIndirectObjects() {
|
|
29390
|
-
|
|
29391
|
-
|
|
29392
|
-
|
|
29393
|
-
|
|
29394
|
-
|
|
29395
|
-
yield this.parseIndirectObject();
|
|
29396
|
-
}
|
|
29397
|
-
catch (e) {
|
|
29398
|
-
// TODO: Add tracing/logging mechanism to track when this happens!
|
|
29399
|
-
this.bytes.moveTo(initialOffset);
|
|
29400
|
-
this.tryToParseInvalidIndirectObject();
|
|
29401
|
-
}
|
|
29402
|
-
this.skipWhitespaceAndComments();
|
|
29403
|
-
// TODO: Can this be done only when needed, to avoid harming performance?
|
|
29404
|
-
this.skipJibberish();
|
|
29405
|
-
if (this.shouldWaitForTick())
|
|
29406
|
-
yield waitForTick();
|
|
29321
|
+
async parseIndirectObjects() {
|
|
29322
|
+
this.skipWhitespaceAndComments();
|
|
29323
|
+
while (!this.bytes.done() && IsDigit[this.bytes.peek()]) {
|
|
29324
|
+
const initialOffset = this.bytes.offset();
|
|
29325
|
+
try {
|
|
29326
|
+
await this.parseIndirectObject();
|
|
29407
29327
|
}
|
|
29408
|
-
|
|
29328
|
+
catch (e) {
|
|
29329
|
+
// TODO: Add tracing/logging mechanism to track when this happens!
|
|
29330
|
+
this.bytes.moveTo(initialOffset);
|
|
29331
|
+
this.tryToParseInvalidIndirectObject();
|
|
29332
|
+
}
|
|
29333
|
+
this.skipWhitespaceAndComments();
|
|
29334
|
+
// TODO: Can this be done only when needed, to avoid harming performance?
|
|
29335
|
+
this.skipJibberish();
|
|
29336
|
+
if (this.shouldWaitForTick())
|
|
29337
|
+
await waitForTick();
|
|
29338
|
+
}
|
|
29409
29339
|
}
|
|
29410
29340
|
maybeParseCrossRefSection() {
|
|
29411
29341
|
this.skipWhitespaceAndComments();
|
|
@@ -29465,15 +29395,13 @@ class PDFParser extends PDFObjectParser {
|
|
|
29465
29395
|
this.skipWhitespaceAndComments();
|
|
29466
29396
|
return PDFTrailer.forLastCrossRefSectionOffset(offset);
|
|
29467
29397
|
}
|
|
29468
|
-
parseDocumentSection() {
|
|
29469
|
-
|
|
29470
|
-
|
|
29471
|
-
|
|
29472
|
-
|
|
29473
|
-
|
|
29474
|
-
|
|
29475
|
-
this.skipJibberish();
|
|
29476
|
-
});
|
|
29398
|
+
async parseDocumentSection() {
|
|
29399
|
+
await this.parseIndirectObjects();
|
|
29400
|
+
this.maybeParseCrossRefSection();
|
|
29401
|
+
this.maybeParseTrailerDict();
|
|
29402
|
+
this.maybeParseTrailer();
|
|
29403
|
+
// TODO: Can this be done only when needed, to avoid harming performance?
|
|
29404
|
+
this.skipJibberish();
|
|
29477
29405
|
}
|
|
29478
29406
|
/**
|
|
29479
29407
|
* This operation is not necessary for valid PDF files. But some invalid PDFs
|
|
@@ -32196,6 +32124,16 @@ const segmentToBezier = (cx1, cy1, th0, th1, rx, ry, sinTh, cosTh) => {
|
|
|
32196
32124
|
};
|
|
32197
32125
|
const svgPathToOperators = (path) => apply(parse(path));
|
|
32198
32126
|
|
|
32127
|
+
const clipSpace = ({ topLeft, topRight, bottomRight, bottomLeft }) => [
|
|
32128
|
+
moveTo(topLeft.x, topLeft.y),
|
|
32129
|
+
lineTo(topRight.x, topRight.y),
|
|
32130
|
+
lineTo(bottomRight.x, bottomRight.y),
|
|
32131
|
+
lineTo(bottomLeft.x, bottomLeft.y),
|
|
32132
|
+
closePath(),
|
|
32133
|
+
clip(),
|
|
32134
|
+
endPath(),
|
|
32135
|
+
];
|
|
32136
|
+
const clipSpaces = (spaces) => spaces.flatMap(clipSpace);
|
|
32199
32137
|
const drawText = (line, options) => [
|
|
32200
32138
|
pushGraphicsState(),
|
|
32201
32139
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
@@ -32211,6 +32149,8 @@ const drawLinesOfText = (lines, options) => {
|
|
|
32211
32149
|
const operators = [
|
|
32212
32150
|
pushGraphicsState(),
|
|
32213
32151
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32152
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32153
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32214
32154
|
beginText(),
|
|
32215
32155
|
setFillingColor(options.color),
|
|
32216
32156
|
setFontAndSize(options.font, options.size),
|
|
@@ -32226,6 +32166,8 @@ const drawLinesOfText = (lines, options) => {
|
|
|
32226
32166
|
const drawImage = (name, options) => [
|
|
32227
32167
|
pushGraphicsState(),
|
|
32228
32168
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32169
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32170
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32229
32171
|
translate(options.x, options.y),
|
|
32230
32172
|
rotateRadians(toRadians(options.rotate)),
|
|
32231
32173
|
scale(options.width, options.height),
|
|
@@ -32248,6 +32190,8 @@ const drawLine = (options) => {
|
|
|
32248
32190
|
return [
|
|
32249
32191
|
pushGraphicsState(),
|
|
32250
32192
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32193
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32194
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32251
32195
|
options.color && setStrokingColor(options.color),
|
|
32252
32196
|
setLineWidth(options.thickness),
|
|
32253
32197
|
setDashPattern((_a = options.dashArray) !== null && _a !== void 0 ? _a : [], (_b = options.dashPhase) !== null && _b !== void 0 ? _b : 0),
|
|
@@ -32261,6 +32205,36 @@ const drawLine = (options) => {
|
|
|
32261
32205
|
};
|
|
32262
32206
|
const drawRectangle = (options) => {
|
|
32263
32207
|
var _a, _b;
|
|
32208
|
+
let ops = [];
|
|
32209
|
+
if (!options.radius || asNumber(options.radius) <= 0) {
|
|
32210
|
+
ops = [
|
|
32211
|
+
moveTo(0, 0),
|
|
32212
|
+
lineTo(0, options.height),
|
|
32213
|
+
lineTo(options.width, options.height),
|
|
32214
|
+
lineTo(options.width, 0),
|
|
32215
|
+
closePath(),
|
|
32216
|
+
];
|
|
32217
|
+
}
|
|
32218
|
+
else {
|
|
32219
|
+
let radius = asNumber(options.radius);
|
|
32220
|
+
const width = asNumber(options.width);
|
|
32221
|
+
const height = asNumber(options.height);
|
|
32222
|
+
if (radius > width / 2.0 || radius > height / 2.0) {
|
|
32223
|
+
radius = Math.min(width / 2.0, height / 2.0);
|
|
32224
|
+
}
|
|
32225
|
+
const offset = KAPPA * radius;
|
|
32226
|
+
ops = [
|
|
32227
|
+
moveTo(0, radius),
|
|
32228
|
+
appendBezierCurve(0, radius - offset, radius - offset, 0, radius, 0),
|
|
32229
|
+
lineTo(width - radius, 0),
|
|
32230
|
+
appendBezierCurve(width - radius + offset, 0, width, radius - offset, width, radius),
|
|
32231
|
+
lineTo(width, height - radius),
|
|
32232
|
+
appendBezierCurve(width, height - radius + offset, width - radius + offset, height, width - radius, height),
|
|
32233
|
+
lineTo(radius, height),
|
|
32234
|
+
appendBezierCurve(radius - offset, height, 0, height - radius + offset, 0, height - radius),
|
|
32235
|
+
closePath(),
|
|
32236
|
+
];
|
|
32237
|
+
}
|
|
32264
32238
|
return [
|
|
32265
32239
|
pushGraphicsState(),
|
|
32266
32240
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
@@ -32269,14 +32243,12 @@ const drawRectangle = (options) => {
|
|
|
32269
32243
|
setLineWidth(options.borderWidth),
|
|
32270
32244
|
options.borderLineCap && setLineCap(options.borderLineCap),
|
|
32271
32245
|
setDashPattern((_a = options.borderDashArray) !== null && _a !== void 0 ? _a : [], (_b = options.borderDashPhase) !== null && _b !== void 0 ? _b : 0),
|
|
32246
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32247
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32272
32248
|
translate(options.x, options.y),
|
|
32273
32249
|
rotateRadians(toRadians(options.rotate)),
|
|
32274
32250
|
skewRadians(toRadians(options.xSkew), toRadians(options.ySkew)),
|
|
32275
|
-
|
|
32276
|
-
lineTo(0, options.height),
|
|
32277
|
-
lineTo(options.width, options.height),
|
|
32278
|
-
lineTo(options.width, 0),
|
|
32279
|
-
closePath(),
|
|
32251
|
+
...ops,
|
|
32280
32252
|
// prettier-ignore
|
|
32281
32253
|
options.color && options.borderWidth ? fillAndStroke()
|
|
32282
32254
|
: options.color ? fill()
|
|
@@ -32340,6 +32312,8 @@ const drawEllipse = (options) => {
|
|
|
32340
32312
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32341
32313
|
options.color && setFillingColor(options.color),
|
|
32342
32314
|
options.borderColor && setStrokingColor(options.borderColor),
|
|
32315
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32316
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32343
32317
|
setLineWidth(options.borderWidth),
|
|
32344
32318
|
options.borderLineCap && setLineCap(options.borderLineCap),
|
|
32345
32319
|
setDashPattern((_a = options.borderDashArray) !== null && _a !== void 0 ? _a : [], (_b = options.borderDashPhase) !== null && _b !== void 0 ? _b : 0),
|
|
@@ -32372,6 +32346,8 @@ const drawSvgPath = (path, options) => {
|
|
|
32372
32346
|
return [
|
|
32373
32347
|
pushGraphicsState(),
|
|
32374
32348
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32349
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32350
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32375
32351
|
translate(options.x, options.y),
|
|
32376
32352
|
rotateRadians(toRadians((_a = options.rotate) !== null && _a !== void 0 ? _a : degrees(0))),
|
|
32377
32353
|
options.scale && scale(options.scale, options.scale),
|
|
@@ -33033,7 +33009,7 @@ const defaultCheckBoxAppearanceProvider = (checkBox, widget) => {
|
|
|
33033
33009
|
const borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0;
|
|
33034
33010
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33035
33011
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33036
|
-
const rotate = rotateInPlace(
|
|
33012
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33037
33013
|
const black = rgb(0, 0, 0);
|
|
33038
33014
|
const borderColor = (_b = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor())) !== null && _b !== void 0 ? _b : black;
|
|
33039
33015
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33060,21 +33036,37 @@ const defaultCheckBoxAppearanceProvider = (checkBox, widget) => {
|
|
|
33060
33036
|
normal: {
|
|
33061
33037
|
on: [
|
|
33062
33038
|
...rotate,
|
|
33063
|
-
...drawCheckBox(
|
|
33039
|
+
...drawCheckBox({
|
|
33040
|
+
...options,
|
|
33041
|
+
color: normalBackgroundColor,
|
|
33042
|
+
filled: true,
|
|
33043
|
+
}),
|
|
33064
33044
|
],
|
|
33065
33045
|
off: [
|
|
33066
33046
|
...rotate,
|
|
33067
|
-
...drawCheckBox(
|
|
33047
|
+
...drawCheckBox({
|
|
33048
|
+
...options,
|
|
33049
|
+
color: normalBackgroundColor,
|
|
33050
|
+
filled: false,
|
|
33051
|
+
}),
|
|
33068
33052
|
],
|
|
33069
33053
|
},
|
|
33070
33054
|
down: {
|
|
33071
33055
|
on: [
|
|
33072
33056
|
...rotate,
|
|
33073
|
-
...drawCheckBox(
|
|
33057
|
+
...drawCheckBox({
|
|
33058
|
+
...options,
|
|
33059
|
+
color: downBackgroundColor,
|
|
33060
|
+
filled: true,
|
|
33061
|
+
}),
|
|
33074
33062
|
],
|
|
33075
33063
|
off: [
|
|
33076
33064
|
...rotate,
|
|
33077
|
-
...drawCheckBox(
|
|
33065
|
+
...drawCheckBox({
|
|
33066
|
+
...options,
|
|
33067
|
+
color: downBackgroundColor,
|
|
33068
|
+
filled: false,
|
|
33069
|
+
}),
|
|
33078
33070
|
],
|
|
33079
33071
|
},
|
|
33080
33072
|
};
|
|
@@ -33090,7 +33082,7 @@ const defaultRadioGroupAppearanceProvider = (radioGroup, widget) => {
|
|
|
33090
33082
|
const borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0;
|
|
33091
33083
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33092
33084
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33093
|
-
const rotate = rotateInPlace(
|
|
33085
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33094
33086
|
const black = rgb(0, 0, 0);
|
|
33095
33087
|
const borderColor = (_b = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor())) !== null && _b !== void 0 ? _b : black;
|
|
33096
33088
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33116,21 +33108,37 @@ const defaultRadioGroupAppearanceProvider = (radioGroup, widget) => {
|
|
|
33116
33108
|
normal: {
|
|
33117
33109
|
on: [
|
|
33118
33110
|
...rotate,
|
|
33119
|
-
...drawRadioButton(
|
|
33111
|
+
...drawRadioButton({
|
|
33112
|
+
...options,
|
|
33113
|
+
color: normalBackgroundColor,
|
|
33114
|
+
filled: true,
|
|
33115
|
+
}),
|
|
33120
33116
|
],
|
|
33121
33117
|
off: [
|
|
33122
33118
|
...rotate,
|
|
33123
|
-
...drawRadioButton(
|
|
33119
|
+
...drawRadioButton({
|
|
33120
|
+
...options,
|
|
33121
|
+
color: normalBackgroundColor,
|
|
33122
|
+
filled: false,
|
|
33123
|
+
}),
|
|
33124
33124
|
],
|
|
33125
33125
|
},
|
|
33126
33126
|
down: {
|
|
33127
33127
|
on: [
|
|
33128
33128
|
...rotate,
|
|
33129
|
-
...drawRadioButton(
|
|
33129
|
+
...drawRadioButton({
|
|
33130
|
+
...options,
|
|
33131
|
+
color: downBackgroundColor,
|
|
33132
|
+
filled: true,
|
|
33133
|
+
}),
|
|
33130
33134
|
],
|
|
33131
33135
|
off: [
|
|
33132
33136
|
...rotate,
|
|
33133
|
-
...drawRadioButton(
|
|
33137
|
+
...drawRadioButton({
|
|
33138
|
+
...options,
|
|
33139
|
+
color: downBackgroundColor,
|
|
33140
|
+
filled: false,
|
|
33141
|
+
}),
|
|
33134
33142
|
],
|
|
33135
33143
|
},
|
|
33136
33144
|
};
|
|
@@ -33151,7 +33159,7 @@ const defaultButtonAppearanceProvider = (button, widget, font) => {
|
|
|
33151
33159
|
const borderWidth = (_d = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _d !== void 0 ? _d : 0;
|
|
33152
33160
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33153
33161
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33154
|
-
const rotate = rotateInPlace(
|
|
33162
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33155
33163
|
const black = rgb(0, 0, 0);
|
|
33156
33164
|
const borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor());
|
|
33157
33165
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33197,11 +33205,19 @@ const defaultButtonAppearanceProvider = (button, widget, font) => {
|
|
|
33197
33205
|
return {
|
|
33198
33206
|
normal: [
|
|
33199
33207
|
...rotate,
|
|
33200
|
-
...drawButton(
|
|
33208
|
+
...drawButton({
|
|
33209
|
+
...options,
|
|
33210
|
+
color: normalBackgroundColor,
|
|
33211
|
+
textLines: [normalLayout.line],
|
|
33212
|
+
}),
|
|
33201
33213
|
],
|
|
33202
33214
|
down: [
|
|
33203
33215
|
...rotate,
|
|
33204
|
-
...drawButton(
|
|
33216
|
+
...drawButton({
|
|
33217
|
+
...options,
|
|
33218
|
+
color: downBackgroundColor,
|
|
33219
|
+
textLines: [downLayout.line],
|
|
33220
|
+
}),
|
|
33205
33221
|
],
|
|
33206
33222
|
};
|
|
33207
33223
|
};
|
|
@@ -33219,7 +33235,7 @@ const defaultTextFieldAppearanceProvider = (textField, widget, font) => {
|
|
|
33219
33235
|
const borderWidth = (_b = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _b !== void 0 ? _b : 0;
|
|
33220
33236
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33221
33237
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33222
|
-
const rotate = rotateInPlace(
|
|
33238
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33223
33239
|
const black = rgb(0, 0, 0);
|
|
33224
33240
|
const borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor());
|
|
33225
33241
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33300,7 +33316,7 @@ const defaultDropdownAppearanceProvider = (dropdown, widget, font) => {
|
|
|
33300
33316
|
const borderWidth = (_b = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _b !== void 0 ? _b : 0;
|
|
33301
33317
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33302
33318
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33303
|
-
const rotate = rotateInPlace(
|
|
33319
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33304
33320
|
const black = rgb(0, 0, 0);
|
|
33305
33321
|
const borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor());
|
|
33306
33322
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33354,7 +33370,7 @@ const defaultOptionListAppearanceProvider = (optionList, widget, font) => {
|
|
|
33354
33370
|
const borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0;
|
|
33355
33371
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33356
33372
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33357
|
-
const rotate = rotateInPlace(
|
|
33373
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33358
33374
|
const black = rgb(0, 0, 0);
|
|
33359
33375
|
const borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor());
|
|
33360
33376
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33472,13 +33488,11 @@ class PDFEmbeddedPage {
|
|
|
33472
33488
|
*
|
|
33473
33489
|
* @returns Resolves when the embedding is complete.
|
|
33474
33490
|
*/
|
|
33475
|
-
embed() {
|
|
33476
|
-
|
|
33477
|
-
|
|
33478
|
-
|
|
33479
|
-
|
|
33480
|
-
}
|
|
33481
|
-
});
|
|
33491
|
+
async embed() {
|
|
33492
|
+
if (!this.alreadyEmbedded) {
|
|
33493
|
+
await this.embedder.embedIntoContext(this.doc.context, this.ref);
|
|
33494
|
+
this.alreadyEmbedded = true;
|
|
33495
|
+
}
|
|
33482
33496
|
}
|
|
33483
33497
|
}
|
|
33484
33498
|
/**
|
|
@@ -33597,14 +33611,12 @@ class PDFFont {
|
|
|
33597
33611
|
*
|
|
33598
33612
|
* @returns Resolves when the embedding is complete.
|
|
33599
33613
|
*/
|
|
33600
|
-
embed() {
|
|
33601
|
-
|
|
33602
|
-
|
|
33603
|
-
|
|
33604
|
-
|
|
33605
|
-
|
|
33606
|
-
}
|
|
33607
|
-
});
|
|
33614
|
+
async embed() {
|
|
33615
|
+
// TODO: Cleanup orphan embedded objects if a font is embedded multiple times...
|
|
33616
|
+
if (this.modified) {
|
|
33617
|
+
await this.embedder.embedIntoContext(this.doc.context, this.ref);
|
|
33618
|
+
this.modified = false;
|
|
33619
|
+
}
|
|
33608
33620
|
}
|
|
33609
33621
|
}
|
|
33610
33622
|
/**
|
|
@@ -33703,22 +33715,20 @@ class PDFImage {
|
|
|
33703
33715
|
*
|
|
33704
33716
|
* @returns Resolves when the embedding is complete.
|
|
33705
33717
|
*/
|
|
33706
|
-
embed() {
|
|
33707
|
-
|
|
33708
|
-
|
|
33709
|
-
|
|
33710
|
-
|
|
33711
|
-
|
|
33712
|
-
|
|
33713
|
-
|
|
33714
|
-
|
|
33715
|
-
|
|
33716
|
-
|
|
33717
|
-
|
|
33718
|
-
|
|
33719
|
-
|
|
33720
|
-
this.embedder = undefined;
|
|
33721
|
-
});
|
|
33718
|
+
async embed() {
|
|
33719
|
+
if (!this.embedder)
|
|
33720
|
+
return;
|
|
33721
|
+
// The image should only be embedded once. If there's a pending embed
|
|
33722
|
+
// operation then wait on it. Otherwise we need to start the embed.
|
|
33723
|
+
if (!this.embedTask) {
|
|
33724
|
+
const { doc, ref } = this;
|
|
33725
|
+
this.embedTask = this.embedder.embedIntoContext(doc.context, ref);
|
|
33726
|
+
}
|
|
33727
|
+
await this.embedTask;
|
|
33728
|
+
// We clear `this.embedder` so that the indirectly referenced image data
|
|
33729
|
+
// can be garbage collected, thus avoiding a memory leak.
|
|
33730
|
+
// See https://github.com/Hopding/pdf-lib/pull/1032/files.
|
|
33731
|
+
this.embedder = undefined;
|
|
33722
33732
|
}
|
|
33723
33733
|
}
|
|
33724
33734
|
/**
|
|
@@ -34063,7 +34073,7 @@ class PDFField {
|
|
|
34063
34073
|
const bs = widget.getBorderStyle();
|
|
34064
34074
|
const borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0;
|
|
34065
34075
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
34066
|
-
const rotate = rotateInPlace(
|
|
34076
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
34067
34077
|
const adj = adjustDimsForRotation(rectangle, rotation);
|
|
34068
34078
|
const imageDims = image.scaleToFit(adj.width - borderWidth * 2, adj.height - borderWidth * 2);
|
|
34069
34079
|
// Support borders on images and maybe other properties
|
|
@@ -36984,7 +36994,7 @@ class PDFForm {
|
|
|
36984
36994
|
const operators = [
|
|
36985
36995
|
pushGraphicsState(),
|
|
36986
36996
|
translate(rectangle.x, rectangle.y),
|
|
36987
|
-
...rotateInPlace(
|
|
36997
|
+
...rotateInPlace({ ...rectangle, rotation: 0 }),
|
|
36988
36998
|
drawObject(xObjectKey),
|
|
36989
36999
|
popGraphicsState(),
|
|
36990
37000
|
].filter(Boolean);
|
|
@@ -37329,39 +37339,37 @@ class PDFEmbeddedFile {
|
|
|
37329
37339
|
*
|
|
37330
37340
|
* @returns Resolves when the embedding is complete.
|
|
37331
37341
|
*/
|
|
37332
|
-
embed() {
|
|
37333
|
-
|
|
37334
|
-
|
|
37335
|
-
|
|
37336
|
-
|
|
37337
|
-
this.doc.catalog.set(PDFName.of('Names'), this.doc.context.obj({}));
|
|
37338
|
-
}
|
|
37339
|
-
const Names = this.doc.catalog.lookup(PDFName.of('Names'), PDFDict);
|
|
37340
|
-
if (!Names.has(PDFName.of('EmbeddedFiles'))) {
|
|
37341
|
-
Names.set(PDFName.of('EmbeddedFiles'), this.doc.context.obj({}));
|
|
37342
|
-
}
|
|
37343
|
-
const EmbeddedFiles = Names.lookup(PDFName.of('EmbeddedFiles'), PDFDict);
|
|
37344
|
-
if (!EmbeddedFiles.has(PDFName.of('Names'))) {
|
|
37345
|
-
EmbeddedFiles.set(PDFName.of('Names'), this.doc.context.obj([]));
|
|
37346
|
-
}
|
|
37347
|
-
const EFNames = EmbeddedFiles.lookup(PDFName.of('Names'), PDFArray);
|
|
37348
|
-
EFNames.push(PDFHexString.fromText(this.embedder.fileName));
|
|
37349
|
-
EFNames.push(ref);
|
|
37350
|
-
/**
|
|
37351
|
-
* The AF-Tag is needed to achieve PDF-A3 compliance for embedded files
|
|
37352
|
-
*
|
|
37353
|
-
* The following document outlines the uses cases of the associated files (AF) tag.
|
|
37354
|
-
* See:
|
|
37355
|
-
* https://www.pdfa.org/wp-content/uploads/2018/10/PDF20_AN002-AF.pdf
|
|
37356
|
-
*/
|
|
37357
|
-
if (!this.doc.catalog.has(PDFName.of('AF'))) {
|
|
37358
|
-
this.doc.catalog.set(PDFName.of('AF'), this.doc.context.obj([]));
|
|
37359
|
-
}
|
|
37360
|
-
const AF = this.doc.catalog.lookup(PDFName.of('AF'), PDFArray);
|
|
37361
|
-
AF.push(ref);
|
|
37362
|
-
this.alreadyEmbedded = true;
|
|
37342
|
+
async embed() {
|
|
37343
|
+
if (!this.alreadyEmbedded) {
|
|
37344
|
+
const ref = await this.embedder.embedIntoContext(this.doc.context, this.ref);
|
|
37345
|
+
if (!this.doc.catalog.has(PDFName.of('Names'))) {
|
|
37346
|
+
this.doc.catalog.set(PDFName.of('Names'), this.doc.context.obj({}));
|
|
37363
37347
|
}
|
|
37364
|
-
|
|
37348
|
+
const Names = this.doc.catalog.lookup(PDFName.of('Names'), PDFDict);
|
|
37349
|
+
if (!Names.has(PDFName.of('EmbeddedFiles'))) {
|
|
37350
|
+
Names.set(PDFName.of('EmbeddedFiles'), this.doc.context.obj({}));
|
|
37351
|
+
}
|
|
37352
|
+
const EmbeddedFiles = Names.lookup(PDFName.of('EmbeddedFiles'), PDFDict);
|
|
37353
|
+
if (!EmbeddedFiles.has(PDFName.of('Names'))) {
|
|
37354
|
+
EmbeddedFiles.set(PDFName.of('Names'), this.doc.context.obj([]));
|
|
37355
|
+
}
|
|
37356
|
+
const EFNames = EmbeddedFiles.lookup(PDFName.of('Names'), PDFArray);
|
|
37357
|
+
EFNames.push(PDFHexString.fromText(this.embedder.fileName));
|
|
37358
|
+
EFNames.push(ref);
|
|
37359
|
+
/**
|
|
37360
|
+
* The AF-Tag is needed to achieve PDF-A3 compliance for embedded files
|
|
37361
|
+
*
|
|
37362
|
+
* The following document outlines the uses cases of the associated files (AF) tag.
|
|
37363
|
+
* See:
|
|
37364
|
+
* https://www.pdfa.org/wp-content/uploads/2018/10/PDF20_AN002-AF.pdf
|
|
37365
|
+
*/
|
|
37366
|
+
if (!this.doc.catalog.has(PDFName.of('AF'))) {
|
|
37367
|
+
this.doc.catalog.set(PDFName.of('AF'), this.doc.context.obj([]));
|
|
37368
|
+
}
|
|
37369
|
+
const AF = this.doc.catalog.lookup(PDFName.of('AF'), PDFArray);
|
|
37370
|
+
AF.push(ref);
|
|
37371
|
+
this.alreadyEmbedded = true;
|
|
37372
|
+
}
|
|
37365
37373
|
}
|
|
37366
37374
|
}
|
|
37367
37375
|
/**
|
|
@@ -37396,28 +37404,26 @@ class PDFJavaScript {
|
|
|
37396
37404
|
*
|
|
37397
37405
|
* @returns Resolves when the embedding is complete.
|
|
37398
37406
|
*/
|
|
37399
|
-
embed() {
|
|
37400
|
-
|
|
37401
|
-
|
|
37402
|
-
|
|
37403
|
-
|
|
37404
|
-
|
|
37405
|
-
catalog.set(PDFName.of('Names'), context.obj({}));
|
|
37406
|
-
}
|
|
37407
|
-
const Names = catalog.lookup(PDFName.of('Names'), PDFDict);
|
|
37408
|
-
if (!Names.has(PDFName.of('JavaScript'))) {
|
|
37409
|
-
Names.set(PDFName.of('JavaScript'), context.obj({}));
|
|
37410
|
-
}
|
|
37411
|
-
const Javascript = Names.lookup(PDFName.of('JavaScript'), PDFDict);
|
|
37412
|
-
if (!Javascript.has(PDFName.of('Names'))) {
|
|
37413
|
-
Javascript.set(PDFName.of('Names'), context.obj([]));
|
|
37414
|
-
}
|
|
37415
|
-
const JSNames = Javascript.lookup(PDFName.of('Names'), PDFArray);
|
|
37416
|
-
JSNames.push(PDFHexString.fromText(this.embedder.scriptName));
|
|
37417
|
-
JSNames.push(ref);
|
|
37418
|
-
this.alreadyEmbedded = true;
|
|
37407
|
+
async embed() {
|
|
37408
|
+
if (!this.alreadyEmbedded) {
|
|
37409
|
+
const { catalog, context } = this.doc;
|
|
37410
|
+
const ref = await this.embedder.embedIntoContext(this.doc.context, this.ref);
|
|
37411
|
+
if (!catalog.has(PDFName.of('Names'))) {
|
|
37412
|
+
catalog.set(PDFName.of('Names'), context.obj({}));
|
|
37419
37413
|
}
|
|
37420
|
-
|
|
37414
|
+
const Names = catalog.lookup(PDFName.of('Names'), PDFDict);
|
|
37415
|
+
if (!Names.has(PDFName.of('JavaScript'))) {
|
|
37416
|
+
Names.set(PDFName.of('JavaScript'), context.obj({}));
|
|
37417
|
+
}
|
|
37418
|
+
const Javascript = Names.lookup(PDFName.of('JavaScript'), PDFDict);
|
|
37419
|
+
if (!Javascript.has(PDFName.of('Names'))) {
|
|
37420
|
+
Javascript.set(PDFName.of('Names'), context.obj([]));
|
|
37421
|
+
}
|
|
37422
|
+
const JSNames = Javascript.lookup(PDFName.of('Names'), PDFArray);
|
|
37423
|
+
JSNames.push(PDFHexString.fromText(this.embedder.scriptName));
|
|
37424
|
+
JSNames.push(ref);
|
|
37425
|
+
this.alreadyEmbedded = true;
|
|
37426
|
+
}
|
|
37421
37427
|
}
|
|
37422
37428
|
}
|
|
37423
37429
|
/**
|
|
@@ -37441,21 +37447,19 @@ class JavaScriptEmbedder {
|
|
|
37441
37447
|
static for(script, scriptName) {
|
|
37442
37448
|
return new JavaScriptEmbedder(script, scriptName);
|
|
37443
37449
|
}
|
|
37444
|
-
embedIntoContext(context, ref) {
|
|
37445
|
-
|
|
37446
|
-
|
|
37447
|
-
|
|
37448
|
-
|
|
37449
|
-
JS: PDFHexString.fromText(this.script),
|
|
37450
|
-
});
|
|
37451
|
-
if (ref) {
|
|
37452
|
-
context.assign(ref, jsActionDict);
|
|
37453
|
-
return ref;
|
|
37454
|
-
}
|
|
37455
|
-
else {
|
|
37456
|
-
return context.register(jsActionDict);
|
|
37457
|
-
}
|
|
37450
|
+
async embedIntoContext(context, ref) {
|
|
37451
|
+
const jsActionDict = context.obj({
|
|
37452
|
+
Type: 'Action',
|
|
37453
|
+
S: 'JavaScript',
|
|
37454
|
+
JS: PDFHexString.fromText(this.script),
|
|
37458
37455
|
});
|
|
37456
|
+
if (ref) {
|
|
37457
|
+
context.assign(ref, jsActionDict);
|
|
37458
|
+
return ref;
|
|
37459
|
+
}
|
|
37460
|
+
else {
|
|
37461
|
+
return context.register(jsActionDict);
|
|
37462
|
+
}
|
|
37459
37463
|
}
|
|
37460
37464
|
}
|
|
37461
37465
|
|
|
@@ -39189,42 +39193,38 @@ class PDFDocument {
|
|
|
39189
39193
|
* @param options The options to be used when loading the document.
|
|
39190
39194
|
* @returns Resolves with a document loaded from the input.
|
|
39191
39195
|
*/
|
|
39192
|
-
static load(pdf, options = {}) {
|
|
39193
|
-
|
|
39194
|
-
|
|
39195
|
-
|
|
39196
|
-
|
|
39197
|
-
|
|
39198
|
-
|
|
39199
|
-
|
|
39200
|
-
|
|
39201
|
-
|
|
39202
|
-
|
|
39203
|
-
|
|
39204
|
-
|
|
39205
|
-
|
|
39206
|
-
|
|
39207
|
-
|
|
39208
|
-
|
|
39209
|
-
|
|
39210
|
-
|
|
39211
|
-
}
|
|
39212
|
-
});
|
|
39196
|
+
static async load(pdf, options = {}) {
|
|
39197
|
+
const { ignoreEncryption = false, parseSpeed = ParseSpeeds.Slow, throwOnInvalidObject = false, updateMetadata = true, capNumbers = false, password, } = options;
|
|
39198
|
+
assertIs(pdf, 'pdf', ['string', Uint8Array, ArrayBuffer]);
|
|
39199
|
+
assertIs(ignoreEncryption, 'ignoreEncryption', ['boolean']);
|
|
39200
|
+
assertIs(parseSpeed, 'parseSpeed', ['number']);
|
|
39201
|
+
assertIs(throwOnInvalidObject, 'throwOnInvalidObject', ['boolean']);
|
|
39202
|
+
assertIs(password, 'password', ['string', 'undefined']);
|
|
39203
|
+
const bytes = toUint8Array(pdf);
|
|
39204
|
+
const context = await PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, capNumbers).parseDocument();
|
|
39205
|
+
if (!!context.lookup(context.trailerInfo.Encrypt) && password !== undefined) {
|
|
39206
|
+
// Decrypt
|
|
39207
|
+
const fileIds = context.lookup(context.trailerInfo.ID, PDFArray);
|
|
39208
|
+
const encryptDict = context.lookup(context.trailerInfo.Encrypt, PDFDict);
|
|
39209
|
+
const decryptedContext = await PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, capNumbers, new CipherTransformFactory(encryptDict, fileIds.get(0).asBytes(), password)).parseDocument();
|
|
39210
|
+
return new PDFDocument(decryptedContext, true, updateMetadata);
|
|
39211
|
+
}
|
|
39212
|
+
else {
|
|
39213
|
+
return new PDFDocument(context, ignoreEncryption, updateMetadata);
|
|
39214
|
+
}
|
|
39213
39215
|
}
|
|
39214
39216
|
/**
|
|
39215
39217
|
* Create a new [[PDFDocument]].
|
|
39216
39218
|
* @returns Resolves with the newly created document.
|
|
39217
39219
|
*/
|
|
39218
|
-
static create(options = {}) {
|
|
39219
|
-
|
|
39220
|
-
|
|
39221
|
-
|
|
39222
|
-
|
|
39223
|
-
|
|
39224
|
-
|
|
39225
|
-
|
|
39226
|
-
return new PDFDocument(context, false, updateMetadata);
|
|
39227
|
-
});
|
|
39220
|
+
static async create(options = {}) {
|
|
39221
|
+
const { updateMetadata = true } = options;
|
|
39222
|
+
const context = PDFContext.create();
|
|
39223
|
+
const pageTree = PDFPageTree.withContext(context);
|
|
39224
|
+
const pageTreeRef = context.register(pageTree);
|
|
39225
|
+
const catalog = PDFCatalog.withContextAndPages(context, pageTreeRef);
|
|
39226
|
+
context.trailerInfo.Root = context.register(catalog);
|
|
39227
|
+
return new PDFDocument(context, false, updateMetadata);
|
|
39228
39228
|
}
|
|
39229
39229
|
/**
|
|
39230
39230
|
* Register a fontkit instance. This must be done before custom fonts can
|
|
@@ -39708,22 +39708,20 @@ class PDFDocument {
|
|
|
39708
39708
|
* @param indices The indices of the pages that should be copied.
|
|
39709
39709
|
* @returns Resolves with an array of pages copied into this document.
|
|
39710
39710
|
*/
|
|
39711
|
-
copyPages(srcDoc, indices) {
|
|
39712
|
-
|
|
39713
|
-
|
|
39714
|
-
|
|
39715
|
-
|
|
39716
|
-
|
|
39717
|
-
|
|
39718
|
-
|
|
39719
|
-
|
|
39720
|
-
|
|
39721
|
-
|
|
39722
|
-
|
|
39723
|
-
|
|
39724
|
-
|
|
39725
|
-
return copiedPages;
|
|
39726
|
-
});
|
|
39711
|
+
async copyPages(srcDoc, indices) {
|
|
39712
|
+
assertIs(srcDoc, 'srcDoc', [[PDFDocument, 'PDFDocument']]);
|
|
39713
|
+
assertIs(indices, 'indices', [Array]);
|
|
39714
|
+
await srcDoc.flush();
|
|
39715
|
+
const copier = PDFObjectCopier.for(srcDoc.context, this.context);
|
|
39716
|
+
const srcPages = srcDoc.getPages();
|
|
39717
|
+
const copiedPages = new Array(indices.length);
|
|
39718
|
+
for (let idx = 0, len = indices.length; idx < len; idx++) {
|
|
39719
|
+
const srcPage = srcPages[indices[idx]];
|
|
39720
|
+
const copiedPage = copier.copy(srcPage.node);
|
|
39721
|
+
const ref = this.context.register(copiedPage);
|
|
39722
|
+
copiedPages[idx] = PDFPage.of(copiedPage, ref, this);
|
|
39723
|
+
}
|
|
39724
|
+
return copiedPages;
|
|
39727
39725
|
}
|
|
39728
39726
|
/**
|
|
39729
39727
|
* Get a copy of this document.
|
|
@@ -39739,37 +39737,35 @@ class PDFDocument {
|
|
|
39739
39737
|
*
|
|
39740
39738
|
* @returns Resolves with a copy this document.
|
|
39741
39739
|
*/
|
|
39742
|
-
copy() {
|
|
39743
|
-
|
|
39744
|
-
|
|
39745
|
-
|
|
39746
|
-
|
|
39747
|
-
|
|
39748
|
-
|
|
39749
|
-
|
|
39750
|
-
|
|
39751
|
-
|
|
39752
|
-
|
|
39753
|
-
|
|
39754
|
-
|
|
39755
|
-
|
|
39756
|
-
|
|
39757
|
-
|
|
39758
|
-
|
|
39759
|
-
|
|
39760
|
-
|
|
39761
|
-
|
|
39762
|
-
|
|
39763
|
-
|
|
39764
|
-
|
|
39765
|
-
|
|
39766
|
-
|
|
39767
|
-
|
|
39768
|
-
|
|
39769
|
-
|
|
39770
|
-
|
|
39771
|
-
return pdfCopy;
|
|
39772
|
-
});
|
|
39740
|
+
async copy() {
|
|
39741
|
+
const pdfCopy = await PDFDocument.create();
|
|
39742
|
+
const contentPages = await pdfCopy.copyPages(this, this.getPageIndices());
|
|
39743
|
+
for (let idx = 0, len = contentPages.length; idx < len; idx++) {
|
|
39744
|
+
pdfCopy.addPage(contentPages[idx]);
|
|
39745
|
+
}
|
|
39746
|
+
if (this.getAuthor() !== undefined) {
|
|
39747
|
+
pdfCopy.setAuthor(this.getAuthor());
|
|
39748
|
+
}
|
|
39749
|
+
if (this.getCreationDate() !== undefined) {
|
|
39750
|
+
pdfCopy.setCreationDate(this.getCreationDate());
|
|
39751
|
+
}
|
|
39752
|
+
if (this.getCreator() !== undefined) {
|
|
39753
|
+
pdfCopy.setCreator(this.getCreator());
|
|
39754
|
+
}
|
|
39755
|
+
if (this.getModificationDate() !== undefined) {
|
|
39756
|
+
pdfCopy.setModificationDate(this.getModificationDate());
|
|
39757
|
+
}
|
|
39758
|
+
if (this.getProducer() !== undefined) {
|
|
39759
|
+
pdfCopy.setProducer(this.getProducer());
|
|
39760
|
+
}
|
|
39761
|
+
if (this.getSubject() !== undefined) {
|
|
39762
|
+
pdfCopy.setSubject(this.getSubject());
|
|
39763
|
+
}
|
|
39764
|
+
if (this.getTitle() !== undefined) {
|
|
39765
|
+
pdfCopy.setTitle(this.getTitle());
|
|
39766
|
+
}
|
|
39767
|
+
pdfCopy.defaultWordBreaks = this.defaultWordBreaks;
|
|
39768
|
+
return pdfCopy;
|
|
39773
39769
|
}
|
|
39774
39770
|
/**
|
|
39775
39771
|
* Add JavaScript to this document. The supplied `script` is executed when the
|
|
@@ -39858,23 +39854,21 @@ class PDFDocument {
|
|
|
39858
39854
|
* @param name The name of the file to be attached.
|
|
39859
39855
|
* @returns Resolves when the attachment is complete.
|
|
39860
39856
|
*/
|
|
39861
|
-
attach(attachment, name, options = {}) {
|
|
39862
|
-
|
|
39863
|
-
|
|
39864
|
-
|
|
39865
|
-
|
|
39866
|
-
|
|
39867
|
-
|
|
39868
|
-
|
|
39869
|
-
|
|
39870
|
-
|
|
39871
|
-
|
|
39872
|
-
|
|
39873
|
-
|
|
39874
|
-
|
|
39875
|
-
|
|
39876
|
-
this.embeddedFiles.push(embeddedFile);
|
|
39877
|
-
});
|
|
39857
|
+
async attach(attachment, name, options = {}) {
|
|
39858
|
+
assertIs(attachment, 'attachment', ['string', Uint8Array, ArrayBuffer]);
|
|
39859
|
+
assertIs(name, 'name', ['string']);
|
|
39860
|
+
assertOrUndefined(options.mimeType, 'mimeType', ['string']);
|
|
39861
|
+
assertOrUndefined(options.description, 'description', ['string']);
|
|
39862
|
+
assertOrUndefined(options.creationDate, 'options.creationDate', [Date]);
|
|
39863
|
+
assertOrUndefined(options.modificationDate, 'options.modificationDate', [
|
|
39864
|
+
Date,
|
|
39865
|
+
]);
|
|
39866
|
+
assertIsOneOfOrUndefined(options.afRelationship, 'options.afRelationship', AFRelationship);
|
|
39867
|
+
const bytes = toUint8Array(attachment);
|
|
39868
|
+
const embedder = FileEmbedder.for(bytes, name, options);
|
|
39869
|
+
const ref = this.context.nextRef();
|
|
39870
|
+
const embeddedFile = PDFEmbeddedFile.of(ref, this, embedder);
|
|
39871
|
+
this.embeddedFiles.push(embeddedFile);
|
|
39878
39872
|
}
|
|
39879
39873
|
/**
|
|
39880
39874
|
* Embed a font into this document. The input data can be provided in multiple
|
|
@@ -39911,30 +39905,28 @@ class PDFDocument {
|
|
|
39911
39905
|
* @param options The options to be used when embedding the font.
|
|
39912
39906
|
* @returns Resolves with the embedded font.
|
|
39913
39907
|
*/
|
|
39914
|
-
embedFont(font, options = {}) {
|
|
39915
|
-
|
|
39916
|
-
|
|
39917
|
-
|
|
39918
|
-
|
|
39919
|
-
|
|
39920
|
-
|
|
39921
|
-
|
|
39922
|
-
|
|
39923
|
-
|
|
39924
|
-
|
|
39925
|
-
|
|
39926
|
-
|
|
39927
|
-
|
|
39928
|
-
|
|
39929
|
-
|
|
39930
|
-
|
|
39931
|
-
|
|
39932
|
-
|
|
39933
|
-
|
|
39934
|
-
|
|
39935
|
-
|
|
39936
|
-
return pdfFont;
|
|
39937
|
-
});
|
|
39908
|
+
async embedFont(font, options = {}) {
|
|
39909
|
+
const { subset = false, customName, features } = options;
|
|
39910
|
+
assertIs(font, 'font', ['string', Uint8Array, ArrayBuffer]);
|
|
39911
|
+
assertIs(subset, 'subset', ['boolean']);
|
|
39912
|
+
let embedder;
|
|
39913
|
+
if (isStandardFont(font)) {
|
|
39914
|
+
embedder = StandardFontEmbedder.for(font, customName);
|
|
39915
|
+
}
|
|
39916
|
+
else if (canBeConvertedToUint8Array(font)) {
|
|
39917
|
+
const bytes = toUint8Array(font);
|
|
39918
|
+
const fontkit = this.assertFontkit();
|
|
39919
|
+
embedder = subset
|
|
39920
|
+
? await CustomFontSubsetEmbedder.for(fontkit, bytes, customName, features)
|
|
39921
|
+
: await CustomFontEmbedder.for(fontkit, bytes, customName, features);
|
|
39922
|
+
}
|
|
39923
|
+
else {
|
|
39924
|
+
throw new TypeError('`font` must be one of `StandardFonts | string | Uint8Array | ArrayBuffer`');
|
|
39925
|
+
}
|
|
39926
|
+
const ref = this.context.nextRef();
|
|
39927
|
+
const pdfFont = PDFFont.of(ref, this, embedder);
|
|
39928
|
+
this.fonts.push(pdfFont);
|
|
39929
|
+
return pdfFont;
|
|
39938
39930
|
}
|
|
39939
39931
|
/**
|
|
39940
39932
|
* Embed a standard font into this document.
|
|
@@ -39988,16 +39980,14 @@ class PDFDocument {
|
|
|
39988
39980
|
* @param jpg The input data for a JPEG image.
|
|
39989
39981
|
* @returns Resolves with the embedded image.
|
|
39990
39982
|
*/
|
|
39991
|
-
embedJpg(jpg) {
|
|
39992
|
-
|
|
39993
|
-
|
|
39994
|
-
|
|
39995
|
-
|
|
39996
|
-
|
|
39997
|
-
|
|
39998
|
-
|
|
39999
|
-
return pdfImage;
|
|
40000
|
-
});
|
|
39983
|
+
async embedJpg(jpg) {
|
|
39984
|
+
assertIs(jpg, 'jpg', ['string', Uint8Array, ArrayBuffer]);
|
|
39985
|
+
const bytes = toUint8Array(jpg);
|
|
39986
|
+
const embedder = await JpegEmbedder.for(bytes);
|
|
39987
|
+
const ref = this.context.nextRef();
|
|
39988
|
+
const pdfImage = PDFImage.of(ref, this, embedder);
|
|
39989
|
+
this.images.push(pdfImage);
|
|
39990
|
+
return pdfImage;
|
|
40001
39991
|
}
|
|
40002
39992
|
/**
|
|
40003
39993
|
* Embed a PNG image into this document. The input data can be provided in
|
|
@@ -40029,16 +40019,14 @@ class PDFDocument {
|
|
|
40029
40019
|
* @param png The input data for a PNG image.
|
|
40030
40020
|
* @returns Resolves with the embedded image.
|
|
40031
40021
|
*/
|
|
40032
|
-
embedPng(png) {
|
|
40033
|
-
|
|
40034
|
-
|
|
40035
|
-
|
|
40036
|
-
|
|
40037
|
-
|
|
40038
|
-
|
|
40039
|
-
|
|
40040
|
-
return pdfImage;
|
|
40041
|
-
});
|
|
40022
|
+
async embedPng(png) {
|
|
40023
|
+
assertIs(png, 'png', ['string', Uint8Array, ArrayBuffer]);
|
|
40024
|
+
const bytes = toUint8Array(png);
|
|
40025
|
+
const embedder = await PngEmbedder.for(bytes);
|
|
40026
|
+
const ref = this.context.nextRef();
|
|
40027
|
+
const pdfImage = PDFImage.of(ref, this, embedder);
|
|
40028
|
+
this.images.push(pdfImage);
|
|
40029
|
+
return pdfImage;
|
|
40042
40030
|
}
|
|
40043
40031
|
/**
|
|
40044
40032
|
* Embed one or more PDF pages into this document.
|
|
@@ -40060,19 +40048,17 @@ class PDFDocument {
|
|
|
40060
40048
|
* @param indices The indices of the pages that should be embedded.
|
|
40061
40049
|
* @returns Resolves with an array of the embedded pages.
|
|
40062
40050
|
*/
|
|
40063
|
-
embedPdf(pdf, indices = [0]) {
|
|
40064
|
-
|
|
40065
|
-
|
|
40066
|
-
|
|
40067
|
-
|
|
40068
|
-
|
|
40069
|
-
|
|
40070
|
-
|
|
40071
|
-
|
|
40072
|
-
|
|
40073
|
-
|
|
40074
|
-
return this.embedPages(srcPages);
|
|
40075
|
-
});
|
|
40051
|
+
async embedPdf(pdf, indices = [0]) {
|
|
40052
|
+
assertIs(pdf, 'pdf', [
|
|
40053
|
+
'string',
|
|
40054
|
+
Uint8Array,
|
|
40055
|
+
ArrayBuffer,
|
|
40056
|
+
[PDFDocument, 'PDFDocument'],
|
|
40057
|
+
]);
|
|
40058
|
+
assertIs(indices, 'indices', [Array]);
|
|
40059
|
+
const srcDoc = pdf instanceof PDFDocument ? pdf : await PDFDocument.load(pdf);
|
|
40060
|
+
const srcPages = pluckIndices(srcDoc.getPages(), indices);
|
|
40061
|
+
return this.embedPages(srcPages);
|
|
40076
40062
|
}
|
|
40077
40063
|
/**
|
|
40078
40064
|
* Embed a single PDF page into this document.
|
|
@@ -40106,12 +40092,10 @@ class PDFDocument {
|
|
|
40106
40092
|
* page anywhere it is drawn.
|
|
40107
40093
|
* @returns Resolves with the embedded pdf page.
|
|
40108
40094
|
*/
|
|
40109
|
-
embedPage(page, boundingBox, transformationMatrix) {
|
|
40110
|
-
|
|
40111
|
-
|
|
40112
|
-
|
|
40113
|
-
return embeddedPage;
|
|
40114
|
-
});
|
|
40095
|
+
async embedPage(page, boundingBox, transformationMatrix) {
|
|
40096
|
+
assertIs(page, 'page', [[PDFPage, 'PDFPage']]);
|
|
40097
|
+
const [embeddedPage] = await this.embedPages([page], [boundingBox], [transformationMatrix]);
|
|
40098
|
+
return embeddedPage;
|
|
40115
40099
|
}
|
|
40116
40100
|
/**
|
|
40117
40101
|
* Embed one or more PDF pages into this document.
|
|
@@ -40141,34 +40125,32 @@ class PDFDocument {
|
|
|
40141
40125
|
* (each page's transformation will apply anywhere it is drawn).
|
|
40142
40126
|
* @returns Resolves with an array of the embedded pdf pages.
|
|
40143
40127
|
*/
|
|
40144
|
-
embedPages(pages, boundingBoxes = [], transformationMatrices = []) {
|
|
40145
|
-
|
|
40146
|
-
|
|
40147
|
-
|
|
40148
|
-
|
|
40149
|
-
|
|
40150
|
-
|
|
40151
|
-
|
|
40152
|
-
|
|
40153
|
-
|
|
40154
|
-
|
|
40155
|
-
|
|
40156
|
-
|
|
40157
|
-
|
|
40158
|
-
|
|
40159
|
-
|
|
40160
|
-
|
|
40161
|
-
|
|
40162
|
-
|
|
40163
|
-
|
|
40164
|
-
|
|
40165
|
-
|
|
40166
|
-
|
|
40167
|
-
|
|
40168
|
-
|
|
40169
|
-
|
|
40170
|
-
return embeddedPages;
|
|
40171
|
-
});
|
|
40128
|
+
async embedPages(pages, boundingBoxes = [], transformationMatrices = []) {
|
|
40129
|
+
if (pages.length === 0)
|
|
40130
|
+
return [];
|
|
40131
|
+
// Assert all pages have the same context
|
|
40132
|
+
for (let idx = 0, len = pages.length - 1; idx < len; idx++) {
|
|
40133
|
+
const currPage = pages[idx];
|
|
40134
|
+
const nextPage = pages[idx + 1];
|
|
40135
|
+
if (currPage.node.context !== nextPage.node.context) {
|
|
40136
|
+
throw new PageEmbeddingMismatchedContextError();
|
|
40137
|
+
}
|
|
40138
|
+
}
|
|
40139
|
+
const context = pages[0].node.context;
|
|
40140
|
+
const maybeCopyPage = context === this.context
|
|
40141
|
+
? (p) => p
|
|
40142
|
+
: PDFObjectCopier.for(context, this.context).copy;
|
|
40143
|
+
const embeddedPages = new Array(pages.length);
|
|
40144
|
+
for (let idx = 0, len = pages.length; idx < len; idx++) {
|
|
40145
|
+
const page = maybeCopyPage(pages[idx].node);
|
|
40146
|
+
const box = boundingBoxes[idx];
|
|
40147
|
+
const matrix = transformationMatrices[idx];
|
|
40148
|
+
const embedder = await PDFPageEmbedder.for(page, box, matrix);
|
|
40149
|
+
const ref = this.context.nextRef();
|
|
40150
|
+
embeddedPages[idx] = PDFEmbeddedPage.of(ref, this, embedder);
|
|
40151
|
+
}
|
|
40152
|
+
this.embeddedPages.push(...embeddedPages);
|
|
40153
|
+
return embeddedPages;
|
|
40172
40154
|
}
|
|
40173
40155
|
/**
|
|
40174
40156
|
* > **NOTE:** You shouldn't need to call this method directly. The [[save]]
|
|
@@ -40180,14 +40162,12 @@ class PDFDocument {
|
|
|
40180
40162
|
*
|
|
40181
40163
|
* @returns Resolves when the flush is complete.
|
|
40182
40164
|
*/
|
|
40183
|
-
flush() {
|
|
40184
|
-
|
|
40185
|
-
|
|
40186
|
-
|
|
40187
|
-
|
|
40188
|
-
|
|
40189
|
-
yield this.embedAll(this.javaScripts);
|
|
40190
|
-
});
|
|
40165
|
+
async flush() {
|
|
40166
|
+
await this.embedAll(this.fonts);
|
|
40167
|
+
await this.embedAll(this.images);
|
|
40168
|
+
await this.embedAll(this.embeddedPages);
|
|
40169
|
+
await this.embedAll(this.embeddedFiles);
|
|
40170
|
+
await this.embedAll(this.javaScripts);
|
|
40191
40171
|
}
|
|
40192
40172
|
/**
|
|
40193
40173
|
* Serialize this document to an array of bytes making up a PDF file.
|
|
@@ -40205,24 +40185,22 @@ class PDFDocument {
|
|
|
40205
40185
|
* @param options The options to be used when saving the document.
|
|
40206
40186
|
* @returns Resolves with the bytes of the serialized document.
|
|
40207
40187
|
*/
|
|
40208
|
-
save(options = {}) {
|
|
40209
|
-
|
|
40210
|
-
|
|
40211
|
-
|
|
40212
|
-
|
|
40213
|
-
|
|
40214
|
-
|
|
40215
|
-
|
|
40216
|
-
|
|
40217
|
-
|
|
40218
|
-
|
|
40219
|
-
|
|
40220
|
-
|
|
40221
|
-
|
|
40222
|
-
|
|
40223
|
-
|
|
40224
|
-
return Writer.forContext(this.context, objectsPerTick).serializeToBuffer();
|
|
40225
|
-
});
|
|
40188
|
+
async save(options = {}) {
|
|
40189
|
+
const { useObjectStreams = true, addDefaultPage = true, objectsPerTick = 50, updateFieldAppearances = true, } = options;
|
|
40190
|
+
assertIs(useObjectStreams, 'useObjectStreams', ['boolean']);
|
|
40191
|
+
assertIs(addDefaultPage, 'addDefaultPage', ['boolean']);
|
|
40192
|
+
assertIs(objectsPerTick, 'objectsPerTick', ['number']);
|
|
40193
|
+
assertIs(updateFieldAppearances, 'updateFieldAppearances', ['boolean']);
|
|
40194
|
+
if (addDefaultPage && this.getPageCount() === 0)
|
|
40195
|
+
this.addPage();
|
|
40196
|
+
if (updateFieldAppearances) {
|
|
40197
|
+
const form = this.formCache.getValue();
|
|
40198
|
+
if (form)
|
|
40199
|
+
form.updateFieldAppearances();
|
|
40200
|
+
}
|
|
40201
|
+
await this.flush();
|
|
40202
|
+
const Writer = useObjectStreams ? PDFStreamWriter : PDFWriter;
|
|
40203
|
+
return Writer.forContext(this.context, objectsPerTick).serializeToBuffer();
|
|
40226
40204
|
}
|
|
40227
40205
|
/**
|
|
40228
40206
|
* Serialize this document to a base64 encoded string or data URI making up a
|
|
@@ -40239,14 +40217,12 @@ class PDFDocument {
|
|
|
40239
40217
|
* @returns Resolves with a base64 encoded string or data URI of the
|
|
40240
40218
|
* serialized document.
|
|
40241
40219
|
*/
|
|
40242
|
-
saveAsBase64(options = {}) {
|
|
40243
|
-
|
|
40244
|
-
|
|
40245
|
-
|
|
40246
|
-
|
|
40247
|
-
|
|
40248
|
-
return dataUri ? `data:application/pdf;base64,${base64}` : base64;
|
|
40249
|
-
});
|
|
40220
|
+
async saveAsBase64(options = {}) {
|
|
40221
|
+
const { dataUri = false, ...otherOptions } = options;
|
|
40222
|
+
assertIs(dataUri, 'dataUri', ['boolean']);
|
|
40223
|
+
const bytes = await this.save(otherOptions);
|
|
40224
|
+
const base64 = encodeToBase64(bytes);
|
|
40225
|
+
return dataUri ? `data:application/pdf;base64,${base64}` : base64;
|
|
40250
40226
|
}
|
|
40251
40227
|
findPageForAnnotationRef(ref) {
|
|
40252
40228
|
const pages = this.getPages();
|
|
@@ -40259,12 +40235,10 @@ class PDFDocument {
|
|
|
40259
40235
|
}
|
|
40260
40236
|
return undefined;
|
|
40261
40237
|
}
|
|
40262
|
-
embedAll(embeddables) {
|
|
40263
|
-
|
|
40264
|
-
|
|
40265
|
-
|
|
40266
|
-
}
|
|
40267
|
-
});
|
|
40238
|
+
async embedAll(embeddables) {
|
|
40239
|
+
for (let idx = 0, len = embeddables.length; idx < len; idx++) {
|
|
40240
|
+
await embeddables[idx].embed();
|
|
40241
|
+
}
|
|
40268
40242
|
}
|
|
40269
40243
|
updateInfoDict() {
|
|
40270
40244
|
const pdfLib = `pdf-lib (https://github.com/Hopding/pdf-lib)`;
|
|
@@ -41628,772 +41602,70 @@ exports.isBlock = isBlock;
|
|
|
41628
41602
|
|
|
41629
41603
|
var index = /*@__PURE__*/unwrapExports(dist);
|
|
41630
41604
|
|
|
41631
|
-
|
|
41632
|
-
const FLOAT_APPROXIMATION = 0.000001;
|
|
41633
|
-
/** Calculates the distance between 2 points */
|
|
41634
|
-
const distance = (A, B) => norm(vector(A, B));
|
|
41635
|
-
const distanceCoords = (A, B) => norm(minus(B, A));
|
|
41636
|
-
/** Calculates the distance denoted by a vector */
|
|
41637
|
-
const norm = (vect) => Math.sqrt(vect.x * vect.x + vect.y * vect.y);
|
|
41638
|
-
/** Calculates the orthogonal vector of provided vector */
|
|
41639
|
-
const orthogonal = ({ x, y }) => ({
|
|
41640
|
-
x: -y,
|
|
41641
|
-
y: x,
|
|
41642
|
-
});
|
|
41643
|
-
/** Check if 2 vectors are proportional */
|
|
41644
|
-
const isColinear = ({ x: ux, y: uy }, { x: vx, y: vy }) => isEqual(ux * vy, uy * vx);
|
|
41645
|
-
/** Check if 2 floating values can be considered equals */
|
|
41646
|
-
const isEqual = (a, b) => Math.round(Math.abs(a - b) / FLOAT_APPROXIMATION) === 0;
|
|
41647
|
-
/** Calculate the scalar product between 2 vectors */
|
|
41648
|
-
const scalar = ({ x: ux, y: uy }, { x: vx, y: vy }) => ux * vx + uy * vy;
|
|
41649
|
-
/** Calculate the sum of 2 vectors */
|
|
41650
|
-
const plus = ({ x: ux, y: uy }, { x: vx, y: vy }) => ({ x: ux + vx, y: uy + vy });
|
|
41651
|
-
/** Calculate the vector multiplied by a scalar */
|
|
41652
|
-
const times = ({ x, y }, k = 1) => ({
|
|
41653
|
-
x: k * x,
|
|
41654
|
-
y: k * y,
|
|
41655
|
-
});
|
|
41656
|
-
/** Calculate the difference of 2 vectors */
|
|
41657
|
-
const minus = (u, v) => plus(u, times(v, -1));
|
|
41658
|
-
/** Returns the vector between 2 points. */
|
|
41659
|
-
const vector = (A, B) => minus(B.toCoords(), A.toCoords());
|
|
41660
|
-
/**
|
|
41661
|
-
* Returns the angle between the vector and the horizontal axis (Ox).
|
|
41662
|
-
* The return value is between -PI and PI.
|
|
41663
|
-
* @returns {number} angle in radian between -Pi and Pi
|
|
41664
|
-
*/
|
|
41665
|
-
const orientation = ({ x, y }) => {
|
|
41666
|
-
const alpha = Math.acos(x / Math.sqrt(x * x + y * y));
|
|
41667
|
-
return y > 0 ? alpha : -alpha;
|
|
41668
|
-
};
|
|
41669
|
-
/** Returns the unit vector associated to the provided vector,
|
|
41670
|
-
* or the Null vector (0, 0) if the vector is null
|
|
41671
|
-
*/
|
|
41672
|
-
const unitVector = (u) => {
|
|
41673
|
-
const l = norm(u);
|
|
41674
|
-
return l > 0 ? times(u, 1 / l) : u;
|
|
41675
|
-
};
|
|
41676
|
-
/** Returns the angle from u to v in radian */
|
|
41677
|
-
const angle = (u, v, previousAngle = 0) => {
|
|
41678
|
-
let sweep = orientation(v) - orientation(u);
|
|
41679
|
-
// If the angle has the same sign as the arc orientation, we return the angle as is
|
|
41680
|
-
// Otherwise, we need to correct the value, adding or removing 2π
|
|
41681
|
-
while (Math.abs(previousAngle - sweep) > Math.PI) {
|
|
41682
|
-
sweep += Math.sign(previousAngle - sweep) * 2 * Math.PI;
|
|
41683
|
-
}
|
|
41684
|
-
return sweep;
|
|
41685
|
-
};
|
|
41686
|
-
/** Returns the angle between the lines (BA) and (BC) in radian
|
|
41687
|
-
* @returns {number} the angle in radian, between -Pi and Pi
|
|
41688
|
-
*/
|
|
41689
|
-
const angleABC = (A, B, C, previousAngle = 0) => angle(vector(B, A), vector(B, C), previousAngle);
|
|
41690
|
-
/** Rotate the vector by an angle in radian */
|
|
41691
|
-
const rotate = (vect, teta) => {
|
|
41692
|
-
const { x, y } = vect;
|
|
41693
|
-
const nx = x * Math.cos(teta) - y * Math.sin(teta);
|
|
41694
|
-
const ny = y * Math.cos(teta) + x * Math.sin(teta);
|
|
41695
|
-
return { x: nx, y: ny };
|
|
41696
|
-
};
|
|
41697
|
-
|
|
41698
|
-
class GraphElement {
|
|
41699
|
-
distance(P) {
|
|
41700
|
-
const H = this.orthoProjection(P);
|
|
41701
|
-
return distance(H, P);
|
|
41702
|
-
}
|
|
41703
|
-
}
|
|
41704
|
-
|
|
41705
|
-
class Point extends GraphElement {
|
|
41706
|
-
constructor(coords = { x: 0, y: 0 }) {
|
|
41707
|
-
super();
|
|
41708
|
-
this.x = coords.x;
|
|
41709
|
-
this.y = coords.y;
|
|
41710
|
-
}
|
|
41711
|
-
toCoords() {
|
|
41712
|
-
return { x: this.x, y: this.y };
|
|
41713
|
-
}
|
|
41714
|
-
isEqual(element) {
|
|
41715
|
-
if (!(element instanceof Point))
|
|
41716
|
-
return false;
|
|
41717
|
-
const A = this.toCoords();
|
|
41718
|
-
const B = element.toCoords();
|
|
41719
|
-
return isEqual(A.x, B.x) && isEqual(A.y, B.y);
|
|
41720
|
-
}
|
|
41721
|
-
orthoProjection() {
|
|
41722
|
-
return new Point(this.toCoords());
|
|
41723
|
-
}
|
|
41724
|
-
plus(vect) {
|
|
41725
|
-
const P = new Point(plus(this.toCoords(), vect));
|
|
41726
|
-
return P;
|
|
41727
|
-
}
|
|
41728
|
-
}
|
|
41729
|
-
Point.type = 'PointFixed';
|
|
41730
|
-
|
|
41731
|
-
class Circle extends GraphElement {
|
|
41732
|
-
constructor(O = new Point(), r = 1) {
|
|
41733
|
-
super();
|
|
41734
|
-
this.O = O;
|
|
41735
|
-
this.r = r;
|
|
41736
|
-
}
|
|
41737
|
-
ray() {
|
|
41738
|
-
return this.r;
|
|
41739
|
-
}
|
|
41740
|
-
center() {
|
|
41741
|
-
return this.O;
|
|
41742
|
-
}
|
|
41743
|
-
/** This is used to standardize type Circle | Arc */
|
|
41744
|
-
getCircle() {
|
|
41745
|
-
return this;
|
|
41746
|
-
}
|
|
41747
|
-
isEqual(element) {
|
|
41748
|
-
return (element instanceof Circle &&
|
|
41749
|
-
this.center().isEqual(element.center()) &&
|
|
41750
|
-
isEqual(this.ray(), element.ray()));
|
|
41751
|
-
}
|
|
41752
|
-
includes(P) {
|
|
41753
|
-
return isEqual(distance(this.center(), P), this.ray());
|
|
41754
|
-
}
|
|
41755
|
-
orthoProjection(P) {
|
|
41756
|
-
const center = this.center().toCoords();
|
|
41757
|
-
const coords = P.toCoords();
|
|
41758
|
-
if (distanceCoords(coords, center) < this.ray())
|
|
41759
|
-
return P;
|
|
41760
|
-
const vect = times(unitVector(minus(coords, center)), this.ray());
|
|
41761
|
-
return new Point(plus(center, vect));
|
|
41762
|
-
}
|
|
41763
|
-
}
|
|
41605
|
+
const identityMatrix = [1, 0, 0, 1, 0, 0];
|
|
41764
41606
|
|
|
41765
|
-
|
|
41766
|
-
|
|
41767
|
-
|
|
41768
|
-
|
|
41769
|
-
|
|
41770
|
-
|
|
41771
|
-
|
|
41772
|
-
|
|
41773
|
-
|
|
41774
|
-
|
|
41775
|
-
|
|
41776
|
-
|
|
41777
|
-
|
|
41778
|
-
|
|
41779
|
-
|
|
41780
|
-
|
|
41781
|
-
|
|
41782
|
-
|
|
41783
|
-
|
|
41784
|
-
|
|
41785
|
-
}
|
|
41786
|
-
ray() {
|
|
41787
|
-
return distance(this.center(), this.origin());
|
|
41788
|
-
}
|
|
41789
|
-
isEqual(element) {
|
|
41790
|
-
if (!(element instanceof Arc))
|
|
41791
|
-
return false;
|
|
41792
|
-
const dest = this.destination();
|
|
41793
|
-
const o = this.origin();
|
|
41794
|
-
const eDest = element.destination();
|
|
41795
|
-
const eO = element.origin();
|
|
41796
|
-
return (this.getCircle().isEqual(element.getCircle()) &&
|
|
41797
|
-
((dest.isEqual(eDest) && o.isEqual(eO)) ||
|
|
41798
|
-
(dest.isEqual(eO) && o.isEqual(eDest))));
|
|
41799
|
-
}
|
|
41800
|
-
getCircle() {
|
|
41801
|
-
const circle = new Circle(this.center(), this.ray());
|
|
41802
|
-
return circle;
|
|
41803
|
-
}
|
|
41804
|
-
originVect() {
|
|
41805
|
-
return vector(this.center(), this.origin());
|
|
41806
|
-
}
|
|
41807
|
-
middle() {
|
|
41808
|
-
const halfSweep = this.sweep() / 2;
|
|
41809
|
-
const mid = this.center().plus(rotate(vector(this.center(), this.origin()), halfSweep));
|
|
41810
|
-
return mid;
|
|
41811
|
-
}
|
|
41812
|
-
includes(P) {
|
|
41813
|
-
// As angles are returned between -π and π, we need the middle of the arc
|
|
41814
|
-
return (this.getCircle().includes(P) &&
|
|
41815
|
-
Math.abs(angleABC(this.middle(), this.center(), P)) <=
|
|
41816
|
-
Math.abs(this.sweep() / 2));
|
|
41817
|
-
}
|
|
41818
|
-
orthoProjection(P) {
|
|
41819
|
-
const H = this.getCircle().orthoProjection(P);
|
|
41820
|
-
if (this.includes(H))
|
|
41821
|
-
return H;
|
|
41822
|
-
else {
|
|
41823
|
-
const origin = this.origin().toCoords();
|
|
41824
|
-
const destination = this.destination().toCoords();
|
|
41825
|
-
// Returns the closest between origin and destination
|
|
41826
|
-
const coords = distanceCoords(H.toCoords(), origin) <
|
|
41827
|
-
distanceCoords(H.toCoords(), destination)
|
|
41828
|
-
? origin
|
|
41829
|
-
: destination;
|
|
41830
|
-
return new Point(coords);
|
|
41607
|
+
const combineMatrix = ([a, b, c, d, e, f], [a2, b2, c2, d2, e2, f2]) => [
|
|
41608
|
+
a * a2 + c * b2,
|
|
41609
|
+
b * a2 + d * b2,
|
|
41610
|
+
a * c2 + c * d2,
|
|
41611
|
+
b * c2 + d * d2,
|
|
41612
|
+
a * e2 + c * f2 + e,
|
|
41613
|
+
b * e2 + d * f2 + f,
|
|
41614
|
+
];
|
|
41615
|
+
const applyTransformation = ([a, b, c, d, e, f], { x, y }) => ({
|
|
41616
|
+
x: a * x + c * y + e,
|
|
41617
|
+
y: b * x + d * y + f
|
|
41618
|
+
});
|
|
41619
|
+
const transformationToMatrix = (name, args) => {
|
|
41620
|
+
switch (name) {
|
|
41621
|
+
case 'scale':
|
|
41622
|
+
case 'scaleX':
|
|
41623
|
+
case 'scaleY': {
|
|
41624
|
+
// [sx 0 0 sy 0 0]
|
|
41625
|
+
const [sx, sy = sx] = args;
|
|
41626
|
+
return [name === 'scaleY' ? 1 : sx, 0, 0, name === 'scaleX' ? 1 : sy, 0, 0];
|
|
41831
41627
|
}
|
|
41832
|
-
|
|
41833
|
-
|
|
41834
|
-
|
|
41835
|
-
|
|
41836
|
-
|
|
41837
|
-
|
|
41838
|
-
|
|
41839
|
-
}
|
|
41840
|
-
getPoints() {
|
|
41841
|
-
return [...this.points];
|
|
41842
|
-
}
|
|
41843
|
-
translate(translationVector) {
|
|
41844
|
-
this.points = this.points.map((point) => plus(point, translationVector));
|
|
41845
|
-
}
|
|
41846
|
-
isEqual(element) {
|
|
41847
|
-
if (!(element instanceof Plot))
|
|
41848
|
-
return false;
|
|
41849
|
-
const points = this.getPoints().map((coord) => new Point(coord));
|
|
41850
|
-
const points2 = element.getPoints().map((coord) => new Point(coord));
|
|
41851
|
-
return (points.every((point, i) => point.isEqual(points2[i])) ||
|
|
41852
|
-
points.reverse().every((point, i) => point.isEqual(points2[i])));
|
|
41853
|
-
}
|
|
41854
|
-
orthoProjection(P) {
|
|
41855
|
-
const points = this.getPoints();
|
|
41856
|
-
const orthos = points
|
|
41857
|
-
.slice(0, -1)
|
|
41858
|
-
.map((pt, i) => new Segment(new Point(pt), new Point(points[i + 1])))
|
|
41859
|
-
.map((seg) => seg.orthoProjection(P));
|
|
41860
|
-
let min = Number.POSITIVE_INFINITY;
|
|
41861
|
-
let closest = new Point(points[0]);
|
|
41862
|
-
orthos.forEach((ortho) => {
|
|
41863
|
-
const d = ortho.distance(P);
|
|
41864
|
-
if (d < min) {
|
|
41865
|
-
min = d;
|
|
41866
|
-
closest = ortho;
|
|
41867
|
-
}
|
|
41868
|
-
});
|
|
41869
|
-
return closest;
|
|
41870
|
-
}
|
|
41871
|
-
}
|
|
41872
|
-
|
|
41873
|
-
class Rectangle extends GraphElement {
|
|
41874
|
-
constructor(start = new Point(), end = new Point()) {
|
|
41875
|
-
super();
|
|
41876
|
-
this.start = start;
|
|
41877
|
-
this.end = end;
|
|
41878
|
-
}
|
|
41879
|
-
getSize() {
|
|
41880
|
-
const start = this.start.toCoords();
|
|
41881
|
-
const end = this.end.toCoords();
|
|
41882
|
-
return {
|
|
41883
|
-
width: Math.abs(start.x - end.x),
|
|
41884
|
-
height: Math.abs(start.y - end.y),
|
|
41885
|
-
};
|
|
41886
|
-
}
|
|
41887
|
-
getCoords() {
|
|
41888
|
-
const start = this.start.toCoords();
|
|
41889
|
-
const end = this.end.toCoords();
|
|
41890
|
-
return {
|
|
41891
|
-
x: Math.min(start.x, end.x),
|
|
41892
|
-
y: Math.max(start.y, end.y),
|
|
41893
|
-
};
|
|
41894
|
-
}
|
|
41895
|
-
getStart() {
|
|
41896
|
-
const start = new Point(this.getCoords());
|
|
41897
|
-
return start;
|
|
41898
|
-
}
|
|
41899
|
-
getEnd() {
|
|
41900
|
-
const { width, height } = this.getSize();
|
|
41901
|
-
const end = new Point(this.getStart()).plus({ x: width, y: -height });
|
|
41902
|
-
return end;
|
|
41903
|
-
}
|
|
41904
|
-
center() {
|
|
41905
|
-
const center = new Segment(this.getStart(), this.getEnd()).middle();
|
|
41906
|
-
return center;
|
|
41907
|
-
}
|
|
41908
|
-
isEqual(element) {
|
|
41909
|
-
return (element instanceof Rectangle &&
|
|
41910
|
-
this.getStart().isEqual(element.getStart()) &&
|
|
41911
|
-
this.getEnd().isEqual(element.getEnd()));
|
|
41912
|
-
}
|
|
41913
|
-
orthoProjection(P) {
|
|
41914
|
-
const { x, y } = this.getCoords();
|
|
41915
|
-
const end = this.getEnd().toCoords();
|
|
41916
|
-
const { x: Px, y: Py } = P.toCoords();
|
|
41917
|
-
const Hx = Px < x ? x : Px > end.x ? end.x : Px;
|
|
41918
|
-
const Hy = Py > y ? y : Py < end.y ? end.y : Py;
|
|
41919
|
-
return new Point({ x: Hx, y: Hy });
|
|
41920
|
-
}
|
|
41921
|
-
}
|
|
41922
|
-
Rectangle.type = 'Rectangle';
|
|
41923
|
-
|
|
41924
|
-
function intersections(A, B) {
|
|
41925
|
-
if (A instanceof Point || B instanceof Point)
|
|
41926
|
-
return [];
|
|
41927
|
-
else if (A instanceof Text || B instanceof Text)
|
|
41928
|
-
return [];
|
|
41929
|
-
else if (A instanceof Image || B instanceof Image)
|
|
41930
|
-
return [];
|
|
41931
|
-
// TODO: calculate the coords of the intersection: https://www.emathzone.com/tutorials/geometry/intersection-of-line-and-ellipse.html
|
|
41932
|
-
else if (A instanceof Line)
|
|
41933
|
-
return intersectionsLine(A, B);
|
|
41934
|
-
else if (A instanceof Segment) {
|
|
41935
|
-
return intersectionsLine(A.getLine(), B).filter((P) => A.includes(new Point(P)));
|
|
41936
|
-
}
|
|
41937
|
-
else if (A instanceof Circle)
|
|
41938
|
-
return intersectionsCircle(A, B);
|
|
41939
|
-
else if (A instanceof Arc) {
|
|
41940
|
-
return intersectionsCircle(A.getCircle(), B).filter((P) => A.includes(new Point(P)));
|
|
41941
|
-
}
|
|
41942
|
-
else if (A instanceof Plot)
|
|
41943
|
-
return intersectionsPlot(A, B);
|
|
41944
|
-
else if (A instanceof Rectangle)
|
|
41945
|
-
return intersectionsRectangle(A, B);
|
|
41946
|
-
else if (A instanceof Ellipse)
|
|
41947
|
-
return intersectionsEllipse(A, B);
|
|
41948
|
-
return A;
|
|
41949
|
-
}
|
|
41950
|
-
function intersectionsLine(A, B) {
|
|
41951
|
-
if (B instanceof Line)
|
|
41952
|
-
return intersectionLine(A, B);
|
|
41953
|
-
else if (B instanceof Segment) {
|
|
41954
|
-
return intersectionLine(A, B.getLine()).filter((P) => B.includes(new Point(P)));
|
|
41955
|
-
}
|
|
41956
|
-
else if (B instanceof Circle)
|
|
41957
|
-
return intersectionCircleLine(B, A);
|
|
41958
|
-
else if (B instanceof Arc) {
|
|
41959
|
-
return intersectionsCircle(B.getCircle(), A).filter((P) => B.includes(new Point(P)));
|
|
41960
|
-
}
|
|
41961
|
-
else if (B instanceof Plot)
|
|
41962
|
-
return intersectionsPlot(B, A);
|
|
41963
|
-
else if (B instanceof Rectangle)
|
|
41964
|
-
return intersectionsRectangle(B, A);
|
|
41965
|
-
else if (B instanceof Ellipse)
|
|
41966
|
-
return intersectionsEllipse(B, A);
|
|
41967
|
-
return B;
|
|
41968
|
-
}
|
|
41969
|
-
function intersectionsEllipse(A, B) {
|
|
41970
|
-
if (B instanceof Line)
|
|
41971
|
-
return intersectionsLineAndEllipse(A, B);
|
|
41972
|
-
else if (B instanceof Segment) {
|
|
41973
|
-
return intersectionsEllipse(A, B.getLine()).filter((P) => B.includes(new Point(P)));
|
|
41974
|
-
}
|
|
41975
|
-
// TODO:
|
|
41976
|
-
// else if (B instanceof Circle) return intersectionEllipseCircle(B, A)
|
|
41977
|
-
else if (B instanceof Circle)
|
|
41978
|
-
return [];
|
|
41979
|
-
// TODO:
|
|
41980
|
-
// else if (B instanceof Ellipse) return intersectionEllipseEllipse(B, A)
|
|
41981
|
-
else if (B instanceof Ellipse)
|
|
41982
|
-
return [];
|
|
41983
|
-
else if (B instanceof Arc) {
|
|
41984
|
-
return intersectionsEllipse(A, B.getCircle()).filter((P) => B.includes(new Point(P)));
|
|
41985
|
-
}
|
|
41986
|
-
else if (B instanceof Plot)
|
|
41987
|
-
return intersectionsPlot(B, A);
|
|
41988
|
-
else if (B instanceof Rectangle)
|
|
41989
|
-
return intersectionsRectangle(B, A);
|
|
41990
|
-
return B;
|
|
41991
|
-
}
|
|
41992
|
-
function intersectionsLineAndEllipse(A, B) {
|
|
41993
|
-
const center = A.center().toCoords();
|
|
41994
|
-
const a = A.a();
|
|
41995
|
-
const b = A.b();
|
|
41996
|
-
const rotation = A.rotation();
|
|
41997
|
-
const isLineParallel2YAxis = isEqual(B.dirVect().x, 0);
|
|
41998
|
-
// this is a dummy value to represent a point on the line
|
|
41999
|
-
const p1Y = isLineParallel2YAxis ? 1 : B.y(1);
|
|
42000
|
-
const p1X = isLineParallel2YAxis ? B.origin().toCoords().x : 1;
|
|
42001
|
-
const p1 = { x: p1X, y: p1Y };
|
|
42002
|
-
// this is a dummy value to represent a point on the line
|
|
42003
|
-
const p2Y = isLineParallel2YAxis ? 2 : B.y(2);
|
|
42004
|
-
const p2X = isLineParallel2YAxis ? B.origin().toCoords().x : 2;
|
|
42005
|
-
const p2 = { x: p2X, y: p2Y };
|
|
42006
|
-
const p1Normalized = rotate({ x: p1.x - center.x, y: p1.y - center.y }, -rotation);
|
|
42007
|
-
const p2Normalized = rotate({ x: p2.x - center.x, y: p2.y - center.y }, -rotation);
|
|
42008
|
-
const angular = (p1Normalized.y - p2Normalized.y) / (p1Normalized.x - p2Normalized.x);
|
|
42009
|
-
const linear = p1Normalized.y - angular * p1Normalized.x;
|
|
42010
|
-
const lineY = (x) => angular * x + linear;
|
|
42011
|
-
const denormalize = (coord) => {
|
|
42012
|
-
const rotated = rotate(coord, rotation);
|
|
42013
|
-
return {
|
|
42014
|
-
x: rotated.x + center.x,
|
|
42015
|
-
y: rotated.y + center.y,
|
|
42016
|
-
};
|
|
42017
|
-
};
|
|
42018
|
-
// Intersection with vertical line
|
|
42019
|
-
if (isEqual(p1Normalized.x - p2Normalized.x, 0)) {
|
|
42020
|
-
const x = p1Normalized.x;
|
|
42021
|
-
const delta = b ** 2 - (x ** 2 * b ** 2) / a ** 2;
|
|
42022
|
-
if (delta < 0)
|
|
42023
|
-
return [];
|
|
42024
|
-
else if (delta === 0) {
|
|
42025
|
-
return [{ x, y: 0 }].map(denormalize);
|
|
41628
|
+
case 'translate':
|
|
41629
|
+
case 'translateX':
|
|
41630
|
+
case 'translateY': {
|
|
41631
|
+
// [1 0 0 1 tx ty]
|
|
41632
|
+
const [tx, ty = tx] = args;
|
|
41633
|
+
// -ty is necessary because the pdf's y axis is inverted
|
|
41634
|
+
return [1, 0, 0, 1, name === 'translateY' ? 0 : tx, name === 'translateX' ? 0 : -ty];
|
|
42026
41635
|
}
|
|
42027
|
-
|
|
42028
|
-
|
|
42029
|
-
const
|
|
42030
|
-
|
|
42031
|
-
|
|
42032
|
-
|
|
42033
|
-
|
|
42034
|
-
|
|
42035
|
-
|
|
42036
|
-
|
|
42037
|
-
|
|
42038
|
-
|
|
42039
|
-
|
|
42040
|
-
|
|
42041
|
-
|
|
42042
|
-
|
|
42043
|
-
|
|
42044
|
-
|
|
42045
|
-
|
|
42046
|
-
|
|
42047
|
-
|
|
42048
|
-
return [{ x, y }].map(denormalize);
|
|
42049
|
-
}
|
|
42050
|
-
else {
|
|
42051
|
-
const x1 = (-beta + Math.sqrt(delta)) / (2 * alpha);
|
|
42052
|
-
const y1 = lineY(x1);
|
|
42053
|
-
const x2 = (-beta - Math.sqrt(delta)) / (2 * alpha);
|
|
42054
|
-
const y2 = lineY(x2);
|
|
42055
|
-
return [
|
|
42056
|
-
{ x: x1, y: y1 },
|
|
42057
|
-
{ x: x2, y: y2 },
|
|
42058
|
-
].map(denormalize);
|
|
42059
|
-
}
|
|
42060
|
-
}
|
|
42061
|
-
function intersectionLine(A, B) {
|
|
42062
|
-
if (isColinear(A.dirVect(), B.dirVect()))
|
|
42063
|
-
return [];
|
|
42064
|
-
else {
|
|
42065
|
-
const { x: ux, y: uy } = A.dirVect();
|
|
42066
|
-
const { x: vx, y: vy } = B.dirVect();
|
|
42067
|
-
const { x: xA, y: yA } = A.origin().toCoords();
|
|
42068
|
-
const { x: xB, y: yB } = B.origin().toCoords();
|
|
42069
|
-
const x = (ux * (vx * (yA - yB) + vy * xB) - uy * vx * xA) / (ux * vy - uy * vx);
|
|
42070
|
-
const y = (uy * (vy * (xA - xB) + vx * yB) - ux * vy * yA) / (uy * vx - ux * vy);
|
|
42071
|
-
return [{ x, y }];
|
|
42072
|
-
}
|
|
42073
|
-
}
|
|
42074
|
-
function intersectionsPlot(A, B) {
|
|
42075
|
-
const points = A.getPoints().map((pt) => new Point(pt));
|
|
42076
|
-
const head = points.pop();
|
|
42077
|
-
const segments = points.map((pt, i) => new Segment(pt, points[i + 1] || head));
|
|
42078
|
-
// @ts-ignore
|
|
42079
|
-
const inters = segments.map((s) => intersections(s, B)).flat();
|
|
42080
|
-
return inters;
|
|
42081
|
-
}
|
|
42082
|
-
function intersectionsRectangle(A, B) {
|
|
42083
|
-
const P1 = A.getCoords();
|
|
42084
|
-
const P3 = A.getEnd();
|
|
42085
|
-
const P2 = { x: P1.x, y: P3.y };
|
|
42086
|
-
const P4 = { x: P3.x, y: P1.y };
|
|
42087
|
-
return intersections(new Plot([P1, P2, P3, P4, P1]), B);
|
|
42088
|
-
}
|
|
42089
|
-
function intersectionCircleLine(A, B) {
|
|
42090
|
-
const rA = A.ray();
|
|
42091
|
-
const O = A.center();
|
|
42092
|
-
const H = B.orthoProjection(O);
|
|
42093
|
-
const OH = distance(O, H);
|
|
42094
|
-
// The line is tangeant
|
|
42095
|
-
if (isEqual(OH, rA))
|
|
42096
|
-
return [H];
|
|
42097
|
-
// The line is too far from the circle
|
|
42098
|
-
else if (OH > A.ray())
|
|
42099
|
-
return [];
|
|
42100
|
-
// The line cut the circle in 2 points
|
|
42101
|
-
else {
|
|
42102
|
-
// Pythagore
|
|
42103
|
-
const HP = Math.sqrt(rA * rA - OH * OH);
|
|
42104
|
-
const vect = unitVector(B.dirVect());
|
|
42105
|
-
return [H.plus(times(vect, HP)), H.plus(times(vect, -HP))];
|
|
42106
|
-
}
|
|
42107
|
-
}
|
|
42108
|
-
function intersectionCircle(A, B) {
|
|
42109
|
-
const oA = A.center();
|
|
42110
|
-
const oB = B.center();
|
|
42111
|
-
const rA = A.ray();
|
|
42112
|
-
const rB = B.ray();
|
|
42113
|
-
const axis = vector(oA, oB);
|
|
42114
|
-
const CC = norm(axis);
|
|
42115
|
-
// The circles are tangeant
|
|
42116
|
-
if (isEqual(CC, rA + rB))
|
|
42117
|
-
return [A.orthoProjection(oB).toCoords()];
|
|
42118
|
-
// The circles are too far from eachother
|
|
42119
|
-
else if (CC > rA + rB)
|
|
42120
|
-
return [];
|
|
42121
|
-
// The intersections belong to an orthogonal axis
|
|
42122
|
-
else {
|
|
42123
|
-
const ratio = 1 / 2 + (rA * rA - rB * rB) / (CC * CC) / 2;
|
|
42124
|
-
const H = oA.plus(times(axis, ratio));
|
|
42125
|
-
return intersectionCircleLine(A, new Line(H, H.plus(orthogonal(axis))));
|
|
42126
|
-
}
|
|
42127
|
-
}
|
|
42128
|
-
function intersectionsCircle(A, B) {
|
|
42129
|
-
if (B instanceof Circle)
|
|
42130
|
-
return intersectionCircle(A, B);
|
|
42131
|
-
else if (B instanceof Line)
|
|
42132
|
-
return intersectionCircleLine(A, B);
|
|
42133
|
-
else if (B instanceof Segment) {
|
|
42134
|
-
return intersectionCircleLine(A, B.getLine()).filter((P) => B.includes(new Point(P)));
|
|
42135
|
-
}
|
|
42136
|
-
else if (B instanceof Arc) {
|
|
42137
|
-
return intersectionCircle(A, B.getCircle()).filter((P) => B.includes(new Point(P)));
|
|
42138
|
-
}
|
|
42139
|
-
else if (B instanceof Plot)
|
|
42140
|
-
return intersectionsPlot(B, A);
|
|
42141
|
-
else if (B instanceof Rectangle)
|
|
42142
|
-
return intersectionsRectangle(B, A);
|
|
42143
|
-
else if (B instanceof Ellipse)
|
|
42144
|
-
return intersectionsEllipse(B, A);
|
|
42145
|
-
return B;
|
|
42146
|
-
}
|
|
42147
|
-
function getIntersections(elements) {
|
|
42148
|
-
const checked = [];
|
|
42149
|
-
const inters = [];
|
|
42150
|
-
elements.forEach((elt) => {
|
|
42151
|
-
checked.forEach((e) => inters.push(...intersections(e, elt)));
|
|
42152
|
-
checked.push(elt);
|
|
42153
|
-
});
|
|
42154
|
-
return inters;
|
|
42155
|
-
}
|
|
42156
|
-
|
|
42157
|
-
class Line extends GraphElement {
|
|
42158
|
-
constructor(A = new Point(), B = new Point()) {
|
|
42159
|
-
super();
|
|
42160
|
-
this.A = A;
|
|
42161
|
-
this.B = B;
|
|
42162
|
-
}
|
|
42163
|
-
origin() {
|
|
42164
|
-
return this.A;
|
|
42165
|
-
}
|
|
42166
|
-
dirVect() {
|
|
42167
|
-
return vector(this.A, this.B);
|
|
42168
|
-
}
|
|
42169
|
-
/** Line equation */
|
|
42170
|
-
y(x) {
|
|
42171
|
-
const a = this.a();
|
|
42172
|
-
const b = this.b();
|
|
42173
|
-
return a * x + b;
|
|
42174
|
-
}
|
|
42175
|
-
/** The slope */
|
|
42176
|
-
a() {
|
|
42177
|
-
const dirVect = this.dirVect();
|
|
42178
|
-
return dirVect.y / dirVect.x;
|
|
42179
|
-
}
|
|
42180
|
-
/** Origin y coordinate */
|
|
42181
|
-
b() {
|
|
42182
|
-
const O = this.origin().toCoords();
|
|
42183
|
-
const a = this.a();
|
|
42184
|
-
return O.y - a * O.x;
|
|
42185
|
-
}
|
|
42186
|
-
isEqual(element) {
|
|
42187
|
-
const vect = this.dirVect();
|
|
42188
|
-
return (element instanceof Line &&
|
|
42189
|
-
isColinear(vect, element.dirVect()) &&
|
|
42190
|
-
(isEqual(vect.x, 0)
|
|
42191
|
-
? // We need to take care of the case of the vertical line
|
|
42192
|
-
isEqual(this.origin().toCoords().x, element.origin().toCoords().x)
|
|
42193
|
-
: isEqual(this.b(), element.b())));
|
|
42194
|
-
}
|
|
42195
|
-
/** Reversed line equation */
|
|
42196
|
-
x(y) {
|
|
42197
|
-
const dirVect = this.dirVect();
|
|
42198
|
-
return ((y - this.b()) * dirVect.x) / dirVect.y;
|
|
42199
|
-
}
|
|
42200
|
-
includes(P) {
|
|
42201
|
-
const { x, y } = P.toCoords();
|
|
42202
|
-
const vect = this.dirVect();
|
|
42203
|
-
return isEqual(vect.x, 0)
|
|
42204
|
-
? isEqual(this.origin().toCoords().x, x)
|
|
42205
|
-
: isEqual(this.y(x), y);
|
|
42206
|
-
}
|
|
42207
|
-
/** This is used to standarsize type Segment | HalfLine | Line */
|
|
42208
|
-
getLine() {
|
|
42209
|
-
const line = new Line(this.origin(), this.B);
|
|
42210
|
-
return line;
|
|
42211
|
-
}
|
|
42212
|
-
orthoProjection(P) {
|
|
42213
|
-
const vectOrtho = orthogonal(this.dirVect());
|
|
42214
|
-
const A = new Point(P.toCoords());
|
|
42215
|
-
const ortho = new Line(A, A.plus(vectOrtho));
|
|
42216
|
-
const H = intersectionLine(this, ortho)[0];
|
|
42217
|
-
return new Point(H);
|
|
42218
|
-
}
|
|
42219
|
-
}
|
|
42220
|
-
|
|
42221
|
-
class Segment extends GraphElement {
|
|
42222
|
-
constructor(A = new Point(), B = new Point()) {
|
|
42223
|
-
super();
|
|
42224
|
-
this.A = A;
|
|
42225
|
-
this.B = B;
|
|
42226
|
-
}
|
|
42227
|
-
origin() {
|
|
42228
|
-
return this.A;
|
|
42229
|
-
}
|
|
42230
|
-
destination() {
|
|
42231
|
-
return this.B;
|
|
42232
|
-
}
|
|
42233
|
-
dirVect() {
|
|
42234
|
-
return vector(this.origin(), this.destination());
|
|
42235
|
-
}
|
|
42236
|
-
length() {
|
|
42237
|
-
return distance(this.destination(), this.origin());
|
|
42238
|
-
}
|
|
42239
|
-
isEqual(element) {
|
|
42240
|
-
if (!(element instanceof Segment))
|
|
42241
|
-
return false;
|
|
42242
|
-
const o = this.origin();
|
|
42243
|
-
const dest = this.destination();
|
|
42244
|
-
const oE = element.origin();
|
|
42245
|
-
const destE = element.destination();
|
|
42246
|
-
return (element instanceof Segment &&
|
|
42247
|
-
((o.isEqual(oE) && dest.isEqual(destE)) ||
|
|
42248
|
-
(o.isEqual(destE) && dest.isEqual(oE))));
|
|
42249
|
-
}
|
|
42250
|
-
/** Returns an equivalent line object */
|
|
42251
|
-
getLine() {
|
|
42252
|
-
const line = new Line(this.origin(), this.destination());
|
|
42253
|
-
return line;
|
|
42254
|
-
}
|
|
42255
|
-
includes(P) {
|
|
42256
|
-
const vect = this.dirVect();
|
|
42257
|
-
const otherVect = vector(this.origin(), P);
|
|
42258
|
-
// The vectors are not even colinear
|
|
42259
|
-
if (!isColinear(vect, otherVect))
|
|
42260
|
-
return false;
|
|
42261
|
-
// The point is behind the origin
|
|
42262
|
-
else if (scalar(vect, otherVect) < 0)
|
|
42263
|
-
return false;
|
|
42264
|
-
// The point is after the destination
|
|
42265
|
-
else if (norm(vect) < norm(otherVect))
|
|
42266
|
-
return false;
|
|
42267
|
-
else
|
|
42268
|
-
return true;
|
|
42269
|
-
}
|
|
42270
|
-
middle() {
|
|
42271
|
-
const mid = new Point(plus(this.origin().toCoords(), times(this.dirVect(), 0.5)));
|
|
42272
|
-
return mid;
|
|
42273
|
-
}
|
|
42274
|
-
orthoProjection(P) {
|
|
42275
|
-
const H = this.getLine().orthoProjection(P);
|
|
42276
|
-
const vect = this.dirVect();
|
|
42277
|
-
const origin = this.origin().toCoords();
|
|
42278
|
-
const destination = this.destination().toCoords();
|
|
42279
|
-
const otherVect = vector(this.origin(), H);
|
|
42280
|
-
// The point is before the origin
|
|
42281
|
-
if (scalar(vect, otherVect) < 0)
|
|
42282
|
-
return new Point(origin);
|
|
42283
|
-
// The point is after the destination
|
|
42284
|
-
else if (norm(vect) < norm(otherVect))
|
|
42285
|
-
return new Point(destination);
|
|
42286
|
-
// The point is within the segment
|
|
42287
|
-
else
|
|
42288
|
-
return H;
|
|
42289
|
-
}
|
|
42290
|
-
}
|
|
42291
|
-
Segment.type = 'Segment';
|
|
42292
|
-
|
|
42293
|
-
class Ellipse extends GraphElement {
|
|
42294
|
-
constructor(A = new Point(), B = new Point(), C = new Point()) {
|
|
42295
|
-
super();
|
|
42296
|
-
this.A = A;
|
|
42297
|
-
this.B = B;
|
|
42298
|
-
this.C = C;
|
|
42299
|
-
}
|
|
42300
|
-
center() {
|
|
42301
|
-
const center = this.axis().middle();
|
|
42302
|
-
return center;
|
|
42303
|
-
}
|
|
42304
|
-
axis() {
|
|
42305
|
-
const axis = new Segment(this.A, this.B);
|
|
42306
|
-
return axis;
|
|
42307
|
-
}
|
|
42308
|
-
a() {
|
|
42309
|
-
const axis = this.axis();
|
|
42310
|
-
return Math.max(axis.length() / 2, axis.distance(this.C));
|
|
42311
|
-
}
|
|
42312
|
-
b() {
|
|
42313
|
-
const axis = this.axis();
|
|
42314
|
-
return Math.min(axis.length() / 2, axis.distance(this.C));
|
|
42315
|
-
}
|
|
42316
|
-
rotation() {
|
|
42317
|
-
const axis = this.axis();
|
|
42318
|
-
return axis.length() / 2 > axis.distance(this.C)
|
|
42319
|
-
? orientation(axis.dirVect())
|
|
42320
|
-
: orientation(orthogonal(axis.dirVect()));
|
|
42321
|
-
}
|
|
42322
|
-
getSize() {
|
|
42323
|
-
return { width: 2 * this.a(), height: 2 * this.b() };
|
|
42324
|
-
}
|
|
42325
|
-
isEqual(element) {
|
|
42326
|
-
if (!(element instanceof Ellipse))
|
|
42327
|
-
return false;
|
|
42328
|
-
const a = this.a();
|
|
42329
|
-
const b = this.b();
|
|
42330
|
-
const rotation = this.rotation();
|
|
42331
|
-
const eltA = element.a();
|
|
42332
|
-
const eltB = element.b();
|
|
42333
|
-
const eltRotation = element.rotation();
|
|
42334
|
-
// If the main axis is the same on both ellipse
|
|
42335
|
-
if (eltA < eltB === a < b) {
|
|
42336
|
-
// The rotation is equivalent module PI as the element is symetrical
|
|
42337
|
-
return (isEqual(eltA, a) &&
|
|
42338
|
-
isEqual(eltB, b) &&
|
|
42339
|
-
isEqual(rotation + (Math.PI % Math.PI), eltRotation + (Math.PI % Math.PI)));
|
|
42340
|
-
}
|
|
42341
|
-
// If the small axis is different
|
|
42342
|
-
else {
|
|
42343
|
-
// We add a rotation of PI / 2 to emulate the fact that the main axis are actually orthogonal
|
|
42344
|
-
return (isEqual(eltA, b) &&
|
|
42345
|
-
isEqual(eltB, a) &&
|
|
42346
|
-
isEqual(rotation + (Math.PI % Math.PI), eltRotation + (((3 * Math.PI) / 2) % Math.PI)));
|
|
42347
|
-
}
|
|
42348
|
-
}
|
|
42349
|
-
includes(P) {
|
|
42350
|
-
const { x, y } = P.toCoords();
|
|
42351
|
-
const { x: cx, y: cy } = this.center().toCoords();
|
|
42352
|
-
const teta = this.rotation();
|
|
42353
|
-
return isEqual(Math.pow(((x - cx) * Math.cos(teta) + (y - cy) * Math.sin(teta)) / this.a(), 2) +
|
|
42354
|
-
Math.pow(((x - cx) * Math.sin(teta) - (y - cy) * Math.cos(teta)) / this.b(), 2), 1);
|
|
42355
|
-
}
|
|
42356
|
-
orthoProjection(P) {
|
|
42357
|
-
// We will consider that the parametric projection is a correct approximation of the distance for the current case, even if it is not orthogonal
|
|
42358
|
-
const C = this.center();
|
|
42359
|
-
const axis = this.axis();
|
|
42360
|
-
const CP = vector(C, P);
|
|
42361
|
-
const teta = angle(axis.dirVect(), vector(C, P));
|
|
42362
|
-
const ray = this.polarRay(teta);
|
|
42363
|
-
if (distance(P, this.center()) < ray)
|
|
42364
|
-
return P;
|
|
42365
|
-
const vect = times(unitVector(CP), ray);
|
|
42366
|
-
return new Point(this.center().plus(vect).toCoords());
|
|
42367
|
-
}
|
|
42368
|
-
polarRay(teta) {
|
|
42369
|
-
const a = this.a();
|
|
42370
|
-
const b = this.b();
|
|
42371
|
-
const excentricity = Math.sqrt(Math.abs(a * a - b * b)) / Math.max(a, b);
|
|
42372
|
-
return (Math.min(a, b) / Math.sqrt(1 - Math.pow(excentricity * Math.cos(teta), 2)));
|
|
42373
|
-
}
|
|
42374
|
-
}
|
|
42375
|
-
|
|
42376
|
-
/**
|
|
42377
|
-
* take an array of T and turn it into an 2D-array where each sub array has n elements
|
|
42378
|
-
* ex: [1,2,3,4] -> [[1,2], [3, 4]]
|
|
42379
|
-
* @param arr the array of elements
|
|
42380
|
-
* @param n the size of each sub array
|
|
42381
|
-
*/
|
|
42382
|
-
const groupBy = (arr, n) => {
|
|
42383
|
-
if (arr.length <= n)
|
|
42384
|
-
return [arr];
|
|
42385
|
-
return arr === null || arr === void 0 ? void 0 : arr.reduce((acc, curr, i) => {
|
|
42386
|
-
const index = Math.floor(i / n);
|
|
42387
|
-
if (i % n) {
|
|
42388
|
-
acc[index].push(curr);
|
|
41636
|
+
case 'rotate': {
|
|
41637
|
+
// [cos(a) sin(a) -sin(a) cos(a) 0 0]
|
|
41638
|
+
const [a, x = 0, y = 0] = args;
|
|
41639
|
+
const t1 = transformationToMatrix('translate', [x, y]);
|
|
41640
|
+
const t2 = transformationToMatrix('translate', [-x, -y]);
|
|
41641
|
+
// -args[0] -> the '-' operator is necessary because the pdf rotation system is inverted
|
|
41642
|
+
const aRadians = degreesToRadians(-a);
|
|
41643
|
+
const r = [Math.cos(aRadians), Math.sin(aRadians), -Math.sin(aRadians), Math.cos(aRadians), 0, 0];
|
|
41644
|
+
// rotation around a point is the combination of: translate * rotate * (-translate)
|
|
41645
|
+
return combineMatrix(combineMatrix(t1, r), t2);
|
|
41646
|
+
}
|
|
41647
|
+
case 'skewY':
|
|
41648
|
+
case 'skewX': {
|
|
41649
|
+
// [1 tan(a) 0 1 0 0]
|
|
41650
|
+
// [1 0 tan(a) 1 0 0]
|
|
41651
|
+
// -args[0] -> the '-' operator is necessary because the pdf rotation system is inverted
|
|
41652
|
+
const a = degreesToRadians(-args[0]);
|
|
41653
|
+
const skew = Math.tan(a);
|
|
41654
|
+
const skewX = name === 'skewX' ? skew : 0;
|
|
41655
|
+
const skewY = name === 'skewY' ? skew : 0;
|
|
41656
|
+
return [1, skewY, skewX, 1, 0, 0];
|
|
42389
41657
|
}
|
|
42390
|
-
|
|
42391
|
-
|
|
41658
|
+
case 'matrix': {
|
|
41659
|
+
const [a, b, c, d, e, f] = args;
|
|
41660
|
+
const r = transformationToMatrix('scale', [1, -1]);
|
|
41661
|
+
const m = [a, b, c, d, e, f];
|
|
41662
|
+
return combineMatrix(combineMatrix(r, m), r);
|
|
42392
41663
|
}
|
|
42393
|
-
|
|
42394
|
-
|
|
41664
|
+
default:
|
|
41665
|
+
return identityMatrix;
|
|
41666
|
+
}
|
|
42395
41667
|
};
|
|
42396
|
-
const
|
|
41668
|
+
const combineTransformation = (matrix, name, args) => combineMatrix(matrix, transformationToMatrix(name, args));
|
|
42397
41669
|
const StrokeLineCapMap = {
|
|
42398
41670
|
butt: LineCapStyle.Butt,
|
|
42399
41671
|
round: LineCapStyle.Round,
|
|
@@ -42408,662 +41680,144 @@ const StrokeLineJoinMap = {
|
|
|
42408
41680
|
miter: LineJoinStyle.Miter,
|
|
42409
41681
|
round: LineJoinStyle.Round,
|
|
42410
41682
|
};
|
|
42411
|
-
const getInnerSegment = (start, end, rect) => {
|
|
42412
|
-
const isStartInside = isCoordinateInsideTheRect(start, rect);
|
|
42413
|
-
const isEndInside = isCoordinateInsideTheRect(end, rect);
|
|
42414
|
-
let resultLineStart = start;
|
|
42415
|
-
let resultLineEnd = end;
|
|
42416
|
-
// it means that the segment is already inside the rect
|
|
42417
|
-
if (isEndInside && isStartInside)
|
|
42418
|
-
return new Segment(start, end);
|
|
42419
|
-
const line = new Segment(start, end);
|
|
42420
|
-
const intersection = getIntersections([rect, line]);
|
|
42421
|
-
// if there's no intersection it means that the line doesn't intersects the svgRect and isn't visible
|
|
42422
|
-
if (intersection.length === 0)
|
|
42423
|
-
return;
|
|
42424
|
-
if (!isStartInside) {
|
|
42425
|
-
// replace the line start point by the nearest intersection
|
|
42426
|
-
const nearestPoint = intersection.sort((p1, p2) => distanceCoords(start, p1) - distanceCoords(start, p2))[0];
|
|
42427
|
-
resultLineStart = new Point(nearestPoint);
|
|
42428
|
-
}
|
|
42429
|
-
if (!isEndInside) {
|
|
42430
|
-
// replace the line start point by the nearest intersection
|
|
42431
|
-
const nearestPoint = intersection.sort((p1, p2) => distanceCoords(end, p1) - distanceCoords(end, p2))[0];
|
|
42432
|
-
resultLineEnd = new Point(nearestPoint);
|
|
42433
|
-
}
|
|
42434
|
-
return new Segment(resultLineStart, resultLineEnd);
|
|
42435
|
-
};
|
|
42436
|
-
const cropSvgElement = (svgRect, element) => {
|
|
42437
|
-
var _a, _b;
|
|
42438
|
-
switch (element.tagName) {
|
|
42439
|
-
case 'text': {
|
|
42440
|
-
const fontSize = element.svgAttributes.fontSize || 12;
|
|
42441
|
-
// TODO: compute the right font boundaries to know which characters should be drawn
|
|
42442
|
-
// this is an workaround to draw text that are just a little outside the viewbox boundaries
|
|
42443
|
-
const start = new Point({
|
|
42444
|
-
x: element.svgAttributes.x || 0,
|
|
42445
|
-
y: element.svgAttributes.y || 0,
|
|
42446
|
-
});
|
|
42447
|
-
const paddingRect = new Rectangle(new Point({
|
|
42448
|
-
x: svgRect.start.x - fontSize,
|
|
42449
|
-
y: svgRect.start.y + fontSize,
|
|
42450
|
-
}), new Point({ x: svgRect.end.x + fontSize, y: svgRect.end.y - fontSize }));
|
|
42451
|
-
if (!isCoordinateInsideTheRect(start, paddingRect)) {
|
|
42452
|
-
element.set_content('');
|
|
42453
|
-
}
|
|
42454
|
-
break;
|
|
42455
|
-
}
|
|
42456
|
-
case 'line': {
|
|
42457
|
-
const start = new Point({
|
|
42458
|
-
x: element.svgAttributes.x1,
|
|
42459
|
-
y: element.svgAttributes.y1,
|
|
42460
|
-
});
|
|
42461
|
-
const end = new Point({
|
|
42462
|
-
x: element.svgAttributes.x2,
|
|
42463
|
-
y: element.svgAttributes.y2,
|
|
42464
|
-
});
|
|
42465
|
-
const line = getInnerSegment(start, end, svgRect);
|
|
42466
|
-
element.svgAttributes.x1 = line ? line.A.x : 0;
|
|
42467
|
-
element.svgAttributes.x2 = line ? line.B.x : 0;
|
|
42468
|
-
element.svgAttributes.y1 = line ? line.A.y : 0;
|
|
42469
|
-
element.svgAttributes.y2 = line ? line.B.y : 0;
|
|
42470
|
-
break;
|
|
42471
|
-
}
|
|
42472
|
-
case 'path': {
|
|
42473
|
-
// the path origin coordinate
|
|
42474
|
-
const basePoint = new Point({
|
|
42475
|
-
x: element.svgAttributes.x || 0,
|
|
42476
|
-
y: element.svgAttributes.y || 0,
|
|
42477
|
-
});
|
|
42478
|
-
const normalizePoint = (p) => new Point({ x: p.x - basePoint.x, y: p.y - basePoint.y });
|
|
42479
|
-
/**
|
|
42480
|
-
*
|
|
42481
|
-
* @param origin is the origin of the current drawing in the page coordinate system
|
|
42482
|
-
* @param command the path instruction
|
|
42483
|
-
* @param params the instruction params
|
|
42484
|
-
* @returns the point where the next instruction starts and the new instruction text
|
|
42485
|
-
*/
|
|
42486
|
-
const handlePath = (origin, command, params) => {
|
|
42487
|
-
switch (command) {
|
|
42488
|
-
case 'm':
|
|
42489
|
-
case 'M': {
|
|
42490
|
-
const isLocalInstruction = command === command.toLocaleLowerCase();
|
|
42491
|
-
const nextPoint = new Point({
|
|
42492
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + params[0],
|
|
42493
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + params[1],
|
|
42494
|
-
});
|
|
42495
|
-
return {
|
|
42496
|
-
point: nextPoint,
|
|
42497
|
-
command: `${command}${params[0]},${params[1]}`,
|
|
42498
|
-
};
|
|
42499
|
-
}
|
|
42500
|
-
case 'v':
|
|
42501
|
-
case 'V':
|
|
42502
|
-
case 'h':
|
|
42503
|
-
case 'H':
|
|
42504
|
-
case 'l':
|
|
42505
|
-
case 'L': {
|
|
42506
|
-
const isLocalInstruction = ['l', 'v', 'h'].includes(command);
|
|
42507
|
-
const getNextPoint = () => {
|
|
42508
|
-
switch (command.toLocaleLowerCase()) {
|
|
42509
|
-
case 'l':
|
|
42510
|
-
return new Point({
|
|
42511
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + params[0],
|
|
42512
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + params[1],
|
|
42513
|
-
});
|
|
42514
|
-
case 'v':
|
|
42515
|
-
return new Point({
|
|
42516
|
-
x: origin.x,
|
|
42517
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + params[0],
|
|
42518
|
-
});
|
|
42519
|
-
case 'h':
|
|
42520
|
-
return new Point({
|
|
42521
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + params[0],
|
|
42522
|
-
y: origin.y,
|
|
42523
|
-
});
|
|
42524
|
-
default:
|
|
42525
|
-
return new Point({
|
|
42526
|
-
x: 0,
|
|
42527
|
-
y: 0,
|
|
42528
|
-
});
|
|
42529
|
-
}
|
|
42530
|
-
};
|
|
42531
|
-
const nextPoint = getNextPoint();
|
|
42532
|
-
const normalizedNext = normalizePoint(nextPoint);
|
|
42533
|
-
let endPoint = new Point({ x: nextPoint.x, y: nextPoint.y });
|
|
42534
|
-
let startPoint = new Point({ x: origin.x, y: origin.y });
|
|
42535
|
-
const result = getInnerSegment(startPoint, endPoint, svgRect);
|
|
42536
|
-
if (!result) {
|
|
42537
|
-
return {
|
|
42538
|
-
point: nextPoint,
|
|
42539
|
-
command: `M${normalizedNext.x},${normalizedNext.y}`,
|
|
42540
|
-
};
|
|
42541
|
-
}
|
|
42542
|
-
// if the point wasn't moved it means that it's inside the rect
|
|
42543
|
-
const isStartInside = result.A.isEqual(startPoint);
|
|
42544
|
-
const isEndInside = result.B.isEqual(endPoint);
|
|
42545
|
-
// the intersection points are referencing the pdf coordinates, it's necessary to convert these points to the path's origin point
|
|
42546
|
-
endPoint = normalizePoint(new Point(result.B.toCoords()));
|
|
42547
|
-
startPoint = normalizePoint(new Point(result.A.toCoords()));
|
|
42548
|
-
const startInstruction = isStartInside
|
|
42549
|
-
? ''
|
|
42550
|
-
: `M${startPoint.x},${startPoint.y}`;
|
|
42551
|
-
const endInstruction = isEndInside
|
|
42552
|
-
? ''
|
|
42553
|
-
: `M${normalizedNext.x},${normalizedNext.y}`;
|
|
42554
|
-
return {
|
|
42555
|
-
point: nextPoint,
|
|
42556
|
-
command: `${startInstruction} L${endPoint.x},${endPoint.y} ${endInstruction} `,
|
|
42557
|
-
};
|
|
42558
|
-
}
|
|
42559
|
-
case 'a':
|
|
42560
|
-
case 'A': {
|
|
42561
|
-
const isLocalInstruction = command === 'a';
|
|
42562
|
-
const [, , , , , x, y] = params;
|
|
42563
|
-
const nextPoint = new Point({
|
|
42564
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + x,
|
|
42565
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + y,
|
|
42566
|
-
});
|
|
42567
|
-
// TODO: implement the code to fit the Elliptical Arc Curve instructions into the viewbox
|
|
42568
|
-
return {
|
|
42569
|
-
point: nextPoint,
|
|
42570
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42571
|
-
};
|
|
42572
|
-
}
|
|
42573
|
-
case 'c':
|
|
42574
|
-
case 'C': {
|
|
42575
|
-
const isLocalInstruction = command === 'c';
|
|
42576
|
-
let x = 0;
|
|
42577
|
-
let y = 0;
|
|
42578
|
-
for (let pendingParams = params; pendingParams.length > 0; pendingParams = pendingParams.slice(6)) {
|
|
42579
|
-
const [, , , , pendingX, pendingY] = pendingParams;
|
|
42580
|
-
if (isLocalInstruction) {
|
|
42581
|
-
x += pendingX;
|
|
42582
|
-
y += pendingY;
|
|
42583
|
-
}
|
|
42584
|
-
else {
|
|
42585
|
-
x = pendingX;
|
|
42586
|
-
y = pendingY;
|
|
42587
|
-
}
|
|
42588
|
-
}
|
|
42589
|
-
const nextPoint = new Point({
|
|
42590
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + x,
|
|
42591
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + y,
|
|
42592
|
-
});
|
|
42593
|
-
// TODO: implement the code to fit the Cubic Bézier Curve instructions into the viewbox
|
|
42594
|
-
return {
|
|
42595
|
-
point: nextPoint,
|
|
42596
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42597
|
-
};
|
|
42598
|
-
}
|
|
42599
|
-
case 's':
|
|
42600
|
-
case 'S':
|
|
42601
|
-
const isLocalInstruction = command === 's';
|
|
42602
|
-
let x = 0;
|
|
42603
|
-
let y = 0;
|
|
42604
|
-
for (let pendingParams = params; pendingParams.length > 0; pendingParams = pendingParams.slice(4)) {
|
|
42605
|
-
const [, , pendingX, pendingY] = pendingParams;
|
|
42606
|
-
x += pendingX;
|
|
42607
|
-
y += pendingY;
|
|
42608
|
-
}
|
|
42609
|
-
const nextPoint = new Point({
|
|
42610
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + x,
|
|
42611
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + y,
|
|
42612
|
-
});
|
|
42613
|
-
return {
|
|
42614
|
-
point: nextPoint,
|
|
42615
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42616
|
-
};
|
|
42617
|
-
case 'q':
|
|
42618
|
-
case 'Q': {
|
|
42619
|
-
const isLocalInstruction = command === 'q';
|
|
42620
|
-
const [, , x, y] = params;
|
|
42621
|
-
const nextPoint = new Point({
|
|
42622
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + x,
|
|
42623
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + y,
|
|
42624
|
-
});
|
|
42625
|
-
// TODO: implement the code to fit the Quadratic Bézier Curve instructions into the viewbox
|
|
42626
|
-
return {
|
|
42627
|
-
point: nextPoint,
|
|
42628
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42629
|
-
};
|
|
42630
|
-
}
|
|
42631
|
-
// TODO: Handle the remaining svg instructions: t,q
|
|
42632
|
-
default:
|
|
42633
|
-
return {
|
|
42634
|
-
point: origin,
|
|
42635
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42636
|
-
};
|
|
42637
|
-
}
|
|
42638
|
-
};
|
|
42639
|
-
const commands = (_a = element.svgAttributes.d) === null || _a === void 0 ? void 0 : _a.match(/(v|h|a|l|t|m|q|c|s|z)([0-9,e\s.-]*)/gi);
|
|
42640
|
-
let currentPoint = new Point({ x: basePoint.x, y: basePoint.y });
|
|
42641
|
-
const newPath = commands === null || commands === void 0 ? void 0 : commands.map((command) => {
|
|
42642
|
-
var _a, _b;
|
|
42643
|
-
const letter = (_a = command.match(/[a-z]/i)) === null || _a === void 0 ? void 0 : _a[0];
|
|
42644
|
-
const params = (_b = command
|
|
42645
|
-
.match(/(-?[0-9]+\.[0-9]+(e[+-]?[0-9]+)?)|(-?\.[0-9]+(e[+-]?[0-9]+)?)|(-?[0-9]+)/gi)) === null || _b === void 0 ? void 0 : _b.filter((m) => m !== '').map((v) => parseFloat(v));
|
|
42646
|
-
if (letter && params) {
|
|
42647
|
-
const result = handlePath(currentPoint, letter, params);
|
|
42648
|
-
if (result) {
|
|
42649
|
-
currentPoint = result.point;
|
|
42650
|
-
return result.command;
|
|
42651
|
-
}
|
|
42652
|
-
}
|
|
42653
|
-
return command;
|
|
42654
|
-
}).join(' ');
|
|
42655
|
-
element.svgAttributes.d = newPath;
|
|
42656
|
-
break;
|
|
42657
|
-
}
|
|
42658
|
-
case 'ellipse':
|
|
42659
|
-
case 'circle': {
|
|
42660
|
-
if (element.svgAttributes.cx === undefined ||
|
|
42661
|
-
element.svgAttributes.cy === undefined ||
|
|
42662
|
-
element.svgAttributes.rx === undefined ||
|
|
42663
|
-
element.svgAttributes.ry === undefined) {
|
|
42664
|
-
break;
|
|
42665
|
-
}
|
|
42666
|
-
const { cx = 0, cy = 0, rx = 0, ry = 0 } = element.svgAttributes;
|
|
42667
|
-
const center = new Point({
|
|
42668
|
-
x: cx,
|
|
42669
|
-
y: cy,
|
|
42670
|
-
});
|
|
42671
|
-
const rotation = ((_b = element.svgAttributes.rotation) === null || _b === void 0 ? void 0 : _b.angle) || 0;
|
|
42672
|
-
// these points are relative to the ellipse's center
|
|
42673
|
-
const a = new Point(rotate({ x: -rx, y: 0 }, degreesToRadians(rotation)));
|
|
42674
|
-
const b = new Point(rotate({ x: rx, y: 0 }, degreesToRadians(rotation)));
|
|
42675
|
-
const c = new Point(rotate({ x: 0, y: ry }, degreesToRadians(rotation)));
|
|
42676
|
-
// these points are relative to the real coordinate system
|
|
42677
|
-
const A = center.plus(a);
|
|
42678
|
-
const B = center.plus(b);
|
|
42679
|
-
const C = center.plus(c);
|
|
42680
|
-
const ellipse = new Ellipse(A, B, C);
|
|
42681
|
-
const intersections = getIntersections([svgRect, ellipse]);
|
|
42682
|
-
const isCenterInsideRect = isCoordinateInsideTheRect(center, svgRect);
|
|
42683
|
-
/**
|
|
42684
|
-
* if there are less than 2 intersection, there are two possibilities:
|
|
42685
|
-
* - the ellipse is outside the viewbox and therefore isn't visible
|
|
42686
|
-
* - the ellipse is inside the viewbox and don't need to be cropped
|
|
42687
|
-
*/
|
|
42688
|
-
if (intersections.length < 2) {
|
|
42689
|
-
!isCenterInsideRect && element.setAttribute('rx', '0');
|
|
42690
|
-
!isCenterInsideRect && (element.svgAttributes.rx = 0);
|
|
42691
|
-
!isCenterInsideRect && element.setAttribute('ry', '0');
|
|
42692
|
-
!isCenterInsideRect && (element.svgAttributes.ry = 0);
|
|
42693
|
-
break;
|
|
42694
|
-
}
|
|
42695
|
-
// viewbox rectangle coordinates
|
|
42696
|
-
const P1 = new Point(svgRect.getCoords());
|
|
42697
|
-
const P3 = new Point(svgRect.getEnd());
|
|
42698
|
-
const P2 = new Point({ x: P3.x, y: P1.y });
|
|
42699
|
-
const P4 = new Point({ x: P1.x, y: P3.y });
|
|
42700
|
-
const top = new Segment(P1, P2);
|
|
42701
|
-
const right = new Segment(P2, P3);
|
|
42702
|
-
const bottom = new Segment(P3, P4);
|
|
42703
|
-
const left = new Segment(P4, P1);
|
|
42704
|
-
// Warning: keep the order of the segments, it's important when building the path that will represent the ellipse
|
|
42705
|
-
const rectSegments = [top, right, bottom, left];
|
|
42706
|
-
const isPointInsideEllipse = (P) => (P.x - cx) ** 2 / rx ** 2 + (P.y - cy) ** 2 / ry ** 2 <= 1;
|
|
42707
|
-
// check if the rect boundaries are inside the circle
|
|
42708
|
-
const isRectInsideEllipse = isPointInsideEllipse(P1) &&
|
|
42709
|
-
isPointInsideEllipse(P2) &&
|
|
42710
|
-
isPointInsideEllipse(P3) &&
|
|
42711
|
-
isPointInsideEllipse(P4);
|
|
42712
|
-
// the segments that are intersecting the circle. And, therefore, are lines that are cropping the drawing
|
|
42713
|
-
const circleSegments = isRectInsideEllipse
|
|
42714
|
-
? rectSegments
|
|
42715
|
-
: rectSegments.map((segment, i) => {
|
|
42716
|
-
const [p1, p2] = getIntersections([segment, ellipse])
|
|
42717
|
-
// it's important to sort the segment's point because it impacts the angle of the arc, the points are sorted on clockwise direction
|
|
42718
|
-
.sort((p1, p2) => {
|
|
42719
|
-
// top
|
|
42720
|
-
if (i === 0) {
|
|
42721
|
-
return p1.x - p2.x;
|
|
42722
|
-
// right
|
|
42723
|
-
}
|
|
42724
|
-
else if (i === 1) {
|
|
42725
|
-
return p2.y - p1.y;
|
|
42726
|
-
// bottom
|
|
42727
|
-
}
|
|
42728
|
-
else if (i === 2) {
|
|
42729
|
-
return p2.x - p1.x;
|
|
42730
|
-
// left
|
|
42731
|
-
}
|
|
42732
|
-
else {
|
|
42733
|
-
return p1.y - p2.y;
|
|
42734
|
-
}
|
|
42735
|
-
});
|
|
42736
|
-
if (p1 && p2) {
|
|
42737
|
-
return new Segment(new Point(p1), new Point(p2));
|
|
42738
|
-
// if the other point isn't inside the circle it means that the circle isn't cropped by the segment
|
|
42739
|
-
}
|
|
42740
|
-
else if (p1 &&
|
|
42741
|
-
(isPointInsideEllipse(segment.A) ||
|
|
42742
|
-
isPointInsideEllipse(segment.B))) {
|
|
42743
|
-
const intersectionPoint = new Point(p1);
|
|
42744
|
-
const innerPoint = isPointInsideEllipse(segment.A)
|
|
42745
|
-
? segment.A
|
|
42746
|
-
: segment.B;
|
|
42747
|
-
// ensures that the segment is always following the clockwise direction
|
|
42748
|
-
const start = innerPoint.isEqual(segment.A)
|
|
42749
|
-
? innerPoint
|
|
42750
|
-
: intersectionPoint;
|
|
42751
|
-
const end = innerPoint.isEqual(segment.A)
|
|
42752
|
-
? intersectionPoint
|
|
42753
|
-
: innerPoint;
|
|
42754
|
-
return new Segment(start, end);
|
|
42755
|
-
// if there's no intersection and the segment's points are inside the Ellipse it means that the segment should be drawn as part of the ellipse
|
|
42756
|
-
}
|
|
42757
|
-
else if (!(p1 && p2) &&
|
|
42758
|
-
isPointInsideEllipse(segment.A) &&
|
|
42759
|
-
isPointInsideEllipse(segment.B)) {
|
|
42760
|
-
return segment;
|
|
42761
|
-
}
|
|
42762
|
-
return;
|
|
42763
|
-
});
|
|
42764
|
-
const inverseAngle = (angle) => (360 - angle) % 360;
|
|
42765
|
-
const pointsAngle = (p1, p2, direction = 'clockwise') => {
|
|
42766
|
-
const startAngle = radiansToDegrees(Math.atan2(p1.y - center.y, p1.x - center.x));
|
|
42767
|
-
const endAngle = radiansToDegrees(Math.atan2(p2.y - center.y, p2.x - center.x));
|
|
42768
|
-
const arcAngle = (endAngle + (360 - startAngle)) % 360;
|
|
42769
|
-
return direction === 'clockwise' ? arcAngle : inverseAngle(arcAngle);
|
|
42770
|
-
};
|
|
42771
|
-
/**
|
|
42772
|
-
* - draw a line for each segment
|
|
42773
|
-
* - if two segments aren't connected draw an arc connecting them
|
|
42774
|
-
*/
|
|
42775
|
-
let startPoint;
|
|
42776
|
-
// the point where the pen is located
|
|
42777
|
-
let currentPoint;
|
|
42778
|
-
let lastSegment;
|
|
42779
|
-
let path = circleSegments.reduce((path, segment) => {
|
|
42780
|
-
if (!segment)
|
|
42781
|
-
return path;
|
|
42782
|
-
if (!startPoint) {
|
|
42783
|
-
startPoint = segment.A;
|
|
42784
|
-
path = `M ${segment.A.x},${segment.A.y}`;
|
|
42785
|
-
}
|
|
42786
|
-
// if the current segment isn't connected to the last one, connect both with an arc
|
|
42787
|
-
if (lastSegment && !lastSegment.B.isEqual(segment.A)) {
|
|
42788
|
-
const arcAngle = pointsAngle(segment.A, lastSegment.B);
|
|
42789
|
-
// angles greater than 180 degrees are marked as large-arc-flag = 1
|
|
42790
|
-
path += `A ${rx},${ry} ${rotation} ${arcAngle > 180 ? 1 : 0},0 ${segment.A.x}, ${segment.A.y}`;
|
|
42791
|
-
}
|
|
42792
|
-
path += ` L ${segment.B.x},${segment.B.y}`;
|
|
42793
|
-
currentPoint = segment.B;
|
|
42794
|
-
lastSegment = segment;
|
|
42795
|
-
return path;
|
|
42796
|
-
}, '');
|
|
42797
|
-
// if the path isn't closed, close it by drawing an arc
|
|
42798
|
-
if (startPoint && currentPoint && !startPoint.isEqual(currentPoint)) {
|
|
42799
|
-
const arcAngle = pointsAngle(currentPoint, startPoint, 'counter-clockwise');
|
|
42800
|
-
// angles greater than 180 degrees are marked as large-arc-flag = 1
|
|
42801
|
-
path += `A ${rx},${ry} ${rotation} ${arcAngle > 180 ? 1 : 0},0 ${startPoint.x}, ${startPoint.y}`;
|
|
42802
|
-
}
|
|
42803
|
-
// create a new element that will represent the cropped ellipse
|
|
42804
|
-
const newElement = index.parse(`<path d="${path}" fill="red"/>`).firstChild;
|
|
42805
|
-
const svgAttributes = Object.assign(Object.assign({}, element.svgAttributes), {
|
|
42806
|
-
// the x and y values are 0 because all the path coordinates are global
|
|
42807
|
-
x: 0, y: 0,
|
|
42808
|
-
// the path coordinates are already rotated
|
|
42809
|
-
rotate: undefined, d: path });
|
|
42810
|
-
Object.assign(newElement, { svgAttributes });
|
|
42811
|
-
return newElement;
|
|
42812
|
-
}
|
|
42813
|
-
case 'rect': {
|
|
42814
|
-
const { x = 0, y = 0, width = 0, height = 0, rotate: rawRotation, } = element.svgAttributes;
|
|
42815
|
-
const rotation = (rawRotation === null || rawRotation === void 0 ? void 0 : rawRotation.angle) || 0;
|
|
42816
|
-
if (!(width && height))
|
|
42817
|
-
return element;
|
|
42818
|
-
// bottomLeft point
|
|
42819
|
-
const origin = new Point({ x, y });
|
|
42820
|
-
const rotateAroundOrigin = (p) => new Point(rotate(normalize(p), degreesToRadians(rotation))).plus(origin);
|
|
42821
|
-
const normalize = (p) => p.plus({ x: -origin.x, y: -origin.y });
|
|
42822
|
-
const topLeft = rotateAroundOrigin(origin.plus({ x: 0, y: -height }));
|
|
42823
|
-
const topRight = rotateAroundOrigin(origin.plus({ x: width, y: -height }));
|
|
42824
|
-
const bottomRight = rotateAroundOrigin(origin.plus({ x: width, y: 0 }));
|
|
42825
|
-
const pointToString = (p) => [p.x, p.y].join();
|
|
42826
|
-
const d = `M${pointToString(topLeft)} L${pointToString(topRight)} L${pointToString(bottomRight)} L${pointToString(origin)} L${pointToString(topLeft)}`;
|
|
42827
|
-
const el = index.parse(`<path d="${d}"/>`).firstChild;
|
|
42828
|
-
const newAttributes = Object.assign(Object.assign({}, element.svgAttributes), { d, x: 0, y: 0 });
|
|
42829
|
-
// @ts-ignore
|
|
42830
|
-
delete newAttributes.width;
|
|
42831
|
-
// @ts-ignore
|
|
42832
|
-
delete newAttributes.height;
|
|
42833
|
-
delete newAttributes.rotate;
|
|
42834
|
-
delete newAttributes.rotation;
|
|
42835
|
-
Object.assign(el, {
|
|
42836
|
-
svgAttributes: newAttributes,
|
|
42837
|
-
});
|
|
42838
|
-
return cropSvgElement(svgRect, el);
|
|
42839
|
-
}
|
|
42840
|
-
// TODO: implement the crop for the following elements
|
|
42841
|
-
case 'image':
|
|
42842
|
-
default:
|
|
42843
|
-
return element;
|
|
42844
|
-
}
|
|
42845
|
-
return element;
|
|
42846
|
-
};
|
|
42847
41683
|
// TODO: Improve type system to require the correct props for each tagName.
|
|
42848
41684
|
/** methods to draw SVGElements onto a PDFPage */
|
|
42849
41685
|
const runnersToPage = (page, options) => ({
|
|
42850
|
-
text(element) {
|
|
42851
|
-
|
|
42852
|
-
|
|
42853
|
-
|
|
42854
|
-
|
|
42855
|
-
|
|
42856
|
-
|
|
42857
|
-
|
|
42858
|
-
|
|
42859
|
-
|
|
42860
|
-
|
|
42861
|
-
|
|
42862
|
-
|
|
42863
|
-
|
|
42864
|
-
|
|
42865
|
-
|
|
42866
|
-
|
|
42867
|
-
|
|
42868
|
-
|
|
42869
|
-
|
|
42870
|
-
|
|
42871
|
-
|
|
42872
|
-
|
|
42873
|
-
|
|
42874
|
-
|
|
42875
|
-
|
|
42876
|
-
|
|
42877
|
-
|
|
42878
|
-
|
|
42879
|
-
|
|
42880
|
-
|
|
42881
|
-
|
|
42882
|
-
|
|
42883
|
-
|
|
42884
|
-
|
|
42885
|
-
|
|
42886
|
-
|
|
42887
|
-
|
|
42888
|
-
|
|
42889
|
-
|
|
42890
|
-
font,
|
|
42891
|
-
size: fontSize,
|
|
42892
|
-
color: element.svgAttributes.fill,
|
|
42893
|
-
opacity: element.svgAttributes.fillOpacity,
|
|
42894
|
-
rotate: element.svgAttributes.rotate,
|
|
42895
|
-
});
|
|
41686
|
+
async text(element) {
|
|
41687
|
+
const anchor = element.svgAttributes.textAnchor;
|
|
41688
|
+
const dominantBaseline = element.svgAttributes.dominantBaseline;
|
|
41689
|
+
const text = element.text.trim().replace(/\s/g, ' ');
|
|
41690
|
+
const fontSize = element.svgAttributes.fontSize || 12;
|
|
41691
|
+
/** This will find the best font for the provided style in the list */
|
|
41692
|
+
function getBestFont(style, fonts) {
|
|
41693
|
+
const family = style.fontFamily;
|
|
41694
|
+
if (!family)
|
|
41695
|
+
return undefined;
|
|
41696
|
+
const isBold = style.fontWeight === 'bold' || Number(style.fontWeight) >= 700;
|
|
41697
|
+
const isItalic = style.fontStyle === 'italic';
|
|
41698
|
+
const getFont = (bold, italic, family) => fonts[family + (bold ? '_bold' : '') + (italic ? '_italic' : '')];
|
|
41699
|
+
return (getFont(isBold, isItalic, family) ||
|
|
41700
|
+
getFont(isBold, false, family) ||
|
|
41701
|
+
getFont(false, isItalic, family) ||
|
|
41702
|
+
getFont(false, false, family) ||
|
|
41703
|
+
Object.keys(fonts).find((fontFamily) => fontFamily.startsWith(family)));
|
|
41704
|
+
}
|
|
41705
|
+
const font = options.fonts && getBestFont(element.svgAttributes, options.fonts);
|
|
41706
|
+
const textWidth = (font || page.getFont()[0]).widthOfTextAtSize(text, fontSize);
|
|
41707
|
+
const textHeight = (font || page.getFont()[0]).heightAtSize(fontSize);
|
|
41708
|
+
const offsetX = anchor === 'middle' ? textWidth / 2 : anchor === 'end' ? textWidth : 0;
|
|
41709
|
+
const offsetY = dominantBaseline === 'text-before-edge'
|
|
41710
|
+
? textHeight
|
|
41711
|
+
: dominantBaseline === 'text-after-edge'
|
|
41712
|
+
? -textHeight
|
|
41713
|
+
: dominantBaseline === 'middle'
|
|
41714
|
+
? textHeight / 2
|
|
41715
|
+
: 0;
|
|
41716
|
+
page.drawText(text, {
|
|
41717
|
+
x: -offsetX,
|
|
41718
|
+
y: -offsetY,
|
|
41719
|
+
font,
|
|
41720
|
+
// TODO: the font size should be correctly scaled too
|
|
41721
|
+
size: fontSize,
|
|
41722
|
+
color: element.svgAttributes.fill,
|
|
41723
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41724
|
+
matrix: element.svgAttributes.matrix,
|
|
41725
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42896
41726
|
});
|
|
42897
41727
|
},
|
|
42898
|
-
line(element) {
|
|
42899
|
-
|
|
42900
|
-
|
|
42901
|
-
|
|
42902
|
-
|
|
42903
|
-
|
|
42904
|
-
|
|
42905
|
-
|
|
42906
|
-
|
|
42907
|
-
|
|
42908
|
-
|
|
42909
|
-
|
|
42910
|
-
|
|
42911
|
-
|
|
42912
|
-
|
|
42913
|
-
|
|
41728
|
+
async line(element) {
|
|
41729
|
+
page.drawLine({
|
|
41730
|
+
start: {
|
|
41731
|
+
x: element.svgAttributes.x1 || 0,
|
|
41732
|
+
y: -element.svgAttributes.y1 || 0,
|
|
41733
|
+
},
|
|
41734
|
+
end: {
|
|
41735
|
+
x: element.svgAttributes.x2 || 0,
|
|
41736
|
+
y: -element.svgAttributes.y2 || 0,
|
|
41737
|
+
},
|
|
41738
|
+
thickness: element.svgAttributes.strokeWidth,
|
|
41739
|
+
color: element.svgAttributes.stroke,
|
|
41740
|
+
opacity: element.svgAttributes.strokeOpacity,
|
|
41741
|
+
lineCap: element.svgAttributes.strokeLineCap,
|
|
41742
|
+
matrix: element.svgAttributes.matrix,
|
|
41743
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42914
41744
|
});
|
|
42915
41745
|
},
|
|
42916
|
-
path(element) {
|
|
42917
|
-
|
|
42918
|
-
|
|
42919
|
-
|
|
42920
|
-
|
|
42921
|
-
|
|
42922
|
-
|
|
42923
|
-
|
|
42924
|
-
|
|
42925
|
-
|
|
42926
|
-
|
|
42927
|
-
|
|
42928
|
-
|
|
42929
|
-
|
|
42930
|
-
|
|
42931
|
-
|
|
42932
|
-
fillRule: element.svgAttributes.fillRule,
|
|
42933
|
-
});
|
|
41746
|
+
async path(element) {
|
|
41747
|
+
if (!element.svgAttributes.d)
|
|
41748
|
+
return;
|
|
41749
|
+
// See https://jsbin.com/kawifomupa/edit?html,output and
|
|
41750
|
+
page.drawSvgPath(element.svgAttributes.d, {
|
|
41751
|
+
x: 0,
|
|
41752
|
+
y: 0,
|
|
41753
|
+
borderColor: element.svgAttributes.stroke,
|
|
41754
|
+
borderWidth: element.svgAttributes.strokeWidth,
|
|
41755
|
+
borderOpacity: element.svgAttributes.strokeOpacity,
|
|
41756
|
+
borderLineCap: element.svgAttributes.strokeLineCap,
|
|
41757
|
+
color: element.svgAttributes.fill,
|
|
41758
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41759
|
+
fillRule: element.svgAttributes.fillRule,
|
|
41760
|
+
matrix: element.svgAttributes.matrix,
|
|
41761
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42934
41762
|
});
|
|
42935
41763
|
},
|
|
42936
|
-
image(element) {
|
|
42937
|
-
|
|
42938
|
-
|
|
42939
|
-
|
|
42940
|
-
|
|
42941
|
-
|
|
42942
|
-
|
|
42943
|
-
|
|
42944
|
-
|
|
42945
|
-
|
|
42946
|
-
|
|
42947
|
-
|
|
42948
|
-
|
|
42949
|
-
|
|
42950
|
-
|
|
42951
|
-
|
|
42952
|
-
|
|
42953
|
-
ySkew: element.svgAttributes.skewY,
|
|
42954
|
-
rotate: element.svgAttributes.rotate,
|
|
42955
|
-
});
|
|
41764
|
+
async image(element) {
|
|
41765
|
+
const { src } = element.svgAttributes;
|
|
41766
|
+
if (!src)
|
|
41767
|
+
return;
|
|
41768
|
+
const isPng = src.match(/\.png(\?|$)|^data:image\/png;base64/gim);
|
|
41769
|
+
const img = isPng
|
|
41770
|
+
? await page.doc.embedPng(src)
|
|
41771
|
+
: await page.doc.embedJpg(src);
|
|
41772
|
+
const { x, y, width, height } = getFittingRectangle(img.width, img.height, element.svgAttributes.width || img.width, element.svgAttributes.height || img.height, element.svgAttributes.preserveAspectRatio);
|
|
41773
|
+
page.drawImage(img, {
|
|
41774
|
+
x,
|
|
41775
|
+
y: -y - height,
|
|
41776
|
+
width,
|
|
41777
|
+
height,
|
|
41778
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41779
|
+
matrix: element.svgAttributes.matrix,
|
|
41780
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42956
41781
|
});
|
|
42957
41782
|
},
|
|
42958
|
-
rect(element) {
|
|
42959
|
-
|
|
42960
|
-
|
|
42961
|
-
|
|
42962
|
-
|
|
42963
|
-
|
|
42964
|
-
|
|
42965
|
-
|
|
42966
|
-
|
|
42967
|
-
|
|
42968
|
-
|
|
42969
|
-
|
|
42970
|
-
|
|
42971
|
-
|
|
42972
|
-
|
|
42973
|
-
|
|
42974
|
-
ySkew: element.svgAttributes.skewY,
|
|
42975
|
-
rotate: element.svgAttributes.rotate,
|
|
42976
|
-
});
|
|
41783
|
+
async rect(element) {
|
|
41784
|
+
if (!element.svgAttributes.fill && !element.svgAttributes.stroke)
|
|
41785
|
+
return;
|
|
41786
|
+
page.drawRectangle({
|
|
41787
|
+
x: 0,
|
|
41788
|
+
y: 0,
|
|
41789
|
+
width: element.svgAttributes.width,
|
|
41790
|
+
height: element.svgAttributes.height * -1,
|
|
41791
|
+
borderColor: element.svgAttributes.stroke,
|
|
41792
|
+
borderWidth: element.svgAttributes.strokeWidth,
|
|
41793
|
+
borderOpacity: element.svgAttributes.strokeOpacity,
|
|
41794
|
+
borderLineCap: element.svgAttributes.strokeLineCap,
|
|
41795
|
+
color: element.svgAttributes.fill,
|
|
41796
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41797
|
+
matrix: element.svgAttributes.matrix,
|
|
41798
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42977
41799
|
});
|
|
42978
41800
|
},
|
|
42979
|
-
ellipse(element) {
|
|
42980
|
-
|
|
42981
|
-
|
|
42982
|
-
|
|
42983
|
-
|
|
42984
|
-
|
|
42985
|
-
|
|
42986
|
-
|
|
42987
|
-
|
|
42988
|
-
|
|
42989
|
-
|
|
42990
|
-
|
|
42991
|
-
|
|
42992
|
-
|
|
42993
|
-
});
|
|
41801
|
+
async ellipse(element) {
|
|
41802
|
+
page.drawEllipse({
|
|
41803
|
+
x: element.svgAttributes.cx || 0,
|
|
41804
|
+
y: -(element.svgAttributes.cy || 0),
|
|
41805
|
+
xScale: element.svgAttributes.rx,
|
|
41806
|
+
yScale: element.svgAttributes.ry,
|
|
41807
|
+
borderColor: element.svgAttributes.stroke,
|
|
41808
|
+
borderWidth: element.svgAttributes.strokeWidth,
|
|
41809
|
+
borderOpacity: element.svgAttributes.strokeOpacity,
|
|
41810
|
+
borderLineCap: element.svgAttributes.strokeLineCap,
|
|
41811
|
+
color: element.svgAttributes.fill,
|
|
41812
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41813
|
+
matrix: element.svgAttributes.matrix,
|
|
41814
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42994
41815
|
});
|
|
42995
41816
|
},
|
|
42996
|
-
circle(element) {
|
|
42997
|
-
return
|
|
42998
|
-
return runnersToPage(page, options).ellipse(element);
|
|
42999
|
-
});
|
|
41817
|
+
async circle(element) {
|
|
41818
|
+
return runnersToPage(page, options).ellipse(element);
|
|
43000
41819
|
},
|
|
43001
41820
|
});
|
|
43002
|
-
const transform = (converter, name, args) => {
|
|
43003
|
-
switch (name) {
|
|
43004
|
-
case 'scaleX':
|
|
43005
|
-
return transform(converter, 'scale', [args[0], 0]);
|
|
43006
|
-
case 'scaleY':
|
|
43007
|
-
return transform(converter, 'scale', [0, args[0]]);
|
|
43008
|
-
case 'scale':
|
|
43009
|
-
const [xScale, yScale = xScale] = args;
|
|
43010
|
-
return {
|
|
43011
|
-
point: (x, y) => converter.point(x * xScale, y * yScale),
|
|
43012
|
-
size: (w, h) => converter.size(w * xScale, h * yScale),
|
|
43013
|
-
};
|
|
43014
|
-
case 'translateX':
|
|
43015
|
-
return transform(converter, 'translate', [args[0], 0]);
|
|
43016
|
-
case 'translateY':
|
|
43017
|
-
return transform(converter, 'translate', [0, args[0]]);
|
|
43018
|
-
case 'translate':
|
|
43019
|
-
const [dx, dy = dx] = args;
|
|
43020
|
-
return {
|
|
43021
|
-
point: (x, y) => converter.point(x + dx, y + dy),
|
|
43022
|
-
size: converter.size,
|
|
43023
|
-
};
|
|
43024
|
-
case 'rotate': {
|
|
43025
|
-
if (args.length > 1) {
|
|
43026
|
-
const [a, x, y = x] = args;
|
|
43027
|
-
let tempResult = transform(converter, 'translate', [x, y]);
|
|
43028
|
-
tempResult = transform(tempResult, 'rotate', [a]);
|
|
43029
|
-
return transform(tempResult, 'translate', [-x, -y]);
|
|
43030
|
-
}
|
|
43031
|
-
else {
|
|
43032
|
-
const [a] = args;
|
|
43033
|
-
const angle = degreesToRadians(a);
|
|
43034
|
-
return {
|
|
43035
|
-
point: (x, y) => converter.point(x * Math.cos(angle) - y * Math.sin(angle), y * Math.cos(angle) + x * Math.sin(angle)),
|
|
43036
|
-
size: converter.size,
|
|
43037
|
-
};
|
|
43038
|
-
}
|
|
43039
|
-
}
|
|
43040
|
-
case 'matrix': {
|
|
43041
|
-
const [scaleX, skewY, skewX, scaleY, translateX, translateY] = args;
|
|
43042
|
-
return {
|
|
43043
|
-
point: (x, y) => converter.point(x * scaleX + y * skewX + translateX, x * skewY + y * scaleY + translateY),
|
|
43044
|
-
size: (w, h) => converter.size(w * scaleX, h * scaleY),
|
|
43045
|
-
};
|
|
43046
|
-
}
|
|
43047
|
-
case 'skewX': {
|
|
43048
|
-
const angle = degreesToRadians(args[0]);
|
|
43049
|
-
return {
|
|
43050
|
-
point: (x, y) => converter.point((1 + x) * Math.tan(angle), y),
|
|
43051
|
-
size: converter.size,
|
|
43052
|
-
};
|
|
43053
|
-
}
|
|
43054
|
-
case 'skewY': {
|
|
43055
|
-
const angle = degreesToRadians(args[0]);
|
|
43056
|
-
return {
|
|
43057
|
-
point: (x, y) => converter.point(x, (1 + y) * Math.tan(angle)),
|
|
43058
|
-
size: converter.size,
|
|
43059
|
-
};
|
|
43060
|
-
}
|
|
43061
|
-
default: {
|
|
43062
|
-
console.log('transformation unsupported:', name);
|
|
43063
|
-
return converter;
|
|
43064
|
-
}
|
|
43065
|
-
}
|
|
43066
|
-
};
|
|
43067
41821
|
const styleOrAttribute = (attributes, style, attribute, def) => {
|
|
43068
41822
|
const value = style[attribute] || attributes[attribute];
|
|
43069
41823
|
if (!value && typeof def !== 'undefined')
|
|
@@ -43093,8 +41847,8 @@ const parseColor = (color, inherited) => {
|
|
|
43093
41847
|
alpha: parsedColor.alpha ? parsedColor.alpha + '' : undefined,
|
|
43094
41848
|
};
|
|
43095
41849
|
};
|
|
43096
|
-
const parseAttributes = (element, inherited,
|
|
43097
|
-
var _a, _b, _c, _d
|
|
41850
|
+
const parseAttributes = (element, inherited, matrix) => {
|
|
41851
|
+
var _a, _b, _c, _d;
|
|
43098
41852
|
const attributes = element.attributes;
|
|
43099
41853
|
const style = parseStyles(attributes.style);
|
|
43100
41854
|
const widthRaw = styleOrAttribute(attributes, style, 'width', '');
|
|
@@ -43150,7 +41904,6 @@ const parseAttributes = (element, inherited, converter) => {
|
|
|
43150
41904
|
dominantBaseline: attributes['dominant-baseline'],
|
|
43151
41905
|
preserveAspectRatio: attributes.preserveAspectRatio,
|
|
43152
41906
|
};
|
|
43153
|
-
let newConverter = converter;
|
|
43154
41907
|
let transformList = attributes.transform || '';
|
|
43155
41908
|
// Handle transformations set as direct attributes
|
|
43156
41909
|
[
|
|
@@ -43169,28 +41922,11 @@ const parseAttributes = (element, inherited, converter) => {
|
|
|
43169
41922
|
transformList = attributes[name] + ' ' + transformList;
|
|
43170
41923
|
}
|
|
43171
41924
|
});
|
|
43172
|
-
// skewX, skewY, rotate and scale are handled by the pdf-lib
|
|
43173
|
-
['skewX', 'skewY', 'rotate'].forEach((name) => {
|
|
43174
|
-
var _a;
|
|
43175
|
-
if (attributes[name]) {
|
|
43176
|
-
const d = (_a = attributes[name].match(/-?(\d+\.?|\.)\d*/)) === null || _a === void 0 ? void 0 : _a[0];
|
|
43177
|
-
if (d !== undefined) {
|
|
43178
|
-
svgAttributes[name] = {
|
|
43179
|
-
angle: parseInt(d, 10),
|
|
43180
|
-
type: RotationTypes.Degrees,
|
|
43181
|
-
};
|
|
43182
|
-
}
|
|
43183
|
-
}
|
|
43184
|
-
});
|
|
43185
|
-
if (attributes.scale) {
|
|
43186
|
-
const d = (_e = attributes.scale.match(/-?(\d+\.?|\.)\d*/)) === null || _e === void 0 ? void 0 : _e[0];
|
|
43187
|
-
if (d !== undefined)
|
|
43188
|
-
svgAttributes.scale = parseInt(d, 10);
|
|
43189
|
-
}
|
|
43190
41925
|
// Convert x/y as if it was a translation
|
|
43191
41926
|
if (x || y) {
|
|
43192
41927
|
transformList = transformList + `translate(${x || 0} ${y || 0}) `;
|
|
43193
41928
|
}
|
|
41929
|
+
let newMatrix = matrix;
|
|
43194
41930
|
// Apply the transformations
|
|
43195
41931
|
if (transformList) {
|
|
43196
41932
|
const regexTransform = /(\w+)\((.+?)\)/g;
|
|
@@ -43201,295 +41937,38 @@ const parseAttributes = (element, inherited, converter) => {
|
|
|
43201
41937
|
.split(/\s*,\s*|\s+/)
|
|
43202
41938
|
.filter((value) => value.length > 0)
|
|
43203
41939
|
.map((value) => parseFloat(value));
|
|
43204
|
-
|
|
43205
|
-
newConverter = transform(newConverter, name, args);
|
|
43206
|
-
const xAxisVector = minus(currentConverter.point(0, 0), currentConverter.point(1, 0));
|
|
43207
|
-
const xAxisVectorPostTransform = minus(newConverter.point(0, 0), newConverter.point(1, 0));
|
|
43208
|
-
// matrix transform may also represent rotations: https://www.w3.org/TR/SVGTiny12/coords.html
|
|
43209
|
-
if (name === 'rotate' || name === 'matrix') {
|
|
43210
|
-
// transformations over x and y axis might change the page coord direction
|
|
43211
|
-
const { width: xDirection, height: yDirection } = currentConverter.size(1, 1);
|
|
43212
|
-
const rotationAdded = name === 'rotate' ? args[0] : radiansToDegrees(angle(xAxisVectorPostTransform, xAxisVector));
|
|
43213
|
-
// the page Y coord is inverted so the angle rotation is inverted too
|
|
43214
|
-
const pageYDirection = -1;
|
|
43215
|
-
newInherited.rotation = degrees(pageYDirection * rotationAdded * Math.sign(xDirection * yDirection) +
|
|
43216
|
-
(((_f = inherited.rotation) === null || _f === void 0 ? void 0 : _f.angle) || 0));
|
|
43217
|
-
svgAttributes.rotate = newInherited.rotation;
|
|
43218
|
-
}
|
|
41940
|
+
newMatrix = combineTransformation(newMatrix, name, args);
|
|
43219
41941
|
parsed = regexTransform.exec(transformList);
|
|
43220
41942
|
}
|
|
43221
41943
|
}
|
|
43222
|
-
|
|
43223
|
-
|
|
43224
|
-
svgAttributes.x = newX;
|
|
43225
|
-
svgAttributes.y = newY;
|
|
41944
|
+
svgAttributes.x = x;
|
|
41945
|
+
svgAttributes.y = y;
|
|
43226
41946
|
if (attributes.cx || attributes.cy) {
|
|
43227
|
-
|
|
43228
|
-
svgAttributes.
|
|
43229
|
-
svgAttributes.cy = newCY;
|
|
41947
|
+
svgAttributes.cx = cx;
|
|
41948
|
+
svgAttributes.cy = cy;
|
|
43230
41949
|
}
|
|
43231
41950
|
if (attributes.rx || attributes.ry || attributes.r) {
|
|
43232
|
-
|
|
43233
|
-
svgAttributes.
|
|
43234
|
-
svgAttributes.ry = newRY;
|
|
41951
|
+
svgAttributes.rx = rx;
|
|
41952
|
+
svgAttributes.ry = ry;
|
|
43235
41953
|
}
|
|
43236
41954
|
if (attributes.x1 || attributes.y1) {
|
|
43237
|
-
|
|
43238
|
-
svgAttributes.
|
|
43239
|
-
svgAttributes.y1 = newY1;
|
|
41955
|
+
svgAttributes.x1 = x1;
|
|
41956
|
+
svgAttributes.y1 = y1;
|
|
43240
41957
|
}
|
|
43241
41958
|
if (attributes.x2 || attributes.y2) {
|
|
43242
|
-
|
|
43243
|
-
svgAttributes.
|
|
43244
|
-
svgAttributes.y2 = newY2;
|
|
41959
|
+
svgAttributes.x2 = x2;
|
|
41960
|
+
svgAttributes.y2 = y2;
|
|
43245
41961
|
}
|
|
43246
41962
|
if (attributes.width || attributes.height) {
|
|
43247
|
-
|
|
43248
|
-
svgAttributes.
|
|
43249
|
-
svgAttributes.height = size.height;
|
|
41963
|
+
svgAttributes.width = width !== null && width !== void 0 ? width : inherited.width;
|
|
41964
|
+
svgAttributes.height = height !== null && height !== void 0 ? height : inherited.height;
|
|
43250
41965
|
}
|
|
43251
|
-
// We convert all the points from the path
|
|
43252
41966
|
if (attributes.d) {
|
|
43253
|
-
|
|
43254
|
-
|
|
43255
|
-
let currentX = 0;
|
|
43256
|
-
let currentY = 0;
|
|
43257
|
-
svgAttributes.d = (_g = attributes.d) === null || _g === void 0 ? void 0 : _g.replace(/(l|m|s|t|q|c|z|a|v|h)([0-9,e\s.-]*)/gi, (command) => {
|
|
43258
|
-
var _a, _b;
|
|
43259
|
-
const letter = (_a = command.match(/[a-z]/i)) === null || _a === void 0 ? void 0 : _a[0];
|
|
43260
|
-
if ((letter === null || letter === void 0 ? void 0 : letter.toLocaleLowerCase()) === 'z')
|
|
43261
|
-
return letter;
|
|
43262
|
-
// const params = command.match(/([0-9e.-]+)/ig)?.filter(m => m !== '')//.map(v => parseFloat(v))
|
|
43263
|
-
const params = (_b = command
|
|
43264
|
-
.match(/(-?[0-9]+\.[0-9]+(e[+-]?[0-9]+)?)|(-?\.[0-9]+(e[+-]?[0-9]+)?)|(-?[0-9]+)/gi)) === null || _b === void 0 ? void 0 : _b.filter((m) => m !== ''); // .map(v => parseFloat(v))
|
|
43265
|
-
if (!params)
|
|
43266
|
-
return letter || '';
|
|
43267
|
-
switch (letter === null || letter === void 0 ? void 0 : letter.toLocaleLowerCase()) {
|
|
43268
|
-
case 'm':
|
|
43269
|
-
case 'l': {
|
|
43270
|
-
const groupedParams = groupBy(params, 2);
|
|
43271
|
-
return groupedParams
|
|
43272
|
-
.map((pair, pairIndex) => {
|
|
43273
|
-
const [x, y] = pair;
|
|
43274
|
-
const xReal = parseFloatValue(x, inherited.width) || 0;
|
|
43275
|
-
const yReal = parseFloatValue(y, innerHeight) || 0;
|
|
43276
|
-
if (letter === letter.toLowerCase()) {
|
|
43277
|
-
currentX += xReal;
|
|
43278
|
-
currentY += yReal;
|
|
43279
|
-
}
|
|
43280
|
-
else {
|
|
43281
|
-
currentX = xReal;
|
|
43282
|
-
currentY = yReal;
|
|
43283
|
-
}
|
|
43284
|
-
const point = newConverter.point(currentX, currentY);
|
|
43285
|
-
return ((pairIndex > 0 || letter.toUpperCase() === 'L' ? 'L' : 'M') +
|
|
43286
|
-
[point.x - xOrigin, point.y - yOrigin].join(','));
|
|
43287
|
-
})
|
|
43288
|
-
.join(' ');
|
|
43289
|
-
}
|
|
43290
|
-
case 'v': {
|
|
43291
|
-
return params
|
|
43292
|
-
.map((value) => {
|
|
43293
|
-
const coord = parseFloatValue(value) || 0;
|
|
43294
|
-
if (letter === letter.toLowerCase()) {
|
|
43295
|
-
currentY += coord;
|
|
43296
|
-
}
|
|
43297
|
-
else {
|
|
43298
|
-
currentY = coord;
|
|
43299
|
-
}
|
|
43300
|
-
const point = newConverter.point(currentX, currentY);
|
|
43301
|
-
// we can't use 'v' as the final command because rotations might require a different command after the path parsing
|
|
43302
|
-
// for instance, a 90 degree rotation would turn a 'v' into an 'h' command
|
|
43303
|
-
return `L${point.x - xOrigin} ${point.y - yOrigin}`;
|
|
43304
|
-
})
|
|
43305
|
-
.join(' ');
|
|
43306
|
-
}
|
|
43307
|
-
case 'h': {
|
|
43308
|
-
return params
|
|
43309
|
-
.map((value) => {
|
|
43310
|
-
const coord = parseFloatValue(value) || 0;
|
|
43311
|
-
if (letter === letter.toLowerCase()) {
|
|
43312
|
-
currentX += coord;
|
|
43313
|
-
}
|
|
43314
|
-
else {
|
|
43315
|
-
currentX = coord;
|
|
43316
|
-
}
|
|
43317
|
-
const point = newConverter.point(currentX, currentY);
|
|
43318
|
-
// we can't use 'h' as the final command because rotations might require a different command after the path parsing
|
|
43319
|
-
// for instance, a 90 degree rotation would turn a 'h' into an 'v' command
|
|
43320
|
-
return `L${point.x - xOrigin} ${point.y - yOrigin}`;
|
|
43321
|
-
})
|
|
43322
|
-
.join(' ');
|
|
43323
|
-
}
|
|
43324
|
-
case 'a': {
|
|
43325
|
-
const groupedParams = groupBy(params, 7);
|
|
43326
|
-
return groupedParams
|
|
43327
|
-
.map((p) => {
|
|
43328
|
-
const [rxPixel, ryPixel, xAxisRotation = '0', largeArc = '0', sweepFlag = '0', xPixel, yPixel,] = p;
|
|
43329
|
-
const realRx = parseFloatValue(rxPixel, inherited.width) || 0;
|
|
43330
|
-
const realRy = parseFloatValue(ryPixel, inherited.height) || 0;
|
|
43331
|
-
const realX = parseFloatValue(xPixel, inherited.width) || 0;
|
|
43332
|
-
const realY = parseFloatValue(yPixel, inherited.height) || 0;
|
|
43333
|
-
const { width: newRx, height: newRy } = newConverter.size(realRx, realRy);
|
|
43334
|
-
let point;
|
|
43335
|
-
if (letter === letter.toLowerCase()) {
|
|
43336
|
-
currentX += realX;
|
|
43337
|
-
currentY += realY;
|
|
43338
|
-
}
|
|
43339
|
-
else {
|
|
43340
|
-
currentX = realX;
|
|
43341
|
-
currentY = realY;
|
|
43342
|
-
}
|
|
43343
|
-
point = newConverter.point(currentX, currentY);
|
|
43344
|
-
// transformations over x and y axis might change the page coord direction
|
|
43345
|
-
const { width: xDirection, height: yDirection } = newConverter.size(1, 1);
|
|
43346
|
-
// -1 is the default direction
|
|
43347
|
-
const pageYDirection = -1 * Math.sign(xDirection * yDirection);
|
|
43348
|
-
const oppositeSweepFlag = sweepFlag === '0' ? '1' : '0';
|
|
43349
|
-
return [
|
|
43350
|
-
letter.toUpperCase(),
|
|
43351
|
-
newRx,
|
|
43352
|
-
newRy,
|
|
43353
|
-
xAxisRotation,
|
|
43354
|
-
largeArc,
|
|
43355
|
-
pageYDirection === -1 ? oppositeSweepFlag : sweepFlag,
|
|
43356
|
-
point.x - xOrigin,
|
|
43357
|
-
point.y - yOrigin,
|
|
43358
|
-
].join(' ');
|
|
43359
|
-
})
|
|
43360
|
-
.join(' ');
|
|
43361
|
-
}
|
|
43362
|
-
case 'c': {
|
|
43363
|
-
const groupedParams = groupBy(params, 6);
|
|
43364
|
-
const result = groupedParams
|
|
43365
|
-
.map(([c1X, c1Y, c2X, c2Y, xString, yString]) => [
|
|
43366
|
-
parseFloatValue(c1X, inherited.width) || 0,
|
|
43367
|
-
parseFloatValue(c1Y, inherited.height) || 0,
|
|
43368
|
-
parseFloatValue(c2X, inherited.width) || 0,
|
|
43369
|
-
parseFloatValue(c2Y, inherited.height) || 0,
|
|
43370
|
-
parseFloatValue(xString, inherited.width) || 0,
|
|
43371
|
-
parseFloatValue(yString, inherited.height) || 0,
|
|
43372
|
-
])
|
|
43373
|
-
.map(([c1X, c1Y, c2X, c2Y, xReal, yReal]) => {
|
|
43374
|
-
let controlPoint1X;
|
|
43375
|
-
let controlPoint1Y;
|
|
43376
|
-
let controlPoint2X;
|
|
43377
|
-
let controlPoint2Y;
|
|
43378
|
-
if (letter === letter.toLowerCase()) {
|
|
43379
|
-
controlPoint1X = currentX + c1X;
|
|
43380
|
-
controlPoint1Y = currentY + c1Y;
|
|
43381
|
-
controlPoint2X = currentX + c2X;
|
|
43382
|
-
controlPoint2Y = currentY + c2Y;
|
|
43383
|
-
currentX += xReal;
|
|
43384
|
-
currentY += yReal;
|
|
43385
|
-
}
|
|
43386
|
-
else {
|
|
43387
|
-
controlPoint1X = c1X;
|
|
43388
|
-
controlPoint1Y = c1Y;
|
|
43389
|
-
controlPoint2X = c2X;
|
|
43390
|
-
controlPoint2Y = c2Y;
|
|
43391
|
-
currentX = xReal;
|
|
43392
|
-
currentY = yReal;
|
|
43393
|
-
}
|
|
43394
|
-
const controlPoint1 = newConverter.point(controlPoint1X, controlPoint1Y);
|
|
43395
|
-
const controlPoint2 = newConverter.point(controlPoint2X, controlPoint2Y);
|
|
43396
|
-
const point = newConverter.point(currentX, currentY);
|
|
43397
|
-
return [
|
|
43398
|
-
controlPoint1.x - xOrigin,
|
|
43399
|
-
controlPoint1.y - yOrigin,
|
|
43400
|
-
controlPoint2.x - xOrigin,
|
|
43401
|
-
controlPoint2.y - yOrigin,
|
|
43402
|
-
point.x - xOrigin,
|
|
43403
|
-
point.y - yOrigin,
|
|
43404
|
-
].join(',');
|
|
43405
|
-
})
|
|
43406
|
-
.join(' ');
|
|
43407
|
-
return (letter === null || letter === void 0 ? void 0 : letter.toUpperCase()) + '' + result;
|
|
43408
|
-
}
|
|
43409
|
-
case 's': {
|
|
43410
|
-
const groupedParams = groupBy(params, 4);
|
|
43411
|
-
const result = groupedParams
|
|
43412
|
-
// the control point 1 is omitted because it's the reflection of c2
|
|
43413
|
-
.map(([c2X, c2Y, xString, yString]) => [
|
|
43414
|
-
parseFloatValue(c2X, inherited.width) || 0,
|
|
43415
|
-
parseFloatValue(c2Y, inherited.height) || 0,
|
|
43416
|
-
parseFloatValue(xString, inherited.width) || 0,
|
|
43417
|
-
parseFloatValue(yString, inherited.height) || 0,
|
|
43418
|
-
])
|
|
43419
|
-
.map(([c2X, c2Y, xReal, yReal]) => {
|
|
43420
|
-
let controlPoint2X;
|
|
43421
|
-
let controlPoint2Y;
|
|
43422
|
-
if (letter === letter.toLowerCase()) {
|
|
43423
|
-
controlPoint2X = currentX + c2X;
|
|
43424
|
-
controlPoint2Y = currentY + c2Y;
|
|
43425
|
-
currentX += xReal;
|
|
43426
|
-
currentY += yReal;
|
|
43427
|
-
}
|
|
43428
|
-
else {
|
|
43429
|
-
controlPoint2X = c2X;
|
|
43430
|
-
controlPoint2Y = c2Y;
|
|
43431
|
-
currentX = xReal;
|
|
43432
|
-
currentY = yReal;
|
|
43433
|
-
}
|
|
43434
|
-
const controlPoint2 = newConverter.point(controlPoint2X, controlPoint2Y);
|
|
43435
|
-
const point = newConverter.point(currentX, currentY);
|
|
43436
|
-
return [
|
|
43437
|
-
controlPoint2.x - xOrigin,
|
|
43438
|
-
controlPoint2.y - yOrigin,
|
|
43439
|
-
point.x - xOrigin,
|
|
43440
|
-
point.y - yOrigin,
|
|
43441
|
-
].join(',');
|
|
43442
|
-
})
|
|
43443
|
-
.join(' ');
|
|
43444
|
-
return (letter === null || letter === void 0 ? void 0 : letter.toUpperCase()) + '' + result;
|
|
43445
|
-
}
|
|
43446
|
-
default: {
|
|
43447
|
-
const groupedParams = groupBy(params, 2);
|
|
43448
|
-
const result = groupedParams
|
|
43449
|
-
.map(([xString, yString]) => [
|
|
43450
|
-
parseFloatValue(xString, inherited.width) || 0,
|
|
43451
|
-
parseFloatValue(yString, inherited.height) || 0,
|
|
43452
|
-
])
|
|
43453
|
-
.map(([xReal, yReal]) => {
|
|
43454
|
-
if (letter === letter.toLowerCase()) {
|
|
43455
|
-
currentX += xReal;
|
|
43456
|
-
currentY += yReal;
|
|
43457
|
-
}
|
|
43458
|
-
else {
|
|
43459
|
-
currentX = xReal;
|
|
43460
|
-
currentY = yReal;
|
|
43461
|
-
}
|
|
43462
|
-
const point = newConverter.point(currentX, currentY);
|
|
43463
|
-
return [point.x - xOrigin, point.y - yOrigin].join(',');
|
|
43464
|
-
})
|
|
43465
|
-
.join(' ');
|
|
43466
|
-
return (letter === null || letter === void 0 ? void 0 : letter.toUpperCase()) + '' + result;
|
|
43467
|
-
}
|
|
43468
|
-
}
|
|
43469
|
-
});
|
|
43470
|
-
}
|
|
43471
|
-
if (attributes.viewBox) {
|
|
43472
|
-
const viewBox = parseViewBox(attributes.viewBox);
|
|
43473
|
-
const size = {
|
|
43474
|
-
width: width || inherited.viewBox.width,
|
|
43475
|
-
height: height || inherited.viewBox.height,
|
|
43476
|
-
};
|
|
43477
|
-
const localConverter = getConverterWithAspectRatio(size, viewBox, attributes.preserveAspectRatio);
|
|
43478
|
-
const oldConverter = newConverter;
|
|
43479
|
-
newConverter = {
|
|
43480
|
-
point: (px, py) => {
|
|
43481
|
-
const { x: localX, y: localY } = localConverter.point(px, py);
|
|
43482
|
-
return oldConverter.point(localX, localY);
|
|
43483
|
-
},
|
|
43484
|
-
size: (w, h) => {
|
|
43485
|
-
const { width: localWidth, height: localHeight } = localConverter.size(w, h);
|
|
43486
|
-
return oldConverter.size(localWidth, localHeight);
|
|
43487
|
-
},
|
|
43488
|
-
};
|
|
41967
|
+
newMatrix = combineTransformation(newMatrix, 'scale', [1, -1]);
|
|
41968
|
+
svgAttributes.d = attributes.d;
|
|
43489
41969
|
}
|
|
43490
|
-
// apply the converter only when there's a local fontSize instruction
|
|
43491
41970
|
if (fontSizeRaw && newInherited.fontSize) {
|
|
43492
|
-
newInherited.fontSize =
|
|
41971
|
+
newInherited.fontSize = newInherited.fontSize;
|
|
43493
41972
|
}
|
|
43494
41973
|
if (newInherited.fontFamily) {
|
|
43495
41974
|
// Handle complex fontFamily like `"Linux Libertine O", serif`
|
|
@@ -43498,43 +41977,13 @@ const parseAttributes = (element, inherited, converter) => {
|
|
|
43498
41977
|
newInherited.fontFamily = inner[1] || inner[2];
|
|
43499
41978
|
}
|
|
43500
41979
|
if (newInherited.strokeWidth) {
|
|
43501
|
-
|
|
43502
|
-
svgAttributes.strokeWidth = Math.max(Math.min(Math.abs(result.width), Math.abs(result.height)), 1);
|
|
41980
|
+
svgAttributes.strokeWidth = newInherited.strokeWidth;
|
|
43503
41981
|
}
|
|
43504
41982
|
return {
|
|
43505
41983
|
inherited: newInherited,
|
|
43506
41984
|
svgAttributes,
|
|
43507
|
-
converter: newConverter,
|
|
43508
41985
|
tagName: element.tagName,
|
|
43509
|
-
|
|
43510
|
-
};
|
|
43511
|
-
const getConverter = (box, viewBox) => {
|
|
43512
|
-
const { width, height } = box;
|
|
43513
|
-
const { x: xMin, y: yMin, width: viewWidth, height: viewHeight } = viewBox;
|
|
43514
|
-
const converter = {
|
|
43515
|
-
point: (xReal, yReal) => ({
|
|
43516
|
-
x: ((xReal - xMin) / viewWidth) * (width || 0),
|
|
43517
|
-
y: ((yReal - yMin) / viewHeight) * (height || 0),
|
|
43518
|
-
}),
|
|
43519
|
-
size: (wReal, hReal) => ({
|
|
43520
|
-
width: (wReal / viewWidth) * (width || 0),
|
|
43521
|
-
height: (hReal / viewHeight) * (height || 0),
|
|
43522
|
-
}),
|
|
43523
|
-
};
|
|
43524
|
-
return converter;
|
|
43525
|
-
};
|
|
43526
|
-
const getConverterWithAspectRatio = (size, viewBox, preserveAspectRatio) => {
|
|
43527
|
-
// explanation about how the svg attributes applies transformations to the child elements
|
|
43528
|
-
// https://www.w3.org/TR/SVG/coords.html#ComputingAViewportsTransform
|
|
43529
|
-
const { x, y, width, height } = getFittingRectangle(viewBox.width, viewBox.height, size.width, size.height, preserveAspectRatio);
|
|
43530
|
-
const ratioConverter = getConverter({ width, height }, viewBox);
|
|
43531
|
-
// We translate the drawing in the page when the aspect ratio is different, according to the preserveAspectRatio instructions.
|
|
43532
|
-
return {
|
|
43533
|
-
point: (xReal, yReal) => {
|
|
43534
|
-
const P = ratioConverter.point(xReal, yReal);
|
|
43535
|
-
return { x: P.x + x, y: P.y + y };
|
|
43536
|
-
},
|
|
43537
|
-
size: ratioConverter.size,
|
|
41986
|
+
matrix: newMatrix,
|
|
43538
41987
|
};
|
|
43539
41988
|
};
|
|
43540
41989
|
const getFittingRectangle = (originalWidth, originalHeight, targetWidth, targetHeight, preserveAspectRatio) => {
|
|
@@ -43572,16 +42021,62 @@ const getFittingRectangle = (originalWidth, originalHeight, targetWidth, targetH
|
|
|
43572
42021
|
})();
|
|
43573
42022
|
return { x, y, width, height };
|
|
43574
42023
|
};
|
|
43575
|
-
const
|
|
42024
|
+
const getAspectRatioTransformation = (matrix, originalWidth, originalHeight, targetWidth, targetHeight, preserveAspectRatio) => {
|
|
42025
|
+
const scaleX = targetWidth / originalWidth;
|
|
42026
|
+
const scaleY = targetHeight / originalHeight;
|
|
42027
|
+
const boxScale = combineTransformation(matrix, 'scale', [
|
|
42028
|
+
scaleX,
|
|
42029
|
+
scaleY
|
|
42030
|
+
]);
|
|
42031
|
+
if (preserveAspectRatio === 'none') {
|
|
42032
|
+
return {
|
|
42033
|
+
clipBox: boxScale,
|
|
42034
|
+
content: boxScale
|
|
42035
|
+
};
|
|
42036
|
+
}
|
|
42037
|
+
// TODO: the following code works for the 'meet' param but not for the 'slice'
|
|
42038
|
+
const scale = targetWidth > targetHeight ? scaleY : scaleX;
|
|
42039
|
+
const dx = targetWidth - (originalWidth * scale);
|
|
42040
|
+
const dy = targetHeight - (originalHeight * scale);
|
|
42041
|
+
const [x, y] = (() => {
|
|
42042
|
+
switch (preserveAspectRatio) {
|
|
42043
|
+
case 'xMinYMin':
|
|
42044
|
+
return [0, 0];
|
|
42045
|
+
case 'xMidYMin':
|
|
42046
|
+
return [dx / 2, 0];
|
|
42047
|
+
case 'xMaxYMin':
|
|
42048
|
+
return [dx, dy / 2];
|
|
42049
|
+
case 'xMinYMid':
|
|
42050
|
+
return [0, dy];
|
|
42051
|
+
case 'xMaxYMid':
|
|
42052
|
+
return [dx, dy / 2];
|
|
42053
|
+
case 'xMinYMax':
|
|
42054
|
+
return [0, dy];
|
|
42055
|
+
case 'xMidYMax':
|
|
42056
|
+
return [dx / 2, dy];
|
|
42057
|
+
case 'xMaxYMax':
|
|
42058
|
+
return [dx, dy];
|
|
42059
|
+
case 'xMidYMid':
|
|
42060
|
+
default:
|
|
42061
|
+
return [dx / 2, dy / 2];
|
|
42062
|
+
}
|
|
42063
|
+
})();
|
|
42064
|
+
const contentTransform = combineTransformation(combineTransformation(matrix, 'translate', [x, y]), 'scale', [scale]);
|
|
42065
|
+
return {
|
|
42066
|
+
clipBox: boxScale,
|
|
42067
|
+
content: contentTransform
|
|
42068
|
+
};
|
|
42069
|
+
};
|
|
42070
|
+
const parseHTMLNode = (node, inherited, matrix, clipSpaces) => {
|
|
43576
42071
|
if (node.nodeType === index.NodeType.COMMENT_NODE)
|
|
43577
42072
|
return [];
|
|
43578
42073
|
else if (node.nodeType === index.NodeType.TEXT_NODE)
|
|
43579
42074
|
return [];
|
|
43580
42075
|
else if (node.tagName === 'g') {
|
|
43581
|
-
return parseGroupNode(node, inherited,
|
|
42076
|
+
return parseGroupNode(node, inherited, matrix, clipSpaces);
|
|
43582
42077
|
}
|
|
43583
42078
|
else if (node.tagName === 'svg') {
|
|
43584
|
-
return parseSvgNode(node, inherited,
|
|
42079
|
+
return parseSvgNode(node, inherited, matrix, clipSpaces);
|
|
43585
42080
|
}
|
|
43586
42081
|
else {
|
|
43587
42082
|
if (node.tagName === 'polygon') {
|
|
@@ -43589,36 +42084,69 @@ const parseHTMLNode = (node, inherited, converter) => {
|
|
|
43589
42084
|
node.attributes.d = `M${node.attributes.points}Z`;
|
|
43590
42085
|
delete node.attributes.points;
|
|
43591
42086
|
}
|
|
43592
|
-
const attributes = parseAttributes(node, inherited,
|
|
43593
|
-
const svgAttributes =
|
|
42087
|
+
const attributes = parseAttributes(node, inherited, matrix);
|
|
42088
|
+
const svgAttributes = {
|
|
42089
|
+
...attributes.inherited,
|
|
42090
|
+
...attributes.svgAttributes,
|
|
42091
|
+
matrix: attributes.matrix,
|
|
42092
|
+
clipSpaces
|
|
42093
|
+
};
|
|
43594
42094
|
Object.assign(node, { svgAttributes });
|
|
43595
42095
|
return [node];
|
|
43596
42096
|
}
|
|
43597
42097
|
};
|
|
43598
|
-
const parseSvgNode = (node, inherited,
|
|
42098
|
+
const parseSvgNode = (node, inherited, matrix, clipSpaces) => {
|
|
43599
42099
|
var _a, _b;
|
|
43600
42100
|
// if the width/height aren't set, the svg will have the same dimension as the current drawing space
|
|
43601
42101
|
(_a = node.attributes.width) !== null && _a !== void 0 ? _a : node.setAttribute('width', inherited.viewBox.width + '');
|
|
43602
42102
|
(_b = node.attributes.height) !== null && _b !== void 0 ? _b : node.setAttribute('height', inherited.viewBox.height + '');
|
|
43603
|
-
const attributes = parseAttributes(node, inherited,
|
|
42103
|
+
const attributes = parseAttributes(node, inherited, matrix);
|
|
43604
42104
|
const result = [];
|
|
43605
42105
|
const viewBox = node.attributes.viewBox
|
|
43606
42106
|
? parseViewBox(node.attributes.viewBox)
|
|
43607
42107
|
: node.attributes.width && node.attributes.height
|
|
43608
42108
|
? parseViewBox(`0 0 ${node.attributes.width} ${node.attributes.height}`)
|
|
43609
42109
|
: inherited.viewBox;
|
|
43610
|
-
const
|
|
42110
|
+
const x = parseFloat(node.attributes.x) || 0;
|
|
42111
|
+
const y = parseFloat(node.attributes.y) || 0;
|
|
42112
|
+
let newMatrix = combineTransformation(matrix, 'translate', [x, y]);
|
|
42113
|
+
const { clipBox: clipBoxTransform, content: contentTransform } = getAspectRatioTransformation(newMatrix, viewBox.width, viewBox.height, parseFloat(node.attributes.width), parseFloat(node.attributes.height), node.attributes.preserveAspectRatio || 'xMidYMid');
|
|
42114
|
+
const topLeft = applyTransformation(clipBoxTransform, {
|
|
42115
|
+
x: 0,
|
|
42116
|
+
y: 0,
|
|
42117
|
+
});
|
|
42118
|
+
const topRight = applyTransformation(clipBoxTransform, {
|
|
42119
|
+
x: viewBox.width,
|
|
42120
|
+
y: 0,
|
|
42121
|
+
});
|
|
42122
|
+
const bottomRight = applyTransformation(clipBoxTransform, {
|
|
42123
|
+
x: viewBox.width,
|
|
42124
|
+
y: -viewBox.height,
|
|
42125
|
+
});
|
|
42126
|
+
const bottomLeft = applyTransformation(clipBoxTransform, {
|
|
42127
|
+
x: 0,
|
|
42128
|
+
y: -viewBox.height,
|
|
42129
|
+
});
|
|
42130
|
+
const baseClipSpace = {
|
|
42131
|
+
topLeft,
|
|
42132
|
+
topRight,
|
|
42133
|
+
bottomRight,
|
|
42134
|
+
bottomLeft
|
|
42135
|
+
};
|
|
42136
|
+
// TODO: maybe this is the correct transformation
|
|
42137
|
+
// newMatrix = combineTransformation(newMatrix, 'translate', [-baseClipSpace.xMin, -baseClipSpace.yMin])
|
|
42138
|
+
newMatrix = combineTransformation(contentTransform, 'translate', [-viewBox.x, -viewBox.y]);
|
|
43611
42139
|
node.childNodes.forEach((child) => {
|
|
43612
|
-
const parsedNodes = parseHTMLNode(child,
|
|
42140
|
+
const parsedNodes = parseHTMLNode(child, { ...attributes.inherited, viewBox }, newMatrix, [...clipSpaces, baseClipSpace]);
|
|
43613
42141
|
result.push(...parsedNodes);
|
|
43614
42142
|
});
|
|
43615
42143
|
return result;
|
|
43616
42144
|
};
|
|
43617
|
-
const parseGroupNode = (node, inherited,
|
|
43618
|
-
const attributes = parseAttributes(node, inherited,
|
|
42145
|
+
const parseGroupNode = (node, inherited, matrix, clipSpaces) => {
|
|
42146
|
+
const attributes = parseAttributes(node, inherited, matrix);
|
|
43619
42147
|
const result = [];
|
|
43620
42148
|
node.childNodes.forEach((child) => {
|
|
43621
|
-
result.push(...parseHTMLNode(child, attributes.inherited, attributes.
|
|
42149
|
+
result.push(...parseHTMLNode(child, attributes.inherited, attributes.matrix, clipSpaces));
|
|
43622
42150
|
});
|
|
43623
42151
|
return result;
|
|
43624
42152
|
};
|
|
@@ -43645,22 +42173,21 @@ const parseViewBox = (viewBox) => {
|
|
|
43645
42173
|
height: heightViewBox,
|
|
43646
42174
|
};
|
|
43647
42175
|
};
|
|
43648
|
-
const parse$1 = (svg, { width, height,
|
|
42176
|
+
const parse$1 = (svg, { width, height, fontSize }, size, matrix) => {
|
|
43649
42177
|
const htmlElement = index.parse(svg).firstChild;
|
|
43650
42178
|
if (width)
|
|
43651
42179
|
htmlElement.setAttribute('width', width + '');
|
|
43652
42180
|
if (height)
|
|
43653
42181
|
htmlElement.setAttribute('height', height + '');
|
|
43654
|
-
if (x !== undefined)
|
|
43655
|
-
htmlElement.setAttribute('x', x + '');
|
|
43656
|
-
if (y !== undefined)
|
|
43657
|
-
htmlElement.setAttribute('y', size.height - y + '');
|
|
43658
42182
|
if (fontSize)
|
|
43659
42183
|
htmlElement.setAttribute('font-size', fontSize + '');
|
|
43660
42184
|
// TODO: what should be the default viewBox?
|
|
43661
|
-
return parseHTMLNode(htmlElement,
|
|
42185
|
+
return parseHTMLNode(htmlElement, {
|
|
42186
|
+
...size,
|
|
42187
|
+
viewBox: parseViewBox(htmlElement.attributes.viewBox || '0 0 1 1'),
|
|
42188
|
+
}, matrix, []);
|
|
43662
42189
|
};
|
|
43663
|
-
const drawSvg = (page, svg, options) =>
|
|
42190
|
+
const drawSvg = async (page, svg, options) => {
|
|
43664
42191
|
if (!svg)
|
|
43665
42192
|
return;
|
|
43666
42193
|
const size = page.getSize();
|
|
@@ -43685,19 +42212,42 @@ const drawSvg = (page, svg, options) => __awaiter(void 0, void 0, void 0, functi
|
|
|
43685
42212
|
.map(([key, val]) => `${key}:${val};`)
|
|
43686
42213
|
.join(''));
|
|
43687
42214
|
}
|
|
43688
|
-
|
|
43689
|
-
const defaultConverter = {
|
|
43690
|
-
point: (xP, yP) => ({ x: xP, y: size.height - yP }),
|
|
43691
|
-
size: (w, h) => ({ width: w, height: h }),
|
|
43692
|
-
};
|
|
42215
|
+
const baseTransformation = [1, 0, 0, 1, options.x || 0, options.y || 0];
|
|
43693
42216
|
const runners = runnersToPage(page, options);
|
|
43694
|
-
const elements = parse$1(firstChild.outerHTML, options, size,
|
|
43695
|
-
|
|
42217
|
+
const elements = parse$1(firstChild.outerHTML, options, size, baseTransformation);
|
|
42218
|
+
await elements.reduce(async (prev, elt) => {
|
|
43696
42219
|
var _a;
|
|
43697
|
-
|
|
42220
|
+
await prev;
|
|
42221
|
+
// uncomment these lines to draw the clipSpaces
|
|
42222
|
+
// elt.svgAttributes.clipSpaces.forEach(space => {
|
|
42223
|
+
// page.drawLine({
|
|
42224
|
+
// start: space.topLeft,
|
|
42225
|
+
// end: space.topRight,
|
|
42226
|
+
// color: parseColor('#000000')?.rgb,
|
|
42227
|
+
// thickness: 1
|
|
42228
|
+
// })
|
|
42229
|
+
// page.drawLine({
|
|
42230
|
+
// start: space.topRight,
|
|
42231
|
+
// end: space.bottomRight,
|
|
42232
|
+
// color: parseColor('#000000')?.rgb,
|
|
42233
|
+
// thickness: 1
|
|
42234
|
+
// })
|
|
42235
|
+
// page.drawLine({
|
|
42236
|
+
// start: space.bottomRight,
|
|
42237
|
+
// end: space.bottomLeft,
|
|
42238
|
+
// color: parseColor('#000000')?.rgb,
|
|
42239
|
+
// thickness: 1
|
|
42240
|
+
// })
|
|
42241
|
+
// page.drawLine({
|
|
42242
|
+
// start: space.bottomLeft,
|
|
42243
|
+
// end: space.topLeft,
|
|
42244
|
+
// color: parseColor('#000000')?.rgb,
|
|
42245
|
+
// thickness: 1
|
|
42246
|
+
// })
|
|
42247
|
+
// })
|
|
43698
42248
|
return (_a = runners[elt.tagName]) === null || _a === void 0 ? void 0 : _a.call(runners, elt);
|
|
43699
|
-
}
|
|
43700
|
-
}
|
|
42249
|
+
}, Promise.resolve());
|
|
42250
|
+
};
|
|
43701
42251
|
|
|
43702
42252
|
/**
|
|
43703
42253
|
* Represents a single page of a [[PDFDocument]].
|
|
@@ -44554,6 +43104,8 @@ class PDFPage {
|
|
|
44554
43104
|
y: (_f = options.y) !== null && _f !== void 0 ? _f : this.y,
|
|
44555
43105
|
lineHeight: (_g = options.lineHeight) !== null && _g !== void 0 ? _g : this.lineHeight,
|
|
44556
43106
|
graphicsState: graphicsStateKey,
|
|
43107
|
+
matrix: options.matrix,
|
|
43108
|
+
clipSpaces: options.clipSpaces
|
|
44557
43109
|
}));
|
|
44558
43110
|
if (options.font) {
|
|
44559
43111
|
if (oldFont)
|
|
@@ -44615,6 +43167,8 @@ class PDFPage {
|
|
|
44615
43167
|
xSkew: (_f = options.xSkew) !== null && _f !== void 0 ? _f : degrees(0),
|
|
44616
43168
|
ySkew: (_g = options.ySkew) !== null && _g !== void 0 ? _g : degrees(0),
|
|
44617
43169
|
graphicsState: graphicsStateKey,
|
|
43170
|
+
matrix: options.matrix,
|
|
43171
|
+
clipSpaces: options.clipSpaces
|
|
44618
43172
|
}));
|
|
44619
43173
|
}
|
|
44620
43174
|
/**
|
|
@@ -44773,6 +43327,8 @@ class PDFPage {
|
|
|
44773
43327
|
borderLineCap: (_j = options.borderLineCap) !== null && _j !== void 0 ? _j : undefined,
|
|
44774
43328
|
graphicsState: graphicsStateKey,
|
|
44775
43329
|
fillRule: options.fillRule,
|
|
43330
|
+
matrix: options.matrix,
|
|
43331
|
+
clipSpaces: options.clipSpaces
|
|
44776
43332
|
}));
|
|
44777
43333
|
}
|
|
44778
43334
|
/**
|
|
@@ -44826,6 +43382,8 @@ class PDFPage {
|
|
|
44826
43382
|
dashPhase: (_d = options.dashPhase) !== null && _d !== void 0 ? _d : undefined,
|
|
44827
43383
|
lineCap: (_e = options.lineCap) !== null && _e !== void 0 ? _e : undefined,
|
|
44828
43384
|
graphicsState: graphicsStateKey,
|
|
43385
|
+
matrix: options.matrix,
|
|
43386
|
+
clipSpaces: options.clipSpaces,
|
|
44829
43387
|
}));
|
|
44830
43388
|
}
|
|
44831
43389
|
/**
|
|
@@ -44844,12 +43402,13 @@ class PDFPage {
|
|
|
44844
43402
|
* color: rgb(0.75, 0.2, 0.2),
|
|
44845
43403
|
* opacity: 0.5,
|
|
44846
43404
|
* borderOpacity: 0.75,
|
|
43405
|
+
* radius: 0.1,
|
|
44847
43406
|
* })
|
|
44848
43407
|
* ```
|
|
44849
43408
|
* @param options The options to be used when drawing the rectangle.
|
|
44850
43409
|
*/
|
|
44851
43410
|
drawRectangle(options = {}) {
|
|
44852
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
43411
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
44853
43412
|
assertOrUndefined(options.x, 'options.x', ['number']);
|
|
44854
43413
|
assertOrUndefined(options.y, 'options.y', ['number']);
|
|
44855
43414
|
assertOrUndefined(options.width, 'options.width', ['number']);
|
|
@@ -44872,6 +43431,7 @@ class PDFPage {
|
|
|
44872
43431
|
assertIsOneOfOrUndefined(options.borderLineCap, 'options.borderLineCap', LineCapStyle);
|
|
44873
43432
|
assertRangeOrUndefined(options.borderOpacity, 'options.borderOpacity', 0, 1);
|
|
44874
43433
|
assertIsOneOfOrUndefined(options.blendMode, 'options.blendMode', BlendMode);
|
|
43434
|
+
assertOrUndefined(options.radius, 'options.radius', ['number']);
|
|
44875
43435
|
const graphicsStateKey = this.maybeEmbedGraphicsState({
|
|
44876
43436
|
opacity: options.opacity,
|
|
44877
43437
|
borderOpacity: options.borderOpacity,
|
|
@@ -44896,6 +43456,9 @@ class PDFPage {
|
|
|
44896
43456
|
borderDashPhase: (_m = options.borderDashPhase) !== null && _m !== void 0 ? _m : undefined,
|
|
44897
43457
|
graphicsState: graphicsStateKey,
|
|
44898
43458
|
borderLineCap: (_o = options.borderLineCap) !== null && _o !== void 0 ? _o : undefined,
|
|
43459
|
+
matrix: options.matrix,
|
|
43460
|
+
clipSpaces: options.clipSpaces,
|
|
43461
|
+
radius: (_p = options.radius) !== null && _p !== void 0 ? _p : 0,
|
|
44899
43462
|
}));
|
|
44900
43463
|
}
|
|
44901
43464
|
/**
|
|
@@ -44920,7 +43483,7 @@ class PDFPage {
|
|
|
44920
43483
|
drawSquare(options = {}) {
|
|
44921
43484
|
const { size } = options;
|
|
44922
43485
|
assertOrUndefined(size, 'size', ['number']);
|
|
44923
|
-
this.drawRectangle(
|
|
43486
|
+
this.drawRectangle({ ...options, width: size, height: size });
|
|
44924
43487
|
}
|
|
44925
43488
|
/**
|
|
44926
43489
|
* Draw an ellipse on this page. For example:
|
|
@@ -44985,6 +43548,8 @@ class PDFPage {
|
|
|
44985
43548
|
borderDashPhase: (_k = options.borderDashPhase) !== null && _k !== void 0 ? _k : undefined,
|
|
44986
43549
|
borderLineCap: (_l = options.borderLineCap) !== null && _l !== void 0 ? _l : undefined,
|
|
44987
43550
|
graphicsState: graphicsStateKey,
|
|
43551
|
+
matrix: options.matrix,
|
|
43552
|
+
clipSpaces: options.clipSpaces,
|
|
44988
43553
|
}));
|
|
44989
43554
|
}
|
|
44990
43555
|
/**
|
|
@@ -45008,7 +43573,7 @@ class PDFPage {
|
|
|
45008
43573
|
drawCircle(options = {}) {
|
|
45009
43574
|
const { size = 100 } = options;
|
|
45010
43575
|
assertOrUndefined(size, 'size', ['number']);
|
|
45011
|
-
this.drawEllipse(
|
|
43576
|
+
this.drawEllipse({ ...options, xScale: size, yScale: size });
|
|
45012
43577
|
}
|
|
45013
43578
|
setOrEmbedFont(font) {
|
|
45014
43579
|
const oldFont = this.font;
|
|
@@ -45032,21 +43597,19 @@ class PDFPage {
|
|
|
45032
43597
|
* @param svg The SVG to be drawn.
|
|
45033
43598
|
* @param options The options to be used when drawing the SVG.
|
|
45034
43599
|
*/
|
|
45035
|
-
drawSvg(svg, options = {}) {
|
|
43600
|
+
async drawSvg(svg, options = {}) {
|
|
45036
43601
|
var _a, _b;
|
|
45037
|
-
|
|
45038
|
-
|
|
45039
|
-
|
|
45040
|
-
|
|
45041
|
-
|
|
45042
|
-
|
|
45043
|
-
|
|
45044
|
-
|
|
45045
|
-
|
|
45046
|
-
|
|
45047
|
-
|
|
45048
|
-
height: options.height,
|
|
45049
|
-
});
|
|
43602
|
+
assertIs(svg, 'svg', ['string']);
|
|
43603
|
+
assertOrUndefined(options.x, 'options.x', ['number']);
|
|
43604
|
+
assertOrUndefined(options.y, 'options.y', ['number']);
|
|
43605
|
+
assertOrUndefined(options.width, 'options.width', ['number']);
|
|
43606
|
+
assertOrUndefined(options.height, 'options.height', ['number']);
|
|
43607
|
+
await drawSvg(this, svg, {
|
|
43608
|
+
x: (_a = options.x) !== null && _a !== void 0 ? _a : this.x,
|
|
43609
|
+
y: (_b = options.y) !== null && _b !== void 0 ? _b : this.y,
|
|
43610
|
+
fonts: options.fonts,
|
|
43611
|
+
width: options.width,
|
|
43612
|
+
height: options.height,
|
|
45050
43613
|
});
|
|
45051
43614
|
}
|
|
45052
43615
|
getFont() {
|