web-doc 0.8.0 → 0.10.0
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/THIRD_PARTY_NOTICES.md +14 -0
- package/dist/adapters/office.js +2 -1
- package/dist/contracts.d.ts +9 -0
- package/dist/edit/ai/tools.js +3 -1
- package/dist/edit/docx/elements.js +19 -1
- package/dist/edit/docx/types.d.ts +8 -0
- package/dist/edit/pdf/engine/cff.d.ts +28 -0
- package/dist/edit/pdf/engine/cff.js +416 -0
- package/dist/edit/pdf/engine/document.d.ts +3 -1
- package/dist/edit/pdf/engine/document.js +69 -4
- package/dist/edit/pdf/engine/elements.d.ts +13 -0
- package/dist/edit/pdf/engine/elements.js +12 -1
- package/dist/edit/pdf/engine/existing-text.js +6 -4
- package/dist/edit/pdf/engine/fonts.js +13 -10
- package/dist/edit/pdf/engine/glyph-names.d.ts +2 -0
- package/dist/edit/pdf/engine/glyph-names.js +163 -0
- package/dist/edit/pdf/engine/handler.js +2 -0
- package/dist/edit/pdf/engine/opentype.d.ts +14 -0
- package/dist/edit/pdf/engine/opentype.js +317 -0
- package/dist/edit/pdf/engine/pages.js +9 -1
- package/dist/edit/pdf/engine/text-font.d.ts +4 -0
- package/dist/edit/pdf/engine/text-font.js +81 -0
- package/dist/edit/pdf/provider.d.ts +3 -1
- package/dist/edit/pdf/provider.js +3 -0
- package/dist/edit/pdf/schemas.js +4 -1
- package/dist/edit/pdf/session.d.ts +2 -1
- package/dist/edit/pdf/session.js +3 -0
- package/dist/edit/pdf/types.d.ts +55 -3
- package/dist/edit/pptx/session.d.ts +7 -2
- package/dist/edit/pptx/session.js +41 -3
- package/dist/fonts/THIRD_PARTY_NOTICES.md +6 -3
- package/dist/fonts/manifest.json +4 -4
- package/dist/fonts/noto-sans-latin-cyrillic.ttf +0 -0
- package/dist/viewport.js +83 -20
- package/dist/worker-protocol.d.ts +1 -1
- package/dist/workers/ooxml-edit-worker.js +15 -1
- package/dist/workers/pdf-edit-worker.js +1176 -197
- package/package.json +1 -1
|
@@ -3661,7 +3661,7 @@ var init_index_browser = __esm({
|
|
|
3661
3661
|
// count: 1
|
|
3662
3662
|
];
|
|
3663
3663
|
generateFuncType(sig, typeSectionBody);
|
|
3664
|
-
var
|
|
3664
|
+
var bytes2 = [
|
|
3665
3665
|
0,
|
|
3666
3666
|
97,
|
|
3667
3667
|
115,
|
|
@@ -3675,9 +3675,9 @@ var init_index_browser = __esm({
|
|
|
3675
3675
|
1
|
|
3676
3676
|
// Type section code
|
|
3677
3677
|
];
|
|
3678
|
-
uleb128Encode(typeSectionBody.length,
|
|
3679
|
-
|
|
3680
|
-
|
|
3678
|
+
uleb128Encode(typeSectionBody.length, bytes2);
|
|
3679
|
+
bytes2.push(...typeSectionBody);
|
|
3680
|
+
bytes2.push(
|
|
3681
3681
|
2,
|
|
3682
3682
|
7,
|
|
3683
3683
|
// import section
|
|
@@ -3699,7 +3699,7 @@ var init_index_browser = __esm({
|
|
|
3699
3699
|
0,
|
|
3700
3700
|
0
|
|
3701
3701
|
);
|
|
3702
|
-
var module = new WebAssembly.Module(new Uint8Array(
|
|
3702
|
+
var module = new WebAssembly.Module(new Uint8Array(bytes2));
|
|
3703
3703
|
var instance = new WebAssembly.Instance(module, { "e": { "f": func } });
|
|
3704
3704
|
var wrappedFunc = instance.exports["f"];
|
|
3705
3705
|
return wrappedFunc;
|
|
@@ -5850,13 +5850,16 @@ var pdfOperationSchemas = Object.freeze({
|
|
|
5850
5850
|
},
|
|
5851
5851
|
["from", "to"]
|
|
5852
5852
|
),
|
|
5853
|
+
// Exactly one of `rotation` (absolute) and `by` (a turn from the current
|
|
5854
|
+
// angle); the handler reports a batch that gives both or neither.
|
|
5853
5855
|
rotatePage: operation(
|
|
5854
5856
|
"rotatePage",
|
|
5855
5857
|
{
|
|
5856
5858
|
pageIndex: { type: "integer", minimum: 0 },
|
|
5857
|
-
rotation: { enum: [0, 90, 180, 270] }
|
|
5859
|
+
rotation: { enum: [0, 90, 180, 270] },
|
|
5860
|
+
by: { enum: [90, 180, 270] }
|
|
5858
5861
|
},
|
|
5859
|
-
["pageIndex"
|
|
5862
|
+
["pageIndex"]
|
|
5860
5863
|
),
|
|
5861
5864
|
insertShape: operation(
|
|
5862
5865
|
"insertShape",
|
|
@@ -6375,15 +6378,15 @@ function readMark(pdfium, object) {
|
|
|
6375
6378
|
for (let index = 0; index < lib.FPDFPageObj_CountMarks(object); index += 1) {
|
|
6376
6379
|
const mark = lib.FPDFPageObj_GetMark(object, index);
|
|
6377
6380
|
const name = pdfium.readWideStringOut(
|
|
6378
|
-
(buffer,
|
|
6381
|
+
(buffer, bytes2, out) => lib.FPDFPageObjMark_GetName(mark, buffer, bytes2, out)
|
|
6379
6382
|
);
|
|
6380
6383
|
if (name !== MARK_NAME) continue;
|
|
6381
6384
|
const raw = pdfium.readWideStringOut(
|
|
6382
|
-
(buffer,
|
|
6385
|
+
(buffer, bytes2, out) => lib.FPDFPageObjMark_GetParamStringValue(
|
|
6383
6386
|
mark,
|
|
6384
6387
|
MARK_PARAM,
|
|
6385
6388
|
buffer,
|
|
6386
|
-
|
|
6389
|
+
bytes2,
|
|
6387
6390
|
out
|
|
6388
6391
|
)
|
|
6389
6392
|
);
|
|
@@ -6532,17 +6535,21 @@ var TABLE_OPERATIONS = Object.freeze([
|
|
|
6532
6535
|
]);
|
|
6533
6536
|
function textOf(pdfium, object, textPage) {
|
|
6534
6537
|
return pdfium.readWideString(
|
|
6535
|
-
(buffer,
|
|
6538
|
+
(buffer, bytes2) => pdfium.lib.FPDFTextObj_GetText(object, textPage, buffer, bytes2)
|
|
6536
6539
|
);
|
|
6537
6540
|
}
|
|
6541
|
+
function textScale(matrix) {
|
|
6542
|
+
const scale = matrix ? Math.hypot(matrix[2], matrix[3]) : 1;
|
|
6543
|
+
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
6544
|
+
}
|
|
6538
6545
|
function textStyle(pdfium, object) {
|
|
6539
6546
|
const { lib } = pdfium;
|
|
6540
6547
|
const font = lib.FPDFTextObj_GetFont(object);
|
|
6541
6548
|
const baseName = pdfium.readUtf8String(
|
|
6542
|
-
(buffer,
|
|
6549
|
+
(buffer, bytes2) => lib.FPDFFont_GetBaseFontName(font, buffer, bytes2)
|
|
6543
6550
|
);
|
|
6544
6551
|
const family = lib.FPDFFont_GetIsEmbedded(font) ? pdfium.readUtf8String(
|
|
6545
|
-
(buffer,
|
|
6552
|
+
(buffer, bytes2) => lib.FPDFFont_GetFamilyName(font, buffer, bytes2)
|
|
6546
6553
|
) || declaredFamily(baseName) : declaredFamily(baseName);
|
|
6547
6554
|
const flags = lib.FPDFFont_GetFlags(font);
|
|
6548
6555
|
const weight = lib.FPDFFont_GetWeight(font);
|
|
@@ -6551,9 +6558,14 @@ function textStyle(pdfium, object) {
|
|
|
6551
6558
|
"float",
|
|
6552
6559
|
([pointer]) => lib.FPDFTextObj_GetFontSize(object, pointer)
|
|
6553
6560
|
)?.[0] ?? 0;
|
|
6561
|
+
const matrix = pdfium.readNumbers(
|
|
6562
|
+
6,
|
|
6563
|
+
"float",
|
|
6564
|
+
([pointer]) => lib.FPDFPageObj_GetMatrix(object, pointer)
|
|
6565
|
+
);
|
|
6554
6566
|
return {
|
|
6555
6567
|
fontFamily: family,
|
|
6556
|
-
fontSize: round(size),
|
|
6568
|
+
fontSize: round(size * textScale(matrix)),
|
|
6557
6569
|
bold: weight >= 600 || (flags & FLAG_FORCE_BOLD) !== 0 || /bold|black|heavy/i.test(baseName),
|
|
6558
6570
|
italic: (flags & FLAG_ITALIC) !== 0 || /italic|oblique/i.test(baseName),
|
|
6559
6571
|
color: fillColor(pdfium, object) ?? "#000000"
|
|
@@ -6897,7 +6909,7 @@ var FontLibrary = class {
|
|
|
6897
6909
|
if (this.#coveringRegistered(request)) return void 0;
|
|
6898
6910
|
if (this.#fallback && this.#covers(this.#fallback, request.text))
|
|
6899
6911
|
return void 0;
|
|
6900
|
-
const bad =
|
|
6912
|
+
const bad = this.#fallback ? this.#firstMissing(this.#fallback, request.text) : firstNonWinAnsi(request.text);
|
|
6901
6913
|
return {
|
|
6902
6914
|
path: "/text",
|
|
6903
6915
|
code: "font-unavailable",
|
|
@@ -6944,8 +6956,8 @@ var FontLibrary = class {
|
|
|
6944
6956
|
for (const handle of handles.values()) pdfium.lib.FPDFFont_Close(handle);
|
|
6945
6957
|
this.#handles.delete(document2);
|
|
6946
6958
|
}
|
|
6947
|
-
covers(
|
|
6948
|
-
return this.#covers(
|
|
6959
|
+
covers(bytes2, text) {
|
|
6960
|
+
return this.#covers(bytes2, text);
|
|
6949
6961
|
}
|
|
6950
6962
|
#coveringRegistered(request) {
|
|
6951
6963
|
const candidates = this.#registered.filter((font) => sameFamily(font.family, request.family)).map((font) => ({ font, bytes: this.#loadedBytes(font) })).filter(
|
|
@@ -6954,33 +6966,37 @@ var FontLibrary = class {
|
|
|
6954
6966
|
const score = (font) => (isBold(font) === request.bold ? 2 : 0) + (isItalic(font) === request.italic ? 1 : 0);
|
|
6955
6967
|
return candidates.sort((a, b) => score(b.font) - score(a.font))[0];
|
|
6956
6968
|
}
|
|
6957
|
-
#covers(
|
|
6958
|
-
|
|
6969
|
+
#covers(bytes2, text) {
|
|
6970
|
+
return this.#firstMissing(bytes2, text) === void 0;
|
|
6971
|
+
}
|
|
6972
|
+
/** The first character of `text` the font has no glyph for; layout handles line breaks and spaces. */
|
|
6973
|
+
#firstMissing(bytes2, text) {
|
|
6974
|
+
let coverage = this.#coverage.get(bytes2);
|
|
6959
6975
|
if (!coverage) {
|
|
6960
|
-
coverage = parseCmap(
|
|
6961
|
-
this.#coverage.set(
|
|
6976
|
+
coverage = parseCmap(bytes2);
|
|
6977
|
+
this.#coverage.set(bytes2, coverage);
|
|
6962
6978
|
}
|
|
6963
6979
|
for (const character of text) {
|
|
6964
6980
|
const code = character.codePointAt(0);
|
|
6965
6981
|
if (code === 10 || code === 32) continue;
|
|
6966
|
-
if (!coverage.has(code)) return
|
|
6982
|
+
if (!coverage.has(code)) return character;
|
|
6967
6983
|
}
|
|
6968
|
-
return
|
|
6984
|
+
return void 0;
|
|
6969
6985
|
}
|
|
6970
|
-
#load(pdfium, document2,
|
|
6986
|
+
#load(pdfium, document2, bytes2) {
|
|
6971
6987
|
let handles = this.#handles.get(document2);
|
|
6972
6988
|
if (!handles) {
|
|
6973
6989
|
handles = /* @__PURE__ */ new Map();
|
|
6974
6990
|
this.#handles.set(document2, handles);
|
|
6975
6991
|
}
|
|
6976
|
-
let handle = handles.get(
|
|
6992
|
+
let handle = handles.get(bytes2);
|
|
6977
6993
|
if (handle === void 0) {
|
|
6978
|
-
const pointer = pdfium.writeBytes(
|
|
6994
|
+
const pointer = pdfium.writeBytes(bytes2);
|
|
6979
6995
|
try {
|
|
6980
6996
|
handle = pdfium.lib.FPDFText_LoadFont(
|
|
6981
6997
|
document2,
|
|
6982
6998
|
pointer,
|
|
6983
|
-
|
|
6999
|
+
bytes2.byteLength,
|
|
6984
7000
|
FONT_TRUETYPE,
|
|
6985
7001
|
true
|
|
6986
7002
|
);
|
|
@@ -6988,7 +7004,7 @@ var FontLibrary = class {
|
|
|
6988
7004
|
pdfium.free(pointer);
|
|
6989
7005
|
}
|
|
6990
7006
|
if (!handle) throw new Error("PDFium could not load the font");
|
|
6991
|
-
handles.set(
|
|
7007
|
+
handles.set(bytes2, handle);
|
|
6992
7008
|
}
|
|
6993
7009
|
return handle;
|
|
6994
7010
|
}
|
|
@@ -6997,12 +7013,12 @@ var FontLibrary = class {
|
|
|
6997
7013
|
}
|
|
6998
7014
|
async #bytesOf(font) {
|
|
6999
7015
|
const key = sourceKey(font);
|
|
7000
|
-
let
|
|
7001
|
-
if (!
|
|
7002
|
-
|
|
7003
|
-
this.#bytes.set(key,
|
|
7016
|
+
let bytes2 = this.#bytes.get(key);
|
|
7017
|
+
if (!bytes2) {
|
|
7018
|
+
bytes2 = typeof font.source === "string" ? await this.#fetch(font.source) : new Uint8Array(font.source);
|
|
7019
|
+
this.#bytes.set(key, bytes2);
|
|
7004
7020
|
}
|
|
7005
|
-
return
|
|
7021
|
+
return bytes2;
|
|
7006
7022
|
}
|
|
7007
7023
|
};
|
|
7008
7024
|
function sourceKey(font) {
|
|
@@ -7017,18 +7033,12 @@ function isBold(font) {
|
|
|
7017
7033
|
function isItalic(font) {
|
|
7018
7034
|
return font.style !== "normal";
|
|
7019
7035
|
}
|
|
7020
|
-
function firstUncovered(text, library) {
|
|
7021
|
-
void library;
|
|
7022
|
-
for (const character of text)
|
|
7023
|
-
if (character !== "\n" && character !== " ") return character;
|
|
7024
|
-
return void 0;
|
|
7025
|
-
}
|
|
7026
7036
|
function glyphOutlines(view, tables) {
|
|
7027
|
-
const
|
|
7037
|
+
const head2 = tables.get("head");
|
|
7028
7038
|
const maxp = tables.get("maxp");
|
|
7029
7039
|
const loca = tables.get("loca");
|
|
7030
|
-
if (!
|
|
7031
|
-
const longOffsets = view.getInt16(
|
|
7040
|
+
if (!head2 || !maxp || !loca || !tables.has("glyf")) return void 0;
|
|
7041
|
+
const longOffsets = view.getInt16(head2.offset + 50) === 1;
|
|
7032
7042
|
const count = view.getUint16(maxp.offset + 4);
|
|
7033
7043
|
return (glyph) => {
|
|
7034
7044
|
if (glyph < 0 || glyph >= count) return false;
|
|
@@ -7038,8 +7048,8 @@ function glyphOutlines(view, tables) {
|
|
|
7038
7048
|
return end > start;
|
|
7039
7049
|
};
|
|
7040
7050
|
}
|
|
7041
|
-
function parseCmap(
|
|
7042
|
-
const view = new DataView(
|
|
7051
|
+
function parseCmap(bytes2) {
|
|
7052
|
+
const view = new DataView(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
7043
7053
|
const ranges = [];
|
|
7044
7054
|
const glyphs = /* @__PURE__ */ new Map();
|
|
7045
7055
|
let outlines;
|
|
@@ -7050,10 +7060,10 @@ function parseCmap(bytes) {
|
|
|
7050
7060
|
for (let index = 0; index < tables; index += 1) {
|
|
7051
7061
|
const record = 12 + index * 16;
|
|
7052
7062
|
const tag = String.fromCharCode(
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7063
|
+
bytes2[record],
|
|
7064
|
+
bytes2[record + 1],
|
|
7065
|
+
bytes2[record + 2],
|
|
7066
|
+
bytes2[record + 3]
|
|
7057
7067
|
);
|
|
7058
7068
|
offsets.set(tag, {
|
|
7059
7069
|
offset: view.getUint32(record + 8),
|
|
@@ -7222,6 +7232,915 @@ var TextMeasurer = class {
|
|
|
7222
7232
|
}
|
|
7223
7233
|
};
|
|
7224
7234
|
|
|
7235
|
+
// src/edit/pdf/engine/glyph-names.ts
|
|
7236
|
+
var AGLFN = `
|
|
7237
|
+
A 0041 AE 00C6 AEacute 01FC Aacute 00C1 Abreve 0102 Acircumflex 00C2
|
|
7238
|
+
Adieresis 00C4 Agrave 00C0 Alpha 0391 Alphatonos 0386 Amacron 0100
|
|
7239
|
+
Aogonek 0104 Aring 00C5 Aringacute 01FA Atilde 00C3 B 0042 Beta 0392 C 0043
|
|
7240
|
+
Cacute 0106 Ccaron 010C Ccedilla 00C7 Ccircumflex 0108 Cdotaccent 010A
|
|
7241
|
+
Chi 03A7 D 0044 Dcaron 010E Dcroat 0110 Delta 2206 E 0045 Eacute 00C9
|
|
7242
|
+
Ebreve 0114 Ecaron 011A Ecircumflex 00CA Edieresis 00CB Edotaccent 0116
|
|
7243
|
+
Egrave 00C8 Emacron 0112 Eng 014A Eogonek 0118 Epsilon 0395
|
|
7244
|
+
Epsilontonos 0388 Eta 0397 Etatonos 0389 Eth 00D0 Euro 20AC F 0046 G 0047
|
|
7245
|
+
Gamma 0393 Gbreve 011E Gcaron 01E6 Gcircumflex 011C Gdotaccent 0120 H 0048
|
|
7246
|
+
H18533 25CF H18543 25AA H18551 25AB H22073 25A1 Hbar 0126 Hcircumflex 0124
|
|
7247
|
+
I 0049 IJ 0132 Iacute 00CD Ibreve 012C Icircumflex 00CE Idieresis 00CF
|
|
7248
|
+
Idotaccent 0130 Ifraktur 2111 Igrave 00CC Imacron 012A Iogonek 012E
|
|
7249
|
+
Iota 0399 Iotadieresis 03AA Iotatonos 038A Itilde 0128 J 004A
|
|
7250
|
+
Jcircumflex 0134 K 004B Kappa 039A L 004C Lacute 0139 Lambda 039B
|
|
7251
|
+
Lcaron 013D Ldot 013F Lslash 0141 M 004D Mu 039C N 004E Nacute 0143
|
|
7252
|
+
Ncaron 0147 Ntilde 00D1 Nu 039D O 004F OE 0152 Oacute 00D3 Obreve 014E
|
|
7253
|
+
Ocircumflex 00D4 Odieresis 00D6 Ograve 00D2 Ohorn 01A0 Ohungarumlaut 0150
|
|
7254
|
+
Omacron 014C Omega 2126 Omegatonos 038F Omicron 039F Omicrontonos 038C
|
|
7255
|
+
Oslash 00D8 Oslashacute 01FE Otilde 00D5 P 0050 Phi 03A6 Pi 03A0 Psi 03A8
|
|
7256
|
+
Q 0051 R 0052 Racute 0154 Rcaron 0158 Rfraktur 211C Rho 03A1 S 0053
|
|
7257
|
+
SF010000 250C SF020000 2514 SF030000 2510 SF040000 2518 SF050000 253C
|
|
7258
|
+
SF060000 252C SF070000 2534 SF080000 251C SF090000 2524 SF100000 2500
|
|
7259
|
+
SF110000 2502 SF190000 2561 SF200000 2562 SF210000 2556 SF220000 2555
|
|
7260
|
+
SF230000 2563 SF240000 2551 SF250000 2557 SF260000 255D SF270000 255C
|
|
7261
|
+
SF280000 255B SF360000 255E SF370000 255F SF380000 255A SF390000 2554
|
|
7262
|
+
SF400000 2569 SF410000 2566 SF420000 2560 SF430000 2550 SF440000 256C
|
|
7263
|
+
SF450000 2567 SF460000 2568 SF470000 2564 SF480000 2565 SF490000 2559
|
|
7264
|
+
SF500000 2558 SF510000 2552 SF520000 2553 SF530000 256B SF540000 256A
|
|
7265
|
+
Sacute 015A Scaron 0160 Scedilla 015E Scircumflex 015C Sigma 03A3 T 0054
|
|
7266
|
+
Tau 03A4 Tbar 0166 Tcaron 0164 Theta 0398 Thorn 00DE U 0055 Uacute 00DA
|
|
7267
|
+
Ubreve 016C Ucircumflex 00DB Udieresis 00DC Ugrave 00D9 Uhorn 01AF
|
|
7268
|
+
Uhungarumlaut 0170 Umacron 016A Uogonek 0172 Upsilon 03A5 Upsilon1 03D2
|
|
7269
|
+
Upsilondieresis 03AB Upsilontonos 038E Uring 016E Utilde 0168 V 0056 W 0057
|
|
7270
|
+
Wacute 1E82 Wcircumflex 0174 Wdieresis 1E84 Wgrave 1E80 X 0058 Xi 039E
|
|
7271
|
+
Y 0059 Yacute 00DD Ycircumflex 0176 Ydieresis 0178 Ygrave 1EF2 Z 005A
|
|
7272
|
+
Zacute 0179 Zcaron 017D Zdotaccent 017B Zeta 0396 a 0061 aacute 00E1
|
|
7273
|
+
abreve 0103 acircumflex 00E2 acute 00B4 acutecomb 0301 adieresis 00E4
|
|
7274
|
+
ae 00E6 aeacute 01FD agrave 00E0 aleph 2135 alpha 03B1 alphatonos 03AC
|
|
7275
|
+
amacron 0101 ampersand 0026 angle 2220 angleleft 2329 angleright 232A
|
|
7276
|
+
anoteleia 0387 aogonek 0105 approxequal 2248 aring 00E5 aringacute 01FB
|
|
7277
|
+
arrowboth 2194 arrowdblboth 21D4 arrowdbldown 21D3 arrowdblleft 21D0
|
|
7278
|
+
arrowdblright 21D2 arrowdblup 21D1 arrowdown 2193 arrowleft 2190
|
|
7279
|
+
arrowright 2192 arrowup 2191 arrowupdn 2195 arrowupdnbse 21A8
|
|
7280
|
+
asciicircum 005E asciitilde 007E asterisk 002A asteriskmath 2217 at 0040
|
|
7281
|
+
atilde 00E3 b 0062 backslash 005C bar 007C beta 03B2 block 2588
|
|
7282
|
+
braceleft 007B braceright 007D bracketleft 005B bracketright 005D breve 02D8
|
|
7283
|
+
brokenbar 00A6 bullet 2022 c 0063 cacute 0107 caron 02C7 carriagereturn 21B5
|
|
7284
|
+
ccaron 010D ccedilla 00E7 ccircumflex 0109 cdotaccent 010B cedilla 00B8
|
|
7285
|
+
cent 00A2 chi 03C7 circle 25CB circlemultiply 2297 circleplus 2295
|
|
7286
|
+
circumflex 02C6 club 2663 colon 003A colonmonetary 20A1 comma 002C
|
|
7287
|
+
congruent 2245 copyright 00A9 currency 00A4 d 0064 dagger 2020
|
|
7288
|
+
daggerdbl 2021 dcaron 010F dcroat 0111 degree 00B0 delta 03B4 diamond 2666
|
|
7289
|
+
dieresis 00A8 dieresistonos 0385 divide 00F7 dkshade 2593 dnblock 2584
|
|
7290
|
+
dollar 0024 dong 20AB dotaccent 02D9 dotbelowcomb 0323 dotlessi 0131
|
|
7291
|
+
dotmath 22C5 e 0065 eacute 00E9 ebreve 0115 ecaron 011B ecircumflex 00EA
|
|
7292
|
+
edieresis 00EB edotaccent 0117 egrave 00E8 eight 0038 element 2208
|
|
7293
|
+
ellipsis 2026 emacron 0113 emdash 2014 emptyset 2205 endash 2013 eng 014B
|
|
7294
|
+
eogonek 0119 epsilon 03B5 epsilontonos 03AD equal 003D equivalence 2261
|
|
7295
|
+
estimated 212E eta 03B7 etatonos 03AE eth 00F0 exclam 0021 exclamdbl 203C
|
|
7296
|
+
exclamdown 00A1 existential 2203 f 0066 female 2640 figuredash 2012
|
|
7297
|
+
filledbox 25A0 filledrect 25AC five 0035 fiveeighths 215D florin 0192
|
|
7298
|
+
four 0034 fraction 2044 franc 20A3 g 0067 gamma 03B3 gbreve 011F gcaron 01E7
|
|
7299
|
+
gcircumflex 011D gdotaccent 0121 germandbls 00DF gradient 2207 grave 0060
|
|
7300
|
+
gravecomb 0300 greater 003E greaterequal 2265 guillemotleft 00AB
|
|
7301
|
+
guillemotright 00BB guilsinglleft 2039 guilsinglright 203A h 0068 hbar 0127
|
|
7302
|
+
hcircumflex 0125 heart 2665 hookabovecomb 0309 house 2302 hungarumlaut 02DD
|
|
7303
|
+
hyphen 002D i 0069 iacute 00ED ibreve 012D icircumflex 00EE idieresis 00EF
|
|
7304
|
+
igrave 00EC ij 0133 imacron 012B infinity 221E integral 222B integralbt 2321
|
|
7305
|
+
integraltp 2320 intersection 2229 invbullet 25D8 invcircle 25D9
|
|
7306
|
+
invsmileface 263B iogonek 012F iota 03B9 iotadieresis 03CA
|
|
7307
|
+
iotadieresistonos 0390 iotatonos 03AF itilde 0129 j 006A jcircumflex 0135
|
|
7308
|
+
k 006B kappa 03BA kgreenlandic 0138 l 006C lacute 013A lambda 03BB
|
|
7309
|
+
lcaron 013E ldot 0140 less 003C lessequal 2264 lfblock 258C lira 20A4
|
|
7310
|
+
logicaland 2227 logicalnot 00AC logicalor 2228 longs 017F lozenge 25CA
|
|
7311
|
+
lslash 0142 ltshade 2591 m 006D macron 00AF male 2642 minus 2212 minute 2032
|
|
7312
|
+
mu 00B5 multiply 00D7 musicalnote 266A musicalnotedbl 266B n 006E
|
|
7313
|
+
nacute 0144 napostrophe 0149 ncaron 0148 nine 0039 notelement 2209
|
|
7314
|
+
notequal 2260 notsubset 2284 ntilde 00F1 nu 03BD numbersign 0023 o 006F
|
|
7315
|
+
oacute 00F3 obreve 014F ocircumflex 00F4 odieresis 00F6 oe 0153 ogonek 02DB
|
|
7316
|
+
ograve 00F2 ohorn 01A1 ohungarumlaut 0151 omacron 014D omega 03C9
|
|
7317
|
+
omega1 03D6 omegatonos 03CE omicron 03BF omicrontonos 03CC one 0031
|
|
7318
|
+
onedotenleader 2024 oneeighth 215B onehalf 00BD onequarter 00BC
|
|
7319
|
+
onethird 2153 openbullet 25E6 ordfeminine 00AA ordmasculine 00BA
|
|
7320
|
+
orthogonal 221F oslash 00F8 oslashacute 01FF otilde 00F5 p 0070
|
|
7321
|
+
paragraph 00B6 parenleft 0028 parenright 0029 partialdiff 2202 percent 0025
|
|
7322
|
+
period 002E periodcentered 00B7 perpendicular 22A5 perthousand 2030
|
|
7323
|
+
peseta 20A7 phi 03C6 phi1 03D5 pi 03C0 plus 002B plusminus 00B1
|
|
7324
|
+
prescription 211E product 220F propersubset 2282 propersuperset 2283
|
|
7325
|
+
proportional 221D psi 03C8 q 0071 question 003F questiondown 00BF
|
|
7326
|
+
quotedbl 0022 quotedblbase 201E quotedblleft 201C quotedblright 201D
|
|
7327
|
+
quoteleft 2018 quotereversed 201B quoteright 2019 quotesinglbase 201A
|
|
7328
|
+
quotesingle 0027 r 0072 racute 0155 radical 221A rcaron 0159
|
|
7329
|
+
reflexsubset 2286 reflexsuperset 2287 registered 00AE revlogicalnot 2310
|
|
7330
|
+
rho 03C1 ring 02DA rtblock 2590 s 0073 sacute 015B scaron 0161 scedilla 015F
|
|
7331
|
+
scircumflex 015D second 2033 section 00A7 semicolon 003B seven 0037
|
|
7332
|
+
seveneighths 215E shade 2592 sigma 03C3 sigma1 03C2 similar 223C six 0036
|
|
7333
|
+
slash 002F smileface 263A space 0020 spade 2660 sterling 00A3 suchthat 220B
|
|
7334
|
+
summation 2211 sun 263C t 0074 tau 03C4 tbar 0167 tcaron 0165 therefore 2234
|
|
7335
|
+
theta 03B8 theta1 03D1 thorn 00FE three 0033 threeeighths 215C
|
|
7336
|
+
threequarters 00BE tilde 02DC tildecomb 0303 tonos 0384 trademark 2122
|
|
7337
|
+
triagdn 25BC triaglf 25C4 triagrt 25BA triagup 25B2 two 0032
|
|
7338
|
+
twodotenleader 2025 twothirds 2154 u 0075 uacute 00FA ubreve 016D
|
|
7339
|
+
ucircumflex 00FB udieresis 00FC ugrave 00F9 uhorn 01B0 uhungarumlaut 0171
|
|
7340
|
+
umacron 016B underscore 005F underscoredbl 2017 union 222A universal 2200
|
|
7341
|
+
uogonek 0173 upblock 2580 upsilon 03C5 upsilondieresis 03CB
|
|
7342
|
+
upsilondieresistonos 03B0 upsilontonos 03CD uring 016F utilde 0169 v 0076
|
|
7343
|
+
w 0077 wacute 1E83 wcircumflex 0175 wdieresis 1E85 weierstrass 2118
|
|
7344
|
+
wgrave 1E81 x 0078 xi 03BE y 0079 yacute 00FD ycircumflex 0177
|
|
7345
|
+
ydieresis 00FF yen 00A5 ygrave 1EF3 z 007A zacute 017A zcaron 017E
|
|
7346
|
+
zdotaccent 017C zero 0030 zeta 03B6
|
|
7347
|
+
`;
|
|
7348
|
+
var AGL_EXTRAS = `
|
|
7349
|
+
fi FB01 fl FB02 ff FB00 ffi FB03 ffl FB04 onesuperior 00B9 twosuperior 00B2
|
|
7350
|
+
threesuperior 00B3 nbspace 00A0
|
|
7351
|
+
`;
|
|
7352
|
+
var GLYPH_UNICODE = new Map(
|
|
7353
|
+
`${AGLFN} ${AGL_EXTRAS}`.trim().split(/\s+/).flatMap(
|
|
7354
|
+
(word, index, words) => index % 2 === 0 ? [[word, Number.parseInt(words[index + 1], 16)]] : []
|
|
7355
|
+
)
|
|
7356
|
+
);
|
|
7357
|
+
|
|
7358
|
+
// src/edit/pdf/engine/cff.ts
|
|
7359
|
+
var ISO_ADOBE_NAMES = `
|
|
7360
|
+
.notdef space exclam quotedbl numbersign dollar percent ampersand
|
|
7361
|
+
quoteright parenleft parenright asterisk plus comma hyphen period slash
|
|
7362
|
+
zero one two three four five six seven eight nine colon semicolon less
|
|
7363
|
+
equal greater question at A B C D E F G H I J K L M N O P Q R S T U V W X Y
|
|
7364
|
+
Z bracketleft backslash bracketright asciicircum underscore quoteleft a b c
|
|
7365
|
+
d e f g h i j k l m n o p q r s t u v w x y z braceleft bar braceright
|
|
7366
|
+
asciitilde exclamdown cent sterling fraction yen florin section currency
|
|
7367
|
+
quotesingle quotedblleft guillemotleft guilsinglleft guilsinglright fi fl
|
|
7368
|
+
endash dagger daggerdbl periodcentered paragraph bullet quotesinglbase
|
|
7369
|
+
quotedblbase quotedblright guillemotright ellipsis perthousand questiondown
|
|
7370
|
+
grave acute circumflex tilde macron breve dotaccent dieresis ring cedilla
|
|
7371
|
+
hungarumlaut ogonek caron emdash AE ordfeminine Lslash Oslash OE
|
|
7372
|
+
ordmasculine ae dotlessi lslash oslash oe germandbls onesuperior logicalnot
|
|
7373
|
+
mu trademark Eth onehalf plusminus Thorn onequarter divide brokenbar degree
|
|
7374
|
+
thorn threequarters twosuperior registered minus eth multiply threesuperior
|
|
7375
|
+
copyright Aacute Acircumflex Adieresis Agrave Aring Atilde Ccedilla Eacute
|
|
7376
|
+
Ecircumflex Edieresis Egrave Iacute Icircumflex Idieresis Igrave Ntilde
|
|
7377
|
+
Oacute Ocircumflex Odieresis Ograve Otilde Scaron Uacute Ucircumflex
|
|
7378
|
+
Udieresis Ugrave Yacute Ydieresis Zcaron aacute acircumflex adieresis
|
|
7379
|
+
agrave aring atilde ccedilla eacute ecircumflex edieresis egrave iacute
|
|
7380
|
+
icircumflex idieresis igrave ntilde oacute ocircumflex odieresis ograve
|
|
7381
|
+
otilde scaron uacute ucircumflex udieresis ugrave yacute ydieresis zcaron
|
|
7382
|
+
`.trim().split(/\s+/);
|
|
7383
|
+
function glyphUnicode(name) {
|
|
7384
|
+
if (!name || name === ".notdef") return void 0;
|
|
7385
|
+
const known = GLYPH_UNICODE.get(name);
|
|
7386
|
+
if (known !== void 0) return known;
|
|
7387
|
+
const match = /^uni([0-9A-F]{4})$|^u([0-9A-F]{4,6})$/.exec(name);
|
|
7388
|
+
const hex2 = match?.[1] ?? match?.[2];
|
|
7389
|
+
if (!hex2) return void 0;
|
|
7390
|
+
const code = Number.parseInt(hex2, 16);
|
|
7391
|
+
const surrogate = code >= 55296 && code <= 57343;
|
|
7392
|
+
const nonCharacter = (code & 65534) === 65534;
|
|
7393
|
+
return code <= 1114111 && !surrogate && !nonCharacter ? code : void 0;
|
|
7394
|
+
}
|
|
7395
|
+
var OP = {
|
|
7396
|
+
fontBBox: 5,
|
|
7397
|
+
charset: 15,
|
|
7398
|
+
charStrings: 17,
|
|
7399
|
+
private: 18,
|
|
7400
|
+
defaultWidthX: 20,
|
|
7401
|
+
nominalWidthX: 21,
|
|
7402
|
+
subrs: 19,
|
|
7403
|
+
charstringType: 1206,
|
|
7404
|
+
fontMatrix: 1207,
|
|
7405
|
+
ros: 1230
|
|
7406
|
+
};
|
|
7407
|
+
var STANDARD_STRINGS = 391;
|
|
7408
|
+
function readCff(bytes2) {
|
|
7409
|
+
try {
|
|
7410
|
+
const at = (offset2) => {
|
|
7411
|
+
if (!Number.isInteger(offset2) || offset2 < 0 || offset2 >= bytes2.length)
|
|
7412
|
+
throw new RangeError("Outside the font");
|
|
7413
|
+
return bytes2[offset2];
|
|
7414
|
+
};
|
|
7415
|
+
const u162 = (offset2) => at(offset2) << 8 | at(offset2 + 1);
|
|
7416
|
+
if (at(0) !== 1) return void 0;
|
|
7417
|
+
const names2 = readIndex(bytes2, at(2), at, u162);
|
|
7418
|
+
const tops = readIndex(bytes2, names2.end, at, u162);
|
|
7419
|
+
const strings = readIndex(bytes2, tops.end, at, u162);
|
|
7420
|
+
const globalSubrs = readIndex(bytes2, strings.end, at, u162);
|
|
7421
|
+
if (names2.items.length !== 1 || tops.items.length !== 1) return void 0;
|
|
7422
|
+
const top = readDict(bytes2, ...tops.items[0], at);
|
|
7423
|
+
const charStringsAt = top.get(OP.charStrings)?.[0];
|
|
7424
|
+
if (charStringsAt === void 0) return void 0;
|
|
7425
|
+
if ((top.get(OP.charstringType)?.[0] ?? 2) !== 2) return void 0;
|
|
7426
|
+
const charStrings = readIndex(bytes2, charStringsAt, at, u162);
|
|
7427
|
+
const glyphCount = charStrings.items.length;
|
|
7428
|
+
if (glyphCount === 0) return void 0;
|
|
7429
|
+
const [scale = 1e-3, skewX = 0, skewY = 0, scaleY = 1e-3] = top.get(OP.fontMatrix) ?? [];
|
|
7430
|
+
if (skewX !== 0 || skewY !== 0 || scale !== scaleY || scale <= 0)
|
|
7431
|
+
return void 0;
|
|
7432
|
+
const unitsPerEm = Math.round(1 / scale);
|
|
7433
|
+
if (unitsPerEm < 16 || unitsPerEm > 16384) return void 0;
|
|
7434
|
+
const [xMin = 0, yMin = 0, xMax = 0, yMax = 0] = top.get(OP.fontBBox) ?? [];
|
|
7435
|
+
const cid = top.has(OP.ros);
|
|
7436
|
+
const [nameStart, nameEnd] = names2.items[0];
|
|
7437
|
+
const name = latin1(
|
|
7438
|
+
bytes2.subarray(nameStart, Math.min(nameEnd, nameStart + 127))
|
|
7439
|
+
);
|
|
7440
|
+
if (cid)
|
|
7441
|
+
return {
|
|
7442
|
+
name,
|
|
7443
|
+
cid,
|
|
7444
|
+
glyphNames: [],
|
|
7445
|
+
widths: [],
|
|
7446
|
+
bbox: [xMin, yMin, xMax, yMax],
|
|
7447
|
+
unitsPerEm
|
|
7448
|
+
};
|
|
7449
|
+
const custom = /* @__PURE__ */ new Map();
|
|
7450
|
+
const stringOf = (sid) => {
|
|
7451
|
+
if (sid < ISO_ADOBE_NAMES.length) return ISO_ADOBE_NAMES[sid];
|
|
7452
|
+
const item = strings.items[sid - STANDARD_STRINGS];
|
|
7453
|
+
if (!item) return void 0;
|
|
7454
|
+
if (!custom.has(sid))
|
|
7455
|
+
custom.set(
|
|
7456
|
+
sid,
|
|
7457
|
+
// A glyph name is 63 characters at most.
|
|
7458
|
+
item[1] - item[0] <= 63 ? latin1(bytes2.subarray(...item)) : void 0
|
|
7459
|
+
);
|
|
7460
|
+
return custom.get(sid);
|
|
7461
|
+
};
|
|
7462
|
+
const glyphNames = charsetNames(
|
|
7463
|
+
top.get(OP.charset)?.[0] ?? 0,
|
|
7464
|
+
glyphCount,
|
|
7465
|
+
stringOf,
|
|
7466
|
+
at,
|
|
7467
|
+
u162
|
|
7468
|
+
);
|
|
7469
|
+
const [privateSize, privateAt] = top.get(OP.private) ?? [0, 0];
|
|
7470
|
+
const privateDict = privateSize ? readDict(bytes2, privateAt, privateAt + privateSize, at) : /* @__PURE__ */ new Map();
|
|
7471
|
+
const localAt = privateDict.get(OP.subrs)?.[0];
|
|
7472
|
+
const metrics = {
|
|
7473
|
+
bytes: bytes2,
|
|
7474
|
+
defaultWidth: privateDict.get(OP.defaultWidthX)?.[0] ?? 0,
|
|
7475
|
+
nominalWidth: privateDict.get(OP.nominalWidthX)?.[0] ?? 0,
|
|
7476
|
+
global: globalSubrs.items,
|
|
7477
|
+
local: localAt === void 0 ? [] : readIndex(bytes2, privateAt + localAt, at, u162).items
|
|
7478
|
+
};
|
|
7479
|
+
const widths = charStrings.items.map(
|
|
7480
|
+
([start, end]) => charstringWidth(metrics, start, end)
|
|
7481
|
+
);
|
|
7482
|
+
return {
|
|
7483
|
+
name,
|
|
7484
|
+
cid,
|
|
7485
|
+
glyphNames,
|
|
7486
|
+
widths,
|
|
7487
|
+
bbox: [xMin, yMin, xMax, yMax],
|
|
7488
|
+
unitsPerEm
|
|
7489
|
+
};
|
|
7490
|
+
} catch (error) {
|
|
7491
|
+
if (error instanceof RangeError) return void 0;
|
|
7492
|
+
throw error;
|
|
7493
|
+
}
|
|
7494
|
+
}
|
|
7495
|
+
function cffWithSafeName(bytes2) {
|
|
7496
|
+
try {
|
|
7497
|
+
const at = (offset2) => {
|
|
7498
|
+
if (offset2 < 0 || offset2 >= bytes2.length)
|
|
7499
|
+
throw new RangeError("Outside the font");
|
|
7500
|
+
return bytes2[offset2];
|
|
7501
|
+
};
|
|
7502
|
+
const u162 = (offset2) => at(offset2) << 8 | at(offset2 + 1);
|
|
7503
|
+
const names2 = readIndex(bytes2, at(2), at, u162);
|
|
7504
|
+
const [start, end] = names2.items[0] ?? [0, 0];
|
|
7505
|
+
if (names2.items.length !== 1 || end - start > 127) return void 0;
|
|
7506
|
+
const safe = bytes2.slice();
|
|
7507
|
+
for (let offset2 = start; offset2 < end; offset2 += 1) {
|
|
7508
|
+
const byte = safe[offset2];
|
|
7509
|
+
if (offset2 === start && byte === 0) continue;
|
|
7510
|
+
if (byte < 33 || byte > 126 || UNSAFE_NAME_BYTES.has(byte))
|
|
7511
|
+
safe[offset2] = 95;
|
|
7512
|
+
}
|
|
7513
|
+
return safe;
|
|
7514
|
+
} catch (error) {
|
|
7515
|
+
if (error instanceof RangeError) return void 0;
|
|
7516
|
+
throw error;
|
|
7517
|
+
}
|
|
7518
|
+
}
|
|
7519
|
+
var UNSAFE_NAME_BYTES = new Set(
|
|
7520
|
+
[..."[](){}<>/%"].map((character) => character.charCodeAt(0))
|
|
7521
|
+
);
|
|
7522
|
+
function readIndex(bytes2, start, at, u162) {
|
|
7523
|
+
const count = u162(start);
|
|
7524
|
+
if (count === 0) return { items: [], end: start + 2 };
|
|
7525
|
+
const offSize = at(start + 2);
|
|
7526
|
+
if (offSize < 1 || offSize > 4) throw new RangeError("Bad offset size");
|
|
7527
|
+
const offset2 = (index) => {
|
|
7528
|
+
let value = 0;
|
|
7529
|
+
for (let byte = 0; byte < offSize; byte += 1)
|
|
7530
|
+
value = value * 256 + at(start + 3 + index * offSize + byte);
|
|
7531
|
+
return value;
|
|
7532
|
+
};
|
|
7533
|
+
if (offset2(0) !== 1) throw new RangeError("Bad INDEX");
|
|
7534
|
+
const base = start + 2 + (count + 1) * offSize;
|
|
7535
|
+
const items = [];
|
|
7536
|
+
for (let index = 0; index < count; index += 1) {
|
|
7537
|
+
const from = base + offset2(index);
|
|
7538
|
+
const to = base + offset2(index + 1);
|
|
7539
|
+
if (to < from || to > bytes2.length) throw new RangeError("Bad INDEX");
|
|
7540
|
+
items.push([from, to]);
|
|
7541
|
+
}
|
|
7542
|
+
return { items, end: base + offset2(count) };
|
|
7543
|
+
}
|
|
7544
|
+
function readDict(bytes2, start, end, at) {
|
|
7545
|
+
if (end > bytes2.length) throw new RangeError("DICT past the font");
|
|
7546
|
+
const entries = /* @__PURE__ */ new Map();
|
|
7547
|
+
let operands = [];
|
|
7548
|
+
let offset2 = start;
|
|
7549
|
+
while (offset2 < end) {
|
|
7550
|
+
const byte = at(offset2);
|
|
7551
|
+
if (byte <= 21) {
|
|
7552
|
+
const operator = byte === 12 ? 1200 + at(offset2 + 1) : byte;
|
|
7553
|
+
offset2 += byte === 12 ? 2 : 1;
|
|
7554
|
+
entries.set(operator, operands);
|
|
7555
|
+
operands = [];
|
|
7556
|
+
} else if (byte === 28) {
|
|
7557
|
+
operands.push(int16(at(offset2 + 1) << 8 | at(offset2 + 2)));
|
|
7558
|
+
offset2 += 3;
|
|
7559
|
+
} else if (byte === 29) {
|
|
7560
|
+
operands.push(
|
|
7561
|
+
at(offset2 + 1) << 24 | at(offset2 + 2) << 16 | at(offset2 + 3) << 8 | at(offset2 + 4)
|
|
7562
|
+
);
|
|
7563
|
+
offset2 += 5;
|
|
7564
|
+
} else if (byte === 30) {
|
|
7565
|
+
let text = "";
|
|
7566
|
+
offset2 += 1;
|
|
7567
|
+
for (let done = false; !done; offset2 += 1) {
|
|
7568
|
+
const pair = at(offset2);
|
|
7569
|
+
for (const nibble of [pair >> 4, pair & 15]) {
|
|
7570
|
+
if (nibble === 15) {
|
|
7571
|
+
done = true;
|
|
7572
|
+
break;
|
|
7573
|
+
}
|
|
7574
|
+
text += REAL_NIBBLES[nibble] ?? "";
|
|
7575
|
+
}
|
|
7576
|
+
}
|
|
7577
|
+
operands.push(Number.parseFloat(text));
|
|
7578
|
+
} else if (byte >= 32 && byte <= 246) {
|
|
7579
|
+
operands.push(byte - 139);
|
|
7580
|
+
offset2 += 1;
|
|
7581
|
+
} else if (byte >= 247 && byte <= 250) {
|
|
7582
|
+
operands.push((byte - 247) * 256 + at(offset2 + 1) + 108);
|
|
7583
|
+
offset2 += 2;
|
|
7584
|
+
} else if (byte >= 251 && byte <= 254) {
|
|
7585
|
+
operands.push(-(byte - 251) * 256 - at(offset2 + 1) - 108);
|
|
7586
|
+
offset2 += 2;
|
|
7587
|
+
} else throw new RangeError("Bad DICT byte");
|
|
7588
|
+
}
|
|
7589
|
+
return entries;
|
|
7590
|
+
}
|
|
7591
|
+
var REAL_NIBBLES = [
|
|
7592
|
+
"0",
|
|
7593
|
+
"1",
|
|
7594
|
+
"2",
|
|
7595
|
+
"3",
|
|
7596
|
+
"4",
|
|
7597
|
+
"5",
|
|
7598
|
+
"6",
|
|
7599
|
+
"7",
|
|
7600
|
+
"8",
|
|
7601
|
+
"9",
|
|
7602
|
+
".",
|
|
7603
|
+
"E",
|
|
7604
|
+
"E-",
|
|
7605
|
+
"",
|
|
7606
|
+
"-"
|
|
7607
|
+
];
|
|
7608
|
+
function charsetNames(offset2, glyphCount, stringOf, at, u162) {
|
|
7609
|
+
const names2 = [".notdef"];
|
|
7610
|
+
if (offset2 === 0) {
|
|
7611
|
+
for (let glyph = 1; glyph < glyphCount; glyph += 1)
|
|
7612
|
+
names2.push(stringOf(glyph));
|
|
7613
|
+
return names2;
|
|
7614
|
+
}
|
|
7615
|
+
if (offset2 <= 2) return [...names2, ...Array(glyphCount - 1)];
|
|
7616
|
+
const format = at(offset2);
|
|
7617
|
+
let cursor = offset2 + 1;
|
|
7618
|
+
if (format === 0) {
|
|
7619
|
+
for (let glyph = 1; glyph < glyphCount; glyph += 1, cursor += 2)
|
|
7620
|
+
names2.push(stringOf(u162(cursor)));
|
|
7621
|
+
} else if (format === 1 || format === 2) {
|
|
7622
|
+
while (names2.length < glyphCount) {
|
|
7623
|
+
const first = u162(cursor);
|
|
7624
|
+
const left = format === 1 ? at(cursor + 2) : u162(cursor + 2);
|
|
7625
|
+
cursor += format === 1 ? 3 : 4;
|
|
7626
|
+
for (let step = 0; step <= left && names2.length < glyphCount; step += 1)
|
|
7627
|
+
names2.push(stringOf(first + step));
|
|
7628
|
+
}
|
|
7629
|
+
} else throw new RangeError("Bad charset format");
|
|
7630
|
+
return names2;
|
|
7631
|
+
}
|
|
7632
|
+
function charstringWidth(context, start, end) {
|
|
7633
|
+
const { bytes: bytes2, defaultWidth, nominalWidth } = context;
|
|
7634
|
+
const stack = [];
|
|
7635
|
+
const walk = (from, to, depth) => {
|
|
7636
|
+
let offset2 = from;
|
|
7637
|
+
while (offset2 < to) {
|
|
7638
|
+
const byte = bytes2[offset2];
|
|
7639
|
+
const size = byte === 28 ? 3 : byte === 255 ? 5 : byte >= 247 && byte <= 254 ? 2 : 1;
|
|
7640
|
+
if (offset2 + size > to) return defaultWidth;
|
|
7641
|
+
if (byte === 28 || byte >= 32) {
|
|
7642
|
+
const next = (step) => bytes2[offset2 + step];
|
|
7643
|
+
stack.push(
|
|
7644
|
+
byte === 28 ? int16(next(1) << 8 | next(2)) : byte <= 246 ? byte - 139 : byte <= 250 ? (byte - 247) * 256 + next(1) + 108 : byte <= 254 ? -(byte - 251) * 256 - next(1) - 108 : (next(1) << 24 | next(2) << 16 | next(3) << 8 | next(4)) / 65536
|
|
7645
|
+
);
|
|
7646
|
+
if (stack.length > 48) return defaultWidth;
|
|
7647
|
+
offset2 += size;
|
|
7648
|
+
continue;
|
|
7649
|
+
}
|
|
7650
|
+
offset2 += 1;
|
|
7651
|
+
if (byte === 10 || byte === 29) {
|
|
7652
|
+
const subrs = byte === 10 ? context.local : context.global;
|
|
7653
|
+
const index = stack.pop();
|
|
7654
|
+
const subr = index === void 0 ? void 0 : subrs[index + subrBias(subrs.length)];
|
|
7655
|
+
if (!subr || depth >= 10) return defaultWidth;
|
|
7656
|
+
const width = walk(subr[0], subr[1], depth + 1);
|
|
7657
|
+
if (width !== void 0) return width;
|
|
7658
|
+
continue;
|
|
7659
|
+
}
|
|
7660
|
+
if (byte === 11) return depth > 0 ? void 0 : defaultWidth;
|
|
7661
|
+
const takes = STACK_CLEARING[byte];
|
|
7662
|
+
if (takes === void 0) return defaultWidth;
|
|
7663
|
+
const count = stack.length;
|
|
7664
|
+
const widthFirst = takes === "pairs" ? count % 2 === 1 : takes === "endchar" ? count === 1 || count === 5 : count > takes;
|
|
7665
|
+
return widthFirst ? stack[0] + nominalWidth : defaultWidth;
|
|
7666
|
+
}
|
|
7667
|
+
return depth > 0 ? void 0 : defaultWidth;
|
|
7668
|
+
};
|
|
7669
|
+
return walk(start, end, 0) ?? defaultWidth;
|
|
7670
|
+
}
|
|
7671
|
+
function subrBias(count) {
|
|
7672
|
+
return count < 1240 ? 107 : count < 33900 ? 1131 : 32768;
|
|
7673
|
+
}
|
|
7674
|
+
var STACK_CLEARING = {
|
|
7675
|
+
1: "pairs",
|
|
7676
|
+
// hstem
|
|
7677
|
+
3: "pairs",
|
|
7678
|
+
// vstem
|
|
7679
|
+
18: "pairs",
|
|
7680
|
+
// hstemhm
|
|
7681
|
+
23: "pairs",
|
|
7682
|
+
// vstemhm
|
|
7683
|
+
19: "pairs",
|
|
7684
|
+
// hintmask, after implied vstems
|
|
7685
|
+
20: "pairs",
|
|
7686
|
+
// cntrmask
|
|
7687
|
+
21: 2,
|
|
7688
|
+
// rmoveto
|
|
7689
|
+
22: 1,
|
|
7690
|
+
// hmoveto
|
|
7691
|
+
4: 1,
|
|
7692
|
+
// vmoveto
|
|
7693
|
+
14: "endchar"
|
|
7694
|
+
// endchar: none, or four for an accented character
|
|
7695
|
+
};
|
|
7696
|
+
function int16(value) {
|
|
7697
|
+
return value >= 32768 ? value - 65536 : value;
|
|
7698
|
+
}
|
|
7699
|
+
function latin1(bytes2) {
|
|
7700
|
+
return String.fromCharCode(...bytes2);
|
|
7701
|
+
}
|
|
7702
|
+
|
|
7703
|
+
// src/edit/pdf/engine/opentype.ts
|
|
7704
|
+
var SFNT_TRUETYPE = 65536;
|
|
7705
|
+
var SFNT_CFF = 1330926671;
|
|
7706
|
+
function cffOpenType(program, font, unicode) {
|
|
7707
|
+
const safe = cffWithSafeName(program);
|
|
7708
|
+
if (unicode.size === 0 || !safe) return void 0;
|
|
7709
|
+
const em = font.unitsPerEm;
|
|
7710
|
+
const [xMin, yMin, xMax, yMax] = fontBox(font.bbox, em);
|
|
7711
|
+
const glyphCount = font.widths.length;
|
|
7712
|
+
const widths = font.widths.map(
|
|
7713
|
+
(width) => Math.max(0, Math.min(65535, Math.round(width)))
|
|
7714
|
+
);
|
|
7715
|
+
const codes = [...unicode.keys()].sort((a, b) => a - b);
|
|
7716
|
+
const tables = /* @__PURE__ */ new Map([
|
|
7717
|
+
["CFF ", safe],
|
|
7718
|
+
["OS/2", os2(em, widths, codes, yMin, yMax)],
|
|
7719
|
+
["cmap", cmap(unicode, codes)],
|
|
7720
|
+
["head", head(em, xMin, yMin, xMax, yMax)],
|
|
7721
|
+
["hhea", hhea(widths, glyphCount, xMin, yMin, xMax, yMax)],
|
|
7722
|
+
["hmtx", concat(widths.map((width) => bytes(u16(width), i16(0))))],
|
|
7723
|
+
["maxp", bytes(u32(20480), u16(glyphCount))],
|
|
7724
|
+
["name", names(postScriptName(font.name))],
|
|
7725
|
+
["post", post(em)]
|
|
7726
|
+
]);
|
|
7727
|
+
return assemble(tables, SFNT_CFF);
|
|
7728
|
+
}
|
|
7729
|
+
function fontBox(box, em) {
|
|
7730
|
+
const clamp = (value) => Math.max(-32768, Math.min(32767, Math.round(value)));
|
|
7731
|
+
const [x0 = 0, y0 = 0, x1 = 0, y1 = 0] = box.map(clamp);
|
|
7732
|
+
if (y1 <= y0) return [0, clamp(-em * 0.2), clamp(em), clamp(em * 0.8)];
|
|
7733
|
+
return [Math.min(x0, x1), y0, Math.max(x0, x1), y1];
|
|
7734
|
+
}
|
|
7735
|
+
function completeSfnt(program, fontName) {
|
|
7736
|
+
const tables = sfntTables(program);
|
|
7737
|
+
const headTable = tables?.get("head");
|
|
7738
|
+
const hheaTable = tables?.get("hhea");
|
|
7739
|
+
const maxpTable = tables?.get("maxp");
|
|
7740
|
+
const hmtxTable = tables?.get("hmtx");
|
|
7741
|
+
if (!tables || !tables.has("cmap") || !headTable || headTable.length < 54 || !hheaTable || hheaTable.length < 36 || !maxpTable || maxpTable.length < 6 || !hmtxTable)
|
|
7742
|
+
return void 0;
|
|
7743
|
+
const view = (table) => new DataView(table.buffer, table.byteOffset, table.byteLength);
|
|
7744
|
+
const headView = view(headTable);
|
|
7745
|
+
const em = headView.getUint16(18);
|
|
7746
|
+
const yMin = headView.getInt16(38);
|
|
7747
|
+
const yMax = headView.getInt16(42);
|
|
7748
|
+
const ownHead = headTable.slice();
|
|
7749
|
+
ownHead.fill(0, 8, 12);
|
|
7750
|
+
tables.set("head", ownHead);
|
|
7751
|
+
if (!tables.has("OS/2")) {
|
|
7752
|
+
const metrics = view(hheaTable).getUint16(34);
|
|
7753
|
+
const widths = Array.from(
|
|
7754
|
+
{ length: Math.min(metrics, hmtxTable.length >> 2) },
|
|
7755
|
+
(_, glyph) => view(hmtxTable).getUint16(glyph * 4)
|
|
7756
|
+
);
|
|
7757
|
+
tables.set("OS/2", os2(em, widths, [], yMin, yMax));
|
|
7758
|
+
}
|
|
7759
|
+
if (!tables.has("name")) tables.set("name", names(postScriptName(fontName)));
|
|
7760
|
+
if (!tables.has("post")) tables.set("post", post(em));
|
|
7761
|
+
const version = view(program).getUint32(0);
|
|
7762
|
+
return assemble(tables, version === SFNT_CFF ? SFNT_CFF : SFNT_TRUETYPE);
|
|
7763
|
+
}
|
|
7764
|
+
function hasUnicodeCmap(program) {
|
|
7765
|
+
const table = sfntTables(program)?.get("cmap");
|
|
7766
|
+
if (!table || table.length < 4) return false;
|
|
7767
|
+
const view = new DataView(table.buffer, table.byteOffset, table.byteLength);
|
|
7768
|
+
const count = Math.min(view.getUint16(2), table.length - 4 >> 3);
|
|
7769
|
+
for (let index = 0; index < count; index += 1) {
|
|
7770
|
+
const platform = view.getUint16(4 + index * 8);
|
|
7771
|
+
const encoding = view.getUint16(6 + index * 8);
|
|
7772
|
+
if (platform === 0 || platform === 3 && (encoding === 1 || encoding === 10))
|
|
7773
|
+
return true;
|
|
7774
|
+
}
|
|
7775
|
+
return false;
|
|
7776
|
+
}
|
|
7777
|
+
function sfntTables(program) {
|
|
7778
|
+
if (program.length < 12) return void 0;
|
|
7779
|
+
const view = new DataView(
|
|
7780
|
+
program.buffer,
|
|
7781
|
+
program.byteOffset,
|
|
7782
|
+
program.byteLength
|
|
7783
|
+
);
|
|
7784
|
+
const count = view.getUint16(4);
|
|
7785
|
+
if (count === 0 || 12 + count * 16 > program.length) return void 0;
|
|
7786
|
+
const tables = /* @__PURE__ */ new Map();
|
|
7787
|
+
for (let index = 0; index < count; index += 1) {
|
|
7788
|
+
const record = 12 + index * 16;
|
|
7789
|
+
const tag = String.fromCharCode(...program.subarray(record, record + 4));
|
|
7790
|
+
const offset2 = view.getUint32(record + 8);
|
|
7791
|
+
const length = view.getUint32(record + 12);
|
|
7792
|
+
if (tables.has(tag) || offset2 + length > program.length) return void 0;
|
|
7793
|
+
tables.set(tag, program.subarray(offset2, offset2 + length));
|
|
7794
|
+
}
|
|
7795
|
+
return tables;
|
|
7796
|
+
}
|
|
7797
|
+
function postScriptName(name) {
|
|
7798
|
+
return name.replace(/^[A-Z]{6}\+/, "").replace(/[^\x21-\x7e]|[[\](){}<>/%]/g, "").slice(0, 63) || "Embedded";
|
|
7799
|
+
}
|
|
7800
|
+
function post(em) {
|
|
7801
|
+
return bytes(
|
|
7802
|
+
u32(196608),
|
|
7803
|
+
u32(0),
|
|
7804
|
+
i16(-Math.round(em / 10)),
|
|
7805
|
+
i16(Math.round(em / 20)),
|
|
7806
|
+
u32(0),
|
|
7807
|
+
u32(0),
|
|
7808
|
+
u32(0),
|
|
7809
|
+
u32(0),
|
|
7810
|
+
u32(0)
|
|
7811
|
+
);
|
|
7812
|
+
}
|
|
7813
|
+
function head(em, xMin, yMin, xMax, yMax) {
|
|
7814
|
+
return bytes(
|
|
7815
|
+
u32(65536),
|
|
7816
|
+
u32(65536),
|
|
7817
|
+
u32(0),
|
|
7818
|
+
// checkSumAdjustment, set once the font is assembled
|
|
7819
|
+
u32(1594834165),
|
|
7820
|
+
u16(11),
|
|
7821
|
+
u16(em),
|
|
7822
|
+
u32(0),
|
|
7823
|
+
u32(0),
|
|
7824
|
+
u32(0),
|
|
7825
|
+
u32(0),
|
|
7826
|
+
i16(xMin),
|
|
7827
|
+
i16(yMin),
|
|
7828
|
+
i16(xMax),
|
|
7829
|
+
i16(yMax),
|
|
7830
|
+
u16(0),
|
|
7831
|
+
u16(8),
|
|
7832
|
+
i16(2),
|
|
7833
|
+
i16(0),
|
|
7834
|
+
i16(0)
|
|
7835
|
+
);
|
|
7836
|
+
}
|
|
7837
|
+
function hhea(widths, glyphCount, xMin, yMin, xMax, yMax) {
|
|
7838
|
+
return bytes(
|
|
7839
|
+
u32(65536),
|
|
7840
|
+
i16(yMax),
|
|
7841
|
+
i16(yMin),
|
|
7842
|
+
i16(0),
|
|
7843
|
+
u16(widths.reduce((most, width) => Math.max(most, width), 0)),
|
|
7844
|
+
i16(xMin),
|
|
7845
|
+
i16(0),
|
|
7846
|
+
i16(xMax),
|
|
7847
|
+
i16(1),
|
|
7848
|
+
i16(0),
|
|
7849
|
+
i16(0),
|
|
7850
|
+
i16(0),
|
|
7851
|
+
i16(0),
|
|
7852
|
+
i16(0),
|
|
7853
|
+
i16(0),
|
|
7854
|
+
i16(0),
|
|
7855
|
+
u16(glyphCount)
|
|
7856
|
+
);
|
|
7857
|
+
}
|
|
7858
|
+
function os2(em, widths, codes, yMin, yMax) {
|
|
7859
|
+
const scaled = (fraction) => Math.round(em * fraction);
|
|
7860
|
+
const drawn = widths.filter((width) => width > 0);
|
|
7861
|
+
const average = drawn.length ? Math.round(drawn.reduce((sum, width) => sum + width, 0) / drawn.length) : 0;
|
|
7862
|
+
return bytes(
|
|
7863
|
+
u16(4),
|
|
7864
|
+
i16(average),
|
|
7865
|
+
u16(400),
|
|
7866
|
+
u16(5),
|
|
7867
|
+
u16(0),
|
|
7868
|
+
i16(scaled(0.65)),
|
|
7869
|
+
i16(scaled(0.6)),
|
|
7870
|
+
i16(0),
|
|
7871
|
+
i16(scaled(0.075)),
|
|
7872
|
+
i16(scaled(0.65)),
|
|
7873
|
+
i16(scaled(0.6)),
|
|
7874
|
+
i16(0),
|
|
7875
|
+
i16(scaled(0.35)),
|
|
7876
|
+
i16(scaled(0.05)),
|
|
7877
|
+
i16(scaled(0.25)),
|
|
7878
|
+
i16(0),
|
|
7879
|
+
new Array(10).fill(0),
|
|
7880
|
+
u32(0),
|
|
7881
|
+
u32(0),
|
|
7882
|
+
u32(0),
|
|
7883
|
+
u32(0),
|
|
7884
|
+
[87, 68, 79, 67],
|
|
7885
|
+
// "WDOC"
|
|
7886
|
+
u16(64),
|
|
7887
|
+
// regular
|
|
7888
|
+
u16(Math.min(codes[0] ?? 32, 65535)),
|
|
7889
|
+
u16(Math.min(codes.at(-1) ?? 65535, 65535)),
|
|
7890
|
+
i16(yMax),
|
|
7891
|
+
i16(yMin),
|
|
7892
|
+
i16(0),
|
|
7893
|
+
u16(Math.max(0, yMax)),
|
|
7894
|
+
u16(Math.max(0, -yMin)),
|
|
7895
|
+
u32(1),
|
|
7896
|
+
u32(0),
|
|
7897
|
+
i16(scaled(0.5)),
|
|
7898
|
+
i16(scaled(0.7)),
|
|
7899
|
+
u16(0),
|
|
7900
|
+
u16(32),
|
|
7901
|
+
u16(0)
|
|
7902
|
+
);
|
|
7903
|
+
}
|
|
7904
|
+
function cmap(unicode, codes) {
|
|
7905
|
+
const basic = codes.filter((code) => code <= 65535);
|
|
7906
|
+
const format4 = cmapFormat4(unicode, basic);
|
|
7907
|
+
const format12 = !format4 || codes.length > basic.length ? cmapFormat12(unicode, codes) : void 0;
|
|
7908
|
+
const subtables = [
|
|
7909
|
+
...format4 ? [{ platform: 0, encoding: 3, data: format4 }] : [],
|
|
7910
|
+
...format12 ? [{ platform: 0, encoding: 4, data: format12 }] : [],
|
|
7911
|
+
...format4 ? [{ platform: 3, encoding: 1, data: format4 }] : [],
|
|
7912
|
+
...format12 ? [{ platform: 3, encoding: 10, data: format12 }] : []
|
|
7913
|
+
];
|
|
7914
|
+
const unique = [...new Set(subtables.map((subtable) => subtable.data))];
|
|
7915
|
+
const headerSize = 4 + subtables.length * 8;
|
|
7916
|
+
const offsets = /* @__PURE__ */ new Map();
|
|
7917
|
+
let offset2 = headerSize;
|
|
7918
|
+
for (const data of unique) {
|
|
7919
|
+
offsets.set(data, offset2);
|
|
7920
|
+
offset2 += data.length;
|
|
7921
|
+
}
|
|
7922
|
+
return concat([
|
|
7923
|
+
bytes(u16(0), u16(subtables.length)),
|
|
7924
|
+
...subtables.map(
|
|
7925
|
+
({ platform, encoding, data }) => bytes(u16(platform), u16(encoding), u32(offsets.get(data)))
|
|
7926
|
+
),
|
|
7927
|
+
...unique
|
|
7928
|
+
]);
|
|
7929
|
+
}
|
|
7930
|
+
function cmapFormat4(unicode, codes) {
|
|
7931
|
+
const segments = [];
|
|
7932
|
+
for (const code of codes) {
|
|
7933
|
+
const glyph = unicode.get(code);
|
|
7934
|
+
const last = segments.at(-1);
|
|
7935
|
+
if (last && code === last.end + 1 && glyph === last.glyph + (code - last.start))
|
|
7936
|
+
last.end = code;
|
|
7937
|
+
else segments.push({ start: code, end: code, glyph });
|
|
7938
|
+
}
|
|
7939
|
+
segments.push({ start: 65535, end: 65535, glyph: 0 });
|
|
7940
|
+
const count = segments.length;
|
|
7941
|
+
if (16 + count * 8 > 65535) return void 0;
|
|
7942
|
+
const searchRange = 2 * 2 ** Math.floor(Math.log2(count));
|
|
7943
|
+
const delta = (segment) => segment.start === 65535 ? 1 : segment.glyph - segment.start & 65535;
|
|
7944
|
+
return bytes(
|
|
7945
|
+
u16(4),
|
|
7946
|
+
u16(16 + count * 8),
|
|
7947
|
+
u16(0),
|
|
7948
|
+
u16(count * 2),
|
|
7949
|
+
u16(searchRange),
|
|
7950
|
+
u16(Math.floor(Math.log2(count))),
|
|
7951
|
+
u16(count * 2 - searchRange),
|
|
7952
|
+
segments.flatMap((segment) => u16(segment.end)),
|
|
7953
|
+
u16(0),
|
|
7954
|
+
segments.flatMap((segment) => u16(segment.start)),
|
|
7955
|
+
segments.flatMap((segment) => u16(delta(segment))),
|
|
7956
|
+
segments.flatMap(() => u16(0))
|
|
7957
|
+
);
|
|
7958
|
+
}
|
|
7959
|
+
function cmapFormat12(unicode, codes) {
|
|
7960
|
+
const groups = [];
|
|
7961
|
+
for (const code of codes) {
|
|
7962
|
+
const glyph = unicode.get(code);
|
|
7963
|
+
const last = groups.at(-1);
|
|
7964
|
+
if (last && code === last.end + 1 && glyph === last.glyph + (code - last.start))
|
|
7965
|
+
last.end = code;
|
|
7966
|
+
else groups.push({ start: code, end: code, glyph });
|
|
7967
|
+
}
|
|
7968
|
+
return bytes(
|
|
7969
|
+
u16(12),
|
|
7970
|
+
u16(0),
|
|
7971
|
+
u32(16 + groups.length * 12),
|
|
7972
|
+
u32(0),
|
|
7973
|
+
u32(groups.length),
|
|
7974
|
+
groups.flatMap((group) => [
|
|
7975
|
+
...u32(group.start),
|
|
7976
|
+
...u32(group.end),
|
|
7977
|
+
...u32(group.glyph)
|
|
7978
|
+
])
|
|
7979
|
+
);
|
|
7980
|
+
}
|
|
7981
|
+
function names(postScript) {
|
|
7982
|
+
const records = [
|
|
7983
|
+
[1, postScript],
|
|
7984
|
+
[2, "Regular"],
|
|
7985
|
+
[3, `${postScript}-web-doc`],
|
|
7986
|
+
[4, postScript],
|
|
7987
|
+
[5, "Version 1.0"],
|
|
7988
|
+
[6, postScript]
|
|
7989
|
+
];
|
|
7990
|
+
const strings = records.map(
|
|
7991
|
+
([, text]) => [...text].flatMap((character) => u16(character.charCodeAt(0)))
|
|
7992
|
+
);
|
|
7993
|
+
let offset2 = 0;
|
|
7994
|
+
const entries = records.map(([id], index) => {
|
|
7995
|
+
const entry = [
|
|
7996
|
+
...u16(3),
|
|
7997
|
+
...u16(1),
|
|
7998
|
+
...u16(1033),
|
|
7999
|
+
...u16(id),
|
|
8000
|
+
...u16(strings[index].length),
|
|
8001
|
+
...u16(offset2)
|
|
8002
|
+
];
|
|
8003
|
+
offset2 += strings[index].length;
|
|
8004
|
+
return entry;
|
|
8005
|
+
});
|
|
8006
|
+
return bytes(
|
|
8007
|
+
u16(0),
|
|
8008
|
+
u16(records.length),
|
|
8009
|
+
u16(6 + records.length * 12),
|
|
8010
|
+
entries.flat(),
|
|
8011
|
+
strings.flat()
|
|
8012
|
+
);
|
|
8013
|
+
}
|
|
8014
|
+
function assemble(tables, version) {
|
|
8015
|
+
const tags = [...tables.keys()].sort();
|
|
8016
|
+
const count = tags.length;
|
|
8017
|
+
const selector = Math.floor(Math.log2(count));
|
|
8018
|
+
const headerSize = 12 + count * 16;
|
|
8019
|
+
let offset2 = headerSize;
|
|
8020
|
+
const placed = tags.map((tag) => {
|
|
8021
|
+
const data = tables.get(tag);
|
|
8022
|
+
const at = offset2;
|
|
8023
|
+
offset2 += data.length + 3 & ~3;
|
|
8024
|
+
return { tag, data, at };
|
|
8025
|
+
});
|
|
8026
|
+
const font = new Uint8Array(offset2);
|
|
8027
|
+
font.set(
|
|
8028
|
+
bytes(
|
|
8029
|
+
u32(version),
|
|
8030
|
+
u16(count),
|
|
8031
|
+
u16(2 ** selector * 16),
|
|
8032
|
+
u16(selector),
|
|
8033
|
+
u16(count * 16 - 2 ** selector * 16),
|
|
8034
|
+
placed.flatMap(({ tag, data, at }) => [
|
|
8035
|
+
...[...tag].map((character) => character.charCodeAt(0)),
|
|
8036
|
+
...u32(checksum(data)),
|
|
8037
|
+
...u32(at),
|
|
8038
|
+
...u32(data.length)
|
|
8039
|
+
])
|
|
8040
|
+
)
|
|
8041
|
+
);
|
|
8042
|
+
for (const { data, at } of placed) font.set(data, at);
|
|
8043
|
+
const head2 = placed.find((table) => table.tag === "head");
|
|
8044
|
+
const adjustment = 2981146554 - checksum(font) >>> 0;
|
|
8045
|
+
font.set(u32(adjustment), head2.at + 8);
|
|
8046
|
+
return font;
|
|
8047
|
+
}
|
|
8048
|
+
function checksum(data) {
|
|
8049
|
+
let sum = 0;
|
|
8050
|
+
for (let offset2 = 0; offset2 < data.length; offset2 += 4)
|
|
8051
|
+
sum = sum + ((data[offset2] ?? 0) << 24 | (data[offset2 + 1] ?? 0) << 16 | (data[offset2 + 2] ?? 0) << 8 | (data[offset2 + 3] ?? 0)) >>> 0;
|
|
8052
|
+
return sum;
|
|
8053
|
+
}
|
|
8054
|
+
function u16(value) {
|
|
8055
|
+
return [value >> 8 & 255, value & 255];
|
|
8056
|
+
}
|
|
8057
|
+
function i16(value) {
|
|
8058
|
+
return u16(value < 0 ? value + 65536 : value);
|
|
8059
|
+
}
|
|
8060
|
+
function u32(value) {
|
|
8061
|
+
return [
|
|
8062
|
+
value >>> 24 & 255,
|
|
8063
|
+
value >>> 16 & 255,
|
|
8064
|
+
value >>> 8 & 255,
|
|
8065
|
+
value & 255
|
|
8066
|
+
];
|
|
8067
|
+
}
|
|
8068
|
+
function bytes(...parts) {
|
|
8069
|
+
return concat(parts.map((part) => Uint8Array.from(part)));
|
|
8070
|
+
}
|
|
8071
|
+
function concat(parts) {
|
|
8072
|
+
const out = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0));
|
|
8073
|
+
let offset2 = 0;
|
|
8074
|
+
for (const part of parts) {
|
|
8075
|
+
out.set(part, offset2);
|
|
8076
|
+
offset2 += part.length;
|
|
8077
|
+
}
|
|
8078
|
+
return out;
|
|
8079
|
+
}
|
|
8080
|
+
|
|
8081
|
+
// src/edit/pdf/engine/text-font.ts
|
|
8082
|
+
function textFaceOf(pdfium, object, cache) {
|
|
8083
|
+
const { lib } = pdfium;
|
|
8084
|
+
const font = lib.FPDFTextObj_GetFont(object);
|
|
8085
|
+
const family = textStyle(pdfium, object).fontFamily;
|
|
8086
|
+
const baseName = pdfium.readUtf8String(
|
|
8087
|
+
(buffer, bytes2) => lib.FPDFFont_GetBaseFontName(font, buffer, bytes2)
|
|
8088
|
+
);
|
|
8089
|
+
if (!lib.FPDFFont_GetIsEmbedded(font))
|
|
8090
|
+
return { key: `name:${baseName}`, family, missing: "not-embedded" };
|
|
8091
|
+
const program = fontProgram(pdfium, font);
|
|
8092
|
+
if (!program)
|
|
8093
|
+
return { key: `embedded:${baseName}`, family, missing: "unreadable" };
|
|
8094
|
+
const key = `${baseName}#${fnv1a(program).toString(16)}`;
|
|
8095
|
+
const known = cache.get(key);
|
|
8096
|
+
if (known) return { ...known, family };
|
|
8097
|
+
const face = { key, family, ...faceOf(program, baseName) };
|
|
8098
|
+
cache.set(key, face);
|
|
8099
|
+
return face;
|
|
8100
|
+
}
|
|
8101
|
+
function faceOf(program, baseName) {
|
|
8102
|
+
const tag = String.fromCharCode(...program.subarray(0, 4));
|
|
8103
|
+
const truetype = tag === "true" || program[0] === 0 && program[1] === 1 && program[2] === 0 && program[3] === 0;
|
|
8104
|
+
if (truetype || tag === "OTTO") {
|
|
8105
|
+
if (!hasUnicodeCmap(program)) return { missing: "no-unicode" };
|
|
8106
|
+
const data2 = completeSfnt(program, baseName);
|
|
8107
|
+
return data2 ? { face: { data: data2, format: truetype ? "truetype" : "opentype" } } : { missing: "unreadable" };
|
|
8108
|
+
}
|
|
8109
|
+
if (tag.startsWith("%!") || program[0] === 128) return { missing: "type1" };
|
|
8110
|
+
const cff = readCff(program);
|
|
8111
|
+
if (!cff) return { missing: "unreadable" };
|
|
8112
|
+
if (cff.cid) return { missing: "cid-keyed" };
|
|
8113
|
+
const unicode = /* @__PURE__ */ new Map();
|
|
8114
|
+
cff.glyphNames.forEach((name, glyph) => {
|
|
8115
|
+
const code = glyphUnicode(name);
|
|
8116
|
+
if (code !== void 0 && !unicode.has(code)) unicode.set(code, glyph);
|
|
8117
|
+
});
|
|
8118
|
+
const data = cffOpenType(program, cff, unicode);
|
|
8119
|
+
return data ? { face: { data, format: "opentype" } } : { missing: "no-unicode" };
|
|
8120
|
+
}
|
|
8121
|
+
function fontProgram(pdfium, font) {
|
|
8122
|
+
const { lib } = pdfium;
|
|
8123
|
+
const size = pdfium.readNumbers(
|
|
8124
|
+
1,
|
|
8125
|
+
"i32",
|
|
8126
|
+
([out2]) => lib.FPDFFont_GetFontData(font, 0, 0, out2)
|
|
8127
|
+
)?.[0];
|
|
8128
|
+
if (!size) return void 0;
|
|
8129
|
+
const buffer = pdfium.malloc(size);
|
|
8130
|
+
const out = pdfium.malloc(4);
|
|
8131
|
+
try {
|
|
8132
|
+
return lib.FPDFFont_GetFontData(font, buffer, size, out) ? pdfium.readBytes(buffer, size) : void 0;
|
|
8133
|
+
} finally {
|
|
8134
|
+
pdfium.free(out);
|
|
8135
|
+
pdfium.free(buffer);
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
8138
|
+
function fnv1a(bytes2) {
|
|
8139
|
+
let hash = 2166136261;
|
|
8140
|
+
for (const byte of bytes2) hash = Math.imul(hash ^ byte, 16777619);
|
|
8141
|
+
return hash >>> 0;
|
|
8142
|
+
}
|
|
8143
|
+
|
|
7225
8144
|
// src/edit/pdf/engine/text-layout.ts
|
|
7226
8145
|
function layoutText(input) {
|
|
7227
8146
|
const step = input.fontSize * input.lineHeight;
|
|
@@ -7407,7 +8326,7 @@ function drawTable(context, pageIndex, spec, insertAt) {
|
|
|
7407
8326
|
);
|
|
7408
8327
|
const geometry = context.geometry(pageIndex);
|
|
7409
8328
|
const overflow = spec.at.y + layout.height > displayedSize(geometry).height + 1e-3;
|
|
7410
|
-
const
|
|
8329
|
+
const head2 = JSON.stringify(spec);
|
|
7411
8330
|
const memberMark = { kind: "table", id: spec.id };
|
|
7412
8331
|
const member = JSON.stringify(memberMark);
|
|
7413
8332
|
const at = (x, y) => pageToUser(geometry, x, y);
|
|
@@ -7446,7 +8365,7 @@ function drawTable(context, pageIndex, spec, insertAt) {
|
|
|
7446
8365
|
const [r2, g2, b2] = parseColor(style.headerFill);
|
|
7447
8366
|
lib.FPDFPageObj_SetFillColor(fill, r2, g2, b2, 255);
|
|
7448
8367
|
lib.FPDFPath_SetDrawMode(fill, FILL_ALTERNATE, false);
|
|
7449
|
-
place(fill, OBJECT_PATH, spec,
|
|
8368
|
+
place(fill, OBJECT_PATH, spec, head2);
|
|
7450
8369
|
}
|
|
7451
8370
|
const frame = [
|
|
7452
8371
|
at(spec.at.x, spec.at.y),
|
|
@@ -7474,7 +8393,7 @@ function drawTable(context, pageIndex, spec, insertAt) {
|
|
|
7474
8393
|
lib.FPDFPageObj_SetStrokeColor(grid, r, g, b, 255);
|
|
7475
8394
|
lib.FPDFPageObj_SetStrokeWidth(grid, style.borderWidth);
|
|
7476
8395
|
lib.FPDFPath_SetDrawMode(grid, FILL_NONE, true);
|
|
7477
|
-
place(grid, OBJECT_PATH, spec,
|
|
8396
|
+
place(grid, OBJECT_PATH, spec, head2);
|
|
7478
8397
|
layout.rows.forEach((row) => {
|
|
7479
8398
|
row.cells.forEach((lines, columnIndex) => {
|
|
7480
8399
|
const column = layout.columns[columnIndex];
|
|
@@ -8129,7 +9048,7 @@ function canKeepFont(context, target, text) {
|
|
|
8129
9048
|
const font = lib.FPDFTextObj_GetFont(object);
|
|
8130
9049
|
if (!lib.FPDFFont_GetIsEmbedded(font)) {
|
|
8131
9050
|
const base = pdfium.readUtf8String(
|
|
8132
|
-
(buffer,
|
|
9051
|
+
(buffer, bytes2) => lib.FPDFFont_GetBaseFontName(font, buffer, bytes2)
|
|
8133
9052
|
);
|
|
8134
9053
|
return isStandardFamily(base.split(/[-,]/)[0] ?? "") && firstNonWinAnsi(text) === void 0;
|
|
8135
9054
|
}
|
|
@@ -8179,11 +9098,11 @@ function replaceInPlace(context, target, text) {
|
|
|
8179
9098
|
const textPage = lib.FPDFText_LoadPage(page);
|
|
8180
9099
|
try {
|
|
8181
9100
|
return pdfium.readWideString(
|
|
8182
|
-
(buffer,
|
|
9101
|
+
(buffer, bytes2) => lib.FPDFTextObj_GetText(
|
|
8183
9102
|
lib.FPDFPage_GetObject(page, index),
|
|
8184
9103
|
textPage,
|
|
8185
9104
|
buffer,
|
|
8186
|
-
|
|
9105
|
+
bytes2
|
|
8187
9106
|
)
|
|
8188
9107
|
);
|
|
8189
9108
|
} finally {
|
|
@@ -8221,7 +9140,7 @@ function splitAround(context, target, before, middle, after) {
|
|
|
8221
9140
|
1,
|
|
8222
9141
|
"float",
|
|
8223
9142
|
([pointer]) => lib.FPDFTextObj_GetFontSize(old, pointer)
|
|
8224
|
-
)?.[0] ?? style.fontSize;
|
|
9143
|
+
)?.[0] ?? style.fontSize / textScale(matrix);
|
|
8225
9144
|
const [a, b, c, d, e, f] = matrix;
|
|
8226
9145
|
const [r, g, bl] = parseColor(style.color);
|
|
8227
9146
|
const parts = [
|
|
@@ -8266,7 +9185,7 @@ function splitAround(context, target, before, middle, after) {
|
|
|
8266
9185
|
try {
|
|
8267
9186
|
objects.forEach((object, at) => {
|
|
8268
9187
|
const read2 = pdfium.readWideString(
|
|
8269
|
-
(buffer,
|
|
9188
|
+
(buffer, bytes2) => lib.FPDFTextObj_GetText(object, textPage, buffer, bytes2)
|
|
8270
9189
|
);
|
|
8271
9190
|
if (read2.trimEnd() !== parts[at].text.trimEnd()) faithful = false;
|
|
8272
9191
|
});
|
|
@@ -8328,7 +9247,7 @@ function replaceWithFallback(context, target, text) {
|
|
|
8328
9247
|
1,
|
|
8329
9248
|
"float",
|
|
8330
9249
|
([pointer]) => lib.FPDFTextObj_GetFontSize(old, pointer)
|
|
8331
|
-
)?.[0] ?? style.fontSize;
|
|
9250
|
+
)?.[0] ?? style.fontSize / textScale(matrix);
|
|
8332
9251
|
const object = lib.FPDFPageObj_CreateTextObj(
|
|
8333
9252
|
context.document,
|
|
8334
9253
|
font.handle,
|
|
@@ -8371,7 +9290,7 @@ function resize(context, target, fontSize) {
|
|
|
8371
9290
|
let text;
|
|
8372
9291
|
try {
|
|
8373
9292
|
text = pdfium.readWideString(
|
|
8374
|
-
(buffer,
|
|
9293
|
+
(buffer, bytes2) => lib.FPDFTextObj_GetText(old, textPage, buffer, bytes2)
|
|
8375
9294
|
);
|
|
8376
9295
|
} finally {
|
|
8377
9296
|
lib.FPDFText_ClosePage(textPage);
|
|
@@ -8389,7 +9308,7 @@ function resize(context, target, fontSize) {
|
|
|
8389
9308
|
const object = lib.FPDFPageObj_CreateTextObj(
|
|
8390
9309
|
context.document,
|
|
8391
9310
|
lib.FPDFTextObj_GetFont(old),
|
|
8392
|
-
fontSize
|
|
9311
|
+
fontSize / textScale(matrix)
|
|
8393
9312
|
);
|
|
8394
9313
|
setText(pdfium, object, text);
|
|
8395
9314
|
lib.FPDFPageObj_SetFillColor(
|
|
@@ -8663,11 +9582,14 @@ var rotatePage = {
|
|
|
8663
9582
|
validate(operation2, context, issue) {
|
|
8664
9583
|
if (operation2.pageIndex >= context.pageCount)
|
|
8665
9584
|
issue("/pageIndex", "unknown-target", `No page ${operation2.pageIndex}`);
|
|
9585
|
+
if (operation2.rotation === void 0 === (operation2.by === void 0))
|
|
9586
|
+
issue("", "one-of", "Give exactly one of `rotation` and `by`");
|
|
8666
9587
|
},
|
|
8667
9588
|
apply(operation2, context) {
|
|
8668
9589
|
const { lib } = context.pdfium;
|
|
8669
9590
|
context.withPage(operation2.pageIndex, (page) => {
|
|
8670
|
-
lib.
|
|
9591
|
+
const quarters = operation2.by !== void 0 ? (lib.FPDFPage_GetRotation(page) + operation2.by / 90) % 4 : operation2.rotation / 90;
|
|
9592
|
+
lib.FPDFPage_SetRotation(page, quarters);
|
|
8671
9593
|
});
|
|
8672
9594
|
context.invalidatePage(operation2.pageIndex);
|
|
8673
9595
|
return {
|
|
@@ -8888,8 +9810,8 @@ var PdfCompactionError = class extends ViewerError {
|
|
|
8888
9810
|
});
|
|
8889
9811
|
}
|
|
8890
9812
|
};
|
|
8891
|
-
function compactPdf(
|
|
8892
|
-
const { objects, trailer, trailerReferences, headerEnd } = parseFile(
|
|
9813
|
+
function compactPdf(bytes2) {
|
|
9814
|
+
const { objects, trailer, trailerReferences, headerEnd } = parseFile(bytes2);
|
|
8893
9815
|
const byNumber = new Map(objects.map((object) => [object.number, object]));
|
|
8894
9816
|
const reachable = /* @__PURE__ */ new Set();
|
|
8895
9817
|
const queue = [...trailerReferences];
|
|
@@ -8902,12 +9824,12 @@ function compactPdf(bytes) {
|
|
|
8902
9824
|
queue.push(...object.references);
|
|
8903
9825
|
}
|
|
8904
9826
|
const kept = objects.filter((object) => reachable.has(object.number));
|
|
8905
|
-
const parts = [
|
|
9827
|
+
const parts = [bytes2.subarray(0, headerEnd)];
|
|
8906
9828
|
const offsets = /* @__PURE__ */ new Map();
|
|
8907
9829
|
let position = headerEnd;
|
|
8908
9830
|
for (const object of kept) {
|
|
8909
9831
|
offsets.set(object.number, position);
|
|
8910
|
-
const slice =
|
|
9832
|
+
const slice = bytes2.subarray(object.start, object.end);
|
|
8911
9833
|
parts.push(slice, NEWLINE);
|
|
8912
9834
|
position += slice.byteLength + 1;
|
|
8913
9835
|
}
|
|
@@ -8933,10 +9855,10 @@ ${position}
|
|
|
8933
9855
|
%%EOF
|
|
8934
9856
|
`)
|
|
8935
9857
|
);
|
|
8936
|
-
return
|
|
9858
|
+
return concat2(parts);
|
|
8937
9859
|
}
|
|
8938
|
-
function parseFile(
|
|
8939
|
-
const lexer = new Lexer(
|
|
9860
|
+
function parseFile(bytes2) {
|
|
9861
|
+
const lexer = new Lexer(bytes2);
|
|
8940
9862
|
const objects = [];
|
|
8941
9863
|
let trailer;
|
|
8942
9864
|
let trailerReferences = [];
|
|
@@ -8956,7 +9878,7 @@ function parseFile(bytes) {
|
|
|
8956
9878
|
throw new PdfCompactionError("an object header is malformed");
|
|
8957
9879
|
const object = parseObject(
|
|
8958
9880
|
lexer,
|
|
8959
|
-
|
|
9881
|
+
bytes2,
|
|
8960
9882
|
first.value,
|
|
8961
9883
|
second.value,
|
|
8962
9884
|
first.start
|
|
@@ -8971,7 +9893,7 @@ function parseFile(bytes) {
|
|
|
8971
9893
|
const dictionaryStart = lexer.skipWhitespace();
|
|
8972
9894
|
const references = [];
|
|
8973
9895
|
const dictionaryEnd = skipValue(lexer, references);
|
|
8974
|
-
trailer =
|
|
9896
|
+
trailer = latin12(bytes2.subarray(dictionaryStart, dictionaryEnd));
|
|
8975
9897
|
trailerReferences = references;
|
|
8976
9898
|
continue;
|
|
8977
9899
|
}
|
|
@@ -8993,7 +9915,7 @@ function parseFile(bytes) {
|
|
|
8993
9915
|
throw new PdfCompactionError("the file has no objects");
|
|
8994
9916
|
return { objects, trailer, trailerReferences, headerEnd };
|
|
8995
9917
|
}
|
|
8996
|
-
function parseObject(lexer,
|
|
9918
|
+
function parseObject(lexer, bytes2, number, generation, start) {
|
|
8997
9919
|
const references = [];
|
|
8998
9920
|
let integer;
|
|
8999
9921
|
let lengthValue;
|
|
@@ -9014,7 +9936,7 @@ function parseObject(lexer, bytes, number, generation, start) {
|
|
|
9014
9936
|
const dictionaryStart = lexer.position;
|
|
9015
9937
|
const dictionaryEnd = skipValue(lexer, references);
|
|
9016
9938
|
if (first.kind === "delimiter" && first.value === "<<") {
|
|
9017
|
-
const length = findLength(
|
|
9939
|
+
const length = findLength(bytes2, dictionaryStart, dictionaryEnd);
|
|
9018
9940
|
lengthValue = length?.value;
|
|
9019
9941
|
lengthReference = length?.reference;
|
|
9020
9942
|
}
|
|
@@ -9022,16 +9944,16 @@ function parseObject(lexer, bytes, number, generation, start) {
|
|
|
9022
9944
|
let next = lexer.next();
|
|
9023
9945
|
if (next.kind === "keyword" && next.value === "stream") {
|
|
9024
9946
|
let dataStart = next.end;
|
|
9025
|
-
if (
|
|
9026
|
-
if (
|
|
9947
|
+
if (bytes2[dataStart] === CR) dataStart += 1;
|
|
9948
|
+
if (bytes2[dataStart] === LF) dataStart += 1;
|
|
9027
9949
|
let dataEnd;
|
|
9028
9950
|
if (lengthValue !== void 0) dataEnd = dataStart + lengthValue;
|
|
9029
9951
|
else if (lengthReference !== void 0) {
|
|
9030
9952
|
const known = lexer.integerObjects.get(lengthReference);
|
|
9031
9953
|
if (known !== void 0) dataEnd = dataStart + known;
|
|
9032
9954
|
}
|
|
9033
|
-
if (dataEnd === void 0 || dataEnd >
|
|
9034
|
-
dataEnd = findEndstream(
|
|
9955
|
+
if (dataEnd === void 0 || dataEnd > bytes2.length || !followedByEndstream(bytes2, dataEnd)) {
|
|
9956
|
+
dataEnd = findEndstream(bytes2, dataStart);
|
|
9035
9957
|
if (dataEnd === void 0)
|
|
9036
9958
|
throw new PdfCompactionError(`object ${number} has no endstream`);
|
|
9037
9959
|
}
|
|
@@ -9086,8 +10008,8 @@ function skipValue(lexer, references) {
|
|
|
9086
10008
|
} while (depth > 0);
|
|
9087
10009
|
return end;
|
|
9088
10010
|
}
|
|
9089
|
-
function findLength(
|
|
9090
|
-
const lexer = new Lexer(
|
|
10011
|
+
function findLength(bytes2, start, end) {
|
|
10012
|
+
const lexer = new Lexer(bytes2.subarray(start, end));
|
|
9091
10013
|
for (; ; ) {
|
|
9092
10014
|
const token = lexer.next();
|
|
9093
10015
|
if (token.kind === "end") return void 0;
|
|
@@ -9103,20 +10025,20 @@ function findLength(bytes, start, end) {
|
|
|
9103
10025
|
return { value: value.value };
|
|
9104
10026
|
}
|
|
9105
10027
|
}
|
|
9106
|
-
function followedByEndstream(
|
|
10028
|
+
function followedByEndstream(bytes2, at) {
|
|
9107
10029
|
let index = at;
|
|
9108
|
-
while (index <
|
|
9109
|
-
return matchesAscii(
|
|
10030
|
+
while (index < bytes2.length && isWhitespace(bytes2[index])) index += 1;
|
|
10031
|
+
return matchesAscii(bytes2, index, "endstream");
|
|
9110
10032
|
}
|
|
9111
|
-
function findEndstream(
|
|
9112
|
-
for (let index = from; index <=
|
|
9113
|
-
if (
|
|
10033
|
+
function findEndstream(bytes2, from) {
|
|
10034
|
+
for (let index = from; index <= bytes2.length - 9; index += 1) {
|
|
10035
|
+
if (bytes2[index] !== 101 || !matchesAscii(bytes2, index, "endstream"))
|
|
9114
10036
|
continue;
|
|
9115
10037
|
const after = index + 9;
|
|
9116
|
-
if (after <
|
|
10038
|
+
if (after < bytes2.length && !isWhitespace(bytes2[after])) continue;
|
|
9117
10039
|
let end = index;
|
|
9118
|
-
if (end > from &&
|
|
9119
|
-
if (end > from &&
|
|
10040
|
+
if (end > from && bytes2[end - 1] === LF) end -= 1;
|
|
10041
|
+
if (end > from && bytes2[end - 1] === CR) end -= 1;
|
|
9120
10042
|
return end;
|
|
9121
10043
|
}
|
|
9122
10044
|
return void 0;
|
|
@@ -9127,8 +10049,8 @@ var Lexer = class {
|
|
|
9127
10049
|
#lastName = "";
|
|
9128
10050
|
/** Objects whose value is a bare integer, as seen so far: indirect lengths. */
|
|
9129
10051
|
integerObjects = /* @__PURE__ */ new Map();
|
|
9130
|
-
constructor(
|
|
9131
|
-
this.#bytes =
|
|
10052
|
+
constructor(bytes2) {
|
|
10053
|
+
this.#bytes = bytes2;
|
|
9132
10054
|
}
|
|
9133
10055
|
get position() {
|
|
9134
10056
|
return this.#position;
|
|
@@ -9147,35 +10069,35 @@ var Lexer = class {
|
|
|
9147
10069
|
}
|
|
9148
10070
|
/** Skips whitespace and comments; returns where the next token starts. */
|
|
9149
10071
|
skipWhitespace() {
|
|
9150
|
-
const
|
|
10072
|
+
const bytes2 = this.#bytes;
|
|
9151
10073
|
for (; ; ) {
|
|
9152
|
-
while (this.#position <
|
|
10074
|
+
while (this.#position < bytes2.length && isWhitespace(bytes2[this.#position]))
|
|
9153
10075
|
this.#position += 1;
|
|
9154
|
-
if (
|
|
9155
|
-
while (this.#position <
|
|
10076
|
+
if (bytes2[this.#position] !== 37) return this.#position;
|
|
10077
|
+
while (this.#position < bytes2.length && bytes2[this.#position] !== LF && bytes2[this.#position] !== CR)
|
|
9156
10078
|
this.#position += 1;
|
|
9157
10079
|
}
|
|
9158
10080
|
}
|
|
9159
10081
|
next() {
|
|
9160
|
-
const
|
|
10082
|
+
const bytes2 = this.#bytes;
|
|
9161
10083
|
const start = this.skipWhitespace();
|
|
9162
|
-
if (start >=
|
|
9163
|
-
const byte =
|
|
10084
|
+
if (start >= bytes2.length) return { kind: "end", start, end: start };
|
|
10085
|
+
const byte = bytes2[start];
|
|
9164
10086
|
if (byte === 40) {
|
|
9165
10087
|
let depth = 0;
|
|
9166
10088
|
let index2 = start;
|
|
9167
|
-
for (; index2 <
|
|
9168
|
-
const current =
|
|
10089
|
+
for (; index2 < bytes2.length; index2 += 1) {
|
|
10090
|
+
const current = bytes2[index2];
|
|
9169
10091
|
if (current === 92)
|
|
9170
10092
|
index2 += 1;
|
|
9171
10093
|
else if (current === 40) depth += 1;
|
|
9172
10094
|
else if (current === 41 && --depth === 0) break;
|
|
9173
10095
|
}
|
|
9174
|
-
this.#position = Math.min(index2 + 1,
|
|
10096
|
+
this.#position = Math.min(index2 + 1, bytes2.length);
|
|
9175
10097
|
return { kind: "string", start, end: this.#position };
|
|
9176
10098
|
}
|
|
9177
10099
|
if (byte === 60) {
|
|
9178
|
-
if (
|
|
10100
|
+
if (bytes2[start + 1] === 60) {
|
|
9179
10101
|
this.#position = start + 2;
|
|
9180
10102
|
return {
|
|
9181
10103
|
kind: "delimiter",
|
|
@@ -9185,11 +10107,11 @@ var Lexer = class {
|
|
|
9185
10107
|
};
|
|
9186
10108
|
}
|
|
9187
10109
|
let index2 = start + 1;
|
|
9188
|
-
while (index2 <
|
|
9189
|
-
this.#position = Math.min(index2 + 1,
|
|
10110
|
+
while (index2 < bytes2.length && bytes2[index2] !== 62) index2 += 1;
|
|
10111
|
+
this.#position = Math.min(index2 + 1, bytes2.length);
|
|
9190
10112
|
return { kind: "string", start, end: this.#position };
|
|
9191
10113
|
}
|
|
9192
|
-
if (byte === 62 &&
|
|
10114
|
+
if (byte === 62 && bytes2[start + 1] === 62) {
|
|
9193
10115
|
this.#position = start + 2;
|
|
9194
10116
|
return {
|
|
9195
10117
|
kind: "delimiter",
|
|
@@ -9209,16 +10131,16 @@ var Lexer = class {
|
|
|
9209
10131
|
}
|
|
9210
10132
|
if (byte === 47) {
|
|
9211
10133
|
let index2 = start + 1;
|
|
9212
|
-
while (index2 <
|
|
10134
|
+
while (index2 < bytes2.length && isRegular(bytes2[index2])) index2 += 1;
|
|
9213
10135
|
this.#position = index2;
|
|
9214
|
-
this.#lastName =
|
|
10136
|
+
this.#lastName = latin12(bytes2.subarray(start + 1, index2));
|
|
9215
10137
|
return { kind: "name", start, end: index2 };
|
|
9216
10138
|
}
|
|
9217
10139
|
let index = start;
|
|
9218
|
-
while (index <
|
|
10140
|
+
while (index < bytes2.length && isRegular(bytes2[index])) index += 1;
|
|
9219
10141
|
if (index === start) index += 1;
|
|
9220
10142
|
this.#position = index;
|
|
9221
|
-
const text =
|
|
10143
|
+
const text = latin12(bytes2.subarray(start, index));
|
|
9222
10144
|
const value = Number(text);
|
|
9223
10145
|
if (/^[+-]?(\d+\.?\d*|\.\d+)$/.test(text) && Number.isFinite(value))
|
|
9224
10146
|
return { kind: "number", value, start, end: index };
|
|
@@ -9235,22 +10157,22 @@ function isWhitespace(byte) {
|
|
|
9235
10157
|
function isRegular(byte) {
|
|
9236
10158
|
return !isWhitespace(byte) && byte !== 40 && byte !== 41 && byte !== 60 && byte !== 62 && byte !== 91 && byte !== 93 && byte !== 123 && byte !== 125 && byte !== 47 && byte !== 37;
|
|
9237
10159
|
}
|
|
9238
|
-
function matchesAscii(
|
|
9239
|
-
if (at + text.length >
|
|
10160
|
+
function matchesAscii(bytes2, at, text) {
|
|
10161
|
+
if (at + text.length > bytes2.length) return false;
|
|
9240
10162
|
for (let index = 0; index < text.length; index += 1)
|
|
9241
|
-
if (
|
|
10163
|
+
if (bytes2[at + index] !== text.charCodeAt(index)) return false;
|
|
9242
10164
|
return true;
|
|
9243
10165
|
}
|
|
9244
|
-
function
|
|
10166
|
+
function latin12(bytes2) {
|
|
9245
10167
|
let text = "";
|
|
9246
|
-
for (let offset2 = 0; offset2 <
|
|
9247
|
-
text += String.fromCharCode(...
|
|
10168
|
+
for (let offset2 = 0; offset2 < bytes2.length; offset2 += 32768)
|
|
10169
|
+
text += String.fromCharCode(...bytes2.subarray(offset2, offset2 + 32768));
|
|
9248
10170
|
return text;
|
|
9249
10171
|
}
|
|
9250
10172
|
function ascii(text) {
|
|
9251
10173
|
return Uint8Array.from(text, (character) => character.charCodeAt(0) & 255);
|
|
9252
10174
|
}
|
|
9253
|
-
function
|
|
10175
|
+
function concat2(parts) {
|
|
9254
10176
|
const out = new Uint8Array(
|
|
9255
10177
|
parts.reduce((total, part) => total + part.byteLength, 0)
|
|
9256
10178
|
);
|
|
@@ -9276,10 +10198,10 @@ var AssetStore = class {
|
|
|
9276
10198
|
has(id) {
|
|
9277
10199
|
return this.#bytes.has(id);
|
|
9278
10200
|
}
|
|
9279
|
-
set(id,
|
|
10201
|
+
set(id, bytes2) {
|
|
9280
10202
|
if (this.#bytes.has(id)) return;
|
|
9281
|
-
this.#bytes.set(id,
|
|
9282
|
-
this.#total +=
|
|
10203
|
+
this.#bytes.set(id, bytes2);
|
|
10204
|
+
this.#total += bytes2.byteLength;
|
|
9283
10205
|
}
|
|
9284
10206
|
/** Bytes held, for limits. */
|
|
9285
10207
|
get byteLength() {
|
|
@@ -9289,8 +10211,8 @@ var AssetStore = class {
|
|
|
9289
10211
|
function resolveBinary(data, assets) {
|
|
9290
10212
|
if (data instanceof Uint8Array) return data;
|
|
9291
10213
|
if (isAssetReference(data)) {
|
|
9292
|
-
const
|
|
9293
|
-
if (!
|
|
10214
|
+
const bytes2 = assets.get(data);
|
|
10215
|
+
if (!bytes2)
|
|
9294
10216
|
throw new ViewerError("invalid-operation", `Unknown asset ${data}`, {
|
|
9295
10217
|
details: {
|
|
9296
10218
|
issues: [
|
|
@@ -9303,7 +10225,7 @@ function resolveBinary(data, assets) {
|
|
|
9303
10225
|
]
|
|
9304
10226
|
}
|
|
9305
10227
|
});
|
|
9306
|
-
return
|
|
10228
|
+
return bytes2;
|
|
9307
10229
|
}
|
|
9308
10230
|
return Uint8Array.from(atob(data), (character) => character.charCodeAt(0));
|
|
9309
10231
|
}
|
|
@@ -9318,17 +10240,17 @@ var ImageCache = class {
|
|
|
9318
10240
|
const operation2 = raw;
|
|
9319
10241
|
if (operation2.op !== "insertImage" || operation2.mimeType !== "image/png")
|
|
9320
10242
|
continue;
|
|
9321
|
-
const
|
|
9322
|
-
if (!isPng(
|
|
9323
|
-
const key = contentKey(
|
|
10243
|
+
const bytes2 = resolveBinary(operation2.data, assets);
|
|
10244
|
+
if (!isPng(bytes2)) continue;
|
|
10245
|
+
const key = contentKey(bytes2);
|
|
9324
10246
|
if (this.#decoded.has(key)) continue;
|
|
9325
|
-
this.#decoded.set(key, await decode(
|
|
10247
|
+
this.#decoded.set(key, await decode(bytes2, "image/png"));
|
|
9326
10248
|
while (this.#decoded.size > 8)
|
|
9327
10249
|
this.#decoded.delete(this.#decoded.keys().next().value);
|
|
9328
10250
|
}
|
|
9329
10251
|
}
|
|
9330
|
-
get(
|
|
9331
|
-
return this.#decoded.get(contentKey(
|
|
10252
|
+
get(bytes2) {
|
|
10253
|
+
return this.#decoded.get(contentKey(bytes2));
|
|
9332
10254
|
}
|
|
9333
10255
|
};
|
|
9334
10256
|
var insertImage = {
|
|
@@ -9338,19 +10260,19 @@ var insertImage = {
|
|
|
9338
10260
|
return;
|
|
9339
10261
|
}
|
|
9340
10262
|
validateRect(operation2.rect, context.geometry(operation2.pageIndex), issue);
|
|
9341
|
-
const
|
|
9342
|
-
if (
|
|
10263
|
+
const bytes2 = resolveBinary(operation2.data, context.assets);
|
|
10264
|
+
if (bytes2.byteLength > context.limits.maxInputBytes)
|
|
9343
10265
|
throw new ViewerError(
|
|
9344
10266
|
"resource-limit",
|
|
9345
10267
|
"Image data exceeds maxInputBytes",
|
|
9346
10268
|
{
|
|
9347
10269
|
details: {
|
|
9348
|
-
bytes:
|
|
10270
|
+
bytes: bytes2.byteLength,
|
|
9349
10271
|
limit: context.limits.maxInputBytes
|
|
9350
10272
|
}
|
|
9351
10273
|
}
|
|
9352
10274
|
);
|
|
9353
|
-
const size = operation2.mimeType === "image/png" ? pngSize(
|
|
10275
|
+
const size = operation2.mimeType === "image/png" ? pngSize(bytes2) : jpegSize(bytes2);
|
|
9354
10276
|
if (!size) {
|
|
9355
10277
|
issue(
|
|
9356
10278
|
"/data",
|
|
@@ -9366,19 +10288,19 @@ var insertImage = {
|
|
|
9366
10288
|
"Decoded image exceeds maxDecodedPixels",
|
|
9367
10289
|
{ details: { pixels, limit: context.limits.maxDecodedPixels } }
|
|
9368
10290
|
);
|
|
9369
|
-
if (operation2.mimeType === "image/png" && !context.images.get(
|
|
10291
|
+
if (operation2.mimeType === "image/png" && !context.images.get(bytes2))
|
|
9370
10292
|
issue("/data", "invalid-data", "The PNG could not be decoded");
|
|
9371
10293
|
},
|
|
9372
10294
|
apply(operation2, context) {
|
|
9373
10295
|
const { pdfium } = context;
|
|
9374
10296
|
const { lib } = pdfium;
|
|
9375
|
-
const
|
|
10297
|
+
const bytes2 = resolveBinary(operation2.data, context.assets);
|
|
9376
10298
|
const id = context.newId(operation2.pageIndex);
|
|
9377
10299
|
const geometry = context.geometry(operation2.pageIndex);
|
|
9378
10300
|
const image = lib.FPDFPageObj_NewImageObj(context.document);
|
|
9379
10301
|
if (operation2.mimeType === "image/jpeg") {
|
|
9380
10302
|
const loaded = pdfium.withFileAccess(
|
|
9381
|
-
|
|
10303
|
+
bytes2,
|
|
9382
10304
|
(fileAccess) => lib.FPDFImageObj_LoadJpegFileInline(0, 0, image, fileAccess)
|
|
9383
10305
|
);
|
|
9384
10306
|
if (!loaded)
|
|
@@ -9386,7 +10308,7 @@ var insertImage = {
|
|
|
9386
10308
|
details: { stage: "apply" }
|
|
9387
10309
|
});
|
|
9388
10310
|
} else {
|
|
9389
|
-
const decoded = context.images.get(
|
|
10311
|
+
const decoded = context.images.get(bytes2);
|
|
9390
10312
|
setBitmap(context.pdfium, image, decoded);
|
|
9391
10313
|
}
|
|
9392
10314
|
const { rect } = operation2;
|
|
@@ -9460,24 +10382,24 @@ function setBitmap(pdfium, image, decoded) {
|
|
|
9460
10382
|
pdfium.free(buffer);
|
|
9461
10383
|
}
|
|
9462
10384
|
}
|
|
9463
|
-
function isPng(
|
|
9464
|
-
return
|
|
10385
|
+
function isPng(bytes2) {
|
|
10386
|
+
return bytes2.length > 24 && bytes2[0] === 137 && bytes2[1] === 80 && bytes2[2] === 78 && bytes2[3] === 71;
|
|
9465
10387
|
}
|
|
9466
|
-
function pngSize(
|
|
9467
|
-
if (!isPng(
|
|
9468
|
-
const view = new DataView(
|
|
10388
|
+
function pngSize(bytes2) {
|
|
10389
|
+
if (!isPng(bytes2)) return void 0;
|
|
10390
|
+
const view = new DataView(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
9469
10391
|
const width = view.getUint32(16);
|
|
9470
10392
|
const height = view.getUint32(20);
|
|
9471
10393
|
return width > 0 && height > 0 ? { width, height } : void 0;
|
|
9472
10394
|
}
|
|
9473
|
-
function jpegSize(
|
|
9474
|
-
if (
|
|
10395
|
+
function jpegSize(bytes2) {
|
|
10396
|
+
if (bytes2.length < 4 || bytes2[0] !== 255 || bytes2[1] !== 216)
|
|
9475
10397
|
return void 0;
|
|
9476
|
-
const view = new DataView(
|
|
10398
|
+
const view = new DataView(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
9477
10399
|
let offset2 = 2;
|
|
9478
|
-
while (offset2 + 9 <
|
|
9479
|
-
if (
|
|
9480
|
-
const marker =
|
|
10400
|
+
while (offset2 + 9 < bytes2.length) {
|
|
10401
|
+
if (bytes2[offset2] !== 255) return void 0;
|
|
10402
|
+
const marker = bytes2[offset2 + 1];
|
|
9481
10403
|
if (marker === 216 || marker >= 208 && marker <= 215 || marker === 1) {
|
|
9482
10404
|
offset2 += 2;
|
|
9483
10405
|
continue;
|
|
@@ -9493,10 +10415,10 @@ function jpegSize(bytes) {
|
|
|
9493
10415
|
}
|
|
9494
10416
|
return void 0;
|
|
9495
10417
|
}
|
|
9496
|
-
function contentKey(
|
|
10418
|
+
function contentKey(bytes2) {
|
|
9497
10419
|
let hash = 2166136261;
|
|
9498
|
-
for (const byte of
|
|
9499
|
-
return `${
|
|
10420
|
+
for (const byte of bytes2) hash = Math.imul(hash ^ byte, 16777619) >>> 0;
|
|
10421
|
+
return `${bytes2.byteLength}:${hash.toString(16)}`;
|
|
9500
10422
|
}
|
|
9501
10423
|
|
|
9502
10424
|
// src/limits.ts
|
|
@@ -9542,12 +10464,12 @@ function detectFeatures(pdfium, document2, original) {
|
|
|
9542
10464
|
if (containsAscii(original, "pdfaid:part")) features.push("pdfa");
|
|
9543
10465
|
return features;
|
|
9544
10466
|
}
|
|
9545
|
-
function containsAscii(
|
|
10467
|
+
function containsAscii(bytes2, needle) {
|
|
9546
10468
|
const first = needle.charCodeAt(0);
|
|
9547
|
-
const limit =
|
|
9548
|
-
for (let at =
|
|
10469
|
+
const limit = bytes2.length - needle.length;
|
|
10470
|
+
for (let at = bytes2.indexOf(first); at >= 0 && at <= limit; at = bytes2.indexOf(first, at + 1)) {
|
|
9549
10471
|
let index = 1;
|
|
9550
|
-
while (index < needle.length &&
|
|
10472
|
+
while (index < needle.length && bytes2[at + index] === needle.charCodeAt(index))
|
|
9551
10473
|
index += 1;
|
|
9552
10474
|
if (index === needle.length) return true;
|
|
9553
10475
|
}
|
|
@@ -9612,6 +10534,8 @@ var PdfEditDocument = class {
|
|
|
9612
10534
|
#measurer;
|
|
9613
10535
|
#pages;
|
|
9614
10536
|
#batches = 0;
|
|
10537
|
+
/** Browser faces of the document's fonts, by font program; see `textFont`. */
|
|
10538
|
+
#faces = /* @__PURE__ */ new Map();
|
|
9615
10539
|
constructor(pdfium, original, fonts = new FontLibrary(async () => {
|
|
9616
10540
|
throw new Error("No font source is configured");
|
|
9617
10541
|
}), limits = defaultResourceLimits, assets = new AssetStore(), compact = compactPdf) {
|
|
@@ -9887,6 +10811,18 @@ var PdfEditDocument = class {
|
|
|
9887
10811
|
return element ? layoutOf(this.#pdfium, scan, element) : void 0;
|
|
9888
10812
|
});
|
|
9889
10813
|
}
|
|
10814
|
+
/** The browser face of the font a text or text box element is drawn in, see `TextFont`. */
|
|
10815
|
+
textFont(elementId) {
|
|
10816
|
+
const location = this.#locate(elementId);
|
|
10817
|
+
const element = location && this.getElement(elementId);
|
|
10818
|
+
if (!element || element.kind !== "text" && element.kind !== "textBox")
|
|
10819
|
+
return void 0;
|
|
10820
|
+
const { lib } = this.#pdfium;
|
|
10821
|
+
return this.#withPage(location.pageIndex, (page) => {
|
|
10822
|
+
const object = location.indexes.map((index) => lib.FPDFPage_GetObject(page, index)).find((entry) => lib.FPDFPageObj_GetType(entry) === OBJECT_TEXT);
|
|
10823
|
+
return object === void 0 ? void 0 : { elementId, ...textFaceOf(this.#pdfium, object, this.#faces) };
|
|
10824
|
+
});
|
|
10825
|
+
}
|
|
9890
10826
|
/** The layouts of every text element on a page, with the page's displayed size. */
|
|
9891
10827
|
pageLayout(pageIndex) {
|
|
9892
10828
|
if (pageIndex < 0 || pageIndex >= this.#pages.length) return void 0;
|
|
@@ -10043,8 +10979,11 @@ var PdfEditDocument = class {
|
|
|
10043
10979
|
},
|
|
10044
10980
|
// Ids name the state the batch leads to, the operation and the item,
|
|
10045
10981
|
// so replaying the history reproduces them and an undone id is never
|
|
10046
|
-
// handed out again.
|
|
10047
|
-
|
|
10982
|
+
// handed out again. A file saved by an earlier session carries the ids
|
|
10983
|
+
// that session numbered from 1 as well, so one already on the page
|
|
10984
|
+
// gets the first free `~n` instead (ACTION-886); the saved objects are
|
|
10985
|
+
// part of the base, so a replay meets them and picks the same id.
|
|
10986
|
+
newId: (pageIndex, suffix = "") => `${this.#unusedId(pageIndex, `${this.#pages[pageIndex].key}:n${stateId}.${operationIndex}.${created++}`)}${suffix}`,
|
|
10048
10987
|
withPage: (pageIndex, use) => this.#writePage(pageIndex, use),
|
|
10049
10988
|
appendObjects: (pageIndex, records) => {
|
|
10050
10989
|
const page = this.#pages[pageIndex];
|
|
@@ -10191,8 +11130,8 @@ var PdfEditDocument = class {
|
|
|
10191
11130
|
const textPage = lib.FPDFText_LoadPage(page);
|
|
10192
11131
|
try {
|
|
10193
11132
|
for (const [id, indexes] of members) {
|
|
10194
|
-
const
|
|
10195
|
-
if (!
|
|
11133
|
+
const head2 = heads.get(id);
|
|
11134
|
+
if (!head2 || !markIsFresh(this.#pdfium, page, textPage, geometry, head2, indexes))
|
|
10196
11135
|
stale.add(id);
|
|
10197
11136
|
}
|
|
10198
11137
|
} finally {
|
|
@@ -10200,10 +11139,48 @@ var PdfEditDocument = class {
|
|
|
10200
11139
|
}
|
|
10201
11140
|
}
|
|
10202
11141
|
record.objects = objects.map(
|
|
10203
|
-
(object, index) => object.mark && stale.has(object.id) ? {
|
|
11142
|
+
(object, index) => object.mark && stale.has(object.id) ? {
|
|
11143
|
+
id: `${record.key}:o${index}`,
|
|
11144
|
+
type: object.type,
|
|
11145
|
+
staleMarkId: object.id
|
|
11146
|
+
} : object
|
|
10204
11147
|
);
|
|
10205
11148
|
return record.objects;
|
|
10206
11149
|
}
|
|
11150
|
+
/**
|
|
11151
|
+
* `id`, or its first free `~n` when an object saved by an earlier session
|
|
11152
|
+
* has it already. Only ids a session numbered (`<key>:n…`) can collide, so
|
|
11153
|
+
* only those are gathered; the objects are read without the page's text.
|
|
11154
|
+
*/
|
|
11155
|
+
#unusedId(pageIndex, id) {
|
|
11156
|
+
const record = this.#pages[pageIndex];
|
|
11157
|
+
const objects = record.objects ?? this.#loadObjects(pageIndex);
|
|
11158
|
+
const numbered = `${record.key}:n`;
|
|
11159
|
+
const taken = /* @__PURE__ */ new Set();
|
|
11160
|
+
for (const object of objects) {
|
|
11161
|
+
if (object.id.startsWith(numbered)) taken.add(object.id);
|
|
11162
|
+
if (object.staleMarkId?.startsWith(numbered))
|
|
11163
|
+
taken.add(object.staleMarkId);
|
|
11164
|
+
}
|
|
11165
|
+
if (!taken.has(id)) return id;
|
|
11166
|
+
let suffix = 1;
|
|
11167
|
+
while (taken.has(`${id}~${suffix}`)) suffix += 1;
|
|
11168
|
+
return `${id}~${suffix}`;
|
|
11169
|
+
}
|
|
11170
|
+
/** A page's objects, loading the page alone when they are not known yet. */
|
|
11171
|
+
#loadObjects(pageIndex) {
|
|
11172
|
+
const { lib } = this.#pdfium;
|
|
11173
|
+
const page = lib.FPDF_LoadPage(this.#document.handle, pageIndex);
|
|
11174
|
+
if (!page)
|
|
11175
|
+
throw new ViewerError("render-failed", "PDFium could not load the page", {
|
|
11176
|
+
details: { pageIndex }
|
|
11177
|
+
});
|
|
11178
|
+
try {
|
|
11179
|
+
return this.#objectsOf(pageIndex, page);
|
|
11180
|
+
} finally {
|
|
11181
|
+
lib.FPDF_ClosePage(page);
|
|
11182
|
+
}
|
|
11183
|
+
}
|
|
10207
11184
|
/** Marks from other sessions keep their id only if it cannot collide with ours. */
|
|
10208
11185
|
#ownMark(mark, pageKey) {
|
|
10209
11186
|
return mark.id.startsWith(`${pageKey}:`) ? mark : { ...mark, id: `${pageKey}:${mark.id}` };
|
|
@@ -10272,12 +11249,12 @@ var PdfEditDocument = class {
|
|
|
10272
11249
|
const { lib } = this.#pdfium;
|
|
10273
11250
|
const count = lib.FPDFText_CountChars(textPage);
|
|
10274
11251
|
if (count === 0) return;
|
|
10275
|
-
const
|
|
10276
|
-
const buffer = this.#pdfium.malloc(
|
|
11252
|
+
const bytes2 = (count + 1) * 2;
|
|
11253
|
+
const buffer = this.#pdfium.malloc(bytes2);
|
|
10277
11254
|
let text;
|
|
10278
11255
|
try {
|
|
10279
11256
|
lib.FPDFText_GetText(textPage, 0, count, buffer);
|
|
10280
|
-
text = this.#pdfium.readWideStringAt(buffer,
|
|
11257
|
+
text = this.#pdfium.readWideStringAt(buffer, bytes2);
|
|
10281
11258
|
} finally {
|
|
10282
11259
|
this.#pdfium.free(buffer);
|
|
10283
11260
|
}
|
|
@@ -10318,7 +11295,7 @@ var PdfEditDocument = class {
|
|
|
10318
11295
|
}
|
|
10319
11296
|
if (!bases.has(object)) {
|
|
10320
11297
|
const own = this.#pdfium.readWideString(
|
|
10321
|
-
(buffer,
|
|
11298
|
+
(buffer, bytes2) => lib.FPDFTextObj_GetText(object, textPage, buffer, bytes2)
|
|
10322
11299
|
);
|
|
10323
11300
|
const whole = elementTexts.get(elementId) ?? "";
|
|
10324
11301
|
const from = cursors.get(elementId) ?? 0;
|
|
@@ -10450,11 +11427,11 @@ function createPdfEditHandler(host) {
|
|
|
10450
11427
|
case "edit-materialize": {
|
|
10451
11428
|
const { purpose, options } = payload ?? {};
|
|
10452
11429
|
const mode = options?.mode;
|
|
10453
|
-
const { bytes, warnings } = engine().materializeDocument(
|
|
11430
|
+
const { bytes: bytes2, warnings } = engine().materializeDocument(
|
|
10454
11431
|
purpose ?? "show",
|
|
10455
11432
|
mode === "full" || mode === "incremental" ? mode : void 0
|
|
10456
11433
|
);
|
|
10457
|
-
return { data:
|
|
11434
|
+
return { data: bytes2.buffer, warnings };
|
|
10458
11435
|
}
|
|
10459
11436
|
case "edit-restore": {
|
|
10460
11437
|
const { batches, base } = payload;
|
|
@@ -10495,6 +11472,8 @@ function createPdfEditHandler(host) {
|
|
|
10495
11472
|
const { pageIndex, elementIds, scale } = payload;
|
|
10496
11473
|
return engine().renderPageWithout(pageIndex, elementIds, scale);
|
|
10497
11474
|
}
|
|
11475
|
+
case "edit-text-font":
|
|
11476
|
+
return engine().textFont(payload.id);
|
|
10498
11477
|
case "edit-page-layout":
|
|
10499
11478
|
return engine().pageLayout(
|
|
10500
11479
|
payload.pageIndex
|
|
@@ -10546,9 +11525,9 @@ var Pdfium = class _Pdfium {
|
|
|
10546
11525
|
if (pointer) this.#runtime.wasmExports.free(pointer);
|
|
10547
11526
|
}
|
|
10548
11527
|
/** Copies bytes into the WASM heap; the caller frees the pointer. */
|
|
10549
|
-
writeBytes(
|
|
10550
|
-
const pointer = this.malloc(
|
|
10551
|
-
this.#runtime.HEAPU8.set(
|
|
11528
|
+
writeBytes(bytes2) {
|
|
11529
|
+
const pointer = this.malloc(bytes2.byteLength);
|
|
11530
|
+
this.#runtime.HEAPU8.set(bytes2, pointer);
|
|
10552
11531
|
return pointer;
|
|
10553
11532
|
}
|
|
10554
11533
|
readBytes(pointer, length) {
|
|
@@ -10556,26 +11535,26 @@ var Pdfium = class _Pdfium {
|
|
|
10556
11535
|
}
|
|
10557
11536
|
/** Writes a NUL-terminated UTF-16LE string; the caller frees the pointer. */
|
|
10558
11537
|
writeWideString(text) {
|
|
10559
|
-
const
|
|
10560
|
-
const pointer = this.malloc(
|
|
10561
|
-
this.#runtime.stringToUTF16(text, pointer,
|
|
11538
|
+
const bytes2 = (text.length + 1) * 2;
|
|
11539
|
+
const pointer = this.malloc(bytes2);
|
|
11540
|
+
this.#runtime.stringToUTF16(text, pointer, bytes2);
|
|
10562
11541
|
return pointer;
|
|
10563
11542
|
}
|
|
10564
11543
|
/** Reads a NUL-terminated UTF-16LE string of at most `bytes` bytes. */
|
|
10565
|
-
readWideStringAt(pointer,
|
|
10566
|
-
return this.#runtime.UTF16ToString(pointer,
|
|
11544
|
+
readWideStringAt(pointer, bytes2) {
|
|
11545
|
+
return this.#runtime.UTF16ToString(pointer, bytes2);
|
|
10567
11546
|
}
|
|
10568
11547
|
/**
|
|
10569
11548
|
* Reads a UTF-16LE string from an API that returns the byte size it needs
|
|
10570
11549
|
* when called with an empty buffer.
|
|
10571
11550
|
*/
|
|
10572
11551
|
readWideString(read2) {
|
|
10573
|
-
const
|
|
10574
|
-
if (
|
|
10575
|
-
const pointer = this.malloc(
|
|
11552
|
+
const bytes2 = read2(0, 0);
|
|
11553
|
+
if (bytes2 <= 2) return "";
|
|
11554
|
+
const pointer = this.malloc(bytes2);
|
|
10576
11555
|
try {
|
|
10577
|
-
read2(pointer,
|
|
10578
|
-
return this.#runtime.UTF16ToString(pointer,
|
|
11556
|
+
read2(pointer, bytes2);
|
|
11557
|
+
return this.#runtime.UTF16ToString(pointer, bytes2);
|
|
10579
11558
|
} finally {
|
|
10580
11559
|
this.free(pointer);
|
|
10581
11560
|
}
|
|
@@ -10588,12 +11567,12 @@ var Pdfium = class _Pdfium {
|
|
|
10588
11567
|
const outBytes = this.malloc(4);
|
|
10589
11568
|
try {
|
|
10590
11569
|
if (!read2(0, 0, outBytes)) return "";
|
|
10591
|
-
const
|
|
10592
|
-
if (
|
|
10593
|
-
const pointer = this.malloc(
|
|
11570
|
+
const bytes2 = this.#runtime.getValue(outBytes, "i32");
|
|
11571
|
+
if (bytes2 <= 2) return "";
|
|
11572
|
+
const pointer = this.malloc(bytes2);
|
|
10594
11573
|
try {
|
|
10595
|
-
if (!read2(pointer,
|
|
10596
|
-
return this.#runtime.UTF16ToString(pointer,
|
|
11574
|
+
if (!read2(pointer, bytes2, outBytes)) return "";
|
|
11575
|
+
return this.#runtime.UTF16ToString(pointer, bytes2);
|
|
10597
11576
|
} finally {
|
|
10598
11577
|
this.free(pointer);
|
|
10599
11578
|
}
|
|
@@ -10603,12 +11582,12 @@ var Pdfium = class _Pdfium {
|
|
|
10603
11582
|
}
|
|
10604
11583
|
/** Reads a NUL-terminated UTF-8 string from an API that returns the byte size it needs. */
|
|
10605
11584
|
readUtf8String(read2) {
|
|
10606
|
-
const
|
|
10607
|
-
if (
|
|
10608
|
-
const pointer = this.malloc(
|
|
11585
|
+
const bytes2 = read2(0, 0);
|
|
11586
|
+
if (bytes2 <= 1) return "";
|
|
11587
|
+
const pointer = this.malloc(bytes2);
|
|
10609
11588
|
try {
|
|
10610
|
-
read2(pointer,
|
|
10611
|
-
const raw = this.readBytes(pointer,
|
|
11589
|
+
read2(pointer, bytes2);
|
|
11590
|
+
const raw = this.readBytes(pointer, bytes2);
|
|
10612
11591
|
const end = raw.indexOf(0);
|
|
10613
11592
|
return new TextDecoder().decode(end < 0 ? raw : raw.subarray(0, end));
|
|
10614
11593
|
} finally {
|
|
@@ -10643,20 +11622,20 @@ var Pdfium = class _Pdfium {
|
|
|
10643
11622
|
* a WASM table callback. Only for APIs that read the data before returning,
|
|
10644
11623
|
* such as the inline JPEG loader.
|
|
10645
11624
|
*/
|
|
10646
|
-
withFileAccess(
|
|
11625
|
+
withFileAccess(bytes2, use) {
|
|
10647
11626
|
const runtime = this.#runtime;
|
|
10648
11627
|
const callback = runtime.addFunction(
|
|
10649
11628
|
(_parameter, position, buffer, size) => {
|
|
10650
|
-
if (position < 0 || size < 0 || position + size >
|
|
11629
|
+
if (position < 0 || size < 0 || position + size > bytes2.byteLength)
|
|
10651
11630
|
return 0;
|
|
10652
|
-
runtime.HEAPU8.set(
|
|
11631
|
+
runtime.HEAPU8.set(bytes2.subarray(position, position + size), buffer);
|
|
10653
11632
|
return 1;
|
|
10654
11633
|
},
|
|
10655
11634
|
"iiiii"
|
|
10656
11635
|
);
|
|
10657
11636
|
const fileAccess = this.malloc(FILE_ACCESS_BYTES);
|
|
10658
11637
|
try {
|
|
10659
|
-
runtime.setValue(fileAccess,
|
|
11638
|
+
runtime.setValue(fileAccess, bytes2.byteLength, "i32");
|
|
10660
11639
|
runtime.setValue(fileAccess + 4, callback, "i32");
|
|
10661
11640
|
runtime.setValue(fileAccess + 8, 0, "i32");
|
|
10662
11641
|
return use(fileAccess);
|
|
@@ -10666,9 +11645,9 @@ var Pdfium = class _Pdfium {
|
|
|
10666
11645
|
}
|
|
10667
11646
|
}
|
|
10668
11647
|
/** Opens a document from bytes; PDFium reads them lazily, so they stay in the heap. */
|
|
10669
|
-
openDocument(
|
|
10670
|
-
const data = this.writeBytes(
|
|
10671
|
-
const handle = this.lib.FPDF_LoadMemDocument(data,
|
|
11648
|
+
openDocument(bytes2) {
|
|
11649
|
+
const data = this.writeBytes(bytes2);
|
|
11650
|
+
const handle = this.lib.FPDF_LoadMemDocument(data, bytes2.byteLength, "");
|
|
10672
11651
|
if (!handle) {
|
|
10673
11652
|
const error = this.lib.FPDF_GetLastError();
|
|
10674
11653
|
this.free(data);
|
|
@@ -10733,9 +11712,9 @@ var PdfiumDocument = class {
|
|
|
10733
11712
|
this.#pdfium.free(this.#data);
|
|
10734
11713
|
}
|
|
10735
11714
|
};
|
|
10736
|
-
function exactArrayBuffer(
|
|
10737
|
-
if (
|
|
10738
|
-
return
|
|
11715
|
+
function exactArrayBuffer(bytes2) {
|
|
11716
|
+
if (bytes2 instanceof ArrayBuffer) return bytes2;
|
|
11717
|
+
return bytes2.buffer instanceof ArrayBuffer && bytes2.byteOffset === 0 && bytes2.byteLength === bytes2.buffer.byteLength ? bytes2.buffer : bytes2.slice().buffer;
|
|
10739
11718
|
}
|
|
10740
11719
|
|
|
10741
11720
|
// src/worker-protocol.ts
|
|
@@ -10820,9 +11799,9 @@ attachWorkerEndpoint(
|
|
|
10820
11799
|
createPdfEditHandler({
|
|
10821
11800
|
loadPdfium: async (wasmUrl) => Pdfium.load(await fetchBytes(wasmUrl)),
|
|
10822
11801
|
fetchBytes,
|
|
10823
|
-
decodeImage: async (
|
|
11802
|
+
decodeImage: async (bytes2, mimeType) => {
|
|
10824
11803
|
const bitmap = await createImageBitmap(
|
|
10825
|
-
new Blob([new Uint8Array(
|
|
11804
|
+
new Blob([new Uint8Array(bytes2)], { type: mimeType })
|
|
10826
11805
|
);
|
|
10827
11806
|
try {
|
|
10828
11807
|
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|