getByte: function() {
var bufferLength = this.bufferLength;
var pos = this.pos;
- if (bufferLength == pos) {
+ if (bufferLength <= pos) {
if (this.eof)
return;
this.readBlock();
lookChar: function() {
var bufferLength = this.bufferLength;
var pos = this.pos;
- if (bufferLength == pos) {
+ if (bufferLength <= pos) {
if (this.eof)
return;
this.readBlock();
var DecryptStream = (function() {
function constructor(str, fileKey, encAlgorithm, keyLength) {
- // TODO
+ TODO("decrypt stream is not implemented");
}
constructor.prototype = Stream.prototype;
e = this.getEntry(num);
var gen = ref.gen;
+ var stream, parser;
if (e.uncompressed) {
if (e.gen != gen)
throw("inconsistent generation in XRef");
- var stream = this.stream.makeSubStream(e.offset);
- var parser = new Parser(new Lexer(stream), true, this);
+ stream = this.stream.makeSubStream(e.offset);
+ parser = new Parser(new Lexer(stream), true, this);
var obj1 = parser.getObj();
var obj2 = parser.getObj();
var obj3 = parser.getObj();
this.cache[num] = e;
return e;
}
- error("compressed entry");
+ // compressed entry
+ stream = this.fetch({num:e.offset, gen:0});
+ if (!IsStream(stream))
+ error("bad ObjStm stream");
+ var first = stream.parameters.get("First");
+ var n = stream.parameters.get("N");
+ if (!IsInt(first) || !IsInt(n)) {
+ error("invalid first and n parameters for ObjStm stream");
+ }
+ parser = new Parser(new Lexer(stream), false);
+ var i, entries = [], nums = [];
+ // read the object numbers to populate cache
+ for (i = 0; i < n; ++i) {
+ var num = parser.getObj();
+ if (!IsInt(num)) {
+ error("invalid object number in the ObjStm stream");
+ }
+ nums.push(num);
+ var offset = parser.getObj();
+ if (!IsInt(offset)) {
+ error("invalid object offset in the ObjStm stream");
+ }
+ }
+ // read stream objects for cache
+ for (i = 0; i < n; ++i) {
+ entries.push(parser.getObj());
+ this.cache[nums[i]] = entries[i];
+ }
+ e = entries[e.gen];
+ if (!e) {
+ error("bad XRef entry for compressed object");
+ }
+ return e;
},
getCatalogObj: function() {
return this.fetch(this.root);
: null));
},
compile: function(gfx, fonts) {
- if (!this.code) {
- var xref = this.xref;
- var content = xref.fetchIfRef(this.content);
- var resources = xref.fetchIfRef(this.resources);
+ if (this.code) {
+ // content was compiled
+ return;
+ }
+ var xref = this.xref;
+ var content;
+ var resources = xref.fetchIfRef(this.resources);
+ if (!IsArray(this.content)) {
+ // content is not an array, shortcut
+ content = xref.fetchIfRef(this.content);
this.code = gfx.compile(content, xref, resources, fonts);
+ return;
}
+ // the content is an array, compiling all items
+ var i, n = this.content.length, compiledItems = [];
+ for (i = 0; i < n; ++i) {
+ content = xref.fetchIfRef(this.content[i]);
+ compiledItems.push(gfx.compile(content, xref, resources, fonts));
+ }
+ // creating the function that executes all compiled items
+ this.code = function(gfx) {
+ var i, n = compiledItems.length;
+ for (i = 0; i < n; ++i) {
+ compiledItems[i](gfx);
+ }
+ };
},
display: function(gfx) {
+ assert(this.code instanceof Function, "page content must be compiled first");
var xref = this.xref;
- var content = xref.fetchIfRef(this.content);
var resources = xref.fetchIfRef(this.resources);
var mediaBox = xref.fetchIfRef(this.mediaBox);
- assertWellFormed(IsStream(content) && IsDict(resources),
- "invalid page content or resources");
+ assertWellFormed(IsDict(resources), "invalid page resources");
gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
width: mediaBox[2] - mediaBox[0],
height: mediaBox[3] - mediaBox[1] });