Commit 09358ab1 authored by Chris Harrelson's avatar Chris Harrelson Committed by Commit Bot

[SPv175] Add mask effect node for masked SVG roots.

Previously, this would crash.

Bug: 811269

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I672a77ef521537b2306ab174064c1af3e90df982
Reviewed-on: https://chromium-review.googlesource.com/938748Reviewed-by: default avatarFredrik Söderquist <fs@opera.com>
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539837}
parent fa165f60
<!doctype HTML>
<svg>
<rect width="100" height="100" fill="green"/>
</svg>
<!doctype HTML>
<svg mask="url(#m)">
<mask id="m">
<rect fill="white" width="100" height="100"/>
</mask>
<rect width="100" height="100" fill="green"/>
<rect width="100" height="100" fill="red" x="100"/>
</svg>
......@@ -29,8 +29,10 @@
#include "core/layout/LayoutAnalyzer.h"
#include "core/layout/LayoutEmbeddedContent.h"
#include "core/layout/LayoutView.h"
#include "core/layout/svg/LayoutSVGResourceMasker.h"
#include "core/layout/svg/LayoutSVGText.h"
#include "core/layout/svg/SVGLayoutSupport.h"
#include "core/layout/svg/SVGResources.h"
#include "core/layout/svg/SVGResourcesCache.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/SVGRootPainter.h"
......@@ -455,6 +457,19 @@ LayoutRect LayoutSVGRoot::LocalVisualRectIgnoringVisibility() const {
return LayoutRect(EnclosingIntRect(visual_rect));
}
bool LayoutSVGRoot::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const {
// The rule extends LayoutBox's instead of LayoutReplaced's.
if (!LayoutBox::PaintedOutputOfObjectHasNoEffectRegardlessOfSize())
return false;
if (SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(*this)) {
if (resources->Masker())
return false;
}
return true;
}
// This method expects local CSS box coordinates.
// Callers with local SVG viewport coordinates should first apply the
// localToBorderBoxTransform to convert from SVG viewport coordinates to local
......
......@@ -94,6 +94,8 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced {
const char* GetName() const override { return "LayoutSVGRoot"; }
bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const final;
private:
const LayoutObjectChildList* Children() const { return &children_; }
LayoutObjectChildList* Children() { return &children_; }
......@@ -140,11 +142,6 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced {
LayoutRect LocalVisualRectIgnoringVisibility() const override;
bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const final {
// The rule is the same as LayoutBox's instead of LayoutReplaced's.
return LayoutBox::PaintedOutputOfObjectHasNoEffectRegardlessOfSize();
}
void MapLocalToAncestor(
const LayoutBoxModelObject* ancestor,
TransformState&,
......
......@@ -99,4 +99,37 @@ TEST_F(LayoutSVGRootTest, VisualRectMappingWithViewportClipWithoutBorder) {
EXPECT_EQ(LayoutRect(80, 80, 100, 20), rect);
}
TEST_F(LayoutSVGRootTest,
PaintedOutputOfObjectHasNoEffectRegardlessOfSizeEmpty) {
SetBodyInnerHTML(R"HTML(
<svg id="svg" width="100.1%" height="16">
<rect width="100%" height="16" fill="#fff"></rect>
</svg>
)HTML");
const LayoutSVGRoot& root =
*ToLayoutSVGRoot(GetLayoutObjectByElementId("svg"));
EXPECT_TRUE(root.PaintedOutputOfObjectHasNoEffectRegardlessOfSize());
}
TEST_F(LayoutSVGRootTest,
PaintedOutputOfObjectHasNoEffectRegardlessOfSizeMask) {
SetBodyInnerHTML(R"HTML(
<svg id="svg" width="16" height="16" mask="url(#test)">
<rect width="100%" height="16" fill="#fff"></rect>
<defs>
<mask id="test">
<g>
<rect width="100%" height="100%" fill="#ffffff" style=""></rect>
</g>
</mask>
</defs>
</svg>
)HTML");
const LayoutSVGRoot& root =
*ToLayoutSVGRoot(GetLayoutObjectByElementId("svg"));
EXPECT_FALSE(root.PaintedOutputOfObjectHasNoEffectRegardlessOfSize());
}
} // namespace blink
......@@ -18,7 +18,7 @@ Optional<IntRect> CSSMaskPainter::MaskBoundingBox(
if (!object.IsBoxModelObject() && !object.IsSVGChild())
return WTF::nullopt;
if (object.IsSVGChild()) {
if (object.IsSVG()) {
SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(object);
LayoutSVGResourceMasker* masker = resources ? resources->Masker() : nullptr;
......
......@@ -669,15 +669,21 @@ static bool NeedsEffect(const LayoutObject& object) {
const bool is_css_isolated_group =
object.IsBoxModelObject() && style.IsStackingContext();
if (!is_css_isolated_group && !object.IsSVGChild())
if (!is_css_isolated_group && !object.IsSVG())
return false;
if (object.IsSVG()) {
// This handles SVGRoot objects which have PaintLayers.
if (object.IsSVGRoot() && object.HasNonIsolatedBlendingDescendants())
if (object.IsSVGRoot() && is_css_isolated_group &&
object.HasNonIsolatedBlendingDescendants())
return true;
if (SVGLayoutSupport::IsIsolationRequired(&object))
return true;
if (SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(object)) {
if (resources->Masker()) {
return true;
}
}
} else if (object.IsBoxModelObject()) {
if (PaintLayer* layer = ToLayoutBoxModelObject(object).Layer()) {
if (layer->HasNonIsolatedDescendantWithBlendMode())
......@@ -699,14 +705,6 @@ static bool NeedsEffect(const LayoutObject& object) {
if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation(style))
return true;
if (object.IsSVGChild()) {
if (SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(object)) {
if (resources->Masker())
return true;
}
}
if (object.StyleRef().HasMask())
return true;
......
......@@ -6,6 +6,7 @@
#include "core/html/HTMLIFrameElement.h"
#include "core/layout/LayoutTreeAsText.h"
#include "core/layout/svg/LayoutSVGRoot.h"
#include "core/paint/ObjectPaintProperties.h"
#include "core/paint/PaintPropertyTreePrinter.h"
#include "platform/graphics/paint/GeometryMapper.h"
......@@ -5177,4 +5178,26 @@ TEST_P(PaintPropertyTreeBuilderTest,
EXPECT_TRUE(ToLayoutBoxModelObject(target)->Layer()->NeedsRepaint());
}
TEST_P(PaintPropertyTreeBuilderTest, SVGRootWithMask) {
// SPv1 has no effect tree.
if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
return;
SetBodyInnerHTML(R"HTML(
<svg id="svg" width="16" height="16" mask="url(#test)">
<rect width="100%" height="16" fill="#fff"></rect>
<defs>
<mask id="test">
<g>
<rect width="100%" height="100%" fill="#ffffff" style=""></rect>
</g>
</mask>
</defs>
</svg>
)HTML");
const LayoutSVGRoot& root =
*ToLayoutSVGRoot(GetLayoutObjectByElementId("svg"));
EXPECT_TRUE(root.FirstFragment().PaintProperties()->Mask());
}
} // namespace blink
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