| Differences between
and this patch
- WebCore/ChangeLog +38 lines
Lines 1-3 WebCore/ChangeLog_sec1
1
2010-07-05  Nikolas Zimmermann  <nzimmermann@rim.com>
2
3
        Reviewed by NOBODY (OOPS!).
4
5
        SVGRenderContainer forces too many kids to relayout
6
        https://bugs.webkit.org/show_bug.cgi?id=15391
7
8
        Fixing a long-standing performance issue. We should only ever need to relayout container children when the parent bounds change.
9
        The bounds of a container can only change, if the outermost RenderSVGRoot container uses relative length values and its size changes.
10
        This can either happen when the window resizes for standalone SVG documents, or if an enclosing RenderBox changes width/height values.
11
12
        Only relayout container children if the container has selfNeedsLayout() true, or if the parent bounds change.
13
        Lively Kernel doesn't do any relayouts anymore, except if you change the Safari window size, this is a great progression.
14
15
        * rendering/RenderPath.cpp:
16
        (WebCore::RenderPath::layout): No need to special case Path updates, if the element uses relative lengths. SVGRenderSupport now handles this case.
17
        * rendering/RenderSVGContainer.cpp:
18
        (WebCore::RenderSVGContainer::layout): Fix some style issues.
19
        * rendering/RenderSVGContainer.h:
20
        (WebCore::RenderSVGContainer::setDrawsContents): Inlined for speed.
21
        (WebCore::RenderSVGContainer::drawsContents): Ditto.
22
        * rendering/RenderSVGRoot.cpp:
23
        (WebCore::RenderSVGRoot::RenderSVGRoot): Initialize m_isLayoutSizeChanged to false.
24
        (WebCore::RenderSVGRoot::layout): Set m_isLayoutSizeChanged=true when the RenderSVGRoot size changes during layout.
25
        (WebCore::RenderSVGRoot::calcViewport): Remove hasRelativeLengths() special case.
26
        * rendering/RenderSVGRoot.h:
27
        (WebCore::RenderSVGRoot::isLayoutSizeChanged): New function, which returns true during layout() if the outermost <svg> size changes.
28
        * rendering/RenderSVGViewportContainer.cpp:
29
        (WebCore::RenderSVGViewportContainer::calcViewport): Cleanup code, and remove obsolete hasRelativeLengths() special case.
30
        * rendering/SVGRenderSupport.cpp:
31
        (WebCore::svgRootTreeObject): Added helper function, that returns the RenderSVGRoot for a given RenderObject.
32
        (WebCore::SVGRenderSupport::layoutChildren): Remove FIXME, only relayout container children, if the parent bounds change and the child uses relative lengths.
33
        * svg/SVGStyledElement.cpp:
34
        (WebCore::SVGStyledElement::updateRelativeLengthsInformation): Implemented this function. Keeps track of relative lengths elements, so that the
35
                                                                       hasRelativeLengths() information is always up2date.
36
        * svg/SVGStyledElement.h:
37
        (WebCore::SVGStyledElement::hasRelativeLengths): Don't call the virtual selfHasRelativeLengths() information, just return wheter m_elementsWithRelativeLengths is not empty.
38
1
2010-07-05  Pavel Feldman  <pfeldman@chromium.org>
39
2010-07-05  Pavel Feldman  <pfeldman@chromium.org>
2
40
3
        Reviewed by Yury Semikhatsky.
41
        Reviewed by Yury Semikhatsky.
- WebCore/rendering/RenderPath.cpp -6 lines
Lines 100-112 void RenderPath::layout() WebCore/rendering/RenderPath.cpp_sec1
100
    LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
100
    LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
101
    SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
101
    SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
102
102
103
    // We need to update the Path object whenever the underlying SVGStyledTransformableElement uses relative values
104
    // as the viewport size may have changed. It would be nice to optimize this to detect these changes, and only
105
    // update when needed, even when using relative values.
106
    bool needsPathUpdate = m_needsPathUpdate;
103
    bool needsPathUpdate = m_needsPathUpdate;
107
    if (!needsPathUpdate && element->hasRelativeLengths())
108
        needsPathUpdate = true;
109
110
    if (needsPathUpdate) {
104
    if (needsPathUpdate) {
111
        m_path = element->toPathData();
105
        m_path = element->toPathData();
112
        m_needsPathUpdate = false;
106
        m_needsPathUpdate = false;
- WebCore/rendering/RenderSVGContainer.cpp -14 / +9 lines
Lines 40-68 RenderSVGContainer::RenderSVGContainer(S WebCore/rendering/RenderSVGContainer.cpp_sec1
40
{
40
{
41
}
41
}
42
42
43
bool RenderSVGContainer::drawsContents() const
44
{
45
    return m_drawsContents;
46
}
47
48
void RenderSVGContainer::setDrawsContents(bool drawsContents)
49
{
50
    m_drawsContents = drawsContents;
51
}
52
53
void RenderSVGContainer::layout()
43
void RenderSVGContainer::layout()
54
{
44
{
55
    ASSERT(needsLayout());
45
    ASSERT(needsLayout());
56
    ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
57
46
58
    calcViewport(); // Allow RenderSVGViewportContainer to update its viewport
47
    // RenderSVGRoot disables layoutState for the SVG rendering tree.
48
    ASSERT(!view()->layoutStateEnabled());
49
50
    // Allow RenderSVGViewportContainer to update its viewport.
51
    calcViewport();
59
52
60
    LayoutRepainter repainter(*this, checkForRepaintDuringLayout() || selfWillPaint());
53
    LayoutRepainter repainter(*this, checkForRepaintDuringLayout() || selfWillPaint());
61
    calculateLocalTransform(); // Allow RenderSVGTransformableContainer to update its transform
54
55
    // Allow RenderSVGTransformableContainer to update its transform.
56
    calculateLocalTransform();
62
57
63
    SVGRenderSupport::layoutChildren(this, selfNeedsLayout());
58
    SVGRenderSupport::layoutChildren(this, selfNeedsLayout());
64
    repainter.repaintAfterLayout();
65
59
60
    repainter.repaintAfterLayout();
66
    setNeedsLayout(false);
61
    setNeedsLayout(false);
67
}
62
}
68
63
- WebCore/rendering/RenderSVGContainer.h -4 / +2 lines
Lines 39-46 public: WebCore/rendering/RenderSVGContainer.h_sec1
39
    RenderObjectChildList* children() { return &m_children; }
39
    RenderObjectChildList* children() { return &m_children; }
40
40
41
    // <marker> uses these methods to only allow drawing children during a special marker draw time
41
    // <marker> uses these methods to only allow drawing children during a special marker draw time
42
    void setDrawsContents(bool);
42
    void setDrawsContents(bool drawsContents) { m_drawsContents = drawsContents; }
43
    bool drawsContents() const;
43
    bool drawsContents() const { return m_drawsContents; }
44
44
45
    virtual void paint(PaintInfo&, int parentX, int parentY);
45
    virtual void paint(PaintInfo&, int parentX, int parentY);
46
46
Lines 97-101 void toRenderSVGContainer(const RenderSV WebCore/rendering/RenderSVGContainer.h_sec2
97
97
98
#endif // ENABLE(SVG)
98
#endif // ENABLE(SVG)
99
#endif // RenderSVGContainer_h
99
#endif // RenderSVGContainer_h
100
101
// vim:ts=4:noet
- WebCore/rendering/RenderSVGRoot.cpp -7 / +6 lines
Lines 45-50 namespace WebCore { WebCore/rendering/RenderSVGRoot.cpp_sec1
45
45
46
RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node)
46
RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node)
47
    : RenderBox(node)
47
    : RenderBox(node)
48
    , m_isLayoutSizeChanged(false)
48
{
49
{
49
    setReplaced(true);
50
    setReplaced(true);
50
}
51
}
Lines 113-125 void RenderSVGRoot::layout() WebCore/rendering/RenderSVGRoot.cpp_sec2
113
    IntSize oldSize(width(), height());
114
    IntSize oldSize(width(), height());
114
    calcWidth();
115
    calcWidth();
115
    calcHeight();
116
    calcHeight();
116
117
    calcViewport();
117
    calcViewport();
118
118
119
    // RenderSVGRoot needs to take special care to propagate window size changes to the children,
120
    // if the outermost <svg> is using relative x/y/width/height values. Hence the additonal parameters.
121
    SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
119
    SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
122
    SVGRenderSupport::layoutChildren(this, needsLayout || (svg->hasRelativeLengths() && oldSize != size()));
120
    m_isLayoutSizeChanged = svg->hasRelativeLengths() && oldSize != size();
121
122
    SVGRenderSupport::layoutChildren(this, needsLayout);
123
    m_isLayoutSizeChanged = false;
124
123
    repainter.repaintAfterLayout();
125
    repainter.repaintAfterLayout();
124
126
125
    view()->enableLayoutState();
127
    view()->enableLayoutState();
Lines 197-205 void RenderSVGRoot::calcViewport() WebCore/rendering/RenderSVGRoot.cpp_sec3
197
{
199
{
198
    SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
200
    SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
199
201
200
    if (!selfNeedsLayout() && !svg->hasRelativeLengths())
201
        return;
202
203
    if (!svg->hasSetContainerSize()) {
202
    if (!svg->hasSetContainerSize()) {
204
        // In the normal case of <svg> being stand-alone or in a CSSBoxModel object we use
203
        // In the normal case of <svg> being stand-alone or in a CSSBoxModel object we use
205
        // RenderBox::width()/height() (which pulls data from RenderStyle)
204
        // RenderBox::width()/height() (which pulls data from RenderStyle)
- WebCore/rendering/RenderSVGRoot.h +3 lines
Lines 40-45 public: WebCore/rendering/RenderSVGRoot.h_sec1
40
    const RenderObjectChildList* children() const { return &m_children; }
40
    const RenderObjectChildList* children() const { return &m_children; }
41
    RenderObjectChildList* children() { return &m_children; }
41
    RenderObjectChildList* children() { return &m_children; }
42
42
43
    bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
44
43
private:
45
private:
44
    virtual RenderObjectChildList* virtualChildren() { return children(); }
46
    virtual RenderObjectChildList* virtualChildren() { return children(); }
45
    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
47
    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
Lines 84-89 private: WebCore/rendering/RenderSVGRoot.h_sec2
84
    RenderObjectChildList m_children;
86
    RenderObjectChildList m_children;
85
    FloatSize m_viewportSize;
87
    FloatSize m_viewportSize;
86
    mutable AffineTransform m_localToParentTransform;
88
    mutable AffineTransform m_localToParentTransform;
89
    bool m_isLayoutSizeChanged : 1;
87
};
90
};
88
91
89
inline RenderSVGRoot* toRenderSVGRoot(RenderObject* object)
92
inline RenderSVGRoot* toRenderSVGRoot(RenderObject* object)
- WebCore/rendering/RenderSVGViewportContainer.cpp -12 / +7 lines
Lines 45-62 void RenderSVGViewportContainer::applyVi WebCore/rendering/RenderSVGViewportContainer.cpp_sec1
45
45
46
void RenderSVGViewportContainer::calcViewport()
46
void RenderSVGViewportContainer::calcViewport()
47
{
47
{
48
    SVGElement* svgelem = static_cast<SVGElement*>(node());
48
     SVGElement* element = static_cast<SVGElement*>(node());
49
    if (svgelem->hasTagName(SVGNames::svgTag)) {
49
     if (element->hasTagName(SVGNames::svgTag)) {
50
        SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
50
         SVGSVGElement* svg = static_cast<SVGSVGElement*>(element);
51
51
         m_viewport = FloatRect(svg->x().value(svg)
52
        if (!selfNeedsLayout() && !svg->hasRelativeLengths())
52
                                , svg->y().value(svg)
53
            return;
53
                                , svg->width().value(svg)
54
54
                                , svg->height().value(svg));
55
        float x = svg->x().value(svg);
56
        float y = svg->y().value(svg);
57
        float w = svg->width().value(svg);
58
        float h = svg->height().value(svg);
59
        m_viewport = FloatRect(x, y, w, h);
60
    }
55
    }
61
}
56
}
62
57
- WebCore/rendering/SVGRenderSupport.cpp -9 / +28 lines
Lines 32-43 WebCore/rendering/SVGRenderSupport.cpp_sec1
32
#include "ImageBuffer.h"
32
#include "ImageBuffer.h"
33
#include "NodeRenderStyle.h"
33
#include "NodeRenderStyle.h"
34
#include "RenderLayer.h"
34
#include "RenderLayer.h"
35
#include "RenderPath.h"
35
#include "RenderSVGContainer.h"
36
#include "RenderSVGContainer.h"
36
#include "RenderSVGResource.h"
37
#include "RenderSVGResource.h"
37
#include "RenderSVGResourceClipper.h"
38
#include "RenderSVGResourceClipper.h"
38
#include "RenderSVGResourceFilter.h"
39
#include "RenderSVGResourceFilter.h"
39
#include "RenderSVGResourceMarker.h"
40
#include "RenderSVGResourceMarker.h"
40
#include "RenderSVGResourceMasker.h"
41
#include "RenderSVGResourceMasker.h"
42
#include "RenderSVGRoot.h"
41
#include "SVGStyledElement.h"
43
#include "SVGStyledElement.h"
42
#include "TransformState.h"
44
#include "TransformState.h"
43
#include <wtf/UnusedParam.h>
45
#include <wtf/UnusedParam.h>
Lines 230-254 FloatRect SVGRenderSupport::computeConta WebCore/rendering/SVGRenderSupport.cpp_sec2
230
    return boundingBox;
232
    return boundingBox;
231
}
233
}
232
234
235
static inline RenderSVGRoot* svgRootTreeObject(RenderObject* start)
236
{
237
    while (start && !start->isSVGRoot())
238
        start = start->parent();
239
240
    ASSERT(start);
241
    ASSERT(start->isSVGRoot());
242
    return toRenderSVGRoot(start);
243
}
244
233
void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
245
void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
234
{
246
{
247
    bool layoutSizeChanged = svgRootTreeObject(start)->isLayoutSizeChanged();
248
235
    for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
249
    for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
236
        // Only force our kids to layout if we're being asked to relayout as a result of a parent changing
237
        // FIXME: We should be able to skip relayout of non-relative kids when only bounds size has changed
238
        // that's a possible future optimization using LayoutState
239
        // http://bugs.webkit.org/show_bug.cgi?id=15391
240
        bool needsLayout = selfNeedsLayout;
250
        bool needsLayout = selfNeedsLayout;
241
        if (!needsLayout) {
251
252
        if (layoutSizeChanged) {
253
            // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
242
            if (SVGElement* element = child->node()->isSVGElement() ? static_cast<SVGElement*>(child->node()) : 0) {
254
            if (SVGElement* element = child->node()->isSVGElement() ? static_cast<SVGElement*>(child->node()) : 0) {
243
                if (element->isStyled())
255
                if (element->isStyled() && static_cast<SVGStyledElement*>(element)->hasRelativeLengths()) {
244
                    needsLayout = static_cast<SVGStyledElement*>(element)->hasRelativeLengths();
256
                    // When the layout size changed and when using relative values tell the RenderPath to update its Path object
257
                    if (child->isRenderPath())
258
                        toRenderPath(child)->setNeedsPathUpdate();
259
260
                    needsLayout = true;
261
                }
245
            }
262
            }
246
        }
263
        }
247
264
248
        if (needsLayout)
265
        if (needsLayout) {
249
            child->setNeedsLayout(true, false);
266
            child->setNeedsLayout(true, false);
267
            child->layout();
268
        } else
269
            child->layoutIfNeeded();
250
270
251
        child->layoutIfNeeded();
252
        ASSERT(!child->needsLayout());
271
        ASSERT(!child->needsLayout());
253
    }
272
    }
254
}
273
}
- WebCore/svg/SVGStyledElement.cpp -3 / +36 lines
Lines 366-375 AffineTransform SVGStyledElement::localC WebCore/svg/SVGStyledElement.cpp_sec1
366
    return AffineTransform();
366
    return AffineTransform();
367
}
367
}
368
368
369
void SVGStyledElement::updateRelativeLengthsInformation(bool, SVGStyledElement*)
369
void SVGStyledElement::updateRelativeLengthsInformation(bool hasRelativeLengths, SVGStyledElement* element)
370
{
370
{
371
    // FIXME: The actual code will land in a follow-up patch.
371
    // If we're not yet in a document, this function will be called again from insertedIntoDocument(). Do nothing now.
372
    // See https://bugs.webkit.org/show_bug.cgi?id=41566
372
    if (!inDocument())
373
        return;
374
375
    // An element wants to notify us that its own relative lengths state changed.
376
    // Register it in the relative length map, and register us in the parent relative length map.
377
    // Register the parent in the grandparents map, etc. Repeat procedure until the root of the SVG tree.
378
379
    if (hasRelativeLengths)
380
        m_elementsWithRelativeLengths.add(element);
381
    else {
382
        if (!m_elementsWithRelativeLengths.contains(element)) {
383
            // We were never registered. Do nothing.
384
            return;
385
        }
386
387
        m_elementsWithRelativeLengths.remove(element);
388
    }
389
390
    // Find first styled parent node, and notify it that we've changed our relative length state.
391
    Node* node = parent();
392
    while (node) {
393
        if (!node->isSVGElement())
394
            break;
395
396
        SVGElement* element = static_cast<SVGElement*>(node);
397
        if (!element->isStyled()) {
398
            node = node->parent();
399
            continue;
400
        }
401
402
        // Register us in the parent element map.
403
        static_cast<SVGStyledElement*>(element)->updateRelativeLengthsInformation(hasRelativeLengths, this);
404
        break;
405
    }
373
}
406
}
374
407
375
}
408
}
- WebCore/svg/SVGStyledElement.h -2 / +2 lines
Lines 40-47 namespace WebCore { WebCore/svg/SVGStyledElement.h_sec1
40
40
41
        virtual String title() const;
41
        virtual String title() const;
42
42
43
        // FIXME: The actual code will land in a follow-up patch.
43
        bool hasRelativeLengths() const { return !m_elementsWithRelativeLengths.isEmpty(); }
44
        bool hasRelativeLengths() const { return selfHasRelativeLengths(); }
45
44
46
        virtual bool isStyled() const { return true; }
45
        virtual bool isStyled() const { return true; }
47
        virtual bool supportsMarkers() const { return false; }
46
        virtual bool supportsMarkers() const { return false; }
Lines 81-86 namespace WebCore { WebCore/svg/SVGStyledElement.h_sec2
81
        virtual bool selfHasRelativeLengths() const { return false; }
80
        virtual bool selfHasRelativeLengths() const { return false; }
82
81
83
    private:
82
    private:
83
        HashSet<SVGStyledElement*> m_elementsWithRelativeLengths;
84
        DECLARE_ANIMATED_PROPERTY(SVGStyledElement, HTMLNames::classAttr, String, ClassName, className)
84
        DECLARE_ANIMATED_PROPERTY(SVGStyledElement, HTMLNames::classAttr, String, ClassName, className)
85
    };
85
    };
86
86
- LayoutTests/ChangeLog +11 lines
Lines 1-3 LayoutTests/ChangeLog_sec1
1
2010-07-05  Nikolas Zimmermann  <nzimmermann@rim.com>
2
3
        Reviewed by NOBODY (OOPS!).
4
5
        SVGRenderContainer forces too many kids to relayout
6
        https://bugs.webkit.org/show_bug.cgi?id=15391
7
8
        Update results, svg/hixie/error/013.xml. Marginal size change, but a progression.
9
10
        * platform/mac/svg/hixie/error/013-expected.txt:
11
1
2010-07-05  Nikolas Zimmermann  <nzimmermann@rim.com>
12
2010-07-05  Nikolas Zimmermann  <nzimmermann@rim.com>
2
13
3
        Reviewed by Dirk Schulze.
14
        Reviewed by Dirk Schulze.
- LayoutTests/platform/mac/svg/hixie/error/013-expected.txt -1 / +1 lines
Lines 5-11 layer at (0,0) size 800x100 LayoutTests/platform/mac/svg/hixie/error/013-expected.txt_sec1
5
  RenderBlock {html} at (0,0) size 800x100
5
  RenderBlock {html} at (0,0) size 800x100
6
    RenderBody {body} at (8,8) size 784x76
6
    RenderBody {body} at (8,8) size 784x76
7
      RenderBlock (anonymous) at (0,0) size 784x24
7
      RenderBlock (anonymous) at (0,0) size 784x24
8
        RenderSVGRoot {svg} at (8,8) size 769x20
8
        RenderSVGRoot {svg} at (8,8) size 784x20
9
          RenderSVGText {text} at (10,20) size 125x13 contains 1 chunk(s)
9
          RenderSVGText {text} at (10,20) size 125x13 contains 1 chunk(s)
10
            RenderSVGInlineText {#text} at (0,0) size 125x13
10
            RenderSVGInlineText {#text} at (0,0) size 125x13
11
              chunk 1 text run 1 at (10.00,30.00) startOffset 0 endOffset 30 width 125.00: "FAIL (This should not render.)"
11
              chunk 1 text run 1 at (10.00,30.00) startOffset 0 endOffset 30 width 125.00: "FAIL (This should not render.)"

Return to Bug 15391