RESOLVED INVALID 155288
Compositing layer is too large when inner element has a blur that is within bounds
https://bugs.webkit.org/show_bug.cgi?id=155288
Summary Compositing layer is too large when inner element has a blur that is within b...
Jon Lee
Reported 2016-03-09 21:11:36 PST
Created attachment 273543 [details] Sample test case See attached test case. The first example has: <div class="container"> <div class="particle" style="filter:blur(10px)"></div> </div> particle is fixed 80x80, the container is 100x100. The 10px blur should make the particle 100x100 large, but the compositing layer (see web inspector) shows a 136x136 layer. For example 2, the blur on the container should be 120x120, but it's 156x156 instead. It's strange in example 3 that the layer is 100x100, but the blur extends past. I think example 4 is correct?
Attachments
Sample test case (857 bytes, text/html)
2016-03-09 21:11 PST, Jon Lee
no flags
Simon Fraser (smfr)
Comment 1 2016-03-09 22:38:02 PST
For the first square: renderer().style().filterOutsets().expandRect(unionBounds); is adding 28px on each side for the 10px blur. This comes from outsetSizeForBlur() which has this comment: // We take the half kernel size and multiply it with three, because we run box blur three times. The kernel size is 19x19, which is computed by: unsigned size = std::max<unsigned>(2, static_cast<unsigned>(floorf(value * gaussianKernelFactor() + 0.5f))); where gaussianKernelFactor() returns 1.87997127 This is emulating the suggested approximation the SVG spec <https://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement>
Simon Fraser (smfr)
Comment 2 2016-03-09 23:01:59 PST
http://dbaron.org/log/20110225-blur-radius also explains this well. "The SVG feGaussianBlur filter primitive has a stdDeviation attribute, which takes the standard deviation (σ) of the Gaussian blur. So in SVG, the number given is half the number that you would give to get the same blur with CSS or canvas." I think when dbaron says "with CSS" he's referring to box-shadow. The CSS blur filter matches SVG. This means that "filter: blur(10px)" and "box-shadow: 0 0 10px black" don't match which is sad.
Simon Fraser (smfr)
Comment 3 2016-03-09 23:18:56 PST
For box-shadow we do this: // Blurring uses a Gaussian function whose std. deviation is m_radius/2, and which in theory // extends to infinity. In 8-bit contexts, however, rounding causes the effect to become // undetectable at around 1.4x the radius. const float radiusExtentMultiplier = 1.4; but recall that box-shadow's "radius" is actually 2 * sigma, so I think this agrees with the 3 * 1.87997127 / 2 = 2.82 for SVG.
Simon Fraser (smfr)
Comment 4 2016-03-09 23:26:45 PST
To summarize your test case: First square: filter: blur(10px) extends the 80x80 circle by a factor of 10 * (3 * 1.87997127 / 2) = 28px on each side, so the resulting layer size is correct. Second square: filter is composited, and extends the 100x100 container now by 28px per side, hence the 156x156. Third square: filters apply after overflow:hidden, so it's clipped, then blurred. Fourth square: filters apply after rect clipping, so it's clipped, then blurred.
Note You need to log in before you can comment on or make changes to this bug.