2006-09-19 Eric Seidel <eric@eseidel.com>
authoreseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Sep 2006 05:26:46 +0000 (05:26 +0000)
committereseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Sep 2006 05:26:46 +0000 (05:26 +0000)
        Reviewed by adele.

        Markers should clip to their viewport.
        http://bugzilla.opendarwin.org/show_bug.cgi?id=5967

        Test: svg/custom/marker-overflow-clip.svg

        * kcanvas/KCanvasResources.cpp:
        (WebCore::KCanvasMarker::KCanvasMarker):
        (WebCore::KCanvasMarker::setMarker):
        (WebCore::KCanvasMarker::draw):
        * kcanvas/KCanvasResources.h:
        (WebCore::KCanvasMasker::mask):
        * ksvg2/svg/SVGMarkerElement.cpp:
        (WebCore::SVGMarkerElement::SVGMarkerElement):
        (WebCore::SVGMarkerElement::parseMappedAttribute):
        (WebCore::SVGMarkerElement::canvasResource):
        (WebCore::SVGMarkerElement::createRenderer):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@16461 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/svg/custom/marker-overflow-clip-expected.checksum [new file with mode: 0644]
LayoutTests/svg/custom/marker-overflow-clip-expected.png [new file with mode: 0644]
LayoutTests/svg/custom/marker-overflow-clip-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/marker-overflow-clip.svg [new file with mode: 0644]
WebCore/ChangeLog
WebCore/kcanvas/KCanvasResources.cpp
WebCore/kcanvas/KCanvasResources.h
WebCore/kcanvas/RenderSVGContainer.h
WebCore/ksvg2/svg/SVGMarkerElement.cpp

index 3bb0e09dc28fa05889bb9b59635e0b8cb9f8e60b..d25c6442b2636a76b98f921544c62a7b0f0e0d71 100644 (file)
@@ -1,3 +1,15 @@
+2006-09-19  Eric Seidel  <eric@eseidel.com>
+
+        Reviewed by adele.
+
+        Markers should clip to their viewport.
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=5967
+
+        * svg/custom/marker-overflow-clip-expected.checksum: Added.
+        * svg/custom/marker-overflow-clip-expected.png: Added.
+        * svg/custom/marker-overflow-clip-expected.txt: Added.
+        * svg/custom/marker-overflow-clip.svg: Added.
+
 2006-09-19  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by eseidel
diff --git a/LayoutTests/svg/custom/marker-overflow-clip-expected.checksum b/LayoutTests/svg/custom/marker-overflow-clip-expected.checksum
new file mode 100644 (file)
index 0000000..5f0f769
--- /dev/null
@@ -0,0 +1 @@
+6b65f0a81531c26c0619d72984424eae
\ No newline at end of file
diff --git a/LayoutTests/svg/custom/marker-overflow-clip-expected.png b/LayoutTests/svg/custom/marker-overflow-clip-expected.png
new file mode 100644 (file)
index 0000000..c942822
Binary files /dev/null and b/LayoutTests/svg/custom/marker-overflow-clip-expected.png differ
diff --git a/LayoutTests/svg/custom/marker-overflow-clip-expected.txt b/LayoutTests/svg/custom/marker-overflow-clip-expected.txt
new file mode 100644 (file)
index 0000000..4d2ec29
--- /dev/null
@@ -0,0 +1,12 @@
+KCanvasResource {id="marker" [type=MARKER] [angle=auto] [ref x=50.00 y=50.00]}
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+    KCanvasContainer {svg} at (-50,-50) size 200x200
+      KCanvasContainer {marker} at (-25,-25) size 100x100
+        KCanvasItem {rect} at (-25,-25) size 100x100 [fill={[type=SOLID] [color=#FF0000]}] [data="M-50.00,-50.00L150.00,-50.00L150.00,150.00L-50.00,150.00"]
+        KCanvasItem {rect} at (0,0) size 50x50 [fill={[type=SOLID] [color=#008000]}] [data="M0.00,0.00L100.00,0.00L100.00,100.00L0.00,100.00"]
+      KCanvasItem {rect} at (0,0) size 25x25 [fill={[type=SOLID] [color=#000000]}] [data="M0.00,0.00L25.00,0.00L25.00,25.00L0.00,25.00"]
+      KCanvasItem {path} at (100,100) size 0x0 [start marker=#marker] [data="M100.00,100.00L100.00,100.00"]
+      RenderSVGText {text} at (0,0) size 800x18
+        RenderText {#text} at (0,0) size 298x18
+          text run at (0,0) width 298: "There should be a 150x150 green rect at 25x25"
diff --git a/LayoutTests/svg/custom/marker-overflow-clip.svg b/LayoutTests/svg/custom/marker-overflow-clip.svg
new file mode 100644 (file)
index 0000000..c12ae90
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg">
+    <marker id="marker" viewBox="0 0 100 100" refX="50" refY="50" markerUnits="strokeWidth" markerWidth="50" markerHeight="50" orient="auto">
+        <rect fill="red" x="-50" y="-50" width="200" height="200" />
+        <rect x="0" y="0" width="100" height="100" fill="green"/>
+    </marker>
+    <rect width="25" height="25" />
+    <path d="M 100 100 L 100 100 " fill="none" stroke="none" stroke-width="3" marker-start="url(#marker)"/>
+    <text x="30" y="20"> There should be a 150x150 green rect at 25x25</text>
+</svg>
index d6e48409e8fdeda2dde7a7d43e05d7d33a797cdd..d700724b040ba785390ea8d5d23819952eee2241 100644 (file)
@@ -1,3 +1,24 @@
+2006-09-19  Eric Seidel  <eric@eseidel.com>
+
+        Reviewed by adele.
+        
+        Markers should clip to their viewport.
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=5967
+
+        Test: svg/custom/marker-overflow-clip.svg
+
+        * kcanvas/KCanvasResources.cpp:
+        (WebCore::KCanvasMarker::KCanvasMarker):
+        (WebCore::KCanvasMarker::setMarker):
+        (WebCore::KCanvasMarker::draw):
+        * kcanvas/KCanvasResources.h:
+        (WebCore::KCanvasMasker::mask):
+        * ksvg2/svg/SVGMarkerElement.cpp:
+        (WebCore::SVGMarkerElement::SVGMarkerElement):
+        (WebCore::SVGMarkerElement::parseMappedAttribute):
+        (WebCore::SVGMarkerElement::canvasResource):
+        (WebCore::SVGMarkerElement::createRenderer):
+
 2006-09-19  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by eseidel
index 2da36f80c942785e9c68c7d84bcf16162a14abf5..91d9adea1e73f031b6741462f7f5731dc6ee7c98 100644 (file)
@@ -167,20 +167,21 @@ TextStream& KCanvasMasker::externalRepresentation(TextStream &ts) const
 }
 
 // KCanvasMarker
-KCanvasMarker::KCanvasMarker(RenderObject *marker) : KCanvasResource()
+KCanvasMarker::KCanvasMarker(RenderSVGContainer* marker)
+    : KCanvasResource()
+    , m_refX(0)
+    , m_refY(0)
+    , m_marker(marker)
+    , m_useStrokeWidth(true)
 {
-    m_refX = 0;
-    m_refY = 0;
-    m_marker = marker;
     setAutoAngle();
-    m_useStrokeWidth = true;
 }
 
 KCanvasMarker::~KCanvasMarker()
 {
 }
 
-void KCanvasMarker::setMarker(RenderObject *marker)
+void KCanvasMarker::setMarker(RenderSVGContainer* marker)
 {
     m_marker = marker;
 }
@@ -226,46 +227,39 @@ bool KCanvasMarker::useStrokeWidth() const
     return m_useStrokeWidth;
 }
 
-void KCanvasMarker::setScale(float scaleX, float scaleY)
-{
-    m_scaleX = scaleX;
-    m_scaleY = scaleY;
-}
-
-float KCanvasMarker::scaleX() const
-{
-    return m_scaleX;
-}
-
-float KCanvasMarker::scaleY() const
-{
-    return m_scaleY;
-}
-
 void KCanvasMarker::draw(GraphicsContext* context, const FloatRect& rect, double x, double y, double strokeWidth, double angle)
 {
-    if(m_marker)
-    {
-        AffineTransform translation;
-        translation.translate(x, y);
-
-        AffineTransform rotation;
-        // stroke width
-        if(m_useStrokeWidth)
-            rotation.scale(strokeWidth, strokeWidth);
-        rotation.rotate(m_angle > -1 ? m_angle : angle);
-        rotation.scale(m_scaleX, m_scaleY);
-        rotation.translate(-m_refX, -m_refY);
-
-        // FIXME: PaintInfo should be passed into this method instead.
-        // FIXME: bounding box fractions lost
-        RenderObject::PaintInfo info(context, enclosingIntRect(rect), PaintPhaseForeground, 0, 0, 0);
-        rotation = rotation * translation;
-        m_marker->setLocalTransform(rotation);
-        static_cast<RenderSVGContainer *>(m_marker)->setDrawsContents(true);
-        m_marker->paint(info, 0, 0);
-        static_cast<RenderSVGContainer *>(m_marker)->setDrawsContents(false);
-    }
+    if (!m_marker)
+        return;
+    
+    AffineTransform transform;
+    transform.translate(x, y);
+    transform.rotate(m_angle > -1 ? m_angle : angle);
+    
+    // refX and refY are given in coordinates relative to the viewport established by the marker, yet they affect
+    // the translation performed on the viewport itself.
+    AffineTransform viewportTransform;
+    if (m_useStrokeWidth)
+        viewportTransform.scale(strokeWidth, strokeWidth);
+    if (!m_marker->viewBox().isEmpty())
+        viewportTransform *= m_marker->viewportTransform();
+    double refX, refY;
+    viewportTransform.map(m_refX, m_refY, &refX, &refY);
+    transform.translate(-refX, -refY);
+    
+    if (m_useStrokeWidth)
+        transform.scale(strokeWidth, strokeWidth);
+    
+    // FIXME: PaintInfo should be passed into this method instead of being created here
+    // FIXME: bounding box fractions are lost
+    RenderObject::PaintInfo info(context, enclosingIntRect(rect), PaintPhaseForeground, 0, 0, 0);
+    
+    context->save();
+    context->concatCTM(transform);
+    m_marker->setDrawsContents(true);
+    m_marker->paint(info, 0, 0);
+    m_marker->setDrawsContents(false);
+    context->restore();
 }
 
 TextStream& KCanvasMarker::externalRepresentation(TextStream &ts) const
index 633de2774369d34027a187af061ce87f2bb3e2a6..373eb44490b8a8f45b2b258181c6fae962c3c40b 100644 (file)
@@ -27,7 +27,7 @@
 #include "DeprecatedValueList.h"
 #include "Path.h"
 #include "RenderPath.h"
-#include <kcanvas/KCanvasResourceListener.h>
+#include "KCanvasResourceListener.h"
 
 namespace WebCore {
 
@@ -55,7 +55,7 @@ public:
     virtual ~KCanvasResource();
 
     virtual void invalidate();
-    void addClient(const RenderPath *item);
+    void addClient(const RenderPath*);
 
     const RenderPathList &clients() const;
     
@@ -107,7 +107,7 @@ public:
     virtual bool isClipper() const { return true; }
 
     void resetClipData();
-    void addClipData(const Path& path, WindRule rule, bool bboxUnits);
+    void addClipData(const Path&, WindRule, bool bboxUnits);
     
     virtual void applyClip(const FloatRect& boundingBox) const = 0;
 
@@ -127,8 +127,8 @@ public:
     virtual ~KCanvasMasker();
     
     virtual bool isMasker() const { return true; }
-    void setMask(KCanvasImage *mask);
-    KCanvasImage *mask() const { return m_mask; }
+    void setMask(KCanvasImage*);
+    KCanvasImagemask() const { return m_mask; }
     
     virtual void applyMask(const FloatRect& boundingBox) const = 0;
 
@@ -140,12 +140,12 @@ protected:
 class KCanvasMarker : public KCanvasResource
 {
 public:
-    KCanvasMarker(RenderObject *marker = 0);
+    KCanvasMarker(RenderSVGContainer* = 0);
     virtual ~KCanvasMarker();
     
     virtual bool isMarker() const { return true; }
 
-    void setMarker(RenderObject *marker);
+    void setMarker(RenderSVGContainer*);
     
     void setRef(double refX, double refY);
     double refX() const;    
@@ -158,18 +158,14 @@ public:
     void setUseStrokeWidth(bool useStrokeWidth = true);
     bool useStrokeWidth() const;
 
-    void setScale(float scaleX, float scaleY);
-    float scaleX() const;
-    float scaleY() const;
-
     void draw(GraphicsContext*, const FloatRect&, double x, double y, double strokeWidth = 1, double angle = 0);
 
     TextStream& externalRepresentation(TextStream &) const; 
 
 private:
     double m_refX, m_refY;
-    float m_angle, m_scaleX, m_scaleY;
-    RenderObject *m_marker;
+    float m_angle;
+    RenderSVGContainer* m_marker;
     bool m_useStrokeWidth;
 };
 
index 3b9e355117ebe355422b4d7a0ad891bff5ab58f8..a0af4a4da2ef7f07a675dcf3489dc4c3b079e216 100644 (file)
@@ -94,9 +94,10 @@ public:
     void setSlice(bool);
     bool slice() const;
     
+    AffineTransform viewportTransform() const;
+    
 private:
     AffineTransform getAspectRatio(const FloatRect& logical, const FloatRect& physical) const;
-    AffineTransform viewportTransform() const;
 
     bool m_drawsContents : 1;
     bool m_slice : 1;
index 0d272287b7f2265f9bc26dc1a520f8beff30d110..9214a094d4a79741445670e32cd948e346bd588e 100644 (file)
 #include "SVGMarkerElement.h"
 
 #include "Attr.h"
+#include "KRenderingDevice.h"
 #include "PlatformString.h"
+#include "RenderSVGContainer.h"
 #include "SVGAngle.h"
-#include "SVGAngle.h"
-#include "SVGLength.h"
 #include "SVGFitToViewBox.h"
 #include "SVGHelper.h"
+#include "SVGLength.h"
 #include "SVGMatrix.h"
 #include "SVGNames.h"
+#include "SVGPreserveAspectRatio.h"
 #include "SVGSVGElement.h"
 #include "ksvg.h"
-#include <kcanvas/RenderSVGContainer.h>
-#include <kcanvas/device/KRenderingDevice.h>
 
 namespace WebCore {
 
@@ -52,8 +52,8 @@ SVGMarkerElement::SVGMarkerElement(const QualifiedName& tagName, Document *doc)
     , m_markerUnits(SVG_MARKERUNITS_STROKEWIDTH)
     , m_orientType(0)
     , m_orientAngle(new SVGAngle(this))
+    , m_marker(0)
 {
-    m_marker = 0;
 }
 
 SVGMarkerElement::~SVGMarkerElement()
@@ -67,8 +67,7 @@ void SVGMarkerElement::parseMappedAttribute(MappedAttribute *attr)
     if (attr->name() == SVGNames::markerUnitsAttr) {
         if (value == "userSpaceOnUse")
             setMarkerUnitsBaseValue(SVG_MARKERUNITS_USERSPACEONUSE);
-    }
-    else if (attr->name() == SVGNames::refXAttr)
+    } else if (attr->name() == SVGNames::refXAttr)
         refXBaseValue()->setValueAsString(value);
     else if (attr->name() == SVGNames::refYAttr)
         refYBaseValue()->setValueAsString(value);
@@ -76,21 +75,21 @@ void SVGMarkerElement::parseMappedAttribute(MappedAttribute *attr)
         markerWidthBaseValue()->setValueAsString(value);
     else if (attr->name() == SVGNames::markerHeightAttr)
         markerHeightBaseValue()->setValueAsString(value);
-    else if (attr->name() == SVGNames::orientAttr)
-    {
+    else if (attr->name() == SVGNames::orientAttr) {
         if (value == "auto")
             setOrientToAuto();
         else {
-            SVGAngle *angle = SVGSVGElement::createSVGAngle();
+            SVGAngle* angle = new SVGAngle(0);
             angle->setValueAsString(value);
             setOrientToAngle(angle);
         }
-    }
-    else
-    {
-        if(SVGLangSpace::parseMappedAttribute(attr)) return;
-        if(SVGExternalResourcesRequired::parseMappedAttribute(attr)) return;
-        if(SVGFitToViewBox::parseMappedAttribute(attr)) return;
+    } else {
+        if (SVGLangSpace::parseMappedAttribute(attr))
+            return;
+        if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
+            return;
+        if (SVGFitToViewBox::parseMappedAttribute(attr))
+            return;
 
         SVGStyledElement::parseMappedAttribute(attr);
     }
@@ -118,34 +117,33 @@ void SVGMarkerElement::setOrientToAngle(SVGAngle *angle)
 KCanvasMarker *SVGMarkerElement::canvasResource()
 {
     if(!m_marker)
-        m_marker = static_cast<KCanvasMarker *>(renderingDevice()->createResource(RS_MARKER));
+        m_marker = static_cast<KCanvasMarker*>(renderingDevice()->createResource(RS_MARKER));
     
-    m_marker->setMarker(renderer());
+    m_marker->setMarker(static_cast<RenderSVGContainer*>(renderer()));
 
     // Spec: If the attribute is not specified, the effect is as if a
     // value of "0" were specified.
-    if(!m_orientType)
+    if (!m_orientType)
         setOrientToAngle(SVGSVGElement::createSVGAngle());
     
-    if(orientType() == SVG_MARKER_ORIENT_ANGLE)
+    if (orientType() == SVG_MARKER_ORIENT_ANGLE)
         m_marker->setAngle(orientAngle()->value());
     else
         m_marker->setAutoAngle();
 
     m_marker->setRef(refX()->value(), refY()->value());
-    
     m_marker->setUseStrokeWidth(markerUnits() == SVG_MARKERUNITS_STROKEWIDTH);
-    double w = markerWidth()->value();
-    double h = markerHeight()->value();
-    RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(w, h);
-    m_marker->setScale(viewBox->matrix().m11(), viewBox->matrix().m22());
     
     return m_marker;
 }
 
 RenderObject* SVGMarkerElement::createRenderer(RenderArena* arena, RenderStyle* style)
 {
-    RenderSVGContainer *markerContainer = new (arena) RenderSVGContainer(this);
+    RenderSVGContainer* markerContainer = new (arena) RenderSVGContainer(this);
+    markerContainer->setViewport(FloatRect(0, 0, markerWidth()->value(), markerHeight()->value()));
+    markerContainer->setViewBox(viewBox());
+    markerContainer->setAlign(KCAlign(preserveAspectRatio()->align() - 1));
+    markerContainer->setSlice(preserveAspectRatio()->meetOrSlice() == SVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE);
     markerContainer->setDrawsContents(false); // Marker contents will be explicitly drawn.
     return markerContainer;
 }