https://bugs.webkit.org/show_bug.cgi?id=73860
Reviewed by Dirk Schulze.
Source/WebCore:
Consider following testcase:
<defs>
<rect id="rect" fill="red" width="50" height="50"/>
<filter id="filter">
<feImage xlink:href="#rect"/>
</filter>
</defs>
<rect width="50" height="50" filter="url(#filter)"/>
If the <rect id="rect"> gets changed dynamically (attribute/property/style change) the <feImage>
doesn't notice this, as there's no link between the <rect> and the <feImage>, as the <rect> is not
a child of the <feImage/>. To get invalidations working for these situations, we have to track
the referencingElement & referencedElement in SVGDocumentExtensions.
Fixes parts the SVG-Wow twirl testcase and David Daileys SVG waves example.
Tests: svg/filters/feImage-animated-transform-on-target-rect.svg
svg/filters/feImage-late-indirect-update.svg
svg/filters/feImage-mutliple-targets-id-change.svg
svg/filters/feImage-target-attribute-change-with-use-indirection-2.svg
svg/filters/feImage-target-attribute-change-with-use-indirection.svg
svg/filters/feImage-target-attribute-change.svg
svg/filters/feImage-target-inline-style-change.svg
svg/filters/feImage-target-property-change.svg
svg/filters/feImage-target-style-change.svg
* rendering/svg/RenderSVGResource.cpp:
(WebCore::removeFromFilterCacheAndInvalidateDependencies): Renamed from removeFromFilterCache, as it has another purpose now.
(WebCore::RenderSVGResource::markForLayoutAndParentResourceInvalidation): s/removeFromFilterCache/removeFromFilterCacheAndInvalidateDependencies/.
* rendering/svg/RenderSVGResource.h: Removed removeFromFilterCache, it got inlined.
* svg/SVGDocumentExtensions.cpp: Add a new HashMap<SVGElement*, OwnPtr<HashSet<SVGElement*> > > used for dependency tracking.
(WebCore::SVGDocumentExtensions::setOfElementsReferencingTarget): Returns all elements the passed in element depends on.
(WebCore::SVGDocumentExtensions::addElementReferencingTarget): Register element 'a' referencing target 'b'.
(WebCore::SVGDocumentExtensions::removeAllTargetReferencesForElement): Called by element 'a' on destruction or any target change.
(WebCore::SVGDocumentExtensions::removeAllElementReferencesForTarget): Called by element 'b' on destruction.
* svg/SVGDocumentExtensions.h: Expose new methods.
* svg/SVGElement.cpp:
(WebCore::SVGElement::~SVGElement): Call remove removeAllElementReferencesForTarget on destruction.
* svg/SVGFEImageElement.cpp:
(WebCore::SVGFEImageElement::clearResourceReferences):
(WebCore::SVGFEImageElement::buildPendingResource):
LayoutTests:
Add lots of new testcases covering <feImage> invalidation, when the referenced target changes.
Thanks to the repaint harness, it uncovered a bug with feImage-late-indirect-update.svg - there no gray
overlay rects are visible, as the whole screen gets repainted, which is a bug!
* platform/mac/svg/filters/feImage-animated-transform-on-target-rect-expected.png: Added.
* platform/mac/svg/filters/feImage-change-target-id-expected.png: Added.
* platform/mac/svg/filters/feImage-change-target-id-expected.txt: Added.
* platform/mac/svg/filters/feImage-late-indirect-update-expected.png: Added.
* platform/mac/svg/filters/feImage-late-indirect-update-expected.txt: Added.
* platform/mac/svg/filters/feImage-multiple-targets-id-change-expected.png: Added.
* platform/mac/svg/filters/feImage-multiple-targets-id-change-expected.txt: Added.
* platform/mac/svg/filters/feImage-remove-target-expected.png: Added.
* platform/mac/svg/filters/feImage-remove-target-expected.txt: Added.
* platform/mac/svg/filters/feImage-target-add-to-document-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-add-to-document-expected.png.
* platform/mac/svg/filters/feImage-target-add-to-document-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-add-to-document-expected.txt.
* platform/mac/svg/filters/feImage-target-attribute-change-expected.png: Added.
* platform/mac/svg/filters/feImage-target-attribute-change-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
* platform/mac/svg/filters/feImage-target-attribute-change-with-use-indirection-2-expected.png: Added.
* platform/mac/svg/filters/feImage-target-attribute-change-with-use-indirection-2-expected.txt: Added.
* platform/mac/svg/filters/feImage-target-attribute-change-with-use-indirection-expected.png: Added.
* platform/mac/svg/filters/feImage-target-attribute-change-with-use-indirection-expected.txt: Added.
* platform/mac/svg/filters/feImage-target-changes-id-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-changes-id-expected.png.
* platform/mac/svg/filters/feImage-target-changes-id-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
* platform/mac/svg/filters/feImage-target-id-change-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-id-change-expected.png.
* platform/mac/svg/filters/feImage-target-id-change-expected.txt: Renamed from LayoutTests/svg/filters/feImage-target-id-change-expected.txt.
* platform/mac/svg/filters/feImage-target-inline-style-change-expected.png: Added.
* platform/mac/svg/filters/feImage-target-inline-style-change-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
* platform/mac/svg/filters/feImage-target-property-change-expected.png: Added.
* platform/mac/svg/filters/feImage-target-property-change-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
* platform/mac/svg/filters/feImage-target-reappend-to-document-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-reappend-to-document-expected.png.
* platform/mac/svg/filters/feImage-target-reappend-to-document-expected.txt: Renamed from LayoutTests/svg/filters/feImage-target-reappend-to-document-expected.txt.
* platform/mac/svg/filters/feImage-target-remove-from-document-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-remove-from-document-expected.png.
* platform/mac/svg/filters/feImage-target-remove-from-document-expected.txt: Renamed from LayoutTests/svg/filters/feImage-target-remove-from-document-expected.txt.
* platform/mac/svg/filters/feImage-target-style-change-expected.png: Added.
* platform/mac/svg/filters/feImage-target-style-change-expected.txt: Renamed from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
* svg/filters/feImage-animated-transform-on-target-rect-expected.txt: Added.
* svg/filters/feImage-animated-transform-on-target-rect.svg: Added.
* svg/filters/feImage-change-target-id.svg: Added.
* svg/filters/feImage-late-indirect-update.svg: Added.
* svg/filters/feImage-multiple-targets-id-change.svg: Added.
* svg/filters/feImage-remove-target.svg: Added.
* svg/filters/feImage-target-attribute-change-with-use-indirection-2.svg: Added.
* svg/filters/feImage-target-attribute-change-with-use-indirection.svg: Added.
* svg/filters/feImage-target-attribute-change.svg: Added.
* svg/filters/feImage-target-inline-style-change.svg: Added.
* svg/filters/feImage-target-property-change.svg: Added.
* svg/filters/feImage-target-style-change.svg: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@107067
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-02-08 Nikolas Zimmermann <nzimmermann@rim.com>
+
+ feImage doesn't invalidate when its target SVG element is animated
+ https://bugs.webkit.org/show_bug.cgi?id=73860
+
+ Reviewed by Dirk Schulze.
+
+ Add lots of new testcases covering <feImage> invalidation, when the referenced target changes.
+ Thanks to the repaint harness, it uncovered a bug with feImage-late-indirect-update.svg - there no gray
+ overlay rects are visible, as the whole screen gets repainted, which is a bug!
+
+ * platform/mac/svg/filters/feImage-animated-transform-on-target-rect-expected.png: Added.
+ * platform/mac/svg/filters/feImage-change-target-id-expected.png: Added.
+ * platform/mac/svg/filters/feImage-change-target-id-expected.txt: Added.
+ * platform/mac/svg/filters/feImage-late-indirect-update-expected.png: Added.
+ * platform/mac/svg/filters/feImage-late-indirect-update-expected.txt: Added.
+ * platform/mac/svg/filters/feImage-multiple-targets-id-change-expected.png: Added.
+ * platform/mac/svg/filters/feImage-multiple-targets-id-change-expected.txt: Added.
+ * platform/mac/svg/filters/feImage-remove-target-expected.png: Added.
+ * platform/mac/svg/filters/feImage-remove-target-expected.txt: Added.
+ * platform/mac/svg/filters/feImage-target-add-to-document-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-add-to-document-expected.png.
+ * platform/mac/svg/filters/feImage-target-add-to-document-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-add-to-document-expected.txt.
+ * platform/mac/svg/filters/feImage-target-attribute-change-expected.png: Added.
+ * platform/mac/svg/filters/feImage-target-attribute-change-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
+ * platform/mac/svg/filters/feImage-target-attribute-change-with-use-indirection-2-expected.png: Added.
+ * platform/mac/svg/filters/feImage-target-attribute-change-with-use-indirection-2-expected.txt: Added.
+ * platform/mac/svg/filters/feImage-target-attribute-change-with-use-indirection-expected.png: Added.
+ * platform/mac/svg/filters/feImage-target-attribute-change-with-use-indirection-expected.txt: Added.
+ * platform/mac/svg/filters/feImage-target-changes-id-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-changes-id-expected.png.
+ * platform/mac/svg/filters/feImage-target-changes-id-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
+ * platform/mac/svg/filters/feImage-target-id-change-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-id-change-expected.png.
+ * platform/mac/svg/filters/feImage-target-id-change-expected.txt: Renamed from LayoutTests/svg/filters/feImage-target-id-change-expected.txt.
+ * platform/mac/svg/filters/feImage-target-inline-style-change-expected.png: Added.
+ * platform/mac/svg/filters/feImage-target-inline-style-change-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
+ * platform/mac/svg/filters/feImage-target-property-change-expected.png: Added.
+ * platform/mac/svg/filters/feImage-target-property-change-expected.txt: Copied from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
+ * platform/mac/svg/filters/feImage-target-reappend-to-document-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-reappend-to-document-expected.png.
+ * platform/mac/svg/filters/feImage-target-reappend-to-document-expected.txt: Renamed from LayoutTests/svg/filters/feImage-target-reappend-to-document-expected.txt.
+ * platform/mac/svg/filters/feImage-target-remove-from-document-expected.png: Renamed from LayoutTests/svg/filters/feImage-target-remove-from-document-expected.png.
+ * platform/mac/svg/filters/feImage-target-remove-from-document-expected.txt: Renamed from LayoutTests/svg/filters/feImage-target-remove-from-document-expected.txt.
+ * platform/mac/svg/filters/feImage-target-style-change-expected.png: Added.
+ * platform/mac/svg/filters/feImage-target-style-change-expected.txt: Renamed from LayoutTests/svg/filters/feImage-target-changes-id-expected.txt.
+ * svg/filters/feImage-animated-transform-on-target-rect-expected.txt: Added.
+ * svg/filters/feImage-animated-transform-on-target-rect.svg: Added.
+ * svg/filters/feImage-change-target-id.svg: Added.
+ * svg/filters/feImage-late-indirect-update.svg: Added.
+ * svg/filters/feImage-multiple-targets-id-change.svg: Added.
+ * svg/filters/feImage-remove-target.svg: Added.
+ * svg/filters/feImage-target-attribute-change-with-use-indirection-2.svg: Added.
+ * svg/filters/feImage-target-attribute-change-with-use-indirection.svg: Added.
+ * svg/filters/feImage-target-attribute-change.svg: Added.
+ * svg/filters/feImage-target-inline-style-change.svg: Added.
+ * svg/filters/feImage-target-property-change.svg: Added.
+ * svg/filters/feImage-target-style-change.svg: Added.
+
2012-02-08 Csaba Osztrogonác <ossy@webkit.org>
[Qt] Unreviewed gardening. Unskip now passing tests, skip failing tests and one update.
BUGWK78084 : svg/custom/text-ctm.svg = IMAGE+TEXT
BUGWK78084 : svg/custom/text-hit-test.svg = IMAGE+TEXT
+// feImage now supports dynamic invalidations if the target changes.
+BUGWK73860 : svg/filters/feImage-animated-transform-on-target-rect.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-change-target-id.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-late-indirect-update.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-multiple-targets-id-change.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-remove-target.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-target-attribute-change-with-use-indirection-2.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-target-attribute-change-with-use-indirection.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-target-attribute-change.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-target-inline-style-change.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-target-property-change.svg = IMAGE+TEXT
+BUGWK73860 : svg/filters/feImage-target-style-change.svg = IMAGE+TEXT
+
BUGWK78038 DEBUG : compositing/iframes/invisible-nested-iframe-show.html = PASS CRASH
BUGWK78038 DEBUG : compositing/iframes/layout-on-compositing-change.html = PASS CRASH
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 111x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="0x0"]
+ RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 800x600
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGResourceLinearGradient {linearGradient} [id="gradient"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,1)]
+ RenderSVGGradientStop {stop} [offset=0.00] [color=#008000]
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="400x300"]
+ RenderSVGPath {ellipse} at (200,150) size 400x300 [fill={[type=LINEAR-GRADIENT] [id="gradient"]}] [cx=400.00] [cy=300.00] [rx=200.00] [ry=150.00]
+ RenderSVGRect {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=800.00] [height=600.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-80,-60) size 960x720
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 105x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGResourceFilter {filter} [id="image1"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="100x100"]
+ RenderSVGResourceFilter {filter} [id="image2"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="100x100"]
+ RenderSVGRect {rect} at (0,0) size 56x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=50.00] [height=100.00]
+ [filter="image1"] RenderSVGResourceFilter {filter} at (-5,-10) size 60x120
+ RenderSVGRect {rect} at (45,0) size 60x111 [fill={[type=SOLID] [color=#000000]}] [x=50.00] [y=0.00] [width=50.00] [height=100.00]
+ [filter="image2"] RenderSVGResourceFilter {filter} at (45,-10) size 60x120
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 111x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="0x0"]
+ RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 111x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGRect {rect} at (0,0) size 50x100 [fill={[type=SOLID] [color=#008000]}] [x=-50.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGContainer {use} at (0,0) size 100x100
+ RenderSVGContainer {g} at (0,0) size 100x100 [transform={m=((1.00,0.00)(0.00,1.00)) t=(50.00,0.00)}]
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=-50.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="100x100"]
+ RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 111x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGContainer {use} at (0,0) size 100x100
+ RenderSVGContainer {g} at (0,0) size 100x100
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="100x100"]
+ RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 111x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="100x100"]
+ RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 111x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="100x100"]
+ RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 111x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="100x100"]
+ RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (0,0) size 111x111
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+ [feImage image-size="100x100"]
+ RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
+ [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
--- /dev/null
+Passes if rect is not rotated
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <defs>
+ <rect id="rect" fill="green" width="50" height="50" transform="rotate(45)">
+ <animateTransform id="animation" attributeName="transform" type="rotate" calcMode="discrete" begin="indefinite" from="45" to="0" dur="0.1s" fill="freeze"/>
+ </rect>
+
+ <filter id="filter">
+ <feImage xlink:href="#rect"/>
+ </filter>
+ </defs>
+ <text y="-50">Passes if rect is not rotated</text>
+ <rect fill="red" x="50" y="50" width="50" height="50" filter="url(#filter)"/>
+
+<script><![CDATA[
+ function repaintTest() {
+ if (window.layoutTestController)
+ layoutTestController.waitUntilDone();
+
+ document.getElementById("animation").beginElement();
+ setTimeout(finishTest, 50);
+
+ function finishTest() {
+ // Wait for the animation to finish
+ if (document.getElementById("rect").transform.animVal.getItem(0).matrix.a != 1) {
+ setTimeout(finishTest, 50);
+ return;
+ }
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+ }
+ }
+
+ if (window.layoutTestController)
+ layoutTestController.dumpAsText(true);
+]]></script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>Nothing should be rendered</title>
+ <defs>
+ <rect id="rect" width="100" height="100" fill="green"/>
+
+ <filter id="filter">
+ <feImage id="feimage" xlink:href="#rect" />
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="100" height="100" filter="url(#filter)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ document.getElementById("rect").setAttribute("id", "away");
+ }
+ ]]>
+ </script>
+</svg>
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+<script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+<defs>
+ <linearGradient id="gradient" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="1" y2="1">
+ <stop id="stop" stop-color="red" offset="0"/>
+ </linearGradient>
+
+ <filter id="filter" >
+ <feImage xlink:href="#ellipse"/>
+ </filter>
+ <ellipse id="ellipse" cx="50%" cy="50%" rx="25%" ry="25%" fill="url(#gradient)"/>
+</defs>
+<rect width="100%" height="100%" filter='url(#filter)'/>
+
+<script>
+function repaintTest() {
+ document.getElementById("stop").setAttribute("stop-color", "green");
+}
+</script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>There should be a single green 100x100 square.</title>
+ <defs>
+ <rect id="rect" width="1" height="100" fill="green"/>
+
+ <filter id="image1">
+ <feImage id="feimage1" xlink:href="#rect" />
+ </filter>
+
+ <filter id="image2">
+ <feImage id="feimage2" xlink:href="#rect" />
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="50" height="100" filter="url(#image1)" />
+ <rect x="50" y="0" width="50" height="100" filter="url(#image2)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ document.getElementById("rect").setAttribute("width", "100");
+ }
+ ]]>
+ </script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>Nothing should be rendered</title>
+ <defs>
+ <rect id="rect" width="100" height="100" fill="green"/>
+
+ <filter id="filter">
+ <feImage id="feimage" xlink:href="#rect" />
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="100" height="100" filter="url(#filter)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ var rect = document.getElementById("rect");
+ rect.parentNode.removeChild(rect);
+ }
+ ]]>
+ </script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>There should be a single green 100x100 square.</title>
+ <defs>
+ <rect id="rect" x="-50" width="100" height="100" fill="green"/>
+ <use xlink:href="#rect" id="use"/>
+
+ <filter id="filter">
+ <feImage id="feimage" xlink:href="#use"/>
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="100" height="100" filter="url(#filter)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ document.getElementById("use").setAttribute("x", "50");
+ }
+ ]]>
+ </script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>There should be a single green 100x100 square.</title>
+ <defs>
+ <rect id="rect" width="1" height="100" fill="green"/>
+ <use xlink:href="#rect" id="use"/>
+
+ <filter id="filter">
+ <feImage id="feimage" xlink:href="#use"/>
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="100" height="100" filter="url(#filter)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ document.getElementById("rect").setAttribute("width", "100");
+ }
+ ]]>
+ </script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>There should be a single green 100x100 square.</title>
+ <defs>
+ <rect id="rect" width="1" height="100" fill="green"/>
+
+ <filter id="filter">
+ <feImage id="feimage" xlink:href="#rect" />
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="100" height="100" filter="url(#filter)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ document.getElementById("rect").setAttribute("width", "100");
+ }
+ ]]>
+ </script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>There should be a single green 100x100 square.</title>
+ <defs>
+ <rect id="rect" width="100" height="100" style="fill: red"/>
+
+ <filter id="filter">
+ <feImage id="feimage" xlink:href="#rect" />
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="100" height="100" filter="url(#filter)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ document.getElementById("rect").setAttribute("style", "fill: green");
+ }
+ ]]>
+ </script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>There should be a single green 100x100 square.</title>
+ <defs>
+ <rect id="rect" width="1" height="100" fill="green"/>
+
+ <filter id="filter">
+ <feImage id="feimage" xlink:href="#rect" />
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="100" height="100" filter="url(#filter)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ document.getElementById("rect").width.baseVal.value = 100;
+ }
+ ]]>
+ </script>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runRepaintTest()">
+ <script xlink:href="../../fast/repaint/resources/repaint.js"></script>
+ <title>There should be a single green 100x100 square.</title>
+ <defs>
+ <rect id="rect" width="100" height="100" fill="red"/>
+
+ <filter id="filter">
+ <feImage id="feimage" xlink:href="#rect" />
+ </filter>
+ </defs>
+ <rect x="0" y="0" width="100" height="100" filter="url(#filter)" />
+ <script>
+ <![CDATA[
+ function repaintTest() {
+ document.getElementById("rect").style.fill = "green";
+ }
+ ]]>
+ </script>
+</svg>
+2012-02-08 Nikolas Zimmermann <nzimmermann@rim.com>
+
+ feImage doesn't invalidate when its target SVG element is animated
+ https://bugs.webkit.org/show_bug.cgi?id=73860
+
+ Reviewed by Dirk Schulze.
+
+ Consider following testcase:
+ <defs>
+ <rect id="rect" fill="red" width="50" height="50"/>
+ <filter id="filter">
+ <feImage xlink:href="#rect"/>
+ </filter>
+ </defs>
+ <rect width="50" height="50" filter="url(#filter)"/>
+
+ If the <rect id="rect"> gets changed dynamically (attribute/property/style change) the <feImage>
+ doesn't notice this, as there's no link between the <rect> and the <feImage>, as the <rect> is not
+ a child of the <feImage/>. To get invalidations working for these situations, we have to track
+ the referencingElement & referencedElement in SVGDocumentExtensions.
+
+ Fixes parts the SVG-Wow twirl testcase and David Daileys SVG waves example.
+
+ Tests: svg/filters/feImage-animated-transform-on-target-rect.svg
+ svg/filters/feImage-late-indirect-update.svg
+ svg/filters/feImage-mutliple-targets-id-change.svg
+ svg/filters/feImage-target-attribute-change-with-use-indirection-2.svg
+ svg/filters/feImage-target-attribute-change-with-use-indirection.svg
+ svg/filters/feImage-target-attribute-change.svg
+ svg/filters/feImage-target-inline-style-change.svg
+ svg/filters/feImage-target-property-change.svg
+ svg/filters/feImage-target-style-change.svg
+
+ * rendering/svg/RenderSVGResource.cpp:
+ (WebCore::removeFromFilterCacheAndInvalidateDependencies): Renamed from removeFromFilterCache, as it has another purpose now.
+ (WebCore::RenderSVGResource::markForLayoutAndParentResourceInvalidation): s/removeFromFilterCache/removeFromFilterCacheAndInvalidateDependencies/.
+ * rendering/svg/RenderSVGResource.h: Removed removeFromFilterCache, it got inlined.
+ * svg/SVGDocumentExtensions.cpp: Add a new HashMap<SVGElement*, OwnPtr<HashSet<SVGElement*> > > used for dependency tracking.
+ (WebCore::SVGDocumentExtensions::setOfElementsReferencingTarget): Returns all elements the passed in element depends on.
+ (WebCore::SVGDocumentExtensions::addElementReferencingTarget): Register element 'a' referencing target 'b'.
+ (WebCore::SVGDocumentExtensions::removeAllTargetReferencesForElement): Called by element 'a' on destruction or any target change.
+ (WebCore::SVGDocumentExtensions::removeAllElementReferencesForTarget): Called by element 'b' on destruction.
+ * svg/SVGDocumentExtensions.h: Expose new methods.
+ * svg/SVGElement.cpp:
+ (WebCore::SVGElement::~SVGElement): Call remove removeAllElementReferencesForTarget on destruction.
+ * svg/SVGFEImageElement.cpp:
+ (WebCore::SVGFEImageElement::clearResourceReferences):
+ (WebCore::SVGFEImageElement::buildPendingResource):
+
2012-02-08 Kihong Kwon <kihong.kwon@samsung.com>
[EFL] Using string method instead of char* operation in the platformLanguage().
return s_sharedSolidPaintingResource;
}
-void RenderSVGResource::removeFromFilterCache(RenderObject* object)
+static inline void removeFromFilterCacheAndInvalidateDependencies(RenderObject* object, bool needsLayout)
{
-#if ENABLE(FILTERS)
ASSERT(object);
-
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
- if (!resources)
+#if ENABLE(FILTERS)
+ if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) {
+ if (RenderSVGResourceFilter* filter = resources->filter())
+ filter->removeClientFromCache(object);
+ }
+#endif
+ if (!object->node() || !object->node()->isSVGElement())
return;
-
- RenderSVGResourceFilter* filter = resources->filter();
- if (!filter)
+ HashSet<SVGElement*>* dependencies = object->document()->accessSVGExtensions()->setOfElementsReferencingTarget(static_cast<SVGElement*>(object->node()));
+ if (!dependencies)
return;
-
- filter->removeClientFromCache(object);
-#else
- UNUSED_PARAM(object);
-#endif
+ HashSet<SVGElement*>::iterator end = dependencies->end();
+ for (HashSet<SVGElement*>::iterator it = dependencies->begin(); it != end; ++it) {
+ if (RenderObject* renderer = (*it)->renderer())
+ RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, needsLayout);
+ }
}
void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject* object, bool needsLayout)
{
ASSERT(object);
+ ASSERT(object->document());
+ ASSERT(object->node());
+
if (needsLayout)
object->setNeedsLayout(true);
- removeFromFilterCache(object);
+ removeFromFilterCacheAndInvalidateDependencies(object, needsLayout);
// Invalidate resources in ancestor chain, if needed.
RenderObject* current = object->parent();
while (current) {
- removeFromFilterCache(current);
+ removeFromFilterCacheAndInvalidateDependencies(current, needsLayout);
if (current->isSVGResourceContainer()) {
// This will process the rest of the ancestors.
static RenderSVGResourceSolidColor* sharedSolidPaintingResource();
static void markForLayoutAndParentResourceInvalidation(RenderObject*, bool needsLayout = true);
-
-private:
- static void removeFromFilterCache(RenderObject*);
};
}
#include "SVGSMILElement.h"
#include "SVGSVGElement.h"
#include "ScriptableDocumentParser.h"
+#include "XLinkNames.h"
#include <wtf/text/AtomicString.h>
namespace WebCore {
element->clearHasPendingResourcesIfPossible();
// We use the removePendingResource function here because it deals with set lifetime correctly.
- Vector<AtomicString>::iterator endVector = toBeRemoved.end();
- for (Vector<AtomicString>::iterator it = toBeRemoved.begin(); it != endVector; ++it)
+ Vector<AtomicString>::iterator vectorEnd = toBeRemoved.end();
+ for (Vector<AtomicString>::iterator it = toBeRemoved.begin(); it != vectorEnd; ++it)
removePendingResource(*it);
}
element->clearHasPendingResourcesIfPossible();
}
+HashSet<SVGElement*>* SVGDocumentExtensions::setOfElementsReferencingTarget(SVGElement* referencedElement) const
+{
+ ASSERT(referencedElement);
+ const HashMap<SVGElement*, OwnPtr<HashSet<SVGElement*> > >::const_iterator it = m_elementDependencies.find(referencedElement);
+ if (it == m_elementDependencies.end())
+ return 0;
+ return it->second.get();
+}
+
+void SVGDocumentExtensions::addElementReferencingTarget(SVGElement* referencingElement, SVGElement* referencedElement)
+{
+ ASSERT(referencingElement);
+ ASSERT(referencedElement);
+
+ if (HashSet<SVGElement*>* elements = m_elementDependencies.get(referencedElement)) {
+ elements->add(referencingElement);
+ return;
+ }
+
+ OwnPtr<HashSet<SVGElement*> > elements = adoptPtr(new HashSet<SVGElement*>);
+ elements->add(referencingElement);
+ m_elementDependencies.set(referencedElement, elements.release());
+}
+
+void SVGDocumentExtensions::removeAllTargetReferencesForElement(SVGElement* referencingElement)
+{
+ Vector<SVGElement*> toBeRemoved;
+
+ HashMap<SVGElement*, OwnPtr<HashSet<SVGElement*> > >::iterator end = m_elementDependencies.end();
+ for (HashMap<SVGElement*, OwnPtr<HashSet<SVGElement*> > >::iterator it = m_elementDependencies.begin(); it != end; ++it) {
+ SVGElement* referencedElement = it->first;
+ HashSet<SVGElement*>* referencingElements = it->second.get();
+ HashSet<SVGElement*>::iterator setIt = referencingElements->find(referencingElement);
+ if (setIt == referencingElements->end())
+ continue;
+
+ referencingElements->remove(setIt);
+ if (referencingElements->isEmpty())
+ toBeRemoved.append(referencedElement);
+ }
+
+ Vector<SVGElement*>::iterator vectorEnd = toBeRemoved.end();
+ for (Vector<SVGElement*>::iterator it = toBeRemoved.begin(); it != vectorEnd; ++it)
+ m_elementDependencies.remove(*it);
+}
+
+void SVGDocumentExtensions::removeAllElementReferencesForTarget(SVGElement* referencedElement)
+{
+ ASSERT(referencedElement);
+ HashMap<SVGElement*, OwnPtr<HashSet<SVGElement*> > >::iterator it = m_elementDependencies.find(referencedElement);
+ if (it == m_elementDependencies.end())
+ return;
+ ASSERT(it->first == referencedElement);
+ Vector<SVGElement*> toBeNotified;
+
+ HashSet<SVGElement*>* referencingElements = it->second.get();
+ HashSet<SVGElement*>::iterator setEnd = referencingElements->end();
+ for (HashSet<SVGElement*>::iterator setIt = referencingElements->begin(); setIt != setEnd; ++setIt)
+ toBeNotified.append(*setIt);
+
+ m_elementDependencies.remove(it);
+
+ // Force rebuilding the referencingElement so it knows about this change.
+ Vector<SVGElement*>::iterator vectorEnd = toBeNotified.end();
+ for (Vector<SVGElement*>::iterator vectorIt = toBeNotified.begin(); vectorIt != vectorEnd; ++vectorIt)
+ (*vectorIt)->svgAttributeChanged(XLinkNames::hrefAttr);
+}
+
}
#endif
SVGResourcesCache* resourcesCache() const { return m_resourcesCache.get(); }
+ HashSet<SVGElement*>* setOfElementsReferencingTarget(SVGElement* referencedElement) const;
+ void addElementReferencingTarget(SVGElement* referencingElement, SVGElement* referencedElement);
+ void removeAllTargetReferencesForElement(SVGElement* referencingElement);
+ void removeAllElementReferencesForTarget(SVGElement* referencedElement);
+
private:
Document* m_document; // weak reference
HashSet<SVGSVGElement*> m_timeContainers; // For SVG 1.2 support this will need to be made more general.
HashMap<SVGElement*, HashSet<SVGSMILElement*>* > m_animatedElements;
HashMap<AtomicString, RenderSVGResourceContainer*> m_resources;
HashMap<AtomicString, SVGPendingElements*> m_pendingResources;
+ HashMap<SVGElement*, OwnPtr<HashSet<SVGElement*> > > m_elementDependencies;
OwnPtr<SVGResourcesCache> m_resourcesCache;
public:
rareDataMap.remove(it);
}
document()->accessSVGExtensions()->removeAllAnimationElementsFromTarget(this);
+ document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this);
}
SVGElementRareData* SVGElement::rareSVGData() const
void SVGElement::removedFromDocument()
{
document()->accessSVGExtensions()->removeAllAnimationElementsFromTarget(this);
+ document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this);
StyledElement::removedFromDocument();
}
if (isSynchronizingSVGAttributes())
return;
- if (isIdAttributeName(attr->name()))
+ if (isIdAttributeName(attr->name())) {
document()->accessSVGExtensions()->removeAllAnimationElementsFromTarget(this);
+ document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this);
+ }
// Changes to the style attribute are processed lazily (see Element::getAttribute() and related methods),
// so we don't want changes to the style attribute to result in extra work here.
m_cachedImage->removeClient(this);
m_cachedImage = 0;
}
+
+ ASSERT(document());
+ document()->accessSVGExtensions()->removeAllTargetReferencesForElement(this);
}
void SVGFEImageElement::requestImageResource()
document()->accessSVGExtensions()->addPendingResource(id, this);
ASSERT(hasPendingResources());
}
+ } else if (target->isSVGElement()) {
+ // Register us with the target in the dependencies map. Any change of hrefElement
+ // that leads to relayout/repainting now informs us, so we can react to it.
+ document()->accessSVGExtensions()->addElementReferencingTarget(this, static_cast<SVGElement*>(target));
}
invalidate();