1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-22 16:18:08 +02:00

Merge remote-tracking branch 'upstream/master' into refactor

This commit is contained in:
Kalervo Kujala 2012-01-05 22:24:35 +02:00
commit bc3b8e0ff1
23 changed files with 1417 additions and 179 deletions

View file

@ -255,8 +255,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
// Scale so that canvas units are the same as PDF user space units
this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height);
this.textDivs = [];
this.textLayerQueue = [];
// Move the media left-top corner to the (0,0) canvas position
this.ctx.translate(-mediaBox.x, -mediaBox.y);
if (this.textLayer)
this.textLayer.beginLayout();
},
executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR,
@ -320,27 +323,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
endDrawing: function canvasGraphicsEndDrawing() {
this.ctx.restore();
var textLayer = this.textLayer;
if (!textLayer)
return;
var self = this;
var textDivs = this.textDivs;
this.textLayerTimer = setInterval(function renderTextLayer() {
if (textDivs.length === 0) {
clearInterval(self.textLayerTimer);
return;
}
var textDiv = textDivs.shift();
if (textDiv.dataset.textLength > 1) { // avoid div by zero
textLayer.appendChild(textDiv);
// Adjust div width (via letterSpacing) to match canvas text
// Due to the .offsetWidth calls, this is slow
textDiv.style.letterSpacing =
((textDiv.dataset.canvasWidth - textDiv.offsetWidth) /
(textDiv.dataset.textLength - 1)) + 'px';
}
}, 0);
if (this.textLayer)
this.textLayer.endLayout();
},
// Graphics state
@ -359,6 +343,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
setDash: function canvasGraphicsSetDash(dashArray, dashPhase) {
this.ctx.mozDash = dashArray;
this.ctx.mozDashOffset = dashPhase;
this.ctx.webkitLineDash = dashArray;
this.ctx.webkitLineDashOffset = dashPhase;
},
setRenderingIntent: function canvasGraphicsSetRenderingIntent(intent) {
TODO('set rendering intent: ' + intent);
@ -630,24 +616,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
return geometry;
},
pushTextDivs: function canvasGraphicsPushTextDivs(text) {
var div = document.createElement('div');
var fontSize = this.current.fontSize;
// vScale and hScale already contain the scaling to pixel units
// as mozCurrentTransform reflects ctx.scale() changes
// (see beginDrawing())
var fontHeight = fontSize * text.geom.vScale;
div.dataset.canvasWidth = text.canvasWidth * text.geom.hScale;
div.style.fontSize = fontHeight + 'px';
div.style.fontFamily = this.current.font.loadedName || 'sans-serif';
div.style.left = text.geom.x + 'px';
div.style.top = (text.geom.y - fontHeight) + 'px';
div.innerHTML = text.str;
div.dataset.textLength = text.length;
this.textDivs.push(div);
},
showText: function canvasGraphicsShowText(str, skipTextSelection) {
var ctx = this.ctx;
var current = this.current;
@ -672,6 +640,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
ctx.translate(current.x, current.y);
ctx.scale(textHScale, 1);
ctx.lineWidth /= current.textMatrix[0];
if (textSelection) {
this.save();
@ -708,6 +677,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
} else {
ctx.save();
this.applyTextTransforms();
ctx.lineWidth /= current.textMatrix[0] * fontMatrix[0];
if (textSelection)
text.geom = this.getTextGeometry();
@ -744,7 +715,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
width += charWidth;
text.str += glyph.unicode === ' ' ? ' ' : glyph.unicode;
text.str += glyph.unicode === ' ' ? '\u00A0' : glyph.unicode;
text.length++;
text.canvasWidth += charWidth;
}
@ -753,7 +724,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
if (textSelection)
this.pushTextDivs(text);
this.textLayer.appendText(text, font.loadedName, fontSize);
return text;
},
@ -796,7 +767,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (e < 0 && text.geom.spaceWidth > 0) { // avoid div by zero
var numFakeSpaces = Math.round(-e / text.geom.spaceWidth);
if (numFakeSpaces > 0) {
text.str += '&nbsp;';
text.str += '\u00A0';
text.length++;
}
}
@ -806,7 +777,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (textSelection) {
if (shownText.str === ' ') {
text.str += '&nbsp;';
text.str += '\u00A0';
} else {
text.str += shownText.str;
}
@ -819,7 +790,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
if (textSelection)
this.pushTextDivs(text);
this.textLayer.appendText(text, font.loadedName, fontSize);
},
nextLineShowText: function canvasGraphicsNextLineShowText(text) {
this.nextLine();

View file

@ -70,8 +70,7 @@ var Page = (function PageClosure() {
this.xref = xref;
this.ref = ref;
this.ctx = null;
this.callback = null;
this.displayReadyPromise = null;
}
Page.prototype = {
@ -110,9 +109,11 @@ var Page = (function PageClosure() {
width: this.width,
height: this.height
};
var mediaBox = this.mediaBox;
var offsetX = mediaBox[0], offsetY = mediaBox[1];
if (isArray(obj) && obj.length == 4) {
var tl = this.rotatePoint(obj[0], obj[1]);
var br = this.rotatePoint(obj[2], obj[3]);
var tl = this.rotatePoint(obj[0] - offsetX, obj[1] - offsetY);
var br = this.rotatePoint(obj[2] - offsetX, obj[3] - offsetY);
view.x = Math.min(tl.x, br.x);
view.y = Math.min(tl.y, br.y);
view.width = Math.abs(tl.x - br.x);
@ -165,20 +166,12 @@ var Page = (function PageClosure() {
IRQueue, fonts) {
var self = this;
this.IRQueue = IRQueue;
var gfx = new CanvasGraphics(this.ctx, this.objs, this.textLayer);
var displayContinuation = function pageDisplayContinuation() {
// Always defer call to display() to work around bug in
// Firefox error reporting from XHR callbacks.
setTimeout(function pageSetTimeout() {
try {
self.display(gfx, self.callback);
} catch (e) {
if (self.callback)
self.callback(e);
else
throw e;
}
self.displayReadyPromise.resolve();
});
};
@ -395,12 +388,35 @@ var Page = (function PageClosure() {
return items;
},
startRendering: function pageStartRendering(ctx, callback, textLayer) {
this.ctx = ctx;
this.callback = callback;
this.textLayer = textLayer;
this.startRenderingTime = Date.now();
this.pdf.startRendering(this);
// If there is no displayReadyPromise yet, then the IRQueue was never
// requested before. Make the request and create the promise.
if (!this.displayReadyPromise) {
this.pdf.startRendering(this);
this.displayReadyPromise = new Promise();
}
// Once the IRQueue and fonts are loaded, perform the actual rendering.
this.displayReadyPromise.then(
function pageDisplayReadyPromise() {
var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
try {
this.display(gfx, callback);
} catch (e) {
if (callback)
callback(e);
else
throw e;
}
}.bind(this),
function pageDisplayReadPromiseError(reason) {
if (callback)
callback(reason);
else
throw reason;
}
);
}
};
@ -523,10 +539,19 @@ var PDFDocModel = (function PDFDocModelClosure() {
},
setup: function pdfDocSetup(ownerPassword, userPassword) {
this.checkHeader();
this.xref = new XRef(this.stream,
this.startXRef,
this.mainXRefEntriesOffset);
this.catalog = new Catalog(this.xref);
var xref = new XRef(this.stream,
this.startXRef,
this.mainXRefEntriesOffset);
this.xref = xref;
this.catalog = new Catalog(xref);
if (xref.trailer && xref.trailer.has('ID')) {
var fileID = '';
var id = xref.fetchIfRef(xref.trailer.get('ID'))[0];
id.split('').forEach(function(el) {
fileID += Number(el.charCodeAt(0)).toString(16);
});
this.fileID = fileID;
}
},
get numPages() {
var linearization = this.linearization;
@ -534,6 +559,22 @@ var PDFDocModel = (function PDFDocModelClosure() {
// shadow the prototype getter
return shadow(this, 'numPages', num);
},
getFingerprint: function pdfDocGetFingerprint() {
if (this.fileID) {
return this.fileID;
} else {
// If we got no fileID, then we generate one,
// from the first 100 bytes of PDF
var data = this.stream.bytes.subarray(0, 100);
var hash = calculateMD5(data, 0, data.length);
var strHash = '';
for (var i = 0, length = hash.length; i < length; i++) {
strHash += Number(hash[i]).toString(16);
}
return strHash;
}
},
getPage: function pdfDocGetPage(n) {
return this.catalog.getPage(n);
}
@ -560,7 +601,7 @@ var PDFDoc = (function PDFDocClosure() {
this.data = data;
this.stream = stream;
this.pdf = new PDFDocModel(stream);
this.fingerprint = this.pdf.getFingerprint();
this.catalog = this.pdf.catalog;
this.objs = new PDFObjects();
@ -579,36 +620,35 @@ var PDFDoc = (function PDFDocClosure() {
throw 'No PDFJS.workerSrc specified';
}
var worker;
try {
worker = new Worker(workerSrc);
} catch (e) {
// Some versions of FF can't create a worker on localhost, see:
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
globalScope.PDFJS.disableWorker = true;
this.setupFakeWorker();
var worker = new Worker(workerSrc);
var messageHandler = new MessageHandler('main', worker);
// Tell the worker the file it was created from.
messageHandler.send('workerSrc', workerSrc);
messageHandler.on('test', function pdfDocTest(supportTypedArray) {
if (supportTypedArray) {
this.worker = worker;
this.setupMessageHandler(messageHandler);
} else {
globalScope.PDFJS.disableWorker = true;
this.setupFakeWorker();
}
}.bind(this));
var testObj = new Uint8Array(1);
// Some versions of Opera throw a DATA_CLONE_ERR on
// serializing the typed array.
messageHandler.send('test', testObj);
return;
}
var messageHandler = new MessageHandler('main', worker);
// Tell the worker the file it was created from.
messageHandler.send('workerSrc', workerSrc);
messageHandler.on('test', function pdfDocTest(supportTypedArray) {
if (supportTypedArray) {
this.worker = worker;
this.setupMessageHandler(messageHandler);
} else {
this.setupFakeWorker();
}
}.bind(this));
var testObj = new Uint8Array(1);
messageHandler.send('test', testObj);
} else {
this.setupFakeWorker();
} catch (e) {}
}
// Either workers are disabled, not supported or have thrown an exception.
// Thus, we fallback to a faked worker.
globalScope.PDFJS.disableWorker = true;
this.setupFakeWorker();
}
PDFDoc.prototype = {
@ -692,8 +732,8 @@ var PDFDoc = (function PDFDocClosure() {
messageHandler.on('page_error', function pdfDocError(data) {
var page = this.pageCache[data.pageNum];
if (page.callback)
page.callback(data.error);
if (page.displayReadyPromise)
page.displayReadyPromise.reject(data.error);
else
throw data.error;
}, this);

View file

@ -2092,7 +2092,7 @@ var Font = (function FontClosure() {
window.btoa(data) + ');');
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}';
document.documentElement.firstChild.appendChild(
document.documentElement.getElementsByTagName('head')[0].appendChild(
document.createElement('style'));
var styleSheet = document.styleSheets[document.styleSheets.length - 1];

View file

@ -270,7 +270,6 @@ var PDFFunction = (function PDFFunctionClosure() {
constructStiched: function pdfFunctionConstructStiched(fn, dict, xref) {
var domain = dict.get('Domain');
var range = dict.get('Range');
if (!domain)
error('No domain');
@ -279,13 +278,13 @@ var PDFFunction = (function PDFFunctionClosure() {
if (inputSize != 1)
error('Bad domain for stiched function');
var fnRefs = dict.get('Functions');
var fnRefs = xref.fetchIfRef(dict.get('Functions'));
var fns = [];
for (var i = 0, ii = fnRefs.length; i < ii; ++i)
fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i])));
var bounds = dict.get('Bounds');
var encode = dict.get('Encode');
var bounds = xref.fetchIfRef(dict.get('Bounds'));
var encode = xref.fetchIfRef(dict.get('Encode'));
return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
},
@ -336,16 +335,550 @@ var PDFFunction = (function PDFFunctionClosure() {
};
},
constructPostScript: function pdfFunctionConstructPostScript() {
return [CONSTRUCT_POSTSCRIPT];
constructPostScript: function pdfFunctionConstructPostScript(fn, dict,
xref) {
var domain = dict.get('Domain');
var range = dict.get('Range');
if (!domain)
error('No domain.');
if (!range)
error('No range.');
var lexer = new PostScriptLexer(fn);
var parser = new PostScriptParser(lexer);
var code = parser.parse();
return [CONSTRUCT_POSTSCRIPT, domain, range, code];
},
constructPostScriptFromIR: function pdfFunctionConstructPostScriptFromIR() {
TODO('unhandled type of function');
return function constructPostScriptFromIRResult() {
return [255, 105, 180];
constructPostScriptFromIR:
function pdfFunctionConstructPostScriptFromIR(IR) {
var domain = IR[1];
var range = IR[2];
var code = IR[3];
var numOutputs = range.length / 2;
var evaluator = new PostScriptEvaluator(code);
// Cache the values for a big speed up, the cache size is limited though
// since the number of possible values can be huge from a PS function.
var cache = new FunctionCache();
return function constructPostScriptFromIRResult(args) {
var initialStack = [];
for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
initialStack.push(args[i]);
}
var key = initialStack.join('_');
if (cache.has(key))
return cache.get(key);
var stack = evaluator.execute(initialStack);
var transformed = new Array(numOutputs);
for (i = numOutputs - 1; i >= 0; --i) {
var out = stack.pop();
var rangeIndex = 2 * i;
if (out < range[rangeIndex])
out = range[rangeIndex];
else if (out > range[rangeIndex + 1])
out = range[rangeIndex + 1];
transformed[i] = out;
}
cache.set(key, transformed);
return transformed;
};
}
};
})();
var FunctionCache = (function FunctionCacheClosure() {
// Of 10 PDF's with type4 functions the maxium number of distinct values seen
// was 256. This still may need some tweaking in the future though.
var MAX_CACHE_SIZE = 1024;
function FunctionCache() {
this.cache = {};
this.total = 0;
}
FunctionCache.prototype = {
has: function has(key) {
return key in this.cache;
},
get: function get(key) {
return this.cache[key];
},
set: function set(key, value) {
if (this.total < MAX_CACHE_SIZE) {
this.cache[key] = value;
this.total++;
}
}
};
return FunctionCache;
})();
var PostScriptStack = (function PostScriptStackClosure() {
var MAX_STACK_SIZE = 100;
function PostScriptStack(initialStack) {
this.stack = initialStack || [];
}
PostScriptStack.prototype = {
push: function push(value) {
if (this.stack.length >= MAX_STACK_SIZE)
error('PostScript function stack overflow.');
this.stack.push(value);
},
pop: function pop() {
if (this.stack.length <= 0)
error('PostScript function stack underflow.');
return this.stack.pop();
},
copy: function copy(n) {
if (this.stack.length + n >= MAX_STACK_SIZE)
error('PostScript function stack overflow.');
var stack = this.stack;
for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++)
stack.push(stack[i]);
},
index: function index(n) {
this.push(this.stack[this.stack.length - n - 1]);
},
// rotate the last n stack elements p times
roll: function roll(n, p) {
var stack = this.stack;
var l = stack.length - n;
var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
for (i = l, j = r; i < j; i++, j--) {
t = stack[i]; stack[i] = stack[j]; stack[j] = t;
}
for (i = l, j = c - 1; i < j; i++, j--) {
t = stack[i]; stack[i] = stack[j]; stack[j] = t;
}
for (i = c, j = r; i < j; i++, j--) {
t = stack[i]; stack[i] = stack[j]; stack[j] = t;
}
}
};
return PostScriptStack;
})();
var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
function PostScriptEvaluator(operators, operands) {
this.operators = operators;
this.operands = operands;
}
PostScriptEvaluator.prototype = {
execute: function execute(initialStack) {
var stack = new PostScriptStack(initialStack);
var counter = 0;
var operators = this.operators;
var length = operators.length;
var operator, a, b;
while (counter < length) {
operator = operators[counter++];
if (typeof operator == 'number') {
// Operator is really an operand and should be pushed to the stack.
stack.push(operator);
continue;
}
switch (operator) {
// non standard ps operators
case 'jz': // jump if false
b = stack.pop();
a = stack.pop();
if (!a)
counter = b;
break;
case 'j': // jump
a = stack.pop();
counter = a;
break;
// all ps operators in alphabetical order (excluding if/ifelse)
case 'abs':
a = stack.pop();
stack.push(Math.abs(a));
break;
case 'add':
b = stack.pop();
a = stack.pop();
stack.push(a + b);
break;
case 'and':
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b))
stack.push(a && b);
else
stack.push(a & b);
break;
case 'atan':
a = stack.pop();
stack.push(Math.atan(a));
break;
case 'bitshift':
b = stack.pop();
a = stack.pop();
if (a > 0)
stack.push(a << b);
else
stack.push(a >> b);
break;
case 'ceiling':
a = stack.pop();
stack.push(Math.ceil(a));
break;
case 'copy':
a = stack.pop();
stack.copy(a);
break;
case 'cos':
a = stack.pop();
stack.push(Math.cos(a));
break;
case 'cvi':
a = stack.pop() | 0;
stack.push(a);
break;
case 'cvr':
// noop
break;
case 'div':
b = stack.pop();
a = stack.pop();
stack.push(a / b);
break;
case 'dup':
stack.copy(1);
break;
case 'eq':
b = stack.pop();
a = stack.pop();
stack.push(a == b);
break;
case 'exch':
stack.roll(2, 1);
break;
case 'exp':
b = stack.pop();
a = stack.pop();
stack.push(Math.pow(a, b));
break;
case 'false':
stack.push(false);
break;
case 'floor':
a = stack.pop();
stack.push(Math.floor(a));
break;
case 'ge':
b = stack.pop();
a = stack.pop();
stack.push(a >= b);
break;
case 'gt':
b = stack.pop();
a = stack.pop();
stack.push(a > b);
break;
case 'idiv':
b = stack.pop();
a = stack.pop();
stack.push((a / b) | 0);
break;
case 'index':
a = stack.pop();
stack.index(a);
break;
case 'le':
b = stack.pop();
a = stack.pop();
stack.push(a <= b);
break;
case 'ln':
a = stack.pop();
stack.push(Math.log(a));
break;
case 'log':
a = stack.pop();
stack.push(Math.log(a) / Math.LN10);
break;
case 'lt':
b = stack.pop();
a = stack.pop();
stack.push(a < b);
break;
case 'mod':
b = stack.pop();
a = stack.pop();
stack.push(a % b);
break;
case 'mul':
b = stack.pop();
a = stack.pop();
stack.push(a * b);
break;
case 'ne':
b = stack.pop();
a = stack.pop();
stack.push(a != b);
break;
case 'neg':
a = stack.pop();
stack.push(-b);
break;
case 'not':
a = stack.pop();
if (isBool(a) && isBool(b))
stack.push(a && b);
else
stack.push(a & b);
break;
case 'or':
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b))
stack.push(a || b);
else
stack.push(a | b);
break;
case 'pop':
stack.pop();
break;
case 'roll':
b = stack.pop();
a = stack.pop();
stack.roll(a, b);
break;
case 'round':
a = stack.pop();
stack.push(Math.round(a));
break;
case 'sin':
a = stack.pop();
stack.push(Math.sin(a));
break;
case 'sqrt':
a = stack.pop();
stack.push(Math.sqrt(a));
break;
case 'sub':
b = stack.pop();
a = stack.pop();
stack.push(a - b);
break;
case 'true':
stack.push(true);
break;
case 'truncate':
a = stack.pop();
a = a < 0 ? Math.ceil(a) : Math.floor(a);
stack.push(a);
break;
case 'xor':
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b))
stack.push(a != b);
else
stack.push(a ^ b);
break;
default:
error('Unknown operator ' + operator);
break;
}
}
return stack.stack;
}
};
return PostScriptEvaluator;
})();
var PostScriptParser = (function PostScriptParserClosure() {
function PostScriptParser(lexer) {
this.lexer = lexer;
this.operators = [];
this.token;
this.prev;
}
PostScriptParser.prototype = {
nextToken: function nextToken() {
this.prev = this.token;
this.token = this.lexer.getToken();
},
accept: function accept(type) {
if (this.token.type == type) {
this.nextToken();
return true;
}
return false;
},
expect: function expect(type) {
if (this.accept(type))
return true;
error('Unexpected symbol: found ' + this.token.type + ' expected ' +
type + '.');
},
parse: function parse() {
this.nextToken();
this.expect(PostScriptTokenTypes.LBRACE);
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
return this.operators;
},
parseBlock: function parseBlock() {
while (true) {
if (this.accept(PostScriptTokenTypes.NUMBER)) {
this.operators.push(this.prev.value);
} else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
this.operators.push(this.prev.value);
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
this.parseCondition();
} else {
return;
}
}
},
parseCondition: function parseCondition() {
// Add two place holders that will be updated later
var conditionLocation = this.operators.length;
this.operators.push(null, null);
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
if (this.accept(PostScriptTokenTypes.IF)) {
// The true block is right after the 'if' so it just falls through on
// true else it jumps and skips the true block.
this.operators[conditionLocation] = this.operators.length;
this.operators[conditionLocation + 1] = 'jz';
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
var jumpLocation = this.operators.length;
this.operators.push(null, null);
var endOfTrue = this.operators.length;
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
this.expect(PostScriptTokenTypes.IFELSE);
// The jump is added at the end of the true block to skip the false
// block.
this.operators[jumpLocation] = this.operators.length;
this.operators[jumpLocation + 1] = 'j';
this.operators[conditionLocation] = endOfTrue;
this.operators[conditionLocation + 1] = 'jz';
} else {
error('PS Function: error parsing conditional.');
}
}
};
return PostScriptParser;
})();
var PostScriptTokenTypes = {
LBRACE: 0,
RBRACE: 1,
NUMBER: 2,
OPERATOR: 3,
IF: 4,
IFELSE: 5
};
var PostScriptToken = (function PostScriptTokenClosure() {
function PostScriptToken(type, value) {
this.type = type;
this.value = value;
}
var opCache = {};
PostScriptToken.getOperator = function getOperator(op) {
var opValue = opCache[op];
if (opValue)
return opValue;
return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
};
PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
'{');
PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
'}');
PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
'IFELSE');
return PostScriptToken;
})();
var PostScriptLexer = (function PostScriptLexerClosure() {
function PostScriptLexer(stream) {
this.stream = stream;
}
PostScriptLexer.prototype = {
getToken: function getToken() {
var s = '';
var ch;
var comment = false;
var stream = this.stream;
// skip comments
while (true) {
if (!(ch = stream.getChar()))
return EOF;
if (comment) {
if (ch == '\x0a' || ch == '\x0d')
comment = false;
} else if (ch == '%') {
comment = true;
} else if (!Lexer.isSpace(ch)) {
break;
}
}
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '+': case '-': case '.':
return new PostScriptToken(PostScriptTokenTypes.NUMBER,
this.getNumber(ch));
case '{':
return PostScriptToken.LBRACE;
case '}':
return PostScriptToken.RBRACE;
}
// operator
var str = ch.toLowerCase();
while (true) {
ch = stream.lookChar().toLowerCase();
if (ch >= 'a' && ch <= 'z')
str += ch;
else
break;
stream.skip();
}
switch (str) {
case 'if':
return PostScriptToken.IF;
case 'ifelse':
return PostScriptToken.IFELSE;
default:
return PostScriptToken.getOperator(str);
}
},
getNumber: function getNumber(ch) {
var str = ch;
var stream = this.stream;
while (true) {
ch = stream.lookChar();
if ((ch >= '0' && ch <= '9') || ch == '-' || ch == '.')
str += ch;
else
break;
stream.skip();
}
var value = parseFloat(str);
if (isNaN(value))
error('Invalid floating point number: ' + value);
return value;
}
};
return PostScriptLexer;
})();

View file

@ -8,8 +8,7 @@ var Name = (function NameClosure() {
this.name = name;
}
Name.prototype = {
};
Name.prototype = {};
return Name;
})();
@ -19,9 +18,7 @@ var Cmd = (function CmdClosure() {
this.cmd = cmd;
}
Cmd.prototype = {
};
Cmd.prototype = {};
var cmdCache = {};
@ -80,8 +77,7 @@ var Ref = (function RefClosure() {
this.gen = gen;
}
Ref.prototype = {
};
Ref.prototype = {};
return Ref;
})();
@ -273,7 +269,7 @@ var XRef = (function XRefClosure() {
this.entries = [];
this.xrefstms = {};
var trailerDict = this.readXRef(startXRef);
this.trailer = trailerDict;
// prepare the XRef cache
this.cache = [];

View file

@ -1856,10 +1856,10 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
// values. The first array element indicates whether a valid code is being
// returned. The second array element is the actual code. The third array
// element indicates whether EOF was reached.
var findTableCode = function ccittFaxStreamFindTableCode(start, end, table,
limit) {
var limitValue = limit || 0;
CCITTFaxStream.prototype.findTableCode =
function ccittFaxStreamFindTableCode(start, end, table, limit) {
var limitValue = limit || 0;
for (var i = start; i <= end; ++i) {
var code = this.lookBits(i);
if (code == EOF)
@ -1890,7 +1890,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
return p[1];
}
} else {
var result = findTableCode(1, 7, twoDimTable);
var result = this.findTableCode(1, 7, twoDimTable);
if (result[0] && result[2])
return result[1];
}
@ -1919,11 +1919,11 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
return p[1];
}
} else {
var result = findTableCode(1, 9, whiteTable2);
var result = this.findTableCode(1, 9, whiteTable2);
if (result[0])
return result[1];
result = findTableCode(11, 12, whiteTable1);
result = this.findTableCode(11, 12, whiteTable1);
if (result[0])
return result[1];
}
@ -1952,15 +1952,15 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
return p[1];
}
} else {
var result = findTableCode(2, 6, blackTable3);
var result = this.findTableCode(2, 6, blackTable3);
if (result[0])
return result[1];
result = findTableCode(7, 12, blackTable2, 64);
result = this.findTableCode(7, 12, blackTable2, 64);
if (result[0])
return result[1];
result = findTableCode(10, 13, blackTable1);
result = this.findTableCode(10, 13, blackTable1);
if (result[0])
return result[1];
}

View file

@ -206,6 +206,8 @@ var Promise = (function PromiseClosure() {
*/
function Promise(name, data) {
this.name = name;
this.isRejected = false;
this.error = null;
// If you build a promise and pass in some data it's already resolved.
if (data != null) {
this.isResolved = true;
@ -216,6 +218,7 @@ var Promise = (function PromiseClosure() {
this._data = EMPTY_PROMISE;
}
this.callbacks = [];
this.errbacks = [];
};
/**
* Builds a promise that is resolved when all the passed in promises are
@ -282,9 +285,12 @@ var Promise = (function PromiseClosure() {
if (this.isResolved) {
throw 'A Promise can be resolved only once ' + this.name;
}
if (this.isRejected) {
throw 'The Promise was already rejected ' + this.name;
}
this.isResolved = true;
this.data = data;
this.data = data || null;
var callbacks = this.callbacks;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
@ -292,7 +298,24 @@ var Promise = (function PromiseClosure() {
}
},
then: function promiseThen(callback) {
reject: function proimseReject(reason) {
if (this.isRejected) {
throw 'A Promise can be rejected only once ' + this.name;
}
if (this.isResolved) {
throw 'The Promise was already resolved ' + this.name;
}
this.isRejected = true;
this.error = reason || null;
var errbacks = this.errbacks;
for (var i = 0, ii = errbacks.length; i < ii; i++) {
errbacks[i].call(null, reason);
}
},
then: function promiseThen(callback, errback) {
if (!callback) {
throw 'Requiring callback' + this.name;
}
@ -301,8 +324,13 @@ var Promise = (function PromiseClosure() {
if (this.isResolved) {
var data = this.data;
callback.call(null, data);
} else if (this.isRejected && errorback) {
var error = this.error;
errback.call(null, error);
} else {
this.callbacks.push(callback);
if (errback)
this.errbacks.push(errback);
}
}
};