@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.js
CHANGED
|
@@ -16049,13 +16049,22 @@
|
|
|
16049
16049
|
return PDFRawStream.of(this.obj(dict), typedArrayFor(contents));
|
|
16050
16050
|
}
|
|
16051
16051
|
flateStream(contents, dict = {}) {
|
|
16052
|
-
return this.stream(pako_1$1.deflate(typedArrayFor(contents)),
|
|
16052
|
+
return this.stream(pako_1$1.deflate(typedArrayFor(contents)), {
|
|
16053
|
+
...dict,
|
|
16054
|
+
Filter: 'FlateDecode',
|
|
16055
|
+
});
|
|
16053
16056
|
}
|
|
16054
16057
|
contentStream(operators, dict = {}) {
|
|
16055
16058
|
return PDFContentStream.of(this.obj(dict), operators);
|
|
16056
16059
|
}
|
|
16057
16060
|
formXObject(operators, dict = {}) {
|
|
16058
|
-
return this.contentStream(operators,
|
|
16061
|
+
return this.contentStream(operators, {
|
|
16062
|
+
BBox: this.obj([0, 0, 0, 0]),
|
|
16063
|
+
Matrix: this.obj([1, 0, 0, 1, 0, 0]),
|
|
16064
|
+
...dict,
|
|
16065
|
+
Type: 'XObject',
|
|
16066
|
+
Subtype: 'Form',
|
|
16067
|
+
});
|
|
16059
16068
|
}
|
|
16060
16069
|
/*
|
|
16061
16070
|
* Reference to PDFContentStream that contains a single PDFOperator: `q`.
|
|
@@ -16390,43 +16399,6 @@
|
|
|
16390
16399
|
}
|
|
16391
16400
|
PDFObjectCopier.for = (src, dest) => new PDFObjectCopier(src, dest);
|
|
16392
16401
|
|
|
16393
|
-
/*! *****************************************************************************
|
|
16394
|
-
Copyright (c) Microsoft Corporation.
|
|
16395
|
-
|
|
16396
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
16397
|
-
purpose with or without fee is hereby granted.
|
|
16398
|
-
|
|
16399
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
16400
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
16401
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
16402
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
16403
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16404
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
16405
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
16406
|
-
***************************************************************************** */
|
|
16407
|
-
|
|
16408
|
-
function __rest(s, e) {
|
|
16409
|
-
var t = {};
|
|
16410
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
16411
|
-
t[p] = s[p];
|
|
16412
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16413
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16414
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
16415
|
-
t[p[i]] = s[p[i]];
|
|
16416
|
-
}
|
|
16417
|
-
return t;
|
|
16418
|
-
}
|
|
16419
|
-
|
|
16420
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
16421
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
16422
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16423
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16424
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16425
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
16426
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
16427
|
-
});
|
|
16428
|
-
}
|
|
16429
|
-
|
|
16430
16402
|
/**
|
|
16431
16403
|
* Entries should be added using the [[addEntry]] and [[addDeletedEntry]]
|
|
16432
16404
|
* methods **in order of ascending object number**.
|
|
@@ -16672,52 +16644,50 @@
|
|
|
16672
16644
|
this.context = context;
|
|
16673
16645
|
this.objectsPerTick = objectsPerTick;
|
|
16674
16646
|
}
|
|
16675
|
-
serializeToBuffer() {
|
|
16676
|
-
|
|
16677
|
-
|
|
16678
|
-
|
|
16679
|
-
|
|
16680
|
-
|
|
16647
|
+
async serializeToBuffer() {
|
|
16648
|
+
const { size, header, indirectObjects, xref, trailerDict, trailer } = await this.computeBufferSize();
|
|
16649
|
+
let offset = 0;
|
|
16650
|
+
const buffer = new Uint8Array(size);
|
|
16651
|
+
offset += header.copyBytesInto(buffer, offset);
|
|
16652
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16653
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16654
|
+
for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
|
|
16655
|
+
const [ref, object] = indirectObjects[idx];
|
|
16656
|
+
const objectNumber = String(ref.objectNumber);
|
|
16657
|
+
offset += copyStringIntoBuffer(objectNumber, buffer, offset);
|
|
16658
|
+
buffer[offset++] = CharCodes$1.Space;
|
|
16659
|
+
const generationNumber = String(ref.generationNumber);
|
|
16660
|
+
offset += copyStringIntoBuffer(generationNumber, buffer, offset);
|
|
16661
|
+
buffer[offset++] = CharCodes$1.Space;
|
|
16662
|
+
buffer[offset++] = CharCodes$1.o;
|
|
16663
|
+
buffer[offset++] = CharCodes$1.b;
|
|
16664
|
+
buffer[offset++] = CharCodes$1.j;
|
|
16681
16665
|
buffer[offset++] = CharCodes$1.Newline;
|
|
16666
|
+
offset += object.copyBytesInto(buffer, offset);
|
|
16682
16667
|
buffer[offset++] = CharCodes$1.Newline;
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
if (this.shouldWaitForTick(n))
|
|
16707
|
-
yield waitForTick();
|
|
16708
|
-
}
|
|
16709
|
-
if (xref) {
|
|
16710
|
-
offset += xref.copyBytesInto(buffer, offset);
|
|
16711
|
-
buffer[offset++] = CharCodes$1.Newline;
|
|
16712
|
-
}
|
|
16713
|
-
if (trailerDict) {
|
|
16714
|
-
offset += trailerDict.copyBytesInto(buffer, offset);
|
|
16715
|
-
buffer[offset++] = CharCodes$1.Newline;
|
|
16716
|
-
buffer[offset++] = CharCodes$1.Newline;
|
|
16717
|
-
}
|
|
16718
|
-
offset += trailer.copyBytesInto(buffer, offset);
|
|
16719
|
-
return buffer;
|
|
16720
|
-
});
|
|
16668
|
+
buffer[offset++] = CharCodes$1.e;
|
|
16669
|
+
buffer[offset++] = CharCodes$1.n;
|
|
16670
|
+
buffer[offset++] = CharCodes$1.d;
|
|
16671
|
+
buffer[offset++] = CharCodes$1.o;
|
|
16672
|
+
buffer[offset++] = CharCodes$1.b;
|
|
16673
|
+
buffer[offset++] = CharCodes$1.j;
|
|
16674
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16675
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16676
|
+
const n = object instanceof PDFObjectStream ? object.getObjectsCount() : 1;
|
|
16677
|
+
if (this.shouldWaitForTick(n))
|
|
16678
|
+
await waitForTick();
|
|
16679
|
+
}
|
|
16680
|
+
if (xref) {
|
|
16681
|
+
offset += xref.copyBytesInto(buffer, offset);
|
|
16682
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16683
|
+
}
|
|
16684
|
+
if (trailerDict) {
|
|
16685
|
+
offset += trailerDict.copyBytesInto(buffer, offset);
|
|
16686
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16687
|
+
buffer[offset++] = CharCodes$1.Newline;
|
|
16688
|
+
}
|
|
16689
|
+
offset += trailer.copyBytesInto(buffer, offset);
|
|
16690
|
+
return buffer;
|
|
16721
16691
|
}
|
|
16722
16692
|
computeIndirectObjectSize([ref, object]) {
|
|
16723
16693
|
const refSize = ref.sizeInBytes() + 3; // 'R' -> 'obj\n'
|
|
@@ -16733,28 +16703,26 @@
|
|
|
16733
16703
|
ID: this.context.trailerInfo.ID,
|
|
16734
16704
|
});
|
|
16735
16705
|
}
|
|
16736
|
-
computeBufferSize() {
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
|
|
16740
|
-
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
16749
|
-
|
|
16750
|
-
|
|
16751
|
-
|
|
16752
|
-
|
|
16753
|
-
|
|
16754
|
-
|
|
16755
|
-
|
|
16756
|
-
return { size, header, indirectObjects, xref, trailerDict, trailer };
|
|
16757
|
-
});
|
|
16706
|
+
async computeBufferSize() {
|
|
16707
|
+
const header = PDFHeader.forVersion(1, 7);
|
|
16708
|
+
let size = header.sizeInBytes() + 2;
|
|
16709
|
+
const xref = PDFCrossRefSection.create();
|
|
16710
|
+
const indirectObjects = this.context.enumerateIndirectObjects();
|
|
16711
|
+
for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
|
|
16712
|
+
const indirectObject = indirectObjects[idx];
|
|
16713
|
+
const [ref] = indirectObject;
|
|
16714
|
+
xref.addEntry(ref, size);
|
|
16715
|
+
size += this.computeIndirectObjectSize(indirectObject);
|
|
16716
|
+
if (this.shouldWaitForTick(1))
|
|
16717
|
+
await waitForTick();
|
|
16718
|
+
}
|
|
16719
|
+
const xrefOffset = size;
|
|
16720
|
+
size += xref.sizeInBytes() + 1; // '\n'
|
|
16721
|
+
const trailerDict = PDFTrailerDict.of(this.createTrailerDict());
|
|
16722
|
+
size += trailerDict.sizeInBytes() + 2; // '\n\n'
|
|
16723
|
+
const trailer = PDFTrailer.forLastCrossRefSectionOffset(xrefOffset);
|
|
16724
|
+
size += trailer.sizeInBytes();
|
|
16725
|
+
return { size, header, indirectObjects, xref, trailerDict, trailer };
|
|
16758
16726
|
}
|
|
16759
16727
|
}
|
|
16760
16728
|
PDFWriter.forContext = (context, objectsPerTick) => new PDFWriter(context, objectsPerTick);
|
|
@@ -16959,63 +16927,61 @@
|
|
|
16959
16927
|
this.encodeStreams = encodeStreams;
|
|
16960
16928
|
this.objectsPerStream = objectsPerStream;
|
|
16961
16929
|
}
|
|
16962
|
-
computeBufferSize() {
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
16967
|
-
|
|
16968
|
-
|
|
16969
|
-
|
|
16970
|
-
|
|
16971
|
-
|
|
16972
|
-
|
|
16973
|
-
|
|
16974
|
-
|
|
16975
|
-
|
|
16976
|
-
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
|
|
16980
|
-
uncompressedObjects.push(indirectObject);
|
|
16981
|
-
xrefStream.addUncompressedEntry(ref, size);
|
|
16982
|
-
size += this.computeIndirectObjectSize(indirectObject);
|
|
16983
|
-
if (this.shouldWaitForTick(1))
|
|
16984
|
-
yield waitForTick();
|
|
16985
|
-
}
|
|
16986
|
-
else {
|
|
16987
|
-
let chunk = last(compressedObjects);
|
|
16988
|
-
let objectStreamRef = last(objectStreamRefs);
|
|
16989
|
-
if (!chunk || chunk.length % this.objectsPerStream === 0) {
|
|
16990
|
-
chunk = [];
|
|
16991
|
-
compressedObjects.push(chunk);
|
|
16992
|
-
objectStreamRef = PDFRef.of(objectNumber++);
|
|
16993
|
-
objectStreamRefs.push(objectStreamRef);
|
|
16994
|
-
}
|
|
16995
|
-
xrefStream.addCompressedEntry(ref, objectStreamRef, chunk.length);
|
|
16996
|
-
chunk.push(indirectObject);
|
|
16997
|
-
}
|
|
16998
|
-
}
|
|
16999
|
-
for (let idx = 0, len = compressedObjects.length; idx < len; idx++) {
|
|
17000
|
-
const chunk = compressedObjects[idx];
|
|
17001
|
-
const ref = objectStreamRefs[idx];
|
|
17002
|
-
const objectStream = PDFObjectStream.withContextAndObjects(this.context, chunk, this.encodeStreams);
|
|
16930
|
+
async computeBufferSize() {
|
|
16931
|
+
let objectNumber = this.context.largestObjectNumber + 1;
|
|
16932
|
+
const header = PDFHeader.forVersion(1, 7);
|
|
16933
|
+
let size = header.sizeInBytes() + 2;
|
|
16934
|
+
const xrefStream = PDFCrossRefStream.create(this.createTrailerDict(), this.encodeStreams);
|
|
16935
|
+
const uncompressedObjects = [];
|
|
16936
|
+
const compressedObjects = [];
|
|
16937
|
+
const objectStreamRefs = [];
|
|
16938
|
+
const indirectObjects = this.context.enumerateIndirectObjects();
|
|
16939
|
+
for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
|
|
16940
|
+
const indirectObject = indirectObjects[idx];
|
|
16941
|
+
const [ref, object] = indirectObject;
|
|
16942
|
+
const shouldNotCompress = ref === this.context.trailerInfo.Encrypt ||
|
|
16943
|
+
object instanceof PDFStream ||
|
|
16944
|
+
object instanceof PDFInvalidObject ||
|
|
16945
|
+
ref.generationNumber !== 0;
|
|
16946
|
+
if (shouldNotCompress) {
|
|
16947
|
+
uncompressedObjects.push(indirectObject);
|
|
17003
16948
|
xrefStream.addUncompressedEntry(ref, size);
|
|
17004
|
-
size += this.computeIndirectObjectSize(
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
|
|
17010
|
-
|
|
17011
|
-
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
|
|
16949
|
+
size += this.computeIndirectObjectSize(indirectObject);
|
|
16950
|
+
if (this.shouldWaitForTick(1))
|
|
16951
|
+
await waitForTick();
|
|
16952
|
+
}
|
|
16953
|
+
else {
|
|
16954
|
+
let chunk = last(compressedObjects);
|
|
16955
|
+
let objectStreamRef = last(objectStreamRefs);
|
|
16956
|
+
if (!chunk || chunk.length % this.objectsPerStream === 0) {
|
|
16957
|
+
chunk = [];
|
|
16958
|
+
compressedObjects.push(chunk);
|
|
16959
|
+
objectStreamRef = PDFRef.of(objectNumber++);
|
|
16960
|
+
objectStreamRefs.push(objectStreamRef);
|
|
16961
|
+
}
|
|
16962
|
+
xrefStream.addCompressedEntry(ref, objectStreamRef, chunk.length);
|
|
16963
|
+
chunk.push(indirectObject);
|
|
16964
|
+
}
|
|
16965
|
+
}
|
|
16966
|
+
for (let idx = 0, len = compressedObjects.length; idx < len; idx++) {
|
|
16967
|
+
const chunk = compressedObjects[idx];
|
|
16968
|
+
const ref = objectStreamRefs[idx];
|
|
16969
|
+
const objectStream = PDFObjectStream.withContextAndObjects(this.context, chunk, this.encodeStreams);
|
|
16970
|
+
xrefStream.addUncompressedEntry(ref, size);
|
|
16971
|
+
size += this.computeIndirectObjectSize([ref, objectStream]);
|
|
16972
|
+
uncompressedObjects.push([ref, objectStream]);
|
|
16973
|
+
if (this.shouldWaitForTick(chunk.length))
|
|
16974
|
+
await waitForTick();
|
|
16975
|
+
}
|
|
16976
|
+
const xrefStreamRef = PDFRef.of(objectNumber++);
|
|
16977
|
+
xrefStream.dict.set(PDFName.of('Size'), PDFNumber.of(objectNumber));
|
|
16978
|
+
xrefStream.addUncompressedEntry(xrefStreamRef, size);
|
|
16979
|
+
const xrefOffset = size;
|
|
16980
|
+
size += this.computeIndirectObjectSize([xrefStreamRef, xrefStream]);
|
|
16981
|
+
uncompressedObjects.push([xrefStreamRef, xrefStream]);
|
|
16982
|
+
const trailer = PDFTrailer.forLastCrossRefSectionOffset(xrefOffset);
|
|
16983
|
+
size += trailer.sizeInBytes();
|
|
16984
|
+
return { size, header, indirectObjects: uncompressedObjects, trailer };
|
|
17019
16985
|
}
|
|
17020
16986
|
}
|
|
17021
16987
|
PDFStreamWriter.forContext = (context, objectsPerTick, encodeStreams = true, objectsPerStream = 50) => new PDFStreamWriter(context, objectsPerTick, encodeStreams, objectsPerStream);
|
|
@@ -17386,11 +17352,9 @@ end\
|
|
|
17386
17352
|
this.baseFontName = '';
|
|
17387
17353
|
this.glyphCache = Cache.populatedBy(this.allGlyphsInFontSortedById);
|
|
17388
17354
|
}
|
|
17389
|
-
static for(fontkit, fontData, customName, fontFeatures) {
|
|
17390
|
-
|
|
17391
|
-
|
|
17392
|
-
return new CustomFontEmbedder(font, fontData, customName, fontFeatures);
|
|
17393
|
-
});
|
|
17355
|
+
static async for(fontkit, fontData, customName, fontFeatures) {
|
|
17356
|
+
const font = await fontkit.create(fontData);
|
|
17357
|
+
return new CustomFontEmbedder(font, fontData, customName, fontFeatures);
|
|
17394
17358
|
}
|
|
17395
17359
|
/**
|
|
17396
17360
|
* Encode the JavaScript string into this font. (JavaScript encodes strings in
|
|
@@ -17436,85 +17400,75 @@ end\
|
|
|
17436
17400
|
this.customName || context.addRandomSuffix(this.fontName);
|
|
17437
17401
|
return this.embedFontDict(context, ref);
|
|
17438
17402
|
}
|
|
17439
|
-
embedFontDict(context, ref) {
|
|
17440
|
-
|
|
17441
|
-
|
|
17442
|
-
|
|
17443
|
-
|
|
17444
|
-
|
|
17445
|
-
|
|
17446
|
-
|
|
17447
|
-
|
|
17448
|
-
|
|
17449
|
-
ToUnicode: unicodeCMapRef,
|
|
17450
|
-
});
|
|
17451
|
-
if (ref) {
|
|
17452
|
-
context.assign(ref, fontDict);
|
|
17453
|
-
return ref;
|
|
17454
|
-
}
|
|
17455
|
-
else {
|
|
17456
|
-
return context.register(fontDict);
|
|
17457
|
-
}
|
|
17403
|
+
async embedFontDict(context, ref) {
|
|
17404
|
+
const cidFontDictRef = await this.embedCIDFontDict(context);
|
|
17405
|
+
const unicodeCMapRef = this.embedUnicodeCmap(context);
|
|
17406
|
+
const fontDict = context.obj({
|
|
17407
|
+
Type: 'Font',
|
|
17408
|
+
Subtype: 'Type0',
|
|
17409
|
+
BaseFont: this.baseFontName,
|
|
17410
|
+
Encoding: 'Identity-H',
|
|
17411
|
+
DescendantFonts: [cidFontDictRef],
|
|
17412
|
+
ToUnicode: unicodeCMapRef,
|
|
17458
17413
|
});
|
|
17414
|
+
if (ref) {
|
|
17415
|
+
context.assign(ref, fontDict);
|
|
17416
|
+
return ref;
|
|
17417
|
+
}
|
|
17418
|
+
else {
|
|
17419
|
+
return context.register(fontDict);
|
|
17420
|
+
}
|
|
17459
17421
|
}
|
|
17460
17422
|
isCFF() {
|
|
17461
17423
|
return this.font.cff;
|
|
17462
17424
|
}
|
|
17463
|
-
embedCIDFontDict(context) {
|
|
17464
|
-
|
|
17465
|
-
|
|
17466
|
-
|
|
17467
|
-
|
|
17468
|
-
|
|
17469
|
-
|
|
17470
|
-
|
|
17471
|
-
|
|
17472
|
-
|
|
17473
|
-
|
|
17474
|
-
|
|
17475
|
-
|
|
17476
|
-
|
|
17477
|
-
W: this.computeWidths(),
|
|
17478
|
-
});
|
|
17479
|
-
return context.register(cidFontDict);
|
|
17425
|
+
async embedCIDFontDict(context) {
|
|
17426
|
+
const fontDescriptorRef = await this.embedFontDescriptor(context);
|
|
17427
|
+
const cidFontDict = context.obj({
|
|
17428
|
+
Type: 'Font',
|
|
17429
|
+
Subtype: this.isCFF() ? 'CIDFontType0' : 'CIDFontType2',
|
|
17430
|
+
CIDToGIDMap: 'Identity',
|
|
17431
|
+
BaseFont: this.baseFontName,
|
|
17432
|
+
CIDSystemInfo: {
|
|
17433
|
+
Registry: PDFString.of('Adobe'),
|
|
17434
|
+
Ordering: PDFString.of('Identity'),
|
|
17435
|
+
Supplement: 0,
|
|
17436
|
+
},
|
|
17437
|
+
FontDescriptor: fontDescriptorRef,
|
|
17438
|
+
W: this.computeWidths(),
|
|
17480
17439
|
});
|
|
17481
|
-
|
|
17482
|
-
|
|
17483
|
-
|
|
17484
|
-
|
|
17485
|
-
|
|
17486
|
-
|
|
17487
|
-
|
|
17488
|
-
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
|
|
17492
|
-
|
|
17493
|
-
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
|
|
17497
|
-
|
|
17498
|
-
|
|
17499
|
-
|
|
17500
|
-
|
|
17501
|
-
|
|
17502
|
-
});
|
|
17503
|
-
return context.register(fontDescriptor);
|
|
17440
|
+
return context.register(cidFontDict);
|
|
17441
|
+
}
|
|
17442
|
+
async embedFontDescriptor(context) {
|
|
17443
|
+
const fontStreamRef = await this.embedFontStream(context);
|
|
17444
|
+
const { scale } = this;
|
|
17445
|
+
const { italicAngle, ascent, descent, capHeight, xHeight } = this.font;
|
|
17446
|
+
const { minX, minY, maxX, maxY } = this.font.bbox;
|
|
17447
|
+
const fontDescriptor = context.obj({
|
|
17448
|
+
Type: 'FontDescriptor',
|
|
17449
|
+
FontName: this.baseFontName,
|
|
17450
|
+
Flags: deriveFontFlags(this.font),
|
|
17451
|
+
FontBBox: [minX * scale, minY * scale, maxX * scale, maxY * scale],
|
|
17452
|
+
ItalicAngle: italicAngle,
|
|
17453
|
+
Ascent: ascent * scale,
|
|
17454
|
+
Descent: descent * scale,
|
|
17455
|
+
CapHeight: (capHeight || ascent) * scale,
|
|
17456
|
+
XHeight: (xHeight || 0) * scale,
|
|
17457
|
+
// Not sure how to compute/find this, nor is anybody else really:
|
|
17458
|
+
// https://stackoverflow.com/questions/35485179/stemv-value-of-the-truetype-font
|
|
17459
|
+
StemV: 0,
|
|
17460
|
+
[this.isCFF() ? 'FontFile3' : 'FontFile2']: fontStreamRef,
|
|
17504
17461
|
});
|
|
17462
|
+
return context.register(fontDescriptor);
|
|
17505
17463
|
}
|
|
17506
|
-
serializeFont() {
|
|
17507
|
-
return
|
|
17508
|
-
return this.fontData;
|
|
17509
|
-
});
|
|
17464
|
+
async serializeFont() {
|
|
17465
|
+
return this.fontData;
|
|
17510
17466
|
}
|
|
17511
|
-
embedFontStream(context) {
|
|
17512
|
-
|
|
17513
|
-
|
|
17514
|
-
Subtype: this.isCFF() ? 'CIDFontType0C' : undefined,
|
|
17515
|
-
});
|
|
17516
|
-
return context.register(fontStream);
|
|
17467
|
+
async embedFontStream(context) {
|
|
17468
|
+
const fontStream = context.flateStream(await this.serializeFont(), {
|
|
17469
|
+
Subtype: this.isCFF() ? 'CIDFontType0C' : undefined,
|
|
17517
17470
|
});
|
|
17471
|
+
return context.register(fontStream);
|
|
17518
17472
|
}
|
|
17519
17473
|
embedUnicodeCmap(context) {
|
|
17520
17474
|
const cmap = createCmap(this.glyphCache.access(), this.glyphId.bind(this));
|
|
@@ -17561,11 +17515,9 @@ end\
|
|
|
17561
17515
|
this.glyphCache = Cache.populatedBy(() => this.glyphs);
|
|
17562
17516
|
this.glyphIdMap = new Map();
|
|
17563
17517
|
}
|
|
17564
|
-
static for(fontkit, fontData, customFontName, fontFeatures) {
|
|
17565
|
-
|
|
17566
|
-
|
|
17567
|
-
return new CustomFontSubsetEmbedder(font, fontData, customFontName, fontFeatures);
|
|
17568
|
-
});
|
|
17518
|
+
static async for(fontkit, fontData, customFontName, fontFeatures) {
|
|
17519
|
+
const font = await fontkit.create(fontData);
|
|
17520
|
+
return new CustomFontSubsetEmbedder(font, fontData, customFontName, fontFeatures);
|
|
17569
17521
|
}
|
|
17570
17522
|
encodeText(text) {
|
|
17571
17523
|
const { glyphs } = this.font.layout(text, this.fontFeatures);
|
|
@@ -17630,39 +17582,37 @@ end\
|
|
|
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 @@ end\
|
|
|
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 @@ end\
|
|
|
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 @@ end\
|
|
|
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.
|
|
@@ -29124,23 +29062,21 @@ end\
|
|
|
29124
29062
|
this.firstOffset = dict.lookup(PDFName.of('First'), PDFNumber).asNumber();
|
|
29125
29063
|
this.objectCount = dict.lookup(PDFName.of('N'), PDFNumber).asNumber();
|
|
29126
29064
|
}
|
|
29127
|
-
parseIntoContext() {
|
|
29128
|
-
|
|
29129
|
-
|
|
29130
|
-
|
|
29131
|
-
|
|
29132
|
-
|
|
29133
|
-
|
|
29134
|
-
|
|
29135
|
-
|
|
29136
|
-
|
|
29137
|
-
|
|
29138
|
-
|
|
29139
|
-
|
|
29140
|
-
|
|
29141
|
-
|
|
29142
|
-
}
|
|
29143
|
-
});
|
|
29065
|
+
async parseIntoContext() {
|
|
29066
|
+
if (this.alreadyParsed) {
|
|
29067
|
+
throw new ReparseError('PDFObjectStreamParser', 'parseIntoContext');
|
|
29068
|
+
}
|
|
29069
|
+
this.alreadyParsed = true;
|
|
29070
|
+
const offsetsAndObjectNumbers = this.parseOffsetsAndObjectNumbers();
|
|
29071
|
+
for (let idx = 0, len = offsetsAndObjectNumbers.length; idx < len; idx++) {
|
|
29072
|
+
const { objectNumber, offset } = offsetsAndObjectNumbers[idx];
|
|
29073
|
+
this.bytes.moveTo(this.firstOffset + offset);
|
|
29074
|
+
const ref = PDFRef.of(objectNumber, 0);
|
|
29075
|
+
const object = this.parseObject(ref);
|
|
29076
|
+
this.context.assign(ref, object);
|
|
29077
|
+
if (this.shouldWaitForTick())
|
|
29078
|
+
await waitForTick();
|
|
29079
|
+
}
|
|
29144
29080
|
}
|
|
29145
29081
|
parseOffsetsAndObjectNumbers() {
|
|
29146
29082
|
const offsetsAndObjectNumbers = [];
|
|
@@ -29248,29 +29184,27 @@ end\
|
|
|
29248
29184
|
this.throwOnInvalidObject = throwOnInvalidObject;
|
|
29249
29185
|
this.context.isDecrypted = !!(cryptoFactory === null || cryptoFactory === void 0 ? void 0 : cryptoFactory.encryptionKey);
|
|
29250
29186
|
}
|
|
29251
|
-
parseDocument() {
|
|
29252
|
-
|
|
29253
|
-
|
|
29254
|
-
|
|
29255
|
-
|
|
29256
|
-
|
|
29257
|
-
|
|
29258
|
-
|
|
29259
|
-
|
|
29260
|
-
|
|
29261
|
-
|
|
29262
|
-
|
|
29263
|
-
throw new StalledParserError(this.bytes.position());
|
|
29264
|
-
}
|
|
29265
|
-
prevOffset = offset;
|
|
29266
|
-
}
|
|
29267
|
-
this.maybeRecoverRoot();
|
|
29268
|
-
if (this.context.lookup(PDFRef.of(0))) {
|
|
29269
|
-
console.warn('Removing parsed object: 0 0 R');
|
|
29270
|
-
this.context.delete(PDFRef.of(0));
|
|
29187
|
+
async parseDocument() {
|
|
29188
|
+
if (this.alreadyParsed) {
|
|
29189
|
+
throw new ReparseError('PDFParser', 'parseDocument');
|
|
29190
|
+
}
|
|
29191
|
+
this.alreadyParsed = true;
|
|
29192
|
+
this.context.header = this.parseHeader();
|
|
29193
|
+
let prevOffset;
|
|
29194
|
+
while (!this.bytes.done()) {
|
|
29195
|
+
await this.parseDocumentSection();
|
|
29196
|
+
const offset = this.bytes.offset();
|
|
29197
|
+
if (offset === prevOffset) {
|
|
29198
|
+
throw new StalledParserError(this.bytes.position());
|
|
29271
29199
|
}
|
|
29272
|
-
|
|
29273
|
-
}
|
|
29200
|
+
prevOffset = offset;
|
|
29201
|
+
}
|
|
29202
|
+
this.maybeRecoverRoot();
|
|
29203
|
+
if (this.context.lookup(PDFRef.of(0))) {
|
|
29204
|
+
console.warn('Removing parsed object: 0 0 R');
|
|
29205
|
+
this.context.delete(PDFRef.of(0));
|
|
29206
|
+
}
|
|
29207
|
+
return this.context;
|
|
29274
29208
|
}
|
|
29275
29209
|
maybeRecoverRoot() {
|
|
29276
29210
|
const isValidCatalog = (obj) => obj instanceof PDFDict &&
|
|
@@ -29322,30 +29256,28 @@ end\
|
|
|
29322
29256
|
return false;
|
|
29323
29257
|
}
|
|
29324
29258
|
}
|
|
29325
|
-
parseIndirectObject() {
|
|
29326
|
-
|
|
29327
|
-
|
|
29328
|
-
|
|
29329
|
-
|
|
29330
|
-
|
|
29331
|
-
|
|
29332
|
-
|
|
29333
|
-
|
|
29334
|
-
|
|
29335
|
-
|
|
29336
|
-
|
|
29337
|
-
|
|
29338
|
-
|
|
29339
|
-
|
|
29340
|
-
|
|
29341
|
-
|
|
29342
|
-
|
|
29343
|
-
|
|
29344
|
-
|
|
29345
|
-
|
|
29346
|
-
|
|
29347
|
-
return ref;
|
|
29348
|
-
});
|
|
29259
|
+
async parseIndirectObject() {
|
|
29260
|
+
const ref = this.parseIndirectObjectHeader();
|
|
29261
|
+
this.skipWhitespaceAndComments();
|
|
29262
|
+
const object = this.parseObject(ref);
|
|
29263
|
+
this.skipWhitespaceAndComments();
|
|
29264
|
+
// if (!this.matchKeyword(Keywords.endobj)) {
|
|
29265
|
+
// throw new MissingKeywordError(this.bytes.position(), Keywords.endobj);
|
|
29266
|
+
// }
|
|
29267
|
+
// TODO: Log a warning if this fails...
|
|
29268
|
+
this.matchKeyword(Keywords.endobj);
|
|
29269
|
+
if (object instanceof PDFRawStream &&
|
|
29270
|
+
object.dict.lookup(PDFName.of('Type')) === PDFName.of('ObjStm')) {
|
|
29271
|
+
await PDFObjectStreamParser.forStream(object, this.shouldWaitForTick).parseIntoContext();
|
|
29272
|
+
}
|
|
29273
|
+
else if (object instanceof PDFRawStream &&
|
|
29274
|
+
object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef')) {
|
|
29275
|
+
PDFXRefStreamParser.forStream(object).parseIntoContext();
|
|
29276
|
+
}
|
|
29277
|
+
else {
|
|
29278
|
+
this.context.assign(ref, object);
|
|
29279
|
+
}
|
|
29280
|
+
return ref;
|
|
29349
29281
|
}
|
|
29350
29282
|
// TODO: Improve and clean this up
|
|
29351
29283
|
tryToParseInvalidIndirectObject() {
|
|
@@ -29374,26 +29306,24 @@ end\
|
|
|
29374
29306
|
this.context.assign(ref, object);
|
|
29375
29307
|
return ref;
|
|
29376
29308
|
}
|
|
29377
|
-
parseIndirectObjects() {
|
|
29378
|
-
|
|
29379
|
-
|
|
29380
|
-
|
|
29381
|
-
|
|
29382
|
-
|
|
29383
|
-
yield this.parseIndirectObject();
|
|
29384
|
-
}
|
|
29385
|
-
catch (e) {
|
|
29386
|
-
// TODO: Add tracing/logging mechanism to track when this happens!
|
|
29387
|
-
this.bytes.moveTo(initialOffset);
|
|
29388
|
-
this.tryToParseInvalidIndirectObject();
|
|
29389
|
-
}
|
|
29390
|
-
this.skipWhitespaceAndComments();
|
|
29391
|
-
// TODO: Can this be done only when needed, to avoid harming performance?
|
|
29392
|
-
this.skipJibberish();
|
|
29393
|
-
if (this.shouldWaitForTick())
|
|
29394
|
-
yield waitForTick();
|
|
29309
|
+
async parseIndirectObjects() {
|
|
29310
|
+
this.skipWhitespaceAndComments();
|
|
29311
|
+
while (!this.bytes.done() && IsDigit[this.bytes.peek()]) {
|
|
29312
|
+
const initialOffset = this.bytes.offset();
|
|
29313
|
+
try {
|
|
29314
|
+
await this.parseIndirectObject();
|
|
29395
29315
|
}
|
|
29396
|
-
|
|
29316
|
+
catch (e) {
|
|
29317
|
+
// TODO: Add tracing/logging mechanism to track when this happens!
|
|
29318
|
+
this.bytes.moveTo(initialOffset);
|
|
29319
|
+
this.tryToParseInvalidIndirectObject();
|
|
29320
|
+
}
|
|
29321
|
+
this.skipWhitespaceAndComments();
|
|
29322
|
+
// TODO: Can this be done only when needed, to avoid harming performance?
|
|
29323
|
+
this.skipJibberish();
|
|
29324
|
+
if (this.shouldWaitForTick())
|
|
29325
|
+
await waitForTick();
|
|
29326
|
+
}
|
|
29397
29327
|
}
|
|
29398
29328
|
maybeParseCrossRefSection() {
|
|
29399
29329
|
this.skipWhitespaceAndComments();
|
|
@@ -29453,15 +29383,13 @@ end\
|
|
|
29453
29383
|
this.skipWhitespaceAndComments();
|
|
29454
29384
|
return PDFTrailer.forLastCrossRefSectionOffset(offset);
|
|
29455
29385
|
}
|
|
29456
|
-
parseDocumentSection() {
|
|
29457
|
-
|
|
29458
|
-
|
|
29459
|
-
|
|
29460
|
-
|
|
29461
|
-
|
|
29462
|
-
|
|
29463
|
-
this.skipJibberish();
|
|
29464
|
-
});
|
|
29386
|
+
async parseDocumentSection() {
|
|
29387
|
+
await this.parseIndirectObjects();
|
|
29388
|
+
this.maybeParseCrossRefSection();
|
|
29389
|
+
this.maybeParseTrailerDict();
|
|
29390
|
+
this.maybeParseTrailer();
|
|
29391
|
+
// TODO: Can this be done only when needed, to avoid harming performance?
|
|
29392
|
+
this.skipJibberish();
|
|
29465
29393
|
}
|
|
29466
29394
|
/**
|
|
29467
29395
|
* This operation is not necessary for valid PDF files. But some invalid PDFs
|
|
@@ -32176,6 +32104,16 @@ end\
|
|
|
32176
32104
|
};
|
|
32177
32105
|
const svgPathToOperators = (path) => apply(parse(path));
|
|
32178
32106
|
|
|
32107
|
+
const clipSpace = ({ topLeft, topRight, bottomRight, bottomLeft }) => [
|
|
32108
|
+
moveTo(topLeft.x, topLeft.y),
|
|
32109
|
+
lineTo(topRight.x, topRight.y),
|
|
32110
|
+
lineTo(bottomRight.x, bottomRight.y),
|
|
32111
|
+
lineTo(bottomLeft.x, bottomLeft.y),
|
|
32112
|
+
closePath(),
|
|
32113
|
+
clip(),
|
|
32114
|
+
endPath(),
|
|
32115
|
+
];
|
|
32116
|
+
const clipSpaces = (spaces) => spaces.flatMap(clipSpace);
|
|
32179
32117
|
const drawText = (line, options) => [
|
|
32180
32118
|
pushGraphicsState(),
|
|
32181
32119
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
@@ -32191,6 +32129,8 @@ end\
|
|
|
32191
32129
|
const operators = [
|
|
32192
32130
|
pushGraphicsState(),
|
|
32193
32131
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32132
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32133
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32194
32134
|
beginText(),
|
|
32195
32135
|
setFillingColor(options.color),
|
|
32196
32136
|
setFontAndSize(options.font, options.size),
|
|
@@ -32206,6 +32146,8 @@ end\
|
|
|
32206
32146
|
const drawImage = (name, options) => [
|
|
32207
32147
|
pushGraphicsState(),
|
|
32208
32148
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32149
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32150
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32209
32151
|
translate(options.x, options.y),
|
|
32210
32152
|
rotateRadians(toRadians(options.rotate)),
|
|
32211
32153
|
scale(options.width, options.height),
|
|
@@ -32228,6 +32170,8 @@ end\
|
|
|
32228
32170
|
return [
|
|
32229
32171
|
pushGraphicsState(),
|
|
32230
32172
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32173
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32174
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32231
32175
|
options.color && setStrokingColor(options.color),
|
|
32232
32176
|
setLineWidth(options.thickness),
|
|
32233
32177
|
setDashPattern((_a = options.dashArray) !== null && _a !== void 0 ? _a : [], (_b = options.dashPhase) !== null && _b !== void 0 ? _b : 0),
|
|
@@ -32241,6 +32185,36 @@ end\
|
|
|
32241
32185
|
};
|
|
32242
32186
|
const drawRectangle = (options) => {
|
|
32243
32187
|
var _a, _b;
|
|
32188
|
+
let ops = [];
|
|
32189
|
+
if (!options.radius || asNumber(options.radius) <= 0) {
|
|
32190
|
+
ops = [
|
|
32191
|
+
moveTo(0, 0),
|
|
32192
|
+
lineTo(0, options.height),
|
|
32193
|
+
lineTo(options.width, options.height),
|
|
32194
|
+
lineTo(options.width, 0),
|
|
32195
|
+
closePath(),
|
|
32196
|
+
];
|
|
32197
|
+
}
|
|
32198
|
+
else {
|
|
32199
|
+
let radius = asNumber(options.radius);
|
|
32200
|
+
const width = asNumber(options.width);
|
|
32201
|
+
const height = asNumber(options.height);
|
|
32202
|
+
if (radius > width / 2.0 || radius > height / 2.0) {
|
|
32203
|
+
radius = Math.min(width / 2.0, height / 2.0);
|
|
32204
|
+
}
|
|
32205
|
+
const offset = KAPPA * radius;
|
|
32206
|
+
ops = [
|
|
32207
|
+
moveTo(0, radius),
|
|
32208
|
+
appendBezierCurve(0, radius - offset, radius - offset, 0, radius, 0),
|
|
32209
|
+
lineTo(width - radius, 0),
|
|
32210
|
+
appendBezierCurve(width - radius + offset, 0, width, radius - offset, width, radius),
|
|
32211
|
+
lineTo(width, height - radius),
|
|
32212
|
+
appendBezierCurve(width, height - radius + offset, width - radius + offset, height, width - radius, height),
|
|
32213
|
+
lineTo(radius, height),
|
|
32214
|
+
appendBezierCurve(radius - offset, height, 0, height - radius + offset, 0, height - radius),
|
|
32215
|
+
closePath(),
|
|
32216
|
+
];
|
|
32217
|
+
}
|
|
32244
32218
|
return [
|
|
32245
32219
|
pushGraphicsState(),
|
|
32246
32220
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
@@ -32249,14 +32223,12 @@ end\
|
|
|
32249
32223
|
setLineWidth(options.borderWidth),
|
|
32250
32224
|
options.borderLineCap && setLineCap(options.borderLineCap),
|
|
32251
32225
|
setDashPattern((_a = options.borderDashArray) !== null && _a !== void 0 ? _a : [], (_b = options.borderDashPhase) !== null && _b !== void 0 ? _b : 0),
|
|
32226
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32227
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32252
32228
|
translate(options.x, options.y),
|
|
32253
32229
|
rotateRadians(toRadians(options.rotate)),
|
|
32254
32230
|
skewRadians(toRadians(options.xSkew), toRadians(options.ySkew)),
|
|
32255
|
-
|
|
32256
|
-
lineTo(0, options.height),
|
|
32257
|
-
lineTo(options.width, options.height),
|
|
32258
|
-
lineTo(options.width, 0),
|
|
32259
|
-
closePath(),
|
|
32231
|
+
...ops,
|
|
32260
32232
|
// prettier-ignore
|
|
32261
32233
|
options.color && options.borderWidth ? fillAndStroke()
|
|
32262
32234
|
: options.color ? fill()
|
|
@@ -32320,6 +32292,8 @@ end\
|
|
|
32320
32292
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32321
32293
|
options.color && setFillingColor(options.color),
|
|
32322
32294
|
options.borderColor && setStrokingColor(options.borderColor),
|
|
32295
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32296
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32323
32297
|
setLineWidth(options.borderWidth),
|
|
32324
32298
|
options.borderLineCap && setLineCap(options.borderLineCap),
|
|
32325
32299
|
setDashPattern((_a = options.borderDashArray) !== null && _a !== void 0 ? _a : [], (_b = options.borderDashPhase) !== null && _b !== void 0 ? _b : 0),
|
|
@@ -32352,6 +32326,8 @@ end\
|
|
|
32352
32326
|
return [
|
|
32353
32327
|
pushGraphicsState(),
|
|
32354
32328
|
options.graphicsState && setGraphicsState(options.graphicsState),
|
|
32329
|
+
...(options.clipSpaces ? clipSpaces(options.clipSpaces) : []),
|
|
32330
|
+
options.matrix && concatTransformationMatrix(...options.matrix),
|
|
32355
32331
|
translate(options.x, options.y),
|
|
32356
32332
|
rotateRadians(toRadians((_a = options.rotate) !== null && _a !== void 0 ? _a : degrees(0))),
|
|
32357
32333
|
options.scale && scale(options.scale, options.scale),
|
|
@@ -33012,7 +32988,7 @@ end\
|
|
|
33012
32988
|
const borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0;
|
|
33013
32989
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33014
32990
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33015
|
-
const rotate = rotateInPlace(
|
|
32991
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33016
32992
|
const black = rgb(0, 0, 0);
|
|
33017
32993
|
const borderColor = (_b = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor())) !== null && _b !== void 0 ? _b : black;
|
|
33018
32994
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33039,21 +33015,37 @@ end\
|
|
|
33039
33015
|
normal: {
|
|
33040
33016
|
on: [
|
|
33041
33017
|
...rotate,
|
|
33042
|
-
...drawCheckBox(
|
|
33018
|
+
...drawCheckBox({
|
|
33019
|
+
...options,
|
|
33020
|
+
color: normalBackgroundColor,
|
|
33021
|
+
filled: true,
|
|
33022
|
+
}),
|
|
33043
33023
|
],
|
|
33044
33024
|
off: [
|
|
33045
33025
|
...rotate,
|
|
33046
|
-
...drawCheckBox(
|
|
33026
|
+
...drawCheckBox({
|
|
33027
|
+
...options,
|
|
33028
|
+
color: normalBackgroundColor,
|
|
33029
|
+
filled: false,
|
|
33030
|
+
}),
|
|
33047
33031
|
],
|
|
33048
33032
|
},
|
|
33049
33033
|
down: {
|
|
33050
33034
|
on: [
|
|
33051
33035
|
...rotate,
|
|
33052
|
-
...drawCheckBox(
|
|
33036
|
+
...drawCheckBox({
|
|
33037
|
+
...options,
|
|
33038
|
+
color: downBackgroundColor,
|
|
33039
|
+
filled: true,
|
|
33040
|
+
}),
|
|
33053
33041
|
],
|
|
33054
33042
|
off: [
|
|
33055
33043
|
...rotate,
|
|
33056
|
-
...drawCheckBox(
|
|
33044
|
+
...drawCheckBox({
|
|
33045
|
+
...options,
|
|
33046
|
+
color: downBackgroundColor,
|
|
33047
|
+
filled: false,
|
|
33048
|
+
}),
|
|
33057
33049
|
],
|
|
33058
33050
|
},
|
|
33059
33051
|
};
|
|
@@ -33069,7 +33061,7 @@ end\
|
|
|
33069
33061
|
const borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0;
|
|
33070
33062
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33071
33063
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33072
|
-
const rotate = rotateInPlace(
|
|
33064
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33073
33065
|
const black = rgb(0, 0, 0);
|
|
33074
33066
|
const borderColor = (_b = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor())) !== null && _b !== void 0 ? _b : black;
|
|
33075
33067
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33095,21 +33087,37 @@ end\
|
|
|
33095
33087
|
normal: {
|
|
33096
33088
|
on: [
|
|
33097
33089
|
...rotate,
|
|
33098
|
-
...drawRadioButton(
|
|
33090
|
+
...drawRadioButton({
|
|
33091
|
+
...options,
|
|
33092
|
+
color: normalBackgroundColor,
|
|
33093
|
+
filled: true,
|
|
33094
|
+
}),
|
|
33099
33095
|
],
|
|
33100
33096
|
off: [
|
|
33101
33097
|
...rotate,
|
|
33102
|
-
...drawRadioButton(
|
|
33098
|
+
...drawRadioButton({
|
|
33099
|
+
...options,
|
|
33100
|
+
color: normalBackgroundColor,
|
|
33101
|
+
filled: false,
|
|
33102
|
+
}),
|
|
33103
33103
|
],
|
|
33104
33104
|
},
|
|
33105
33105
|
down: {
|
|
33106
33106
|
on: [
|
|
33107
33107
|
...rotate,
|
|
33108
|
-
...drawRadioButton(
|
|
33108
|
+
...drawRadioButton({
|
|
33109
|
+
...options,
|
|
33110
|
+
color: downBackgroundColor,
|
|
33111
|
+
filled: true,
|
|
33112
|
+
}),
|
|
33109
33113
|
],
|
|
33110
33114
|
off: [
|
|
33111
33115
|
...rotate,
|
|
33112
|
-
...drawRadioButton(
|
|
33116
|
+
...drawRadioButton({
|
|
33117
|
+
...options,
|
|
33118
|
+
color: downBackgroundColor,
|
|
33119
|
+
filled: false,
|
|
33120
|
+
}),
|
|
33113
33121
|
],
|
|
33114
33122
|
},
|
|
33115
33123
|
};
|
|
@@ -33130,7 +33138,7 @@ end\
|
|
|
33130
33138
|
const borderWidth = (_d = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _d !== void 0 ? _d : 0;
|
|
33131
33139
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33132
33140
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33133
|
-
const rotate = rotateInPlace(
|
|
33141
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33134
33142
|
const black = rgb(0, 0, 0);
|
|
33135
33143
|
const borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor());
|
|
33136
33144
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33176,11 +33184,19 @@ end\
|
|
|
33176
33184
|
return {
|
|
33177
33185
|
normal: [
|
|
33178
33186
|
...rotate,
|
|
33179
|
-
...drawButton(
|
|
33187
|
+
...drawButton({
|
|
33188
|
+
...options,
|
|
33189
|
+
color: normalBackgroundColor,
|
|
33190
|
+
textLines: [normalLayout.line],
|
|
33191
|
+
}),
|
|
33180
33192
|
],
|
|
33181
33193
|
down: [
|
|
33182
33194
|
...rotate,
|
|
33183
|
-
...drawButton(
|
|
33195
|
+
...drawButton({
|
|
33196
|
+
...options,
|
|
33197
|
+
color: downBackgroundColor,
|
|
33198
|
+
textLines: [downLayout.line],
|
|
33199
|
+
}),
|
|
33184
33200
|
],
|
|
33185
33201
|
};
|
|
33186
33202
|
};
|
|
@@ -33198,7 +33214,7 @@ end\
|
|
|
33198
33214
|
const borderWidth = (_b = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _b !== void 0 ? _b : 0;
|
|
33199
33215
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33200
33216
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33201
|
-
const rotate = rotateInPlace(
|
|
33217
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33202
33218
|
const black = rgb(0, 0, 0);
|
|
33203
33219
|
const borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor());
|
|
33204
33220
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33279,7 +33295,7 @@ end\
|
|
|
33279
33295
|
const borderWidth = (_b = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _b !== void 0 ? _b : 0;
|
|
33280
33296
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33281
33297
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33282
|
-
const rotate = rotateInPlace(
|
|
33298
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33283
33299
|
const black = rgb(0, 0, 0);
|
|
33284
33300
|
const borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor());
|
|
33285
33301
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33333,7 +33349,7 @@ end\
|
|
|
33333
33349
|
const borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0;
|
|
33334
33350
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
33335
33351
|
const { width, height } = adjustDimsForRotation(rectangle, rotation);
|
|
33336
|
-
const rotate = rotateInPlace(
|
|
33352
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
33337
33353
|
const black = rgb(0, 0, 0);
|
|
33338
33354
|
const borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor());
|
|
33339
33355
|
const normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor());
|
|
@@ -33451,13 +33467,11 @@ end\
|
|
|
33451
33467
|
*
|
|
33452
33468
|
* @returns Resolves when the embedding is complete.
|
|
33453
33469
|
*/
|
|
33454
|
-
embed() {
|
|
33455
|
-
|
|
33456
|
-
|
|
33457
|
-
|
|
33458
|
-
|
|
33459
|
-
}
|
|
33460
|
-
});
|
|
33470
|
+
async embed() {
|
|
33471
|
+
if (!this.alreadyEmbedded) {
|
|
33472
|
+
await this.embedder.embedIntoContext(this.doc.context, this.ref);
|
|
33473
|
+
this.alreadyEmbedded = true;
|
|
33474
|
+
}
|
|
33461
33475
|
}
|
|
33462
33476
|
}
|
|
33463
33477
|
/**
|
|
@@ -33576,14 +33590,12 @@ end\
|
|
|
33576
33590
|
*
|
|
33577
33591
|
* @returns Resolves when the embedding is complete.
|
|
33578
33592
|
*/
|
|
33579
|
-
embed() {
|
|
33580
|
-
|
|
33581
|
-
|
|
33582
|
-
|
|
33583
|
-
|
|
33584
|
-
|
|
33585
|
-
}
|
|
33586
|
-
});
|
|
33593
|
+
async embed() {
|
|
33594
|
+
// TODO: Cleanup orphan embedded objects if a font is embedded multiple times...
|
|
33595
|
+
if (this.modified) {
|
|
33596
|
+
await this.embedder.embedIntoContext(this.doc.context, this.ref);
|
|
33597
|
+
this.modified = false;
|
|
33598
|
+
}
|
|
33587
33599
|
}
|
|
33588
33600
|
}
|
|
33589
33601
|
/**
|
|
@@ -33682,22 +33694,20 @@ end\
|
|
|
33682
33694
|
*
|
|
33683
33695
|
* @returns Resolves when the embedding is complete.
|
|
33684
33696
|
*/
|
|
33685
|
-
embed() {
|
|
33686
|
-
|
|
33687
|
-
|
|
33688
|
-
|
|
33689
|
-
|
|
33690
|
-
|
|
33691
|
-
|
|
33692
|
-
|
|
33693
|
-
|
|
33694
|
-
|
|
33695
|
-
|
|
33696
|
-
|
|
33697
|
-
|
|
33698
|
-
|
|
33699
|
-
this.embedder = undefined;
|
|
33700
|
-
});
|
|
33697
|
+
async embed() {
|
|
33698
|
+
if (!this.embedder)
|
|
33699
|
+
return;
|
|
33700
|
+
// The image should only be embedded once. If there's a pending embed
|
|
33701
|
+
// operation then wait on it. Otherwise we need to start the embed.
|
|
33702
|
+
if (!this.embedTask) {
|
|
33703
|
+
const { doc, ref } = this;
|
|
33704
|
+
this.embedTask = this.embedder.embedIntoContext(doc.context, ref);
|
|
33705
|
+
}
|
|
33706
|
+
await this.embedTask;
|
|
33707
|
+
// We clear `this.embedder` so that the indirectly referenced image data
|
|
33708
|
+
// can be garbage collected, thus avoiding a memory leak.
|
|
33709
|
+
// See https://github.com/Hopding/pdf-lib/pull/1032/files.
|
|
33710
|
+
this.embedder = undefined;
|
|
33701
33711
|
}
|
|
33702
33712
|
}
|
|
33703
33713
|
/**
|
|
@@ -34041,7 +34051,7 @@ end\
|
|
|
34041
34051
|
const bs = widget.getBorderStyle();
|
|
34042
34052
|
const borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0;
|
|
34043
34053
|
const rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation());
|
|
34044
|
-
const rotate = rotateInPlace(
|
|
34054
|
+
const rotate = rotateInPlace({ ...rectangle, rotation });
|
|
34045
34055
|
const adj = adjustDimsForRotation(rectangle, rotation);
|
|
34046
34056
|
const imageDims = image.scaleToFit(adj.width - borderWidth * 2, adj.height - borderWidth * 2);
|
|
34047
34057
|
// Support borders on images and maybe other properties
|
|
@@ -36961,7 +36971,7 @@ end\
|
|
|
36961
36971
|
const operators = [
|
|
36962
36972
|
pushGraphicsState(),
|
|
36963
36973
|
translate(rectangle.x, rectangle.y),
|
|
36964
|
-
...rotateInPlace(
|
|
36974
|
+
...rotateInPlace({ ...rectangle, rotation: 0 }),
|
|
36965
36975
|
drawObject(xObjectKey),
|
|
36966
36976
|
popGraphicsState(),
|
|
36967
36977
|
].filter(Boolean);
|
|
@@ -37305,39 +37315,37 @@ end\
|
|
|
37305
37315
|
*
|
|
37306
37316
|
* @returns Resolves when the embedding is complete.
|
|
37307
37317
|
*/
|
|
37308
|
-
embed() {
|
|
37309
|
-
|
|
37310
|
-
|
|
37311
|
-
|
|
37312
|
-
|
|
37313
|
-
this.doc.catalog.set(PDFName.of('Names'), this.doc.context.obj({}));
|
|
37314
|
-
}
|
|
37315
|
-
const Names = this.doc.catalog.lookup(PDFName.of('Names'), PDFDict);
|
|
37316
|
-
if (!Names.has(PDFName.of('EmbeddedFiles'))) {
|
|
37317
|
-
Names.set(PDFName.of('EmbeddedFiles'), this.doc.context.obj({}));
|
|
37318
|
-
}
|
|
37319
|
-
const EmbeddedFiles = Names.lookup(PDFName.of('EmbeddedFiles'), PDFDict);
|
|
37320
|
-
if (!EmbeddedFiles.has(PDFName.of('Names'))) {
|
|
37321
|
-
EmbeddedFiles.set(PDFName.of('Names'), this.doc.context.obj([]));
|
|
37322
|
-
}
|
|
37323
|
-
const EFNames = EmbeddedFiles.lookup(PDFName.of('Names'), PDFArray);
|
|
37324
|
-
EFNames.push(PDFHexString.fromText(this.embedder.fileName));
|
|
37325
|
-
EFNames.push(ref);
|
|
37326
|
-
/**
|
|
37327
|
-
* The AF-Tag is needed to achieve PDF-A3 compliance for embedded files
|
|
37328
|
-
*
|
|
37329
|
-
* The following document outlines the uses cases of the associated files (AF) tag.
|
|
37330
|
-
* See:
|
|
37331
|
-
* https://www.pdfa.org/wp-content/uploads/2018/10/PDF20_AN002-AF.pdf
|
|
37332
|
-
*/
|
|
37333
|
-
if (!this.doc.catalog.has(PDFName.of('AF'))) {
|
|
37334
|
-
this.doc.catalog.set(PDFName.of('AF'), this.doc.context.obj([]));
|
|
37335
|
-
}
|
|
37336
|
-
const AF = this.doc.catalog.lookup(PDFName.of('AF'), PDFArray);
|
|
37337
|
-
AF.push(ref);
|
|
37338
|
-
this.alreadyEmbedded = true;
|
|
37318
|
+
async embed() {
|
|
37319
|
+
if (!this.alreadyEmbedded) {
|
|
37320
|
+
const ref = await this.embedder.embedIntoContext(this.doc.context, this.ref);
|
|
37321
|
+
if (!this.doc.catalog.has(PDFName.of('Names'))) {
|
|
37322
|
+
this.doc.catalog.set(PDFName.of('Names'), this.doc.context.obj({}));
|
|
37339
37323
|
}
|
|
37340
|
-
|
|
37324
|
+
const Names = this.doc.catalog.lookup(PDFName.of('Names'), PDFDict);
|
|
37325
|
+
if (!Names.has(PDFName.of('EmbeddedFiles'))) {
|
|
37326
|
+
Names.set(PDFName.of('EmbeddedFiles'), this.doc.context.obj({}));
|
|
37327
|
+
}
|
|
37328
|
+
const EmbeddedFiles = Names.lookup(PDFName.of('EmbeddedFiles'), PDFDict);
|
|
37329
|
+
if (!EmbeddedFiles.has(PDFName.of('Names'))) {
|
|
37330
|
+
EmbeddedFiles.set(PDFName.of('Names'), this.doc.context.obj([]));
|
|
37331
|
+
}
|
|
37332
|
+
const EFNames = EmbeddedFiles.lookup(PDFName.of('Names'), PDFArray);
|
|
37333
|
+
EFNames.push(PDFHexString.fromText(this.embedder.fileName));
|
|
37334
|
+
EFNames.push(ref);
|
|
37335
|
+
/**
|
|
37336
|
+
* The AF-Tag is needed to achieve PDF-A3 compliance for embedded files
|
|
37337
|
+
*
|
|
37338
|
+
* The following document outlines the uses cases of the associated files (AF) tag.
|
|
37339
|
+
* See:
|
|
37340
|
+
* https://www.pdfa.org/wp-content/uploads/2018/10/PDF20_AN002-AF.pdf
|
|
37341
|
+
*/
|
|
37342
|
+
if (!this.doc.catalog.has(PDFName.of('AF'))) {
|
|
37343
|
+
this.doc.catalog.set(PDFName.of('AF'), this.doc.context.obj([]));
|
|
37344
|
+
}
|
|
37345
|
+
const AF = this.doc.catalog.lookup(PDFName.of('AF'), PDFArray);
|
|
37346
|
+
AF.push(ref);
|
|
37347
|
+
this.alreadyEmbedded = true;
|
|
37348
|
+
}
|
|
37341
37349
|
}
|
|
37342
37350
|
}
|
|
37343
37351
|
/**
|
|
@@ -37372,28 +37380,26 @@ end\
|
|
|
37372
37380
|
*
|
|
37373
37381
|
* @returns Resolves when the embedding is complete.
|
|
37374
37382
|
*/
|
|
37375
|
-
embed() {
|
|
37376
|
-
|
|
37377
|
-
|
|
37378
|
-
|
|
37379
|
-
|
|
37380
|
-
|
|
37381
|
-
catalog.set(PDFName.of('Names'), context.obj({}));
|
|
37382
|
-
}
|
|
37383
|
-
const Names = catalog.lookup(PDFName.of('Names'), PDFDict);
|
|
37384
|
-
if (!Names.has(PDFName.of('JavaScript'))) {
|
|
37385
|
-
Names.set(PDFName.of('JavaScript'), context.obj({}));
|
|
37386
|
-
}
|
|
37387
|
-
const Javascript = Names.lookup(PDFName.of('JavaScript'), PDFDict);
|
|
37388
|
-
if (!Javascript.has(PDFName.of('Names'))) {
|
|
37389
|
-
Javascript.set(PDFName.of('Names'), context.obj([]));
|
|
37390
|
-
}
|
|
37391
|
-
const JSNames = Javascript.lookup(PDFName.of('Names'), PDFArray);
|
|
37392
|
-
JSNames.push(PDFHexString.fromText(this.embedder.scriptName));
|
|
37393
|
-
JSNames.push(ref);
|
|
37394
|
-
this.alreadyEmbedded = true;
|
|
37383
|
+
async embed() {
|
|
37384
|
+
if (!this.alreadyEmbedded) {
|
|
37385
|
+
const { catalog, context } = this.doc;
|
|
37386
|
+
const ref = await this.embedder.embedIntoContext(this.doc.context, this.ref);
|
|
37387
|
+
if (!catalog.has(PDFName.of('Names'))) {
|
|
37388
|
+
catalog.set(PDFName.of('Names'), context.obj({}));
|
|
37395
37389
|
}
|
|
37396
|
-
|
|
37390
|
+
const Names = catalog.lookup(PDFName.of('Names'), PDFDict);
|
|
37391
|
+
if (!Names.has(PDFName.of('JavaScript'))) {
|
|
37392
|
+
Names.set(PDFName.of('JavaScript'), context.obj({}));
|
|
37393
|
+
}
|
|
37394
|
+
const Javascript = Names.lookup(PDFName.of('JavaScript'), PDFDict);
|
|
37395
|
+
if (!Javascript.has(PDFName.of('Names'))) {
|
|
37396
|
+
Javascript.set(PDFName.of('Names'), context.obj([]));
|
|
37397
|
+
}
|
|
37398
|
+
const JSNames = Javascript.lookup(PDFName.of('Names'), PDFArray);
|
|
37399
|
+
JSNames.push(PDFHexString.fromText(this.embedder.scriptName));
|
|
37400
|
+
JSNames.push(ref);
|
|
37401
|
+
this.alreadyEmbedded = true;
|
|
37402
|
+
}
|
|
37397
37403
|
}
|
|
37398
37404
|
}
|
|
37399
37405
|
/**
|
|
@@ -37417,21 +37423,19 @@ end\
|
|
|
37417
37423
|
static for(script, scriptName) {
|
|
37418
37424
|
return new JavaScriptEmbedder(script, scriptName);
|
|
37419
37425
|
}
|
|
37420
|
-
embedIntoContext(context, ref) {
|
|
37421
|
-
|
|
37422
|
-
|
|
37423
|
-
|
|
37424
|
-
|
|
37425
|
-
JS: PDFHexString.fromText(this.script),
|
|
37426
|
-
});
|
|
37427
|
-
if (ref) {
|
|
37428
|
-
context.assign(ref, jsActionDict);
|
|
37429
|
-
return ref;
|
|
37430
|
-
}
|
|
37431
|
-
else {
|
|
37432
|
-
return context.register(jsActionDict);
|
|
37433
|
-
}
|
|
37426
|
+
async embedIntoContext(context, ref) {
|
|
37427
|
+
const jsActionDict = context.obj({
|
|
37428
|
+
Type: 'Action',
|
|
37429
|
+
S: 'JavaScript',
|
|
37430
|
+
JS: PDFHexString.fromText(this.script),
|
|
37434
37431
|
});
|
|
37432
|
+
if (ref) {
|
|
37433
|
+
context.assign(ref, jsActionDict);
|
|
37434
|
+
return ref;
|
|
37435
|
+
}
|
|
37436
|
+
else {
|
|
37437
|
+
return context.register(jsActionDict);
|
|
37438
|
+
}
|
|
37435
37439
|
}
|
|
37436
37440
|
}
|
|
37437
37441
|
|
|
@@ -39165,42 +39169,38 @@ end\
|
|
|
39165
39169
|
* @param options The options to be used when loading the document.
|
|
39166
39170
|
* @returns Resolves with a document loaded from the input.
|
|
39167
39171
|
*/
|
|
39168
|
-
static load(pdf, options = {}) {
|
|
39169
|
-
|
|
39170
|
-
|
|
39171
|
-
|
|
39172
|
-
|
|
39173
|
-
|
|
39174
|
-
|
|
39175
|
-
|
|
39176
|
-
|
|
39177
|
-
|
|
39178
|
-
|
|
39179
|
-
|
|
39180
|
-
|
|
39181
|
-
|
|
39182
|
-
|
|
39183
|
-
|
|
39184
|
-
|
|
39185
|
-
|
|
39186
|
-
|
|
39187
|
-
}
|
|
39188
|
-
});
|
|
39172
|
+
static async load(pdf, options = {}) {
|
|
39173
|
+
const { ignoreEncryption = false, parseSpeed = exports.ParseSpeeds.Slow, throwOnInvalidObject = false, updateMetadata = true, capNumbers = false, password, } = options;
|
|
39174
|
+
assertIs(pdf, 'pdf', ['string', Uint8Array, ArrayBuffer]);
|
|
39175
|
+
assertIs(ignoreEncryption, 'ignoreEncryption', ['boolean']);
|
|
39176
|
+
assertIs(parseSpeed, 'parseSpeed', ['number']);
|
|
39177
|
+
assertIs(throwOnInvalidObject, 'throwOnInvalidObject', ['boolean']);
|
|
39178
|
+
assertIs(password, 'password', ['string', 'undefined']);
|
|
39179
|
+
const bytes = toUint8Array(pdf);
|
|
39180
|
+
const context = await PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, capNumbers).parseDocument();
|
|
39181
|
+
if (!!context.lookup(context.trailerInfo.Encrypt) && password !== undefined) {
|
|
39182
|
+
// Decrypt
|
|
39183
|
+
const fileIds = context.lookup(context.trailerInfo.ID, PDFArray);
|
|
39184
|
+
const encryptDict = context.lookup(context.trailerInfo.Encrypt, PDFDict);
|
|
39185
|
+
const decryptedContext = await PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, capNumbers, new CipherTransformFactory(encryptDict, fileIds.get(0).asBytes(), password)).parseDocument();
|
|
39186
|
+
return new PDFDocument(decryptedContext, true, updateMetadata);
|
|
39187
|
+
}
|
|
39188
|
+
else {
|
|
39189
|
+
return new PDFDocument(context, ignoreEncryption, updateMetadata);
|
|
39190
|
+
}
|
|
39189
39191
|
}
|
|
39190
39192
|
/**
|
|
39191
39193
|
* Create a new [[PDFDocument]].
|
|
39192
39194
|
* @returns Resolves with the newly created document.
|
|
39193
39195
|
*/
|
|
39194
|
-
static create(options = {}) {
|
|
39195
|
-
|
|
39196
|
-
|
|
39197
|
-
|
|
39198
|
-
|
|
39199
|
-
|
|
39200
|
-
|
|
39201
|
-
|
|
39202
|
-
return new PDFDocument(context, false, updateMetadata);
|
|
39203
|
-
});
|
|
39196
|
+
static async create(options = {}) {
|
|
39197
|
+
const { updateMetadata = true } = options;
|
|
39198
|
+
const context = PDFContext.create();
|
|
39199
|
+
const pageTree = PDFPageTree.withContext(context);
|
|
39200
|
+
const pageTreeRef = context.register(pageTree);
|
|
39201
|
+
const catalog = PDFCatalog.withContextAndPages(context, pageTreeRef);
|
|
39202
|
+
context.trailerInfo.Root = context.register(catalog);
|
|
39203
|
+
return new PDFDocument(context, false, updateMetadata);
|
|
39204
39204
|
}
|
|
39205
39205
|
/**
|
|
39206
39206
|
* Register a fontkit instance. This must be done before custom fonts can
|
|
@@ -39684,22 +39684,20 @@ end\
|
|
|
39684
39684
|
* @param indices The indices of the pages that should be copied.
|
|
39685
39685
|
* @returns Resolves with an array of pages copied into this document.
|
|
39686
39686
|
*/
|
|
39687
|
-
copyPages(srcDoc, indices) {
|
|
39688
|
-
|
|
39689
|
-
|
|
39690
|
-
|
|
39691
|
-
|
|
39692
|
-
|
|
39693
|
-
|
|
39694
|
-
|
|
39695
|
-
|
|
39696
|
-
|
|
39697
|
-
|
|
39698
|
-
|
|
39699
|
-
|
|
39700
|
-
|
|
39701
|
-
return copiedPages;
|
|
39702
|
-
});
|
|
39687
|
+
async copyPages(srcDoc, indices) {
|
|
39688
|
+
assertIs(srcDoc, 'srcDoc', [[PDFDocument, 'PDFDocument']]);
|
|
39689
|
+
assertIs(indices, 'indices', [Array]);
|
|
39690
|
+
await srcDoc.flush();
|
|
39691
|
+
const copier = PDFObjectCopier.for(srcDoc.context, this.context);
|
|
39692
|
+
const srcPages = srcDoc.getPages();
|
|
39693
|
+
const copiedPages = new Array(indices.length);
|
|
39694
|
+
for (let idx = 0, len = indices.length; idx < len; idx++) {
|
|
39695
|
+
const srcPage = srcPages[indices[idx]];
|
|
39696
|
+
const copiedPage = copier.copy(srcPage.node);
|
|
39697
|
+
const ref = this.context.register(copiedPage);
|
|
39698
|
+
copiedPages[idx] = PDFPage.of(copiedPage, ref, this);
|
|
39699
|
+
}
|
|
39700
|
+
return copiedPages;
|
|
39703
39701
|
}
|
|
39704
39702
|
/**
|
|
39705
39703
|
* Get a copy of this document.
|
|
@@ -39715,37 +39713,35 @@ end\
|
|
|
39715
39713
|
*
|
|
39716
39714
|
* @returns Resolves with a copy this document.
|
|
39717
39715
|
*/
|
|
39718
|
-
copy() {
|
|
39719
|
-
|
|
39720
|
-
|
|
39721
|
-
|
|
39722
|
-
|
|
39723
|
-
|
|
39724
|
-
|
|
39725
|
-
|
|
39726
|
-
|
|
39727
|
-
|
|
39728
|
-
|
|
39729
|
-
|
|
39730
|
-
|
|
39731
|
-
|
|
39732
|
-
|
|
39733
|
-
|
|
39734
|
-
|
|
39735
|
-
|
|
39736
|
-
|
|
39737
|
-
|
|
39738
|
-
|
|
39739
|
-
|
|
39740
|
-
|
|
39741
|
-
|
|
39742
|
-
|
|
39743
|
-
|
|
39744
|
-
|
|
39745
|
-
|
|
39746
|
-
|
|
39747
|
-
return pdfCopy;
|
|
39748
|
-
});
|
|
39716
|
+
async copy() {
|
|
39717
|
+
const pdfCopy = await PDFDocument.create();
|
|
39718
|
+
const contentPages = await pdfCopy.copyPages(this, this.getPageIndices());
|
|
39719
|
+
for (let idx = 0, len = contentPages.length; idx < len; idx++) {
|
|
39720
|
+
pdfCopy.addPage(contentPages[idx]);
|
|
39721
|
+
}
|
|
39722
|
+
if (this.getAuthor() !== undefined) {
|
|
39723
|
+
pdfCopy.setAuthor(this.getAuthor());
|
|
39724
|
+
}
|
|
39725
|
+
if (this.getCreationDate() !== undefined) {
|
|
39726
|
+
pdfCopy.setCreationDate(this.getCreationDate());
|
|
39727
|
+
}
|
|
39728
|
+
if (this.getCreator() !== undefined) {
|
|
39729
|
+
pdfCopy.setCreator(this.getCreator());
|
|
39730
|
+
}
|
|
39731
|
+
if (this.getModificationDate() !== undefined) {
|
|
39732
|
+
pdfCopy.setModificationDate(this.getModificationDate());
|
|
39733
|
+
}
|
|
39734
|
+
if (this.getProducer() !== undefined) {
|
|
39735
|
+
pdfCopy.setProducer(this.getProducer());
|
|
39736
|
+
}
|
|
39737
|
+
if (this.getSubject() !== undefined) {
|
|
39738
|
+
pdfCopy.setSubject(this.getSubject());
|
|
39739
|
+
}
|
|
39740
|
+
if (this.getTitle() !== undefined) {
|
|
39741
|
+
pdfCopy.setTitle(this.getTitle());
|
|
39742
|
+
}
|
|
39743
|
+
pdfCopy.defaultWordBreaks = this.defaultWordBreaks;
|
|
39744
|
+
return pdfCopy;
|
|
39749
39745
|
}
|
|
39750
39746
|
/**
|
|
39751
39747
|
* Add JavaScript to this document. The supplied `script` is executed when the
|
|
@@ -39834,23 +39830,21 @@ end\
|
|
|
39834
39830
|
* @param name The name of the file to be attached.
|
|
39835
39831
|
* @returns Resolves when the attachment is complete.
|
|
39836
39832
|
*/
|
|
39837
|
-
attach(attachment, name, options = {}) {
|
|
39838
|
-
|
|
39839
|
-
|
|
39840
|
-
|
|
39841
|
-
|
|
39842
|
-
|
|
39843
|
-
|
|
39844
|
-
|
|
39845
|
-
|
|
39846
|
-
|
|
39847
|
-
|
|
39848
|
-
|
|
39849
|
-
|
|
39850
|
-
|
|
39851
|
-
|
|
39852
|
-
this.embeddedFiles.push(embeddedFile);
|
|
39853
|
-
});
|
|
39833
|
+
async attach(attachment, name, options = {}) {
|
|
39834
|
+
assertIs(attachment, 'attachment', ['string', Uint8Array, ArrayBuffer]);
|
|
39835
|
+
assertIs(name, 'name', ['string']);
|
|
39836
|
+
assertOrUndefined(options.mimeType, 'mimeType', ['string']);
|
|
39837
|
+
assertOrUndefined(options.description, 'description', ['string']);
|
|
39838
|
+
assertOrUndefined(options.creationDate, 'options.creationDate', [Date]);
|
|
39839
|
+
assertOrUndefined(options.modificationDate, 'options.modificationDate', [
|
|
39840
|
+
Date,
|
|
39841
|
+
]);
|
|
39842
|
+
assertIsOneOfOrUndefined(options.afRelationship, 'options.afRelationship', exports.AFRelationship);
|
|
39843
|
+
const bytes = toUint8Array(attachment);
|
|
39844
|
+
const embedder = FileEmbedder.for(bytes, name, options);
|
|
39845
|
+
const ref = this.context.nextRef();
|
|
39846
|
+
const embeddedFile = PDFEmbeddedFile.of(ref, this, embedder);
|
|
39847
|
+
this.embeddedFiles.push(embeddedFile);
|
|
39854
39848
|
}
|
|
39855
39849
|
/**
|
|
39856
39850
|
* Embed a font into this document. The input data can be provided in multiple
|
|
@@ -39887,30 +39881,28 @@ end\
|
|
|
39887
39881
|
* @param options The options to be used when embedding the font.
|
|
39888
39882
|
* @returns Resolves with the embedded font.
|
|
39889
39883
|
*/
|
|
39890
|
-
embedFont(font, options = {}) {
|
|
39891
|
-
|
|
39892
|
-
|
|
39893
|
-
|
|
39894
|
-
|
|
39895
|
-
|
|
39896
|
-
|
|
39897
|
-
|
|
39898
|
-
|
|
39899
|
-
|
|
39900
|
-
|
|
39901
|
-
|
|
39902
|
-
|
|
39903
|
-
|
|
39904
|
-
|
|
39905
|
-
|
|
39906
|
-
|
|
39907
|
-
|
|
39908
|
-
|
|
39909
|
-
|
|
39910
|
-
|
|
39911
|
-
|
|
39912
|
-
return pdfFont;
|
|
39913
|
-
});
|
|
39884
|
+
async embedFont(font, options = {}) {
|
|
39885
|
+
const { subset = false, customName, features } = options;
|
|
39886
|
+
assertIs(font, 'font', ['string', Uint8Array, ArrayBuffer]);
|
|
39887
|
+
assertIs(subset, 'subset', ['boolean']);
|
|
39888
|
+
let embedder;
|
|
39889
|
+
if (isStandardFont(font)) {
|
|
39890
|
+
embedder = StandardFontEmbedder.for(font, customName);
|
|
39891
|
+
}
|
|
39892
|
+
else if (canBeConvertedToUint8Array(font)) {
|
|
39893
|
+
const bytes = toUint8Array(font);
|
|
39894
|
+
const fontkit = this.assertFontkit();
|
|
39895
|
+
embedder = subset
|
|
39896
|
+
? await CustomFontSubsetEmbedder.for(fontkit, bytes, customName, features)
|
|
39897
|
+
: await CustomFontEmbedder.for(fontkit, bytes, customName, features);
|
|
39898
|
+
}
|
|
39899
|
+
else {
|
|
39900
|
+
throw new TypeError('`font` must be one of `StandardFonts | string | Uint8Array | ArrayBuffer`');
|
|
39901
|
+
}
|
|
39902
|
+
const ref = this.context.nextRef();
|
|
39903
|
+
const pdfFont = PDFFont.of(ref, this, embedder);
|
|
39904
|
+
this.fonts.push(pdfFont);
|
|
39905
|
+
return pdfFont;
|
|
39914
39906
|
}
|
|
39915
39907
|
/**
|
|
39916
39908
|
* Embed a standard font into this document.
|
|
@@ -39964,16 +39956,14 @@ end\
|
|
|
39964
39956
|
* @param jpg The input data for a JPEG image.
|
|
39965
39957
|
* @returns Resolves with the embedded image.
|
|
39966
39958
|
*/
|
|
39967
|
-
embedJpg(jpg) {
|
|
39968
|
-
|
|
39969
|
-
|
|
39970
|
-
|
|
39971
|
-
|
|
39972
|
-
|
|
39973
|
-
|
|
39974
|
-
|
|
39975
|
-
return pdfImage;
|
|
39976
|
-
});
|
|
39959
|
+
async embedJpg(jpg) {
|
|
39960
|
+
assertIs(jpg, 'jpg', ['string', Uint8Array, ArrayBuffer]);
|
|
39961
|
+
const bytes = toUint8Array(jpg);
|
|
39962
|
+
const embedder = await JpegEmbedder.for(bytes);
|
|
39963
|
+
const ref = this.context.nextRef();
|
|
39964
|
+
const pdfImage = PDFImage.of(ref, this, embedder);
|
|
39965
|
+
this.images.push(pdfImage);
|
|
39966
|
+
return pdfImage;
|
|
39977
39967
|
}
|
|
39978
39968
|
/**
|
|
39979
39969
|
* Embed a PNG image into this document. The input data can be provided in
|
|
@@ -40005,16 +39995,14 @@ end\
|
|
|
40005
39995
|
* @param png The input data for a PNG image.
|
|
40006
39996
|
* @returns Resolves with the embedded image.
|
|
40007
39997
|
*/
|
|
40008
|
-
embedPng(png) {
|
|
40009
|
-
|
|
40010
|
-
|
|
40011
|
-
|
|
40012
|
-
|
|
40013
|
-
|
|
40014
|
-
|
|
40015
|
-
|
|
40016
|
-
return pdfImage;
|
|
40017
|
-
});
|
|
39998
|
+
async embedPng(png) {
|
|
39999
|
+
assertIs(png, 'png', ['string', Uint8Array, ArrayBuffer]);
|
|
40000
|
+
const bytes = toUint8Array(png);
|
|
40001
|
+
const embedder = await PngEmbedder.for(bytes);
|
|
40002
|
+
const ref = this.context.nextRef();
|
|
40003
|
+
const pdfImage = PDFImage.of(ref, this, embedder);
|
|
40004
|
+
this.images.push(pdfImage);
|
|
40005
|
+
return pdfImage;
|
|
40018
40006
|
}
|
|
40019
40007
|
/**
|
|
40020
40008
|
* Embed one or more PDF pages into this document.
|
|
@@ -40036,19 +40024,17 @@ end\
|
|
|
40036
40024
|
* @param indices The indices of the pages that should be embedded.
|
|
40037
40025
|
* @returns Resolves with an array of the embedded pages.
|
|
40038
40026
|
*/
|
|
40039
|
-
embedPdf(pdf, indices = [0]) {
|
|
40040
|
-
|
|
40041
|
-
|
|
40042
|
-
|
|
40043
|
-
|
|
40044
|
-
|
|
40045
|
-
|
|
40046
|
-
|
|
40047
|
-
|
|
40048
|
-
|
|
40049
|
-
|
|
40050
|
-
return this.embedPages(srcPages);
|
|
40051
|
-
});
|
|
40027
|
+
async embedPdf(pdf, indices = [0]) {
|
|
40028
|
+
assertIs(pdf, 'pdf', [
|
|
40029
|
+
'string',
|
|
40030
|
+
Uint8Array,
|
|
40031
|
+
ArrayBuffer,
|
|
40032
|
+
[PDFDocument, 'PDFDocument'],
|
|
40033
|
+
]);
|
|
40034
|
+
assertIs(indices, 'indices', [Array]);
|
|
40035
|
+
const srcDoc = pdf instanceof PDFDocument ? pdf : await PDFDocument.load(pdf);
|
|
40036
|
+
const srcPages = pluckIndices(srcDoc.getPages(), indices);
|
|
40037
|
+
return this.embedPages(srcPages);
|
|
40052
40038
|
}
|
|
40053
40039
|
/**
|
|
40054
40040
|
* Embed a single PDF page into this document.
|
|
@@ -40082,12 +40068,10 @@ end\
|
|
|
40082
40068
|
* page anywhere it is drawn.
|
|
40083
40069
|
* @returns Resolves with the embedded pdf page.
|
|
40084
40070
|
*/
|
|
40085
|
-
embedPage(page, boundingBox, transformationMatrix) {
|
|
40086
|
-
|
|
40087
|
-
|
|
40088
|
-
|
|
40089
|
-
return embeddedPage;
|
|
40090
|
-
});
|
|
40071
|
+
async embedPage(page, boundingBox, transformationMatrix) {
|
|
40072
|
+
assertIs(page, 'page', [[PDFPage, 'PDFPage']]);
|
|
40073
|
+
const [embeddedPage] = await this.embedPages([page], [boundingBox], [transformationMatrix]);
|
|
40074
|
+
return embeddedPage;
|
|
40091
40075
|
}
|
|
40092
40076
|
/**
|
|
40093
40077
|
* Embed one or more PDF pages into this document.
|
|
@@ -40117,34 +40101,32 @@ end\
|
|
|
40117
40101
|
* (each page's transformation will apply anywhere it is drawn).
|
|
40118
40102
|
* @returns Resolves with an array of the embedded pdf pages.
|
|
40119
40103
|
*/
|
|
40120
|
-
embedPages(pages, boundingBoxes = [], transformationMatrices = []) {
|
|
40121
|
-
|
|
40122
|
-
|
|
40123
|
-
|
|
40124
|
-
|
|
40125
|
-
|
|
40126
|
-
|
|
40127
|
-
|
|
40128
|
-
|
|
40129
|
-
|
|
40130
|
-
|
|
40131
|
-
|
|
40132
|
-
|
|
40133
|
-
|
|
40134
|
-
|
|
40135
|
-
|
|
40136
|
-
|
|
40137
|
-
|
|
40138
|
-
|
|
40139
|
-
|
|
40140
|
-
|
|
40141
|
-
|
|
40142
|
-
|
|
40143
|
-
|
|
40144
|
-
|
|
40145
|
-
|
|
40146
|
-
return embeddedPages;
|
|
40147
|
-
});
|
|
40104
|
+
async embedPages(pages, boundingBoxes = [], transformationMatrices = []) {
|
|
40105
|
+
if (pages.length === 0)
|
|
40106
|
+
return [];
|
|
40107
|
+
// Assert all pages have the same context
|
|
40108
|
+
for (let idx = 0, len = pages.length - 1; idx < len; idx++) {
|
|
40109
|
+
const currPage = pages[idx];
|
|
40110
|
+
const nextPage = pages[idx + 1];
|
|
40111
|
+
if (currPage.node.context !== nextPage.node.context) {
|
|
40112
|
+
throw new PageEmbeddingMismatchedContextError();
|
|
40113
|
+
}
|
|
40114
|
+
}
|
|
40115
|
+
const context = pages[0].node.context;
|
|
40116
|
+
const maybeCopyPage = context === this.context
|
|
40117
|
+
? (p) => p
|
|
40118
|
+
: PDFObjectCopier.for(context, this.context).copy;
|
|
40119
|
+
const embeddedPages = new Array(pages.length);
|
|
40120
|
+
for (let idx = 0, len = pages.length; idx < len; idx++) {
|
|
40121
|
+
const page = maybeCopyPage(pages[idx].node);
|
|
40122
|
+
const box = boundingBoxes[idx];
|
|
40123
|
+
const matrix = transformationMatrices[idx];
|
|
40124
|
+
const embedder = await PDFPageEmbedder.for(page, box, matrix);
|
|
40125
|
+
const ref = this.context.nextRef();
|
|
40126
|
+
embeddedPages[idx] = PDFEmbeddedPage.of(ref, this, embedder);
|
|
40127
|
+
}
|
|
40128
|
+
this.embeddedPages.push(...embeddedPages);
|
|
40129
|
+
return embeddedPages;
|
|
40148
40130
|
}
|
|
40149
40131
|
/**
|
|
40150
40132
|
* > **NOTE:** You shouldn't need to call this method directly. The [[save]]
|
|
@@ -40156,14 +40138,12 @@ end\
|
|
|
40156
40138
|
*
|
|
40157
40139
|
* @returns Resolves when the flush is complete.
|
|
40158
40140
|
*/
|
|
40159
|
-
flush() {
|
|
40160
|
-
|
|
40161
|
-
|
|
40162
|
-
|
|
40163
|
-
|
|
40164
|
-
|
|
40165
|
-
yield this.embedAll(this.javaScripts);
|
|
40166
|
-
});
|
|
40141
|
+
async flush() {
|
|
40142
|
+
await this.embedAll(this.fonts);
|
|
40143
|
+
await this.embedAll(this.images);
|
|
40144
|
+
await this.embedAll(this.embeddedPages);
|
|
40145
|
+
await this.embedAll(this.embeddedFiles);
|
|
40146
|
+
await this.embedAll(this.javaScripts);
|
|
40167
40147
|
}
|
|
40168
40148
|
/**
|
|
40169
40149
|
* Serialize this document to an array of bytes making up a PDF file.
|
|
@@ -40181,24 +40161,22 @@ end\
|
|
|
40181
40161
|
* @param options The options to be used when saving the document.
|
|
40182
40162
|
* @returns Resolves with the bytes of the serialized document.
|
|
40183
40163
|
*/
|
|
40184
|
-
save(options = {}) {
|
|
40185
|
-
|
|
40186
|
-
|
|
40187
|
-
|
|
40188
|
-
|
|
40189
|
-
|
|
40190
|
-
|
|
40191
|
-
|
|
40192
|
-
|
|
40193
|
-
|
|
40194
|
-
|
|
40195
|
-
|
|
40196
|
-
|
|
40197
|
-
|
|
40198
|
-
|
|
40199
|
-
|
|
40200
|
-
return Writer.forContext(this.context, objectsPerTick).serializeToBuffer();
|
|
40201
|
-
});
|
|
40164
|
+
async save(options = {}) {
|
|
40165
|
+
const { useObjectStreams = true, addDefaultPage = true, objectsPerTick = 50, updateFieldAppearances = true, } = options;
|
|
40166
|
+
assertIs(useObjectStreams, 'useObjectStreams', ['boolean']);
|
|
40167
|
+
assertIs(addDefaultPage, 'addDefaultPage', ['boolean']);
|
|
40168
|
+
assertIs(objectsPerTick, 'objectsPerTick', ['number']);
|
|
40169
|
+
assertIs(updateFieldAppearances, 'updateFieldAppearances', ['boolean']);
|
|
40170
|
+
if (addDefaultPage && this.getPageCount() === 0)
|
|
40171
|
+
this.addPage();
|
|
40172
|
+
if (updateFieldAppearances) {
|
|
40173
|
+
const form = this.formCache.getValue();
|
|
40174
|
+
if (form)
|
|
40175
|
+
form.updateFieldAppearances();
|
|
40176
|
+
}
|
|
40177
|
+
await this.flush();
|
|
40178
|
+
const Writer = useObjectStreams ? PDFStreamWriter : PDFWriter;
|
|
40179
|
+
return Writer.forContext(this.context, objectsPerTick).serializeToBuffer();
|
|
40202
40180
|
}
|
|
40203
40181
|
/**
|
|
40204
40182
|
* Serialize this document to a base64 encoded string or data URI making up a
|
|
@@ -40215,14 +40193,12 @@ end\
|
|
|
40215
40193
|
* @returns Resolves with a base64 encoded string or data URI of the
|
|
40216
40194
|
* serialized document.
|
|
40217
40195
|
*/
|
|
40218
|
-
saveAsBase64(options = {}) {
|
|
40219
|
-
|
|
40220
|
-
|
|
40221
|
-
|
|
40222
|
-
|
|
40223
|
-
|
|
40224
|
-
return dataUri ? `data:application/pdf;base64,${base64}` : base64;
|
|
40225
|
-
});
|
|
40196
|
+
async saveAsBase64(options = {}) {
|
|
40197
|
+
const { dataUri = false, ...otherOptions } = options;
|
|
40198
|
+
assertIs(dataUri, 'dataUri', ['boolean']);
|
|
40199
|
+
const bytes = await this.save(otherOptions);
|
|
40200
|
+
const base64 = encodeToBase64(bytes);
|
|
40201
|
+
return dataUri ? `data:application/pdf;base64,${base64}` : base64;
|
|
40226
40202
|
}
|
|
40227
40203
|
findPageForAnnotationRef(ref) {
|
|
40228
40204
|
const pages = this.getPages();
|
|
@@ -40235,12 +40211,10 @@ end\
|
|
|
40235
40211
|
}
|
|
40236
40212
|
return undefined;
|
|
40237
40213
|
}
|
|
40238
|
-
embedAll(embeddables) {
|
|
40239
|
-
|
|
40240
|
-
|
|
40241
|
-
|
|
40242
|
-
}
|
|
40243
|
-
});
|
|
40214
|
+
async embedAll(embeddables) {
|
|
40215
|
+
for (let idx = 0, len = embeddables.length; idx < len; idx++) {
|
|
40216
|
+
await embeddables[idx].embed();
|
|
40217
|
+
}
|
|
40244
40218
|
}
|
|
40245
40219
|
updateInfoDict() {
|
|
40246
40220
|
const pdfLib = `pdf-lib (https://github.com/Hopding/pdf-lib)`;
|
|
@@ -41603,772 +41577,70 @@ end\
|
|
|
41603
41577
|
|
|
41604
41578
|
var index = /*@__PURE__*/unwrapExports(dist);
|
|
41605
41579
|
|
|
41606
|
-
|
|
41607
|
-
const FLOAT_APPROXIMATION = 0.000001;
|
|
41608
|
-
/** Calculates the distance between 2 points */
|
|
41609
|
-
const distance = (A, B) => norm(vector(A, B));
|
|
41610
|
-
const distanceCoords = (A, B) => norm(minus(B, A));
|
|
41611
|
-
/** Calculates the distance denoted by a vector */
|
|
41612
|
-
const norm = (vect) => Math.sqrt(vect.x * vect.x + vect.y * vect.y);
|
|
41613
|
-
/** Calculates the orthogonal vector of provided vector */
|
|
41614
|
-
const orthogonal = ({ x, y }) => ({
|
|
41615
|
-
x: -y,
|
|
41616
|
-
y: x,
|
|
41617
|
-
});
|
|
41618
|
-
/** Check if 2 vectors are proportional */
|
|
41619
|
-
const isColinear = ({ x: ux, y: uy }, { x: vx, y: vy }) => isEqual(ux * vy, uy * vx);
|
|
41620
|
-
/** Check if 2 floating values can be considered equals */
|
|
41621
|
-
const isEqual = (a, b) => Math.round(Math.abs(a - b) / FLOAT_APPROXIMATION) === 0;
|
|
41622
|
-
/** Calculate the scalar product between 2 vectors */
|
|
41623
|
-
const scalar = ({ x: ux, y: uy }, { x: vx, y: vy }) => ux * vx + uy * vy;
|
|
41624
|
-
/** Calculate the sum of 2 vectors */
|
|
41625
|
-
const plus = ({ x: ux, y: uy }, { x: vx, y: vy }) => ({ x: ux + vx, y: uy + vy });
|
|
41626
|
-
/** Calculate the vector multiplied by a scalar */
|
|
41627
|
-
const times = ({ x, y }, k = 1) => ({
|
|
41628
|
-
x: k * x,
|
|
41629
|
-
y: k * y,
|
|
41630
|
-
});
|
|
41631
|
-
/** Calculate the difference of 2 vectors */
|
|
41632
|
-
const minus = (u, v) => plus(u, times(v, -1));
|
|
41633
|
-
/** Returns the vector between 2 points. */
|
|
41634
|
-
const vector = (A, B) => minus(B.toCoords(), A.toCoords());
|
|
41635
|
-
/**
|
|
41636
|
-
* Returns the angle between the vector and the horizontal axis (Ox).
|
|
41637
|
-
* The return value is between -PI and PI.
|
|
41638
|
-
* @returns {number} angle in radian between -Pi and Pi
|
|
41639
|
-
*/
|
|
41640
|
-
const orientation = ({ x, y }) => {
|
|
41641
|
-
const alpha = Math.acos(x / Math.sqrt(x * x + y * y));
|
|
41642
|
-
return y > 0 ? alpha : -alpha;
|
|
41643
|
-
};
|
|
41644
|
-
/** Returns the unit vector associated to the provided vector,
|
|
41645
|
-
* or the Null vector (0, 0) if the vector is null
|
|
41646
|
-
*/
|
|
41647
|
-
const unitVector = (u) => {
|
|
41648
|
-
const l = norm(u);
|
|
41649
|
-
return l > 0 ? times(u, 1 / l) : u;
|
|
41650
|
-
};
|
|
41651
|
-
/** Returns the angle from u to v in radian */
|
|
41652
|
-
const angle = (u, v, previousAngle = 0) => {
|
|
41653
|
-
let sweep = orientation(v) - orientation(u);
|
|
41654
|
-
// If the angle has the same sign as the arc orientation, we return the angle as is
|
|
41655
|
-
// Otherwise, we need to correct the value, adding or removing 2π
|
|
41656
|
-
while (Math.abs(previousAngle - sweep) > Math.PI) {
|
|
41657
|
-
sweep += Math.sign(previousAngle - sweep) * 2 * Math.PI;
|
|
41658
|
-
}
|
|
41659
|
-
return sweep;
|
|
41660
|
-
};
|
|
41661
|
-
/** Returns the angle between the lines (BA) and (BC) in radian
|
|
41662
|
-
* @returns {number} the angle in radian, between -Pi and Pi
|
|
41663
|
-
*/
|
|
41664
|
-
const angleABC = (A, B, C, previousAngle = 0) => angle(vector(B, A), vector(B, C), previousAngle);
|
|
41665
|
-
/** Rotate the vector by an angle in radian */
|
|
41666
|
-
const rotate = (vect, teta) => {
|
|
41667
|
-
const { x, y } = vect;
|
|
41668
|
-
const nx = x * Math.cos(teta) - y * Math.sin(teta);
|
|
41669
|
-
const ny = y * Math.cos(teta) + x * Math.sin(teta);
|
|
41670
|
-
return { x: nx, y: ny };
|
|
41671
|
-
};
|
|
41672
|
-
|
|
41673
|
-
class GraphElement {
|
|
41674
|
-
distance(P) {
|
|
41675
|
-
const H = this.orthoProjection(P);
|
|
41676
|
-
return distance(H, P);
|
|
41677
|
-
}
|
|
41678
|
-
}
|
|
41679
|
-
|
|
41680
|
-
class Point extends GraphElement {
|
|
41681
|
-
constructor(coords = { x: 0, y: 0 }) {
|
|
41682
|
-
super();
|
|
41683
|
-
this.x = coords.x;
|
|
41684
|
-
this.y = coords.y;
|
|
41685
|
-
}
|
|
41686
|
-
toCoords() {
|
|
41687
|
-
return { x: this.x, y: this.y };
|
|
41688
|
-
}
|
|
41689
|
-
isEqual(element) {
|
|
41690
|
-
if (!(element instanceof Point))
|
|
41691
|
-
return false;
|
|
41692
|
-
const A = this.toCoords();
|
|
41693
|
-
const B = element.toCoords();
|
|
41694
|
-
return isEqual(A.x, B.x) && isEqual(A.y, B.y);
|
|
41695
|
-
}
|
|
41696
|
-
orthoProjection() {
|
|
41697
|
-
return new Point(this.toCoords());
|
|
41698
|
-
}
|
|
41699
|
-
plus(vect) {
|
|
41700
|
-
const P = new Point(plus(this.toCoords(), vect));
|
|
41701
|
-
return P;
|
|
41702
|
-
}
|
|
41703
|
-
}
|
|
41704
|
-
Point.type = 'PointFixed';
|
|
41705
|
-
|
|
41706
|
-
class Circle extends GraphElement {
|
|
41707
|
-
constructor(O = new Point(), r = 1) {
|
|
41708
|
-
super();
|
|
41709
|
-
this.O = O;
|
|
41710
|
-
this.r = r;
|
|
41711
|
-
}
|
|
41712
|
-
ray() {
|
|
41713
|
-
return this.r;
|
|
41714
|
-
}
|
|
41715
|
-
center() {
|
|
41716
|
-
return this.O;
|
|
41717
|
-
}
|
|
41718
|
-
/** This is used to standardize type Circle | Arc */
|
|
41719
|
-
getCircle() {
|
|
41720
|
-
return this;
|
|
41721
|
-
}
|
|
41722
|
-
isEqual(element) {
|
|
41723
|
-
return (element instanceof Circle &&
|
|
41724
|
-
this.center().isEqual(element.center()) &&
|
|
41725
|
-
isEqual(this.ray(), element.ray()));
|
|
41726
|
-
}
|
|
41727
|
-
includes(P) {
|
|
41728
|
-
return isEqual(distance(this.center(), P), this.ray());
|
|
41729
|
-
}
|
|
41730
|
-
orthoProjection(P) {
|
|
41731
|
-
const center = this.center().toCoords();
|
|
41732
|
-
const coords = P.toCoords();
|
|
41733
|
-
if (distanceCoords(coords, center) < this.ray())
|
|
41734
|
-
return P;
|
|
41735
|
-
const vect = times(unitVector(minus(coords, center)), this.ray());
|
|
41736
|
-
return new Point(plus(center, vect));
|
|
41737
|
-
}
|
|
41738
|
-
}
|
|
41580
|
+
const identityMatrix = [1, 0, 0, 1, 0, 0];
|
|
41739
41581
|
|
|
41740
|
-
|
|
41741
|
-
|
|
41742
|
-
|
|
41743
|
-
|
|
41744
|
-
|
|
41745
|
-
|
|
41746
|
-
|
|
41747
|
-
|
|
41748
|
-
|
|
41749
|
-
|
|
41750
|
-
|
|
41751
|
-
|
|
41752
|
-
|
|
41753
|
-
|
|
41754
|
-
|
|
41755
|
-
|
|
41756
|
-
|
|
41757
|
-
|
|
41758
|
-
|
|
41759
|
-
|
|
41760
|
-
}
|
|
41761
|
-
ray() {
|
|
41762
|
-
return distance(this.center(), this.origin());
|
|
41763
|
-
}
|
|
41764
|
-
isEqual(element) {
|
|
41765
|
-
if (!(element instanceof Arc))
|
|
41766
|
-
return false;
|
|
41767
|
-
const dest = this.destination();
|
|
41768
|
-
const o = this.origin();
|
|
41769
|
-
const eDest = element.destination();
|
|
41770
|
-
const eO = element.origin();
|
|
41771
|
-
return (this.getCircle().isEqual(element.getCircle()) &&
|
|
41772
|
-
((dest.isEqual(eDest) && o.isEqual(eO)) ||
|
|
41773
|
-
(dest.isEqual(eO) && o.isEqual(eDest))));
|
|
41774
|
-
}
|
|
41775
|
-
getCircle() {
|
|
41776
|
-
const circle = new Circle(this.center(), this.ray());
|
|
41777
|
-
return circle;
|
|
41778
|
-
}
|
|
41779
|
-
originVect() {
|
|
41780
|
-
return vector(this.center(), this.origin());
|
|
41781
|
-
}
|
|
41782
|
-
middle() {
|
|
41783
|
-
const halfSweep = this.sweep() / 2;
|
|
41784
|
-
const mid = this.center().plus(rotate(vector(this.center(), this.origin()), halfSweep));
|
|
41785
|
-
return mid;
|
|
41786
|
-
}
|
|
41787
|
-
includes(P) {
|
|
41788
|
-
// As angles are returned between -π and π, we need the middle of the arc
|
|
41789
|
-
return (this.getCircle().includes(P) &&
|
|
41790
|
-
Math.abs(angleABC(this.middle(), this.center(), P)) <=
|
|
41791
|
-
Math.abs(this.sweep() / 2));
|
|
41792
|
-
}
|
|
41793
|
-
orthoProjection(P) {
|
|
41794
|
-
const H = this.getCircle().orthoProjection(P);
|
|
41795
|
-
if (this.includes(H))
|
|
41796
|
-
return H;
|
|
41797
|
-
else {
|
|
41798
|
-
const origin = this.origin().toCoords();
|
|
41799
|
-
const destination = this.destination().toCoords();
|
|
41800
|
-
// Returns the closest between origin and destination
|
|
41801
|
-
const coords = distanceCoords(H.toCoords(), origin) <
|
|
41802
|
-
distanceCoords(H.toCoords(), destination)
|
|
41803
|
-
? origin
|
|
41804
|
-
: destination;
|
|
41805
|
-
return new Point(coords);
|
|
41582
|
+
const combineMatrix = ([a, b, c, d, e, f], [a2, b2, c2, d2, e2, f2]) => [
|
|
41583
|
+
a * a2 + c * b2,
|
|
41584
|
+
b * a2 + d * b2,
|
|
41585
|
+
a * c2 + c * d2,
|
|
41586
|
+
b * c2 + d * d2,
|
|
41587
|
+
a * e2 + c * f2 + e,
|
|
41588
|
+
b * e2 + d * f2 + f,
|
|
41589
|
+
];
|
|
41590
|
+
const applyTransformation = ([a, b, c, d, e, f], { x, y }) => ({
|
|
41591
|
+
x: a * x + c * y + e,
|
|
41592
|
+
y: b * x + d * y + f
|
|
41593
|
+
});
|
|
41594
|
+
const transformationToMatrix = (name, args) => {
|
|
41595
|
+
switch (name) {
|
|
41596
|
+
case 'scale':
|
|
41597
|
+
case 'scaleX':
|
|
41598
|
+
case 'scaleY': {
|
|
41599
|
+
// [sx 0 0 sy 0 0]
|
|
41600
|
+
const [sx, sy = sx] = args;
|
|
41601
|
+
return [name === 'scaleY' ? 1 : sx, 0, 0, name === 'scaleX' ? 1 : sy, 0, 0];
|
|
41806
41602
|
}
|
|
41807
|
-
|
|
41808
|
-
|
|
41809
|
-
|
|
41810
|
-
|
|
41811
|
-
|
|
41812
|
-
|
|
41813
|
-
|
|
41814
|
-
}
|
|
41815
|
-
getPoints() {
|
|
41816
|
-
return [...this.points];
|
|
41817
|
-
}
|
|
41818
|
-
translate(translationVector) {
|
|
41819
|
-
this.points = this.points.map((point) => plus(point, translationVector));
|
|
41820
|
-
}
|
|
41821
|
-
isEqual(element) {
|
|
41822
|
-
if (!(element instanceof Plot))
|
|
41823
|
-
return false;
|
|
41824
|
-
const points = this.getPoints().map((coord) => new Point(coord));
|
|
41825
|
-
const points2 = element.getPoints().map((coord) => new Point(coord));
|
|
41826
|
-
return (points.every((point, i) => point.isEqual(points2[i])) ||
|
|
41827
|
-
points.reverse().every((point, i) => point.isEqual(points2[i])));
|
|
41828
|
-
}
|
|
41829
|
-
orthoProjection(P) {
|
|
41830
|
-
const points = this.getPoints();
|
|
41831
|
-
const orthos = points
|
|
41832
|
-
.slice(0, -1)
|
|
41833
|
-
.map((pt, i) => new Segment(new Point(pt), new Point(points[i + 1])))
|
|
41834
|
-
.map((seg) => seg.orthoProjection(P));
|
|
41835
|
-
let min = Number.POSITIVE_INFINITY;
|
|
41836
|
-
let closest = new Point(points[0]);
|
|
41837
|
-
orthos.forEach((ortho) => {
|
|
41838
|
-
const d = ortho.distance(P);
|
|
41839
|
-
if (d < min) {
|
|
41840
|
-
min = d;
|
|
41841
|
-
closest = ortho;
|
|
41842
|
-
}
|
|
41843
|
-
});
|
|
41844
|
-
return closest;
|
|
41845
|
-
}
|
|
41846
|
-
}
|
|
41847
|
-
|
|
41848
|
-
class Rectangle extends GraphElement {
|
|
41849
|
-
constructor(start = new Point(), end = new Point()) {
|
|
41850
|
-
super();
|
|
41851
|
-
this.start = start;
|
|
41852
|
-
this.end = end;
|
|
41853
|
-
}
|
|
41854
|
-
getSize() {
|
|
41855
|
-
const start = this.start.toCoords();
|
|
41856
|
-
const end = this.end.toCoords();
|
|
41857
|
-
return {
|
|
41858
|
-
width: Math.abs(start.x - end.x),
|
|
41859
|
-
height: Math.abs(start.y - end.y),
|
|
41860
|
-
};
|
|
41861
|
-
}
|
|
41862
|
-
getCoords() {
|
|
41863
|
-
const start = this.start.toCoords();
|
|
41864
|
-
const end = this.end.toCoords();
|
|
41865
|
-
return {
|
|
41866
|
-
x: Math.min(start.x, end.x),
|
|
41867
|
-
y: Math.max(start.y, end.y),
|
|
41868
|
-
};
|
|
41869
|
-
}
|
|
41870
|
-
getStart() {
|
|
41871
|
-
const start = new Point(this.getCoords());
|
|
41872
|
-
return start;
|
|
41873
|
-
}
|
|
41874
|
-
getEnd() {
|
|
41875
|
-
const { width, height } = this.getSize();
|
|
41876
|
-
const end = new Point(this.getStart()).plus({ x: width, y: -height });
|
|
41877
|
-
return end;
|
|
41878
|
-
}
|
|
41879
|
-
center() {
|
|
41880
|
-
const center = new Segment(this.getStart(), this.getEnd()).middle();
|
|
41881
|
-
return center;
|
|
41882
|
-
}
|
|
41883
|
-
isEqual(element) {
|
|
41884
|
-
return (element instanceof Rectangle &&
|
|
41885
|
-
this.getStart().isEqual(element.getStart()) &&
|
|
41886
|
-
this.getEnd().isEqual(element.getEnd()));
|
|
41887
|
-
}
|
|
41888
|
-
orthoProjection(P) {
|
|
41889
|
-
const { x, y } = this.getCoords();
|
|
41890
|
-
const end = this.getEnd().toCoords();
|
|
41891
|
-
const { x: Px, y: Py } = P.toCoords();
|
|
41892
|
-
const Hx = Px < x ? x : Px > end.x ? end.x : Px;
|
|
41893
|
-
const Hy = Py > y ? y : Py < end.y ? end.y : Py;
|
|
41894
|
-
return new Point({ x: Hx, y: Hy });
|
|
41895
|
-
}
|
|
41896
|
-
}
|
|
41897
|
-
Rectangle.type = 'Rectangle';
|
|
41898
|
-
|
|
41899
|
-
function intersections(A, B) {
|
|
41900
|
-
if (A instanceof Point || B instanceof Point)
|
|
41901
|
-
return [];
|
|
41902
|
-
else if (A instanceof Text || B instanceof Text)
|
|
41903
|
-
return [];
|
|
41904
|
-
else if (A instanceof Image || B instanceof Image)
|
|
41905
|
-
return [];
|
|
41906
|
-
// TODO: calculate the coords of the intersection: https://www.emathzone.com/tutorials/geometry/intersection-of-line-and-ellipse.html
|
|
41907
|
-
else if (A instanceof Line)
|
|
41908
|
-
return intersectionsLine(A, B);
|
|
41909
|
-
else if (A instanceof Segment) {
|
|
41910
|
-
return intersectionsLine(A.getLine(), B).filter((P) => A.includes(new Point(P)));
|
|
41911
|
-
}
|
|
41912
|
-
else if (A instanceof Circle)
|
|
41913
|
-
return intersectionsCircle(A, B);
|
|
41914
|
-
else if (A instanceof Arc) {
|
|
41915
|
-
return intersectionsCircle(A.getCircle(), B).filter((P) => A.includes(new Point(P)));
|
|
41916
|
-
}
|
|
41917
|
-
else if (A instanceof Plot)
|
|
41918
|
-
return intersectionsPlot(A, B);
|
|
41919
|
-
else if (A instanceof Rectangle)
|
|
41920
|
-
return intersectionsRectangle(A, B);
|
|
41921
|
-
else if (A instanceof Ellipse)
|
|
41922
|
-
return intersectionsEllipse(A, B);
|
|
41923
|
-
return A;
|
|
41924
|
-
}
|
|
41925
|
-
function intersectionsLine(A, B) {
|
|
41926
|
-
if (B instanceof Line)
|
|
41927
|
-
return intersectionLine(A, B);
|
|
41928
|
-
else if (B instanceof Segment) {
|
|
41929
|
-
return intersectionLine(A, B.getLine()).filter((P) => B.includes(new Point(P)));
|
|
41930
|
-
}
|
|
41931
|
-
else if (B instanceof Circle)
|
|
41932
|
-
return intersectionCircleLine(B, A);
|
|
41933
|
-
else if (B instanceof Arc) {
|
|
41934
|
-
return intersectionsCircle(B.getCircle(), A).filter((P) => B.includes(new Point(P)));
|
|
41935
|
-
}
|
|
41936
|
-
else if (B instanceof Plot)
|
|
41937
|
-
return intersectionsPlot(B, A);
|
|
41938
|
-
else if (B instanceof Rectangle)
|
|
41939
|
-
return intersectionsRectangle(B, A);
|
|
41940
|
-
else if (B instanceof Ellipse)
|
|
41941
|
-
return intersectionsEllipse(B, A);
|
|
41942
|
-
return B;
|
|
41943
|
-
}
|
|
41944
|
-
function intersectionsEllipse(A, B) {
|
|
41945
|
-
if (B instanceof Line)
|
|
41946
|
-
return intersectionsLineAndEllipse(A, B);
|
|
41947
|
-
else if (B instanceof Segment) {
|
|
41948
|
-
return intersectionsEllipse(A, B.getLine()).filter((P) => B.includes(new Point(P)));
|
|
41949
|
-
}
|
|
41950
|
-
// TODO:
|
|
41951
|
-
// else if (B instanceof Circle) return intersectionEllipseCircle(B, A)
|
|
41952
|
-
else if (B instanceof Circle)
|
|
41953
|
-
return [];
|
|
41954
|
-
// TODO:
|
|
41955
|
-
// else if (B instanceof Ellipse) return intersectionEllipseEllipse(B, A)
|
|
41956
|
-
else if (B instanceof Ellipse)
|
|
41957
|
-
return [];
|
|
41958
|
-
else if (B instanceof Arc) {
|
|
41959
|
-
return intersectionsEllipse(A, B.getCircle()).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
|
-
return B;
|
|
41966
|
-
}
|
|
41967
|
-
function intersectionsLineAndEllipse(A, B) {
|
|
41968
|
-
const center = A.center().toCoords();
|
|
41969
|
-
const a = A.a();
|
|
41970
|
-
const b = A.b();
|
|
41971
|
-
const rotation = A.rotation();
|
|
41972
|
-
const isLineParallel2YAxis = isEqual(B.dirVect().x, 0);
|
|
41973
|
-
// this is a dummy value to represent a point on the line
|
|
41974
|
-
const p1Y = isLineParallel2YAxis ? 1 : B.y(1);
|
|
41975
|
-
const p1X = isLineParallel2YAxis ? B.origin().toCoords().x : 1;
|
|
41976
|
-
const p1 = { x: p1X, y: p1Y };
|
|
41977
|
-
// this is a dummy value to represent a point on the line
|
|
41978
|
-
const p2Y = isLineParallel2YAxis ? 2 : B.y(2);
|
|
41979
|
-
const p2X = isLineParallel2YAxis ? B.origin().toCoords().x : 2;
|
|
41980
|
-
const p2 = { x: p2X, y: p2Y };
|
|
41981
|
-
const p1Normalized = rotate({ x: p1.x - center.x, y: p1.y - center.y }, -rotation);
|
|
41982
|
-
const p2Normalized = rotate({ x: p2.x - center.x, y: p2.y - center.y }, -rotation);
|
|
41983
|
-
const angular = (p1Normalized.y - p2Normalized.y) / (p1Normalized.x - p2Normalized.x);
|
|
41984
|
-
const linear = p1Normalized.y - angular * p1Normalized.x;
|
|
41985
|
-
const lineY = (x) => angular * x + linear;
|
|
41986
|
-
const denormalize = (coord) => {
|
|
41987
|
-
const rotated = rotate(coord, rotation);
|
|
41988
|
-
return {
|
|
41989
|
-
x: rotated.x + center.x,
|
|
41990
|
-
y: rotated.y + center.y,
|
|
41991
|
-
};
|
|
41992
|
-
};
|
|
41993
|
-
// Intersection with vertical line
|
|
41994
|
-
if (isEqual(p1Normalized.x - p2Normalized.x, 0)) {
|
|
41995
|
-
const x = p1Normalized.x;
|
|
41996
|
-
const delta = b ** 2 - (x ** 2 * b ** 2) / a ** 2;
|
|
41997
|
-
if (delta < 0)
|
|
41998
|
-
return [];
|
|
41999
|
-
else if (delta === 0) {
|
|
42000
|
-
return [{ x, y: 0 }].map(denormalize);
|
|
41603
|
+
case 'translate':
|
|
41604
|
+
case 'translateX':
|
|
41605
|
+
case 'translateY': {
|
|
41606
|
+
// [1 0 0 1 tx ty]
|
|
41607
|
+
const [tx, ty = tx] = args;
|
|
41608
|
+
// -ty is necessary because the pdf's y axis is inverted
|
|
41609
|
+
return [1, 0, 0, 1, name === 'translateY' ? 0 : tx, name === 'translateX' ? 0 : -ty];
|
|
42001
41610
|
}
|
|
42002
|
-
|
|
42003
|
-
|
|
42004
|
-
const
|
|
42005
|
-
|
|
42006
|
-
|
|
42007
|
-
|
|
42008
|
-
|
|
42009
|
-
|
|
42010
|
-
|
|
42011
|
-
|
|
42012
|
-
|
|
42013
|
-
|
|
42014
|
-
|
|
42015
|
-
|
|
42016
|
-
|
|
42017
|
-
|
|
42018
|
-
|
|
42019
|
-
|
|
42020
|
-
|
|
42021
|
-
|
|
42022
|
-
|
|
42023
|
-
return [{ x, y }].map(denormalize);
|
|
42024
|
-
}
|
|
42025
|
-
else {
|
|
42026
|
-
const x1 = (-beta + Math.sqrt(delta)) / (2 * alpha);
|
|
42027
|
-
const y1 = lineY(x1);
|
|
42028
|
-
const x2 = (-beta - Math.sqrt(delta)) / (2 * alpha);
|
|
42029
|
-
const y2 = lineY(x2);
|
|
42030
|
-
return [
|
|
42031
|
-
{ x: x1, y: y1 },
|
|
42032
|
-
{ x: x2, y: y2 },
|
|
42033
|
-
].map(denormalize);
|
|
42034
|
-
}
|
|
42035
|
-
}
|
|
42036
|
-
function intersectionLine(A, B) {
|
|
42037
|
-
if (isColinear(A.dirVect(), B.dirVect()))
|
|
42038
|
-
return [];
|
|
42039
|
-
else {
|
|
42040
|
-
const { x: ux, y: uy } = A.dirVect();
|
|
42041
|
-
const { x: vx, y: vy } = B.dirVect();
|
|
42042
|
-
const { x: xA, y: yA } = A.origin().toCoords();
|
|
42043
|
-
const { x: xB, y: yB } = B.origin().toCoords();
|
|
42044
|
-
const x = (ux * (vx * (yA - yB) + vy * xB) - uy * vx * xA) / (ux * vy - uy * vx);
|
|
42045
|
-
const y = (uy * (vy * (xA - xB) + vx * yB) - ux * vy * yA) / (uy * vx - ux * vy);
|
|
42046
|
-
return [{ x, y }];
|
|
42047
|
-
}
|
|
42048
|
-
}
|
|
42049
|
-
function intersectionsPlot(A, B) {
|
|
42050
|
-
const points = A.getPoints().map((pt) => new Point(pt));
|
|
42051
|
-
const head = points.pop();
|
|
42052
|
-
const segments = points.map((pt, i) => new Segment(pt, points[i + 1] || head));
|
|
42053
|
-
// @ts-ignore
|
|
42054
|
-
const inters = segments.map((s) => intersections(s, B)).flat();
|
|
42055
|
-
return inters;
|
|
42056
|
-
}
|
|
42057
|
-
function intersectionsRectangle(A, B) {
|
|
42058
|
-
const P1 = A.getCoords();
|
|
42059
|
-
const P3 = A.getEnd();
|
|
42060
|
-
const P2 = { x: P1.x, y: P3.y };
|
|
42061
|
-
const P4 = { x: P3.x, y: P1.y };
|
|
42062
|
-
return intersections(new Plot([P1, P2, P3, P4, P1]), B);
|
|
42063
|
-
}
|
|
42064
|
-
function intersectionCircleLine(A, B) {
|
|
42065
|
-
const rA = A.ray();
|
|
42066
|
-
const O = A.center();
|
|
42067
|
-
const H = B.orthoProjection(O);
|
|
42068
|
-
const OH = distance(O, H);
|
|
42069
|
-
// The line is tangeant
|
|
42070
|
-
if (isEqual(OH, rA))
|
|
42071
|
-
return [H];
|
|
42072
|
-
// The line is too far from the circle
|
|
42073
|
-
else if (OH > A.ray())
|
|
42074
|
-
return [];
|
|
42075
|
-
// The line cut the circle in 2 points
|
|
42076
|
-
else {
|
|
42077
|
-
// Pythagore
|
|
42078
|
-
const HP = Math.sqrt(rA * rA - OH * OH);
|
|
42079
|
-
const vect = unitVector(B.dirVect());
|
|
42080
|
-
return [H.plus(times(vect, HP)), H.plus(times(vect, -HP))];
|
|
42081
|
-
}
|
|
42082
|
-
}
|
|
42083
|
-
function intersectionCircle(A, B) {
|
|
42084
|
-
const oA = A.center();
|
|
42085
|
-
const oB = B.center();
|
|
42086
|
-
const rA = A.ray();
|
|
42087
|
-
const rB = B.ray();
|
|
42088
|
-
const axis = vector(oA, oB);
|
|
42089
|
-
const CC = norm(axis);
|
|
42090
|
-
// The circles are tangeant
|
|
42091
|
-
if (isEqual(CC, rA + rB))
|
|
42092
|
-
return [A.orthoProjection(oB).toCoords()];
|
|
42093
|
-
// The circles are too far from eachother
|
|
42094
|
-
else if (CC > rA + rB)
|
|
42095
|
-
return [];
|
|
42096
|
-
// The intersections belong to an orthogonal axis
|
|
42097
|
-
else {
|
|
42098
|
-
const ratio = 1 / 2 + (rA * rA - rB * rB) / (CC * CC) / 2;
|
|
42099
|
-
const H = oA.plus(times(axis, ratio));
|
|
42100
|
-
return intersectionCircleLine(A, new Line(H, H.plus(orthogonal(axis))));
|
|
42101
|
-
}
|
|
42102
|
-
}
|
|
42103
|
-
function intersectionsCircle(A, B) {
|
|
42104
|
-
if (B instanceof Circle)
|
|
42105
|
-
return intersectionCircle(A, B);
|
|
42106
|
-
else if (B instanceof Line)
|
|
42107
|
-
return intersectionCircleLine(A, B);
|
|
42108
|
-
else if (B instanceof Segment) {
|
|
42109
|
-
return intersectionCircleLine(A, B.getLine()).filter((P) => B.includes(new Point(P)));
|
|
42110
|
-
}
|
|
42111
|
-
else if (B instanceof Arc) {
|
|
42112
|
-
return intersectionCircle(A, B.getCircle()).filter((P) => B.includes(new Point(P)));
|
|
42113
|
-
}
|
|
42114
|
-
else if (B instanceof Plot)
|
|
42115
|
-
return intersectionsPlot(B, A);
|
|
42116
|
-
else if (B instanceof Rectangle)
|
|
42117
|
-
return intersectionsRectangle(B, A);
|
|
42118
|
-
else if (B instanceof Ellipse)
|
|
42119
|
-
return intersectionsEllipse(B, A);
|
|
42120
|
-
return B;
|
|
42121
|
-
}
|
|
42122
|
-
function getIntersections(elements) {
|
|
42123
|
-
const checked = [];
|
|
42124
|
-
const inters = [];
|
|
42125
|
-
elements.forEach((elt) => {
|
|
42126
|
-
checked.forEach((e) => inters.push(...intersections(e, elt)));
|
|
42127
|
-
checked.push(elt);
|
|
42128
|
-
});
|
|
42129
|
-
return inters;
|
|
42130
|
-
}
|
|
42131
|
-
|
|
42132
|
-
class Line extends GraphElement {
|
|
42133
|
-
constructor(A = new Point(), B = new Point()) {
|
|
42134
|
-
super();
|
|
42135
|
-
this.A = A;
|
|
42136
|
-
this.B = B;
|
|
42137
|
-
}
|
|
42138
|
-
origin() {
|
|
42139
|
-
return this.A;
|
|
42140
|
-
}
|
|
42141
|
-
dirVect() {
|
|
42142
|
-
return vector(this.A, this.B);
|
|
42143
|
-
}
|
|
42144
|
-
/** Line equation */
|
|
42145
|
-
y(x) {
|
|
42146
|
-
const a = this.a();
|
|
42147
|
-
const b = this.b();
|
|
42148
|
-
return a * x + b;
|
|
42149
|
-
}
|
|
42150
|
-
/** The slope */
|
|
42151
|
-
a() {
|
|
42152
|
-
const dirVect = this.dirVect();
|
|
42153
|
-
return dirVect.y / dirVect.x;
|
|
42154
|
-
}
|
|
42155
|
-
/** Origin y coordinate */
|
|
42156
|
-
b() {
|
|
42157
|
-
const O = this.origin().toCoords();
|
|
42158
|
-
const a = this.a();
|
|
42159
|
-
return O.y - a * O.x;
|
|
42160
|
-
}
|
|
42161
|
-
isEqual(element) {
|
|
42162
|
-
const vect = this.dirVect();
|
|
42163
|
-
return (element instanceof Line &&
|
|
42164
|
-
isColinear(vect, element.dirVect()) &&
|
|
42165
|
-
(isEqual(vect.x, 0)
|
|
42166
|
-
? // We need to take care of the case of the vertical line
|
|
42167
|
-
isEqual(this.origin().toCoords().x, element.origin().toCoords().x)
|
|
42168
|
-
: isEqual(this.b(), element.b())));
|
|
42169
|
-
}
|
|
42170
|
-
/** Reversed line equation */
|
|
42171
|
-
x(y) {
|
|
42172
|
-
const dirVect = this.dirVect();
|
|
42173
|
-
return ((y - this.b()) * dirVect.x) / dirVect.y;
|
|
42174
|
-
}
|
|
42175
|
-
includes(P) {
|
|
42176
|
-
const { x, y } = P.toCoords();
|
|
42177
|
-
const vect = this.dirVect();
|
|
42178
|
-
return isEqual(vect.x, 0)
|
|
42179
|
-
? isEqual(this.origin().toCoords().x, x)
|
|
42180
|
-
: isEqual(this.y(x), y);
|
|
42181
|
-
}
|
|
42182
|
-
/** This is used to standarsize type Segment | HalfLine | Line */
|
|
42183
|
-
getLine() {
|
|
42184
|
-
const line = new Line(this.origin(), this.B);
|
|
42185
|
-
return line;
|
|
42186
|
-
}
|
|
42187
|
-
orthoProjection(P) {
|
|
42188
|
-
const vectOrtho = orthogonal(this.dirVect());
|
|
42189
|
-
const A = new Point(P.toCoords());
|
|
42190
|
-
const ortho = new Line(A, A.plus(vectOrtho));
|
|
42191
|
-
const H = intersectionLine(this, ortho)[0];
|
|
42192
|
-
return new Point(H);
|
|
42193
|
-
}
|
|
42194
|
-
}
|
|
42195
|
-
|
|
42196
|
-
class Segment extends GraphElement {
|
|
42197
|
-
constructor(A = new Point(), B = new Point()) {
|
|
42198
|
-
super();
|
|
42199
|
-
this.A = A;
|
|
42200
|
-
this.B = B;
|
|
42201
|
-
}
|
|
42202
|
-
origin() {
|
|
42203
|
-
return this.A;
|
|
42204
|
-
}
|
|
42205
|
-
destination() {
|
|
42206
|
-
return this.B;
|
|
42207
|
-
}
|
|
42208
|
-
dirVect() {
|
|
42209
|
-
return vector(this.origin(), this.destination());
|
|
42210
|
-
}
|
|
42211
|
-
length() {
|
|
42212
|
-
return distance(this.destination(), this.origin());
|
|
42213
|
-
}
|
|
42214
|
-
isEqual(element) {
|
|
42215
|
-
if (!(element instanceof Segment))
|
|
42216
|
-
return false;
|
|
42217
|
-
const o = this.origin();
|
|
42218
|
-
const dest = this.destination();
|
|
42219
|
-
const oE = element.origin();
|
|
42220
|
-
const destE = element.destination();
|
|
42221
|
-
return (element instanceof Segment &&
|
|
42222
|
-
((o.isEqual(oE) && dest.isEqual(destE)) ||
|
|
42223
|
-
(o.isEqual(destE) && dest.isEqual(oE))));
|
|
42224
|
-
}
|
|
42225
|
-
/** Returns an equivalent line object */
|
|
42226
|
-
getLine() {
|
|
42227
|
-
const line = new Line(this.origin(), this.destination());
|
|
42228
|
-
return line;
|
|
42229
|
-
}
|
|
42230
|
-
includes(P) {
|
|
42231
|
-
const vect = this.dirVect();
|
|
42232
|
-
const otherVect = vector(this.origin(), P);
|
|
42233
|
-
// The vectors are not even colinear
|
|
42234
|
-
if (!isColinear(vect, otherVect))
|
|
42235
|
-
return false;
|
|
42236
|
-
// The point is behind the origin
|
|
42237
|
-
else if (scalar(vect, otherVect) < 0)
|
|
42238
|
-
return false;
|
|
42239
|
-
// The point is after the destination
|
|
42240
|
-
else if (norm(vect) < norm(otherVect))
|
|
42241
|
-
return false;
|
|
42242
|
-
else
|
|
42243
|
-
return true;
|
|
42244
|
-
}
|
|
42245
|
-
middle() {
|
|
42246
|
-
const mid = new Point(plus(this.origin().toCoords(), times(this.dirVect(), 0.5)));
|
|
42247
|
-
return mid;
|
|
42248
|
-
}
|
|
42249
|
-
orthoProjection(P) {
|
|
42250
|
-
const H = this.getLine().orthoProjection(P);
|
|
42251
|
-
const vect = this.dirVect();
|
|
42252
|
-
const origin = this.origin().toCoords();
|
|
42253
|
-
const destination = this.destination().toCoords();
|
|
42254
|
-
const otherVect = vector(this.origin(), H);
|
|
42255
|
-
// The point is before the origin
|
|
42256
|
-
if (scalar(vect, otherVect) < 0)
|
|
42257
|
-
return new Point(origin);
|
|
42258
|
-
// The point is after the destination
|
|
42259
|
-
else if (norm(vect) < norm(otherVect))
|
|
42260
|
-
return new Point(destination);
|
|
42261
|
-
// The point is within the segment
|
|
42262
|
-
else
|
|
42263
|
-
return H;
|
|
42264
|
-
}
|
|
42265
|
-
}
|
|
42266
|
-
Segment.type = 'Segment';
|
|
42267
|
-
|
|
42268
|
-
class Ellipse extends GraphElement {
|
|
42269
|
-
constructor(A = new Point(), B = new Point(), C = new Point()) {
|
|
42270
|
-
super();
|
|
42271
|
-
this.A = A;
|
|
42272
|
-
this.B = B;
|
|
42273
|
-
this.C = C;
|
|
42274
|
-
}
|
|
42275
|
-
center() {
|
|
42276
|
-
const center = this.axis().middle();
|
|
42277
|
-
return center;
|
|
42278
|
-
}
|
|
42279
|
-
axis() {
|
|
42280
|
-
const axis = new Segment(this.A, this.B);
|
|
42281
|
-
return axis;
|
|
42282
|
-
}
|
|
42283
|
-
a() {
|
|
42284
|
-
const axis = this.axis();
|
|
42285
|
-
return Math.max(axis.length() / 2, axis.distance(this.C));
|
|
42286
|
-
}
|
|
42287
|
-
b() {
|
|
42288
|
-
const axis = this.axis();
|
|
42289
|
-
return Math.min(axis.length() / 2, axis.distance(this.C));
|
|
42290
|
-
}
|
|
42291
|
-
rotation() {
|
|
42292
|
-
const axis = this.axis();
|
|
42293
|
-
return axis.length() / 2 > axis.distance(this.C)
|
|
42294
|
-
? orientation(axis.dirVect())
|
|
42295
|
-
: orientation(orthogonal(axis.dirVect()));
|
|
42296
|
-
}
|
|
42297
|
-
getSize() {
|
|
42298
|
-
return { width: 2 * this.a(), height: 2 * this.b() };
|
|
42299
|
-
}
|
|
42300
|
-
isEqual(element) {
|
|
42301
|
-
if (!(element instanceof Ellipse))
|
|
42302
|
-
return false;
|
|
42303
|
-
const a = this.a();
|
|
42304
|
-
const b = this.b();
|
|
42305
|
-
const rotation = this.rotation();
|
|
42306
|
-
const eltA = element.a();
|
|
42307
|
-
const eltB = element.b();
|
|
42308
|
-
const eltRotation = element.rotation();
|
|
42309
|
-
// If the main axis is the same on both ellipse
|
|
42310
|
-
if (eltA < eltB === a < b) {
|
|
42311
|
-
// The rotation is equivalent module PI as the element is symetrical
|
|
42312
|
-
return (isEqual(eltA, a) &&
|
|
42313
|
-
isEqual(eltB, b) &&
|
|
42314
|
-
isEqual(rotation + (Math.PI % Math.PI), eltRotation + (Math.PI % Math.PI)));
|
|
42315
|
-
}
|
|
42316
|
-
// If the small axis is different
|
|
42317
|
-
else {
|
|
42318
|
-
// We add a rotation of PI / 2 to emulate the fact that the main axis are actually orthogonal
|
|
42319
|
-
return (isEqual(eltA, b) &&
|
|
42320
|
-
isEqual(eltB, a) &&
|
|
42321
|
-
isEqual(rotation + (Math.PI % Math.PI), eltRotation + (((3 * Math.PI) / 2) % Math.PI)));
|
|
42322
|
-
}
|
|
42323
|
-
}
|
|
42324
|
-
includes(P) {
|
|
42325
|
-
const { x, y } = P.toCoords();
|
|
42326
|
-
const { x: cx, y: cy } = this.center().toCoords();
|
|
42327
|
-
const teta = this.rotation();
|
|
42328
|
-
return isEqual(Math.pow(((x - cx) * Math.cos(teta) + (y - cy) * Math.sin(teta)) / this.a(), 2) +
|
|
42329
|
-
Math.pow(((x - cx) * Math.sin(teta) - (y - cy) * Math.cos(teta)) / this.b(), 2), 1);
|
|
42330
|
-
}
|
|
42331
|
-
orthoProjection(P) {
|
|
42332
|
-
// We will consider that the parametric projection is a correct approximation of the distance for the current case, even if it is not orthogonal
|
|
42333
|
-
const C = this.center();
|
|
42334
|
-
const axis = this.axis();
|
|
42335
|
-
const CP = vector(C, P);
|
|
42336
|
-
const teta = angle(axis.dirVect(), vector(C, P));
|
|
42337
|
-
const ray = this.polarRay(teta);
|
|
42338
|
-
if (distance(P, this.center()) < ray)
|
|
42339
|
-
return P;
|
|
42340
|
-
const vect = times(unitVector(CP), ray);
|
|
42341
|
-
return new Point(this.center().plus(vect).toCoords());
|
|
42342
|
-
}
|
|
42343
|
-
polarRay(teta) {
|
|
42344
|
-
const a = this.a();
|
|
42345
|
-
const b = this.b();
|
|
42346
|
-
const excentricity = Math.sqrt(Math.abs(a * a - b * b)) / Math.max(a, b);
|
|
42347
|
-
return (Math.min(a, b) / Math.sqrt(1 - Math.pow(excentricity * Math.cos(teta), 2)));
|
|
42348
|
-
}
|
|
42349
|
-
}
|
|
42350
|
-
|
|
42351
|
-
/**
|
|
42352
|
-
* take an array of T and turn it into an 2D-array where each sub array has n elements
|
|
42353
|
-
* ex: [1,2,3,4] -> [[1,2], [3, 4]]
|
|
42354
|
-
* @param arr the array of elements
|
|
42355
|
-
* @param n the size of each sub array
|
|
42356
|
-
*/
|
|
42357
|
-
const groupBy = (arr, n) => {
|
|
42358
|
-
if (arr.length <= n)
|
|
42359
|
-
return [arr];
|
|
42360
|
-
return arr === null || arr === void 0 ? void 0 : arr.reduce((acc, curr, i) => {
|
|
42361
|
-
const index = Math.floor(i / n);
|
|
42362
|
-
if (i % n) {
|
|
42363
|
-
acc[index].push(curr);
|
|
41611
|
+
case 'rotate': {
|
|
41612
|
+
// [cos(a) sin(a) -sin(a) cos(a) 0 0]
|
|
41613
|
+
const [a, x = 0, y = 0] = args;
|
|
41614
|
+
const t1 = transformationToMatrix('translate', [x, y]);
|
|
41615
|
+
const t2 = transformationToMatrix('translate', [-x, -y]);
|
|
41616
|
+
// -args[0] -> the '-' operator is necessary because the pdf rotation system is inverted
|
|
41617
|
+
const aRadians = degreesToRadians(-a);
|
|
41618
|
+
const r = [Math.cos(aRadians), Math.sin(aRadians), -Math.sin(aRadians), Math.cos(aRadians), 0, 0];
|
|
41619
|
+
// rotation around a point is the combination of: translate * rotate * (-translate)
|
|
41620
|
+
return combineMatrix(combineMatrix(t1, r), t2);
|
|
41621
|
+
}
|
|
41622
|
+
case 'skewY':
|
|
41623
|
+
case 'skewX': {
|
|
41624
|
+
// [1 tan(a) 0 1 0 0]
|
|
41625
|
+
// [1 0 tan(a) 1 0 0]
|
|
41626
|
+
// -args[0] -> the '-' operator is necessary because the pdf rotation system is inverted
|
|
41627
|
+
const a = degreesToRadians(-args[0]);
|
|
41628
|
+
const skew = Math.tan(a);
|
|
41629
|
+
const skewX = name === 'skewX' ? skew : 0;
|
|
41630
|
+
const skewY = name === 'skewY' ? skew : 0;
|
|
41631
|
+
return [1, skewY, skewX, 1, 0, 0];
|
|
42364
41632
|
}
|
|
42365
|
-
|
|
42366
|
-
|
|
41633
|
+
case 'matrix': {
|
|
41634
|
+
const [a, b, c, d, e, f] = args;
|
|
41635
|
+
const r = transformationToMatrix('scale', [1, -1]);
|
|
41636
|
+
const m = [a, b, c, d, e, f];
|
|
41637
|
+
return combineMatrix(combineMatrix(r, m), r);
|
|
42367
41638
|
}
|
|
42368
|
-
|
|
42369
|
-
|
|
41639
|
+
default:
|
|
41640
|
+
return identityMatrix;
|
|
41641
|
+
}
|
|
42370
41642
|
};
|
|
42371
|
-
const
|
|
41643
|
+
const combineTransformation = (matrix, name, args) => combineMatrix(matrix, transformationToMatrix(name, args));
|
|
42372
41644
|
const StrokeLineCapMap = {
|
|
42373
41645
|
butt: exports.LineCapStyle.Butt,
|
|
42374
41646
|
round: exports.LineCapStyle.Round,
|
|
@@ -42383,662 +41655,144 @@ end\
|
|
|
42383
41655
|
miter: exports.LineJoinStyle.Miter,
|
|
42384
41656
|
round: exports.LineJoinStyle.Round,
|
|
42385
41657
|
};
|
|
42386
|
-
const getInnerSegment = (start, end, rect) => {
|
|
42387
|
-
const isStartInside = isCoordinateInsideTheRect(start, rect);
|
|
42388
|
-
const isEndInside = isCoordinateInsideTheRect(end, rect);
|
|
42389
|
-
let resultLineStart = start;
|
|
42390
|
-
let resultLineEnd = end;
|
|
42391
|
-
// it means that the segment is already inside the rect
|
|
42392
|
-
if (isEndInside && isStartInside)
|
|
42393
|
-
return new Segment(start, end);
|
|
42394
|
-
const line = new Segment(start, end);
|
|
42395
|
-
const intersection = getIntersections([rect, line]);
|
|
42396
|
-
// if there's no intersection it means that the line doesn't intersects the svgRect and isn't visible
|
|
42397
|
-
if (intersection.length === 0)
|
|
42398
|
-
return;
|
|
42399
|
-
if (!isStartInside) {
|
|
42400
|
-
// replace the line start point by the nearest intersection
|
|
42401
|
-
const nearestPoint = intersection.sort((p1, p2) => distanceCoords(start, p1) - distanceCoords(start, p2))[0];
|
|
42402
|
-
resultLineStart = new Point(nearestPoint);
|
|
42403
|
-
}
|
|
42404
|
-
if (!isEndInside) {
|
|
42405
|
-
// replace the line start point by the nearest intersection
|
|
42406
|
-
const nearestPoint = intersection.sort((p1, p2) => distanceCoords(end, p1) - distanceCoords(end, p2))[0];
|
|
42407
|
-
resultLineEnd = new Point(nearestPoint);
|
|
42408
|
-
}
|
|
42409
|
-
return new Segment(resultLineStart, resultLineEnd);
|
|
42410
|
-
};
|
|
42411
|
-
const cropSvgElement = (svgRect, element) => {
|
|
42412
|
-
var _a, _b;
|
|
42413
|
-
switch (element.tagName) {
|
|
42414
|
-
case 'text': {
|
|
42415
|
-
const fontSize = element.svgAttributes.fontSize || 12;
|
|
42416
|
-
// TODO: compute the right font boundaries to know which characters should be drawn
|
|
42417
|
-
// this is an workaround to draw text that are just a little outside the viewbox boundaries
|
|
42418
|
-
const start = new Point({
|
|
42419
|
-
x: element.svgAttributes.x || 0,
|
|
42420
|
-
y: element.svgAttributes.y || 0,
|
|
42421
|
-
});
|
|
42422
|
-
const paddingRect = new Rectangle(new Point({
|
|
42423
|
-
x: svgRect.start.x - fontSize,
|
|
42424
|
-
y: svgRect.start.y + fontSize,
|
|
42425
|
-
}), new Point({ x: svgRect.end.x + fontSize, y: svgRect.end.y - fontSize }));
|
|
42426
|
-
if (!isCoordinateInsideTheRect(start, paddingRect)) {
|
|
42427
|
-
element.set_content('');
|
|
42428
|
-
}
|
|
42429
|
-
break;
|
|
42430
|
-
}
|
|
42431
|
-
case 'line': {
|
|
42432
|
-
const start = new Point({
|
|
42433
|
-
x: element.svgAttributes.x1,
|
|
42434
|
-
y: element.svgAttributes.y1,
|
|
42435
|
-
});
|
|
42436
|
-
const end = new Point({
|
|
42437
|
-
x: element.svgAttributes.x2,
|
|
42438
|
-
y: element.svgAttributes.y2,
|
|
42439
|
-
});
|
|
42440
|
-
const line = getInnerSegment(start, end, svgRect);
|
|
42441
|
-
element.svgAttributes.x1 = line ? line.A.x : 0;
|
|
42442
|
-
element.svgAttributes.x2 = line ? line.B.x : 0;
|
|
42443
|
-
element.svgAttributes.y1 = line ? line.A.y : 0;
|
|
42444
|
-
element.svgAttributes.y2 = line ? line.B.y : 0;
|
|
42445
|
-
break;
|
|
42446
|
-
}
|
|
42447
|
-
case 'path': {
|
|
42448
|
-
// the path origin coordinate
|
|
42449
|
-
const basePoint = new Point({
|
|
42450
|
-
x: element.svgAttributes.x || 0,
|
|
42451
|
-
y: element.svgAttributes.y || 0,
|
|
42452
|
-
});
|
|
42453
|
-
const normalizePoint = (p) => new Point({ x: p.x - basePoint.x, y: p.y - basePoint.y });
|
|
42454
|
-
/**
|
|
42455
|
-
*
|
|
42456
|
-
* @param origin is the origin of the current drawing in the page coordinate system
|
|
42457
|
-
* @param command the path instruction
|
|
42458
|
-
* @param params the instruction params
|
|
42459
|
-
* @returns the point where the next instruction starts and the new instruction text
|
|
42460
|
-
*/
|
|
42461
|
-
const handlePath = (origin, command, params) => {
|
|
42462
|
-
switch (command) {
|
|
42463
|
-
case 'm':
|
|
42464
|
-
case 'M': {
|
|
42465
|
-
const isLocalInstruction = command === command.toLocaleLowerCase();
|
|
42466
|
-
const nextPoint = new Point({
|
|
42467
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + params[0],
|
|
42468
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + params[1],
|
|
42469
|
-
});
|
|
42470
|
-
return {
|
|
42471
|
-
point: nextPoint,
|
|
42472
|
-
command: `${command}${params[0]},${params[1]}`,
|
|
42473
|
-
};
|
|
42474
|
-
}
|
|
42475
|
-
case 'v':
|
|
42476
|
-
case 'V':
|
|
42477
|
-
case 'h':
|
|
42478
|
-
case 'H':
|
|
42479
|
-
case 'l':
|
|
42480
|
-
case 'L': {
|
|
42481
|
-
const isLocalInstruction = ['l', 'v', 'h'].includes(command);
|
|
42482
|
-
const getNextPoint = () => {
|
|
42483
|
-
switch (command.toLocaleLowerCase()) {
|
|
42484
|
-
case 'l':
|
|
42485
|
-
return new Point({
|
|
42486
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + params[0],
|
|
42487
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + params[1],
|
|
42488
|
-
});
|
|
42489
|
-
case 'v':
|
|
42490
|
-
return new Point({
|
|
42491
|
-
x: origin.x,
|
|
42492
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + params[0],
|
|
42493
|
-
});
|
|
42494
|
-
case 'h':
|
|
42495
|
-
return new Point({
|
|
42496
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + params[0],
|
|
42497
|
-
y: origin.y,
|
|
42498
|
-
});
|
|
42499
|
-
default:
|
|
42500
|
-
return new Point({
|
|
42501
|
-
x: 0,
|
|
42502
|
-
y: 0,
|
|
42503
|
-
});
|
|
42504
|
-
}
|
|
42505
|
-
};
|
|
42506
|
-
const nextPoint = getNextPoint();
|
|
42507
|
-
const normalizedNext = normalizePoint(nextPoint);
|
|
42508
|
-
let endPoint = new Point({ x: nextPoint.x, y: nextPoint.y });
|
|
42509
|
-
let startPoint = new Point({ x: origin.x, y: origin.y });
|
|
42510
|
-
const result = getInnerSegment(startPoint, endPoint, svgRect);
|
|
42511
|
-
if (!result) {
|
|
42512
|
-
return {
|
|
42513
|
-
point: nextPoint,
|
|
42514
|
-
command: `M${normalizedNext.x},${normalizedNext.y}`,
|
|
42515
|
-
};
|
|
42516
|
-
}
|
|
42517
|
-
// if the point wasn't moved it means that it's inside the rect
|
|
42518
|
-
const isStartInside = result.A.isEqual(startPoint);
|
|
42519
|
-
const isEndInside = result.B.isEqual(endPoint);
|
|
42520
|
-
// the intersection points are referencing the pdf coordinates, it's necessary to convert these points to the path's origin point
|
|
42521
|
-
endPoint = normalizePoint(new Point(result.B.toCoords()));
|
|
42522
|
-
startPoint = normalizePoint(new Point(result.A.toCoords()));
|
|
42523
|
-
const startInstruction = isStartInside
|
|
42524
|
-
? ''
|
|
42525
|
-
: `M${startPoint.x},${startPoint.y}`;
|
|
42526
|
-
const endInstruction = isEndInside
|
|
42527
|
-
? ''
|
|
42528
|
-
: `M${normalizedNext.x},${normalizedNext.y}`;
|
|
42529
|
-
return {
|
|
42530
|
-
point: nextPoint,
|
|
42531
|
-
command: `${startInstruction} L${endPoint.x},${endPoint.y} ${endInstruction} `,
|
|
42532
|
-
};
|
|
42533
|
-
}
|
|
42534
|
-
case 'a':
|
|
42535
|
-
case 'A': {
|
|
42536
|
-
const isLocalInstruction = command === 'a';
|
|
42537
|
-
const [, , , , , x, y] = params;
|
|
42538
|
-
const nextPoint = new Point({
|
|
42539
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + x,
|
|
42540
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + y,
|
|
42541
|
-
});
|
|
42542
|
-
// TODO: implement the code to fit the Elliptical Arc Curve instructions into the viewbox
|
|
42543
|
-
return {
|
|
42544
|
-
point: nextPoint,
|
|
42545
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42546
|
-
};
|
|
42547
|
-
}
|
|
42548
|
-
case 'c':
|
|
42549
|
-
case 'C': {
|
|
42550
|
-
const isLocalInstruction = command === 'c';
|
|
42551
|
-
let x = 0;
|
|
42552
|
-
let y = 0;
|
|
42553
|
-
for (let pendingParams = params; pendingParams.length > 0; pendingParams = pendingParams.slice(6)) {
|
|
42554
|
-
const [, , , , pendingX, pendingY] = pendingParams;
|
|
42555
|
-
if (isLocalInstruction) {
|
|
42556
|
-
x += pendingX;
|
|
42557
|
-
y += pendingY;
|
|
42558
|
-
}
|
|
42559
|
-
else {
|
|
42560
|
-
x = pendingX;
|
|
42561
|
-
y = pendingY;
|
|
42562
|
-
}
|
|
42563
|
-
}
|
|
42564
|
-
const nextPoint = new Point({
|
|
42565
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + x,
|
|
42566
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + y,
|
|
42567
|
-
});
|
|
42568
|
-
// TODO: implement the code to fit the Cubic Bézier Curve instructions into the viewbox
|
|
42569
|
-
return {
|
|
42570
|
-
point: nextPoint,
|
|
42571
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42572
|
-
};
|
|
42573
|
-
}
|
|
42574
|
-
case 's':
|
|
42575
|
-
case 'S':
|
|
42576
|
-
const isLocalInstruction = command === 's';
|
|
42577
|
-
let x = 0;
|
|
42578
|
-
let y = 0;
|
|
42579
|
-
for (let pendingParams = params; pendingParams.length > 0; pendingParams = pendingParams.slice(4)) {
|
|
42580
|
-
const [, , pendingX, pendingY] = pendingParams;
|
|
42581
|
-
x += pendingX;
|
|
42582
|
-
y += pendingY;
|
|
42583
|
-
}
|
|
42584
|
-
const nextPoint = new Point({
|
|
42585
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + x,
|
|
42586
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + y,
|
|
42587
|
-
});
|
|
42588
|
-
return {
|
|
42589
|
-
point: nextPoint,
|
|
42590
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42591
|
-
};
|
|
42592
|
-
case 'q':
|
|
42593
|
-
case 'Q': {
|
|
42594
|
-
const isLocalInstruction = command === 'q';
|
|
42595
|
-
const [, , x, y] = params;
|
|
42596
|
-
const nextPoint = new Point({
|
|
42597
|
-
x: (isLocalInstruction ? origin.x : basePoint.x) + x,
|
|
42598
|
-
y: (isLocalInstruction ? origin.y : basePoint.y) + y,
|
|
42599
|
-
});
|
|
42600
|
-
// TODO: implement the code to fit the Quadratic Bézier Curve instructions into the viewbox
|
|
42601
|
-
return {
|
|
42602
|
-
point: nextPoint,
|
|
42603
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42604
|
-
};
|
|
42605
|
-
}
|
|
42606
|
-
// TODO: Handle the remaining svg instructions: t,q
|
|
42607
|
-
default:
|
|
42608
|
-
return {
|
|
42609
|
-
point: origin,
|
|
42610
|
-
command: `${command} ${params.map((p) => `${p}`).join()}`,
|
|
42611
|
-
};
|
|
42612
|
-
}
|
|
42613
|
-
};
|
|
42614
|
-
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);
|
|
42615
|
-
let currentPoint = new Point({ x: basePoint.x, y: basePoint.y });
|
|
42616
|
-
const newPath = commands === null || commands === void 0 ? void 0 : commands.map((command) => {
|
|
42617
|
-
var _a, _b;
|
|
42618
|
-
const letter = (_a = command.match(/[a-z]/i)) === null || _a === void 0 ? void 0 : _a[0];
|
|
42619
|
-
const params = (_b = command
|
|
42620
|
-
.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));
|
|
42621
|
-
if (letter && params) {
|
|
42622
|
-
const result = handlePath(currentPoint, letter, params);
|
|
42623
|
-
if (result) {
|
|
42624
|
-
currentPoint = result.point;
|
|
42625
|
-
return result.command;
|
|
42626
|
-
}
|
|
42627
|
-
}
|
|
42628
|
-
return command;
|
|
42629
|
-
}).join(' ');
|
|
42630
|
-
element.svgAttributes.d = newPath;
|
|
42631
|
-
break;
|
|
42632
|
-
}
|
|
42633
|
-
case 'ellipse':
|
|
42634
|
-
case 'circle': {
|
|
42635
|
-
if (element.svgAttributes.cx === undefined ||
|
|
42636
|
-
element.svgAttributes.cy === undefined ||
|
|
42637
|
-
element.svgAttributes.rx === undefined ||
|
|
42638
|
-
element.svgAttributes.ry === undefined) {
|
|
42639
|
-
break;
|
|
42640
|
-
}
|
|
42641
|
-
const { cx = 0, cy = 0, rx = 0, ry = 0 } = element.svgAttributes;
|
|
42642
|
-
const center = new Point({
|
|
42643
|
-
x: cx,
|
|
42644
|
-
y: cy,
|
|
42645
|
-
});
|
|
42646
|
-
const rotation = ((_b = element.svgAttributes.rotation) === null || _b === void 0 ? void 0 : _b.angle) || 0;
|
|
42647
|
-
// these points are relative to the ellipse's center
|
|
42648
|
-
const a = new Point(rotate({ x: -rx, y: 0 }, degreesToRadians(rotation)));
|
|
42649
|
-
const b = new Point(rotate({ x: rx, y: 0 }, degreesToRadians(rotation)));
|
|
42650
|
-
const c = new Point(rotate({ x: 0, y: ry }, degreesToRadians(rotation)));
|
|
42651
|
-
// these points are relative to the real coordinate system
|
|
42652
|
-
const A = center.plus(a);
|
|
42653
|
-
const B = center.plus(b);
|
|
42654
|
-
const C = center.plus(c);
|
|
42655
|
-
const ellipse = new Ellipse(A, B, C);
|
|
42656
|
-
const intersections = getIntersections([svgRect, ellipse]);
|
|
42657
|
-
const isCenterInsideRect = isCoordinateInsideTheRect(center, svgRect);
|
|
42658
|
-
/**
|
|
42659
|
-
* if there are less than 2 intersection, there are two possibilities:
|
|
42660
|
-
* - the ellipse is outside the viewbox and therefore isn't visible
|
|
42661
|
-
* - the ellipse is inside the viewbox and don't need to be cropped
|
|
42662
|
-
*/
|
|
42663
|
-
if (intersections.length < 2) {
|
|
42664
|
-
!isCenterInsideRect && element.setAttribute('rx', '0');
|
|
42665
|
-
!isCenterInsideRect && (element.svgAttributes.rx = 0);
|
|
42666
|
-
!isCenterInsideRect && element.setAttribute('ry', '0');
|
|
42667
|
-
!isCenterInsideRect && (element.svgAttributes.ry = 0);
|
|
42668
|
-
break;
|
|
42669
|
-
}
|
|
42670
|
-
// viewbox rectangle coordinates
|
|
42671
|
-
const P1 = new Point(svgRect.getCoords());
|
|
42672
|
-
const P3 = new Point(svgRect.getEnd());
|
|
42673
|
-
const P2 = new Point({ x: P3.x, y: P1.y });
|
|
42674
|
-
const P4 = new Point({ x: P1.x, y: P3.y });
|
|
42675
|
-
const top = new Segment(P1, P2);
|
|
42676
|
-
const right = new Segment(P2, P3);
|
|
42677
|
-
const bottom = new Segment(P3, P4);
|
|
42678
|
-
const left = new Segment(P4, P1);
|
|
42679
|
-
// Warning: keep the order of the segments, it's important when building the path that will represent the ellipse
|
|
42680
|
-
const rectSegments = [top, right, bottom, left];
|
|
42681
|
-
const isPointInsideEllipse = (P) => (P.x - cx) ** 2 / rx ** 2 + (P.y - cy) ** 2 / ry ** 2 <= 1;
|
|
42682
|
-
// check if the rect boundaries are inside the circle
|
|
42683
|
-
const isRectInsideEllipse = isPointInsideEllipse(P1) &&
|
|
42684
|
-
isPointInsideEllipse(P2) &&
|
|
42685
|
-
isPointInsideEllipse(P3) &&
|
|
42686
|
-
isPointInsideEllipse(P4);
|
|
42687
|
-
// the segments that are intersecting the circle. And, therefore, are lines that are cropping the drawing
|
|
42688
|
-
const circleSegments = isRectInsideEllipse
|
|
42689
|
-
? rectSegments
|
|
42690
|
-
: rectSegments.map((segment, i) => {
|
|
42691
|
-
const [p1, p2] = getIntersections([segment, ellipse])
|
|
42692
|
-
// it's important to sort the segment's point because it impacts the angle of the arc, the points are sorted on clockwise direction
|
|
42693
|
-
.sort((p1, p2) => {
|
|
42694
|
-
// top
|
|
42695
|
-
if (i === 0) {
|
|
42696
|
-
return p1.x - p2.x;
|
|
42697
|
-
// right
|
|
42698
|
-
}
|
|
42699
|
-
else if (i === 1) {
|
|
42700
|
-
return p2.y - p1.y;
|
|
42701
|
-
// bottom
|
|
42702
|
-
}
|
|
42703
|
-
else if (i === 2) {
|
|
42704
|
-
return p2.x - p1.x;
|
|
42705
|
-
// left
|
|
42706
|
-
}
|
|
42707
|
-
else {
|
|
42708
|
-
return p1.y - p2.y;
|
|
42709
|
-
}
|
|
42710
|
-
});
|
|
42711
|
-
if (p1 && p2) {
|
|
42712
|
-
return new Segment(new Point(p1), new Point(p2));
|
|
42713
|
-
// if the other point isn't inside the circle it means that the circle isn't cropped by the segment
|
|
42714
|
-
}
|
|
42715
|
-
else if (p1 &&
|
|
42716
|
-
(isPointInsideEllipse(segment.A) ||
|
|
42717
|
-
isPointInsideEllipse(segment.B))) {
|
|
42718
|
-
const intersectionPoint = new Point(p1);
|
|
42719
|
-
const innerPoint = isPointInsideEllipse(segment.A)
|
|
42720
|
-
? segment.A
|
|
42721
|
-
: segment.B;
|
|
42722
|
-
// ensures that the segment is always following the clockwise direction
|
|
42723
|
-
const start = innerPoint.isEqual(segment.A)
|
|
42724
|
-
? innerPoint
|
|
42725
|
-
: intersectionPoint;
|
|
42726
|
-
const end = innerPoint.isEqual(segment.A)
|
|
42727
|
-
? intersectionPoint
|
|
42728
|
-
: innerPoint;
|
|
42729
|
-
return new Segment(start, end);
|
|
42730
|
-
// 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
|
|
42731
|
-
}
|
|
42732
|
-
else if (!(p1 && p2) &&
|
|
42733
|
-
isPointInsideEllipse(segment.A) &&
|
|
42734
|
-
isPointInsideEllipse(segment.B)) {
|
|
42735
|
-
return segment;
|
|
42736
|
-
}
|
|
42737
|
-
return;
|
|
42738
|
-
});
|
|
42739
|
-
const inverseAngle = (angle) => (360 - angle) % 360;
|
|
42740
|
-
const pointsAngle = (p1, p2, direction = 'clockwise') => {
|
|
42741
|
-
const startAngle = radiansToDegrees(Math.atan2(p1.y - center.y, p1.x - center.x));
|
|
42742
|
-
const endAngle = radiansToDegrees(Math.atan2(p2.y - center.y, p2.x - center.x));
|
|
42743
|
-
const arcAngle = (endAngle + (360 - startAngle)) % 360;
|
|
42744
|
-
return direction === 'clockwise' ? arcAngle : inverseAngle(arcAngle);
|
|
42745
|
-
};
|
|
42746
|
-
/**
|
|
42747
|
-
* - draw a line for each segment
|
|
42748
|
-
* - if two segments aren't connected draw an arc connecting them
|
|
42749
|
-
*/
|
|
42750
|
-
let startPoint;
|
|
42751
|
-
// the point where the pen is located
|
|
42752
|
-
let currentPoint;
|
|
42753
|
-
let lastSegment;
|
|
42754
|
-
let path = circleSegments.reduce((path, segment) => {
|
|
42755
|
-
if (!segment)
|
|
42756
|
-
return path;
|
|
42757
|
-
if (!startPoint) {
|
|
42758
|
-
startPoint = segment.A;
|
|
42759
|
-
path = `M ${segment.A.x},${segment.A.y}`;
|
|
42760
|
-
}
|
|
42761
|
-
// if the current segment isn't connected to the last one, connect both with an arc
|
|
42762
|
-
if (lastSegment && !lastSegment.B.isEqual(segment.A)) {
|
|
42763
|
-
const arcAngle = pointsAngle(segment.A, lastSegment.B);
|
|
42764
|
-
// angles greater than 180 degrees are marked as large-arc-flag = 1
|
|
42765
|
-
path += `A ${rx},${ry} ${rotation} ${arcAngle > 180 ? 1 : 0},0 ${segment.A.x}, ${segment.A.y}`;
|
|
42766
|
-
}
|
|
42767
|
-
path += ` L ${segment.B.x},${segment.B.y}`;
|
|
42768
|
-
currentPoint = segment.B;
|
|
42769
|
-
lastSegment = segment;
|
|
42770
|
-
return path;
|
|
42771
|
-
}, '');
|
|
42772
|
-
// if the path isn't closed, close it by drawing an arc
|
|
42773
|
-
if (startPoint && currentPoint && !startPoint.isEqual(currentPoint)) {
|
|
42774
|
-
const arcAngle = pointsAngle(currentPoint, startPoint, 'counter-clockwise');
|
|
42775
|
-
// angles greater than 180 degrees are marked as large-arc-flag = 1
|
|
42776
|
-
path += `A ${rx},${ry} ${rotation} ${arcAngle > 180 ? 1 : 0},0 ${startPoint.x}, ${startPoint.y}`;
|
|
42777
|
-
}
|
|
42778
|
-
// create a new element that will represent the cropped ellipse
|
|
42779
|
-
const newElement = index.parse(`<path d="${path}" fill="red"/>`).firstChild;
|
|
42780
|
-
const svgAttributes = Object.assign(Object.assign({}, element.svgAttributes), {
|
|
42781
|
-
// the x and y values are 0 because all the path coordinates are global
|
|
42782
|
-
x: 0, y: 0,
|
|
42783
|
-
// the path coordinates are already rotated
|
|
42784
|
-
rotate: undefined, d: path });
|
|
42785
|
-
Object.assign(newElement, { svgAttributes });
|
|
42786
|
-
return newElement;
|
|
42787
|
-
}
|
|
42788
|
-
case 'rect': {
|
|
42789
|
-
const { x = 0, y = 0, width = 0, height = 0, rotate: rawRotation, } = element.svgAttributes;
|
|
42790
|
-
const rotation = (rawRotation === null || rawRotation === void 0 ? void 0 : rawRotation.angle) || 0;
|
|
42791
|
-
if (!(width && height))
|
|
42792
|
-
return element;
|
|
42793
|
-
// bottomLeft point
|
|
42794
|
-
const origin = new Point({ x, y });
|
|
42795
|
-
const rotateAroundOrigin = (p) => new Point(rotate(normalize(p), degreesToRadians(rotation))).plus(origin);
|
|
42796
|
-
const normalize = (p) => p.plus({ x: -origin.x, y: -origin.y });
|
|
42797
|
-
const topLeft = rotateAroundOrigin(origin.plus({ x: 0, y: -height }));
|
|
42798
|
-
const topRight = rotateAroundOrigin(origin.plus({ x: width, y: -height }));
|
|
42799
|
-
const bottomRight = rotateAroundOrigin(origin.plus({ x: width, y: 0 }));
|
|
42800
|
-
const pointToString = (p) => [p.x, p.y].join();
|
|
42801
|
-
const d = `M${pointToString(topLeft)} L${pointToString(topRight)} L${pointToString(bottomRight)} L${pointToString(origin)} L${pointToString(topLeft)}`;
|
|
42802
|
-
const el = index.parse(`<path d="${d}"/>`).firstChild;
|
|
42803
|
-
const newAttributes = Object.assign(Object.assign({}, element.svgAttributes), { d, x: 0, y: 0 });
|
|
42804
|
-
// @ts-ignore
|
|
42805
|
-
delete newAttributes.width;
|
|
42806
|
-
// @ts-ignore
|
|
42807
|
-
delete newAttributes.height;
|
|
42808
|
-
delete newAttributes.rotate;
|
|
42809
|
-
delete newAttributes.rotation;
|
|
42810
|
-
Object.assign(el, {
|
|
42811
|
-
svgAttributes: newAttributes,
|
|
42812
|
-
});
|
|
42813
|
-
return cropSvgElement(svgRect, el);
|
|
42814
|
-
}
|
|
42815
|
-
// TODO: implement the crop for the following elements
|
|
42816
|
-
case 'image':
|
|
42817
|
-
default:
|
|
42818
|
-
return element;
|
|
42819
|
-
}
|
|
42820
|
-
return element;
|
|
42821
|
-
};
|
|
42822
41658
|
// TODO: Improve type system to require the correct props for each tagName.
|
|
42823
41659
|
/** methods to draw SVGElements onto a PDFPage */
|
|
42824
41660
|
const runnersToPage = (page, options) => ({
|
|
42825
|
-
text(element) {
|
|
42826
|
-
|
|
42827
|
-
|
|
42828
|
-
|
|
42829
|
-
|
|
42830
|
-
|
|
42831
|
-
|
|
42832
|
-
|
|
42833
|
-
|
|
42834
|
-
|
|
42835
|
-
|
|
42836
|
-
|
|
42837
|
-
|
|
42838
|
-
|
|
42839
|
-
|
|
42840
|
-
|
|
42841
|
-
|
|
42842
|
-
|
|
42843
|
-
|
|
42844
|
-
|
|
42845
|
-
|
|
42846
|
-
|
|
42847
|
-
|
|
42848
|
-
|
|
42849
|
-
|
|
42850
|
-
|
|
42851
|
-
|
|
42852
|
-
|
|
42853
|
-
|
|
42854
|
-
|
|
42855
|
-
|
|
42856
|
-
|
|
42857
|
-
|
|
42858
|
-
|
|
42859
|
-
|
|
42860
|
-
|
|
42861
|
-
|
|
42862
|
-
|
|
42863
|
-
|
|
42864
|
-
|
|
42865
|
-
font,
|
|
42866
|
-
size: fontSize,
|
|
42867
|
-
color: element.svgAttributes.fill,
|
|
42868
|
-
opacity: element.svgAttributes.fillOpacity,
|
|
42869
|
-
rotate: element.svgAttributes.rotate,
|
|
42870
|
-
});
|
|
41661
|
+
async text(element) {
|
|
41662
|
+
const anchor = element.svgAttributes.textAnchor;
|
|
41663
|
+
const dominantBaseline = element.svgAttributes.dominantBaseline;
|
|
41664
|
+
const text = element.text.trim().replace(/\s/g, ' ');
|
|
41665
|
+
const fontSize = element.svgAttributes.fontSize || 12;
|
|
41666
|
+
/** This will find the best font for the provided style in the list */
|
|
41667
|
+
function getBestFont(style, fonts) {
|
|
41668
|
+
const family = style.fontFamily;
|
|
41669
|
+
if (!family)
|
|
41670
|
+
return undefined;
|
|
41671
|
+
const isBold = style.fontWeight === 'bold' || Number(style.fontWeight) >= 700;
|
|
41672
|
+
const isItalic = style.fontStyle === 'italic';
|
|
41673
|
+
const getFont = (bold, italic, family) => fonts[family + (bold ? '_bold' : '') + (italic ? '_italic' : '')];
|
|
41674
|
+
return (getFont(isBold, isItalic, family) ||
|
|
41675
|
+
getFont(isBold, false, family) ||
|
|
41676
|
+
getFont(false, isItalic, family) ||
|
|
41677
|
+
getFont(false, false, family) ||
|
|
41678
|
+
Object.keys(fonts).find((fontFamily) => fontFamily.startsWith(family)));
|
|
41679
|
+
}
|
|
41680
|
+
const font = options.fonts && getBestFont(element.svgAttributes, options.fonts);
|
|
41681
|
+
const textWidth = (font || page.getFont()[0]).widthOfTextAtSize(text, fontSize);
|
|
41682
|
+
const textHeight = (font || page.getFont()[0]).heightAtSize(fontSize);
|
|
41683
|
+
const offsetX = anchor === 'middle' ? textWidth / 2 : anchor === 'end' ? textWidth : 0;
|
|
41684
|
+
const offsetY = dominantBaseline === 'text-before-edge'
|
|
41685
|
+
? textHeight
|
|
41686
|
+
: dominantBaseline === 'text-after-edge'
|
|
41687
|
+
? -textHeight
|
|
41688
|
+
: dominantBaseline === 'middle'
|
|
41689
|
+
? textHeight / 2
|
|
41690
|
+
: 0;
|
|
41691
|
+
page.drawText(text, {
|
|
41692
|
+
x: -offsetX,
|
|
41693
|
+
y: -offsetY,
|
|
41694
|
+
font,
|
|
41695
|
+
// TODO: the font size should be correctly scaled too
|
|
41696
|
+
size: fontSize,
|
|
41697
|
+
color: element.svgAttributes.fill,
|
|
41698
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41699
|
+
matrix: element.svgAttributes.matrix,
|
|
41700
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42871
41701
|
});
|
|
42872
41702
|
},
|
|
42873
|
-
line(element) {
|
|
42874
|
-
|
|
42875
|
-
|
|
42876
|
-
|
|
42877
|
-
|
|
42878
|
-
|
|
42879
|
-
|
|
42880
|
-
|
|
42881
|
-
|
|
42882
|
-
|
|
42883
|
-
|
|
42884
|
-
|
|
42885
|
-
|
|
42886
|
-
|
|
42887
|
-
|
|
42888
|
-
|
|
41703
|
+
async line(element) {
|
|
41704
|
+
page.drawLine({
|
|
41705
|
+
start: {
|
|
41706
|
+
x: element.svgAttributes.x1 || 0,
|
|
41707
|
+
y: -element.svgAttributes.y1 || 0,
|
|
41708
|
+
},
|
|
41709
|
+
end: {
|
|
41710
|
+
x: element.svgAttributes.x2 || 0,
|
|
41711
|
+
y: -element.svgAttributes.y2 || 0,
|
|
41712
|
+
},
|
|
41713
|
+
thickness: element.svgAttributes.strokeWidth,
|
|
41714
|
+
color: element.svgAttributes.stroke,
|
|
41715
|
+
opacity: element.svgAttributes.strokeOpacity,
|
|
41716
|
+
lineCap: element.svgAttributes.strokeLineCap,
|
|
41717
|
+
matrix: element.svgAttributes.matrix,
|
|
41718
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42889
41719
|
});
|
|
42890
41720
|
},
|
|
42891
|
-
path(element) {
|
|
42892
|
-
|
|
42893
|
-
|
|
42894
|
-
|
|
42895
|
-
|
|
42896
|
-
|
|
42897
|
-
|
|
42898
|
-
|
|
42899
|
-
|
|
42900
|
-
|
|
42901
|
-
|
|
42902
|
-
|
|
42903
|
-
|
|
42904
|
-
|
|
42905
|
-
|
|
42906
|
-
|
|
42907
|
-
fillRule: element.svgAttributes.fillRule,
|
|
42908
|
-
});
|
|
41721
|
+
async path(element) {
|
|
41722
|
+
if (!element.svgAttributes.d)
|
|
41723
|
+
return;
|
|
41724
|
+
// See https://jsbin.com/kawifomupa/edit?html,output and
|
|
41725
|
+
page.drawSvgPath(element.svgAttributes.d, {
|
|
41726
|
+
x: 0,
|
|
41727
|
+
y: 0,
|
|
41728
|
+
borderColor: element.svgAttributes.stroke,
|
|
41729
|
+
borderWidth: element.svgAttributes.strokeWidth,
|
|
41730
|
+
borderOpacity: element.svgAttributes.strokeOpacity,
|
|
41731
|
+
borderLineCap: element.svgAttributes.strokeLineCap,
|
|
41732
|
+
color: element.svgAttributes.fill,
|
|
41733
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41734
|
+
fillRule: element.svgAttributes.fillRule,
|
|
41735
|
+
matrix: element.svgAttributes.matrix,
|
|
41736
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42909
41737
|
});
|
|
42910
41738
|
},
|
|
42911
|
-
image(element) {
|
|
42912
|
-
|
|
42913
|
-
|
|
42914
|
-
|
|
42915
|
-
|
|
42916
|
-
|
|
42917
|
-
|
|
42918
|
-
|
|
42919
|
-
|
|
42920
|
-
|
|
42921
|
-
|
|
42922
|
-
|
|
42923
|
-
|
|
42924
|
-
|
|
42925
|
-
|
|
42926
|
-
|
|
42927
|
-
|
|
42928
|
-
ySkew: element.svgAttributes.skewY,
|
|
42929
|
-
rotate: element.svgAttributes.rotate,
|
|
42930
|
-
});
|
|
41739
|
+
async image(element) {
|
|
41740
|
+
const { src } = element.svgAttributes;
|
|
41741
|
+
if (!src)
|
|
41742
|
+
return;
|
|
41743
|
+
const isPng = src.match(/\.png(\?|$)|^data:image\/png;base64/gim);
|
|
41744
|
+
const img = isPng
|
|
41745
|
+
? await page.doc.embedPng(src)
|
|
41746
|
+
: await page.doc.embedJpg(src);
|
|
41747
|
+
const { x, y, width, height } = getFittingRectangle(img.width, img.height, element.svgAttributes.width || img.width, element.svgAttributes.height || img.height, element.svgAttributes.preserveAspectRatio);
|
|
41748
|
+
page.drawImage(img, {
|
|
41749
|
+
x,
|
|
41750
|
+
y: -y - height,
|
|
41751
|
+
width,
|
|
41752
|
+
height,
|
|
41753
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41754
|
+
matrix: element.svgAttributes.matrix,
|
|
41755
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42931
41756
|
});
|
|
42932
41757
|
},
|
|
42933
|
-
rect(element) {
|
|
42934
|
-
|
|
42935
|
-
|
|
42936
|
-
|
|
42937
|
-
|
|
42938
|
-
|
|
42939
|
-
|
|
42940
|
-
|
|
42941
|
-
|
|
42942
|
-
|
|
42943
|
-
|
|
42944
|
-
|
|
42945
|
-
|
|
42946
|
-
|
|
42947
|
-
|
|
42948
|
-
|
|
42949
|
-
ySkew: element.svgAttributes.skewY,
|
|
42950
|
-
rotate: element.svgAttributes.rotate,
|
|
42951
|
-
});
|
|
41758
|
+
async rect(element) {
|
|
41759
|
+
if (!element.svgAttributes.fill && !element.svgAttributes.stroke)
|
|
41760
|
+
return;
|
|
41761
|
+
page.drawRectangle({
|
|
41762
|
+
x: 0,
|
|
41763
|
+
y: 0,
|
|
41764
|
+
width: element.svgAttributes.width,
|
|
41765
|
+
height: element.svgAttributes.height * -1,
|
|
41766
|
+
borderColor: element.svgAttributes.stroke,
|
|
41767
|
+
borderWidth: element.svgAttributes.strokeWidth,
|
|
41768
|
+
borderOpacity: element.svgAttributes.strokeOpacity,
|
|
41769
|
+
borderLineCap: element.svgAttributes.strokeLineCap,
|
|
41770
|
+
color: element.svgAttributes.fill,
|
|
41771
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41772
|
+
matrix: element.svgAttributes.matrix,
|
|
41773
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42952
41774
|
});
|
|
42953
41775
|
},
|
|
42954
|
-
ellipse(element) {
|
|
42955
|
-
|
|
42956
|
-
|
|
42957
|
-
|
|
42958
|
-
|
|
42959
|
-
|
|
42960
|
-
|
|
42961
|
-
|
|
42962
|
-
|
|
42963
|
-
|
|
42964
|
-
|
|
42965
|
-
|
|
42966
|
-
|
|
42967
|
-
|
|
42968
|
-
});
|
|
41776
|
+
async ellipse(element) {
|
|
41777
|
+
page.drawEllipse({
|
|
41778
|
+
x: element.svgAttributes.cx || 0,
|
|
41779
|
+
y: -(element.svgAttributes.cy || 0),
|
|
41780
|
+
xScale: element.svgAttributes.rx,
|
|
41781
|
+
yScale: element.svgAttributes.ry,
|
|
41782
|
+
borderColor: element.svgAttributes.stroke,
|
|
41783
|
+
borderWidth: element.svgAttributes.strokeWidth,
|
|
41784
|
+
borderOpacity: element.svgAttributes.strokeOpacity,
|
|
41785
|
+
borderLineCap: element.svgAttributes.strokeLineCap,
|
|
41786
|
+
color: element.svgAttributes.fill,
|
|
41787
|
+
opacity: element.svgAttributes.fillOpacity,
|
|
41788
|
+
matrix: element.svgAttributes.matrix,
|
|
41789
|
+
clipSpaces: element.svgAttributes.clipSpaces,
|
|
42969
41790
|
});
|
|
42970
41791
|
},
|
|
42971
|
-
circle(element) {
|
|
42972
|
-
return
|
|
42973
|
-
return runnersToPage(page, options).ellipse(element);
|
|
42974
|
-
});
|
|
41792
|
+
async circle(element) {
|
|
41793
|
+
return runnersToPage(page, options).ellipse(element);
|
|
42975
41794
|
},
|
|
42976
41795
|
});
|
|
42977
|
-
const transform = (converter, name, args) => {
|
|
42978
|
-
switch (name) {
|
|
42979
|
-
case 'scaleX':
|
|
42980
|
-
return transform(converter, 'scale', [args[0], 0]);
|
|
42981
|
-
case 'scaleY':
|
|
42982
|
-
return transform(converter, 'scale', [0, args[0]]);
|
|
42983
|
-
case 'scale':
|
|
42984
|
-
const [xScale, yScale = xScale] = args;
|
|
42985
|
-
return {
|
|
42986
|
-
point: (x, y) => converter.point(x * xScale, y * yScale),
|
|
42987
|
-
size: (w, h) => converter.size(w * xScale, h * yScale),
|
|
42988
|
-
};
|
|
42989
|
-
case 'translateX':
|
|
42990
|
-
return transform(converter, 'translate', [args[0], 0]);
|
|
42991
|
-
case 'translateY':
|
|
42992
|
-
return transform(converter, 'translate', [0, args[0]]);
|
|
42993
|
-
case 'translate':
|
|
42994
|
-
const [dx, dy = dx] = args;
|
|
42995
|
-
return {
|
|
42996
|
-
point: (x, y) => converter.point(x + dx, y + dy),
|
|
42997
|
-
size: converter.size,
|
|
42998
|
-
};
|
|
42999
|
-
case 'rotate': {
|
|
43000
|
-
if (args.length > 1) {
|
|
43001
|
-
const [a, x, y = x] = args;
|
|
43002
|
-
let tempResult = transform(converter, 'translate', [x, y]);
|
|
43003
|
-
tempResult = transform(tempResult, 'rotate', [a]);
|
|
43004
|
-
return transform(tempResult, 'translate', [-x, -y]);
|
|
43005
|
-
}
|
|
43006
|
-
else {
|
|
43007
|
-
const [a] = args;
|
|
43008
|
-
const angle = degreesToRadians(a);
|
|
43009
|
-
return {
|
|
43010
|
-
point: (x, y) => converter.point(x * Math.cos(angle) - y * Math.sin(angle), y * Math.cos(angle) + x * Math.sin(angle)),
|
|
43011
|
-
size: converter.size,
|
|
43012
|
-
};
|
|
43013
|
-
}
|
|
43014
|
-
}
|
|
43015
|
-
case 'matrix': {
|
|
43016
|
-
const [scaleX, skewY, skewX, scaleY, translateX, translateY] = args;
|
|
43017
|
-
return {
|
|
43018
|
-
point: (x, y) => converter.point(x * scaleX + y * skewX + translateX, x * skewY + y * scaleY + translateY),
|
|
43019
|
-
size: (w, h) => converter.size(w * scaleX, h * scaleY),
|
|
43020
|
-
};
|
|
43021
|
-
}
|
|
43022
|
-
case 'skewX': {
|
|
43023
|
-
const angle = degreesToRadians(args[0]);
|
|
43024
|
-
return {
|
|
43025
|
-
point: (x, y) => converter.point((1 + x) * Math.tan(angle), y),
|
|
43026
|
-
size: converter.size,
|
|
43027
|
-
};
|
|
43028
|
-
}
|
|
43029
|
-
case 'skewY': {
|
|
43030
|
-
const angle = degreesToRadians(args[0]);
|
|
43031
|
-
return {
|
|
43032
|
-
point: (x, y) => converter.point(x, (1 + y) * Math.tan(angle)),
|
|
43033
|
-
size: converter.size,
|
|
43034
|
-
};
|
|
43035
|
-
}
|
|
43036
|
-
default: {
|
|
43037
|
-
console.log('transformation unsupported:', name);
|
|
43038
|
-
return converter;
|
|
43039
|
-
}
|
|
43040
|
-
}
|
|
43041
|
-
};
|
|
43042
41796
|
const styleOrAttribute = (attributes, style, attribute, def) => {
|
|
43043
41797
|
const value = style[attribute] || attributes[attribute];
|
|
43044
41798
|
if (!value && typeof def !== 'undefined')
|
|
@@ -43068,8 +41822,8 @@ end\
|
|
|
43068
41822
|
alpha: parsedColor.alpha ? parsedColor.alpha + '' : undefined,
|
|
43069
41823
|
};
|
|
43070
41824
|
};
|
|
43071
|
-
const parseAttributes = (element, inherited,
|
|
43072
|
-
var _a, _b, _c, _d
|
|
41825
|
+
const parseAttributes = (element, inherited, matrix) => {
|
|
41826
|
+
var _a, _b, _c, _d;
|
|
43073
41827
|
const attributes = element.attributes;
|
|
43074
41828
|
const style = parseStyles(attributes.style);
|
|
43075
41829
|
const widthRaw = styleOrAttribute(attributes, style, 'width', '');
|
|
@@ -43125,7 +41879,6 @@ end\
|
|
|
43125
41879
|
dominantBaseline: attributes['dominant-baseline'],
|
|
43126
41880
|
preserveAspectRatio: attributes.preserveAspectRatio,
|
|
43127
41881
|
};
|
|
43128
|
-
let newConverter = converter;
|
|
43129
41882
|
let transformList = attributes.transform || '';
|
|
43130
41883
|
// Handle transformations set as direct attributes
|
|
43131
41884
|
[
|
|
@@ -43144,28 +41897,11 @@ end\
|
|
|
43144
41897
|
transformList = attributes[name] + ' ' + transformList;
|
|
43145
41898
|
}
|
|
43146
41899
|
});
|
|
43147
|
-
// skewX, skewY, rotate and scale are handled by the pdf-lib
|
|
43148
|
-
['skewX', 'skewY', 'rotate'].forEach((name) => {
|
|
43149
|
-
var _a;
|
|
43150
|
-
if (attributes[name]) {
|
|
43151
|
-
const d = (_a = attributes[name].match(/-?(\d+\.?|\.)\d*/)) === null || _a === void 0 ? void 0 : _a[0];
|
|
43152
|
-
if (d !== undefined) {
|
|
43153
|
-
svgAttributes[name] = {
|
|
43154
|
-
angle: parseInt(d, 10),
|
|
43155
|
-
type: exports.RotationTypes.Degrees,
|
|
43156
|
-
};
|
|
43157
|
-
}
|
|
43158
|
-
}
|
|
43159
|
-
});
|
|
43160
|
-
if (attributes.scale) {
|
|
43161
|
-
const d = (_e = attributes.scale.match(/-?(\d+\.?|\.)\d*/)) === null || _e === void 0 ? void 0 : _e[0];
|
|
43162
|
-
if (d !== undefined)
|
|
43163
|
-
svgAttributes.scale = parseInt(d, 10);
|
|
43164
|
-
}
|
|
43165
41900
|
// Convert x/y as if it was a translation
|
|
43166
41901
|
if (x || y) {
|
|
43167
41902
|
transformList = transformList + `translate(${x || 0} ${y || 0}) `;
|
|
43168
41903
|
}
|
|
41904
|
+
let newMatrix = matrix;
|
|
43169
41905
|
// Apply the transformations
|
|
43170
41906
|
if (transformList) {
|
|
43171
41907
|
const regexTransform = /(\w+)\((.+?)\)/g;
|
|
@@ -43176,295 +41912,38 @@ end\
|
|
|
43176
41912
|
.split(/\s*,\s*|\s+/)
|
|
43177
41913
|
.filter((value) => value.length > 0)
|
|
43178
41914
|
.map((value) => parseFloat(value));
|
|
43179
|
-
|
|
43180
|
-
newConverter = transform(newConverter, name, args);
|
|
43181
|
-
const xAxisVector = minus(currentConverter.point(0, 0), currentConverter.point(1, 0));
|
|
43182
|
-
const xAxisVectorPostTransform = minus(newConverter.point(0, 0), newConverter.point(1, 0));
|
|
43183
|
-
// matrix transform may also represent rotations: https://www.w3.org/TR/SVGTiny12/coords.html
|
|
43184
|
-
if (name === 'rotate' || name === 'matrix') {
|
|
43185
|
-
// transformations over x and y axis might change the page coord direction
|
|
43186
|
-
const { width: xDirection, height: yDirection } = currentConverter.size(1, 1);
|
|
43187
|
-
const rotationAdded = name === 'rotate' ? args[0] : radiansToDegrees(angle(xAxisVectorPostTransform, xAxisVector));
|
|
43188
|
-
// the page Y coord is inverted so the angle rotation is inverted too
|
|
43189
|
-
const pageYDirection = -1;
|
|
43190
|
-
newInherited.rotation = degrees(pageYDirection * rotationAdded * Math.sign(xDirection * yDirection) +
|
|
43191
|
-
(((_f = inherited.rotation) === null || _f === void 0 ? void 0 : _f.angle) || 0));
|
|
43192
|
-
svgAttributes.rotate = newInherited.rotation;
|
|
43193
|
-
}
|
|
41915
|
+
newMatrix = combineTransformation(newMatrix, name, args);
|
|
43194
41916
|
parsed = regexTransform.exec(transformList);
|
|
43195
41917
|
}
|
|
43196
41918
|
}
|
|
43197
|
-
|
|
43198
|
-
|
|
43199
|
-
svgAttributes.x = newX;
|
|
43200
|
-
svgAttributes.y = newY;
|
|
41919
|
+
svgAttributes.x = x;
|
|
41920
|
+
svgAttributes.y = y;
|
|
43201
41921
|
if (attributes.cx || attributes.cy) {
|
|
43202
|
-
|
|
43203
|
-
svgAttributes.
|
|
43204
|
-
svgAttributes.cy = newCY;
|
|
41922
|
+
svgAttributes.cx = cx;
|
|
41923
|
+
svgAttributes.cy = cy;
|
|
43205
41924
|
}
|
|
43206
41925
|
if (attributes.rx || attributes.ry || attributes.r) {
|
|
43207
|
-
|
|
43208
|
-
svgAttributes.
|
|
43209
|
-
svgAttributes.ry = newRY;
|
|
41926
|
+
svgAttributes.rx = rx;
|
|
41927
|
+
svgAttributes.ry = ry;
|
|
43210
41928
|
}
|
|
43211
41929
|
if (attributes.x1 || attributes.y1) {
|
|
43212
|
-
|
|
43213
|
-
svgAttributes.
|
|
43214
|
-
svgAttributes.y1 = newY1;
|
|
41930
|
+
svgAttributes.x1 = x1;
|
|
41931
|
+
svgAttributes.y1 = y1;
|
|
43215
41932
|
}
|
|
43216
41933
|
if (attributes.x2 || attributes.y2) {
|
|
43217
|
-
|
|
43218
|
-
svgAttributes.
|
|
43219
|
-
svgAttributes.y2 = newY2;
|
|
41934
|
+
svgAttributes.x2 = x2;
|
|
41935
|
+
svgAttributes.y2 = y2;
|
|
43220
41936
|
}
|
|
43221
41937
|
if (attributes.width || attributes.height) {
|
|
43222
|
-
|
|
43223
|
-
svgAttributes.
|
|
43224
|
-
svgAttributes.height = size.height;
|
|
41938
|
+
svgAttributes.width = width !== null && width !== void 0 ? width : inherited.width;
|
|
41939
|
+
svgAttributes.height = height !== null && height !== void 0 ? height : inherited.height;
|
|
43225
41940
|
}
|
|
43226
|
-
// We convert all the points from the path
|
|
43227
41941
|
if (attributes.d) {
|
|
43228
|
-
|
|
43229
|
-
|
|
43230
|
-
let currentX = 0;
|
|
43231
|
-
let currentY = 0;
|
|
43232
|
-
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) => {
|
|
43233
|
-
var _a, _b;
|
|
43234
|
-
const letter = (_a = command.match(/[a-z]/i)) === null || _a === void 0 ? void 0 : _a[0];
|
|
43235
|
-
if ((letter === null || letter === void 0 ? void 0 : letter.toLocaleLowerCase()) === 'z')
|
|
43236
|
-
return letter;
|
|
43237
|
-
// const params = command.match(/([0-9e.-]+)/ig)?.filter(m => m !== '')//.map(v => parseFloat(v))
|
|
43238
|
-
const params = (_b = command
|
|
43239
|
-
.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))
|
|
43240
|
-
if (!params)
|
|
43241
|
-
return letter || '';
|
|
43242
|
-
switch (letter === null || letter === void 0 ? void 0 : letter.toLocaleLowerCase()) {
|
|
43243
|
-
case 'm':
|
|
43244
|
-
case 'l': {
|
|
43245
|
-
const groupedParams = groupBy(params, 2);
|
|
43246
|
-
return groupedParams
|
|
43247
|
-
.map((pair, pairIndex) => {
|
|
43248
|
-
const [x, y] = pair;
|
|
43249
|
-
const xReal = parseFloatValue(x, inherited.width) || 0;
|
|
43250
|
-
const yReal = parseFloatValue(y, innerHeight) || 0;
|
|
43251
|
-
if (letter === letter.toLowerCase()) {
|
|
43252
|
-
currentX += xReal;
|
|
43253
|
-
currentY += yReal;
|
|
43254
|
-
}
|
|
43255
|
-
else {
|
|
43256
|
-
currentX = xReal;
|
|
43257
|
-
currentY = yReal;
|
|
43258
|
-
}
|
|
43259
|
-
const point = newConverter.point(currentX, currentY);
|
|
43260
|
-
return ((pairIndex > 0 || letter.toUpperCase() === 'L' ? 'L' : 'M') +
|
|
43261
|
-
[point.x - xOrigin, point.y - yOrigin].join(','));
|
|
43262
|
-
})
|
|
43263
|
-
.join(' ');
|
|
43264
|
-
}
|
|
43265
|
-
case 'v': {
|
|
43266
|
-
return params
|
|
43267
|
-
.map((value) => {
|
|
43268
|
-
const coord = parseFloatValue(value) || 0;
|
|
43269
|
-
if (letter === letter.toLowerCase()) {
|
|
43270
|
-
currentY += coord;
|
|
43271
|
-
}
|
|
43272
|
-
else {
|
|
43273
|
-
currentY = coord;
|
|
43274
|
-
}
|
|
43275
|
-
const point = newConverter.point(currentX, currentY);
|
|
43276
|
-
// we can't use 'v' as the final command because rotations might require a different command after the path parsing
|
|
43277
|
-
// for instance, a 90 degree rotation would turn a 'v' into an 'h' command
|
|
43278
|
-
return `L${point.x - xOrigin} ${point.y - yOrigin}`;
|
|
43279
|
-
})
|
|
43280
|
-
.join(' ');
|
|
43281
|
-
}
|
|
43282
|
-
case 'h': {
|
|
43283
|
-
return params
|
|
43284
|
-
.map((value) => {
|
|
43285
|
-
const coord = parseFloatValue(value) || 0;
|
|
43286
|
-
if (letter === letter.toLowerCase()) {
|
|
43287
|
-
currentX += coord;
|
|
43288
|
-
}
|
|
43289
|
-
else {
|
|
43290
|
-
currentX = coord;
|
|
43291
|
-
}
|
|
43292
|
-
const point = newConverter.point(currentX, currentY);
|
|
43293
|
-
// we can't use 'h' as the final command because rotations might require a different command after the path parsing
|
|
43294
|
-
// for instance, a 90 degree rotation would turn a 'h' into an 'v' command
|
|
43295
|
-
return `L${point.x - xOrigin} ${point.y - yOrigin}`;
|
|
43296
|
-
})
|
|
43297
|
-
.join(' ');
|
|
43298
|
-
}
|
|
43299
|
-
case 'a': {
|
|
43300
|
-
const groupedParams = groupBy(params, 7);
|
|
43301
|
-
return groupedParams
|
|
43302
|
-
.map((p) => {
|
|
43303
|
-
const [rxPixel, ryPixel, xAxisRotation = '0', largeArc = '0', sweepFlag = '0', xPixel, yPixel,] = p;
|
|
43304
|
-
const realRx = parseFloatValue(rxPixel, inherited.width) || 0;
|
|
43305
|
-
const realRy = parseFloatValue(ryPixel, inherited.height) || 0;
|
|
43306
|
-
const realX = parseFloatValue(xPixel, inherited.width) || 0;
|
|
43307
|
-
const realY = parseFloatValue(yPixel, inherited.height) || 0;
|
|
43308
|
-
const { width: newRx, height: newRy } = newConverter.size(realRx, realRy);
|
|
43309
|
-
let point;
|
|
43310
|
-
if (letter === letter.toLowerCase()) {
|
|
43311
|
-
currentX += realX;
|
|
43312
|
-
currentY += realY;
|
|
43313
|
-
}
|
|
43314
|
-
else {
|
|
43315
|
-
currentX = realX;
|
|
43316
|
-
currentY = realY;
|
|
43317
|
-
}
|
|
43318
|
-
point = newConverter.point(currentX, currentY);
|
|
43319
|
-
// transformations over x and y axis might change the page coord direction
|
|
43320
|
-
const { width: xDirection, height: yDirection } = newConverter.size(1, 1);
|
|
43321
|
-
// -1 is the default direction
|
|
43322
|
-
const pageYDirection = -1 * Math.sign(xDirection * yDirection);
|
|
43323
|
-
const oppositeSweepFlag = sweepFlag === '0' ? '1' : '0';
|
|
43324
|
-
return [
|
|
43325
|
-
letter.toUpperCase(),
|
|
43326
|
-
newRx,
|
|
43327
|
-
newRy,
|
|
43328
|
-
xAxisRotation,
|
|
43329
|
-
largeArc,
|
|
43330
|
-
pageYDirection === -1 ? oppositeSweepFlag : sweepFlag,
|
|
43331
|
-
point.x - xOrigin,
|
|
43332
|
-
point.y - yOrigin,
|
|
43333
|
-
].join(' ');
|
|
43334
|
-
})
|
|
43335
|
-
.join(' ');
|
|
43336
|
-
}
|
|
43337
|
-
case 'c': {
|
|
43338
|
-
const groupedParams = groupBy(params, 6);
|
|
43339
|
-
const result = groupedParams
|
|
43340
|
-
.map(([c1X, c1Y, c2X, c2Y, xString, yString]) => [
|
|
43341
|
-
parseFloatValue(c1X, inherited.width) || 0,
|
|
43342
|
-
parseFloatValue(c1Y, inherited.height) || 0,
|
|
43343
|
-
parseFloatValue(c2X, inherited.width) || 0,
|
|
43344
|
-
parseFloatValue(c2Y, inherited.height) || 0,
|
|
43345
|
-
parseFloatValue(xString, inherited.width) || 0,
|
|
43346
|
-
parseFloatValue(yString, inherited.height) || 0,
|
|
43347
|
-
])
|
|
43348
|
-
.map(([c1X, c1Y, c2X, c2Y, xReal, yReal]) => {
|
|
43349
|
-
let controlPoint1X;
|
|
43350
|
-
let controlPoint1Y;
|
|
43351
|
-
let controlPoint2X;
|
|
43352
|
-
let controlPoint2Y;
|
|
43353
|
-
if (letter === letter.toLowerCase()) {
|
|
43354
|
-
controlPoint1X = currentX + c1X;
|
|
43355
|
-
controlPoint1Y = currentY + c1Y;
|
|
43356
|
-
controlPoint2X = currentX + c2X;
|
|
43357
|
-
controlPoint2Y = currentY + c2Y;
|
|
43358
|
-
currentX += xReal;
|
|
43359
|
-
currentY += yReal;
|
|
43360
|
-
}
|
|
43361
|
-
else {
|
|
43362
|
-
controlPoint1X = c1X;
|
|
43363
|
-
controlPoint1Y = c1Y;
|
|
43364
|
-
controlPoint2X = c2X;
|
|
43365
|
-
controlPoint2Y = c2Y;
|
|
43366
|
-
currentX = xReal;
|
|
43367
|
-
currentY = yReal;
|
|
43368
|
-
}
|
|
43369
|
-
const controlPoint1 = newConverter.point(controlPoint1X, controlPoint1Y);
|
|
43370
|
-
const controlPoint2 = newConverter.point(controlPoint2X, controlPoint2Y);
|
|
43371
|
-
const point = newConverter.point(currentX, currentY);
|
|
43372
|
-
return [
|
|
43373
|
-
controlPoint1.x - xOrigin,
|
|
43374
|
-
controlPoint1.y - yOrigin,
|
|
43375
|
-
controlPoint2.x - xOrigin,
|
|
43376
|
-
controlPoint2.y - yOrigin,
|
|
43377
|
-
point.x - xOrigin,
|
|
43378
|
-
point.y - yOrigin,
|
|
43379
|
-
].join(',');
|
|
43380
|
-
})
|
|
43381
|
-
.join(' ');
|
|
43382
|
-
return (letter === null || letter === void 0 ? void 0 : letter.toUpperCase()) + '' + result;
|
|
43383
|
-
}
|
|
43384
|
-
case 's': {
|
|
43385
|
-
const groupedParams = groupBy(params, 4);
|
|
43386
|
-
const result = groupedParams
|
|
43387
|
-
// the control point 1 is omitted because it's the reflection of c2
|
|
43388
|
-
.map(([c2X, c2Y, xString, yString]) => [
|
|
43389
|
-
parseFloatValue(c2X, inherited.width) || 0,
|
|
43390
|
-
parseFloatValue(c2Y, inherited.height) || 0,
|
|
43391
|
-
parseFloatValue(xString, inherited.width) || 0,
|
|
43392
|
-
parseFloatValue(yString, inherited.height) || 0,
|
|
43393
|
-
])
|
|
43394
|
-
.map(([c2X, c2Y, xReal, yReal]) => {
|
|
43395
|
-
let controlPoint2X;
|
|
43396
|
-
let controlPoint2Y;
|
|
43397
|
-
if (letter === letter.toLowerCase()) {
|
|
43398
|
-
controlPoint2X = currentX + c2X;
|
|
43399
|
-
controlPoint2Y = currentY + c2Y;
|
|
43400
|
-
currentX += xReal;
|
|
43401
|
-
currentY += yReal;
|
|
43402
|
-
}
|
|
43403
|
-
else {
|
|
43404
|
-
controlPoint2X = c2X;
|
|
43405
|
-
controlPoint2Y = c2Y;
|
|
43406
|
-
currentX = xReal;
|
|
43407
|
-
currentY = yReal;
|
|
43408
|
-
}
|
|
43409
|
-
const controlPoint2 = newConverter.point(controlPoint2X, controlPoint2Y);
|
|
43410
|
-
const point = newConverter.point(currentX, currentY);
|
|
43411
|
-
return [
|
|
43412
|
-
controlPoint2.x - xOrigin,
|
|
43413
|
-
controlPoint2.y - yOrigin,
|
|
43414
|
-
point.x - xOrigin,
|
|
43415
|
-
point.y - yOrigin,
|
|
43416
|
-
].join(',');
|
|
43417
|
-
})
|
|
43418
|
-
.join(' ');
|
|
43419
|
-
return (letter === null || letter === void 0 ? void 0 : letter.toUpperCase()) + '' + result;
|
|
43420
|
-
}
|
|
43421
|
-
default: {
|
|
43422
|
-
const groupedParams = groupBy(params, 2);
|
|
43423
|
-
const result = groupedParams
|
|
43424
|
-
.map(([xString, yString]) => [
|
|
43425
|
-
parseFloatValue(xString, inherited.width) || 0,
|
|
43426
|
-
parseFloatValue(yString, inherited.height) || 0,
|
|
43427
|
-
])
|
|
43428
|
-
.map(([xReal, yReal]) => {
|
|
43429
|
-
if (letter === letter.toLowerCase()) {
|
|
43430
|
-
currentX += xReal;
|
|
43431
|
-
currentY += yReal;
|
|
43432
|
-
}
|
|
43433
|
-
else {
|
|
43434
|
-
currentX = xReal;
|
|
43435
|
-
currentY = yReal;
|
|
43436
|
-
}
|
|
43437
|
-
const point = newConverter.point(currentX, currentY);
|
|
43438
|
-
return [point.x - xOrigin, point.y - yOrigin].join(',');
|
|
43439
|
-
})
|
|
43440
|
-
.join(' ');
|
|
43441
|
-
return (letter === null || letter === void 0 ? void 0 : letter.toUpperCase()) + '' + result;
|
|
43442
|
-
}
|
|
43443
|
-
}
|
|
43444
|
-
});
|
|
43445
|
-
}
|
|
43446
|
-
if (attributes.viewBox) {
|
|
43447
|
-
const viewBox = parseViewBox(attributes.viewBox);
|
|
43448
|
-
const size = {
|
|
43449
|
-
width: width || inherited.viewBox.width,
|
|
43450
|
-
height: height || inherited.viewBox.height,
|
|
43451
|
-
};
|
|
43452
|
-
const localConverter = getConverterWithAspectRatio(size, viewBox, attributes.preserveAspectRatio);
|
|
43453
|
-
const oldConverter = newConverter;
|
|
43454
|
-
newConverter = {
|
|
43455
|
-
point: (px, py) => {
|
|
43456
|
-
const { x: localX, y: localY } = localConverter.point(px, py);
|
|
43457
|
-
return oldConverter.point(localX, localY);
|
|
43458
|
-
},
|
|
43459
|
-
size: (w, h) => {
|
|
43460
|
-
const { width: localWidth, height: localHeight } = localConverter.size(w, h);
|
|
43461
|
-
return oldConverter.size(localWidth, localHeight);
|
|
43462
|
-
},
|
|
43463
|
-
};
|
|
41942
|
+
newMatrix = combineTransformation(newMatrix, 'scale', [1, -1]);
|
|
41943
|
+
svgAttributes.d = attributes.d;
|
|
43464
41944
|
}
|
|
43465
|
-
// apply the converter only when there's a local fontSize instruction
|
|
43466
41945
|
if (fontSizeRaw && newInherited.fontSize) {
|
|
43467
|
-
newInherited.fontSize =
|
|
41946
|
+
newInherited.fontSize = newInherited.fontSize;
|
|
43468
41947
|
}
|
|
43469
41948
|
if (newInherited.fontFamily) {
|
|
43470
41949
|
// Handle complex fontFamily like `"Linux Libertine O", serif`
|
|
@@ -43473,43 +41952,13 @@ end\
|
|
|
43473
41952
|
newInherited.fontFamily = inner[1] || inner[2];
|
|
43474
41953
|
}
|
|
43475
41954
|
if (newInherited.strokeWidth) {
|
|
43476
|
-
|
|
43477
|
-
svgAttributes.strokeWidth = Math.max(Math.min(Math.abs(result.width), Math.abs(result.height)), 1);
|
|
41955
|
+
svgAttributes.strokeWidth = newInherited.strokeWidth;
|
|
43478
41956
|
}
|
|
43479
41957
|
return {
|
|
43480
41958
|
inherited: newInherited,
|
|
43481
41959
|
svgAttributes,
|
|
43482
|
-
converter: newConverter,
|
|
43483
41960
|
tagName: element.tagName,
|
|
43484
|
-
|
|
43485
|
-
};
|
|
43486
|
-
const getConverter = (box, viewBox) => {
|
|
43487
|
-
const { width, height } = box;
|
|
43488
|
-
const { x: xMin, y: yMin, width: viewWidth, height: viewHeight } = viewBox;
|
|
43489
|
-
const converter = {
|
|
43490
|
-
point: (xReal, yReal) => ({
|
|
43491
|
-
x: ((xReal - xMin) / viewWidth) * (width || 0),
|
|
43492
|
-
y: ((yReal - yMin) / viewHeight) * (height || 0),
|
|
43493
|
-
}),
|
|
43494
|
-
size: (wReal, hReal) => ({
|
|
43495
|
-
width: (wReal / viewWidth) * (width || 0),
|
|
43496
|
-
height: (hReal / viewHeight) * (height || 0),
|
|
43497
|
-
}),
|
|
43498
|
-
};
|
|
43499
|
-
return converter;
|
|
43500
|
-
};
|
|
43501
|
-
const getConverterWithAspectRatio = (size, viewBox, preserveAspectRatio) => {
|
|
43502
|
-
// explanation about how the svg attributes applies transformations to the child elements
|
|
43503
|
-
// https://www.w3.org/TR/SVG/coords.html#ComputingAViewportsTransform
|
|
43504
|
-
const { x, y, width, height } = getFittingRectangle(viewBox.width, viewBox.height, size.width, size.height, preserveAspectRatio);
|
|
43505
|
-
const ratioConverter = getConverter({ width, height }, viewBox);
|
|
43506
|
-
// We translate the drawing in the page when the aspect ratio is different, according to the preserveAspectRatio instructions.
|
|
43507
|
-
return {
|
|
43508
|
-
point: (xReal, yReal) => {
|
|
43509
|
-
const P = ratioConverter.point(xReal, yReal);
|
|
43510
|
-
return { x: P.x + x, y: P.y + y };
|
|
43511
|
-
},
|
|
43512
|
-
size: ratioConverter.size,
|
|
41961
|
+
matrix: newMatrix,
|
|
43513
41962
|
};
|
|
43514
41963
|
};
|
|
43515
41964
|
const getFittingRectangle = (originalWidth, originalHeight, targetWidth, targetHeight, preserveAspectRatio) => {
|
|
@@ -43547,16 +41996,62 @@ end\
|
|
|
43547
41996
|
})();
|
|
43548
41997
|
return { x, y, width, height };
|
|
43549
41998
|
};
|
|
43550
|
-
const
|
|
41999
|
+
const getAspectRatioTransformation = (matrix, originalWidth, originalHeight, targetWidth, targetHeight, preserveAspectRatio) => {
|
|
42000
|
+
const scaleX = targetWidth / originalWidth;
|
|
42001
|
+
const scaleY = targetHeight / originalHeight;
|
|
42002
|
+
const boxScale = combineTransformation(matrix, 'scale', [
|
|
42003
|
+
scaleX,
|
|
42004
|
+
scaleY
|
|
42005
|
+
]);
|
|
42006
|
+
if (preserveAspectRatio === 'none') {
|
|
42007
|
+
return {
|
|
42008
|
+
clipBox: boxScale,
|
|
42009
|
+
content: boxScale
|
|
42010
|
+
};
|
|
42011
|
+
}
|
|
42012
|
+
// TODO: the following code works for the 'meet' param but not for the 'slice'
|
|
42013
|
+
const scale = targetWidth > targetHeight ? scaleY : scaleX;
|
|
42014
|
+
const dx = targetWidth - (originalWidth * scale);
|
|
42015
|
+
const dy = targetHeight - (originalHeight * scale);
|
|
42016
|
+
const [x, y] = (() => {
|
|
42017
|
+
switch (preserveAspectRatio) {
|
|
42018
|
+
case 'xMinYMin':
|
|
42019
|
+
return [0, 0];
|
|
42020
|
+
case 'xMidYMin':
|
|
42021
|
+
return [dx / 2, 0];
|
|
42022
|
+
case 'xMaxYMin':
|
|
42023
|
+
return [dx, dy / 2];
|
|
42024
|
+
case 'xMinYMid':
|
|
42025
|
+
return [0, dy];
|
|
42026
|
+
case 'xMaxYMid':
|
|
42027
|
+
return [dx, dy / 2];
|
|
42028
|
+
case 'xMinYMax':
|
|
42029
|
+
return [0, dy];
|
|
42030
|
+
case 'xMidYMax':
|
|
42031
|
+
return [dx / 2, dy];
|
|
42032
|
+
case 'xMaxYMax':
|
|
42033
|
+
return [dx, dy];
|
|
42034
|
+
case 'xMidYMid':
|
|
42035
|
+
default:
|
|
42036
|
+
return [dx / 2, dy / 2];
|
|
42037
|
+
}
|
|
42038
|
+
})();
|
|
42039
|
+
const contentTransform = combineTransformation(combineTransformation(matrix, 'translate', [x, y]), 'scale', [scale]);
|
|
42040
|
+
return {
|
|
42041
|
+
clipBox: boxScale,
|
|
42042
|
+
content: contentTransform
|
|
42043
|
+
};
|
|
42044
|
+
};
|
|
42045
|
+
const parseHTMLNode = (node, inherited, matrix, clipSpaces) => {
|
|
43551
42046
|
if (node.nodeType === index.NodeType.COMMENT_NODE)
|
|
43552
42047
|
return [];
|
|
43553
42048
|
else if (node.nodeType === index.NodeType.TEXT_NODE)
|
|
43554
42049
|
return [];
|
|
43555
42050
|
else if (node.tagName === 'g') {
|
|
43556
|
-
return parseGroupNode(node, inherited,
|
|
42051
|
+
return parseGroupNode(node, inherited, matrix, clipSpaces);
|
|
43557
42052
|
}
|
|
43558
42053
|
else if (node.tagName === 'svg') {
|
|
43559
|
-
return parseSvgNode(node, inherited,
|
|
42054
|
+
return parseSvgNode(node, inherited, matrix, clipSpaces);
|
|
43560
42055
|
}
|
|
43561
42056
|
else {
|
|
43562
42057
|
if (node.tagName === 'polygon') {
|
|
@@ -43564,36 +42059,69 @@ end\
|
|
|
43564
42059
|
node.attributes.d = `M${node.attributes.points}Z`;
|
|
43565
42060
|
delete node.attributes.points;
|
|
43566
42061
|
}
|
|
43567
|
-
const attributes = parseAttributes(node, inherited,
|
|
43568
|
-
const svgAttributes =
|
|
42062
|
+
const attributes = parseAttributes(node, inherited, matrix);
|
|
42063
|
+
const svgAttributes = {
|
|
42064
|
+
...attributes.inherited,
|
|
42065
|
+
...attributes.svgAttributes,
|
|
42066
|
+
matrix: attributes.matrix,
|
|
42067
|
+
clipSpaces
|
|
42068
|
+
};
|
|
43569
42069
|
Object.assign(node, { svgAttributes });
|
|
43570
42070
|
return [node];
|
|
43571
42071
|
}
|
|
43572
42072
|
};
|
|
43573
|
-
const parseSvgNode = (node, inherited,
|
|
42073
|
+
const parseSvgNode = (node, inherited, matrix, clipSpaces) => {
|
|
43574
42074
|
var _a, _b;
|
|
43575
42075
|
// if the width/height aren't set, the svg will have the same dimension as the current drawing space
|
|
43576
42076
|
(_a = node.attributes.width) !== null && _a !== void 0 ? _a : node.setAttribute('width', inherited.viewBox.width + '');
|
|
43577
42077
|
(_b = node.attributes.height) !== null && _b !== void 0 ? _b : node.setAttribute('height', inherited.viewBox.height + '');
|
|
43578
|
-
const attributes = parseAttributes(node, inherited,
|
|
42078
|
+
const attributes = parseAttributes(node, inherited, matrix);
|
|
43579
42079
|
const result = [];
|
|
43580
42080
|
const viewBox = node.attributes.viewBox
|
|
43581
42081
|
? parseViewBox(node.attributes.viewBox)
|
|
43582
42082
|
: node.attributes.width && node.attributes.height
|
|
43583
42083
|
? parseViewBox(`0 0 ${node.attributes.width} ${node.attributes.height}`)
|
|
43584
42084
|
: inherited.viewBox;
|
|
43585
|
-
const
|
|
42085
|
+
const x = parseFloat(node.attributes.x) || 0;
|
|
42086
|
+
const y = parseFloat(node.attributes.y) || 0;
|
|
42087
|
+
let newMatrix = combineTransformation(matrix, 'translate', [x, y]);
|
|
42088
|
+
const { clipBox: clipBoxTransform, content: contentTransform } = getAspectRatioTransformation(newMatrix, viewBox.width, viewBox.height, parseFloat(node.attributes.width), parseFloat(node.attributes.height), node.attributes.preserveAspectRatio || 'xMidYMid');
|
|
42089
|
+
const topLeft = applyTransformation(clipBoxTransform, {
|
|
42090
|
+
x: 0,
|
|
42091
|
+
y: 0,
|
|
42092
|
+
});
|
|
42093
|
+
const topRight = applyTransformation(clipBoxTransform, {
|
|
42094
|
+
x: viewBox.width,
|
|
42095
|
+
y: 0,
|
|
42096
|
+
});
|
|
42097
|
+
const bottomRight = applyTransformation(clipBoxTransform, {
|
|
42098
|
+
x: viewBox.width,
|
|
42099
|
+
y: -viewBox.height,
|
|
42100
|
+
});
|
|
42101
|
+
const bottomLeft = applyTransformation(clipBoxTransform, {
|
|
42102
|
+
x: 0,
|
|
42103
|
+
y: -viewBox.height,
|
|
42104
|
+
});
|
|
42105
|
+
const baseClipSpace = {
|
|
42106
|
+
topLeft,
|
|
42107
|
+
topRight,
|
|
42108
|
+
bottomRight,
|
|
42109
|
+
bottomLeft
|
|
42110
|
+
};
|
|
42111
|
+
// TODO: maybe this is the correct transformation
|
|
42112
|
+
// newMatrix = combineTransformation(newMatrix, 'translate', [-baseClipSpace.xMin, -baseClipSpace.yMin])
|
|
42113
|
+
newMatrix = combineTransformation(contentTransform, 'translate', [-viewBox.x, -viewBox.y]);
|
|
43586
42114
|
node.childNodes.forEach((child) => {
|
|
43587
|
-
const parsedNodes = parseHTMLNode(child,
|
|
42115
|
+
const parsedNodes = parseHTMLNode(child, { ...attributes.inherited, viewBox }, newMatrix, [...clipSpaces, baseClipSpace]);
|
|
43588
42116
|
result.push(...parsedNodes);
|
|
43589
42117
|
});
|
|
43590
42118
|
return result;
|
|
43591
42119
|
};
|
|
43592
|
-
const parseGroupNode = (node, inherited,
|
|
43593
|
-
const attributes = parseAttributes(node, inherited,
|
|
42120
|
+
const parseGroupNode = (node, inherited, matrix, clipSpaces) => {
|
|
42121
|
+
const attributes = parseAttributes(node, inherited, matrix);
|
|
43594
42122
|
const result = [];
|
|
43595
42123
|
node.childNodes.forEach((child) => {
|
|
43596
|
-
result.push(...parseHTMLNode(child, attributes.inherited, attributes.
|
|
42124
|
+
result.push(...parseHTMLNode(child, attributes.inherited, attributes.matrix, clipSpaces));
|
|
43597
42125
|
});
|
|
43598
42126
|
return result;
|
|
43599
42127
|
};
|
|
@@ -43620,22 +42148,21 @@ end\
|
|
|
43620
42148
|
height: heightViewBox,
|
|
43621
42149
|
};
|
|
43622
42150
|
};
|
|
43623
|
-
const parse$1 = (svg, { width, height,
|
|
42151
|
+
const parse$1 = (svg, { width, height, fontSize }, size, matrix) => {
|
|
43624
42152
|
const htmlElement = index.parse(svg).firstChild;
|
|
43625
42153
|
if (width)
|
|
43626
42154
|
htmlElement.setAttribute('width', width + '');
|
|
43627
42155
|
if (height)
|
|
43628
42156
|
htmlElement.setAttribute('height', height + '');
|
|
43629
|
-
if (x !== undefined)
|
|
43630
|
-
htmlElement.setAttribute('x', x + '');
|
|
43631
|
-
if (y !== undefined)
|
|
43632
|
-
htmlElement.setAttribute('y', size.height - y + '');
|
|
43633
42157
|
if (fontSize)
|
|
43634
42158
|
htmlElement.setAttribute('font-size', fontSize + '');
|
|
43635
42159
|
// TODO: what should be the default viewBox?
|
|
43636
|
-
return parseHTMLNode(htmlElement,
|
|
42160
|
+
return parseHTMLNode(htmlElement, {
|
|
42161
|
+
...size,
|
|
42162
|
+
viewBox: parseViewBox(htmlElement.attributes.viewBox || '0 0 1 1'),
|
|
42163
|
+
}, matrix, []);
|
|
43637
42164
|
};
|
|
43638
|
-
const drawSvg = (page, svg, options) =>
|
|
42165
|
+
const drawSvg = async (page, svg, options) => {
|
|
43639
42166
|
if (!svg)
|
|
43640
42167
|
return;
|
|
43641
42168
|
const size = page.getSize();
|
|
@@ -43660,19 +42187,42 @@ end\
|
|
|
43660
42187
|
.map(([key, val]) => `${key}:${val};`)
|
|
43661
42188
|
.join(''));
|
|
43662
42189
|
}
|
|
43663
|
-
|
|
43664
|
-
const defaultConverter = {
|
|
43665
|
-
point: (xP, yP) => ({ x: xP, y: size.height - yP }),
|
|
43666
|
-
size: (w, h) => ({ width: w, height: h }),
|
|
43667
|
-
};
|
|
42190
|
+
const baseTransformation = [1, 0, 0, 1, options.x || 0, options.y || 0];
|
|
43668
42191
|
const runners = runnersToPage(page, options);
|
|
43669
|
-
const elements = parse$1(firstChild.outerHTML, options, size,
|
|
43670
|
-
|
|
42192
|
+
const elements = parse$1(firstChild.outerHTML, options, size, baseTransformation);
|
|
42193
|
+
await elements.reduce(async (prev, elt) => {
|
|
43671
42194
|
var _a;
|
|
43672
|
-
|
|
42195
|
+
await prev;
|
|
42196
|
+
// uncomment these lines to draw the clipSpaces
|
|
42197
|
+
// elt.svgAttributes.clipSpaces.forEach(space => {
|
|
42198
|
+
// page.drawLine({
|
|
42199
|
+
// start: space.topLeft,
|
|
42200
|
+
// end: space.topRight,
|
|
42201
|
+
// color: parseColor('#000000')?.rgb,
|
|
42202
|
+
// thickness: 1
|
|
42203
|
+
// })
|
|
42204
|
+
// page.drawLine({
|
|
42205
|
+
// start: space.topRight,
|
|
42206
|
+
// end: space.bottomRight,
|
|
42207
|
+
// color: parseColor('#000000')?.rgb,
|
|
42208
|
+
// thickness: 1
|
|
42209
|
+
// })
|
|
42210
|
+
// page.drawLine({
|
|
42211
|
+
// start: space.bottomRight,
|
|
42212
|
+
// end: space.bottomLeft,
|
|
42213
|
+
// color: parseColor('#000000')?.rgb,
|
|
42214
|
+
// thickness: 1
|
|
42215
|
+
// })
|
|
42216
|
+
// page.drawLine({
|
|
42217
|
+
// start: space.bottomLeft,
|
|
42218
|
+
// end: space.topLeft,
|
|
42219
|
+
// color: parseColor('#000000')?.rgb,
|
|
42220
|
+
// thickness: 1
|
|
42221
|
+
// })
|
|
42222
|
+
// })
|
|
43673
42223
|
return (_a = runners[elt.tagName]) === null || _a === void 0 ? void 0 : _a.call(runners, elt);
|
|
43674
|
-
}
|
|
43675
|
-
}
|
|
42224
|
+
}, Promise.resolve());
|
|
42225
|
+
};
|
|
43676
42226
|
|
|
43677
42227
|
/**
|
|
43678
42228
|
* Represents a single page of a [[PDFDocument]].
|
|
@@ -44529,6 +43079,8 @@ end\
|
|
|
44529
43079
|
y: (_f = options.y) !== null && _f !== void 0 ? _f : this.y,
|
|
44530
43080
|
lineHeight: (_g = options.lineHeight) !== null && _g !== void 0 ? _g : this.lineHeight,
|
|
44531
43081
|
graphicsState: graphicsStateKey,
|
|
43082
|
+
matrix: options.matrix,
|
|
43083
|
+
clipSpaces: options.clipSpaces
|
|
44532
43084
|
}));
|
|
44533
43085
|
if (options.font) {
|
|
44534
43086
|
if (oldFont)
|
|
@@ -44590,6 +43142,8 @@ end\
|
|
|
44590
43142
|
xSkew: (_f = options.xSkew) !== null && _f !== void 0 ? _f : degrees(0),
|
|
44591
43143
|
ySkew: (_g = options.ySkew) !== null && _g !== void 0 ? _g : degrees(0),
|
|
44592
43144
|
graphicsState: graphicsStateKey,
|
|
43145
|
+
matrix: options.matrix,
|
|
43146
|
+
clipSpaces: options.clipSpaces
|
|
44593
43147
|
}));
|
|
44594
43148
|
}
|
|
44595
43149
|
/**
|
|
@@ -44748,6 +43302,8 @@ end\
|
|
|
44748
43302
|
borderLineCap: (_j = options.borderLineCap) !== null && _j !== void 0 ? _j : undefined,
|
|
44749
43303
|
graphicsState: graphicsStateKey,
|
|
44750
43304
|
fillRule: options.fillRule,
|
|
43305
|
+
matrix: options.matrix,
|
|
43306
|
+
clipSpaces: options.clipSpaces
|
|
44751
43307
|
}));
|
|
44752
43308
|
}
|
|
44753
43309
|
/**
|
|
@@ -44801,6 +43357,8 @@ end\
|
|
|
44801
43357
|
dashPhase: (_d = options.dashPhase) !== null && _d !== void 0 ? _d : undefined,
|
|
44802
43358
|
lineCap: (_e = options.lineCap) !== null && _e !== void 0 ? _e : undefined,
|
|
44803
43359
|
graphicsState: graphicsStateKey,
|
|
43360
|
+
matrix: options.matrix,
|
|
43361
|
+
clipSpaces: options.clipSpaces,
|
|
44804
43362
|
}));
|
|
44805
43363
|
}
|
|
44806
43364
|
/**
|
|
@@ -44819,12 +43377,13 @@ end\
|
|
|
44819
43377
|
* color: rgb(0.75, 0.2, 0.2),
|
|
44820
43378
|
* opacity: 0.5,
|
|
44821
43379
|
* borderOpacity: 0.75,
|
|
43380
|
+
* radius: 0.1,
|
|
44822
43381
|
* })
|
|
44823
43382
|
* ```
|
|
44824
43383
|
* @param options The options to be used when drawing the rectangle.
|
|
44825
43384
|
*/
|
|
44826
43385
|
drawRectangle(options = {}) {
|
|
44827
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
43386
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
44828
43387
|
assertOrUndefined(options.x, 'options.x', ['number']);
|
|
44829
43388
|
assertOrUndefined(options.y, 'options.y', ['number']);
|
|
44830
43389
|
assertOrUndefined(options.width, 'options.width', ['number']);
|
|
@@ -44847,6 +43406,7 @@ end\
|
|
|
44847
43406
|
assertIsOneOfOrUndefined(options.borderLineCap, 'options.borderLineCap', exports.LineCapStyle);
|
|
44848
43407
|
assertRangeOrUndefined(options.borderOpacity, 'options.borderOpacity', 0, 1);
|
|
44849
43408
|
assertIsOneOfOrUndefined(options.blendMode, 'options.blendMode', exports.BlendMode);
|
|
43409
|
+
assertOrUndefined(options.radius, 'options.radius', ['number']);
|
|
44850
43410
|
const graphicsStateKey = this.maybeEmbedGraphicsState({
|
|
44851
43411
|
opacity: options.opacity,
|
|
44852
43412
|
borderOpacity: options.borderOpacity,
|
|
@@ -44871,6 +43431,9 @@ end\
|
|
|
44871
43431
|
borderDashPhase: (_m = options.borderDashPhase) !== null && _m !== void 0 ? _m : undefined,
|
|
44872
43432
|
graphicsState: graphicsStateKey,
|
|
44873
43433
|
borderLineCap: (_o = options.borderLineCap) !== null && _o !== void 0 ? _o : undefined,
|
|
43434
|
+
matrix: options.matrix,
|
|
43435
|
+
clipSpaces: options.clipSpaces,
|
|
43436
|
+
radius: (_p = options.radius) !== null && _p !== void 0 ? _p : 0,
|
|
44874
43437
|
}));
|
|
44875
43438
|
}
|
|
44876
43439
|
/**
|
|
@@ -44895,7 +43458,7 @@ end\
|
|
|
44895
43458
|
drawSquare(options = {}) {
|
|
44896
43459
|
const { size } = options;
|
|
44897
43460
|
assertOrUndefined(size, 'size', ['number']);
|
|
44898
|
-
this.drawRectangle(
|
|
43461
|
+
this.drawRectangle({ ...options, width: size, height: size });
|
|
44899
43462
|
}
|
|
44900
43463
|
/**
|
|
44901
43464
|
* Draw an ellipse on this page. For example:
|
|
@@ -44960,6 +43523,8 @@ end\
|
|
|
44960
43523
|
borderDashPhase: (_k = options.borderDashPhase) !== null && _k !== void 0 ? _k : undefined,
|
|
44961
43524
|
borderLineCap: (_l = options.borderLineCap) !== null && _l !== void 0 ? _l : undefined,
|
|
44962
43525
|
graphicsState: graphicsStateKey,
|
|
43526
|
+
matrix: options.matrix,
|
|
43527
|
+
clipSpaces: options.clipSpaces,
|
|
44963
43528
|
}));
|
|
44964
43529
|
}
|
|
44965
43530
|
/**
|
|
@@ -44983,7 +43548,7 @@ end\
|
|
|
44983
43548
|
drawCircle(options = {}) {
|
|
44984
43549
|
const { size = 100 } = options;
|
|
44985
43550
|
assertOrUndefined(size, 'size', ['number']);
|
|
44986
|
-
this.drawEllipse(
|
|
43551
|
+
this.drawEllipse({ ...options, xScale: size, yScale: size });
|
|
44987
43552
|
}
|
|
44988
43553
|
setOrEmbedFont(font) {
|
|
44989
43554
|
const oldFont = this.font;
|
|
@@ -45007,21 +43572,19 @@ end\
|
|
|
45007
43572
|
* @param svg The SVG to be drawn.
|
|
45008
43573
|
* @param options The options to be used when drawing the SVG.
|
|
45009
43574
|
*/
|
|
45010
|
-
drawSvg(svg, options = {}) {
|
|
43575
|
+
async drawSvg(svg, options = {}) {
|
|
45011
43576
|
var _a, _b;
|
|
45012
|
-
|
|
45013
|
-
|
|
45014
|
-
|
|
45015
|
-
|
|
45016
|
-
|
|
45017
|
-
|
|
45018
|
-
|
|
45019
|
-
|
|
45020
|
-
|
|
45021
|
-
|
|
45022
|
-
|
|
45023
|
-
height: options.height,
|
|
45024
|
-
});
|
|
43577
|
+
assertIs(svg, 'svg', ['string']);
|
|
43578
|
+
assertOrUndefined(options.x, 'options.x', ['number']);
|
|
43579
|
+
assertOrUndefined(options.y, 'options.y', ['number']);
|
|
43580
|
+
assertOrUndefined(options.width, 'options.width', ['number']);
|
|
43581
|
+
assertOrUndefined(options.height, 'options.height', ['number']);
|
|
43582
|
+
await drawSvg(this, svg, {
|
|
43583
|
+
x: (_a = options.x) !== null && _a !== void 0 ? _a : this.x,
|
|
43584
|
+
y: (_b = options.y) !== null && _b !== void 0 ? _b : this.y,
|
|
43585
|
+
fonts: options.fonts,
|
|
43586
|
+
width: options.width,
|
|
43587
|
+
height: options.height,
|
|
45025
43588
|
});
|
|
45026
43589
|
}
|
|
45027
43590
|
getFont() {
|