Merge pull request #12127 from Snuffleupagus/type3Dependencies

Improve how Type3-fonts with dependencies are handled
This commit is contained in:
Tim van der Meij 2020-07-27 23:44:51 +02:00 committed by GitHub
commit 403816040e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 34 deletions

View File

@ -455,14 +455,7 @@ class PartialEvaluator {
_sendImgData(objId, imgData, cacheGlobally = false) { _sendImgData(objId, imgData, cacheGlobally = false) {
const transfers = imgData ? [imgData.data.buffer] : null; const transfers = imgData ? [imgData.data.buffer] : null;
if (this.parsingType3Font) { if (this.parsingType3Font || cacheGlobally) {
return this.handler.sendWithPromise(
"commonobj",
[objId, "FontType3Res", imgData],
transfers
);
}
if (cacheGlobally) {
return this.handler.send( return this.handler.send(
"commonobj", "commonobj",
[objId, "Image", imgData], [objId, "Image", imgData],
@ -581,7 +574,7 @@ class PartialEvaluator {
operatorList.addDependency(objId); operatorList.addDependency(objId);
args = [objId, w, h]; args = [objId, w, h];
const imgPromise = PDFImage.buildImage({ PDFImage.buildImage({
xref: this.xref, xref: this.xref,
res: resources, res: resources,
image, image,
@ -600,13 +593,6 @@ class PartialEvaluator {
return this._sendImgData(objId, /* imgData = */ null, cacheGlobally); return this._sendImgData(objId, /* imgData = */ null, cacheGlobally);
}); });
if (this.parsingType3Font) {
// In the very rare case where a Type3 image resource is being parsed,
// wait for the image to be both decoded *and* sent to simplify the
// rendering code on the main-thread (see issue10717.pdf).
await imgPromise;
}
operatorList.addOp(OPS.paintImageXObject, args); operatorList.addOp(OPS.paintImageXObject, args);
if (cacheKey) { if (cacheKey) {
localImageCache.set(cacheKey, imageRef, { localImageCache.set(cacheKey, imageRef, {
@ -741,8 +727,12 @@ class PartialEvaluator {
return translated; return translated;
} }
return translated return translated
.loadType3Data(this, resources, operatorList, task) .loadType3Data(this, resources, task)
.then(function () { .then(function () {
// Add the dependencies to the parent operatorList so they are
// resolved before Type3 operatorLists are executed synchronously.
operatorList.addDependencies(translated.type3Dependencies);
return translated; return translated;
}) })
.catch(reason => { .catch(reason => {
@ -3354,6 +3344,7 @@ class TranslatedFont {
this.dict = dict; this.dict = dict;
this._extraProperties = extraProperties; this._extraProperties = extraProperties;
this.type3Loaded = null; this.type3Loaded = null;
this.type3Dependencies = font.isType3Font ? new Set() : null;
this.sent = false; this.sent = false;
} }
@ -3386,35 +3377,29 @@ class TranslatedFont {
PartialEvaluator.buildFontPaths(this.font, glyphs, handler); PartialEvaluator.buildFontPaths(this.font, glyphs, handler);
} }
loadType3Data(evaluator, resources, parentOperatorList, task) { loadType3Data(evaluator, resources, task) {
if (!this.font.isType3Font) {
throw new Error("Must be a Type3 font.");
}
if (this.type3Loaded) { if (this.type3Loaded) {
return this.type3Loaded; return this.type3Loaded;
} }
if (!this.font.isType3Font) {
throw new Error("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.
//
// Also, ensure that any Type3 image resources (which should be very rare
// in practice) are completely decoded on the worker-thread, to simplify
// the rendering code on the main-thread (see issue10717.pdf).
var type3Options = Object.create(evaluator.options); var type3Options = Object.create(evaluator.options);
type3Options.ignoreErrors = false; type3Options.ignoreErrors = false;
var type3Evaluator = evaluator.clone(type3Options); var type3Evaluator = evaluator.clone(type3Options);
type3Evaluator.parsingType3Font = true; type3Evaluator.parsingType3Font = true;
var translatedFont = this.font; const translatedFont = this.font,
type3Dependencies = this.type3Dependencies;
var loadCharProcsPromise = Promise.resolve(); var loadCharProcsPromise = Promise.resolve();
var charProcs = this.dict.get("CharProcs"); var charProcs = this.dict.get("CharProcs");
var fontResources = this.dict.get("Resources") || resources; var fontResources = this.dict.get("Resources") || resources;
var charProcKeys = charProcs.getKeys();
var charProcOperatorList = Object.create(null); var charProcOperatorList = Object.create(null);
for (var i = 0, n = charProcKeys.length; i < n; ++i) { for (const key of charProcs.getKeys()) {
const key = charProcKeys[i];
loadCharProcsPromise = loadCharProcsPromise.then(function () { loadCharProcsPromise = loadCharProcsPromise.then(function () {
var glyphStream = charProcs.get(key); var glyphStream = charProcs.get(key);
var operatorList = new OperatorList(); var operatorList = new OperatorList();
@ -3428,9 +3413,9 @@ class TranslatedFont {
.then(function () { .then(function () {
charProcOperatorList[key] = operatorList.getIR(); charProcOperatorList[key] = operatorList.getIR();
// Add the dependencies to the parent operator list so they are for (const dependency of operatorList.dependencies) {
// resolved before sub operator list is executed synchronously. type3Dependencies.add(dependency);
parentOperatorList.addDependencies(operatorList.dependencies); }
}) })
.catch(function (reason) { .catch(function (reason) {
warn(`Type3 font resource "${key}" is not available.`); warn(`Type3 font resource "${key}" is not available.`);

View File

@ -2265,7 +2265,6 @@ class WorkerTransport {
}); });
break; break;
case "FontPath": case "FontPath":
case "FontType3Res":
case "Image": case "Image":
this.commonObjs.resolve(id, exportedData); this.commonObjs.resolve(id, exportedData);
break; break;