Skip to content

Commit

Permalink
JavaScript side of PNacl image stream decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
pbrant committed Feb 13, 2017
1 parent aca86c6 commit f0046e3
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 9 deletions.
79 changes: 77 additions & 2 deletions src/core/evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/* globals assert, ColorSpace, DecodeStream, Dict, Encodings,
error, ErrorFont, Font, FONT_IDENTITY_MATRIX, fontCharsToUnicode,
FontFlags, ImageKind, info, isArray, isCmd, isDict, isEOF, isName,
isNum, isStream, isString, JpegStream, Lexer, Metrics,
isNum, isStream, isString, JpegStream, Jbig2Stream, JpxStream, Lexer, Metrics,
MurmurHash3_64, Name, Parser, Pattern, PDFImage, PDFJS, serifFonts,
stdFontMap, symbolsFonts, getTilingPatternIR, warn, Util, Promise,
RefSetCache, isRef, TextRenderingMode, ToUnicodeMap, CMapFactory,
Expand All @@ -39,6 +39,75 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
this.fontCache = fontCache;
}

function WorkerNativeImageStreamDecoder(handler) {
this.handler = handler;
}
WorkerNativeImageStreamDecoder.prototype = {
decode: function NativeImageStreamDecoder_decode(image) {
var jbigImageRequest = function() {
var globals = undefined;
if (isDict(image.params)) {
var globalsStream = image.params.get('JBIG2Globals');
if (isStream(globalsStream)) {
globals = globalsStream.getBytes();
}
}

var page = image.bytes;

var data;
if (globals) {
var ary = new Uint8Array(globals.length + page.length);
ary.set(globals, 0);
ary.set(page, globals.length);
data = ary.buffer;
} else {
data = page.buffer.slice(page.byteOffset, page.byteOffset + page.byteLength);
}

return { action: 'DecodeJbig2Stream', data: data };
}

var jpxImageRequest = function() {
var ary = image.bytes;
var cs = image.dict.get('ColorSpace', 'CS');
return {
action: 'DecodeJpxStream',
data: {
image: ary.buffer.slice(ary.byteOffset, ary.byteOffset + ary.byteLength),
sMaskInData: image.dict.get('SMaskInData'),
indexed: isArray(cs) && isName(cs[0], 'Indexed')
}
};
}

var decodeRequest;
if (image instanceof Jbig2Stream) {
decodeRequest = jbigImageRequest();
} else if (image instanceof JpxStream) {
decodeRequest = jpxImageRequest();
}

var decodePromise = this.handler.sendWithPromise('DecodeNativeImageStream', decodeRequest);
return decodePromise.then(function (data) {
if (data) {
var result = new Stream(data, 0, data.byteLength, image.dict);
var orig = image.stream;
orig.reset();
result.stream = orig;
return result;
} else {
return image;
}
});
}
};

WorkerNativeImageStreamDecoder.isSupported =
function WorkerNativeImageStreamDecoder_isSupported(image) {
return image instanceof Jbig2Stream || image instanceof JpxStream;
};

// Trying to minimize Date.now() usage and check every 100 time
var TIME_SLOT_DURATION_MS = 20;
var CHECK_TIME_EVERY = 100;
Expand Down Expand Up @@ -249,7 +318,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return;
}

PDFImage.buildImage(self.handler, self.xref, resources, image, inline).
var workerNativeImageStreamDecoder = null;
if (WorkerNativeImageStreamDecoder.isSupported(image)) {
workerNativeImageStreamDecoder = new WorkerNativeImageStreamDecoder(self.handler);
}

PDFImage.buildImage(self.handler, self.xref, resources, image, inline,
workerNativeImageStreamDecoder).
then(function(imageObj) {
var imgData = imageObj.createImageData(/* forceRGBA = */ false);
self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData],
Expand Down
13 changes: 8 additions & 5 deletions src/core/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ 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) {
function handleImageData(handler, xref, res, image, nativeImageStreamDecoder) {
if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) {
// For natively supported jpegs send them to the main thread for decoding.
var dict = image.dict;
Expand All @@ -37,6 +37,8 @@ var PDFImage = (function PDFImageClosure() {
var data = message.data;
return new Stream(data, 0, data.length, image.dict);
});
} else if (nativeImageStreamDecoder) {
return nativeImageStreamDecoder.decode(image);
} else {
return Promise.resolve(image);
}
Expand Down Expand Up @@ -152,22 +154,23 @@ var PDFImage = (function PDFImageClosure() {
* with a PDFImage when the image is ready to be used.
*/
PDFImage.buildImage = function PDFImage_buildImage(handler, xref,
res, image, inline) {
var imagePromise = handleImageData(handler, xref, res, image);
res, image, inline,
nativeImageStreamDecoder) {
var imagePromise = handleImageData(handler, xref, res, image, nativeImageStreamDecoder);
var smaskPromise;
var maskPromise;

var smask = image.dict.get('SMask');
var mask = image.dict.get('Mask');

if (smask) {
smaskPromise = handleImageData(handler, xref, res, smask);
smaskPromise = handleImageData(handler, xref, res, smask, nativeImageStreamDecoder);
maskPromise = Promise.resolve(null);
} else {
smaskPromise = Promise.resolve(null);
if (mask) {
if (isStream(mask)) {
maskPromise = handleImageData(handler, xref, res, mask);
maskPromise = handleImageData(handler, xref, res, mask, nativeImageStreamDecoder);
} else if (isArray(mask)) {
maskPromise = Promise.resolve(mask);
} else {
Expand Down
44 changes: 44 additions & 0 deletions src/display/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,23 @@ var WorkerTransport = (function WorkerTransportClosure() {
img.src = imageUrl;
});
});

messageHandler.on('DecodeNativeImageStream', function decodeNativeImageStream(data) {
if (NativeImageStreamDecoder.enabled) {
return NativeImageStreamDecoder.messageHandler.sendWithPromise(data.action, data.data)
.then(
function (imageData) {
return imageData;
},
function (error) {
warn('Native image stream decoder failed with error: ' + error);
return false;
}
);
} else {
return false;
}
}, this);
},

fetchDocument: function WorkerTransport_fetchDocument(loadingTask, source) {
Expand Down Expand Up @@ -1652,3 +1669,30 @@ var InternalRenderTask = (function InternalRenderTaskClosure() {

return InternalRenderTask;
})();

var NativeImageStreamDecoder = (function NativeImageStreamDecoderClosure() {
var result = {
init: function(module) {
info('Initializing native image stream decoder message handler');
result.enabled = true;
var messageHandler =
new MessageHandler(
"NativeImageStreamDecoder",
module,
true
);
messageHandler.postMessageTransfers = false;
messageHandler.on('Error', function (message) {
console.error("Image stream decoder returned error: " + message);
});
result.messageHandler = messageHandler;
},
disable: function() {
result.enabled = false;
result.messageHandler = null;
warn('Disabling native image stream decoder');
}
};
return result;
})();

10 changes: 8 additions & 2 deletions src/shared/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ PDFJS.createObjectURL = (function createObjectURLClosure() {
};
})();

function MessageHandler(name, comObj) {
function MessageHandler(name, comObj, useEventListener) {
this.name = name;
this.comObj = comObj;
this.callbackIndex = 1;
Expand All @@ -1472,7 +1472,7 @@ function MessageHandler(name, comObj) {
UnsupportedManager.notify(data);
}];

comObj.onmessage = function messageHandlerComObjOnMessage(event) {
var _onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
var data = event.data;
if (data.isReply) {
var callbackId = data.callbackId;
Expand Down Expand Up @@ -1512,6 +1512,12 @@ function MessageHandler(name, comObj) {
error('Unknown action from worker: ' + data.action);
}
};

if (useEventListener) {
comObj.addEventListener('message', _onComObjOnMessage);
} else {
comObj.onmessage = _onComObjOnMessage;
}
}

MessageHandler.prototype = {
Expand Down
1 change: 1 addition & 0 deletions web/viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
</head>

<body tabindex="1" class="loadingInProgress">
<div id="imageStreamDecoderListener"></div>
<div id="outerContainer">

<div id="sidebarContainer">
Expand Down
35 changes: 35 additions & 0 deletions web/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
OverlayManager, PDFFindController, PDFFindBar, getVisibleElements,
watchScroll, PDFViewer, PDFRenderingQueue, PresentationModeState,
RenderingStates, DEFAULT_SCALE, UNKNOWN_SCALE,
NativeImageStreamDecoder,
IGNORE_CURRENT_POSITION_ON_ZOOM: true */

'use strict';
Expand Down Expand Up @@ -1463,6 +1464,40 @@ function webViewerInitialized() {
//document.getElementById('secondaryOpenFile').setAttribute('hidden', 'true');
//#endif

var imageStreamDecoderListener =
navigator.mimeTypes['application/x-pnacl'] && document.getElementById('imageStreamDecoderListener');

if (imageStreamDecoderListener) {
var moduleEl = document.createElement('embed');
moduleEl.setAttribute('width', 0);
moduleEl.setAttribute('height', 0);
moduleEl.setAttribute('path', 'image_stream_decoder');
moduleEl.setAttribute('src', 'image_stream_decoder/image_stream_decoder.nmf');
moduleEl.setAttribute('type', 'application/x-pnacl');

var initImageStreamDecoder = function() {
console.info('Native image stream decoder module loaded successfully.');
NativeImageStreamDecoder.init(moduleEl);
};
var disableImageStreamDecoder = function(which) {
return function() {
console.error(
'Image stream decoder has stopped (' + which +
'). Last error was ' + moduleEl.lastError + '.'
);
NativeImageStreamDecoder.disable();
}
};

var listenerEl = imageStreamDecoderListener;
listenerEl.addEventListener('load', initImageStreamDecoder, true);
listenerEl.addEventListener('error', disableImageStreamDecoder('error'), true);
listenerEl.addEventListener('crash', disableImageStreamDecoder('crash'), true);
listenerEl.appendChild(moduleEl);

document.body.appendChild(listenerEl);
}

//#if !(FIREFOX || MOZCENTRAL)
var locale = PDFJS.locale || navigator.language;
//#endif
Expand Down

0 comments on commit f0046e3

Please sign in to comment.