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