Re: [css3-background] Where we are with Blur value discussion

On Wed, Jul 14, 2010 at 2:16 PM, Aryeh Gregor <Simetrical+w3c@gmail.com> wrote:
> On Tue, Jul 13, 2010 at 7:49 PM, Tab Atkins Jr. <jackalmage@gmail.com> wrote:
>> Explaining it in terms of existing graphics libraries may help
>> implementors, but it does nothing for authors, who have no idea how
>> the graphics libraries work or what the relationship is between a
>> radius parameter and "how big my shadow will be".
>
> So what?  They can try it and see.

That part's not acceptable.  Authors win over implementors in general,
and in this case having the authors perform mental math or
guess-and-check every single time they use a shadow (or force them to
develop an intuition for it) versus implementors figuring out the
proper conversion once and putting that in their code isn't even a
contest.  Authors win.


> What the spec needs to do is
> define something that implementations can implement without ambiguity,
> pixel-perfect or indistinguishable from it.  There is no reason to
> settle here for less than a pixel-perfect description.  Opera and
> Chrome render the following document identically:
>
> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
> "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
> <svg xmlns="http://www.w3.org/2000/svg"><defs>
> <filter id="Gaussian_Blur"><feGaussianBlur in="SourceGraphic"
> stdDeviation="5"/></filter>
> </defs>
> <rect x="100" y="100" width="100" height="100"
> style="fill:black;filter:url(#Gaussian_Blur)"/>
> </svg>
>
> (Firefox doesn't seem to support feGaussianBlur.)  The following
> should render exactly the same as the SVG in all browsers, because
> HTML5 specifies an exact algorithm also based on Gaussian blurs:
>
> data:text/html,<!doctype html>
> <style>* { margin: 0 }</style>
> <canvas height="300" width="300"></canvas>
> <script>
> window.addEventListener('load', function () {
> context = document.getElementsByTagName("canvas")[0].getContext("2d");
> context.shadowBlur = 12.5;
> context.shadowOffsetX = 400;
> context.shadowOffsetY = 400;
> context.shadowColor = 'black';
> context.fillRect(-300, -300, 100, 100);
> }, false);
> </script>
>
> Opera displays it correctly, pixel-for-pixel.  Chrome and Firefox both
> seem to have buggy canvas shadow implementations, but that's clearly a
> bug in both of them, and I assume it will be fixed.
>
> Anyway, the point is, IMO it's a *must* to have pixel-perfect
> definitions here.  SVG and canvas already do.  If you want a length
> value here (which is reasonable but unfortunately doesn't match canvas
> or SVG), say that the standard deviation should be chosen so that the
> given length falls at the point where the shadow is exactly 95%
> transparent, or something.  But we need something precise.

To be frank, <canvas> has a sucky API in general.  SVG isn't known for
its author-friendliness either - writing SVG by hand is quite rare.
CSS is designed to be author-friendly, and should work hard to
maintain that as much as possible.

I like pixel-perfect specs, because they're ideal for testing, though
I can accept non-pixel-perfect as long as they give guarantees that
can be machine-tested.  If we're okay with saying that shadow blur
must be done via a gaussian blur, that's cool.  In that case we should
do exactly as you say, and define the gaussian by giving the length at
which the gaussian must hit 99% transparency or similar.

*However*, I'm pretty certain we can't do that.  Gaussian blurs can be
*expensive*, and drawing shadows in CSS is a perf-sensitive matter.
Safari found that out directly - they use CoreGraphics to provide a
true gaussian blur, and it causes pretty crazy perf hits on some pages
that misuse shadows, while Chrome/Linux's use of the Skia graphics
library (which produces ugly shadows at large sizes) zooms through
them.

That's fine.  Using an ugly-but-fast shadow for small sizes where it's
not noticeably different from the slow-but-pretty shadow is totally
cool.  Chrome/Linux should be doing something prettier when the shadow
is large, but that's a browser bug then, just like it's a browser bug
on Safari when their page render times go through the roof from them
using an expensive shadow algorithm at all times.

Further, even if we were to define that it *must* be a gaussian with
so-and-so stdev, that wouldn't guarantee pixel-perfection.  Computing
a *real* gaussian requires sampling every pixel in the canvas - each
pixel contributes a non-zero amount of weight out to infinity.
Particular graphics libraries, of course, approximate the gaussian
with a transformation kernel that's typically around 6 stdevs wide.
Given a sufficiently large shadow and blur, though, graphics libraries
that use different-sized kernels will produce detectably different
shadows.

In conclusion, I think it is *perfectly reasonable* for browsers to
use multiple types of shadow algorithms at their discretion*.  As spec
writers, we just need to do our part for authors and ensure that they
look approximately the same according to certain chosen metrics;
namely, that the shadow is a monotonic function, and the 99% point of
the function must occur at +/- 1% of the given length from the shadow
origin, or similar.  We can test that, and we can rely on browsers to
gradually do whatever maximizes the pretty/perf graph.

~TJ

* Heck, while we're all talking about gaussian blurs, *real shadows
aren't blurred by a gaussian*.  Real physical light is distributed
near a shadow edge via a subtly different function.  I see no reason
to prevent someone from using a more realistic shadow blur if they
want to burn the cycles on it.

Received on Wednesday, 14 July 2010 23:20:47 UTC