Implement paintReadyJpegXObject + add infrastructure to handle JpegStreams
This commit is contained in:
parent
5bfa9e4f3b
commit
d887d2bd29
106
pdf.js
106
pdf.js
@ -859,6 +859,31 @@ var PredictorStream = (function() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var JpegStreamIR = (function() {
|
||||
function JpegStreamIR(objId, IR) {
|
||||
var src = IR;
|
||||
|
||||
// create DOM image
|
||||
var img = new Image();
|
||||
img.onload = (function() {
|
||||
this.loaded = true;
|
||||
Objects[objId] = this;
|
||||
if (this.onLoad)
|
||||
this.onLoad();
|
||||
}).bind(this);
|
||||
img.src = src;
|
||||
this.domImage = img;
|
||||
}
|
||||
|
||||
JpegStreamIR.prototype = {
|
||||
getImage: function() {
|
||||
return this.domImage;
|
||||
}
|
||||
}
|
||||
|
||||
return JpegStreamIR;
|
||||
})()
|
||||
|
||||
// A JpegStream can't be read directly. We use the platform to render
|
||||
// the underlying JPEG data for us.
|
||||
var JpegStream = (function() {
|
||||
@ -891,30 +916,23 @@ var JpegStream = (function() {
|
||||
newBytes.set(embedMarker, 2);
|
||||
return newBytes;
|
||||
}
|
||||
|
||||
|
||||
function constructor(bytes, dict) {
|
||||
// TODO: per poppler, some images may have "junk" before that
|
||||
// need to be removed
|
||||
this.dict = dict;
|
||||
|
||||
|
||||
if (isYcckImage(bytes))
|
||||
bytes = fixYcckImage(bytes);
|
||||
|
||||
// create DOM image
|
||||
var img = new Image();
|
||||
img.onload = (function() {
|
||||
this.loaded = true;
|
||||
if (this.onLoad)
|
||||
this.onLoad();
|
||||
}).bind(this);
|
||||
img.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));
|
||||
this.domImage = img;
|
||||
this.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
getImage: function() {
|
||||
return this.domImage;
|
||||
getIR: function() {
|
||||
return this.src;
|
||||
},
|
||||
|
||||
getChar: function() {
|
||||
error('internal error: getChar is not valid on JpegStream');
|
||||
}
|
||||
@ -4100,6 +4118,8 @@ var EvalState = (function() {
|
||||
var FontsMap = {};
|
||||
var FontLoadedCounter = 0;
|
||||
|
||||
var objIdCounter = 0;
|
||||
|
||||
var PartialEvaluator = (function() {
|
||||
function constructor() {
|
||||
this.state = new EvalState();
|
||||
@ -4273,25 +4293,27 @@ var PartialEvaluator = (function() {
|
||||
fonts, images, uniquePrefix);
|
||||
var matrix = xobj.dict.get('Matrix');
|
||||
var bbox = xobj.dict.get('BBox');
|
||||
args = [raw, matrix, bbox];
|
||||
args = [ raw, matrix, bbox ];
|
||||
fn = "paintReadyFormXObject";
|
||||
}
|
||||
if (xobj instanceof JpegStream) {
|
||||
images.bind(xobj); // monitoring image load
|
||||
// console.log("got xobj that is a JpegStream");
|
||||
}
|
||||
|
||||
if (xobj.dict.get('Subtype').name == "Image") {
|
||||
// Check if we have an image that is not rendered by the platform.
|
||||
// Needs to be rendered ourself.
|
||||
if (!(xobj instanceof JpegStream)) {
|
||||
var image = xobj;
|
||||
var dict = image.dict;
|
||||
var w = dict.get('Width', 'W');
|
||||
var h = dict.get('Height', 'H');
|
||||
|
||||
} else if ('Image' == type.name) {
|
||||
var image = xobj;
|
||||
var dict = image.dict;
|
||||
var w = dict.get('Width', 'W');
|
||||
var h = dict.get('Height', 'H');
|
||||
|
||||
if (image instanceof JpegStream) {
|
||||
var objId = ++objIdCounter;
|
||||
images.push({
|
||||
id: objId,
|
||||
IR: image.getIR()
|
||||
});
|
||||
|
||||
// TODO: Place dependency note in IR queue.
|
||||
fn = 'paintReadyJpegXObject';
|
||||
args = [ objId, w, h ];
|
||||
} else {
|
||||
// Needs to be rendered ourself.
|
||||
var inline = false;
|
||||
|
||||
var imageObj = new PDFImage(xref, resources, image, inline);
|
||||
|
||||
if (imageObj.imageMask) {
|
||||
@ -4308,12 +4330,10 @@ var PartialEvaluator = (function() {
|
||||
|
||||
fn = "paintReadyImageXObject";
|
||||
args = [ imgData ];
|
||||
|
||||
// console.log("xobj subtype image", w, h, imageObj.imageMask);
|
||||
}
|
||||
} else {
|
||||
error('Unhandled XObject subtype ' + type.name);
|
||||
}
|
||||
// console.log("xobj subtype", xobj.dict.get('Subtype').name);
|
||||
|
||||
}
|
||||
} else if (cmd == 'Tf') { // eagerly collect all fonts
|
||||
var fontName = args[0].name;
|
||||
@ -5533,6 +5553,24 @@ var CanvasGraphics = (function() {
|
||||
this.restore();
|
||||
},
|
||||
|
||||
paintReadyJpegXObject: function(objId, w, h) {
|
||||
var image = Objects[objId];
|
||||
if (!image) {
|
||||
error("Dependent image isn't ready yet");
|
||||
}
|
||||
|
||||
this.save();
|
||||
|
||||
var ctx = this.ctx;
|
||||
ctx.scale(1 / w, -1 / h);
|
||||
|
||||
var domImage = image.getImage();
|
||||
ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
|
||||
0, -h, w, h);
|
||||
|
||||
this.restore();
|
||||
},
|
||||
|
||||
paintImageXObject: function(ref, image, inline) {
|
||||
this.save();
|
||||
|
||||
|
29
worker.js
29
worker.js
@ -50,6 +50,9 @@ var WorkerPage = (function() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
// This holds a list of objects the IR queue depends on.
|
||||
var Objects = {};
|
||||
|
||||
var WorkerPDFDoc = (function() {
|
||||
function constructor(data) {
|
||||
this.data = data;
|
||||
@ -60,7 +63,7 @@ var WorkerPDFDoc = (function() {
|
||||
|
||||
this.pageCache = [];
|
||||
|
||||
var useWorker = true;
|
||||
var useWorker = false;
|
||||
|
||||
if (useWorker) {
|
||||
var worker = new Worker("../worker/boot.js");
|
||||
@ -90,9 +93,27 @@ var WorkerPDFDoc = (function() {
|
||||
font.file.end - font.file.start, fontFileDict);
|
||||
font.file = new FlateStream(fontFile);
|
||||
}
|
||||
|
||||
console.log("startRenderingFromPreCompilation:", "numberOfFonts", fonts.length);
|
||||
page.startRenderingFromPreCompilation(data.preCompilation, data.fonts, data.images);
|
||||
|
||||
var imageLoadingDone = function() {
|
||||
console.log("startRenderingFromPreCompilation:", "numberOfFonts", fonts.length);
|
||||
page.startRenderingFromPreCompilation(data.preCompilation, data.fonts, data.images);
|
||||
}
|
||||
|
||||
var images = data.images;
|
||||
if (images.length != 0) {
|
||||
// Generate JpegStreams based on IR information and start rendering
|
||||
// once the compilation is done.
|
||||
var loader = new ImagesLoader();
|
||||
loader.onLoad = imageLoadingDone;
|
||||
|
||||
for (var i = 0; i < images.length; i++) {
|
||||
var image = images[i];
|
||||
var stream = new JpegStreamIR(image.id, image.IR);
|
||||
loader.bind(stream);
|
||||
}
|
||||
} else {
|
||||
imageLoadingDone();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (!useWorker) {
|
||||
|
@ -22,8 +22,7 @@ var WorkerHandler = {
|
||||
// but stops at one point and sends the result back to the main thread.
|
||||
var gfx = new CanvasGraphics(null);
|
||||
var fonts = [];
|
||||
// TODO: Figure out how image loading is handled inside the worker.
|
||||
var images = new ImagesLoader();
|
||||
var images = [];
|
||||
|
||||
// Pre compile the pdf page and fetch the fonts/images.
|
||||
var preCompilation = page.preCompile(gfx, fonts, images);
|
||||
@ -76,9 +75,9 @@ var WorkerHandler = {
|
||||
handler.send("page", {
|
||||
pageNum: pageNum,
|
||||
fonts: fontsMin,
|
||||
images: [],
|
||||
images: images,
|
||||
preCompilation: preCompilation,
|
||||
});
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user