[whatwg] Enabling LCD Text and antialiasing in canvas

Rik Cabanier cabanier at gmail.com
Tue Mar 12 14:36:07 PDT 2013

On Tue, Mar 12, 2013 at 10:03 AM, Stephen White <senorblanco at chromium.org>wrote:

> 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.
> Description:
> 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.

What does 'normal' mean? Is it 'composite with the usual formula' or
'composite with source-over'?

I still think a matteColor can accomplish the same and have the added
benefit of flexibility and easy of specification...

> 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