tighten up the interpreter loop

This commit is contained in:
Andreas Gal 2011-05-06 18:15:51 -07:00
parent 36f657b4ad
commit d65ebb7533

254
pdf.js
View File

@ -808,111 +808,9 @@ var Interpreter = (function() {
this.gfx = graphics; this.gfx = graphics;
} }
const MAX_ARGS = 33;
const CMD_TABLE = {
// Graphics state
w : { params: [ "Num" ],
op: function(args) {
this.gfx.setLineWidth(args[0]);
} },
d : { params: [ "Array", "Num" ],
op: function(args) {
this.gfx.setDash(args[0], args[1]);
} },
q : { params: [ ],
op: function(args) {
this.gfx.save();
} },
Q : { params: [ ],
op: function(args) {
this.gfx.restore();
} },
cm: { params: [ "Num", "Num", "Num", "Num", "Num", "Num" ],
op: function(args) {
this.gfx.transform(args[0], args[1], args[2], args[3], args[4], args[5]);
} },
// Path
m : { params: [ "Num", "Num" ],
op: function(args) {
this.gfx.moveTo(args[0], args[1]);
} },
l : { params: [ "Num", "Num" ],
op: function(args) {
this.gfx.lineTo(args[0], args[1]);
} },
c : { params: [ "Num", "Num", "Num", "Num", "Num", "Num" ],
op: function(args) {
this.gfx.curveTo(args[0], args[1], args[2], args[3], args[4], args[5]);
} },
h : { params: [ ],
op: function(args) {
this.gfx.closePath();
} },
re: { params: [ "Num", "Num", "Num", "Num" ],
op: function(args) {
this.gfx.rectangle(args[0], args[1], args[2], args[3]);
} },
S : { params: [ ],
op: function(args) {
this.gfx.stroke();
} },
f : { params: [ ],
op: function(args) {
this.gfx.fill();
} },
B : { params: [ ],
op: function(args) {
this.gfx.fillStroke();
} },
b : { params: [ ],
op: function(args) {
this.gfx.closeFillStroke();
} },
// Clipping
// Text
BT: { params: [ ],
op: function(args) {
this.gfx.beginText();
} },
ET: { params: [ ],
op: function(args) {
this.gfx.endText();
} },
Tf: { params: [ "Name", "Num" ],
op: function(args) {
var font = this.res.Font[args[0]];
this.gfx.setFont(font, args[1]);
} },
Td: { params: [ "Num", "Num" ],
op: function(args) {
this.gfx.moveText(args[0], args[1]);
} },
Tj: { params: [ "String" ],
op: function(args) {
this.gfx.showText(args[0]);
} },
// Type3 fonts
// Color
g : { params: [ "Num" ],
op: function(args) {
this.gfx.setFillGray(args[0]);
} },
RG: { params: [ "Num", "Num", "Num" ],
op: function(args) {
this.gfx.setStrokeRGBColor(args[0], args[1], args[2]);
} },
rg: { params: [ "Num", "Num", "Num" ],
op: function(args) {
this.gfx.setFillRGBColor(args[0], args[1], args[2]);
} },
// Shading
// Images
// XObjects
// Marked content
// Compatibility
};
constructor.prototype = { constructor.prototype = {
compile: function(parser) {
},
interpret: function(obj) { interpret: function(obj) {
return this.interpretHelper(new Parser(new Lexer(obj), true)); return this.interpretHelper(new Parser(new Lexer(obj), true));
}, },
@ -920,38 +818,26 @@ var Interpreter = (function() {
this.gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1], this.gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
width: mediaBox[2] - mediaBox[0], width: mediaBox[2] - mediaBox[0],
height: mediaBox[3] - mediaBox[1] }); height: mediaBox[3] - mediaBox[1] });
var args = [];
var args = [ ]; var gfx = this.gfx;
var obj; var obj;
while (!IsEOF(obj = parser.getObj())) { while (!IsEOF(obj = parser.getObj())) {
if (IsCmd(obj)) { if (IsCmd(obj)) {
var cmd = obj.cmd; var cmd = obj.cmd;
if (!(cmd in CMD_TABLE)) var fn = gfx[cmd];
this.error("Unknown command '"+ cmd +"'"); if (fn && cmd[0] != "$") {
if (fn.length != args.length)
var op = CMD_TABLE[cmd]; this.error("Invalid number of arguments '" + cmd + "'");
//if (!this.typeCheck(op.params, args)) fn.apply(gfx, args);
//this.error("Wrong arguments for command '"+ cmd +"'"); } else
this.error("Unknown command '" + cmd + "'");
op.op.call(this, args);
args.length = 0; args.length = 0;
} else if (MAX_ARGS == args.length) {
this.error("Too many arguments");
} else { } else {
args.push(IsName(obj) ? obj.name : obj); args.push(obj);
} }
} }
this.gfx.endDrawing(); this.gfx.endDrawing();
}, },
typeCheck: function(params, args) {
if (params.length != args.length)
return false;
for (var i = 0; i < params.length; ++i)
if (!args[i]["is"+ params[i]]())
return false;
return true;
},
error: function(what) { error: function(what) {
throw new Error(what); throw new Error(what);
}, },
@ -977,85 +863,85 @@ var EchoGraphics = (function() {
}, },
// Graphics state // Graphics state
setLineWidth: function(width) { w: function(width) { // setLineWidth
this.printdentln(width +" w"); this.printdentln(width +" w");
}, },
setDash: function(dashArray, dashPhase) { d: function(dashArray, dashPhase) { // setDash
this.printdentln(""+ dashArray +" "+ dashPhase +" d"); this.printdentln(""+ dashArray +" "+ dashPhase +" d");
}, },
save: function() { q: function() { // save
this.printdentln("q"); this.printdentln("q");
}, },
restore: function() { Q: function() { // restore
this.printdentln("Q"); this.printdentln("Q");
}, },
transform: function(a, b, c, d, e, f) { cm: function(a, b, c, d, e, f) { // transform
this.printdentln(""+ a +" "+ b +" "+ c + this.printdentln(""+ a +" "+ b +" "+ c +
" "+d +" "+ e +" "+ f + " cm"); " "+d +" "+ e +" "+ f + " cm");
}, },
// Path // Path
moveTo: function(x, y) { m: function(x, y) { // moveTo
this.printdentln(""+ x +" "+ y +" m"); this.printdentln(""+ x +" "+ y +" m");
}, },
lineTo: function(x, y) { l: function(x, y) { // lineTo
this.printdentln(""+ x +" "+ y +" l"); this.printdentln(""+ x +" "+ y +" l");
}, },
curveTo: function(x1, y1, x2, y2, x3, y3) { c: function(x1, y1, x2, y2, x3, y3) { // curvoTo
this.printdentln(""+ x1 +" "+ y1 + this.printdentln(""+ x1 +" "+ y1 +
" "+ x2 +" "+ y2 + " "+ x2 +" "+ y2 +
" "+ x3 +" "+ y3 + " c"); " "+ x3 +" "+ y3 + " c");
}, },
closePath: function() { h: function() { // closePath
this.printdentln("h"); this.printdentln("h");
}, },
rectangle: function(x, y, width, height) { re: function(x, y, width, height) { // rectangle
this.printdentln(""+ x +" "+ y + " "+ width +" "+ height +" re"); this.printdentln(""+ x +" "+ y + " "+ width +" "+ height +" re");
}, },
stroke: function() { S: function() { // stroke
this.printdentln("S"); this.printdentln("S");
}, },
fill: function() { f: function() { // fill
this.printdentln("f"); this.printdentln("f");
}, },
fillStroke: function() { B: function() { // fillStroke
this.printdentln("B"); this.printdentln("B");
}, },
closeFillStroke: function() { b: function() { // closeFillStroke
this.printdentln("b"); this.printdentln("b");
}, },
// Clipping // Clipping
// Text // Text
beginText: function() { BT: function() { // beginText
this.printdentln("BT"); this.printdentln("BT");
this.indent(); this.indent();
}, },
endText: function() { ET: function() { // endText
this.dedent(); this.dedent();
this.printdentln("ET"); this.printdentln("ET");
}, },
setFont: function(font, size) { Tf: function(font, size) { // setFont
this.printdentln("/"+ font.Name +" "+ size +" Tf"); this.printdentln("/"+ font.name +" "+ size +" Tf");
}, },
moveText: function (x, y) { Td: function (x, y) { // moveText
this.printdentln(""+ x +" "+ y +" Td"); this.printdentln(""+ x +" "+ y +" Td");
}, },
showText: function(text) { Tj: function(text) { // showText
this.printdentln("( "+ text +" ) Tj"); this.printdentln("( "+ text +" ) Tj");
}, },
// Type3 fonts // Type3 fonts
// Color // Color
setFillGray: function(gray) { g: function(gray) { // setFillGray
this.printdentln(""+ gray +" g"); this.printdentln(""+ gray +" g");
}, },
setStrokeRGBColor: function(r, g, b) { RG: function(r, g, b) { // setStrokeRGBColor
this.printdentln(""+ r +" "+ g +" "+ b +" RG"); this.printdentln(""+ r +" "+ g +" "+ b +" RG");
}, },
setFillRGBColor: function(r, g, b) { rg: function(r, g, b) { // setFillRGBColor
this.printdentln(""+ r +" "+ g +" "+ b +" rg"); this.printdentln(""+ r +" "+ g +" "+ b +" rg");
}, },
@ -1122,75 +1008,75 @@ var CanvasGraphics = (function() {
}, },
// Graphics state // Graphics state
setLineWidth: function(width) { w: function(width) { // setLineWidth
this.ctx.lineWidth = width; this.ctx.lineWidth = width;
}, },
setDash: function(dashArray, dashPhase) { d: function(dashArray, dashPhase) { // setDash
// NYI // TODO
}, },
save: function() { q: function() { // save
this.ctx.save(); this.ctx.save();
this.stateStack.push(this.current); this.stateStack.push(this.current);
this.current = new CanvasExtraState(); this.current = new CanvasExtraState();
}, },
restore: function() { Q: function() { // restore
this.current = this.stateStack.pop(); this.current = this.stateStack.pop();
this.ctx.restore(); this.ctx.restore();
}, },
transform: function(a, b, c, d, e, f) { cm: function(a, b, c, d, e, f) { // transform
this.ctx.transform(a, b, c, d, e, f); this.ctx.transform(a, b, c, d, e, f);
}, },
// Path // Path
moveTo: function(x, y) { m: function(x, y) { // moveTo
this.ctx.moveTo(x, y); this.ctx.moveTo(x, y);
}, },
lineTo: function(x, y) { l: function(x, y) { // lineTo
this.ctx.lineTo(x, y); this.ctx.lineTo(x, y);
}, },
curveTo: function(x1, y1, x2, y2, x3, y3) { c: function(x1, y1, x2, y2, x3, y3) { // curveTo
this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
}, },
closePath: function() { h: function() { // closePath
this.ctx.closePath(); this.ctx.closePath();
}, },
rectangle: function(x, y, width, height) { re: function(x, y, width, height) { // rectangle
this.ctx.rect(x, y, width, height); this.ctx.rect(x, y, width, height);
}, },
stroke: function() { S: function() { // stroke
this.ctx.stroke(); this.ctx.stroke();
this.consumePath(); this.$consumePath();
}, },
fill: function() { f: function() { // fill
this.ctx.fill(); this.ctx.fill();
this.consumePath(); this.$consumePath();
}, },
fillStroke: function() { B: function() { // fillStroke
this.ctx.fill(); this.ctx.fill();
this.ctx.stroke(); this.ctx.stroke();
this.consumePath(); this.$consumePath();
}, },
closeFillStroke: function() { b: function() { // closeFillStroke
return this.fillStroke(); return this.B(); // fillStroke
}, },
// Clipping // Clipping
// Text // Text
beginText: function() { BT: function() { // beginText
// TODO
}, },
endText: function() { ET: function() { // endText
// TODO
}, },
setFont: function(font, size) { Tf: function(font, size) { // setFont
this.ctx.font = size +'px '+ font.BaseFont; this.ctx.font = size +'px '+ font.BaseFont;
}, },
moveText: function (x, y) { Td: function (x, y) { // moveText
this.current.lineX = x; this.current.lineX = x;
this.current.lineY = y; this.current.lineY = y;
}, },
showText: function(text) { Tj: function(text) { // showText
this.ctx.save(); this.ctx.save();
this.ctx.translate(0, 2 * this.current.lineY); this.ctx.translate(0, 2 * this.current.lineY);
this.ctx.scale(1, -1); this.ctx.scale(1, -1);
@ -1203,20 +1089,22 @@ var CanvasGraphics = (function() {
// Type3 fonts // Type3 fonts
// Color // Color
setFillGray: function(gray) { g: function(gray) { // setFillGray
this.setFillRGBColor(gray, gray, gray); this.rg(gray, gray, gray); // setFillRGBColor
}, },
setStrokeRGBColor: function(r, g, b) { RG: function(r, g, b) { // setStrokeRGBColor
this.ctx.strokeStyle = this.makeCssRgb(r, g, b); this.ctx.strokeStyle = this.$makeCssRgb(r, g, b);
}, },
setFillRGBColor: function(r, g, b) { rg: function(r, g, b) { // setFillRGBColor
this.ctx.fillStyle = this.makeCssRgb(r, g, b); this.ctx.fillStyle = this.$makeCssRgb(r, g, b);
}, },
consumePath: function() { // Helper functions that are not allowed to be called directly.
$consumePath: function() {
this.ctx.beginPath(); this.ctx.beginPath();
}, },
makeCssRgb: function(r, g, b) { $makeCssRgb: function(r, g, b) {
var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
return "rgb("+ ri +","+ gi +","+ bi +")"; return "rgb("+ ri +","+ gi +","+ bi +")";
}, },