|
|
@ -3996,10 +3996,6 @@ var CanvasGraphics = (function() { |
|
|
|
}, |
|
|
|
}, |
|
|
|
setFillColor: function(/*...*/) { |
|
|
|
setFillColor: function(/*...*/) { |
|
|
|
var cs = this.getFillColorSpace(); |
|
|
|
var cs = this.getFillColorSpace(); |
|
|
|
if (cs.name == 'Pattern') { |
|
|
|
|
|
|
|
TODO('implement Pattern fill'); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var color = cs.getRgb(arguments); |
|
|
|
var color = cs.getRgb(arguments); |
|
|
|
this.setFillRGBColor.apply(this, color); |
|
|
|
this.setFillRGBColor.apply(this, color); |
|
|
|
}, |
|
|
|
}, |
|
|
@ -4008,28 +4004,54 @@ var CanvasGraphics = (function() { |
|
|
|
|
|
|
|
|
|
|
|
if (cs.name == 'Pattern') { |
|
|
|
if (cs.name == 'Pattern') { |
|
|
|
var patternName = arguments[0]; |
|
|
|
var patternName = arguments[0]; |
|
|
|
if (IsName(patternName)) { |
|
|
|
this.setFillPattern(patternName); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// TODO real impl
|
|
|
|
|
|
|
|
this.setFillColor.apply(this, arguments); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
setFillPattern: function(patternName) { |
|
|
|
|
|
|
|
if (!IsName(patternName)) |
|
|
|
|
|
|
|
error("Bad args to getPattern"); |
|
|
|
|
|
|
|
|
|
|
|
var xref = this.xref; |
|
|
|
var xref = this.xref; |
|
|
|
var patternRes = xref.fetchIfRef(this.res.get('Pattern')); |
|
|
|
var patternRes = xref.fetchIfRef(this.res.get("Pattern")); |
|
|
|
if (!patternRes) |
|
|
|
if (!patternRes) |
|
|
|
error('Unable to find pattern resource'); |
|
|
|
error("Unable to find pattern resource"); |
|
|
|
|
|
|
|
|
|
|
|
var pattern = xref.fetchIfRef(patternRes.get(patternName.name)); |
|
|
|
var pattern = xref.fetchIfRef(patternRes.get(patternName.name)); |
|
|
|
var patternDict = IsStream(pattern) ? pattern.dict : pattern; |
|
|
|
var dict = IsStream(pattern) ? pattern.dict : pattern; |
|
|
|
var types = [null, this.tilingFill, |
|
|
|
|
|
|
|
function() { TODO('Shading Patterns'); }]; |
|
|
|
var types = [null, this.setTilingPattern, this.setShadingPattern]; |
|
|
|
var typeNum = patternDict.get('PatternType'); |
|
|
|
|
|
|
|
|
|
|
|
var typeNum = dict.get("PatternType"); |
|
|
|
var patternFn = types[typeNum]; |
|
|
|
var patternFn = types[typeNum]; |
|
|
|
if (!patternFn) |
|
|
|
if (!patternFn) |
|
|
|
error('Unhandled pattern type'); |
|
|
|
error("Unhandled pattern type"); |
|
|
|
patternFn.call(this, pattern, patternDict); |
|
|
|
patternFn.call(this, pattern, dict); |
|
|
|
} |
|
|
|
}, |
|
|
|
} else { |
|
|
|
setShadingPattern: function(pattern, dict) { |
|
|
|
// TODO real impl
|
|
|
|
var matrix = dict.get("Matrix"); |
|
|
|
this.setFillColor.apply(this, arguments); |
|
|
|
|
|
|
|
} |
|
|
|
var inv = [0,0,0,0,0,0]; |
|
|
|
|
|
|
|
var det = 1 / (matrix[0] * matrix[3] - matrix[1] * matrix[2]); |
|
|
|
|
|
|
|
inv[0] = matrix[3] * det; |
|
|
|
|
|
|
|
inv[1] = -matrix[1] * det; |
|
|
|
|
|
|
|
inv[2] = -matrix[2] * det; |
|
|
|
|
|
|
|
inv[3] = matrix[0] * det; |
|
|
|
|
|
|
|
inv[4] = det * (matrix[2] * matrix[5] - matrix[3] * matrix[4]); |
|
|
|
|
|
|
|
inv[5] = det * (matrix[1] * matrix[4] - matrix[0] * matrix[5]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.transform.apply(this, matrix); |
|
|
|
|
|
|
|
var shading = this.getShading(pattern.get("Shading")); |
|
|
|
|
|
|
|
this.ctx.fillStyle = shading; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// HACK to get the gradient to show at the right location. If
|
|
|
|
|
|
|
|
// removed, the gradient will show at the pre-transform coordinates.
|
|
|
|
|
|
|
|
this.ctx.fillRect(0,0,0,0); |
|
|
|
|
|
|
|
this.transform.apply(this, inv); |
|
|
|
}, |
|
|
|
}, |
|
|
|
tilingFill: function(pattern) { |
|
|
|
setTilingPattern: function(pattern, dict) { |
|
|
|
function applyMatrix(point, m) { |
|
|
|
function applyMatrix(point, m) { |
|
|
|
var x = point[0] * m[0] + point[1] * m[2] + m[4]; |
|
|
|
var x = point[0] * m[0] + point[1] * m[2] + m[4]; |
|
|
|
var y = point[0] * m[1] + point[1] * m[3] + m[5]; |
|
|
|
var y = point[0] * m[1] + point[1] * m[3] + m[5]; |
|
|
@ -4047,7 +4069,6 @@ var CanvasGraphics = (function() { |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
this.save(); |
|
|
|
this.save(); |
|
|
|
var dict = pattern.dict; |
|
|
|
|
|
|
|
var ctx = this.ctx; |
|
|
|
var ctx = this.ctx; |
|
|
|
|
|
|
|
|
|
|
|
var paintType = dict.get('PaintType'); |
|
|
|
var paintType = dict.get('PaintType'); |
|
|
@ -4143,7 +4164,7 @@ var CanvasGraphics = (function() { |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// Shading
|
|
|
|
// Shading
|
|
|
|
shadingFill: function(entryRef) { |
|
|
|
shadingFill: function(shadingName) { |
|
|
|
var xref = this.xref; |
|
|
|
var xref = this.xref; |
|
|
|
var res = this.res; |
|
|
|
var res = this.res; |
|
|
|
|
|
|
|
|
|
|
@ -4151,11 +4172,26 @@ var CanvasGraphics = (function() { |
|
|
|
if (!shadingRes) |
|
|
|
if (!shadingRes) |
|
|
|
error('No shading resource found'); |
|
|
|
error('No shading resource found'); |
|
|
|
|
|
|
|
|
|
|
|
var shading = xref.fetchIfRef(shadingRes.get(entryRef.name)); |
|
|
|
var shading = xref.fetchIfRef(shadingRes.get(shadingName.name)); |
|
|
|
if (!shading) |
|
|
|
if (!shading) |
|
|
|
error('No shading object found'); |
|
|
|
error('No shading object found'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var shadingFill = this.getShading(shading); |
|
|
|
|
|
|
|
|
|
|
|
this.save(); |
|
|
|
this.save(); |
|
|
|
|
|
|
|
this.ctx.fillStyle = shadingFill; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// HACK to draw the gradient onto an infinite rectangle.
|
|
|
|
|
|
|
|
// PDF gradients are drawn across the entire image while
|
|
|
|
|
|
|
|
// Canvas only allows gradients to be drawn in a rectangle
|
|
|
|
|
|
|
|
// The following bug should allow us to remove this.
|
|
|
|
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=664884
|
|
|
|
|
|
|
|
this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.restore(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
getShading: function(shading) { |
|
|
|
|
|
|
|
shading = this.xref.fetchIfRef(shading); |
|
|
|
|
|
|
|
|
|
|
|
var bbox = shading.get('BBox'); |
|
|
|
var bbox = shading.get('BBox'); |
|
|
|
if (bbox && IsArray(bbox) && 4 == bbox.length) { |
|
|
|
if (bbox && IsArray(bbox) && 4 == bbox.length) { |
|
|
@ -4164,28 +4200,25 @@ var CanvasGraphics = (function() { |
|
|
|
this.endPath(); |
|
|
|
this.endPath(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var cs = shading.get2('ColorSpace', 'CS'); |
|
|
|
|
|
|
|
TODO('shading-fill color space'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var background = shading.get('Background'); |
|
|
|
var background = shading.get('Background'); |
|
|
|
if (background) |
|
|
|
if (background) |
|
|
|
TODO('handle background colors'); |
|
|
|
TODO('handle background colors'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var cs = shading.get2('ColorSpace', 'CS'); |
|
|
|
|
|
|
|
cs = ColorSpace.parse(cs, this.xref, this.res); |
|
|
|
|
|
|
|
|
|
|
|
var types = [null, |
|
|
|
var types = [null, |
|
|
|
this.fillFunctionShading, |
|
|
|
null, |
|
|
|
this.fillAxialShading, |
|
|
|
this.getAxialShading, |
|
|
|
this.fillRadialShading]; |
|
|
|
this.getRadialShading]; |
|
|
|
|
|
|
|
|
|
|
|
var typeNum = shading.get('ShadingType'); |
|
|
|
var typeNum = shading.get('ShadingType'); |
|
|
|
var fillFn = types[typeNum]; |
|
|
|
var shadingFn = types[typeNum]; |
|
|
|
if (!fillFn) |
|
|
|
if (!shadingFn) |
|
|
|
error("Unknown or NYI type of shading '" + typeNum + "'"); |
|
|
|
error("Unknown or NYI type of shading '"+ typeNum +"'"); |
|
|
|
fillFn.apply(this, [shading]); |
|
|
|
return shadingFn.call(this, shading, cs); |
|
|
|
|
|
|
|
|
|
|
|
this.restore(); |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
getAxialShading: function(sh, cs) { |
|
|
|
fillAxialShading: function(sh) { |
|
|
|
|
|
|
|
var coordsArr = sh.get('Coords'); |
|
|
|
var coordsArr = sh.get('Coords'); |
|
|
|
var x0 = coordsArr[0], y0 = coordsArr[1], |
|
|
|
var x0 = coordsArr[0], y0 = coordsArr[1], |
|
|
|
x1 = coordsArr[2], y1 = coordsArr[3]; |
|
|
|
x1 = coordsArr[2], y1 = coordsArr[3]; |
|
|
@ -4216,24 +4249,59 @@ var CanvasGraphics = (function() { |
|
|
|
// if there are sharp color changes. Ideally, we would implement
|
|
|
|
// if there are sharp color changes. Ideally, we would implement
|
|
|
|
// the spec faithfully and add lossless optimizations.
|
|
|
|
// the spec faithfully and add lossless optimizations.
|
|
|
|
var step = (t1 - t0) / 10; |
|
|
|
var step = (t1 - t0) / 10; |
|
|
|
|
|
|
|
var diff = t1 - t0; |
|
|
|
|
|
|
|
|
|
|
|
for (var i = t0; i <= t1; i += step) { |
|
|
|
for (var i = t0; i <= t1; i += step) { |
|
|
|
var c = fn.func([i]); |
|
|
|
var color = fn.func([i]); |
|
|
|
gradient.addColorStop(i, this.makeCssRgb.apply(this, c)); |
|
|
|
var rgbColor = cs.getRgb(color); |
|
|
|
|
|
|
|
gradient.addColorStop((i - t0) / diff, |
|
|
|
|
|
|
|
this.makeCssRgb.apply(this, rgbColor)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.ctx.fillStyle = gradient; |
|
|
|
return gradient; |
|
|
|
|
|
|
|
|
|
|
|
// HACK to draw the gradient onto an infinite rectangle.
|
|
|
|
|
|
|
|
// PDF gradients are drawn across the entire image while
|
|
|
|
|
|
|
|
// Canvas only allows gradients to be drawn in a rectangle
|
|
|
|
|
|
|
|
// The following bug should allow us to remove this.
|
|
|
|
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=664884
|
|
|
|
|
|
|
|
this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
getRadialShading: function(sh, cs) { |
|
|
|
|
|
|
|
var coordsArr = sh.get('Coords'); |
|
|
|
|
|
|
|
var x0 = coordsArr[0], y0 = coordsArr[1], r0 = coordsArr[2]; |
|
|
|
|
|
|
|
var x1 = coordsArr[3], y1 = coordsArr[4], r1 = coordsArr[5]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var t0 = 0.0, t1 = 1.0; |
|
|
|
|
|
|
|
if (sh.has('Domain')) { |
|
|
|
|
|
|
|
var domainArr = sh.get('Domain'); |
|
|
|
|
|
|
|
t0 = domainArr[0], t1 = domainArr[1]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var extendStart = false, extendEnd = false; |
|
|
|
|
|
|
|
if (sh.has('Extend')) { |
|
|
|
|
|
|
|
var extendArr = sh.get('Extend'); |
|
|
|
|
|
|
|
extendStart = extendArr[0], extendEnd = extendArr[1]; |
|
|
|
|
|
|
|
TODO('Support extend'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var fnObj = sh.get('Function'); |
|
|
|
|
|
|
|
fnObj = this.xref.fetchIfRef(fnObj); |
|
|
|
|
|
|
|
if (IsArray(fnObj)) |
|
|
|
|
|
|
|
error('No support for array of functions'); |
|
|
|
|
|
|
|
else if (!IsPDFFunction(fnObj)) |
|
|
|
|
|
|
|
error('Invalid function'); |
|
|
|
|
|
|
|
var fn = new PDFFunction(this.xref, fnObj); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var gradient = |
|
|
|
|
|
|
|
this.ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 10 samples seems good enough for now, but probably won't work
|
|
|
|
|
|
|
|
// if there are sharp color changes. Ideally, we would implement
|
|
|
|
|
|
|
|
// the spec faithfully and add lossless optimizations.
|
|
|
|
|
|
|
|
var step = (t1 - t0) / 10; |
|
|
|
|
|
|
|
var diff = t1 - t0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = t0; i <= t1; i += step) { |
|
|
|
|
|
|
|
var color = fn.func([i]); |
|
|
|
|
|
|
|
var rgbColor = cs.getRgb(color); |
|
|
|
|
|
|
|
gradient.addColorStop((i - t0) / diff, |
|
|
|
|
|
|
|
this.makeCssRgb.apply(this, rgbColor)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fillRadialShading: function(sh) { |
|
|
|
return gradient; |
|
|
|
TODO('radial shading'); |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// Images
|
|
|
|
// Images
|
|
|
@ -4626,10 +4694,10 @@ var DeviceRgbCS = (function() { |
|
|
|
this.defaultColor = [0, 0, 0]; |
|
|
|
this.defaultColor = [0, 0, 0]; |
|
|
|
} |
|
|
|
} |
|
|
|
constructor.prototype = { |
|
|
|
constructor.prototype = { |
|
|
|
getRgb: function graycs_getRgb(color) { |
|
|
|
getRgb: function rgbcs_getRgb(color) { |
|
|
|
return color; |
|
|
|
return color; |
|
|
|
}, |
|
|
|
}, |
|
|
|
getRgbBuffer: function graycs_getRgbBuffer(input) { |
|
|
|
getRgbBuffer: function rgbcs_getRgbBuffer(input) { |
|
|
|
return input; |
|
|
|
return input; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
@ -4643,14 +4711,61 @@ var DeviceCmykCS = (function() { |
|
|
|
this.defaultColor = [0, 0, 0, 1]; |
|
|
|
this.defaultColor = [0, 0, 0, 1]; |
|
|
|
} |
|
|
|
} |
|
|
|
constructor.prototype = { |
|
|
|
constructor.prototype = { |
|
|
|
getRgb: function graycs_getRgb(color) { |
|
|
|
getRgb: function cmykcs_getRgb(color) { |
|
|
|
var c = color[0], y = color[1], m = color[2], k = color[3]; |
|
|
|
var c = color[0], m = color[1], y = color[2], k = color[3]; |
|
|
|
var ri = (1 - Math.min(1, c * (1 - k) + k)) | 0; |
|
|
|
var c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k; |
|
|
|
var gi = (1 - Math.min(1, m * (1 - k) + k)) | 0; |
|
|
|
|
|
|
|
var bi = (1 - Math.min(1, y * (1 - k) + k)) | 0; |
|
|
|
var x, r, g, b; |
|
|
|
return [ri, gi, bi]; |
|
|
|
// this is a matrix multiplication, unrolled for performance
|
|
|
|
}, |
|
|
|
// code is taken from the poppler implementation
|
|
|
|
getRgbBuffer: function graycs_getRgbBuffer(colorBuf) { |
|
|
|
x = c1 * m1 * y1 * k1; // 0 0 0 0
|
|
|
|
|
|
|
|
r = g = b = x; |
|
|
|
|
|
|
|
x = c1 * m1 * y1 * k; // 0 0 0 1
|
|
|
|
|
|
|
|
r += 0.1373 * x; |
|
|
|
|
|
|
|
g += 0.1216 * x; |
|
|
|
|
|
|
|
b += 0.1255 * x; |
|
|
|
|
|
|
|
x = c1 * m1 * y * k1; // 0 0 1 0
|
|
|
|
|
|
|
|
r += x; |
|
|
|
|
|
|
|
g += 0.9490 * x; |
|
|
|
|
|
|
|
x = c1 * m1 * y * k; // 0 0 1 1
|
|
|
|
|
|
|
|
r += 0.1098 * x; |
|
|
|
|
|
|
|
g += 0.1020 * x; |
|
|
|
|
|
|
|
x = c1 * m * y1 * k1; // 0 1 0 0
|
|
|
|
|
|
|
|
r += 0.9255 * x; |
|
|
|
|
|
|
|
b += 0.5490 * x; |
|
|
|
|
|
|
|
x = c1 * m * y1 * k; // 0 1 0 1
|
|
|
|
|
|
|
|
r += 0.1412 * x; |
|
|
|
|
|
|
|
x = c1 * m * y * k1; // 0 1 1 0
|
|
|
|
|
|
|
|
r += 0.9294 * x; |
|
|
|
|
|
|
|
g += 0.1098 * x; |
|
|
|
|
|
|
|
b += 0.1412 * x; |
|
|
|
|
|
|
|
x = c1 * m * y * k; // 0 1 1 1
|
|
|
|
|
|
|
|
r += 0.1333 * x; |
|
|
|
|
|
|
|
x = c * m1 * y1 * k1; // 1 0 0 0
|
|
|
|
|
|
|
|
g += 0.6784 * x; |
|
|
|
|
|
|
|
b += 0.9373 * x; |
|
|
|
|
|
|
|
x = c * m1 * y1 * k; // 1 0 0 1
|
|
|
|
|
|
|
|
g += 0.0588 * x; |
|
|
|
|
|
|
|
b += 0.1412 * x; |
|
|
|
|
|
|
|
x = c * m1 * y * k1; // 1 0 1 0
|
|
|
|
|
|
|
|
g += 0.6510 * x; |
|
|
|
|
|
|
|
b += 0.3137 * x; |
|
|
|
|
|
|
|
x = c * m1 * y * k; // 1 0 1 1
|
|
|
|
|
|
|
|
g += 0.0745 * x; |
|
|
|
|
|
|
|
x = c * m * y1 * k1; // 1 1 0 0
|
|
|
|
|
|
|
|
r += 0.1804 * x; |
|
|
|
|
|
|
|
g += 0.1922 * x; |
|
|
|
|
|
|
|
b += 0.5725 * x; |
|
|
|
|
|
|
|
x = c * m * y1 * k; // 1 1 0 1
|
|
|
|
|
|
|
|
b += 0.0078 * x; |
|
|
|
|
|
|
|
x = c * m * y * k1; // 1 1 1 0
|
|
|
|
|
|
|
|
r += 0.2118 * x; |
|
|
|
|
|
|
|
g += 0.2119 * x; |
|
|
|
|
|
|
|
b += 0.2235 * x; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return [r, g, b]; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
getRgbBuffer: function cmykcs_getRgbBuffer(colorBuf) { |
|
|
|
error('conversion from rgb to cmyk not implemented for images'); |
|
|
|
error('conversion from rgb to cmyk not implemented for images'); |
|
|
|
return colorBuf; |
|
|
|
return colorBuf; |
|
|
|
} |
|
|
|
} |
|
|
|