From 30bee9fe0c4f41ca07e11b440d64102f5921e477 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 13 Apr 2017 13:16:35 -0500 Subject: [PATCH] Moves Uint32ArrayView and hasCanvasTypedArrays into compatibility.js. --- src/core/murmurhash3.js | 28 ++----------- src/display/canvas.js | 14 +------ src/display/dom_utils.js | 17 -------- src/display/global.js | 8 +--- src/shared/compatibility.js | 74 ++++++++++++++++++++++++++++++++++- src/shared/util.js | 50 ++--------------------- test/unit/murmurhash3_spec.js | 2 +- 7 files changed, 83 insertions(+), 110 deletions(-) diff --git a/src/core/murmurhash3.js b/src/core/murmurhash3.js index ccb4c9c1e..c6a343e44 100644 --- a/src/core/murmurhash3.js +++ b/src/core/murmurhash3.js @@ -29,8 +29,6 @@ } }(this, function (exports, sharedUtil) { -var Uint32ArrayView = sharedUtil.Uint32ArrayView; - var MurmurHash3_64 = (function MurmurHash3_64Closure(seed) { // Workaround for missing math precision in JS. var MASK_HIGH = 0xffff0000; @@ -42,21 +40,8 @@ var MurmurHash3_64 = (function MurmurHash3_64Closure(seed) { this.h2 = seed ? seed & 0xffffffff : SEED; } - var alwaysUseUint32ArrayView = false; - if (typeof PDFJSDev === 'undefined' || - !PDFJSDev.test('FIREFOX || MOZCENTRAL || CHROME')) { - // old webkits have issues with non-aligned arrays - try { - // eslint-disable-next-line no-new - new Uint32Array(new Uint8Array(5).buffer, 0, 1); - } catch (e) { - alwaysUseUint32ArrayView = true; - } - } - MurmurHash3_64.prototype = { update: function MurmurHash3_64_update(input) { - var useUint32ArrayView = alwaysUseUint32ArrayView; var i; if (typeof input === 'string') { var data = new Uint8Array(input.length * 2); @@ -70,14 +55,9 @@ var MurmurHash3_64 = (function MurmurHash3_64Closure(seed) { data[length++] = code & 0xff; } } - } else if (input instanceof Uint8Array) { + } else if (typeof input === 'object' && ('byteLength' in input)) { data = input; - length = data.length; - } else if (typeof input === 'object' && ('length' in input)) { - // processing regular arrays as well, e.g. for IE9 - data = input; - length = data.length; - useUint32ArrayView = true; + length = data.byteLength; } else { throw new Error('Wrong data format in MurmurHash3_64_update. ' + 'Input must be a string or array.'); @@ -86,9 +66,7 @@ var MurmurHash3_64 = (function MurmurHash3_64Closure(seed) { var blockCounts = length >> 2; var tailLength = length - blockCounts * 4; // we don't care about endianness here - var dataUint32 = useUint32ArrayView ? - new Uint32ArrayView(data, blockCounts) : - new Uint32Array(data.buffer, 0, blockCounts); + var dataUint32 = new Uint32Array(data.buffer, 0, blockCounts); var k1 = 0; var k2 = 0; var h1 = this.h1; diff --git a/src/display/canvas.js b/src/display/canvas.js index 0f9b3eb75..a2b4a3f63 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -36,7 +36,6 @@ var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX; var ImageKind = sharedUtil.ImageKind; var OPS = sharedUtil.OPS; var TextRenderingMode = sharedUtil.TextRenderingMode; -var Uint32ArrayView = sharedUtil.Uint32ArrayView; var Util = sharedUtil.Util; var assert = sharedUtil.assert; var info = sharedUtil.info; @@ -49,7 +48,6 @@ var warn = sharedUtil.warn; var TilingPattern = displayPatternHelper.TilingPattern; var getShadingPatternFromIR = displayPatternHelper.getShadingPatternFromIR; var WebGLUtils = displayWebGL.WebGLUtils; -var hasCanvasTypedArrays = displayDOMUtils.hasCanvasTypedArrays; // contexts store most of the state we need natively. // However, PDF needs a bit more state, which we store here. @@ -68,12 +66,6 @@ var MAX_SIZE_TO_COMPILE = 1000; var FULL_CHUNK_HEIGHT = 16; -var HasCanvasTypedArraysCached = { - get value() { - return shadow(HasCanvasTypedArraysCached, 'value', hasCanvasTypedArrays()); - } -}; - var IsLittleEndianCached = { get value() { return shadow(IsLittleEndianCached, 'value', isLittleEndian()); @@ -510,13 +502,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { if (imgData.kind === ImageKind.GRAYSCALE_1BPP) { // Grayscale, 1 bit per pixel (i.e. black-and-white). var srcLength = src.byteLength; - var dest32 = HasCanvasTypedArraysCached.value ? - new Uint32Array(dest.buffer) : new Uint32ArrayView(dest); + var dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2); var dest32DataLength = dest32.length; var fullSrcDiff = (width + 7) >> 3; var white = 0xFFFFFFFF; - var black = (IsLittleEndianCached.value || - !HasCanvasTypedArraysCached.value) ? 0xFF000000 : 0x000000FF; + var black = IsLittleEndianCached.value ? 0xFF000000 : 0x000000FF; for (i = 0; i < totalChunks; i++) { thisChunkHeight = (i < fullChunks) ? FULL_CHUNK_HEIGHT : partialChunkHeight; diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index 8812e6f19..d8d59df9a 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -189,22 +189,6 @@ var RenderingCancelledException = (function RenderingCancelledException() { return RenderingCancelledException; })(); -var hasCanvasTypedArrays; -if (typeof PDFJSDev === 'undefined' || - !PDFJSDev.test('FIREFOX || MOZCENTRAL || CHROME')) { - hasCanvasTypedArrays = function hasCanvasTypedArrays() { - var canvas = document.createElement('canvas'); - canvas.width = canvas.height = 1; - var ctx = canvas.getContext('2d'); - var imageData = ctx.createImageData(1, 1); - return (typeof imageData.data.buffer !== 'undefined'); - }; -} else { - hasCanvasTypedArrays = function () { - return true; - }; -} - var LinkTarget = { NONE: 0, // Default value. SELF: 1, @@ -354,7 +338,6 @@ exports.isValidUrl = isValidUrl; exports.getFilenameFromUrl = getFilenameFromUrl; exports.LinkTarget = LinkTarget; exports.RenderingCancelledException = RenderingCancelledException; -exports.hasCanvasTypedArrays = hasCanvasTypedArrays; exports.getDefaultSetting = getDefaultSetting; exports.DEFAULT_LINK_REL = DEFAULT_LINK_REL; exports.DOMCanvasFactory = DOMCanvasFactory; diff --git a/src/display/global.js b/src/display/global.js index c4e5f653e..2393c8826 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -296,13 +296,7 @@ PDFJS.PDFDataRangeTransport = displayAPI.PDFDataRangeTransport; PDFJS.PDFWorker = displayAPI.PDFWorker; - Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', { - configurable: true, - get: function PDFJS_hasCanvasTypedArrays() { - var value = displayDOMUtils.hasCanvasTypedArrays(); - return sharedUtil.shadow(PDFJS, 'hasCanvasTypedArrays', value); - } - }); + PDFJS.hasCanvasTypedArrays = true; // compatibility.js ensures this invariant PDFJS.CustomStyle = displayDOMUtils.CustomStyle; PDFJS.LinkTarget = LinkTarget; PDFJS.addLinkAttributes = displayDOMUtils.addLinkAttributes; diff --git a/src/shared/compatibility.js b/src/shared/compatibility.js index c791ab3e5..e01b95ce6 100644 --- a/src/shared/compatibility.js +++ b/src/shared/compatibility.js @@ -94,6 +94,41 @@ PDFJS.compatibilityChecked = true; } } + function Uint32ArrayView(buffer, length) { + this.buffer = buffer; + this.byteLength = buffer.length; + this.length = length; + ensureUint32ArrayViewProps(this.length); + } + Uint32ArrayView.prototype = Object.create(null); + + var uint32ArrayViewSetters = 0; + function createUint32ArrayProp(index) { + return { + get: function () { + var buffer = this.buffer, offset = index << 2; + return (buffer[offset] | (buffer[offset + 1] << 8) | + (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0; + }, + set: function (value) { + var buffer = this.buffer, offset = index << 2; + buffer[offset] = value & 255; + buffer[offset + 1] = (value >> 8) & 255; + buffer[offset + 2] = (value >> 16) & 255; + buffer[offset + 3] = (value >>> 24) & 255; + } + }; + } + + function ensureUint32ArrayViewProps(length) { + while (uint32ArrayViewSetters < length) { + Object.defineProperty(Uint32ArrayView.prototype, + uint32ArrayViewSetters, + createUint32ArrayProp(uint32ArrayViewSetters)); + uint32ArrayViewSetters++; + } + } + function TypedArray(arg1) { var result, i, n; if (typeof arg1 === 'number') { @@ -126,11 +161,48 @@ PDFJS.compatibilityChecked = true; // we don't need support for set, byteLength for 32-bit array // so we can use the TypedArray as well - globalScope.Uint32Array = TypedArray; globalScope.Int32Array = TypedArray; globalScope.Uint16Array = TypedArray; globalScope.Float32Array = TypedArray; globalScope.Float64Array = TypedArray; + + globalScope.Uint32Array = function () { + if (arguments.length === 3) { + // Building view for buffer, offset, and length + if (arguments[1] !== 0) { + throw new Error('offset !== 0 is not supported'); + } + return new Uint32ArrayView(arguments[0], arguments[2]); + } + return TypedArray.apply(this, arguments); + }; +})(); + +// window.CanvasPixelArray.buffer/.byteLength +// Support: IE9 +(function canvasPixelArrayBuffer() { + if (!hasDOM || !window.CanvasPixelArray) { + return; + } + var cpaProto = window.CanvasPixelArray.prototype; + if ('buffer' in cpaProto) { + return; + } + // Trying to fake CanvasPixelArray as Uint8ClampedArray. + Object.defineProperty(cpaProto, 'buffer', { + get: function () { + return this; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(cpaProto, 'byteLength', { + get: function () { + return this.length; + }, + enumerable: false, + configurable: true + }); })(); // URL = URL || webkitURL diff --git a/src/shared/util.js b/src/shared/util.js index cdfd5980c..dc8857472 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -618,10 +618,10 @@ function readUint32(data, offset) { // Lazy test the endianness of the platform // NOTE: This will be 'true' for simulated TypedArrays function isLittleEndian() { - var buffer8 = new Uint8Array(2); + var buffer8 = new Uint8Array(4); buffer8[0] = 1; - var buffer16 = new Uint16Array(buffer8.buffer); - return (buffer16[0] === 1); + var view32 = new Uint32Array(buffer8.buffer, 0, 1); + return (view32[0] === 1); } // Checks if it's possible to eval JS expressions. @@ -634,50 +634,6 @@ function isEvalSupported() { } } -if (typeof PDFJSDev === 'undefined' || - !PDFJSDev.test('FIREFOX || MOZCENTRAL || CHROME')) { - var Uint32ArrayView = (function Uint32ArrayViewClosure() { - function Uint32ArrayView(buffer, length) { - this.buffer = buffer; - this.byteLength = buffer.length; - this.length = length === undefined ? (this.byteLength >> 2) : length; - ensureUint32ArrayViewProps(this.length); - } - Uint32ArrayView.prototype = Object.create(null); - - var uint32ArrayViewSetters = 0; - function createUint32ArrayProp(index) { - return { - get: function () { - var buffer = this.buffer, offset = index << 2; - return (buffer[offset] | (buffer[offset + 1] << 8) | - (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0; - }, - set: function (value) { - var buffer = this.buffer, offset = index << 2; - buffer[offset] = value & 255; - buffer[offset + 1] = (value >> 8) & 255; - buffer[offset + 2] = (value >> 16) & 255; - buffer[offset + 3] = (value >>> 24) & 255; - } - }; - } - - function ensureUint32ArrayViewProps(length) { - while (uint32ArrayViewSetters < length) { - Object.defineProperty(Uint32ArrayView.prototype, - uint32ArrayViewSetters, - createUint32ArrayProp(uint32ArrayViewSetters)); - uint32ArrayViewSetters++; - } - } - - return Uint32ArrayView; - })(); - - exports.Uint32ArrayView = Uint32ArrayView; -} - var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; var Util = (function UtilClosure() { diff --git a/test/unit/murmurhash3_spec.js b/test/unit/murmurhash3_spec.js index 4c089d94d..7fc55de9a 100644 --- a/test/unit/murmurhash3_spec.js +++ b/test/unit/murmurhash3_spec.js @@ -53,7 +53,7 @@ describe('MurmurHash3_64', function() { }); it('correctly generates a hash from a Uint32Array', function() { var hash = new MurmurHash3_64(); - hash.update(new Uint32Array(sourceCharCodes)); + hash.update(new Uint32Array(new Uint8Array(sourceCharCodes).buffer)); expect(hash.hexdigest()).toEqual(hexDigestExpected); });