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

Rik Cabanier cabanier at gmail.com
Wed Jul 24 22:24:52 PDT 2013


On Wed, Jul 24, 2013 at 4:54 PM, Glenn Maynard <glenn at zewt.org> wrote:

> On Wed, Jul 24, 2013 at 1:25 PM, Rik Cabanier <cabanier at gmail.com> wrote:
>
>> sorry, that was a typo. I meant to say 'translate(.5, .5)' will offset
>> your fills.
>>
>
> (All I meant in the first place was that the pixel ratio isn't a factor
> here.  Maybe it's SVG that needs the ratio-dependent adjustment.)
>
>
>> That is very confusing. So, if there's a scale, you have to unapply the
>> scale to the .5 offset?
>>
>
> If there's a scale, the width of the stroke is going to be scaled too.  In
> that case, you either have to do adjustments across the board (no
> translation is going to make a 0.9-pixel stroke fill a pixel), or you need
> to do something like disabling antialiasing.
>
>
>>  I agree this isn't all that obvious.  What if there was an option for
>>> strokes to align themselves to the inside or outside of the path, instead
>>> of centering over the path?  That way, drawing 5x5-10x10 would cause both
>>> the stroke and the edge of the fill to be pixel-aligned.  This is
>>> Photoshop's "Position" stroke option, which can be set to "inside",
>>> "outside" or "center".  I don't know if that makes sense with the way paths
>>> work, and it would make the stroke's path dependent on its width.
>>>
>>
>> That's a cool feature, but doesn't solve the problem. Users would still
>> need to be aware that they need to align to whole pixels to stroke.
>>
>
> It solves the problem that it's a bit of a pain to have to supply
> edge-aligned coordinates when you're filling and centered coordinates when
> you're using a 1px stroke.  It eliminates the need to do any half-pixel
> offsetting at all in a lot of cases.
>
>
>> Do you mean Canvas transforms or higher-level transforms, like CSS
>>> scaling?  I don't think Canvas can help with the latter.
>>>
>>
>> Canvas transforms. I agree the resampling or transforming the canvas
>> bitmap after the fact is not something we can control.
>>
>>
>>> Non-integer pixel ratios lead to all kinds of aliasing and quality
>>> problems.  I suspect trying to fix them is futile...
>>>
>>
>> A lot of people have zoom turned on and there are quite a few devices
>> that have non-integer pixel ratios. I'd like to solve the problem
>> everywhere if possible.
>>
>
> If zoom is on, then that's the above: a compositing-stage transform that
> happens after rendering, which Canvas probably can't help with.
>
> If you have a non-integer pixel ratio, and no "HD" canvas backing store
> (it sounds like those may be getting dropped), then that seems like the
> same issue: the canvas will be rescaled at compositing time and there's
> nothing Canvas itself can do to prevent blurriness.  (The developer could
> still work around it by hand, by using a higher-resolution Canvas so the
> backing store doesn't actually get resized at compositing time.  They'll
> need to do this anyway, or everything will be blurry, not just strokes.)
>

Yes, that's what I had in mind: the developer detects the device pixel
ratio and scales up the canvas so the pixels match.


>
>
>
>>  In PDF there is a feature called "strokeAdjust" that will make the
>>>> stroke align to pixel boundaries. I've attached a drawing that shows the
>>>> feature. Basically, if you turn it on and the stroke doesn't fill the
>>>> entire pixel, that pixel isn't drawn.
>>>> Apple has a Core Graphics function called "CGGStateSetStrokeAdjust" so
>>>> at least they would be able to implement this easily. :-)
>>>>
>>>
>>> Isn't this simply disabling antialiasing?  That's what the illustration
>>> seems to show.
>>>
>>
>> It tells the renderer not to use over-scan but center-scan for strokes. I
>> was under the impression that GPU have centerscan by default and that
>> implementors have to add a bunch of code to work around this.
>>
>
> I don't follow the terminology, but from your image and description ("If
> there's less than a pixel total, you expand the stroke to at least a
> pixel", that sounds like disabling antialiasing (maybe only for certain
> lines).
>

It's more that the pixel is shrunk but is clamped to at least 1 pixel.

I asked our rendering people and it sounds like the feature is implemented
quite as described in the book. I'm still trying to find out the details...


>
>  That'll work in certain cases, with the caveats that have been
>>> mentioned: you don't want it when animating lines, for diagonals, if you
>>> have rounded corners, etc.
>>>
>>
>> I *think* we still alias in certain cases. I will check.
>>
>
> You could get more complex and turn off antialiasing for lines that aren't
> exactly vertical or horizontal.  I suspect that would cause odd issues; for
> example, seams at the boundary between a horizontal line and a rounded
> edge, or a rounded edge being dimmer than the hard edges it connects.  (I
> also don't know enough about paths and their implementations to know how
> feasible this is.)
>

Yeah, it's quite complex.


>
> It sounds complex and with its own problems, and the only case where it
> might help is if you want to draw hard lines after calling
> canvas.scale(0.9, 0.9), which seems uncommon to me.  In all typical cases,
> being able to set strokes to inside or outside seem to handle the rest (if
> that's something that fits in Canvas's path design; I don't know the
> algorithm).
>



More information about the whatwg mailing list