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 #if ENABLE(SVG) 25 #include "SVGImageElement.h" 26 27 #include "Attribute.h" 28 #include "CSSPropertyNames.h" 29 #include "RenderImageResource.h" 30 #include "RenderSVGImage.h" 31 #include "RenderSVGResource.h" 32 #include "SVGNames.h" 33 #include "SVGSVGElement.h" 34 #include "XLinkNames.h" 35 36 namespace WebCore { 37 38 // Animated property definitions 39 DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::xAttr, X, x) 40 DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::yAttr, Y, y) 41 DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::widthAttr, Width, width) 42 DEFINE_ANIMATED_LENGTH(SVGImageElement, SVGNames::heightAttr, Height, height) 43 DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGImageElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio) 44 DEFINE_ANIMATED_STRING(SVGImageElement, XLinkNames::hrefAttr, Href, href) 45 DEFINE_ANIMATED_BOOLEAN(SVGImageElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 46 47 inline SVGImageElement::SVGImageElement(const QualifiedName& tagName, Document* document) 48 : SVGStyledTransformableElement(tagName, document) 49 , m_x(LengthModeWidth) 50 , m_y(LengthModeHeight) 51 , m_width(LengthModeWidth) 52 , m_height(LengthModeHeight) 53 , m_imageLoader(this) 54 { 55 } 56 57 PassRefPtr<SVGImageElement> SVGImageElement::create(const QualifiedName& tagName, Document* document) 58 { 59 return adoptRef(new SVGImageElement(tagName, document)); 60 } 61 62 void SVGImageElement::parseMappedAttribute(Attribute* attr) 63 { 64 if (attr->name() == SVGNames::xAttr) 65 setXBaseValue(SVGLength(LengthModeWidth, attr->value())); 66 else if (attr->name() == SVGNames::yAttr) 67 setYBaseValue(SVGLength(LengthModeHeight, attr->value())); 68 else if (attr->name() == SVGNames::preserveAspectRatioAttr) 69 SVGPreserveAspectRatio::parsePreserveAspectRatio(this, attr->value()); 70 else if (attr->name() == SVGNames::widthAttr) { 71 setWidthBaseValue(SVGLength(LengthModeWidth, attr->value())); 72 addCSSProperty(attr, CSSPropertyWidth, attr->value()); 73 if (widthBaseValue().value(this) < 0.0) 74 document()->accessSVGExtensions()->reportError("A negative value for image attribute <width> is not allowed"); 75 } else if (attr->name() == SVGNames::heightAttr) { 76 setHeightBaseValue(SVGLength(LengthModeHeight, attr->value())); 77 addCSSProperty(attr, CSSPropertyHeight, attr->value()); 78 if (heightBaseValue().value(this) < 0.0) 79 document()->accessSVGExtensions()->reportError("A negative value for image attribute <height> is not allowed"); 80 } else { 81 if (SVGTests::parseMappedAttribute(attr)) 82 return; 83 if (SVGLangSpace::parseMappedAttribute(attr)) 84 return; 85 if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) 86 return; 87 if (SVGURIReference::parseMappedAttribute(attr)) 88 return; 89 SVGStyledTransformableElement::parseMappedAttribute(attr); 90 } 91 } 92 93 void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName) 94 { 95 SVGStyledTransformableElement::svgAttributeChanged(attrName); 96 97 if (SVGURIReference::isKnownAttribute(attrName)) 98 m_imageLoader.updateFromElementIgnoringPreviousError(); 99 100 bool isLengthAttribute = attrName == SVGNames::xAttr 101 || attrName == SVGNames::yAttr 102 || attrName == SVGNames::widthAttr 103 || attrName == SVGNames::heightAttr; 104 105 if (isLengthAttribute) 106 updateRelativeLengthsInformation(); 107 108 if (SVGTests::handleAttributeChange(this, attrName)) 109 return; 110 111 RenderObject* renderer = this->renderer(); 112 if (!renderer) 113 return; 114 115 if (isLengthAttribute) { 116 renderer->updateFromElement(); 117 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false); 118 return; 119 } 120 121 if (attrName == SVGNames::preserveAspectRatioAttr 122 || SVGLangSpace::isKnownAttribute(attrName) 123 || SVGExternalResourcesRequired::isKnownAttribute(attrName)) 124 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 125 } 126 127 void SVGImageElement::synchronizeProperty(const QualifiedName& attrName) 128 { 129 SVGStyledTransformableElement::synchronizeProperty(attrName); 130 131 if (attrName == anyQName()) { 132 synchronizeX(); 133 synchronizeY(); 134 synchronizeWidth(); 135 synchronizeHeight(); 136 synchronizePreserveAspectRatio(); 137 synchronizeExternalResourcesRequired(); 138 synchronizeHref(); 139 SVGTests::synchronizeProperties(this, attrName); 140 return; 141 } 142 143 if (attrName == SVGNames::xAttr) 144 synchronizeX(); 145 else if (attrName == SVGNames::yAttr) 146 synchronizeY(); 147 else if (attrName == SVGNames::widthAttr) 148 synchronizeWidth(); 149 else if (attrName == SVGNames::heightAttr) 150 synchronizeHeight(); 151 else if (attrName == SVGNames::preserveAspectRatioAttr) 152 synchronizePreserveAspectRatio(); 153 else if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) 154 synchronizeExternalResourcesRequired(); 155 else if (SVGURIReference::isKnownAttribute(attrName)) 156 synchronizeHref(); 157 else if (SVGTests::isKnownAttribute(attrName)) 158 SVGTests::synchronizeProperties(this, attrName); 159 } 160 161 AttributeToPropertyTypeMap& SVGImageElement::attributeToPropertyTypeMap() 162 { 163 DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ()); 164 return s_attributeToPropertyTypeMap; 165 } 166 167 void SVGImageElement::fillAttributeToPropertyTypeMap() 168 { 169 AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap(); 170 171 SVGStyledTransformableElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap); 172 attributeToPropertyTypeMap.set(SVGNames::xAttr, AnimatedLength); 173 attributeToPropertyTypeMap.set(SVGNames::yAttr, AnimatedLength); 174 attributeToPropertyTypeMap.set(SVGNames::widthAttr, AnimatedLength); 175 attributeToPropertyTypeMap.set(SVGNames::heightAttr, AnimatedLength); 176 attributeToPropertyTypeMap.set(SVGNames::preserveAspectRatioAttr, AnimatedPreserveAspectRatio); 177 attributeToPropertyTypeMap.set(XLinkNames::hrefAttr, AnimatedString); 178 } 179 180 bool SVGImageElement::selfHasRelativeLengths() const 181 { 182 return x().isRelative() 183 || y().isRelative() 184 || width().isRelative() 185 || height().isRelative(); 186 } 187 188 RenderObject* SVGImageElement::createRenderer(RenderArena* arena, RenderStyle*) 189 { 190 return new (arena) RenderSVGImage(this); 191 } 192 193 bool SVGImageElement::haveLoadedRequiredResources() 194 { 195 return !externalResourcesRequiredBaseValue() || m_imageLoader.haveFiredLoadEvent(); 196 } 197 198 void SVGImageElement::attach() 199 { 200 SVGStyledTransformableElement::attach(); 201 202 if (RenderSVGImage* imageObj = toRenderSVGImage(renderer())) { 203 if (imageObj->imageResource()->hasImage()) 204 return; 205 206 imageObj->imageResource()->setCachedImage(m_imageLoader.image()); 207 } 208 } 209 210 void SVGImageElement::insertedIntoDocument() 211 { 212 SVGStyledTransformableElement::insertedIntoDocument(); 213 214 // Update image loader, as soon as we're living in the tree. 215 // We can only resolve base URIs properly, after that! 216 m_imageLoader.updateFromElement(); 217 } 218 219 const QualifiedName& SVGImageElement::imageSourceAttributeName() const 220 { 221 return XLinkNames::hrefAttr; 222 } 223 224 void SVGImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 225 { 226 SVGStyledTransformableElement::addSubresourceAttributeURLs(urls); 227 228 addSubresourceURL(urls, document()->completeURL(href())); 229 } 230 231 void SVGImageElement::willMoveToNewOwnerDocument() 232 { 233 m_imageLoader.elementWillMoveToNewOwnerDocument(); 234 SVGStyledTransformableElement::willMoveToNewOwnerDocument(); 235 } 236 237 } 238 239 #endif // ENABLE(SVG) 240