From 3f533a1cb04adbf422d58ce71eed6d4e851611ee Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Jan 2014 20:08:39 -0600 Subject: [PATCH] Use a more compact typed array to pass the image mask from the worker to the main thread. --- src/core/evaluator.js | 3 +-- src/core/image.js | 31 +++++++++++++------------------ src/display/canvas.js | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 9cf4a4463..b52a52da2 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -262,8 +262,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { var inverseDecode = !!decode && decode[0] > 0; operatorList.addOp(OPS.paintImageMaskXObject, - [PDFImage.createMask(imgArray, width, height, - inverseDecode)] + [PDFImage.createMask(imgArray, width, height, inverseDecode)] ); return; } diff --git a/src/core/image.js b/src/core/image.js index e7baf4fb2..f4781c03f 100644 --- a/src/core/image.js +++ b/src/core/image.js @@ -209,26 +209,21 @@ var PDFImage = (function PDFImageClosure() { PDFImage.createMask = function PDFImage_createMask(imgArray, width, height, inverseDecode) { - var buffer = new Uint8Array(width * height * 4); - var imgArrayPos = 0; - var i, j, mask, buf; - // removing making non-masked pixels transparent - var bufferPos = 3; // alpha component offset - for (i = 0; i < height; i++) { - mask = 0; - for (j = 0; j < width; j++) { - if (!mask) { - buf = imgArray[imgArrayPos++]; - mask = 128; - } - if (!(buf & mask) !== inverseDecode) { - buffer[bufferPos] = 255; - } - bufferPos += 4; - mask >>= 1; + // Copy imgArray into a typed array (inverting if necessary) so it can be + // transferred to the main thread. + var length = ((width + 7) >> 3) * height; + var data = new Uint8Array(length); + if (inverseDecode) { + for (var i = 0; i < length; i++) { + data[i] = ~imgArray[i]; + } + } else { + for (var i = 0; i < length; i++) { + data[i] = imgArray[i]; } } - return {data: buffer, width: width, height: height}; + + return {data: data, width: width, height: height}; }; PDFImage.prototype = { diff --git a/src/display/canvas.js b/src/display/canvas.js index f4f04e611..c9864ec70 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -431,6 +431,34 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { ctx.putImageData(tmpImgData, 0, 0); } + function putBinaryImageMask(ctx, imgData) { + var width = imgData.width, height = imgData.height; + var tmpImgData = ctx.createImageData(width, height); + var data = imgData.data; + var tmpImgDataPixels = tmpImgData.data; + var dataPos = 0; + + // Expand the mask so it can be used by the canvas. Any required inversion + // has already been handled. + var tmpPos = 3; // alpha component offset + for (var i = 0; i < height; i++) { + var mask = 0; + for (var j = 0; j < width; j++) { + if (!mask) { + var elem = data[dataPos++]; + mask = 128; + } + if (!(elem & mask)) { + tmpImgDataPixels[tmpPos] = 255; + } + tmpPos += 4; + mask >>= 1; + } + } + + ctx.putImageData(tmpImgData, 0, 0); + } + function copyCtxState(sourceCtx, destCtx) { var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha', 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit', @@ -1611,7 +1639,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var maskCtx = maskCanvas.context; maskCtx.save(); - putBinaryImageData(maskCtx, img); + putBinaryImageMask(maskCtx, img); maskCtx.globalCompositeOperation = 'source-in'; @@ -1638,7 +1666,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var maskCtx = maskCanvas.context; maskCtx.save(); - putBinaryImageData(maskCtx, image); + putBinaryImageMask(maskCtx, image); maskCtx.globalCompositeOperation = 'source-in';