Convert TranslatedFont.prototype.loadType3Data to an asynchronous method

The Type3 glyphs are parsed in series, which was implemented by chaining the `getOperatorList` promises together one after another.
Thanks to modern JavaScript this can be simplified a little bit, since we can just `await` within the loop instead.
This commit is contained in:
Jonas Jenwald 2026-08-05 22:51:49 +02:00
parent 5f181fd8b0
commit 74fe316f31

View File

@ -4885,47 +4885,45 @@ class TranslatedFont {
); );
} }
loadType3Data(evaluator, resources, task, seenRefs = null) { async loadType3Data(evaluator, resources, task, seenRefs = null) {
if (this.#type3Loaded) { if (this.#type3Loaded) {
return this.#type3Loaded; return this.#type3Loaded;
} }
const { font, type3Dependencies } = this; const { dict, font, type3Dependencies } = this;
assert(font.isType3Font, "Must be a Type3 font."); assert(font.isType3Font, "Must be a Type3 font.");
const { promise, resolve } = Promise.withResolvers();
this.#type3Loaded = promise;
// When parsing Type3 glyphs, always ignore them if there are errors. // When parsing Type3 glyphs, always ignore them if there are errors.
// Compared to the parsing of e.g. an entire page, it doesn't really // Compared to the parsing of e.g. an entire page, it doesn't really
// make sense to only be able to render a Type3 glyph partially. // make sense to only be able to render a Type3 glyph partially.
const type3Evaluator = evaluator.clone({ ignoreErrors: false }); const type3Evaluator = evaluator.clone({ ignoreErrors: false });
// Prevent circular references in Type3 fonts. // Prevent circular references in Type3 fonts.
const type3FontRefs = new RefSet(evaluator.type3FontRefs); const type3FontRefs = new RefSet(evaluator.type3FontRefs);
if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) { if (dict.objId && !type3FontRefs.has(dict.objId)) {
type3FontRefs.put(this.dict.objId); type3FontRefs.put(dict.objId);
} }
type3Evaluator.type3FontRefs = type3FontRefs; type3Evaluator.type3FontRefs = type3FontRefs;
let loadCharProcsPromise = Promise.resolve(); const charProcs = dict.get("CharProcs");
const charProcs = this.dict.get("CharProcs"); const fontResources = dict.get("Resources") || resources;
const fontResources = this.dict.get("Resources") || resources;
const charProcOperatorList = Object.create(null); const charProcOperatorList = Object.create(null);
const [x0, y0, x1, y1] = font.bbox, const [x0, y0, x1, y1] = font.bbox;
width = x1 - x0, const fontBBoxSize = Math.hypot(x1 - x0, y1 - y0);
height = y1 - y0;
const fontBBoxSize = Math.hypot(width, height);
for (const key of charProcs.getKeys()) { for (const key of charProcs.getKeys()) {
loadCharProcsPromise = loadCharProcsPromise.then(() => { try {
const glyphStream = charProcs.get(key);
const operatorList = new OperatorList(); const operatorList = new OperatorList();
return type3Evaluator await type3Evaluator.getOperatorList({
.getOperatorList({ stream: charProcs.get(key),
stream: glyphStream,
task, task,
resources: fontResources, resources: fontResources,
operatorList, operatorList,
prevRefs: seenRefs, prevRefs: seenRefs,
}) });
.then(() => {
// According to the PDF specification, section "9.6.5 Type 3 Fonts" // According to the PDF specification, section "9.6.5 Type 3 Fonts"
// and "Table 113": // and "Table 113":
// "A glyph description that begins with the d1 operator should // "A glyph description that begins with the d1 operator should
@ -4947,21 +4945,19 @@ class TranslatedFont {
for (const dependency of operatorList.dependencies) { for (const dependency of operatorList.dependencies) {
type3Dependencies.add(dependency); type3Dependencies.add(dependency);
} }
}) } catch {
.catch(function (reason) {
warn(`Type3 font resource "${key}" is not available.`); warn(`Type3 font resource "${key}" is not available.`);
const dummyOperatorList = new OperatorList(); charProcOperatorList[key] = new OperatorList().getIR();
charProcOperatorList[key] = dummyOperatorList.getIR();
});
});
} }
this.#type3Loaded = loadCharProcsPromise.then(() => { }
font.charProcOperatorList = charProcOperatorList; font.charProcOperatorList = charProcOperatorList;
if (this._bbox) { if (this._bbox) {
font.isCharBBox = true; font.isCharBBox = true;
font.bbox = this._bbox; font.bbox = this._bbox;
} }
});
resolve();
return this.#type3Loaded; return this.#type3Loaded;
} }