Extracts evaluator preprocessor and refactor text extraction
This commit is contained in:
parent
455265474a
commit
09f8f951c8
@ -40,119 +40,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
this.fontCache = fontCache;
|
this.fontCache = fontCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specifies properties for each command
|
|
||||||
//
|
|
||||||
// If variableArgs === true: [0, `numArgs`] expected
|
|
||||||
// If variableArgs === false: exactly `numArgs` expected
|
|
||||||
var OP_MAP = {
|
|
||||||
// Graphic state
|
|
||||||
w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false },
|
|
||||||
J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false },
|
|
||||||
j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false },
|
|
||||||
M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false },
|
|
||||||
d: { id: OPS.setDash, numArgs: 2, variableArgs: false },
|
|
||||||
ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false },
|
|
||||||
i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false },
|
|
||||||
gs: { id: OPS.setGState, numArgs: 1, variableArgs: false },
|
|
||||||
q: { id: OPS.save, numArgs: 0, variableArgs: false },
|
|
||||||
Q: { id: OPS.restore, numArgs: 0, variableArgs: false },
|
|
||||||
cm: { id: OPS.transform, numArgs: 6, variableArgs: false },
|
|
||||||
|
|
||||||
// Path
|
|
||||||
m: { id: OPS.moveTo, numArgs: 2, variableArgs: false },
|
|
||||||
l: { id: OPS.lineTo, numArgs: 2, variableArgs: false },
|
|
||||||
c: { id: OPS.curveTo, numArgs: 6, variableArgs: false },
|
|
||||||
v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false },
|
|
||||||
y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false },
|
|
||||||
h: { id: OPS.closePath, numArgs: 0, variableArgs: false },
|
|
||||||
re: { id: OPS.rectangle, numArgs: 4, variableArgs: false },
|
|
||||||
S: { id: OPS.stroke, numArgs: 0, variableArgs: false },
|
|
||||||
s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false },
|
|
||||||
f: { id: OPS.fill, numArgs: 0, variableArgs: false },
|
|
||||||
F: { id: OPS.fill, numArgs: 0, variableArgs: false },
|
|
||||||
'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false },
|
|
||||||
B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false },
|
|
||||||
'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false },
|
|
||||||
b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false },
|
|
||||||
'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false },
|
|
||||||
n: { id: OPS.endPath, numArgs: 0, variableArgs: false },
|
|
||||||
|
|
||||||
// Clipping
|
|
||||||
W: { id: OPS.clip, numArgs: 0, variableArgs: false },
|
|
||||||
'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false },
|
|
||||||
|
|
||||||
// Text
|
|
||||||
BT: { id: OPS.beginText, numArgs: 0, variableArgs: false },
|
|
||||||
ET: { id: OPS.endText, numArgs: 0, variableArgs: false },
|
|
||||||
Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false },
|
|
||||||
Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false },
|
|
||||||
Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false },
|
|
||||||
TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false },
|
|
||||||
Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false },
|
|
||||||
Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false },
|
|
||||||
Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false },
|
|
||||||
Td: { id: OPS.moveText, numArgs: 2, variableArgs: false },
|
|
||||||
TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false },
|
|
||||||
Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false },
|
|
||||||
'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false },
|
|
||||||
Tj: { id: OPS.showText, numArgs: 1, variableArgs: false },
|
|
||||||
TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false },
|
|
||||||
'\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false },
|
|
||||||
'"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3,
|
|
||||||
variableArgs: false },
|
|
||||||
|
|
||||||
// Type3 fonts
|
|
||||||
d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false },
|
|
||||||
d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false },
|
|
||||||
|
|
||||||
// Color
|
|
||||||
CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false },
|
|
||||||
cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false },
|
|
||||||
SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true },
|
|
||||||
SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true },
|
|
||||||
sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true },
|
|
||||||
scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true },
|
|
||||||
G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false },
|
|
||||||
g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false },
|
|
||||||
RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false },
|
|
||||||
rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false },
|
|
||||||
K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false },
|
|
||||||
k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false },
|
|
||||||
|
|
||||||
// Shading
|
|
||||||
sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false },
|
|
||||||
|
|
||||||
// Images
|
|
||||||
BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false },
|
|
||||||
ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false },
|
|
||||||
EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false },
|
|
||||||
|
|
||||||
// XObjects
|
|
||||||
Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false },
|
|
||||||
MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false },
|
|
||||||
DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false },
|
|
||||||
BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false },
|
|
||||||
BDC: { id: OPS.beginMarkedContentProps, numArgs: 2,
|
|
||||||
variableArgs: false },
|
|
||||||
EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false },
|
|
||||||
|
|
||||||
// Compatibility
|
|
||||||
BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false },
|
|
||||||
EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false },
|
|
||||||
|
|
||||||
// (reserved partial commands for the lexer)
|
|
||||||
BM: null,
|
|
||||||
BD: null,
|
|
||||||
'true': null,
|
|
||||||
fa: null,
|
|
||||||
fal: null,
|
|
||||||
fals: null,
|
|
||||||
'false': null,
|
|
||||||
nu: null,
|
|
||||||
nul: null,
|
|
||||||
'null': null
|
|
||||||
};
|
|
||||||
|
|
||||||
var TILING_PATTERN = 1, SHADING_PATTERN = 2;
|
var TILING_PATTERN = 1, SHADING_PATTERN = 2;
|
||||||
|
|
||||||
PartialEvaluator.prototype = {
|
PartialEvaluator.prototype = {
|
||||||
@ -198,7 +85,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
|
|
||||||
buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
|
buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
|
||||||
xobj, smask,
|
xobj, smask,
|
||||||
operatorList) {
|
operatorList,
|
||||||
|
state) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var matrix = xobj.dict.get('Matrix');
|
var matrix = xobj.dict.get('Matrix');
|
||||||
@ -226,7 +114,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]);
|
operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]);
|
||||||
|
|
||||||
this.getOperatorList(xobj, xobj.dict.get('Resources') || resources,
|
this.getOperatorList(xobj, xobj.dict.get('Resources') || resources,
|
||||||
operatorList);
|
operatorList, state);
|
||||||
operatorList.addOp(OPS.paintFormXObjectEnd, []);
|
operatorList.addOp(OPS.paintFormXObjectEnd, []);
|
||||||
|
|
||||||
if (group) {
|
if (group) {
|
||||||
@ -532,7 +420,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
|
|
||||||
getOperatorList: function PartialEvaluator_getOperatorList(stream,
|
getOperatorList: function PartialEvaluator_getOperatorList(stream,
|
||||||
resources,
|
resources,
|
||||||
operatorList) {
|
operatorList,
|
||||||
|
evaluatorState) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var xref = this.xref;
|
var xref = this.xref;
|
||||||
@ -543,54 +432,16 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
resources = resources || new Dict();
|
resources = resources || new Dict();
|
||||||
var xobjs = resources.get('XObject') || new Dict();
|
var xobjs = resources.get('XObject') || new Dict();
|
||||||
var patterns = resources.get('Pattern') || new Dict();
|
var patterns = resources.get('Pattern') || new Dict();
|
||||||
// TODO(mduan): pass array of knownCommands rather than OP_MAP
|
var preprocessor = new EvaluatorPreprocessor(stream, xref);
|
||||||
// dictionary
|
if (evaluatorState) {
|
||||||
var parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
|
preprocessor.setState(evaluatorState);
|
||||||
|
}
|
||||||
|
|
||||||
var promise = new LegacyPromise();
|
var promise = new LegacyPromise();
|
||||||
var args = [];
|
var operation;
|
||||||
while (true) {
|
while ((operation = preprocessor.read())) {
|
||||||
|
var args = operation.args;
|
||||||
var obj = parser.getObj();
|
var fn = operation.fn;
|
||||||
|
|
||||||
if (isEOF(obj)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCmd(obj)) {
|
|
||||||
var cmd = obj.cmd;
|
|
||||||
|
|
||||||
// Check that the command is valid
|
|
||||||
var opSpec = OP_MAP[cmd];
|
|
||||||
if (!opSpec) {
|
|
||||||
warn('Unknown command "' + cmd + '"');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fn = opSpec.id;
|
|
||||||
|
|
||||||
// Validate the number of arguments for the command
|
|
||||||
if (opSpec.variableArgs) {
|
|
||||||
if (args.length > opSpec.numArgs) {
|
|
||||||
info('Command ' + fn + ': expected [0,' + opSpec.numArgs +
|
|
||||||
'] args, but received ' + args.length + ' args');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (args.length < opSpec.numArgs) {
|
|
||||||
// If we receive too few args, it's not possible to possible
|
|
||||||
// to execute the command, so skip the command
|
|
||||||
info('Command ' + fn + ': because expected ' +
|
|
||||||
opSpec.numArgs + ' args, but received ' + args.length +
|
|
||||||
' args; skipping');
|
|
||||||
args = [];
|
|
||||||
continue;
|
|
||||||
} else if (args.length > opSpec.numArgs) {
|
|
||||||
info('Command ' + fn + ': expected ' + opSpec.numArgs +
|
|
||||||
' args, but received ' + args.length + ' args');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO figure out how to type-check vararg functions
|
|
||||||
|
|
||||||
switch (fn) {
|
switch (fn) {
|
||||||
case OPS.setStrokeColorN:
|
case OPS.setStrokeColorN:
|
||||||
@ -642,7 +493,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if ('Form' == type.name) {
|
if ('Form' == type.name) {
|
||||||
self.buildFormXObject(resources, xobj, null, operatorList);
|
self.buildFormXObject(resources, xobj, null, operatorList,
|
||||||
|
preprocessor.getState());
|
||||||
args = [];
|
args = [];
|
||||||
continue;
|
continue;
|
||||||
} else if ('Image' == type.name) {
|
} else if ('Image' == type.name) {
|
||||||
@ -733,12 +585,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
operatorList.addOp(fn, args);
|
operatorList.addOp(fn, args);
|
||||||
args = [];
|
}
|
||||||
parser.saveState();
|
|
||||||
} else if (obj !== null && obj !== undefined) {
|
// some pdf don't close all restores inside object/form
|
||||||
args.push(obj instanceof Dict ? obj.getAll() : obj);
|
// closing those for them
|
||||||
assertWellFormed(args.length <= 33, 'Too many arguments');
|
for (var i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
|
||||||
}
|
operatorList.addOp(OPS.restore, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
return operatorList;
|
return operatorList;
|
||||||
@ -775,65 +627,55 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
// 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 parser = new Parser(new Lexer(stream), false);
|
var preprocessor = new EvaluatorPreprocessor(stream, xref);
|
||||||
var res = resources;
|
var res = resources;
|
||||||
var args = [], obj;
|
|
||||||
|
|
||||||
var chunk = '';
|
var chunk = '';
|
||||||
var font = null;
|
var font = null;
|
||||||
var charSpace = 0, wordSpace = 0;
|
var charSpace = 0, wordSpace = 0;
|
||||||
while (!isEOF(obj = parser.getObj())) {
|
var operation;
|
||||||
if (isCmd(obj)) {
|
while ((operation = preprocessor.read())) {
|
||||||
var cmd = obj.cmd;
|
var fn = operation.fn;
|
||||||
switch (cmd) {
|
var args = operation.args;
|
||||||
|
switch (fn) {
|
||||||
// TODO: Add support for SAVE/RESTORE and XFORM here.
|
// TODO: Add support for SAVE/RESTORE and XFORM here.
|
||||||
case 'Tf':
|
case OPS.setFont:
|
||||||
font = handleSetFont(args[0].name).translated;
|
font = handleSetFont(args[0].name).translated;
|
||||||
textState.fontSize = args[1];
|
textState.fontSize = args[1];
|
||||||
break;
|
break;
|
||||||
case 'Ts':
|
case OPS.setTextRise:
|
||||||
textState.textRise = args[0];
|
textState.textRise = args[0];
|
||||||
break;
|
break;
|
||||||
case 'Tz':
|
case OPS.setHScale:
|
||||||
textState.textHScale = args[0] / 100;
|
textState.textHScale = args[0] / 100;
|
||||||
break;
|
break;
|
||||||
case 'TL':
|
case OPS.setLeading:
|
||||||
textState.leading = args[0];
|
textState.leading = args[0];
|
||||||
break;
|
break;
|
||||||
case 'Td':
|
case OPS.moveText:
|
||||||
textState.translateTextMatrix(args[0], args[1]);
|
textState.translateTextMatrix(args[0], args[1]);
|
||||||
break;
|
break;
|
||||||
case 'TD':
|
case OPS.setLeadingMoveText:
|
||||||
textState.leading = -args[1];
|
textState.leading = -args[1];
|
||||||
textState.translateTextMatrix(args[0], args[1]);
|
textState.translateTextMatrix(args[0], args[1]);
|
||||||
break;
|
break;
|
||||||
case 'T*':
|
case OPS.nextLine:
|
||||||
textState.translateTextMatrix(0, -textState.leading);
|
textState.translateTextMatrix(0, -textState.leading);
|
||||||
break;
|
break;
|
||||||
case 'Tm':
|
case OPS.setTextMatrix:
|
||||||
textState.setTextMatrix(args[0], args[1],
|
textState.setTextMatrix(args[0], args[1],
|
||||||
args[2], args[3], args[4], args[5]);
|
args[2], args[3], args[4], args[5]);
|
||||||
break;
|
break;
|
||||||
case 'Tc':
|
case OPS.setCharSpacing:
|
||||||
charSpace = args[0];
|
charSpace = args[0];
|
||||||
break;
|
break;
|
||||||
case 'Tw':
|
case OPS.setWordSpacing:
|
||||||
wordSpace = args[0];
|
wordSpace = args[0];
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case OPS.beginText:
|
||||||
textState.push();
|
|
||||||
break;
|
|
||||||
case 'Q':
|
|
||||||
textState.pop();
|
|
||||||
break;
|
|
||||||
case 'BT':
|
|
||||||
textState.initialiseTextObj();
|
textState.initialiseTextObj();
|
||||||
break;
|
break;
|
||||||
case 'cm':
|
case OPS.showSpacedText:
|
||||||
textState.transformCTM(args[0], args[1], args[2],
|
|
||||||
args[3], args[4], args[5]);
|
|
||||||
break;
|
|
||||||
case 'TJ':
|
|
||||||
var items = args[0];
|
var items = args[0];
|
||||||
for (var j = 0, jj = items.length; j < jj; j++) {
|
for (var j = 0, jj = items.length; j < jj; j++) {
|
||||||
if (typeof items[j] === 'string') {
|
if (typeof items[j] === 'string') {
|
||||||
@ -851,20 +693,20 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'Tj':
|
case OPS.showText:
|
||||||
chunk += fontCharsToUnicode(args[0], font);
|
chunk += fontCharsToUnicode(args[0], font);
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case OPS.nextLineShowText:
|
||||||
// For search, adding a extra white space for line breaks would be
|
// For search, adding a extra white space for line breaks would be
|
||||||
// better here, but that causes too much spaces in the
|
// better here, but that causes too much spaces in the
|
||||||
// text-selection divs.
|
// text-selection divs.
|
||||||
chunk += fontCharsToUnicode(args[0], font);
|
chunk += fontCharsToUnicode(args[0], font);
|
||||||
break;
|
break;
|
||||||
case '"':
|
case OPS.nextLineSetSpacingShowText:
|
||||||
// Note comment in "'"
|
// Note comment in "'"
|
||||||
chunk += fontCharsToUnicode(args[2], font);
|
chunk += fontCharsToUnicode(args[2], font);
|
||||||
break;
|
break;
|
||||||
case 'Do':
|
case OPS.paintXObject:
|
||||||
// Set the chunk such that the following if won't add something
|
// Set the chunk such that the following if won't add something
|
||||||
// to the state.
|
// to the state.
|
||||||
chunk = '';
|
chunk = '';
|
||||||
@ -898,7 +740,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
state
|
state
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'gs':
|
case OPS.setGState:
|
||||||
var dictName = args[0];
|
var dictName = args[0];
|
||||||
var extGState = resources.get('ExtGState');
|
var extGState = resources.get('ExtGState');
|
||||||
|
|
||||||
@ -917,7 +759,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
|
|
||||||
if (chunk !== '') {
|
if (chunk !== '') {
|
||||||
var bidiText = PDFJS.bidi(chunk, -1, font.vertical);
|
var bidiText = PDFJS.bidi(chunk, -1, font.vertical);
|
||||||
var renderParams = textState.calcRenderParams();
|
var renderParams = textState.calcRenderParams(preprocessor.ctm);
|
||||||
|
bidiText.x = renderParams.renderMatrix[4] - (textState.fontSize *
|
||||||
|
renderParams.vScale * Math.sin(renderParams.angle));
|
||||||
|
bidiText.y = renderParams.renderMatrix[5] + (textState.fontSize *
|
||||||
|
renderParams.vScale * Math.cos(renderParams.angle));
|
||||||
var fontHeight = textState.fontSize * renderParams.vScale;
|
var fontHeight = textState.fontSize * renderParams.vScale;
|
||||||
var fontAscent = font.ascent ? font.ascent * fontHeight :
|
var fontAscent = font.ascent ? font.ascent * fontHeight :
|
||||||
font.descent ? (1 + font.descent) * fontHeight : fontHeight;
|
font.descent ? (1 + font.descent) * fontHeight : fontHeight;
|
||||||
@ -933,12 +779,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
|
|
||||||
chunk = '';
|
chunk = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
args = [];
|
|
||||||
} else if (obj !== null && obj !== undefined) {
|
|
||||||
assertWellFormed(args.length <= 33, 'Too many arguments');
|
|
||||||
args.push(obj);
|
|
||||||
}
|
|
||||||
} // while
|
} // while
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@ -1597,7 +1437,6 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
var TextState = (function TextStateClosure() {
|
var TextState = (function TextStateClosure() {
|
||||||
function TextState() {
|
function TextState() {
|
||||||
this.fontSize = 0;
|
this.fontSize = 0;
|
||||||
this.ctm = [1, 0, 0, 1, 0, 0];
|
|
||||||
this.textMatrix = [1, 0, 0, 1, 0, 0];
|
this.textMatrix = [1, 0, 0, 1, 0, 0];
|
||||||
this.stateStack = [];
|
this.stateStack = [];
|
||||||
//textState variables
|
//textState variables
|
||||||
@ -1606,15 +1445,6 @@ var TextState = (function TextStateClosure() {
|
|||||||
this.textRise = 0;
|
this.textRise = 0;
|
||||||
}
|
}
|
||||||
TextState.prototype = {
|
TextState.prototype = {
|
||||||
push: function TextState_push() {
|
|
||||||
this.stateStack.push(this.ctm.slice());
|
|
||||||
},
|
|
||||||
pop: function TextState_pop() {
|
|
||||||
var prev = this.stateStack.pop();
|
|
||||||
if (prev) {
|
|
||||||
this.ctm = prev;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initialiseTextObj: function TextState_initialiseTextObj() {
|
initialiseTextObj: function TextState_initialiseTextObj() {
|
||||||
var m = this.textMatrix;
|
var m = this.textMatrix;
|
||||||
m[0] = 1, m[1] = 0, m[2] = 0, m[3] = 1, m[4] = 0, m[5] = 0;
|
m[0] = 1, m[1] = 0, m[2] = 0, m[3] = 1, m[4] = 0, m[5] = 0;
|
||||||
@ -1623,24 +1453,13 @@ var TextState = (function TextStateClosure() {
|
|||||||
var m = this.textMatrix;
|
var m = this.textMatrix;
|
||||||
m[0] = a, m[1] = b, m[2] = c, m[3] = d, m[4] = e, m[5] = f;
|
m[0] = a, m[1] = b, m[2] = c, m[3] = d, m[4] = e, m[5] = f;
|
||||||
},
|
},
|
||||||
transformCTM: function TextState_transformCTM(a, b, c, d, e, f) {
|
|
||||||
var m = this.ctm;
|
|
||||||
var m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], m4 = m[4], m5 = m[5];
|
|
||||||
m[0] = m0 * a + m2 * b;
|
|
||||||
m[1] = m1 * a + m3 * b;
|
|
||||||
m[2] = m0 * c + m2 * d;
|
|
||||||
m[3] = m1 * c + m3 * d;
|
|
||||||
m[4] = m0 * e + m2 * f + m4;
|
|
||||||
m[5] = m1 * e + m3 * f + m5;
|
|
||||||
},
|
|
||||||
translateTextMatrix: function TextState_translateTextMatrix(x, y) {
|
translateTextMatrix: function TextState_translateTextMatrix(x, y) {
|
||||||
var m = this.textMatrix;
|
var m = this.textMatrix;
|
||||||
m[4] = m[0] * x + m[2] * y + m[4];
|
m[4] = m[0] * x + m[2] * y + m[4];
|
||||||
m[5] = m[1] * x + m[3] * y + m[5];
|
m[5] = m[1] * x + m[3] * y + m[5];
|
||||||
},
|
},
|
||||||
calcRenderParams: function TextState_calcRenderingParams() {
|
calcRenderParams: function TextState_calcRenderingParams(cm) {
|
||||||
var tm = this.textMatrix;
|
var tm = this.textMatrix;
|
||||||
var cm = this.ctm;
|
|
||||||
var a = this.fontSize;
|
var a = this.fontSize;
|
||||||
var b = a * this.textHScale;
|
var b = a * this.textHScale;
|
||||||
var c = this.textRise;
|
var c = this.textRise;
|
||||||
@ -1683,3 +1502,218 @@ var EvalState = (function EvalStateClosure() {
|
|||||||
return EvalState;
|
return EvalState;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
var EvaluatorPreprocessor = (function EvaluatorPreprocessor() {
|
||||||
|
// Specifies properties for each command
|
||||||
|
//
|
||||||
|
// If variableArgs === true: [0, `numArgs`] expected
|
||||||
|
// If variableArgs === false: exactly `numArgs` expected
|
||||||
|
var OP_MAP = {
|
||||||
|
// Graphic state
|
||||||
|
w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false },
|
||||||
|
J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false },
|
||||||
|
j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false },
|
||||||
|
M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false },
|
||||||
|
d: { id: OPS.setDash, numArgs: 2, variableArgs: false },
|
||||||
|
ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false },
|
||||||
|
i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false },
|
||||||
|
gs: { id: OPS.setGState, numArgs: 1, variableArgs: false },
|
||||||
|
q: { id: OPS.save, numArgs: 0, variableArgs: false },
|
||||||
|
Q: { id: OPS.restore, numArgs: 0, variableArgs: false },
|
||||||
|
cm: { id: OPS.transform, numArgs: 6, variableArgs: false },
|
||||||
|
|
||||||
|
// Path
|
||||||
|
m: { id: OPS.moveTo, numArgs: 2, variableArgs: false },
|
||||||
|
l: { id: OPS.lineTo, numArgs: 2, variableArgs: false },
|
||||||
|
c: { id: OPS.curveTo, numArgs: 6, variableArgs: false },
|
||||||
|
v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false },
|
||||||
|
y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false },
|
||||||
|
h: { id: OPS.closePath, numArgs: 0, variableArgs: false },
|
||||||
|
re: { id: OPS.rectangle, numArgs: 4, variableArgs: false },
|
||||||
|
S: { id: OPS.stroke, numArgs: 0, variableArgs: false },
|
||||||
|
s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false },
|
||||||
|
f: { id: OPS.fill, numArgs: 0, variableArgs: false },
|
||||||
|
F: { id: OPS.fill, numArgs: 0, variableArgs: false },
|
||||||
|
'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false },
|
||||||
|
B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false },
|
||||||
|
'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false },
|
||||||
|
b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false },
|
||||||
|
'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false },
|
||||||
|
n: { id: OPS.endPath, numArgs: 0, variableArgs: false },
|
||||||
|
|
||||||
|
// Clipping
|
||||||
|
W: { id: OPS.clip, numArgs: 0, variableArgs: false },
|
||||||
|
'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false },
|
||||||
|
|
||||||
|
// Text
|
||||||
|
BT: { id: OPS.beginText, numArgs: 0, variableArgs: false },
|
||||||
|
ET: { id: OPS.endText, numArgs: 0, variableArgs: false },
|
||||||
|
Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false },
|
||||||
|
Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false },
|
||||||
|
Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false },
|
||||||
|
TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false },
|
||||||
|
Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false },
|
||||||
|
Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false },
|
||||||
|
Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false },
|
||||||
|
Td: { id: OPS.moveText, numArgs: 2, variableArgs: false },
|
||||||
|
TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false },
|
||||||
|
Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false },
|
||||||
|
'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false },
|
||||||
|
Tj: { id: OPS.showText, numArgs: 1, variableArgs: false },
|
||||||
|
TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false },
|
||||||
|
'\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false },
|
||||||
|
'"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3,
|
||||||
|
variableArgs: false },
|
||||||
|
|
||||||
|
// Type3 fonts
|
||||||
|
d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false },
|
||||||
|
d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false },
|
||||||
|
|
||||||
|
// Color
|
||||||
|
CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false },
|
||||||
|
cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false },
|
||||||
|
SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true },
|
||||||
|
SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true },
|
||||||
|
sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true },
|
||||||
|
scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true },
|
||||||
|
G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false },
|
||||||
|
g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false },
|
||||||
|
RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false },
|
||||||
|
rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false },
|
||||||
|
K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false },
|
||||||
|
k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false },
|
||||||
|
|
||||||
|
// Shading
|
||||||
|
sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false },
|
||||||
|
|
||||||
|
// Images
|
||||||
|
BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false },
|
||||||
|
ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false },
|
||||||
|
EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false },
|
||||||
|
|
||||||
|
// XObjects
|
||||||
|
Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false },
|
||||||
|
MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false },
|
||||||
|
DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false },
|
||||||
|
BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false },
|
||||||
|
BDC: { id: OPS.beginMarkedContentProps, numArgs: 2,
|
||||||
|
variableArgs: false },
|
||||||
|
EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false },
|
||||||
|
|
||||||
|
// Compatibility
|
||||||
|
BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false },
|
||||||
|
EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false },
|
||||||
|
|
||||||
|
// (reserved partial commands for the lexer)
|
||||||
|
BM: null,
|
||||||
|
BD: null,
|
||||||
|
'true': null,
|
||||||
|
fa: null,
|
||||||
|
fal: null,
|
||||||
|
fals: null,
|
||||||
|
'false': null,
|
||||||
|
nu: null,
|
||||||
|
nul: null,
|
||||||
|
'null': null
|
||||||
|
};
|
||||||
|
|
||||||
|
function EvaluatorPreprocessor(stream, xref) {
|
||||||
|
// TODO(mduan): pass array of knownCommands rather than OP_MAP
|
||||||
|
// dictionary
|
||||||
|
this.parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
|
||||||
|
this.ctm = new Float32Array([1, 0, 0, 1, 0, 0]);
|
||||||
|
this.savedStates = [];
|
||||||
|
}
|
||||||
|
EvaluatorPreprocessor.prototype = {
|
||||||
|
get savedStatesDepth() {
|
||||||
|
return this.savedStates.length;
|
||||||
|
},
|
||||||
|
read: function EvaluatorPreprocessor_read() {
|
||||||
|
var args = [];
|
||||||
|
while (true) {
|
||||||
|
var obj = this.parser.getObj();
|
||||||
|
if (isEOF(obj)) {
|
||||||
|
return null; // no more commands
|
||||||
|
}
|
||||||
|
if (!isCmd(obj)) {
|
||||||
|
// argument
|
||||||
|
if (obj !== null && obj !== undefined) {
|
||||||
|
args.push(obj instanceof Dict ? obj.getAll() : obj);
|
||||||
|
assertWellFormed(args.length <= 33, 'Too many arguments');
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd = obj.cmd;
|
||||||
|
// Check that the command is valid
|
||||||
|
var opSpec = OP_MAP[cmd];
|
||||||
|
if (!opSpec) {
|
||||||
|
warn('Unknown command "' + cmd + '"');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fn = opSpec.id;
|
||||||
|
|
||||||
|
// Validate the number of arguments for the command
|
||||||
|
if (opSpec.variableArgs) {
|
||||||
|
if (args.length > opSpec.numArgs) {
|
||||||
|
info('Command ' + fn + ': expected [0,' + opSpec.numArgs +
|
||||||
|
'] args, but received ' + args.length + ' args');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (args.length < opSpec.numArgs) {
|
||||||
|
// If we receive too few args, it's not possible to possible
|
||||||
|
// to execute the command, so skip the command
|
||||||
|
info('Command ' + fn + ': because expected ' +
|
||||||
|
opSpec.numArgs + ' args, but received ' + args.length +
|
||||||
|
' args; skipping');
|
||||||
|
args = [];
|
||||||
|
continue;
|
||||||
|
} else if (args.length > opSpec.numArgs) {
|
||||||
|
info('Command ' + fn + ': expected ' + opSpec.numArgs +
|
||||||
|
' args, but received ' + args.length + ' args');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO figure out how to type-check vararg functions
|
||||||
|
|
||||||
|
this.preprocessCommand(fn, args);
|
||||||
|
|
||||||
|
return {fn: fn, args: args};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getState: function EvaluatorPreprocessor_getState() {
|
||||||
|
return {
|
||||||
|
ctm: this.ctm
|
||||||
|
};
|
||||||
|
},
|
||||||
|
setState: function EvaluatorPreprocessor_setState(state) {
|
||||||
|
this.ctm = state.ctm;
|
||||||
|
},
|
||||||
|
preprocessCommand: function EvaluatorPreprocessor_preprocessCommand(fn,
|
||||||
|
args) {
|
||||||
|
switch (fn | 0) {
|
||||||
|
case OPS.save:
|
||||||
|
this.savedStates.push(this.getState());
|
||||||
|
break;
|
||||||
|
case OPS.restore:
|
||||||
|
var previousState = this.savedStates.pop();
|
||||||
|
if (previousState) {
|
||||||
|
this.setState(previousState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPS.transform:
|
||||||
|
var ctm = this.ctm;
|
||||||
|
var m = new Float32Array(6);
|
||||||
|
m[0] = ctm[0] * args[0] + ctm[2] * args[1];
|
||||||
|
m[1] = ctm[1] * args[0] + ctm[3] * args[1];
|
||||||
|
m[2] = ctm[0] * args[2] + ctm[2] * args[3];
|
||||||
|
m[3] = ctm[1] * args[2] + ctm[3] * args[3];
|
||||||
|
m[4] = ctm[0] * args[4] + ctm[2] * args[5] + ctm[4];
|
||||||
|
m[5] = ctm[1] * args[4] + ctm[3] * args[5] + ctm[5];
|
||||||
|
this.ctm = m;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return EvaluatorPreprocessor;
|
||||||
|
})();
|
||||||
|
@ -36,21 +36,6 @@ var Parser = (function ParserClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Parser.prototype = {
|
Parser.prototype = {
|
||||||
saveState: function Parser_saveState() {
|
|
||||||
this.state = {
|
|
||||||
buf1: this.buf1,
|
|
||||||
buf2: this.buf2,
|
|
||||||
streamPos: this.lexer.stream.pos
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
restoreState: function Parser_restoreState() {
|
|
||||||
var state = this.state;
|
|
||||||
this.buf1 = state.buf1;
|
|
||||||
this.buf2 = state.buf2;
|
|
||||||
this.lexer.stream.pos = state.streamPos;
|
|
||||||
},
|
|
||||||
|
|
||||||
refill: function Parser_refill() {
|
refill: function Parser_refill() {
|
||||||
this.buf1 = this.lexer.getObj();
|
this.buf1 = this.lexer.getObj();
|
||||||
this.buf2 = this.lexer.getObj();
|
this.buf2 = this.lexer.getObj();
|
||||||
|
@ -376,7 +376,6 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
|||||||
this.fillAlpha = 1;
|
this.fillAlpha = 1;
|
||||||
this.strokeAlpha = 1;
|
this.strokeAlpha = 1;
|
||||||
this.lineWidth = 1;
|
this.lineWidth = 1;
|
||||||
this.paintFormXObjectDepth = 0;
|
|
||||||
|
|
||||||
this.old = old;
|
this.old = old;
|
||||||
}
|
}
|
||||||
@ -1453,7 +1452,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix,
|
paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix,
|
||||||
bbox) {
|
bbox) {
|
||||||
this.save();
|
this.save();
|
||||||
this.current.paintFormXObjectDepth++;
|
|
||||||
this.baseTransformStack.push(this.baseTransform);
|
this.baseTransformStack.push(this.baseTransform);
|
||||||
|
|
||||||
if (matrix && isArray(matrix) && 6 == matrix.length)
|
if (matrix && isArray(matrix) && 6 == matrix.length)
|
||||||
@ -1471,12 +1469,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
|
paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
|
||||||
var depth = this.current.paintFormXObjectDepth;
|
this.restore();
|
||||||
do {
|
|
||||||
this.restore();
|
|
||||||
// some pdf don't close all restores inside object
|
|
||||||
// closing those for them
|
|
||||||
} while (this.current.paintFormXObjectDepth >= depth);
|
|
||||||
this.baseTransform = this.baseTransformStack.pop();
|
this.baseTransform = this.baseTransformStack.pop();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ describe('evaluator', function() {
|
|||||||
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
||||||
new XrefMock(), new HandlerMock(),
|
new XrefMock(), new HandlerMock(),
|
||||||
'prefix');
|
'prefix');
|
||||||
var stream = new StringStream('qTT');
|
var stream = new StringStream('fTT');
|
||||||
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
||||||
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
expect(result.fnArray.length).toEqual(1);
|
expect(result.fnArray.length).toEqual(1);
|
||||||
expect(result.fnArray[0]).toEqual(OPS.save);
|
expect(result.fnArray[0]).toEqual(OPS.fill);
|
||||||
expect(result.argsArray[0].length).toEqual(0);
|
expect(result.argsArray[0].length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -72,13 +72,13 @@ describe('evaluator', function() {
|
|||||||
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
||||||
new XrefMock(), new HandlerMock(),
|
new XrefMock(), new HandlerMock(),
|
||||||
'prefix');
|
'prefix');
|
||||||
var stream = new StringStream('qqq');
|
var stream = new StringStream('fff');
|
||||||
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
||||||
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
expect(result.fnArray.length).toEqual(3);
|
expect(result.fnArray.length).toEqual(3);
|
||||||
expect(result.fnArray[0]).toEqual(OPS.save);
|
expect(result.fnArray[0]).toEqual(OPS.fill);
|
||||||
expect(result.fnArray[1]).toEqual(OPS.save);
|
expect(result.fnArray[1]).toEqual(OPS.fill);
|
||||||
expect(result.fnArray[2]).toEqual(OPS.save);
|
expect(result.fnArray[2]).toEqual(OPS.fill);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle three glued operations #2', function() {
|
it('should handle three glued operations #2', function() {
|
||||||
@ -100,11 +100,11 @@ describe('evaluator', function() {
|
|||||||
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
||||||
new XrefMock(), new HandlerMock(),
|
new XrefMock(), new HandlerMock(),
|
||||||
'prefix');
|
'prefix');
|
||||||
var stream = new StringStream('q5 Ts');
|
var stream = new StringStream('f5 Ts');
|
||||||
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
||||||
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
expect(result.fnArray.length).toEqual(2);
|
expect(result.fnArray.length).toEqual(2);
|
||||||
expect(result.fnArray[0]).toEqual(OPS.save);
|
expect(result.fnArray[0]).toEqual(OPS.fill);
|
||||||
expect(result.fnArray[1]).toEqual(OPS.setTextRise);
|
expect(result.fnArray[1]).toEqual(OPS.setTextRise);
|
||||||
expect(result.argsArray.length).toEqual(2);
|
expect(result.argsArray.length).toEqual(2);
|
||||||
expect(result.argsArray[1].length).toEqual(1);
|
expect(result.argsArray[1].length).toEqual(1);
|
||||||
@ -115,13 +115,13 @@ describe('evaluator', function() {
|
|||||||
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
||||||
new XrefMock(), new HandlerMock(),
|
new XrefMock(), new HandlerMock(),
|
||||||
'prefix');
|
'prefix');
|
||||||
var stream = new StringStream('trueifalserinullq');
|
var stream = new StringStream('trueifalserinullh');
|
||||||
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
||||||
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
expect(result.fnArray.length).toEqual(3);
|
expect(result.fnArray.length).toEqual(3);
|
||||||
expect(result.fnArray[0]).toEqual(OPS.setFlatness);
|
expect(result.fnArray[0]).toEqual(OPS.setFlatness);
|
||||||
expect(result.fnArray[1]).toEqual(OPS.setRenderingIntent);
|
expect(result.fnArray[1]).toEqual(OPS.setRenderingIntent);
|
||||||
expect(result.fnArray[2]).toEqual(OPS.save);
|
expect(result.fnArray[2]).toEqual(OPS.closePath);
|
||||||
expect(result.argsArray.length).toEqual(3);
|
expect(result.argsArray.length).toEqual(3);
|
||||||
expect(result.argsArray[0].length).toEqual(1);
|
expect(result.argsArray[0].length).toEqual(1);
|
||||||
expect(result.argsArray[0][0]).toEqual(true);
|
expect(result.argsArray[0][0]).toEqual(true);
|
||||||
@ -163,6 +163,19 @@ describe('evaluator', function() {
|
|||||||
expect(result.argsArray).toEqual([]);
|
expect(result.argsArray).toEqual([]);
|
||||||
expect(result.fnArray).toEqual([]);
|
expect(result.fnArray).toEqual([]);
|
||||||
});
|
});
|
||||||
|
it('should close opened saves', function() {
|
||||||
|
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
||||||
|
new XrefMock(), new HandlerMock(),
|
||||||
|
'prefix');
|
||||||
|
var stream = new StringStream('qq');
|
||||||
|
var result = evaluator.getOperatorList(stream, new ResourcesMock());
|
||||||
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
|
expect(result.fnArray.length).toEqual(4);
|
||||||
|
expect(result.fnArray[0]).toEqual(OPS.save);
|
||||||
|
expect(result.fnArray[1]).toEqual(OPS.save);
|
||||||
|
expect(result.fnArray[2]).toEqual(OPS.restore);
|
||||||
|
expect(result.fnArray[3]).toEqual(OPS.restore);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user