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