Split out Stream functionality
This commit is contained in:
parent
2040b871da
commit
d3f3e611c3
136
pdf.js
136
pdf.js
@ -20,6 +20,44 @@ var HashMap = (function() {
|
|||||||
return constructor;
|
return constructor;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
var Stream = (function() {
|
||||||
|
function constructor(arrayBuffer) {
|
||||||
|
this.bytes = Uint8Array(arrayBuffer);
|
||||||
|
this.pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor.prototype = {
|
||||||
|
reset: function() {
|
||||||
|
this.pos = 0;
|
||||||
|
},
|
||||||
|
lookChar: function() {
|
||||||
|
var bytes = this.bytes;
|
||||||
|
if (this.pos >= bytes.length)
|
||||||
|
return EOF;
|
||||||
|
return String.fromCharCode(bytes[this.pos]);
|
||||||
|
},
|
||||||
|
getChar: function() {
|
||||||
|
var ch = this.lookChar();
|
||||||
|
this.pos++;
|
||||||
|
return ch;
|
||||||
|
},
|
||||||
|
putBack: function() {
|
||||||
|
this.pos--;
|
||||||
|
},
|
||||||
|
skipChar: function() {
|
||||||
|
this.pos++;
|
||||||
|
},
|
||||||
|
moveStart: function(delta) {
|
||||||
|
this.bytes = Uint8Array(arrayBuffer, delta);
|
||||||
|
this.pos -= delta;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor.EOF = -1;
|
||||||
|
|
||||||
|
return constructor;
|
||||||
|
});
|
||||||
|
|
||||||
var Obj = (function() {
|
var Obj = (function() {
|
||||||
function constructor(type, value) {
|
function constructor(type, value) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -62,11 +100,8 @@ var Obj = (function() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
var Lexer = (function() {
|
var Lexer = (function() {
|
||||||
const EOF = -1;
|
function constructor(stream) {
|
||||||
|
this.stream = stream;
|
||||||
function constructor(bytes) {
|
|
||||||
this.bytes = bytes;
|
|
||||||
this.pos = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A '1' in this array means the character is white space. A '1' or
|
// A '1' in this array means the character is white space. A '1' or
|
||||||
@ -106,29 +141,14 @@ var Lexer = (function() {
|
|||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
error: function(msg) {
|
error: function(msg) {
|
||||||
},
|
// TODO
|
||||||
lookChar: function() {
|
|
||||||
var bytes = this.bytes;
|
|
||||||
if (this.pos >= bytes.length)
|
|
||||||
return EOF;
|
|
||||||
return String.fromCharCode(bytes[this.pos]);
|
|
||||||
},
|
|
||||||
getChar: function() {
|
|
||||||
var ch = this.lookChar();
|
|
||||||
this.pos++;
|
|
||||||
return ch;
|
|
||||||
},
|
|
||||||
putBack: function() {
|
|
||||||
this.pos--;
|
|
||||||
},
|
|
||||||
skipChar: function() {
|
|
||||||
this.pos++;
|
|
||||||
},
|
},
|
||||||
getNumber: function(ch) {
|
getNumber: function(ch) {
|
||||||
var floating = false;
|
var floating = false;
|
||||||
var str = ch;
|
var str = ch;
|
||||||
|
var stream = this.stream;
|
||||||
do {
|
do {
|
||||||
ch = this.getChar();
|
ch = stream.getChar();
|
||||||
if (ch == "." && !floating) {
|
if (ch == "." && !floating) {
|
||||||
str += ch;
|
str += ch;
|
||||||
floating = true;
|
floating = true;
|
||||||
@ -142,7 +162,7 @@ var Lexer = (function() {
|
|||||||
floating = true;
|
floating = true;
|
||||||
} else {
|
} else {
|
||||||
// put back the last character, it doesn't belong to us
|
// put back the last character, it doesn't belong to us
|
||||||
this.putBack();
|
stream.putBack();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (true);
|
} while (true);
|
||||||
@ -166,8 +186,9 @@ var Lexer = (function() {
|
|||||||
var numParent = 1;
|
var numParent = 1;
|
||||||
var done = false;
|
var done = false;
|
||||||
var str = ch;
|
var str = ch;
|
||||||
|
var stream = this.stream;
|
||||||
do {
|
do {
|
||||||
switch (ch = this.getChar()) {
|
switch (ch = stream.getChar()) {
|
||||||
case EOF:
|
case EOF:
|
||||||
this.error("Unterminated string");
|
this.error("Unterminated string");
|
||||||
done = true;
|
done = true;
|
||||||
@ -184,7 +205,7 @@ var Lexer = (function() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
switch (ch = this.getChar()) {
|
switch (ch = stream.getChar()) {
|
||||||
case 'n':
|
case 'n':
|
||||||
str += '\n';
|
str += '\n';
|
||||||
break;
|
break;
|
||||||
@ -208,23 +229,22 @@ var Lexer = (function() {
|
|||||||
case '0': case '1': case '2': case '3':
|
case '0': case '1': case '2': case '3':
|
||||||
case '4': case '5': case '6': case '7':
|
case '4': case '5': case '6': case '7':
|
||||||
var x = ch - '0';
|
var x = ch - '0';
|
||||||
ch = this.lookChar();
|
ch = stream.lookChar();
|
||||||
if (ch >= '0' && ch <= '7') {
|
if (ch >= '0' && ch <= '7') {
|
||||||
this.getChar();
|
this.getChar();
|
||||||
x = (x << 3) + (x - '0');
|
x = (x << 3) + (x - '0');
|
||||||
ch = this.lookChar();
|
ch = stream.lookChar();
|
||||||
if (ch >= '0' && ch <= '7') {
|
if (ch >= '0' && ch <= '7') {
|
||||||
getChar();
|
stream.getChar();
|
||||||
x = (x << 3) + (x - '0');
|
x = (x << 3) + (x - '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str += String.fromCharCode(x);
|
str += String.fromCharCode(x);
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
ch = this.lookChar();
|
ch = stream.lookChar();
|
||||||
if (ch == '\n') {
|
if (ch == '\n')
|
||||||
this.getChar();
|
stream.getChar();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
break;
|
break;
|
||||||
@ -248,14 +268,15 @@ var Lexer = (function() {
|
|||||||
},
|
},
|
||||||
getName: function(ch) {
|
getName: function(ch) {
|
||||||
var str = "";
|
var str = "";
|
||||||
while ((ch = this.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
|
var stream = this.stream;
|
||||||
this.getChar();
|
while ((ch = stream.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
|
||||||
|
stream.getChar();
|
||||||
if (ch == "#") {
|
if (ch == "#") {
|
||||||
ch = this.lookChar();
|
ch = stream.lookChar();
|
||||||
var x = ToHexDigit(ch);
|
var x = ToHexDigit(ch);
|
||||||
if (x != -1) {
|
if (x != -1) {
|
||||||
this.getChar();
|
stream.getChar();
|
||||||
var x2 = ToHexDigit(this.getChar());
|
var x2 = ToHexDigit(stream.getChar());
|
||||||
if (x2 == -1)
|
if (x2 == -1)
|
||||||
this.error("Illegal digit in hex char in name");
|
this.error("Illegal digit in hex char in name");
|
||||||
str += String.fromCharCode((x << 4) | x2);
|
str += String.fromCharCode((x << 4) | x2);
|
||||||
@ -273,8 +294,9 @@ var Lexer = (function() {
|
|||||||
},
|
},
|
||||||
getHexString: function(ch) {
|
getHexString: function(ch) {
|
||||||
var str = "";
|
var str = "";
|
||||||
|
var stream = this.stream;
|
||||||
while (1) {
|
while (1) {
|
||||||
ch = this.getChar();
|
ch = stream.getChar();
|
||||||
if (ch == '>') {
|
if (ch == '>') {
|
||||||
break;
|
break;
|
||||||
} else if (ch == EOF) {
|
} else if (ch == EOF) {
|
||||||
@ -295,9 +317,10 @@ var Lexer = (function() {
|
|||||||
getObj: function() {
|
getObj: function() {
|
||||||
// skip whitespace and comments
|
// skip whitespace and comments
|
||||||
var comment = false;
|
var comment = false;
|
||||||
|
var stream = this.stream;
|
||||||
while (true) {
|
while (true) {
|
||||||
var ch;
|
var ch;
|
||||||
if ((ch = this.getChar()) == EOF)
|
if ((ch = stream.getChar()) == EOF)
|
||||||
return new Obj(Object.EOF);
|
return new Obj(Object.EOF);
|
||||||
if (comment) {
|
if (comment) {
|
||||||
if (ch == '\r' || ch == '\n')
|
if (ch == '\r' || ch == '\n')
|
||||||
@ -325,18 +348,18 @@ var Lexer = (function() {
|
|||||||
return new Obj(Obj.Cmd, ch);
|
return new Obj(Obj.Cmd, ch);
|
||||||
// hex string or dict punctuation
|
// hex string or dict punctuation
|
||||||
case '<':
|
case '<':
|
||||||
ch = this.lookChar();
|
ch = stream.lookChar();
|
||||||
if (ch == '<') {
|
if (ch == '<') {
|
||||||
// dict punctuation
|
// dict punctuation
|
||||||
this.getChar();
|
stream.getChar();
|
||||||
return new Obj(Obj.Cmd, ch);
|
return new Obj(Obj.Cmd, ch);
|
||||||
}
|
}
|
||||||
return this.getHexString(ch);
|
return this.getHexString(ch);
|
||||||
// dict punctuation
|
// dict punctuation
|
||||||
case '>':
|
case '>':
|
||||||
ch = this.lookChar();
|
ch = stream.lookChar();
|
||||||
if (ch == '>') {
|
if (ch == '>') {
|
||||||
this.getChar();
|
stream.getChar();
|
||||||
return new Obj(Obj.Cmd, ch);
|
return new Obj(Obj.Cmd, ch);
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
@ -349,8 +372,8 @@ var Lexer = (function() {
|
|||||||
|
|
||||||
// command
|
// command
|
||||||
var str = ch;
|
var str = ch;
|
||||||
while ((ch = this.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
|
while ((ch = stream.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
|
||||||
getChar();
|
stream.getChar();
|
||||||
if (str.length == 128) {
|
if (str.length == 128) {
|
||||||
error("Command token too long");
|
error("Command token too long");
|
||||||
break;
|
break;
|
||||||
@ -475,8 +498,8 @@ var Parser = (function() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
var Linearization = (function () {
|
var Linearization = (function () {
|
||||||
function constructor(bytes) {
|
function constructor(stream) {
|
||||||
this.parser = new Parser(new Lexer(bytes), false);
|
this.parser = new Parser(new Lexer(stream), false);
|
||||||
var obj1 = this.parser.getObj();
|
var obj1 = this.parser.getObj();
|
||||||
var obj2 = this.parser.getObj();
|
var obj2 = this.parser.getObj();
|
||||||
var obj3 = this.parser.getObj();
|
var obj3 = this.parser.getObj();
|
||||||
@ -547,8 +570,8 @@ var Linearization = (function () {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
var PDFDoc = (function () {
|
var PDFDoc = (function () {
|
||||||
function constructor(arrayBuffer) {
|
function constructor(stream) {
|
||||||
this.setup(arrayBuffer);
|
this.setup(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
@ -576,20 +599,23 @@ var PDFDoc = (function () {
|
|||||||
},
|
},
|
||||||
// Find the header, remove leading garbage and setup the stream
|
// Find the header, remove leading garbage and setup the stream
|
||||||
// starting from the header.
|
// starting from the header.
|
||||||
checkHeader: function(arrayBuffer) {
|
checkHeader: function(stream) {
|
||||||
const headerSearchSize = 1024;
|
const headerSearchSize = 1024;
|
||||||
|
|
||||||
var stream = new Uint8Array(arrayBuffer);
|
stream.reset();
|
||||||
|
|
||||||
var skip = 0;
|
var skip = 0;
|
||||||
var header = "%PDF-";
|
var header = "%PDF-";
|
||||||
while (skip < headerSearchSize) {
|
while (skip < headerSearchSize) {
|
||||||
for (var i = 0; i < header.length; ++i)
|
stream.setPos(skip);
|
||||||
if (this.stream[skip+i] != header.charCodeAt(i))
|
for (var i = 0; i < header.length; ++i) {
|
||||||
|
if (stream.getChar() != header.charCodeAt(i))
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Found the header, trim off any garbage before it.
|
// Found the header, trim off any garbage before it.
|
||||||
if (i == header.length) {
|
if (i == header.length) {
|
||||||
this.stream = new Uint8Array(arrayBuffer, skip);
|
stream.moveStart(skip);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user