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