summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/svg/SVGResources.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGResources.cpp')
-rw-r--r--Source/WebCore/rendering/svg/SVGResources.cpp240
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