Title: [107108] trunk
Revision
107108
Author
k...@webkit.org
Date
2012-02-08 11:19:03 -0800 (Wed, 08 Feb 2012)

Log Message

viewBox on nested SVG causes wrong content size for relative values
https://bugs.webkit.org/show_bug.cgi?id=69459

Reviewed by Nikolas.

Source/WebCore: 

In the past we just checked the change of the viewport size of the root SVG element. If the size changed, all childs
with relative length values needed a relayout. We did not consider that we might have other viewports in the document.
Childs with relative lengths had a strange zooming, if just the viewport size of an inner SVG element changed.

With this patch we check if the size of the nearest viewport changes. Is this the case, childs with relative lengths
need a relayout.

Test: inner-svg-change-viewBox.svg

* rendering/svg/RenderSVGContainer.cpp:
(WebCore::RenderSVGContainer::layout):
* rendering/svg/RenderSVGContainer.h:
(RenderSVGContainer):
(WebCore::RenderSVGContainer::determineIfLayoutSizeChanged): Check if we need layout and have relative length values.
* rendering/svg/RenderSVGRoot.cpp:
(WebCore::RenderSVGRoot::layout): Remove resetting 'viewport size changed' flag for code operability. No influence on the layout.
* rendering/svg/RenderSVGViewportContainer.cpp:
(WebCore::RenderSVGViewportContainer::RenderSVGViewportContainer): Add a flag that indicates that the viewport size changes.
(WebCore::RenderSVGViewportContainer::determineIfLayoutSizeChanged): The flag gets set during the layout phase of the SVG element if the size changes.
(WebCore):
* rendering/svg/RenderSVGViewportContainer.h:
(WebCore::RenderSVGViewportContainer::isLayoutSizeChanged): Added getter to get flag status.
(RenderSVGViewportContainer):
(WebCore::toRenderSVGViewportContainer): Added casting function for constant RenderObjects.
(WebCore):
* rendering/svg/SVGRenderSupport.cpp:
(WebCore::layoutSizeOfNearestViewportChanged): Search the nearest viewport and check if the size changed.
(WebCore):
(WebCore::SVGRenderSupport::layoutChildren): Don't check the roots viewport for size changes, but the nearest viewport.
* svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::svgAttributeChanged): Added viewBoxAttr to the list of attributes that cause relayout.

LayoutTests: 

Test relayout of content of inner SVG on change of relative length values.

* svg/repaint/inner-svg-change-viewBox-expected.png: Added.
* svg/repaint/inner-svg-change-viewBox-expected.txt: Added.
* svg/repaint/inner-svg-change-viewBox.svg: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (107107 => 107108)


--- trunk/LayoutTests/ChangeLog	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/LayoutTests/ChangeLog	2012-02-08 19:19:03 UTC (rev 107108)
@@ -1,3 +1,16 @@
+2012-02-08  Dirk Schulze  <k...@webkit.org>
+
+        viewBox on nested SVG causes wrong content size for relative values
+        https://bugs.webkit.org/show_bug.cgi?id=69459
+
+        Reviewed by Nikolas.
+
+        Test relayout of content of inner SVG on change of relative length values.
+
+        * svg/repaint/inner-svg-change-viewBox-expected.png: Added.
+        * svg/repaint/inner-svg-change-viewBox-expected.txt: Added.
+        * svg/repaint/inner-svg-change-viewBox.svg: Added.
+
 2012-02-08  Gregg Tavares  <g...@chromium.org>
 
         Implement new WEBGL compressed texture extensions

Added: trunk/LayoutTests/svg/repaint/inner-svg-change-viewBox-expected.png


(Binary files differ)
Property changes on: trunk/LayoutTests/svg/repaint/inner-svg-change-viewBox-expected.png ___________________________________________________________________

Added: svn:mime-type

Added: trunk/LayoutTests/svg/repaint/inner-svg-change-viewBox-expected.txt (0 => 107108)


--- trunk/LayoutTests/svg/repaint/inner-svg-change-viewBox-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/svg/repaint/inner-svg-change-viewBox-expected.txt	2012-02-08 19:19:03 UTC (rev 107108)
@@ -0,0 +1,6 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 200x200
+  RenderSVGRoot {svg} at (0,0) size 100x100
+    RenderSVGViewportContainer {svg} at (0,0) size 100x100
+      RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]

Added: trunk/LayoutTests/svg/repaint/inner-svg-change-viewBox.svg (0 => 107108)


--- trunk/LayoutTests/svg/repaint/inner-svg-change-viewBox.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/repaint/inner-svg-change-viewBox.svg	2012-02-08 19:19:03 UTC (rev 107108)
@@ -0,0 +1,14 @@
+<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" _onload_="runRepaintTest()">
+<script xlink:href=""
+<script>
+<![CDATA[
+    function repaintTest() {
+        document.getElementById('s').setAttribute("viewBox", "0 0 200 200");
+    }
+]]>
+</script>
+
+<svg id="s" viewBox="0 0 800 800">
+    <rect fill="green" width="50%" height="50%"/>
+</svg>
+</svg>

Modified: trunk/Source/WebCore/ChangeLog (107107 => 107108)


--- trunk/Source/WebCore/ChangeLog	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/Source/WebCore/ChangeLog	2012-02-08 19:19:03 UTC (rev 107108)
@@ -1,3 +1,42 @@
+2012-02-08  Dirk Schulze  <k...@webkit.org>
+
+        viewBox on nested SVG causes wrong content size for relative values
+        https://bugs.webkit.org/show_bug.cgi?id=69459
+
+        Reviewed by Nikolas.
+
+        In the past we just checked the change of the viewport size of the root SVG element. If the size changed, all childs
+        with relative length values needed a relayout. We did not consider that we might have other viewports in the document.
+        Childs with relative lengths had a strange zooming, if just the viewport size of an inner SVG element changed.
+
+        With this patch we check if the size of the nearest viewport changes. Is this the case, childs with relative lengths
+        need a relayout.
+
+        Test: inner-svg-change-viewBox.svg
+
+        * rendering/svg/RenderSVGContainer.cpp:
+        (WebCore::RenderSVGContainer::layout):
+        * rendering/svg/RenderSVGContainer.h:
+        (RenderSVGContainer):
+        (WebCore::RenderSVGContainer::determineIfLayoutSizeChanged): Check if we need layout and have relative length values.
+        * rendering/svg/RenderSVGRoot.cpp:
+        (WebCore::RenderSVGRoot::layout): Remove resetting 'viewport size changed' flag for code operability. No influence on the layout.
+        * rendering/svg/RenderSVGViewportContainer.cpp:
+        (WebCore::RenderSVGViewportContainer::RenderSVGViewportContainer): Add a flag that indicates that the viewport size changes.
+        (WebCore::RenderSVGViewportContainer::determineIfLayoutSizeChanged): The flag gets set during the layout phase of the SVG element if the size changes.
+        (WebCore):
+        * rendering/svg/RenderSVGViewportContainer.h:
+        (WebCore::RenderSVGViewportContainer::isLayoutSizeChanged): Added getter to get flag status.
+        (RenderSVGViewportContainer):
+        (WebCore::toRenderSVGViewportContainer): Added casting function for constant RenderObjects.
+        (WebCore):
+        * rendering/svg/SVGRenderSupport.cpp:
+        (WebCore::layoutSizeOfNearestViewportChanged): Search the nearest viewport and check if the size changed.
+        (WebCore):
+        (WebCore::SVGRenderSupport::layoutChildren): Don't check the roots viewport for size changes, but the nearest viewport.
+        * svg/SVGSVGElement.cpp:
+        (WebCore::SVGSVGElement::svgAttributeChanged): Added viewBoxAttr to the list of attributes that cause relayout.
+
 2012-02-08  Gregg Tavares  <g...@google.com>
 
         Implement new WEBGL compressed texture extensions

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp (107107 => 107108)


--- trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp	2012-02-08 19:19:03 UTC (rev 107108)
@@ -63,6 +63,9 @@
     // Allow RenderSVGTransformableContainer to update its transform.
     bool updatedTransform = calculateLocalTransform();
 
+    // RenderSVGViewportContainer needs to set the 'layout size changed' flag.
+    determineIfLayoutSizeChanged();
+
     SVGRenderSupport::layoutChildren(this, selfNeedsLayout() || SVGRenderSupport::filtersForceContainerLayout(this));
 
     // Invalidate all resources of this client if our layout changed.

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h (107107 => 107108)


--- trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h	2012-02-08 19:19:03 UTC (rev 107108)
@@ -67,6 +67,8 @@
     virtual void applyViewportClip(PaintInfo&) { }
     virtual bool pointIsInsideViewportClip(const FloatPoint& /*pointInParent*/) { return true; }
 
+    virtual void determineIfLayoutSizeChanged() { }
+
     bool selfWillPaint();
     void updateCachedBoundaries();
 

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp (107107 => 107108)


--- trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp	2012-02-08 19:19:03 UTC (rev 107108)
@@ -214,7 +214,6 @@
     SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
     m_isLayoutSizeChanged = needsLayout || (svg->hasRelativeLengths() && oldSize != size());
     SVGRenderSupport::layoutChildren(this, needsLayout || SVGRenderSupport::filtersForceContainerLayout(this));
-    m_isLayoutSizeChanged = false;
 
     // At this point LayoutRepainter already grabbed the old bounds,
     // recalculate them now so repaintAfterLayout() uses the new bounds.

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp (107107 => 107108)


--- trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp	2012-02-08 19:19:03 UTC (rev 107108)
@@ -34,9 +34,18 @@
 
 RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node)
     : RenderSVGContainer(node)
+    , m_isLayoutSizeChanged(false)
 {
 }
 
+void RenderSVGViewportContainer::determineIfLayoutSizeChanged()
+{
+    if (!node()->hasTagName(SVGNames::svgTag))
+        return;
+
+    m_isLayoutSizeChanged = static_cast<SVGSVGElement*>(node())->hasRelativeLengths() && selfNeedsLayout();
+}
+
 void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
 {
     if (SVGRenderSupport::isOverflowHidden(this))

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h (107107 => 107108)


--- trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h	2012-02-08 19:19:03 UTC (rev 107108)
@@ -35,6 +35,10 @@
     explicit RenderSVGViewportContainer(SVGStyledElement*);
     FloatRect viewport() const { return m_viewport; }
 
+    bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
+
+    virtual void determineIfLayoutSizeChanged();
+
 private:
     virtual bool isSVGContainer() const { return true; }
     virtual bool isSVGViewportContainer() const { return true; }
@@ -50,6 +54,7 @@
 
     FloatRect m_viewport;
     mutable AffineTransform m_localToParentTransform;
+    bool m_isLayoutSizeChanged : 1;
 };
   
 inline RenderSVGViewportContainer* toRenderSVGViewportContainer(RenderObject* object)
@@ -58,6 +63,12 @@
     return static_cast<RenderSVGViewportContainer*>(object);
 }
 
+inline const RenderSVGViewportContainer* toRenderSVGViewportContainer(const RenderObject* object)
+{
+    ASSERT(!object || !strcmp(object->renderName(), "RenderSVGViewportContainer"));
+    return static_cast<const RenderSVGViewportContainer*>(object);
+}
+
 // This will catch anyone doing an unnecessary cast.
 void toRenderSVGViewportContainer(const RenderSVGViewportContainer*);
 

Modified: trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp (107107 => 107108)


--- trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp	2012-02-08 19:19:03 UTC (rev 107108)
@@ -39,6 +39,7 @@
 #include "RenderSVGResourceMarker.h"
 #include "RenderSVGResourceMasker.h"
 #include "RenderSVGRoot.h"
+#include "RenderSVGViewportContainer.h"
 #include "SVGResources.h"
 #include "SVGResourcesCache.h"
 #include "SVGStyledElement.h"
@@ -231,9 +232,22 @@
         invalidateResourcesOfChildren(child);
 }
 
+static inline bool layoutSizeOfNearestViewportChanged(const RenderObject* start)
+{
+    while (start && !start->isSVGRoot() && !start->isSVGViewportContainer())
+        start = start->parent();
+
+    ASSERT(start);
+    ASSERT(start->isSVGRoot() || start->isSVGViewportContainer());
+    if (start->isSVGViewportContainer())
+        return toRenderSVGViewportContainer(start)->isLayoutSizeChanged();
+
+    return toRenderSVGRoot(start)->isLayoutSizeChanged();
+}
+
 void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
 {
-    bool layoutSizeChanged = findTreeRootObject(start)->isLayoutSizeChanged();
+    bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start);
     HashSet<RenderObject*> notlayoutedObjects;
 
     for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {

Modified: trunk/Source/WebCore/svg/SVGSVGElement.cpp (107107 => 107108)


--- trunk/Source/WebCore/svg/SVGSVGElement.cpp	2012-02-08 19:13:56 UTC (rev 107107)
+++ trunk/Source/WebCore/svg/SVGSVGElement.cpp	2012-02-08 19:19:03 UTC (rev 107108)
@@ -303,7 +303,8 @@
     if (updateRelativeLengths
         || SVGLangSpace::isKnownAttribute(attrName)
         || SVGExternalResourcesRequired::isKnownAttribute(attrName)
-        || SVGZoomAndPan::isKnownAttribute(attrName)) {
+        || SVGZoomAndPan::isKnownAttribute(attrName)
+        || attrName == SVGNames::viewBoxAttr) {
         if (renderer())
             RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer());
         return;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to