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

Dirk Schulze dschulze at adobe.com
Wed Jul 24 03:13:14 PDT 2013


On Jul 24, 2013, at 7:19 AM, Rik Cabanier <cabanier at gmail.com> wrote:

> On Tue, Jul 23, 2013 at 6:20 PM, Glenn Maynard <glenn at zewt.org> wrote:
> 
>> (The below is about Canvas only; I'm not very familiar with SVG.  I think
>> they should be two separate discussions.)
>> 
> 
> Agreed. Sorry to confuse the issue.
> 
> 
>> 
>> On Tue, Jul 23, 2013 at 6:19 PM, Rik Cabanier <cabanier at gmail.com> wrote:
>> 
>>> we've noticed that if you draw lines in canvas or SVG, they always end up
>>> blurry.
>>> For instance see this fiddle: http://jsfiddle.net/V92Gn/128/
>>> 
>>> This happens because you offset 1 pixel and then draw a half pixel stroke
>>> on each side. Since it covers only half the pixel, the color gets mapped
>>> to
>>> 50% gray.
>>> You can work around this by doing an extra offset of half the
>>> devicepixelratio,
>> 
>> 
>> For Canvas, you should always add 0.5, since you're in the canvas
>> coordinate space, before the pixel ratio is applied.
>> 
> 
> That seemed like an OK idea until I thought about it some more.
> Doing a .5 scale will also affect your fills so a rect will now have
> aliased borders.
> 
> Also adjusting for non-round device pixel ratio or as Kornel mentions,
> having transforms will still result in blurry lines (unless you do a bunch
> of math)
> 
> 
>> 
>> This is the same coordinate system used by OpenGL and Direct3D 10 (and
>> up), with pixels centered around 0.5x0.5.  That is, a pixel sits between
>> 0x0 and 1x1.  If you're specifying the center of the line (eg. where the
>> stroke grows outwards from), you need to add a half pixel.  (When you're
>> specifying a bounding box, such as drawImage, you don't, since you're at
>> the edge rather than the center of a pixel.)
>> 
>> I'm not sure if there's a way to disable antialiasing for paths.
>> Disabling antialiasing to allow people to specify wrong coordinates only
>> seems like it would be more confusing, though.
>> 
> 
> Disabling it is not a solution. The 'crispEdges' option does this and the
> results look bad.
> 
> 
>> The only solution is to educate people about when and why they need to add
>> a half pixel; even if there was a way to avoid this in general (I'm not
>> sure there is, for an API with Canvas's functionality), it's much too late
>> to change this.
>> 
> 
> I agree that we can't change this, but maybe we can add something to make
> it better.
> 
> In PDF there is a feature called "strokeAdjust" that will make the stroke
> align to pixel boundaries. Basically, if you turn it on strokeAdjust and
> the stroke doesn't fill the entire pixel, that pixel isn't drawn. If
> there's less than a pixel total, you expand the stroke to at least a pixel.
> 
> Apple has a Core Graphics function called "CGGStateSetStrokeAdjust" so they
> would be able to implement this easily. :-)

Means implementations would need to take viewport, transformations of the document, transformations on elements in the DOM hierarchy, zoom level, aspect ratio of the canvas, position of the canvas in the document, transformations in the canvas  and device pixel resolution into account to snap lines to the correct position on the individual device, right?Otherwise it sounds to be hard to guarantee that you don't see antialiased strokes and lines might snap more then just one device pixel. This would also be a problem for aligning shapes to each other in the canvas I guess.
What happens on the next transformation after a drawing operation. Say you draw a line that was snapped to the grid and then you do scale(1.1, 1.1). Shall the implementation redraw the canvas? After all it is an pixel image. A vector based drawing format would be better suited for such a task.

Greetings,
Dirk


More information about the whatwg mailing list