|
|
@ -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; |
|
|
|
|
|
|
|
})(); |
|
|
|