diff --git a/src/core/colorspace.js b/src/core/colorspace.js index 3ac1b9d71..e51465cd7 100644 --- a/src/core/colorspace.js +++ b/src/core/colorspace.js @@ -18,194 +18,198 @@ import { } from '../shared/util'; import { isDict, isName, isStream } from './primitives'; -var ColorSpace = (function ColorSpaceClosure() { +/** + * Resizes an RGB image with 3 components. + * @param {TypedArray} src - The source buffer. + * @param {TypedArray} dest - The destination buffer. + * @param {Number} w1 - Original width. + * @param {Number} h1 - Original height. + * @param {Number} w2 - New width. + * @param {Number} h2 - New height. + * @param {Number} alpha01 - Size reserved for the alpha channel. + */ +function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) { + var COMPONENTS = 3; + alpha01 = alpha01 !== 1 ? 0 : alpha01; + var xRatio = w1 / w2; + var yRatio = h1 / h2; + var newIndex = 0, oldIndex; + var xScaled = new Uint16Array(w2); + var w1Scanline = w1 * COMPONENTS; + + for (let i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio) * COMPONENTS; + } + for (let i = 0; i < h2; i++) { + const py = Math.floor(i * yRatio) * w1Scanline; + for (let j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + dest[newIndex++] = src[oldIndex++]; + dest[newIndex++] = src[oldIndex++]; + dest[newIndex++] = src[oldIndex++]; + newIndex += alpha01; + } + } +} + +class ColorSpace { + constructor(name, numComps) { + if (this.constructor === ColorSpace) { + unreachable('Cannot initialize ColorSpace.'); + } + this.name = name; + this.numComps = numComps; + } + /** - * Resizes an RGB image with 3 components. - * @param {TypedArray} src - The source buffer. - * @param {TypedArray} dest - The destination buffer. - * @param {Number} w1 - Original width. - * @param {Number} h1 - Original height. - * @param {Number} w2 - New width. - * @param {Number} h2 - New height. - * @param {Number} alpha01 - Size reserved for the alpha channel. + * Converts the color value to the RGB color. The color components are + * located in the src array starting from the srcOffset. Returns the array + * of the rgb components, each value ranging from [0,255]. */ - function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) { - var COMPONENTS = 3; - alpha01 = alpha01 !== 1 ? 0 : alpha01; - var xRatio = w1 / w2; - var yRatio = h1 / h2; - var i, j, py, newIndex = 0, oldIndex; - var xScaled = new Uint16Array(w2); - var w1Scanline = w1 * COMPONENTS; - - for (i = 0; i < w2; i++) { - xScaled[i] = Math.floor(i * xRatio) * COMPONENTS; - } - for (i = 0; i < h2; i++) { - py = Math.floor(i * yRatio) * w1Scanline; - for (j = 0; j < w2; j++) { - oldIndex = py + xScaled[j]; - dest[newIndex++] = src[oldIndex++]; - dest[newIndex++] = src[oldIndex++]; - dest[newIndex++] = src[oldIndex++]; - newIndex += alpha01; - } - } + getRgb(src, srcOffset) { + let rgb = new Uint8ClampedArray(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; } - // Constructor should define this.numComps, this.name - function ColorSpace() { - unreachable('should not call ColorSpace constructor'); + /** + * Converts the color value to the RGB color, similar to the getRgb method. + * The result placed into the dest array starting from the destOffset. + */ + getRgbItem(src, srcOffset, dest, destOffset) { + unreachable('Should not call ColorSpace.getRgbItem'); } - ColorSpace.prototype = { - /** - * Converts the color value to the RGB color. The color components are - * located in the src array starting from the srcOffset. Returns the array - * of the rgb components, each value ranging from [0,255]. - */ - getRgb(src, srcOffset) { - let rgb = new Uint8ClampedArray(3); - this.getRgbItem(src, srcOffset, rgb, 0); - return rgb; - }, - /** - * Converts the color value to the RGB color, similar to the getRgb method. - * The result placed into the dest array starting from the destOffset. - */ - getRgbItem(src, srcOffset, dest, destOffset) { - unreachable('Should not call ColorSpace.getRgbItem'); - }, - /** - * Converts the specified number of the color values to the RGB colors. - * The colors are located in the src array starting from the srcOffset. - * The result is placed into the dest array starting from the destOffset. - * The src array items shall be in [0,2^bits) range, the dest array items - * will be in [0,255] range. alpha01 indicates how many alpha components - * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA - * array). - */ - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - unreachable('Should not call ColorSpace.getRgbBuffer'); - }, - /** - * Determines the number of bytes required to store the result of the - * conversion done by the getRgbBuffer method. As in getRgbBuffer, - * |alpha01| is either 0 (RGB output) or 1 (RGBA output). - */ - getOutputLength(inputLength, alpha01) { - unreachable('Should not call ColorSpace.getOutputLength'); - }, - /** - * Returns true if source data will be equal the result/output data. - */ - isPassthrough(bits) { - return false; - }, - /** - * Fills in the RGB colors in the destination buffer. alpha01 indicates - * how many alpha components there are in the dest array; it will be either - * 0 (RGB array) or 1 (RGBA array). - */ - fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, - bpc, comps, alpha01) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'ColorSpace.fillRgb: Unsupported "dest" type.'); + /** + * Converts the specified number of the color values to the RGB colors. + * The colors are located in the src array starting from the srcOffset. + * The result is placed into the dest array starting from the destOffset. + * The src array items shall be in [0,2^bits) range, the dest array items + * will be in [0,255] range. alpha01 indicates how many alpha components + * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA + * array). + */ + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + unreachable('Should not call ColorSpace.getRgbBuffer'); + } + + /** + * Determines the number of bytes required to store the result of the + * conversion done by the getRgbBuffer method. As in getRgbBuffer, + * |alpha01| is either 0 (RGB output) or 1 (RGBA output). + */ + getOutputLength(inputLength, alpha01) { + unreachable('Should not call ColorSpace.getOutputLength'); + } + + /** + * Returns true if source data will be equal the result/output data. + */ + isPassthrough(bits) { + return false; + } + + /** + * Fills in the RGB colors in the destination buffer. alpha01 indicates + * how many alpha components there are in the dest array; it will be either + * 0 (RGB array) or 1 (RGBA array). + */ + fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, + bpc, comps, alpha01) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'ColorSpace.fillRgb: Unsupported "dest" type.'); + } + var count = originalWidth * originalHeight; + var rgbBuf = null; + var numComponentColors = 1 << bpc; + var needsResizing = originalHeight !== height || originalWidth !== width; + + if (this.isPassthrough(bpc)) { + rgbBuf = comps; + } else if (this.numComps === 1 && count > numComponentColors && + this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { + // Optimization: create a color map when there is just one component and + // we are converting more colors than the size of the color map. We + // don't build the map if the colorspace is gray or rgb since those + // methods are faster than building a map. This mainly offers big speed + // ups for indexed and alternate colorspaces. + // + // TODO it may be worth while to cache the color map. While running + // testing I never hit a cache so I will leave that out for now (perhaps + // we are reparsing colorspaces too much?). + var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : + new Uint16Array(numComponentColors); + for (let i = 0; i < numComponentColors; i++) { + allColors[i] = i; } - var count = originalWidth * originalHeight; - var rgbBuf = null; - var numComponentColors = 1 << bpc; - var needsResizing = originalHeight !== height || originalWidth !== width; - var i, ii; + var colorMap = new Uint8ClampedArray(numComponentColors * 3); + this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, + /* alpha01 = */ 0); - if (this.isPassthrough(bpc)) { - rgbBuf = comps; - } else if (this.numComps === 1 && count > numComponentColors && - this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { - // Optimization: create a color map when there is just one component and - // we are converting more colors than the size of the color map. We - // don't build the map if the colorspace is gray or rgb since those - // methods are faster than building a map. This mainly offers big speed - // ups for indexed and alternate colorspaces. - // - // TODO it may be worth while to cache the color map. While running - // testing I never hit a cache so I will leave that out for now (perhaps - // we are reparsing colorspaces too much?). - var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : - new Uint16Array(numComponentColors); - var key; - for (i = 0; i < numComponentColors; i++) { - allColors[i] = i; - } - var colorMap = new Uint8ClampedArray(numComponentColors * 3); - this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, - /* alpha01 = */ 0); - - var destPos, rgbPos; - if (!needsResizing) { - // Fill in the RGB values directly into |dest|. - destPos = 0; - for (i = 0; i < count; ++i) { - key = comps[i] * 3; - dest[destPos++] = colorMap[key]; - dest[destPos++] = colorMap[key + 1]; - dest[destPos++] = colorMap[key + 2]; - destPos += alpha01; - } - } else { - rgbBuf = new Uint8Array(count * 3); - rgbPos = 0; - for (i = 0; i < count; ++i) { - key = comps[i] * 3; - rgbBuf[rgbPos++] = colorMap[key]; - rgbBuf[rgbPos++] = colorMap[key + 1]; - rgbBuf[rgbPos++] = colorMap[key + 2]; - } + if (!needsResizing) { + // Fill in the RGB values directly into |dest|. + let destPos = 0; + for (let i = 0; i < count; ++i) { + const key = comps[i] * 3; + dest[destPos++] = colorMap[key]; + dest[destPos++] = colorMap[key + 1]; + dest[destPos++] = colorMap[key + 2]; + destPos += alpha01; } } else { - if (!needsResizing) { - // Fill in the RGB values directly into |dest|. - this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, - alpha01); - } else { - rgbBuf = new Uint8ClampedArray(count * 3); - this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, - /* alpha01 = */ 0); + rgbBuf = new Uint8Array(count * 3); + let rgbPos = 0; + for (let i = 0; i < count; ++i) { + const key = comps[i] * 3; + rgbBuf[rgbPos++] = colorMap[key]; + rgbBuf[rgbPos++] = colorMap[key + 1]; + rgbBuf[rgbPos++] = colorMap[key + 2]; } } + } else { + if (!needsResizing) { + // Fill in the RGB values directly into |dest|. + this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, + alpha01); + } else { + rgbBuf = new Uint8ClampedArray(count * 3); + this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, /* alpha01 = */ 0); + } + } - if (rgbBuf) { - if (needsResizing) { - resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, - width, height, alpha01); - } else { - rgbPos = 0; - destPos = 0; - for (i = 0, ii = width * actualHeight; i < ii; i++) { - dest[destPos++] = rgbBuf[rgbPos++]; - dest[destPos++] = rgbBuf[rgbPos++]; - dest[destPos++] = rgbBuf[rgbPos++]; - destPos += alpha01; - } + if (rgbBuf) { + if (needsResizing) { + resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, + width, height, alpha01); + } else { + let destPos = 0, rgbPos = 0; + for (let i = 0, ii = width * actualHeight; i < ii; i++) { + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + destPos += alpha01; } } - }, - /** - * True if the colorspace has components in the default range of [0, 1]. - * This should be true for all colorspaces except for lab color spaces - * which are [0,100], [-128, 127], [-128, 127]. - */ - usesZeroToOneRange: true, - }; + } + } - ColorSpace.parse = function(cs, xref, res, pdfFunctionFactory) { - let IR = ColorSpace.parseToIR(cs, xref, res, pdfFunctionFactory); - return ColorSpace.fromIR(IR); - }; + /** + * True if the colorspace has components in the default range of [0, 1]. + * This should be true for all colorspaces except for lab color spaces + * which are [0,100], [-128, 127], [-128, 127]. + */ + get usesZeroToOneRange() { + return shadow(this, 'usesZeroToOneRange', true); + } - ColorSpace.fromIR = function(IR) { + static parse(cs, xref, res, pdfFunctionFactory) { + let IR = this.parseToIR(cs, xref, res, pdfFunctionFactory); + return this.fromIR(IR); + } + + static fromIR(IR) { var name = Array.isArray(IR) ? IR[0] : IR; var whitePoint, blackPoint, gamma; @@ -230,21 +234,19 @@ var ColorSpace = (function ColorSpaceClosure() { case 'PatternCS': var basePatternCS = IR[1]; if (basePatternCS) { - basePatternCS = ColorSpace.fromIR(basePatternCS); + basePatternCS = this.fromIR(basePatternCS); } return new PatternCS(basePatternCS); case 'IndexedCS': var baseIndexedCS = IR[1]; var hiVal = IR[2]; var lookup = IR[3]; - return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), - hiVal, lookup); + return new IndexedCS(this.fromIR(baseIndexedCS), hiVal, lookup); case 'AlternateCS': var numComps = IR[1]; var alt = IR[2]; var tintFn = IR[3]; - return new AlternateCS(numComps, ColorSpace.fromIR(alt), - tintFn); + return new AlternateCS(numComps, this.fromIR(alt), tintFn); case 'LabCS': whitePoint = IR[1]; blackPoint = IR[2]; @@ -253,9 +255,9 @@ var ColorSpace = (function ColorSpaceClosure() { default: throw new FormatError(`Unknown colorspace name: ${name}`); } - }; + } - ColorSpace.parseToIR = function(cs, xref, res = null, pdfFunctionFactory) { + static parseToIR(cs, xref, res = null, pdfFunctionFactory) { cs = xref.fetchIfRef(cs); if (isName(cs)) { switch (cs.name) { @@ -277,8 +279,7 @@ var ColorSpace = (function ColorSpaceClosure() { let resCS = colorSpaces.get(cs.name); if (resCS) { if (isName(resCS)) { - return ColorSpace.parseToIR(resCS, xref, res, - pdfFunctionFactory); + return this.parseToIR(resCS, xref, res, pdfFunctionFactory); } cs = resCS; break; @@ -321,11 +322,10 @@ var ColorSpace = (function ColorSpaceClosure() { numComps = dict.get('N'); alt = dict.get('Alternate'); if (alt) { - var altIR = ColorSpace.parseToIR(alt, xref, res, - pdfFunctionFactory); + var altIR = this.parseToIR(alt, xref, res, pdfFunctionFactory); // Parse the /Alternate CS to ensure that the number of components // are correct, and also (indirectly) that it is not a PatternCS. - var altCS = ColorSpace.fromIR(altIR, pdfFunctionFactory); + var altCS = this.fromIR(altIR, pdfFunctionFactory); if (altCS.numComps === numComps) { return altIR; } @@ -342,14 +342,14 @@ var ColorSpace = (function ColorSpaceClosure() { case 'Pattern': var basePatternCS = cs[1] || null; if (basePatternCS) { - basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res, - pdfFunctionFactory); + basePatternCS = this.parseToIR(basePatternCS, xref, res, + pdfFunctionFactory); } return ['PatternCS', basePatternCS]; case 'Indexed': case 'I': - var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res, - pdfFunctionFactory); + var baseIndexedCS = this.parseToIR(cs[1], xref, res, + pdfFunctionFactory); var hiVal = xref.fetchIfRef(cs[2]) + 1; var lookup = xref.fetchIfRef(cs[3]); if (isStream(lookup)) { @@ -360,7 +360,7 @@ var ColorSpace = (function ColorSpaceClosure() { case 'DeviceN': var name = xref.fetchIfRef(cs[1]); numComps = Array.isArray(name) ? name.length : 1; - alt = ColorSpace.parseToIR(cs[2], xref, res, pdfFunctionFactory); + alt = this.parseToIR(cs[2], xref, res, pdfFunctionFactory); let tintFn = pdfFunctionFactory.create(xref.fetchIfRef(cs[3])); return ['AlternateCS', numComps, alt, tintFn]; case 'Lab': @@ -374,7 +374,8 @@ var ColorSpace = (function ColorSpaceClosure() { } } throw new FormatError(`unrecognized color space object: "${cs}"`); - }; + } + /** * Checks if a decode map matches the default decode map for a color space. * This handles the general decode maps where there are two values per @@ -384,7 +385,7 @@ var ColorSpace = (function ColorSpaceClosure() { * @param {Array} decode Decode map (usually from an image). * @param {Number} n Number of components the color space has. */ - ColorSpace.isDefaultDecode = function(decode, n) { + static isDefaultDecode(decode, n) { if (!Array.isArray(decode)) { return true; } @@ -399,22 +400,22 @@ var ColorSpace = (function ColorSpaceClosure() { } } return true; - }; + } - ColorSpace.singletons = { - get gray() { - return shadow(this, 'gray', new DeviceGrayCS()); - }, - get rgb() { - return shadow(this, 'rgb', new DeviceRgbCS()); - }, - get cmyk() { - return shadow(this, 'cmyk', new DeviceCmykCS()); - }, - }; - - return ColorSpace; -})(); + static get singletons() { + return shadow(this, 'singletons', { + get gray() { + return shadow(this, 'gray', new DeviceGrayCS()); + }, + get rgb() { + return shadow(this, 'rgb', new DeviceRgbCS()); + }, + get cmyk() { + return shadow(this, 'cmyk', new DeviceCmykCS()); + }, + }); + } +} /** * Alternate color space handles both Separation and DeviceN color spaces. A @@ -424,101 +425,91 @@ var ColorSpace = (function ColorSpaceClosure() { * * The default color is `new Float32Array(new Array(numComps).fill(1))`. */ -var AlternateCS = (function AlternateCSClosure() { - function AlternateCS(numComps, base, tintFn) { - this.name = 'Alternate'; - this.numComps = numComps; +class AlternateCS extends ColorSpace { + constructor(numComps, base, tintFn) { + super('Alternate', numComps); this.base = base; this.tintFn = tintFn; this.tmpBuf = new Float32Array(base.numComps); } - AlternateCS.prototype = { - getRgb: ColorSpace.prototype.getRgb, - getRgbItem(src, srcOffset, dest, destOffset) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'AlternateCS.getRgbItem: Unsupported "dest" type.'); - } - var tmpBuf = this.tmpBuf; - this.tintFn(src, srcOffset, tmpBuf, 0); - this.base.getRgbItem(tmpBuf, 0, dest, destOffset); - }, - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'AlternateCS.getRgbBuffer: Unsupported "dest" type.'); - } - var tintFn = this.tintFn; - var base = this.base; - var scale = 1 / ((1 << bits) - 1); - var baseNumComps = base.numComps; - var usesZeroToOneRange = base.usesZeroToOneRange; - var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && - alpha01 === 0; - var pos = isPassthrough ? destOffset : 0; - let baseBuf = isPassthrough ? - dest : new Uint8ClampedArray(baseNumComps * count); - var numComps = this.numComps; + getRgbItem(src, srcOffset, dest, destOffset) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'AlternateCS.getRgbItem: Unsupported "dest" type.'); + } + var tmpBuf = this.tmpBuf; + this.tintFn(src, srcOffset, tmpBuf, 0); + this.base.getRgbItem(tmpBuf, 0, dest, destOffset); + } - var scaled = new Float32Array(numComps); - var tinted = new Float32Array(baseNumComps); - var i, j; + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'AlternateCS.getRgbBuffer: Unsupported "dest" type.'); + } + var tintFn = this.tintFn; + var base = this.base; + var scale = 1 / ((1 << bits) - 1); + var baseNumComps = base.numComps; + var usesZeroToOneRange = base.usesZeroToOneRange; + var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && + alpha01 === 0; + var pos = isPassthrough ? destOffset : 0; + let baseBuf = isPassthrough ? + dest : new Uint8ClampedArray(baseNumComps * count); + var numComps = this.numComps; - for (i = 0; i < count; i++) { - for (j = 0; j < numComps; j++) { - scaled[j] = src[srcOffset++] * scale; - } - tintFn(scaled, 0, tinted, 0); - if (usesZeroToOneRange) { - for (j = 0; j < baseNumComps; j++) { - baseBuf[pos++] = tinted[j] * 255; - } - } else { - base.getRgbItem(tinted, 0, baseBuf, pos); - pos += baseNumComps; + var scaled = new Float32Array(numComps); + var tinted = new Float32Array(baseNumComps); + var i, j; + + for (i = 0; i < count; i++) { + for (j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; + } + tintFn(scaled, 0, tinted, 0); + if (usesZeroToOneRange) { + for (j = 0; j < baseNumComps; j++) { + baseBuf[pos++] = tinted[j] * 255; } + } else { + base.getRgbItem(tinted, 0, baseBuf, pos); + pos += baseNumComps; } + } - if (!isPassthrough) { - base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); - } - }, - getOutputLength(inputLength, alpha01) { - return this.base.getOutputLength(inputLength * - this.base.numComps / this.numComps, - alpha01); - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - fillRgb: ColorSpace.prototype.fillRgb, - isDefaultDecode(decodeMap) { - return ColorSpace.isDefaultDecode(decodeMap, this.numComps); - }, - usesZeroToOneRange: true, - }; + if (!isPassthrough) { + base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); + } + } - return AlternateCS; -})(); + getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * + this.base.numComps / this.numComps, + alpha01); + } -var PatternCS = (function PatternCSClosure() { - function PatternCS(baseCS) { - this.name = 'Pattern'; + isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + } +} + +class PatternCS extends ColorSpace { + constructor(baseCS) { + super('Pattern', null); this.base = baseCS; } - PatternCS.prototype = {}; - - return PatternCS; -})(); +} /** * The default color is `new Uint8Array([0])`. */ -var IndexedCS = (function IndexedCSClosure() { - function IndexedCS(base, highVal, lookup) { - this.name = 'Indexed'; - this.numComps = 1; +class IndexedCS extends ColorSpace { + constructor(base, highVal, lookup) { + super('Indexed', 1); this.base = base; this.highVal = highVal; @@ -541,157 +532,144 @@ var IndexedCS = (function IndexedCSClosure() { } } - IndexedCS.prototype = { - getRgb: ColorSpace.prototype.getRgb, - getRgbItem(src, srcOffset, dest, destOffset) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'IndexedCS.getRgbItem: Unsupported "dest" type.'); - } - var numComps = this.base.numComps; - var start = src[srcOffset] * numComps; - this.base.getRgbBuffer(this.lookup, start, 1, dest, destOffset, 8, 0); - }, - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'IndexedCS.getRgbBuffer: Unsupported "dest" type.'); - } - var base = this.base; - var numComps = base.numComps; - var outputDelta = base.getOutputLength(numComps, alpha01); - var lookup = this.lookup; + getRgbItem(src, srcOffset, dest, destOffset) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'IndexedCS.getRgbItem: Unsupported "dest" type.'); + } + var numComps = this.base.numComps; + var start = src[srcOffset] * numComps; + this.base.getRgbBuffer(this.lookup, start, 1, dest, destOffset, 8, 0); + } - for (var i = 0; i < count; ++i) { - var lookupPos = src[srcOffset++] * numComps; - base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); - destOffset += outputDelta; - } - }, - getOutputLength(inputLength, alpha01) { - return this.base.getOutputLength(inputLength * this.base.numComps, - alpha01); - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - fillRgb: ColorSpace.prototype.fillRgb, - isDefaultDecode(decodeMap) { - // indexed color maps shouldn't be changed - return true; - }, - usesZeroToOneRange: true, - }; - return IndexedCS; -})(); + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'IndexedCS.getRgbBuffer: Unsupported "dest" type.'); + } + var base = this.base; + var numComps = base.numComps; + var outputDelta = base.getOutputLength(numComps, alpha01); + var lookup = this.lookup; + + for (var i = 0; i < count; ++i) { + var lookupPos = src[srcOffset++] * numComps; + base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); + destOffset += outputDelta; + } + } + + getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps, alpha01); + } + + isDefaultDecode(decodeMap) { + return true; // Indexed color maps shouldn't be changed. + } +} /** * The default color is `new Float32Array([0])`. */ -var DeviceGrayCS = (function DeviceGrayCSClosure() { - function DeviceGrayCS() { - this.name = 'DeviceGray'; - this.numComps = 1; +class DeviceGrayCS extends ColorSpace { + constructor() { + super('DeviceGray', 1); } - DeviceGrayCS.prototype = { - getRgb: ColorSpace.prototype.getRgb, - getRgbItem(src, srcOffset, dest, destOffset) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'DeviceGrayCS.getRgbItem: Unsupported "dest" type.'); - } - let c = src[srcOffset] * 255; - dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; - }, - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'DeviceGrayCS.getRgbBuffer: Unsupported "dest" type.'); - } - var scale = 255 / ((1 << bits) - 1); - var j = srcOffset, q = destOffset; - for (var i = 0; i < count; ++i) { - let c = scale * src[j++]; - dest[q++] = c; - dest[q++] = c; - dest[q++] = c; - q += alpha01; - } - }, - getOutputLength(inputLength, alpha01) { - return inputLength * (3 + alpha01); - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - fillRgb: ColorSpace.prototype.fillRgb, - isDefaultDecode(decodeMap) { - return ColorSpace.isDefaultDecode(decodeMap, this.numComps); - }, - usesZeroToOneRange: true, - }; - return DeviceGrayCS; -})(); + getRgbItem(src, srcOffset, dest, destOffset) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'DeviceGrayCS.getRgbItem: Unsupported "dest" type.'); + } + let c = src[srcOffset] * 255; + dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; + } + + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'DeviceGrayCS.getRgbBuffer: Unsupported "dest" type.'); + } + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < count; ++i) { + let c = scale * src[j++]; + dest[q++] = c; + dest[q++] = c; + dest[q++] = c; + q += alpha01; + } + } + + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + } + + isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + } +} /** * The default color is `new Float32Array([0, 0, 0])`. */ -var DeviceRgbCS = (function DeviceRgbCSClosure() { - function DeviceRgbCS() { - this.name = 'DeviceRGB'; - this.numComps = 3; +class DeviceRgbCS extends ColorSpace { + constructor() { + super('DeviceRGB', 3); } - DeviceRgbCS.prototype = { - getRgb: ColorSpace.prototype.getRgb, - getRgbItem(src, srcOffset, dest, destOffset) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'DeviceRgbCS.getRgbItem: Unsupported "dest" type.'); - } - dest[destOffset] = src[srcOffset] * 255; - dest[destOffset + 1] = src[srcOffset + 1] * 255; - dest[destOffset + 2] = src[srcOffset + 2] * 255; - }, - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - if (typeof PDFJSDev === 'undefined' || - PDFJSDev.test('!PRODUCTION || TESTING')) { - assert(dest instanceof Uint8ClampedArray, - 'DeviceRgbCS.getRgbBuffer: Unsupported "dest" type.'); - } - if (bits === 8 && alpha01 === 0) { - dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); - return; - } - var scale = 255 / ((1 << bits) - 1); - var j = srcOffset, q = destOffset; - for (var i = 0; i < count; ++i) { - dest[q++] = scale * src[j++]; - dest[q++] = scale * src[j++]; - dest[q++] = scale * src[j++]; - q += alpha01; - } - }, - getOutputLength(inputLength, alpha01) { - return (inputLength * (3 + alpha01) / 3) | 0; - }, - isPassthrough(bits) { - return bits === 8; - }, - fillRgb: ColorSpace.prototype.fillRgb, - isDefaultDecode(decodeMap) { - return ColorSpace.isDefaultDecode(decodeMap, this.numComps); - }, - usesZeroToOneRange: true, - }; - return DeviceRgbCS; -})(); + + getRgbItem(src, srcOffset, dest, destOffset) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'DeviceRgbCS.getRgbItem: Unsupported "dest" type.'); + } + dest[destOffset] = src[srcOffset] * 255; + dest[destOffset + 1] = src[srcOffset + 1] * 255; + dest[destOffset + 2] = src[srcOffset + 2] * 255; + } + + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + if (typeof PDFJSDev === 'undefined' || + PDFJSDev.test('!PRODUCTION || TESTING')) { + assert(dest instanceof Uint8ClampedArray, + 'DeviceRgbCS.getRgbBuffer: Unsupported "dest" type.'); + } + if (bits === 8 && alpha01 === 0) { + dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); + return; + } + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < count; ++i) { + dest[q++] = scale * src[j++]; + dest[q++] = scale * src[j++]; + dest[q++] = scale * src[j++]; + q += alpha01; + } + } + + getOutputLength(inputLength, alpha01) { + return (inputLength * (3 + alpha01) / 3) | 0; + } + + isPassthrough(bits) { + return bits === 8; + } + + isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + } +} /** * The default color is `new Float32Array([0, 0, 0, 1])`. */ -var DeviceCmykCS = (function DeviceCmykCSClosure() { +const DeviceCmykCS = (function DeviceCmykCSClosure() { // The coefficients below was found using numerical analysis: the method of // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors, // where color_value is the tabular value from the table of sampled RGB colors @@ -734,12 +712,11 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() { k * (-22.33816807309886 * k - 180.12613974708367); } - function DeviceCmykCS() { - this.name = 'DeviceCMYK'; - this.numComps = 4; - } - DeviceCmykCS.prototype = { - getRgb: ColorSpace.prototype.getRgb, + class DeviceCmykCS extends ColorSpace { + constructor() { + super('DeviceCMYK', 4); + } + getRgbItem(src, srcOffset, dest, destOffset) { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('!PRODUCTION || TESTING')) { @@ -747,7 +724,8 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() { 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'); } convertToRgb(src, srcOffset, 1, dest, destOffset); - }, + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('!PRODUCTION || TESTING')) { @@ -760,18 +738,16 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() { srcOffset += 4; destOffset += 3 + alpha01; } - }, + } + getOutputLength(inputLength, alpha01) { return (inputLength / 4 * (3 + alpha01)) | 0; - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - fillRgb: ColorSpace.prototype.fillRgb, + } + isDefaultDecode(decodeMap) { return ColorSpace.isDefaultDecode(decodeMap, this.numComps); - }, - usesZeroToOneRange: true, - }; - + } + } return DeviceCmykCS; })(); @@ -780,52 +756,7 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() { * * The default color is `new Float32Array([0])`. */ -var CalGrayCS = (function CalGrayCSClosure() { - function CalGrayCS(whitePoint, blackPoint, gamma) { - this.name = 'CalGray'; - this.numComps = 1; - - if (!whitePoint) { - throw new FormatError( - 'WhitePoint missing - required for color space CalGray'); - } - blackPoint = blackPoint || [0, 0, 0]; - gamma = gamma || 1; - - // Translate arguments to spec variables. - this.XW = whitePoint[0]; - this.YW = whitePoint[1]; - this.ZW = whitePoint[2]; - - this.XB = blackPoint[0]; - this.YB = blackPoint[1]; - this.ZB = blackPoint[2]; - - this.G = gamma; - - // Validate variables as per spec. - if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { - throw new FormatError(`Invalid WhitePoint components for ${this.name}` + - ', no fallback available'); - } - - if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { - info('Invalid BlackPoint for ' + this.name + ', falling back to default'); - this.XB = this.YB = this.ZB = 0; - } - - if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { - warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB + - ', ZB: ' + this.ZB + ', only default values are supported.'); - } - - if (this.G < 1) { - info('Invalid Gamma: ' + this.G + ' for ' + this.name + - ', falling back to default'); - this.G = 1; - } - } - +const CalGrayCS = (function CalGrayCSClosure() { function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { // A represents a gray component of a calibrated gray space. // A <---> AG in the spec @@ -843,8 +774,51 @@ var CalGrayCS = (function CalGrayCSClosure() { dest[destOffset + 2] = val; } - CalGrayCS.prototype = { - getRgb: ColorSpace.prototype.getRgb, + class CalGrayCS extends ColorSpace { + constructor(whitePoint, blackPoint, gamma) { + super('CalGray', 1); + + if (!whitePoint) { + throw new FormatError( + 'WhitePoint missing - required for color space CalGray'); + } + blackPoint = blackPoint || [0, 0, 0]; + gamma = gamma || 1; + + // Translate arguments to spec variables. + this.XW = whitePoint[0]; + this.YW = whitePoint[1]; + this.ZW = whitePoint[2]; + + this.XB = blackPoint[0]; + this.YB = blackPoint[1]; + this.ZB = blackPoint[2]; + + this.G = gamma; + + // Validate variables as per spec. + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + throw new FormatError(`Invalid WhitePoint components for ${this.name}` + + ', no fallback available'); + } + + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info(`Invalid BlackPoint for ${this.name}, falling back to default.`); + this.XB = this.YB = this.ZB = 0; + } + + if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { + warn(`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ` + + `ZB: ${this.ZB}, only default values are supported.`); + } + + if (this.G < 1) { + info(`Invalid Gamma: ${this.G} for ${this.name}, ` + + 'falling back to default.'); + this.G = 1; + } + } + getRgbItem(src, srcOffset, dest, destOffset) { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('!PRODUCTION || TESTING')) { @@ -852,7 +826,8 @@ var CalGrayCS = (function CalGrayCSClosure() { 'CalGrayCS.getRgbItem: Unsupported "dest" type.'); } convertToRgb(this, src, srcOffset, dest, destOffset, 1); - }, + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('!PRODUCTION || TESTING')) { @@ -866,17 +841,16 @@ var CalGrayCS = (function CalGrayCSClosure() { srcOffset += 1; destOffset += 3 + alpha01; } - }, + } + getOutputLength(inputLength, alpha01) { return inputLength * (3 + alpha01); - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - fillRgb: ColorSpace.prototype.fillRgb, + } + isDefaultDecode(decodeMap) { return ColorSpace.isDefaultDecode(decodeMap, this.numComps); - }, - usesZeroToOneRange: true, - }; + } + } return CalGrayCS; })(); @@ -885,7 +859,7 @@ var CalGrayCS = (function CalGrayCSClosure() { * * The default color is `new Float32Array([0, 0, 0])`. */ -var CalRGBCS = (function CalRGBCSClosure() { +const CalRGBCS = (function CalRGBCSClosure() { // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these // matrices. var BRADFORD_SCALE_MATRIX = new Float32Array([ @@ -912,62 +886,6 @@ var CalRGBCS = (function CalRGBCSClosure() { var DECODE_L_CONSTANT = Math.pow(((8 + 16) / 116), 3) / 8.0; - function CalRGBCS(whitePoint, blackPoint, gamma, matrix) { - this.name = 'CalRGB'; - this.numComps = 3; - - if (!whitePoint) { - throw new FormatError( - 'WhitePoint missing - required for color space CalRGB'); - } - blackPoint = blackPoint || new Float32Array(3); - gamma = gamma || new Float32Array([1, 1, 1]); - matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]); - - // Translate arguments to spec variables. - var XW = whitePoint[0]; - var YW = whitePoint[1]; - var ZW = whitePoint[2]; - this.whitePoint = whitePoint; - - var XB = blackPoint[0]; - var YB = blackPoint[1]; - var ZB = blackPoint[2]; - this.blackPoint = blackPoint; - - this.GR = gamma[0]; - this.GG = gamma[1]; - this.GB = gamma[2]; - - this.MXA = matrix[0]; - this.MYA = matrix[1]; - this.MZA = matrix[2]; - this.MXB = matrix[3]; - this.MYB = matrix[4]; - this.MZB = matrix[5]; - this.MXC = matrix[6]; - this.MYC = matrix[7]; - this.MZC = matrix[8]; - - // Validate variables as per spec. - if (XW < 0 || ZW < 0 || YW !== 1) { - throw new FormatError(`Invalid WhitePoint components for ${this.name}` + - ', no fallback available'); - } - - if (XB < 0 || YB < 0 || ZB < 0) { - info('Invalid BlackPoint for ' + this.name + ' [' + XB + ', ' + YB + - ', ' + ZB + '], falling back to default'); - this.blackPoint = new Float32Array(3); - } - - if (this.GR < 0 || this.GG < 0 || this.GB < 0) { - info('Invalid Gamma [' + this.GR + ', ' + this.GG + ', ' + this.GB + - '] for ' + this.name + ', falling back to default'); - this.GR = this.GG = this.GB = 1; - } - } - function matrixProduct(a, b, result) { result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2]; @@ -995,7 +913,6 @@ var CalRGBCS = (function CalRGBCSClosure() { if (color <= 0.0031308) { return adjustToRange(0, 1, 12.92 * color); } - return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055); } @@ -1007,19 +924,16 @@ var CalRGBCS = (function CalRGBCSClosure() { if (L < 0) { return -decodeL(-L); } - if (L > 8.0) { return Math.pow(((L + 16) / 116), 3); } - return L * DECODE_L_CONSTANT; } function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) { // In case the blackPoint is already the default blackPoint then there is // no need to do compensation. - if (sourceBlackPoint[0] === 0 && - sourceBlackPoint[1] === 0 && + if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) { result[0] = XYZ_Flat[0]; result[1] = XYZ_Flat[1]; @@ -1131,8 +1045,62 @@ var CalRGBCS = (function CalRGBCSClosure() { dest[destOffset + 2] = sRGBTransferFunction(SRGB[2]) * 255; } - CalRGBCS.prototype = { - getRgb: ColorSpace.prototype.getRgb, + class CalRGBCS extends ColorSpace { + constructor(whitePoint, blackPoint, gamma, matrix) { + super('CalRGB', 3); + + if (!whitePoint) { + throw new FormatError( + 'WhitePoint missing - required for color space CalRGB'); + } + blackPoint = blackPoint || new Float32Array(3); + gamma = gamma || new Float32Array([1, 1, 1]); + matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]); + + // Translate arguments to spec variables. + var XW = whitePoint[0]; + var YW = whitePoint[1]; + var ZW = whitePoint[2]; + this.whitePoint = whitePoint; + + var XB = blackPoint[0]; + var YB = blackPoint[1]; + var ZB = blackPoint[2]; + this.blackPoint = blackPoint; + + this.GR = gamma[0]; + this.GG = gamma[1]; + this.GB = gamma[2]; + + this.MXA = matrix[0]; + this.MYA = matrix[1]; + this.MZA = matrix[2]; + this.MXB = matrix[3]; + this.MYB = matrix[4]; + this.MZB = matrix[5]; + this.MXC = matrix[6]; + this.MYC = matrix[7]; + this.MZC = matrix[8]; + + // Validate variables as per spec. + if (XW < 0 || ZW < 0 || YW !== 1) { + throw new FormatError(`Invalid WhitePoint components for ${this.name}` + + ', no fallback available'); + } + + if (XB < 0 || YB < 0 || ZB < 0) { + info(`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], ` + + 'falling back to default.'); + this.blackPoint = new Float32Array(3); + } + + if (this.GR < 0 || this.GG < 0 || this.GB < 0) { + info(`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ` + + `${this.name}, falling back to default.`); + this.GR = this.GG = this.GB = 1; + } + } + getRgbItem(src, srcOffset, dest, destOffset) { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('!PRODUCTION || TESTING')) { @@ -1140,7 +1108,8 @@ var CalRGBCS = (function CalRGBCSClosure() { 'CalRGBCS.getRgbItem: Unsupported "dest" type.'); } convertToRgb(this, src, srcOffset, dest, destOffset, 1); - }, + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('!PRODUCTION || TESTING')) { @@ -1154,17 +1123,16 @@ var CalRGBCS = (function CalRGBCSClosure() { srcOffset += 3; destOffset += 3 + alpha01; } - }, + } + getOutputLength(inputLength, alpha01) { return (inputLength * (3 + alpha01) / 3) | 0; - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - fillRgb: ColorSpace.prototype.fillRgb, + } + isDefaultDecode(decodeMap) { return ColorSpace.isDefaultDecode(decodeMap, this.numComps); - }, - usesZeroToOneRange: true, - }; + } + } return CalRGBCS; })(); @@ -1173,53 +1141,7 @@ var CalRGBCS = (function CalRGBCSClosure() { * * The default color is `new Float32Array([0, 0, 0])`. */ -var LabCS = (function LabCSClosure() { - function LabCS(whitePoint, blackPoint, range) { - this.name = 'Lab'; - this.numComps = 3; - - if (!whitePoint) { - throw new FormatError( - 'WhitePoint missing - required for color space Lab'); - } - blackPoint = blackPoint || [0, 0, 0]; - range = range || [-100, 100, -100, 100]; - - // Translate args to spec variables - this.XW = whitePoint[0]; - this.YW = whitePoint[1]; - this.ZW = whitePoint[2]; - this.amin = range[0]; - this.amax = range[1]; - this.bmin = range[2]; - this.bmax = range[3]; - - // These are here just for completeness - the spec doesn't offer any - // formulas that use BlackPoint in Lab - this.XB = blackPoint[0]; - this.YB = blackPoint[1]; - this.ZB = blackPoint[2]; - - // Validate vars as per spec - if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { - throw new FormatError( - 'Invalid WhitePoint components, no fallback available'); - } - - if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { - info('Invalid BlackPoint, falling back to default'); - this.XB = this.YB = this.ZB = 0; - } - - if (this.amin > this.amax || this.bmin > this.bmax) { - info('Invalid Range, falling back to defaults'); - this.amin = -100; - this.amax = 100; - this.bmin = -100; - this.bmax = 100; - } - } - +const LabCS = (function LabCSClosure() { // Function g(x) from spec function fn_g(x) { var result; @@ -1285,8 +1207,52 @@ var LabCS = (function LabCSClosure() { dest[destOffset + 2] = Math.sqrt(b) * 255; } - LabCS.prototype = { - getRgb: ColorSpace.prototype.getRgb, + class LabCS extends ColorSpace { + constructor(whitePoint, blackPoint, range) { + super('Lab', 3); + + if (!whitePoint) { + throw new FormatError( + 'WhitePoint missing - required for color space Lab'); + } + blackPoint = blackPoint || [0, 0, 0]; + range = range || [-100, 100, -100, 100]; + + // Translate args to spec variables + this.XW = whitePoint[0]; + this.YW = whitePoint[1]; + this.ZW = whitePoint[2]; + this.amin = range[0]; + this.amax = range[1]; + this.bmin = range[2]; + this.bmax = range[3]; + + // These are here just for completeness - the spec doesn't offer any + // formulas that use BlackPoint in Lab + this.XB = blackPoint[0]; + this.YB = blackPoint[1]; + this.ZB = blackPoint[2]; + + // Validate vars as per spec + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + throw new FormatError( + 'Invalid WhitePoint components, no fallback available'); + } + + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info('Invalid BlackPoint, falling back to default'); + this.XB = this.YB = this.ZB = 0; + } + + if (this.amin > this.amax || this.bmin > this.bmax) { + info('Invalid Range, falling back to defaults'); + this.amin = -100; + this.amax = 100; + this.bmin = -100; + this.bmax = 100; + } + } + getRgbItem(src, srcOffset, dest, destOffset) { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('!PRODUCTION || TESTING')) { @@ -1294,7 +1260,8 @@ var LabCS = (function LabCSClosure() { 'LabCS.getRgbItem: Unsupported "dest" type.'); } convertToRgb(this, src, srcOffset, false, dest, destOffset); - }, + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('!PRODUCTION || TESTING')) { @@ -1307,19 +1274,22 @@ var LabCS = (function LabCSClosure() { srcOffset += 3; destOffset += 3 + alpha01; } - }, + } + getOutputLength(inputLength, alpha01) { return (inputLength * (3 + alpha01) / 3) | 0; - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - fillRgb: ColorSpace.prototype.fillRgb, + } + isDefaultDecode(decodeMap) { // XXX: Decoding is handled with the lab conversion because of the strange // ranges that are used. return true; - }, - usesZeroToOneRange: false, - }; + } + + get usesZeroToOneRange() { + return shadow(this, 'usesZeroToOneRange', false); + } + } return LabCS; })();