@@ -30,101 +30,104 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
30
30
this .fontIdCounter = 0 ;
31
31
}
32
32
33
+ // Specifies properties for each command
34
+ //
35
+ // If variableArgs === true: [0, `numArgs`] expected
36
+ // If variableArgs === false: exactly `numArgs` expected
33
37
var OP_MAP = {
34
- // Graphics state
35
- w : 'setLineWidth' ,
36
- J : 'setLineCap' ,
37
- j : 'setLineJoin' ,
38
- M : 'setMiterLimit' ,
39
- d : 'setDash' ,
40
- ri : 'setRenderingIntent' ,
41
- i : 'setFlatness' ,
42
- gs : 'setGState' ,
43
- q : 'save' ,
44
- Q : 'restore' ,
45
- cm : 'transform' ,
38
+ // Graphic state
39
+ w : { fnName : 'setLineWidth' , numArgs : 1 , variableArgs : false } ,
40
+ J : { fnName : 'setLineCap' , numArgs : 1 , variableArgs : false } ,
41
+ j : { fnName : 'setLineJoin' , numArgs : 1 , variableArgs : false } ,
42
+ M : { fnName : 'setMiterLimit' , numArgs : 1 , variableArgs : false } ,
43
+ d : { fnName : 'setDash' , numArgs : 2 , variableArgs : false } ,
44
+ ri : { fnName : 'setRenderingIntent' , numArgs : 1 , variableArgs : false } ,
45
+ i : { fnName : 'setFlatness' , numArgs : 1 , variableArgs : false } ,
46
+ gs : { fnName : 'setGState' , numArgs : 1 , variableArgs : false } ,
47
+ q : { fnName : 'save' , numArgs : 0 , variableArgs : false } ,
48
+ Q : { fnName : 'restore' , numArgs : 0 , variableArgs : false } ,
49
+ cm : { fnName : 'transform' , numArgs : 6 , variableArgs : false } ,
46
50
47
51
// Path
48
- m : 'moveTo' ,
49
- l : 'lineTo' ,
50
- c : 'curveTo' ,
51
- v : 'curveTo2' ,
52
- y : 'curveTo3' ,
53
- h : 'closePath' ,
54
- re : 'rectangle' ,
55
- S : 'stroke' ,
56
- s : 'closeStroke' ,
57
- f : 'fill' ,
58
- F : 'fill' ,
59
- 'f*' : 'eoFill' ,
60
- B : 'fillStroke' ,
61
- 'B*' : 'eoFillStroke' ,
62
- b : 'closeFillStroke' ,
63
- 'b*' : 'closeEOFillStroke' ,
64
- n : 'endPath' ,
52
+ m : { fnName : 'moveTo' , numArgs : 2 , variableArgs : false } ,
53
+ l : { fnName : 'lineTo' , numArgs : 2 , variableArgs : false } ,
54
+ c : { fnName : 'curveTo' , numArgs : 6 , variableArgs : false } ,
55
+ v : { fnName : 'curveTo2' , numArgs : 4 , variableArgs : false } ,
56
+ y : { fnName : 'curveTo3' , numArgs : 4 , variableArgs : false } ,
57
+ h : { fnName : 'closePath' , numArgs : 0 , variableArgs : false } ,
58
+ re : { fnName : 'rectangle' , numArgs : 4 , variableArgs : false } ,
59
+ S : { fnName : 'stroke' , numArgs : 0 , variableArgs : false } ,
60
+ s : { fnName : 'closeStroke' , numArgs : 0 , variableArgs : false } ,
61
+ f : { fnName : 'fill' , numArgs : 0 , variableArgs : false } ,
62
+ F : { fnName : 'fill' , numArgs : 0 , variableArgs : false } ,
63
+ 'f*' : { fnName : 'eoFill' , numArgs : 0 , variableArgs : false } ,
64
+ B : { fnName : 'fillStroke' , numArgs : 0 , variableArgs : false } ,
65
+ 'B*' : { fnName : 'eoFillStroke' , numArgs : 0 , variableArgs : false } ,
66
+ b : { fnName : 'closeFillStroke' , numArgs : 0 , variableArgs : false } ,
67
+ 'b*' : { fnName : 'closeEOFillStroke' , numArgs : 0 , variableArgs : false } ,
68
+ n : { fnName : 'endPath' , numArgs : 0 , variableArgs : false } ,
65
69
66
70
// Clipping
67
- W : 'clip' ,
68
- 'W*' : 'eoClip' ,
71
+ W : { fnName : 'clip' , numArgs : 0 , variableArgs : false } ,
72
+ 'W*' : { fnName : 'eoClip' , numArgs : 0 , variableArgs : false } ,
69
73
70
74
// Text
71
- BT : 'beginText' ,
72
- ET : 'endText' ,
73
- Tc : 'setCharSpacing' ,
74
- Tw : 'setWordSpacing' ,
75
- Tz : 'setHScale' ,
76
- TL : 'setLeading' ,
77
- Tf : 'setFont' ,
78
- Tr : 'setTextRenderingMode' ,
79
- Ts : 'setTextRise' ,
80
- Td : 'moveText' ,
81
- TD : 'setLeadingMoveText' ,
82
- Tm : 'setTextMatrix' ,
83
- 'T*' : 'nextLine' ,
84
- Tj : 'showText' ,
85
- TJ : 'showSpacedText' ,
86
- "'" : 'nextLineShowText' ,
87
- '"' : 'nextLineSetSpacingShowText' ,
75
+ BT : { fnName : 'beginText' , numArgs : 0 , variableArgs : false },
76
+ ET : { fnName : 'endText' , numArgs : 0 , variableArgs : false },
77
+ Tc : { fnName : 'setCharSpacing' , numArgs : 1 , variableArgs : false },
78
+ Tw : { fnName : 'setWordSpacing' , numArgs : 1 , variableArgs : false },
79
+ Tz : { fnName : 'setHScale' , numArgs : 1 , variableArgs : false },
80
+ TL : { fnName : 'setLeading' , numArgs : 1 , variableArgs : false },
81
+ Tf : { fnName : 'setFont' , numArgs : 2 , variableArgs : false },
82
+ Tr : { fnName : 'setTextRenderingMode' , numArgs : 1 , variableArgs : false },
83
+ Ts : { fnName : 'setTextRise' , numArgs : 1 , variableArgs : false },
84
+ Td : { fnName : 'moveText' , numArgs : 2 , variableArgs : false },
85
+ TD : { fnName : 'setLeadingMoveText' , numArgs : 2 , variableArgs : false },
86
+ Tm : { fnName : 'setTextMatrix' , numArgs : 6 , variableArgs : false },
87
+ 'T*' : { fnName : 'nextLine' , numArgs : 0 , variableArgs : false },
88
+ Tj : { fnName : 'showText' , numArgs : 1 , variableArgs : false },
89
+ TJ : { fnName : 'showSpacedText' , numArgs : 1 , variableArgs : false },
90
+ '\'' : { fnName : 'nextLineShowText' , numArgs : 1 , variableArgs : false },
91
+ '"' : { fnName : 'nextLineSetSpacingShowText' , numArgs : 3 ,
92
+ variableArgs : false },
88
93
89
94
// Type3 fonts
90
- d0 : 'setCharWidth' ,
91
- d1 : 'setCharWidthAndBounds' ,
95
+ d0 : { fnName : 'setCharWidth' , numArgs : 2 , variableArgs : false } ,
96
+ d1 : { fnName : 'setCharWidthAndBounds' , numArgs : 6 , variableArgs : false } ,
92
97
93
98
// Color
94
- CS : 'setStrokeColorSpace' ,
95
- cs : 'setFillColorSpace' ,
96
- SC : 'setStrokeColor' ,
97
- SCN : 'setStrokeColorN' ,
98
- sc : 'setFillColor' ,
99
- scn : 'setFillColorN' ,
100
- G : 'setStrokeGray' ,
101
- g : 'setFillGray' ,
102
- RG : 'setStrokeRGBColor' ,
103
- rg : 'setFillRGBColor' ,
104
- K : 'setStrokeCMYKColor' ,
105
- k : 'setFillCMYKColor' ,
99
+ CS : { fnName : 'setStrokeColorSpace' , numArgs : 1 , variableArgs : false } ,
100
+ cs : { fnName : 'setFillColorSpace' , numArgs : 1 , variableArgs : false } ,
101
+ SC : { fnName : 'setStrokeColor' , numArgs : 4 , variableArgs : true } ,
102
+ SCN : { fnName : 'setStrokeColorN' , numArgs : 33 , variableArgs : true } ,
103
+ sc : { fnName : 'setFillColor' , numArgs : 4 , variableArgs : true } ,
104
+ scn : { fnName : 'setFillColorN' , numArgs : 33 , variableArgs : true } ,
105
+ G : { fnName : 'setStrokeGray' , numArgs : 1 , variableArgs : false } ,
106
+ g : { fnName : 'setFillGray' , numArgs : 1 , variableArgs : false } ,
107
+ RG : { fnName : 'setStrokeRGBColor' , numArgs : 3 , variableArgs : false } ,
108
+ rg : { fnName : 'setFillRGBColor' , numArgs : 3 , variableArgs : false } ,
109
+ K : { fnName : 'setStrokeCMYKColor' , numArgs : 4 , variableArgs : false } ,
110
+ k : { fnName : 'setFillCMYKColor' , numArgs : 4 , variableArgs : false } ,
106
111
107
112
// Shading
108
- sh : 'shadingFill' ,
113
+ sh : { fnName : 'shadingFill' , numArgs : 1 , variableArgs : false } ,
109
114
110
115
// Images
111
- BI : 'beginInlineImage' ,
112
- ID : 'beginImageData' ,
113
- EI : 'endInlineImage' ,
116
+ BI : { fnName : 'beginInlineImage' , numArgs : 0 , variableArgs : false } ,
117
+ ID : { fnName : 'beginImageData' , numArgs : 0 , variableArgs : false } ,
118
+ EI : { fnName : 'endInlineImage' , numArgs : 0 , variableArgs : false } ,
114
119
115
120
// XObjects
116
- Do : 'paintXObject' ,
117
-
118
- // Marked content
119
- MP : 'markPoint' ,
120
- DP : 'markPointProps' ,
121
- BMC : 'beginMarkedContent' ,
122
- BDC : 'beginMarkedContentProps' ,
123
- EMC : 'endMarkedContent' ,
121
+ Do : { fnName : 'paintXObject' , numArgs : 1 , variableArgs : false },
122
+ MP : { fnName : 'markPoint' , numArgs : 1 , variableArgs : false },
123
+ DP : { fnName : 'markPointProps' , numArgs : 2 , variableArgs : false },
124
+ BMC : { fnName : 'beginMarkedContent' , numArgs : 1 , variableArgs : false },
125
+ BDC : { fnName : 'beginMarkedContentProps' , numArgs : 2 , variableArgs : false },
126
+ EMC : { fnName : 'endMarkedContent' , numArgs : 0 , variableArgs : false },
124
127
125
128
// Compatibility
126
- BX : 'beginCompat' ,
127
- EX : 'endCompat' ,
129
+ BX : { fnName : 'beginCompat' , numArgs : 0 , variableArgs : false } ,
130
+ EX : { fnName : 'endCompat' , numArgs : 0 , variableArgs : false } ,
128
131
129
132
// (reserved partial commands for the lexer)
130
133
BM : null ,
@@ -314,20 +317,51 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
314
317
resources = resources || new Dict ();
315
318
var xobjs = resources .get ('XObject' ) || new Dict ();
316
319
var patterns = resources .get ('Pattern' ) || new Dict ();
320
+ // TODO(mduan): pass array of knownCommands rather than OP_MAP
321
+ // dictionary
317
322
var parser = new Parser (new Lexer (stream , OP_MAP ), false , xref );
318
323
var res = resources ;
319
324
var args = [], obj ;
320
325
var TILING_PATTERN = 1 , SHADING_PATTERN = 2 ;
321
326
322
327
while (true ) {
323
328
obj = parser .getObj ();
324
- if (isEOF (obj ))
329
+ if (isEOF (obj )) {
325
330
break ;
331
+ }
326
332
327
333
if (isCmd (obj )) {
328
334
var cmd = obj .cmd ;
329
- var fn = OP_MAP [cmd ];
330
- assertWellFormed (fn , 'Unknown command "' + cmd + '"' );
335
+
336
+ // Check that the command is valid
337
+ var opSpec = OP_MAP [cmd ];
338
+ if (!opSpec ) {
339
+ warn ('Unknown command "' + cmd + '"' );
340
+ continue ;
341
+ }
342
+
343
+ var fn = opSpec .fnName ;
344
+
345
+ // Validate the number of arguments for the command
346
+ if (opSpec .variableArgs ) {
347
+ if (args .length > opSpec .numArgs ) {
348
+ info ('Command ' + fn + ': expected [0,' + opSpec .numArgs +
349
+ '] args, but received ' + args .length + ' args' );
350
+ }
351
+ } else {
352
+ if (args .length < opSpec .numArgs ) {
353
+ // If we receive too few args, it's not possible to possible
354
+ // to execute the command, so skip the command
355
+ info ('Command ' + fn + ': because expected ' + opSpec .numArgs +
356
+ ' args, but received ' + args .length + ' args; skipping' );
357
+ args = [];
358
+ continue ;
359
+ } else if (args .length > opSpec .numArgs ) {
360
+ info ('Command ' + fn + ': expected ' + opSpec .numArgs +
361
+ ' args, but received ' + args .length + ' args' );
362
+ }
363
+ }
364
+
331
365
// TODO figure out how to type-check vararg functions
332
366
333
367
if ((cmd == 'SCN' || cmd == 'scn' ) && !args [args .length - 1 ].code ) {
@@ -509,8 +543,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
509
543
argsArray .push (args );
510
544
args = [];
511
545
} else if (obj != null ) {
512
- assertWellFormed (args .length <= 33 , 'Too many arguments' );
513
546
args .push (obj instanceof Dict ? obj .getAll () : obj );
547
+ assertWellFormed (args .length <= 33 , 'Too many arguments' );
514
548
}
515
549
}
516
550
0 commit comments