[whatwg] Stroking algorithm in Canvas 2d

Ian Hickson ian at hixie.ch
Thu Oct 10 11:29:03 PDT 2013


On Thu, 10 Oct 2013, Jasper St. Pierre wrote:
> >
> > If there's a good reason to do this, other than "we've always done it 
> > this way", then it's certainly a good thing to consider. If none of 
> > the browsers are willing to implement it the way the spec describes 
> > it, that's also a reason to change the spec. But just that it's always 
> > been done that way isn't a reason at all.
> 
> Differentiating from the drawing model we've always been used that can 
> easily be used by their underlying libraries seems like churn for both 
> people used to vector graphics libraries (a number of people using cairo 
> are porting their projects over to <canvas>), and implementers.

Sure, but if it results in a better model overall, it seems worth it.

The problem I see with the "reset at every move" model is that there's no 
way to _not_ reset at every move. As Justin points out, you could easily 
adjust the "no-reset" model to reset by just inserting annotations into 
the path that cause it to reset.


On Thu, 10 Oct 2013, Justin Novosad wrote:
> >
> >    http://goo.gl/hwK7fv
> 
> So in the case of a box, it makes perfect sense for the corners to be 
> start/stop points in the dashing pattern.  It gives a reassuring sense 
> of symmetry to the drawing.

That would be a third dashing model, different from both the spec and 
Rik's proposal.


> On the other hand, if you are drawing a continuous curve in a graphing 
> application, you would want constant density in the dashing pattern even 
> though the curve way be built from a series of subpaths.

Right, that's the basis on which I wrote the proposal in the spec.


> The algorithm suggested by Rik allows for both, but is not ideal.

Rik's proposal is different from both of those, as I see it: it resets at 
every move, so the density will be biased towards the start of the dash 
pattern, and it doesn't reset at corners, so it doesn't give the symmetry 
you mention above.


> Basically: dashing is continuous over joins. If you want to insert a 
> break point in the dashing pattern, you just end the current path and 
> start a new one, or break continuity by calling moveTo like you (Ian) 
> did in the fiddle cited above.

Right. That biases the density to the start of the pattern.


> The main issue I see with that algorithm is that it does not solve the 
> case where you would want a join and a dashing break at the same point. 
> I think that is an important case to support, in particular for drawing 
> rectangles.

It also doesn't support the case where you want a new subpath but not a 
break in the pattern.


> One way we could address this by adding a new path method that inserts a 
> break in the dashing pattern (without unjoining the subpaths).

That would solve one of the two limitations, yes.


> Also, I think it should be implicit in the rect() path primitive that 
> the corners are joined and that they are also stop/start points for the 
> dashing pattern.

If we provide the option to annotate the path in this way, we should 
probably just provide an argument to control that.


On Thu, 10 Oct 2013, Rik Cabanier wrote:
> > 
> > One way we could address this by adding a new path method that inserts 
> > a break in the dashing pattern (without unjoining the subpaths). Also, 
> > I think it should be implicit in the rect() path primitive that the 
> > corners are joined and that they are also stop/start points for the 
> > dashing pattern.
> 
> That would break current behavior . We will need a new API or additional 
> arguments (a dash array?)

Can you elaborate? What would break?


On Thu, 10 Oct 2013, Rik Cabanier wrote:
> 
> I think in your mind, you put the path down and then the stroke follows 
> that path. It's as if you take one continuous stroked and dashed line, 
> then cut it in pieces and then drape over the path.

Right.


> This is not how stroking works.

It's not how stroking works in PDF, but there's no reason that I can see 
that it shouldn't be how stroking works.

Why is your model superior?


> > > They're not always lines though. What about curves?
> >
> > Curves are lines too. The spec uses the term "path", though.
> 
> We've touched on this before. Curves can't simply be offset and still be 
> bezier curves.
>
> For instance, if you take the following snippet of SVG:
> 
> <path fill="none" stroke="#000000" stroke-miterlimit="10"
> d="M50,150C50,50,82.908,42.906,150,62.886"/>
> 
> The outlined stroke will look like this:
> 
> <path d="M256.5,150h-1*c*0-47.957,7.732-76.057,24.333-88.435*c*18.433-13.744,47.57-7.718,76.31,0.841l-0.285,0.958
> *c*-38.963-11.603-60.816-11.894-75.427-0.998*C*264.104,74.54,256.5,102.386,256.5,150z"/>
> 
> Note how there are now 2 beziers on each edge to approximate the stroke.

I agree with what you're saying but I don't see why this is a problem.

Why is approximating a problem? It's not like we're doing pure math paths 
here, they're all approximated at the end of the day. The spec doesn't 
specify how you implement it exactly, it just requires that we have 
consistent results that, within the limitations of the hardware (e.g. only 
1 pixel for every 10 microns) are indistinguishable from the theoretical 
results.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'



More information about the whatwg mailing list