Convert src/core/operator_list.js to use standard classes

With modern JavaScript modules, where only *explicitly* exported properties are visible to the outside, the `QueueOptimizerClosure` should no longer be necessary.

Furthermore, to reduce the possibility of `NullOptimizer` and `QueueOptimizer` getting out of sync (note e.g. the inconsistency fixed in PR 10784), we now let the latter extend the former one.
This commit is contained in:
Jonas Jenwald 2021-05-16 13:39:54 +02:00
parent 8a8a67de3b
commit 3cfa316d40

View File

@ -13,10 +13,9 @@
* limitations under the License.
*/
import { assert, ImageKind, OPS, warn } from "../shared/util.js";
import { assert, ImageKind, OPS, shadow, warn } from "../shared/util.js";
const QueueOptimizer = (function QueueOptimizerClosure() {
function addState(parentState, pattern, checkFn, iterateFn, processFn) {
function addState(parentState, pattern, checkFn, iterateFn, processFn) {
let state = parentState;
for (let i = 0, ii = pattern.length - 1; i < ii; i++) {
const item = pattern[i];
@ -27,14 +26,9 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
iterateFn,
processFn,
};
}
}
function handlePaintSolidColorImageMask(
iFirstSave,
count,
fnArray,
argsArray
) {
function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray) {
// Handles special case of mainly LaTeX documents which use image masks to
// draw lines with the current fill style.
// 'count' groups of (save, transform, paintImageMaskXObject, restore)+
@ -57,13 +51,13 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
break;
}
return count - i;
}
}
const InitialState = [];
const InitialState = [];
// This replaces (save, transform, paintInlineImageXObject, restore)+
// sequences with one |paintInlineImageXObjectGroup| operation.
addState(
// This replaces (save, transform, paintInlineImageXObject, restore)+
// sequences with one |paintInlineImageXObjectGroup| operation.
addState(
InitialState,
[OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore],
null,
@ -175,12 +169,12 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
return iFirstSave + 1;
}
);
);
// This replaces (save, transform, paintImageMaskXObject, restore)+
// sequences with one |paintImageMaskXObjectGroup| or one
// |paintImageMaskXObjectRepeat| operation.
addState(
// This replaces (save, transform, paintImageMaskXObject, restore)+
// sequences with one |paintImageMaskXObjectGroup| or one
// |paintImageMaskXObjectRepeat| operation.
addState(
InitialState,
[OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore],
null,
@ -297,20 +291,19 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
return iFirstSave + 1;
}
);
);
// This replaces (save, transform, paintImageXObject, restore)+ sequences
// with one paintImageXObjectRepeat operation, if the |transform| and
// |paintImageXObjectRepeat| ops are appropriate.
addState(
// This replaces (save, transform, paintImageXObject, restore)+ sequences
// with one paintImageXObjectRepeat operation, if the |transform| and
// |paintImageXObjectRepeat| ops are appropriate.
addState(
InitialState,
[OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore],
function (context) {
const argsArray = context.argsArray;
const iFirstTransform = context.iCurr - 2;
return (
argsArray[iFirstTransform][1] === 0 &&
argsArray[iFirstTransform][2] === 0
argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0
);
},
function iterateImageGroup(context, i) {
@ -397,12 +390,12 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
return iFirstSave + 1;
}
);
);
// This replaces (beginText, setFont, setTextMatrix, showText, endText)+
// sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+
// sequences, if the font for each one is the same.
addState(
// This replaces (beginText, setFont, setTextMatrix, showText, endText)+
// sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+
// sequences, if the font for each one is the same.
addState(
InitialState,
[OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText],
null,
@ -489,11 +482,29 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
return iEndText + 1;
}
);
);
// eslint-disable-next-line no-shadow
function QueueOptimizer(queue) {
class NullOptimizer {
constructor(queue) {
this.queue = queue;
}
_optimize() {}
push(fn, args) {
this.queue.fnArray.push(fn);
this.queue.argsArray.push(args);
this._optimize();
}
flush() {}
reset() {}
}
class QueueOptimizer extends NullOptimizer {
constructor(queue) {
super(queue);
this.state = null;
this.context = {
iCurr: 0,
@ -504,7 +515,6 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
this.lastProcessed = 0;
}
QueueOptimizer.prototype = {
_optimize() {
// Process new fnArray item(s) chunk.
const fnArray = this.queue.fnArray;
@ -557,13 +567,7 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
this.state = state;
this.match = match;
this.lastProcessed = i;
},
push(fn, args) {
this.queue.fnArray.push(fn);
this.queue.argsArray.push(args);
this._optimize();
},
}
flush() {
while (this.match) {
@ -574,43 +578,26 @@ const QueueOptimizer = (function QueueOptimizerClosure() {
// Repeat optimization until all chunks are exhausted.
this._optimize();
}
},
}
reset() {
this.state = null;
this.match = null;
this.lastProcessed = 0;
},
};
return QueueOptimizer;
})();
}
}
const NullOptimizer = (function NullOptimizerClosure() {
// eslint-disable-next-line no-shadow
function NullOptimizer(queue) {
this.queue = queue;
class OperatorList {
static get CHUNK_SIZE() {
return shadow(this, "CHUNK_SIZE", 1000);
}
NullOptimizer.prototype = {
push(fn, args) {
this.queue.fnArray.push(fn);
this.queue.argsArray.push(args);
},
// Close to chunk size.
static get CHUNK_SIZE_ABOUT() {
return shadow(this, "CHUNK_SIZE_ABOUT", OperatorList.CHUNK_SIZE - 5);
}
flush() {},
reset() {},
};
return NullOptimizer;
})();
const OperatorList = (function OperatorListClosure() {
const CHUNK_SIZE = 1000;
const CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size
// eslint-disable-next-line no-shadow
function OperatorList(intent, streamSink) {
constructor(intent, streamSink) {
this._streamSink = streamSink;
this.fnArray = [];
this.argsArray = [];
@ -625,14 +612,13 @@ const OperatorList = (function OperatorListClosure() {
this._resolved = streamSink ? null : Promise.resolve();
}
OperatorList.prototype = {
get length() {
return this.argsArray.length;
},
}
get ready() {
return this._resolved || this._streamSink.ready;
},
}
/**
* @type {number} The total length of the entire operator list, since
@ -640,23 +626,23 @@ const OperatorList = (function OperatorListClosure() {
*/
get totalLength() {
return this._totalLength + this.length;
},
}
addOp(fn, args) {
this.optimizer.push(fn, args);
this.weight++;
if (this._streamSink) {
if (this.weight >= CHUNK_SIZE) {
if (this.weight >= OperatorList.CHUNK_SIZE) {
this.flush();
} else if (
this.weight >= CHUNK_SIZE_ABOUT &&
this.weight >= OperatorList.CHUNK_SIZE_ABOUT &&
(fn === OPS.restore || fn === OPS.endText)
) {
// heuristic to flush on boundary of restore or endText
// Heuristic to flush on boundary of restore or endText.
this.flush();
}
}
},
}
addDependency(dependency) {
if (this.dependencies.has(dependency)) {
@ -664,13 +650,13 @@ const OperatorList = (function OperatorListClosure() {
}
this.dependencies.add(dependency);
this.addOp(OPS.dependency, [dependency]);
},
}
addDependencies(dependencies) {
for (const dependency of dependencies) {
this.addDependency(dependency);
}
},
}
addOpList(opList) {
if (!(opList instanceof OperatorList)) {
@ -683,7 +669,7 @@ const OperatorList = (function OperatorListClosure() {
for (let i = 0, ii = opList.length; i < ii; i++) {
this.addOp(opList.fnArray[i], opList.argsArray[i]);
}
},
}
getIR() {
return {
@ -691,7 +677,7 @@ const OperatorList = (function OperatorListClosure() {
argsArray: this.argsArray,
length: this.length,
};
},
}
get _transfers() {
const transfers = [];
@ -701,7 +687,7 @@ const OperatorList = (function OperatorListClosure() {
case OPS.paintInlineImageXObject:
case OPS.paintInlineImageXObjectGroup:
case OPS.paintImageMaskXObject:
const arg = argsArray[i][0]; // first param in imgData
const arg = argsArray[i][0]; // First parameter in imgData.
if (
typeof PDFJSDev === "undefined" ||
@ -719,7 +705,7 @@ const OperatorList = (function OperatorListClosure() {
}
}
return transfers;
},
}
flush(lastChunk = false) {
this.optimizer.flush();
@ -742,10 +728,7 @@ const OperatorList = (function OperatorListClosure() {
this.argsArray.length = 0;
this.weight = 0;
this.optimizer.reset();
},
};
return OperatorList;
})();
}
}
export { OperatorList };