Skip to content

Commit 9d2b39d

Browse files
committed
Encode FontPath data into an ArrayBuffer
Serialize FontPath commands into a binary format and store it in an ArrayBuffer so that it can eventually be stored in a SharedArrayBuffer.
1 parent d83cbb2 commit 9d2b39d

File tree

9 files changed

+282
-180
lines changed

9 files changed

+282
-180
lines changed

src/core/evaluator.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
lookupMatrix,
4141
lookupNormalRect,
4242
} from "./core_utils.js";
43+
import { FontInfo, FontPathInfo } from "../shared/obj-bin-transform.js";
4344
import {
4445
getEncoding,
4546
MacRomanEncoding,
@@ -72,7 +73,6 @@ import { BaseStream } from "./base_stream.js";
7273
import { bidi } from "./bidi.js";
7374
import { ColorSpace } from "./colorspace.js";
7475
import { ColorSpaceUtils } from "./colorspace_utils.js";
75-
import { FontInfo } from "../shared/obj-bin-transform.js";
7676
import { getFontSubstitution } from "./font_substitutions.js";
7777
import { getGlyphsUnicode } from "./glyphlist.js";
7878
import { getMetrics } from "./metrics.js";
@@ -4660,11 +4660,8 @@ class PartialEvaluator {
46604660
if (font.renderer.hasBuiltPath(fontChar)) {
46614661
return;
46624662
}
4663-
handler.send("commonobj", [
4664-
glyphName,
4665-
"FontPath",
4666-
font.renderer.getPathJs(fontChar),
4667-
]);
4663+
const buffer = FontPathInfo.write(font.renderer.getPathJs(fontChar));
4664+
handler.send("commonobj", [glyphName, "FontPath", buffer], [buffer]);
46684665
} catch (reason) {
46694666
if (evaluatorOptions.ignoreErrors) {
46704667
warn(`buildFontPaths - ignoring ${glyphName} glyph: "${reason}".`);

src/core/font_renderer.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -770,10 +770,6 @@ class Commands {
770770
restore() {
771771
this.currentTransform = this.transformStack.pop() || [1, 0, 0, 1, 0, 0];
772772
}
773-
774-
getSVG() {
775-
return this.cmds.join("");
776-
}
777773
}
778774

779775
class CompiledFont {
@@ -836,7 +832,7 @@ class CompiledFont {
836832
this.compileGlyphImpl(code, cmds, glyphId);
837833
cmds.add("Z");
838834

839-
return cmds.getSVG();
835+
return cmds.cmds;
840836
}
841837

842838
compileGlyphImpl() {

src/display/api.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {
4545
StatTimer,
4646
} from "./display_utils.js";
4747
import { FontFaceObject, FontLoader } from "./font_loader.js";
48+
import { FontInfo, FontPathInfo } from "../shared/obj-bin-transform.js";
4849
import {
4950
getDataProp,
5051
getFactoryUrlProp,
@@ -67,7 +68,6 @@ import { DOMCMapReaderFactory } from "display-cmap_reader_factory";
6768
import { DOMFilterFactory } from "./filter_factory.js";
6869
import { DOMStandardFontDataFactory } from "display-standard_fontdata_factory";
6970
import { DOMWasmFactory } from "display-wasm_factory";
70-
import { FontInfo } from "../shared/obj-bin-transform.js";
7171
import { GlobalWorkerOptions } from "./worker_options.js";
7272
import { Metadata } from "./metadata.js";
7373
import { OptionalContentConfig } from "./optional_content_config.js";
@@ -2803,6 +2803,8 @@ class WorkerTransport {
28032803
}
28042804
break;
28052805
case "FontPath":
2806+
this.commonObjs.resolve(id, new FontPathInfo(exportedData));
2807+
break;
28062808
case "Image":
28072809
case "Pattern":
28082810
this.commonObjs.resolve(id, exportedData);

src/display/font_loader.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ class FontFaceObject {
435435
} catch (ex) {
436436
warn(`getPathGenerator - ignoring character: "${ex}".`);
437437
}
438-
const path = new Path2D(cmds || "");
438+
const path = new Path2D(cmds?.getSVG() || "");
439439

440440
if (!this.fontExtraProperties) {
441441
// Remove the raw path-string, since we don't need it anymore.

src/shared/obj-bin-transform.js

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,4 +606,79 @@ class FontInfo {
606606
}
607607
}
608608

609-
export { CssFontInfo, FontInfo, SystemFontInfo };
609+
class FontPathInfo {
610+
static write(path) {
611+
let lengthEstimate = 0;
612+
const commands = [];
613+
for (const cmd of path) {
614+
const code = cmd.charCodeAt(0);
615+
let args = null;
616+
if (code === 67 || code === 76 || code === 77) {
617+
args = cmd.slice(1).split(" ");
618+
lengthEstimate += 1 + args.length * 8;
619+
} else if (code === 90) {
620+
lengthEstimate += 1;
621+
} else {
622+
throw new Error(`Invalid path command: ${cmd}`);
623+
}
624+
commands.push({ code, args });
625+
}
626+
627+
const buffer = new ArrayBuffer(4 + lengthEstimate);
628+
const view = new DataView(buffer);
629+
let offset = 0;
630+
631+
view.setUint32(offset, commands.length);
632+
offset += 4;
633+
for (const { code, args } of commands) {
634+
view.setUint8(offset, code);
635+
offset += 1;
636+
if (args) {
637+
for (const arg of args) {
638+
view.setFloat64(offset, parseFloat(arg), true);
639+
offset += 8;
640+
}
641+
}
642+
}
643+
644+
assert(offset === buffer.byteLength, "FontPathInfo.write: Buffer overflow");
645+
return buffer;
646+
}
647+
648+
#buffer;
649+
650+
#view;
651+
652+
constructor(buffer) {
653+
this.#buffer = buffer;
654+
this.#view = new DataView(this.#buffer);
655+
}
656+
657+
getSVG() {
658+
const length = this.#view.getUint32(0);
659+
const cmds = [];
660+
let offset = 4;
661+
for (let i = 0; i < length; i++) {
662+
const code = String.fromCharCode(this.#view.getUint8(offset));
663+
offset += 1;
664+
// eslint-disable-next-line no-nested-ternary
665+
const numArgs = code === "M" || code === "L" ? 2 : code === "C" ? 6 : 0;
666+
let args = null;
667+
if (numArgs > 0) {
668+
args = [];
669+
for (let j = 0; j < numArgs; j++) {
670+
args.push(this.#view.getFloat64(offset, true));
671+
offset += 8;
672+
}
673+
}
674+
cmds.push(code + (args ? args.join(" ") : ""));
675+
}
676+
assert(
677+
offset === this.#buffer.byteLength,
678+
"FontPathInfo.toString: Buffer overflow"
679+
);
680+
return cmds.join("");
681+
}
682+
}
683+
684+
export { CssFontInfo, FontInfo, FontPathInfo, SystemFontInfo };

test/unit/bin_font_info_spec.js

Lines changed: 0 additions & 164 deletions
This file was deleted.

test/unit/clitests.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
"app_options_spec.js",
1111
"autolinker_spec.js",
1212
"bidi_spec.js",
13-
"bin_font_info_spec.js",
1413
"canvas_factory_spec.js",
1514
"cff_parser_spec.js",
1615
"cmap_spec.js",
@@ -33,6 +32,7 @@
3332
"murmurhash3_spec.js",
3433
"network_utils_spec.js",
3534
"node_stream_spec.js",
35+
"obj_bin_transform_spec.js",
3636
"parser_spec.js",
3737
"pdf.image_decoders_spec.js",
3838
"pdf.worker_spec.js",

test/unit/jasmine-boot.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ async function initializePDFJS(callback) {
5353
"pdfjs-test/unit/app_options_spec.js",
5454
"pdfjs-test/unit/autolinker_spec.js",
5555
"pdfjs-test/unit/bidi_spec.js",
56-
"pdfjs-test/unit/bin_font_info_spec.js",
5756
"pdfjs-test/unit/canvas_factory_spec.js",
5857
"pdfjs-test/unit/cff_parser_spec.js",
5958
"pdfjs-test/unit/cmap_spec.js",
@@ -76,6 +75,7 @@ async function initializePDFJS(callback) {
7675
"pdfjs-test/unit/murmurhash3_spec.js",
7776
"pdfjs-test/unit/network_spec.js",
7877
"pdfjs-test/unit/network_utils_spec.js",
78+
"pdfjs-test/unit/obj_bin_transform_spec.js",
7979
"pdfjs-test/unit/parser_spec.js",
8080
"pdfjs-test/unit/pdf.image_decoders_spec.js",
8181
"pdfjs-test/unit/pdf.worker_spec.js",

0 commit comments

Comments
 (0)