Skip to content

Commit deba913

Browse files
committed
Merge branch 'master' of https://github.com/mozilla/pdf.js
2 parents 38ffebc + fa1133f commit deba913

File tree

6 files changed

+190
-92
lines changed

6 files changed

+190
-92
lines changed

src/evaluator.js

Lines changed: 131 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -30,101 +30,104 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
3030
this.fontIdCounter = 0;
3131
}
3232

33+
// Specifies properties for each command
34+
//
35+
// If variableArgs === true: [0, `numArgs`] expected
36+
// If variableArgs === false: exactly `numArgs` expected
3337
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 },
4650

4751
// 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 },
6569

6670
// Clipping
67-
W: 'clip',
68-
'W*': 'eoClip',
71+
W: { fnName: 'clip', numArgs: 0, variableArgs: false },
72+
'W*': { fnName: 'eoClip', numArgs: 0, variableArgs: false },
6973

7074
// 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 },
8893

8994
// Type3 fonts
90-
d0: 'setCharWidth',
91-
d1: 'setCharWidthAndBounds',
95+
d0: { fnName: 'setCharWidth', numArgs: 2, variableArgs: false },
96+
d1: { fnName: 'setCharWidthAndBounds', numArgs: 6, variableArgs: false },
9297

9398
// 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 },
106111

107112
// Shading
108-
sh: 'shadingFill',
113+
sh: { fnName: 'shadingFill', numArgs: 1, variableArgs: false },
109114

110115
// 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 },
114119

115120
// 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 },
124127

125128
// Compatibility
126-
BX: 'beginCompat',
127-
EX: 'endCompat',
129+
BX: { fnName: 'beginCompat', numArgs: 0, variableArgs: false },
130+
EX: { fnName: 'endCompat', numArgs: 0, variableArgs: false },
128131

129132
// (reserved partial commands for the lexer)
130133
BM: null,
@@ -314,20 +317,51 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
314317
resources = resources || new Dict();
315318
var xobjs = resources.get('XObject') || new Dict();
316319
var patterns = resources.get('Pattern') || new Dict();
320+
// TODO(mduan): pass array of knownCommands rather than OP_MAP
321+
// dictionary
317322
var parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
318323
var res = resources;
319324
var args = [], obj;
320325
var TILING_PATTERN = 1, SHADING_PATTERN = 2;
321326

322327
while (true) {
323328
obj = parser.getObj();
324-
if (isEOF(obj))
329+
if (isEOF(obj)) {
325330
break;
331+
}
326332

327333
if (isCmd(obj)) {
328334
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+
331365
// TODO figure out how to type-check vararg functions
332366

333367
if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
@@ -509,8 +543,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
509543
argsArray.push(args);
510544
args = [];
511545
} else if (obj != null) {
512-
assertWellFormed(args.length <= 33, 'Too many arguments');
513546
args.push(obj instanceof Dict ? obj.getAll() : obj);
547+
assertWellFormed(args.length <= 33, 'Too many arguments');
514548
}
515549
}
516550

@@ -1146,10 +1180,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
11461180
// a variant.
11471181
var firstChar = dict.get('FirstChar') || 0;
11481182
var lastChar = dict.get('LastChar') || maxCharIndex;
1183+
11491184
var fontName = descriptor.get('FontName');
1185+
var baseFont = baseDict.get('BaseFont');
11501186
// Some bad pdf's have a string as the font name.
1151-
if (isString(fontName))
1187+
if (isString(fontName)) {
11521188
fontName = new Name(fontName);
1189+
}
1190+
if (isString(baseFont)) {
1191+
baseFont = new Name(baseFont);
1192+
}
1193+
1194+
var fontNameStr = fontName && fontName.name;
1195+
var baseFontStr = baseFont && baseFont.name;
1196+
if (fontNameStr !== baseFontStr) {
1197+
warn('The FontDescriptor\'s FontName is "' + fontNameStr +
1198+
'" but should be the same as the Font\'s BaseFont "' +
1199+
baseFontStr + '"');
1200+
}
1201+
fontName = fontName || baseFont;
1202+
11531203
assertWellFormed(isName(fontName), 'invalid font name');
11541204

11551205
var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');

test/pdfs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
*.pdf
22

33
!tracemonkey.pdf
4+
!issue2391-1.pdf
45
!ArabicCIDTrueType.pdf
56
!ThuluthFeatures.pdf
67
!arial_unicode_ab_cidfont.pdf
@@ -38,3 +39,4 @@
3839
!mixedfonts.pdf
3940
!shading_extend.pdf
4041
!noembed-identity.pdf
42+
!issue2099-1.pdf

test/pdfs/issue2099-1.pdf

2.79 KB
Binary file not shown.

test/pdfs/issue2391-1.pdf

2.72 KB
Binary file not shown.

test/test_manifest.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
"rounds": 1,
1818
"type": "text"
1919
},
20+
{ "id": "issue2391-1",
21+
"file": "pdfs/issue2391-1.pdf",
22+
"md5": "25ae9cb959612e7b343b55da63af2716",
23+
"rounds": 1,
24+
"pageLimit": 1,
25+
"type": "load"
26+
},
2027
{ "id": "html5-canvas-cheat-sheet-load",
2128
"file": "pdfs/canvas.pdf",
2229
"md5": "59510028561daf62e00bf9f6f066b033",
@@ -801,5 +808,11 @@
801808
"md5": "05d3803b6c22451e18cb60d8d8c75c0c",
802809
"rounds": 1,
803810
"type": "eq"
811+
},
812+
{ "id": "issue2099-1",
813+
"file": "pdfs/issue2099-1.pdf",
814+
"md5": "c7eca682d70a976dfc4b7e64d3e9f1ce",
815+
"rounds": 1,
816+
"type": "eq"
804817
}
805818
]

0 commit comments

Comments
 (0)