Backend skeleton and temporary testing code

This commit is contained in:
Chris Jones 2011-05-04 14:46:39 -05:00
parent ef2e66bf99
commit c46faf9e76

266
pdf.js
View File

@ -72,11 +72,12 @@ var Obj = (function() {
];
for (var i = 0; i < types.length; ++i) {
var typeName = types[i];
constructor[typeName] = i;
let type = i;
var typeName = types[type];
constructor[typeName] = type;
constructor.prototype["is" + typeName] =
(function (value) {
return this.type == i &&
return this.type == type &&
(typeof value == "undefined" || value == this.value);
});
}
@ -626,3 +627,262 @@ var PDFDoc = (function () {
}
};
})();
var Interpreter = (function() {
function constructor(xref, resources, catalog, graphics) {
this.xref = xref;
this.resStack = [ resources ];
this.catalog = catalog;
this.gfx = graphics;
}
const MAX_ARGS = 33;
constructor.prototype = {
interpret: function(obj) {
return this.interpretHelper(new Parser(new Lexer(obj), true));
},
interpretHelper: function(parser) {
var args = [ ];
var obj;
while (!((obj = parser.getObj()).isEOF())) {
if (obj.isCmd()) {
this.dispatch(obj, args);
args = [ ]; // yuck
} else if (MAX_ARGS == args.length) {
this.error("Too many arguments");
} else {
args.push(obj);
}
}
},
dispatch: function(cmdObj, args) {
this.getAndCheckCmd(cmdObj, args).apply(
this, args.map(function(o) o.value));
},
getAndCheckCmd: function(cmdObj, args) {
const CMD_TABLE = {
// Text commands
"BT": { fn: "beginText",
params: [ ] },
"ET": { fn: "endText",
params: [ ] },
"Td": { fn: "moveText",
params: [ "Num", "Num" ] },
"Tf": { fn: "setFont",
params: [ "Name", "Num" ] },
"Tj": { fn: "showText",
params: [ "String" ] },
};
var cmdName = cmdObj.value
var cmd = CMD_TABLE[cmdName];
if (!cmd) {
this.error("Unknown command '"+ cmdName +"'");
} else if (!this.typeCheck(cmd, args)) {
this.error("Wrong arguments for command '"+ cmdName +"'");
}
return this[cmd.fn];
},
typeCheck: function(cmd, args) {
return true;
},
// Text commands
beginText: function() {
this.gfx.beginText();
},
endText: function() {
this.gfx.endText();
},
moveText: function(x, y) {
this.gfx.moveText(x, y);
},
setFont: function(font, size) {
// lookup font
this.gfx.setFont(font, size);
},
showText: function(text) {
this.gfx.showText(text);
}
};
return constructor;
})();
var EchoGraphics = (function() {
function constructor() {
this.out = "";
this.indentation = 0;
this.indentationStr = "";
}
constructor.prototype = {
// Graphics state
save: function() {
this.printdentln("q");
},
restore: function() {
this.printdentln("Q");
},
// Text
beginText: function() {
this.printdentln("BT");
this.indent();
},
setFont: function(font, sizePt) {
this.printdentln("/"+ font +" "+ sizePt +" Tf");
},
moveText: function (x, y) {
this.printdentln(""+ x +" "+ y +" Td");
},
showText: function(text) {
this.printdentln("( "+ text +" ) Tj");
},
endText: function() {
this.dedent();
this.printdentln("ET");
},
// Output state
print: function(str) {
this.out += str;
},
println: function(str) {
this.print(str);
this.out += "\n";
},
printdentln: function(str) {
this.print(this.indentationStr);
this.println(str);
},
indent: function() {
this.indentation += 2;
this.indentationStr += " ";
},
dedent: function() {
this.indentation -= 2;
this.indentationStr = this.indentationStr.slice(0, -2);
},
};
return constructor;
})();
var CanvasGraphicsState = (function() {
function constructor(canvasCtx, hdpi, vdpi, pageBox) {
// XXX canvas2d context has much of this; need to fill in what
// canvas state doesn't store.
this.ctx = canvasCtx;
// Page state
this.hdpi = hdpi
this.vdpi = vdpi
// ...
// Fill state
// ...
// Stroke state
// ...
// Line state
// ...
// Text state
// ...
// Current path
// ...
// Transforms
// ...
// Clipping
// ...
}
constructor.prototype = {
// Coordinate transforms
// ...
// CTM mutators
// ...
// Path mutators
// ...
};
return constructor;
})();
var CanvasGraphics = (function() {
function constructor(canvasCtx, hdpi, vdpi, pageBox) {
this.ctx = canvasCtx;
this.current = new CanvasGraphicsState(this.ctx, hdpi, vdpi, pageBox);
this.stateStack = [ ];
}
constructor.prototype = {
save: function() {
this.ctx.save();
this.stateStack.push(this.current);
// ????
this.current = new CanvasGraphicsState(this.ctx,
hdpi, vdpi, pageBox);
},
restore: function() {
this.current = this.stateStack.pop();
this.ctx.restore();
},
};
return constructor;
})();
//var PostscriptGraphics
//var SVGGraphics
// XXX temporary testing code
var MockParser = (function() {
function constructor(objs) {
this.objs = objs;
}
constructor.prototype = {
getObj: function() {
return this.objs.shift();
}
};
return constructor;
})();
function runEchoTests() {
function cmd(c) { return new Obj(Obj.Cmd, c); }
function name(n) { return new Obj(Obj.Name, n); }
function int(i) { return new Obj(Obj.Int, i); }
function string(s) { return new Obj(Obj.String, s); }
function eof() { return new Obj(Obj.EOF); }
var tests = [
{ name: "Hello world",
objs: [
cmd("BT"),
name("F1"), int(24), cmd("Tf"),
int(100), int(100), cmd("Td"),
string("Hello World"), cmd("Tj"),
cmd("ET"),
eof()
]
},
];
tests.forEach(function(test) {
putstr("Running echo test '"+ test.name +"'... ");
var output = "";
var gfx = new EchoGraphics(output);
var i = new Interpreter(null, null, null, gfx);
i.interpretHelper(new MockParser(test.objs));
print("done. Output:");
print(gfx.out);
});
}
runEchoTests();