[whatwg] Blurry lines in 2D Canvas (and SVG)

Stephen White senorblanco at chromium.org
Fri Aug 9 19:58:49 PDT 2013

On Fri, Aug 9, 2013 at 8:16 PM, Rik Cabanier <cabanier at gmail.com> wrote:

> On Fri, Aug 9, 2013 at 2:17 PM, Stephen White <senorblanco at chromium.org>wrote:
>> I think one problem you might run into is that, if you consider a stroked
>> line to be centered on pixel centers rather than pixel edges, then the same
>> path when filled and stroked would touch different pixels along each edge.
>> Consider a 10x10 rectangle, drawn at coordinates coordinates 5, 5. If
>> filled, this would fill pixels 5-14 in X and 5-14 in Y. If stroked, this
>> will draw 1-pixel wide rectangles centered along (5, 5) -> (14, 5) -> (14,
>> 14) -> (5, 5). With antialiasing this will touch pixels 4->15 in each
>> dimension.  http://jsfiddle.net/6KS4V/
>> If the stroke was instead drawn centered over half pixels, the stroked
>> rects would be centered along (5.5, 5.5) -> (14.5, 5.5) -> (14.5, 14.5) ->
>> (14.5, 5.5) -> (5.5, 5.5). This would touch pixels 5->15 in each dimension.
>> If drawn with transparency, the resulting left and top edges would look
>> different than the bottom and right edges.  E.g.,
>> http://jsfiddle.net/9xbkX/.
>> (Please ignore blurriness induced by the CSS upscaling; you can remove
>> the CSS and use a zooming tool if you prefer).
> Yes, I agree that strokes and fills should be treated the same to avoid
> this problem.
> I'm unsure if Glenn's suggestion for an outer and inner stroke fix the
> problem. An inner or outer stroke will look very different.

Sure, but it's up to the developer to choose. It looks like Illustrator has
something very similar; see the "Align Stroke" buttons here:
I don't have a copy of Illustrator to try it, though.

In addition if the corners of the path don't align with the grid, you will
> get a blurry outline again.

Well, as long as you choose the right mitering style, I think the corners
would be fine. It's basically the same algorithm as normal path stroking,
except instead of translating half the stroke width on either side of the
path along the tangent, you'd just use the path as one edge and translate
the other the full stroke width.

As an experiment, I drew 4 rectangles in JSFiddle with stroke width of .5,
> .75, 1, 1.5 and 2: http://jsfiddle.net/6KS4V/2/
> I aligned them to the grid as Glenn suggested.
> This is a blown up screenshot from IE (Firefox looked the same):
> http://bit.ly/16FVCKd
> and here's one from Chrome: http://bit.ly/19Tf9Ko
> The rectangle that's 2 points wide is somewhat blurry, but the one that is
> 1.5  is very bad.
> Chrome seems ignore stroke widths that are smaller than 1 (which is
> reasonable).

I think this more like what the "outer" stroke style would do:

The interior rectangle is the same in each one, with the outer edge nudged
outwards along the tangent (the sizes may be wrong for the <1 lineWidth
cases; I didn't spend too long on it).


> I then recreated the content in Illustrator, opened the file in Acrobat
> and took a screenshot: http://bit.ly/15loBhu
> As you can see, Acrobat doesn't apply any anti-aliasing. It seems to
> 'snap' the points to the grid and adjust the stroke width so it fills whole
> pixels. I ran some experiments and I *think* this is also what CSS does.
> I believe that this could be accomplished with a new attribute in the
> graphics state. Doing it programmatically should also work but is quite
> difficult.
> I wonder if our mozilla friends that work on shumway and pdf.js are
> running into this...

More information about the whatwg mailing list