Merge branch 'master' of git://github.com/mozilla/pdf.js.git into forms-1
This commit is contained in:
commit
b010f293a2
@ -205,3 +205,4 @@ a "PDF Reference" from Adobe:
|
||||
|
||||
Recommended chapters to read: "2. Overview", "3.4 File Structure",
|
||||
"4.1 Graphics Objects" that lists the PDF commands.
|
||||
|
||||
|
139
src/canvas.js
139
src/canvas.js
@ -17,8 +17,8 @@ var TextRenderingMode = {
|
||||
ADD_TO_PATH: 7
|
||||
};
|
||||
|
||||
var CanvasExtraState = (function canvasExtraState() {
|
||||
function constructor(old) {
|
||||
var CanvasExtraState = (function CanvasExtraStateClosure() {
|
||||
function CanvasExtraState(old) {
|
||||
// Are soft masks and alpha values shapes or opacities?
|
||||
this.alphaIsShape = false;
|
||||
this.fontSize = 0;
|
||||
@ -52,7 +52,7 @@ var CanvasExtraState = (function canvasExtraState() {
|
||||
this.old = old;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
CanvasExtraState.prototype = {
|
||||
clone: function canvasextra_clone() {
|
||||
return Object.create(this);
|
||||
},
|
||||
@ -61,7 +61,7 @@ var CanvasExtraState = (function canvasExtraState() {
|
||||
this.y = y;
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
return CanvasExtraState;
|
||||
})();
|
||||
|
||||
function ScratchCanvas(width, height) {
|
||||
@ -181,12 +181,12 @@ function addContextCurrentTransform(ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
var CanvasGraphics = (function canvasGraphics() {
|
||||
var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
// Defines the time the executeIRQueue is going to be executing
|
||||
// before it stops and shedules a continue of execution.
|
||||
var kExecutionTime = 50;
|
||||
|
||||
function constructor(canvasCtx, objs, textLayer) {
|
||||
function CanvasGraphics(canvasCtx, objs, textLayer) {
|
||||
this.ctx = canvasCtx;
|
||||
this.current = new CanvasExtraState();
|
||||
this.stateStack = [];
|
||||
@ -206,7 +206,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
var NORMAL_CLIP = {};
|
||||
var EO_CLIP = {};
|
||||
|
||||
constructor.prototype = {
|
||||
CanvasGraphics.prototype = {
|
||||
slowCommands: {
|
||||
'stroke': true,
|
||||
'closeStroke': true,
|
||||
@ -638,17 +638,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
geometry.hScale = tr[0] - bl[0];
|
||||
geometry.vScale = tr[1] - bl[1];
|
||||
}
|
||||
var spaceGlyph = font.charsToGlyphs(' ');
|
||||
|
||||
// Hack (sometimes space is not encoded)
|
||||
if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0)
|
||||
spaceGlyph = font.charsToGlyphs('i');
|
||||
|
||||
// Fallback
|
||||
if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0)
|
||||
spaceGlyph = [{width: 0}];
|
||||
|
||||
geometry.spaceWidth = spaceGlyph[0].width;
|
||||
geometry.spaceWidth = font.spaceWidth;
|
||||
return geometry;
|
||||
},
|
||||
|
||||
@ -687,13 +677,6 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
var textSelection = textLayer && !skipTextSelection ? true : false;
|
||||
var textRenderingMode = current.textRenderingMode;
|
||||
|
||||
if (textSelection) {
|
||||
ctx.save();
|
||||
this.applyTextTransforms();
|
||||
text.geom = this.getTextGeometry();
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// Type3 fonts - each glyph is a "mini-PDF"
|
||||
if (font.coded) {
|
||||
ctx.save();
|
||||
@ -701,6 +684,13 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
ctx.translate(current.x, current.y);
|
||||
|
||||
ctx.scale(textHScale, 1);
|
||||
|
||||
if (textSelection) {
|
||||
this.save();
|
||||
ctx.scale(1, -1);
|
||||
text.geom = this.getTextGeometry();
|
||||
this.restore();
|
||||
}
|
||||
for (var i = 0; i < glyphsLength; ++i) {
|
||||
|
||||
var glyph = glyphs[i];
|
||||
@ -720,7 +710,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
var width = transformed[0] * fontSize + charSpacing;
|
||||
|
||||
ctx.translate(width, 0);
|
||||
current.x += width * textHScale2;
|
||||
current.x += width * textHScale;
|
||||
|
||||
text.str += glyph.unicode;
|
||||
text.length++;
|
||||
@ -730,6 +720,8 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
} else {
|
||||
ctx.save();
|
||||
this.applyTextTransforms();
|
||||
if (textSelection)
|
||||
text.geom = this.getTextGeometry();
|
||||
|
||||
var width = 0;
|
||||
for (var i = 0; i < glyphsLength; ++i) {
|
||||
@ -780,17 +772,25 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
showSpacedText: function canvasGraphicsShowSpacedText(arr) {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var fontSize = current.fontSize;
|
||||
var textHScale2 = current.textHScale *
|
||||
(current.font.fontMatrix || IDENTITY_MATRIX)[0];
|
||||
var textHScale = current.textHScale;
|
||||
if (!font.coded)
|
||||
textHScale *= (font.fontMatrix || IDENTITY_MATRIX)[0];
|
||||
var arrLength = arr.length;
|
||||
var textLayer = this.textLayer;
|
||||
var font = current.font;
|
||||
var text = {str: '', length: 0, canvasWidth: 0, geom: {}};
|
||||
var textSelection = textLayer ? true : false;
|
||||
|
||||
if (textSelection) {
|
||||
ctx.save();
|
||||
// Type3 fonts - each glyph is a "mini-PDF" (see also showText)
|
||||
if (font.coded) {
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.scale(1, -1);
|
||||
ctx.translate(current.x, -1 * current.y);
|
||||
ctx.scale(textHScale, 1);
|
||||
} else
|
||||
this.applyTextTransforms();
|
||||
text.geom = this.getTextGeometry();
|
||||
ctx.restore();
|
||||
@ -799,7 +799,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
for (var i = 0; i < arrLength; ++i) {
|
||||
var e = arr[i];
|
||||
if (isNum(e)) {
|
||||
var spacingLength = -e * 0.001 * fontSize * textHScale2;
|
||||
var spacingLength = -e * 0.001 * fontSize * textHScale;
|
||||
current.x += spacingLength;
|
||||
|
||||
if (textSelection) {
|
||||
@ -807,9 +807,10 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
text.canvasWidth += spacingLength;
|
||||
if (e < 0 && text.geom.spaceWidth > 0) { // avoid div by zero
|
||||
var numFakeSpaces = Math.round(-e / text.geom.spaceWidth);
|
||||
for (var j = 0; j < numFakeSpaces; ++j)
|
||||
if (numFakeSpaces > 0) {
|
||||
text.str += ' ';
|
||||
text.length += numFakeSpaces > 0 ? 1 : 0;
|
||||
text.length++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isString(e)) {
|
||||
@ -985,9 +986,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]);
|
||||
@ -1037,8 +1038,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');
|
||||
}
|
||||
|
||||
@ -1048,7 +1049,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);
|
||||
|
||||
@ -1104,7 +1104,11 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
this.restore();
|
||||
},
|
||||
|
||||
paintImageXObject: function canvasGraphicsPaintImageXObject(imgData) {
|
||||
paintImageXObject: function canvasGraphicsPaintImageXObject(objId) {
|
||||
var imgData = this.objs.get(objId);
|
||||
if (!imgData) {
|
||||
error('Dependent image isn\'t ready yet');
|
||||
}
|
||||
this.save();
|
||||
var ctx = this.ctx;
|
||||
var w = imgData.width;
|
||||
@ -1114,26 +1118,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) {
|
||||
@ -1191,6 +1185,41 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return CanvasGraphics;
|
||||
})();
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,13 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var ColorSpace = (function colorSpaceColorSpace() {
|
||||
var ColorSpace = (function ColorSpaceClosure() {
|
||||
// Constructor should define this.numComps, this.defaultColor, this.name
|
||||
function constructor() {
|
||||
function ColorSpace() {
|
||||
error('should not call ColorSpace constructor');
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
ColorSpace.prototype = {
|
||||
// Input: array of size numComps representing color component values
|
||||
// Output: array of rgb values, each value ranging from [0.1]
|
||||
getRgb: function colorSpaceGetRgb(color) {
|
||||
@ -22,15 +22,15 @@ var ColorSpace = (function colorSpaceColorSpace() {
|
||||
}
|
||||
};
|
||||
|
||||
constructor.parse = function colorSpaceParse(cs, xref, res) {
|
||||
var IR = constructor.parseToIR(cs, xref, res);
|
||||
ColorSpace.parse = function colorSpaceParse(cs, xref, res) {
|
||||
var IR = ColorSpace.parseToIR(cs, xref, res);
|
||||
if (IR instanceof AlternateCS)
|
||||
return IR;
|
||||
|
||||
return constructor.fromIR(IR);
|
||||
return ColorSpace.fromIR(IR);
|
||||
};
|
||||
|
||||
constructor.fromIR = function colorSpaceFromIR(IR) {
|
||||
ColorSpace.fromIR = function colorSpaceFromIR(IR) {
|
||||
var name = isArray(IR) ? IR[0] : IR;
|
||||
|
||||
switch (name) {
|
||||
@ -63,7 +63,7 @@ var ColorSpace = (function colorSpaceColorSpace() {
|
||||
return null;
|
||||
};
|
||||
|
||||
constructor.parseToIR = function colorSpaceParseToIR(cs, xref, res) {
|
||||
ColorSpace.parseToIR = function colorSpaceParseToIR(cs, xref, res) {
|
||||
if (isName(cs)) {
|
||||
var colorSpaces = xref.fetchIfRef(res.get('ColorSpace'));
|
||||
if (isDict(colorSpaces)) {
|
||||
@ -155,7 +155,7 @@ var ColorSpace = (function colorSpaceColorSpace() {
|
||||
return null;
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return ColorSpace;
|
||||
})();
|
||||
|
||||
/**
|
||||
@ -164,8 +164,8 @@ var ColorSpace = (function colorSpaceColorSpace() {
|
||||
* Both color spaces use a tinting function to convert colors to a base color
|
||||
* space.
|
||||
*/
|
||||
var AlternateCS = (function alternateCS() {
|
||||
function constructor(numComps, base, tintFn) {
|
||||
var AlternateCS = (function AlternateCSClosure() {
|
||||
function AlternateCS(numComps, base, tintFn) {
|
||||
this.name = 'Alternate';
|
||||
this.numComps = numComps;
|
||||
this.defaultColor = [];
|
||||
@ -175,7 +175,7 @@ var AlternateCS = (function alternateCS() {
|
||||
this.tintFn = tintFn;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
AlternateCS.prototype = {
|
||||
getRgb: function altcs_getRgb(color) {
|
||||
var tinted = this.tintFn(color);
|
||||
return this.base.getRgb(tinted);
|
||||
@ -203,21 +203,21 @@ var AlternateCS = (function alternateCS() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return AlternateCS;
|
||||
})();
|
||||
|
||||
var PatternCS = (function patternCS() {
|
||||
function constructor(baseCS) {
|
||||
var PatternCS = (function PatternCSClosure() {
|
||||
function PatternCS(baseCS) {
|
||||
this.name = 'Pattern';
|
||||
this.base = baseCS;
|
||||
}
|
||||
constructor.prototype = {};
|
||||
PatternCS.prototype = {};
|
||||
|
||||
return constructor;
|
||||
return PatternCS;
|
||||
})();
|
||||
|
||||
var IndexedCS = (function indexedCS() {
|
||||
function constructor(base, highVal, lookup) {
|
||||
var IndexedCS = (function IndexedCSClosure() {
|
||||
function IndexedCS(base, highVal, lookup) {
|
||||
this.name = 'Indexed';
|
||||
this.numComps = 1;
|
||||
this.defaultColor = [0];
|
||||
@ -240,7 +240,7 @@ var IndexedCS = (function indexedCS() {
|
||||
this.lookup = lookupArray;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
IndexedCS.prototype = {
|
||||
getRgb: function indexcs_getRgb(color) {
|
||||
var numComps = this.base.numComps;
|
||||
var start = color[0] * numComps;
|
||||
@ -269,17 +269,17 @@ var IndexedCS = (function indexedCS() {
|
||||
return base.getRgbBuffer(baseBuf, 8);
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
return IndexedCS;
|
||||
})();
|
||||
|
||||
var DeviceGrayCS = (function deviceGrayCS() {
|
||||
function constructor() {
|
||||
var DeviceGrayCS = (function DeviceGrayCSClosure() {
|
||||
function DeviceGrayCS() {
|
||||
this.name = 'DeviceGray';
|
||||
this.numComps = 1;
|
||||
this.defaultColor = [0];
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
DeviceGrayCS.prototype = {
|
||||
getRgb: function graycs_getRgb(color) {
|
||||
var c = color[0];
|
||||
return [c, c, c];
|
||||
@ -297,16 +297,16 @@ var DeviceGrayCS = (function deviceGrayCS() {
|
||||
return rgbBuf;
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
return DeviceGrayCS;
|
||||
})();
|
||||
|
||||
var DeviceRgbCS = (function deviceRgbCS() {
|
||||
function constructor() {
|
||||
var DeviceRgbCS = (function DeviceRgbCSClosure() {
|
||||
function DeviceRgbCS() {
|
||||
this.name = 'DeviceRGB';
|
||||
this.numComps = 3;
|
||||
this.defaultColor = [0, 0, 0];
|
||||
}
|
||||
constructor.prototype = {
|
||||
DeviceRgbCS.prototype = {
|
||||
getRgb: function rgbcs_getRgb(color) {
|
||||
return color;
|
||||
},
|
||||
@ -321,16 +321,16 @@ var DeviceRgbCS = (function deviceRgbCS() {
|
||||
return rgbBuf;
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
return DeviceRgbCS;
|
||||
})();
|
||||
|
||||
var DeviceCmykCS = (function deviceCmykCS() {
|
||||
function constructor() {
|
||||
var DeviceCmykCS = (function DeviceCmykCSClosure() {
|
||||
function DeviceCmykCS() {
|
||||
this.name = 'DeviceCMYK';
|
||||
this.numComps = 4;
|
||||
this.defaultColor = [0, 0, 0, 1];
|
||||
}
|
||||
constructor.prototype = {
|
||||
DeviceCmykCS.prototype = {
|
||||
getRgb: function cmykcs_getRgb(color) {
|
||||
var c = color[0], m = color[1], y = color[2], k = color[3];
|
||||
var c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k;
|
||||
@ -406,6 +406,6 @@ var DeviceCmykCS = (function deviceCmykCS() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return DeviceCmykCS;
|
||||
})();
|
||||
|
||||
|
88
src/core.js
88
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;
|
||||
@ -54,8 +56,8 @@ function getPdf(arg, callback) {
|
||||
}
|
||||
globalScope.PDFJS.getPdf = getPdf;
|
||||
|
||||
var Page = (function pagePage() {
|
||||
function constructor(xref, pageNumber, pageDict, ref) {
|
||||
var Page = (function PageClosure() {
|
||||
function Page(xref, pageNumber, pageDict, ref) {
|
||||
this.pageNumber = pageNumber;
|
||||
this.pageDict = pageDict;
|
||||
this.stats = {
|
||||
@ -72,7 +74,7 @@ var Page = (function pagePage() {
|
||||
this.callback = null;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Page.prototype = {
|
||||
getPageProp: function pageGetPageProp(key) {
|
||||
return this.xref.fetchIfRef(this.pageDict.get(key));
|
||||
},
|
||||
@ -392,7 +394,7 @@ var Page = (function pagePage() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Page;
|
||||
})();
|
||||
|
||||
/**
|
||||
@ -405,8 +407,8 @@ var Page = (function pagePage() {
|
||||
* need for the `PDFDocModel` anymore and there is only one object on the
|
||||
* main thread and not one entire copy on each worker instance.
|
||||
*/
|
||||
var PDFDocModel = (function pdfDoc() {
|
||||
function constructor(arg, callback) {
|
||||
var PDFDocModel = (function PDFDocModelClosure() {
|
||||
function PDFDocModel(arg, callback) {
|
||||
if (isStream(arg))
|
||||
init.call(this, arg);
|
||||
else if (isArrayBuffer(arg))
|
||||
@ -438,7 +440,7 @@ var PDFDocModel = (function pdfDoc() {
|
||||
return true; /* found */
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
PDFDocModel.prototype = {
|
||||
get linearization() {
|
||||
var length = this.stream.length;
|
||||
var linearization = false;
|
||||
@ -460,12 +462,17 @@ var PDFDocModel = (function pdfDoc() {
|
||||
if (find(stream, 'endobj', 1024))
|
||||
startXRef = stream.pos + 6;
|
||||
} else {
|
||||
// Find startxref at the end of the file.
|
||||
var start = stream.end - 1024;
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
stream.pos = start;
|
||||
if (find(stream, 'startxref', 1024, true)) {
|
||||
// Find startxref by jumping backward from the end of the file.
|
||||
var step = 1024;
|
||||
var found = false, pos = stream.end;
|
||||
while (!found && pos > 0) {
|
||||
pos -= step - 'startxref'.length;
|
||||
if (pos < 0)
|
||||
pos = 0;
|
||||
stream.pos = pos;
|
||||
found = find(stream, 'startxref', step, true);
|
||||
}
|
||||
if (found) {
|
||||
stream.skip(9);
|
||||
var ch;
|
||||
do {
|
||||
@ -522,11 +529,11 @@ var PDFDocModel = (function pdfDoc() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return PDFDocModel;
|
||||
})();
|
||||
|
||||
var PDFDoc = (function pdfDoc() {
|
||||
function constructor(arg, callback) {
|
||||
var PDFDoc = (function PDFDocClosure() {
|
||||
function PDFDoc(arg, callback) {
|
||||
var stream = null;
|
||||
var data = null;
|
||||
|
||||
@ -594,7 +601,7 @@ var PDFDoc = (function pdfDoc() {
|
||||
}
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
PDFDoc.prototype = {
|
||||
setupFakeWorker: function() {
|
||||
// If we don't use a worker, just post/sendMessage to the main thread.
|
||||
var fakeWorker = {
|
||||
@ -630,8 +637,12 @@ 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 'Image':
|
||||
var imageData = data[2];
|
||||
this.objs.resolve(id, imageData);
|
||||
break;
|
||||
case 'Font':
|
||||
var name = data[2];
|
||||
@ -677,6 +688,41 @@ var PDFDoc = (function pdfDoc() {
|
||||
throw data.error;
|
||||
}, this);
|
||||
|
||||
messageHandler.on('jpeg_decode', function(data, promise) {
|
||||
var imageData = data[0];
|
||||
var components = data[1];
|
||||
if (components != 3 && components != 1)
|
||||
error('Only 3 component or 1 component can be returned');
|
||||
|
||||
var img = new Image();
|
||||
img.onload = (function jpegImageLoaderOnload() {
|
||||
var width = img.width;
|
||||
var height = img.height;
|
||||
var size = width * height;
|
||||
var rgbaLength = size * 4;
|
||||
var buf = new Uint8Array(size * components);
|
||||
var tmpCanvas = new ScratchCanvas(width, height);
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
tmpCtx.drawImage(img, 0, 0);
|
||||
var data = tmpCtx.getImageData(0, 0, width, height).data;
|
||||
|
||||
if (components == 3) {
|
||||
for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
|
||||
buf[j] = data[i];
|
||||
buf[j + 1] = data[i + 1];
|
||||
buf[j + 2] = data[i + 2];
|
||||
}
|
||||
} else if (components == 1) {
|
||||
for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
|
||||
buf[j] = data[i];
|
||||
}
|
||||
}
|
||||
promise.resolve({ data: buf, width: width, height: height});
|
||||
}).bind(this);
|
||||
var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
|
||||
img.src = src;
|
||||
});
|
||||
|
||||
setTimeout(function pdfDocFontReadySetTimeout() {
|
||||
messageHandler.send('doc', this.data);
|
||||
this.workerReadyPromise.resolve(true);
|
||||
@ -723,7 +769,7 @@ var PDFDoc = (function pdfDoc() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return PDFDoc;
|
||||
})();
|
||||
|
||||
globalScope.PDFJS.PDFDoc = PDFDoc;
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var ARCFourCipher = (function arcFourCipher() {
|
||||
function constructor(key) {
|
||||
var ARCFourCipher = (function ARCFourCipherClosure() {
|
||||
function ARCFourCipher(key) {
|
||||
this.a = 0;
|
||||
this.b = 0;
|
||||
var s = new Uint8Array(256);
|
||||
@ -20,7 +20,7 @@ var ARCFourCipher = (function arcFourCipher() {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
ARCFourCipher.prototype = {
|
||||
encryptBlock: function arcFourCipherEncryptBlock(data) {
|
||||
var i, n = data.length, tmp, tmp2;
|
||||
var a = this.a, b = this.b, s = this.s;
|
||||
@ -39,12 +39,12 @@ var ARCFourCipher = (function arcFourCipher() {
|
||||
return output;
|
||||
}
|
||||
};
|
||||
constructor.prototype.decryptBlock = constructor.prototype.encryptBlock;
|
||||
ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
|
||||
|
||||
return constructor;
|
||||
return ARCFourCipher;
|
||||
})();
|
||||
|
||||
var calculateMD5 = (function calculateMD5() {
|
||||
var calculateMD5 = (function calculateMD5Closure() {
|
||||
var r = new Uint8Array([
|
||||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
@ -128,20 +128,20 @@ var calculateMD5 = (function calculateMD5() {
|
||||
return hash;
|
||||
})();
|
||||
|
||||
var NullCipher = (function nullCipher() {
|
||||
function constructor() {
|
||||
var NullCipher = (function NullCipherClosure() {
|
||||
function NullCipher() {
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
NullCipher.prototype = {
|
||||
decryptBlock: function nullCipherDecryptBlock(data) {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return NullCipher;
|
||||
})();
|
||||
|
||||
var AES128Cipher = (function aes128Cipher() {
|
||||
var AES128Cipher = (function AES128CipherClosure() {
|
||||
var rcon = new Uint8Array([
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
|
||||
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
|
||||
@ -330,7 +330,7 @@ var AES128Cipher = (function aes128Cipher() {
|
||||
return state;
|
||||
}
|
||||
|
||||
function constructor(key) {
|
||||
function AES128Cipher(key) {
|
||||
this.key = expandKey128(key);
|
||||
this.buffer = new Uint8Array(16);
|
||||
this.bufferPosition = 0;
|
||||
@ -370,7 +370,7 @@ var AES128Cipher = (function aes128Cipher() {
|
||||
return output;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
AES128Cipher.prototype = {
|
||||
decryptBlock: function aes128CipherDecryptBlock(data) {
|
||||
var i, sourceLength = data.length;
|
||||
var buffer = this.buffer, bufferLength = this.bufferPosition;
|
||||
@ -391,15 +391,15 @@ var AES128Cipher = (function aes128Cipher() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return AES128Cipher;
|
||||
})();
|
||||
|
||||
var CipherTransform = (function cipherTransform() {
|
||||
function constructor(stringCipherConstructor, streamCipherConstructor) {
|
||||
var CipherTransform = (function CipherTransformClosure() {
|
||||
function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
|
||||
this.stringCipherConstructor = stringCipherConstructor;
|
||||
this.streamCipherConstructor = streamCipherConstructor;
|
||||
}
|
||||
constructor.prototype = {
|
||||
CipherTransform.prototype = {
|
||||
createStream: function cipherTransformCreateStream(stream) {
|
||||
var cipher = new this.streamCipherConstructor();
|
||||
return new DecryptStream(stream,
|
||||
@ -415,10 +415,10 @@ var CipherTransform = (function cipherTransform() {
|
||||
return bytesToString(data);
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
return CipherTransform;
|
||||
})();
|
||||
|
||||
var CipherTransformFactory = (function cipherTransformFactory() {
|
||||
var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
||||
function prepareKeyData(fileId, password, ownerPassword, userPassword,
|
||||
flags, revision, keyLength, encryptMetadata) {
|
||||
var defaultPasswordBytes = new Uint8Array([
|
||||
@ -490,7 +490,7 @@ var CipherTransformFactory = (function cipherTransformFactory() {
|
||||
|
||||
var identityName = new Name('Identity');
|
||||
|
||||
function constructor(dict, fileId, password) {
|
||||
function CipherTransformFactory(dict, fileId, password) {
|
||||
var filter = dict.get('Filter');
|
||||
if (!isName(filter) || filter.name != 'Standard')
|
||||
error('unknown encryption method');
|
||||
@ -573,7 +573,7 @@ var CipherTransformFactory = (function cipherTransformFactory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
CipherTransformFactory.prototype = {
|
||||
createCipherTransform: function buildCipherCreateCipherTransform(num,
|
||||
gen) {
|
||||
if (this.algorithm == 4) {
|
||||
@ -592,6 +592,6 @@ var CipherTransformFactory = (function cipherTransformFactory() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return CipherTransformFactory;
|
||||
})();
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var PartialEvaluator = (function partialEvaluator() {
|
||||
function constructor(xref, handler, uniquePrefix) {
|
||||
var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
function PartialEvaluator(xref, handler, uniquePrefix) {
|
||||
this.state = new EvalState();
|
||||
this.stateStack = [];
|
||||
|
||||
@ -111,7 +111,7 @@ var PartialEvaluator = (function partialEvaluator() {
|
||||
EX: 'endCompat'
|
||||
};
|
||||
|
||||
constructor.prototype = {
|
||||
PartialEvaluator.prototype = {
|
||||
getIRQueue: function partialEvaluatorGetIRQueue(stream, resources,
|
||||
queue, dependency) {
|
||||
|
||||
@ -184,53 +184,13 @@ var PartialEvaluator = (function partialEvaluator() {
|
||||
var w = dict.get('Width', 'W');
|
||||
var h = dict.get('Height', 'H');
|
||||
|
||||
if (image instanceof JpegStream && image.isNative) {
|
||||
var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
|
||||
handler.send('obj', [objId, 'JpegStream', image.getIR()]);
|
||||
|
||||
// Add the dependency on the image object.
|
||||
insertDependency([objId]);
|
||||
|
||||
// The normal fn.
|
||||
fn = 'paintJpegXObject';
|
||||
args = [objId, w, h];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Needs to be rendered ourself.
|
||||
|
||||
// Figure out if the image has an imageMask.
|
||||
var imageMask = dict.get('ImageMask', 'IM') || false;
|
||||
|
||||
// If there is no imageMask, create the PDFImage and a lot
|
||||
// of image processing can be done here.
|
||||
if (!imageMask) {
|
||||
var imageObj = new PDFImage(xref, resources, image, inline);
|
||||
|
||||
if (imageObj.imageMask) {
|
||||
throw 'Can\'t handle this in the web worker :/';
|
||||
}
|
||||
|
||||
var imgData = {
|
||||
width: w,
|
||||
height: h,
|
||||
data: new Uint8Array(w * h * 4)
|
||||
};
|
||||
var pixels = imgData.data;
|
||||
imageObj.fillRgbaBuffer(pixels, imageObj.decode);
|
||||
|
||||
fn = 'paintImageXObject';
|
||||
args = [imgData];
|
||||
return;
|
||||
}
|
||||
|
||||
if (imageMask) {
|
||||
// This depends on a tmpCanvas beeing filled with the
|
||||
// current fillStyle, such that processing the pixel
|
||||
// data can't be done here. Instead of creating a
|
||||
// complete PDFImage, only read the information needed
|
||||
// for later.
|
||||
fn = 'paintImageMaskXObject';
|
||||
|
||||
var width = dict.get('Width', 'W');
|
||||
var height = dict.get('Height', 'H');
|
||||
@ -239,7 +199,37 @@ var PartialEvaluator = (function partialEvaluator() {
|
||||
var decode = dict.get('Decode', 'D');
|
||||
var inverseDecode = !!decode && decode[0] > 0;
|
||||
|
||||
fn = 'paintImageMaskXObject';
|
||||
args = [imgArray, inverseDecode, width, height];
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no imageMask, create the PDFImage and a lot
|
||||
// of image processing can be done here.
|
||||
var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
|
||||
insertDependency([objId]);
|
||||
args = [objId, w, h];
|
||||
|
||||
var softMask = dict.get('SMask', 'IM') || false;
|
||||
if (!softMask && image instanceof JpegStream && image.isNative) {
|
||||
// These JPEGs don't need any more processing so we can just send it.
|
||||
fn = 'paintJpegXObject';
|
||||
handler.send('obj', [objId, 'JpegStream', image.getIR()]);
|
||||
return;
|
||||
}
|
||||
|
||||
fn = 'paintImageXObject';
|
||||
|
||||
PDFImage.buildImage(function(imageObj) {
|
||||
var imgData = {
|
||||
width: w,
|
||||
height: h,
|
||||
data: new Uint8Array(w * h * 4)
|
||||
};
|
||||
var pixels = imgData.data;
|
||||
imageObj.fillRgbaBuffer(pixels, imageObj.decode);
|
||||
handler.send('obj', [objId, 'Image', imgData]);
|
||||
}, handler, xref, resources, image, inline);
|
||||
}
|
||||
|
||||
uniquePrefix = uniquePrefix || '';
|
||||
@ -858,11 +848,11 @@ var PartialEvaluator = (function partialEvaluator() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return PartialEvaluator;
|
||||
})();
|
||||
|
||||
var EvalState = (function evalState() {
|
||||
function constructor() {
|
||||
var EvalState = (function EvalStateClosure() {
|
||||
function EvalState() {
|
||||
// Are soft masks and alpha values shapes or opacities?
|
||||
this.alphaIsShape = false;
|
||||
this.fontSize = 0;
|
||||
@ -879,8 +869,8 @@ var EvalState = (function evalState() {
|
||||
this.fillColorSpace = null;
|
||||
this.strokeColorSpace = null;
|
||||
}
|
||||
constructor.prototype = {
|
||||
EvalState.prototype = {
|
||||
};
|
||||
return constructor;
|
||||
return EvalState;
|
||||
})();
|
||||
|
||||
|
110
src/fonts.js
110
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.
|
||||
*/
|
||||
@ -733,8 +731,8 @@ function isSpecialUnicode(unicode) {
|
||||
* var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
|
||||
* type1Font.bind();
|
||||
*/
|
||||
var Font = (function Font() {
|
||||
var constructor = function font_constructor(name, file, properties) {
|
||||
var Font = (function FontClosure() {
|
||||
function Font(name, file, properties) {
|
||||
this.name = name;
|
||||
this.coded = properties.coded;
|
||||
this.charProcIRQueues = properties.charProcIRQueues;
|
||||
@ -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) +
|
||||
@ -1222,7 +1229,7 @@ var Font = (function Font() {
|
||||
return nameTable;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Font.prototype = {
|
||||
name: null,
|
||||
font: null,
|
||||
mimetype: null,
|
||||
@ -1758,7 +1765,7 @@ var Font = (function Font() {
|
||||
var hasShortCmap = !!cmapTable.hasShortCmap;
|
||||
var toUnicode = this.toUnicode;
|
||||
|
||||
if (hasShortCmap && toUnicode) {
|
||||
if (toUnicode && toUnicode.length > 0) {
|
||||
// checking if cmap is just identity map
|
||||
var isIdentity = true;
|
||||
for (var i = 0, ii = glyphs.length; i < ii; i++) {
|
||||
@ -1769,15 +1776,38 @@ var Font = (function Font() {
|
||||
}
|
||||
// if it is, replacing with meaningful toUnicode values
|
||||
if (isIdentity) {
|
||||
var usedUnicodes = [], unassignedUnicodeItems = [];
|
||||
for (var i = 0, ii = glyphs.length; i < ii; i++) {
|
||||
var unicode = toUnicode[i + 1] || i + 1;
|
||||
var unicode = toUnicode[i + 1];
|
||||
if (!unicode || unicode in usedUnicodes) {
|
||||
unassignedUnicodeItems.push(i);
|
||||
continue;
|
||||
}
|
||||
glyphs[i].unicode = unicode;
|
||||
usedUnicodes[unicode] = true;
|
||||
}
|
||||
var unusedUnicode = kCmapGlyphOffset;
|
||||
for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; j++) {
|
||||
var i = unassignedUnicodeItems[j];
|
||||
while (unusedUnicode in usedUnicodes)
|
||||
unusedUnicode++;
|
||||
var cid = i + 1;
|
||||
// override only if unicode mapping is not specified
|
||||
if (!(cid in toUnicode))
|
||||
toUnicode[cid] = unusedUnicode;
|
||||
glyphs[i].unicode = unusedUnicode++;
|
||||
}
|
||||
this.useToUnicode = true;
|
||||
}
|
||||
}
|
||||
properties.hasShortCmap = hasShortCmap;
|
||||
|
||||
// remove glyph references outside range of avaialable glyphs
|
||||
for (var i = 0, ii = ids.length; i < ii; i++) {
|
||||
if (ids[i] >= numGlyphs)
|
||||
ids[i] = 0;
|
||||
}
|
||||
|
||||
createGlyphNameMap(glyphs, ids, properties);
|
||||
this.glyphNameMap = properties.glyphNameMap;
|
||||
|
||||
@ -1903,9 +1933,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 +1947,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-
|
||||
@ -2071,6 +2101,37 @@ var Font = (function Font() {
|
||||
return rule;
|
||||
},
|
||||
|
||||
get spaceWidth() {
|
||||
// trying to estimate space character width
|
||||
var possibleSpaceReplacements = ['space', 'minus', 'one', 'i'];
|
||||
var width;
|
||||
for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
|
||||
var glyphName = possibleSpaceReplacements[i];
|
||||
// if possible, getting width by glyph name
|
||||
if (glyphName in this.widths) {
|
||||
width = this.widths[glyphName];
|
||||
break;
|
||||
}
|
||||
var glyphUnicode = GlyphsUnicode[glyphName];
|
||||
// finding the charcode via unicodeToCID map
|
||||
var charcode = 0;
|
||||
if (this.composite)
|
||||
charcode = this.unicodeToCID[glyphUnicode];
|
||||
// ... via toUnicode map
|
||||
if (!charcode && 'toUnicode' in this)
|
||||
charcode = this.toUnicode.indexOf(glyphUnicode);
|
||||
// setting it to unicode if negative or undefined
|
||||
if (!(charcode > 0))
|
||||
charcode = glyphUnicode;
|
||||
// trying to get width via charcode
|
||||
width = this.widths[charcode];
|
||||
if (width)
|
||||
break; // the non-zero width found
|
||||
}
|
||||
width = (width || this.defaultWidth) * this.widthMultiplier;
|
||||
return shadow(this, 'spaceWidth', width);
|
||||
},
|
||||
|
||||
charToGlyph: function fonts_charToGlyph(charcode) {
|
||||
var unicode, width, codeIRQueue;
|
||||
|
||||
@ -2095,9 +2156,9 @@ var Font = (function Font() {
|
||||
break;
|
||||
case 'Type1':
|
||||
var glyphName = this.differences[charcode] || this.encoding[charcode];
|
||||
if (this.noUnicodeAdaptation) {
|
||||
if (!isNum(width))
|
||||
width = this.widths[glyphName];
|
||||
if (this.noUnicodeAdaptation) {
|
||||
unicode = GlyphsUnicode[glyphName] || charcode;
|
||||
break;
|
||||
}
|
||||
@ -2110,6 +2171,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 +2203,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 +2218,7 @@ var Font = (function Font() {
|
||||
};
|
||||
},
|
||||
|
||||
charsToGlyphs: function fonts_chars2Glyphs(chars) {
|
||||
charsToGlyphs: function fonts_charsToGlyphs(chars) {
|
||||
var charsCache = this.charsCache;
|
||||
var glyphs;
|
||||
|
||||
@ -2200,7 +2266,7 @@ var Font = (function Font() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Font;
|
||||
})();
|
||||
|
||||
/*
|
||||
@ -3110,9 +3176,9 @@ CFF.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
var Type2CFF = (function type2CFF() {
|
||||
var Type2CFF = (function Type2CFFClosure() {
|
||||
// TODO: replace parsing code with the Type2Parser in font_utils.js
|
||||
function constructor(file, properties) {
|
||||
function Type2CFF(file, properties) {
|
||||
var bytes = file.getBytes();
|
||||
this.bytes = bytes;
|
||||
this.properties = properties;
|
||||
@ -3120,7 +3186,7 @@ var Type2CFF = (function type2CFF() {
|
||||
this.data = this.parse();
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Type2CFF.prototype = {
|
||||
parse: function cff_parse() {
|
||||
var header = this.parseHeader();
|
||||
var properties = this.properties;
|
||||
@ -3664,6 +3730,6 @@ var Type2CFF = (function type2CFF() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Type2CFF;
|
||||
})();
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var PDFFunction = (function pdfFunction() {
|
||||
var PDFFunction = (function PDFFunctionClosure() {
|
||||
var CONSTRUCT_SAMPLED = 0;
|
||||
var CONSTRUCT_INTERPOLATED = 2;
|
||||
var CONSTRUCT_STICHED = 3;
|
||||
|
106
src/image.js
106
src/image.js
@ -3,8 +3,28 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var PDFImage = (function pdfImage() {
|
||||
function constructor(xref, res, image, inline) {
|
||||
var PDFImage = (function PDFImageClosure() {
|
||||
/**
|
||||
* Decode the image in the main thread if it supported. Resovles the promise
|
||||
* when the image data is ready.
|
||||
*/
|
||||
function handleImageData(handler, xref, res, image, promise) {
|
||||
if (image instanceof JpegStream && image.isNative) {
|
||||
// For natively supported jpegs send them to the main thread for decoding.
|
||||
var dict = image.dict;
|
||||
var colorSpace = dict.get('ColorSpace', 'CS');
|
||||
colorSpace = ColorSpace.parse(colorSpace, xref, res);
|
||||
var numComps = colorSpace.numComps;
|
||||
handler.send('jpeg_decode', [image.getIR(), numComps], function(message) {
|
||||
var data = message.data;
|
||||
var stream = new Stream(data, 0, data.length, image.dict);
|
||||
promise.resolve(stream);
|
||||
});
|
||||
} else {
|
||||
promise.resolve(image);
|
||||
}
|
||||
}
|
||||
function PDFImage(xref, res, image, inline, smask) {
|
||||
this.image = image;
|
||||
if (image.getParams) {
|
||||
// JPX/JPEG2000 streams directly contain bits per component
|
||||
@ -51,16 +71,39 @@ var PDFImage = (function pdfImage() {
|
||||
this.decode = dict.get('Decode', 'D');
|
||||
|
||||
var mask = xref.fetchIfRef(dict.get('Mask'));
|
||||
var smask = xref.fetchIfRef(dict.get('SMask'));
|
||||
|
||||
if (mask) {
|
||||
TODO('masked images');
|
||||
} else if (smask) {
|
||||
this.smask = new PDFImage(xref, res, smask);
|
||||
this.smask = new PDFImage(xref, res, smask, false);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Handles processing of image data and calls the callback with an argument
|
||||
* of a PDFImage when the image is ready to be used.
|
||||
*/
|
||||
PDFImage.buildImage = function buildImage(callback, handler, xref, res,
|
||||
image, inline) {
|
||||
var imageDataPromise = new Promise();
|
||||
var smaskPromise = new Promise();
|
||||
// The image data and smask data may not be ready yet, wait till both are
|
||||
// resolved.
|
||||
Promise.all([imageDataPromise, smaskPromise]).then(function(results) {
|
||||
var imageData = results[0], smaskData = results[1];
|
||||
var image = new PDFImage(xref, res, imageData, inline, smaskData);
|
||||
callback(image);
|
||||
});
|
||||
|
||||
constructor.prototype = {
|
||||
handleImageData(handler, xref, res, image, imageDataPromise);
|
||||
|
||||
var smask = xref.fetchIfRef(image.dict.get('SMask'));
|
||||
if (smask)
|
||||
handleImageData(handler, xref, res, smask, smaskPromise);
|
||||
else
|
||||
smaskPromise.resolve(null);
|
||||
};
|
||||
|
||||
PDFImage.prototype = {
|
||||
getComponents: function getComponents(buffer, decodeMap) {
|
||||
var bpc = this.bpc;
|
||||
if (bpc == 8)
|
||||
@ -130,18 +173,6 @@ var PDFImage = (function pdfImage() {
|
||||
var buf = new Uint8Array(width * height);
|
||||
|
||||
if (smask) {
|
||||
if (smask.image.getImage) {
|
||||
// smask is a DOM image
|
||||
var tempCanvas = new ScratchCanvas(width, height);
|
||||
var tempCtx = tempCanvas.getContext('2d');
|
||||
var domImage = smask.image.getImage();
|
||||
tempCtx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
|
||||
0, 0, width, height);
|
||||
var data = tempCtx.getImageData(0, 0, width, height).data;
|
||||
for (var i = 0, j = 0, ii = width * height; i < ii; ++i, j += 4)
|
||||
buf[i] = data[j]; // getting first component value
|
||||
return buf;
|
||||
}
|
||||
var sw = smask.width;
|
||||
var sh = smask.height;
|
||||
if (sw != this.width || sh != this.height)
|
||||
@ -159,8 +190,7 @@ var PDFImage = (function pdfImage() {
|
||||
applyStencilMask: function applyStencilMask(buffer, inverseDecode) {
|
||||
var width = this.width, height = this.height;
|
||||
var bitStrideLength = (width + 7) >> 3;
|
||||
this.image.reset();
|
||||
var imgArray = this.image.getBytes(bitStrideLength * height);
|
||||
var imgArray = this.getImageBytes(bitStrideLength * height);
|
||||
var imgArrayPos = 0;
|
||||
var i, j, mask, buf;
|
||||
// removing making non-masked pixels transparent
|
||||
@ -188,8 +218,7 @@ var PDFImage = (function pdfImage() {
|
||||
|
||||
// rows start at byte boundary;
|
||||
var rowBytes = (width * numComps * bpc + 7) >> 3;
|
||||
this.image.reset();
|
||||
var imgArray = this.image.getBytes(height * rowBytes);
|
||||
var imgArray = this.getImageBytes(height * rowBytes);
|
||||
|
||||
var comps = this.colorSpace.getRgbBuffer(
|
||||
this.getComponents(imgArray, decodeMap), bpc);
|
||||
@ -216,42 +245,27 @@ var PDFImage = (function pdfImage() {
|
||||
|
||||
// rows start at byte boundary;
|
||||
var rowBytes = (width * numComps * bpc + 7) >> 3;
|
||||
this.image.reset();
|
||||
var imgArray = this.image.getBytes(height * rowBytes);
|
||||
var imgArray = this.getImageBytes(height * rowBytes);
|
||||
|
||||
var comps = this.getComponents(imgArray);
|
||||
var length = width * height;
|
||||
|
||||
for (var i = 0; i < length; ++i)
|
||||
buffer[i] = comps[i];
|
||||
},
|
||||
getImageBytes: function getImageBytes(length) {
|
||||
this.image.reset();
|
||||
return this.image.getBytes(length);
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
return PDFImage;
|
||||
})();
|
||||
|
||||
var JpegImageLoader = (function jpegImage() {
|
||||
function JpegImageLoader(objId, imageData, objs) {
|
||||
var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
|
||||
|
||||
function loadJpegStream(id, imageData, objs) {
|
||||
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;
|
||||
objs.resolve(id, img);
|
||||
});
|
||||
img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
|
||||
}
|
||||
|
||||
JpegImageLoader.prototype = {
|
||||
getImage: function jpegImageLoaderGetImage() {
|
||||
return this.domImage;
|
||||
}
|
||||
};
|
||||
|
||||
return JpegImageLoader;
|
||||
})();
|
||||
|
||||
|
60
src/obj.js
60
src/obj.js
@ -3,34 +3,34 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var Name = (function nameName() {
|
||||
function constructor(name) {
|
||||
var Name = (function NameClosure() {
|
||||
function Name(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Name.prototype = {
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Name;
|
||||
})();
|
||||
|
||||
var Cmd = (function cmdCmd() {
|
||||
function constructor(cmd) {
|
||||
var Cmd = (function CmdClosure() {
|
||||
function Cmd(cmd) {
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Cmd.prototype = {
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Cmd;
|
||||
})();
|
||||
|
||||
var Dict = (function dictDict() {
|
||||
function constructor() {
|
||||
var Dict = (function DictClosure() {
|
||||
function Dict() {
|
||||
this.map = Object.create(null);
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Dict.prototype = {
|
||||
get: function dictGet(key1, key2, key3) {
|
||||
var value;
|
||||
if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
|
||||
@ -60,29 +60,29 @@ var Dict = (function dictDict() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Dict;
|
||||
})();
|
||||
|
||||
var Ref = (function refRef() {
|
||||
function constructor(num, gen) {
|
||||
var Ref = (function RefClosure() {
|
||||
function Ref(num, gen) {
|
||||
this.num = num;
|
||||
this.gen = gen;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Ref.prototype = {
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Ref;
|
||||
})();
|
||||
|
||||
// The reference is identified by number and generation,
|
||||
// this structure stores only one instance of the reference.
|
||||
var RefSet = (function refSet() {
|
||||
function constructor() {
|
||||
var RefSet = (function RefSetClosure() {
|
||||
function RefSet() {
|
||||
this.dict = {};
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
RefSet.prototype = {
|
||||
has: function refSetHas(ref) {
|
||||
return !!this.dict['R' + ref.num + '.' + ref.gen];
|
||||
},
|
||||
@ -92,18 +92,18 @@ var RefSet = (function refSet() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return RefSet;
|
||||
})();
|
||||
|
||||
var Catalog = (function catalogCatalog() {
|
||||
function constructor(xref) {
|
||||
var Catalog = (function CatalogClosure() {
|
||||
function Catalog(xref) {
|
||||
this.xref = xref;
|
||||
var obj = xref.getCatalogObj();
|
||||
assertWellFormed(isDict(obj), 'catalog object is not a dictionary');
|
||||
this.catDict = obj;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Catalog.prototype = {
|
||||
get toplevelPagesDict() {
|
||||
var pagesObj = this.catDict.get('Pages');
|
||||
assertWellFormed(isRef(pagesObj), 'invalid top-level pages reference');
|
||||
@ -253,11 +253,11 @@ var Catalog = (function catalogCatalog() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Catalog;
|
||||
})();
|
||||
|
||||
var XRef = (function xRefXRef() {
|
||||
function constructor(stream, startXRef, mainXRefEntriesOffset) {
|
||||
var XRef = (function XRefClosure() {
|
||||
function XRef(stream, startXRef, mainXRefEntriesOffset) {
|
||||
this.stream = stream;
|
||||
this.entries = [];
|
||||
this.xrefstms = {};
|
||||
@ -278,7 +278,7 @@ var XRef = (function xRefXRef() {
|
||||
error('Invalid root reference');
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
XRef.prototype = {
|
||||
readXRefTable: function readXRefTable(parser) {
|
||||
var obj;
|
||||
while (true) {
|
||||
@ -598,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;
|
||||
}
|
||||
@ -642,7 +642,7 @@ var XRef = (function xRefXRef() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return XRef;
|
||||
})();
|
||||
|
||||
/**
|
||||
@ -651,7 +651,7 @@ var XRef = (function xRefXRef() {
|
||||
* inside of a worker. The `PDFObjects` implements some basic functions to
|
||||
* manage these objects.
|
||||
*/
|
||||
var PDFObjects = (function pdfObjects() {
|
||||
var PDFObjects = (function PDFObjectsClosure() {
|
||||
function PDFObjects() {
|
||||
this.objs = {};
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ function isEOF(v) {
|
||||
return v == EOF;
|
||||
}
|
||||
|
||||
var Parser = (function parserParser() {
|
||||
function constructor(lexer, allowStreams, xref) {
|
||||
var Parser = (function ParserClosure() {
|
||||
function Parser(lexer, allowStreams, xref) {
|
||||
this.lexer = lexer;
|
||||
this.allowStreams = allowStreams;
|
||||
this.xref = xref;
|
||||
@ -18,7 +18,7 @@ var Parser = (function parserParser() {
|
||||
this.refill();
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Parser.prototype = {
|
||||
refill: function parserRefill() {
|
||||
this.buf1 = this.lexer.getObj();
|
||||
this.buf2 = this.lexer.getObj();
|
||||
@ -249,20 +249,20 @@ var Parser = (function parserParser() {
|
||||
if (name == 'CCITTFaxDecode' || name == 'CCF') {
|
||||
return new CCITTFaxStream(stream, params);
|
||||
}
|
||||
TODO('filter "' + name + '" not supported yet');
|
||||
warn('filter "' + name + '" not supported yet');
|
||||
return stream;
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Parser;
|
||||
})();
|
||||
|
||||
var Lexer = (function lexer() {
|
||||
function constructor(stream) {
|
||||
var Lexer = (function LexerClosure() {
|
||||
function Lexer(stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
constructor.isSpace = function lexerIsSpace(ch) {
|
||||
Lexer.isSpace = function lexerIsSpace(ch) {
|
||||
return ch == ' ' || ch == '\t' || ch == '\x0d' || ch == '\x0a';
|
||||
};
|
||||
|
||||
@ -296,7 +296,7 @@ var Lexer = (function lexer() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Lexer.prototype = {
|
||||
getNumber: function lexerGetNumber(ch) {
|
||||
var floating = false;
|
||||
var str = ch;
|
||||
@ -558,11 +558,11 @@ var Lexer = (function lexer() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Lexer;
|
||||
})();
|
||||
|
||||
var Linearization = (function linearizationLinearization() {
|
||||
function constructor(stream) {
|
||||
var Linearization = (function LinearizationClosure() {
|
||||
function Linearization(stream) {
|
||||
this.parser = new Parser(new Lexer(stream), false);
|
||||
var obj1 = this.parser.getObj();
|
||||
var obj2 = this.parser.getObj();
|
||||
@ -576,7 +576,7 @@ var Linearization = (function linearizationLinearization() {
|
||||
}
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Linearization.prototype = {
|
||||
getInt: function linearizationGetInt(name) {
|
||||
var linDict = this.linDict;
|
||||
var obj;
|
||||
@ -635,6 +635,6 @@ var Linearization = (function linearizationLinearization() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Linearization;
|
||||
})();
|
||||
|
||||
|
@ -8,13 +8,13 @@ var PatternType = {
|
||||
RADIAL: 3
|
||||
};
|
||||
|
||||
var Pattern = (function patternPattern() {
|
||||
var Pattern = (function PatternClosure() {
|
||||
// Constructor should define this.getPattern
|
||||
function constructor() {
|
||||
function Pattern() {
|
||||
error('should not call Pattern constructor');
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
Pattern.prototype = {
|
||||
// Input: current Canvas context
|
||||
// Output: the appropriate fillStyle or strokeStyle
|
||||
getPattern: function pattern_getStyle(ctx) {
|
||||
@ -22,11 +22,11 @@ var Pattern = (function patternPattern() {
|
||||
}
|
||||
};
|
||||
|
||||
constructor.shadingFromIR = function pattern_shadingFromIR(ctx, raw) {
|
||||
Pattern.shadingFromIR = function pattern_shadingFromIR(ctx, raw) {
|
||||
return Shadings[raw[0]].fromIR(ctx, raw);
|
||||
};
|
||||
|
||||
constructor.parseShading = function pattern_shading(shading, matrix, xref,
|
||||
Pattern.parseShading = function pattern_shading(shading, matrix, xref,
|
||||
res, ctx) {
|
||||
|
||||
var dict = isStream(shading) ? shading.dict : shading;
|
||||
@ -41,15 +41,15 @@ var Pattern = (function patternPattern() {
|
||||
return new Shadings.Dummy();
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
return Pattern;
|
||||
})();
|
||||
|
||||
var Shadings = {};
|
||||
|
||||
// Radial and axial shading have very similar implementations
|
||||
// If needed, the implementations can be broken into two classes
|
||||
Shadings.RadialAxial = (function radialAxialShading() {
|
||||
function constructor(dict, matrix, xref, res, ctx) {
|
||||
Shadings.RadialAxial = (function RadialAxialClosure() {
|
||||
function RadialAxial(dict, matrix, xref, res, ctx) {
|
||||
this.matrix = matrix;
|
||||
this.coordsArr = dict.get('Coords');
|
||||
this.shadingType = dict.get('ShadingType');
|
||||
@ -102,7 +102,7 @@ Shadings.RadialAxial = (function radialAxialShading() {
|
||||
this.colorStops = colorStops;
|
||||
}
|
||||
|
||||
constructor.fromIR = function radialAxialShadingGetIR(ctx, raw) {
|
||||
RadialAxial.fromIR = function radialAxialShadingGetIR(ctx, raw) {
|
||||
var type = raw[1];
|
||||
var colorStops = raw[2];
|
||||
var p0 = raw[3];
|
||||
@ -134,7 +134,7 @@ Shadings.RadialAxial = (function radialAxialShading() {
|
||||
return grad;
|
||||
};
|
||||
|
||||
constructor.prototype = {
|
||||
RadialAxial.prototype = {
|
||||
getIR: function radialAxialShadingGetIR() {
|
||||
var coordsArr = this.coordsArr;
|
||||
var type = this.shadingType;
|
||||
@ -162,28 +162,32 @@ Shadings.RadialAxial = (function radialAxialShading() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return RadialAxial;
|
||||
})();
|
||||
|
||||
Shadings.Dummy = (function dummyShading() {
|
||||
function constructor() {
|
||||
Shadings.Dummy = (function DummyClosure() {
|
||||
function Dummy() {
|
||||
this.type = 'Pattern';
|
||||
}
|
||||
|
||||
constructor.fromIR = function dummyShadingFromIR() {
|
||||
Dummy.fromIR = function dummyShadingFromIR() {
|
||||
return 'hotpink';
|
||||
};
|
||||
|
||||
constructor.prototype = {
|
||||
Dummy.prototype = {
|
||||
getIR: function dummyShadingGetIR() {
|
||||
return ['Dummy'];
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
return Dummy;
|
||||
})();
|
||||
|
||||
var TilingPattern = (function tilingPattern() {
|
||||
var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
|
||||
var TilingPattern = (function TilingPatternClosure() {
|
||||
var PaintType = {
|
||||
COLORED: 1,
|
||||
UNCOLORED: 2
|
||||
};
|
||||
var MAX_PATTERN_SIZE = 512;
|
||||
|
||||
function TilingPattern(IR, color, ctx, objs) {
|
||||
var IRQueue = IR[2];
|
||||
@ -209,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);
|
||||
@ -225,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;
|
||||
|
166
src/stream.js
166
src/stream.js
@ -3,8 +3,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var Stream = (function streamStream() {
|
||||
function constructor(arrayBuffer, start, length, dict) {
|
||||
var Stream = (function StreamClosure() {
|
||||
function Stream(arrayBuffer, start, length, dict) {
|
||||
this.bytes = new Uint8Array(arrayBuffer);
|
||||
this.start = start || 0;
|
||||
this.pos = this.start;
|
||||
@ -14,7 +14,7 @@ var Stream = (function streamStream() {
|
||||
|
||||
// required methods for a stream. if a particular stream does not
|
||||
// implement these, an error should be thrown
|
||||
constructor.prototype = {
|
||||
Stream.prototype = {
|
||||
get length() {
|
||||
return this.end - this.start;
|
||||
},
|
||||
@ -67,11 +67,11 @@ var Stream = (function streamStream() {
|
||||
isStream: true
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Stream;
|
||||
})();
|
||||
|
||||
var StringStream = (function stringStream() {
|
||||
function constructor(str) {
|
||||
var StringStream = (function StringStreamClosure() {
|
||||
function StringStream(str) {
|
||||
var length = str.length;
|
||||
var bytes = new Uint8Array(length);
|
||||
for (var n = 0; n < length; ++n)
|
||||
@ -79,21 +79,21 @@ var StringStream = (function stringStream() {
|
||||
Stream.call(this, bytes);
|
||||
}
|
||||
|
||||
constructor.prototype = Stream.prototype;
|
||||
StringStream.prototype = Stream.prototype;
|
||||
|
||||
return constructor;
|
||||
return StringStream;
|
||||
})();
|
||||
|
||||
// super class for the decoding streams
|
||||
var DecodeStream = (function decodeStream() {
|
||||
function constructor() {
|
||||
var DecodeStream = (function DecodeStreamClosure() {
|
||||
function DecodeStream() {
|
||||
this.pos = 0;
|
||||
this.bufferLength = 0;
|
||||
this.eof = false;
|
||||
this.buffer = null;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
DecodeStream.prototype = {
|
||||
ensureBuffer: function decodestream_ensureBuffer(requested) {
|
||||
var buffer = this.buffer;
|
||||
var current = buffer ? buffer.byteLength : 0;
|
||||
@ -178,24 +178,24 @@ var DecodeStream = (function decodeStream() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return DecodeStream;
|
||||
})();
|
||||
|
||||
var FakeStream = (function fakeStream() {
|
||||
function constructor(stream) {
|
||||
var FakeStream = (function FakeStreamClosure() {
|
||||
function FakeStream(stream) {
|
||||
this.dict = stream.dict;
|
||||
DecodeStream.call(this);
|
||||
}
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
constructor.prototype.readBlock = function fakeStreamReadBlock() {
|
||||
FakeStream.prototype = Object.create(DecodeStream.prototype);
|
||||
FakeStream.prototype.readBlock = function fakeStreamReadBlock() {
|
||||
var bufferLength = this.bufferLength;
|
||||
bufferLength += 1024;
|
||||
var buffer = this.ensureBuffer(bufferLength);
|
||||
this.bufferLength = bufferLength;
|
||||
};
|
||||
|
||||
constructor.prototype.getBytes = function fakeStreamGetBytes(length) {
|
||||
FakeStream.prototype.getBytes = function fakeStreamGetBytes(length) {
|
||||
var end, pos = this.pos;
|
||||
|
||||
if (length) {
|
||||
@ -217,18 +217,20 @@ var FakeStream = (function fakeStream() {
|
||||
return this.buffer.subarray(pos, end);
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return FakeStream;
|
||||
})();
|
||||
|
||||
var StreamsSequenceStream = (function streamSequenceStream() {
|
||||
function constructor(streams) {
|
||||
var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
|
||||
function StreamsSequenceStream(streams) {
|
||||
this.streams = streams;
|
||||
DecodeStream.call(this);
|
||||
}
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
StreamsSequenceStream.prototype.readBlock =
|
||||
function streamSequenceStreamReadBlock() {
|
||||
|
||||
constructor.prototype.readBlock = function streamSequenceStreamReadBlock() {
|
||||
var streams = this.streams;
|
||||
if (streams.length == 0) {
|
||||
this.eof = true;
|
||||
@ -243,10 +245,10 @@ var StreamsSequenceStream = (function streamSequenceStream() {
|
||||
this.bufferLength = newLength;
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return StreamsSequenceStream;
|
||||
})();
|
||||
|
||||
var FlateStream = (function flateStream() {
|
||||
var FlateStream = (function FlateStreamClosure() {
|
||||
var codeLenCodeMap = new Uint32Array([
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||
]);
|
||||
@ -339,7 +341,7 @@ var FlateStream = (function flateStream() {
|
||||
0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
|
||||
]), 5];
|
||||
|
||||
function constructor(stream) {
|
||||
function FlateStream(stream) {
|
||||
var bytes = stream.getBytes();
|
||||
var bytesPos = 0;
|
||||
|
||||
@ -364,9 +366,9 @@ var FlateStream = (function flateStream() {
|
||||
DecodeStream.call(this);
|
||||
}
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
FlateStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
constructor.prototype.getBits = function flateStreamGetBits(bits) {
|
||||
FlateStream.prototype.getBits = function flateStreamGetBits(bits) {
|
||||
var codeSize = this.codeSize;
|
||||
var codeBuf = this.codeBuf;
|
||||
var bytes = this.bytes;
|
||||
@ -386,7 +388,7 @@ var FlateStream = (function flateStream() {
|
||||
return b;
|
||||
};
|
||||
|
||||
constructor.prototype.getCode = function flateStreamGetCode(table) {
|
||||
FlateStream.prototype.getCode = function flateStreamGetCode(table) {
|
||||
var codes = table[0];
|
||||
var maxLen = table[1];
|
||||
var codeSize = this.codeSize;
|
||||
@ -412,7 +414,7 @@ var FlateStream = (function flateStream() {
|
||||
return codeVal;
|
||||
};
|
||||
|
||||
constructor.prototype.generateHuffmanTable =
|
||||
FlateStream.prototype.generateHuffmanTable =
|
||||
function flateStreamGenerateHuffmanTable(lengths) {
|
||||
var n = lengths.length;
|
||||
|
||||
@ -451,7 +453,7 @@ var FlateStream = (function flateStream() {
|
||||
return [codes, maxLen];
|
||||
};
|
||||
|
||||
constructor.prototype.readBlock = function flateStreamReadBlock() {
|
||||
FlateStream.prototype.readBlock = function flateStreamReadBlock() {
|
||||
// read block header
|
||||
var hdr = this.getBits(3);
|
||||
if (hdr & 1)
|
||||
@ -582,11 +584,11 @@ var FlateStream = (function flateStream() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return FlateStream;
|
||||
})();
|
||||
|
||||
var PredictorStream = (function predictorStream() {
|
||||
function constructor(stream, params) {
|
||||
var PredictorStream = (function PredictorStreamClosure() {
|
||||
function PredictorStream(stream, params) {
|
||||
var predictor = this.predictor = params.get('Predictor') || 1;
|
||||
|
||||
if (predictor <= 1)
|
||||
@ -613,9 +615,9 @@ var PredictorStream = (function predictorStream() {
|
||||
return this;
|
||||
}
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
PredictorStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
constructor.prototype.readBlockTiff =
|
||||
PredictorStream.prototype.readBlockTiff =
|
||||
function predictorStreamReadBlockTiff() {
|
||||
var rowBytes = this.rowBytes;
|
||||
|
||||
@ -676,7 +678,9 @@ var PredictorStream = (function predictorStream() {
|
||||
this.bufferLength += rowBytes;
|
||||
};
|
||||
|
||||
constructor.prototype.readBlockPng = function predictorStreamReadBlockPng() {
|
||||
PredictorStream.prototype.readBlockPng =
|
||||
function predictorStreamReadBlockPng() {
|
||||
|
||||
var rowBytes = this.rowBytes;
|
||||
var pixBytes = this.pixBytes;
|
||||
|
||||
@ -753,7 +757,7 @@ var PredictorStream = (function predictorStream() {
|
||||
this.bufferLength += rowBytes;
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return PredictorStream;
|
||||
})();
|
||||
|
||||
/**
|
||||
@ -763,7 +767,7 @@ var PredictorStream = (function predictorStream() {
|
||||
* a library to decode these images and the stream behaves like all the other
|
||||
* DecodeStreams.
|
||||
*/
|
||||
var JpegStream = (function jpegStream() {
|
||||
var JpegStream = (function JpegStreamClosure() {
|
||||
function isAdobeImage(bytes) {
|
||||
var maxBytesScanned = Math.max(bytes.length - 16, 1024);
|
||||
// Looking for APP14, 'Adobe'
|
||||
@ -794,7 +798,7 @@ var JpegStream = (function jpegStream() {
|
||||
return newBytes;
|
||||
}
|
||||
|
||||
function constructor(bytes, dict, xref) {
|
||||
function JpegStream(bytes, dict, xref) {
|
||||
// TODO: per poppler, some images may have 'junk' before that
|
||||
// need to be removed
|
||||
this.dict = dict;
|
||||
@ -825,9 +829,9 @@ var JpegStream = (function jpegStream() {
|
||||
DecodeStream.call(this);
|
||||
}
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
JpegStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
constructor.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) {
|
||||
JpegStream.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) {
|
||||
if (this.bufferLength)
|
||||
return;
|
||||
var jpegImage = new JpegImage();
|
||||
@ -839,18 +843,18 @@ var JpegStream = (function jpegStream() {
|
||||
this.buffer = data;
|
||||
this.bufferLength = data.length;
|
||||
};
|
||||
constructor.prototype.getIR = function jpegStreamGetIR() {
|
||||
JpegStream.prototype.getIR = function jpegStreamGetIR() {
|
||||
return this.src;
|
||||
};
|
||||
constructor.prototype.getChar = function jpegStreamGetChar() {
|
||||
JpegStream.prototype.getChar = function jpegStreamGetChar() {
|
||||
error('internal error: getChar is not valid on JpegStream');
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return JpegStream;
|
||||
})();
|
||||
|
||||
var DecryptStream = (function decryptStream() {
|
||||
function constructor(str, decrypt) {
|
||||
var DecryptStream = (function DecryptStreamClosure() {
|
||||
function DecryptStream(str, decrypt) {
|
||||
this.str = str;
|
||||
this.dict = str.dict;
|
||||
this.decrypt = decrypt;
|
||||
@ -860,9 +864,9 @@ var DecryptStream = (function decryptStream() {
|
||||
|
||||
var chunkSize = 512;
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
DecryptStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
constructor.prototype.readBlock = function decryptStreamReadBlock() {
|
||||
DecryptStream.prototype.readBlock = function decryptStreamReadBlock() {
|
||||
var chunk = this.str.getBytes(chunkSize);
|
||||
if (!chunk || chunk.length == 0) {
|
||||
this.eof = true;
|
||||
@ -879,11 +883,11 @@ var DecryptStream = (function decryptStream() {
|
||||
this.bufferLength = bufferLength;
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return DecryptStream;
|
||||
})();
|
||||
|
||||
var Ascii85Stream = (function ascii85Stream() {
|
||||
function constructor(str) {
|
||||
var Ascii85Stream = (function Ascii85StreamClosure() {
|
||||
function Ascii85Stream(str) {
|
||||
this.str = str;
|
||||
this.dict = str.dict;
|
||||
this.input = new Uint8Array(5);
|
||||
@ -891,9 +895,9 @@ var Ascii85Stream = (function ascii85Stream() {
|
||||
DecodeStream.call(this);
|
||||
}
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
constructor.prototype.readBlock = function ascii85StreamReadBlock() {
|
||||
Ascii85Stream.prototype.readBlock = function ascii85StreamReadBlock() {
|
||||
var tildaCode = '~'.charCodeAt(0);
|
||||
var zCode = 'z'.charCodeAt(0);
|
||||
var str = this.str;
|
||||
@ -948,11 +952,11 @@ var Ascii85Stream = (function ascii85Stream() {
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Ascii85Stream;
|
||||
})();
|
||||
|
||||
var AsciiHexStream = (function asciiHexStream() {
|
||||
function constructor(str) {
|
||||
var AsciiHexStream = (function AsciiHexStreamClosure() {
|
||||
function AsciiHexStream(str) {
|
||||
this.str = str;
|
||||
this.dict = str.dict;
|
||||
|
||||
@ -986,9 +990,9 @@ var AsciiHexStream = (function asciiHexStream() {
|
||||
102: 15
|
||||
};
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
constructor.prototype.readBlock = function asciiHexStreamReadBlock() {
|
||||
AsciiHexStream.prototype.readBlock = function asciiHexStreamReadBlock() {
|
||||
var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n,
|
||||
decodeLength, buffer, bufferLength, i, length;
|
||||
|
||||
@ -1018,10 +1022,10 @@ var AsciiHexStream = (function asciiHexStream() {
|
||||
this.eof = true;
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return AsciiHexStream;
|
||||
})();
|
||||
|
||||
var CCITTFaxStream = (function ccittFaxStream() {
|
||||
var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
||||
|
||||
var ccittEOL = -2;
|
||||
var twoDimPass = 0;
|
||||
@ -1449,7 +1453,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
[2, 2], [2, 2], [2, 2], [2, 2]
|
||||
];
|
||||
|
||||
function constructor(str, params) {
|
||||
function CCITTFaxStream(str, params) {
|
||||
this.str = str;
|
||||
this.dict = str.dict;
|
||||
|
||||
@ -1494,9 +1498,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
DecodeStream.call(this);
|
||||
}
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
CCITTFaxStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
constructor.prototype.readBlock = function ccittFaxStreamReadBlock() {
|
||||
CCITTFaxStream.prototype.readBlock = function ccittFaxStreamReadBlock() {
|
||||
while (!this.eof) {
|
||||
var c = this.lookChar();
|
||||
this.buf = EOF;
|
||||
@ -1505,7 +1509,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
}
|
||||
};
|
||||
|
||||
constructor.prototype.addPixels =
|
||||
CCITTFaxStream.prototype.addPixels =
|
||||
function ccittFaxStreamAddPixels(a1, blackPixels) {
|
||||
var codingLine = this.codingLine;
|
||||
var codingPos = this.codingPos;
|
||||
@ -1525,7 +1529,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
this.codingPos = codingPos;
|
||||
};
|
||||
|
||||
constructor.prototype.addPixelsNeg =
|
||||
CCITTFaxStream.prototype.addPixelsNeg =
|
||||
function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
|
||||
var codingLine = this.codingLine;
|
||||
var codingPos = this.codingPos;
|
||||
@ -1554,7 +1558,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
this.codingPos = codingPos;
|
||||
};
|
||||
|
||||
constructor.prototype.lookChar = function ccittFaxStreamLookChar() {
|
||||
CCITTFaxStream.prototype.lookChar = function ccittFaxStreamLookChar() {
|
||||
if (this.buf != EOF)
|
||||
return this.buf;
|
||||
|
||||
@ -1873,7 +1877,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
return [false, 0, false];
|
||||
};
|
||||
|
||||
constructor.prototype.getTwoDimCode = function ccittFaxStreamGetTwoDimCode() {
|
||||
CCITTFaxStream.prototype.getTwoDimCode =
|
||||
function ccittFaxStreamGetTwoDimCode() {
|
||||
|
||||
var code = 0;
|
||||
var p;
|
||||
if (this.eoblock) {
|
||||
@ -1892,7 +1898,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
return EOF;
|
||||
};
|
||||
|
||||
constructor.prototype.getWhiteCode = function ccittFaxStreamGetWhiteCode() {
|
||||
CCITTFaxStream.prototype.getWhiteCode =
|
||||
function ccittFaxStreamGetWhiteCode() {
|
||||
|
||||
var code = 0;
|
||||
var p;
|
||||
var n;
|
||||
@ -1924,7 +1932,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
return 1;
|
||||
};
|
||||
|
||||
constructor.prototype.getBlackCode = function ccittFaxStreamGetBlackCode() {
|
||||
CCITTFaxStream.prototype.getBlackCode =
|
||||
function ccittFaxStreamGetBlackCode() {
|
||||
|
||||
var code, p;
|
||||
if (this.eoblock) {
|
||||
code = this.lookBits(13);
|
||||
@ -1959,7 +1969,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
return 1;
|
||||
};
|
||||
|
||||
constructor.prototype.lookBits = function ccittFaxStreamLookBits(n) {
|
||||
CCITTFaxStream.prototype.lookBits = function ccittFaxStreamLookBits(n) {
|
||||
var c;
|
||||
while (this.inputBits < n) {
|
||||
if ((c = this.str.getByte()) == null) {
|
||||
@ -1974,16 +1984,16 @@ var CCITTFaxStream = (function ccittFaxStream() {
|
||||
return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
|
||||
};
|
||||
|
||||
constructor.prototype.eatBits = function ccittFaxStreamEatBits(n) {
|
||||
CCITTFaxStream.prototype.eatBits = function ccittFaxStreamEatBits(n) {
|
||||
if ((this.inputBits -= n) < 0)
|
||||
this.inputBits = 0;
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return CCITTFaxStream;
|
||||
})();
|
||||
|
||||
var LZWStream = (function lzwStream() {
|
||||
function constructor(str, earlyChange) {
|
||||
var LZWStream = (function LZWStreamClosure() {
|
||||
function LZWStream(str, earlyChange) {
|
||||
this.str = str;
|
||||
this.dict = str.dict;
|
||||
this.cachedData = 0;
|
||||
@ -2009,9 +2019,9 @@ var LZWStream = (function lzwStream() {
|
||||
DecodeStream.call(this);
|
||||
}
|
||||
|
||||
constructor.prototype = Object.create(DecodeStream.prototype);
|
||||
LZWStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
constructor.prototype.readBits = function lzwStreamReadBits(n) {
|
||||
LZWStream.prototype.readBits = function lzwStreamReadBits(n) {
|
||||
var bitsCached = this.bitsCached;
|
||||
var cachedData = this.cachedData;
|
||||
while (bitsCached < n) {
|
||||
@ -2029,7 +2039,7 @@ var LZWStream = (function lzwStream() {
|
||||
return (cachedData >>> bitsCached) & ((1 << n) - 1);
|
||||
};
|
||||
|
||||
constructor.prototype.readBlock = function lzwStreamReadBlock() {
|
||||
LZWStream.prototype.readBlock = function lzwStreamReadBlock() {
|
||||
var blockSize = 512;
|
||||
var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
|
||||
var i, j, q;
|
||||
@ -2108,6 +2118,6 @@ var LZWStream = (function lzwStream() {
|
||||
this.bufferLength = currentBufferLength;
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return LZWStream;
|
||||
})();
|
||||
|
||||
|
42
src/util.js
42
src/util.js
@ -76,24 +76,24 @@ function stringToBytes(str) {
|
||||
|
||||
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
|
||||
|
||||
var Util = (function utilUtil() {
|
||||
function constructor() {}
|
||||
constructor.makeCssRgb = function makergb(r, g, b) {
|
||||
var Util = (function UtilClosure() {
|
||||
function Util() {}
|
||||
Util.makeCssRgb = function makergb(r, g, b) {
|
||||
var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
|
||||
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
||||
};
|
||||
constructor.makeCssCmyk = function makecmyk(c, m, y, k) {
|
||||
Util.makeCssCmyk = function makecmyk(c, m, y, k) {
|
||||
c = (new DeviceCmykCS()).getRgb([c, m, y, k]);
|
||||
var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0;
|
||||
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
||||
};
|
||||
constructor.applyTransform = function apply(p, m) {
|
||||
Util.applyTransform = function apply(p, m) {
|
||||
var xt = p[0] * m[0] + p[1] * m[2] + m[4];
|
||||
var yt = p[0] * m[1] + p[1] * m[3] + m[5];
|
||||
return [xt, yt];
|
||||
};
|
||||
|
||||
return constructor;
|
||||
return Util;
|
||||
})();
|
||||
|
||||
var PDFStringTranslateTable = [
|
||||
@ -197,7 +197,7 @@ function isPDFFunction(v) {
|
||||
* can be set. If any of these happens twice or the data is required before
|
||||
* it was set, an exception is throw.
|
||||
*/
|
||||
var Promise = (function promise() {
|
||||
var Promise = (function PromiseClosure() {
|
||||
var EMPTY_PROMISE = {};
|
||||
|
||||
/**
|
||||
@ -217,7 +217,33 @@ var Promise = (function promise() {
|
||||
}
|
||||
this.callbacks = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds a promise that is resolved when all the passed in promises are
|
||||
* resolved.
|
||||
* @param {Promise[]} promises Array of promises to wait for.
|
||||
* @return {Promise} New dependant promise.
|
||||
*/
|
||||
Promise.all = function(promises) {
|
||||
var deferred = new Promise();
|
||||
var unresolved = promises.length;
|
||||
var results = [];
|
||||
if (unresolved === 0) {
|
||||
deferred.resolve(results);
|
||||
return deferred;
|
||||
}
|
||||
for (var i = 0; i < unresolved; ++i) {
|
||||
var promise = promises[i];
|
||||
promise.then((function(i) {
|
||||
return function(value) {
|
||||
results[i] = value;
|
||||
unresolved--;
|
||||
if (unresolved === 0)
|
||||
deferred.resolve(results);
|
||||
};
|
||||
})(i));
|
||||
}
|
||||
return deferred;
|
||||
};
|
||||
Promise.prototype = {
|
||||
hasData: false,
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
function MessageHandler(name, comObj) {
|
||||
this.name = name;
|
||||
this.comObj = comObj;
|
||||
this.callbackIndex = 1;
|
||||
var callbacks = this.callbacks = {};
|
||||
var ah = this.actionHandler = {};
|
||||
|
||||
ah['console_log'] = [function ahConsoleLog(data) {
|
||||
@ -14,11 +16,33 @@ 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) {
|
||||
if (data.isReply) {
|
||||
var callbackId = data.callbackId;
|
||||
if (data.callbackId in callbacks) {
|
||||
var callback = callbacks[callbackId];
|
||||
delete callbacks[callbackId];
|
||||
callback(data.data);
|
||||
} else {
|
||||
throw 'Cannot resolve callback ' + callbackId;
|
||||
}
|
||||
} else if (data.action in ah) {
|
||||
var action = ah[data.action];
|
||||
if (data.callbackId) {
|
||||
var promise = new Promise();
|
||||
promise.then(function(resolvedData) {
|
||||
comObj.postMessage({
|
||||
isReply: true,
|
||||
callbackId: data.callbackId,
|
||||
data: resolvedData
|
||||
});
|
||||
});
|
||||
action[0].call(action[1], data.data, promise);
|
||||
} else {
|
||||
action[0].call(action[1], data.data);
|
||||
}
|
||||
} else {
|
||||
throw 'Unkown action from worker: ' + data.action;
|
||||
}
|
||||
@ -33,12 +57,23 @@ MessageHandler.prototype = {
|
||||
}
|
||||
ah[actionName] = [handler, scope];
|
||||
},
|
||||
|
||||
send: function messageHandlerSend(actionName, data) {
|
||||
this.comObj.postMessage({
|
||||
/**
|
||||
* Sends a message to the comObj to invoke the action with the supplied data.
|
||||
* @param {String} actionName Action to call.
|
||||
* @param {JSON} data JSON data to send.
|
||||
* @param {function} [callback] Optional callback that will handle a reply.
|
||||
*/
|
||||
send: function messageHandlerSend(actionName, data, callback) {
|
||||
var message = {
|
||||
action: actionName,
|
||||
data: data
|
||||
});
|
||||
};
|
||||
if (callback) {
|
||||
var callbackId = this.callbackIndex++;
|
||||
this.callbacks[callbackId] = callback;
|
||||
message.callbackId = callbackId;
|
||||
}
|
||||
this.comObj.postMessage(message);
|
||||
}
|
||||
};
|
||||
|
||||
@ -83,8 +118,8 @@ var WorkerMessageHandler = {
|
||||
} catch (e) {
|
||||
// Turn the error into an obj that can be serialized
|
||||
e = {
|
||||
message: e.message,
|
||||
stack: e.stack
|
||||
message: typeof e === 'object' ? e.message : e,
|
||||
stack: typeof e === 'object' ? e.stack : null
|
||||
};
|
||||
handler.send('page_error', {
|
||||
pageNum: pageNum,
|
||||
|
@ -139,6 +139,11 @@ function nextPage(task, loadError) {
|
||||
if (task.skipPages && task.skipPages.indexOf(task.pageNum) >= 0) {
|
||||
log(' skipping page ' + task.pageNum + '/' + task.pdfDoc.numPages +
|
||||
'... ');
|
||||
// empty the canvas
|
||||
canvas.width = 1;
|
||||
canvas.height = 1;
|
||||
clear(canvas.getContext('2d'));
|
||||
|
||||
snapshotCurrentPage(task, '');
|
||||
return;
|
||||
}
|
||||
@ -160,6 +165,10 @@ 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(error) {
|
||||
@ -167,7 +176,8 @@ function nextPage(task, loadError) {
|
||||
if (error)
|
||||
failureMessage = 'render : ' + error.message;
|
||||
snapshotCurrentPage(task, failureMessage);
|
||||
}
|
||||
},
|
||||
textLayer
|
||||
);
|
||||
} catch (e) {
|
||||
failure = 'page setup : ' + e.toString();
|
||||
|
3
test/pdfs/.gitignore
vendored
3
test/pdfs/.gitignore
vendored
@ -17,3 +17,6 @@
|
||||
!devicen.pdf
|
||||
!cmykjpeg.pdf
|
||||
!issue840.pdf
|
||||
!scan-bad.pdf
|
||||
!freeculture.pdf
|
||||
!issue918.pdf
|
||||
|
1
test/pdfs/aboutstacks.pdf.link
Normal file
1
test/pdfs/aboutstacks.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://greenhousechallenge.org/media/item/313/38/About-Stacks.pdf
|
1
test/pdfs/bpl13210.pdf.link
Normal file
1
test/pdfs/bpl13210.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://h20000.www2.hp.com/bc/docs/support/SupportManual/bpl13210/bpl13210.pdf
|
BIN
test/pdfs/freeculture.pdf
Normal file
BIN
test/pdfs/freeculture.pdf
Normal file
Binary file not shown.
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
|
BIN
test/pdfs/issue918.pdf
Normal file
BIN
test/pdfs/issue918.pdf
Normal file
Binary file not shown.
1
test/pdfs/issue919.pdf.link
Normal file
1
test/pdfs/issue919.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://agb.traviangames.com/Travian_AR_Terms.pdf
|
1
test/pdfs/lista_preliminar.pdf.link
Normal file
1
test/pdfs/lista_preliminar.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://www.lfg.com.br/concursodebolsas/lista_preliminar_classificao.pdf
|
BIN
test/pdfs/scan-bad.pdf
Executable file
BIN
test/pdfs/scan-bad.pdf
Executable file
Binary file not shown.
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
|
@ -12,6 +12,7 @@ DOC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
|
||||
ANAL = True
|
||||
DEFAULT_MANIFEST_FILE = 'test_manifest.json'
|
||||
EQLOG_FILE = 'eq.log'
|
||||
BROWSERLOG_FILE = 'browser.log'
|
||||
REFDIR = 'ref'
|
||||
TMPDIR = 'tmp'
|
||||
VERBOSE = False
|
||||
@ -229,6 +230,7 @@ class BaseBrowserCommand(object):
|
||||
def setup(self):
|
||||
self.tempDir = tempfile.mkdtemp()
|
||||
self.profileDir = os.path.join(self.tempDir, "profile")
|
||||
self.browserLog = open(BROWSERLOG_FILE, "w")
|
||||
|
||||
def teardown(self):
|
||||
# If the browser is still running, wait up to ten seconds for it to quit
|
||||
@ -245,6 +247,8 @@ class BaseBrowserCommand(object):
|
||||
if self.tempDir is not None and os.path.exists(self.tempDir):
|
||||
shutil.rmtree(self.tempDir)
|
||||
|
||||
self.browserLog.close()
|
||||
|
||||
def start(self, url):
|
||||
raise Exception("Can't start BaseBrowserCommand")
|
||||
|
||||
@ -262,7 +266,7 @@ class FirefoxBrowserCommand(BaseBrowserCommand):
|
||||
if platform.system() == "Darwin":
|
||||
cmds.append("-foreground")
|
||||
cmds.extend(["-no-remote", "-profile", self.profileDir, url])
|
||||
self.process = subprocess.Popen(cmds)
|
||||
self.process = subprocess.Popen(cmds, stdout = self.browserLog, stderr = self.browserLog)
|
||||
|
||||
class ChromeBrowserCommand(BaseBrowserCommand):
|
||||
def _fixupMacPath(self):
|
||||
@ -272,7 +276,7 @@ class ChromeBrowserCommand(BaseBrowserCommand):
|
||||
cmds = [self.path]
|
||||
cmds.extend(["--user-data-dir=%s" % self.profileDir,
|
||||
"--no-first-run", "--disable-sync", url])
|
||||
self.process = subprocess.Popen(cmds)
|
||||
self.process = subprocess.Popen(cmds, stdout = self.browserLog, stderr = self.browserLog)
|
||||
|
||||
def makeBrowserCommand(browser):
|
||||
path = browser["path"].lower()
|
||||
|
@ -20,7 +20,6 @@
|
||||
{ "id": "intelisa-load",
|
||||
"file": "pdfs/intelisa.pdf",
|
||||
"md5": "f5712097d29287a97f1278839814f682",
|
||||
"md5": "f3ed5487d1afa34d8b77c0c734a95c79",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
@ -88,6 +87,13 @@
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "freeculture",
|
||||
"file": "pdfs/freeculture.pdf",
|
||||
"md5": "dcdf3a8268e6a18938a42d5149efcfca",
|
||||
"rounds": 1,
|
||||
"pageLimit": 5,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "wnv_chinese-pdf",
|
||||
"file": "pdfs/wnv_chinese.pdf",
|
||||
"md5": "db682638e68391125e8982d3c984841e",
|
||||
@ -221,6 +227,12 @@
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
},
|
||||
{ "id": "scan-bad",
|
||||
"file": "pdfs/scan-bad.pdf",
|
||||
"md5": "4cf988f01ab83f61aca57f406dfd6584",
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
},
|
||||
{ "id": "ibwa-bad",
|
||||
"file": "pdfs/ibwa-bad.pdf",
|
||||
"md5": "6ca059d32b74ac2688ae06f727fee755",
|
||||
@ -296,5 +308,58 @@
|
||||
"md5": "20d88011dd7e3c4fb5274979094dab93",
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "bpl13210",
|
||||
"file": "pdfs/bpl13210.pdf",
|
||||
"md5": "8a08512baa9fa95378d9ad4b995947c7",
|
||||
"link": true,
|
||||
"pageLimit": 5,
|
||||
"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"
|
||||
},
|
||||
{ "id": "lista_preliminar",
|
||||
"file": "pdfs/lista_preliminar.pdf",
|
||||
"md5": "4eff251319eeb660ba8a7a5cfac7787d",
|
||||
"rounds": 1,
|
||||
"link": true,
|
||||
"pageLimit": 3,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "issue919",
|
||||
"file": "pdfs/issue919.pdf",
|
||||
"md5": "3a1716a512aca4d7a8d6106bd4885d14",
|
||||
"rounds": 1,
|
||||
"link": true,
|
||||
"pageLimit": 3,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "issue918",
|
||||
"file": "pdfs/issue918.pdf",
|
||||
"md5": "d582cc0f2592ae82936589ced2a47e55",
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "aboutstacks",
|
||||
"file": "pdfs/aboutstacks.pdf",
|
||||
"md5": "6e7c8416a293ba2d83bc8dd20c6ccf51",
|
||||
"rounds": 1,
|
||||
"link": true,
|
||||
"type": "eq"
|
||||
}
|
||||
]
|
||||
|
@ -27,8 +27,8 @@
|
||||
<script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
||||
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
||||
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE -->
|
||||
|
||||
<script type="text/javascript" src="viewer.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -139,4 +139,3 @@
|
||||
<div id="viewer"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
101
web/viewer.js
101
web/viewer.js
@ -360,6 +360,7 @@ var PDFView = {
|
||||
outlineScrollView.setAttribute('hidden', 'true');
|
||||
thumbsSwitchButton.setAttribute('data-selected', true);
|
||||
outlineSwitchButton.removeAttribute('data-selected');
|
||||
updateThumbViewArea();
|
||||
break;
|
||||
case 'outline':
|
||||
thumbsScrollView.setAttribute('hidden', 'true');
|
||||
@ -394,6 +395,34 @@ var PDFView = {
|
||||
currentHeight += singlePage.height * singlePage.scale + kBottomMargin;
|
||||
}
|
||||
return visiblePages;
|
||||
},
|
||||
|
||||
getVisibleThumbs: function pdfViewGetVisibleThumbs() {
|
||||
var thumbs = this.thumbnails;
|
||||
var kBottomMargin = 5;
|
||||
var visibleThumbs = [];
|
||||
|
||||
var view = document.getElementById('sidebarScrollView');
|
||||
var currentHeight = kBottomMargin;
|
||||
var top = view.scrollTop;
|
||||
for (var i = 1; i <= thumbs.length; ++i) {
|
||||
var thumb = thumbs[i - 1];
|
||||
var thumbHeight = thumb.height * thumb.scaleY + kBottomMargin;
|
||||
if (currentHeight + thumbHeight > top)
|
||||
break;
|
||||
|
||||
currentHeight += thumbHeight;
|
||||
}
|
||||
|
||||
var bottom = top + view.clientHeight;
|
||||
for (; i <= thumbs.length && currentHeight < bottom; ++i) {
|
||||
var singleThumb = thumbs[i - 1];
|
||||
visibleThumbs.push({ id: singleThumb.id, y: currentHeight,
|
||||
view: singleThumb });
|
||||
currentHeight += singleThumb.height * singleThumb.scaleY + kBottomMargin;
|
||||
}
|
||||
|
||||
return visibleThumbs;
|
||||
}
|
||||
};
|
||||
|
||||
@ -584,7 +613,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
];
|
||||
|
||||
if (scale && scale !== PDFView.currentScale)
|
||||
PDFView.setScale(scale, true);
|
||||
PDFView.parseScale(scale, true);
|
||||
|
||||
setTimeout(function pageViewScrollIntoViewRelayout() {
|
||||
// letting page to re-layout before scrolling
|
||||
@ -667,6 +696,19 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
|
||||
return false;
|
||||
};
|
||||
|
||||
var view = page.view;
|
||||
this.width = view.width;
|
||||
this.height = view.height;
|
||||
this.id = id;
|
||||
|
||||
var maxThumbSize = 134;
|
||||
var canvasWidth = pageRatio >= 1 ? maxThumbSize :
|
||||
maxThumbSize * pageRatio;
|
||||
var canvasHeight = pageRatio <= 1 ? maxThumbSize :
|
||||
maxThumbSize / pageRatio;
|
||||
var scaleX = this.scaleX = (canvasWidth / this.width);
|
||||
var scaleY = this.scaleY = (canvasHeight / this.height);
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.id = 'thumbnailContainer' + id;
|
||||
div.className = 'thumbnail';
|
||||
@ -681,11 +723,8 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
|
||||
canvas.id = 'thumbnail' + id;
|
||||
canvas.mozOpaque = true;
|
||||
|
||||
var maxThumbSize = 134;
|
||||
canvas.width = pageRatio >= 1 ? maxThumbSize :
|
||||
maxThumbSize * pageRatio;
|
||||
canvas.height = pageRatio <= 1 ? maxThumbSize :
|
||||
maxThumbSize / pageRatio;
|
||||
canvas.width = canvasWidth;
|
||||
canvas.height = canvasHeight;
|
||||
|
||||
div.setAttribute('data-loaded', true);
|
||||
div.appendChild(canvas);
|
||||
@ -697,8 +736,6 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
|
||||
ctx.restore();
|
||||
|
||||
var view = page.view;
|
||||
var scaleX = (canvas.width / page.width);
|
||||
var scaleY = (canvas.height / page.height);
|
||||
ctx.translate(-view.x * scaleX, -view.y * scaleY);
|
||||
div.style.width = (view.width * scaleX) + 'px';
|
||||
div.style.height = (view.height * scaleY) + 'px';
|
||||
@ -779,6 +816,12 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
||||
document.getElementById('fileInput').setAttribute('hidden', 'true');
|
||||
else
|
||||
document.getElementById('fileInput').value = null;
|
||||
|
||||
if ('disableWorker' in params)
|
||||
PDFJS.disableWorker = params['disableWorker'] === 'true' ? true : false;
|
||||
|
||||
var sidebarScrollView = document.getElementById('sidebarScrollView');
|
||||
sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true);
|
||||
}, true);
|
||||
|
||||
window.addEventListener('unload', function webViewerUnload(evt) {
|
||||
@ -817,6 +860,29 @@ window.addEventListener('scroll', function webViewerScroll(evt) {
|
||||
updateViewarea();
|
||||
}, true);
|
||||
|
||||
|
||||
var thumbnailTimer;
|
||||
|
||||
function updateThumbViewArea() {
|
||||
// Only render thumbs after pausing scrolling for this amount of time
|
||||
// (makes UI more responsive)
|
||||
var delay = 50; // in ms
|
||||
|
||||
if (thumbnailTimer)
|
||||
clearTimeout(thumbnailTimer);
|
||||
|
||||
thumbnailTimer = setTimeout(function() {
|
||||
var visibleThumbs = PDFView.getVisibleThumbs();
|
||||
for (var i = 0; i < visibleThumbs.length; i++) {
|
||||
var thumb = visibleThumbs[i];
|
||||
PDFView.thumbnails[thumb.id - 1].draw();
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
window.addEventListener('transitionend', updateThumbViewArea, true);
|
||||
window.addEventListener('webkitTransitionEnd', updateThumbViewArea, true);
|
||||
|
||||
window.addEventListener('resize', function webViewerResize(evt) {
|
||||
if (document.getElementById('pageWidthOption').selected ||
|
||||
document.getElementById('pageFitOption').selected)
|
||||
@ -857,25 +923,6 @@ window.addEventListener('change', function webViewerChange(evt) {
|
||||
document.getElementById('download').setAttribute('hidden', 'true');
|
||||
}, true);
|
||||
|
||||
window.addEventListener('transitionend', function webViewerTransitionend(evt) {
|
||||
var pageIndex = 0;
|
||||
var pagesCount = PDFView.pages.length;
|
||||
|
||||
var container = document.getElementById('sidebarView');
|
||||
container._interval = window.setInterval(function interval() {
|
||||
// skipping the thumbnails with set images
|
||||
while (pageIndex < pagesCount && PDFView.thumbnails[pageIndex].hasImage)
|
||||
pageIndex++;
|
||||
|
||||
if (pageIndex >= pagesCount) {
|
||||
window.clearInterval(container._interval);
|
||||
return;
|
||||
}
|
||||
|
||||
PDFView.thumbnails[pageIndex++].draw();
|
||||
}, 500);
|
||||
}, true);
|
||||
|
||||
window.addEventListener('scalechange', function scalechange(evt) {
|
||||
var customScaleOption = document.getElementById('customScaleOption');
|
||||
customScaleOption.selected = false;
|
||||
|
Loading…
Reference in New Issue
Block a user