Merge pull request #10727 from Snuffleupagus/type3-image-resources
Support (rare) Type3 fonts which contains image resources (issue 10717)
This commit is contained in:
commit
55d9b35d37
@ -73,6 +73,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
this.builtInCMapCache = builtInCMapCache;
|
this.builtInCMapCache = builtInCMapCache;
|
||||||
this.options = options || DefaultPartialEvaluatorOptions;
|
this.options = options || DefaultPartialEvaluatorOptions;
|
||||||
this.pdfFunctionFactory = pdfFunctionFactory;
|
this.pdfFunctionFactory = pdfFunctionFactory;
|
||||||
|
this.parsingType3Font = false;
|
||||||
|
|
||||||
this.fetchBuiltInCMap = async (name) => {
|
this.fetchBuiltInCMap = async (name) => {
|
||||||
if (this.builtInCMapCache.has(name)) {
|
if (this.builtInCMapCache.has(name)) {
|
||||||
@ -293,21 +294,21 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
buildPaintImageXObject({ resources, image, isInline = false, operatorList,
|
async buildPaintImageXObject({ resources, image, isInline = false,
|
||||||
cacheKey, imageCache,
|
operatorList, cacheKey, imageCache,
|
||||||
forceDisableNativeImageDecoder = false, }) {
|
forceDisableNativeImageDecoder = false, }) {
|
||||||
var dict = image.dict;
|
var dict = image.dict;
|
||||||
var w = dict.get('Width', 'W');
|
var w = dict.get('Width', 'W');
|
||||||
var h = dict.get('Height', 'H');
|
var h = dict.get('Height', 'H');
|
||||||
|
|
||||||
if (!(w && isNum(w)) || !(h && isNum(h))) {
|
if (!(w && isNum(w)) || !(h && isNum(h))) {
|
||||||
warn('Image dimensions are missing, or not numbers.');
|
warn('Image dimensions are missing, or not numbers.');
|
||||||
return Promise.resolve();
|
return;
|
||||||
}
|
}
|
||||||
var maxImageSize = this.options.maxImageSize;
|
var maxImageSize = this.options.maxImageSize;
|
||||||
if (maxImageSize !== -1 && w * h > maxImageSize) {
|
if (maxImageSize !== -1 && w * h > maxImageSize) {
|
||||||
warn('Image exceeded maximum allowed size and was removed.');
|
warn('Image exceeded maximum allowed size and was removed.');
|
||||||
return Promise.resolve();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageMask = (dict.get('ImageMask', 'IM') || false);
|
var imageMask = (dict.get('ImageMask', 'IM') || false);
|
||||||
@ -343,7 +344,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
args,
|
args,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var softMask = (dict.get('SMask', 'SM') || false);
|
var softMask = (dict.get('SMask', 'SM') || false);
|
||||||
@ -364,14 +365,21 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
// any other kind.
|
// any other kind.
|
||||||
imgData = imageObj.createImageData(/* forceRGBA = */ true);
|
imgData = imageObj.createImageData(/* forceRGBA = */ true);
|
||||||
operatorList.addOp(OPS.paintInlineImageXObject, [imgData]);
|
operatorList.addOp(OPS.paintInlineImageXObject, [imgData]);
|
||||||
return Promise.resolve();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nativeImageDecoderSupport = forceDisableNativeImageDecoder ?
|
const nativeImageDecoderSupport = forceDisableNativeImageDecoder ?
|
||||||
NativeImageDecoding.NONE : this.options.nativeImageDecoderSupport;
|
NativeImageDecoding.NONE : this.options.nativeImageDecoderSupport;
|
||||||
// If there is no imageMask, create the PDFImage and a lot
|
// If there is no imageMask, create the PDFImage and a lot
|
||||||
// of image processing can be done here.
|
// of image processing can be done here.
|
||||||
var objId = 'img_' + this.idFactory.createObjId();
|
let objId = 'img_' + this.idFactory.createObjId();
|
||||||
|
|
||||||
|
if (this.parsingType3Font) {
|
||||||
|
assert(nativeImageDecoderSupport === NativeImageDecoding.NONE,
|
||||||
|
'Type3 image resources should be completely decoded in the worker.');
|
||||||
|
|
||||||
|
objId = `g_${this.pdfManager.docId}_type3res_${objId}`;
|
||||||
|
}
|
||||||
|
|
||||||
if (nativeImageDecoderSupport !== NativeImageDecoding.NONE &&
|
if (nativeImageDecoderSupport !== NativeImageDecoding.NONE &&
|
||||||
!softMask && !mask && image instanceof JpegStream &&
|
!softMask && !mask && image instanceof JpegStream &&
|
||||||
@ -428,7 +436,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
operatorList.addDependency(objId);
|
operatorList.addDependency(objId);
|
||||||
args = [objId, w, h];
|
args = [objId, w, h];
|
||||||
|
|
||||||
PDFImage.buildImage({
|
const imgPromise = PDFImage.buildImage({
|
||||||
handler: this.handler,
|
handler: this.handler,
|
||||||
xref: this.xref,
|
xref: this.xref,
|
||||||
res: resources,
|
res: resources,
|
||||||
@ -438,13 +446,30 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
pdfFunctionFactory: this.pdfFunctionFactory,
|
pdfFunctionFactory: this.pdfFunctionFactory,
|
||||||
}).then((imageObj) => {
|
}).then((imageObj) => {
|
||||||
var imgData = imageObj.createImageData(/* forceRGBA = */ false);
|
var imgData = imageObj.createImageData(/* forceRGBA = */ false);
|
||||||
|
|
||||||
|
if (this.parsingType3Font) {
|
||||||
|
return this.handler.sendWithPromise('commonobj',
|
||||||
|
[objId, 'FontType3Res', imgData], [imgData.data.buffer]);
|
||||||
|
}
|
||||||
this.handler.send('obj', [objId, this.pageIndex, 'Image', imgData],
|
this.handler.send('obj', [objId, this.pageIndex, 'Image', imgData],
|
||||||
[imgData.data.buffer]);
|
[imgData.data.buffer]);
|
||||||
}).catch((reason) => {
|
}).catch((reason) => {
|
||||||
warn('Unable to decode image: ' + reason);
|
warn('Unable to decode image: ' + reason);
|
||||||
|
|
||||||
|
if (this.parsingType3Font) {
|
||||||
|
return this.handler.sendWithPromise('commonobj',
|
||||||
|
[objId, 'FontType3Res', null]);
|
||||||
|
}
|
||||||
this.handler.send('obj', [objId, this.pageIndex, 'Image', null]);
|
this.handler.send('obj', [objId, this.pageIndex, 'Image', null]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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) {
|
||||||
imageCache[cacheKey] = {
|
imageCache[cacheKey] = {
|
||||||
@ -452,7 +477,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
args,
|
args,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSMask: function PartialEvaluator_handleSmask(smask, resources,
|
handleSMask: function PartialEvaluator_handleSmask(smask, resources,
|
||||||
@ -2622,9 +2646,15 @@ var TranslatedFont = (function TranslatedFontClosure() {
|
|||||||
// 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;
|
||||||
|
type3Options.nativeImageDecoderSupport = NativeImageDecoding.NONE;
|
||||||
var type3Evaluator = evaluator.clone(type3Options);
|
var type3Evaluator = evaluator.clone(type3Options);
|
||||||
|
type3Evaluator.parsingType3Font = true;
|
||||||
|
|
||||||
var translatedFont = this.font;
|
var translatedFont = this.font;
|
||||||
var loadCharProcsPromise = Promise.resolve();
|
var loadCharProcsPromise = Promise.resolve();
|
||||||
|
@ -2003,6 +2003,7 @@ class WorkerTransport {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'FontPath':
|
case 'FontPath':
|
||||||
|
case 'FontType3Res':
|
||||||
this.commonObjs.resolve(id, exportedData);
|
this.commonObjs.resolve(id, exportedData);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -805,11 +805,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
if (fnId !== OPS.dependency) {
|
if (fnId !== OPS.dependency) {
|
||||||
this[fnId].apply(this, argsArray[i]);
|
this[fnId].apply(this, argsArray[i]);
|
||||||
} else {
|
} else {
|
||||||
var deps = argsArray[i];
|
for (const depObjId of argsArray[i]) {
|
||||||
for (var n = 0, nn = deps.length; n < nn; n++) {
|
const objsPool = depObjId.startsWith('g_') ? commonObjs : objs;
|
||||||
var depObjId = deps[n];
|
|
||||||
var common = depObjId[0] === 'g' && depObjId[1] === '_';
|
|
||||||
var objsPool = common ? commonObjs : objs;
|
|
||||||
|
|
||||||
// If the promise isn't resolved yet, add the continueCallback
|
// If the promise isn't resolved yet, add the continueCallback
|
||||||
// to the promise and bail out.
|
// to the promise and bail out.
|
||||||
@ -1930,7 +1927,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
|
paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
|
||||||
var domImage = this.objs.get(objId);
|
const domImage = this.processingType3 ? this.commonObjs.get(objId) :
|
||||||
|
this.objs.get(objId);
|
||||||
if (!domImage) {
|
if (!domImage) {
|
||||||
warn('Dependent image isn\'t ready yet');
|
warn('Dependent image isn\'t ready yet');
|
||||||
return;
|
return;
|
||||||
@ -2067,7 +2065,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
|
paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
|
||||||
var imgData = this.objs.get(objId);
|
const imgData = this.processingType3 ? this.commonObjs.get(objId) :
|
||||||
|
this.objs.get(objId);
|
||||||
if (!imgData) {
|
if (!imgData) {
|
||||||
warn('Dependent image isn\'t ready yet');
|
warn('Dependent image isn\'t ready yet');
|
||||||
return;
|
return;
|
||||||
@ -2079,7 +2078,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
paintImageXObjectRepeat:
|
paintImageXObjectRepeat:
|
||||||
function CanvasGraphics_paintImageXObjectRepeat(objId, scaleX, scaleY,
|
function CanvasGraphics_paintImageXObjectRepeat(objId, scaleX, scaleY,
|
||||||
positions) {
|
positions) {
|
||||||
var imgData = this.objs.get(objId);
|
const imgData = this.processingType3 ? this.commonObjs.get(objId) :
|
||||||
|
this.objs.get(objId);
|
||||||
if (!imgData) {
|
if (!imgData) {
|
||||||
warn('Dependent image isn\'t ready yet');
|
warn('Dependent image isn\'t ready yet');
|
||||||
return;
|
return;
|
||||||
|
1
test/pdfs/issue10717.pdf.link
Normal file
1
test/pdfs/issue10717.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://github.com/mozilla/pdf.js/files/3057353/test.pdf
|
@ -1252,6 +1252,16 @@
|
|||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
|
{ "id": "issue10717",
|
||||||
|
"file": "pdfs/issue10717.pdf",
|
||||||
|
"md5": "6d2ed03db798cc6beb3c7bdf103f5c1a",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"firstPage": 1,
|
||||||
|
"lastPage": 2,
|
||||||
|
"type": "eq",
|
||||||
|
"about": "Type3 fonts with image resources; both pages need to be tested, otherwise the bug won't manifest."
|
||||||
|
},
|
||||||
{ "id": "close-path-bug",
|
{ "id": "close-path-bug",
|
||||||
"file": "pdfs/close-path-bug.pdf",
|
"file": "pdfs/close-path-bug.pdf",
|
||||||
"md5": "48dd17ef58393857d2d038d33699cac5",
|
"md5": "48dd17ef58393857d2d038d33699cac5",
|
||||||
|
Loading…
Reference in New Issue
Block a user