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