Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using even-odd fill on HTML canvas

Are there any open source libraries (JaveScript) that implement even-odd fill rule on canvas. If I try to implement it myself then how complex would it be (considering general case which has complex curves also) and would it hit on the performance (due to overhead of doing it for each pixel in JaveScript).

What are the methods for converting even-odd fill to non-zero winding (considering a generic solution that will work for every case). Once method I found was to divide the shape into all non-intersecting polygons and fill them separately.

One option is to use SVG and draw the SVG on canvas, but I also found that native SVG rendering is a bit slow on iPad, but is SVG slow even when I draw it on HTML canvas (on iPad)?

Thanks in advance

like image 643
Rahul Avatar asked Sep 16 '12 12:09

Rahul


2 Answers

See fill() method API:

   void ctx.fill();
   void ctx.fill(fillRule);
   void ctx.fill(path, fillRule);

fillRule can be "nonzero" or "evenodd"
--- "nonzero": The non-zero winding rule, which is the default rule.
--- "evenodd": The even-odd winding rule.

Browser compatibility:
--- IE 11+, Firefox 31+, Chrome are OK.
--- I didn't test on IE 9/10.
--- Use ctx.mozFillRule = 'evenodd'; with old Firefox 30/30-.

canvas fillRule evenodd nonzero

like image 35
cuixiping Avatar answered Sep 23 '22 13:09

cuixiping


I came across this question as I was looking for the same some time ago. That is, use a "evenodd" fill-rule inside a HTML canvas.

After a little research, and going through mailing lists and patches, I noticed that, as it turns out, recent versions of both Firefox and Chrome have support for this, but each in a different, browser-specific, way.

In Firefox it is a matter of using the mozFillRule attribute. Example:

//
// Firefox Example
//
// canv has the HTML canvas element
var ctx = canv.getContext("2d");
ctx.fillStyle = "#ff0000";
ctx.mozFillRule = 'evenodd';
ctx.beginPath();
ctx.moveTo(100, 10);
ctx.lineTo(40, 180);
ctx.lineTo(190, 60);
ctx.lineTo(10,60);
ctx.lineTo(160,180);
ctx.closePath();
ctx.fill();

In Chrome, you do it by passing the string evenodd as a parameter to the fill method. Example:

//
// Chrome Example
//
// canv has the HTML canvas element
var ctx = canv.getContext("2d");
ctx.fillStyle = "#ff0000";
ctx.beginPath();
ctx.moveTo(100, 10);
ctx.lineTo(40, 180);
ctx.lineTo(190, 60);
ctx.lineTo(10,60);
ctx.lineTo(160,180);
ctx.closePath();
ctx.fill('evenodd');

These are the two browsers I researched for, so I don't know about the state of this in other browers. Hopefully in the not-so-distant future we will be able to use this feature via the fillRule attibute that is now part of the HTML standard.

like image 179
E.D. Avatar answered Sep 21 '22 13:09

E.D.