- From: Rik Cabanier <cabanier@gmail.com>
- Date: Mon, 27 Jan 2014 10:26:26 -0800
- To: Joe Gregorio <jcgregorio@google.com>
- Cc: whatwg <whatwg@lists.whatwg.org>
On Fri, Jan 24, 2014 at 12:08 PM, Joe Gregorio <jcgregorio@google.com>wrote: > Rik, > From the Skia perspective we have the following feedback on the proposal. > Thanks for your feedback! > > While we can see how Shape2D can be implemented, it isn't clear that it's > such a large performance benefit over what Path provides, so we aren't > opposed to Shape2D, but don't believe implementing Path should be held up > for the sake of Shape2D. Path itself is a huge win for performance over > having only a single current default path and has utility without the > need > for Shape2D. > I agree. Maybe it's OK to have a staged approach where we introduce the concept of Path first and possible add shapes later. > In general we would like to see a layered approach to drawing objects, > starting with something primitive like Path, and at the most general a > Display List[1] that contains the full set of capabilities of > CanvasRenderingContext2D. That layering could be done in two or three > objects, either [Path, DisplayList] or [Path, Shape2D, DisplayList]. In > all > cases you can use the lower level objects to construct higher level > objects, > i.e. use one or more Paths to build a Shape2D, and use Paths and Shape2Ds > to > define a DisplayList. > That is an interesting concept. Do you have a more detailed proposal or a prototype in the works? At first blush, this seems more like streamlined SVG :-) What we'd like to see happen: > 1. Review the Path add* methods and possibly simplify them, see below. > 2. Keep the rest of the Path object and the Path related methods on the > CanvasRenderingContext2D. > 3. If Shape2D moves forward do it by adding different versions of fill, > clip, etc to CanvasRenderingContext2D, such as: > > void fill(optional CanvasFillRule fillRule = "nonzero"); > void fill(Path path, optional CanvasFillRule fillRule = "nonzero"); > void fill(Shape2D shape); > > 4. Possibly work on a DisplayList design, but only after some > experimentation. > > We have some particular feedback on the Shape2D design that is inline > below: > > [1] http://en.wikipedia.org/wiki/Display_list > > > All, > > > > around a year ago, I wrote a blog post [1] that introduced a new 'Shape' > > class that described a filled or stroked region or an area of text. > Java2D > > has a similar concept that they call 'Area' [2]. > > > > We've had some discussions but it doesn't look like there was any sort of > > conclusion. I'd like to pick it back up now that we have a partial > > implementation of the Path object and people are starting to look into > > extending it. > > > > I'll reiterate my proposal: > > 1. remove all the addxxx methods from the Path2D object [3] > > Path object are just containers for segments. Aggregating segments will > > generally not give the desired results since the segments will interact > > (see [1]). > > AddPath *could* be kept if people see a strong use case. > > The add* methods could be simplified to: > > void addPath(Path path, SVGMatrix? transformation); > void addPathByStrokingPath(Path path, CanvasDrawingStyles styles, > SVGMatrix? transformation); > void addText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? > transformation, unrestricted double x, unrestricted double y, optional > unrestricted double maxWidth); > void addTextAlongPath(DOMString text, CanvasDrawingStyles styles, > SVGMatrix? transformation, Path path, optional unrestricted double > maxWidth); > > The functionality of the addPathByStrokingText methods below can be done by > applying the above methods. > > void addPathByStrokingText(DOMString text, CanvasDrawingStyles styles, > SVGMatrix? transformation, unrestricted double x, unrestricted double y, > optional unrestricted double maxWidth); > void addPathByStrokingText(DOMString text, CanvasDrawingStyles styles, > SVGMatrix? transformation, Path path, optional unrestricted double > maxWidth); > My issue with this add* methods is that they likely will not do what an author expects since the path segments will interact in unexpected ways. In addition, I think no browser follows the spec for "tracing a path" [1]. Since paths will interact with the segments that that algorithm generates, we will get into interoperability issues. > > > > 2. introduce a new class 'Shape2D' > > Interface: > > > > [Constructor, > > Constructor(Path2D , CanvasWindingRule = "nonzero"), > > Constructor(Path2D , CanvasDrawingStyles, SVGMatrix?), // strokes a > path > > Constructor(DomString text, CanvasDrawingStyles, SVGMatrix?, > unrestricted > > double, unrestricted double, boolean isStroked = false, optional > > unrestricted double)] > > interface Shape2D{ > > Shape2D transform(matrix); // returns a transformed path > > Why not do this as another constructor? > > Constructor(Shape2D, SVGMatrix) > No particular reason. It's a bit more compact to do it with a method so you don't have to call 'new'. > > > Shape2D add(Shape2D); // returns a path that is the union of the 2 > paths > > Just to clarify, add() means a union of the two shapes, with no > side-effects > resulting from winding rules of the individual path? > Yes > > Shape2D seems reasonable and useful just as an immutable capture of all > "coverage" aspects of geometry. If add() is hard for platforms to support, > or > is expensive and clients don't know that, perhaps we can leave it out of > this > version. If we really want to have add(), why not include the full > compliment > of Set operations [ diff, xor, intersect ], which are no harder to > implement > (afaik) once you've implemented add(). > The reason I didn't add them, is that it's straightforward for implementation that don't have access to such a library. For instance, if there was a union of a fill and a stroke, you could call 'fill' and 'stroke' under the hood. > > > } > > > > This class will represent a painted area. Because it knows the winding > and > > stroking rules, the browser will be able to do expensive math in advance. > > It can also cache the region on the GPU. > > constructors: > > a. default constructor that creates an empty region > > b. constructor that take a path and a winding rule. This represents a > > filled region > > c. constructor that takes a path, canvasDrawingStyles object and a > matrix. > > This represent a stroked region. > > d. constructor that takes text + canvasDrawingStyles. This represent a > > region of filled or stroked text. > > > > methods: > > a. transform -> transform the shape by the matrix and returns a new shape > > b. add -> add the region of the shape to the current shape and return as > a > > new shape > > > > 3. Add new methods: > fill(Shape2D)/clip(Shape2D)/isPointInShape(Shape2D,...) > > > > 4. remove stroke(path), fill(path), clip(path), isPointInPath(path,...) > > > > 5. HitRegionOptions takes a Shape2D instead of a path + winding rule > > > > What do people think? > > > > > > 1: http://blogs.adobe.com/webplatform/2013/01/31/revised-canvas-paths/ > > 2: http://docs.oracle.com/javase/tutorial/2d/advanced/complexshapes.html > > 3: > 1: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#trace-a-path
Received on Monday, 27 January 2014 18:26:53 UTC