/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
-
function warn(msg) {
if (console && console.log)
console.log(msg);
}
var Stream = (function() {
- function constructor(arrayBuffer) {
+ function constructor(arrayBuffer, dict) {
this.bytes = new Uint8Array(arrayBuffer);
this.pos = 0;
this.start = 0;
+ this.dict = dict;
}
constructor.prototype = {
moveStart: function() {
this.start = this.pos;
},
- makeSubStream: function(pos, length) {
+ makeSubStream: function(pos, length, dict) {
var buffer = this.bytes.buffer;
if (length)
- return new Stream(new Uint8Array(buffer, pos, length));
- return new Stream(new Uint8Array(buffer, pos));
+ return new Stream(new Uint8Array(buffer, pos, length), dict);
+ return new Stream(new Uint8Array(buffer, pos), dict);
}
};
case '\\':
case '(':
case ')':
- str += c;
+ str += ch;
break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
error("Missing 'endstream'");
this.shift();
- stream = stream.makeSubStream(pos, length);
+ stream = stream.makeSubStream(pos, length, dict);
if (this.fileKey) {
stream = new DecryptStream(stream,
this.fileKey,
var mediaBox = xref.fetchIfRef(this.mediaBox);
if (!IsStream(contents) || !IsDict(resources))
error("invalid page contents or resources");
- gfx.resources = resources;
gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
width: mediaBox[2] - mediaBox[0],
height: mediaBox[3] - mediaBox[1] });
- var args = [];
- var map = gfx.map;
- var parser = new Parser(new Lexer(contents), false);
- var obj;
- while (!IsEOF(obj = parser.getObj())) {
- if (IsCmd(obj)) {
- var cmd = obj.cmd;
- var fn = map[cmd];
- if (fn)
- // TODO figure out how to type-check vararg functions
- fn.apply(gfx, args);
- else
- error("Unknown command '" + cmd + "'");
- args.length = 0;
- } else {
- if (args.length > 33)
- error("Too many arguments '" + cmd + "'");
- args.push(obj);
- }
- }
+ gfx.interpret(new Parser(new Lexer(contents), false),
+ xref, resources);
gfx.endDrawing();
}
};
this.current = new CanvasExtraState();
this.stateStack = [ ];
this.pendingClip = null;
+ this.res = null;
+ this.xobjs = null;
this.map = {
// Graphics state
w: this.setLineWidth,
this.ctx.scale(cw / mediaBox.width, -ch / mediaBox.height);
this.ctx.translate(0, -mediaBox.height);
},
+
+ interpret: function(parser, xref, resources) {
+ var savedXref = this.xref, savedRes = this.res, savedXobjs = this.xobjs;
+ this.xref = xref;
+ this.res = resources || new Dict();
+ this.xobjs = this.res.get("XObject") || new Dict();
+
+ var args = [];
+ var map = this.map;
+ var obj;
+ while (!IsEOF(obj = parser.getObj())) {
+ if (IsCmd(obj)) {
+ var cmd = obj.cmd;
+ var fn = map[cmd];
+ if (fn)
+ // TODO figure out how to type-check vararg functions
+ fn.apply(this, args);
+ else
+ error("Unknown command '" + cmd + "'");
+ args.length = 0;
+ } else {
+ if (args.length > 33)
+ error("Too many arguments '" + cmd + "'");
+ args.push(obj);
+ }
+ }
+
+ this.xobjs = savedXobjs;
+ this.res = savedRes;
+ this.xref = savedXref;
+ },
+
endDrawing: function() {
this.ctx.restore();
},
this.current = new CanvasExtraState();
},
restore: function() {
- this.current = this.stateStack.pop();
- this.ctx.restore();
+ var prev = this.stateStack.pop();
+ if (prev) {
+ this.current = prev;
+ this.ctx.restore();
+ }
},
transform: function(a, b, c, d, e, f) {
this.ctx.transform(a, b, c, d, e, f);
// TODO
},
setFont: function(fontRef, size) {
- var font = this.resources.get("Font").get(fontRef.name);
+ var font = this.res.get("Font").get(fontRef.name);
+ if (!font)
+ return;
this.current.fontSize = size;
this.ctx.font = this.current.fontSize +'px '+ font.BaseFont;
},
// XObjects
paintXObject: function(obj) {
- // TODO
+ var xobj = this.xobjs.get(obj.name);
+ if (!xobj)
+ return;
+ xobj = this.xref.fetchIfRef(xobj);
+ if (!IsStream(xobj))
+ error("XObject should be a stream");
+
+ this.interpret(new Parser(new Lexer(xobj), false),
+ this.xref, xobj.dict.get("Resources"));
},
// Helper functions