WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
NEW
196295
Changing a drop shadow filter does not render properly outside of element boundaries
https://bugs.webkit.org/show_bug.cgi?id=196295
Summary
Changing a drop shadow filter does not render properly outside of element bou...
Tom Bigelajzen
Reported
2019-03-27 08:03:45 PDT
Created
attachment 366070
[details]
how the shadow looks on Safari 12.1 when values changed Use case: - Add an Element (not square preferably) - Apply a drop-shadow() filter to it - Change the drop shadow values with Javascript Actual: The drop shadow refreshes only in the boundaries of the Element but not outside of it Expected: Should repaint the entire shadow Link:
https://codepen.io/tombigel/pen/QoXjEN
I created this pen to play with drop shadow so it's a bit of an overkill but if you change any param you will see the issue (see screenshot) Tested on: Does not recreate on Chrome, Firefox, Safari 12.0.3 Recreates on Safari 12.1, Safari Technology Preview 78 Notes: I also encountered a similar bug only on Safari 12.1+ with animating -webkit-clip-path, hadn't had time to create a simple test case for it
Attachments
how the shadow looks on Safari 12.1 when values changed
(43.47 KB, image/png)
2019-03-27 08:03 PDT
,
Tom Bigelajzen
no flags
Details
Small testcase
(889 bytes, text/html)
2021-10-21 20:41 PDT
,
Simon Fraser (smfr)
no flags
Details
View All
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2019-03-28 11:31:41 PDT
<
rdar://problem/49387957
>
Simon Fraser (smfr)
Comment 2
2019-03-28 12:00:47 PDT
Huh, I could have sworn this worked in the past.
Simon Fraser (smfr)
Comment 3
2019-03-28 21:10:33 PDT
I was thinking of box-shadow repainting. We don't have a code path that ensures correct repainting of layers with out-setting filters, for changes on the renderer with the filter, or descendants. We just get a RepaintLayer RenderStyle diff type, and call renderer.repaint(). Also we just do this in willChangeStyle, so we only ever repaint the "before" state of the filter when the style changes. What we'll need to do before and after the style change is to walk the ancestor RenderLayer chain and ensure that repaint rects get inflated for filters that move pixels.
Tom Bigelajzen
Comment 4
2021-06-16 05:18:20 PDT
Update 2021: Still recreates in 14.x Found a viable workaround - using "will-change: filter" On Chrome it breaks the shadow in a weird way so it's a partial workaround because it requires browser detection.
Simon Fraser (smfr)
Comment 5
2021-10-21 20:41:45 PDT
Created
attachment 442108
[details]
Small testcase
Simon Fraser (smfr)
Comment 6
2021-10-21 21:07:35 PDT
Need something like this: diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index d7990e430f10a0c962fe11483f9a55d67349431b..bf5946d3de53e610bc24ec3c9b6c848ef3f8b419 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -4860,7 +4860,8 @@ void RenderBox::addVisualEffectOverflow() bool hasBoxShadow = style().boxShadow(); bool hasBorderImageOutsets = style().hasBorderImageOutsets(); bool hasOutline = outlineStyleForRepaint().hasOutlineInVisualOverflow(); - if (!hasBoxShadow && !hasBorderImageOutsets && !hasOutline) + bool hasFilter = style().hasFilter(); + if (!hasBoxShadow && !hasBorderImageOutsets && !hasOutline && !hasFilter) return; addVisualOverflow(applyVisualEffectOverflow(borderBoxRect())); @@ -4901,6 +4902,16 @@ LayoutRect RenderBox::applyVisualEffectOverflow(const LayoutRect& borderBox) con overflowMinY = std::min(overflowMinY, borderBox.y() - ((!isFlipped || !isHorizontal) ? borderOutsets.top() : borderOutsets.bottom())); overflowMaxY = std::max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsets.bottom() : borderOutsets.top())); } + + if (style().hasFilter()) { + auto filterOutsets = style().filterOutsets(); + + // FIXME: For writing modes. + overflowMinX = std::min(overflowMinX, borderBox.x() - filterOutsets.left()); + overflowMaxX = std::max(overflowMaxX, borderBox.maxX() + filterOutsets.right()); + overflowMinY = std::min(overflowMinY, borderBox.y() - filterOutsets.top()); + overflowMaxY = std::max(overflowMaxY, borderBox.maxY() + filterOutsets.bottom()); + } if (outlineStyleForRepaint().hasOutlineInVisualOverflow()) { LayoutUnit outlineSize { outlineStyleForRepaint().outlineSize() }; diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp index 606c99b83dfb71b2682e91412745a6d0c3f6b124..f559b34a8bf0daf73f5ab2a42ff259f3bb55ab42 100644 --- a/Source/WebCore/rendering/style/RenderStyle.cpp +++ b/Source/WebCore/rendering/style/RenderStyle.cpp @@ -643,6 +643,10 @@ inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) c return visualOverflowForDecorations(*this, { }) != visualOverflowForDecorations(other, { }); } + // FIXME: Examine filters to determine if outsets changed. + if (filter() != other.filter()) + return true; + if (hasOutlineInVisualOverflow() != other.hasOutlineInVisualOverflow()) return true; return false;
Simon Fraser (smfr)
Comment 7
2025-06-05 17:23:45 PDT
***
Bug 202472
has been marked as a duplicate of this bug. ***
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug