Browse Source

Merge pull request #4613 from yurydelendik/buildImagePromise

Refactors buildImage to use Promise; don't draw bad images
Yury Delendik 11 years ago
parent
commit
eb8924a79f
  1. 10
      src/core/evaluator.js
  2. 56
      src/core/image.js
  3. 2
      src/display/api.js
  4. 9
      src/display/canvas.js

10
src/core/evaluator.js

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

56
src/core/image.js

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
/* globals ColorSpace, DecodeStream, error, info, isArray, ImageKind, isStream, /* globals ColorSpace, DecodeStream, error, info, isArray, ImageKind, isStream,
JpegStream, JpxImage, Name, Promise, Stream, warn, LegacyPromise */ JpegStream, JpxImage, Name, Promise, Stream, warn */
'use strict'; 'use strict';
@ -24,20 +24,24 @@ var PDFImage = (function PDFImageClosure() {
* Decode the image in the main thread if it supported. Resovles the promise * Decode the image in the main thread if it supported. Resovles the promise
* when the image data is ready. * 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)) { if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) {
// For natively supported jpegs send them to the main thread for decoding. // For natively supported jpegs send them to the main thread for decoding.
var dict = image.dict; var dict = image.dict;
var colorSpace = dict.get('ColorSpace', 'CS'); var colorSpace = dict.get('ColorSpace', 'CS');
colorSpace = ColorSpace.parse(colorSpace, xref, res); colorSpace = ColorSpace.parse(colorSpace, xref, res);
var numComps = colorSpace.numComps; var numComps = colorSpace.numComps;
var resolvePromise;
handler.send('JpegDecode', [image.getIR(), numComps], function(message) { handler.send('JpegDecode', [image.getIR(), numComps], function(message) {
var data = message.data; var data = message.data;
var stream = new Stream(data, 0, data.length, image.dict); var stream = new Stream(data, 0, data.length, image.dict);
promise.resolve(stream); resolvePromise(stream);
});
return new Promise(function (resolve) {
resolvePromise = resolve;
}); });
} else { } 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 * Handles processing of image data and returns the Promise that is resolved
* of a PDFImage when the image is ready to be used. * 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) { res, image, inline) {
var imageDataPromise = new LegacyPromise(); var imagePromise = handleImageData(handler, xref, res, image);
var smaskPromise = new LegacyPromise(); var smaskPromise;
var maskPromise = new LegacyPromise(); var maskPromise;
// 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 smask = image.dict.get('SMask'); var smask = image.dict.get('SMask');
var mask = image.dict.get('Mask'); var mask = image.dict.get('Mask');
if (smask) { if (smask) {
handleImageData(handler, xref, res, smask, smaskPromise); smaskPromise = handleImageData(handler, xref, res, smask);
maskPromise.resolve(null); maskPromise = Promise.resolve(null);
} else { } else {
smaskPromise.resolve(null); smaskPromise = Promise.resolve(null);
if (mask) { if (mask) {
if (isStream(mask)) { if (isStream(mask)) {
handleImageData(handler, xref, res, mask, maskPromise); maskPromise = handleImageData(handler, xref, res, mask);
} else if (isArray(mask)) { } else if (isArray(mask)) {
maskPromise.resolve(mask); maskPromise = Promise.resolve(mask);
} else { } else {
warn('Unsupported mask format.'); warn('Unsupported mask format.');
maskPromise.resolve(null); maskPromise = Promise.resolve(null);
} }
} else { } 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);
});
}; };
/** /**

2
src/display/api.js

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

9
src/display/canvas.js

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

Loading…
Cancel
Save