[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

zimmermann at webkit.org zimmermann at webkit.org
Wed Dec 22 11:38:03 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 7667c8e8b003bead34ea542a9cb8acc740c314b0
Author: zimmermann at webkit.org <zimmermann at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sun Aug 1 09:49:04 2010 +0000

    2010-08-01  Nikolas Zimmermann  <nzimmermann at rim.com>
    
            Reviewed by Dirk Schulze.
    
            SVG gradients do not update when scripted via xlink
            https://bugs.webkit.org/show_bug.cgi?id=42953
    
            Unify cycle detection logic for chainable (through xlink:href) and ordinary resources.
            All operate on the render tree now, instead of falling back to the DOM tree for xlink:href queries.
    
            When linking resources, register as regular client, so the regular update mechanisms work as expected.
            <linearGradient id="foo"><stop../> </linearGradient>
            <linearGradient id="bar" xlink:href="#foo"/>
            <rect fill="url(#bar)"/>
    
            Without that the rect won't receive invalidation notifications, as foo <-> bar had no connection.
            Fixes the last outstanding class of invalidations. Also speeds up the cycle detetion, when using chained resources,
            as no SVG DOM queries have to be executed anymore.
    
            Test: svg/custom/js-update-stop-linked-gradient.svg
    
            * rendering/RenderSVGResourceContainer.cpp:
            (WebCore::RenderSVGResourceContainer::markAllClientsForInvalidation):
            (WebCore::linkedResourceForContainer):
            * rendering/SVGResources.cpp:
            (WebCore::SVGResources::SVGResources):
            (WebCore::chainableResourceTags):
            (WebCore::targetReferenceFromResource):
            (WebCore::registerPendingResource):
            (WebCore::SVGResources::buildCachedResources):
            (WebCore::SVGResources::invalidateClient):
            (WebCore::SVGResources::resourceDestroyed):
            (WebCore::SVGResources::buildSetOfResources):
            (WebCore::SVGResources::setLinkedResource):
            (WebCore::SVGResources::resetLinkedResource):
            (WebCore::SVGResources::dump):
            * rendering/SVGResources.h:
            (WebCore::SVGResources::linkedResource):
            * rendering/SVGResourcesCycleSolver.cpp:
            (WebCore::SVGResourcesCycleSolver::resolveCycles):
            (WebCore::SVGResourcesCycleSolver::breakCycle):
            * rendering/SVGResourcesCycleSolver.h:
            * svg/SVGFilterElement.cpp:
            (WebCore::SVGFilterElement::SVGFilterElement):
            * svg/SVGFilterElement.h:
            * svg/SVGGradientElement.cpp:
            (WebCore::SVGGradientElement::SVGGradientElement):
            * svg/SVGGradientElement.h:
            * svg/SVGLinearGradientElement.cpp:
            (WebCore::SVGLinearGradientElement::collectGradientProperties):
            * svg/SVGPatternElement.cpp:
            (WebCore::SVGPatternElement::SVGPatternElement):
            (WebCore::SVGPatternElement::collectPatternProperties):
            * svg/SVGPatternElement.h:
            * svg/SVGRadialGradientElement.cpp:
            (WebCore::SVGRadialGradientElement::collectGradientProperties):
    
    2010-08-01  Nikolas Zimmermann  <nzimmermann at rim.com>
    
            Reviewed by Dirk Schulze.
    
            SVG gradients do not update when scripted via xlink
            https://bugs.webkit.org/show_bug.cgi?id=42953
    
            Add new test covering updates of linked gradients.
    
            * platform/mac/svg/custom/js-update-stop-linked-gradient-expected.checksum: Added.
            * platform/mac/svg/custom/js-update-stop-linked-gradient-expected.png: Added.
            * platform/mac/svg/custom/js-update-stop-linked-gradient-expected.txt: Added.
            * svg/custom/js-update-stop-linked-gradient.svg: Added.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@64440 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 2210ab8..52d7752 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,17 @@
+2010-08-01  Nikolas Zimmermann  <nzimmermann at rim.com>
+
+        Reviewed by Dirk Schulze.
+
+        SVG gradients do not update when scripted via xlink
+        https://bugs.webkit.org/show_bug.cgi?id=42953
+
+        Add new test covering updates of linked gradients.
+
+        * platform/mac/svg/custom/js-update-stop-linked-gradient-expected.checksum: Added.
+        * platform/mac/svg/custom/js-update-stop-linked-gradient-expected.png: Added.
+        * platform/mac/svg/custom/js-update-stop-linked-gradient-expected.txt: Added.
+        * svg/custom/js-update-stop-linked-gradient.svg: Added.
+
 2010-07-31  Dan Bernstein  <mitz at apple.com>
 
         Reviewed by Darin Adler.
diff --git a/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.checksum b/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.checksum
new file mode 100644
index 0000000..600b220
--- /dev/null
+++ b/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.checksum
@@ -0,0 +1 @@
+8246eae6ce090047882694a4ae3fa4d2
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.png b/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.png
new file mode 100644
index 0000000..512c4f3
Binary files /dev/null and b/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.txt b/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.txt
new file mode 100644
index 0000000..7dbf29e
--- /dev/null
+++ b/LayoutTests/platform/mac/svg/custom/js-update-stop-linked-gradient-expected.txt
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 450x450
+  RenderSVGRoot {svg} at (10,10) size 430x314
+    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+      RenderSVGResourceLinearGradient {linearGradient} [id="gradient"] [gradientUnits=userSpaceOnUse] [start=(10,10)] [end=(440,10)]
+        RenderSVGGradientStop {stop} [offset=0.00] [color=#008000]
+        RenderSVGGradientStop {stop} [offset=1.00] [color=#008000]
+      RenderSVGResourceLinearGradient {linearGradient} [id="linkedGradient2"] [gradientUnits=userSpaceOnUse] [start=(10,10)] [end=(440,10)]
+      RenderSVGResourceLinearGradient {linearGradient} [id="linkedGradient1"] [gradientUnits=userSpaceOnUse] [start=(10,10)] [end=(440,10)]
+    RenderPath {rect} at (10,10) size 430x80 [fill={[type=LINEAR-GRADIENT] [id="gradient"]}] [data="M10.00,10.00 L440.00,10.00 L440.00,90.00 L10.00,90.00 Z"]
+    RenderPath {rect} at (10,110) size 430x80 [fill={[type=LINEAR-GRADIENT] [id="linkedGradient1"]}] [data="M10.00,110.00 L440.00,110.00 L440.00,190.00 L10.00,190.00 Z"]
+    RenderPath {rect} at (10,210) size 430x80 [fill={[type=LINEAR-GRADIENT] [id="linkedGradient2"]}] [data="M10.00,210.00 L440.00,210.00 L440.00,290.00 L10.00,290.00 Z"]
+    RenderSVGText {text} at (33,306) size 374x18 contains 1 chunk(s)
+      RenderSVGInlineText {#text} at (0,0) size 374x18
+        chunk 1 (middle anchor) text run 1 at (33.00,320.00) startOffset 0 endOffset 61 width 374.00: "All gradients should look the same, especially after clicking"
+caret: position 0 of child 0 {#text} of child 11 {text} of child 1 {svg} of document
diff --git a/LayoutTests/svg/custom/js-update-stop-linked-gradient.svg b/LayoutTests/svg/custom/js-update-stop-linked-gradient.svg
new file mode 100644
index 0000000..0db8d9f
--- /dev/null
+++ b/LayoutTests/svg/custom/js-update-stop-linked-gradient.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="450" height="450" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+    <linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="10" y1="10" x2="440" y2="10">
+        <stop stop-color="green" offset="0"/>
+        <stop id="stop1" stop-color="red" offset="0.5"/>
+        <stop stop-color="green" offset="1"/>
+    </linearGradient>
+
+    <linearGradient id="linkedGradient2" xlink:href="#linkedGradient1"/>
+    <linearGradient id="linkedGradient1" xlink:href="#gradient"/>
+</defs>
+
+<script>
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone();
+
+if (window.eventSender) {
+    window.setTimeout(function() {
+        eventSender.mouseMoveTo(150, 50);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+    }, 0);
+}
+
+function mouseHandler(evt)
+{
+    var stop = document.getElementById("stop1");
+    stop.parentNode.removeChild(stop);
+
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+</script>
+
+<rect onclick="mouseHandler(evt)" x="10" y="10" width="430" height="80" fill="url(#gradient)"/>
+<rect x="10" y="110" width="430" height="80" fill="url(#linkedGradient1)"/>
+<rect x="10" y="210" width="430" height="80" fill="url(#linkedGradient2)"/>
+<text text-anchor="middle" x="220" y="320">All gradients should look the same, especially after clicking</text>
+</svg>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index c924cc4..536b422 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,60 @@
+2010-08-01  Nikolas Zimmermann  <nzimmermann at rim.com>
+
+        Reviewed by Dirk Schulze.
+
+        SVG gradients do not update when scripted via xlink
+        https://bugs.webkit.org/show_bug.cgi?id=42953
+
+        Unify cycle detection logic for chainable (through xlink:href) and ordinary resources.
+        All operate on the render tree now, instead of falling back to the DOM tree for xlink:href queries.
+
+        When linking resources, register as regular client, so the regular update mechanisms work as expected.
+        <linearGradient id="foo"><stop../> </linearGradient>
+        <linearGradient id="bar" xlink:href="#foo"/>
+        <rect fill="url(#bar)"/>
+
+        Without that the rect won't receive invalidation notifications, as foo <-> bar had no connection.
+        Fixes the last outstanding class of invalidations. Also speeds up the cycle detetion, when using chained resources,
+        as no SVG DOM queries have to be executed anymore.
+
+        Test: svg/custom/js-update-stop-linked-gradient.svg
+
+        * rendering/RenderSVGResourceContainer.cpp:
+        (WebCore::RenderSVGResourceContainer::markAllClientsForInvalidation):
+        (WebCore::linkedResourceForContainer):
+        * rendering/SVGResources.cpp:
+        (WebCore::SVGResources::SVGResources):
+        (WebCore::chainableResourceTags):
+        (WebCore::targetReferenceFromResource):
+        (WebCore::registerPendingResource):
+        (WebCore::SVGResources::buildCachedResources):
+        (WebCore::SVGResources::invalidateClient):
+        (WebCore::SVGResources::resourceDestroyed):
+        (WebCore::SVGResources::buildSetOfResources):
+        (WebCore::SVGResources::setLinkedResource):
+        (WebCore::SVGResources::resetLinkedResource):
+        (WebCore::SVGResources::dump):
+        * rendering/SVGResources.h:
+        (WebCore::SVGResources::linkedResource):
+        * rendering/SVGResourcesCycleSolver.cpp:
+        (WebCore::SVGResourcesCycleSolver::resolveCycles):
+        (WebCore::SVGResourcesCycleSolver::breakCycle):
+        * rendering/SVGResourcesCycleSolver.h:
+        * svg/SVGFilterElement.cpp:
+        (WebCore::SVGFilterElement::SVGFilterElement):
+        * svg/SVGFilterElement.h:
+        * svg/SVGGradientElement.cpp:
+        (WebCore::SVGGradientElement::SVGGradientElement):
+        * svg/SVGGradientElement.h:
+        * svg/SVGLinearGradientElement.cpp:
+        (WebCore::SVGLinearGradientElement::collectGradientProperties):
+        * svg/SVGPatternElement.cpp:
+        (WebCore::SVGPatternElement::SVGPatternElement):
+        (WebCore::SVGPatternElement::collectPatternProperties):
+        * svg/SVGPatternElement.h:
+        * svg/SVGRadialGradientElement.cpp:
+        (WebCore::SVGRadialGradientElement::collectGradientProperties):
+
 2010-07-31  Dan Bernstein  <mitz at apple.com>
 
         Try to fix the Windows build when zlib is not available.
diff --git a/WebCore/rendering/RenderSVGResourceContainer.cpp b/WebCore/rendering/RenderSVGResourceContainer.cpp
index 90d81db..7e43300 100644
--- a/WebCore/rendering/RenderSVGResourceContainer.cpp
+++ b/WebCore/rendering/RenderSVGResourceContainer.cpp
@@ -95,8 +95,14 @@ void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode
 
     HashSet<RenderObject*>::iterator end = m_clients.end();
     for (HashSet<RenderObject*>::iterator it = m_clients.begin(); it != end; ++it) {
-        markClientForInvalidation(*it, mode);
-        RenderSVGResource::markForLayoutAndParentResourceInvalidation(*it, needsLayout);
+        RenderObject* client = *it;
+        if (client->isSVGResourceContainer()) {
+            client->toRenderSVGResourceContainer()->invalidateClients();
+            continue;
+        }
+
+        markClientForInvalidation(client, mode);
+        RenderSVGResource::markForLayoutAndParentResourceInvalidation(client, needsLayout);
     }
 }
 
diff --git a/WebCore/rendering/SVGResources.cpp b/WebCore/rendering/SVGResources.cpp
index b6ec75a..fa1677b 100644
--- a/WebCore/rendering/SVGResources.cpp
+++ b/WebCore/rendering/SVGResources.cpp
@@ -25,7 +25,10 @@
 #include "RenderSVGResourceFilter.h"
 #include "RenderSVGResourceMarker.h"
 #include "RenderSVGResourceMasker.h"
+#include "SVGFilterElement.h"
+#include "SVGGradientElement.h"
 #include "SVGPaint.h"
+#include "SVGPatternElement.h"
 #include "SVGRenderStyle.h"
 #include "SVGURIReference.h"
 
@@ -35,6 +38,7 @@ SVGResources::SVGResources()
     : m_clipperFilterMaskerData(0)
     , m_markerData(0)
     , m_fillStrokeData(0)
+    , m_linkedResource(0)
 {
 }
 
@@ -117,6 +121,34 @@ static HashSet<AtomicStringImpl*>& fillAndStrokeTags()
     return s_tagList;
 }
 
+static HashSet<AtomicStringImpl*>& chainableResourceTags()
+{
+    DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ());
+    if (s_tagList.isEmpty()) {
+        s_tagList.add(SVGNames::linearGradientTag.localName().impl());
+        s_tagList.add(SVGNames::filterTag.localName().impl());
+        s_tagList.add(SVGNames::patternTag.localName().impl());
+        s_tagList.add(SVGNames::radialGradientTag.localName().impl());
+    }
+
+    return s_tagList;
+}
+
+static inline String targetReferenceFromResource(SVGElement* element)
+{
+    String target;
+    if (element->hasTagName(SVGNames::patternTag))
+        target = static_cast<SVGPatternElement*>(element)->href();
+    else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
+        target = static_cast<SVGGradientElement*>(element)->href();
+    else if (element->hasTagName(SVGNames::filterTag))
+        target = static_cast<SVGFilterElement*>(element)->href();
+    else
+        ASSERT_NOT_REACHED();
+
+    return SVGURIReference::getTarget(target);
+}
+
 static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document* document, SVGPaint* paint, AtomicString& id, bool& hasPendingResource)
 {
     ASSERT(paint);
@@ -133,17 +165,13 @@ static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document*
     return 0;
 }
 
-static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, Node* node)
+static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement* element)
 {
-    ASSERT(node);
-    if (!node->isSVGElement())
-        return;
-
-    SVGElement* svgElement = static_cast<SVGElement*>(node);
-    if (!svgElement->isStyled())
+    ASSERT(element);
+    if (!element->isStyled())
         return;
 
-    extensions->addPendingResource(id, static_cast<SVGStyledElement*>(svgElement));
+    extensions->addPendingResource(id, static_cast<SVGStyledElement*>(element));
 }
 
 bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRenderStyle* style)
@@ -153,7 +181,11 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen
 
     Node* node = object->node();
     ASSERT(node);
-    ASSERT(node->isElementNode());
+    ASSERT(node->isSVGElement());
+
+    SVGElement* element = static_cast<SVGElement*>(node);
+    if (!element)
+        return false;
 
     Document* document = object->document();
     ASSERT(document);
@@ -161,7 +193,7 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen
     SVGDocumentExtensions* extensions = document->accessSVGExtensions();
     ASSERT(extensions);
 
-    AtomicStringImpl* tagNameImpl = static_cast<Element*>(node)->tagQName().localName().impl();
+    AtomicStringImpl* tagNameImpl = element->tagQName().localName().impl();
     if (!tagNameImpl)
         return false;
 
@@ -172,7 +204,7 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen
             if (setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(document, id)))
                 foundResources = true;
             else
-                registerPendingResource(extensions, id, node);
+                registerPendingResource(extensions, id, element);
         }
 
 #if ENABLE(FILTERS)
@@ -181,7 +213,7 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen
             if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id)))
                 foundResources = true;
             else
-                registerPendingResource(extensions, id, node);
+                registerPendingResource(extensions, id, element);
         }
 #endif
 
@@ -190,7 +222,7 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen
             if (setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(document, id)))
                 foundResources = true;
             else
-                registerPendingResource(extensions, id, node);
+                registerPendingResource(extensions, id, element);
         }
     }
 
@@ -199,19 +231,19 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen
         if (setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId)))
             foundResources = true;
         else
-            registerPendingResource(extensions, markerStartId, node);
+            registerPendingResource(extensions, markerStartId, element);
 
         AtomicString markerMidId(style->markerMidResource());
         if (setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId)))
             foundResources = true;
         else
-            registerPendingResource(extensions, markerMidId, node);
+            registerPendingResource(extensions, markerMidId, element);
 
         AtomicString markerEndId(style->markerEndResource());
         if (setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId)))
             foundResources = true;
         else
-            registerPendingResource(extensions, markerEndId, node);
+            registerPendingResource(extensions, markerEndId, element);
     }
 
     if (fillAndStrokeTags().contains(tagNameImpl)) {
@@ -221,7 +253,7 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen
             if (setFill(paintingResourceFromSVGPaint(document, style->fillPaint(), id, hasPendingResource)))
                 foundResources = true;
             else if (hasPendingResource)
-                registerPendingResource(extensions, id, node);
+                registerPendingResource(extensions, id, element);
         }
 
         if (style->hasStroke()) {
@@ -230,18 +262,34 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen
             if (setStroke(paintingResourceFromSVGPaint(document, style->strokePaint(), id, hasPendingResource)))
                 foundResources = true;
             else if (hasPendingResource)
-                registerPendingResource(extensions, id, node);
+                registerPendingResource(extensions, id, element);
         }
     }
 
+    if (chainableResourceTags().contains(tagNameImpl)) {
+        AtomicString id(targetReferenceFromResource(element));
+        if (setLinkedResource(getRenderSVGResourceContainerById(document, id)))
+            foundResources = true;
+        else
+            registerPendingResource(extensions, id, element);
+    }
+
     return foundResources;
 }
 
 void SVGResources::invalidateClient(RenderObject* object) const
 {
-    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData)
+    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
         return;
 
+    if (m_linkedResource) {
+        ASSERT(!m_clipperFilterMaskerData);
+        ASSERT(!m_markerData);
+        ASSERT(!m_fillStrokeData);
+        m_linkedResource->invalidateClient(object);
+        return;
+    }
+
     if (m_clipperFilterMaskerData) {
         if (m_clipperFilterMaskerData->clipper)
             m_clipperFilterMaskerData->clipper->invalidateClient(object);
@@ -273,8 +321,17 @@ void SVGResources::invalidateClient(RenderObject* object) const
 void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource)
 {
     ASSERT(resource);
-    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData)
+    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
+        return;
+
+    if (m_linkedResource == resource) {
+        ASSERT(!m_clipperFilterMaskerData);
+        ASSERT(!m_markerData);
+        ASSERT(!m_fillStrokeData);
+        m_linkedResource->invalidateClients();
+        m_linkedResource = 0;
         return;
+    }
 
     switch (resource->resourceType()) {
     case MaskerResourceType:
@@ -340,9 +397,17 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource)
 
 void SVGResources::buildSetOfResources(HashSet<RenderSVGResourceContainer*>& set)
 {
-    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData)
+    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
         return;
 
+    if (m_linkedResource) {
+        ASSERT(!m_clipperFilterMaskerData);
+        ASSERT(!m_markerData);
+        ASSERT(!m_fillStrokeData);
+        set.add(m_linkedResource);
+        return;
+    }
+
     if (m_clipperFilterMaskerData) {
         if (m_clipperFilterMaskerData->clipper)
             set.add(m_clipperFilterMaskerData->clipper);
@@ -525,6 +590,21 @@ void SVGResources::resetStroke()
     m_fillStrokeData->stroke = 0;
 }
 
+bool SVGResources::setLinkedResource(RenderSVGResourceContainer* linkedResource)
+{
+    if (!linkedResource)
+        return false;
+
+    m_linkedResource = linkedResource;
+    return true;
+}
+
+void SVGResources::resetLinkedResource()
+{
+    ASSERT(m_linkedResource);
+    m_linkedResource = 0;
+}
+
 #ifndef NDEBUG
 void SVGResources::dump(const RenderObject* object)
 {
@@ -562,6 +642,9 @@ void SVGResources::dump(const RenderObject* object)
         if (RenderSVGResourceContainer* stroke = m_fillStrokeData->stroke)
             fprintf(stderr, " |-> Stroke     : %p (node=%p)\n", stroke, stroke->node());
     }
+
+    if (m_linkedResource)
+        fprintf(stderr, " |-> xlink:href : %p (node=%p)\n", m_linkedResource, m_linkedResource->node());
 }
 #endif
 
diff --git a/WebCore/rendering/SVGResources.h b/WebCore/rendering/SVGResources.h
index 0486758..a07a990 100644
--- a/WebCore/rendering/SVGResources.h
+++ b/WebCore/rendering/SVGResources.h
@@ -58,6 +58,9 @@ public:
     RenderSVGResourceContainer* fill() const { return m_fillStrokeData ? m_fillStrokeData->fill : 0; }
     RenderSVGResourceContainer* stroke() const { return m_fillStrokeData ? m_fillStrokeData->stroke : 0; }
 
+    // Chainable resources - linked through xlink:href
+    RenderSVGResourceContainer* linkedResource() const { return m_linkedResource; }
+
     void buildSetOfResources(HashSet<RenderSVGResourceContainer*>&);
 
     // Methods operating on all cached resources
@@ -82,6 +85,7 @@ private:
     void resetMasker();
     void resetFill();
     void resetStroke();
+    void resetLinkedResource();
 
 private:
     bool setClipper(RenderSVGResourceClipper*);
@@ -94,6 +98,7 @@ private:
     bool setMasker(RenderSVGResourceMasker*);
     bool setFill(RenderSVGResourceContainer*);
     bool setStroke(RenderSVGResourceContainer*);
+    bool setLinkedResource(RenderSVGResourceContainer*);
 
     // From SVG 1.1 2nd Edition
     // clipper: 'container elements' and 'graphics elements'
@@ -165,6 +170,7 @@ private:
     OwnPtr<ClipperFilterMaskerData> m_clipperFilterMaskerData;
     OwnPtr<MarkerData> m_markerData;
     OwnPtr<FillStrokeData> m_fillStrokeData;
+    RenderSVGResourceContainer* m_linkedResource;
 };
 
 }
diff --git a/WebCore/rendering/SVGResourcesCycleSolver.cpp b/WebCore/rendering/SVGResourcesCycleSolver.cpp
index 2d38a8c..3cd6d8d 100644
--- a/WebCore/rendering/SVGResourcesCycleSolver.cpp
+++ b/WebCore/rendering/SVGResourcesCycleSolver.cpp
@@ -94,89 +94,6 @@ bool SVGResourcesCycleSolver::resourceContainsCycles(RenderObject* renderer) con
     return false;
 }
 
-static inline String targetReferenceFromResource(SVGElement* element, bool& isValid)
-{
-    String target;
-    if (element->hasTagName(SVGNames::patternTag))
-        target = static_cast<SVGPatternElement*>(element)->href();
-    else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
-        target = static_cast<SVGGradientElement*>(element)->href();
-    else if (element->hasTagName(SVGNames::filterTag))
-        target = static_cast<SVGFilterElement*>(element)->href();
-    else {
-        isValid = false;
-        return target;
-    }
-
-    return SVGURIReference::getTarget(target);
-}
-
-static inline void setFollowLinkForChainableResource(SVGElement* element, bool followLink)
-{
-    if (element->hasTagName(SVGNames::patternTag))
-        static_cast<SVGPatternElement*>(element)->setFollowLink(followLink);
-    else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
-        static_cast<SVGGradientElement*>(element)->setFollowLink(followLink);
-    else if (element->hasTagName(SVGNames::filterTag))
-        static_cast<SVGFilterElement*>(element)->setFollowLink(followLink);
-}
-
-bool SVGResourcesCycleSolver::chainableResourceContainsCycles(RenderSVGResourceContainer* container) const
-{
-    ASSERT(container);
-    ASSERT(container->node());
-    ASSERT(container->node()->isSVGElement());
-
-    // Chainable resources cycle detection is performed in the DOM tree.
-    SVGElement* element = static_cast<SVGElement*>(container->node());
-    ASSERT(element);
-
-    HashSet<SVGElement*> processedObjects;
-
-    bool isValid = true;
-    String target = targetReferenceFromResource(element, isValid);
-    ASSERT(isValid);
-
-    SVGElement* previousElement = element;
-    while (!target.isEmpty()) {
-        Node* targetNode = element->document()->getElementById(target);
-        if (!targetNode || !targetNode->isSVGElement())
-            break;
-
-        // Catch cylic chaining, otherwhise we'll run into an infinite loop here.
-        // <pattern id="foo" xlink:href="#bar"/> <pattern id="bar xlink:href="#foo"/>
-        SVGElement* targetElement = static_cast<SVGElement*>(targetNode);
-
-        bool followLink = true;
-        if (processedObjects.contains(targetElement) || targetElement == element)
-            followLink = false;
-
-        setFollowLinkForChainableResource(previousElement, followLink);
-        if (!followLink)
-            return false;
-
-        previousElement = targetElement;
-        processedObjects.add(targetElement);
-        target = targetReferenceFromResource(targetElement, isValid);
-        if (!isValid)
-            break;
-    }
-
-    // Couldn't find any direct cycle in the xlink:href chain, maybe there's an indirect one.
-    // <pattern id="foo" xlink:href="#bar"/> <pattern id="bar"> <rect fill="url(#foo)"...
-    HashSet<SVGElement*>::iterator end = processedObjects.end();
-    for (HashSet<SVGElement*>::iterator it = processedObjects.begin(); it != end; ++it) {
-        RenderObject* renderer = (*it)->renderer();
-        if (!renderer)
-            continue;
-        ASSERT(renderer->isSVGResourceContainer());
-        if (m_allResources.contains(renderer->toRenderSVGResourceContainer()))
-            return true;
-    }
-
-    return false;
-}
-
 void SVGResourcesCycleSolver::resolveCycles()
 {
     ASSERT(m_allResources.isEmpty());
@@ -221,6 +138,10 @@ void SVGResourcesCycleSolver::resolveCycles()
     for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it)
         m_allResources.add(*it);
 
+    // If we're a resource, add ourselves to the HashSet.
+    if (m_renderer->isSVGResourceContainer())
+        m_allResources.add(m_renderer->toRenderSVGResourceContainer());
+
     ASSERT(!m_allResources.isEmpty());
 
     // The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer'
@@ -228,22 +149,6 @@ void SVGResourcesCycleSolver::resolveCycles()
     end = localResources.end();
     for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) {
         RenderSVGResourceContainer* resource = *it;
-
-        // Special handling for resources that can be chained using xlink:href - need to detect cycles as well!
-        switch (resource->resourceType()) {
-        case PatternResourceType:
-        case LinearGradientResourceType:
-        case RadialGradientResourceType:
-        case FilterResourceType:
-            if (chainableResourceContainsCycles(resource)) {
-                breakCycle(resource);
-                continue;
-            }
-            break;
-        default:
-            break;
-        }
-
         if (parentResources.contains(resource) || resourceContainsCycles(resource))
             breakCycle(resource);
     }
@@ -259,6 +164,11 @@ void SVGResourcesCycleSolver::resolveCycles()
 void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer* resourceLeadingToCycle)
 {
     ASSERT(resourceLeadingToCycle);
+    if (resourceLeadingToCycle == m_resources->linkedResource()) {
+        m_resources->resetLinkedResource();
+        return;
+    }
+
     switch (resourceLeadingToCycle->resourceType()) {
     case MaskerResourceType:
         ASSERT(resourceLeadingToCycle == m_resources->masker());
diff --git a/WebCore/rendering/SVGResourcesCycleSolver.h b/WebCore/rendering/SVGResourcesCycleSolver.h
index 1f49354..e63ee63 100644
--- a/WebCore/rendering/SVGResourcesCycleSolver.h
+++ b/WebCore/rendering/SVGResourcesCycleSolver.h
@@ -38,7 +38,6 @@ public:
 
 private:
     bool resourceContainsCycles(RenderObject*) const;
-    bool chainableResourceContainsCycles(RenderSVGResourceContainer*) const;
     void breakCycle(RenderSVGResourceContainer*);
 
     RenderObject* m_renderer;
diff --git a/WebCore/svg/SVGFilterElement.cpp b/WebCore/svg/SVGFilterElement.cpp
index 73a935b..0d55bb1 100644
--- a/WebCore/svg/SVGFilterElement.cpp
+++ b/WebCore/svg/SVGFilterElement.cpp
@@ -47,7 +47,6 @@ SVGFilterElement::SVGFilterElement(const QualifiedName& tagName, Document* doc)
     , SVGURIReference()
     , SVGLangSpace()
     , SVGExternalResourcesRequired()
-    , m_followLink(true)
     , m_filterUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
     , m_primitiveUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
     , m_x(LengthModeWidth, "-10%")
diff --git a/WebCore/svg/SVGFilterElement.h b/WebCore/svg/SVGFilterElement.h
index d37fff4..cdb2297 100644
--- a/WebCore/svg/SVGFilterElement.h
+++ b/WebCore/svg/SVGFilterElement.h
@@ -55,14 +55,9 @@ public:
 
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
 
-    // FIXME: Add xlink:href support for filters, and use this property
-    void setFollowLink(bool followLink) { m_followLink = followLink; }
-
 private:
     virtual bool selfHasRelativeLengths() const;
 
-    bool m_followLink;
-
     DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::filterUnitsAttr, int, FilterUnits, filterUnits)
     DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::primitiveUnitsAttr, int, PrimitiveUnits, primitiveUnits)
     DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::xAttr, SVGLength, X, x)
diff --git a/WebCore/svg/SVGGradientElement.cpp b/WebCore/svg/SVGGradientElement.cpp
index 43e5b34..0d06955 100644
--- a/WebCore/svg/SVGGradientElement.cpp
+++ b/WebCore/svg/SVGGradientElement.cpp
@@ -42,7 +42,6 @@ SVGGradientElement::SVGGradientElement(const QualifiedName& tagName, Document* d
     : SVGStyledElement(tagName, doc)
     , SVGURIReference()
     , SVGExternalResourcesRequired()
-    , m_followLink(true)
     , m_gradientUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
     , m_gradientTransform(SVGTransformList::create(SVGNames::gradientTransformAttr))
 {
diff --git a/WebCore/svg/SVGGradientElement.h b/WebCore/svg/SVGGradientElement.h
index 3602cff..11a13e4 100644
--- a/WebCore/svg/SVGGradientElement.h
+++ b/WebCore/svg/SVGGradientElement.h
@@ -47,11 +47,7 @@ namespace WebCore {
 
         Vector<Gradient::ColorStop> buildStops();
  
-        void setFollowLink(bool followLink) { m_followLink = followLink; }
-
     protected:
-        bool m_followLink;
-
         DECLARE_ANIMATED_PROPERTY(SVGGradientElement, SVGNames::spreadMethodAttr, int, SpreadMethod, spreadMethod)
         DECLARE_ANIMATED_PROPERTY(SVGGradientElement, SVGNames::gradientUnitsAttr, int, GradientUnits, gradientUnits)
         DECLARE_ANIMATED_PROPERTY(SVGGradientElement, SVGNames::gradientTransformAttr, SVGTransformList*, GradientTransform, gradientTransform)
diff --git a/WebCore/svg/SVGLinearGradientElement.cpp b/WebCore/svg/SVGLinearGradientElement.cpp
index 94e4ef7..37f380b 100644
--- a/WebCore/svg/SVGLinearGradientElement.cpp
+++ b/WebCore/svg/SVGLinearGradientElement.cpp
@@ -155,7 +155,7 @@ LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties()
         processedGradients.add(current);
 
         // Respect xlink:href, take attributes from referenced element
-        Node* refNode = m_followLink ? ownerDocument()->getElementById(SVGURIReference::getTarget(current->href())) : 0;
+        Node* refNode = ownerDocument()->getElementById(SVGURIReference::getTarget(current->href()));
         if (refNode && (refNode->hasTagName(SVGNames::linearGradientTag) || refNode->hasTagName(SVGNames::radialGradientTag))) {
             current = static_cast<SVGGradientElement*>(refNode);
 
diff --git a/WebCore/svg/SVGPatternElement.cpp b/WebCore/svg/SVGPatternElement.cpp
index 6196ff5..ee42118 100644
--- a/WebCore/svg/SVGPatternElement.cpp
+++ b/WebCore/svg/SVGPatternElement.cpp
@@ -56,7 +56,6 @@ SVGPatternElement::SVGPatternElement(const QualifiedName& tagName, Document* doc
     , SVGLangSpace()
     , SVGExternalResourcesRequired()
     , SVGFitToViewBox()
-    , m_followLink(true)
     , m_x(LengthModeWidth)
     , m_y(LengthModeHeight)
     , m_width(LengthModeWidth)
@@ -239,7 +238,7 @@ PatternAttributes SVGPatternElement::collectPatternProperties() const
         processedPatterns.add(current);
 
         // Respect xlink:href, take attributes from referenced element
-        Node* refNode = m_followLink ? ownerDocument()->getElementById(SVGURIReference::getTarget(current->href())) : 0;
+        Node* refNode = ownerDocument()->getElementById(SVGURIReference::getTarget(current->href()));
         if (refNode && refNode->hasTagName(SVGNames::patternTag)) {
             current = static_cast<const SVGPatternElement*>(const_cast<const Node*>(refNode));
 
diff --git a/WebCore/svg/SVGPatternElement.h b/WebCore/svg/SVGPatternElement.h
index f1bd3f4..2a8a7fe 100644
--- a/WebCore/svg/SVGPatternElement.h
+++ b/WebCore/svg/SVGPatternElement.h
@@ -57,13 +57,10 @@ namespace WebCore {
         virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
 
         PatternAttributes collectPatternProperties() const;
-        void setFollowLink(bool followLink) { m_followLink = followLink; }
 
     private:
         virtual bool selfHasRelativeLengths() const;
 
-        bool m_followLink;
-
         DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::xAttr, SVGLength, X, x)
         DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::yAttr, SVGLength, Y, y)
         DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::widthAttr, SVGLength, Width, width)
diff --git a/WebCore/svg/SVGRadialGradientElement.cpp b/WebCore/svg/SVGRadialGradientElement.cpp
index dc1c8d5..a970817 100644
--- a/WebCore/svg/SVGRadialGradientElement.cpp
+++ b/WebCore/svg/SVGRadialGradientElement.cpp
@@ -168,7 +168,7 @@ RadialGradientAttributes SVGRadialGradientElement::collectGradientProperties()
         processedGradients.add(current);
 
         // Respect xlink:href, take attributes from referenced element
-        Node* refNode = m_followLink ? ownerDocument()->getElementById(SVGURIReference::getTarget(current->href())) : 0;
+        Node* refNode = ownerDocument()->getElementById(SVGURIReference::getTarget(current->href()));
         if (refNode && (refNode->hasTagName(SVGNames::radialGradientTag) || refNode->hasTagName(SVGNames::linearGradientTag))) {
             current = static_cast<SVGGradientElement*>(refNode);
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list