[whatwg] Blurry lines in 2D Canvas

Jasper St. Pierre jstpierre at mecheye.net
Fri Sep 27 14:38:56 PDT 2013


The issue here is that the canvas API does not specify how pixels are sited
on the canvas: if you imagine pixels as enlarged squares on a grid (shush,
I know), does an X coordinate of 5 name the center of the square, or the
intersection between 4th and 5th squares?

If we say that it names the center of the square itself, then we'll have
sharp strokes but blurry fills -- filling from x=5 to x=10 will only fill
half the area in the 5th square.
If we say that it names the intersection between the pixels then we'll have
blurry strokes but sharp fills.

For perspective, old APIs that didn't have support for antialiased graphics
like X11 and GDI say that it's the former, but the lack of antialiasing
made it not noticeable.

Modern APIs like cairo, Quartz 2D and Direct2D say it's the latter, and
stick by it. The recommended solution is either to use even line widths
with pixel-perfect coordinates or add 0.5 to all lines you draw so they're
offset by half a pixel. [0]

Neither of these are perfect solutions when you have transforms; perhaps
optional support for crisp lines or otherwise turning off AA would be a
good idea.

But whatever we do, we should certainly pick a pixel citing system (and I'd
highly suggest the latter) and make it explicit in the spec.

http://cairographics.org/FAQ/#sharp_lines


On Fri, Sep 27, 2013 at 5:21 PM, Ruben Rodriguez II <whatwg at therealcha0s.net
> wrote:

> I would just like to note that sometimes we do not WANT to draw precise
> shapes. :) Many people enjoy the aesthetic of 2d pixel-based graphics, and
> it should be a viable choice for the graphical style of a game, for
> instance. Canvas makes this more difficult, and it shouldn't be so!
>
> Why can't we have a global option to turn this off if we want to? I'm not
> trying to advocate for throwing away all antialiasing... I understand that
> most applications will probably want it by default, and agree with having
> it as the default.
>
> Basically all it is is http://www.whatwg.org/specs/**
> web-apps/current-work/**multipage/the-canvas-element.**
> html#image-smoothing<http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#image-smoothing>... except that we're not talking about scaling.
>
> On 09/05/2013 05:22 PM, Ian Hickson wrote:
>
>> On Tue, 23 Jul 2013, Rik Cabanier 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/
>>>
>> Not always, only if you don't draw the line aligned with the pixel grid
>> (e.g. you draw a diagonal line, or a horizontal or vertical line that
>> isn't centered in the middle of pixels on the pixels grid, or a horizontal
>> or vertical line whose width isn't an integral number of pixels, etc).
>>
>> The options, on a pixel grid display, are:
>>
>>   - don't honour the position precisely -- this leads to very ugly
>>     artifacts when animating (lines jerk around), and basically means that
>>     the graphics aren't accurate.
>>
>>   - instead of describing the shapes as vectors, describe them using
>>     programs that can adapt to the position and size they're being drawn
>>     at, such that they automatically snap to the pixel grid in a pretty
>>     fashion -- this is what fonts do.
>>
>>   - try to trick the eye by using anti-aliasing when things don't line up
>>     exactly on the pixel grid.
>>
>> The first two really aren't plausible options for <canvas>.
>>
>>
>> On Wed, 24 Jul 2013, Kornel Lesiński wrote:
>>
>>> For 1-pixel lines it could be fixed by allowing authors to specify that
>>> path should be stroked with lines aligned to inside/outside of the path
>>> (which is a useful feature on its own).
>>>
>> https://www.w3.org/Bugs/**Public/show_bug.cgi?id=22674<https://www.w3.org/Bugs/Public/show_bug.cgi?id=22674>
>>
>>
>> On Tue, 23 Jul 2013, Rik Cabanier wrote:
>>
>>> Sure, but how can we fix this?
>>>
>> What is there to fix? The options above are basically the only options.
>> You can't not do one of them -- there's no way to draw a crisp line that
>> isn't pixel aligned. There's no pixels there. Similarly, there's no way to
>> draw a line that's neither horizontal nor vertical yet is crisp and
>> doesn't look jaggy. The pixels are squares, they don't rotate on modern
>> pixel displays.
>>
>>
>> On Wed, 24 Jul 2013, Kornel Lesiński wrote:
>>
>>> Should arc() and bezier curves also be snapped? What if you want a line
>>> that touches the curve?
>>>
>> That's precisely the problem with snapping -- it is far worse than
>> antialiasing. You can't draw precise shapes if you have snapping.
>>
>>
>> On Wed, 24 Jul 2013, Dirk Schulze wrote:
>>
>>> 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.
>>>
>> Indeed.
>>
>>
>>
>> On Sat, 10 Aug 2013, Rik Cabanier wrote:
>>
>>> I was wondering if this is something that happens in Flash as well. It
>>> turns out that there's an option called "hinting: Keep stroke anchors on
>>> full pixels to prevent blurry lines." There's a blog post on what this
>>> does:
>>> http://www.kaourantin.net/**2005/08/stroke-hinting-in-**
>>> flash-player-8-aka.html<http://www.kaourantin.net/2005/08/stroke-hinting-in-flash-player-8-aka.html>
>>> <http://www.kaourantin.net/**2005/08/stroke-hinting-in-**
>>> flash-player-8-aka.html<http://www.kaourantin.net/2005/08/stroke-hinting-in-flash-player-8-aka.html>
>>> >
>>>
>>> I created an example (in flash sorry) that shows the feature:
>>> http://cabanier.github.io/**BlendExamples/pixelsnap/**pixelsnap.html<http://cabanier.github.io/BlendExamples/pixelsnap/pixelsnap.html>
>>> 2 sets of strokes move across the screen and are also scaled.
>>>
>>> The top strokes behave like canvas does today. They start of blurry and
>>> during the animation they slowly get ticker. For some reason it doesn't
>>> look very smooth.
>>> The bottom strokes have hinting turned on. They are sharp at the
>>> beginning
>>> and during the animation they stay the same size until the internal
>>> stroke
>>> width is large enough. At that point you see a 'jump'.
>>>
>>> I think canvas should have a similar feature...
>>>
>> Can you elaborate on how exactly you would want this to work? How would
>> you avoid the alignment and distortion problems when applying this to
>> anything less trivial than a rectangle?
>>
>>
>


-- 
  Jasper



More information about the whatwg mailing list