[whatwg] Enabling LCD Text and antialiasing in canvas

Stephen White senorblanco at chromium.org
Fri Feb 15 14:09:16 PST 2013

On Fri, Feb 15, 2013 at 2:37 PM, Robert O'Callahan <robert at ocallahan.org>wrote:

> On Sat, Feb 16, 2013 at 4:35 AM, Stephen White <senorblanco at chromium.org>wrote:
>> Even with these constraints, I don't think we can guarantee that it's
>> safe to use LCD AA text. Once you've drawn with LCD AA text, even if it's
>> safe at the time of drawing, there's no guarantee that it will be safe
>> later.  For instance, if you then drawImage() that canvas rotated into
>> another canvas, or even just full-page-zoom it, you'll see colour fringing.
>> Or apply CSS 2D or 3D transforms. There are also existing apps which use
>> canvas for 2D text glyphs, and then transform and place them rotated in
>> WebGL. Those will show colour fringing.
> This came up on the list earlier.
> Even within canvas, there may be a way to break it if the LCD AA text is
>> drawn first and a dest-alpha compositing mode is used overtop (I haven't
>> verified this though).
> I don't think that's a problem. All destination alpha values will be 1
> even after the subpixel AA test is painted, and you'll treat it as normal.

I was thinking something like this:

- draw subpixel AA text over an opaque background
- draw a partially-transparent rect with destination-atop mode over the
subpixel AA text

Now some of the subpixel AA text is still there, but the destination alpha
is non-1, so things will go bad when you composite into the page.  (At
least I think it will.. Porter-Duff makes my head spin sometimes.)

>  So I'm starting to think that LCD AA text really has to be opt-in, to
>> avoid breaking existing content. By opting it, you're agreeing that these
>> artifacts are acceptable for your app. For example, you know that even if
>> you're going to do a canvas-to-canvas draw, you're always going to draw at
>> 1:1 scale and no rotation.
> It's difficult to know that on a mobile browser or any other browser where
> you have some kind of fast zoom UI.
> The suggestion on the list earlier was to keep two versions of the canvas
> buffer: one with grayscale AA, another with subpixel AA, and composite with
> the subpixel AA buffer when we can do that safely, otherwise use the
> grayscale AA version. In many implementations there would be a performance
> hit for this, so it would make sense to have authors opt-in to that
> performance hit.

It would also be a needless performance hit if the developer knew that they
always wanted subpixel AA, and that their app would never fringe.

> Rob
> --
> Wrfhf pnyyrq gurz gbtrgure naq fnvq, “Lbh xabj gung gur ehyref bs gur
> Tragvyrf ybeq vg bire gurz, naq gurve uvtu bssvpvnyf rkrepvfr nhgubevgl
> bire gurz. Abg fb jvgu lbh. Vafgrnq, jubrire jnagf gb orpbzr terng nzbat
> lbh zhfg or lbhe freinag, naq jubrire jnagf gb or svefg zhfg or lbhe fynir
> — whfg nf gur Fba bs Zna qvq abg pbzr gb or freirq, ohg gb freir, naq gb
> tvir uvf yvsr nf n enafbz sbe znal.” [Znggurj 20:25-28]

So let me take a stab at a brief summary of the proposals so far, and the
pros and cons of each (correct me if I missed anything):

pro:  fairly easy to implement
pro:  no performance hit over regular rendering
pro:  many opportunities for optimization
pro:  catches all in-canvas cases of color fringing
con:  does not handle any out-of-canvas color fringing
con:  opt-in

automatic opacity detection
pro:  catches most (all?) cases of in-canvas color fringing
pro:  some opportunties for optimization (must be conservative in some
con:  does not catch color fringing on CSS transforms, canvas -> WebGL, etc

context attribute (something like:  context.textAntialising = { 'none',
'grayscale', 'subpixel' })
pro:  very easy to implement
pro:  no performance hit
con:  does not catch any cases of color fringing; completely up to web
con:  opt-in

deferred canvas rendering (collect commands into a buffer, flush buffer
only when compositing canvas to page, and decide on subpixel AA at that
pro:  catches all cases of color fringing
con:  in some cases, requires an infinite buffer (e.g., a canvas that never
clears, and only accumulates drawing frame-to-frame means you must
accumulate commands indefinitely)
con:  difficult to implement (e.g., canvas-to-canvas drawImage(), etc)
con:  may introduce performance hit due to re-rendering with and without
subpixel AA (in cases where you would rather have just gone without)

two buffers (one grayscale, one LCD AA)
pro:  handles all cases of color fringing
pro:  moderately easy to implement
con:  RAM (or VRAM) usage is doubled
con:  possibly-unnecessary performance hit
con:  must be opt-in

More information about the whatwg mailing list