910af30fe176a5b0e4cefaee30852c43342567b1
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / 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
24 #include "core/svg/SVGFEImageElement.h"
25
26 #include "XLinkNames.h"
27 #include "core/dom/Document.h"
28 #include "core/fetch/FetchRequest.h"
29 #include "core/fetch/ResourceFetcher.h"
30 #include "core/rendering/svg/RenderSVGResource.h"
31 #include "core/svg/SVGElementInstance.h"
32 #include "core/svg/SVGPreserveAspectRatio.h"
33 #include "platform/graphics/Image.h"
34
35 namespace WebCore {
36
37 // Animated property definitions
38
39 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEImageElement)
40     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
41 END_REGISTER_ANIMATED_PROPERTIES
42
43 inline SVGFEImageElement::SVGFEImageElement(Document& document)
44     : SVGFilterPrimitiveStandardAttributes(SVGNames::feImageTag, document)
45     , SVGURIReference(this)
46     , m_preserveAspectRatio(SVGAnimatedPreserveAspectRatio::create(this, SVGNames::preserveAspectRatioAttr, SVGPreserveAspectRatio::create()))
47 {
48     ScriptWrappable::init(this);
49     addToPropertyMap(m_preserveAspectRatio);
50     registerAnimatedPropertiesForSVGFEImageElement();
51 }
52
53 PassRefPtr<SVGFEImageElement> SVGFEImageElement::create(Document& document)
54 {
55     return adoptRef(new SVGFEImageElement(document));
56 }
57
58 SVGFEImageElement::~SVGFEImageElement()
59 {
60     clearResourceReferences();
61 }
62
63 bool SVGFEImageElement::currentFrameHasSingleSecurityOrigin() const
64 {
65     if (m_cachedImage && m_cachedImage->image())
66         return m_cachedImage->image()->currentFrameHasSingleSecurityOrigin();
67
68     return true;
69 }
70
71 void SVGFEImageElement::clearResourceReferences()
72 {
73     if (m_cachedImage) {
74         m_cachedImage->removeClient(this);
75         m_cachedImage = 0;
76     }
77
78     document().accessSVGExtensions()->removeAllTargetReferencesForElement(this);
79 }
80
81 void SVGFEImageElement::fetchImageResource()
82 {
83     FetchRequest request(ResourceRequest(ownerDocument()->completeURL(hrefString())), localName());
84     m_cachedImage = document().fetcher()->fetchImage(request);
85
86     if (m_cachedImage)
87         m_cachedImage->addClient(this);
88 }
89
90 void SVGFEImageElement::buildPendingResource()
91 {
92     clearResourceReferences();
93     if (!inDocument())
94         return;
95
96     AtomicString id;
97     Element* target = SVGURIReference::targetElementFromIRIString(hrefString(), document(), &id);
98     if (!target) {
99         if (id.isEmpty())
100             fetchImageResource();
101         else {
102             document().accessSVGExtensions()->addPendingResource(id, this);
103             ASSERT(hasPendingResources());
104         }
105     } else if (target->isSVGElement()) {
106         // Register us with the target in the dependencies map. Any change of hrefElement
107         // that leads to relayout/repainting now informs us, so we can react to it.
108         document().accessSVGExtensions()->addElementReferencingTarget(this, toSVGElement(target));
109     }
110
111     invalidate();
112 }
113
114 bool SVGFEImageElement::isSupportedAttribute(const QualifiedName& attrName)
115 {
116     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
117     if (supportedAttributes.isEmpty()) {
118         SVGURIReference::addSupportedAttributes(supportedAttributes);
119         supportedAttributes.add(SVGNames::preserveAspectRatioAttr);
120     }
121     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
122 }
123
124 void SVGFEImageElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
125 {
126     if (!isSupportedAttribute(name)) {
127         SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
128         return;
129     }
130
131     SVGParsingError parseError = NoError;
132
133     if (name == SVGNames::preserveAspectRatioAttr) {
134         m_preserveAspectRatio->setBaseValueAsString(value, parseError);
135     } else if (SVGURIReference::parseAttribute(name, value, parseError)) {
136     } else {
137         ASSERT_NOT_REACHED();
138     }
139
140     reportAttributeParsingError(parseError, name, value);
141 }
142
143 void SVGFEImageElement::svgAttributeChanged(const QualifiedName& attrName)
144 {
145     if (!isSupportedAttribute(attrName)) {
146         SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
147         return;
148     }
149
150     SVGElementInstance::InvalidationGuard invalidationGuard(this);
151
152     if (attrName == SVGNames::preserveAspectRatioAttr) {
153         invalidate();
154         return;
155     }
156
157     if (SVGURIReference::isKnownAttribute(attrName)) {
158         buildPendingResource();
159         return;
160     }
161
162     ASSERT_NOT_REACHED();
163 }
164
165 Node::InsertionNotificationRequest SVGFEImageElement::insertedInto(ContainerNode* rootParent)
166 {
167     SVGFilterPrimitiveStandardAttributes::insertedInto(rootParent);
168     buildPendingResource();
169     return InsertionDone;
170 }
171
172 void SVGFEImageElement::removedFrom(ContainerNode* rootParent)
173 {
174     SVGFilterPrimitiveStandardAttributes::removedFrom(rootParent);
175     if (rootParent->inDocument())
176         clearResourceReferences();
177 }
178
179 void SVGFEImageElement::notifyFinished(Resource*)
180 {
181     if (!inDocument())
182         return;
183
184     Element* parent = parentElement();
185     ASSERT(parent);
186
187     if (!parent->hasTagName(SVGNames::filterTag) || !parent->renderer())
188         return;
189
190     if (RenderObject* renderer = this->renderer())
191         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
192 }
193
194 PassRefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*, Filter* filter)
195 {
196     if (m_cachedImage)
197         return FEImage::createWithImage(filter, m_cachedImage->imageForRenderer(renderer()), m_preserveAspectRatio->currentValue());
198     return FEImage::createWithIRIReference(filter, document(), hrefString(), m_preserveAspectRatio->currentValue());
199 }
200
201 }