CTTE: More Document references please
[WebKit-https.git] / 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<AtomicString>& clipperFilterMaskerTags()
48 {
49     DEFINE_STATIC_LOCAL(HashSet<AtomicString>, 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());
54         s_tagList.add(SVGNames::circleTag.localName());
55         s_tagList.add(SVGNames::ellipseTag.localName());
56         s_tagList.add(SVGNames::glyphTag.localName());
57         s_tagList.add(SVGNames::gTag.localName());
58         s_tagList.add(SVGNames::imageTag.localName());
59         s_tagList.add(SVGNames::lineTag.localName());
60         s_tagList.add(SVGNames::markerTag.localName());
61         s_tagList.add(SVGNames::maskTag.localName());
62         s_tagList.add(SVGNames::missing_glyphTag.localName());
63         s_tagList.add(SVGNames::pathTag.localName());
64         s_tagList.add(SVGNames::polygonTag.localName());
65         s_tagList.add(SVGNames::polylineTag.localName());
66         s_tagList.add(SVGNames::rectTag.localName());
67         s_tagList.add(SVGNames::svgTag.localName());
68         s_tagList.add(SVGNames::textTag.localName());
69         s_tagList.add(SVGNames::useTag.localName());
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());
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());
80         s_tagList.add(SVGNames::textPathTag.localName());
81         s_tagList.add(SVGNames::trefTag.localName());
82         s_tagList.add(SVGNames::tspanTag.localName());
83
84         // Not listed in the definitions is the foreignObject element, but clip-path
85         // is a supported attribute.
86         s_tagList.add(SVGNames::foreignObjectTag.localName());
87
88         // Elements that we ignore, as it doesn't make any sense.
89         // defs, pattern, switch (FIXME: Mail SVG WG about these)
90         // symbol (is converted to a svg element, when referenced by use, we can safely ignore it.)
91     }
92
93     return s_tagList;
94 }
95
96 static HashSet<AtomicString>& markerTags()
97 {
98     DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
99     if (s_tagList.isEmpty()) {
100         s_tagList.add(SVGNames::lineTag.localName());
101         s_tagList.add(SVGNames::pathTag.localName());
102         s_tagList.add(SVGNames::polygonTag.localName());
103         s_tagList.add(SVGNames::polylineTag.localName());
104     }
105
106     return s_tagList;
107 }
108
109 static HashSet<AtomicString>& fillAndStrokeTags()
110 {
111     DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
112     if (s_tagList.isEmpty()) {
113         s_tagList.add(SVGNames::altGlyphTag.localName());
114         s_tagList.add(SVGNames::circleTag.localName());
115         s_tagList.add(SVGNames::ellipseTag.localName());
116         s_tagList.add(SVGNames::lineTag.localName());
117         s_tagList.add(SVGNames::pathTag.localName());
118         s_tagList.add(SVGNames::polygonTag.localName());
119         s_tagList.add(SVGNames::polylineTag.localName());
120         s_tagList.add(SVGNames::rectTag.localName());
121         s_tagList.add(SVGNames::textTag.localName());
122         s_tagList.add(SVGNames::textPathTag.localName());
123         s_tagList.add(SVGNames::trefTag.localName());
124         s_tagList.add(SVGNames::tspanTag.localName());
125     }
126
127     return s_tagList;
128 }
129
130 static HashSet<AtomicString>& chainableResourceTags()
131 {
132     DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
133     if (s_tagList.isEmpty()) {
134         s_tagList.add(SVGNames::linearGradientTag.localName());
135         s_tagList.add(SVGNames::filterTag.localName());
136         s_tagList.add(SVGNames::patternTag.localName());
137         s_tagList.add(SVGNames::radialGradientTag.localName());
138     }
139
140     return s_tagList;
141 }
142
143 static inline String targetReferenceFromResource(SVGElement* element)
144 {
145     String target;
146     if (element->hasTagName(SVGNames::patternTag))
147         target = toSVGPatternElement(element)->href();
148     else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
149         target = toSVGGradientElement(element)->href();
150 #if ENABLE(FILTERS)
151     else if (element->hasTagName(SVGNames::filterTag))
152         target = toSVGFilterElement(element)->href();
153 #endif
154     else
155         ASSERT_NOT_REACHED();
156
157     return SVGURIReference::fragmentIdentifierFromIRIString(target, element->document());
158 }
159
160 static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& document, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
161 {
162     if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)
163         return 0;
164
165     id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, document);
166     RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id);
167     if (!container) {
168         hasPendingResource = true;
169         return 0;
170     }
171
172     RenderSVGResourceType resourceType = container->resourceType();
173     if (resourceType != PatternResourceType && resourceType != LinearGradientResourceType && resourceType != RadialGradientResourceType)
174         return 0;
175
176     return container;
177 }
178
179 static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement* element)
180 {
181     ASSERT(element);
182     extensions->addPendingResource(id, element);
183 }
184
185 bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRenderStyle* style)
186 {
187     ASSERT(object);
188     ASSERT(style);
189
190     Node* node = object->node();
191     ASSERT(node);
192     ASSERT_WITH_SECURITY_IMPLICATION(node->isSVGElement());
193
194     SVGElement* element = toSVGElement(node);
195     if (!element)
196         return false;
197
198     Document& document = object->document();
199
200     SVGDocumentExtensions* extensions = document.accessSVGExtensions();
201     ASSERT(extensions);
202
203     const AtomicString& tagName = element->localName();
204     if (tagName.isNull())
205         return false;
206
207     bool foundResources = false;
208     if (clipperFilterMaskerTags().contains(tagName)) {
209         if (style->hasClipper()) {
210             AtomicString id(style->clipperResource());
211             if (setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(document, id)))
212                 foundResources = true;
213             else
214                 registerPendingResource(extensions, id, element);
215         }
216
217 #if ENABLE(FILTERS)
218         if (style->hasFilter()) {
219             AtomicString id(style->filterResource());
220             if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id)))
221                 foundResources = true;
222             else
223                 registerPendingResource(extensions, id, element);
224         }
225 #endif
226
227         if (style->hasMasker()) {
228             AtomicString id(style->maskerResource());
229             if (setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(document, id)))
230                 foundResources = true;
231             else
232                 registerPendingResource(extensions, id, element);
233         }
234     }
235
236     if (markerTags().contains(tagName) && style->hasMarkers()) {
237         AtomicString markerStartId(style->markerStartResource());
238         if (setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId)))
239             foundResources = true;
240         else
241             registerPendingResource(extensions, markerStartId, element);
242
243         AtomicString markerMidId(style->markerMidResource());
244         if (setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId)))
245             foundResources = true;
246         else
247             registerPendingResource(extensions, markerMidId, element);
248
249         AtomicString markerEndId(style->markerEndResource());
250         if (setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId)))
251             foundResources = true;
252         else
253             registerPendingResource(extensions, markerEndId, element);
254     }
255
256     if (fillAndStrokeTags().contains(tagName)) {
257         if (style->hasFill()) {
258             bool hasPendingResource = false;
259             AtomicString id;
260             if (setFill(paintingResourceFromSVGPaint(document, style->fillPaintType(), style->fillPaintUri(), id, hasPendingResource)))
261                 foundResources = true;
262             else if (hasPendingResource)
263                 registerPendingResource(extensions, id, element);
264         }
265
266         if (style->hasStroke()) {
267             bool hasPendingResource = false;
268             AtomicString id;
269             if (setStroke(paintingResourceFromSVGPaint(document, style->strokePaintType(), style->strokePaintUri(), id, hasPendingResource)))
270                 foundResources = true;
271             else if (hasPendingResource)
272                 registerPendingResource(extensions, id, element);
273         }
274     }
275
276     if (chainableResourceTags().contains(tagName)) {
277         AtomicString id(targetReferenceFromResource(element));
278         if (setLinkedResource(getRenderSVGResourceContainerById(document, id)))
279             foundResources = true;
280         else
281             registerPendingResource(extensions, id, element);
282     }
283
284     return foundResources;
285 }
286
287 void SVGResources::removeClientFromCache(RenderObject* object, bool markForInvalidation) const
288 {
289     if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
290         return;
291
292     if (m_linkedResource) {
293         ASSERT(!m_clipperFilterMaskerData);
294         ASSERT(!m_markerData);
295         ASSERT(!m_fillStrokeData);
296         m_linkedResource->removeClientFromCache(object, markForInvalidation);
297         return;
298     }
299
300     if (m_clipperFilterMaskerData) {
301         if (m_clipperFilterMaskerData->clipper)
302             m_clipperFilterMaskerData->clipper->removeClientFromCache(object, markForInvalidation);
303 #if ENABLE(FILTERS)
304         if (m_clipperFilterMaskerData->filter)
305             m_clipperFilterMaskerData->filter->removeClientFromCache(object, markForInvalidation);
306 #endif
307         if (m_clipperFilterMaskerData->masker)
308             m_clipperFilterMaskerData->masker->removeClientFromCache(object, markForInvalidation);
309     }
310
311     if (m_markerData) {
312         if (m_markerData->markerStart)
313             m_markerData->markerStart->removeClientFromCache(object, markForInvalidation);
314         if (m_markerData->markerMid)
315             m_markerData->markerMid->removeClientFromCache(object, markForInvalidation);
316         if (m_markerData->markerEnd)
317             m_markerData->markerEnd->removeClientFromCache(object, markForInvalidation);
318     }
319
320     if (m_fillStrokeData) {
321         if (m_fillStrokeData->fill)
322             m_fillStrokeData->fill->removeClientFromCache(object, markForInvalidation);
323         if (m_fillStrokeData->stroke)
324             m_fillStrokeData->stroke->removeClientFromCache(object, markForInvalidation);
325     }
326 }
327
328 void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource)
329 {
330     ASSERT(resource);
331     if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
332         return;
333
334     if (m_linkedResource == resource) {
335         ASSERT(!m_clipperFilterMaskerData);
336         ASSERT(!m_markerData);
337         ASSERT(!m_fillStrokeData);
338         m_linkedResource->removeAllClientsFromCache();
339         m_linkedResource = 0;
340         return;
341     }
342
343     switch (resource->resourceType()) {
344     case MaskerResourceType:
345         if (!m_clipperFilterMaskerData)
346             break;
347         if (m_clipperFilterMaskerData->masker == resource) {
348             m_clipperFilterMaskerData->masker->removeAllClientsFromCache();
349             m_clipperFilterMaskerData->masker = 0;
350         }
351         break;
352     case MarkerResourceType:
353         if (!m_markerData)
354             break;
355         if (m_markerData->markerStart == resource) {
356             m_markerData->markerStart->removeAllClientsFromCache();
357             m_markerData->markerStart = 0;
358         }
359         if (m_markerData->markerMid == resource) {
360             m_markerData->markerMid->removeAllClientsFromCache();
361             m_markerData->markerMid = 0;
362         }
363         if (m_markerData->markerEnd == resource) {
364             m_markerData->markerEnd->removeAllClientsFromCache();
365             m_markerData->markerEnd = 0;
366         }
367         break;
368     case PatternResourceType:
369     case LinearGradientResourceType:
370     case RadialGradientResourceType:
371         if (!m_fillStrokeData)
372             break;
373         if (m_fillStrokeData->fill == resource) {
374             m_fillStrokeData->fill->removeAllClientsFromCache();
375             m_fillStrokeData->fill = 0;
376         }
377         if (m_fillStrokeData->stroke == resource) {
378             m_fillStrokeData->stroke->removeAllClientsFromCache();
379             m_fillStrokeData->stroke = 0;
380         }
381         break;
382     case FilterResourceType:
383 #if ENABLE(FILTERS)
384         if (!m_clipperFilterMaskerData)
385             break;
386         if (m_clipperFilterMaskerData->filter == resource) {
387             m_clipperFilterMaskerData->filter->removeAllClientsFromCache();
388             m_clipperFilterMaskerData->filter = 0;
389         }
390 #else
391         ASSERT_NOT_REACHED();
392 #endif
393         break;
394     case ClipperResourceType:
395         if (!m_clipperFilterMaskerData)
396             break; 
397         if (m_clipperFilterMaskerData->clipper == resource) {
398             m_clipperFilterMaskerData->clipper->removeAllClientsFromCache();
399             m_clipperFilterMaskerData->clipper = 0;
400         }
401         break;
402     case SolidColorResourceType:
403         ASSERT_NOT_REACHED();
404     }
405 }
406
407 void SVGResources::buildSetOfResources(HashSet<RenderSVGResourceContainer*>& set)
408 {
409     if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
410         return;
411
412     if (m_linkedResource) {
413         ASSERT(!m_clipperFilterMaskerData);
414         ASSERT(!m_markerData);
415         ASSERT(!m_fillStrokeData);
416         set.add(m_linkedResource);
417         return;
418     }
419
420     if (m_clipperFilterMaskerData) {
421         if (m_clipperFilterMaskerData->clipper)
422             set.add(m_clipperFilterMaskerData->clipper);
423 #if ENABLE(FILTERS)
424         if (m_clipperFilterMaskerData->filter)
425             set.add(m_clipperFilterMaskerData->filter);
426 #endif
427         if (m_clipperFilterMaskerData->masker)
428             set.add(m_clipperFilterMaskerData->masker);
429     }
430
431     if (m_markerData) {
432         if (m_markerData->markerStart)
433             set.add(m_markerData->markerStart);
434         if (m_markerData->markerMid)
435             set.add(m_markerData->markerMid);
436         if (m_markerData->markerEnd)
437             set.add(m_markerData->markerEnd);
438     }
439
440     if (m_fillStrokeData) {
441         if (m_fillStrokeData->fill)
442             set.add(m_fillStrokeData->fill);
443         if (m_fillStrokeData->stroke)
444             set.add(m_fillStrokeData->stroke);
445     }
446 }
447
448 bool SVGResources::setClipper(RenderSVGResourceClipper* clipper)
449 {
450     if (!clipper)
451         return false;
452
453     ASSERT(clipper->resourceType() == ClipperResourceType);
454
455     if (!m_clipperFilterMaskerData)
456         m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
457
458     m_clipperFilterMaskerData->clipper = clipper;
459     return true;
460 }
461
462 void SVGResources::resetClipper()
463 {
464     ASSERT(m_clipperFilterMaskerData);
465     ASSERT(m_clipperFilterMaskerData->clipper);
466     m_clipperFilterMaskerData->clipper = 0;
467 }
468
469 #if ENABLE(FILTERS)
470 bool SVGResources::setFilter(RenderSVGResourceFilter* filter)
471 {
472     if (!filter)
473         return false;
474
475     ASSERT(filter->resourceType() == FilterResourceType);
476
477     if (!m_clipperFilterMaskerData)
478         m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
479
480     m_clipperFilterMaskerData->filter = filter;
481     return true;
482 }
483
484 void SVGResources::resetFilter()
485 {
486     ASSERT(m_clipperFilterMaskerData);
487     ASSERT(m_clipperFilterMaskerData->filter);
488     m_clipperFilterMaskerData->filter = 0;
489 }
490 #endif
491
492 bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart)
493 {
494     if (!markerStart)
495         return false;
496
497     ASSERT(markerStart->resourceType() == MarkerResourceType);
498
499     if (!m_markerData)
500         m_markerData = MarkerData::create();
501
502     m_markerData->markerStart = markerStart;
503     return true;
504 }
505
506 void SVGResources::resetMarkerStart()
507 {
508     ASSERT(m_markerData);
509     ASSERT(m_markerData->markerStart);
510     m_markerData->markerStart = 0;
511 }
512
513 bool SVGResources::setMarkerMid(RenderSVGResourceMarker* markerMid)
514 {
515     if (!markerMid)
516         return false;
517
518     ASSERT(markerMid->resourceType() == MarkerResourceType);
519
520     if (!m_markerData)
521         m_markerData = MarkerData::create();
522
523     m_markerData->markerMid = markerMid;
524     return true;
525 }
526
527 void SVGResources::resetMarkerMid()
528 {
529     ASSERT(m_markerData);
530     ASSERT(m_markerData->markerMid);
531     m_markerData->markerMid = 0;
532 }
533
534 bool SVGResources::setMarkerEnd(RenderSVGResourceMarker* markerEnd)
535 {
536     if (!markerEnd)
537         return false;
538
539     ASSERT(markerEnd->resourceType() == MarkerResourceType);
540
541     if (!m_markerData)
542         m_markerData = MarkerData::create();
543
544     m_markerData->markerEnd = markerEnd;
545     return true;
546 }
547
548 void SVGResources::resetMarkerEnd()
549 {
550     ASSERT(m_markerData);
551     ASSERT(m_markerData->markerEnd);
552     m_markerData->markerEnd = 0;
553 }
554
555 bool SVGResources::setMasker(RenderSVGResourceMasker* masker)
556 {
557     if (!masker)
558         return false;
559
560     ASSERT(masker->resourceType() == MaskerResourceType);
561
562     if (!m_clipperFilterMaskerData)
563         m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
564
565     m_clipperFilterMaskerData->masker = masker;
566     return true;
567 }
568
569 void SVGResources::resetMasker()
570 {
571     ASSERT(m_clipperFilterMaskerData);
572     ASSERT(m_clipperFilterMaskerData->masker);
573     m_clipperFilterMaskerData->masker = 0;
574 }
575
576 bool SVGResources::setFill(RenderSVGResourceContainer* fill)
577 {
578     if (!fill)
579         return false;
580
581     ASSERT(fill->resourceType() == PatternResourceType
582            || fill->resourceType() == LinearGradientResourceType
583            || fill->resourceType() == RadialGradientResourceType);
584
585     if (!m_fillStrokeData)
586         m_fillStrokeData = FillStrokeData::create();
587
588     m_fillStrokeData->fill = fill;
589     return true;
590 }
591
592 void SVGResources::resetFill()
593 {
594     ASSERT(m_fillStrokeData);
595     ASSERT(m_fillStrokeData->fill);
596     m_fillStrokeData->fill = 0;
597 }
598
599 bool SVGResources::setStroke(RenderSVGResourceContainer* stroke)
600 {
601     if (!stroke)
602         return false;
603
604     ASSERT(stroke->resourceType() == PatternResourceType
605            || stroke->resourceType() == LinearGradientResourceType
606            || stroke->resourceType() == RadialGradientResourceType);
607
608     if (!m_fillStrokeData)
609         m_fillStrokeData = FillStrokeData::create();
610
611     m_fillStrokeData->stroke = stroke;
612     return true;
613 }
614
615 void SVGResources::resetStroke()
616 {
617     ASSERT(m_fillStrokeData);
618     ASSERT(m_fillStrokeData->stroke);
619     m_fillStrokeData->stroke = 0;
620 }
621
622 bool SVGResources::setLinkedResource(RenderSVGResourceContainer* linkedResource)
623 {
624     if (!linkedResource)
625         return false;
626
627     m_linkedResource = linkedResource;
628     return true;
629 }
630
631 void SVGResources::resetLinkedResource()
632 {
633     ASSERT(m_linkedResource);
634     m_linkedResource = 0;
635 }
636
637 #ifndef NDEBUG
638 void SVGResources::dump(const RenderObject* object)
639 {
640     ASSERT(object);
641     ASSERT(object->node());
642
643     fprintf(stderr, "-> this=%p, SVGResources(renderer=%p, node=%p)\n", this, object, object->node());
644     fprintf(stderr, " | DOM Tree:\n");
645     object->node()->showTreeForThis();
646
647     fprintf(stderr, "\n | List of resources:\n");
648     if (m_clipperFilterMaskerData) {
649         if (RenderSVGResourceClipper* clipper = m_clipperFilterMaskerData->clipper)
650             fprintf(stderr, " |-> Clipper    : %p (node=%p)\n", clipper, &clipper->clipPathElement());
651 #if ENABLE(FILTERS)
652         if (RenderSVGResourceFilter* filter = m_clipperFilterMaskerData->filter)
653             fprintf(stderr, " |-> Filter     : %p (node=%p)\n", filter, &filter->filterElement());
654 #endif
655         if (RenderSVGResourceMasker* masker = m_clipperFilterMaskerData->masker)
656             fprintf(stderr, " |-> Masker     : %p (node=%p)\n", masker, &masker->maskElement());
657     }
658
659     if (m_markerData) {
660         if (RenderSVGResourceMarker* markerStart = m_markerData->markerStart)
661             fprintf(stderr, " |-> MarkerStart: %p (node=%p)\n", markerStart, &markerStart->markerElement());
662         if (RenderSVGResourceMarker* markerMid = m_markerData->markerMid)
663             fprintf(stderr, " |-> MarkerMid  : %p (node=%p)\n", markerMid, &markerMid->markerElement());
664         if (RenderSVGResourceMarker* markerEnd = m_markerData->markerEnd)
665             fprintf(stderr, " |-> MarkerEnd  : %p (node=%p)\n", markerEnd, &markerEnd->markerElement());
666     }
667
668     if (m_fillStrokeData) {
669         if (RenderSVGResourceContainer* fill = m_fillStrokeData->fill)
670             fprintf(stderr, " |-> Fill       : %p (node=%p)\n", fill, &fill->element());
671         if (RenderSVGResourceContainer* stroke = m_fillStrokeData->stroke)
672             fprintf(stderr, " |-> Stroke     : %p (node=%p)\n", stroke, &stroke->element());
673     }
674
675     if (m_linkedResource)
676         fprintf(stderr, " |-> xlink:href : %p (node=%p)\n", m_linkedResource, &m_linkedResource->element());
677 }
678 #endif
679
680 }
681
682 #endif