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