Title: [112091] trunk
Revision
112091
Author
[email protected]
Date
2012-03-26 07:36:59 -0700 (Mon, 26 Mar 2012)

Log Message

Add invalid bounding box concept to SVG containers
https://bugs.webkit.org/show_bug.cgi?id=81104

Patch by Philip Rogers <[email protected]> on 2012-03-26
Reviewed by Nikolas Zimmermann.

Source/WebCore:

An empty <g> element needs to use an invalid bounding box because
an empty bounding box isn't the default state. This change
introduces the concept of an invalid object bounding box for
both RenderSVGContainer and RenderSVGRoot. Code that
does not explicitly check that the bounding box is valid
should be unaffected by this change. We use this new invalid
flag in computeContainerBoundingBoxes so that we do not
include invalid bounding boxes.

This change also contains a small fix in
RenderSVGContainer::toRenderSVGContainer which depended on
RenderSVGViewportContainer not inheriting from RenderSVGContainer,
which it now does.

Test: svg/custom/getBBox-empty-container.html

* rendering/svg/RenderSVGContainer.cpp:
(WebCore::RenderSVGContainer::RenderSVGContainer):
(WebCore::RenderSVGContainer::updateCachedBoundaries):
* rendering/svg/RenderSVGContainer.h:
(WebCore::RenderSVGContainer::isObjectBoundingBoxValid):
(RenderSVGContainer):
(WebCore::toRenderSVGContainer):
* rendering/svg/RenderSVGRoot.cpp:
(WebCore::RenderSVGRoot::RenderSVGRoot):
(WebCore::RenderSVGRoot::updateCachedBoundaries):
* rendering/svg/RenderSVGRoot.h:
(RenderSVGRoot):
* rendering/svg/SVGRenderSupport.cpp:
(WebCore):
(WebCore::updateObjectBoundingBox):
(WebCore::SVGRenderSupport::computeContainerBoundingBoxes):
* rendering/svg/SVGRenderSupport.h:
(SVGRenderSupport):

LayoutTests:

* svg/custom/getBBox-empty-container-expected.txt: Added.
* svg/custom/getBBox-empty-container.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (112090 => 112091)


--- trunk/LayoutTests/ChangeLog	2012-03-26 14:32:52 UTC (rev 112090)
+++ trunk/LayoutTests/ChangeLog	2012-03-26 14:36:59 UTC (rev 112091)
@@ -1,3 +1,13 @@
+2012-03-26  Philip Rogers  <[email protected]>
+
+        Add invalid bounding box concept to SVG containers
+        https://bugs.webkit.org/show_bug.cgi?id=81104
+
+        Reviewed by Nikolas Zimmermann.
+
+        * svg/custom/getBBox-empty-container-expected.txt: Added.
+        * svg/custom/getBBox-empty-container.html: Added.
+
 2012-03-26  Pavel Feldman  <[email protected]>
 
         Not reviewed: [chromium] rebaselining plugins/embed-attributes-style.

Added: trunk/LayoutTests/svg/custom/getBBox-empty-container-expected.txt (0 => 112091)


--- trunk/LayoutTests/svg/custom/getBBox-empty-container-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/svg/custom/getBBox-empty-container-expected.txt	2012-03-26 14:36:59 UTC (rev 112091)
@@ -0,0 +1 @@
+PASS, bounding box sizes are (100, 100) and (100, 100)

Added: trunk/LayoutTests/svg/custom/getBBox-empty-container.html (0 => 112091)


--- trunk/LayoutTests/svg/custom/getBBox-empty-container.html	                        (rev 0)
+++ trunk/LayoutTests/svg/custom/getBBox-empty-container.html	2012-03-26 14:36:59 UTC (rev 112091)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<!-- Test that svg bounding boxes are not affected by empty containers -->
+    <head>
+        <script type="text/_javascript_">
+            function checkBoundingBoxesEqual() {
+                if (window.layoutTestController)
+                    window.layoutTestController.dumpAsText();
+
+                // Ensure both boxes are the same size, meaning the empty <g> does not affect the bbox size.
+                var bboxA = document.getElementById('ga').getBBox();
+                var bboxB = document.getElementById('gb').getBBox();
+                var results = "FAIL";
+                if (bboxA.width == bboxB.width && bboxA.height == bboxB.height)
+                    results = "PASS";
+                document.body.innerHTML = results + ", bounding box sizes are (" + 
+                    bboxA.width + ", " + bboxA.height + ") and (" + 
+                    bboxB.width + ", " + bboxB.height + ")";
+            }
+        </script>
+    </head>
+    <body _onload_="checkBoundingBoxesEqual()">
+        <svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">    
+            <g id="ga">
+                <g></g>
+                <g transform="translate(100, 100)">
+                	<g></g>
+                    <rect x="0" y="0" width="100" height="100" rx="10" ry="10" stroke="#000000" stroke-width="1" fill="#ffffcc" />
+                </g>
+            </g>
+            <g id="gb">
+                <g transform="translate(100, 100)">
+                    <rect x="0" y="0" width="100" height="100" rx="10" ry="10" stroke="#000000" stroke-width="1" fill="#ffffcc" />
+                </g>
+            </g>
+        </svg>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (112090 => 112091)


--- trunk/Source/WebCore/ChangeLog	2012-03-26 14:32:52 UTC (rev 112090)
+++ trunk/Source/WebCore/ChangeLog	2012-03-26 14:36:59 UTC (rev 112091)
@@ -1,3 +1,45 @@
+2012-03-26  Philip Rogers  <[email protected]>
+
+        Add invalid bounding box concept to SVG containers
+        https://bugs.webkit.org/show_bug.cgi?id=81104
+
+        Reviewed by Nikolas Zimmermann.
+
+        An empty <g> element needs to use an invalid bounding box because
+        an empty bounding box isn't the default state. This change
+        introduces the concept of an invalid object bounding box for
+        both RenderSVGContainer and RenderSVGRoot. Code that
+        does not explicitly check that the bounding box is valid
+        should be unaffected by this change. We use this new invalid
+        flag in computeContainerBoundingBoxes so that we do not
+        include invalid bounding boxes.
+
+        This change also contains a small fix in
+        RenderSVGContainer::toRenderSVGContainer which depended on
+        RenderSVGViewportContainer not inheriting from RenderSVGContainer,
+        which it now does.
+
+        Test: svg/custom/getBBox-empty-container.html
+
+        * rendering/svg/RenderSVGContainer.cpp:
+        (WebCore::RenderSVGContainer::RenderSVGContainer):
+        (WebCore::RenderSVGContainer::updateCachedBoundaries):
+        * rendering/svg/RenderSVGContainer.h:
+        (WebCore::RenderSVGContainer::isObjectBoundingBoxValid):
+        (RenderSVGContainer):
+        (WebCore::toRenderSVGContainer):
+        * rendering/svg/RenderSVGRoot.cpp:
+        (WebCore::RenderSVGRoot::RenderSVGRoot):
+        (WebCore::RenderSVGRoot::updateCachedBoundaries):
+        * rendering/svg/RenderSVGRoot.h:
+        (RenderSVGRoot):
+        * rendering/svg/SVGRenderSupport.cpp:
+        (WebCore):
+        (WebCore::updateObjectBoundingBox):
+        (WebCore::SVGRenderSupport::computeContainerBoundingBoxes):
+        * rendering/svg/SVGRenderSupport.h:
+        (SVGRenderSupport):
+
 2012-03-26  Alexei Filippov  <[email protected]>
 
         Web Inspector: Speed up the retainers build phase.

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp (112090 => 112091)


--- trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp	2012-03-26 14:32:52 UTC (rev 112090)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp	2012-03-26 14:36:59 UTC (rev 112091)
@@ -40,6 +40,7 @@
 
 RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node)
     : RenderSVGModelObject(node)
+    , m_objectBoundingBoxValid(false)
     , m_needsBoundariesUpdate(true)
 {
 }
@@ -150,10 +151,11 @@
 void RenderSVGContainer::updateCachedBoundaries()
 {
     m_objectBoundingBox = FloatRect();
+    m_objectBoundingBoxValid = false;
     m_strokeBoundingBox = FloatRect();
     m_repaintBoundingBox = FloatRect();
 
-    SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_strokeBoundingBox, m_repaintBoundingBox);
+    SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox);
     SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
 }
 

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h (112090 => 112091)


--- trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h	2012-03-26 14:32:52 UTC (rev 112090)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h	2012-03-26 14:36:59 UTC (rev 112091)
@@ -42,6 +42,7 @@
     virtual void paint(PaintInfo&, const LayoutPoint&);
     virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; }
     virtual bool didTransformToRootUpdate() { return false; }
+    bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; }
 
 protected:
     virtual RenderObjectChildList* virtualChildren() { return children(); }
@@ -76,6 +77,7 @@
 private:
     RenderObjectChildList m_children;
     FloatRect m_objectBoundingBox;
+    bool m_objectBoundingBoxValid;
     FloatRect m_strokeBoundingBox;
     FloatRect m_repaintBoundingBox;
     bool m_needsBoundariesUpdate : 1;
@@ -83,15 +85,13 @@
   
 inline RenderSVGContainer* toRenderSVGContainer(RenderObject* object)
 {
-    // Note: isSVGContainer is also true for RenderSVGViewportContainer, which is not derived from this.
-    ASSERT(!object || (object->isSVGContainer() && strcmp(object->renderName(), "RenderSVGViewportContainer")));
+    ASSERT(!object || object->isSVGContainer());
     return static_cast<RenderSVGContainer*>(object);
 }
 
 inline const RenderSVGContainer* toRenderSVGContainer(const RenderObject* object)
 {
-    // Note: isSVGContainer is also true for RenderSVGViewportContainer, which is not derived from this.
-    ASSERT(!object || (object->isSVGContainer() && strcmp(object->renderName(), "RenderSVGViewportContainer")));
+    ASSERT(!object || object->isSVGContainer());
     return static_cast<const RenderSVGContainer*>(object);
 }
 

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp (112090 => 112091)


--- trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp	2012-03-26 14:32:52 UTC (rev 112090)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp	2012-03-26 14:36:59 UTC (rev 112091)
@@ -57,6 +57,7 @@
 
 RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node)
     : RenderReplaced(node)
+    , m_objectBoundingBoxValid(false)
     , m_isLayoutSizeChanged(false)
     , m_needsBoundariesOrTransformUpdate(true)
 {
@@ -392,10 +393,11 @@
 void RenderSVGRoot::updateCachedBoundaries()
 {
     m_objectBoundingBox = FloatRect();
+    m_objectBoundingBoxValid = false;
     m_strokeBoundingBox = FloatRect();
     m_repaintBoundingBox = FloatRect();
 
-    SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_strokeBoundingBox, m_repaintBoundingBox);
+    SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox);
     SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
     m_repaintBoundingBox.inflate(borderAndPaddingWidth());
 }

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGRoot.h (112090 => 112091)


--- trunk/Source/WebCore/rendering/svg/RenderSVGRoot.h	2012-03-26 14:32:52 UTC (rev 112090)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGRoot.h	2012-03-26 14:36:59 UTC (rev 112091)
@@ -104,6 +104,7 @@
     RenderObjectChildList m_children;
     IntSize m_containerSize;
     FloatRect m_objectBoundingBox;
+    bool m_objectBoundingBoxValid;
     FloatRect m_strokeBoundingBox;
     FloatRect m_repaintBoundingBox;
     mutable AffineTransform m_localToParentTransform;

Modified: trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp (112090 => 112091)


--- trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp	2012-03-26 14:32:52 UTC (rev 112090)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp	2012-03-26 14:36:59 UTC (rev 112091)
@@ -85,32 +85,38 @@
     parent->mapLocalToContainer(repaintContainer, false, true, transformState, wasFixed);
 }
 
-void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox)
+// Update a bounding box taking into account the validity of the other bounding box.
+static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
 {
-    bool isFirstChild = true;
+    bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isObjectBoundingBoxValid() : true;
+    if (!otherValid)
+        return;
 
+    if (!objectBoundingBoxValid) {
+        objectBoundingBox = otherBoundingBox;
+        objectBoundingBoxValid = true;
+        return;
+    }
+
+    objectBoundingBox.uniteEvenIfEmpty(otherBoundingBox);
+}
+
+void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox)
+{
     for (RenderObject* current = container->firstChild(); current; current = current->nextSibling()) {
         if (current->isSVGHiddenContainer())
             continue;
 
         const AffineTransform& transform = current->localToParentTransform();
         if (transform.isIdentity()) {
-            if (isFirstChild)
-                objectBoundingBox = current->objectBoundingBox();
-            else
-                objectBoundingBox.uniteEvenIfEmpty(current->objectBoundingBox());
+            updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox());
             strokeBoundingBox.unite(current->strokeBoundingBox());
             repaintBoundingBox.unite(current->repaintRectInLocalCoordinates());
         } else {
-            if (isFirstChild)
-                objectBoundingBox = transform.mapRect(current->objectBoundingBox());
-            else
-                objectBoundingBox.uniteEvenIfEmpty(transform.mapRect(current->objectBoundingBox()));
+            updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox()));
             strokeBoundingBox.unite(transform.mapRect(current->strokeBoundingBox()));
             repaintBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates()));
         }
-
-        isFirstChild = false;
     }
 }
 

Modified: trunk/Source/WebCore/rendering/svg/SVGRenderSupport.h (112090 => 112091)


--- trunk/Source/WebCore/rendering/svg/SVGRenderSupport.h	2012-03-26 14:32:52 UTC (rev 112090)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderSupport.h	2012-03-26 14:36:59 UTC (rev 112091)
@@ -57,7 +57,7 @@
     // Determines whether the passed point lies in a clipping area
     static bool pointInClippingArea(RenderObject*, const FloatPoint&);
 
-    static void computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox);
+    static void computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox);
     static bool paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo&);
 
     // Important functions used by nearly all SVG renderers centralizing coordinate transformations / repaint rect calculations
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to