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.
25 #include "SVGImageElement.h"
27 #include "Attribute.h"
28 #include "CSSPropertyNames.h"
29 #include "RenderImageResource.h"
30 #include "RenderSVGImage.h"
31 #include "RenderSVGResource.h"
32 #include "SVGElementInstance.h"
34 #include "SVGSVGElement.h"
35 #include "XLinkNames.h"
39 // Animated property definitions
40 DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::xAttr, X, x)
41 DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::yAttr, Y, y)
42 DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::widthAttr, Width, width)
43 DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::heightAttr, Height, height)
44 DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGImageElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio)
45 DEFINE_ANIMATED_STRING(SVGImageElement, XLinkNames::hrefAttr, Href, href)
46 DEFINE_ANIMATED_BOOLEAN(SVGImageElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
48 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGImageElement)
49 REGISTER_LOCAL_ANIMATED_PROPERTY(x)
50 REGISTER_LOCAL_ANIMATED_PROPERTY(y)
51 REGISTER_LOCAL_ANIMATED_PROPERTY(width)
52 REGISTER_LOCAL_ANIMATED_PROPERTY(height)
53 REGISTER_LOCAL_ANIMATED_PROPERTY(preserveAspectRatio)
54 REGISTER_LOCAL_ANIMATED_PROPERTY(href)
55 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
56 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGStyledTransformableElement)
57 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests)
58 END_REGISTER_ANIMATED_PROPERTIES
60 inline SVGImageElement::SVGImageElement(const QualifiedName& tagName, Document* document)
61 : SVGStyledTransformableElement(tagName, document)
62 , m_x(LengthModeWidth)
63 , m_y(LengthModeHeight)
64 , m_width(LengthModeWidth)
65 , m_height(LengthModeHeight)
68 ASSERT(hasTagName(SVGNames::imageTag));
69 registerAnimatedPropertiesForSVGImageElement();
72 PassRefPtr<SVGImageElement> SVGImageElement::create(const QualifiedName& tagName, Document* document)
74 return adoptRef(new SVGImageElement(tagName, document));
77 bool SVGImageElement::isSupportedAttribute(const QualifiedName& attrName)
79 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
80 if (supportedAttributes.isEmpty()) {
81 SVGTests::addSupportedAttributes(supportedAttributes);
82 SVGLangSpace::addSupportedAttributes(supportedAttributes);
83 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
84 SVGURIReference::addSupportedAttributes(supportedAttributes);
85 supportedAttributes.add(SVGNames::xAttr);
86 supportedAttributes.add(SVGNames::yAttr);
87 supportedAttributes.add(SVGNames::widthAttr);
88 supportedAttributes.add(SVGNames::heightAttr);
89 supportedAttributes.add(SVGNames::preserveAspectRatioAttr);
91 return supportedAttributes.contains(attrName);
94 void SVGImageElement::parseMappedAttribute(Attribute* attr)
96 SVGParsingError parseError = NoError;
98 if (!isSupportedAttribute(attr->name()))
99 SVGStyledTransformableElement::parseMappedAttribute(attr);
100 else if (attr->name() == SVGNames::xAttr)
101 setXBaseValue(SVGLength::construct(LengthModeWidth, attr->value(), parseError));
102 else if (attr->name() == SVGNames::yAttr)
103 setYBaseValue(SVGLength::construct(LengthModeHeight, attr->value(), parseError));
104 else if (attr->name() == SVGNames::preserveAspectRatioAttr)
105 SVGPreserveAspectRatio::parsePreserveAspectRatio(this, attr->value());
106 else if (attr->name() == SVGNames::widthAttr) {
107 setWidthBaseValue(SVGLength::construct(LengthModeWidth, attr->value(), parseError, ForbidNegativeLengths));
108 addCSSProperty(attr, CSSPropertyWidth, attr->value());
109 } else if (attr->name() == SVGNames::heightAttr) {
110 setHeightBaseValue(SVGLength::construct(LengthModeHeight, attr->value(), parseError, ForbidNegativeLengths));
111 addCSSProperty(attr, CSSPropertyHeight, attr->value());
112 } else if (SVGTests::parseMappedAttribute(attr)
113 || SVGLangSpace::parseMappedAttribute(attr)
114 || SVGExternalResourcesRequired::parseMappedAttribute(attr)
115 || SVGURIReference::parseMappedAttribute(attr)) {
117 ASSERT_NOT_REACHED();
119 reportAttributeParsingError(parseError, attr);
122 void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName)
124 if (!isSupportedAttribute(attrName)) {
125 SVGStyledTransformableElement::svgAttributeChanged(attrName);
129 SVGElementInstance::InvalidationGuard invalidationGuard(this);
131 bool isLengthAttribute = attrName == SVGNames::xAttr
132 || attrName == SVGNames::yAttr
133 || attrName == SVGNames::widthAttr
134 || attrName == SVGNames::heightAttr;
136 if (isLengthAttribute)
137 updateRelativeLengthsInformation();
139 if (SVGTests::handleAttributeChange(this, attrName))
142 if (SVGURIReference::isKnownAttribute(attrName)) {
143 m_imageLoader.updateFromElementIgnoringPreviousError();
147 RenderObject* renderer = this->renderer();
151 if (isLengthAttribute) {
152 renderer->updateFromElement();
153 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
157 if (attrName == SVGNames::preserveAspectRatioAttr
158 || SVGLangSpace::isKnownAttribute(attrName)
159 || SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
160 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
164 ASSERT_NOT_REACHED();
167 bool SVGImageElement::selfHasRelativeLengths() const
169 return x().isRelative()
171 || width().isRelative()
172 || height().isRelative();
175 RenderObject* SVGImageElement::createRenderer(RenderArena* arena, RenderStyle*)
177 return new (arena) RenderSVGImage(this);
180 bool SVGImageElement::haveLoadedRequiredResources()
182 return !externalResourcesRequiredBaseValue() || m_imageLoader.haveFiredLoadEvent();
185 void SVGImageElement::attach()
187 SVGStyledTransformableElement::attach();
189 if (RenderSVGImage* imageObj = toRenderSVGImage(renderer())) {
190 if (imageObj->imageResource()->hasImage())
193 imageObj->imageResource()->setCachedImage(m_imageLoader.image());
197 void SVGImageElement::insertedIntoDocument()
199 SVGStyledTransformableElement::insertedIntoDocument();
201 // Update image loader, as soon as we're living in the tree.
202 // We can only resolve base URIs properly, after that!
203 m_imageLoader.updateFromElement();
206 const QualifiedName& SVGImageElement::imageSourceAttributeName() const
208 return XLinkNames::hrefAttr;
211 void SVGImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
213 SVGStyledTransformableElement::addSubresourceAttributeURLs(urls);
215 addSubresourceURL(urls, document()->completeURL(href()));
218 void SVGImageElement::willMoveToNewOwnerDocument()
220 m_imageLoader.elementWillMoveToNewOwnerDocument();
221 SVGStyledTransformableElement::willMoveToNewOwnerDocument();
226 #endif // ENABLE(SVG)