Merge pull request #4122 from yurydelendik/bug878397
Use a more compact typed array to pass the image mask from the worker
This commit is contained in:
commit
71cc234c6a
@ -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;
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
@ -191,6 +191,18 @@ function compileType3Glyph(imgData) {
|
||||
var points = new Uint8Array(width1 * (height + 1));
|
||||
var POINT_TYPES =
|
||||
new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);
|
||||
|
||||
// decodes bit-packed mask data
|
||||
var lineSize = (width + 7) & ~7, data0 = imgData.data;
|
||||
var data = new Uint8Array(lineSize * height), pos = 0, ii;
|
||||
for (i = 0, ii = data0.length; i < ii; i++) {
|
||||
var mask = 128, elem = data0[i];
|
||||
while (mask > 0) {
|
||||
data[pos++] = (elem & mask) ? 0 : 255;
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// finding iteresting points: every point is located between mask pixels,
|
||||
// so there will be points of the (width + 1)x(height + 1) grid. Every point
|
||||
// will have flags assigned based on neighboring mask pixels:
|
||||
@ -201,24 +213,25 @@ function compileType3Glyph(imgData) {
|
||||
// - outside corners: 1, 2, 4, 8;
|
||||
// - inside corners: 7, 11, 13, 14;
|
||||
// - and, intersections: 5, 10.
|
||||
var pos = 3, data = imgData.data, lineSize = width * 4, count = 0;
|
||||
if (data[3] !== 0) {
|
||||
var count = 0;
|
||||
pos = 0;
|
||||
if (data[pos] !== 0) {
|
||||
points[0] = 1;
|
||||
++count;
|
||||
}
|
||||
for (j = 1; j < width; j++) {
|
||||
if (data[pos] !== data[pos + 4]) {
|
||||
if (data[pos] !== data[pos + 1]) {
|
||||
points[j] = data[pos] ? 2 : 1;
|
||||
++count;
|
||||
}
|
||||
pos += 4;
|
||||
pos++;
|
||||
}
|
||||
if (data[pos] !== 0) {
|
||||
points[j] = 2;
|
||||
++count;
|
||||
}
|
||||
pos += 4;
|
||||
for (i = 1; i < height; i++) {
|
||||
pos = i * lineSize;
|
||||
j0 = i * width1;
|
||||
if (data[pos - lineSize] !== data[pos]) {
|
||||
points[j0] = data[pos] ? 1 : 8;
|
||||
@ -228,37 +241,36 @@ function compileType3Glyph(imgData) {
|
||||
// array (in order 8-1-2-4, so we can use '>>2' to shift the column).
|
||||
var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
|
||||
for (j = 1; j < width; j++) {
|
||||
sum = (sum >> 2) + (data[pos + 4] ? 4 : 0) +
|
||||
(data[pos - lineSize + 4] ? 8 : 0);
|
||||
sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) +
|
||||
(data[pos - lineSize + 1] ? 8 : 0);
|
||||
if (POINT_TYPES[sum]) {
|
||||
points[j0 + j] = POINT_TYPES[sum];
|
||||
++count;
|
||||
}
|
||||
pos += 4;
|
||||
pos++;
|
||||
}
|
||||
if (data[pos - lineSize] !== data[pos]) {
|
||||
points[j0 + j] = data[pos] ? 2 : 4;
|
||||
++count;
|
||||
}
|
||||
pos += 4;
|
||||
|
||||
if (count > POINT_TO_PROCESS_LIMIT) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
pos -= lineSize;
|
||||
pos = lineSize * (height - 1);
|
||||
j0 = i * width1;
|
||||
if (data[pos] !== 0) {
|
||||
points[j0] = 8;
|
||||
++count;
|
||||
}
|
||||
for (j = 1; j < width; j++) {
|
||||
if (data[pos] !== data[pos + 4]) {
|
||||
if (data[pos] !== data[pos + 1]) {
|
||||
points[j0 + j] = data[pos] ? 4 : 8;
|
||||
++count;
|
||||
}
|
||||
pos += 4;
|
||||
pos++;
|
||||
}
|
||||
if (data[pos] !== 0) {
|
||||
points[j0 + j] = 4;
|
||||
@ -431,6 +443,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 +1651,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var maskCtx = maskCanvas.context;
|
||||
maskCtx.save();
|
||||
|
||||
putBinaryImageData(maskCtx, img);
|
||||
putBinaryImageMask(maskCtx, img);
|
||||
|
||||
maskCtx.globalCompositeOperation = 'source-in';
|
||||
|
||||
@ -1638,7 +1678,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var maskCtx = maskCanvas.context;
|
||||
maskCtx.save();
|
||||
|
||||
putBinaryImageData(maskCtx, image);
|
||||
putBinaryImageMask(maskCtx, image);
|
||||
|
||||
maskCtx.globalCompositeOperation = 'source-in';
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user