git radial gradients working

This commit is contained in:
sbarman 2011-07-13 11:41:04 -07:00
parent 9701f8d376
commit da845ec5e6

194
pdf.js
View File

@ -3793,7 +3793,7 @@ var PartialEvaluator = (function() {
// <canvas> contexts store most of the state we need natively. // <canvas> contexts store most of the state we need natively.
// However, PDF needs a bit more state, which we store here. // However, PDF needs a bit more state, which we store here.
var CanvasExtraState = (function() { var CanvasExtraState = (function() {
function constructor() { function constructor(old) {
// Are soft masks and alpha values shapes or opacities? // Are soft masks and alpha values shapes or opacities?
this.alphaIsShape = false; this.alphaIsShape = false;
this.fontSize = 0; this.fontSize = 0;
@ -3810,10 +3810,70 @@ var CanvasExtraState = (function() {
this.wordSpace = 0; this.wordSpace = 0;
this.textHScale = 100; this.textHScale = 100;
// Color spaces // Color spaces
this.fillColorSpace = null; this.fillColorSpaceObj = null;
this.strokeColorSpace = null; this.strokeColorSpaceObj = null;
this.fillColorObj = null;
this.strokeColorObj = null;
this.old = old;
} }
constructor.prototype = { constructor.prototype = {
get fillColorSpace() {
var cs = this.fillColorSpaceObj;
if (cs)
return cs;
var old = this.old;
if (old)
return old.fillColorSpace;
return null;
},
set fillColorSpace(cs) {
this.fillColorSpaceObj = cs;
},
get strokeColorSpace() {
var cs = this.strokeColorSpaceObj;
if (cs)
return cs;
var old = this.old;
if (old)
return old.strokeColorSpace;
return null;
},
set strokeColorSpace(cs) {
this.strokeColorSpaceObj = cs;
},
get fillColor() {
var color = this.fillColorObj;
if (color)
return color;
var old = this.old;
if (old)
return old.fillColor;
return null;
},
set fillColor(color) {
this.fillColorObj = color;
},
get strokeColor() {
var color = this.strokeColorObj;
if (color)
return color;
var old = this.old;
if (old)
return old.strokeColor;
return null;
},
set strokeColor(color) {
this.strokeColorObj = color;
}
}; };
return constructor; return constructor;
})(); })();
@ -3906,8 +3966,9 @@ var CanvasGraphics = (function() {
if (this.ctx.$saveCurrentX) { if (this.ctx.$saveCurrentX) {
this.ctx.$saveCurrentX(); this.ctx.$saveCurrentX();
} }
this.stateStack.push(this.current); var old = this.current;
this.current = new CanvasExtraState(); this.stateStack.push(old);
this.current = new CanvasExtraState(old);
}, },
restore: function() { restore: function() {
var prev = this.stateStack.pop(); var prev = this.stateStack.pop();
@ -3954,7 +4015,16 @@ var CanvasGraphics = (function() {
this.stroke(); this.stroke();
}, },
fill: function() { fill: function() {
this.ctx.fill(); var ctx = this.ctx;
var fillColor = this.current.fillColor;
if (fillColor.type === "Pattern") {
this.ctx.fillStyle = fillColor.patternFn.apply(this, ctx);
ctx.fill();
} else {
ctx.fill();
}
this.consumePath(); this.consumePath();
}, },
eoFill: function() { eoFill: function() {
@ -3963,8 +4033,14 @@ var CanvasGraphics = (function() {
this.restoreFillRule(savedFillRule); this.restoreFillRule(savedFillRule);
}, },
fillStroke: function() { fillStroke: function() {
this.ctx.fill(); var ctx = this.ctx;
this.ctx.stroke(); var fillCS = this.current.fillColorSpace;
if (fillCS && fillCS.name === "Pattern")
this.current.fillPattern(ctx);
ctx.fill();
ctx.stroke();
this.consumePath(); this.consumePath();
}, },
eoFillStroke: function() { eoFillStroke: function() {
@ -4143,12 +4219,12 @@ var CanvasGraphics = (function() {
ColorSpace.parse(space, this.xref, this.res); ColorSpace.parse(space, this.xref, this.res);
}, },
setStrokeColor: function(/*...*/) { setStrokeColor: function(/*...*/) {
var cs = this.getStrokeColorSpace(); var cs = this.current.strokeColorSpace;
var color = cs.getRgb(arguments); var color = cs.getRgb(arguments);
this.setStrokeRGBColor.apply(this, color); this.setStrokeRGBColor.apply(this, color);
}, },
setStrokeColorN: function(/*...*/) { setStrokeColorN: function(/*...*/) {
var cs = this.getStrokeColorSpace(); var cs = this.current.strokeColorSpace;
if (cs.name == 'Pattern') { if (cs.name == 'Pattern') {
this.ctx.strokeStyle = this.getPattern(cs, arguments); this.ctx.strokeStyle = this.getPattern(cs, arguments);
@ -4157,15 +4233,19 @@ var CanvasGraphics = (function() {
} }
}, },
setFillColor: function(/*...*/) { setFillColor: function(/*...*/) {
var cs = this.getFillColorSpace(); var cs = this.current.fillColorSpace;
var color = cs.getRgb(arguments); var color = cs.getRgb(arguments);
this.setFillRGBColor.apply(this, color); this.setFillRGBColor.apply(this, color);
}, },
setFillColorN: function(/*...*/) { setFillColorN: function(/*...*/) {
var cs = this.getFillColorSpace(); var cs = this.current.fillColorSpace;
if (cs.name == 'Pattern') { if (cs.name == 'Pattern') {
this.ctx.fillStyle = this.getPattern(cs, arguments); // return a set of functions which will set the pattern
// when fill is called
var pattern = this.getPattern(cs, arguments);
this.current.fillColor = pattern;
this.current.fillColor.type = "Pattern";
} else { } else {
this.setFillColor.apply(this, arguments); this.setFillColor.apply(this, arguments);
} }
@ -4210,9 +4290,9 @@ var CanvasGraphics = (function() {
this.transform.apply(this, matrix); this.transform.apply(this, matrix);
var shading = this.getShading(pattern.get("Shading")); var shading = this.getShading(pattern.get("Shading"));
this.restore(); this.restore();
TODO('store transform so it can be applied before every fill');
return shading; return shading;
// TODO('store transform so it can be applied before every fill');
// return shading;
}, },
getTilingPattern: function(pattern, dict, color) { getTilingPattern: function(pattern, dict, color) {
function multiply(m, tm) { function multiply(m, tm) {
@ -4315,13 +4395,16 @@ var CanvasGraphics = (function() {
this.ctx.strokeStyle = this.makeCssRgb(r, g, b); this.ctx.strokeStyle = this.makeCssRgb(r, g, b);
}, },
setFillRGBColor: function(r, g, b) { setFillRGBColor: function(r, g, b) {
this.ctx.fillStyle = this.makeCssRgb(r, g, b); var color = this.makeCssRgb(r, g, b);
this.ctx.fillStyle = color;
this.current.fillColor = color;
}, },
setStrokeCMYKColor: function(c, m, y, k) { setStrokeCMYKColor: function(c, m, y, k) {
this.ctx.strokeStyle = this.makeCssCmyk(c, m, y, k); this.ctx.strokeStyle = this.makeCssCmyk(c, m, y, k);
}, },
setFillCMYKColor: function(c, m, y, k) { setFillCMYKColor: function(c, m, y, k) {
this.ctx.fillStyle = this.makeCssCmyk(c, m, y, k); var color = (new DeviceCmykCS()).getRgb([c, m, y, k]);
this.setFillRGBColor.apply(this, color);
}, },
// Shading // Shading
@ -4341,7 +4424,7 @@ var CanvasGraphics = (function() {
var shadingFill = this.getShading(shading); var shadingFill = this.getShading(shading);
this.save(); this.save();
ctx.fillStyle = shadingFill; ctx.fillStyle = shadingFill.patternFn.apply(this, ctx);
var inv = ctx.mozCurrentTransformInverse; var inv = ctx.mozCurrentTransformInverse;
if (inv) { if (inv) {
@ -4455,8 +4538,6 @@ var CanvasGraphics = (function() {
}, },
getRadialShading: function(sh, cs) { getRadialShading: function(sh, cs) {
var coordsArr = sh.get('Coords'); 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; var t0 = 0.0, t1 = 1.0;
if (sh.has('Domain')) { if (sh.has('Domain')) {
@ -4478,22 +4559,51 @@ var CanvasGraphics = (function() {
error('Invalid function'); error('Invalid function');
var fn = new PDFFunction(this.xref, fnObj); 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 // 10 samples seems good enough for now, but probably won't work
// 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; var diff = t1 - t0;
var colorStops = [];
for (var i = t0; i <= t1; i += step) { for (var i = t0; i <= t1; i += step) {
var color = fn.func([i]); var color = fn.func([i]);
var rgbColor = cs.getRgb(color); var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color));
gradient.addColorStop((i - t0) / diff, colorStops.push([(i - t0) / diff, rgbColor]);
this.makeCssRgb.apply(this, rgbColor)); }
var patternMatrix = this.ctx.mozCurrentTransform;
return {
patternFn : function() {
var x0 = coordsArr[0], y0 = coordsArr[1], r0 = coordsArr[2];
var x1 = coordsArr[3], y1 = coordsArr[4], r1 = coordsArr[5];
// if the browser supports getting the tranform matrix, convert
// gradient coordinates from pattern space to current user space
if (patternMatrix) {
var userMatrix = this.ctx.mozCurrentTransformInverse;
var p = this.applyTransform(x0, y0, patternMatrix);
p = this.applyTransform(p[0], p[1], userMatrix);
x0 = p[0];
y0 = p[1];
var p = this.applyTransform(x1, y1, patternMatrix);
p = this.applyTransform(p[0], p[1], userMatrix);
x1 = p[0];
y1 = p[1];
}
var gradient =
this.ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
for (var i = 0, ii = colorStops.length; i < ii; ++i) {
var c = colorStops[i];
gradient.addColorStop(c[0], c[1]);
}
return gradient;
}
} }
return gradient;
}, },
// Images // Images
@ -4645,36 +4755,6 @@ var CanvasGraphics = (function() {
var bi = (255 * (1 - Math.min(1, y * (1 - k) + k))) | 0; var bi = (255 * (1 - Math.min(1, y * (1 - k) + k))) | 0;
return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
}, },
getFillColorSpace: function() {
var cs = this.current.fillColorSpace;
if (cs)
return cs;
var states = this.stateStack;
var i = states.length - 1;
while (i >= 0 && !(cs = states[i].fillColorSpace))
--i;
if (cs)
return cs;
else
return new DeviceRgbCS();
},
getStrokeColorSpace: function() {
var cs = this.current.strokeColorSpace;
if (cs)
return cs;
var states = this.stateStack;
var i = states.length - 1;
while (i >= 0 && !(cs = states[i].strokeColorSpace))
--i;
if (cs)
return cs;
else
return new DeviceRgbCS();
},
// We generally keep the canvas context set for // We generally keep the canvas context set for
// nonzero-winding, and just set evenodd for the operations // nonzero-winding, and just set evenodd for the operations
// that need them. // that need them.