diff options
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGResources.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/SVGResources.cpp | 240 |
1 files changed, 129 insertions, 111 deletions
diff --git a/Source/WebCore/rendering/svg/SVGResources.cpp b/Source/WebCore/rendering/svg/SVGResources.cpp index bdb586b89..ea9b45211 100644 --- a/Source/WebCore/rendering/svg/SVGResources.cpp +++ b/Source/WebCore/rendering/svg/SVGResources.cpp @@ -20,19 +20,19 @@ #include "config.h" #include "SVGResources.h" -#if ENABLE(SVG) +#include "FilterOperation.h" #include "RenderSVGResourceClipper.h" #include "RenderSVGResourceFilter.h" #include "RenderSVGResourceMarker.h" #include "RenderSVGResourceMasker.h" +#include "RenderSVGRoot.h" #include "SVGGradientElement.h" #include "SVGNames.h" -#include "SVGPaint.h" #include "SVGPatternElement.h" #include "SVGRenderStyle.h" #include "SVGURIReference.h" -#ifndef NDEBUG +#if ENABLE(TREE_DEBUGGING) #include <stdio.h> #endif @@ -45,44 +45,44 @@ SVGResources::SVGResources() static HashSet<AtomicString>& clipperFilterMaskerTags() { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); - if (s_tagList.isEmpty()) { + static NeverDestroyed<HashSet<AtomicString>> s_tagList; + if (s_tagList.get().isEmpty()) { // "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement // "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement - s_tagList.add(SVGNames::aTag.localName()); - s_tagList.add(SVGNames::circleTag.localName()); - s_tagList.add(SVGNames::ellipseTag.localName()); - s_tagList.add(SVGNames::glyphTag.localName()); - s_tagList.add(SVGNames::gTag.localName()); - s_tagList.add(SVGNames::imageTag.localName()); - s_tagList.add(SVGNames::lineTag.localName()); - s_tagList.add(SVGNames::markerTag.localName()); - s_tagList.add(SVGNames::maskTag.localName()); - s_tagList.add(SVGNames::missing_glyphTag.localName()); - s_tagList.add(SVGNames::pathTag.localName()); - s_tagList.add(SVGNames::polygonTag.localName()); - s_tagList.add(SVGNames::polylineTag.localName()); - s_tagList.add(SVGNames::rectTag.localName()); - s_tagList.add(SVGNames::svgTag.localName()); - s_tagList.add(SVGNames::textTag.localName()); - s_tagList.add(SVGNames::useTag.localName()); + s_tagList.get().add(SVGNames::aTag.localName()); + s_tagList.get().add(SVGNames::circleTag.localName()); + s_tagList.get().add(SVGNames::ellipseTag.localName()); + s_tagList.get().add(SVGNames::glyphTag.localName()); + s_tagList.get().add(SVGNames::gTag.localName()); + s_tagList.get().add(SVGNames::imageTag.localName()); + s_tagList.get().add(SVGNames::lineTag.localName()); + s_tagList.get().add(SVGNames::markerTag.localName()); + s_tagList.get().add(SVGNames::maskTag.localName()); + s_tagList.get().add(SVGNames::missing_glyphTag.localName()); + s_tagList.get().add(SVGNames::pathTag.localName()); + s_tagList.get().add(SVGNames::polygonTag.localName()); + s_tagList.get().add(SVGNames::polylineTag.localName()); + s_tagList.get().add(SVGNames::rectTag.localName()); + s_tagList.get().add(SVGNames::svgTag.localName()); + s_tagList.get().add(SVGNames::textTag.localName()); + s_tagList.get().add(SVGNames::useTag.localName()); // Not listed in the definitions is the clipPath element, the SVG spec says though: // The "clipPath" element or any of its children can specify property "clip-path". // So we have to add clipPathTag here, otherwhise clip-path on clipPath will fail. // (Already mailed SVG WG, waiting for a solution) - s_tagList.add(SVGNames::clipPathTag.localName()); + s_tagList.get().add(SVGNames::clipPathTag.localName()); // Not listed in the definitions are the text content elements, though filter/clipper/masker on tspan/text/.. is allowed. // (Already mailed SVG WG, waiting for a solution) - s_tagList.add(SVGNames::altGlyphTag.localName()); - s_tagList.add(SVGNames::textPathTag.localName()); - s_tagList.add(SVGNames::trefTag.localName()); - s_tagList.add(SVGNames::tspanTag.localName()); + s_tagList.get().add(SVGNames::altGlyphTag.localName()); + s_tagList.get().add(SVGNames::textPathTag.localName()); + s_tagList.get().add(SVGNames::trefTag.localName()); + s_tagList.get().add(SVGNames::tspanTag.localName()); // Not listed in the definitions is the foreignObject element, but clip-path // is a supported attribute. - s_tagList.add(SVGNames::foreignObjectTag.localName()); + s_tagList.get().add(SVGNames::foreignObjectTag.localName()); // Elements that we ignore, as it doesn't make any sense. // defs, pattern, switch (FIXME: Mail SVG WG about these) @@ -94,12 +94,12 @@ static HashSet<AtomicString>& clipperFilterMaskerTags() static HashSet<AtomicString>& markerTags() { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); - if (s_tagList.isEmpty()) { - s_tagList.add(SVGNames::lineTag.localName()); - s_tagList.add(SVGNames::pathTag.localName()); - s_tagList.add(SVGNames::polygonTag.localName()); - s_tagList.add(SVGNames::polylineTag.localName()); + static NeverDestroyed<HashSet<AtomicString>> s_tagList; + if (s_tagList.get().isEmpty()) { + s_tagList.get().add(SVGNames::lineTag.localName()); + s_tagList.get().add(SVGNames::pathTag.localName()); + s_tagList.get().add(SVGNames::polygonTag.localName()); + s_tagList.get().add(SVGNames::polylineTag.localName()); } return s_tagList; @@ -107,20 +107,20 @@ static HashSet<AtomicString>& markerTags() static HashSet<AtomicString>& fillAndStrokeTags() { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); - if (s_tagList.isEmpty()) { - s_tagList.add(SVGNames::altGlyphTag.localName()); - s_tagList.add(SVGNames::circleTag.localName()); - s_tagList.add(SVGNames::ellipseTag.localName()); - s_tagList.add(SVGNames::lineTag.localName()); - s_tagList.add(SVGNames::pathTag.localName()); - s_tagList.add(SVGNames::polygonTag.localName()); - s_tagList.add(SVGNames::polylineTag.localName()); - s_tagList.add(SVGNames::rectTag.localName()); - s_tagList.add(SVGNames::textTag.localName()); - s_tagList.add(SVGNames::textPathTag.localName()); - s_tagList.add(SVGNames::trefTag.localName()); - s_tagList.add(SVGNames::tspanTag.localName()); + static NeverDestroyed<HashSet<AtomicString>> s_tagList; + if (s_tagList.get().isEmpty()) { + s_tagList.get().add(SVGNames::altGlyphTag.localName()); + s_tagList.get().add(SVGNames::circleTag.localName()); + s_tagList.get().add(SVGNames::ellipseTag.localName()); + s_tagList.get().add(SVGNames::lineTag.localName()); + s_tagList.get().add(SVGNames::pathTag.localName()); + s_tagList.get().add(SVGNames::polygonTag.localName()); + s_tagList.get().add(SVGNames::polylineTag.localName()); + s_tagList.get().add(SVGNames::rectTag.localName()); + s_tagList.get().add(SVGNames::textTag.localName()); + s_tagList.get().add(SVGNames::textPathTag.localName()); + s_tagList.get().add(SVGNames::trefTag.localName()); + s_tagList.get().add(SVGNames::tspanTag.localName()); } return s_tagList; @@ -128,12 +128,12 @@ static HashSet<AtomicString>& fillAndStrokeTags() static HashSet<AtomicString>& chainableResourceTags() { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); - if (s_tagList.isEmpty()) { - s_tagList.add(SVGNames::linearGradientTag.localName()); - s_tagList.add(SVGNames::filterTag.localName()); - s_tagList.add(SVGNames::patternTag.localName()); - s_tagList.add(SVGNames::radialGradientTag.localName()); + static NeverDestroyed<HashSet<AtomicString>> s_tagList; + if (s_tagList.get().isEmpty()) { + s_tagList.get().add(SVGNames::linearGradientTag.localName()); + s_tagList.get().add(SVGNames::filterTag.localName()); + s_tagList.get().add(SVGNames::patternTag.localName()); + s_tagList.get().add(SVGNames::radialGradientTag.localName()); } return s_tagList; @@ -142,23 +142,21 @@ static HashSet<AtomicString>& chainableResourceTags() static inline String targetReferenceFromResource(SVGElement& element) { String target; - if (isSVGPatternElement(element)) - target = toSVGPatternElement(element).href(); - else if (isSVGGradientElement(element)) - target = toSVGGradientElement(element).href(); -#if ENABLE(FILTERS) - else if (isSVGFilterElement(element)) - target = toSVGFilterElement(element).href(); -#endif + if (is<SVGPatternElement>(element)) + target = downcast<SVGPatternElement>(element).href(); + else if (is<SVGGradientElement>(element)) + target = downcast<SVGGradientElement>(element).href(); + else if (is<SVGFilterElement>(element)) + target = downcast<SVGFilterElement>(element).href(); else ASSERT_NOT_REACHED(); return SVGURIReference::fragmentIdentifierFromIRIString(target, element.document()); } -static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& document, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource) +static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& document, const SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource) { - if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) + if (paintType != SVG_PAINTTYPE_URI && paintType != SVG_PAINTTYPE_URI_RGBCOLOR && paintType != SVG_PAINTTYPE_URI_CURRENTCOLOR) return 0; id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, document); @@ -175,12 +173,12 @@ static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& return container; } -static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement& element) +static inline void registerPendingResource(SVGDocumentExtensions& extensions, const AtomicString& id, SVGElement& element) { - extensions->addPendingResource(id, &element); + extensions.addPendingResource(id, &element); } -bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVGRenderStyle& svgStyle) +bool SVGResources::buildCachedResources(const RenderElement& renderer, const RenderStyle& style) { ASSERT(renderer.element()); ASSERT_WITH_SECURITY_IMPLICATION(renderer.element()->isSVGElement()); @@ -188,17 +186,18 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG if (!renderer.element()) return false; - auto& element = toSVGElement(*renderer.element()); + auto& element = downcast<SVGElement>(*renderer.element()); Document& document = element.document(); - SVGDocumentExtensions* extensions = document.accessSVGExtensions(); - ASSERT(extensions); + SVGDocumentExtensions& extensions = document.accessSVGExtensions(); const AtomicString& tagName = element.localName(); if (tagName.isNull()) return false; + const SVGRenderStyle& svgStyle = style.svgStyle(); + bool foundResources = false; if (clipperFilterMaskerTags().contains(tagName)) { if (svgStyle.hasClipper()) { @@ -209,15 +208,20 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG registerPendingResource(extensions, id, element); } -#if ENABLE(FILTERS) - if (svgStyle.hasFilter()) { - AtomicString id(svgStyle.filterResource()); - if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id))) - foundResources = true; - else - registerPendingResource(extensions, id, element); + if (style.hasFilter()) { + const FilterOperations& filterOperations = style.filter(); + if (filterOperations.size() == 1) { + const FilterOperation& filterOperation = *filterOperations.at(0); + if (filterOperation.type() == FilterOperation::REFERENCE) { + const auto& referenceFilterOperation = downcast<ReferenceFilterOperation>(filterOperation); + AtomicString id = SVGURIReference::fragmentIdentifierFromIRIString(referenceFilterOperation.url(), element.document()); + if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id))) + foundResources = true; + else + registerPendingResource(extensions, id, element); + } + } } -#endif if (svgStyle.hasMasker()) { AtomicString id(svgStyle.maskerResource()); @@ -279,7 +283,35 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG return foundResources; } -void SVGResources::removeClientFromCache(RenderObject& object, bool markForInvalidation) const +void SVGResources::layoutDifferentRootIfNeeded(const RenderSVGRoot* svgRoot) +{ + if (clipper() && svgRoot != SVGRenderSupport::findTreeRootObject(*clipper())) + clipper()->layoutIfNeeded(); + + if (masker() && svgRoot != SVGRenderSupport::findTreeRootObject(*masker())) + masker()->layoutIfNeeded(); + + if (filter() && svgRoot != SVGRenderSupport::findTreeRootObject(*filter())) + filter()->layoutIfNeeded(); + + if (markerStart() && svgRoot != SVGRenderSupport::findTreeRootObject(*markerStart())) + markerStart()->layoutIfNeeded(); + + if (markerMid() && svgRoot != SVGRenderSupport::findTreeRootObject(*markerMid())) + markerMid()->layoutIfNeeded(); + + if (markerEnd() && svgRoot != SVGRenderSupport::findTreeRootObject(*markerEnd())) + markerEnd()->layoutIfNeeded(); +} + +bool SVGResources::markerReverseStart() const +{ + return m_markerData + && m_markerData->markerStart + && m_markerData->markerStart->markerElement().orientType() == SVGMarkerOrientAutoStartReverse; +} + +void SVGResources::removeClientFromCache(RenderElement& renderer, bool markForInvalidation) const { if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource) return; @@ -288,35 +320,33 @@ void SVGResources::removeClientFromCache(RenderObject& object, bool markForInval ASSERT(!m_clipperFilterMaskerData); ASSERT(!m_markerData); ASSERT(!m_fillStrokeData); - m_linkedResource->removeClientFromCache(object, markForInvalidation); + m_linkedResource->removeClientFromCache(renderer, markForInvalidation); return; } if (m_clipperFilterMaskerData) { if (m_clipperFilterMaskerData->clipper) - m_clipperFilterMaskerData->clipper->removeClientFromCache(object, markForInvalidation); -#if ENABLE(FILTERS) + m_clipperFilterMaskerData->clipper->removeClientFromCache(renderer, markForInvalidation); if (m_clipperFilterMaskerData->filter) - m_clipperFilterMaskerData->filter->removeClientFromCache(object, markForInvalidation); -#endif + m_clipperFilterMaskerData->filter->removeClientFromCache(renderer, markForInvalidation); if (m_clipperFilterMaskerData->masker) - m_clipperFilterMaskerData->masker->removeClientFromCache(object, markForInvalidation); + m_clipperFilterMaskerData->masker->removeClientFromCache(renderer, markForInvalidation); } if (m_markerData) { if (m_markerData->markerStart) - m_markerData->markerStart->removeClientFromCache(object, markForInvalidation); + m_markerData->markerStart->removeClientFromCache(renderer, markForInvalidation); if (m_markerData->markerMid) - m_markerData->markerMid->removeClientFromCache(object, markForInvalidation); + m_markerData->markerMid->removeClientFromCache(renderer, markForInvalidation); if (m_markerData->markerEnd) - m_markerData->markerEnd->removeClientFromCache(object, markForInvalidation); + m_markerData->markerEnd->removeClientFromCache(renderer, markForInvalidation); } if (m_fillStrokeData) { if (m_fillStrokeData->fill) - m_fillStrokeData->fill->removeClientFromCache(object, markForInvalidation); + m_fillStrokeData->fill->removeClientFromCache(renderer, markForInvalidation); if (m_fillStrokeData->stroke) - m_fillStrokeData->stroke->removeClientFromCache(object, markForInvalidation); + m_fillStrokeData->stroke->removeClientFromCache(renderer, markForInvalidation); } } @@ -374,16 +404,12 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer& resource) } break; case FilterResourceType: -#if ENABLE(FILTERS) if (!m_clipperFilterMaskerData) break; if (m_clipperFilterMaskerData->filter == &resource) { m_clipperFilterMaskerData->filter->removeAllClientsFromCache(); m_clipperFilterMaskerData->filter = 0; } -#else - ASSERT_NOT_REACHED(); -#endif break; case ClipperResourceType: if (!m_clipperFilterMaskerData) @@ -414,10 +440,8 @@ void SVGResources::buildSetOfResources(HashSet<RenderSVGResourceContainer*>& set if (m_clipperFilterMaskerData) { if (m_clipperFilterMaskerData->clipper) set.add(m_clipperFilterMaskerData->clipper); -#if ENABLE(FILTERS) if (m_clipperFilterMaskerData->filter) set.add(m_clipperFilterMaskerData->filter); -#endif if (m_clipperFilterMaskerData->masker) set.add(m_clipperFilterMaskerData->masker); } @@ -447,7 +471,7 @@ bool SVGResources::setClipper(RenderSVGResourceClipper* clipper) ASSERT(clipper->resourceType() == ClipperResourceType); if (!m_clipperFilterMaskerData) - m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); + m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>(); m_clipperFilterMaskerData->clipper = clipper; return true; @@ -460,7 +484,6 @@ void SVGResources::resetClipper() m_clipperFilterMaskerData->clipper = 0; } -#if ENABLE(FILTERS) bool SVGResources::setFilter(RenderSVGResourceFilter* filter) { if (!filter) @@ -469,7 +492,7 @@ bool SVGResources::setFilter(RenderSVGResourceFilter* filter) ASSERT(filter->resourceType() == FilterResourceType); if (!m_clipperFilterMaskerData) - m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); + m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>(); m_clipperFilterMaskerData->filter = filter; return true; @@ -481,7 +504,6 @@ void SVGResources::resetFilter() ASSERT(m_clipperFilterMaskerData->filter); m_clipperFilterMaskerData->filter = 0; } -#endif bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart) { @@ -491,7 +513,7 @@ bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart) ASSERT(markerStart->resourceType() == MarkerResourceType); if (!m_markerData) - m_markerData = MarkerData::create(); + m_markerData = std::make_unique<MarkerData>(); m_markerData->markerStart = markerStart; return true; @@ -512,7 +534,7 @@ bool SVGResources::setMarkerMid(RenderSVGResourceMarker* markerMid) ASSERT(markerMid->resourceType() == MarkerResourceType); if (!m_markerData) - m_markerData = MarkerData::create(); + m_markerData = std::make_unique<MarkerData>(); m_markerData->markerMid = markerMid; return true; @@ -533,7 +555,7 @@ bool SVGResources::setMarkerEnd(RenderSVGResourceMarker* markerEnd) ASSERT(markerEnd->resourceType() == MarkerResourceType); if (!m_markerData) - m_markerData = MarkerData::create(); + m_markerData = std::make_unique<MarkerData>(); m_markerData->markerEnd = markerEnd; return true; @@ -554,7 +576,7 @@ bool SVGResources::setMasker(RenderSVGResourceMasker* masker) ASSERT(masker->resourceType() == MaskerResourceType); if (!m_clipperFilterMaskerData) - m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); + m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>(); m_clipperFilterMaskerData->masker = masker; return true; @@ -577,7 +599,7 @@ bool SVGResources::setFill(RenderSVGResourceContainer* fill) || fill->resourceType() == RadialGradientResourceType); if (!m_fillStrokeData) - m_fillStrokeData = FillStrokeData::create(); + m_fillStrokeData = std::make_unique<FillStrokeData>(); m_fillStrokeData->fill = fill; return true; @@ -600,7 +622,7 @@ bool SVGResources::setStroke(RenderSVGResourceContainer* stroke) || stroke->resourceType() == RadialGradientResourceType); if (!m_fillStrokeData) - m_fillStrokeData = FillStrokeData::create(); + m_fillStrokeData = std::make_unique<FillStrokeData>(); m_fillStrokeData->stroke = stroke; return true; @@ -628,7 +650,7 @@ void SVGResources::resetLinkedResource() m_linkedResource = 0; } -#ifndef NDEBUG +#if ENABLE(TREE_DEBUGGING) void SVGResources::dump(const RenderObject* object) { ASSERT(object); @@ -642,10 +664,8 @@ void SVGResources::dump(const RenderObject* object) if (m_clipperFilterMaskerData) { if (RenderSVGResourceClipper* clipper = m_clipperFilterMaskerData->clipper) fprintf(stderr, " |-> Clipper : %p (node=%p)\n", clipper, &clipper->clipPathElement()); -#if ENABLE(FILTERS) if (RenderSVGResourceFilter* filter = m_clipperFilterMaskerData->filter) fprintf(stderr, " |-> Filter : %p (node=%p)\n", filter, &filter->filterElement()); -#endif if (RenderSVGResourceMasker* masker = m_clipperFilterMaskerData->masker) fprintf(stderr, " |-> Masker : %p (node=%p)\n", masker, &masker->maskElement()); } @@ -672,5 +692,3 @@ void SVGResources::dump(const RenderObject* object) #endif } - -#endif |