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
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ViewerError } from "../../../errors.js";
|
|
2
2
|
import { invalidOperationError, parseReference } from "../../operations.js";
|
|
3
3
|
import { layoutOf, layoutsOf, positionIn, rectsOf, } from "./layout.js";
|
|
4
|
-
import { markIsFresh, readMark, scanPage, } from "./elements.js";
|
|
4
|
+
import { markIsFresh, OBJECT_TEXT, readMark, scanPage, } from "./elements.js";
|
|
5
5
|
import { FontLibrary, TextMeasurer } from "./fonts.js";
|
|
6
|
+
import { textFaceOf } from "./text-font.js";
|
|
6
7
|
import { fontRequestsOf } from "./text-box.js";
|
|
7
8
|
import { issueCollector, } from "./operations.js";
|
|
8
9
|
import { insertTextBox } from "./text-box.js";
|
|
@@ -123,6 +124,8 @@ export class PdfEditDocument {
|
|
|
123
124
|
#measurer;
|
|
124
125
|
#pages;
|
|
125
126
|
#batches = 0;
|
|
127
|
+
/** Browser faces of the document's fonts, by font program; see `textFont`. */
|
|
128
|
+
#faces = new Map();
|
|
126
129
|
constructor(pdfium, original, fonts = new FontLibrary(async () => {
|
|
127
130
|
throw new Error("No font source is configured");
|
|
128
131
|
}), limits = defaultResourceLimits, assets = new AssetStore(), compact = compactPdf) {
|
|
@@ -402,6 +405,23 @@ export class PdfEditDocument {
|
|
|
402
405
|
return element ? layoutOf(this.#pdfium, scan, element) : undefined;
|
|
403
406
|
});
|
|
404
407
|
}
|
|
408
|
+
/** The browser face of the font a text or text box element is drawn in, see `TextFont`. */
|
|
409
|
+
textFont(elementId) {
|
|
410
|
+
const location = this.#locate(elementId);
|
|
411
|
+
const element = location && this.getElement(elementId);
|
|
412
|
+
if (!element || (element.kind !== "text" && element.kind !== "textBox"))
|
|
413
|
+
return undefined;
|
|
414
|
+
const { lib } = this.#pdfium;
|
|
415
|
+
return this.#withPage(location.pageIndex, (page) => {
|
|
416
|
+
// A text box's lines share their font; its first line answers.
|
|
417
|
+
const object = location.indexes
|
|
418
|
+
.map((index) => lib.FPDFPage_GetObject(page, index))
|
|
419
|
+
.find((entry) => lib.FPDFPageObj_GetType(entry) === OBJECT_TEXT);
|
|
420
|
+
return object === undefined
|
|
421
|
+
? undefined
|
|
422
|
+
: { elementId, ...textFaceOf(this.#pdfium, object, this.#faces) };
|
|
423
|
+
});
|
|
424
|
+
}
|
|
405
425
|
/** The layouts of every text element on a page, with the page's displayed size. */
|
|
406
426
|
pageLayout(pageIndex) {
|
|
407
427
|
if (pageIndex < 0 || pageIndex >= this.#pages.length)
|
|
@@ -535,8 +555,11 @@ export class PdfEditDocument {
|
|
|
535
555
|
},
|
|
536
556
|
// Ids name the state the batch leads to, the operation and the item,
|
|
537
557
|
// so replaying the history reproduces them and an undone id is never
|
|
538
|
-
// handed out again.
|
|
539
|
-
|
|
558
|
+
// handed out again. A file saved by an earlier session carries the ids
|
|
559
|
+
// that session numbered from 1 as well, so one already on the page
|
|
560
|
+
// gets the first free `~n` instead (ACTION-886); the saved objects are
|
|
561
|
+
// part of the base, so a replay meets them and picks the same id.
|
|
562
|
+
newId: (pageIndex, suffix = "") => `${this.#unusedId(pageIndex, `${this.#pages[pageIndex].key}:n${stateId}.${operationIndex}.${created++}`)}${suffix}`,
|
|
540
563
|
withPage: (pageIndex, use) => this.#writePage(pageIndex, use),
|
|
541
564
|
appendObjects: (pageIndex, records) => {
|
|
542
565
|
const page = this.#pages[pageIndex];
|
|
@@ -686,10 +709,52 @@ export class PdfEditDocument {
|
|
|
686
709
|
}
|
|
687
710
|
}
|
|
688
711
|
record.objects = objects.map((object, index) => object.mark && stale.has(object.id)
|
|
689
|
-
? {
|
|
712
|
+
? {
|
|
713
|
+
id: `${record.key}:o${index}`,
|
|
714
|
+
type: object.type,
|
|
715
|
+
staleMarkId: object.id,
|
|
716
|
+
}
|
|
690
717
|
: object);
|
|
691
718
|
return record.objects;
|
|
692
719
|
}
|
|
720
|
+
/**
|
|
721
|
+
* `id`, or its first free `~n` when an object saved by an earlier session
|
|
722
|
+
* has it already. Only ids a session numbered (`<key>:n…`) can collide, so
|
|
723
|
+
* only those are gathered; the objects are read without the page's text.
|
|
724
|
+
*/
|
|
725
|
+
#unusedId(pageIndex, id) {
|
|
726
|
+
const record = this.#pages[pageIndex];
|
|
727
|
+
const objects = record.objects ?? this.#loadObjects(pageIndex);
|
|
728
|
+
const numbered = `${record.key}:n`;
|
|
729
|
+
const taken = new Set();
|
|
730
|
+
for (const object of objects) {
|
|
731
|
+
if (object.id.startsWith(numbered))
|
|
732
|
+
taken.add(object.id);
|
|
733
|
+
if (object.staleMarkId?.startsWith(numbered))
|
|
734
|
+
taken.add(object.staleMarkId);
|
|
735
|
+
}
|
|
736
|
+
if (!taken.has(id))
|
|
737
|
+
return id;
|
|
738
|
+
let suffix = 1;
|
|
739
|
+
while (taken.has(`${id}~${suffix}`))
|
|
740
|
+
suffix += 1;
|
|
741
|
+
return `${id}~${suffix}`;
|
|
742
|
+
}
|
|
743
|
+
/** A page's objects, loading the page alone when they are not known yet. */
|
|
744
|
+
#loadObjects(pageIndex) {
|
|
745
|
+
const { lib } = this.#pdfium;
|
|
746
|
+
const page = lib.FPDF_LoadPage(this.#document.handle, pageIndex);
|
|
747
|
+
if (!page)
|
|
748
|
+
throw new ViewerError("render-failed", "PDFium could not load the page", {
|
|
749
|
+
details: { pageIndex },
|
|
750
|
+
});
|
|
751
|
+
try {
|
|
752
|
+
return this.#objectsOf(pageIndex, page);
|
|
753
|
+
}
|
|
754
|
+
finally {
|
|
755
|
+
lib.FPDF_ClosePage(page);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
693
758
|
/** Marks from other sessions keep their id only if it cannot collide with ours. */
|
|
694
759
|
#ownMark(mark, pageKey) {
|
|
695
760
|
return mark.id.startsWith(`${pageKey}:`)
|
|
@@ -21,6 +21,12 @@ export interface ObjectRecord {
|
|
|
21
21
|
readonly id: string;
|
|
22
22
|
readonly type: number;
|
|
23
23
|
readonly mark?: MarkParams;
|
|
24
|
+
/**
|
|
25
|
+
* The id a mark the file still carries names, on an object listed as plain
|
|
26
|
+
* because the mark failed its check: a new id must not take it, or saving
|
|
27
|
+
* would join the new object to this one.
|
|
28
|
+
*/
|
|
29
|
+
readonly staleMarkId?: string;
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
32
|
* Reads the objects of a loaded page in drawing order and turns them into
|
|
@@ -41,5 +47,12 @@ export declare function readMark(pdfium: Pdfium, object: number): MarkParams | u
|
|
|
41
47
|
*/
|
|
42
48
|
export declare function markIsFresh(pdfium: Pdfium, page: number, textPage: number, geometry: PageGeometry, mark: MarkParams, indexes: readonly number[]): boolean;
|
|
43
49
|
export declare function objectBounds(pdfium: Pdfium, object: number, geometry: PageGeometry): PageRect | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* How much a text object's matrix scales its glyphs: the length of its
|
|
52
|
+
* vertical axis. Producers often write `1 Tf` and carry the size in the
|
|
53
|
+
* matrix, so the point size the text shows is its font size times this; a
|
|
54
|
+
* turn or a horizontal squeeze leaves it alone.
|
|
55
|
+
*/
|
|
56
|
+
export declare function textScale(matrix: readonly number[] | undefined): number;
|
|
44
57
|
export declare function textStyle(pdfium: Pdfium, object: number): PdfTextStyle;
|
|
45
58
|
export declare function hex(rgba: readonly number[]): string;
|
|
@@ -232,6 +232,16 @@ const TABLE_OPERATIONS = Object.freeze([
|
|
|
232
232
|
function textOf(pdfium, object, textPage) {
|
|
233
233
|
return pdfium.readWideString((buffer, bytes) => pdfium.lib.FPDFTextObj_GetText(object, textPage, buffer, bytes));
|
|
234
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* How much a text object's matrix scales its glyphs: the length of its
|
|
237
|
+
* vertical axis. Producers often write `1 Tf` and carry the size in the
|
|
238
|
+
* matrix, so the point size the text shows is its font size times this; a
|
|
239
|
+
* turn or a horizontal squeeze leaves it alone.
|
|
240
|
+
*/
|
|
241
|
+
export function textScale(matrix) {
|
|
242
|
+
const scale = matrix ? Math.hypot(matrix[2], matrix[3]) : 1;
|
|
243
|
+
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
244
|
+
}
|
|
235
245
|
export function textStyle(pdfium, object) {
|
|
236
246
|
const { lib } = pdfium;
|
|
237
247
|
const font = lib.FPDFTextObj_GetFont(object);
|
|
@@ -245,9 +255,10 @@ export function textStyle(pdfium, object) {
|
|
|
245
255
|
const flags = lib.FPDFFont_GetFlags(font);
|
|
246
256
|
const weight = lib.FPDFFont_GetWeight(font);
|
|
247
257
|
const size = pdfium.readNumbers(1, "float", ([pointer]) => lib.FPDFTextObj_GetFontSize(object, pointer))?.[0] ?? 0;
|
|
258
|
+
const matrix = pdfium.readNumbers(6, "float", ([pointer]) => lib.FPDFPageObj_GetMatrix(object, pointer));
|
|
248
259
|
return {
|
|
249
260
|
fontFamily: family,
|
|
250
|
-
fontSize: round(size),
|
|
261
|
+
fontSize: round(size * textScale(matrix)),
|
|
251
262
|
bold: weight >= 600 ||
|
|
252
263
|
(flags & FLAG_FORCE_BOLD) !== 0 ||
|
|
253
264
|
/bold|black|heavy/i.test(baseName),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { objectBounds, OBJECT_TEXT } from "./elements.js";
|
|
1
|
+
import { objectBounds, OBJECT_TEXT, textScale } from "./elements.js";
|
|
2
2
|
import { firstNonWinAnsi, isStandardFamily, parseCmap, } from "./fonts.js";
|
|
3
3
|
import { pageToUser } from "./geometry.js";
|
|
4
4
|
import { parseColor, setText, textBoxReplaceText, textBoxSetTextStyle, textBoxTarget, } from "./text-box.js";
|
|
@@ -255,7 +255,7 @@ function splitAround(context, target, before, middle, after) {
|
|
|
255
255
|
const old = lib.FPDFPage_GetObject(page, index);
|
|
256
256
|
const oldFont = lib.FPDFTextObj_GetFont(old);
|
|
257
257
|
const matrix = pdfium.readNumbers(6, "float", ([pointer]) => lib.FPDFPageObj_GetMatrix(old, pointer)) ?? [1, 0, 0, 1, 0, 0];
|
|
258
|
-
const size = pdfium.readNumbers(1, "float", ([pointer]) => lib.FPDFTextObj_GetFontSize(old, pointer))?.[0] ?? style.fontSize;
|
|
258
|
+
const size = pdfium.readNumbers(1, "float", ([pointer]) => lib.FPDFTextObj_GetFontSize(old, pointer))?.[0] ?? style.fontSize / textScale(matrix);
|
|
259
259
|
const [a, b, c, d, e, f] = matrix;
|
|
260
260
|
const [r, g, bl] = parseColor(style.color);
|
|
261
261
|
const parts = [
|
|
@@ -349,7 +349,7 @@ function replaceWithFallback(context, target, text) {
|
|
|
349
349
|
context.withPage(location.pageIndex, (page) => {
|
|
350
350
|
const old = lib.FPDFPage_GetObject(page, index);
|
|
351
351
|
const matrix = pdfium.readNumbers(6, "float", ([pointer]) => lib.FPDFPageObj_GetMatrix(old, pointer)) ?? [1, 0, 0, 1, 0, 0];
|
|
352
|
-
const size = pdfium.readNumbers(1, "float", ([pointer]) => lib.FPDFTextObj_GetFontSize(old, pointer))?.[0] ?? style.fontSize;
|
|
352
|
+
const size = pdfium.readNumbers(1, "float", ([pointer]) => lib.FPDFTextObj_GetFontSize(old, pointer))?.[0] ?? style.fontSize / textScale(matrix);
|
|
353
353
|
const object = lib.FPDFPageObj_CreateTextObj(context.document, font.handle, size);
|
|
354
354
|
setText(pdfium, object, text);
|
|
355
355
|
const [r, g, b] = parseColor(style.color);
|
|
@@ -399,7 +399,9 @@ function resize(context, target, fontSize) {
|
|
|
399
399
|
}
|
|
400
400
|
const matrix = pdfium.readNumbers(6, "float", ([pointer]) => lib.FPDFPageObj_GetMatrix(old, pointer)) ?? [1, 0, 0, 1, 0, 0];
|
|
401
401
|
const color = pdfium.readNumbers(4, "i32", ([r, g, b, a]) => lib.FPDFPageObj_GetFillColor(old, r, g, b, a)) ?? [0, 0, 0, 255];
|
|
402
|
-
|
|
402
|
+
// The size is the one the text shows: the old matrix, applied below,
|
|
403
|
+
// scales it again, so the font gets the size undone by that scale.
|
|
404
|
+
const object = lib.FPDFPageObj_CreateTextObj(context.document, lib.FPDFTextObj_GetFont(old), fontSize / textScale(matrix));
|
|
403
405
|
setText(pdfium, object, text);
|
|
404
406
|
lib.FPDFPageObj_SetFillColor(object, color[0], color[1], color[2], color[3]);
|
|
405
407
|
const [a, b, c, d, e, f] = matrix;
|
|
@@ -110,7 +110,13 @@ export class FontLibrary {
|
|
|
110
110
|
return undefined;
|
|
111
111
|
if (this.#fallback && this.#covers(this.#fallback, request.text))
|
|
112
112
|
return undefined;
|
|
113
|
-
|
|
113
|
+
// Name the character that actually stops the text: the first one the
|
|
114
|
+
// fallback lacks when it was tried, else the first the standard fonts
|
|
115
|
+
// cannot encode. Naming the first Cyrillic letter for a dash the
|
|
116
|
+
// fallback lacked sent people after the wrong character (ACTION-879).
|
|
117
|
+
const bad = this.#fallback
|
|
118
|
+
? this.#firstMissing(this.#fallback, request.text)
|
|
119
|
+
: firstNonWinAnsi(request.text);
|
|
114
120
|
return {
|
|
115
121
|
path: "/text",
|
|
116
122
|
code: "font-unavailable",
|
|
@@ -175,6 +181,10 @@ export class FontLibrary {
|
|
|
175
181
|
return candidates.sort((a, b) => score(b.font) - score(a.font))[0];
|
|
176
182
|
}
|
|
177
183
|
#covers(bytes, text) {
|
|
184
|
+
return this.#firstMissing(bytes, text) === undefined;
|
|
185
|
+
}
|
|
186
|
+
/** The first character of `text` the font has no glyph for; layout handles line breaks and spaces. */
|
|
187
|
+
#firstMissing(bytes, text) {
|
|
178
188
|
let coverage = this.#coverage.get(bytes);
|
|
179
189
|
if (!coverage) {
|
|
180
190
|
coverage = parseCmap(bytes);
|
|
@@ -185,9 +195,9 @@ export class FontLibrary {
|
|
|
185
195
|
if (code === 0x0a || code === 0x20)
|
|
186
196
|
continue;
|
|
187
197
|
if (!coverage.has(code))
|
|
188
|
-
return
|
|
198
|
+
return character;
|
|
189
199
|
}
|
|
190
|
-
return
|
|
200
|
+
return undefined;
|
|
191
201
|
}
|
|
192
202
|
#load(pdfium, document, bytes) {
|
|
193
203
|
let handles = this.#handles.get(document);
|
|
@@ -242,13 +252,6 @@ function isBold(font) {
|
|
|
242
252
|
function isItalic(font) {
|
|
243
253
|
return font.style !== "normal";
|
|
244
254
|
}
|
|
245
|
-
function firstUncovered(text, library) {
|
|
246
|
-
void library;
|
|
247
|
-
for (const character of text)
|
|
248
|
-
if (character !== "\n" && character !== " ")
|
|
249
|
-
return character;
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
255
|
/** The code points a TrueType font maps to glyphs, from its cmap table. */
|
|
253
256
|
/**
|
|
254
257
|
* Whether glyphs of a TrueType font have outline data: a subset font can keep
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Glyph names and the code points they stand for: the Adobe Glyph List For
|
|
3
|
+
* New Fonts 1.7 (aglfn.txt), and from the Adobe Glyph List 2.0
|
|
4
|
+
* (glyphlist.txt) the ligatures, superior figures and no-break space that
|
|
5
|
+
* font subsets commonly name, from https://github.com/adobe-type-tools/agl-aglfn.
|
|
6
|
+
* Each is listed as a name and its code point in hexadecimal.
|
|
7
|
+
*
|
|
8
|
+
* Copyright 2002-2019 Adobe (http://www.adobe.com/).
|
|
9
|
+
*
|
|
10
|
+
* Redistribution and use in source and binary forms, with or
|
|
11
|
+
* without modification, are permitted provided that the
|
|
12
|
+
* following conditions are met:
|
|
13
|
+
*
|
|
14
|
+
* Redistributions of source code must retain the above
|
|
15
|
+
* copyright notice, this list of conditions and the following
|
|
16
|
+
* disclaimer.
|
|
17
|
+
*
|
|
18
|
+
* Redistributions in binary form must reproduce the above
|
|
19
|
+
* copyright notice, this list of conditions and the following
|
|
20
|
+
* disclaimer in the documentation and/or other materials
|
|
21
|
+
* provided with the distribution.
|
|
22
|
+
*
|
|
23
|
+
* Neither the name of Adobe nor the names of its contributors
|
|
24
|
+
* may be used to endorse or promote products derived from this
|
|
25
|
+
* software without specific prior written permission.
|
|
26
|
+
*
|
|
27
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
28
|
+
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
29
|
+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
30
|
+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
31
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
32
|
+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
33
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
34
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
35
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
36
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
37
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
38
|
+
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
39
|
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
40
|
+
*/
|
|
41
|
+
const AGLFN = `
|
|
42
|
+
A 0041 AE 00C6 AEacute 01FC Aacute 00C1 Abreve 0102 Acircumflex 00C2
|
|
43
|
+
Adieresis 00C4 Agrave 00C0 Alpha 0391 Alphatonos 0386 Amacron 0100
|
|
44
|
+
Aogonek 0104 Aring 00C5 Aringacute 01FA Atilde 00C3 B 0042 Beta 0392 C 0043
|
|
45
|
+
Cacute 0106 Ccaron 010C Ccedilla 00C7 Ccircumflex 0108 Cdotaccent 010A
|
|
46
|
+
Chi 03A7 D 0044 Dcaron 010E Dcroat 0110 Delta 2206 E 0045 Eacute 00C9
|
|
47
|
+
Ebreve 0114 Ecaron 011A Ecircumflex 00CA Edieresis 00CB Edotaccent 0116
|
|
48
|
+
Egrave 00C8 Emacron 0112 Eng 014A Eogonek 0118 Epsilon 0395
|
|
49
|
+
Epsilontonos 0388 Eta 0397 Etatonos 0389 Eth 00D0 Euro 20AC F 0046 G 0047
|
|
50
|
+
Gamma 0393 Gbreve 011E Gcaron 01E6 Gcircumflex 011C Gdotaccent 0120 H 0048
|
|
51
|
+
H18533 25CF H18543 25AA H18551 25AB H22073 25A1 Hbar 0126 Hcircumflex 0124
|
|
52
|
+
I 0049 IJ 0132 Iacute 00CD Ibreve 012C Icircumflex 00CE Idieresis 00CF
|
|
53
|
+
Idotaccent 0130 Ifraktur 2111 Igrave 00CC Imacron 012A Iogonek 012E
|
|
54
|
+
Iota 0399 Iotadieresis 03AA Iotatonos 038A Itilde 0128 J 004A
|
|
55
|
+
Jcircumflex 0134 K 004B Kappa 039A L 004C Lacute 0139 Lambda 039B
|
|
56
|
+
Lcaron 013D Ldot 013F Lslash 0141 M 004D Mu 039C N 004E Nacute 0143
|
|
57
|
+
Ncaron 0147 Ntilde 00D1 Nu 039D O 004F OE 0152 Oacute 00D3 Obreve 014E
|
|
58
|
+
Ocircumflex 00D4 Odieresis 00D6 Ograve 00D2 Ohorn 01A0 Ohungarumlaut 0150
|
|
59
|
+
Omacron 014C Omega 2126 Omegatonos 038F Omicron 039F Omicrontonos 038C
|
|
60
|
+
Oslash 00D8 Oslashacute 01FE Otilde 00D5 P 0050 Phi 03A6 Pi 03A0 Psi 03A8
|
|
61
|
+
Q 0051 R 0052 Racute 0154 Rcaron 0158 Rfraktur 211C Rho 03A1 S 0053
|
|
62
|
+
SF010000 250C SF020000 2514 SF030000 2510 SF040000 2518 SF050000 253C
|
|
63
|
+
SF060000 252C SF070000 2534 SF080000 251C SF090000 2524 SF100000 2500
|
|
64
|
+
SF110000 2502 SF190000 2561 SF200000 2562 SF210000 2556 SF220000 2555
|
|
65
|
+
SF230000 2563 SF240000 2551 SF250000 2557 SF260000 255D SF270000 255C
|
|
66
|
+
SF280000 255B SF360000 255E SF370000 255F SF380000 255A SF390000 2554
|
|
67
|
+
SF400000 2569 SF410000 2566 SF420000 2560 SF430000 2550 SF440000 256C
|
|
68
|
+
SF450000 2567 SF460000 2568 SF470000 2564 SF480000 2565 SF490000 2559
|
|
69
|
+
SF500000 2558 SF510000 2552 SF520000 2553 SF530000 256B SF540000 256A
|
|
70
|
+
Sacute 015A Scaron 0160 Scedilla 015E Scircumflex 015C Sigma 03A3 T 0054
|
|
71
|
+
Tau 03A4 Tbar 0166 Tcaron 0164 Theta 0398 Thorn 00DE U 0055 Uacute 00DA
|
|
72
|
+
Ubreve 016C Ucircumflex 00DB Udieresis 00DC Ugrave 00D9 Uhorn 01AF
|
|
73
|
+
Uhungarumlaut 0170 Umacron 016A Uogonek 0172 Upsilon 03A5 Upsilon1 03D2
|
|
74
|
+
Upsilondieresis 03AB Upsilontonos 038E Uring 016E Utilde 0168 V 0056 W 0057
|
|
75
|
+
Wacute 1E82 Wcircumflex 0174 Wdieresis 1E84 Wgrave 1E80 X 0058 Xi 039E
|
|
76
|
+
Y 0059 Yacute 00DD Ycircumflex 0176 Ydieresis 0178 Ygrave 1EF2 Z 005A
|
|
77
|
+
Zacute 0179 Zcaron 017D Zdotaccent 017B Zeta 0396 a 0061 aacute 00E1
|
|
78
|
+
abreve 0103 acircumflex 00E2 acute 00B4 acutecomb 0301 adieresis 00E4
|
|
79
|
+
ae 00E6 aeacute 01FD agrave 00E0 aleph 2135 alpha 03B1 alphatonos 03AC
|
|
80
|
+
amacron 0101 ampersand 0026 angle 2220 angleleft 2329 angleright 232A
|
|
81
|
+
anoteleia 0387 aogonek 0105 approxequal 2248 aring 00E5 aringacute 01FB
|
|
82
|
+
arrowboth 2194 arrowdblboth 21D4 arrowdbldown 21D3 arrowdblleft 21D0
|
|
83
|
+
arrowdblright 21D2 arrowdblup 21D1 arrowdown 2193 arrowleft 2190
|
|
84
|
+
arrowright 2192 arrowup 2191 arrowupdn 2195 arrowupdnbse 21A8
|
|
85
|
+
asciicircum 005E asciitilde 007E asterisk 002A asteriskmath 2217 at 0040
|
|
86
|
+
atilde 00E3 b 0062 backslash 005C bar 007C beta 03B2 block 2588
|
|
87
|
+
braceleft 007B braceright 007D bracketleft 005B bracketright 005D breve 02D8
|
|
88
|
+
brokenbar 00A6 bullet 2022 c 0063 cacute 0107 caron 02C7 carriagereturn 21B5
|
|
89
|
+
ccaron 010D ccedilla 00E7 ccircumflex 0109 cdotaccent 010B cedilla 00B8
|
|
90
|
+
cent 00A2 chi 03C7 circle 25CB circlemultiply 2297 circleplus 2295
|
|
91
|
+
circumflex 02C6 club 2663 colon 003A colonmonetary 20A1 comma 002C
|
|
92
|
+
congruent 2245 copyright 00A9 currency 00A4 d 0064 dagger 2020
|
|
93
|
+
daggerdbl 2021 dcaron 010F dcroat 0111 degree 00B0 delta 03B4 diamond 2666
|
|
94
|
+
dieresis 00A8 dieresistonos 0385 divide 00F7 dkshade 2593 dnblock 2584
|
|
95
|
+
dollar 0024 dong 20AB dotaccent 02D9 dotbelowcomb 0323 dotlessi 0131
|
|
96
|
+
dotmath 22C5 e 0065 eacute 00E9 ebreve 0115 ecaron 011B ecircumflex 00EA
|
|
97
|
+
edieresis 00EB edotaccent 0117 egrave 00E8 eight 0038 element 2208
|
|
98
|
+
ellipsis 2026 emacron 0113 emdash 2014 emptyset 2205 endash 2013 eng 014B
|
|
99
|
+
eogonek 0119 epsilon 03B5 epsilontonos 03AD equal 003D equivalence 2261
|
|
100
|
+
estimated 212E eta 03B7 etatonos 03AE eth 00F0 exclam 0021 exclamdbl 203C
|
|
101
|
+
exclamdown 00A1 existential 2203 f 0066 female 2640 figuredash 2012
|
|
102
|
+
filledbox 25A0 filledrect 25AC five 0035 fiveeighths 215D florin 0192
|
|
103
|
+
four 0034 fraction 2044 franc 20A3 g 0067 gamma 03B3 gbreve 011F gcaron 01E7
|
|
104
|
+
gcircumflex 011D gdotaccent 0121 germandbls 00DF gradient 2207 grave 0060
|
|
105
|
+
gravecomb 0300 greater 003E greaterequal 2265 guillemotleft 00AB
|
|
106
|
+
guillemotright 00BB guilsinglleft 2039 guilsinglright 203A h 0068 hbar 0127
|
|
107
|
+
hcircumflex 0125 heart 2665 hookabovecomb 0309 house 2302 hungarumlaut 02DD
|
|
108
|
+
hyphen 002D i 0069 iacute 00ED ibreve 012D icircumflex 00EE idieresis 00EF
|
|
109
|
+
igrave 00EC ij 0133 imacron 012B infinity 221E integral 222B integralbt 2321
|
|
110
|
+
integraltp 2320 intersection 2229 invbullet 25D8 invcircle 25D9
|
|
111
|
+
invsmileface 263B iogonek 012F iota 03B9 iotadieresis 03CA
|
|
112
|
+
iotadieresistonos 0390 iotatonos 03AF itilde 0129 j 006A jcircumflex 0135
|
|
113
|
+
k 006B kappa 03BA kgreenlandic 0138 l 006C lacute 013A lambda 03BB
|
|
114
|
+
lcaron 013E ldot 0140 less 003C lessequal 2264 lfblock 258C lira 20A4
|
|
115
|
+
logicaland 2227 logicalnot 00AC logicalor 2228 longs 017F lozenge 25CA
|
|
116
|
+
lslash 0142 ltshade 2591 m 006D macron 00AF male 2642 minus 2212 minute 2032
|
|
117
|
+
mu 00B5 multiply 00D7 musicalnote 266A musicalnotedbl 266B n 006E
|
|
118
|
+
nacute 0144 napostrophe 0149 ncaron 0148 nine 0039 notelement 2209
|
|
119
|
+
notequal 2260 notsubset 2284 ntilde 00F1 nu 03BD numbersign 0023 o 006F
|
|
120
|
+
oacute 00F3 obreve 014F ocircumflex 00F4 odieresis 00F6 oe 0153 ogonek 02DB
|
|
121
|
+
ograve 00F2 ohorn 01A1 ohungarumlaut 0151 omacron 014D omega 03C9
|
|
122
|
+
omega1 03D6 omegatonos 03CE omicron 03BF omicrontonos 03CC one 0031
|
|
123
|
+
onedotenleader 2024 oneeighth 215B onehalf 00BD onequarter 00BC
|
|
124
|
+
onethird 2153 openbullet 25E6 ordfeminine 00AA ordmasculine 00BA
|
|
125
|
+
orthogonal 221F oslash 00F8 oslashacute 01FF otilde 00F5 p 0070
|
|
126
|
+
paragraph 00B6 parenleft 0028 parenright 0029 partialdiff 2202 percent 0025
|
|
127
|
+
period 002E periodcentered 00B7 perpendicular 22A5 perthousand 2030
|
|
128
|
+
peseta 20A7 phi 03C6 phi1 03D5 pi 03C0 plus 002B plusminus 00B1
|
|
129
|
+
prescription 211E product 220F propersubset 2282 propersuperset 2283
|
|
130
|
+
proportional 221D psi 03C8 q 0071 question 003F questiondown 00BF
|
|
131
|
+
quotedbl 0022 quotedblbase 201E quotedblleft 201C quotedblright 201D
|
|
132
|
+
quoteleft 2018 quotereversed 201B quoteright 2019 quotesinglbase 201A
|
|
133
|
+
quotesingle 0027 r 0072 racute 0155 radical 221A rcaron 0159
|
|
134
|
+
reflexsubset 2286 reflexsuperset 2287 registered 00AE revlogicalnot 2310
|
|
135
|
+
rho 03C1 ring 02DA rtblock 2590 s 0073 sacute 015B scaron 0161 scedilla 015F
|
|
136
|
+
scircumflex 015D second 2033 section 00A7 semicolon 003B seven 0037
|
|
137
|
+
seveneighths 215E shade 2592 sigma 03C3 sigma1 03C2 similar 223C six 0036
|
|
138
|
+
slash 002F smileface 263A space 0020 spade 2660 sterling 00A3 suchthat 220B
|
|
139
|
+
summation 2211 sun 263C t 0074 tau 03C4 tbar 0167 tcaron 0165 therefore 2234
|
|
140
|
+
theta 03B8 theta1 03D1 thorn 00FE three 0033 threeeighths 215C
|
|
141
|
+
threequarters 00BE tilde 02DC tildecomb 0303 tonos 0384 trademark 2122
|
|
142
|
+
triagdn 25BC triaglf 25C4 triagrt 25BA triagup 25B2 two 0032
|
|
143
|
+
twodotenleader 2025 twothirds 2154 u 0075 uacute 00FA ubreve 016D
|
|
144
|
+
ucircumflex 00FB udieresis 00FC ugrave 00F9 uhorn 01B0 uhungarumlaut 0171
|
|
145
|
+
umacron 016B underscore 005F underscoredbl 2017 union 222A universal 2200
|
|
146
|
+
uogonek 0173 upblock 2580 upsilon 03C5 upsilondieresis 03CB
|
|
147
|
+
upsilondieresistonos 03B0 upsilontonos 03CD uring 016F utilde 0169 v 0076
|
|
148
|
+
w 0077 wacute 1E83 wcircumflex 0175 wdieresis 1E85 weierstrass 2118
|
|
149
|
+
wgrave 1E81 x 0078 xi 03BE y 0079 yacute 00FD ycircumflex 0177
|
|
150
|
+
ydieresis 00FF yen 00A5 ygrave 1EF3 z 007A zacute 017A zcaron 017E
|
|
151
|
+
zdotaccent 017C zero 0030 zeta 03B6
|
|
152
|
+
`;
|
|
153
|
+
const AGL_EXTRAS = `
|
|
154
|
+
fi FB01 fl FB02 ff FB00 ffi FB03 ffl FB04 onesuperior 00B9 twosuperior 00B2
|
|
155
|
+
threesuperior 00B3 nbspace 00A0
|
|
156
|
+
`;
|
|
157
|
+
/** Code points by glyph name. */
|
|
158
|
+
export const GLYPH_UNICODE = new Map(`${AGLFN} ${AGL_EXTRAS}`
|
|
159
|
+
.trim()
|
|
160
|
+
.split(/\s+/)
|
|
161
|
+
.flatMap((word, index, words) => index % 2 === 0
|
|
162
|
+
? [[word, Number.parseInt(words[index + 1], 16)]]
|
|
163
|
+
: []));
|
|
@@ -94,6 +94,8 @@ export function createPdfEditHandler(host) {
|
|
|
94
94
|
const { pageIndex, elementIds, scale } = payload;
|
|
95
95
|
return engine().renderPageWithout(pageIndex, elementIds, scale);
|
|
96
96
|
}
|
|
97
|
+
case "edit-text-font":
|
|
98
|
+
return engine().textFont(payload.id);
|
|
97
99
|
case "edit-page-layout":
|
|
98
100
|
return engine().pageLayout(payload.pageIndex);
|
|
99
101
|
case "edit-dispose":
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type CffFont } from "./cff.js";
|
|
2
|
+
/**
|
|
3
|
+
* The OpenType file, or `undefined` when no glyph has a code point or the
|
|
4
|
+
* program's name cannot be made one a browser accepts.
|
|
5
|
+
*/
|
|
6
|
+
export declare function cffOpenType(program: Uint8Array, font: CffFont, unicode: ReadonlyMap<number, number>): Uint8Array | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* An embedded TrueType or OpenType program with the OS/2, name and post
|
|
9
|
+
* tables it lacks, laid out on four-byte boundaries; `undefined` when its
|
|
10
|
+
* table directory or core tables are broken.
|
|
11
|
+
*/
|
|
12
|
+
export declare function completeSfnt(program: Uint8Array, fontName: string): Uint8Array | undefined;
|
|
13
|
+
/** The sfnt file maps Unicode: a cmap subtable for platform 0, or for Windows Unicode BMP or full repertoire. */
|
|
14
|
+
export declare function hasUnicodeCmap(program: Uint8Array): boolean;
|