1/* 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> 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/SVGImageElement.h" 25 26#include "CSSPropertyNames.h" 27#include "SVGNames.h" 28#include "XLinkNames.h" 29#include "core/rendering/RenderImageResource.h" 30#include "core/rendering/svg/RenderSVGImage.h" 31#include "core/rendering/svg/RenderSVGResource.h" 32#include "core/svg/SVGElementInstance.h" 33 34namespace WebCore { 35 36// Animated property definitions 37DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::xAttr, X, x) 38DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::yAttr, Y, y) 39DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::widthAttr, Width, width) 40DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::heightAttr, Height, height) 41DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGImageElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio) 42DEFINE_ANIMATED_STRING(SVGImageElement, XLinkNames::hrefAttr, Href, href) 43DEFINE_ANIMATED_BOOLEAN(SVGImageElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 44 45BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGImageElement) 46 REGISTER_LOCAL_ANIMATED_PROPERTY(x) 47 REGISTER_LOCAL_ANIMATED_PROPERTY(y) 48 REGISTER_LOCAL_ANIMATED_PROPERTY(width) 49 REGISTER_LOCAL_ANIMATED_PROPERTY(height) 50 REGISTER_LOCAL_ANIMATED_PROPERTY(preserveAspectRatio) 51 REGISTER_LOCAL_ANIMATED_PROPERTY(href) 52 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 53 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement) 54END_REGISTER_ANIMATED_PROPERTIES 55 56inline SVGImageElement::SVGImageElement(const QualifiedName& tagName, Document* document) 57 : SVGGraphicsElement(tagName, document) 58 , m_x(LengthModeWidth) 59 , m_y(LengthModeHeight) 60 , m_width(LengthModeWidth) 61 , m_height(LengthModeHeight) 62 , m_imageLoader(this) 63{ 64 ASSERT(hasTagName(SVGNames::imageTag)); 65 ScriptWrappable::init(this); 66 registerAnimatedPropertiesForSVGImageElement(); 67} 68 69PassRefPtr<SVGImageElement> SVGImageElement::create(const QualifiedName& tagName, Document* document) 70{ 71 return adoptRef(new SVGImageElement(tagName, document)); 72} 73 74bool SVGImageElement::isSupportedAttribute(const QualifiedName& attrName) 75{ 76 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 77 if (supportedAttributes.isEmpty()) { 78 SVGLangSpace::addSupportedAttributes(supportedAttributes); 79 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 80 SVGURIReference::addSupportedAttributes(supportedAttributes); 81 supportedAttributes.add(SVGNames::xAttr); 82 supportedAttributes.add(SVGNames::yAttr); 83 supportedAttributes.add(SVGNames::widthAttr); 84 supportedAttributes.add(SVGNames::heightAttr); 85 supportedAttributes.add(SVGNames::preserveAspectRatioAttr); 86 } 87 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 88} 89 90bool SVGImageElement::isPresentationAttribute(const QualifiedName& name) const 91{ 92 if (name == SVGNames::widthAttr || name == SVGNames::heightAttr) 93 return true; 94 return SVGGraphicsElement::isPresentationAttribute(name); 95} 96 97void SVGImageElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) 98{ 99 if (!isSupportedAttribute(name)) 100 SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style); 101 else if (name == SVGNames::widthAttr) 102 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value); 103 else if (name == SVGNames::heightAttr) 104 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, value); 105} 106 107void SVGImageElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 108{ 109 SVGParsingError parseError = NoError; 110 111 if (!isSupportedAttribute(name)) 112 SVGGraphicsElement::parseAttribute(name, value); 113 else if (name == SVGNames::xAttr) 114 setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); 115 else if (name == SVGNames::yAttr) 116 setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); 117 else if (name == SVGNames::preserveAspectRatioAttr) { 118 SVGPreserveAspectRatio preserveAspectRatio; 119 preserveAspectRatio.parse(value); 120 setPreserveAspectRatioBaseValue(preserveAspectRatio); 121 } else if (name == SVGNames::widthAttr) 122 setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths)); 123 else if (name == SVGNames::heightAttr) 124 setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths)); 125 else if (SVGLangSpace::parseAttribute(name, value) 126 || SVGExternalResourcesRequired::parseAttribute(name, value) 127 || SVGURIReference::parseAttribute(name, value)) { 128 } else 129 ASSERT_NOT_REACHED(); 130 131 reportAttributeParsingError(parseError, name, value); 132} 133 134void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName) 135{ 136 if (!isSupportedAttribute(attrName)) { 137 SVGGraphicsElement::svgAttributeChanged(attrName); 138 return; 139 } 140 141 SVGElementInstance::InvalidationGuard invalidationGuard(this); 142 143 bool isLengthAttribute = attrName == SVGNames::xAttr 144 || attrName == SVGNames::yAttr 145 || attrName == SVGNames::widthAttr 146 || attrName == SVGNames::heightAttr; 147 148 if (isLengthAttribute) 149 updateRelativeLengthsInformation(); 150 151 if (SVGURIReference::isKnownAttribute(attrName)) { 152 m_imageLoader.updateFromElementIgnoringPreviousError(); 153 return; 154 } 155 156 RenderObject* renderer = this->renderer(); 157 if (!renderer) 158 return; 159 160 if (isLengthAttribute) { 161 if (toRenderSVGImage(renderer)->updateImageViewport()) 162 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 163 return; 164 } 165 166 if (attrName == SVGNames::preserveAspectRatioAttr 167 || SVGLangSpace::isKnownAttribute(attrName) 168 || SVGExternalResourcesRequired::isKnownAttribute(attrName)) { 169 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 170 return; 171 } 172 173 ASSERT_NOT_REACHED(); 174} 175 176bool SVGImageElement::selfHasRelativeLengths() const 177{ 178 return xCurrentValue().isRelative() 179 || yCurrentValue().isRelative() 180 || widthCurrentValue().isRelative() 181 || heightCurrentValue().isRelative(); 182} 183 184RenderObject* SVGImageElement::createRenderer(RenderStyle*) 185{ 186 return new RenderSVGImage(this); 187} 188 189bool SVGImageElement::haveLoadedRequiredResources() 190{ 191 return !externalResourcesRequiredBaseValue() || !m_imageLoader.hasPendingActivity(); 192} 193 194void SVGImageElement::attach(const AttachContext& context) 195{ 196 SVGGraphicsElement::attach(context); 197 198 if (RenderSVGImage* imageObj = toRenderSVGImage(renderer())) { 199 if (imageObj->imageResource()->hasImage()) 200 return; 201 202 imageObj->imageResource()->setImageResource(m_imageLoader.image()); 203 } 204} 205 206Node::InsertionNotificationRequest SVGImageElement::insertedInto(ContainerNode* rootParent) 207{ 208 SVGGraphicsElement::insertedInto(rootParent); 209 if (!rootParent->inDocument()) 210 return InsertionDone; 211 // Update image loader, as soon as we're living in the tree. 212 // We can only resolve base URIs properly, after that! 213 m_imageLoader.updateFromElement(); 214 return InsertionDone; 215} 216 217const AtomicString& SVGImageElement::imageSourceURL() const 218{ 219 return getAttribute(XLinkNames::hrefAttr); 220} 221 222void SVGImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 223{ 224 SVGGraphicsElement::addSubresourceAttributeURLs(urls); 225 226 addSubresourceURL(urls, document()->completeURL(hrefCurrentValue())); 227} 228 229void SVGImageElement::didMoveToNewDocument(Document* oldDocument) 230{ 231 m_imageLoader.elementDidMoveToNewDocument(); 232 SVGGraphicsElement::didMoveToNewDocument(oldDocument); 233} 234 235} 236