Commit 4aa10ab1 authored by Fredrik Söderqvist's avatar Fredrik Söderqvist Committed by Commit Bot

Introduce SVGContentContainer

Introduces a new child-content-management class for use by LayoutSVGRoot
and LayoutSVGContainer.

Moves shared child management code from SVGLayoutSupport to it, namely:

  LayoutChildren(),
  HitTestChildren(),
  ComputeHasNonIsolatedBlendingDescendants() and
  ComputeContainerBoundingBoxes()

Besides allowing nicer code-sharing (and thus depopulating
SVGLayoutSupport) it also allows better handling of derived, and other,
state relating to the collection of children.

Change-Id: I009a9bcde670fa6f994a9195b08f2f58683b5370
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2489643Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#819840}
parent 10498c98
...@@ -658,6 +658,8 @@ blink_core_sources_layout = [ ...@@ -658,6 +658,8 @@ blink_core_sources_layout = [
"svg/line/svg_root_inline_box.cc", "svg/line/svg_root_inline_box.cc",
"svg/line/svg_root_inline_box.h", "svg/line/svg_root_inline_box.h",
"svg/svg_character_data.h", "svg/svg_character_data.h",
"svg/svg_content_container.cc",
"svg/svg_content_container.h",
"svg/svg_layout_support.cc", "svg/svg_layout_support.cc",
"svg/svg_layout_support.h", "svg/svg_layout_support.h",
"svg/svg_layout_tree_as_text.cc", "svg/svg_layout_tree_as_text.cc",
......
...@@ -65,9 +65,7 @@ void LayoutSVGContainer::UpdateLayout() { ...@@ -65,9 +65,7 @@ void LayoutSVGContainer::UpdateLayout() {
GetElement()->HasRelativeLengths() && GetElement()->HasRelativeLengths() &&
SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this); SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this);
SVGLayoutSupport::LayoutChildren(FirstChild(), false, content_.Layout(false, did_screen_scale_factor_change_, layout_size_changed);
did_screen_scale_factor_change_,
layout_size_changed);
bool bbox_changed = false; bool bbox_changed = false;
if (needs_boundaries_update_) { if (needs_boundaries_update_) {
...@@ -144,7 +142,7 @@ bool LayoutSVGContainer::HasNonIsolatedBlendingDescendants() const { ...@@ -144,7 +142,7 @@ bool LayoutSVGContainer::HasNonIsolatedBlendingDescendants() const {
NOT_DESTROYED(); NOT_DESTROYED();
if (has_non_isolated_blending_descendants_dirty_) { if (has_non_isolated_blending_descendants_dirty_) {
has_non_isolated_blending_descendants_ = has_non_isolated_blending_descendants_ =
SVGLayoutSupport::ComputeHasNonIsolatedBlendingDescendants(this); content_.ComputeHasNonIsolatedBlendingDescendants();
has_non_isolated_blending_descendants_dirty_ = false; has_non_isolated_blending_descendants_dirty_ = false;
} }
return has_non_isolated_blending_descendants_; return has_non_isolated_blending_descendants_;
...@@ -180,9 +178,8 @@ void LayoutSVGContainer::Paint(const PaintInfo& paint_info) const { ...@@ -180,9 +178,8 @@ void LayoutSVGContainer::Paint(const PaintInfo& paint_info) const {
bool LayoutSVGContainer::UpdateCachedBoundaries() { bool LayoutSVGContainer::UpdateCachedBoundaries() {
NOT_DESTROYED(); NOT_DESTROYED();
auto old_object_bounding_box = object_bounding_box_; auto old_object_bounding_box = object_bounding_box_;
SVGLayoutSupport::ComputeContainerBoundingBoxes(this, object_bounding_box_, content_.ComputeBoundingBoxes(
object_bounding_box_valid_, object_bounding_box_, object_bounding_box_valid_, stroke_bounding_box_);
stroke_bounding_box_);
return old_object_bounding_box != object_bounding_box_; return old_object_bounding_box != object_bounding_box_;
} }
...@@ -201,8 +198,7 @@ bool LayoutSVGContainer::NodeAtPoint(HitTestResult& result, ...@@ -201,8 +198,7 @@ bool LayoutSVGContainer::NodeAtPoint(HitTestResult& result,
return false; return false;
if (!ChildPaintBlockedByDisplayLock() && if (!ChildPaintBlockedByDisplayLock() &&
SVGLayoutSupport::HitTestChildren(LastChild(), result, *local_location, content_.HitTest(result, *local_location, hit_test_action))
accumulated_offset, hit_test_action))
return true; return true;
// pointer-events: bounding-box makes it possible for containers to be direct // pointer-events: bounding-box makes it possible for containers to be direct
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_LAYOUT_SVG_CONTAINER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_LAYOUT_SVG_CONTAINER_H_
#include "third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h"
#include "third_party/blink/renderer/core/layout/svg/svg_content_container.h"
#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink { namespace blink {
...@@ -87,6 +88,7 @@ class LayoutSVGContainer : public LayoutSVGModelObject { ...@@ -87,6 +88,7 @@ class LayoutSVGContainer : public LayoutSVGModelObject {
NOT_DESTROYED(); NOT_DESTROYED();
return Children(); return Children();
} }
SVGContentContainer& Content() { return content_; }
bool IsOfType(LayoutObjectType type) const override { bool IsOfType(LayoutObjectType type) const override {
NOT_DESTROYED(); NOT_DESTROYED();
...@@ -119,14 +121,15 @@ class LayoutSVGContainer : public LayoutSVGModelObject { ...@@ -119,14 +121,15 @@ class LayoutSVGContainer : public LayoutSVGModelObject {
private: private:
const LayoutObjectChildList* Children() const { const LayoutObjectChildList* Children() const {
NOT_DESTROYED(); NOT_DESTROYED();
return &children_; return &content_.Children();
} }
LayoutObjectChildList* Children() { LayoutObjectChildList* Children() {
NOT_DESTROYED(); NOT_DESTROYED();
return &children_; return &content_.Children();
} }
LayoutObjectChildList children_; SVGContentContainer content_;
// TODO(fs): Some of this state can move to the "child list" object.
FloatRect object_bounding_box_; FloatRect object_bounding_box_;
FloatRect stroke_bounding_box_; FloatRect stroke_bounding_box_;
bool object_bounding_box_valid_; bool object_bounding_box_valid_;
......
...@@ -38,8 +38,7 @@ void LayoutSVGHiddenContainer::UpdateLayout() { ...@@ -38,8 +38,7 @@ void LayoutSVGHiddenContainer::UpdateLayout() {
GetElement()->HasRelativeLengths() && GetElement()->HasRelativeLengths() &&
SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this); SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this);
SVGLayoutSupport::LayoutChildren(FirstChild(), SelfNeedsLayout(), false, Content().Layout(SelfNeedsLayout(), false, layout_size_changed);
layout_size_changed);
UpdateCachedBoundaries(); UpdateCachedBoundaries();
ClearNeedsLayout(); ClearNeedsLayout();
} }
......
...@@ -249,9 +249,8 @@ void LayoutSVGRoot::UpdateLayout() { ...@@ -249,9 +249,8 @@ void LayoutSVGRoot::UpdateLayout() {
is_layout_size_changed_ = is_layout_size_changed_ =
viewport_may_have_changed && svg->HasRelativeLengths(); viewport_may_have_changed && svg->HasRelativeLengths();
SVGLayoutSupport::LayoutChildren(FirstChild(), false, content_.Layout(false, did_screen_scale_factor_change_,
did_screen_scale_factor_change_, is_layout_size_changed_);
is_layout_size_changed_);
if (needs_boundaries_or_transform_update_) { if (needs_boundaries_or_transform_update_) {
UpdateCachedBoundaries(); UpdateCachedBoundaries();
...@@ -409,7 +408,7 @@ bool LayoutSVGRoot::HasNonIsolatedBlendingDescendants() const { ...@@ -409,7 +408,7 @@ bool LayoutSVGRoot::HasNonIsolatedBlendingDescendants() const {
NOT_DESTROYED(); NOT_DESTROYED();
if (has_non_isolated_blending_descendants_dirty_) { if (has_non_isolated_blending_descendants_dirty_) {
has_non_isolated_blending_descendants_ = has_non_isolated_blending_descendants_ =
SVGLayoutSupport::ComputeHasNonIsolatedBlendingDescendants(this); content_.ComputeHasNonIsolatedBlendingDescendants();
has_non_isolated_blending_descendants_dirty_ = false; has_non_isolated_blending_descendants_dirty_ = false;
} }
return has_non_isolated_blending_descendants_; return has_non_isolated_blending_descendants_;
...@@ -524,9 +523,9 @@ const LayoutObject* LayoutSVGRoot::PushMappingToContainer( ...@@ -524,9 +523,9 @@ const LayoutObject* LayoutSVGRoot::PushMappingToContainer(
void LayoutSVGRoot::UpdateCachedBoundaries() { void LayoutSVGRoot::UpdateCachedBoundaries() {
NOT_DESTROYED(); NOT_DESTROYED();
bool ignore; bool ignore;
SVGLayoutSupport::ComputeContainerBoundingBoxes( content_.ComputeBoundingBoxes(object_bounding_box_,
this, object_bounding_box_, /* object_bounding_box_valid */ ignore,
/* object_bounding_box_valid */ ignore, stroke_bounding_box_); stroke_bounding_box_);
} }
bool LayoutSVGRoot::NodeAtPoint(HitTestResult& result, bool LayoutSVGRoot::NodeAtPoint(HitTestResult& result,
...@@ -549,10 +548,7 @@ bool LayoutSVGRoot::NodeAtPoint(HitTestResult& result, ...@@ -549,10 +548,7 @@ bool LayoutSVGRoot::NodeAtPoint(HitTestResult& result,
TransformedHitTestLocation local_location(local_border_box_location, TransformedHitTestLocation local_location(local_border_box_location,
LocalToBorderBoxTransform()); LocalToBorderBoxTransform());
if (local_location) { if (local_location) {
PhysicalOffset accumulated_offset_for_children; if (content_.HitTest(result, *local_location, hit_test_action))
if (SVGLayoutSupport::HitTestChildren(
LastChild(), result, *local_location,
accumulated_offset_for_children, hit_test_action))
return true; return true;
} }
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_LAYOUT_SVG_ROOT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_LAYOUT_SVG_ROOT_H_
#include "third_party/blink/renderer/core/layout/layout_replaced.h" #include "third_party/blink/renderer/core/layout/layout_replaced.h"
#include "third_party/blink/renderer/core/layout/svg/svg_content_container.h"
namespace blink { namespace blink {
...@@ -124,11 +125,11 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced { ...@@ -124,11 +125,11 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced {
const LayoutObjectChildList* Children() const { const LayoutObjectChildList* Children() const {
NOT_DESTROYED(); NOT_DESTROYED();
return &children_; return &content_.Children();
} }
LayoutObjectChildList* Children() { LayoutObjectChildList* Children() {
NOT_DESTROYED(); NOT_DESTROYED();
return &children_; return &content_.Children();
} }
LayoutObjectChildList* VirtualChildren() override { LayoutObjectChildList* VirtualChildren() override {
...@@ -219,8 +220,9 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced { ...@@ -219,8 +220,9 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced {
CompositingReasons AdditionalCompositingReasons() const override; CompositingReasons AdditionalCompositingReasons() const override;
bool HasDescendantWithCompositingReason() const; bool HasDescendantWithCompositingReason() const;
LayoutObjectChildList children_; SVGContentContainer content_;
LayoutSize container_size_; LayoutSize container_size_;
// TODO(fs): Some of this state can move to the "child list" object.
FloatRect object_bounding_box_; FloatRect object_bounding_box_;
FloatRect stroke_bounding_box_; FloatRect stroke_bounding_box_;
AffineTransform local_to_border_box_transform_; AffineTransform local_to_border_box_transform_;
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/layout/svg/svg_content_container.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_container.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_shape.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_text.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
namespace blink {
void SVGContentContainer::Layout(bool force_layout,
bool screen_scaling_factor_changed,
bool layout_size_changed) {
for (LayoutObject* child = children_.FirstChild(); child;
child = child->NextSibling()) {
bool force_child_layout = force_layout;
if (screen_scaling_factor_changed) {
// If the screen scaling factor changed we need to update the text
// metrics (note: this also happens for layoutSizeChanged=true).
if (child->IsSVGText())
ToLayoutSVGText(child)->SetNeedsTextMetricsUpdate();
force_child_layout = true;
}
if (layout_size_changed) {
// When selfNeedsLayout is false and the layout size changed, we have to
// check whether this child uses relative lengths
if (auto* element = DynamicTo<SVGElement>(child->GetNode())) {
if (element->HasRelativeLengths()) {
// FIXME: this should be done on invalidation, not during layout.
// When the layout size changed and when using relative values tell
// the LayoutSVGShape to update its shape object
if (child->IsSVGShape()) {
ToLayoutSVGShape(child)->SetNeedsShapeUpdate();
} else if (child->IsSVGText()) {
ToLayoutSVGText(child)->SetNeedsTextMetricsUpdate();
ToLayoutSVGText(child)->SetNeedsPositioningValuesUpdate();
}
force_child_layout = true;
}
}
}
// Resource containers are nasty: they can invalidate clients outside the
// current SubtreeLayoutScope.
// Since they only care about viewport size changes (to resolve their
// relative lengths), we trigger their invalidation directly from
// SVGSVGElement::svgAttributeChange() or at a higher SubtreeLayoutScope (in
// LayoutView::layout()). We do not create a SubtreeLayoutScope for
// resources because their ability to reference each other leads to circular
// layout. We protect against that within the layout code for resources, but
// it causes assertions if we use a SubTreeLayoutScope for them.
if (child->IsSVGResourceContainer()) {
// Lay out any referenced resources before the child.
SVGLayoutSupport::LayoutResourcesIfNeeded(*child);
child->LayoutIfNeeded();
} else {
SubtreeLayoutScope layout_scope(*child);
if (force_child_layout) {
layout_scope.SetNeedsLayout(child,
layout_invalidation_reason::kSvgChanged);
}
// Lay out any referenced resources before the child.
SVGLayoutSupport::LayoutResourcesIfNeeded(*child);
child->LayoutIfNeeded();
}
}
}
bool SVGContentContainer::HitTest(HitTestResult& result,
const HitTestLocation& location,
HitTestAction hit_test_action) const {
PhysicalOffset accumulated_offset;
for (LayoutObject* child = children_.LastChild(); child;
child = child->PreviousSibling()) {
if (auto* foreign_object = DynamicTo<LayoutSVGForeignObject>(child)) {
if (foreign_object->NodeAtPointFromSVG(
result, location, accumulated_offset, hit_test_action))
return true;
} else {
if (child->NodeAtPoint(result, location, accumulated_offset,
hit_test_action))
return true;
}
}
return false;
}
// Update a bounding box taking into account the validity of the other bounding
// box.
static inline void UpdateObjectBoundingBox(FloatRect& object_bounding_box,
bool& object_bounding_box_valid,
LayoutObject* other,
FloatRect other_bounding_box) {
auto* svg_container = DynamicTo<LayoutSVGContainer>(other);
bool other_valid =
svg_container ? svg_container->IsObjectBoundingBoxValid() : true;
if (!other_valid)
return;
if (!object_bounding_box_valid) {
object_bounding_box = other_bounding_box;
object_bounding_box_valid = true;
return;
}
object_bounding_box.UniteEvenIfEmpty(other_bounding_box);
}
static bool HasValidBoundingBoxForContainer(const LayoutObject* object) {
if (object->IsSVGShape())
return !ToLayoutSVGShape(object)->IsShapeEmpty();
if (object->IsSVGText())
return ToLayoutSVGText(object)->IsObjectBoundingBoxValid();
if (object->IsSVGHiddenContainer())
return false;
if (auto* foreign_object = DynamicTo<LayoutSVGForeignObject>(object))
return foreign_object->IsObjectBoundingBoxValid();
if (object->IsSVGImage())
return ToLayoutSVGImage(object)->IsObjectBoundingBoxValid();
// TODO(fs): Can we refactor this code to include the container case
// in a more natural way?
return true;
}
void SVGContentContainer::ComputeBoundingBoxes(
FloatRect& object_bounding_box,
bool& object_bounding_box_valid,
FloatRect& stroke_bounding_box) const {
object_bounding_box = FloatRect();
object_bounding_box_valid = false;
stroke_bounding_box = FloatRect();
// When computing the strokeBoundingBox, we use the visualRects of
// the container's children so that the container's stroke includes the
// resources applied to the children (such as clips and filters). This allows
// filters applied to containers to correctly bound the children, and also
// improves inlining of SVG content, as the stroke bound is used in that
// situation also.
for (LayoutObject* current = children_.FirstChild(); current;
current = current->NextSibling()) {
// Don't include elements that are not rendered in the union.
if (!HasValidBoundingBoxForContainer(current))
continue;
const AffineTransform& transform = current->LocalToSVGParentTransform();
UpdateObjectBoundingBox(object_bounding_box, object_bounding_box_valid,
current,
transform.MapRect(current->ObjectBoundingBox()));
stroke_bounding_box.Unite(
transform.MapRect(current->VisualRectInLocalSVGCoordinates()));
}
}
bool SVGContentContainer::ComputeHasNonIsolatedBlendingDescendants() const {
for (LayoutObject* child = children_.FirstChild(); child;
child = child->NextSibling()) {
if (child->IsBlendingAllowed() && child->StyleRef().HasBlendMode())
return true;
if (child->HasNonIsolatedBlendingDescendants() &&
!SVGLayoutSupport::WillIsolateBlendingDescendantsForObject(child))
return true;
}
return false;
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_CONTENT_CONTAINER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_CONTENT_CONTAINER_H_
#include "third_party/blink/renderer/core/layout/api/hit_test_action.h"
#include "third_party/blink/renderer/core/layout/layout_object_child_list.h"
namespace blink {
class FloatRect;
class HitTestLocation;
class HitTestResult;
// Content representation for an SVG container. Wraps a LayoutObjectChildList
// with additional state related to the children of the container. Used by
// <svg>, <g> etc.
class SVGContentContainer {
public:
void Layout(bool force_layout,
bool screen_scaling_factor_changed,
bool layout_size_changed);
bool HitTest(HitTestResult&, const HitTestLocation&, HitTestAction) const;
void ComputeBoundingBoxes(FloatRect& object_bounding_box,
bool& object_bounding_box_valid,
FloatRect& stroke_bounding_box) const;
bool ComputeHasNonIsolatedBlendingDescendants() const;
LayoutObjectChildList& Children() { return children_; }
const LayoutObjectChildList& Children() const { return children_; }
private:
LayoutObjectChildList children_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_CONTENT_CONTAINER_H_
...@@ -26,15 +26,10 @@ ...@@ -26,15 +26,10 @@
#include "third_party/blink/renderer/core/layout/geometry/transform_state.h" #include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
#include "third_party/blink/renderer/core/layout/layout_geometry_map.h" #include "third_party/blink/renderer/core/layout/layout_geometry_map.h"
#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_shape.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_text.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
...@@ -223,79 +218,6 @@ const LayoutObject* SVGLayoutSupport::PushMappingToContainer( ...@@ -223,79 +218,6 @@ const LayoutObject* SVGLayoutSupport::PushMappingToContainer(
return parent; return parent;
} }
// Update a bounding box taking into account the validity of the other bounding
// box.
inline void SVGLayoutSupport::UpdateObjectBoundingBox(
FloatRect& object_bounding_box,
bool& object_bounding_box_valid,
LayoutObject* other,
FloatRect other_bounding_box) {
auto* svg_container = DynamicTo<LayoutSVGContainer>(other);
bool other_valid =
svg_container ? svg_container->IsObjectBoundingBoxValid() : true;
if (!other_valid)
return;
if (!object_bounding_box_valid) {
object_bounding_box = other_bounding_box;
object_bounding_box_valid = true;
return;
}
object_bounding_box.UniteEvenIfEmpty(other_bounding_box);
}
static bool HasValidBoundingBoxForContainer(const LayoutObject* object) {
if (object->IsSVGShape())
return !ToLayoutSVGShape(object)->IsShapeEmpty();
if (object->IsSVGText())
return ToLayoutSVGText(object)->IsObjectBoundingBoxValid();
if (object->IsSVGHiddenContainer())
return false;
if (auto* foreign_object = DynamicTo<LayoutSVGForeignObject>(object))
return foreign_object->IsObjectBoundingBoxValid();
if (object->IsSVGImage())
return ToLayoutSVGImage(object)->IsObjectBoundingBoxValid();
// TODO(fs): Can we refactor this code to include the container case
// in a more natural way?
return true;
}
void SVGLayoutSupport::ComputeContainerBoundingBoxes(
const LayoutObject* container,
FloatRect& object_bounding_box,
bool& object_bounding_box_valid,
FloatRect& stroke_bounding_box) {
object_bounding_box = FloatRect();
object_bounding_box_valid = false;
stroke_bounding_box = FloatRect();
// When computing the strokeBoundingBox, we use the visualRects of
// the container's children so that the container's stroke includes the
// resources applied to the children (such as clips and filters). This allows
// filters applied to containers to correctly bound the children, and also
// improves inlining of SVG content, as the stroke bound is used in that
// situation also.
for (LayoutObject* current = container->SlowFirstChild(); current;
current = current->NextSibling()) {
// Don't include elements that are not rendered in the union.
if (!HasValidBoundingBoxForContainer(current))
continue;
const AffineTransform& transform = current->LocalToSVGParentTransform();
UpdateObjectBoundingBox(object_bounding_box, object_bounding_box_valid,
current,
transform.MapRect(current->ObjectBoundingBox()));
stroke_bounding_box.Unite(
transform.MapRect(current->VisualRectInLocalSVGCoordinates()));
}
}
bool SVGLayoutSupport::LayoutSizeOfNearestViewportChanged( bool SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(
const LayoutObject* start) { const LayoutObject* start) {
for (; start; start = start->Parent()) { for (; start; start = start->Parent()) {
...@@ -323,68 +245,6 @@ bool SVGLayoutSupport::ScreenScaleFactorChanged(const LayoutObject* ancestor) { ...@@ -323,68 +245,6 @@ bool SVGLayoutSupport::ScreenScaleFactorChanged(const LayoutObject* ancestor) {
return false; return false;
} }
void SVGLayoutSupport::LayoutChildren(LayoutObject* first_child,
bool force_layout,
bool screen_scaling_factor_changed,
bool layout_size_changed) {
for (LayoutObject* child = first_child; child; child = child->NextSibling()) {
bool force_child_layout = force_layout;
if (screen_scaling_factor_changed) {
// If the screen scaling factor changed we need to update the text
// metrics (note: this also happens for layoutSizeChanged=true).
if (child->IsSVGText())
ToLayoutSVGText(child)->SetNeedsTextMetricsUpdate();
force_child_layout = true;
}
if (layout_size_changed) {
// When selfNeedsLayout is false and the layout size changed, we have to
// check whether this child uses relative lengths
if (auto* element = DynamicTo<SVGElement>(child->GetNode())) {
if (element->HasRelativeLengths()) {
// FIXME: this should be done on invalidation, not during layout.
// When the layout size changed and when using relative values tell
// the LayoutSVGShape to update its shape object
if (child->IsSVGShape()) {
ToLayoutSVGShape(child)->SetNeedsShapeUpdate();
} else if (child->IsSVGText()) {
ToLayoutSVGText(child)->SetNeedsTextMetricsUpdate();
ToLayoutSVGText(child)->SetNeedsPositioningValuesUpdate();
}
force_child_layout = true;
}
}
}
// Resource containers are nasty: they can invalidate clients outside the
// current SubtreeLayoutScope.
// Since they only care about viewport size changes (to resolve their
// relative lengths), we trigger their invalidation directly from
// SVGSVGElement::svgAttributeChange() or at a higher SubtreeLayoutScope (in
// LayoutView::layout()). We do not create a SubtreeLayoutScope for
// resources because their ability to reference each other leads to circular
// layout. We protect against that within the layout code for resources, but
// it causes assertions if we use a SubTreeLayoutScope for them.
if (child->IsSVGResourceContainer()) {
// Lay out any referenced resources before the child.
LayoutResourcesIfNeeded(*child);
child->LayoutIfNeeded();
} else {
SubtreeLayoutScope layout_scope(*child);
if (force_child_layout) {
layout_scope.SetNeedsLayout(child,
layout_invalidation_reason::kSvgChanged);
}
// Lay out any referenced resources before the child.
LayoutResourcesIfNeeded(*child);
child->LayoutIfNeeded();
}
}
}
void SVGLayoutSupport::LayoutResourcesIfNeeded(const LayoutObject& object) { void SVGLayoutSupport::LayoutResourcesIfNeeded(const LayoutObject& object) {
SVGResources* resources = SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(object); SVGResourcesCache::CachedResourcesForLayoutObject(object);
...@@ -464,26 +324,6 @@ bool SVGLayoutSupport::IntersectsClipPath(const LayoutObject& object, ...@@ -464,26 +324,6 @@ bool SVGLayoutSupport::IntersectsClipPath(const LayoutObject& object,
return resources->Clipper()->HitTestClipContent(reference_box, location); return resources->Clipper()->HitTestClipContent(reference_box, location);
} }
bool SVGLayoutSupport::HitTestChildren(LayoutObject* last_child,
HitTestResult& result,
const HitTestLocation& location,
const PhysicalOffset& accumulated_offset,
HitTestAction hit_test_action) {
for (LayoutObject* child = last_child; child;
child = child->PreviousSibling()) {
if (auto* foreign_object = DynamicTo<LayoutSVGForeignObject>(child)) {
if (foreign_object->NodeAtPointFromSVG(
result, location, accumulated_offset, hit_test_action))
return true;
} else {
if (child->NodeAtPoint(result, location, accumulated_offset,
hit_test_action))
return true;
}
}
return false;
}
DashArray SVGLayoutSupport::ResolveSVGDashArray( DashArray SVGLayoutSupport::ResolveSVGDashArray(
const SVGDashArray& svg_dash_array, const SVGDashArray& svg_dash_array,
const ComputedStyle& style, const ComputedStyle& style,
......
...@@ -47,13 +47,6 @@ class CORE_EXPORT SVGLayoutSupport { ...@@ -47,13 +47,6 @@ class CORE_EXPORT SVGLayoutSupport {
STATIC_ONLY(SVGLayoutSupport); STATIC_ONLY(SVGLayoutSupport);
public: public:
// Shares child layouting code between
// LayoutSVGRoot/LayoutSVG(Hidden)Container
static void LayoutChildren(LayoutObject*,
bool force_layout,
bool screen_scaling_factor_changed,
bool layout_size_changed);
// Layout resources used by this node. // Layout resources used by this node.
static void LayoutResourcesIfNeeded(const LayoutObject&); static void LayoutResourcesIfNeeded(const LayoutObject&);
...@@ -82,18 +75,6 @@ class CORE_EXPORT SVGLayoutSupport { ...@@ -82,18 +75,6 @@ class CORE_EXPORT SVGLayoutSupport {
const FloatRect& reference_box, const FloatRect& reference_box,
const HitTestLocation&); const HitTestLocation&);
// Shared child hit-testing code between LayoutSVGRoot/LayoutSVGContainer.
static bool HitTestChildren(LayoutObject* last_child,
HitTestResult&,
const HitTestLocation&,
const PhysicalOffset& accumulated_offset,
HitTestAction);
static void ComputeContainerBoundingBoxes(const LayoutObject* container,
FloatRect& object_bounding_box,
bool& object_bounding_box_valid,
FloatRect& stroke_bounding_box);
// Important functions used by nearly all SVG layoutObjects centralizing // Important functions used by nearly all SVG layoutObjects centralizing
// coordinate transformations / visual rect calculations // coordinate transformations / visual rect calculations
static FloatRect LocalVisualRect(const LayoutObject&); static FloatRect LocalVisualRect(const LayoutObject&);
...@@ -143,8 +124,6 @@ class CORE_EXPORT SVGLayoutSupport { ...@@ -143,8 +124,6 @@ class CORE_EXPORT SVGLayoutSupport {
// Determines whether a svg node should isolate or not based on ComputedStyle. // Determines whether a svg node should isolate or not based on ComputedStyle.
static bool WillIsolateBlendingDescendantsForStyle(const ComputedStyle&); static bool WillIsolateBlendingDescendantsForStyle(const ComputedStyle&);
static bool WillIsolateBlendingDescendantsForObject(const LayoutObject*); static bool WillIsolateBlendingDescendantsForObject(const LayoutObject*);
template <typename LayoutObjectType>
static bool ComputeHasNonIsolatedBlendingDescendants(const LayoutObjectType*);
static bool IsIsolationRequired(const LayoutObject*); static bool IsIsolationRequired(const LayoutObject*);
static AffineTransform DeprecatedCalculateTransformToLayer( static AffineTransform DeprecatedCalculateTransformToLayer(
...@@ -155,12 +134,6 @@ class CORE_EXPORT SVGLayoutSupport { ...@@ -155,12 +134,6 @@ class CORE_EXPORT SVGLayoutSupport {
const FloatPoint&); const FloatPoint&);
static void NotifySVGRootOfChangedCompositingReasons(const LayoutObject*); static void NotifySVGRootOfChangedCompositingReasons(const LayoutObject*);
private:
static void UpdateObjectBoundingBox(FloatRect& object_bounding_box,
bool& object_bounding_box_valid,
LayoutObject* other,
FloatRect other_bounding_box);
}; };
class SubtreeContentTransformScope { class SubtreeContentTransformScope {
...@@ -179,20 +152,6 @@ class SubtreeContentTransformScope { ...@@ -179,20 +152,6 @@ class SubtreeContentTransformScope {
AffineTransform saved_content_transformation_; AffineTransform saved_content_transformation_;
}; };
template <typename LayoutObjectType>
bool SVGLayoutSupport::ComputeHasNonIsolatedBlendingDescendants(
const LayoutObjectType* object) {
for (LayoutObject* child = object->FirstChild(); child;
child = child->NextSibling()) {
if (child->IsBlendingAllowed() && child->StyleRef().HasBlendMode())
return true;
if (child->HasNonIsolatedBlendingDescendants() &&
!WillIsolateBlendingDescendantsForObject(child))
return true;
}
return false;
}
} // namespace blink } // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_LAYOUT_SUPPORT_H_ #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_LAYOUT_SUPPORT_H_
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