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