1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-26 01:58:06 +02:00

Improve performance with image masks (bug 857031)

- it aims to partially fix performance issue reported: https://bugzilla.mozilla.org/show_bug.cgi?id=857031;
- the idea is too avoid to use byte arrays but use ImageBitmap which are a way faster to draw:
  * an ImageBitmap is Transferable which means that it can be built in the worker instead of in the main thread:
    - this is achieved in using an OffscreenCanvas when it's available, there is a bug to enable them
      for pdf.js: https://bugzilla.mozilla.org/show_bug.cgi?id=1763330;
    - or in using createImageBitmap: in Firefox a task is sent to the main thread to build the bitmap so
      it's slightly slower than using an OffscreenCanvas.
  * it's transfered from the worker to the main thread by "reference";
  * the byte buffers used to create the image data have a very short lifetime and ergo the memory used is globally
    less than before.
- Use the localImageCache for the mask;
- Fix the pdf issue4436r.pdf: it was expected to have a binary stream for the image;
- Move the singlePixel trick from operator_list to image: this way we can use this trick even if it isn't in a set
  as defined in operator_list.
This commit is contained in:
Calixte Denizet 2022-04-06 15:34:08 +02:00
parent 2b673a6941
commit 040fcae5ab
11 changed files with 256 additions and 65 deletions

View file

@ -540,7 +540,7 @@ class PartialEvaluator {
}
_sendImgData(objId, imgData, cacheGlobally = false) {
const transfers = imgData ? [imgData.data.buffer] : null;
const transfers = imgData ? [imgData.bitmap || imgData.data.buffer] : null;
if (this.parsingType3Font || cacheGlobally) {
return this.handler.send(
@ -612,6 +612,33 @@ class PartialEvaluator {
);
const decode = dict.getArray("D", "Decode");
if (this.parsingType3Font) {
imgData = PDFImage.createRawMask({
imgArray,
width: w,
height: h,
imageIsFromDecodeStream: image instanceof DecodeStream,
inverseDecode: !!decode && decode[0] > 0,
interpolate,
});
imgData.cached = !!cacheKey;
args = [imgData];
operatorList.addOp(OPS.paintImageMaskXObject, args);
if (cacheKey) {
localImageCache.set(cacheKey, imageRef, {
fn: OPS.paintImageMaskXObject,
args,
});
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
return;
}
imgData = PDFImage.createMask({
imgArray,
width: w,
@ -620,8 +647,36 @@ class PartialEvaluator {
inverseDecode: !!decode && decode[0] > 0,
interpolate,
});
imgData.cached = !!cacheKey;
args = [imgData];
if (imgData.isSingleOpaquePixel) {
// Handles special case of mainly LaTeX documents which use image
// masks to draw lines with the current fill style.
operatorList.addOp(OPS.paintSolidColorImageMask, []);
if (cacheKey) {
localImageCache.set(cacheKey, imageRef, {
fn: OPS.paintSolidColorImageMask,
args: [],
});
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
return;
}
const objId = `mask_${this.idFactory.createObjId()}`;
operatorList.addDependency(objId);
this._sendImgData(objId, imgData);
args = [
{
data: objId,
width: imgData.width,
height: imgData.height,
interpolate: imgData.interpolate,
},
];
operatorList.addOp(OPS.paintImageMaskXObject, args);
if (cacheKey) {