Refactors optimization list
This commit is contained in:
parent
1c0e1cc591
commit
dbb3d17d8f
@ -1236,136 +1236,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PartialEvaluator.optimizeQueue =
|
|
||||||
function PartialEvaluator_optimizeQueue(queue) {
|
|
||||||
|
|
||||||
function squash(array, index, howMany, element) {
|
|
||||||
if (isArray(array)) {
|
|
||||||
array.splice(index, howMany, element);
|
|
||||||
} else {
|
|
||||||
// Replace the element.
|
|
||||||
array[index] = element;
|
|
||||||
// Shift everything after the element up.
|
|
||||||
var sub = array.subarray(index + howMany);
|
|
||||||
array.set(sub, index + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var fnArray = queue.fnArray, argsArray = queue.argsArray;
|
|
||||||
// grouping paintInlineImageXObject's into paintInlineImageXObjectGroup
|
|
||||||
// searching for (save, transform, paintInlineImageXObject, restore)+
|
|
||||||
var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
|
|
||||||
var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
|
|
||||||
var MAX_WIDTH = 1000;
|
|
||||||
var IMAGE_PADDING = 1;
|
|
||||||
for (var i = 0, ii = argsArray.length; i < ii; i++) {
|
|
||||||
if (fnArray[i] === OPS.paintInlineImageXObject &&
|
|
||||||
fnArray[i - 2] === OPS.save && fnArray[i - 1] === OPS.transform &&
|
|
||||||
fnArray[i + 1] === OPS.restore) {
|
|
||||||
var j = i - 2;
|
|
||||||
for (i += 2; i < ii && fnArray[i - 4] === fnArray[i]; i++) {
|
|
||||||
}
|
|
||||||
var count = Math.min((i - j) >> 2,
|
|
||||||
MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
|
|
||||||
if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// assuming that heights of those image is too small (~1 pixel)
|
|
||||||
// packing as much as possible by lines
|
|
||||||
var maxX = 0;
|
|
||||||
var map = [], maxLineHeight = 0;
|
|
||||||
var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING;
|
|
||||||
for (var q = 0; q < count; q++) {
|
|
||||||
var transform = argsArray[j + (q << 2) + 1];
|
|
||||||
var img = argsArray[j + (q << 2) + 2][0];
|
|
||||||
if (currentX + img.width > MAX_WIDTH) {
|
|
||||||
// starting new line
|
|
||||||
maxX = Math.max(maxX, currentX);
|
|
||||||
currentY += maxLineHeight + 2 * IMAGE_PADDING;
|
|
||||||
currentX = 0;
|
|
||||||
maxLineHeight = 0;
|
|
||||||
}
|
|
||||||
map.push({
|
|
||||||
transform: transform,
|
|
||||||
x: currentX, y: currentY,
|
|
||||||
w: img.width, h: img.height
|
|
||||||
});
|
|
||||||
currentX += img.width + 2 * IMAGE_PADDING;
|
|
||||||
maxLineHeight = Math.max(maxLineHeight, img.height);
|
|
||||||
}
|
|
||||||
var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
|
|
||||||
var imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
|
|
||||||
var imgData = new Uint8Array(imgWidth * imgHeight * 4);
|
|
||||||
var imgRowSize = imgWidth << 2;
|
|
||||||
for (var q = 0; q < count; q++) {
|
|
||||||
var data = argsArray[j + (q << 2) + 2][0].data;
|
|
||||||
// copy image by lines and extends pixels into padding
|
|
||||||
var rowSize = map[q].w << 2;
|
|
||||||
var dataOffset = 0;
|
|
||||||
var offset = (map[q].x + map[q].y * imgWidth) << 2;
|
|
||||||
imgData.set(
|
|
||||||
data.subarray(0, rowSize), offset - imgRowSize);
|
|
||||||
for (var k = 0, kk = map[q].h; k < kk; k++) {
|
|
||||||
imgData.set(
|
|
||||||
data.subarray(dataOffset, dataOffset + rowSize), offset);
|
|
||||||
dataOffset += rowSize;
|
|
||||||
offset += imgRowSize;
|
|
||||||
}
|
|
||||||
imgData.set(
|
|
||||||
data.subarray(dataOffset - rowSize, dataOffset), offset);
|
|
||||||
while (offset >= 0) {
|
|
||||||
data[offset - 4] = data[offset];
|
|
||||||
data[offset - 3] = data[offset + 1];
|
|
||||||
data[offset - 2] = data[offset + 2];
|
|
||||||
data[offset - 1] = data[offset + 3];
|
|
||||||
data[offset + rowSize] = data[offset + rowSize - 4];
|
|
||||||
data[offset + rowSize + 1] = data[offset + rowSize - 3];
|
|
||||||
data[offset + rowSize + 2] = data[offset + rowSize - 2];
|
|
||||||
data[offset + rowSize + 3] = data[offset + rowSize - 1];
|
|
||||||
offset -= imgRowSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// replacing queue items
|
|
||||||
squash(fnArray, j, count * 4, OPS.paintInlineImageXObjectGroup);
|
|
||||||
argsArray.splice(j, count * 4,
|
|
||||||
[{width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP,
|
|
||||||
data: imgData}, map]);
|
|
||||||
i = j;
|
|
||||||
ii = argsArray.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// grouping paintImageMaskXObject's into paintImageMaskXObjectGroup
|
|
||||||
// searching for (save, transform, paintImageMaskXObject, restore)+
|
|
||||||
var MIN_IMAGES_IN_MASKS_BLOCK = 10;
|
|
||||||
var MAX_IMAGES_IN_MASKS_BLOCK = 100;
|
|
||||||
for (var i = 0, ii = argsArray.length; i < ii; i++) {
|
|
||||||
if (fnArray[i] === OPS.paintImageMaskXObject &&
|
|
||||||
fnArray[i - 2] === OPS.save && fnArray[i - 1] === OPS.transform &&
|
|
||||||
fnArray[i + 1] === OPS.restore) {
|
|
||||||
var j = i - 2;
|
|
||||||
for (i += 2; i < ii && fnArray[i - 4] === fnArray[i]; i++) {
|
|
||||||
}
|
|
||||||
var count = Math.min((i - j) >> 2,
|
|
||||||
MAX_IMAGES_IN_MASKS_BLOCK);
|
|
||||||
if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var images = [];
|
|
||||||
for (var q = 0; q < count; q++) {
|
|
||||||
var transform = argsArray[j + (q << 2) + 1];
|
|
||||||
var maskParams = argsArray[j + (q << 2) + 2][0];
|
|
||||||
images.push({data: maskParams.data, width: maskParams.width,
|
|
||||||
height: maskParams.height, transform: transform});
|
|
||||||
}
|
|
||||||
// replacing queue items
|
|
||||||
squash(fnArray, j, count * 4, OPS.paintImageMaskXObjectGroup);
|
|
||||||
argsArray.splice(j, count * 4, [images]);
|
|
||||||
i = j;
|
|
||||||
ii = argsArray.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return PartialEvaluator;
|
return PartialEvaluator;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@ -1454,7 +1324,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
flush: function(lastChunk) {
|
flush: function(lastChunk) {
|
||||||
PartialEvaluator.optimizeQueue(this);
|
new QueueOptimizer().optimize(this);
|
||||||
var transfers = getTransfers(this);
|
var transfers = getTransfers(this);
|
||||||
this.messageHandler.send('RenderPageChunk', {
|
this.messageHandler.send('RenderPageChunk', {
|
||||||
operatorList: {
|
operatorList: {
|
||||||
@ -1758,3 +1628,173 @@ var EvaluatorPreprocessor = (function EvaluatorPreprocessor() {
|
|||||||
};
|
};
|
||||||
return EvaluatorPreprocessor;
|
return EvaluatorPreprocessor;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||||
|
function squash(array, index, howMany, element) {
|
||||||
|
if (isArray(array)) {
|
||||||
|
array.splice(index, howMany, element);
|
||||||
|
} else {
|
||||||
|
// Replace the element.
|
||||||
|
array[index] = element;
|
||||||
|
// Shift everything after the element up.
|
||||||
|
var sub = array.subarray(index + howMany);
|
||||||
|
array.set(sub, index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addState(parentState, pattern, fn) {
|
||||||
|
var state = parentState;
|
||||||
|
for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
|
||||||
|
var item = pattern[i];
|
||||||
|
state = state[item] || (state[item] = []);
|
||||||
|
}
|
||||||
|
state[pattern[pattern.length - 1]] = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
var InitialState = [];
|
||||||
|
|
||||||
|
addState(InitialState,
|
||||||
|
[OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore],
|
||||||
|
function foundInlineImageGroup(context) {
|
||||||
|
// grouping paintInlineImageXObject's into paintInlineImageXObjectGroup
|
||||||
|
// searching for (save, transform, paintInlineImageXObject, restore)+
|
||||||
|
var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
|
||||||
|
var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
|
||||||
|
var MAX_WIDTH = 1000;
|
||||||
|
var IMAGE_PADDING = 1;
|
||||||
|
|
||||||
|
var fnArray = context.fnArray, argsArray = context.argsArray;
|
||||||
|
var j = context.currentOperation - 3, i = j + 4;
|
||||||
|
var ii = context.operationsLength;
|
||||||
|
|
||||||
|
for (; i < ii && fnArray[i - 4] === fnArray[i]; i++) {
|
||||||
|
}
|
||||||
|
var count = Math.min((i - j) >> 2, MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
|
||||||
|
if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
|
||||||
|
context.currentOperation = i - 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// assuming that heights of those image is too small (~1 pixel)
|
||||||
|
// packing as much as possible by lines
|
||||||
|
var maxX = 0;
|
||||||
|
var map = [], maxLineHeight = 0;
|
||||||
|
var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING;
|
||||||
|
for (var q = 0; q < count; q++) {
|
||||||
|
var transform = argsArray[j + (q << 2) + 1];
|
||||||
|
var img = argsArray[j + (q << 2) + 2][0];
|
||||||
|
if (currentX + img.width > MAX_WIDTH) {
|
||||||
|
// starting new line
|
||||||
|
maxX = Math.max(maxX, currentX);
|
||||||
|
currentY += maxLineHeight + 2 * IMAGE_PADDING;
|
||||||
|
currentX = 0;
|
||||||
|
maxLineHeight = 0;
|
||||||
|
}
|
||||||
|
map.push({
|
||||||
|
transform: transform,
|
||||||
|
x: currentX, y: currentY,
|
||||||
|
w: img.width, h: img.height
|
||||||
|
});
|
||||||
|
currentX += img.width + 2 * IMAGE_PADDING;
|
||||||
|
maxLineHeight = Math.max(maxLineHeight, img.height);
|
||||||
|
}
|
||||||
|
var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
|
||||||
|
var imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
|
||||||
|
var imgData = new Uint8Array(imgWidth * imgHeight * 4);
|
||||||
|
var imgRowSize = imgWidth << 2;
|
||||||
|
for (var q = 0; q < count; q++) {
|
||||||
|
var data = argsArray[j + (q << 2) + 2][0].data;
|
||||||
|
// copy image by lines and extends pixels into padding
|
||||||
|
var rowSize = map[q].w << 2;
|
||||||
|
var dataOffset = 0;
|
||||||
|
var offset = (map[q].x + map[q].y * imgWidth) << 2;
|
||||||
|
imgData.set(
|
||||||
|
data.subarray(0, rowSize), offset - imgRowSize);
|
||||||
|
for (var k = 0, kk = map[q].h; k < kk; k++) {
|
||||||
|
imgData.set(
|
||||||
|
data.subarray(dataOffset, dataOffset + rowSize), offset);
|
||||||
|
dataOffset += rowSize;
|
||||||
|
offset += imgRowSize;
|
||||||
|
}
|
||||||
|
imgData.set(
|
||||||
|
data.subarray(dataOffset - rowSize, dataOffset), offset);
|
||||||
|
while (offset >= 0) {
|
||||||
|
data[offset - 4] = data[offset];
|
||||||
|
data[offset - 3] = data[offset + 1];
|
||||||
|
data[offset - 2] = data[offset + 2];
|
||||||
|
data[offset - 1] = data[offset + 3];
|
||||||
|
data[offset + rowSize] = data[offset + rowSize - 4];
|
||||||
|
data[offset + rowSize + 1] = data[offset + rowSize - 3];
|
||||||
|
data[offset + rowSize + 2] = data[offset + rowSize - 2];
|
||||||
|
data[offset + rowSize + 3] = data[offset + rowSize - 1];
|
||||||
|
offset -= imgRowSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// replacing queue items
|
||||||
|
squash(fnArray, j, count * 4, OPS.paintInlineImageXObjectGroup);
|
||||||
|
argsArray.splice(j, count * 4,
|
||||||
|
[{width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP,
|
||||||
|
data: imgData}, map]);
|
||||||
|
context.currentOperation = j;
|
||||||
|
context.operationsLength -= count * 4 - 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
addState(InitialState,
|
||||||
|
[OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore],
|
||||||
|
function foundImageMaskGroup(context) {
|
||||||
|
// grouping paintImageMaskXObject's into paintImageMaskXObjectGroup
|
||||||
|
// searching for (save, transform, paintImageMaskXObject, restore)+
|
||||||
|
var MIN_IMAGES_IN_MASKS_BLOCK = 10;
|
||||||
|
var MAX_IMAGES_IN_MASKS_BLOCK = 100;
|
||||||
|
|
||||||
|
var fnArray = context.fnArray, argsArray = context.argsArray;
|
||||||
|
var j = context.currentOperation - 3, i = j + 4;
|
||||||
|
var ii = context.operationsLength;
|
||||||
|
|
||||||
|
for (; i < ii && fnArray[i - 4] === fnArray[i]; i++) {
|
||||||
|
}
|
||||||
|
var count = Math.min((i - j) >> 2, MAX_IMAGES_IN_MASKS_BLOCK);
|
||||||
|
if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
|
||||||
|
context.currentOperation = i - 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var images = [];
|
||||||
|
for (var q = 0; q < count; q++) {
|
||||||
|
var transform = argsArray[j + (q << 2) + 1];
|
||||||
|
var maskParams = argsArray[j + (q << 2) + 2][0];
|
||||||
|
images.push({data: maskParams.data, width: maskParams.width,
|
||||||
|
height: maskParams.height, transform: transform});
|
||||||
|
}
|
||||||
|
// replacing queue items
|
||||||
|
squash(fnArray, j, count * 4, OPS.paintImageMaskXObjectGroup);
|
||||||
|
argsArray.splice(j, count * 4, [images]);
|
||||||
|
|
||||||
|
context.currentOperation = j;
|
||||||
|
context.operationsLength -= count * 4 - 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
function QueueOptimizer() {
|
||||||
|
}
|
||||||
|
QueueOptimizer.prototype = {
|
||||||
|
optimize: function QueueOptimizer_optimize(queue) {
|
||||||
|
var fnArray = queue.fnArray, argsArray = queue.argsArray;
|
||||||
|
var context = {
|
||||||
|
currentOperation: 0,
|
||||||
|
operationsLength: argsArray.length,
|
||||||
|
fnArray: fnArray,
|
||||||
|
argsArray: argsArray
|
||||||
|
};
|
||||||
|
var i, ii = argsArray.length;
|
||||||
|
var state;
|
||||||
|
for (i = 0; i < ii; i++) {
|
||||||
|
state = (state || InitialState)[fnArray[i]];
|
||||||
|
if (typeof state === 'function') { // we found some handler
|
||||||
|
context.currentOperation = i;
|
||||||
|
state = state(context);
|
||||||
|
i = context.currentOperation;
|
||||||
|
ii = context.operationsLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return QueueOptimizer;
|
||||||
|
})();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user