2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Rob Buis <buis@kde.org>
4 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
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.
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.
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.
24 #include "core/svg/SVGImageElement.h"
26 #include "CSSPropertyNames.h"
27 #include "XLinkNames.h"
28 #include "core/rendering/RenderImageResource.h"
29 #include "core/rendering/svg/RenderSVGImage.h"
30 #include "core/rendering/svg/RenderSVGResource.h"
31 #include "core/svg/SVGElementInstance.h"
35 inline SVGImageElement::SVGImageElement(Document& document)
36 : SVGGraphicsElement(SVGNames::imageTag, document)
37 , SVGURIReference(this)
38 , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
39 , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
40 , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth), ForbidNegativeLengths))
41 , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight), ForbidNegativeLengths))
42 , m_preserveAspectRatio(SVGAnimatedPreserveAspectRatio::create(this, SVGNames::preserveAspectRatioAttr, SVGPreserveAspectRatio::create()))
44 , m_needsLoaderURIUpdate(true)
46 ScriptWrappable::init(this);
48 addToPropertyMap(m_x);
49 addToPropertyMap(m_y);
50 addToPropertyMap(m_width);
51 addToPropertyMap(m_height);
52 addToPropertyMap(m_preserveAspectRatio);
55 PassRefPtr<SVGImageElement> SVGImageElement::create(Document& document)
57 return adoptRef(new SVGImageElement(document));
60 bool SVGImageElement::currentFrameHasSingleSecurityOrigin() const
62 if (RenderSVGImage* renderSVGImage = toRenderSVGImage(renderer())) {
63 if (renderSVGImage->imageResource()->hasImage()) {
64 if (Image* image = renderSVGImage->imageResource()->cachedImage()->image())
65 return image->currentFrameHasSingleSecurityOrigin();
72 bool SVGImageElement::isSupportedAttribute(const QualifiedName& attrName)
74 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
75 if (supportedAttributes.isEmpty()) {
76 SVGURIReference::addSupportedAttributes(supportedAttributes);
77 supportedAttributes.add(SVGNames::xAttr);
78 supportedAttributes.add(SVGNames::yAttr);
79 supportedAttributes.add(SVGNames::widthAttr);
80 supportedAttributes.add(SVGNames::heightAttr);
81 supportedAttributes.add(SVGNames::preserveAspectRatioAttr);
83 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
86 bool SVGImageElement::isPresentationAttribute(const QualifiedName& name) const
88 if (name == SVGNames::widthAttr || name == SVGNames::heightAttr)
90 return SVGGraphicsElement::isPresentationAttribute(name);
93 void SVGImageElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
95 if (!isSupportedAttribute(name))
96 SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style);
97 else if (name == SVGNames::widthAttr)
98 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value);
99 else if (name == SVGNames::heightAttr)
100 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, value);
103 void SVGImageElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
105 SVGParsingError parseError = NoError;
107 if (!isSupportedAttribute(name)) {
108 SVGGraphicsElement::parseAttribute(name, value);
109 } else if (name == SVGNames::xAttr) {
110 m_x->setBaseValueAsString(value, parseError);
111 } else if (name == SVGNames::yAttr) {
112 m_y->setBaseValueAsString(value, parseError);
113 } else if (name == SVGNames::widthAttr) {
114 m_width->setBaseValueAsString(value, parseError);
115 } else if (name == SVGNames::heightAttr) {
116 m_height->setBaseValueAsString(value, parseError);
117 } else if (name == SVGNames::preserveAspectRatioAttr) {
118 m_preserveAspectRatio->setBaseValueAsString(value, parseError);
119 } else if (SVGURIReference::parseAttribute(name, value, parseError)) {
121 ASSERT_NOT_REACHED();
124 reportAttributeParsingError(parseError, name, value);
127 void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName)
129 if (!isSupportedAttribute(attrName)) {
130 SVGGraphicsElement::svgAttributeChanged(attrName);
134 SVGElementInstance::InvalidationGuard invalidationGuard(this);
136 bool isLengthAttribute = attrName == SVGNames::xAttr
137 || attrName == SVGNames::yAttr
138 || attrName == SVGNames::widthAttr
139 || attrName == SVGNames::heightAttr;
141 if (isLengthAttribute)
142 updateRelativeLengthsInformation();
144 if (SVGURIReference::isKnownAttribute(attrName)) {
146 m_imageLoader.updateFromElementIgnoringPreviousError();
148 m_needsLoaderURIUpdate = true;
152 RenderObject* renderer = this->renderer();
156 if (isLengthAttribute) {
157 if (toRenderSVGImage(renderer)->updateImageViewport())
158 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
162 if (attrName == SVGNames::preserveAspectRatioAttr) {
163 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
167 ASSERT_NOT_REACHED();
170 bool SVGImageElement::selfHasRelativeLengths() const
172 return m_x->currentValue()->isRelative()
173 || m_y->currentValue()->isRelative()
174 || m_width->currentValue()->isRelative()
175 || m_height->currentValue()->isRelative();
178 RenderObject* SVGImageElement::createRenderer(RenderStyle*)
180 return new RenderSVGImage(this);
183 bool SVGImageElement::haveLoadedRequiredResources()
185 return !m_needsLoaderURIUpdate && !m_imageLoader.hasPendingActivity();
188 void SVGImageElement::attach(const AttachContext& context)
190 SVGGraphicsElement::attach(context);
192 if (RenderSVGImage* imageObj = toRenderSVGImage(renderer())) {
193 if (imageObj->imageResource()->hasImage())
196 imageObj->imageResource()->setImageResource(m_imageLoader.image());
200 Node::InsertionNotificationRequest SVGImageElement::insertedInto(ContainerNode* rootParent)
202 SVGGraphicsElement::insertedInto(rootParent);
203 if (!rootParent->inDocument())
204 return InsertionDone;
206 // We can only resolve base URIs properly after tree insertion - hence, URI mutations while
207 // detached are deferred until this point.
208 if (m_needsLoaderURIUpdate) {
209 m_imageLoader.updateFromElementIgnoringPreviousError();
210 m_needsLoaderURIUpdate = false;
212 // A previous loader update may have failed to actually fetch the image if the document
213 // was inactive. In that case, force a re-update (but don't clear previous errors).
214 if (!m_imageLoader.image())
215 m_imageLoader.updateFromElement();
218 return InsertionDone;
221 const AtomicString SVGImageElement::imageSourceURL() const
223 return AtomicString(hrefString());
226 void SVGImageElement::didMoveToNewDocument(Document& oldDocument)
228 m_imageLoader.elementDidMoveToNewDocument();
229 SVGGraphicsElement::didMoveToNewDocument(oldDocument);