Skip to content

Commit 44affa7

Browse files
authored
Merge pull request #20197 from ryzokuken/sab-font-data
Serialize font data into an ArrayBuffer
2 parents 594fda1 + 4bed737 commit 44affa7

8 files changed

Lines changed: 920 additions & 19 deletions

File tree

src/core/evaluator.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import { BaseStream } from "./base_stream.js";
7272
import { bidi } from "./bidi.js";
7373
import { ColorSpace } from "./colorspace.js";
7474
import { ColorSpaceUtils } from "./colorspace_utils.js";
75+
import { FontInfo } from "../shared/obj-bin-transform.js";
7576
import { getFontSubstitution } from "./font_substitutions.js";
7677
import { getGlyphsUnicode } from "./glyphlist.js";
7778
import { getMetrics } from "./metrics.js";
@@ -4709,12 +4710,21 @@ class TranslatedFont {
47094710
return;
47104711
}
47114712
this.#sent = true;
4712-
4713-
handler.send("commonobj", [
4714-
this.loadedName,
4715-
"Font",
4716-
this.font.exportData(),
4717-
]);
4713+
const fontData = this.font.exportData();
4714+
const transfer = [];
4715+
if (fontData.data) {
4716+
if (fontData.data.charProcOperatorList) {
4717+
fontData.charProcOperatorList = fontData.data.charProcOperatorList;
4718+
}
4719+
fontData.data = FontInfo.write(fontData.data);
4720+
transfer.push(fontData.data);
4721+
}
4722+
handler.send("commonobj", [this.loadedName, "Font", fontData], transfer);
4723+
// future path: switch to a SharedArrayBuffer
4724+
// const sab = new SharedArrayBuffer(data.byteLength);
4725+
// const view = new Uint8Array(sab);
4726+
// view.set(new Uint8Array(data));
4727+
// handler.send("commonobj", [this.loadedName, "Font", sab]);
47184728
}
47194729

47204730
fallback(handler, evaluatorOptions) {

src/core/fonts.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,19 +1144,27 @@ class Font {
11441144
}
11451145

11461146
exportData() {
1147-
const exportDataProps = this.fontExtraProperties
1148-
? [...EXPORT_DATA_PROPERTIES, ...EXPORT_DATA_EXTRA_PROPERTIES]
1149-
: EXPORT_DATA_PROPERTIES;
1150-
11511147
const data = Object.create(null);
1152-
for (const prop of exportDataProps) {
1148+
for (const prop of EXPORT_DATA_PROPERTIES) {
11531149
const value = this[prop];
11541150
// Ignore properties that haven't been explicitly set.
11551151
if (value !== undefined) {
11561152
data[prop] = value;
11571153
}
11581154
}
1159-
return data;
1155+
1156+
if (!this.fontExtraProperties) {
1157+
return { data };
1158+
}
1159+
1160+
const extra = Object.create(null);
1161+
for (const prop of EXPORT_DATA_EXTRA_PROPERTIES) {
1162+
const value = this[prop];
1163+
if (value !== undefined) {
1164+
extra[prop] = value;
1165+
}
1166+
}
1167+
return { data, extra };
11601168
}
11611169

11621170
fallbackToSystemFont(properties) {

src/display/api.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import { DOMCMapReaderFactory } from "display-cmap_reader_factory";
6767
import { DOMFilterFactory } from "./filter_factory.js";
6868
import { DOMStandardFontDataFactory } from "display-standard_fontdata_factory";
6969
import { DOMWasmFactory } from "display-wasm_factory";
70+
import { FontInfo } from "../shared/obj-bin-transform.js";
7071
import { GlobalWorkerOptions } from "./worker_options.js";
7172
import { Metadata } from "./metadata.js";
7273
import { OptionalContentConfig } from "./optional_content_config.js";
@@ -2760,11 +2761,17 @@ class WorkerTransport {
27602761
break;
27612762
}
27622763

2764+
const fontData = new FontInfo(exportedData);
27632765
const inspectFont =
27642766
this._params.pdfBug && globalThis.FontInspector?.enabled
27652767
? (font, url) => globalThis.FontInspector.fontAdded(font, url)
27662768
: null;
2767-
const font = new FontFaceObject(exportedData, inspectFont);
2769+
const font = new FontFaceObject(
2770+
fontData,
2771+
inspectFont,
2772+
exportedData.extra,
2773+
exportedData.charProcOperatorList
2774+
);
27682775

27692776
this.fontLoader
27702777
.bind(font)
@@ -2776,7 +2783,7 @@ class WorkerTransport {
27762783
// rather than waiting for a `PDFDocumentProxy.cleanup` call.
27772784
// Since `font.data` could be very large, e.g. in some cases
27782785
// multiple megabytes, this will help reduce memory usage.
2779-
font.data = null;
2786+
font.clearData();
27802787
}
27812788
this.commonObjs.resolve(id, font);
27822789
});

src/display/font_loader.js

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -355,12 +355,11 @@ class FontLoader {
355355
}
356356

357357
class FontFaceObject {
358-
constructor(translatedData, inspectFont = null) {
358+
#fontData;
359+
360+
constructor(translatedData, inspectFont = null, extra, charProcOperatorList) {
359361
this.compiledGlyphs = Object.create(null);
360-
// importing translated data
361-
for (const i in translatedData) {
362-
this[i] = translatedData[i];
363-
}
362+
this.#fontData = translatedData;
364363
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
365364
if (typeof this.disableFontFace !== "boolean") {
366365
unreachable("disableFontFace must be available.");
@@ -370,6 +369,12 @@ class FontFaceObject {
370369
}
371370
}
372371
this._inspectFont = inspectFont;
372+
if (extra) {
373+
Object.assign(this, extra);
374+
}
375+
if (charProcOperatorList) {
376+
this.charProcOperatorList = charProcOperatorList;
377+
}
373378
}
374379

375380
createNativeFontFace() {
@@ -438,6 +443,102 @@ class FontFaceObject {
438443
}
439444
return (this.compiledGlyphs[character] = path);
440445
}
446+
447+
get black() {
448+
return this.#fontData.black;
449+
}
450+
451+
get bold() {
452+
return this.#fontData.bold;
453+
}
454+
455+
get disableFontFace() {
456+
return this.#fontData.disableFontFace ?? false;
457+
}
458+
459+
get fontExtraProperties() {
460+
return this.#fontData.fontExtraProperties ?? false;
461+
}
462+
463+
get isInvalidPDFjsFont() {
464+
return this.#fontData.isInvalidPDFjsFont;
465+
}
466+
467+
get isType3Font() {
468+
return this.#fontData.isType3Font;
469+
}
470+
471+
get italic() {
472+
return this.#fontData.italic;
473+
}
474+
475+
get missingFile() {
476+
return this.#fontData.missingFile;
477+
}
478+
479+
get remeasure() {
480+
return this.#fontData.remeasure;
481+
}
482+
483+
get vertical() {
484+
return this.#fontData.vertical;
485+
}
486+
487+
get ascent() {
488+
return this.#fontData.ascent;
489+
}
490+
491+
get defaultWidth() {
492+
return this.#fontData.defaultWidth;
493+
}
494+
495+
get descent() {
496+
return this.#fontData.descent;
497+
}
498+
499+
get bbox() {
500+
return this.#fontData.bbox;
501+
}
502+
503+
get fontMatrix() {
504+
return this.#fontData.fontMatrix;
505+
}
506+
507+
get fallbackName() {
508+
return this.#fontData.fallbackName;
509+
}
510+
511+
get loadedName() {
512+
return this.#fontData.loadedName;
513+
}
514+
515+
get mimetype() {
516+
return this.#fontData.mimetype;
517+
}
518+
519+
get name() {
520+
return this.#fontData.name;
521+
}
522+
523+
get data() {
524+
return this.#fontData.data;
525+
}
526+
527+
clearData() {
528+
this.#fontData.clearData();
529+
}
530+
531+
get cssFontInfo() {
532+
return this.#fontData.cssFontInfo;
533+
}
534+
535+
get systemFontInfo() {
536+
return this.#fontData.systemFontInfo;
537+
}
538+
539+
get defaultVMetrics() {
540+
return this.#fontData.defaultVMetrics;
541+
}
441542
}
442543

443544
export { FontFaceObject, FontLoader };

0 commit comments

Comments
 (0)