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