[whatwg] Enabling LCD Text and antialiasing in canvas

Stephen White senorblanco at chromium.org
Tue Mar 12 10:03:32 PDT 2013

Here's a draft of proposal (1) above:

Motivation:  Compositing a <canvas> element into the page can be expensive,
due to blending operations, and lack of opportunity for culling.  Since
arbitrary graphics operations can affect the opacity of the canvas, it is
difficult to determine programmatically whether the canvas is opaque.
 Allowing the developer to explicitly mark a canvas as opaque allows the
user agent to optimize blending at page composite time, as well to cull
fully-obscured elements behind the canvas.


The "opaque" attribute is a boolean attribute of the canvas element, whose
presence indicates that the alpha values in the canvas backing store must
be 1.0 at all times.  All canvas operations are modified to preserve this
invariant.  If the "opaque" attribute is not present, or if parsing its
value returns an error, then the default value (false) must be used instead.

When a canvas has the opaque attribute, the backing store must be
initialized to opaque black (rgba(0, 0, 0, 1.0)), instead of transparent
black (rgba(0, 0, 0, 0.0)).  Setting, changing, removing or setting the
attribute redundantly to its existing value causes the canvas to be cleared
to the appropriate value.

When a canvas has the opaque attribute, clearRect() clears to opaque black
instead of transparent black.

The behaviour of putImageData() and putImageDataHD() when a canvas has the
opaque attribute is to premultiply the RGB components by the alpha
component as usual, but write 1.0 into destination alpha.  In other words,
if (r, g, b, a) are the component values in a given pixel passed to
putImageData[HD](), then r' = ar, g' = ag, b' = ab are the colour
components of the resulting canvas pixel, and (r', g', b', 1.0) is written
to the canvas backing store.

When a canvas has the opaque attribute, all globalCompositeOperation modes
behave as normal and the resulting RGB components are written to the canvas
backing store, but the alpha component is left unchanged at 1.0.


On Tue, Mar 12, 2013 at 12:53 PM, Stephen White <senorblanco at chromium.org>wrote:

> On Mon, Mar 11, 2013 at 4:32 PM, Robert O'Callahan <robert at ocallahan.org>wrote:
>> On Tue, Mar 12, 2013 at 8:23 AM, Stephen White <senorblanco at chromium.org>wrote:
>>> On Mon, Mar 11, 2013 at 2:56 PM, Robert O'Callahan <robert at ocallahan.org
>>> > wrote:
>>>> On Tue, Mar 12, 2013 at 7:53 AM, Stephen White <
>>>> senorblanco at chromium.org> wrote:
>>>>> All other canvas functionality behaves as normal, including operations
>>>>> which modify the alpha values of the backing store.  However, any such
>>>>> transparency values will be ignored when compositing the canvas into the
>>>>> page, and the canvas will be treated as if every pixel has an alpha of 1.0.
>>>> That would mean getImageData can return non-1.0 alpha values, which is
>>>> probably not what you want to implement.
>>> That's what Firefox/Linux does (in fact, it always seems to return 0.0
>>> alpha from getImageData()).
>> We definitely shouldn't spec that! And I'm pretty sure that behavior
>> would vary across Firefox platforms. But we need to have consistent
>> behavior here.
>>  I considered three options:
>>> 1)  Prevent non-1.0 alpha ever getting into the canvas.  At a minimum,
>>> this would require the following:
>>>    - For putImageData, apply premultiplication, then write 1.0 alpha
>>>    into the canvas.
>>>    - Change initialization and clearRect() to clear to opaque black
>>>    instead of transparent black.
>>>    - Modify all canvas compositing modes to leave destination alpha
>>>    unchanged
>>> The latter is easy to do in OpenGL and CoreGraphics, but hard to do in
>>> Skia, and hard to do in accelerated CoreGraphics (IOSurfaces don't seem to
>>> support any opaque formats, although I could be wrong -- that was just from
>>> an hour or so of experimentation).  I'm not sure about Cairo.
>> You can always implement it slowly using readback. I think we should just
>> spec this, and maybe note that authors shouldn't use non-over operators on
>> opaque canvases. Over time we'll probably find a way to make it fast
>> everywhere.
> I'm a little leery of spec'ing something that has negative performance
> implications.  As an example, the "darker" compositing mode was removed
> from the spec due to hardware-accelerated performance concerns, IIRC.
>  OTOH, unlike that change, this spec should not have performance
> implications for OpenGL or Direct3D acceleration, only CoreGraphics via
> IOSurface and skia (so far).
> How would you feel about simply mapping the dest-alpha-modifying
> compositing modes to source-over, as in proposal 2) above?
> Stephen
>> 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]

More information about the whatwg mailing list