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

On Wed, Jan 9, 2013 at 10:27 AM, Dean Jackson <dino@apple.com> wrote:

>
> On 09/01/2013, at 4: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.
> >
> >>
> >> 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. 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'
>
> I prefer this approach over new methods.
>
> In general, I tend to agree with Rik that winding rule is a geometric
> operation, rather than a context style. It's a shame that this may
> introduce inconsistency (I appreciate Ian's point on that).


Thanks Dean!

Do people have an opinion on a boolean value vs an enum?
A boolean value is slightly faster to execute and type while an enum is
more descriptive.

So far, canvas has not used enum values before.


>
>
>
> >
> > 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'.
> >
> > 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.
> >
> > Greetings,
> > Dirk
> >
> >>
> >> 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 19:49:00 UTC