Merge pull request #19563 from Snuffleupagus/loadType3Data-once
Invoke `TranslatedFont.prototype.loadType3Data` only *once* per font
This commit is contained in:
commit
50c573d16d
@ -1177,9 +1177,7 @@ class Catalog {
|
|||||||
this.pageDictCache.clear();
|
this.pageDictCache.clear();
|
||||||
this.nonBlendModesSet.clear();
|
this.nonBlendModesSet.clear();
|
||||||
|
|
||||||
const translatedFonts = await Promise.all(this.fontCache);
|
for (const { dict } of await Promise.all(this.fontCache)) {
|
||||||
|
|
||||||
for (const { dict } of translatedFonts) {
|
|
||||||
delete dict.cacheKey;
|
delete dict.cacheKey;
|
||||||
}
|
}
|
||||||
this.fontCache.clear();
|
this.fontCache.clear();
|
||||||
|
|||||||
@ -1046,27 +1046,19 @@ class PartialEvaluator {
|
|||||||
) {
|
) {
|
||||||
const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null;
|
const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null;
|
||||||
|
|
||||||
let translated = await this.loadFont(
|
const translated = await this.loadFont(
|
||||||
fontName,
|
fontName,
|
||||||
fontRef,
|
fontRef,
|
||||||
resources,
|
resources,
|
||||||
|
task,
|
||||||
fallbackFontDict,
|
fallbackFontDict,
|
||||||
cssFontInfo
|
cssFontInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
if (translated.font.isType3Font) {
|
if (translated.font.isType3Font) {
|
||||||
try {
|
// Add the dependencies to the parent operatorList so they are
|
||||||
await translated.loadType3Data(this, resources, task);
|
// resolved before Type3 operatorLists are executed synchronously.
|
||||||
// Add the dependencies to the parent operatorList so they are
|
operatorList.addDependencies(translated.type3Dependencies);
|
||||||
// resolved before Type3 operatorLists are executed synchronously.
|
|
||||||
operatorList.addDependencies(translated.type3Dependencies);
|
|
||||||
} catch (reason) {
|
|
||||||
translated = new TranslatedFont({
|
|
||||||
loadedName: "g_font_error",
|
|
||||||
font: new ErrorFont(`Type3 font load error: ${reason}`),
|
|
||||||
dict: translated.font,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.font = translated.font;
|
state.font = translated.font;
|
||||||
@ -1228,6 +1220,7 @@ class PartialEvaluator {
|
|||||||
fontName,
|
fontName,
|
||||||
font,
|
font,
|
||||||
resources,
|
resources,
|
||||||
|
task,
|
||||||
fallbackFontDict = null,
|
fallbackFontDict = null,
|
||||||
cssFontInfo = null
|
cssFontInfo = null
|
||||||
) {
|
) {
|
||||||
@ -1356,14 +1349,21 @@ class PartialEvaluator {
|
|||||||
font.loadedName = `${this.idFactory.getDocId()}_${fontID}`;
|
font.loadedName = `${this.idFactory.getDocId()}_${fontID}`;
|
||||||
|
|
||||||
this.translateFont(preEvaluatedFont)
|
this.translateFont(preEvaluatedFont)
|
||||||
.then(translatedFont => {
|
.then(async translatedFont => {
|
||||||
resolve(
|
const translated = new TranslatedFont({
|
||||||
new TranslatedFont({
|
loadedName: font.loadedName,
|
||||||
loadedName: font.loadedName,
|
font: translatedFont,
|
||||||
font: translatedFont,
|
dict: font,
|
||||||
dict: font,
|
});
|
||||||
})
|
|
||||||
);
|
if (translatedFont.isType3Font) {
|
||||||
|
try {
|
||||||
|
await translated.loadType3Data(this, resources, task);
|
||||||
|
} catch (reason) {
|
||||||
|
throw new Error(`Type3 font load error: ${reason}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(translated);
|
||||||
})
|
})
|
||||||
.catch(reason => {
|
.catch(reason => {
|
||||||
// TODO reject?
|
// TODO reject?
|
||||||
@ -1372,9 +1372,7 @@ class PartialEvaluator {
|
|||||||
resolve(
|
resolve(
|
||||||
new TranslatedFont({
|
new TranslatedFont({
|
||||||
loadedName: font.loadedName,
|
loadedName: font.loadedName,
|
||||||
font: new ErrorFont(
|
font: new ErrorFont(reason?.message),
|
||||||
reason instanceof Error ? reason.message : reason
|
|
||||||
),
|
|
||||||
dict: font,
|
dict: font,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -2616,16 +2614,12 @@ class PartialEvaluator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleSetFont(fontName, fontRef) {
|
async function handleSetFont(fontName, fontRef) {
|
||||||
const translated = await self.loadFont(fontName, fontRef, resources);
|
const translated = await self.loadFont(
|
||||||
|
fontName,
|
||||||
if (translated.font.isType3Font) {
|
fontRef,
|
||||||
try {
|
resources,
|
||||||
await translated.loadType3Data(self, resources, task);
|
task
|
||||||
} catch {
|
);
|
||||||
// Ignore Type3-parsing errors, since we only use `loadType3Data`
|
|
||||||
// here to ensure that we'll always obtain a useful /FontBBox.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textState.loadedName = translated.loadedName;
|
textState.loadedName = translated.loadedName;
|
||||||
textState.font = translated.font;
|
textState.font = translated.font;
|
||||||
@ -4602,20 +4596,22 @@ class PartialEvaluator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TranslatedFont {
|
class TranslatedFont {
|
||||||
|
#sent = false;
|
||||||
|
|
||||||
|
#type3Loaded = null;
|
||||||
|
|
||||||
constructor({ loadedName, font, dict }) {
|
constructor({ loadedName, font, dict }) {
|
||||||
this.loadedName = loadedName;
|
this.loadedName = loadedName;
|
||||||
this.font = font;
|
this.font = font;
|
||||||
this.dict = dict;
|
this.dict = dict;
|
||||||
this.type3Loaded = null;
|
|
||||||
this.type3Dependencies = font.isType3Font ? new Set() : null;
|
this.type3Dependencies = font.isType3Font ? new Set() : null;
|
||||||
this.sent = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
send(handler) {
|
send(handler) {
|
||||||
if (this.sent) {
|
if (this.#sent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.sent = true;
|
this.#sent = true;
|
||||||
|
|
||||||
handler.send("commonobj", [
|
handler.send("commonobj", [
|
||||||
this.loadedName,
|
this.loadedName,
|
||||||
@ -4645,12 +4641,12 @@ class TranslatedFont {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadType3Data(evaluator, resources, task) {
|
loadType3Data(evaluator, resources, task) {
|
||||||
if (this.type3Loaded) {
|
if (this.#type3Loaded) {
|
||||||
return this.type3Loaded;
|
return this.#type3Loaded;
|
||||||
}
|
|
||||||
if (!this.font.isType3Font) {
|
|
||||||
throw new Error("Must be a Type3 font.");
|
|
||||||
}
|
}
|
||||||
|
const { font, type3Dependencies } = this;
|
||||||
|
assert(font.isType3Font, "Must be a Type3 font.");
|
||||||
|
|
||||||
// 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.
|
||||||
@ -4662,14 +4658,12 @@ class TranslatedFont {
|
|||||||
}
|
}
|
||||||
type3Evaluator.type3FontRefs = type3FontRefs;
|
type3Evaluator.type3FontRefs = type3FontRefs;
|
||||||
|
|
||||||
const translatedFont = this.font,
|
|
||||||
type3Dependencies = this.type3Dependencies;
|
|
||||||
let loadCharProcsPromise = Promise.resolve();
|
let loadCharProcsPromise = Promise.resolve();
|
||||||
const charProcs = this.dict.get("CharProcs");
|
const charProcs = this.dict.get("CharProcs");
|
||||||
const fontResources = this.dict.get("Resources") || resources;
|
const fontResources = this.dict.get("Resources") || resources;
|
||||||
const charProcOperatorList = Object.create(null);
|
const charProcOperatorList = Object.create(null);
|
||||||
|
|
||||||
const fontBBox = Util.normalizeRect(translatedFont.bbox || [0, 0, 0, 0]),
|
const fontBBox = Util.normalizeRect(font.bbox || [0, 0, 0, 0]),
|
||||||
width = fontBBox[2] - fontBBox[0],
|
width = fontBBox[2] - fontBBox[0],
|
||||||
height = fontBBox[3] - fontBBox[1];
|
height = fontBBox[3] - fontBBox[1];
|
||||||
const fontBBoxSize = Math.hypot(width, height);
|
const fontBBoxSize = Math.hypot(width, height);
|
||||||
@ -4693,7 +4687,7 @@ class TranslatedFont {
|
|||||||
// colour-related parameters) in the graphics state;
|
// colour-related parameters) in the graphics state;
|
||||||
// any use of such operators shall be ignored."
|
// any use of such operators shall be ignored."
|
||||||
if (operatorList.fnArray[0] === OPS.setCharWidthAndBounds) {
|
if (operatorList.fnArray[0] === OPS.setCharWidthAndBounds) {
|
||||||
this._removeType3ColorOperators(operatorList, fontBBoxSize);
|
this.#removeType3ColorOperators(operatorList, fontBBoxSize);
|
||||||
}
|
}
|
||||||
charProcOperatorList[key] = operatorList.getIR();
|
charProcOperatorList[key] = operatorList.getIR();
|
||||||
|
|
||||||
@ -4708,20 +4702,17 @@ class TranslatedFont {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.type3Loaded = loadCharProcsPromise.then(() => {
|
this.#type3Loaded = loadCharProcsPromise.then(() => {
|
||||||
translatedFont.charProcOperatorList = charProcOperatorList;
|
font.charProcOperatorList = charProcOperatorList;
|
||||||
if (this._bbox) {
|
if (this._bbox) {
|
||||||
translatedFont.isCharBBox = true;
|
font.isCharBBox = true;
|
||||||
translatedFont.bbox = this._bbox;
|
font.bbox = this._bbox;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return this.type3Loaded;
|
return this.#type3Loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#removeType3ColorOperators(operatorList, fontBBoxSize = NaN) {
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_removeType3ColorOperators(operatorList, fontBBoxSize = NaN) {
|
|
||||||
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
||||||
assert(
|
assert(
|
||||||
operatorList.fnArray[0] === OPS.setCharWidthAndBounds,
|
operatorList.fnArray[0] === OPS.setCharWidthAndBounds,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user