Home | History | Annotate | Download | only in svg
      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