Skip to content

Commit abc890a

Browse files
committed
Adds fill('evenodd') as alternative for mozFillRule
1 parent f87de63 commit abc890a

File tree

2 files changed

+52
-33
lines changed

2 files changed

+52
-33
lines changed

src/canvas.js

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
226226
this.current = new CanvasExtraState();
227227
this.stateStack = [];
228228
this.pendingClip = null;
229+
this.pendingEOFill = false;
229230
this.res = null;
230231
this.xobjs = null;
231232
this.commonObjs = commonObjs;
@@ -706,23 +707,43 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
706707
consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
707708
var ctx = this.ctx;
708709
var fillColor = this.current.fillColor;
710+
var needRestore = false;
709711

710712
if (fillColor && fillColor.hasOwnProperty('type') &&
711713
fillColor.type === 'Pattern') {
712714
ctx.save();
713715
ctx.fillStyle = fillColor.getPattern(ctx);
714-
ctx.fill();
715-
ctx.restore();
716+
needRestore = true;
717+
}
718+
719+
if (this.pendingEOFill) {
720+
if ('mozFillRule' in this.ctx) {
721+
this.ctx.mozFillRule = 'evenodd';
722+
this.ctx.fill();
723+
this.ctx.mozFillRule = 'nonzero';
724+
} else {
725+
try {
726+
this.ctx.fill('evenodd');
727+
} catch (ex) {
728+
// shouldn't really happen, but browsers might think differently
729+
this.ctx.fill();
730+
}
731+
}
732+
this.pendingEOFill = false;
716733
} else {
717-
ctx.fill();
734+
this.ctx.fill();
718735
}
719-
if (consumePath)
736+
737+
if (needRestore) {
738+
ctx.restore();
739+
}
740+
if (consumePath) {
720741
this.consumePath();
742+
}
721743
},
722744
eoFill: function CanvasGraphics_eoFill() {
723-
var savedFillRule = this.setEOFillRule();
745+
this.pendingEOFill = true;
724746
this.fill();
725-
this.restoreFillRule(savedFillRule);
726747
},
727748
fillStroke: function CanvasGraphics_fillStroke() {
728749
this.fill(false);
@@ -731,19 +752,17 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
731752
this.consumePath();
732753
},
733754
eoFillStroke: function CanvasGraphics_eoFillStroke() {
734-
var savedFillRule = this.setEOFillRule();
755+
this.pendingEOFill = true;
735756
this.fillStroke();
736-
this.restoreFillRule(savedFillRule);
737757
},
738758
closeFillStroke: function CanvasGraphics_closeFillStroke() {
739759
this.closePath();
740760
this.fillStroke();
741761
},
742762
closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
743-
var savedFillRule = this.setEOFillRule();
763+
this.pendingEOFill = true;
744764
this.closePath();
745765
this.fillStroke();
746-
this.restoreFillRule(savedFillRule);
747766
},
748767
endPath: function CanvasGraphics_endPath() {
749768
this.consumePath();
@@ -1707,29 +1726,26 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
17071726

17081727
consumePath: function CanvasGraphics_consumePath() {
17091728
if (this.pendingClip) {
1710-
var savedFillRule = null;
1711-
if (this.pendingClip == EO_CLIP)
1712-
savedFillRule = this.setEOFillRule();
1713-
1714-
this.ctx.clip();
1715-
1729+
if (this.pendingClip == EO_CLIP) {
1730+
if ('mozFillRule' in this.ctx) {
1731+
this.ctx.mozFillRule = 'evenodd';
1732+
this.ctx.clip();
1733+
this.ctx.mozFillRule = 'nonzero';
1734+
} else {
1735+
try {
1736+
this.ctx.clip('evenodd');
1737+
} catch (ex) {
1738+
// shouldn't really happen, but browsers might think differently
1739+
this.ctx.clip();
1740+
}
1741+
}
1742+
} else {
1743+
this.ctx.clip();
1744+
}
17161745
this.pendingClip = null;
1717-
if (savedFillRule !== null)
1718-
this.restoreFillRule(savedFillRule);
17191746
}
17201747
this.ctx.beginPath();
17211748
},
1722-
// We generally keep the canvas context set for
1723-
// nonzero-winding, and just set evenodd for the operations
1724-
// that need them.
1725-
setEOFillRule: function CanvasGraphics_setEOFillRule() {
1726-
var savedFillRule = this.ctx.mozFillRule;
1727-
this.ctx.mozFillRule = 'evenodd';
1728-
return savedFillRule;
1729-
},
1730-
restoreFillRule: function CanvasGraphics_restoreFillRule(rule) {
1731-
this.ctx.mozFillRule = rule;
1732-
},
17331749
getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
17341750
var inverse = this.ctx.mozCurrentTransformInverse;
17351751
// max of the current horizontal and vertical scale

test/features/tests.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,13 @@ var tests = [
362362
var ctx = canvas.getContext('2d');
363363
ctx.rect(1, 1, 50, 50);
364364
ctx.rect(5, 5, 41, 41);
365-
['fillRule', 'mozFillRule', 'webkitFillRule'].forEach(function (name) {
366-
if (name in ctx) ctx[name] = 'evenodd';
367-
});
368-
ctx.fill();
365+
366+
if ('mozFillRule' in ctx) {
367+
ctx.mozFillRule = 'evenodd';
368+
ctx.fill();
369+
} else {
370+
ctx.fill('evenodd');
371+
}
369372

370373
var data = ctx.getImageData(0, 0, 50, 50).data;
371374
var isEvenOddFill = data[20 * 4 + 20 * 200 + 3] == 0 &&

0 commit comments

Comments
 (0)