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