Refactors getRgb and makeCssRgb calls; reduces amount of created objects

This commit is contained in:
Yury Delendik 2012-11-28 19:32:27 -06:00
parent d4270c7fb3
commit 0029b34d45
5 changed files with 281 additions and 196 deletions

View File

@ -963,8 +963,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}, },
setStrokeColor: function CanvasGraphics_setStrokeColor(/*...*/) { setStrokeColor: function CanvasGraphics_setStrokeColor(/*...*/) {
var cs = this.current.strokeColorSpace; var cs = this.current.strokeColorSpace;
var rgbColor = cs.getRgb(arguments); var rgbColor = cs.getRgb(arguments, 0);
var color = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); var color = Util.makeCssRgb(rgbColor);
this.ctx.strokeStyle = color; this.ctx.strokeStyle = color;
this.current.strokeColor = color; this.current.strokeColor = color;
}, },
@ -976,11 +976,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (base) { if (base) {
var baseComps = base.numComps; var baseComps = base.numComps;
color = []; color = base.getRgb(args, 0);
for (var i = 0; i < baseComps; ++i)
color.push(args[i]);
color = base.getRgb(color);
} }
var pattern = new TilingPattern(IR, color, this.ctx, this.objs); var pattern = new TilingPattern(IR, color, this.ctx, this.objs);
} else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') { } else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
@ -1001,8 +997,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}, },
setFillColor: function CanvasGraphics_setFillColor(/*...*/) { setFillColor: function CanvasGraphics_setFillColor(/*...*/) {
var cs = this.current.fillColorSpace; var cs = this.current.fillColorSpace;
var rgbColor = cs.getRgb(arguments); var rgbColor = cs.getRgb(arguments, 0);
var color = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); var color = Util.makeCssRgb(rgbColor);
this.ctx.fillStyle = color; this.ctx.fillStyle = color;
this.current.fillColor = color; this.current.fillColor = color;
}, },
@ -1019,7 +1015,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (!(this.current.strokeColorSpace instanceof DeviceGrayCS)) if (!(this.current.strokeColorSpace instanceof DeviceGrayCS))
this.current.strokeColorSpace = new DeviceGrayCS(); this.current.strokeColorSpace = new DeviceGrayCS();
var color = Util.makeCssRgb(gray, gray, gray); var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
var color = Util.makeCssRgb(rgbColor);
this.ctx.strokeStyle = color; this.ctx.strokeStyle = color;
this.current.strokeColor = color; this.current.strokeColor = color;
}, },
@ -1027,7 +1024,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (!(this.current.fillColorSpace instanceof DeviceGrayCS)) if (!(this.current.fillColorSpace instanceof DeviceGrayCS))
this.current.fillColorSpace = new DeviceGrayCS(); this.current.fillColorSpace = new DeviceGrayCS();
var color = Util.makeCssRgb(gray, gray, gray); var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
var color = Util.makeCssRgb(rgbColor);
this.ctx.fillStyle = color; this.ctx.fillStyle = color;
this.current.fillColor = color; this.current.fillColor = color;
}, },
@ -1035,7 +1033,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (!(this.current.strokeColorSpace instanceof DeviceRgbCS)) if (!(this.current.strokeColorSpace instanceof DeviceRgbCS))
this.current.strokeColorSpace = new DeviceRgbCS(); this.current.strokeColorSpace = new DeviceRgbCS();
var color = Util.makeCssRgb(r, g, b); var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
var color = Util.makeCssRgb(rgbColor);
this.ctx.strokeStyle = color; this.ctx.strokeStyle = color;
this.current.strokeColor = color; this.current.strokeColor = color;
}, },
@ -1043,7 +1042,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (!(this.current.fillColorSpace instanceof DeviceRgbCS)) if (!(this.current.fillColorSpace instanceof DeviceRgbCS))
this.current.fillColorSpace = new DeviceRgbCS(); this.current.fillColorSpace = new DeviceRgbCS();
var color = Util.makeCssRgb(r, g, b); var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
var color = Util.makeCssRgb(rgbColor);
this.ctx.fillStyle = color; this.ctx.fillStyle = color;
this.current.fillColor = color; this.current.fillColor = color;
}, },
@ -1051,7 +1051,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (!(this.current.strokeColorSpace instanceof DeviceCmykCS)) if (!(this.current.strokeColorSpace instanceof DeviceCmykCS))
this.current.strokeColorSpace = new DeviceCmykCS(); this.current.strokeColorSpace = new DeviceCmykCS();
var color = Util.makeCssCmyk(c, m, y, k); var color = Util.makeCssCmyk(arguments);
this.ctx.strokeStyle = color; this.ctx.strokeStyle = color;
this.current.strokeColor = color; this.current.strokeColor = color;
}, },
@ -1059,7 +1059,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (!(this.current.fillColorSpace instanceof DeviceCmykCS)) if (!(this.current.fillColorSpace instanceof DeviceCmykCS))
this.current.fillColorSpace = new DeviceCmykCS(); this.current.fillColorSpace = new DeviceCmykCS();
var color = Util.makeCssCmyk(c, m, y, k); var color = Util.makeCssCmyk(arguments);
this.ctx.fillStyle = color; this.ctx.fillStyle = color;
this.current.fillColor = color; this.current.fillColor = color;
}, },

View File

@ -24,15 +24,52 @@ var ColorSpace = (function ColorSpaceClosure() {
} }
ColorSpace.prototype = { ColorSpace.prototype = {
// Input: array of size numComps representing color component values /**
// Output: array of rgb values, each value ranging from [0.1] * Converts src array items representing color components values starting
getRgb: function ColorSpace_getRgb(color) { * from srcOffset to RGB color. Returns the array of the rgb components
error('Should not call ColorSpace.getRgb: ' + color); * items, each value ranging from [0,255].
*/
getRgb: function ColorSpace_getRgb(src, srcOffset) {
error('Should not call ColorSpace.getRgb');
}, },
// Input: Uint8Array of component values, each value scaled to [0,255] /**
// Output: Uint8Array of rgb values, each value scaled to [0,255] * Converts src array items representing color components values starting
getRgbBuffer: function ColorSpace_getRgbBuffer(input) { * from srcOffset to RGB colors. The src is Uint8Array with the items that
error('Should not call ColorSpace.getRgbBuffer: ' + input); * represent color components values, each value scaled to [0, 2^bits).
* Only count amount of values with be converted and placed into dest array
* starting from destOffset offset, each value scaled to [0,255].
*/
getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) {
error('Should not call ColorSpace.getRgbBuffer');
},
/**
* Determines amount of the bytes is required to store the reslut of the
* conversion that done by the getRgbBuffer method.
*/
getOutputLength: function ColorSpace_getOutputLength(inputLength) {
error('Should not call ColorSpace.getOutputLength');
},
/**
* Returns true if source data will be equal the result/output data.
*/
isPassthrough: function ColorSpace_isPassthrough(bits) {
return false;
},
/**
* Converts src array items representing color components values starting
* from srcOffset to RGB colors similar to the getRgbBuffer. Returns
* the created buffer.
*/
createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset,
count, bits) {
if (this.isPassthrough(bits)) {
return src.subarray(srcOffset);
}
var destLength = this.getOutputLength(count * this.numComps);
var dest = new Uint8Array(destLength);
this.getRgbBuffer(src, srcOffset, count, dest, 0, bits);
return dest;
} }
}; };
@ -216,39 +253,54 @@ var AlternateCS = (function AlternateCSClosure() {
function AlternateCS(numComps, base, tintFn) { function AlternateCS(numComps, base, tintFn) {
this.name = 'Alternate'; this.name = 'Alternate';
this.numComps = numComps; this.numComps = numComps;
this.defaultColor = []; this.defaultColor = new Float32Array(numComps);
for (var i = 0; i < numComps; ++i) for (var i = 0; i < numComps; ++i) {
this.defaultColor.push(1); this.defaultColor[i] = 1;
}
this.base = base; this.base = base;
this.tintFn = tintFn; this.tintFn = tintFn;
} }
AlternateCS.prototype = { AlternateCS.prototype = {
getRgb: function AlternateCS_getRgb(color) { getRgb: function AlternateCS_getRgb(src, srcOffset) {
var tinted = this.tintFn(color); var baseNumComps = this.base.numComps;
return this.base.getRgb(tinted); var input = 'subarray' in src ?
src.subarray(srcOffset, srcOffset + this.numComps) :
Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps);
var tinted = this.tintFn(input);
return this.base.getRgb(tinted, 0);
}, },
getRgbBuffer: function AlternateCS_getRgbBuffer(input, bits) { getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) {
var tintFn = this.tintFn; var tintFn = this.tintFn;
var base = this.base; var base = this.base;
var scale = 1 / ((1 << bits) - 1); var scale = 1 / ((1 << bits) - 1);
var length = input.length;
var pos = 0;
var baseNumComps = base.numComps; var baseNumComps = base.numComps;
var baseBuf = new Uint8Array(baseNumComps * length); var isPassthrough = base.isPassthrough(8);
var pos = isPassthrough ? destOffset : 0;
var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count);
var numComps = this.numComps; var numComps = this.numComps;
var scaled = [];
for (var i = 0; i < length; i += numComps) {
for (var z = 0; z < numComps; ++z)
scaled[z] = input[i + z] * scale;
var scaled = new Float32Array(numComps);
for (var i = 0; i < count; i++) {
for (var j = 0; j < numComps; j++) {
scaled[j] = src[srcOffset++] * scale;
}
var tinted = tintFn(scaled); var tinted = tintFn(scaled);
for (var j = 0; j < baseNumComps; ++j) for (var j = 0; j < baseNumComps; j++) {
baseBuf[pos++] = 255 * tinted[j]; baseBuf[pos++] = tinted[j] * 255;
}
}
if (!isPassthrough) {
base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8);
} }
return base.getRgbBuffer(baseBuf, 8);
}, },
getOutputLength: function AlternateCS_getOutputLength(inputLength) {
return this.base.getOutputLength(inputLength *
this.base.numComps / this.numComps);
},
isPassthrough: ColorSpace.prototype.isPassthrough,
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) { isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
} }
@ -271,7 +323,7 @@ var IndexedCS = (function IndexedCSClosure() {
function IndexedCS(base, highVal, lookup) { function IndexedCS(base, highVal, lookup) {
this.name = 'Indexed'; this.name = 'Indexed';
this.numComps = 1; this.numComps = 1;
this.defaultColor = [0]; this.defaultColor = new Uint8Array([0]);
this.base = base; this.base = base;
this.highVal = highVal; this.highVal = highVal;
@ -296,33 +348,29 @@ var IndexedCS = (function IndexedCSClosure() {
} }
IndexedCS.prototype = { IndexedCS.prototype = {
getRgb: function IndexedCS_getRgb(color) { getRgb: function IndexedCS_getRgb(src, srcOffset) {
var numComps = this.base.numComps; var numComps = this.base.numComps;
var start = color[0] * numComps; var start = src[srcOffset] * numComps;
var c = []; return this.base.getRgb(this.lookup, start);
for (var i = start, ii = start + numComps; i < ii; ++i)
c.push(this.lookup[i]);
return this.base.getRgb(c);
}, },
getRgbBuffer: function IndexedCS_getRgbBuffer(input) { getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset) {
var base = this.base; var base = this.base;
var numComps = base.numComps; var numComps = base.numComps;
var outputDelta = base.getOutputLength(numComps);
var lookup = this.lookup; var lookup = this.lookup;
var length = input.length;
var baseBuf = new Uint8Array(length * numComps);
var baseBufPos = 0;
for (var i = 0; i < length; ++i) { for (var i = 0; i < count; ++i) {
var lookupPos = input[i] * numComps; var lookupPos = src[srcOffset++] * numComps;
for (var j = 0; j < numComps; ++j) { base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8);
baseBuf[baseBufPos++] = lookup[lookupPos + j]; destOffset += outputDelta;
}
} }
return base.getRgbBuffer(baseBuf, 8);
}, },
getOutputLength: function IndexedCS_getOutputLength(inputLength) {
return this.base.getOutputLength(inputLength * this.base.numComps);
},
isPassthrough: ColorSpace.prototype.isPassthrough,
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) { isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
// indexed color maps shouldn't be changed // indexed color maps shouldn't be changed
return true; return true;
@ -335,26 +383,31 @@ var DeviceGrayCS = (function DeviceGrayCSClosure() {
function DeviceGrayCS() { function DeviceGrayCS() {
this.name = 'DeviceGray'; this.name = 'DeviceGray';
this.numComps = 1; this.numComps = 1;
this.defaultColor = [0]; this.defaultColor = new Float32Array([0]);
} }
DeviceGrayCS.prototype = { DeviceGrayCS.prototype = {
getRgb: function DeviceGrayCS_getRgb(color) { getRgb: function DeviceGrayCS_getRgb(src, srcOffset) {
var c = color[0]; var c = (src[srcOffset] * 255) | 0;
return [c, c, c]; c = c < 0 ? 0 : c > 255 ? 255 : c;
return new Uint8Array([c, c, c]);
}, },
getRgbBuffer: function DeviceGrayCS_getRgbBuffer(input, bits) { getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) {
var scale = 255 / ((1 << bits) - 1); var scale = 255 / ((1 << bits) - 1);
var length = input.length; var j = srcOffset, q = destOffset;
var rgbBuf = new Uint8Array(length * 3); for (var i = 0; i < count; ++i) {
for (var i = 0, j = 0; i < length; ++i) { var c = (scale * src[j++]) | 0;
var c = (scale * input[i]) | 0; dest[q++] = c;
rgbBuf[j++] = c; dest[q++] = c;
rgbBuf[j++] = c; dest[q++] = c;
rgbBuf[j++] = c;
} }
return rgbBuf;
}, },
getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) {
return inputLength * 3;
},
isPassthrough: ColorSpace.prototype.isPassthrough,
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) { isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
} }
@ -366,22 +419,39 @@ var DeviceRgbCS = (function DeviceRgbCSClosure() {
function DeviceRgbCS() { function DeviceRgbCS() {
this.name = 'DeviceRGB'; this.name = 'DeviceRGB';
this.numComps = 3; this.numComps = 3;
this.defaultColor = [0, 0, 0]; this.defaultColor = new Float32Array([0, 0, 0]);
} }
DeviceRgbCS.prototype = { DeviceRgbCS.prototype = {
getRgb: function DeviceRgbCS_getRgb(color) { getRgb: function DeviceRgbCS_getRgb(src, srcOffset) {
return color; var r = src[srcOffset] * 255;
var g = src[srcOffset + 1] * 255;
var b = src[srcOffset + 2] * 255;
var rgb = new Uint8Array(3);
rgb[0] = r < 0 ? 0 : r > 255 ? 255 : r;
rgb[1] = g < 0 ? 0 : g > 255 ? 255 : g;
rgb[2] = b < 0 ? 0 : b > 255 ? 255 : b;
return rgb;
}, },
getRgbBuffer: function DeviceRgbCS_getRgbBuffer(input, bits) { getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count,
if (bits == 8) dest, destOffset, bits) {
return input; var length = count * 3;
if (bits == 8) {
dest.set(src.subarray(srcOffset, srcOffset + length), destOffset);
return;
}
var scale = 255 / ((1 << bits) - 1); var scale = 255 / ((1 << bits) - 1);
var i, length = input.length; var j = srcOffset, q = destOffset;
var rgbBuf = new Uint8Array(length); for (var i = 0; i < length; ++i) {
for (i = 0; i < length; ++i) dest[q++] = (scale * input[j++]) | 0;
rgbBuf[i] = (scale * input[i]) | 0; }
return rgbBuf;
}, },
getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) {
return inputLength;
},
isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
return bits == 8;
},
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) { isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
} }
@ -1059,72 +1129,74 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() {
15, 13, 26, 2, 1, 11, 0, 0, 0, 0, 0, 0, 54, 54, 57, 47, 44, 47, 39, 35, 39, 15, 13, 26, 2, 1, 11, 0, 0, 0, 0, 0, 0, 54, 54, 57, 47, 44, 47, 39, 35, 39,
28, 25, 29, 17, 13, 17, 4, 1, 3, 0, 0, 0, 0, 0, 0]); 28, 25, 29, 17, 13, 17, 4, 1, 3, 0, 0, 0, 0, 0, 0]);
function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
// using lut as in spline interpolation (see function.js)
var cubeVertices = 16; // 1 << number of colors
var cubeN = new Float32Array(cubeVertices);
var cubeVertex = new Uint32Array(cubeVertices);
for (var j = 0; j < cubeVertices; j++)
cubeN[j] = 1;
var k = 3, pos = 1;
var lutDomain = 7, lutStep = 8;
for (var i = 3; i >= 0; i--) {
var e = src[srcOffset + i] * srcScale * lutDomain;
var e0 = e < lutDomain ? Math.floor(e) : e - 1; // e1 = e0 + 1;
var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
var n1 = e - e0; // (e - e0) / (e1 - e0);
var offset0 = e0 * k;
var offset1 = offset0 + k; // e1 * k
for (var j = 0; j < cubeVertices; j++) {
if (j & pos) {
cubeN[j] *= n1;
cubeVertex[j] += offset1;
} else {
cubeN[j] *= n0;
cubeVertex[j] += offset0;
}
}
k *= lutStep;
pos <<= 1;
}
var y0 = 0, y1 = 0, y2 = 0;
for (var i = 0; i < cubeVertices; i++)
y0 += lut[cubeVertex[i]] * cubeN[i];
for (var i = 0; i < cubeVertices; i++)
y1 += lut[cubeVertex[i] + 1] * cubeN[i];
for (var i = 0; i < cubeVertices; i++)
y2 += lut[cubeVertex[i] + 2] * cubeN[i];
dest[destOffset] = y0 > 255 ? 255 : y0;
dest[destOffset + 1] = y1 > 255 ? 255 : y1;
dest[destOffset + 2] = y2 > 255 ? 255 : y2;
}
function DeviceCmykCS() { function DeviceCmykCS() {
this.name = 'DeviceCMYK'; this.name = 'DeviceCMYK';
this.numComps = 4; this.numComps = 4;
this.defaultColor = [0, 0, 0, 1]; this.defaultColor = new Float32Array([0, 0, 0, 1]);
} }
DeviceCmykCS.prototype = { DeviceCmykCS.prototype = {
getRgb: function DeviceCmykCS_getRgb(color) { getRgb: function DeviceCmykCS_getRgb(src, srcOffset) {
// using lut as in spline interpolation (see function.js) var rgb = new Uint8Array(3);
var cubeVertices = 16; // 1 << number of colors convertToRgb(src, srcOffset, 1, rgb, 0);
var cubeN = new Float32Array(cubeVertices); return rgb;
var cubeVertex = new Uint32Array(cubeVertices);
for (var j = 0; j < cubeVertices; j++)
cubeN[j] = 1;
var k = 3, pos = 1;
var lutDomain = 7, lutStep = 8;
for (var i = 3; i >= 0; i--) {
var e = color[i] * lutDomain;
var e0 = e < lutDomain ? Math.floor(e) : e - 1; // e1 = e0 + 1;
var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
var n1 = e - e0; // (e - e0) / (e1 - e0);
var offset0 = e0 * k;
var offset1 = offset0 + k; // e1 * k
for (var j = 0; j < cubeVertices; j++) {
if (j & pos) {
cubeN[j] *= n1;
cubeVertex[j] += offset1;
} else {
cubeN[j] *= n0;
cubeVertex[j] += offset0;
}
}
k *= lutStep;
pos <<= 1;
}
var y = new Float32Array(3);
for (var j = 0; j < 3; ++j) {
var rj = 0;
for (var i = 0; i < cubeVertices; i++)
rj += lut[cubeVertex[i] + j] * cubeN[i];
y[j] = rj;
}
return [y[0] / 255, y[1] / 255, y[2] / 255];
}, },
getRgbBuffer: function DeviceCmykCS_getRgbBuffer(colorBuf, bits) { getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) {
var scale = 1 / ((1 << bits) - 1); var scale = 1 / ((1 << bits) - 1);
var length = colorBuf.length / 4; for (var i = 0; i < count; i++) {
var rgbBuf = new Uint8Array(length * 3); convertToRgb(src, srcOffset, scale, dest, destOffset);
var rgbBufPos = 0; srcOffset += 4;
var colorBufPos = 0; destOffset += 3;
for (var i = 0; i < length; i++) {
var cmyk = [];
for (var j = 0; j < 4; ++j)
cmyk.push(scale * colorBuf[colorBufPos++]);
var rgb = this.getRgb(cmyk);
for (var j = 0; j < 3; ++j)
rgbBuf[rgbBufPos++] = Math.round(rgb[j] * 255);
} }
return rgbBuf;
}, },
getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) {
return (inputLength >> 2) * 3;
},
isPassthrough: ColorSpace.prototype.isPassthrough,
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
} }
@ -1140,7 +1212,7 @@ var LabCS = (function LabCSClosure() {
function LabCS(whitePoint, blackPoint, range) { function LabCS(whitePoint, blackPoint, range) {
this.name = 'Lab'; this.name = 'Lab';
this.numComps = 3; this.numComps = 3;
this.defaultColor = [0, 0, 0]; this.defaultColor = new Float32Array([0, 0, 0]);
if (!whitePoint) if (!whitePoint)
error('WhitePoint missing - required for color space Lab'); error('WhitePoint missing - required for color space Lab');
@ -1188,51 +1260,61 @@ var LabCS = (function LabCSClosure() {
return (108 / 841) * (x - 4 / 29); return (108 / 841) * (x - 4 / 29);
} }
function convertToRgb(cs, src, srcOffset, dest, destOffset) {
// Ls,as,bs <---> L*,a*,b* in the spec
var Ls = src[srcOffset];
var as = src[srcOffset + 1];
var bs = src[srcOffset + 2];
// Adjust limits of 'as' and 'bs'
as = as > cs.amax ? cs.amax : as;
as = as < cs.amin ? cs.amin : as;
bs = bs > cs.bmax ? cs.bmax : bs;
bs = bs < cs.bmin ? cs.bmin : bs;
// Computes intermediate variables X,Y,Z as per spec
var M = (Ls + 16) / 116;
var L = M + (as / 500);
var N = M - (bs / 200);
var X = cs.XW * g(L);
var Y = cs.YW * g(M);
var Z = cs.ZW * g(N);
// XYZ to RGB 3x3 matrix, from:
// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18
var XYZtoRGB = [3.240479, -1.537150, -0.498535,
-0.969256, 1.875992, 0.041556,
0.055648, -0.204043, 1.057311];
var rgb = Util.apply3dTransform(XYZtoRGB, [X, Y, Z]);
// clamp color values to [0,255] range
dest[destOffset] = rgb[0] < 0 ? 0 : rgb[0] > 1 ? 255 : rgb[0] * 255;
dest[destOffset + 1] = rgb[1] < 0 ? 0 : rgb[1] > 1 ? 255 : rgb[1] * 255;
dest[destOffset + 2] = rgb[2] < 0 ? 0 : rgb[2] > 1 ? 255 : rgb[2] * 255;
}
LabCS.prototype = { LabCS.prototype = {
getRgb: function LabCS_getRgb(color) { getRgb: function LabCS_getRgb(src, srcOffset) {
// Ls,as,bs <---> L*,a*,b* in the spec var rgb = new Uint8Array(3);
var Ls = color[0], as = color[1], bs = color[2]; convertToRgb(this, src, srcOffset, rgb, 0);
return rgb;
// Adjust limits of 'as' and 'bs'
as = as > this.amax ? this.amax : as;
as = as < this.amin ? this.amin : as;
bs = bs > this.bmax ? this.bmax : bs;
bs = bs < this.bmin ? this.bmin : bs;
// Computes intermediate variables X,Y,Z as per spec
var M = (Ls + 16) / 116;
var L = M + (as / 500);
var N = M - (bs / 200);
var X = this.XW * g(L);
var Y = this.YW * g(M);
var Z = this.ZW * g(N);
// XYZ to RGB 3x3 matrix, from:
// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18
var XYZtoRGB = [3.240479, -1.537150, -0.498535,
-0.969256, 1.875992, 0.041556,
0.055648, -0.204043, 1.057311];
return Util.apply3dTransform(XYZtoRGB, [X, Y, Z]);
}, },
getRgbBuffer: function LabCS_getRgbBuffer(input, bits) { getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count,
if (bits == 8) dest, destOffset) {
return input; for (var i = 0; i < count; ++i) {
var scale = 255 / ((1 << bits) - 1); convertToRgb(this, src, srcOffset, dest, destOffset);
var i, length = input.length / 3; srcOffset += 3;
var rgbBuf = new Uint8Array(length); destOffset += 3;
var j = 0;
for (i = 0; i < length; ++i) {
// Convert L*, a*, s* into RGB
var rgb = this.getRgb([input[i], input[i + 1], input[i + 2]]);
rgbBuf[j++] = rgb[0];
rgbBuf[j++] = rgb[1];
rgbBuf[j++] = rgb[2];
} }
return rgbBuf; return rgbBuf;
}, },
getOutputLength: function LabCS_getOutputLength(inputLength) {
return inputLength;
},
isPassthrough: ColorSpace.prototype.isPassthrough,
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) { isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
// From Table 90 in Adobe's: // From Table 90 in Adobe's:
// "Document management - Portable document format", 1st ed, 2008 // "Document management - Portable document format", 1st ed, 2008

View File

@ -396,8 +396,8 @@ var PDFImage = (function PDFImageClosure() {
var actualHeight = 0 | (imgArray.length / rowBytes * var actualHeight = 0 | (imgArray.length / rowBytes *
height / originalHeight); height / originalHeight);
var comps = this.colorSpace.getRgbBuffer( var comps = this.colorSpace.createRgbBuffer(this.getComponents(imgArray),
this.getComponents(imgArray), bpc); 0, originalWidth * originalHeight, bpc);
if (originalWidth != width || originalHeight != height) if (originalWidth != width || originalHeight != height)
comps = PDFImage.resize(comps, this.bpc, 3, originalWidth, comps = PDFImage.resize(comps, this.bpc, 3, originalWidth,
originalHeight, width, height); originalHeight, width, height);

View File

@ -138,15 +138,15 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
} }
for (var i = t0; i <= t1; i += step) { for (var i = t0; i <= t1; i += step) {
var rgbColor = cs.getRgb(fn([i])); var rgbColor = cs.getRgb(fn([i]), 0);
var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); var cssColor = Util.makeCssRgb(rgbColor);
colorStops.push([(i - t0) / diff, cssColor]); colorStops.push([(i - t0) / diff, cssColor]);
} }
var background = 'transparent'; var background = 'transparent';
if (dict.has('Background')) { if (dict.has('Background')) {
var rgbColor = cs.getRgb(dict.get('Background')); var rgbColor = cs.getRgb(dict.get('Background'), 0);
background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); background = Util.makeCssRgb(rgbColor);
} }
if (!extendStart) { if (!extendStart) {
@ -294,7 +294,8 @@ var TilingPattern = (function TilingPatternClosure() {
tmpCtx.strokeStyle = ctx.strokeStyle; tmpCtx.strokeStyle = ctx.strokeStyle;
break; break;
case PaintType.UNCOLORED: case PaintType.UNCOLORED:
var cssColor = Util.makeCssRgb(this, color[0], color[1], color[2]); var rgbColor = new DeviceRgbCS().getRgb(color, 0);
var cssColor = Util.makeCssRgb(rgbColor);
tmpCtx.fillStyle = cssColor; tmpCtx.fillStyle = cssColor;
tmpCtx.strokeStyle = cssColor; tmpCtx.strokeStyle = cssColor;
break; break;

View File

@ -196,15 +196,17 @@ var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
var Util = PDFJS.Util = (function UtilClosure() { var Util = PDFJS.Util = (function UtilClosure() {
function Util() {} function Util() {}
Util.makeCssRgb = function Util_makeCssRgb(r, g, b) { Util.makeCssRgb = function Util_makeCssRgb(rgb) {
var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
}; };
Util.makeCssCmyk = function Util_makeCssCmyk(c, m, y, k) { Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) {
c = (new DeviceCmykCS()).getRgb([c, m, y, k]); var cs = new DeviceCmykCS();
var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0; Util.makeCssCmyk = function makeCssCmyk(cmyk) {
return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; var rgb = cs.getRgb(cmyk, 0);
return Util.makeCssRgb(rgb);
};
return Util.makeCssCmyk(cmyk);
}; };
// For 2d affine transforms // For 2d affine transforms