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#include "SVGImageElement.h" 24 25#include "Attribute.h" 26#include "CSSPropertyNames.h" 27#include "RenderImageResource.h" 28#include "RenderSVGImage.h" 29#include "RenderSVGResource.h" 30#include "SVGElementInstance.h" 31#include "SVGNames.h" 32#include "SVGSVGElement.h" 33#include "XLinkNames.h" 34#include <wtf/NeverDestroyed.h> 35 36namespace WebCore { 37 38// Animated property definitions 39DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::xAttr, X, x) 40DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::yAttr, Y, y) 41DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::widthAttr, Width, width) 42DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::heightAttr, Height, height) 43DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGImageElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio) 44DEFINE_ANIMATED_STRING(SVGImageElement, XLinkNames::hrefAttr, Href, href) 45DEFINE_ANIMATED_BOOLEAN(SVGImageElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 46 47BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGImageElement) 48 REGISTER_LOCAL_ANIMATED_PROPERTY(x) 49 REGISTER_LOCAL_ANIMATED_PROPERTY(y) 50 REGISTER_LOCAL_ANIMATED_PROPERTY(width) 51 REGISTER_LOCAL_ANIMATED_PROPERTY(height) 52 REGISTER_LOCAL_ANIMATED_PROPERTY(preserveAspectRatio) 53 REGISTER_LOCAL_ANIMATED_PROPERTY(href) 54 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 55 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement) 56END_REGISTER_ANIMATED_PROPERTIES 57 58inline SVGImageElement::SVGImageElement(const QualifiedName& tagName, Document& document) 59 : SVGGraphicsElement(tagName, document) 60 , m_x(LengthModeWidth) 61 , m_y(LengthModeHeight) 62 , m_width(LengthModeWidth) 63 , m_height(LengthModeHeight) 64 , m_imageLoader(*this) 65{ 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 static NeverDestroyed<HashSet<QualifiedName>> supportedAttributes; 77 if (supportedAttributes.get().isEmpty()) { 78 SVGLangSpace::addSupportedAttributes(supportedAttributes); 79 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 80 SVGURIReference::addSupportedAttributes(supportedAttributes); 81 supportedAttributes.get().add(SVGNames::xAttr); 82 supportedAttributes.get().add(SVGNames::yAttr); 83 supportedAttributes.get().add(SVGNames::widthAttr); 84 supportedAttributes.get().add(SVGNames::heightAttr); 85 supportedAttributes.get().add(SVGNames::preserveAspectRatioAttr); 86 } 87 return supportedAttributes.get().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, MutableStyleProperties& 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 auto 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 x().isRelative() 179 || y().isRelative() 180 || width().isRelative() 181 || height().isRelative(); 182} 183 184RenderPtr<RenderElement> SVGImageElement::createElementRenderer(PassRef<RenderStyle> style) 185{ 186 return createRenderer<RenderSVGImage>(*this, WTF::move(style)); 187} 188 189bool SVGImageElement::haveLoadedRequiredResources() 190{ 191 return !externalResourcesRequiredBaseValue() || !m_imageLoader.hasPendingActivity(); 192} 193 194void SVGImageElement::didAttachRenderers() 195{ 196 if (RenderSVGImage* imageObj = toRenderSVGImage(renderer())) { 197 if (imageObj->imageResource().hasImage()) 198 return; 199 200 imageObj->imageResource().setCachedImage(m_imageLoader.image()); 201 } 202} 203 204Node::InsertionNotificationRequest SVGImageElement::insertedInto(ContainerNode& rootParent) 205{ 206 SVGGraphicsElement::insertedInto(rootParent); 207 if (!rootParent.inDocument()) 208 return InsertionDone; 209 // Update image loader, as soon as we're living in the tree. 210 // We can only resolve base URIs properly, after that! 211 m_imageLoader.updateFromElement(); 212 return InsertionDone; 213} 214 215const AtomicString& SVGImageElement::imageSourceURL() const 216{ 217 return getAttribute(XLinkNames::hrefAttr); 218} 219 220void SVGImageElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const 221{ 222 SVGGraphicsElement::addSubresourceAttributeURLs(urls); 223 224 addSubresourceURL(urls, document().completeURL(href())); 225} 226 227void SVGImageElement::didMoveToNewDocument(Document* oldDocument) 228{ 229 m_imageLoader.elementDidMoveToNewDocument(); 230 SVGGraphicsElement::didMoveToNewDocument(oldDocument); 231} 232 233} 234