Caches last parsed resource image, recornizes image repeats
This commit is contained in:
parent
2c23be369b
commit
f48f57e30a
@ -124,7 +124,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
buildPaintImageXObject: function PartialEvaluator_buildPaintImageXObject(
|
buildPaintImageXObject: function PartialEvaluator_buildPaintImageXObject(
|
||||||
resources, image, inline, operatorList) {
|
resources, image, inline, operatorList,
|
||||||
|
cacheKey, cache) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var dict = image.dict;
|
var dict = image.dict;
|
||||||
var w = dict.get('Width', 'W');
|
var w = dict.get('Width', 'W');
|
||||||
@ -197,8 +198,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData],
|
self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData],
|
||||||
null, [imgData.data.buffer]);
|
null, [imgData.data.buffer]);
|
||||||
}, self.handler, self.xref, resources, image, inline);
|
}, self.handler, self.xref, resources, image, inline);
|
||||||
|
|
||||||
operatorList.addOp(OPS.paintImageXObject, args);
|
operatorList.addOp(OPS.paintImageXObject, args);
|
||||||
|
if (cacheKey) {
|
||||||
|
cache.key = cacheKey;
|
||||||
|
cache.fn = OPS.paintImageXObject;
|
||||||
|
cache.args = args;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSMask: function PartialEvaluator_handleSmask(smask, resources,
|
handleSMask: function PartialEvaluator_handleSmask(smask, resources,
|
||||||
@ -452,6 +457,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var xref = this.xref;
|
var xref = this.xref;
|
||||||
var handler = this.handler;
|
var handler = this.handler;
|
||||||
|
var imageCache = {};
|
||||||
|
|
||||||
operatorList = operatorList || new OperatorList();
|
operatorList = operatorList || new OperatorList();
|
||||||
|
|
||||||
@ -507,6 +513,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
// eagerly compile XForm objects
|
// eagerly compile XForm objects
|
||||||
var name = args[0].name;
|
var name = args[0].name;
|
||||||
|
if (imageCache.key === name) {
|
||||||
|
operatorList.addOp(imageCache.fn, imageCache.args);
|
||||||
|
args = [];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var xobj = xobjs.get(name);
|
var xobj = xobjs.get(name);
|
||||||
if (xobj) {
|
if (xobj) {
|
||||||
assertWellFormed(
|
assertWellFormed(
|
||||||
@ -525,7 +537,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
continue;
|
continue;
|
||||||
} else if ('Image' == type.name) {
|
} else if ('Image' == type.name) {
|
||||||
self.buildPaintImageXObject(resources, xobj, false,
|
self.buildPaintImageXObject(resources, xobj, false,
|
||||||
operatorList);
|
operatorList, name, imageCache);
|
||||||
args = [];
|
args = [];
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
@ -641,6 +653,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
resources = xref.fetchIfRef(resources) || new Dict();
|
resources = xref.fetchIfRef(resources) || new Dict();
|
||||||
// The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
|
// The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
|
||||||
var xobjs = null;
|
var xobjs = null;
|
||||||
|
var xobjsCache = {};
|
||||||
|
|
||||||
var preprocessor = new EvaluatorPreprocessor(stream, xref);
|
var preprocessor = new EvaluatorPreprocessor(stream, xref);
|
||||||
var res = resources;
|
var res = resources;
|
||||||
@ -735,6 +748,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var name = args[0].name;
|
var name = args[0].name;
|
||||||
|
if (xobjsCache.key === name) {
|
||||||
|
if (xobjsCache.texts) {
|
||||||
|
Util.concatenateToArray(bidiTexts, xobjsCache.texts);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
var xobj = xobjs.get(name);
|
var xobj = xobjs.get(name);
|
||||||
if (!xobj)
|
if (!xobj)
|
||||||
break;
|
break;
|
||||||
@ -746,14 +766,19 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
'XObject should have a Name subtype'
|
'XObject should have a Name subtype'
|
||||||
);
|
);
|
||||||
|
|
||||||
if ('Form' !== type.name)
|
if ('Form' !== type.name) {
|
||||||
|
xobjsCache.key = name;
|
||||||
|
xobjsCache.texts = null;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
var formTexts = this.getTextContent(
|
var formTexts = this.getTextContent(
|
||||||
xobj,
|
xobj,
|
||||||
xobj.dict.get('Resources') || resources,
|
xobj.dict.get('Resources') || resources,
|
||||||
textState
|
textState
|
||||||
);
|
);
|
||||||
|
xobjsCache.key = name;
|
||||||
|
xobjsCache.texts = formTexts;
|
||||||
Util.concatenateToArray(bidiTexts, formTexts);
|
Util.concatenateToArray(bidiTexts, formTexts);
|
||||||
break;
|
break;
|
||||||
case OPS.setGState:
|
case OPS.setGState:
|
||||||
@ -1240,7 +1265,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
var OperatorList = (function OperatorListClosure() {
|
var OperatorList = (function OperatorListClosure() {
|
||||||
var CHUNK_SIZE = 100;
|
var CHUNK_SIZE = 1000;
|
||||||
|
|
||||||
function getTransfers(queue) {
|
function getTransfers(queue) {
|
||||||
var transfers = [];
|
var transfers = [];
|
||||||
@ -1776,6 +1801,60 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
context.operationsLength -= count * 4 - 1;
|
context.operationsLength -= count * 4 - 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addState(InitialState,
|
||||||
|
[OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore],
|
||||||
|
function (context) {
|
||||||
|
var MIN_IMAGES_IN_BLOCK = 3;
|
||||||
|
var MAX_IMAGES_IN_BLOCK = 1000;
|
||||||
|
|
||||||
|
var fnArray = context.fnArray, argsArray = context.argsArray;
|
||||||
|
var j = context.currentOperation - 3, i = j + 4;
|
||||||
|
if (argsArray[j + 1][1] !== 0 || argsArray[j + 1][2] !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var ii = context.operationsLength;
|
||||||
|
for (; i + 3 < ii && fnArray[i - 4] === fnArray[i]; i += 4) {
|
||||||
|
if (fnArray[i - 3] !== fnArray[i + 1] ||
|
||||||
|
fnArray[i - 2] !== fnArray[i + 2] ||
|
||||||
|
fnArray[i - 1] !== fnArray[i + 3]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (argsArray[i - 2][0] !== argsArray[i + 2][0]) {
|
||||||
|
break; // different image
|
||||||
|
}
|
||||||
|
var prevTransformArgs = argsArray[i - 3];
|
||||||
|
var transformArgs = argsArray[i + 1];
|
||||||
|
if (prevTransformArgs[0] !== transformArgs[0] ||
|
||||||
|
prevTransformArgs[1] !== transformArgs[1] ||
|
||||||
|
prevTransformArgs[2] !== transformArgs[2] ||
|
||||||
|
prevTransformArgs[3] !== transformArgs[3]) {
|
||||||
|
break; // different transform
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var count = Math.min((i - j) >> 2, MAX_IMAGES_IN_BLOCK);
|
||||||
|
if (count < MIN_IMAGES_IN_BLOCK) {
|
||||||
|
context.currentOperation = i - 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var positions = new Float32Array(count * 2);
|
||||||
|
i = j + 1;
|
||||||
|
for (var q = 0; q < count; q++) {
|
||||||
|
var transformArgs = argsArray[i];
|
||||||
|
positions[(q << 1)] = transformArgs[4];
|
||||||
|
positions[(q << 1) + 1] = transformArgs[5];
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
var args = [argsArray[j + 2][0], argsArray[j + 1][0],
|
||||||
|
argsArray[j + 1][3], positions];
|
||||||
|
// replacing queue items
|
||||||
|
squash(fnArray, j, count * 4, OPS.paintImageMaskXObjectRepeat);
|
||||||
|
argsArray.splice(j, count * 4, args);
|
||||||
|
|
||||||
|
context.currentOperation = j;
|
||||||
|
context.operationsLength -= count * 4 - 1;
|
||||||
|
});
|
||||||
|
|
||||||
addState(InitialState,
|
addState(InitialState,
|
||||||
[OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText],
|
[OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText],
|
||||||
function (context) {
|
function (context) {
|
||||||
|
@ -1959,12 +1959,31 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
|
|
||||||
paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
|
paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
|
||||||
var imgData = this.objs.get(objId);
|
var imgData = this.objs.get(objId);
|
||||||
if (!imgData)
|
if (!imgData) {
|
||||||
error('Dependent image isn\'t ready yet');
|
error('Dependent image isn\'t ready yet');
|
||||||
|
}
|
||||||
|
|
||||||
this.paintInlineImageXObject(imgData);
|
this.paintInlineImageXObject(imgData);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
paintImageMaskXObjectRepeat:
|
||||||
|
function CanvasGraphics_paintImageMaskXObjectRepeat(objId, scaleX, scaleY,
|
||||||
|
positions) {
|
||||||
|
var imgData = this.objs.get(objId);
|
||||||
|
if (!imgData) {
|
||||||
|
error('Dependent image isn\'t ready yet');
|
||||||
|
}
|
||||||
|
|
||||||
|
var width = imgData.width;
|
||||||
|
var height = imgData.height;
|
||||||
|
var map = [];
|
||||||
|
for (var i = 0, ii = positions.length; i < ii; i += 2) {
|
||||||
|
map.push({transform: [scaleX, 0, 0, scaleY, positions[i],
|
||||||
|
positions[i + 1]], x: 0, y: 0, w: width, h: height});
|
||||||
|
}
|
||||||
|
this.paintInlineImageXObjectGroup(imgData, map);
|
||||||
|
},
|
||||||
|
|
||||||
paintInlineImageXObject:
|
paintInlineImageXObject:
|
||||||
function CanvasGraphics_paintInlineImageXObject(imgData) {
|
function CanvasGraphics_paintInlineImageXObject(imgData) {
|
||||||
var width = imgData.width;
|
var width = imgData.width;
|
||||||
|
@ -149,7 +149,8 @@ var OPS = PDFJS.OPS = {
|
|||||||
paintImageMaskXObjectGroup: 84,
|
paintImageMaskXObjectGroup: 84,
|
||||||
paintImageXObject: 85,
|
paintImageXObject: 85,
|
||||||
paintInlineImageXObject: 86,
|
paintInlineImageXObject: 86,
|
||||||
paintInlineImageXObjectGroup: 87
|
paintInlineImageXObjectGroup: 87,
|
||||||
|
paintImageMaskXObjectRepeat: 88
|
||||||
};
|
};
|
||||||
|
|
||||||
// A notice for devs. These are good for things that are helpful to devs, such
|
// A notice for devs. These are good for things that are helpful to devs, such
|
||||||
|
Loading…
x
Reference in New Issue
Block a user