Summary: | Proposal: Add fillRule to canvas | ||
---|---|---|---|
Product: | WebKit | Reporter: | James Ascroft-Leigh <jwal> |
Component: | Canvas | Assignee: | Nobody <webkit-unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | Enhancement | CC: | abarth, a.renevier, cabanier, dglazkov, dino, eoconnor, ian, krit, ojan.autocc, syoichi, webkit.review.bot |
Priority: | P2 | ||
Version: | 528+ (Nightly build) | ||
Hardware: | All | ||
OS: | All | ||
URL: | https://github.com/mozilla/pdf.js/issues/2351 | ||
Attachments: |
Description
James Ascroft-Leigh
2012-12-20 01:30:42 PST
Created attachment 180299 [details]
First-cut patch to expose the webkitFillRule canvas property
The first patch was reversed. This one is in the correct direction.
Comment on attachment 180299 [details] First-cut patch to expose the webkitFillRule canvas property Attachment 180299 [details] did not pass chromium-ews (chromium-xvfb): Output: http://queues.webkit.org/results/15446050 New failing tests: inspector/profiler/canvas2d/canvas2d-api-changes.html Comment on attachment 180299 [details] First-cut patch to expose the webkitFillRule canvas property Attachment 180299 [details] did not pass chromium-ews (chromium-xvfb): Output: http://queues.webkit.org/results/15412983 New failing tests: inspector/profiler/canvas2d/canvas2d-api-changes.html I would like to see more discussion on the W3C and/or WHATWG lists before landing this. We generally only expose Web-facing API when it is in a draft specification, although it is interesting that Mozilla have an equivalent property. (In reply to comment #4) > I would like to see more discussion on the W3C and/or WHATWG lists before landing this. We generally only expose Web-facing API when it is in a draft specification, although it is interesting that Mozilla have an equivalent property. Yes, this new property will also intersect with the new Path API's. Comment on attachment 180299 [details] First-cut patch to expose the webkitFillRule canvas property Attachment 180299 [details] did not pass mac-ews (mac): Output: http://queues.webkit.org/results/15457292 New failing tests: inspector/profiler/canvas2d/canvas2d-api-changes.html Comment on attachment 180299 [details] First-cut patch to expose the webkitFillRule canvas property Attachment 180299 [details] did not pass mac-ews (mac): Output: http://queues.webkit.org/results/15456303 New failing tests: inspector/profiler/canvas2d/canvas2d-api-changes.html The reason it's not in the spec is that y'all haven't told the list that you're interested in implementing it — notice the emptiness under Safari/Chrome here for the "fillRule" row: http://wiki.whatwg.org/wiki/New_Features_Awaiting_Implementation_Interest (If you implement this exactly like Gecko has, don't prefix it, since that's then what I'll spec. If you want to do something different than Gecko, then mail the list and we'll figure out what it should be and then you can implement that, also without prefix. There shouldn't be a reason to put this in prefixed.) I'm happy to put my name down as an "interested implementer" but I have not contributed to WebKit before so I am not sure if it is appropriate for me to make any declaration on behalf of Apple or Google. I can confirm that my intention is for the property to behave the same way as mozFillRule and therefore I will rework the patch to name it fillRule (instead of the prefixed webkitFillRule). I have started to document my (evolving) understanding of exactly how this should work. This includes possible impacts on related areas of functionality that may need retesting after the implementation such as save(). https://github.com/jwal/webkit/wiki/fillRule-specification I think the acceptance tests we need are fairly obvious from what I have so far. Can anyone suggest something I have missed? Created attachment 180692 [details]
Patch to expose fillRule canvas property
Patch updated to expose the property as fillRule (instead of the prefixed webkitFillRule). I also tried to fix the failing test, let's see what the buildbot thinks of the change.
I am starting to add some automated tests for this new feature: https://github.com/jwal/html-testsuite/compare/master (In reply to comment #10) > I'm happy to put my name down as an "interested implementer" but I have not contributed to WebKit before so I am not sure if it is appropriate for me to make any declaration on behalf of Apple or Google. > > I can confirm that my intention is for the property to behave the same way as mozFillRule and therefore I will rework the patch to name it fillRule (instead of the prefixed webkitFillRule). You don't have to worry to make additions to WebKit. However, you should announce this feature on webkit-dev@lists.webkit.org so the WebKit development community is aware of your work. I agree with Ian that you shouldn't prefix your work. EOFill is a well understood, stable feature that won't change. (In reply to comment #12) > Created an attachment (id=180692) [details] > Patch to expose fillRule canvas property > > Patch updated to expose the property as fillRule (instead of the prefixed webkitFillRule). I also tried to fix the failing test, let's see what the buildbot thinks of the change. I think this feature needs more discussion. Specifically I'd like to not have the winding rule as part of the graphics state. There really is no reason since this is not a feature you want to have in the environment (like strokewidth, color, etc) What I'd like to see: - make the fill rule flag part of the path syntax - have separate eofill/eoclip for clipping/drawing with the current path - extend canvas prose so outlines are defined to be unaffected by winding rules. Thanks for the comments about the way this feature is exposed through the canvas API. I think that a discussion on this topic would be healthy but perhaps this is not the correct forum. I have just re-raised this proposal on the whatwg mailing list: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-January/038488.html Hopefully we will get some more comments from there this time around. Rik: As for your specific suggestions, clearly the eofill(), eoclip() and eoIsPointInPath() alternative would work. I don't know how to decide between the two proposals except that one of them is more easily compatible with the Mozilla Firefox prefixed implementation. As for the argument that the winding rule should not be part of the environment, I disagree that this would be a problem in practice. Although I am not an expert canvas programmer, my initial impressions are that the API itself is inherently a stateful one. As long as it is properly included in the state with save() and restore() then any client code wishing to make use of this feature wouldn't be much different for either of these APIs. On the other hand, the only code I have seen which currently makes use of this in pdf.js might benefit from an eofill() function [1] instead of a fillRule property. I suspect the reason it was added as a fillRule property in the first place was because this is how Cairo (a rendering backend used by Firefox) exposes the feature. How should we choose? [1] It seems to want an eofill() method: https://github.com/mozilla/pdf.js/blob/1826daa1d522bc17015098e79cee7c6ca8fd3b36/src/canvas.js#L648 I have also raised this on the webkit-dev@lists.webkit.org mailing list as suggested. http://lists.webkit.org/pipermail/webkit-dev/2013-January/023209.html (In reply to comment #17) > I have also raised this on the webkit-dev@lists.webkit.org mailing list as suggested. > > http://lists.webkit.org/pipermail/webkit-dev/2013-January/023209.html Great! It's probably best to continue the conversation there. I looked at Skia and they make winding part of the fill and clip call. (In reply to comment #18) > (In reply to comment #17) > > I have also raised this on the webkit-dev@lists.webkit.org mailing list as suggested. > > > > http://lists.webkit.org/pipermail/webkit-dev/2013-January/023209.html > > Great! It's probably best to continue the conversation there. > I looked at Skia and they make winding part of the fill and clip call. (In reply to comment #15) > (In reply to comment #12) > > Created an attachment (id=180692) [details] [details] > > Patch to expose fillRule canvas property > > > > Patch updated to expose the property as fillRule (instead of the prefixed webkitFillRule). I also tried to fix the failing test, let's see what the buildbot thinks of the change. > > I think this feature needs more discussion. > Specifically I'd like to not have the winding rule as part of the graphics state. There really is no reason since this is not a feature you want to have in the environment (like strokewidth, color, etc) > > What I'd like to see: > - make the fill rule flag part of the path syntax > - have separate eofill/eoclip for clipping/drawing with the current path > - extend canvas prose so outlines are defined to be unaffected by winding rules. fillRule is already part of our graphics state. IIRC it is the default behavior on most 2d graphics libraries. IMO it makes most sense to add an fillRule attribute instead of changing the path syntax. And even if we could have clipRule and fillRule as separate attributes, it should not be a big deal to use the same attribute for both operations. Maybe it means that fillRule should be renamed to windingRule. This is now in the spec. http://whatwg.org/html/#dom-context-2d-fillrule Comment on attachment 180692 [details] Patch to expose fillRule canvas property View in context: https://bugs.webkit.org/attachment.cgi?id=180692&action=review > Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp:427 > + WindRule rule; > + if (!parseFillRule(s, rule)) > + return; > + if (state().m_fillRule == rule) > + return; > + realizeSaves(); > + modifiableState().m_fillRule = rule; > + GraphicsContext* c = drawingContext(); > + if (!c) > + return; > + c->setFillRule(rule); This is the only interesting bit of this whole change. I don't feel up-to-date enough on GraphicsContext to review this part, but otherwise thsi chagne LGTM. > Source/WebCore/platform/graphics/GraphicsTypes.cpp:111 > + ASSERT(rule >= 0); > + ASSERT(rule < 2); > + const char* const names[2] = { "nonzero", "evenodd" }; > + return names[rule]; I might have written this as an if (rule == NonZero) return "nonzero"; return "evenodd", to avoid any possible OOB, but this is also fine. Created attachment 181308 [details]
Patch to expose fillRule canvas property
Rebase patch against trunk@138802
Comment on attachment 180692 [details] Patch to expose fillRule canvas property View in context: https://bugs.webkit.org/attachment.cgi?id=180692&action=review >> Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp:427 >> + c->setFillRule(rule); > > This is the only interesting bit of this whole change. I don't feel up-to-date enough on GraphicsContext to review this part, but otherwise thsi chagne LGTM. Indeed, and even this doesn't do very much apart from passing the call onto the lower level API. To be honest I didn't think too hard about what should be done at this point but I took the other similar functions in the file as a template for this function. For example https://github.com/jwal/webkit/blob/e8701c215ca234c43b119d3a3a1fe93f28deda34/Source/WebCore/platform/graphics/GraphicsTypes.cpp#L85 I tested this by creating a build of Chromium based on the modified WebKit and ran it on a) A modified version of the original webapp which originally led me to this missing feature b) Hand-crafted test case HTML files specifically for this new feature, based on canvas calls generated directly from the example SVG files in the SVG spec I thought it was sufficient, for now, to perform just these directed tests on Chromium on GNU/Linux on x86_64. >> Source/WebCore/platform/graphics/GraphicsTypes.cpp:111 >> + return names[rule]; > > I might have written this as an if (rule == NonZero) return "nonzero"; return "evenodd", to avoid any possible OOB, but this is also fine. I wrote it like this to be consistent with the other similar functions in this file. Sorry the patch does not apply cleanly any more, the base version was: https://github.com/jwal/webkit/blob/e8701c215ca234c43b119d3a3a1fe93f28deda34/Source/WebCore/platform/graphics/GraphicsTypes.cpp#L85 Update: After some discussion on the mailing list making this a fill-call-time option instead of a state property is being given the consideration it deserves. There is a counter proposal to this one: https://bugs.webkit.org/show_bug.cgi?id=106188 And there is also a proposal to change Mozilla Firefox to match that too: https://bugzilla.mozilla.org/show_bug.cgi?id=827053 I personally believe that setting the winding rule as an option on the fill() call is a better API and am glad to see we aren't rushing into implementing an API we are going to regret later. |