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 39namespace WebCore { 40 41using namespace SVGNames; 42 43SVGResources::SVGResources() 44 : m_linkedResource(0) 45{ 46} 47 48static 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 102bool 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 115static 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 137static 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 150static 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 165static 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 180static 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 199static inline void registerPendingResource(SVGDocumentExtensions& extensions, const AtomicString& id, SVGElement* element) 200{ 201 ASSERT(element); 202 extensions.addPendingResource(id, element); 203} 204 205bool SVGResources::hasResourceData() const 206{ 207 return !m_clipperFilterMaskerData 208 && !m_markerData 209 && !m_fillStrokeData 210 && !m_linkedResource; 211} 212 213static inline SVGResources* ensureResources(OwnPtr<SVGResources>& resources) 214{ 215 if (!resources) 216 resources = adoptPtr(new SVGResources); 217 218 return resources.get(); 219} 220 221PassOwnPtr<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 306void 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 337void 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 376void 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 451void 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 490bool 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 504void SVGResources::resetClipper() 505{ 506 ASSERT(m_clipperFilterMaskerData); 507 ASSERT(m_clipperFilterMaskerData->clipper); 508 m_clipperFilterMaskerData->clipper = 0; 509} 510 511bool 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 525void SVGResources::resetFilter() 526{ 527 ASSERT(m_clipperFilterMaskerData); 528 ASSERT(m_clipperFilterMaskerData->filter); 529 m_clipperFilterMaskerData->filter = 0; 530} 531 532bool 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 546void SVGResources::resetMarkerStart() 547{ 548 ASSERT(m_markerData); 549 ASSERT(m_markerData->markerStart); 550 m_markerData->markerStart = 0; 551} 552 553bool 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 567void SVGResources::resetMarkerMid() 568{ 569 ASSERT(m_markerData); 570 ASSERT(m_markerData->markerMid); 571 m_markerData->markerMid = 0; 572} 573 574bool 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 588void SVGResources::resetMarkerEnd() 589{ 590 ASSERT(m_markerData); 591 ASSERT(m_markerData->markerEnd); 592 m_markerData->markerEnd = 0; 593} 594 595bool 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 609void SVGResources::resetMasker() 610{ 611 ASSERT(m_clipperFilterMaskerData); 612 ASSERT(m_clipperFilterMaskerData->masker); 613 m_clipperFilterMaskerData->masker = 0; 614} 615 616bool 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 632void SVGResources::resetFill() 633{ 634 ASSERT(m_fillStrokeData); 635 ASSERT(m_fillStrokeData->fill); 636 m_fillStrokeData->fill = 0; 637} 638 639bool 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 655void SVGResources::resetStroke() 656{ 657 ASSERT(m_fillStrokeData); 658 ASSERT(m_fillStrokeData->stroke); 659 m_fillStrokeData->stroke = 0; 660} 661 662bool SVGResources::setLinkedResource(RenderSVGResourceContainer* linkedResource) 663{ 664 if (!linkedResource) 665 return false; 666 667 m_linkedResource = linkedResource; 668 return true; 669} 670 671void SVGResources::resetLinkedResource() 672{ 673 ASSERT(m_linkedResource); 674 m_linkedResource = 0; 675} 676 677#ifndef NDEBUG 678void 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