In 2D canvas, determining whether a point is "inside" a path is currently
always done using the non-zero winding rule. I propose extending 2D canvas to
allow determining inside-ness using the even-odd rule. The motivation is
(1) Many/most 2D graphics libraries have this feature; canvas should have it
for completeness. Some other languages/libraries that support even-odd fill
(in alphabetical order): cairo, Direct2D, GDI, PDF, PostScript, Quartz, skia,
and SVG.
(2) While the nonzero-winding and even-odd rules are equivalent in the sense
that there's nothing that can be drawn with one that can't be drawn with the
other, some figures are simpler to draw with one rule instead of the other. We
should add even-odd fill for author convenience.
(3) Using one rule over the other may result in better performance, by
decomposing to less geometry.
The concrete proposal is
interface CanvasRenderingContext2D {
//...
attribute fillRule; // "nonzero", "evenodd" (default "nonzero")
//...
};
The names "nonzero" and "evenodd" were chosen to match the SVG specification
[1]. The SVG specification can be used as a reference for the semantics of
even-odd fill.
|fillRule| applies to all operations currently "hard-coded" to use the
nonzero-winding rule to determine inside-ness. The change proposed here is,
when computing inside-ness, use the rule currently specified by |fillRule|.
The default value of |fillRule| is "nonzero", for backwards compatibility. The
|fillRule| attribute is part of the canvas state saved by save() and restored
by restore(). Script attempting to set |fillRule| to a string not one of
"nonzero" or "evenodd", say "garbage", would have no effect (i.e. *not* change
the value of |fillRule|).
Mozilla has implemented this proposed spec as |mozFillRule| [2]. It will be
available in Firefox "Nightly" builds starting June 11th.
Cheers,
Chris
[1] http://www.w3.org/TR/SVG/painting.html#FillProperties
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=655926