Merge pull request #4613 from yurydelendik/buildImagePromise

Refactors buildImage to use Promise; don't draw bad images
This commit is contained in:
Yury Delendik 2014-04-14 15:23:06 -05:00
commit eb8924a79f
4 changed files with 42 additions and 35 deletions

View File

@ -206,11 +206,15 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return;
}
PDFImage.buildImage(function(imageObj) {
PDFImage.buildImage(self.handler, self.xref, resources, image, inline).
then(function(imageObj) {
var imgData = imageObj.createImageData(/* forceRGBA = */ false);
self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData],
null, [imgData.data.buffer]);
}, self.handler, self.xref, resources, image, inline);
null, [imgData.data.buffer]);
}).then(null, function (reason) {
warn('Unable to decode image: ' + reason);
self.handler.send('obj', [objId, self.pageIndex, 'Image', null]);
});
operatorList.addOp(OPS.paintImageXObject, args);
if (cacheKey) {

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
/* globals ColorSpace, DecodeStream, error, info, isArray, ImageKind, isStream,
JpegStream, JpxImage, Name, Promise, Stream, warn, LegacyPromise */
JpegStream, JpxImage, Name, Promise, Stream, warn */
'use strict';
@ -24,20 +24,24 @@ 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) {
function handleImageData(handler, xref, res, image) {
if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) {
// 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;
var resolvePromise;
handler.send('JpegDecode', [image.getIR(), numComps], function(message) {
var data = message.data;
var stream = new Stream(data, 0, data.length, image.dict);
promise.resolve(stream);
resolvePromise(stream);
});
return new Promise(function (resolve) {
resolvePromise = resolve;
});
} else {
promise.resolve(image);
return Promise.resolve(image);
}
}
/**
@ -144,47 +148,43 @@ var PDFImage = (function PDFImageClosure() {
}
}
/**
* Handles processing of image data and calls the callback with an argument
* of a PDFImage when the image is ready to be used.
* Handles processing of image data and returns the Promise that is resolved
* with a PDFImage when the image is ready to be used.
*/
PDFImage.buildImage = function PDFImage_buildImage(callback, handler, xref,
PDFImage.buildImage = function PDFImage_buildImage(handler, xref,
res, image, inline) {
var imageDataPromise = new LegacyPromise();
var smaskPromise = new LegacyPromise();
var maskPromise = new LegacyPromise();
// The image data and smask data may not be ready yet, wait until both are
// resolved.
Promise.all([imageDataPromise, smaskPromise, maskPromise]).then(
function(results) {
var imageData = results[0], smaskData = results[1], maskData = results[2];
var image = new PDFImage(xref, res, imageData, inline, smaskData,
maskData);
callback(image);
});
handleImageData(handler, xref, res, image, imageDataPromise);
var imagePromise = handleImageData(handler, xref, res, image);
var smaskPromise;
var maskPromise;
var smask = image.dict.get('SMask');
var mask = image.dict.get('Mask');
if (smask) {
handleImageData(handler, xref, res, smask, smaskPromise);
maskPromise.resolve(null);
smaskPromise = handleImageData(handler, xref, res, smask);
maskPromise = Promise.resolve(null);
} else {
smaskPromise.resolve(null);
smaskPromise = Promise.resolve(null);
if (mask) {
if (isStream(mask)) {
handleImageData(handler, xref, res, mask, maskPromise);
maskPromise = handleImageData(handler, xref, res, mask);
} else if (isArray(mask)) {
maskPromise.resolve(mask);
maskPromise = Promise.resolve(mask);
} else {
warn('Unsupported mask format.');
maskPromise.resolve(null);
maskPromise = Promise.resolve(null);
}
} else {
maskPromise.resolve(null);
maskPromise = Promise.resolve(null);
}
}
return Promise.all([imagePromise, smaskPromise, maskPromise]).then(
function(results) {
var imageData = results[0];
var smaskData = results[1];
var maskData = results[2];
return new PDFImage(xref, res, imageData, inline, smaskData, maskData);
});
};
/**

View File

@ -912,7 +912,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
// heuristics that will allow not to store large data
var MAX_IMAGE_SIZE_TO_STORE = 8000000;
if ('data' in imageData &&
if (imageData && 'data' in imageData &&
imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
pageProxy.cleanupAfterRender = true;
}

View File

@ -1824,7 +1824,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
var domImage = this.objs.get(objId);
if (!domImage) {
error('Dependent image isn\'t ready yet');
warn('Dependent image isn\'t ready yet');
return;
}
this.save();
@ -1958,7 +1959,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
var imgData = this.objs.get(objId);
if (!imgData) {
error('Dependent image isn\'t ready yet');
warn('Dependent image isn\'t ready yet');
return;
}
this.paintInlineImageXObject(imgData);
@ -1969,7 +1971,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
positions) {
var imgData = this.objs.get(objId);
if (!imgData) {
error('Dependent image isn\'t ready yet');
warn('Dependent image isn\'t ready yet');
return;
}
var width = imgData.width;