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;
}