initial import
[vuplus_webkit] / Source / WebCore / rendering / svg / SVGResources.cpp
1 /*
2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "SVGResources.h"
22
23 #if ENABLE(SVG)
24 #include "RenderSVGResourceClipper.h"
25 #include "RenderSVGResourceFilter.h"
26 #include "RenderSVGResourceMarker.h"
27 #include "RenderSVGResourceMasker.h"
28 #include "SVGFilterElement.h"
29 #include "SVGGradientElement.h"
30 #include "SVGNames.h"
31 #include "SVGPaint.h"
32 #include "SVGPatternElement.h"
33 #include "SVGRenderStyle.h"
34 #include "SVGURIReference.h"
35
36 #ifndef NDEBUG
37 #include <stdio.h>
38 #endif
39
40 namespace WebCore {
41
42 SVGResources::SVGResources()
43     : m_linkedResource(0)
44 {
45 }
46
47 static HashSet<AtomicStringImpl*>& clipperFilterMaskerTags()
48 {
49     DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ());
50     if (s_tagList.isEmpty()) {
51         // "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement
52         // "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement
53         s_tagList.add(SVGNames::aTag.localName().impl());
54         s_tagList.add(SVGNames::circleTag.localName().impl());
55         s_tagList.add(SVGNames::ellipseTag.localName().impl());
56         s_tagList.add(SVGNames::glyphTag.localName().impl());
57         s_tagList.add(SVGNames::gTag.localName().impl());
58         s_tagList.add(SVGNames::imageTag.localName().impl());
59         s_tagList.add(SVGNames::lineTag.localName().impl());
60         s_tagList.add(SVGNames::markerTag.localName().impl());
61         s_tagList.add(SVGNames::maskTag.localName().impl());
62         s_tagList.add(SVGNames::missing_glyphTag.localName().impl());
63         s_tagList.add(SVGNames::pathTag.localName().impl());
64         s_tagList.add(SVGNames::polygonTag.localName().impl());
65         s_tagList.add(SVGNames::polylineTag.localName().impl());
66         s_tagList.add(SVGNames::rectTag.localName().impl());
67         s_tagList.add(SVGNames::svgTag.localName().impl());
68         s_tagList.add(SVGNames::textTag.localName().impl());
69         s_tagList.add(SVGNames::useTag.localName().impl());
70
71         // Not listed in the definitions is the clipPath element, the SVG spec says though:
72         // The "clipPath" element or any of its children can specify property "clip-path".
73         // So we have to add clipPathTag here, otherwhise clip-path on clipPath will fail.
74         // (Already mailed SVG WG, waiting for a solution)
75         s_tagList.add(SVGNames::clipPathTag.localName().impl());
76
77         // Not listed in the definitions are the text content elements, though filter/clipper/masker on tspan/text/.. is allowed.
78         // (Already mailed SVG WG, waiting for a solution)
79         s_tagList.add(SVGNames::altGlyphTag.localName().impl());
80         s_tagList.add(SVGNames::textPathTag.localName().impl());
81         s_tagList.add(SVGNames::trefTag.localName().impl());
82         s_tagList.add(SVGNames::tspanTag.localName().impl());
83
84         // Elements that we ignore, as it doesn't make any sense.
85         // defs, pattern, switch (FIXME: Mail SVG WG about these)
86         // symbol (is converted to a svg element, when referenced by use, we can safely ignore it.)
87     }
88
89     return s_tagList;
90 }
91
92 static HashSet<AtomicStringImpl*>& markerTags()
93 {
94     DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ());
95     if (s_tagList.isEmpty()) {
96         s_tagList.add(SVGNames::lineTag.localName().impl());
97         s_tagList.add(SVGNames::pathTag.localName().impl());
98         s_tagList.add(SVGNames::polygonTag.localName().impl());
99         s_tagList.add(SVGNames::polylineTag.localName().impl());
100     }
101
102     return s_tagList;
103 }
104
105 static HashSet<AtomicStringImpl*>& fillAndStrokeTags()
106 {
107     DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ());
108     if (s_tagList.isEmpty()) {
109         s_tagList.add(SVGNames::altGlyphTag.localName().impl());
110         s_tagList.add(SVGNames::circleTag.localName().impl());
111         s_tagList.add(SVGNames::ellipseTag.localName().impl());
112         s_tagList.add(SVGNames::lineTag.localName().impl());
113         s_tagList.add(SVGNames::pathTag.localName().impl());
114         s_tagList.add(SVGNames::polygonTag.localName().impl());
115         s_tagList.add(SVGNames::polylineTag.localName().impl());
116         s_tagList.add(SVGNames::rectTag.localName().impl());
117         s_tagList.add(SVGNames::textTag.localName().impl());
118         s_tagList.add(SVGNames::textPathTag.localName().impl());
119         s_tagList.add(SVGNames::trefTag.localName().impl());
120         s_tagList.add(SVGNames::tspanTag.localName().impl());
121     }
122
123     return s_tagList;
124 }
125
126 static HashSet<AtomicStringImpl*>& chainableResourceTags()
127 {
128     DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, s_tagList, ());
129     if (s_tagList.isEmpty()) {
130         s_tagList.add(SVGNames::linearGradientTag.localName().impl());
131         s_tagList.add(SVGNames::filterTag.localName().impl());
132         s_tagList.add(SVGNames::patternTag.localName().impl());
133         s_tagList.add(SVGNames::radialGradientTag.localName().impl());
134     }
135
136     return s_tagList;
137 }
138
139 static inline String targetReferenceFromResource(SVGElement* element)
140 {
141     String target;
142     if (element->hasTagName(SVGNames::patternTag))
143         target = static_cast<SVGPatternElement*>(element)->href();
144     else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
145         target = static_cast<SVGGradientElement*>(element)->href();
146 #if ENABLE(FILTERS)
147     else if (element->hasTagName(SVGNames::filterTag))
148         target = static_cast<SVGFilterElement*>(element)->href();
149 #endif
150     else
151         ASSERT_NOT_REACHED();
152
153     return SVGURIReference::fragmentIdentifierFromIRIString(target, element->document());
154 }
155
156 static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document* document, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
157 {
158     if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)
159         return 0;
160
161     id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, document);
162     RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id);
163     if (!container) {
164         hasPendingResource = true;
165         return 0;
166     }
167
168     RenderSVGResourceType resourceType = container->resourceType();
169     if (resourceType != PatternResourceType && resourceType != LinearGradientResourceType && resourceType != RadialGradientResourceType)
170         return 0;
171
172     return container;
173 }
174
175 static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement* element)
176 {
177     ASSERT(element);
178     ASSERT(element->isStyled());
179     extensions->addPendingResource(id, static_cast<SVGStyledElement*>(element));
180 }
181
182 bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRenderStyle* style)
183 {
184     ASSERT(object);
185     ASSERT(style);
186
187     Node* node = object->node();
188     ASSERT(node);
189     ASSERT(node->isSVGElement());
190
191     SVGElement* element = static_cast<SVGElement*>(node);
192     if (!element)
193         return false;
194
195     Document* document = object->document();
196     ASSERT(document);
197
198     SVGDocumentExtensions* extensions = document->accessSVGExtensions();
199     ASSERT(extensions);
200
201     AtomicStringImpl* tagNameImpl = element->tagQName().localName().impl();
202     if (!tagNameImpl)
203         return false;
204
205     bool foundResources = false;
206     if (clipperFilterMaskerTags().contains(tagNameImpl)) {
207         if (style->hasClipper()) {
208             AtomicString id(style->clipperResource());
209             if (setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(document, id)))
210                 foundResources = true;
211             else
212                 registerPendingResource(extensions, id, element);
213         }
214
215 #if ENABLE(FILTERS)
216         if (style->hasFilter()) {
217             AtomicString id(style->filterResource());
218             if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id)))
219                 foundResources = true;
220             else
221                 registerPendingResource(extensions, id, element);
222         }
223 #endif
224
225         if (style->hasMasker()) {
226             AtomicString id(style->maskerResource());
227             if (setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(document, id)))
228                 foundResources = true;
229             else
230                 registerPendingResource(extensions, id, element);
231         }
232     }
233
234     if (markerTags().contains(tagNameImpl) && style->hasMarkers()) {
235         AtomicString markerStartId(style->markerStartResource());
236         if (setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId)))
237             foundResources = true;
238         else
239             registerPendingResource(extensions, markerStartId, element);
240
241         AtomicString markerMidId(style->markerMidResource());
242         if (setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId)))
243             foundResources = true;
244         else
245             registerPendingResource(extensions, markerMidId, element);
246
247         AtomicString markerEndId(style->markerEndResource());
248         if (setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId)))
249             foundResources = true;
250         else
251             registerPendingResource(extensions, markerEndId, element);
252     }
253
254     if (fillAndStrokeTags().contains(tagNameImpl)) {
255         if (style->hasFill()) {
256             bool hasPendingResource = false;
257             AtomicString id;
258             if (setFill(paintingResourceFromSVGPaint(document, style->fillPaintType(), style->fillPaintUri(), id, hasPendingResource)))
259                 foundResources = true;
260             else if (hasPendingResource)
261                 registerPendingResource(extensions, id, element);
262         }
263
264         if (style->hasStroke()) {
265             bool hasPendingResource = false;
266             AtomicString id;
267             if (setStroke(paintingResourceFromSVGPaint(document, style->strokePaintType(), style->strokePaintUri(), id, hasPendingResource)))
268                 foundResources = true;
269             else if (hasPendingResource)
270                 registerPendingResource(extensions, id, element);
271         }
272     }
273
274     if (chainableResourceTags().contains(tagNameImpl)) {
275         AtomicString id(targetReferenceFromResource(element));
276         if (setLinkedResource(getRenderSVGResourceContainerById(document, id)))
277             foundResources = true;
278         else
279             registerPendingResource(extensions, id, element);
280     }
281
282     return foundResources;
283 }
284
285 void SVGResources::removeClientFromCache(RenderObject* object, bool markForInvalidation) const
286 {
287     if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
288         return;
289
290     if (m_linkedResource) {
291         ASSERT(!m_clipperFilterMaskerData);
292         ASSERT(!m_markerData);
293         ASSERT(!m_fillStrokeData);
294         m_linkedResource->removeClientFromCache(object, markForInvalidation);
295         return;
296     }
297
298     if (m_clipperFilterMaskerData) {
299         if (m_clipperFilterMaskerData->clipper)
300             m_clipperFilterMaskerData->clipper->removeClientFromCache(object, markForInvalidation);
301 #if ENABLE(FILTERS)
302         if (m_clipperFilterMaskerData->filter)
303             m_clipperFilterMaskerData->filter->removeClientFromCache(object, markForInvalidation);
304 #endif
305         if (m_clipperFilterMaskerData->masker)
306             m_clipperFilterMaskerData->masker->removeClientFromCache(object, markForInvalidation);
307     }
308
309     if (m_markerData) {
310         if (m_markerData->markerStart)
311             m_markerData->markerStart->removeClientFromCache(object, markForInvalidation);
312         if (m_markerData->markerMid)
313             m_markerData->markerMid->removeClientFromCache(object, markForInvalidation);
314         if (m_markerData->markerEnd)
315             m_markerData->markerEnd->removeClientFromCache(object, markForInvalidation);
316     }
317
318     if (m_fillStrokeData) {
319         if (m_fillStrokeData->fill)
320             m_fillStrokeData->fill->removeClientFromCache(object, markForInvalidation);
321         if (m_fillStrokeData->stroke)
322             m_fillStrokeData->stroke->removeClientFromCache(object, markForInvalidation);
323     }
324 }
325
326 void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource)
327 {
328     ASSERT(resource);
329     if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
330         return;
331
332     if (m_linkedResource == resource) {
333         ASSERT(!m_clipperFilterMaskerData);
334         ASSERT(!m_markerData);
335         ASSERT(!m_fillStrokeData);
336         m_linkedResource->removeAllClientsFromCache();
337         m_linkedResource = 0;
338         return;
339     }
340
341     switch (resource->resourceType()) {
342     case MaskerResourceType:
343         if (!m_clipperFilterMaskerData)
344             break;
345         if (m_clipperFilterMaskerData->masker == resource) {
346             m_clipperFilterMaskerData->masker->removeAllClientsFromCache();
347             m_clipperFilterMaskerData->masker = 0;
348         }
349         break;
350     case MarkerResourceType:
351         if (!m_markerData)
352             break;
353         if (m_markerData->markerStart == resource) {
354             m_markerData->markerStart->removeAllClientsFromCache();
355             m_markerData->markerStart = 0;
356         }
357         if (m_markerData->markerMid == resource) {
358             m_markerData->markerMid->removeAllClientsFromCache();
359             m_markerData->markerMid = 0;
360         }
361         if (m_markerData->markerEnd == resource) {
362             m_markerData->markerEnd->removeAllClientsFromCache();
363             m_markerData->markerEnd = 0;
364         }
365         break;
366     case PatternResourceType:
367     case LinearGradientResourceType:
368     case RadialGradientResourceType:
369         if (!m_fillStrokeData)
370             break;
371         if (m_fillStrokeData->fill == resource) {
372             m_fillStrokeData->fill->removeAllClientsFromCache();
373             m_fillStrokeData->fill = 0;
374         }
375         if (m_fillStrokeData->stroke == resource) {
376             m_fillStrokeData->stroke->removeAllClientsFromCache();
377             m_fillStrokeData->stroke = 0;
378         }
379         break;
380     case FilterResourceType:
381 #if ENABLE(FILTERS)
382         if (!m_clipperFilterMaskerData)
383             break;
384         if (m_clipperFilterMaskerData->filter == resource) {
385             m_clipperFilterMaskerData->filter->removeAllClientsFromCache();
386             m_clipperFilterMaskerData->filter = 0;
387         }
388 #else
389         ASSERT_NOT_REACHED();
390 #endif
391         break;
392     case ClipperResourceType:
393         if (!m_clipperFilterMaskerData)
394             break; 
395         if (m_clipperFilterMaskerData->clipper == resource) {
396             m_clipperFilterMaskerData->clipper->removeAllClientsFromCache();
397             m_clipperFilterMaskerData->clipper = 0;
398         }
399         break;
400     case SolidColorResourceType:
401         ASSERT_NOT_REACHED();
402     }
403 }
404
405 void SVGResources::buildSetOfResources(HashSet<RenderSVGResourceContainer*>& set)
406 {
407     if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
408         return;
409
410     if (m_linkedResource) {
411         ASSERT(!m_clipperFilterMaskerData);
412         ASSERT(!m_markerData);
413         ASSERT(!m_fillStrokeData);
414         set.add(m_linkedResource);
415         return;
416     }
417
418     if (m_clipperFilterMaskerData) {
419         if (m_clipperFilterMaskerData->clipper)
420             set.add(m_clipperFilterMaskerData->clipper);
421 #if ENABLE(FILTERS)
422         if (m_clipperFilterMaskerData->filter)
423             set.add(m_clipperFilterMaskerData->filter);
424 #endif
425         if (m_clipperFilterMaskerData->masker)
426             set.add(m_clipperFilterMaskerData->masker);
427     }
428
429     if (m_markerData) {
430         if (m_markerData->markerStart)
431             set.add(m_markerData->markerStart);
432         if (m_markerData->markerMid)
433             set.add(m_markerData->markerMid);
434         if (m_markerData->markerEnd)
435             set.add(m_markerData->markerEnd);
436     }
437
438     if (m_fillStrokeData) {
439         if (m_fillStrokeData->fill)
440             set.add(m_fillStrokeData->fill);
441         if (m_fillStrokeData->stroke)
442             set.add(m_fillStrokeData->stroke);
443     }
444 }
445
446 bool SVGResources::setClipper(RenderSVGResourceClipper* clipper)
447 {
448     if (!clipper)
449         return false;
450
451     ASSERT(clipper->resourceType() == ClipperResourceType);
452
453     if (!m_clipperFilterMaskerData)
454         m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
455
456     m_clipperFilterMaskerData->clipper = clipper;
457     return true;
458 }
459
460 void SVGResources::resetClipper()
461 {
462     ASSERT(m_clipperFilterMaskerData);
463     ASSERT(m_clipperFilterMaskerData->clipper);
464     m_clipperFilterMaskerData->clipper = 0;
465 }
466
467 #if ENABLE(FILTERS)
468 bool SVGResources::setFilter(RenderSVGResourceFilter* filter)
469 {
470     if (!filter)
471         return false;
472
473     ASSERT(filter->resourceType() == FilterResourceType);
474
475     if (!m_clipperFilterMaskerData)
476         m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
477
478     m_clipperFilterMaskerData->filter = filter;
479     return true;
480 }
481
482 void SVGResources::resetFilter()
483 {
484     ASSERT(m_clipperFilterMaskerData);
485     ASSERT(m_clipperFilterMaskerData->filter);
486     m_clipperFilterMaskerData->filter = 0;
487 }
488 #endif
489
490 bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart)
491 {
492     if (!markerStart)
493         return false;
494
495     ASSERT(markerStart->resourceType() == MarkerResourceType);
496
497     if (!m_markerData)
498         m_markerData = MarkerData::create();
499
500     m_markerData->markerStart = markerStart;
501     return true;
502 }
503
504 void SVGResources::resetMarkerStart()
505 {
506     ASSERT(m_markerData);
507     ASSERT(m_markerData->markerStart);
508     m_markerData->markerStart = 0;
509 }
510
511 bool SVGResources::setMarkerMid(RenderSVGResourceMarker* markerMid)
512 {
513     if (!markerMid)
514         return false;
515
516     ASSERT(markerMid->resourceType() == MarkerResourceType);
517
518     if (!m_markerData)
519         m_markerData = MarkerData::create();
520
521     m_markerData->markerMid = markerMid;
522     return true;
523 }
524
525 void SVGResources::resetMarkerMid()
526 {
527     ASSERT(m_markerData);
528     ASSERT(m_markerData->markerMid);
529     m_markerData->markerMid = 0;
530 }
531
532 bool SVGResources::setMarkerEnd(RenderSVGResourceMarker* markerEnd)
533 {
534     if (!markerEnd)
535         return false;
536
537     ASSERT(markerEnd->resourceType() == MarkerResourceType);
538
539     if (!m_markerData)
540         m_markerData = MarkerData::create();
541
542     m_markerData->markerEnd = markerEnd;
543     return true;
544 }
545
546 void SVGResources::resetMarkerEnd()
547 {
548     ASSERT(m_markerData);
549     ASSERT(m_markerData->markerEnd);
550     m_markerData->markerEnd = 0;
551 }
552
553 bool SVGResources::setMasker(RenderSVGResourceMasker* masker)
554 {
555     if (!masker)
556         return false;
557
558     ASSERT(masker->resourceType() == MaskerResourceType);
559
560     if (!m_clipperFilterMaskerData)
561         m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
562
563     m_clipperFilterMaskerData->masker = masker;
564     return true;
565 }
566
567 void SVGResources::resetMasker()
568 {
569     ASSERT(m_clipperFilterMaskerData);
570     ASSERT(m_clipperFilterMaskerData->masker);
571     m_clipperFilterMaskerData->masker = 0;
572 }
573
574 bool SVGResources::setFill(RenderSVGResourceContainer* fill)
575 {
576     if (!fill)
577         return false;
578
579     ASSERT(fill->resourceType() == PatternResourceType
580            || fill->resourceType() == LinearGradientResourceType
581            || fill->resourceType() == RadialGradientResourceType);
582
583     if (!m_fillStrokeData)
584         m_fillStrokeData = FillStrokeData::create();
585
586     m_fillStrokeData->fill = fill;
587     return true;
588 }
589
590 void SVGResources::resetFill()
591 {
592     ASSERT(m_fillStrokeData);
593     ASSERT(m_fillStrokeData->fill);
594     m_fillStrokeData->fill = 0;
595 }
596
597 bool SVGResources::setStroke(RenderSVGResourceContainer* stroke)
598 {
599     if (!stroke)
600         return false;
601
602     ASSERT(stroke->resourceType() == PatternResourceType
603            || stroke->resourceType() == LinearGradientResourceType
604            || stroke->resourceType() == RadialGradientResourceType);
605
606     if (!m_fillStrokeData)
607         m_fillStrokeData = FillStrokeData::create();
608
609     m_fillStrokeData->stroke = stroke;
610     return true;
611 }
612
613 void SVGResources::resetStroke()
614 {
615     ASSERT(m_fillStrokeData);
616     ASSERT(m_fillStrokeData->stroke);
617     m_fillStrokeData->stroke = 0;
618 }
619
620 bool SVGResources::setLinkedResource(RenderSVGResourceContainer* linkedResource)
621 {
622     if (!linkedResource)
623         return false;
624
625     m_linkedResource = linkedResource;
626     return true;
627 }
628
629 void SVGResources::resetLinkedResource()
630 {
631     ASSERT(m_linkedResource);
632     m_linkedResource = 0;
633 }
634
635 #ifndef NDEBUG
636 void SVGResources::dump(const RenderObject* object)
637 {
638     ASSERT(object);
639     ASSERT(object->node());
640
641     fprintf(stderr, "-> this=%p, SVGResources(renderer=%p, node=%p)\n", this, object, object->node());
642     fprintf(stderr, " | DOM Tree:\n");
643     object->node()->showTreeForThis();
644
645     fprintf(stderr, "\n | List of resources:\n");
646     if (m_clipperFilterMaskerData) {
647         if (RenderSVGResourceClipper* clipper = m_clipperFilterMaskerData->clipper)
648             fprintf(stderr, " |-> Clipper    : %p (node=%p)\n", clipper, clipper->node());
649 #if ENABLE(FILTERS)
650         if (RenderSVGResourceFilter* filter = m_clipperFilterMaskerData->filter)
651             fprintf(stderr, " |-> Filter     : %p (node=%p)\n", filter, filter->node());
652 #endif
653         if (RenderSVGResourceMasker* masker = m_clipperFilterMaskerData->masker)
654             fprintf(stderr, " |-> Masker     : %p (node=%p)\n", masker, masker->node());
655     }
656
657     if (m_markerData) {
658         if (RenderSVGResourceMarker* markerStart = m_markerData->markerStart)
659             fprintf(stderr, " |-> MarkerStart: %p (node=%p)\n", markerStart, markerStart->node());
660         if (RenderSVGResourceMarker* markerMid = m_markerData->markerMid)
661             fprintf(stderr, " |-> MarkerMid  : %p (node=%p)\n", markerMid, markerMid->node());
662         if (RenderSVGResourceMarker* markerEnd = m_markerData->markerEnd)
663             fprintf(stderr, " |-> MarkerEnd  : %p (node=%p)\n", markerEnd, markerEnd->node());
664     }
665
666     if (m_fillStrokeData) {
667         if (RenderSVGResourceContainer* fill = m_fillStrokeData->fill)
668             fprintf(stderr, " |-> Fill       : %p (node=%p)\n", fill, fill->node());
669         if (RenderSVGResourceContainer* stroke = m_fillStrokeData->stroke)
670             fprintf(stderr, " |-> Stroke     : %p (node=%p)\n", stroke, stroke->node());
671     }
672
673     if (m_linkedResource)
674         fprintf(stderr, " |-> xlink:href : %p (node=%p)\n", m_linkedResource, m_linkedResource->node());
675 }
676 #endif
677
678 }
679
680 #endif