Commit 148889ea authored by Fredrik Söderqvist's avatar Fredrik Söderqvist Committed by Commit Bot

Rework "SelfWillPaint-handling" in SVGContainerPainter

Check if the container has a filter effect property (with a reference
filter) before ensuring a paint chunk.
This both robust against paint-from-prepaint (crbug.com/848056) as well
as achieving the goal of the SelfWillPaint() check.
This also eliminates the last user of SelfWillPaint() so it and
SVGLayoutSupport::HasFilterResource() which it uses can be removed.

Bug: 109224, 848056, 1131498
Change-Id: Ic3da600c011d0a48bf562d9fea013e258d436e56
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2424187
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#810564}
parent 3c578027
......@@ -109,10 +109,6 @@ void LayoutSVGContainer::RemoveChild(LayoutObject* child) {
DescendantIsolationRequirementsChanged(kDescendantIsolationNeedsUpdate);
}
bool LayoutSVGContainer::SelfWillPaint() const {
return SVGLayoutSupport::HasFilterResource(*this);
}
void LayoutSVGContainer::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
LayoutSVGModelObject::StyleDidChange(diff, old_style);
......
......@@ -57,8 +57,6 @@ class LayoutSVGContainer : public LayoutSVGModelObject {
}
bool IsObjectBoundingBoxValid() const { return object_bounding_box_valid_; }
bool SelfWillPaint() const;
bool HasNonIsolatedBlendingDescendants() const final;
const char* GetName() const override { return "LayoutSVGContainer"; }
......
......@@ -436,12 +436,6 @@ FloatRect SVGLayoutSupport::ComputeVisualRectForText(
return visual_rect;
}
bool SVGLayoutSupport::HasFilterResource(const LayoutObject& object) {
SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(object);
return resources && resources->Filter();
}
bool SVGLayoutSupport::IntersectsClipPath(const LayoutObject& object,
const FloatRect& reference_box,
const HitTestLocation& location) {
......
......@@ -77,9 +77,6 @@ class CORE_EXPORT SVGLayoutSupport {
const FloatRect& text_bounds,
const FloatRect& reference_box);
// Determine if the LayoutObject references a filter resource object.
static bool HasFilterResource(const LayoutObject&);
// Determine whether the passed location intersects a clip path referenced by
// the passed LayoutObject.
// |reference_box| is used to resolve 'objectBoundingBox' units/percentages,
......
......@@ -19,12 +19,16 @@
namespace blink {
void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
// Spec: groups w/o children still may render filter content.
if (!layout_svg_container_.FirstChild() &&
!layout_svg_container_.SelfWillPaint())
return;
namespace {
bool HasReferenceFilterEffect(const ObjectPaintProperties& properties) {
return properties.Filter() &&
properties.Filter()->Filter().HasReferenceFilter();
}
} // namespace
void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
// Spec: An empty viewBox on the <svg> element disables rendering.
DCHECK(layout_svg_container_.GetElement());
auto* svg_svg_element =
......@@ -37,12 +41,13 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
return;
}
const auto* properties =
layout_svg_container_.FirstFragment().PaintProperties();
PaintInfo paint_info_before_filtering(paint_info);
if (SVGModelObjectPainter::ShouldUseInfiniteCullRect(
layout_svg_container_.StyleRef())) {
paint_info_before_filtering.ApplyInfiniteCullRect();
} else if (const auto* properties =
layout_svg_container_.FirstFragment().PaintProperties()) {
} else if (properties) {
if (const auto* transform = properties->Transform())
paint_info_before_filtering.TransformCullRect(*transform);
}
......@@ -54,11 +59,6 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
if (layout_svg_container_.IsSVGViewportContainer() &&
SVGLayoutSupport::IsOverflowHidden(layout_svg_container_)) {
const auto* fragment =
paint_info_before_filtering.FragmentToPaint(layout_svg_container_);
if (!fragment)
return;
const auto* properties = fragment->PaintProperties();
// TODO(crbug.com/814815): The condition should be a DCHECK, but for now
// we may paint the object for filters during PrePaint before the
// properties are ready.
......@@ -80,7 +80,7 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
// When a filter applies to the container we need to make sure
// that it is applied even if nothing is painted.
if (paint_state.GetPaintInfo().phase == PaintPhase::kForeground &&
layout_svg_container_.SelfWillPaint())
properties && HasReferenceFilterEffect(*properties))
paint_state.GetPaintInfo().context.GetPaintController().EnsureChunk();
for (LayoutObject* child = layout_svg_container_.FirstChild(); child;
......@@ -95,8 +95,11 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
}
}
SVGModelObjectPainter(layout_svg_container_)
.PaintOutline(paint_info_before_filtering);
// Only paint an outline if there are children.
if (layout_svg_container_.FirstChild()) {
SVGModelObjectPainter(layout_svg_container_)
.PaintOutline(paint_info_before_filtering);
}
if (paint_info_before_filtering.ShouldAddUrlMetadata() &&
paint_info_before_filtering.phase == PaintPhase::kForeground) {
......
<!doctype html>
<title>feImage referencing a child of the filter's target element</title>
<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
<svg>
<filter id='f1' x='0' y='0' width='1' height='1'>
<feFlood flood-color='green'/>
</filter>
<filter id='f2' x='0' y='0' width='1' height='1'>
<feImage href='#inner'/>
</filter>
<g filter='url(#f2)'>
<g id='inner' filter='url(#f1)'>
<rect width='50' height='50' fill='orange'/>
</g>
</g>
</svg>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment