2010-02-08  Nikolas Zimmermann  <nzimmermann@rim.com>

        Reviewed by Dirk Schulze.

        All SVG *-expected.txt files contain wrong results
        https://bugs.webkit.org/show_bug.cgi?id=34703

        Finally dump meaningful information for SVG layout tests.
        Use 'absoluteClippedOverflowRect' which goes through the same code paths used
        to actually calculate repaint rects etc - instead of the legacy CSS-unaware
        code path that mapped 'repaintRectInLocalCoordinates' through 'absoluteTransform'.
        Remove absoluteTransform() - a long standing TODO, finally not needed anymore.

        Despite SVGRenderTreeAsText, SVGPaintServerGradient was also using absoluteTransform().
        Rewrite the code in question, fixing svg/W3C-SVG-1.1/pserver-grad-08-b.svg alignment issues
        when scaling/panning text using gradient on stroke/fill. Affects some other gradient tests as well.

        As we're now dumping clipped overflow rects any problems with repaint rects will become
        immediate visible - it turns out we're not supporting the overflow rules on the outermost <svg>
        element properly (repaint rects and bounding boxes need to take special SVG overflow rules into account).
        Fixing that magically gives pixel-perfect clipped overflow rects for all types of shapes/text/containers.

        Note: This will break any overriden platform-specific SVG results, need to wait for build bots in order to update them.

        * rendering/RenderObject.cpp: Remove absoluteTransform() method, centralize overflow query code in SVGRenderSupport::isOverflowHidden().
        * rendering/RenderObject.h: Remove absoluteTransform() method.
        * rendering/RenderSVGHiddenContainer.h: Ditto.
        * rendering/RenderSVGRoot.cpp:
        (WebCore::RenderSVGRoot::paint): Use SVGRenderSupport::isOverflowHidden() to query SVG overflow mode.
        (WebCore::RenderSVGRoot::computeRectForRepaint): Respect SVG overflow rules here: clip repaintRect against overflow rect _before_ passing
                                                         along to RenderBox. This is the key issue behind wrong absoluteClippedOverflowRect() values.
        (WebCore::RenderSVGRoot::nodeAtPoint): Use SVGRenderSupport::isOverflowHidden() to query SVG overflow mode.
        * rendering/RenderSVGRoot.h: Remove absoluteTransform(). Don't expose viewportSize() anymore.
        * rendering/RenderSVGText.cpp: 
        (WebCore::RenderSVGText::strokeBoundingBox): Fix default stroke width to 1. This was the only wrong place -> fixes repaint rects for stroked text.
        * rendering/RenderSVGViewportContainer.cpp: Remove absoluteTransform() method.
        (WebCore::RenderSVGViewportContainer::pointIsInsideViewportClip): Use SVGRenderSupport::isOverflowHidden() to query SVG overflow mode.
        * rendering/RenderSVGViewportContainer.h: Remove absoluteTransform() method.
        * rendering/SVGRenderSupport.cpp: Refactored overflow queries in one place, centralizing SVG specific assumptions about overflowX/Y.
        (WebCore::SVGRenderBase::isOverflowHidden):
        * rendering/SVGRenderSupport.h:
        * rendering/SVGRenderTreeAsText.cpp: Dump absoluteClippedOverflowRect() instead of absoluteTransform().mapRect(repaintRectInLocalCoordinates()).
        (WebCore::writePositionAndStyle): Affects all layout tests dumping render trees.
        * svg/graphics/SVGPaintServerGradient.cpp: Rewrite Gradient on text fill/stroke support on Cg, to avoid using absoluteTransform().
        (WebCore::absoluteTransformForRenderer):
        (WebCore::createMaskAndSwapContextForTextGradient):
        (WebCore::clipToTextMask):
        (WebCore::SVGPaintServerGradient::setup):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54483 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
index b6a0814..62d5a20 100644
--- a/WebCore/rendering/RenderObject.cpp
+++ b/WebCore/rendering/RenderObject.cpp
@@ -2532,15 +2532,6 @@
     return identity;
 }
 
-TransformationMatrix RenderObject::absoluteTransform() const
-{
-    // FIXME: This should use localToParentTransform(), but much of the SVG code
-    // depends on RenderBox::absoluteTransform() being the sum of the localTransform()s of all parent renderers.
-    if (parent())
-        return localTransform() * parent()->absoluteTransform();
-    return localTransform();
-}
-
 bool RenderObject::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction)
 {
     ASSERT_NOT_REACHED();
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
index 03ba1e6..e38c0c5 100644
--- a/WebCore/rendering/RenderObject.h
+++ b/WebCore/rendering/RenderObject.h
@@ -353,11 +353,6 @@
     // This includes any viewport transforms and x/y offsets as well as the transform="" value off the element.
     virtual const TransformationMatrix& localToParentTransform() const;
 
-    // Walks up the parent chain to create a transform which maps from local to document coords
-    // NOTE: This method is deprecated!  It doesn't respect scroll offsets or repaint containers.
-    // FIXME: This is only virtual so that RenderSVGHiddenContainer can override it to match old LayoutTest results.
-    virtual TransformationMatrix absoluteTransform() const;
-
     // SVG uses FloatPoint precise hit testing, and passes the point in parent
     // coordinates instead of in repaint container coordinates.  Eventually the
     // rest of the rendering tree will move to a similar model.
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.h b/WebCore/rendering/RenderSVGHiddenContainer.h
index 0ef0a43..fdbd2bc 100644
--- a/WebCore/rendering/RenderSVGHiddenContainer.h
+++ b/WebCore/rendering/RenderSVGHiddenContainer.h
@@ -51,9 +51,6 @@
         virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
         virtual void absoluteQuads(Vector<FloatQuad>&);
 
-        // FIXME: This override only exists to match existing LayoutTest results.
-        virtual TransformationMatrix absoluteTransform() const { return TransformationMatrix(); }
-
         virtual FloatRect objectBoundingBox() const;
         virtual FloatRect repaintRectInLocalCoordinates() const;
 
diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp
index 4a3bbcc..7997494 100644
--- a/WebCore/rendering/RenderSVGRoot.cpp
+++ b/WebCore/rendering/RenderSVGRoot.cpp
@@ -129,7 +129,7 @@
         paintBoxDecorations(paintInfo, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y());
 
     // An empty viewport disables rendering.  FIXME: Should we still render filters?
-    if (viewportSize().isEmpty())
+    if (m_viewportSize.isEmpty())
         return;
 
     // Don't paint if we don't have kids, except if we have filters we should paint those.
@@ -140,8 +140,9 @@
     RenderObject::PaintInfo childPaintInfo(paintInfo);
     childPaintInfo.context->save();
 
-    // SVG does not support independent x/y clipping
-    if (style()->overflowX() != OVISIBLE)
+    // In SVG special rules need to be applied that differ from the CSS overflow handling,
+    // see comments in svg.css for spec references, explaining this behaviour
+    if (SVGRenderBase::isOverflowHidden(this))
         childPaintInfo.context->clip(overflowClipRect(borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y()));
 
     // Convert from container offsets (html renderers) to a relative transform (svg renderers).
@@ -167,11 +168,6 @@
         paintOutline(paintInfo.context, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y(), width(), height(), style());
 }
 
-const FloatSize& RenderSVGRoot::viewportSize() const
-{
-    return m_viewportSize;
-}
-
 void RenderSVGRoot::calcViewport()
 {
     SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
@@ -235,13 +231,6 @@
     return m_localToParentTransform;
 }
 
-// FIXME: This method should be removed as soon as callers to RenderBox::absoluteTransform() can be removed.
-TransformationMatrix RenderSVGRoot::absoluteTransform() const
-{
-    // This would apply localTransform() twice if localTransform() were not the identity.
-    return localToParentTransform() * RenderBox::absoluteTransform();
-}
-
 FloatRect RenderSVGRoot::objectBoundingBox() const
 {
     return computeContainerBoundingBox(this, false);
@@ -265,6 +254,12 @@
     // Apply our local transforms (except for x/y translation), then our shadow, 
     // and then call RenderBox's method to handle all the normal CSS Box model bits
     repaintRect = localToBorderBoxTransform().mapRect(repaintRect);
+
+    // In SVG special rules need to be applied that differ from the CSS overflow handling,
+    // see comments in svg.css for spec references, explaining this behaviour
+    if (SVGRenderBase::isOverflowHidden(this))
+        repaintRect.intersect(enclosingIntRect(FloatRect(FloatPoint(), m_viewportSize)));
+
     style()->svgStyle()->inflateForShadow(repaintRect);
     RenderBox::computeRectForRepaint(repaintContainer, repaintRect, fixed);
 }
@@ -288,10 +283,7 @@
     IntPoint pointInBorderBox = pointInParent - parentOriginToBorderBox();
 
     // Note: For now, we're ignoring hits to border and padding for <svg>
-
-    if (style()->overflowX() == OHIDDEN) {
-        // SVG doesn't support independent x/y overflow
-        ASSERT(style()->overflowY() == OHIDDEN);
+    if (SVGRenderBase::isOverflowHidden(this)) {
         IntPoint pointInContentBox = pointInBorderBox - borderOriginToContentBox();
         if (!contentBoxRect().contains(pointInContentBox))
             return false;
diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h
index b2f8f7c..7f42738 100644
--- a/WebCore/rendering/RenderSVGRoot.h
+++ b/WebCore/rendering/RenderSVGRoot.h
@@ -63,9 +63,8 @@
     virtual FloatRect strokeBoundingBox() const { return computeContainerBoundingBox(this, true); }
     virtual FloatRect repaintRectInLocalCoordinates() const;
 
-    // FIXME: Both of these overrides should be removed.
+    // FIXME: This override should be removed.
     virtual TransformationMatrix localTransform() const;
-    virtual TransformationMatrix absoluteTransform() const;
 
     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
 
@@ -74,7 +73,6 @@
     virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
 
     void calcViewport();
-    const FloatSize& viewportSize() const;
 
     bool selfWillPaint() const;
 
diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp
index 0cf0332..c2b6649 100644
--- a/WebCore/rendering/RenderSVGText.cpp
+++ b/WebCore/rendering/RenderSVGText.cpp
@@ -192,7 +192,7 @@
 
     // SVG needs to include the strokeWidth(), not the textStrokeWidth().
     if (style()->svgStyle()->hasStroke()) {
-        float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f);
+        float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 1.0f);
 
 #if ENABLE(SVG_FONTS)
         const Font& font = style()->font();
diff --git a/WebCore/rendering/RenderSVGViewportContainer.cpp b/WebCore/rendering/RenderSVGViewportContainer.cpp
index b46e8c2..277a0ad 100644
--- a/WebCore/rendering/RenderSVGViewportContainer.cpp
+++ b/WebCore/rendering/RenderSVGViewportContainer.cpp
@@ -115,22 +115,13 @@
     // return viewportTransform() * localTransform() * viewportTranslation;
 }
 
-// FIXME: This method should be removed as soon as callers to RenderBox::absoluteTransform() can be removed.
-TransformationMatrix RenderSVGViewportContainer::absoluteTransform() const
-{
-    // This would apply localTransform() twice if localTransform() were not the identity.
-    return localToParentTransform() * RenderSVGContainer::absoluteTransform();
-}
-
 bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& pointInParent)
 {
-    // Respect the viewport clip (which is in parent coords).  SVG does not support separate x/y overflow rules.
-    if (style()->overflowX() == OHIDDEN) {
-        ASSERT(style()->overflowY() == OHIDDEN);
-        if (!m_viewport.contains(pointInParent))
-            return false;
-    }
-    return true;
+    // Respect the viewport clip (which is in parent coords)
+    if (!SVGRenderBase::isOverflowHidden(this))
+        return true;
+    
+    return m_viewport.contains(pointInParent);
 }
 
 }
diff --git a/WebCore/rendering/RenderSVGViewportContainer.h b/WebCore/rendering/RenderSVGViewportContainer.h
index ee08b60..7b9e375 100644
--- a/WebCore/rendering/RenderSVGViewportContainer.h
+++ b/WebCore/rendering/RenderSVGViewportContainer.h
@@ -48,9 +48,6 @@
     TransformationMatrix viewportTransform() const;
     virtual const TransformationMatrix& localToParentTransform() const;
 
-    // FIXME: This override should be removed once callers of RenderBox::absoluteTransform() can be removed.
-    virtual TransformationMatrix absoluteTransform() const;
-
     virtual void calcViewport();
 
     virtual void applyViewportClip(PaintInfo&);
diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp
index 86cbf32..2c80735 100644
--- a/WebCore/rendering/SVGRenderSupport.cpp
+++ b/WebCore/rendering/SVGRenderSupport.cpp
@@ -258,6 +258,17 @@
     }
 }
 
+bool SVGRenderBase::isOverflowHidden(const RenderObject* object)
+{
+    if (object->style()->overflowX() == OHIDDEN) {
+        // SVG doesn't support independent x/y overflow
+        ASSERT(object->style()->overflowY() == OHIDDEN);
+        return true;
+    }
+
+    return false;
+}
+
 FloatRect SVGRenderBase::filterBoundingBoxForRenderer(const RenderObject* object) const
 {
 #if ENABLE(FILTERS)
diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h
index 0804ede..0e01705 100644
--- a/WebCore/rendering/SVGRenderSupport.h
+++ b/WebCore/rendering/SVGRenderSupport.h
@@ -51,6 +51,9 @@
         // Layout all children of the passed render object
         static void layoutChildren(RenderObject*, bool selfNeedsLayout);
 
+        // Helper function determining wheter overflow is hidden
+        static bool isOverflowHidden(const RenderObject*);
+
         virtual FloatRect strokeBoundingBox() const { return FloatRect(); }
         virtual FloatRect markerBoundingBox() const { return FloatRect(); }
 
diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp
index bd6a465..913cad7 100644
--- a/WebCore/rendering/SVGRenderTreeAsText.cpp
+++ b/WebCore/rendering/SVGRenderTreeAsText.cpp
@@ -310,7 +310,7 @@
 
 static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& object)
 {
-    ts << " " << object.absoluteTransform().mapRect(object.repaintRectInLocalCoordinates());
+    ts << " " << const_cast<RenderObject&>(object).absoluteClippedOverflowRect();
     writeStyle(ts, object);
     return ts;
 }