Combine the getPathJs and hasBuiltPath methods in the CompiledFont class

This avoids duplicating the charCode/glyphId lookup, and (slightly) shortens the code. In particular:
 - Given that the path-data is returned as a TypedArray, it's easy enough to instead return `null` to indicate that the glyph was previously compiled.

 - The charCode-cache can be changed into a Set, since we only need to track the "seen" charCodes and not their relation to the glyphIds.

 - The `compileFontPathInfo` call is moved into `CompiledFont` class, since that simplifies the `src/core/evaluator.js` code a tiny bit.
This commit is contained in:
Jonas Jenwald 2026-07-19 16:48:07 +02:00
parent eddd70a2ca
commit 02027ba381
2 changed files with 17 additions and 20 deletions

View File

@ -33,10 +33,6 @@ import {
import { CheckedOperatorList, OperatorList } from "./operator_list.js"; import { CheckedOperatorList, OperatorList } from "./operator_list.js";
import { CMapFactory, IdentityCMap } from "./cmap.js"; import { CMapFactory, IdentityCMap } from "./cmap.js";
import { Cmd, Dict, EOF, isName, Name, Ref, RefSet } from "./primitives.js"; import { Cmd, Dict, EOF, isName, Name, Ref, RefSet } from "./primitives.js";
import {
compileFontPathInfo,
compilePatternInfo,
} from "./obj_bin_transform_core.js";
import { import {
compileType3Glyph, compileType3Glyph,
FontFlags, FontFlags,
@ -83,6 +79,7 @@ import { BaseStream } from "./base_stream.js";
import { bidi } from "./bidi.js"; import { bidi } from "./bidi.js";
import { ColorSpace } from "./colorspace.js"; import { ColorSpace } from "./colorspace.js";
import { ColorSpaceUtils } from "./colorspace_utils.js"; import { ColorSpaceUtils } from "./colorspace_utils.js";
import { compilePatternInfo } from "./obj_bin_transform_core.js";
import { getFontSubstitution } from "./font_substitutions.js"; import { getFontSubstitution } from "./font_substitutions.js";
import { getGlyphsUnicode } from "./glyphlist.js"; import { getGlyphsUnicode } from "./glyphlist.js";
import { getMetrics } from "./metrics.js"; import { getMetrics } from "./metrics.js";
@ -4809,10 +4806,10 @@ class PartialEvaluator {
function buildPath(fontChar) { function buildPath(fontChar) {
const glyphName = `${font.loadedName}_path_${fontChar}`; const glyphName = `${font.loadedName}_path_${fontChar}`;
try { try {
if (font.renderer.hasBuiltPath(fontChar)) { const buffer = font.renderer.getPath(fontChar);
return; if (!buffer) {
return; // Previously compiled, and sent to the main-thread.
} }
const buffer = compileFontPathInfo(font.renderer.getPathJs(fontChar));
handler.send("commonobj", [glyphName, "FontPath", buffer], [buffer]); handler.send("commonobj", [glyphName, "FontPath", buffer], [buffer]);
} catch (reason) { } catch (reason) {
if (evaluatorOptions.ignoreErrors) { if (evaluatorOptions.ignoreErrors) {

View File

@ -26,6 +26,7 @@ import {
warn, warn,
} from "../shared/util.js"; } from "../shared/util.js";
import { CFFParser } from "./cff_parser.js"; import { CFFParser } from "./cff_parser.js";
import { compileFontPathInfo } from "./obj_bin_transform_core.js";
import { getGlyphsUnicode } from "./glyphlist.js"; import { getGlyphsUnicode } from "./glyphlist.js";
import { isNumberArray } from "./core_utils.js"; import { isNumberArray } from "./core_utils.js";
import { StandardEncoding } from "./encodings.js"; import { StandardEncoding } from "./encodings.js";
@ -781,9 +782,9 @@ class Commands {
} }
class CompiledFont { class CompiledFont {
#compiledGlyphs = new Map(); #compiledCharCodes = new Set();
#compiledCharCodeToGlyphId = new Map(); #compiledGlyphs = new Map();
constructor(fontMatrix) { constructor(fontMatrix) {
if ( if (
@ -806,9 +807,16 @@ class CompiledFont {
); );
} }
getPathJs(unicode) { getPath(unicode) {
const { charCode, glyphId } = lookupCmap(this.cmap, unicode); const { charCode, glyphId } = lookupCmap(this.cmap, unicode);
if (
this.#compiledGlyphs.has(glyphId) &&
this.#compiledCharCodes.has(charCode)
) {
return null; // Previously compiled.
}
const path = this.#compiledGlyphs.getOrInsertComputed(glyphId, () => { const path = this.#compiledGlyphs.getOrInsertComputed(glyphId, () => {
try { try {
return this.compileGlyph(this.glyphs[glyphId], glyphId); return this.compileGlyph(this.glyphs[glyphId], glyphId);
@ -816,12 +824,12 @@ class CompiledFont {
return ex; // Avoid attempting to re-compile a corrupt glyph. return ex; // Avoid attempting to re-compile a corrupt glyph.
} }
}); });
this.#compiledCharCodeToGlyphId.getOrInsert(charCode, glyphId); this.#compiledCharCodes.add(charCode);
if (path instanceof Error) { if (path instanceof Error) {
throw path; throw path;
} }
return path; return compileFontPathInfo(path);
} }
compileGlyph(code, glyphId) { compileGlyph(code, glyphId) {
@ -854,14 +862,6 @@ class CompiledFont {
compileGlyphImpl() { compileGlyphImpl() {
unreachable("Children classes should implement this."); unreachable("Children classes should implement this.");
} }
hasBuiltPath(unicode) {
const { charCode, glyphId } = lookupCmap(this.cmap, unicode);
return (
this.#compiledGlyphs.has(glyphId) &&
this.#compiledCharCodeToGlyphId.has(charCode)
);
}
} }
class TrueTypeCompiled extends CompiledFont { class TrueTypeCompiled extends CompiledFont {