blob: 91a9779c18e99f114ea4d408d32cce85670a1f63 [file] [log] [blame]
/*
* Copyright (C) 2006 Apple Computer, Inc.
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "third_party/blink/renderer/core/layout/svg/layout_svg_block.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_view.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h"
#include "third_party/blink/renderer/core/style/shadow_list.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
namespace blink {
LayoutSVGBlock::LayoutSVGBlock(SVGElement* element)
: LayoutBlockFlow(element),
needs_transform_update_(true),
transform_uses_reference_box_(false) {}
SVGElement* LayoutSVGBlock::GetElement() const {
NOT_DESTROYED();
return To<SVGElement>(LayoutObject::GetNode());
}
void LayoutSVGBlock::WillBeDestroyed() {
NOT_DESTROYED();
SVGResources::ClearClipPathFilterMask(*GetElement(), Style());
LayoutBlockFlow::WillBeDestroyed();
}
void LayoutSVGBlock::InsertedIntoTree() {
NOT_DESTROYED();
LayoutBlockFlow::InsertedIntoTree();
LayoutSVGResourceContainer::MarkForLayoutAndParentResourceInvalidation(*this,
false);
if (StyleRef().HasSVGEffect())
SetNeedsPaintPropertyUpdate();
if (CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(*this) !=
CompositingReason::kNone) {
SVGLayoutSupport::NotifySVGRootOfChangedCompositingReasons(this);
}
}
void LayoutSVGBlock::WillBeRemovedFromTree() {
NOT_DESTROYED();
LayoutSVGResourceContainer::MarkForLayoutAndParentResourceInvalidation(*this,
false);
if (StyleRef().HasSVGEffect())
SetNeedsPaintPropertyUpdate();
LayoutBlockFlow::WillBeRemovedFromTree();
if (CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(*this) !=
CompositingReason::kNone) {
SVGLayoutSupport::NotifySVGRootOfChangedCompositingReasons(this);
}
}
void LayoutSVGBlock::UpdateFromStyle() {
NOT_DESTROYED();
LayoutBlockFlow::UpdateFromStyle();
SetFloating(false);
}
bool LayoutSVGBlock::CheckForImplicitTransformChange(bool bbox_changed) const {
NOT_DESTROYED();
// If the transform is relative to the reference box, check relevant
// conditions to see if we need to recompute the transform.
switch (StyleRef().TransformBox()) {
case ETransformBox::kViewBox:
return SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this);
case ETransformBox::kFillBox:
return bbox_changed;
}
NOTREACHED();
return false;
}
bool LayoutSVGBlock::UpdateTransformAfterLayout(bool bounds_changed) {
NOT_DESTROYED();
// If our transform depends on the reference box, we need to check if it needs
// to be updated.
if (!needs_transform_update_ && transform_uses_reference_box_) {
needs_transform_update_ = CheckForImplicitTransformChange(bounds_changed);
if (needs_transform_update_)
SetNeedsPaintPropertyUpdate();
}
if (!needs_transform_update_)
return false;
local_transform_ =
GetElement()->CalculateTransform(SVGElement::kIncludeMotionTransform);
needs_transform_update_ = false;
return true;
}
void LayoutSVGBlock::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
NOT_DESTROYED();
LayoutBlock::StyleDidChange(diff, old_style);
// |HasTransformRelatedProperty| is used for compositing so ensure it was
// correctly set by the call to |StyleDidChange|.
DCHECK_EQ(HasTransformRelatedProperty(),
StyleRef().HasTransformRelatedProperty());
transform_uses_reference_box_ =
TransformHelper::DependsOnReferenceBox(StyleRef());
if (diff.NeedsFullLayout()) {
SetNeedsBoundariesUpdate();
if (diff.TransformChanged())
SetNeedsTransformUpdate();
}
SVGResources::UpdateClipPathFilterMask(*GetElement(), old_style, StyleRef());
if (!Parent())
return;
if (diff.BlendModeChanged()) {
DCHECK(IsBlendingAllowed());
Parent()->DescendantIsolationRequirementsChanged(
StyleRef().HasBlendMode() ? kDescendantIsolationRequired
: kDescendantIsolationNeedsUpdate);
}
if (diff.CompositingReasonsChanged())
SVGLayoutSupport::NotifySVGRootOfChangedCompositingReasons(this);
if (diff.HasDifference())
LayoutSVGResourceContainer::StyleChanged(*this, diff);
}
void LayoutSVGBlock::MapLocalToAncestor(const LayoutBoxModelObject* ancestor,
TransformState& transform_state,
MapCoordinatesFlags flags) const {
NOT_DESTROYED();
// Convert from local HTML coordinates to local SVG coordinates.
transform_state.Move(PhysicalLocation());
// Apply other mappings on local SVG coordinates.
SVGLayoutSupport::MapLocalToAncestor(this, ancestor, transform_state, flags);
}
void LayoutSVGBlock::MapAncestorToLocal(const LayoutBoxModelObject* ancestor,
TransformState& transform_state,
MapCoordinatesFlags flags) const {
NOT_DESTROYED();
if (this == ancestor)
return;
// Map to local SVG coordinates.
SVGLayoutSupport::MapAncestorToLocal(*this, ancestor, transform_state, flags);
// Convert from local SVG coordinates to local HTML coordinates.
transform_state.Move(PhysicalLocation());
}
const LayoutObject* LayoutSVGBlock::PushMappingToContainer(
const LayoutBoxModelObject* ancestor_to_stop_at,
LayoutGeometryMap& geometry_map) const {
NOT_DESTROYED();
// Convert from local HTML coordinates to local SVG coordinates.
geometry_map.Push(this, PhysicalLocation());
// Apply other mappings on local SVG coordinates.
return SVGLayoutSupport::PushMappingToContainer(this, ancestor_to_stop_at,
geometry_map);
}
PhysicalRect LayoutSVGBlock::VisualRectInDocument(VisualRectFlags flags) const {
NOT_DESTROYED();
return SVGLayoutSupport::VisualRectInAncestorSpace(*this, *View(), flags);
}
bool LayoutSVGBlock::MapToVisualRectInAncestorSpaceInternal(
const LayoutBoxModelObject* ancestor,
TransformState& transform_state,
VisualRectFlags) const {
NOT_DESTROYED();
transform_state.Flatten();
PhysicalRect rect(LayoutRect(transform_state.LastPlanarQuad().BoundingBox()));
// Convert from local HTML coordinates to local SVG coordinates.
rect.Move(PhysicalLocation());
// Apply other mappings on local SVG coordinates.
bool retval = SVGLayoutSupport::MapToVisualRectInAncestorSpace(
*this, ancestor, FloatRect(rect), rect);
transform_state.SetQuad(FloatQuad(FloatRect(rect)));
return retval;
}
bool LayoutSVGBlock::NodeAtPoint(HitTestResult&,
const HitTestLocation&,
const PhysicalOffset&,
HitTestAction) {
NOT_DESTROYED();
NOTREACHED();
return false;
}
} // namespace blink