- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Wed, 14 Jul 2010 16:19:54 -0700
- To: Aryeh Gregor <Simetrical+w3c@gmail.com>
- Cc: "L. David Baron" <dbaron@dbaron.org>, Brad Kemper <brad.kemper@gmail.com>, Simon Fraser <smfr@me.com>, Brendan Kenny <bckenny@gmail.com>, www-style list <www-style@w3.org>
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