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

Refactor transform update in LayoutSVGBlock subclasses

The transform is already stored in LayoutSVGBlock, so move the
|needs_transform_update_| flag there as well as the setter. Move the
actual update of the transform to a new helper method on LayoutSVGBlock
named UpdateTransformAfterLayout(). This should make it easier to fix
the referenced bug - which affects both of the subclasses of
LayoutSVGBlock.

Add a TODO about the early transform update in LayoutSVGForeignObject.

Bug: 1094020
Change-Id: Iaa351e06aaafa9dddba868d36ea7841c4d4653d8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2247788Reviewed-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@{#779221}
parent 952af868
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
namespace blink { namespace blink {
LayoutSVGBlock::LayoutSVGBlock(SVGElement* element) LayoutSVGBlock::LayoutSVGBlock(SVGElement* element)
: LayoutBlockFlow(element) {} : LayoutBlockFlow(element), needs_transform_update_(true) {}
SVGElement* LayoutSVGBlock::GetElement() const { SVGElement* LayoutSVGBlock::GetElement() const {
return To<SVGElement>(LayoutObject::GetNode()); return To<SVGElement>(LayoutObject::GetNode());
...@@ -51,6 +51,15 @@ void LayoutSVGBlock::UpdateFromStyle() { ...@@ -51,6 +51,15 @@ void LayoutSVGBlock::UpdateFromStyle() {
SetFloating(false); SetFloating(false);
} }
bool LayoutSVGBlock::UpdateTransformAfterLayout() {
if (!needs_transform_update_)
return false;
local_transform_ =
GetElement()->CalculateTransform(SVGElement::kIncludeMotionTransform);
needs_transform_update_ = false;
return true;
}
void LayoutSVGBlock::StyleDidChange(StyleDifference diff, void LayoutSVGBlock::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) { const ComputedStyle* old_style) {
// Since layout depends on the bounds of the filter, we need to force layout // Since layout depends on the bounds of the filter, we need to force layout
......
...@@ -50,6 +50,7 @@ class LayoutSVGBlock : public LayoutBlockFlow { ...@@ -50,6 +50,7 @@ class LayoutSVGBlock : public LayoutBlockFlow {
LayoutGeometryMap&) const final; LayoutGeometryMap&) const final;
AffineTransform LocalSVGTransform() const final { return local_transform_; } AffineTransform LocalSVGTransform() const final { return local_transform_; }
void SetNeedsTransformUpdate() override { needs_transform_update_ = true; }
PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; } PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; }
...@@ -63,11 +64,13 @@ class LayoutSVGBlock : public LayoutBlockFlow { ...@@ -63,11 +64,13 @@ class LayoutSVGBlock : public LayoutBlockFlow {
VisualRectFlags = kDefaultVisualRectFlags) const final; VisualRectFlags = kDefaultVisualRectFlags) const final;
AffineTransform local_transform_; AffineTransform local_transform_;
bool needs_transform_update_ : 1;
bool IsOfType(LayoutObjectType type) const override { bool IsOfType(LayoutObjectType type) const override {
return type == kLayoutObjectSVG || LayoutBlockFlow::IsOfType(type); return type == kLayoutObjectSVG || LayoutBlockFlow::IsOfType(type);
} }
bool UpdateTransformAfterLayout();
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
private: private:
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
namespace blink { namespace blink {
LayoutSVGForeignObject::LayoutSVGForeignObject(SVGForeignObjectElement* node) LayoutSVGForeignObject::LayoutSVGForeignObject(SVGForeignObjectElement* node)
: LayoutSVGBlock(node), needs_transform_update_(true) {} : LayoutSVGBlock(node) {}
LayoutSVGForeignObject::~LayoutSVGForeignObject() = default; LayoutSVGForeignObject::~LayoutSVGForeignObject() = default;
...@@ -92,12 +92,15 @@ void LayoutSVGForeignObject::UpdateLayout() { ...@@ -92,12 +92,15 @@ void LayoutSVGForeignObject::UpdateLayout() {
auto* foreign = To<SVGForeignObjectElement>(GetElement()); auto* foreign = To<SVGForeignObjectElement>(GetElement());
bool update_cached_boundaries_in_parents = false; // Update our transform before layout, in case any of our descendants rely on
// the transform being somewhat accurate. The |needs_transform_update_| flag
// will be cleared after layout has been performed.
// TODO(fs): Remove this. AFAICS in all cases where we ancestors compute some
// form of CTM, they stop at their nearest ancestor LayoutSVGRoot, and thus
// will not care about this value.
if (needs_transform_update_) { if (needs_transform_update_) {
local_transform_ = local_transform_ =
foreign->CalculateTransform(SVGElement::kIncludeMotionTransform); foreign->CalculateTransform(SVGElement::kIncludeMotionTransform);
needs_transform_update_ = false;
update_cached_boundaries_in_parents = true;
} }
LayoutRect old_viewport = FrameRect(); LayoutRect old_viewport = FrameRect();
...@@ -110,19 +113,24 @@ void LayoutSVGForeignObject::UpdateLayout() { ...@@ -110,19 +113,24 @@ void LayoutSVGForeignObject::UpdateLayout() {
SetX(ElementX()); SetX(ElementX());
SetY(ElementY()); SetY(ElementY());
bool layout_changed = EverHadLayout() && SelfNeedsLayout(); const bool layout_changed = EverHadLayout() && SelfNeedsLayout();
LayoutBlock::UpdateLayout(); LayoutBlock::UpdateLayout();
DCHECK(!NeedsLayout()); DCHECK(!NeedsLayout());
const bool bounds_changed = old_viewport != FrameRect();
// If our bounds changed, notify the parents. bool update_parent_boundaries = bounds_changed;
if (!update_cached_boundaries_in_parents) if (UpdateTransformAfterLayout())
update_cached_boundaries_in_parents = old_viewport != FrameRect(); update_parent_boundaries = true;
if (update_cached_boundaries_in_parents)
// Notify ancestor about our bounds changing.
if (update_parent_boundaries)
LayoutSVGBlock::SetNeedsBoundariesUpdate(); LayoutSVGBlock::SetNeedsBoundariesUpdate();
// Invalidate all resources of this client if our layout changed. // Invalidate all resources of this client if our layout changed.
if (layout_changed) if (layout_changed)
SVGResourcesCache::ClientLayoutChanged(*this); SVGResourcesCache::ClientLayoutChanged(*this);
DCHECK(!needs_transform_update_);
} }
bool LayoutSVGForeignObject::NodeAtPointFromSVG( bool LayoutSVGForeignObject::NodeAtPointFromSVG(
......
...@@ -81,8 +81,6 @@ class LayoutSVGForeignObject final : public LayoutSVGBlock { ...@@ -81,8 +81,6 @@ class LayoutSVGForeignObject final : public LayoutSVGBlock {
LayoutSVGBlock::IsOfType(type); LayoutSVGBlock::IsOfType(type);
} }
void SetNeedsTransformUpdate() override { needs_transform_update_ = true; }
PaintLayerType LayerTypeRequired() const override; PaintLayerType LayerTypeRequired() const override;
bool CreatesNewFormattingContext() const final { bool CreatesNewFormattingContext() const final {
...@@ -101,8 +99,6 @@ class LayoutSVGForeignObject final : public LayoutSVGBlock { ...@@ -101,8 +99,6 @@ class LayoutSVGForeignObject final : public LayoutSVGBlock {
LayoutUnit logical_top, LayoutUnit logical_top,
LogicalExtentComputedValues&) const override; LogicalExtentComputedValues&) const override;
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
bool needs_transform_update_;
}; };
template <> template <>
......
...@@ -67,7 +67,6 @@ LayoutSVGText::LayoutSVGText(SVGTextElement* node) ...@@ -67,7 +67,6 @@ LayoutSVGText::LayoutSVGText(SVGTextElement* node)
: LayoutSVGBlock(node), : LayoutSVGBlock(node),
needs_reordering_(false), needs_reordering_(false),
needs_positioning_values_update_(false), needs_positioning_values_update_(false),
needs_transform_update_(true),
needs_text_metrics_update_(false) {} needs_text_metrics_update_(false) {}
LayoutSVGText::~LayoutSVGText() { LayoutSVGText::~LayoutSVGText() {
...@@ -248,19 +247,19 @@ void LayoutSVGText::UpdateLayout() { ...@@ -248,19 +247,19 @@ void LayoutSVGText::UpdateLayout() {
needs_reordering_ = false; needs_reordering_ = false;
FloatRect new_boundaries = ObjectBoundingBox(); const bool bounds_changed = old_boundaries != ObjectBoundingBox();
bool bounds_changed = old_boundaries != new_boundaries;
// Update the transform after laying out. Update if the bounds // Update the transform after laying out. Update if the bounds
// changed too, since the transform could depend on the bounding // changed too, since the transform could depend on the bounding
// box. // box.
if (bounds_changed || needs_transform_update_) { if (bounds_changed) {
local_transform_ = needs_transform_update_ = true;
GetElement()->CalculateTransform(SVGElement::kIncludeMotionTransform);
needs_transform_update_ = false;
update_parent_boundaries = true; update_parent_boundaries = true;
} }
if (UpdateTransformAfterLayout())
update_parent_boundaries = true;
ClearLayoutOverflow(); ClearLayoutOverflow();
// Invalidate all resources of this client if our layout changed. // Invalidate all resources of this client if our layout changed.
......
...@@ -39,7 +39,6 @@ class LayoutSVGText final : public LayoutSVGBlock { ...@@ -39,7 +39,6 @@ class LayoutSVGText final : public LayoutSVGBlock {
void SetNeedsPositioningValuesUpdate() { void SetNeedsPositioningValuesUpdate() {
needs_positioning_values_update_ = true; needs_positioning_values_update_ = true;
} }
void SetNeedsTransformUpdate() override { needs_transform_update_ = true; }
void SetNeedsTextMetricsUpdate() { needs_text_metrics_update_ = true; } void SetNeedsTextMetricsUpdate() { needs_text_metrics_update_ = true; }
FloatRect VisualRectInLocalSVGCoordinates() const override; FloatRect VisualRectInLocalSVGCoordinates() const override;
FloatRect ObjectBoundingBox() const override; FloatRect ObjectBoundingBox() const override;
...@@ -97,7 +96,6 @@ class LayoutSVGText final : public LayoutSVGBlock { ...@@ -97,7 +96,6 @@ class LayoutSVGText final : public LayoutSVGBlock {
bool needs_reordering_ : 1; bool needs_reordering_ : 1;
bool needs_positioning_values_update_ : 1; bool needs_positioning_values_update_ : 1;
bool needs_transform_update_ : 1;
bool needs_text_metrics_update_ : 1; bool needs_text_metrics_update_ : 1;
Vector<LayoutSVGInlineText*> descendant_text_nodes_; Vector<LayoutSVGInlineText*> descendant_text_nodes_;
}; };
......
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