[whatwg] High-density canvases

On Wed, 17 Jul 2013, Rik Cabanier wrote:
> Ian wrote:
> >
> > The density aspect of this might be pointless, given the failure of 
> > getImageDataHD(); if we're dropping that one, I'll drop this one at 
> > the same time.
> Yes, please drop it since the HD methods are going away from the one 
> implementation.

On Tue, 9 Jul 2013, Stephen White wrote:
> Conversely, if it helps to bring the spec closer to the implementations, 
> one thing we do not intend to implement in Chrome is the automatic 
> high-DPI canvas scaling (ie., auto-doubling of backing stores, 
> getImageDataHD(), putImageDataHD(), etc).
> I believe Apple has also announced that they are dropping support for 
> this in Safari 7.

So my understanding is that the reason this feature failed is that there's 
existing content that assumes a 1:1 ratio, and having an automatic 
high-density mode was making some pages end up with canvases with four 
canvas pixels per CSS pixel (linearly) -- two from the browser making a 
native canvas, times two from the page scaling the canvas for high DPI 
displays. This is a factor of sixteen over a 1:1 canvas, a factor of four 
more than it should be for high DPI, and a big waste of resources.

As much as sites do this manually, though, it's a huge pain in the neck to 
have to worry about pixel density when you're creating your canvas and 
drawing on it, especially if you're not drawing sprites on it.

While we're talking about annoying things, there's also the annoyance that 
canvases tend to not take zoom into account (either density-affecting zoom 
like page zoom on desktop, or "transparent" zoom like pinch-zoom on mobile 
for non-mobile-optimised sites, which the site isn't supposed to know 
about): you have to remember to listen for onresize, and then manually 
blow away your canvas and recreate it at the right density and then 
squeeze it into place so that the coordinate space matches what your code 
is expecting while the <canvas> is actually sized for the display.

There's also the issue of full-bleed canvases where every time the 
container changes, you have to remember to re-update the canvas coordinate 
space and repaint because otherwise your pretty page gets all warped.

It would be nice to fix these all at once, and I think we can, by 
introducing a configuration option on getContext(), in the style of WebGL:

   getContext('2d', { density: 'autosize' });

This would trigger the following behaviour: When the context is created, 
and subsequently when the <canvas> changes size (e.g. due to being sized 
with CSS relative units and the element they're relative to changing), or 
when the display density changes size (e.g. due to page zoom), then:

   - the width and height of the canvas bitmaps get updated to match the
     new native size of the <canvas>, at native density.

   - the coordinate space of the canvas (context.width/context.height) 
     gets updated to match the size of the <canvas> in CSS pixel units.

   - a 'resize' event gets fired at the <canvas>.

We would dump the *HD versions of the methods, and make the regular ones 
go back to returning the actual raw pixels, since that would now work fine 
and still provide HD-quality content everywhere it's available.

What do people think?

Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

Received on Tuesday, 10 September 2013 00:00:55 UTC