| Differences between
and this patch
- a/Source/WebCore/ChangeLog +42 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2022-01-12  Nikolas Zimmermann  <nzimmermann@igalia.com>
2
3
        [LBSE] Introduce SVGContainerLayout
4
        https://bugs.webkit.org/show_bug.cgi?id=235101
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Upstream SVGContainerLayout, a utility class centralizing
9
        the "layout children in SVG render tree" algorithm. The legacy
10
        engines relies on various helper methods in SVGRenderingSupport -- for
11
        LBSE it's all in one place: SVGContainerLayout.
12
13
        The actual two-pass algorithm is described in the technical document
14
        covering LBSE. It's identical to the LBSE downstream version, which
15
        used to pass all layout tests.
16
17
        Currently the functionality is not observable yet, as we don't create
18
        LBSE renderers yet.
19
20
        Covered by existing tests, no change in behaviour.
21
22
        * Sources.txt:
23
        * WebCore.xcodeproj/project.pbxproj:
24
        * rendering/RenderObject.h:
25
        (WebCore::RenderObject::isSVGLayerAwareRenderer const):
26
        * rendering/svg/RenderSVGContainer.cpp:
27
        (WebCore::RenderSVGContainer::layoutChildren):
28
        * rendering/svg/RenderSVGRoot.cpp:
29
        (WebCore::RenderSVGRoot::layout):
30
        * rendering/svg/SVGContainerLayout.cpp: Added.
31
        (WebCore::SVGContainerLayout::SVGContainerLayout):
32
        (WebCore::SVGContainerLayout::layoutChildren):
33
        (WebCore::layoutLocationFromRenderer):
34
        (WebCore::setLayoutLocationForRenderer):
35
        (WebCore::SVGContainerLayout::positionChildrenRelativeToContainer):
36
        (WebCore::SVGContainerLayout::verifyLayoutLocationConsistency):
37
        (WebCore::SVGContainerLayout::layoutDifferentRootIfNeeded):
38
        (WebCore::SVGContainerLayout::invalidateResourcesOfChildren):
39
        (WebCore::SVGContainerLayout::layoutSizeOfNearestViewportChanged const):
40
        (WebCore::SVGContainerLayout::transformToRootChanged):
41
        * rendering/svg/SVGContainerLayout.h: Added.
42
1
2022-01-12  Nikolas Zimmermann  <nzimmermann@igalia.com>
43
2022-01-12  Nikolas Zimmermann  <nzimmermann@igalia.com>
2
44
3
        [LBSE] Begin layer-aware RenderSVGContainer implementation
45
        [LBSE] Begin layer-aware RenderSVGContainer implementation
- a/Source/WebCore/Sources.txt +1 lines
Lines 2503-2508 rendering/svg/RenderSVGTextPath.cpp a/Source/WebCore/Sources.txt_sec1
2503
rendering/svg/RenderSVGTransformableContainer.cpp
2503
rendering/svg/RenderSVGTransformableContainer.cpp
2504
rendering/svg/RenderSVGViewportContainer.cpp
2504
rendering/svg/RenderSVGViewportContainer.cpp
2505
rendering/svg/SVGBoundingBoxComputation.cpp
2505
rendering/svg/SVGBoundingBoxComputation.cpp
2506
rendering/svg/SVGContainerLayout.cpp
2506
rendering/svg/SVGInlineFlowBox.cpp
2507
rendering/svg/SVGInlineFlowBox.cpp
2507
rendering/svg/SVGInlineTextBox.cpp
2508
rendering/svg/SVGInlineTextBox.cpp
2508
rendering/svg/SVGPathData.cpp
2509
rendering/svg/SVGPathData.cpp
- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +6 lines
Lines 245-250 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec1
245
		0854B01B1255E4E600B9CDD0 /* RenderSVGTextPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B0091255E4E600B9CDD0 /* RenderSVGTextPath.h */; };
245
		0854B01B1255E4E600B9CDD0 /* RenderSVGTextPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B0091255E4E600B9CDD0 /* RenderSVGTextPath.h */; };
246
		0854B01D1255E4E600B9CDD0 /* RenderSVGTSpan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B00B1255E4E600B9CDD0 /* RenderSVGTSpan.h */; };
246
		0854B01D1255E4E600B9CDD0 /* RenderSVGTSpan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B00B1255E4E600B9CDD0 /* RenderSVGTSpan.h */; };
247
		0844B01D1255B4E600B9CDD0 /* SVGBoundingBoxComputation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0844B01D1255E4E600B9CDD0 /* SVGBoundingBoxComputation.h */; };
247
		0844B01D1255B4E600B9CDD0 /* SVGBoundingBoxComputation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0844B01D1255E4E600B9CDD0 /* SVGBoundingBoxComputation.h */; };
248
		0844B01D1255B5A610B8AFD1 /* SVGContainerLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 0844B01D1255E5A610B8AFD1 /* SVGContainerLayout.h */; };
248
		0854B01F1255E4E600B9CDD0 /* SVGInlineFlowBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B00D1255E4E600B9CDD0 /* SVGInlineFlowBox.h */; };
249
		0854B01F1255E4E600B9CDD0 /* SVGInlineFlowBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B00D1255E4E600B9CDD0 /* SVGInlineFlowBox.h */; };
249
		0854B0211255E4E600B9CDD0 /* SVGInlineTextBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B00F1255E4E600B9CDD0 /* SVGInlineTextBox.h */; };
250
		0854B0211255E4E600B9CDD0 /* SVGInlineTextBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B00F1255E4E600B9CDD0 /* SVGInlineTextBox.h */; };
250
		0854B0231255E4E600B9CDD0 /* SVGRootInlineBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B0111255E4E600B9CDD0 /* SVGRootInlineBox.h */; };
251
		0854B0231255E4E600B9CDD0 /* SVGRootInlineBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 0854B0111255E4E600B9CDD0 /* SVGRootInlineBox.h */; };
Lines 6188-6194 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec2
6188
		0854B0091255E4E600B9CDD0 /* RenderSVGTextPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGTextPath.h; sourceTree = "<group>"; };
6189
		0854B0091255E4E600B9CDD0 /* RenderSVGTextPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGTextPath.h; sourceTree = "<group>"; };
6189
		0854B00B1255E4E600B9CDD0 /* RenderSVGTSpan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGTSpan.h; sourceTree = "<group>"; };
6190
		0854B00B1255E4E600B9CDD0 /* RenderSVGTSpan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGTSpan.h; sourceTree = "<group>"; };
6190
		0834B00C1244E4E600B9CDD0 /* SVGBoundingBoxComputation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGBoundingBoxComputation.cpp; sourceTree = "<group>"; };
6191
		0834B00C1244E4E600B9CDD0 /* SVGBoundingBoxComputation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGBoundingBoxComputation.cpp; sourceTree = "<group>"; };
6192
		0834B00C1244E5A610B8AFD1 /* SVGContainerLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGContainerLayout.cpp; sourceTree = "<group>"; };
6191
		0844B01D1255E4E600B9CDD0 /* SVGBoundingBoxComputation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGBoundingBoxComputation.h; sourceTree = "<group>"; };
6193
		0844B01D1255E4E600B9CDD0 /* SVGBoundingBoxComputation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGBoundingBoxComputation.h; sourceTree = "<group>"; };
6194
		0844B01D1255E5A610B8AFD1 /* SVGContainerLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGContainerLayout.h; sourceTree = "<group>"; };
6192
		0854B00C1255E4E600B9CDD0 /* SVGInlineFlowBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGInlineFlowBox.cpp; sourceTree = "<group>"; };
6195
		0854B00C1255E4E600B9CDD0 /* SVGInlineFlowBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGInlineFlowBox.cpp; sourceTree = "<group>"; };
6193
		0854B00D1255E4E600B9CDD0 /* SVGInlineFlowBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGInlineFlowBox.h; sourceTree = "<group>"; };
6196
		0854B00D1255E4E600B9CDD0 /* SVGInlineFlowBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGInlineFlowBox.h; sourceTree = "<group>"; };
6194
		0854B00E1255E4E600B9CDD0 /* SVGInlineTextBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGInlineTextBox.cpp; sourceTree = "<group>"; };
6197
		0854B00E1255E4E600B9CDD0 /* SVGInlineTextBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGInlineTextBox.cpp; sourceTree = "<group>"; };
Lines 19004-19009 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec3
19004
				436708AC12D9CA4B00044234 /* RenderSVGViewportContainer.h */,
19007
				436708AC12D9CA4B00044234 /* RenderSVGViewportContainer.h */,
19005
				0834B00C1244E4E600B9CDD0 /* SVGBoundingBoxComputation.cpp */,
19008
				0834B00C1244E4E600B9CDD0 /* SVGBoundingBoxComputation.cpp */,
19006
				0844B01D1255E4E600B9CDD0 /* SVGBoundingBoxComputation.h */,
19009
				0844B01D1255E4E600B9CDD0 /* SVGBoundingBoxComputation.h */,
19010
				0834B00C1244E5A610B8AFD1 /* SVGContainerLayout.cpp */,
19011
				0844B01D1255E5A610B8AFD1 /* SVGContainerLayout.h */,
19007
				0854B00C1255E4E600B9CDD0 /* SVGInlineFlowBox.cpp */,
19012
				0854B00C1255E4E600B9CDD0 /* SVGInlineFlowBox.cpp */,
19008
				0854B00D1255E4E600B9CDD0 /* SVGInlineFlowBox.h */,
19013
				0854B00D1255E4E600B9CDD0 /* SVGInlineFlowBox.h */,
19009
				0854B00E1255E4E600B9CDD0 /* SVGInlineTextBox.cpp */,
19014
				0854B00E1255E4E600B9CDD0 /* SVGInlineTextBox.cpp */,
Lines 37330-37335 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec4
37330
				B222799C0D00BF220071B782 /* SVGCircleElement.h in Headers */,
37335
				B222799C0D00BF220071B782 /* SVGCircleElement.h in Headers */,
37331
				B222799F0D00BF220071B782 /* SVGClipPathElement.h in Headers */,
37336
				B222799F0D00BF220071B782 /* SVGClipPathElement.h in Headers */,
37332
				B22279A50D00BF220071B782 /* SVGComponentTransferFunctionElement.h in Headers */,
37337
				B22279A50D00BF220071B782 /* SVGComponentTransferFunctionElement.h in Headers */,
37338
				0844B01D1255B5A610B8AFD1 /* SVGContainerLayout.h in Headers */,
37333
				B22279A80D00BF220071B782 /* SVGCursorElement.h in Headers */,
37339
				B22279A80D00BF220071B782 /* SVGCursorElement.h in Headers */,
37334
				B22279AE0D00BF220071B782 /* SVGDefsElement.h in Headers */,
37340
				B22279AE0D00BF220071B782 /* SVGDefsElement.h in Headers */,
37335
				B22279B10D00BF220071B782 /* SVGDescElement.h in Headers */,
37341
				B22279B10D00BF220071B782 /* SVGDescElement.h in Headers */,
- a/Source/WebCore/rendering/RenderObject.h +1 lines
Lines 352-357 public: a/Source/WebCore/rendering/RenderObject.h_sec1
352
    bool isSVGRootOrLegacySVGRoot() const { return isSVGRoot() || isLegacySVGRoot(); }
352
    bool isSVGRootOrLegacySVGRoot() const { return isSVGRoot() || isLegacySVGRoot(); }
353
    bool isSVGShapeOrLegacySVGShape() const { return isSVGShape() || isLegacySVGShape(); }
353
    bool isSVGShapeOrLegacySVGShape() const { return isSVGShape() || isLegacySVGShape(); }
354
    bool isRenderOrLegacyRenderSVGModelObject() const { return isRenderSVGModelObject() || isLegacyRenderSVGModelObject(); }
354
    bool isRenderOrLegacyRenderSVGModelObject() const { return isRenderSVGModelObject() || isLegacyRenderSVGModelObject(); }
355
    bool isSVGLayerAwareRenderer() const { return isSVGRoot() || isRenderSVGModelObject() || isSVGText() || isSVGInline() || isSVGForeignObject(); }
355
356
356
    // FIXME: Those belong into a SVG specific base-class for all renderers (see above)
357
    // FIXME: Those belong into a SVG specific base-class for all renderers (see above)
357
    // Unfortunately we don't have such a class yet, because it's not possible for all renderers
358
    // Unfortunately we don't have such a class yet, because it's not possible for all renderers
- a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp -7 / +4 lines
Lines 34-41 a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp_sec1
34
#include "RenderLayer.h"
34
#include "RenderLayer.h"
35
#include "RenderTreeBuilder.h"
35
#include "RenderTreeBuilder.h"
36
#include "RenderView.h"
36
#include "RenderView.h"
37
// FIXME: [LBSE] Upstream SVGContainerLayout
37
#include "SVGContainerLayout.h"
38
// #include "SVGContainerLayout.h"
39
#include "SVGRenderingContext.h"
38
#include "SVGRenderingContext.h"
40
#include "SVGResources.h"
39
#include "SVGResources.h"
41
#include "SVGResourcesCache.h"
40
#include "SVGResourcesCache.h"
Lines 88-104 void RenderSVGContainer::calculateViewport() a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp_sec2
88
87
89
void RenderSVGContainer::layoutChildren()
88
void RenderSVGContainer::layoutChildren()
90
{
89
{
91
    // FIXME: [LBSE] Upstream SVGContainerLayout
90
    SVGContainerLayout containerLayout(*this);
92
    // SVGContainerLayout containerLayout(*this);
91
    containerLayout.layoutChildren(selfNeedsLayout() || SVGRenderSupport::filtersForceContainerLayout(*this));
93
    // containerLayout.layoutChildren(selfNeedsLayout() || SVGRenderSupport::filtersForceContainerLayout(*this));
94
92
95
    SVGBoundingBoxComputation boundingBoxComputation(*this);
93
    SVGBoundingBoxComputation boundingBoxComputation(*this);
96
    m_objectBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::objectBoundingBoxDecoration, &m_objectBoundingBoxValid);
94
    m_objectBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::objectBoundingBoxDecoration, &m_objectBoundingBoxValid);
97
    m_strokeBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::strokeBoundingBoxDecoration);
95
    m_strokeBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::strokeBoundingBoxDecoration);
98
    setLayoutRect(enclosingLayoutRect(m_objectBoundingBox));
96
    setLayoutRect(enclosingLayoutRect(m_objectBoundingBox));
99
97
100
    // FIXME: [LBSE] Upstream SVGContainerLayout
98
    containerLayout.positionChildrenRelativeToContainer();
101
    // containerLayout.positionChildrenRelativeToContainer();
102
}
99
}
103
100
104
void RenderSVGContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
101
void RenderSVGContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp -9 / +1 lines
Lines 44-51 a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp_sec1
44
#include "RenderSVGText.h"
44
#include "RenderSVGText.h"
45
#include "RenderTreeBuilder.h"
45
#include "RenderTreeBuilder.h"
46
#include "RenderView.h"
46
#include "RenderView.h"
47
// FIXME: [LBSE] Upstream SVGContainerLayout
47
#include "SVGContainerLayout.h"
48
// #include "SVGContainerLayout.h"
49
#include "SVGElementTypeHelpers.h"
48
#include "SVGElementTypeHelpers.h"
50
#include "SVGImage.h"
49
#include "SVGImage.h"
51
#include "SVGRenderingContext.h"
50
#include "SVGRenderingContext.h"
Lines 194-212 void RenderSVGRoot::layout() a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp_sec2
194
    updateLayerInformation();
193
    updateLayerInformation();
195
194
196
    {
195
    {
197
        /* FIXME: [LBSE] Upstream SVGContainerLayout
198
        SVGContainerLayout containerLayout(*this);
196
        SVGContainerLayout containerLayout(*this);
199
        containerLayout.layoutChildren(needsLayout || SVGRenderSupport::filtersForceContainerLayout(*this));
197
        containerLayout.layoutChildren(needsLayout || SVGRenderSupport::filtersForceContainerLayout(*this));
200
        */
201
198
202
        SVGBoundingBoxComputation boundingBoxComputation(*this);
199
        SVGBoundingBoxComputation boundingBoxComputation(*this);
203
        m_objectBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::objectBoundingBoxDecoration);
200
        m_objectBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::objectBoundingBoxDecoration);
204
        m_strokeBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::strokeBoundingBoxDecoration);
201
        m_strokeBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::strokeBoundingBoxDecoration);
205
    }
202
    }
206
203
207
    // FIXME: [LBSE] Upstream SVGContainerLayout -- remove SVGRenderSupport::layoutChildren.
208
    SVGRenderSupport::layoutChildren(*this, needsLayout);
209
210
    if (!m_resourcesNeedingToInvalidateClients.isEmpty()) {
204
    if (!m_resourcesNeedingToInvalidateClients.isEmpty()) {
211
        // Invalidate resource clients, which may mark some nodes for layout.
205
        // Invalidate resource clients, which may mark some nodes for layout.
212
        for (auto& resource :  m_resourcesNeedingToInvalidateClients) {
206
        for (auto& resource :  m_resourcesNeedingToInvalidateClients) {
Lines 216-225 void RenderSVGRoot::layout() a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp_sec3
216
210
217
        m_isLayoutSizeChanged = false;
211
        m_isLayoutSizeChanged = false;
218
212
219
        /* FIXME: [LBSE] Upstream SVGContainerLayout
220
        SVGContainerLayout containerLayout(*this);
213
        SVGContainerLayout containerLayout(*this);
221
        containerLayout.layoutChildren(false);
214
        containerLayout.layoutChildren(false);
222
        */
223
    }
215
    }
224
216
225
    m_isLayoutSizeChanged = false;
217
    m_isLayoutSizeChanged = false;
- a/Source/WebCore/rendering/svg/SVGContainerLayout.cpp +293 lines
Line 0 a/Source/WebCore/rendering/svg/SVGContainerLayout.cpp_sec1
1
/*
2
 * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
3
 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
4
 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5
 * Copyright (C) 2009 Google, Inc.  All rights reserved.
6
 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
7
 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
8
 * Copyright (C) 2018 Adobe Systems Incorporated. All rights reserved.
9
 * Copyright (C) 2020 Apple Inc. All rights reserved.
10
 * Copyright (C) 2021 Igalia S.L.
11
 *
12
 * This library is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU Library General Public
14
 * License as published by the Free Software Foundation; either
15
 * version 2 of the License, or (at your option) any later version.
16
 *
17
 * This library is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20
 * Library General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Library General Public License
23
 * along with this library; see the file COPYING.LIB.  If not, write to
24
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25
 * Boston, MA 02110-1301, USA.
26
 */
27
28
#include "config.h"
29
#include "SVGContainerLayout.h"
30
31
#if ENABLE(LAYER_BASED_SVG_ENGINE)
32
#include "Logging.h"
33
#include "RenderAncestorIterator.h"
34
#include "RenderChildIterator.h"
35
#include "RenderSVGForeignObject.h"
36
#include "RenderSVGHiddenContainer.h"
37
#include "RenderSVGInline.h"
38
#include "RenderSVGModelObject.h"
39
#include "RenderSVGRoot.h"
40
#include "RenderSVGShape.h"
41
#include "RenderSVGText.h"
42
#include "RenderSVGTransformableContainer.h"
43
#include "RenderSVGViewportContainer.h"
44
#include "SVGRenderSupport.h"
45
#include "SVGRenderingContext.h"
46
#include "SVGResources.h"
47
#include "SVGResourcesCache.h"
48
49
namespace WebCore {
50
51
SVGContainerLayout::SVGContainerLayout(RenderLayerModelObject& container)
52
    : m_container(container)
53
{
54
}
55
56
void SVGContainerLayout::layoutChildren(bool containerNeedsLayout)
57
{
58
    bool layoutSizeChanged = layoutSizeOfNearestViewportChanged();
59
    bool transformChanged = transformToRootChanged(&m_container);
60
    HashSet<RenderElement*> elementsThatDidNotReceiveLayout;
61
62
    m_positionedChildren.clear();
63
    for (auto& child : childrenOfType<RenderObject>(m_container)) {
64
        if (child.isSVGLayerAwareRenderer()) {
65
            ASSERT(child.hasLayer());
66
            m_positionedChildren.append(downcast<RenderLayerModelObject>(child));
67
        }
68
69
        bool needsLayout = containerNeedsLayout;
70
        bool childEverHadLayout = child.everHadLayout();
71
72
        if (transformChanged) {
73
            // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true).
74
            if (is<RenderSVGText>(child))
75
                downcast<RenderSVGText>(child).setNeedsTextMetricsUpdate();
76
            needsLayout = true;
77
        }
78
79
        if (layoutSizeChanged && child.node() && is<SVGElement>(*child.node())) {
80
            // When containerNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
81
            auto& element = downcast<SVGElement>(*child.node());
82
            if (element.hasRelativeLengths() && 1) {
83
                // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
84
                if (is<RenderSVGShape>(child))
85
                    downcast<RenderSVGShape>(child).setNeedsShapeUpdate();
86
                else if (is<RenderSVGText>(child)) {
87
                    auto& svgText = downcast<RenderSVGText>(child);
88
                    svgText.setNeedsTextMetricsUpdate();
89
                    svgText.setNeedsPositioningValuesUpdate();
90
                }
91
92
                needsLayout = true;
93
            }
94
        }
95
96
        if (needsLayout)
97
            child.setNeedsLayout(MarkOnlyThis);
98
99
        bool childNeededLayout = child.needsLayout();
100
        if (is<RenderElement>(child)) {
101
            auto& element = downcast<RenderElement>(child);
102
            if (childNeededLayout) {
103
                layoutDifferentRootIfNeeded(element);
104
                element.layout();
105
            } else if (layoutSizeChanged)
106
                elementsThatDidNotReceiveLayout.add(&element);
107
108
            if (!childEverHadLayout && element.checkForRepaintDuringLayout())
109
                child.repaint();
110
        }
111
112
        ASSERT(!child.needsLayout());
113
    }
114
115
    if (layoutSizeChanged) {
116
        // If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path.
117
        for (auto* element : elementsThatDidNotReceiveLayout)
118
            invalidateResourcesOfChildren(*element);
119
    } else
120
        ASSERT(elementsThatDidNotReceiveLayout.isEmpty());
121
}
122
123
static inline LayoutPoint layoutLocationFromRenderer(const RenderObject& renderer)
124
{
125
    if (is<RenderSVGModelObject>(renderer))
126
        return downcast<RenderSVGModelObject>(renderer).layoutLocation();
127
128
    if (is<RenderSVGBlock>(renderer)) // <foreignObject> / <text>
129
        return downcast<RenderSVGBlock>(renderer).location();
130
131
    if (is<RenderSVGInline>(renderer)) // <tspan> / <textPath>
132
        return { };
133
134
    ASSERT_NOT_REACHED();
135
    return { };
136
}
137
138
static inline void setLayoutLocationForRenderer(RenderObject& renderer, const LayoutPoint& newLocation)
139
{
140
    if (is<RenderSVGModelObject>(renderer)) {
141
        downcast<RenderSVGModelObject>(renderer).setLayoutLocation(newLocation);
142
        return;
143
    }
144
145
    // <foreignObject> / <text>
146
    if (is<RenderSVGBlock>(renderer)) {
147
        downcast<RenderSVGBlock>(renderer).setLocation(newLocation);
148
        return;
149
    }
150
151
    // <tspan> / <textPath>
152
    if (is<RenderSVGInline>(renderer))
153
        return;
154
155
    ASSERT_NOT_REACHED();
156
}
157
158
void SVGContainerLayout::positionChildrenRelativeToContainer()
159
{
160
    if (m_positionedChildren.isEmpty())
161
        return;
162
163
    auto verifyPositionedChildRendererExpectation = [](RenderObject& renderer) {
164
#if !defined(NDEBUG)
165
        ASSERT(renderer.isSVGLayerAwareRenderer()); // Pre-condition to enter m_positionedChildren
166
        ASSERT(!renderer.isSVGRoot()); // There is only one outermost RenderSVGRoot object
167
        ASSERT(!renderer.isSVGInline()); // Inlines are only allowed within a RenderSVGText tree
168
169
        if (is<RenderSVGModelObject>(renderer) || is<RenderSVGBlock>(renderer))
170
            return;
171
172
        ASSERT_NOT_REACHED();
173
        return;
174
#else
175
        UNUSED_PARAM(renderer);
176
#endif
177
    };
178
179
    // Arrange layout location for all child renderers relative to the container layout location.
180
    auto parentLayoutLocation = flooredLayoutPoint(m_container.objectBoundingBox().minXMinYCorner());
181
    for (RenderObject& child : m_positionedChildren) {
182
        verifyPositionedChildRendererExpectation(child);
183
184
        auto objectBoundingBoxChild = child.objectBoundingBox();
185
        auto layoutLocation = flooredLayoutPoint(objectBoundingBoxChild.minXMinYCorner());
186
        auto desiredLayoutLocation = toLayoutPoint(layoutLocation - parentLayoutLocation);
187
        auto currentLayoutLocation = layoutLocationFromRenderer(child);
188
        if (currentLayoutLocation == desiredLayoutLocation)
189
            continue;
190
        setLayoutLocationForRenderer(child, desiredLayoutLocation);
191
    }
192
}
193
194
void SVGContainerLayout::verifyLayoutLocationConsistency(const RenderElement& renderer)
195
{
196
    if (renderer.isSVGLayerAwareRenderer() && !renderer.isSVGRoot()) {
197
        auto currentLayoutLocation = layoutLocationFromRenderer(renderer);
198
199
        auto expectedLayoutLocation = currentLayoutLocation;
200
        for (auto& ancestor : ancestorsOfType<RenderElement>(renderer)) {
201
            ASSERT(ancestor.isSVGLayerAwareRenderer());
202
            if (ancestor.isSVGRoot())
203
                break;
204
            expectedLayoutLocation.moveBy(layoutLocationFromRenderer(ancestor));
205
        }
206
207
        auto initialLayoutLocation = flooredLayoutPoint(renderer.objectBoundingBox().minXMinYCorner());
208
        if (expectedLayoutLocation == initialLayoutLocation) {
209
            LOG_WITH_STREAM(SVG, stream << "--> SVGContainerLayout renderer " << &renderer << " (" << renderer.renderName() << ")"
210
                << " - verifyLayoutLocationConsistency() objectBoundingBox / layoutLocation are in sync.");
211
        } else {
212
            LOG_WITH_STREAM(SVG, stream << "--> SVGContainerLayout renderer " << &renderer << " (" << renderer.renderName() << ")"
213
                << " - verifyLayoutLocationConsistency() objectBoundingBox / layoutLocation invariant violated -- out of sync due to partial layout?"
214
                << " currentLayoutLocation=" << currentLayoutLocation
215
                << "  (expectedLayoutLocation=" << expectedLayoutLocation
216
                << " != initialLayoutLocation=" << initialLayoutLocation << ")"
217
                << " -> aborting with a render tree dump");
218
219
#if ENABLE(TREE_DEBUGGING)
220
            showRenderTree(&renderer);
221
#endif
222
223
            ASSERT_NOT_REACHED();
224
        }
225
    }
226
227
    for (auto& child : childrenOfType<RenderElement>(renderer)) {
228
        if (child.isSVGLayerAwareRenderer())
229
            verifyLayoutLocationConsistency(child);
230
    }
231
232
#if !defined(NDEBUG)
233
    if (renderer.isSVGRoot()) {
234
        LOG_WITH_STREAM(SVG, stream << "--> SVGContainerLayout renderer " << &renderer << " (" << renderer.renderName() << ")"
235
            << " - verifyLayoutLocationConsistency() end");
236
    }
237
#endif
238
}
239
240
void SVGContainerLayout::layoutDifferentRootIfNeeded(const RenderElement& renderer)
241
{
242
    if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) {
243
        auto* svgRoot = SVGRenderSupport::findTreeRootObject(renderer);
244
        ASSERT(svgRoot);
245
        resources->layoutDifferentRootIfNeeded(svgRoot);
246
    }
247
}
248
249
void SVGContainerLayout::invalidateResourcesOfChildren(RenderElement& renderer)
250
{
251
    ASSERT(!renderer.needsLayout());
252
    if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer))
253
        resources->removeClientFromCache(renderer, false);
254
255
    for (auto& child : childrenOfType<RenderElement>(renderer))
256
        invalidateResourcesOfChildren(child);
257
}
258
259
bool SVGContainerLayout::layoutSizeOfNearestViewportChanged() const
260
{
261
    RenderElement* ancestor = &m_container;
262
    while (ancestor && !is<RenderSVGRoot>(*ancestor) && !is<RenderSVGViewportContainer>(*ancestor))
263
        ancestor = ancestor->parent();
264
265
    ASSERT(ancestor);
266
    if (is<RenderSVGViewportContainer>(*ancestor))
267
        return downcast<RenderSVGViewportContainer>(*ancestor).isLayoutSizeChanged();
268
269
    return downcast<RenderSVGRoot>(*ancestor).isLayoutSizeChanged();
270
}
271
272
bool SVGContainerLayout::transformToRootChanged(const RenderObject* ancestor)
273
{
274
    while (ancestor) {
275
        // FIXME: [LBSE] Upstream RenderSVGTransformableContainer changes
276
        // if (is<RenderSVGTransformableContainer>(*ancestor))
277
        //     return downcast<const RenderSVGTransformableContainer>(*ancestor).didTransformToRootUpdate();
278
279
        // FIXME: [LBSE] Upstream RenderSVGTransformableContainer changes
280
        // if (is<RenderSVGViewportContainer>(*ancestor))
281
        //     return downcast<const RenderSVGViewportContainer>(*ancestor).didTransformToRootUpdate();
282
283
        if (is<RenderSVGRoot>(*ancestor))
284
            return downcast<const RenderSVGRoot>(*ancestor).didTransformToRootUpdate();
285
        ancestor = ancestor->parent();
286
    }
287
288
    return false;
289
}
290
291
}
292
293
#endif // ENABLE(LAYER_BASED_SVG_ENGINE)
- a/Source/WebCore/rendering/svg/SVGContainerLayout.h +58 lines
Line 0 a/Source/WebCore/rendering/svg/SVGContainerLayout.h_sec1
1
/**
2
 * Copyright (C) 2021 Igalia S.L.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Library General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Library General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Library General Public License
15
 * along with this library; see the file COPYING.LIB.  If not, write to
16
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
 * Boston, MA 02110-1301, USA.
18
 */
19
20
#pragma once
21
22
#if ENABLE(LAYER_BASED_SVG_ENGINE)
23
#include "RenderLayerModelObject.h"
24
25
#include <functional>
26
#include <wtf/Noncopyable.h>
27
#include <wtf/Vector.h>
28
29
namespace WebCore {
30
31
class SVGContainerLayout {
32
    WTF_MAKE_NONCOPYABLE(SVGContainerLayout);
33
public:
34
    explicit SVGContainerLayout(RenderLayerModelObject&);
35
    ~SVGContainerLayout() = default;
36
37
    // 'containerNeedsLayout' denotes if the container for which the
38
    // SVGContainerLayout object was created needs to be laid out or not.
39
    void layoutChildren(bool containerNeedsLayout);
40
41
    void positionChildrenRelativeToContainer();
42
43
    static void verifyLayoutLocationConsistency(const RenderElement&);
44
    static bool transformToRootChanged(const RenderObject* ancestor);
45
46
private:
47
    void layoutDifferentRootIfNeeded(const RenderElement&);
48
    void invalidateResourcesOfChildren(RenderElement&);
49
50
    bool layoutSizeOfNearestViewportChanged() const;
51
52
    RenderLayerModelObject& m_container;
53
    Vector<std::reference_wrapper<RenderLayerModelObject>> m_positionedChildren;
54
};
55
56
} // namespace WebCore
57
58
#endif // ENABLE(LAYER_BASED_SVG_ENGINE)

Return to Bug 235101