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