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