Adds fill('evenodd') as alternative for mozFillRule

This commit is contained in:
Yury Delendik 2013-05-03 18:47:40 -05:00
parent f87de639af
commit abc890a9be
2 changed files with 53 additions and 34 deletions

View File

@ -226,6 +226,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.current = new CanvasExtraState(); this.current = new CanvasExtraState();
this.stateStack = []; this.stateStack = [];
this.pendingClip = null; this.pendingClip = null;
this.pendingEOFill = false;
this.res = null; this.res = null;
this.xobjs = null; this.xobjs = null;
this.commonObjs = commonObjs; this.commonObjs = commonObjs;
@ -706,23 +707,43 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
consumePath = typeof consumePath !== 'undefined' ? consumePath : true; consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
var ctx = this.ctx; var ctx = this.ctx;
var fillColor = this.current.fillColor; var fillColor = this.current.fillColor;
var needRestore = false;
if (fillColor && fillColor.hasOwnProperty('type') && if (fillColor && fillColor.hasOwnProperty('type') &&
fillColor.type === 'Pattern') { fillColor.type === 'Pattern') {
ctx.save(); ctx.save();
ctx.fillStyle = fillColor.getPattern(ctx); ctx.fillStyle = fillColor.getPattern(ctx);
ctx.fill(); needRestore = true;
ctx.restore();
} else {
ctx.fill();
} }
if (consumePath)
if (this.pendingEOFill) {
if ('mozFillRule' in this.ctx) {
this.ctx.mozFillRule = 'evenodd';
this.ctx.fill();
this.ctx.mozFillRule = 'nonzero';
} else {
try {
this.ctx.fill('evenodd');
} catch (ex) {
// shouldn't really happen, but browsers might think differently
this.ctx.fill();
}
}
this.pendingEOFill = false;
} else {
this.ctx.fill();
}
if (needRestore) {
ctx.restore();
}
if (consumePath) {
this.consumePath(); this.consumePath();
}
}, },
eoFill: function CanvasGraphics_eoFill() { eoFill: function CanvasGraphics_eoFill() {
var savedFillRule = this.setEOFillRule(); this.pendingEOFill = true;
this.fill(); this.fill();
this.restoreFillRule(savedFillRule);
}, },
fillStroke: function CanvasGraphics_fillStroke() { fillStroke: function CanvasGraphics_fillStroke() {
this.fill(false); this.fill(false);
@ -731,19 +752,17 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.consumePath(); this.consumePath();
}, },
eoFillStroke: function CanvasGraphics_eoFillStroke() { eoFillStroke: function CanvasGraphics_eoFillStroke() {
var savedFillRule = this.setEOFillRule(); this.pendingEOFill = true;
this.fillStroke(); this.fillStroke();
this.restoreFillRule(savedFillRule);
}, },
closeFillStroke: function CanvasGraphics_closeFillStroke() { closeFillStroke: function CanvasGraphics_closeFillStroke() {
this.closePath(); this.closePath();
this.fillStroke(); this.fillStroke();
}, },
closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() { closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
var savedFillRule = this.setEOFillRule(); this.pendingEOFill = true;
this.closePath(); this.closePath();
this.fillStroke(); this.fillStroke();
this.restoreFillRule(savedFillRule);
}, },
endPath: function CanvasGraphics_endPath() { endPath: function CanvasGraphics_endPath() {
this.consumePath(); this.consumePath();
@ -1707,29 +1726,26 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
consumePath: function CanvasGraphics_consumePath() { consumePath: function CanvasGraphics_consumePath() {
if (this.pendingClip) { if (this.pendingClip) {
var savedFillRule = null; if (this.pendingClip == EO_CLIP) {
if (this.pendingClip == EO_CLIP) if ('mozFillRule' in this.ctx) {
savedFillRule = this.setEOFillRule(); this.ctx.mozFillRule = 'evenodd';
this.ctx.clip();
this.ctx.clip(); this.ctx.mozFillRule = 'nonzero';
} else {
try {
this.ctx.clip('evenodd');
} catch (ex) {
// shouldn't really happen, but browsers might think differently
this.ctx.clip();
}
}
} else {
this.ctx.clip();
}
this.pendingClip = null; this.pendingClip = null;
if (savedFillRule !== null)
this.restoreFillRule(savedFillRule);
} }
this.ctx.beginPath(); this.ctx.beginPath();
}, },
// We generally keep the canvas context set for
// nonzero-winding, and just set evenodd for the operations
// that need them.
setEOFillRule: function CanvasGraphics_setEOFillRule() {
var savedFillRule = this.ctx.mozFillRule;
this.ctx.mozFillRule = 'evenodd';
return savedFillRule;
},
restoreFillRule: function CanvasGraphics_restoreFillRule(rule) {
this.ctx.mozFillRule = rule;
},
getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) { getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
var inverse = this.ctx.mozCurrentTransformInverse; var inverse = this.ctx.mozCurrentTransformInverse;
// max of the current horizontal and vertical scale // max of the current horizontal and vertical scale

View File

@ -362,10 +362,13 @@ var tests = [
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
ctx.rect(1, 1, 50, 50); ctx.rect(1, 1, 50, 50);
ctx.rect(5, 5, 41, 41); ctx.rect(5, 5, 41, 41);
['fillRule', 'mozFillRule', 'webkitFillRule'].forEach(function (name) {
if (name in ctx) ctx[name] = 'evenodd'; if ('mozFillRule' in ctx) {
}); ctx.mozFillRule = 'evenodd';
ctx.fill(); ctx.fill();
} else {
ctx.fill('evenodd');
}
var data = ctx.getImageData(0, 0, 50, 50).data; var data = ctx.getImageData(0, 0, 50, 50).data;
var isEvenOddFill = data[20 * 4 + 20 * 200 + 3] == 0 && var isEvenOddFill = data[20 * 4 + 20 * 200 + 3] == 0 &&