Browse Source

cache refs, not streams, in the interest of saving memory

Andreas Gal 14 years ago
parent
commit
bffedbb33c
  1. 89
      pdf.js
  2. 6
      test.html

89
pdf.js

@ -1731,6 +1731,11 @@ var XRef = (function() {
error("reading an XRef stream not implemented yet"); error("reading an XRef stream not implemented yet");
return e; return e;
}, },
fetchIfRef: function(obj) {
if (!IsRef(obj))
return obj;
return this.fetch(obj);
},
fetch: function(ref) { fetch: function(ref) {
var num = ref.num; var num = ref.num;
var e = this.cache[num]; var e = this.cache[num];
@ -1781,18 +1786,10 @@ var Page = (function() {
constructor.prototype = { constructor.prototype = {
get contents() { get contents() {
var obj = this.pageDict.get("Contents"); return this.contents = this.pageDict.get("Contents");
if (IsRef(obj))
obj = this.xref.fetch(obj);
if (!IsStream(obj))
error("invalid page contents object");
return this.contents = obj;
}, },
get resources() { get resources() {
var obj = this.pageDict.get("Resources"); return this.resources = this.pageDict.get("Resources");
if (IsRef(obj))
obj = this.xref.fetch(obj);
return this.resources = (IsDict(obj) ? obj : null);
}, },
get mediaBox() { get mediaBox() {
var obj = this.pageDict.get("MediaBox"); var obj = this.pageDict.get("MediaBox");
@ -1800,13 +1797,18 @@ var Page = (function() {
? obj ? obj
: null); : null);
}, },
display: function() { display: function(start, process) {
var stream = this.contents; var xref = this.xref;
var parser = new Parser(new Lexer(stream), false); var contents = xref.fetchIfRef(this.contents);
var resources = xref.fetchIfRef(this.resources);
var mediaBox = xref.fetchIfRef(this.mediaBox);
if (!IsStream(contents) || !IsDict(resources))
error("invalid page contents or resources");
start(resources, mediaBox);
var parser = new Parser(new Lexer(contents), false);
var obj; var obj;
while (!IsEOF(obj = parser.getObj())) { while (!IsEOF(obj = parser.getObj()))
print(uneval(obj)); process(obj);
}
} }
}; };
@ -1987,12 +1989,8 @@ var PDFDoc = (function() {
})(); })();
var Interpreter = (function() { var Interpreter = (function() {
function constructor(xref, resources, catalog, gfx) { function constructor(gfx) {
this.xref = xref;
this.res = resources;
this.catalog = catalog;
this.gfx = gfx; this.gfx = gfx;
var env = this;
this.map = { this.map = {
// Graphics state // Graphics state
w: gfx.setLineWidth, w: gfx.setLineWidth,
@ -2025,11 +2023,7 @@ var Interpreter = (function() {
// Text // Text
BT: gfx.beginText, BT: gfx.beginText,
ET: gfx.endText, ET: gfx.endText,
Tf: function(fontRef, size) { Tf: gfx.setFont,
var font = env.res.get("Font").get(fontRef.name);
//alert(uneval(font));
gfx.setFont(font, size);
},
Td: gfx.moveText, Td: gfx.moveText,
Tm: gfx.setTextMatrix, Tm: gfx.setTextMatrix,
Tj: gfx.showText, Tj: gfx.showText,
@ -2061,20 +2055,18 @@ var Interpreter = (function() {
} }
constructor.prototype = { constructor.prototype = {
compile: function(parser) { interpret: function(page) {
},
interpret: function(obj) {
return this.interpretHelper(new Parser(new Lexer(obj), true));
},
interpretHelper: function(mediaBox, parser) {
this.gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
width: mediaBox[2] - mediaBox[0],
height: mediaBox[3] - mediaBox[1] });
var args = [];
var gfx = this.gfx; var gfx = this.gfx;
var map = this.map; var map = this.map;
var obj; var args = [];
while (!IsEOF(obj = parser.getObj())) { page.display(
function(resources, mediaBox) {
gfx.resources = resources;
gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
width: mediaBox[2] - mediaBox[0],
height: mediaBox[3] - mediaBox[1] });
},
function(obj) {
if (IsCmd(obj)) { if (IsCmd(obj)) {
var cmd = obj.cmd; var cmd = obj.cmd;
var fn = map[cmd]; var fn = map[cmd];
@ -2090,6 +2082,7 @@ var Interpreter = (function() {
args.push(obj); args.push(obj);
} }
} }
);
this.gfx.endDrawing(); this.gfx.endDrawing();
} }
}; };
@ -2197,7 +2190,8 @@ var EchoGraphics = (function() {
this.dedent(); this.dedent();
this.printdentln("ET"); this.printdentln("ET");
}, },
setFont: function(font, size) { setFont: function(fontRef, size) {
var font = this.resources.get("Font").get(fontRef.name);
this.printdentln("/"+ font.name +" "+ size +" Tf"); this.printdentln("/"+ font.name +" "+ size +" Tf");
}, },
moveText: function (x, y) { moveText: function (x, y) {
@ -2428,7 +2422,8 @@ var CanvasGraphics = (function() {
endText: function() { endText: function() {
// TODO // TODO
}, },
setFont: function(font, size) { setFont: function(fontRef, size) {
var font = this.resources.get("Font").get(fontRef.name);
this.current.fontSize = size; this.current.fontSize = size;
this.ctx.font = this.current.fontSize +'px '+ font.BaseFont; this.ctx.font = this.current.fontSize +'px '+ font.BaseFont;
}, },
@ -2525,20 +2520,6 @@ var CanvasGraphics = (function() {
return constructor; return constructor;
})(); })();
function runEchoTests() {
tests.forEach(function(test) {
putstr("Running echo test '"+ test.name +"'... ");
var output = "";
var gfx = new EchoGraphics(output);
var i = new Interpreter(null, test.res, null, gfx);
i.interpretHelper(test.mediaBox, new MockParser(test.objs));
print("done. Output:");
print(gfx.out);
});
}
function runParseTests() { function runParseTests() {
//var data = snarf("simple_graphics.pdf", "binary"); //var data = snarf("simple_graphics.pdf", "binary");
var data = snarf("/tmp/paper.pdf", "binary"); var data = snarf("/tmp/paper.pdf", "binary");

6
test.html

@ -52,10 +52,8 @@ function displayPage(num) {
ctx.restore(); ctx.restore();
var gfx = new CanvasGraphics(ctx); var gfx = new CanvasGraphics(ctx);
var interp = new Interpreter(null, page.resources, null, gfx); var interp = new Interpreter(gfx);
var stream = page.contents; interp.interpret(page);
var parser = new Parser(new Lexer(stream), false);
interp.interpretHelper(page.mediaBox, parser);
} }
function nextPage() { function nextPage() {

Loading…
Cancel
Save