Rename AtomicString to AtomString
[WebKit-https.git] / Source / WebCore / svg / SVGFEImageElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
4  * Copyright (C) 2010 Dirk Schulze <krit@webkit.org>
5  * Copyright (C) 2018 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24 #include "SVGFEImageElement.h"
25
26 #include "CachedImage.h"
27 #include "CachedResourceLoader.h"
28 #include "CachedResourceRequest.h"
29 #include "Document.h"
30 #include "Image.h"
31 #include "RenderObject.h"
32 #include "RenderSVGResource.h"
33 #include "SVGNames.h"
34 #include "SVGPreserveAspectRatioValue.h"
35 #include <wtf/IsoMallocInlines.h>
36
37 namespace WebCore {
38
39 WTF_MAKE_ISO_ALLOCATED_IMPL(SVGFEImageElement);
40
41 inline SVGFEImageElement::SVGFEImageElement(const QualifiedName& tagName, Document& document)
42     : SVGFilterPrimitiveStandardAttributes(tagName, document)
43     , SVGExternalResourcesRequired(this)
44     , SVGURIReference(this)
45 {
46     ASSERT(hasTagName(SVGNames::feImageTag));
47
48     static std::once_flag onceFlag;
49     std::call_once(onceFlag, [] {
50         PropertyRegistry::registerProperty<SVGNames::preserveAspectRatioAttr, &SVGFEImageElement::m_preserveAspectRatio>();
51     });
52 }
53
54 Ref<SVGFEImageElement> SVGFEImageElement::create(const QualifiedName& tagName, Document& document)
55 {
56     return adoptRef(*new SVGFEImageElement(tagName, document));
57 }
58
59 SVGFEImageElement::~SVGFEImageElement()
60 {
61     clearResourceReferences();
62 }
63
64 bool SVGFEImageElement::hasSingleSecurityOrigin() const
65 {
66     if (!m_cachedImage)
67         return true;
68     auto* image = m_cachedImage->image();
69     return !image || image->hasSingleSecurityOrigin();
70 }
71
72 void SVGFEImageElement::clearResourceReferences()
73 {
74     if (m_cachedImage) {
75         m_cachedImage->removeClient(*this);
76         m_cachedImage = nullptr;
77     }
78
79     document().accessSVGExtensions().removeAllTargetReferencesForElement(*this);
80 }
81
82 void SVGFEImageElement::requestImageResource()
83 {
84     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
85     options.contentSecurityPolicyImposition = isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
86
87     CachedResourceRequest request(ResourceRequest(document().completeURL(href())), options);
88     request.setInitiator(*this);
89     m_cachedImage = document().cachedResourceLoader().requestImage(WTFMove(request)).value_or(nullptr);
90
91     if (m_cachedImage)
92         m_cachedImage->addClient(*this);
93 }
94
95 void SVGFEImageElement::buildPendingResource()
96 {
97     clearResourceReferences();
98     if (!isConnected())
99         return;
100
101     auto target = SVGURIReference::targetElementFromIRIString(href(), treeScope());
102     if (!target.element) {
103         if (target.identifier.isEmpty())
104             requestImageResource();
105         else {
106             document().accessSVGExtensions().addPendingResource(target.identifier, *this);
107             ASSERT(hasPendingResources());
108         }
109     } else if (is<SVGElement>(*target.element)) {
110         // Register us with the target in the dependencies map. Any change of hrefElement
111         // that leads to relayout/repainting now informs us, so we can react to it.
112         document().accessSVGExtensions().addElementReferencingTarget(*this, downcast<SVGElement>(*target.element));
113     }
114
115     invalidate();
116 }
117
118 void SVGFEImageElement::parseAttribute(const QualifiedName& name, const AtomString& value)
119 {
120     if (name == SVGNames::preserveAspectRatioAttr) {
121         SVGPreserveAspectRatioValue preserveAspectRatio;
122         preserveAspectRatio.parse(value);
123         m_preserveAspectRatio->setBaseValInternal(preserveAspectRatio);
124         return;
125     }
126
127     SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
128     SVGURIReference::parseAttribute(name, value);
129     SVGExternalResourcesRequired::parseAttribute(name, value);
130 }
131
132 void SVGFEImageElement::svgAttributeChanged(const QualifiedName& attrName)
133 {
134     if (attrName == SVGNames::preserveAspectRatioAttr) {
135         InstanceInvalidationGuard guard(*this);
136         invalidate();
137         return;
138     }
139
140     if (SVGURIReference::isKnownAttribute(attrName)) {
141         InstanceInvalidationGuard guard(*this);
142         buildPendingResource();
143         return;
144     }
145
146     SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
147 }
148
149 Node::InsertedIntoAncestorResult SVGFEImageElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
150 {
151     SVGFilterPrimitiveStandardAttributes::insertedIntoAncestor(insertionType, parentOfInsertedTree);
152     return InsertedIntoAncestorResult::NeedsPostInsertionCallback;
153 }
154
155 void SVGFEImageElement::didFinishInsertingNode()
156 {
157     buildPendingResource();
158 }
159
160 void SVGFEImageElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
161 {
162     SVGFilterPrimitiveStandardAttributes::removedFromAncestor(removalType, oldParentOfRemovedTree);
163     if (removalType.disconnectedFromDocument)
164         clearResourceReferences();
165 }
166
167 void SVGFEImageElement::notifyFinished(CachedResource&)
168 {
169     if (!isConnected())
170         return;
171
172     auto parent = makeRefPtr(parentElement());
173
174     if (!parent || !parent->hasTagName(SVGNames::filterTag))
175         return;
176
177     RenderElement* parentRenderer = parent->renderer();
178     if (!parentRenderer)
179         return;
180
181     RenderSVGResource::markForLayoutAndParentResourceInvalidation(*parentRenderer);
182 }
183
184 RefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*, Filter& filter) const
185 {
186     if (m_cachedImage)
187         return FEImage::createWithImage(filter, m_cachedImage->imageForRenderer(renderer()), preserveAspectRatio());
188     return FEImage::createWithIRIReference(filter, treeScope(), href(), preserveAspectRatio());
189 }
190
191 void SVGFEImageElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
192 {
193     SVGFilterPrimitiveStandardAttributes::addSubresourceAttributeURLs(urls);
194
195     addSubresourceURL(urls, document().completeURL(href()));
196 }
197
198 }