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