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 42 SVGResources::SVGResources() 43 : m_linkedResource(0) 44 { 45 } 46 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 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 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 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 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 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 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 197 static inline void registerPendingResource(SVGDocumentExtensions& extensions, const AtomicString& id, SVGElement* element) 198 { 199 ASSERT(element); 200 extensions.addPendingResource(id, element); 201 } 202 203 bool SVGResources::hasResourceData() const 204 { 205 return !m_clipperFilterMaskerData 206 && !m_markerData 207 && !m_fillStrokeData 208 && !m_linkedResource; 209 } 210 211 static inline SVGResources* ensureResources(OwnPtr<SVGResources>& resources) 212 { 213 if (!resources) 214 resources = adoptPtr(new SVGResources); 215 216 return resources.get(); 217 } 218 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 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 334 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 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 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 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 501 void SVGResources::resetClipper() 502 { 503 ASSERT(m_clipperFilterMaskerData); 504 ASSERT(m_clipperFilterMaskerData->clipper); 505 m_clipperFilterMaskerData->clipper = 0; 506 } 507 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 522 void SVGResources::resetFilter() 523 { 524 ASSERT(m_clipperFilterMaskerData); 525 ASSERT(m_clipperFilterMaskerData->filter); 526 m_clipperFilterMaskerData->filter = 0; 527 } 528 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 543 void SVGResources::resetMarkerStart() 544 { 545 ASSERT(m_markerData); 546 ASSERT(m_markerData->markerStart); 547 m_markerData->markerStart = 0; 548 } 549 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 564 void SVGResources::resetMarkerMid() 565 { 566 ASSERT(m_markerData); 567 ASSERT(m_markerData->markerMid); 568 m_markerData->markerMid = 0; 569 } 570 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 585 void SVGResources::resetMarkerEnd() 586 { 587 ASSERT(m_markerData); 588 ASSERT(m_markerData->markerEnd); 589 m_markerData->markerEnd = 0; 590 } 591 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 606 void SVGResources::resetMasker() 607 { 608 ASSERT(m_clipperFilterMaskerData); 609 ASSERT(m_clipperFilterMaskerData->masker); 610 m_clipperFilterMaskerData->masker = 0; 611 } 612 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 629 void SVGResources::resetFill() 630 { 631 ASSERT(m_fillStrokeData); 632 ASSERT(m_fillStrokeData->fill); 633 m_fillStrokeData->fill = 0; 634 } 635 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 652 void SVGResources::resetStroke() 653 { 654 ASSERT(m_fillStrokeData); 655 ASSERT(m_fillStrokeData->stroke); 656 m_fillStrokeData->stroke = 0; 657 } 658 659 bool SVGResources::setLinkedResource(RenderSVGResourceContainer* linkedResource) 660 { 661 if (!linkedResource) 662 return false; 663 664 m_linkedResource = linkedResource; 665 return true; 666 } 667 668 void SVGResources::resetLinkedResource() 669 { 670 ASSERT(m_linkedResource); 671 m_linkedResource = 0; 672 } 673 674 #ifndef NDEBUG 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