Reviewed by David Hyatt.

        Split out objectBoundingBox and repaintRectInLocalCoordinates from relativeBBox
        in preparation for simplifying (and fixing) repaint logic in the SVG rendering tree.
        https://bugs.webkit.org/show_bug.cgi?id=25224

        objectBoundingBox() matches the SVG 1.1 concept of a "bounding box"

        repaintRectInLocalCoordinates() should return the a rect covering all painted content.
        However, repaintRectInLocalCoordinates() still only returns the "stroke bounding box"
        in this patch.  In a future patch, repaintRectInLocalCoordinates will be fixed to return
        a rect covering all painted content.  In order to avoid changing several hundred layout test results, I've left
        the behavior as-is for now.  The returned rect is used by various repaintRectInLocalCoordinates
        implementations and sometimes adjusted to include all painted content, but not always, and
        the places where the adjustments are made are sometimes wrong.  Again, will be fixed in
        an upcoming patch.

        This patch discovered a bug in Font::drawTextUsingSVGFont, which is probably causing
        bounding-box relative gradients on SVGFont glyphs to not paint correctly.
        I chose not to try and fix the bug in this patch and instead left a FIXME.

        This patch also discovered that at least tspan.getBBox() is broken.  This
        along with the foreignObject.getBBox() change will be tested (and fixed) in a
        later patch.  https://bugs.webkit.org/show_bug.cgi?id=25225

        No change in behavior (besides the above mentioned foreignObject.getBBox()), thus no tests.

        * rendering/RenderForeignObject.cpp:
        (WebCore::RenderForeignObject::objectBoundingBox): this is a behavior improvement for getBBox() test case coming in a later patch
        (WebCore::RenderForeignObject::repaintRectInLocalCoordinates): only really used for layout test results, might some day be used for repaint.
        * rendering/RenderForeignObject.h:
        * rendering/RenderObject.cpp:
        (WebCore::RenderObject::objectBoundingBox): new methods, ASSERT if used but not implemented.
        (WebCore::RenderObject::repaintRectInLocalCoordinates):
        * rendering/RenderObject.h:
        * rendering/RenderPath.cpp:
        (WebCore::RenderPath::objectBoundingBox):
        (WebCore::RenderPath::repaintRectInLocalCoordinates):
        (WebCore::RenderPath::clippedOverflowRectForRepaint):
        (WebCore::RenderPath::lineHeight):
        (WebCore::RenderPath::baselinePosition):
        (WebCore::RenderPath::paint):
        (WebCore::RenderPath::addFocusRingRects):
        * rendering/RenderPath.h:
        * rendering/RenderSVGContainer.cpp:
        (WebCore::RenderSVGContainer::paint):
        (WebCore::RenderSVGContainer::objectBoundingBox):
        (WebCore::RenderSVGContainer::repaintRectInLocalCoordinates):
        * rendering/RenderSVGContainer.h:
        * rendering/RenderSVGGradientStop.h:
        (WebCore::RenderSVGGradientStop::objectBoundingBox):
        (WebCore::RenderSVGGradientStop::repaintRectInLocalCoordinates):
        * rendering/RenderSVGHiddenContainer.cpp:
        (WebCore::RenderSVGHiddenContainer::objectBoundingBox):
        (WebCore::RenderSVGHiddenContainer::repaintRectInLocalCoordinates):
        * rendering/RenderSVGHiddenContainer.h:
        * rendering/RenderSVGImage.cpp:
        (WebCore::RenderSVGImage::objectBoundingBox):
        (WebCore::RenderSVGImage::repaintRectInLocalCoordinates):
        (WebCore::RenderSVGImage::calculateAbsoluteBounds):
        (WebCore::RenderSVGImage::addFocusRingRects):
        * rendering/RenderSVGImage.h:
        * rendering/RenderSVGRoot.cpp:
        (WebCore::RenderSVGRoot::paint):
        (WebCore::RenderSVGRoot::objectBoundingBox):
        (WebCore::RenderSVGRoot::repaintRectInLocalCoordinates):
        * rendering/RenderSVGRoot.h:
        * rendering/RenderSVGTSpan.h:
        (WebCore::RenderSVGTSpan::objectBoundingBox):
        (WebCore::RenderSVGTSpan::repaintRectInLocalCoordinates):
        * rendering/RenderSVGText.cpp:
        (WebCore::RenderSVGText::clippedOverflowRectForRepaint):
        (WebCore::RenderSVGText::absoluteRects):
        (WebCore::RenderSVGText::absoluteQuads):
        (WebCore::RenderSVGText::objectBoundingBox):
        (WebCore::RenderSVGText::repaintRectInLocalCoordinates):
        * rendering/RenderSVGText.h:
        * rendering/RenderSVGViewportContainer.cpp:
        (WebCore::RenderSVGViewportContainer::viewportTransform):
        * rendering/SVGRenderSupport.cpp:
        (WebCore::computeContainerBoundingBox):
        * rendering/SVGRenderSupport.h:
        * rendering/SVGRenderTreeAsText.cpp:
        (WebCore::operator<<):
        * svg/SVGFont.cpp:
        (WebCore::Font::drawTextUsingSVGFont):
        * svg/SVGLocatable.cpp:
        (WebCore::SVGLocatable::getBBox):
        * svg/SVGPatternElement.cpp:
        (WebCore::SVGPatternElement::buildPattern):
        * svg/graphics/SVGPaintServerGradient.cpp:
        (WebCore::createMaskAndSwapContextForTextGradient):
        (WebCore::clipToTextMask):
        (WebCore::SVGPaintServerGradient::setup):
        * svg/graphics/SVGPaintServerPattern.cpp:
        (WebCore::SVGPaintServerPattern::setup):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@42578 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index c1aee50..68eb602 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,102 @@
+2009-04-15  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by David Hyatt.
+
+        Split out objectBoundingBox and repaintRectInLocalCoordinates from relativeBBox
+        in preparation for simplifying (and fixing) repaint logic in the SVG rendering tree.
+        https://bugs.webkit.org/show_bug.cgi?id=25224
+
+        objectBoundingBox() matches the SVG 1.1 concept of a "bounding box"
+
+        repaintRectInLocalCoordinates() should return the a rect covering all painted content.
+        However, repaintRectInLocalCoordinates() still only returns the "stroke bounding box"
+        in this patch.  In a future patch, repaintRectInLocalCoordinates will be fixed to return
+        a rect covering all painted content.  In order to avoid changing several hundred layout test results, I've left
+        the behavior as-is for now.  The returned rect is used by various repaintRectInLocalCoordinates
+        implementations and sometimes adjusted to include all painted content, but not always, and
+        the places where the adjustments are made are sometimes wrong.  Again, will be fixed in
+        an upcoming patch.
+
+        This patch discovered a bug in Font::drawTextUsingSVGFont, which is probably causing
+        bounding-box relative gradients on SVGFont glyphs to not paint correctly.
+        I chose not to try and fix the bug in this patch and instead left a FIXME.
+
+        This patch also discovered that at least tspan.getBBox() is broken.  This
+        along with the foreignObject.getBBox() change will be tested (and fixed) in a
+        later patch.  https://bugs.webkit.org/show_bug.cgi?id=25225
+
+        No change in behavior (besides the above mentioned foreignObject.getBBox()), thus no tests.
+
+        * rendering/RenderForeignObject.cpp:
+        (WebCore::RenderForeignObject::objectBoundingBox): this is a behavior improvement for getBBox() test case coming in a later patch
+        (WebCore::RenderForeignObject::repaintRectInLocalCoordinates): only really used for layout test results, might some day be used for repaint.
+        * rendering/RenderForeignObject.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::objectBoundingBox): new methods, ASSERT if used but not implemented.
+        (WebCore::RenderObject::repaintRectInLocalCoordinates):
+        * rendering/RenderObject.h:
+        * rendering/RenderPath.cpp:
+        (WebCore::RenderPath::objectBoundingBox):
+        (WebCore::RenderPath::repaintRectInLocalCoordinates):
+        (WebCore::RenderPath::clippedOverflowRectForRepaint):
+        (WebCore::RenderPath::lineHeight):
+        (WebCore::RenderPath::baselinePosition):
+        (WebCore::RenderPath::paint):
+        (WebCore::RenderPath::addFocusRingRects):
+        * rendering/RenderPath.h:
+        * rendering/RenderSVGContainer.cpp:
+        (WebCore::RenderSVGContainer::paint):
+        (WebCore::RenderSVGContainer::objectBoundingBox):
+        (WebCore::RenderSVGContainer::repaintRectInLocalCoordinates):
+        * rendering/RenderSVGContainer.h:
+        * rendering/RenderSVGGradientStop.h:
+        (WebCore::RenderSVGGradientStop::objectBoundingBox):
+        (WebCore::RenderSVGGradientStop::repaintRectInLocalCoordinates):
+        * rendering/RenderSVGHiddenContainer.cpp:
+        (WebCore::RenderSVGHiddenContainer::objectBoundingBox):
+        (WebCore::RenderSVGHiddenContainer::repaintRectInLocalCoordinates):
+        * rendering/RenderSVGHiddenContainer.h:
+        * rendering/RenderSVGImage.cpp:
+        (WebCore::RenderSVGImage::objectBoundingBox):
+        (WebCore::RenderSVGImage::repaintRectInLocalCoordinates):
+        (WebCore::RenderSVGImage::calculateAbsoluteBounds):
+        (WebCore::RenderSVGImage::addFocusRingRects):
+        * rendering/RenderSVGImage.h:
+        * rendering/RenderSVGRoot.cpp:
+        (WebCore::RenderSVGRoot::paint):
+        (WebCore::RenderSVGRoot::objectBoundingBox):
+        (WebCore::RenderSVGRoot::repaintRectInLocalCoordinates):
+        * rendering/RenderSVGRoot.h:
+        * rendering/RenderSVGTSpan.h:
+        (WebCore::RenderSVGTSpan::objectBoundingBox):
+        (WebCore::RenderSVGTSpan::repaintRectInLocalCoordinates):
+        * rendering/RenderSVGText.cpp:
+        (WebCore::RenderSVGText::clippedOverflowRectForRepaint):
+        (WebCore::RenderSVGText::absoluteRects):
+        (WebCore::RenderSVGText::absoluteQuads):
+        (WebCore::RenderSVGText::objectBoundingBox):
+        (WebCore::RenderSVGText::repaintRectInLocalCoordinates):
+        * rendering/RenderSVGText.h:
+        * rendering/RenderSVGViewportContainer.cpp:
+        (WebCore::RenderSVGViewportContainer::viewportTransform):
+        * rendering/SVGRenderSupport.cpp:
+        (WebCore::computeContainerBoundingBox):
+        * rendering/SVGRenderSupport.h:
+        * rendering/SVGRenderTreeAsText.cpp:
+        (WebCore::operator<<):
+        * svg/SVGFont.cpp:
+        (WebCore::Font::drawTextUsingSVGFont):
+        * svg/SVGLocatable.cpp:
+        (WebCore::SVGLocatable::getBBox):
+        * svg/SVGPatternElement.cpp:
+        (WebCore::SVGPatternElement::buildPattern):
+        * svg/graphics/SVGPaintServerGradient.cpp:
+        (WebCore::createMaskAndSwapContextForTextGradient):
+        (WebCore::clipToTextMask):
+        (WebCore::SVGPaintServerGradient::setup):
+        * svg/graphics/SVGPaintServerPattern.cpp:
+        (WebCore::SVGPaintServerPattern::setup):
+
 2009-04-16  Dan Bernstein  <mitz@apple.com>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp
index 0584c1c..52b1f07 100644
--- a/WebCore/rendering/RenderForeignObject.cpp
+++ b/WebCore/rendering/RenderForeignObject.cpp
@@ -1,7 +1,6 @@
 /*
- * This file is part of the WebKit project.
- *
  * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2009 Google, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -70,6 +69,20 @@
     paintInfo.context->restore();
 }
 
+FloatRect RenderForeignObject::objectBoundingBox() const
+{
+    return borderBoxRect();
+}
+
+FloatRect RenderForeignObject::repaintRectInLocalCoordinates() const
+{
+    // HACK: to maintain historical LayoutTest results for now.
+    // RenderForeignObject is a RenderBlock (not a RenderSVGModelObject) so this
+    // should not affect repaint correctness.  But it should really be:
+    // return borderBoxRect();
+    return FloatRect();
+}
+
 void RenderForeignObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
 {
     TransformationMatrix transform = translationForAttributes() * localTransform();
diff --git a/WebCore/rendering/RenderForeignObject.h b/WebCore/rendering/RenderForeignObject.h
index ab96785..a0f20c9 100644
--- a/WebCore/rendering/RenderForeignObject.h
+++ b/WebCore/rendering/RenderForeignObject.h
@@ -1,7 +1,6 @@
 /*
- * This file is part of the WebKit project.
- *
  * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2009 Google, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -46,6 +45,9 @@
     virtual bool requiresLayer() const { return false; }
     virtual void layout();
 
+    virtual FloatRect objectBoundingBox() const;
+    virtual FloatRect repaintRectInLocalCoordinates() const;
+
     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
 
  private:
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
index 0e1277c..f6c0828 100644
--- a/WebCore/rendering/RenderObject.cpp
+++ b/WebCore/rendering/RenderObject.cpp
@@ -2350,8 +2350,17 @@
 
 #if ENABLE(SVG)
 
-FloatRect RenderObject::relativeBBox(bool) const
+FloatRect RenderObject::objectBoundingBox() const
 {
+    ASSERT_NOT_REACHED();
+    return FloatRect();
+}
+
+// Returns the smallest rectangle enclosing all of the painted content
+// respecting clipping, masking, filters, opacity, stroke-width and markers
+FloatRect RenderObject::repaintRectInLocalCoordinates() const
+{
+    ASSERT_NOT_REACHED();
     return FloatRect();
 }
 
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
index cad0430..7c2d51f 100644
--- a/WebCore/rendering/RenderObject.h
+++ b/WebCore/rendering/RenderObject.h
@@ -294,7 +294,17 @@
     virtual bool isRenderPath() const { return false; }
     virtual bool isSVGText() const { return false; }
 
-    virtual FloatRect relativeBBox(bool includeStroke = true) const;
+    // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width.
+    // This is used for all computation of objectBoundingBox relative units and by SVGLocateable::getBBox().
+    // NOTE: Markers are not specifically ignored here by SVG 1.1 spec, but we ignore them
+    // since stroke-width is ignored (and marker size can depend on stroke-width).
+    // objectBoundingBox is returned local coordinates.
+    // The name objectBoundingBox is taken from the SVG 1.1 spec.
+    virtual FloatRect objectBoundingBox() const;
+
+    // Returns the smallest rectangle enclosing all of the painted content
+    // respecting clipping, masking, filters, opacity, stroke-width and markers
+    virtual FloatRect repaintRectInLocalCoordinates() const;
 
     virtual TransformationMatrix localTransform() const;
     virtual TransformationMatrix absoluteTransform() const;
diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp
index 42b735c..f95994c 100644
--- a/WebCore/rendering/RenderPath.cpp
+++ b/WebCore/rendering/RenderPath.cpp
@@ -107,33 +107,34 @@
     return m_path.strokeContains(&strokeStyle, point);
 }
 
-FloatRect RenderPath::relativeBBox(bool includeStroke) const
+FloatRect RenderPath::objectBoundingBox() const
 {
     if (m_path.isEmpty())
         return FloatRect();
 
-    if (includeStroke) {
-        if (m_strokeBbox.isEmpty()) {
-            if (style()->svgStyle()->hasStroke()) {
-                BoundingRectStrokeStyleApplier strokeStyle(this, style());
-                m_strokeBbox = m_path.strokeBoundingRect(&strokeStyle);
-            } else {
-                if (m_fillBBox.isEmpty())
-                    m_fillBBox = m_path.boundingRect();
-
-                m_strokeBbox = m_fillBBox;
-            }
-        }
-
-        return m_strokeBbox;
-    }
-
     if (m_fillBBox.isEmpty())
         m_fillBBox = m_path.boundingRect();
 
     return m_fillBBox;
 }
 
+FloatRect RenderPath::repaintRectInLocalCoordinates() const
+{
+    if (m_path.isEmpty())
+        return FloatRect();
+
+    if (m_strokeBbox.isEmpty()) {
+        if (!style()->svgStyle()->hasStroke())
+            return objectBoundingBox();
+
+        BoundingRectStrokeStyleApplier strokeStyle(this, style());
+        m_strokeBbox = m_path.strokeBoundingRect(&strokeStyle);
+    }
+    // FIXME: This should include filter and marker content too.
+
+    return m_strokeBbox;
+}
+
 void RenderPath::setPath(const Path& newPath)
 {
     m_path = newPath;
@@ -172,7 +173,7 @@
 IntRect RenderPath::clippedOverflowRectForRepaint(RenderBoxModelObject* /*repaintContainer*/)
 {
     // FIXME: handle non-root repaintContainer
-    FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
+    FloatRect repaintRect = absoluteTransform().mapRect(repaintRectInLocalCoordinates());
 
     // Markers can expand the bounding box
     repaintRect.unite(m_markerBounds);
@@ -192,12 +193,12 @@
 
 int RenderPath::lineHeight(bool, bool) const
 {
-    return relativeBBox(true).height();
+    return repaintRectInLocalCoordinates().height();
 }
 
 int RenderPath::baselinePosition(bool, bool) const
 {
-    return relativeBBox(true).height();
+    return repaintRectInLocalCoordinates().height();
 }
 
 static inline void fillAndStrokePath(const Path& path, GraphicsContext* context, RenderStyle* style, RenderPath* object)
@@ -227,7 +228,7 @@
 
     SVGResourceFilter* filter = 0;
 
-    FloatRect boundingBox = relativeBBox(true);
+    FloatRect boundingBox = repaintRectInLocalCoordinates();
     if (paintInfo.phase == PaintPhaseForeground) {
         PaintInfo savedInfo(paintInfo);
 
@@ -251,7 +252,7 @@
 
 void RenderPath::addFocusRingRects(GraphicsContext* graphicsContext, int, int) 
 {
-    graphicsContext->addFocusRingRect(enclosingIntRect(relativeBBox(true)));
+    graphicsContext->addFocusRingRect(enclosingIntRect(repaintRectInLocalCoordinates()));
 }
 
 void RenderPath::absoluteRects(Vector<IntRect>& rects, int, int, bool)
diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h
index 1ada8a9..4688344 100644
--- a/WebCore/rendering/RenderPath.h
+++ b/WebCore/rendering/RenderPath.h
@@ -45,8 +45,8 @@
     bool fillContains(const FloatPoint&, bool requiresFill = true) const;
     bool strokeContains(const FloatPoint&, bool requiresStroke = true) const;
 
-    // Returns an unscaled bounding box (not even including localTransform()) for this vector path
-    virtual FloatRect relativeBBox(bool includeStroke = true) const;
+    virtual FloatRect objectBoundingBox() const;
+    virtual FloatRect repaintRectInLocalCoordinates() const;
 
     const Path& path() const;
     void setPath(const Path&);
diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp
index ebbd1a0..d72625d 100644
--- a/WebCore/rendering/RenderSVGContainer.cpp
+++ b/WebCore/rendering/RenderSVGContainer.cpp
@@ -136,7 +136,7 @@
     SVGResourceFilter* filter = 0;
     PaintInfo savedInfo(paintInfo);
 
-    FloatRect boundingBox = relativeBBox(true);
+    FloatRect boundingBox = repaintRectInLocalCoordinates();
     if (paintInfo.phase == PaintPhaseForeground)
         prepareToRenderSVGContent(this, paintInfo, boundingBox, filter); 
 
@@ -197,23 +197,16 @@
     quads.append(absoluteClippedOverflowRect());
 }
 
-FloatRect RenderSVGContainer::relativeBBox(bool includeStroke) const
+FloatRect RenderSVGContainer::objectBoundingBox() const
 {
-    FloatRect rect;
-    
-    RenderObject* current = firstChild();
-    for (; current != 0; current = current->nextSibling()) {
-        FloatRect childBBox = current->relativeBBox(includeStroke);
-        FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
+    return computeContainerBoundingBox(this, false);
+}
 
-        // <svg> can have a viewBox contributing to the bbox
-        if (current->isSVGContainer())
-            mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
-
-        rect.unite(mappedBBox);
-    }
-
-    return rect;
+// RenderSVGContainer is used for <g> elements which do not themselves have a
+// width or height, so we union all of our child rects as our repaint rect.
+FloatRect RenderSVGContainer::repaintRectInLocalCoordinates() const
+{
+    return computeContainerBoundingBox(this, true);
 }
 
 bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
diff --git a/WebCore/rendering/RenderSVGContainer.h b/WebCore/rendering/RenderSVGContainer.h
index d79011f..64fd271 100644
--- a/WebCore/rendering/RenderSVGContainer.h
+++ b/WebCore/rendering/RenderSVGContainer.h
@@ -57,7 +57,8 @@
     virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
     virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
 
-    FloatRect relativeBBox(bool includeStroke = true) const;
+    virtual FloatRect objectBoundingBox() const;
+    virtual FloatRect repaintRectInLocalCoordinates() const;
 
     virtual bool calculateLocalTransform();
     virtual TransformationMatrix localTransform() const;
diff --git a/WebCore/rendering/RenderSVGGradientStop.h b/WebCore/rendering/RenderSVGGradientStop.h
index 7b7df5c..1d0858d 100644
--- a/WebCore/rendering/RenderSVGGradientStop.h
+++ b/WebCore/rendering/RenderSVGGradientStop.h
@@ -1,7 +1,6 @@
 /*
- * This file is part of the WebKit project.
- *
  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -41,11 +40,13 @@
 
         virtual void layout();
 
-        // This override is needed to prevent an assert on <svg><stop /></svg>
-        // RenderObject's default impl asserts.
+        // This overrides are needed to prevent ASSERTs on <svg><stop /></svg>
+        // RenderObject's default implementations ASSERT_NOT_REACHED()
         // https://bugs.webkit.org/show_bug.cgi?id=20400
         virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject*) { return IntRect(); }
-    
+        virtual FloatRect objectBoundingBox() const { return FloatRect(); }
+        virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
+
     protected:
         virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
 
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.cpp b/WebCore/rendering/RenderSVGHiddenContainer.cpp
index e868836..c958536 100644
--- a/WebCore/rendering/RenderSVGHiddenContainer.cpp
+++ b/WebCore/rendering/RenderSVGHiddenContainer.cpp
@@ -91,7 +91,12 @@
     return false;
 }
 
-FloatRect RenderSVGHiddenContainer::relativeBBox(bool) const
+FloatRect RenderSVGHiddenContainer::objectBoundingBox() const
+{
+    return FloatRect();
+}
+
+FloatRect RenderSVGHiddenContainer::repaintRectInLocalCoordinates() const
 {
     return FloatRect();
 }
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.h b/WebCore/rendering/RenderSVGHiddenContainer.h
index e92eed0..20d221c 100644
--- a/WebCore/rendering/RenderSVGHiddenContainer.h
+++ b/WebCore/rendering/RenderSVGHiddenContainer.h
@@ -55,7 +55,9 @@
         virtual TransformationMatrix absoluteTransform() const;
         virtual TransformationMatrix localTransform() const;
 
-        virtual FloatRect relativeBBox(bool includeStroke = true) const;
+        virtual FloatRect objectBoundingBox() const;
+        virtual FloatRect repaintRectInLocalCoordinates() const;
+
         virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
     };
 }
diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp
index a13ee03..a5f7852 100644
--- a/WebCore/rendering/RenderSVGImage.cpp
+++ b/WebCore/rendering/RenderSVGImage.cpp
@@ -211,7 +211,12 @@
     return false;
 }
 
-FloatRect RenderSVGImage::relativeBBox(bool) const
+FloatRect RenderSVGImage::objectBoundingBox() const
+{
+    return m_localBounds;
+}
+
+FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const
 {
     return m_localBounds;
 }
@@ -227,7 +232,7 @@
 void RenderSVGImage::calculateAbsoluteBounds()
 {
     // FIXME: broken with CSS transforms
-    FloatRect absoluteRect = absoluteTransform().mapRect(relativeBBox(true));
+    FloatRect absoluteRect = absoluteTransform().mapRect(repaintRectInLocalCoordinates());
 
 #if ENABLE(SVG_FILTERS)
     // Filters can expand the bounding box
@@ -251,7 +256,7 @@
 void RenderSVGImage::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
 {
     // this is called from paint() after the localTransform has already been applied
-    IntRect contentRect = enclosingIntRect(relativeBBox());
+    IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates());
     graphicsContext->addFocusRingRect(contentRect);
 }
 
diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h
index 4aedfef..2d95084 100644
--- a/WebCore/rendering/RenderSVGImage.h
+++ b/WebCore/rendering/RenderSVGImage.h
@@ -41,8 +41,10 @@
         virtual ~RenderSVGImage();
         
         virtual TransformationMatrix localTransform() const { return m_localTransform; }
-        
-        virtual FloatRect relativeBBox(bool includeStroke = true) const;
+
+        virtual FloatRect objectBoundingBox() const;
+        virtual FloatRect repaintRectInLocalCoordinates() const;
+
         virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
         virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
         virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp
index ed1e28b..b944847 100644
--- a/WebCore/rendering/RenderSVGRoot.cpp
+++ b/WebCore/rendering/RenderSVGRoot.cpp
@@ -178,7 +178,7 @@
 
     SVGResourceFilter* filter = 0;
 
-    FloatRect boundingBox = relativeBBox(true);
+    FloatRect boundingBox = repaintRectInLocalCoordinates();
     if (childPaintInfo.phase == PaintPhaseForeground)
         prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter);
 
@@ -230,21 +230,15 @@
     return svg->viewBoxToViewTransform(width(), height()) * ctm;
 }
 
-FloatRect RenderSVGRoot::relativeBBox(bool includeStroke) const
+FloatRect RenderSVGRoot::objectBoundingBox() const
 {
-    FloatRect rect;
-    
-    RenderObject* current = firstChild();
-    for (; current != 0; current = current->nextSibling()) {
-        FloatRect childBBox = current->relativeBBox(includeStroke);
-        FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
-        // <svg> can have a viewBox contributing to the bbox
-        if (current->isSVGContainer())
-            mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
-        rect.unite(mappedBBox);
-    }
+    return computeContainerBoundingBox(this, false);
+}
 
-    return rect;
+FloatRect RenderSVGRoot::repaintRectInLocalCoordinates() const
+{
+    // FIXME: This does not include the border but it should!
+    return computeContainerBoundingBox(this, true);
 }
 
 TransformationMatrix RenderSVGRoot::localTransform() const
diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h
index 1a20fb4..15efe52 100644
--- a/WebCore/rendering/RenderSVGRoot.h
+++ b/WebCore/rendering/RenderSVGRoot.h
@@ -55,10 +55,12 @@
 
     bool fillContains(const FloatPoint&) const;
     bool strokeContains(const FloatPoint&) const;
-    FloatRect relativeBBox(bool includeStroke = true) const;
-    
+
+    virtual FloatRect objectBoundingBox() const;
+    virtual FloatRect repaintRectInLocalCoordinates() const;
+
     virtual TransformationMatrix localTransform() const;
-   
+
     FloatRect viewport() const;
 
     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
diff --git a/WebCore/rendering/RenderSVGTSpan.h b/WebCore/rendering/RenderSVGTSpan.h
index d34cd2f..edea86e 100644
--- a/WebCore/rendering/RenderSVGTSpan.h
+++ b/WebCore/rendering/RenderSVGTSpan.h
@@ -1,8 +1,7 @@
 /*
- * This file is part of the WebKit project.
- *
  * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
  *           (C) 2006 Apple Computer Inc.
+ *           (C) 2009 Google Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -34,6 +33,12 @@
     virtual const char* renderName() const { return "RenderSVGTSpan"; }
     virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
     virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+
+    // FIXME: These are incorrect, but have always behaved this way.
+    // These empty implementations prevent us from hitting RenderObject ASSERTS.
+    // tspan.getBBox() will be wrong, and repainting for tspans may not work correctly!
+    virtual FloatRect objectBoundingBox() const { return FloatRect(); }
+    virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
 };
 }
 
diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp
index 8fef1f3..ec94a55 100644
--- a/WebCore/rendering/RenderSVGText.cpp
+++ b/WebCore/rendering/RenderSVGText.cpp
@@ -52,7 +52,7 @@
 IntRect RenderSVGText::clippedOverflowRectForRepaint(RenderBoxModelObject* /*repaintContainer*/)
 {
     // FIXME: handle non-root repaintContainer
-    FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
+    FloatRect repaintRect = absoluteTransform().mapRect(repaintRectInLocalCoordinates());
 
 #if ENABLE(SVG_FILTERS)
     // Filters can expand the bounding box
@@ -134,7 +134,7 @@
 
     TransformationMatrix htmlParentCtm = root->RenderBox::absoluteTransform();
  
-    // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
+    // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard
     // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
     for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
         ASSERT(runBox->isInlineFlowBox());
@@ -159,7 +159,7 @@
 
     TransformationMatrix htmlParentCtm = root->RenderBox::absoluteTransform();
  
-    // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
+    // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard
     // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
     for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
         ASSERT(runBox->isInlineFlowBox());
@@ -181,20 +181,28 @@
     RenderBlock::paint(pi, 0, 0);
 }
 
-FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
+FloatRect RenderSVGText::objectBoundingBox() const
 {
-    FloatRect repaintRect;
+    FloatRect boundingBox;
 
     for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
         ASSERT(runBox->isInlineFlowBox());
 
         InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
         for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine())
-            repaintRect.unite(FloatRect(box->x(), box->y(), box->width(), box->height()));
+            boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height()));
     }
 
+    boundingBox.move(x(), y());
+    return boundingBox;
+}
+
+FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
+{
+    FloatRect repaintRect = objectBoundingBox();
+
     // SVG needs to include the strokeWidth(), not the textStrokeWidth().
-    if (includeStroke && style()->svgStyle()->hasStroke()) {
+    if (style()->svgStyle()->hasStroke()) {
         float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f);
 
 #if ENABLE(SVG_FONTS)
@@ -209,8 +217,6 @@
 
         repaintRect.inflate(strokeWidth);
     }
-
-    repaintRect.move(x(), y());
     return repaintRect;
 }
 
diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h
index 2cd71fa..8434b52 100644
--- a/WebCore/rendering/RenderSVGText.h
+++ b/WebCore/rendering/RenderSVGText.h
@@ -54,7 +54,9 @@
     virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
 
     virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
-    virtual FloatRect relativeBBox(bool includeStroke = true) const;
+
+    virtual FloatRect objectBoundingBox() const;
+    virtual FloatRect repaintRectInLocalCoordinates() const;
     
 private:
     virtual RootInlineBox* createRootBox();
diff --git a/WebCore/rendering/RenderSVGViewportContainer.cpp b/WebCore/rendering/RenderSVGViewportContainer.cpp
index f02302b..f00e3d1 100644
--- a/WebCore/rendering/RenderSVGViewportContainer.cpp
+++ b/WebCore/rendering/RenderSVGViewportContainer.cpp
@@ -137,8 +137,8 @@
         SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node());
         return marker->viewBoxToViewTransform(viewport().width(), viewport().height());
     }
- 
-     return TransformationMatrix();
+
+    return TransformationMatrix();
 }
 
 TransformationMatrix RenderSVGViewportContainer::absoluteTransform() const
diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp
index dd154c7..d73e456 100644
--- a/WebCore/rendering/SVGRenderSupport.cpp
+++ b/WebCore/rendering/SVGRenderSupport.cpp
@@ -2,6 +2,7 @@
  * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
  *           (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
  *           (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.  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
@@ -174,6 +175,25 @@
         size.setHeight(viewHeight);
 }
 
+FloatRect computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent)
+{
+    FloatRect boundingBox;
+
+    RenderObject* current = container->firstChild();
+    for (; current != 0; current = current->nextSibling()) {
+        FloatRect childBBox = includeAllPaintedContent ? current->repaintRectInLocalCoordinates() : current->objectBoundingBox();
+        FloatRect childBBoxInLocalCoords = current->localTransform().mapRect(childBBox);
+
+        // <svg> elements may a viewBox transform as well
+        if (current->isSVGContainer())
+            childBBoxInLocalCoords = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(childBBoxInLocalCoords);
+
+        boundingBox.unite(childBBoxInLocalCoords);
+    }
+
+    return boundingBox;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SVG)
diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h
index 7fdfcf8..2c87223 100644
--- a/WebCore/rendering/SVGRenderSupport.h
+++ b/WebCore/rendering/SVGRenderSupport.h
@@ -1,9 +1,8 @@
 /**
- * This file is part of the DOM implementation for WebKit.
- *
  * Copyright (C) 2007 Rob Buis <buis@kde.org>
  *           (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
  *           (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.  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
@@ -37,6 +36,10 @@
 
 void clampImageBufferSizeToViewport(RenderObject*, IntSize&);
 
+// Used to share the "walk all the children" logic between objectBoundingBox
+// and repaintRectInLocalCoordinates in RenderSVGRoot and RenderSVGContainer
+FloatRect computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent);
+
 }
 
 #endif
diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp
index 30c921e..cbbea53 100644
--- a/WebCore/rendering/SVGRenderTreeAsText.cpp
+++ b/WebCore/rendering/SVGRenderTreeAsText.cpp
@@ -297,7 +297,7 @@
 
 static TextStream& operator<<(TextStream& ts, const RenderPath& path)
 {
-    ts << " " << path.absoluteTransform().mapRect(path.relativeBBox());
+    ts << " " << path.absoluteTransform().mapRect(path.repaintRectInLocalCoordinates());
 
     writeStyle(ts, path);
 
@@ -308,7 +308,7 @@
 
 static TextStream& operator<<(TextStream& ts, const RenderSVGContainer& container)
 {
-    ts << " " << container.absoluteTransform().mapRect(container.relativeBBox());
+    ts << " " << container.absoluteTransform().mapRect(container.repaintRectInLocalCoordinates());
 
     writeStyle(ts, container);
 
@@ -317,7 +317,7 @@
 
 static TextStream& operator<<(TextStream& ts, const RenderSVGRoot& root)
 {
-    ts << " " << root.absoluteTransform().mapRect(root.relativeBBox());
+    ts << " " << root.absoluteTransform().mapRect(root.repaintRectInLocalCoordinates());
 
     writeStyle(ts, root);
 
diff --git a/WebCore/svg/SVGFont.cpp b/WebCore/svg/SVGFont.cpp
index 9b36f87..7e3cec0 100644
--- a/WebCore/svg/SVGFont.cpp
+++ b/WebCore/svg/SVGFont.cpp
@@ -533,6 +533,9 @@
                     context->beginPath();
                     context->addPath(identifier.pathData);
 
+                    // FIXME: setup() tries to get objectBoundingBox() from run.referencingRenderObject()
+                    // which is wrong.  We need to change setup() to take a bounding box instead, or pass
+                    // a RenderObject which would return the bounding box for identifier.pathData
                     if (activePaintServer->setup(context, run.referencingRenderObject(), targetType)) {
                         // Spec: Any properties specified on a text elements which represents a length, such as the
                         // 'stroke-width' property, might produce surprising results since the length value will be
diff --git a/WebCore/svg/SVGLocatable.cpp b/WebCore/svg/SVGLocatable.cpp
index 459c7c0..00acc2a0 100644
--- a/WebCore/svg/SVGLocatable.cpp
+++ b/WebCore/svg/SVGLocatable.cpp
@@ -79,7 +79,7 @@
     if (!element->renderer())
         return FloatRect();
 
-    return element->renderer()->relativeBBox(false);
+    return element->renderer()->objectBoundingBox();
 }
 
 TransformationMatrix SVGLocatable::getCTM(const SVGElement* element)
diff --git a/WebCore/svg/SVGPatternElement.cpp b/WebCore/svg/SVGPatternElement.cpp
index 5d21b94..a52a1a1 100644
--- a/WebCore/svg/SVGPatternElement.cpp
+++ b/WebCore/svg/SVGPatternElement.cpp
@@ -191,7 +191,7 @@
         for (Node* n = attributes.patternContentElement()->firstChild(); n; n = n->nextSibling()) {
             if (!n->isSVGElement() || !static_cast<SVGElement*>(n)->isStyledTransformable() || !n->renderer())
                 continue;
-            patternContentBoundaries.unite(n->renderer()->relativeBBox(true));
+            patternContentBoundaries.unite(n->renderer()->repaintRectInLocalCoordinates());
         }
     }
 
diff --git a/WebCore/svg/graphics/SVGPaintServerGradient.cpp b/WebCore/svg/graphics/SVGPaintServerGradient.cpp
index eb0d80b..812e050 100644
--- a/WebCore/svg/graphics/SVGPaintServerGradient.cpp
+++ b/WebCore/svg/graphics/SVGPaintServerGradient.cpp
@@ -130,7 +130,7 @@
     GraphicsContext*& context, GraphicsContext*& savedContext,
     OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object)
 {
-    FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false);
+    FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->objectBoundingBox();
     IntRect maskRect = enclosingIntRect(object->absoluteTransform().mapRect(maskBBox));
 
     IntSize maskSize(maskRect.width(), maskRect.height());
@@ -159,7 +159,7 @@
     OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object,
     const SVGPaintServerGradient* gradientServer)
 {
-    FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false);
+    FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->objectBoundingBox();
 
     // Fixup transformations to be able to clip to mask
     TransformationMatrix transform = object->absoluteTransform();
@@ -227,7 +227,7 @@
 #else
     if (boundingBoxMode()) {
 #endif
-        FloatRect bbox = object->relativeBBox(false);
+        FloatRect bbox = object->objectBoundingBox();
         // Don't use gradients for 1d objects like horizontal/vertical 
         // lines or rectangles without width or height.
         if (bbox.width() == 0 || bbox.height() == 0) {
@@ -258,7 +258,7 @@
         m_gradient->setGradientSpaceTransform(matrix);
         context->setFillGradient(m_gradient);
 
-        FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false);
+        FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->objectBoundingBox();
 
         context->fillRect(maskBBox);
 
diff --git a/WebCore/svg/graphics/SVGPaintServerPattern.cpp b/WebCore/svg/graphics/SVGPaintServerPattern.cpp
index a2ac5df..046f386 100644
--- a/WebCore/svg/graphics/SVGPaintServerPattern.cpp
+++ b/WebCore/svg/graphics/SVGPaintServerPattern.cpp
@@ -102,7 +102,7 @@
         IntRect textBoundary = const_cast<RenderObject*>(object)->absoluteBoundingBoxRect();
         targetRect = object->absoluteTransform().inverse().mapRect(textBoundary);
     } else
-        targetRect = object->relativeBBox(false);
+        targetRect = object->objectBoundingBox();
 
     const SVGRenderStyle* style = object->style()->svgStyle();
     bool isFilled = (type & ApplyToFillTargetType) && style->hasFill();