diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 7ce1e3999..e353280cd 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -199,11 +199,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { var bitStrideLength = (width + 7) >> 3; var imgArray = image.getBytes(bitStrideLength * height); var decode = dict.get('Decode', 'D'); - var canTransfer = image instanceof DecodeStream; var inverseDecode = (!!decode && decode[0] > 0); imgData = PDFImage.createMask(imgArray, width, height, - canTransfer, inverseDecode); + image instanceof DecodeStream, + inverseDecode); imgData.cached = true; args = [imgData]; operatorList.addOp(OPS.paintImageMaskXObject, args); diff --git a/src/core/image.js b/src/core/image.js index a66081f01..e14e204da 100644 --- a/src/core/image.js +++ b/src/core/image.js @@ -248,23 +248,40 @@ var PDFImage = (function PDFImageClosure() { }; PDFImage.createMask = - function PDFImage_createMask(imgArray, width, height, canTransfer, - inverseDecode) { - // If imgArray came from a DecodeStream, we're safe to transfer it. - // Otherwise, copy it. + function PDFImage_createMask(imgArray, width, height, + imageIsFromDecodeStream, inverseDecode) { + + // |imgArray| might not contain full data for every pixel of the mask, so + // we need to distinguish between |computedLength| and |actualLength|. + // In particular, if inverseDecode is true, then the array we return must + // have a length of |computedLength|. + + var computedLength = ((width + 7) >> 3) * height; var actualLength = imgArray.byteLength; - var data; - if (canTransfer) { + var haveFullData = computedLength == actualLength; + var data, i; + + if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) { + // imgArray came from a DecodeStream and its data is in an appropriate + // form, so we can just transfer it. data = imgArray; - } else { + } else if (!inverseDecode) { data = new Uint8Array(actualLength); data.set(imgArray); + } else { + data = new Uint8Array(computedLength); + data.set(imgArray); + for (i = actualLength; i < computedLength; i++) { + data[i] = 0xff; + } } - // Invert if necessary. It's safe to modify the array -- whether it's the + + // If necessary, invert the original mask data (but not any extra we might + // have added above). It's safe to modify the array -- whether it's the // original or a copy, we're about to transfer it anyway, so nothing else // in this thread can be relying on its contents. if (inverseDecode) { - for (var i = 0; i < actualLength; i++) { + for (i = 0; i < actualLength; i++) { data[i] = ~data[i]; } } diff --git a/test/pdfs/issue4926.pdf.link b/test/pdfs/issue4926.pdf.link new file mode 100644 index 000000000..405474b75 --- /dev/null +++ b/test/pdfs/issue4926.pdf.link @@ -0,0 +1 @@ +http://www.conservation.ca.gov/cgs/information/publications/cgs_notes/note_17/documents/note_17.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 9bfb11a5f..143935840 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -1655,5 +1655,12 @@ "firstPage": 9, "lastPage": 9, "type": "eq" + }, + { "id": "issue4926", + "file": "pdfs/issue4926.pdf", + "md5": "ed881c8ea2f9bc4be94ecb7f2b2c149b", + "rounds": 1, + "link": true, + "type": "eq" } ]