Re: [whatwg] Proposal: Add CanvasRenderingContext2D.fillRule with "nonzero" (default) and "evenodd" options

On Tue, Jan 8, 2013 at 9:08 PM, Dirk Schulze <dschulze@adobe.com> wrote:

>
> On Jan 8, 2013, at 9:35 AM, Rik Cabanier <cabanier@gmail.com> wrote:
>
> > I looked at pdf2js which is using this fillRule property. As I expected,
> introduction of the property results in code like this:
> >     eoFill: function CanvasGraphics_eoFill() {
> >       var savedFillRule = this.setEOFillRule();
> >       this.fill();
> >       this.restoreFillRule(savedFillRule);
> >     },
> > ...
> >     // 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;
> >     },
> >
> > So, for even odd winding, all this code needs to run. With my proposal,
> this gets much simpler:
> >    eoFill: function CanvasGraphics_eoFill() {
> >       this.eoFill();
> >     },
> >
> > You can find a pull request with the needed changes to pdf2js here:
> >
> https://github.com/cabanier/pdf.js/commit/8e80b086376013a5438087714a4d2abb6fe67de1
>
> For PDF.js it would probably be easier to set the fillRule every time
> right before a fill or clip operation, then checking and storing the fill
> rule in the background. This would reduce the code a lot more.
>

that would be at the cost of setting it every time. pdf's can have tens of
thousands of fill calls...


>
> >
> > I also created patches (with test files) for WebKit and mozilla:
> > https://bugs.webkit.org/show_bug.cgi?id=106188
> > https://bugzilla.mozilla.org/show_bug.cgi?id=827053
>
> I looked at the patch for webkit. There are two parts where I would
> disagree and that are potentially confusing.
>
>         eoFill(), eoClip()
>
> It is not obvious what these functions do and how they are different to
> fill() and clip(). The name should be clear about the usage.


I don't disagree. I was simply mimicking what other graphics libraries
(such as Core Graphics) do.


> But I don't think that introducing two new functions to the Canvas API is
> a lot better either. An alternative proposal instead of new functions or
> attributes could be an optional argument for the fill() and stroke()
> functions. This argument would be an enumeration of 'nonzero' and 'evenodd'.
>
>         ctx.fill(); // fill with 'nonzero'
>         ctx.fill('nonzero') // fill with 'nonzero' as well
>         ctx.fill('evenodd') // fill with winding rule 'evenodd'
>
> The boolean argument in isPointInPath seems not to be very descriptive as
> well:
>
>         boolean isPointInPath(unrestricted double x, unrestricted double
> y, boolean windingRule);
>
> It is not obvious if 'true' means 'nonzero' or 'evenodd'. I would
> recommend to use an optional enumeration here, with the default value
> 'nonzero'.
>

That was an oversight on my part. I believe I called it 'isEvenOdd' with
the mozilla patch.

As for boolean vs enums, the canvas 2d API has not used enums before (see
for instance imageSmoothingEnabled or anticlockwise) so this would be a
first. Also, would there be a performance impact of having a string
argument for a call that happens very frequently?


>
> You mentioned that the winding rule should be a part of the Path object. I
> can see the use case that you want to address with it. And things like a
> union path of two path object with different winding rules (as you
> suggested before) is possible, as long as the union path just needs to get
> drawn (can be done with compositing or masking in the implementation). But
> the SVG WG would like to use the Path object as a way to share path data
> between Canvas and SVG. In this case, the implementation must be able to
> flatten a path and provide the path data directly. This is beyond the
> capability of current graphic libraries and requires third party
> planarizer. This needs to be considered before adding this functionality to
> the Path API.


I agree. My point was that the path object (as defined today) is not what a
user would expect since it just aggregates path segments.
What's really needed is a way to union, intersect and subtract paths. This
functionality is also needed to create stroke and text outlines.

There are libraries out there (such as skia, qt and lib2geom) that offer
this functionality but I'm unaware of the quality (or performance) of their
implementations.


>


> >
> > On Thu, Jan 3, 2013 at 3:38 PM, Ian Hickson <ian@hixie.ch> wrote:
> > On Fri, 10 Jun 2011, Chris Jones wrote:
> > >
> > > 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.
> >
> > I've added this to the spec.
> >
> >
> > On Wed, 2 Jan 2013, Dirk Schulze wrote:
> > >
> > > There was a complain on the webkit bug report if fillRule should be
> part
> > > of the graphics state or not. Did you investigate what current 2d
> > > graphics libraries do (qt, Cairo, CG, ...)? Is it part of the graphics
> > > state there?
> >
> > I have made it be part of the graphics state in the spec; it would be
> > unusual in the API for it not to be. However, if this doesn't match
> > implementations, please let me know.
> >
> >
> > On Wed, 2 Jan 2013, Rik Cabanier wrote:
> > >
> > > this features is not a trivial as it seems. Adding this will
> necessitate
> > > updates to the algorithms that deal with paths and the outlining of
> > > strokes and text.
> >
> > Can you elaborate on what updates are needed? I couldn't see any that
> > actually needed to be changed.
> >
> >
> > > As Dirk mentioned, instead of making it part of the graphics state,
> it's
> > > more likely better to make it part of the fill or clip operator like
> > > SVG, PDF and PostScript.
> >
> > That seems like it would be inconsistent with the rest of the canvas API.
> >
> >
> > > In addition, the path object will need to be extended so it can deal
> > > with this idiom.
> >
> > Can you elaborate on how this affects the Path object? It seems like it
> > would be somewhat orthogonal.
> >
> >
> > > The easiest way to implement this, would be to leave the core
> interface of
> > > canvas alone and just extend the path object with winding rules and a
> > > method to 'simplify' a path so it can be drawn with any winding rule.
> >
> > This doesn't seem like it would be easier... in particular, fillRule is
> > now implemented in two browsers, so the implementation cost for them
> would
> > be zero, and they don't yet implement Path at all, so the implementation
> > cost for Path would be quite high, even without "simplify". :-)
> >
> >
> > On Wed, 2 Jan 2013, Rik Cabanier wrote:
> > >
> > > However, just look at how stroke is implemented in the Canvas 2d spec
> or
> > > how you can create paths by stroking or stroked text. They're all
> > > affected by the winding rules.
> >
> > How so?
> >
> >
> > > (The description on how to do strokes in the spec is very wrong, but
> > > that can be addressed later)
> >
> > Can you elaborate on this? If there's a mistake obviously I'd like to fix
> > it...
> >
> >
> > > Dirk and I did a bit more research and found that SVG, PDF, Flash,
> > > PostScript, Skia, Core Graphics and Direct2D all have the winding rules
> > > as part of the fill operator. It seems strange that canvas would choose
> > > to have a different interface...
> >
> > People using the canvas API are more likely to know the canvas API, and
> > thus want extensions to be consistent with the canvas API, than they are
> > to be familiar with PDF, Flash, PostScript, Skia, Core Graphics, or
> > Direct2D. Incidentally, of those, I'm only familiar with SVG, and SVG is
> > similar to what I specced (indeed I don't see how it could be part of the
> > operator since it's a declarative language).
> >
> > --
> > Ian Hickson               U+1047E                )\._.,--....,'``.    fL
> > http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
> > Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
> >
>
>

Received on Wednesday, 9 January 2013 06:21:07 UTC