Merge branch 'master' of git://github.com/mozilla/pdf.js.git into issue-863
This commit is contained in:
commit
54c31968e7
3
Makefile
3
Makefile
@ -64,7 +64,8 @@ bundle: | $(BUILD_DIR)
|
||||
@cd src; \
|
||||
cat $(PDF_JS_FILES) > all_files.tmp; \
|
||||
sed '/PDFJSSCRIPT_INCLUDE_ALL/ r all_files.tmp' pdf.js > ../$(BUILD_TARGET); \
|
||||
sed -i '' "s/PDFJSSCRIPT_BUNDLE_VER/`git log --format="%H" -n 1`/" ../$(BUILD_TARGET); \
|
||||
sed -i.bak "s/PDFJSSCRIPT_BUNDLE_VER/`git log --format="%h" -n 1`/" ../$(BUILD_TARGET); \
|
||||
rm -f ../$(BUILD_TARGET).bak
|
||||
rm -f *.tmp; \
|
||||
cd ..
|
||||
|
||||
|
146
src/canvas.js
146
src/canvas.js
@ -6,6 +6,17 @@
|
||||
// <canvas> contexts store most of the state we need natively.
|
||||
// However, PDF needs a bit more state, which we store here.
|
||||
|
||||
var TextRenderingMode = {
|
||||
FILL: 0,
|
||||
STROKE: 1,
|
||||
FILL_STROKE: 2,
|
||||
INVISIBLE: 3,
|
||||
FILL_ADD_TO_PATH: 4,
|
||||
STROKE_ADD_TO_PATH: 5,
|
||||
FILL_STROKE_ADD_TO_PATH: 6,
|
||||
ADD_TO_PATH: 7
|
||||
};
|
||||
|
||||
var CanvasExtraState = (function canvasExtraState() {
|
||||
function constructor(old) {
|
||||
// Are soft masks and alpha values shapes or opacities?
|
||||
@ -23,6 +34,7 @@ var CanvasExtraState = (function canvasExtraState() {
|
||||
this.charSpacing = 0;
|
||||
this.wordSpacing = 0;
|
||||
this.textHScale = 1;
|
||||
this.textRenderingMode = TextRenderingMode.FILL;
|
||||
// Color spaces
|
||||
this.fillColorSpace = new DeviceGrayCS();
|
||||
this.fillColorSpaceObj = null;
|
||||
@ -195,6 +207,35 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
var EO_CLIP = {};
|
||||
|
||||
constructor.prototype = {
|
||||
slowCommands: {
|
||||
'stroke': true,
|
||||
'closeStroke': true,
|
||||
'fill': true,
|
||||
'eoFill': true,
|
||||
'fillStroke': true,
|
||||
'eoFillStroke': true,
|
||||
'closeFillStroke': true,
|
||||
'closeEOFillStroke': true,
|
||||
'showText': true,
|
||||
'showSpacedText': true,
|
||||
'setStrokeColorSpace': true,
|
||||
'setFillColorSpace': true,
|
||||
'setStrokeColor': true,
|
||||
'setStrokeColorN': true,
|
||||
'setFillColor': true,
|
||||
'setFillColorN_IR': true,
|
||||
'setStrokeGray': true,
|
||||
'setFillGray': true,
|
||||
'setStrokeRGBColor': true,
|
||||
'setFillRGBColor': true,
|
||||
'setStrokeCMYKColor': true,
|
||||
'setFillCMYKColor': true,
|
||||
'paintJpegXObject': true,
|
||||
'paintImageXObject': true,
|
||||
'paintImageMaskXObject': true,
|
||||
'shadingFill': true
|
||||
},
|
||||
|
||||
beginDrawing: function canvasGraphicsBeginDrawing(mediaBox) {
|
||||
var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
|
||||
this.ctx.save();
|
||||
@ -234,13 +275,17 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
}
|
||||
|
||||
var executionEndIdx;
|
||||
var startTime = Date.now();
|
||||
var endTime = Date.now() + kExecutionTime;
|
||||
|
||||
var objs = this.objs;
|
||||
var fnName;
|
||||
var slowCommands = this.slowCommands;
|
||||
|
||||
while (true) {
|
||||
if (fnArray[i] !== 'dependency') {
|
||||
this[fnArray[i]].apply(this, argsArray[i]);
|
||||
fnName = fnArray[i];
|
||||
|
||||
if (fnName !== 'dependency') {
|
||||
this[fnName].apply(this, argsArray[i]);
|
||||
} else {
|
||||
var deps = argsArray[i];
|
||||
for (var n = 0, nn = deps.length; n < nn; n++) {
|
||||
@ -254,6 +299,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
// If the entire IRQueue was executed, stop as were done.
|
||||
@ -264,7 +310,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
// If the execution took longer then a certain amount of time, shedule
|
||||
// to continue exeution after a short delay.
|
||||
// However, this is only possible if a 'continueCallback' is passed in.
|
||||
if (continueCallback && (Date.now() - startTime) > kExecutionTime) {
|
||||
if (continueCallback && slowCommands[fnName] && Date.now() > endTime) {
|
||||
setTimeout(continueCallback, 0);
|
||||
return i;
|
||||
}
|
||||
@ -543,7 +589,9 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
this.ctx.font = rule;
|
||||
},
|
||||
setTextRenderingMode: function canvasGraphicsSetTextRenderingMode(mode) {
|
||||
TODO('text rendering mode: ' + mode);
|
||||
if (mode >= TextRenderingMode.FILL_ADD_TO_PATH)
|
||||
TODO('unsupported text rendering mode: ' + mode);
|
||||
this.current.textRenderingMode = mode;
|
||||
},
|
||||
setTextRise: function canvasGraphicsSetTextRise(rise) {
|
||||
TODO('text rise: ' + rise);
|
||||
@ -637,6 +685,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
var textLayer = this.textLayer;
|
||||
var text = {str: '', length: 0, canvasWidth: 0, geom: {}};
|
||||
var textSelection = textLayer && !skipTextSelection ? true : false;
|
||||
var textRenderingMode = current.textRenderingMode;
|
||||
|
||||
if (textSelection) {
|
||||
ctx.save();
|
||||
@ -693,7 +742,26 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
|
||||
var char = glyph.fontChar;
|
||||
var charWidth = glyph.width * fontSize * 0.001 + charSpacing;
|
||||
ctx.fillText(char, width, 0);
|
||||
|
||||
switch (textRenderingMode) {
|
||||
default: // other unsupported rendering modes
|
||||
case TextRenderingMode.FILL:
|
||||
case TextRenderingMode.FILL_ADD_TO_PATH:
|
||||
ctx.fillText(char, width, 0);
|
||||
break;
|
||||
case TextRenderingMode.STROKE:
|
||||
case TextRenderingMode.STROKE_ADD_TO_PATH:
|
||||
ctx.strokeText(char, width, 0);
|
||||
break;
|
||||
case TextRenderingMode.FILL_STROKE:
|
||||
case TextRenderingMode.FILL_STROKE_ADD_TO_PATH:
|
||||
ctx.fillText(char, width, 0);
|
||||
ctx.strokeText(char, width, 0);
|
||||
break;
|
||||
case TextRenderingMode.INVISIBLE:
|
||||
break;
|
||||
}
|
||||
|
||||
width += charWidth;
|
||||
|
||||
text.str += glyph.unicode === ' ' ? ' ' : glyph.unicode;
|
||||
@ -917,9 +985,9 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
var height = canvas.height;
|
||||
|
||||
var bl = Util.applyTransform([0, 0], inv);
|
||||
var br = Util.applyTransform([0, width], inv);
|
||||
var ul = Util.applyTransform([height, 0], inv);
|
||||
var ur = Util.applyTransform([height, width], inv);
|
||||
var br = Util.applyTransform([0, height], inv);
|
||||
var ul = Util.applyTransform([width, 0], inv);
|
||||
var ur = Util.applyTransform([width, height], inv);
|
||||
|
||||
var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
|
||||
var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
|
||||
@ -969,8 +1037,8 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
},
|
||||
|
||||
paintJpegXObject: function canvasGraphicsPaintJpegXObject(objId, w, h) {
|
||||
var image = this.objs.get(objId);
|
||||
if (!image) {
|
||||
var domImage = this.objs.get(objId);
|
||||
if (!domImage) {
|
||||
error('Dependent image isn\'t ready yet');
|
||||
}
|
||||
|
||||
@ -980,7 +1048,6 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
// scale the image to the unit square
|
||||
ctx.scale(1 / w, -1 / h);
|
||||
|
||||
var domImage = image.getImage();
|
||||
ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
|
||||
0, -h, w, h);
|
||||
|
||||
@ -1046,26 +1113,16 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
|
||||
var tmpCanvas = new this.ScratchCanvas(w, h);
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
var tmpImgData;
|
||||
this.putBinaryImageData(tmpCtx, imgData, w, h);
|
||||
|
||||
// Some browsers can set an UInt8Array directly as imageData, some
|
||||
// can't. As long as we don't have proper feature detection, just
|
||||
// copy over each pixel and set the imageData that way.
|
||||
tmpImgData = tmpCtx.getImageData(0, 0, w, h);
|
||||
|
||||
// Copy over the imageData.
|
||||
var tmpImgDataPixels = tmpImgData.data;
|
||||
var len = tmpImgDataPixels.length;
|
||||
|
||||
while (len--) {
|
||||
tmpImgDataPixels[len] = imgData.data[len];
|
||||
}
|
||||
|
||||
tmpCtx.putImageData(tmpImgData, 0, 0);
|
||||
ctx.drawImage(tmpCanvas, 0, -h);
|
||||
this.restore();
|
||||
},
|
||||
|
||||
putBinaryImageData: function canvasPutBinaryImageData() {
|
||||
//
|
||||
},
|
||||
|
||||
// Marked content
|
||||
|
||||
markPoint: function canvasGraphicsMarkPoint(tag) {
|
||||
@ -1126,3 +1183,38 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
if (!isWorker) {
|
||||
// Feature detection if the browser can use an Uint8Array directly as imgData.
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = 1;
|
||||
canvas.height = 1;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
try {
|
||||
ctx.putImageData({
|
||||
width: 1,
|
||||
height: 1,
|
||||
data: new Uint8Array(4)
|
||||
}, 0, 0);
|
||||
|
||||
CanvasGraphics.prototype.putBinaryImageData =
|
||||
function CanvasGraphicsPutBinaryImageDataNative(ctx, imgData) {
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
};
|
||||
} catch (e) {
|
||||
CanvasGraphics.prototype.putBinaryImageData =
|
||||
function CanvasGraphicsPutBinaryImageDataShim(ctx, imgData, w, h) {
|
||||
var tmpImgData = ctx.getImageData(0, 0, w, h);
|
||||
|
||||
// Copy over the imageData pixel by pixel.
|
||||
var tmpImgDataPixels = tmpImgData.data;
|
||||
var len = tmpImgDataPixels.length;
|
||||
|
||||
while (len--) {
|
||||
tmpImgDataPixels[len] = imgData.data[len];
|
||||
}
|
||||
|
||||
ctx.putImageData(tmpImgData, 0, 0);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
39
src/core.js
39
src/core.js
@ -5,6 +5,8 @@
|
||||
|
||||
var globalScope = (typeof window === 'undefined') ? this : window;
|
||||
|
||||
var isWorker = (typeof window == 'undefined');
|
||||
|
||||
var ERRORS = 0, WARNINGS = 1, TODOS = 5;
|
||||
var verbosity = WARNINGS;
|
||||
|
||||
@ -31,7 +33,7 @@ function getPdf(arg, callback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', params.url);
|
||||
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
||||
xhr.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
|
||||
xhr.expected = (params.url.indexOf('file:') === 0) ? 0 : 200;
|
||||
|
||||
if ('progress' in params)
|
||||
xhr.onprogress = params.progress || undefined;
|
||||
@ -39,11 +41,15 @@ function getPdf(arg, callback) {
|
||||
if ('error' in params)
|
||||
xhr.onerror = params.error || undefined;
|
||||
|
||||
xhr.onreadystatechange = function getPdfOnreadystatechange() {
|
||||
if (xhr.readyState === 4 && xhr.status === xhr.expected) {
|
||||
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
||||
xhr.responseArrayBuffer || xhr.response);
|
||||
callback(data);
|
||||
xhr.onreadystatechange = function getPdfOnreadystatechange(e) {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === xhr.expected) {
|
||||
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
||||
xhr.responseArrayBuffer || xhr.response);
|
||||
callback(data);
|
||||
} else if (params.error) {
|
||||
params.error(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
@ -63,6 +69,9 @@ var Page = (function pagePage() {
|
||||
};
|
||||
this.xref = xref;
|
||||
this.ref = ref;
|
||||
|
||||
this.ctx = null;
|
||||
this.callback = null;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
@ -165,8 +174,10 @@ var Page = (function pagePage() {
|
||||
try {
|
||||
self.display(gfx, self.callback);
|
||||
} catch (e) {
|
||||
if (self.callback) self.callback(e.toString());
|
||||
throw e;
|
||||
if (self.callback)
|
||||
self.callback(e);
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -556,8 +567,8 @@ var PDFDoc = (function pdfDoc() {
|
||||
|
||||
switch (type) {
|
||||
case 'JpegStream':
|
||||
var IR = data[2];
|
||||
new JpegImageLoader(id, IR, this.objs);
|
||||
var imageData = data[2];
|
||||
loadJpegStream(id, imageData, this.objs);
|
||||
break;
|
||||
case 'Font':
|
||||
var name = data[2];
|
||||
@ -595,6 +606,14 @@ var PDFDoc = (function pdfDoc() {
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
messageHandler.on('page_error', function pdfDocError(data) {
|
||||
var page = this.pageCache[data.pageNum];
|
||||
if (page.callback)
|
||||
page.callback(data.error);
|
||||
else
|
||||
throw data.error;
|
||||
}, this);
|
||||
|
||||
setTimeout(function pdfDocFontReadySetTimeout() {
|
||||
messageHandler.send('doc', this.data);
|
||||
this.workerReadyPromise.resolve(true);
|
||||
|
36
src/fonts.js
36
src/fonts.js
@ -3,8 +3,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var isWorker = (typeof window == 'undefined');
|
||||
|
||||
/**
|
||||
* Maximum time to wait for a font to be loaded by font-face rules.
|
||||
*/
|
||||
@ -765,8 +763,10 @@ var Font = (function Font() {
|
||||
|
||||
this.fontMatrix = properties.fontMatrix;
|
||||
this.widthMultiplier = 1.0;
|
||||
if (properties.type == 'Type3')
|
||||
if (properties.type == 'Type3') {
|
||||
this.encoding = properties.baseEncoding;
|
||||
return;
|
||||
}
|
||||
|
||||
// Trying to fix encoding using glyph CIDSystemInfo.
|
||||
this.loadCidToUnicode(properties);
|
||||
@ -884,6 +884,13 @@ var Font = (function Font() {
|
||||
String.fromCharCode(value & 0xff);
|
||||
};
|
||||
|
||||
function safeString16(value) {
|
||||
// clamp value to the 16-bit int range
|
||||
value = value > 0x7FFF ? 0x7FFF : value < -0x8000 ? -0x8000 : value;
|
||||
return String.fromCharCode((value >> 8) & 0xff) +
|
||||
String.fromCharCode(value & 0xff);
|
||||
};
|
||||
|
||||
function string32(value) {
|
||||
return String.fromCharCode((value >> 24) & 0xff) +
|
||||
String.fromCharCode((value >> 16) & 0xff) +
|
||||
@ -1758,7 +1765,7 @@ var Font = (function Font() {
|
||||
var hasShortCmap = !!cmapTable.hasShortCmap;
|
||||
var toUnicode = this.toUnicode;
|
||||
|
||||
if (hasShortCmap && toUnicode) {
|
||||
if (toUnicode) {
|
||||
// checking if cmap is just identity map
|
||||
var isIdentity = true;
|
||||
for (var i = 0, ii = glyphs.length; i < ii; i++) {
|
||||
@ -1903,9 +1910,9 @@ var Font = (function Font() {
|
||||
'\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date
|
||||
'\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date
|
||||
'\x00\x00' + // xMin
|
||||
string16(properties.descent) + // yMin
|
||||
safeString16(properties.descent) + // yMin
|
||||
'\x0F\xFF' + // xMax
|
||||
string16(properties.ascent) + // yMax
|
||||
safeString16(properties.ascent) + // yMax
|
||||
string16(properties.italicAngle ? 2 : 0) + // macStyle
|
||||
'\x00\x11' + // lowestRecPPEM
|
||||
'\x00\x00' + // fontDirectionHint
|
||||
@ -1917,15 +1924,15 @@ var Font = (function Font() {
|
||||
'hhea': (function fontFieldsHhea() {
|
||||
return stringToArray(
|
||||
'\x00\x01\x00\x00' + // Version number
|
||||
string16(properties.ascent) + // Typographic Ascent
|
||||
string16(properties.descent) + // Typographic Descent
|
||||
safeString16(properties.ascent) + // Typographic Ascent
|
||||
safeString16(properties.descent) + // Typographic Descent
|
||||
'\x00\x00' + // Line Gap
|
||||
'\xFF\xFF' + // advanceWidthMax
|
||||
'\x00\x00' + // minLeftSidebearing
|
||||
'\x00\x00' + // minRightSidebearing
|
||||
'\x00\x00' + // xMaxExtent
|
||||
string16(properties.capHeight) + // caretSlopeRise
|
||||
string16(Math.tan(properties.italicAngle) *
|
||||
safeString16(properties.capHeight) + // caretSlopeRise
|
||||
safeString16(Math.tan(properties.italicAngle) *
|
||||
properties.xHeight) + // caretSlopeRun
|
||||
'\x00\x00' + // caretOffset
|
||||
'\x00\x00' + // -reserved-
|
||||
@ -2110,6 +2117,10 @@ var Font = (function Font() {
|
||||
unicode = charcode;
|
||||
break;
|
||||
case 'TrueType':
|
||||
if (this.useToUnicode) {
|
||||
unicode = this.toUnicode[charcode] || charcode;
|
||||
break;
|
||||
}
|
||||
var glyphName = this.differences[charcode] || this.encoding[charcode];
|
||||
if (!glyphName)
|
||||
glyphName = Encodings.StandardEncoding[charcode];
|
||||
@ -2138,7 +2149,8 @@ var Font = (function Font() {
|
||||
break;
|
||||
}
|
||||
|
||||
var unicodeChars = this.toUnicode ? this.toUnicode[charcode] : charcode;
|
||||
var unicodeChars = !('toUnicode' in this) ? charcode :
|
||||
this.toUnicode[charcode] || charcode;
|
||||
if (typeof unicodeChars === 'number')
|
||||
unicodeChars = String.fromCharCode(unicodeChars);
|
||||
|
||||
@ -2152,7 +2164,7 @@ var Font = (function Font() {
|
||||
};
|
||||
},
|
||||
|
||||
charsToGlyphs: function fonts_chars2Glyphs(chars) {
|
||||
charsToGlyphs: function fonts_charsToGlyphs(chars) {
|
||||
var charsCache = this.charsCache;
|
||||
var glyphs;
|
||||
|
||||
|
37
src/image.js
37
src/image.js
@ -130,11 +130,11 @@ var PDFImage = (function pdfImage() {
|
||||
var buf = new Uint8Array(width * height);
|
||||
|
||||
if (smask) {
|
||||
if (smask.image.getImage) {
|
||||
if (smask.image.src) {
|
||||
// smask is a DOM image
|
||||
var tempCanvas = new ScratchCanvas(width, height);
|
||||
var tempCtx = tempCanvas.getContext('2d');
|
||||
var domImage = smask.image.getImage();
|
||||
var domImage = smask.image;
|
||||
tempCtx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
|
||||
0, 0, width, height);
|
||||
var data = tempCtx.getImageData(0, 0, width, height).data;
|
||||
@ -229,29 +229,10 @@ var PDFImage = (function pdfImage() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var JpegImageLoader = (function jpegImage() {
|
||||
function JpegImageLoader(objId, imageData, objs) {
|
||||
var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
|
||||
|
||||
var img = new Image();
|
||||
img.onload = (function jpegImageLoaderOnload() {
|
||||
this.loaded = true;
|
||||
|
||||
objs.resolve(objId, this);
|
||||
|
||||
if (this.onLoad)
|
||||
this.onLoad();
|
||||
}).bind(this);
|
||||
img.src = src;
|
||||
this.domImage = img;
|
||||
}
|
||||
|
||||
JpegImageLoader.prototype = {
|
||||
getImage: function jpegImageLoaderGetImage() {
|
||||
return this.domImage;
|
||||
}
|
||||
};
|
||||
|
||||
return JpegImageLoader;
|
||||
})();
|
||||
|
||||
function loadJpegStream(id, imageData, objs) {
|
||||
var img = new Image();
|
||||
img.onload = (function jpegImageLoaderOnload() {
|
||||
objs.resolve(id, img);
|
||||
});
|
||||
img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
|
||||
}
|
||||
|
35
src/obj.js
35
src/obj.js
@ -518,20 +518,29 @@ var XRef = (function xRefXRef() {
|
||||
readXRef: function readXref(startXRef) {
|
||||
var stream = this.stream;
|
||||
stream.pos = startXRef;
|
||||
var parser = new Parser(new Lexer(stream), true);
|
||||
var obj = parser.getObj();
|
||||
// parse an old-style xref table
|
||||
if (isCmd(obj, 'xref'))
|
||||
return this.readXRefTable(parser);
|
||||
// parse an xref stream
|
||||
if (isInt(obj)) {
|
||||
if (!isInt(parser.getObj()) ||
|
||||
!isCmd(parser.getObj(), 'obj') ||
|
||||
!isStream(obj = parser.getObj())) {
|
||||
error('Invalid XRef stream');
|
||||
|
||||
try {
|
||||
var parser = new Parser(new Lexer(stream), true);
|
||||
var obj = parser.getObj();
|
||||
|
||||
// parse an old-style xref table
|
||||
if (isCmd(obj, 'xref'))
|
||||
return this.readXRefTable(parser);
|
||||
|
||||
// parse an xref stream
|
||||
if (isInt(obj)) {
|
||||
if (!isInt(parser.getObj()) ||
|
||||
!isCmd(parser.getObj(), 'obj') ||
|
||||
!isStream(obj = parser.getObj())) {
|
||||
error('Invalid XRef stream');
|
||||
}
|
||||
return this.readXRefStream(obj);
|
||||
}
|
||||
return this.readXRefStream(obj);
|
||||
} catch (e) {
|
||||
log('Reading of the xref table/stream failed: ' + e);
|
||||
}
|
||||
|
||||
warn('Indexing all PDF objects');
|
||||
return this.indexObjects();
|
||||
},
|
||||
getEntry: function xRefGetEntry(i) {
|
||||
@ -589,7 +598,7 @@ var XRef = (function xRefXRef() {
|
||||
e = parser.getObj();
|
||||
}
|
||||
// Don't cache streams since they are mutable (except images).
|
||||
if (!isStream(e) || e.getImage)
|
||||
if (!isStream(e) || e instanceof JpegStream)
|
||||
this.cache[num] = e;
|
||||
return e;
|
||||
}
|
||||
|
@ -225,7 +225,8 @@ var Parser = (function parserParser() {
|
||||
return new PredictorStream(new FlateStream(stream), params);
|
||||
}
|
||||
return new FlateStream(stream);
|
||||
} else if (name == 'LZWDecode' || name == 'LZW') {
|
||||
}
|
||||
if (name == 'LZWDecode' || name == 'LZW') {
|
||||
var earlyChange = 1;
|
||||
if (params) {
|
||||
if (params.has('EarlyChange'))
|
||||
@ -234,18 +235,21 @@ var Parser = (function parserParser() {
|
||||
new LZWStream(stream, earlyChange), params);
|
||||
}
|
||||
return new LZWStream(stream, earlyChange);
|
||||
} else if (name == 'DCTDecode' || name == 'DCT') {
|
||||
}
|
||||
if (name == 'DCTDecode' || name == 'DCT') {
|
||||
var bytes = stream.getBytes(length);
|
||||
return new JpegStream(bytes, stream.dict, this.xref);
|
||||
} else if (name == 'ASCII85Decode' || name == 'A85') {
|
||||
return new Ascii85Stream(stream);
|
||||
} else if (name == 'ASCIIHexDecode' || name == 'AHx') {
|
||||
return new AsciiHexStream(stream);
|
||||
} else if (name == 'CCITTFaxDecode' || name == 'CCF') {
|
||||
return new CCITTFaxStream(stream, params);
|
||||
} else {
|
||||
TODO('filter "' + name + '" not supported yet');
|
||||
}
|
||||
if (name == 'ASCII85Decode' || name == 'A85') {
|
||||
return new Ascii85Stream(stream);
|
||||
}
|
||||
if (name == 'ASCIIHexDecode' || name == 'AHx') {
|
||||
return new AsciiHexStream(stream);
|
||||
}
|
||||
if (name == 'CCITTFaxDecode' || name == 'CCF') {
|
||||
return new CCITTFaxStream(stream, params);
|
||||
}
|
||||
TODO('filter "' + name + '" not supported yet');
|
||||
return stream;
|
||||
}
|
||||
};
|
||||
|
@ -3,6 +3,11 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var PatternType = {
|
||||
AXIAL: 2,
|
||||
RADIAL: 3
|
||||
};
|
||||
|
||||
var Pattern = (function patternPattern() {
|
||||
// Constructor should define this.getPattern
|
||||
function constructor() {
|
||||
@ -28,9 +33,9 @@ var Pattern = (function patternPattern() {
|
||||
var type = dict.get('ShadingType');
|
||||
|
||||
switch (type) {
|
||||
case 2:
|
||||
case 3:
|
||||
// both radial and axial shadings are handled by RadialAxial shading
|
||||
case PatternType.AXIAL:
|
||||
case PatternType.RADIAL:
|
||||
// Both radial and axial shadings are handled by RadialAxial shading.
|
||||
return new Shadings.RadialAxial(dict, matrix, xref, res, ctx);
|
||||
default:
|
||||
return new Shadings.Dummy();
|
||||
@ -117,9 +122,9 @@ Shadings.RadialAxial = (function radialAxialShading() {
|
||||
}
|
||||
|
||||
var grad;
|
||||
if (type == 2)
|
||||
if (type == PatternType.AXIAL)
|
||||
grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
|
||||
else if (type == 3)
|
||||
else if (type == PatternType.RADIAL)
|
||||
grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
|
||||
|
||||
for (var i = 0, ii = colorStops.length; i < ii; ++i) {
|
||||
@ -133,12 +138,12 @@ Shadings.RadialAxial = (function radialAxialShading() {
|
||||
getIR: function radialAxialShadingGetIR() {
|
||||
var coordsArr = this.coordsArr;
|
||||
var type = this.shadingType;
|
||||
if (type == 2) {
|
||||
if (type == PatternType.AXIAL) {
|
||||
var p0 = [coordsArr[0], coordsArr[1]];
|
||||
var p1 = [coordsArr[2], coordsArr[3]];
|
||||
var r0 = null;
|
||||
var r1 = null;
|
||||
} else if (type == 3) {
|
||||
} else if (type == PatternType.RADIAL) {
|
||||
var p0 = [coordsArr[0], coordsArr[1]];
|
||||
var p1 = [coordsArr[3], coordsArr[4]];
|
||||
var r0 = coordsArr[2];
|
||||
@ -178,7 +183,11 @@ Shadings.Dummy = (function dummyShading() {
|
||||
})();
|
||||
|
||||
var TilingPattern = (function tilingPattern() {
|
||||
var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
|
||||
var PaintType = {
|
||||
COLORED: 1,
|
||||
UNCOLORED: 2
|
||||
};
|
||||
var MAX_PATTERN_SIZE = 512;
|
||||
|
||||
function TilingPattern(IR, color, ctx, objs) {
|
||||
var IRQueue = IR[2];
|
||||
@ -204,13 +213,13 @@ var TilingPattern = (function tilingPattern() {
|
||||
var width = botRight[0] - topLeft[0];
|
||||
var height = botRight[1] - topLeft[1];
|
||||
|
||||
// TODO: hack to avoid OOM, we would idealy compute the tiling
|
||||
// TODO: hack to avoid OOM, we would ideally compute the tiling
|
||||
// pattern to be only as large as the acual size in device space
|
||||
// This could be computed with .mozCurrentTransform, but still
|
||||
// needs to be implemented
|
||||
while (Math.abs(width) > 512 || Math.abs(height) > 512) {
|
||||
width = 512;
|
||||
height = 512;
|
||||
while (Math.abs(width) > MAX_PATTERN_SIZE ||
|
||||
Math.abs(height) > MAX_PATTERN_SIZE) {
|
||||
width = height = MAX_PATTERN_SIZE;
|
||||
}
|
||||
|
||||
var tmpCanvas = new ScratchCanvas(width, height);
|
||||
@ -220,11 +229,11 @@ var TilingPattern = (function tilingPattern() {
|
||||
var graphics = new CanvasGraphics(tmpCtx, objs);
|
||||
|
||||
switch (paintType) {
|
||||
case PAINT_TYPE_COLORED:
|
||||
case PaintType.COLORED:
|
||||
tmpCtx.fillStyle = ctx.fillStyle;
|
||||
tmpCtx.strokeStyle = ctx.strokeStyle;
|
||||
break;
|
||||
case PAINT_TYPE_UNCOLORED:
|
||||
case PaintType.UNCOLORED:
|
||||
color = Util.makeCssRgb.apply(this, color);
|
||||
tmpCtx.fillStyle = color;
|
||||
tmpCtx.strokeStyle = color;
|
||||
|
@ -14,7 +14,6 @@ function MessageHandler(name, comObj) {
|
||||
ah['console_error'] = [function ahConsoleError(data) {
|
||||
console.error.apply(console, data);
|
||||
}];
|
||||
|
||||
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
|
||||
var data = event.data;
|
||||
if (data.action in ah) {
|
||||
@ -67,7 +66,6 @@ var WorkerMessageHandler = {
|
||||
handler.on('page_request', function wphSetupPageRequest(pageNum) {
|
||||
pageNum = parseInt(pageNum);
|
||||
|
||||
var page = pdfDoc.getPage(pageNum);
|
||||
|
||||
// The following code does quite the same as
|
||||
// Page.prototype.startRendering, but stops at one point and sends the
|
||||
@ -77,9 +75,23 @@ var WorkerMessageHandler = {
|
||||
var start = Date.now();
|
||||
|
||||
var dependency = [];
|
||||
|
||||
// Pre compile the pdf page and fetch the fonts/images.
|
||||
var IRQueue = page.getIRQueue(handler, dependency);
|
||||
var IRQueue = null;
|
||||
try {
|
||||
var page = pdfDoc.getPage(pageNum);
|
||||
// Pre compile the pdf page and fetch the fonts/images.
|
||||
IRQueue = page.getIRQueue(handler, dependency);
|
||||
} catch (e) {
|
||||
// Turn the error into an obj that can be serialized
|
||||
e = {
|
||||
message: e.message,
|
||||
stack: e.stack
|
||||
};
|
||||
handler.send('page_error', {
|
||||
pageNum: pageNum,
|
||||
error: e
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum,
|
||||
Date.now() - start, IRQueue.fnArray.length);
|
||||
|
@ -160,12 +160,19 @@ function nextPage(task, loadError) {
|
||||
canvas.height = pageHeight * pdfToCssUnitsCoef;
|
||||
clear(ctx);
|
||||
|
||||
// using non-attached to the document div to test
|
||||
// text layer creation operations
|
||||
var textLayer = document.createElement('div');
|
||||
|
||||
page.startRendering(
|
||||
ctx,
|
||||
function nextPageStartRendering(e) {
|
||||
snapshotCurrentPage(task, (!failure && e) ?
|
||||
('render : ' + e) : failure);
|
||||
}
|
||||
function nextPageStartRendering(error) {
|
||||
var failureMessage = false;
|
||||
if (error)
|
||||
failureMessage = 'render : ' + error.message;
|
||||
snapshotCurrentPage(task, failureMessage);
|
||||
},
|
||||
textLayer
|
||||
);
|
||||
} catch (e) {
|
||||
failure = 'page setup : ' + e.toString();
|
||||
|
1
test/pdfs/geothermal.pdf.link
Normal file
1
test/pdfs/geothermal.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://geothermal.inel.gov/publications/future_of_geothermal_energy.pdf
|
1
test/pdfs/tutorial.pdf.link
Normal file
1
test/pdfs/tutorial.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://cplusplus.com/files/tutorial.pdf
|
@ -20,7 +20,6 @@
|
||||
{ "id": "intelisa-load",
|
||||
"file": "pdfs/intelisa.pdf",
|
||||
"md5": "f5712097d29287a97f1278839814f682",
|
||||
"md5": "f3ed5487d1afa34d8b77c0c734a95c79",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
@ -302,5 +301,21 @@
|
||||
"md5": "20d88011dd7e3c4fb5274979094dab93",
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "tutorial",
|
||||
"file": "pdfs/tutorial.pdf",
|
||||
"md5": "6e122f618c27f3aa9a689423e3be6b8d",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "geothermal.pdf",
|
||||
"file": "pdfs/geothermal.pdf",
|
||||
"md5": "ecffc0ce38ffdf1e90dc952f186e9a91",
|
||||
"rounds": 1,
|
||||
"link": true,
|
||||
"pageLimit": 5,
|
||||
"skipPages": [1],
|
||||
"type": "eq"
|
||||
}
|
||||
]
|
||||
|
@ -273,6 +273,38 @@ canvas {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#errorWrapper {
|
||||
background: none repeat scroll 0 0 #FF5555;
|
||||
color: white;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 30px;
|
||||
z-index: 1000;
|
||||
padding: 3px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
#errorMessageLeft {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#errorMessageRight {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#errorMoreInfo {
|
||||
background-color: #FFFFFF;
|
||||
color: black;
|
||||
padding: 3px;
|
||||
margin: 3px;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.clearBoth {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* === Printed media overrides === */
|
||||
@media print {
|
||||
#sidebar {
|
||||
|
@ -97,6 +97,24 @@
|
||||
|
||||
<span id="info">--</span>
|
||||
</div>
|
||||
<div id="errorWrapper" hidden='true'>
|
||||
<div id="errorMessageLeft">
|
||||
<span id="errorMessage"></span>
|
||||
<button id="errorShowMore" onclick="" oncontextmenu="return false;">
|
||||
More Information
|
||||
</button>
|
||||
<button id="errorShowLess" onclick="" oncontextmenu="return false;" hidden='true'>
|
||||
Less Information
|
||||
</button>
|
||||
</div>
|
||||
<div id="errorMessageRight">
|
||||
<button id="errorClose" oncontextmenu="return false;">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
<div class="clearBoth"></div>
|
||||
<div id="errorMoreInfo" hidden='true'></div>
|
||||
</div>
|
||||
|
||||
<div id="sidebar">
|
||||
<div id="sidebarBox">
|
||||
|
@ -129,7 +129,14 @@ var PDFView = {
|
||||
if (evt.lengthComputable)
|
||||
self.progress(evt.loaded / evt.total);
|
||||
},
|
||||
error: self.error
|
||||
error: function getPdfError(e) {
|
||||
var loadingIndicator = document.getElementById('loading');
|
||||
loadingIndicator.innerHTML = 'Error';
|
||||
var moreInfo = {
|
||||
message: 'Unexpected server response of ' + e.target.status + '.'
|
||||
};
|
||||
self.error('An error occurred while loading the PDF.', moreInfo);
|
||||
}
|
||||
},
|
||||
function getPdfLoad(data) {
|
||||
self.loading = true;
|
||||
@ -168,7 +175,8 @@ var PDFView = {
|
||||
(destRef + 1);
|
||||
if (pageNumber) {
|
||||
var pdfOpenParams = '#page=' + pageNumber;
|
||||
if (isName(dest[1], 'XYZ')) {
|
||||
var destKind = dest[1];
|
||||
if ('name' in destKind && destKind.name == 'XYZ') {
|
||||
var scale = (dest[4] || this.currentScale);
|
||||
pdfOpenParams += '&zoom=' + (scale * 100);
|
||||
if (dest[2] || dest[3]) {
|
||||
@ -181,9 +189,47 @@ var PDFView = {
|
||||
return '';
|
||||
},
|
||||
|
||||
error: function pdfViewError() {
|
||||
var loadingIndicator = document.getElementById('loading');
|
||||
loadingIndicator.innerHTML = 'Error';
|
||||
/**
|
||||
* Show the error box.
|
||||
* @param {String} message A message that is human readable.
|
||||
* @param {Object} moreInfo (optional) Further information about the error
|
||||
* that is more technical. Should have a 'message'
|
||||
* and optionally a 'stack' property.
|
||||
*/
|
||||
error: function pdfViewError(message, moreInfo) {
|
||||
var errorWrapper = document.getElementById('errorWrapper');
|
||||
errorWrapper.removeAttribute('hidden');
|
||||
|
||||
var errorMessage = document.getElementById('errorMessage');
|
||||
errorMessage.innerHTML = message;
|
||||
|
||||
var closeButton = document.getElementById('errorClose');
|
||||
closeButton.onclick = function() {
|
||||
errorWrapper.setAttribute('hidden', 'true');
|
||||
};
|
||||
|
||||
var errorMoreInfo = document.getElementById('errorMoreInfo');
|
||||
var moreInfoButton = document.getElementById('errorShowMore');
|
||||
var lessInfoButton = document.getElementById('errorShowLess');
|
||||
moreInfoButton.onclick = function() {
|
||||
errorMoreInfo.removeAttribute('hidden');
|
||||
moreInfoButton.setAttribute('hidden', 'true');
|
||||
lessInfoButton.removeAttribute('hidden');
|
||||
};
|
||||
lessInfoButton.onclick = function() {
|
||||
errorMoreInfo.setAttribute('hidden', 'true');
|
||||
moreInfoButton.removeAttribute('hidden');
|
||||
lessInfoButton.setAttribute('hidden', 'true');
|
||||
};
|
||||
moreInfoButton.removeAttribute('hidden');
|
||||
lessInfoButton.setAttribute('hidden', 'true');
|
||||
errorMoreInfo.innerHTML = 'PDF.JS Build: ' + PDFJS.build + '\n';
|
||||
|
||||
if (moreInfo) {
|
||||
errorMoreInfo.innerHTML += 'Message: ' + moreInfo.message;
|
||||
if (moreInfo.stack)
|
||||
errorMoreInfo.innerHTML += '\n' + 'Stack: ' + moreInfo.stack;
|
||||
}
|
||||
},
|
||||
|
||||
progress: function pdfViewProgress(level) {
|
||||
@ -200,6 +246,9 @@ var PDFView = {
|
||||
};
|
||||
}
|
||||
|
||||
var errorWrapper = document.getElementById('errorWrapper');
|
||||
errorWrapper.setAttribute('hidden', 'true');
|
||||
|
||||
var loadingIndicator = document.getElementById('loading');
|
||||
loadingIndicator.setAttribute('hidden', 'true');
|
||||
|
||||
@ -216,7 +265,12 @@ var PDFView = {
|
||||
while (container.hasChildNodes())
|
||||
container.removeChild(container.lastChild);
|
||||
|
||||
var pdf = new PDFJS.PDFDoc(data);
|
||||
var pdf;
|
||||
try {
|
||||
pdf = new PDFJS.PDFDoc(data);
|
||||
} catch (e) {
|
||||
this.error('An error occurred while reading the PDF.', e);
|
||||
}
|
||||
var pagesCount = pdf.numPages;
|
||||
document.getElementById('numPages').innerHTML = pagesCount;
|
||||
document.getElementById('pageNumber').max = pagesCount;
|
||||
@ -505,11 +559,15 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
ctx.translate(-this.x * scale, -this.y * scale);
|
||||
|
||||
stats.begin = Date.now();
|
||||
this.content.startRendering(ctx, (function pageViewDrawCallback() {
|
||||
this.updateStats();
|
||||
if (this.onAfterDraw)
|
||||
this.onAfterDraw();
|
||||
}).bind(this), textLayer);
|
||||
this.content.startRendering(ctx,
|
||||
(function pageViewDrawCallback(error) {
|
||||
if (error)
|
||||
PDFView.error('An error occurred while rendering the page.', error);
|
||||
this.updateStats();
|
||||
if (this.onAfterDraw)
|
||||
this.onAfterDraw();
|
||||
}).bind(this), textLayer
|
||||
);
|
||||
|
||||
setupLinks(this.content, this.scale);
|
||||
div.setAttribute('data-loaded', true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user