Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2006 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Nikolas Zimmermann <zimmermann (at) kde.org>
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 #include "core/svg/SVGForeignObjectElement.h"
     23 
     24 #include "core/XLinkNames.h"
     25 #include "core/frame/UseCounter.h"
     26 #include "core/rendering/svg/RenderSVGForeignObject.h"
     27 #include "core/rendering/svg/RenderSVGResource.h"
     28 #include "core/svg/SVGLength.h"
     29 #include "wtf/Assertions.h"
     30 
     31 namespace WebCore {
     32 
     33 inline SVGForeignObjectElement::SVGForeignObjectElement(Document& document)
     34     : SVGGraphicsElement(SVGNames::foreignObjectTag, document)
     35     , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
     36     , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
     37     , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth), ForbidNegativeLengths))
     38     , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight), ForbidNegativeLengths))
     39 {
     40     ScriptWrappable::init(this);
     41 
     42     addToPropertyMap(m_x);
     43     addToPropertyMap(m_y);
     44     addToPropertyMap(m_width);
     45     addToPropertyMap(m_height);
     46 
     47     UseCounter::count(document, UseCounter::SVGForeignObjectElement);
     48 }
     49 
     50 DEFINE_NODE_FACTORY(SVGForeignObjectElement)
     51 
     52 bool SVGForeignObjectElement::isSupportedAttribute(const QualifiedName& attrName)
     53 {
     54     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
     55     if (supportedAttributes.isEmpty()) {
     56         supportedAttributes.add(SVGNames::xAttr);
     57         supportedAttributes.add(SVGNames::yAttr);
     58         supportedAttributes.add(SVGNames::widthAttr);
     59         supportedAttributes.add(SVGNames::heightAttr);
     60     }
     61     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
     62 }
     63 
     64 void SVGForeignObjectElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
     65 {
     66     SVGParsingError parseError = NoError;
     67 
     68     if (!isSupportedAttribute(name))
     69         SVGGraphicsElement::parseAttribute(name, value);
     70     else if (name == SVGNames::xAttr)
     71         m_x->setBaseValueAsString(value, parseError);
     72     else if (name == SVGNames::yAttr)
     73         m_y->setBaseValueAsString(value, parseError);
     74     else if (name == SVGNames::widthAttr)
     75         m_width->setBaseValueAsString(value, parseError);
     76     else if (name == SVGNames::heightAttr)
     77         m_height->setBaseValueAsString(value, parseError);
     78     else
     79         ASSERT_NOT_REACHED();
     80 
     81     reportAttributeParsingError(parseError, name, value);
     82 }
     83 
     84 bool SVGForeignObjectElement::isPresentationAttribute(const QualifiedName& name) const
     85 {
     86     if (name == SVGNames::widthAttr || name == SVGNames::heightAttr)
     87         return true;
     88     return SVGGraphicsElement::isPresentationAttribute(name);
     89 }
     90 
     91 void SVGForeignObjectElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
     92 {
     93     if (name == SVGNames::widthAttr || name == SVGNames::heightAttr) {
     94         RefPtr<SVGLength> length = SVGLength::create(LengthModeOther);
     95         TrackExceptionState exceptionState;
     96         length->setValueAsString(value, exceptionState);
     97         if (!exceptionState.hadException()) {
     98             if (name == SVGNames::widthAttr)
     99                 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value);
    100             else if (name == SVGNames::heightAttr)
    101                 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, value);
    102         }
    103     } else {
    104         SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style);
    105     }
    106 }
    107 
    108 void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName)
    109 {
    110     if (!isSupportedAttribute(attrName)) {
    111         SVGGraphicsElement::svgAttributeChanged(attrName);
    112         return;
    113     }
    114 
    115     if (attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
    116         invalidateSVGPresentationAttributeStyle();
    117         setNeedsStyleRecalc(LocalStyleChange);
    118     }
    119 
    120     SVGElement::InvalidationGuard invalidationGuard(this);
    121 
    122     bool isLengthAttribute = attrName == SVGNames::xAttr
    123                           || attrName == SVGNames::yAttr
    124                           || attrName == SVGNames::widthAttr
    125                           || attrName == SVGNames::heightAttr;
    126 
    127     if (isLengthAttribute)
    128         updateRelativeLengthsInformation();
    129 
    130     if (RenderObject* renderer = this->renderer())
    131         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
    132 }
    133 
    134 RenderObject* SVGForeignObjectElement::createRenderer(RenderStyle*)
    135 {
    136     return new RenderSVGForeignObject(this);
    137 }
    138 
    139 bool SVGForeignObjectElement::rendererIsNeeded(const RenderStyle& style)
    140 {
    141     // Suppress foreignObject renderers in SVG hidden containers.
    142     // (https://bugs.webkit.org/show_bug.cgi?id=87297)
    143     // Note that we currently do not support foreignObject instantiation via <use>, hence it is safe
    144     // to use parentElement() here. If that changes, this method should be updated to use
    145     // parentOrShadowHostElement() instead.
    146     Element* ancestor = parentElement();
    147     while (ancestor && ancestor->isSVGElement()) {
    148         if (ancestor->renderer() && ancestor->renderer()->isSVGHiddenContainer())
    149             return false;
    150 
    151         ancestor = ancestor->parentElement();
    152     }
    153 
    154     return SVGGraphicsElement::rendererIsNeeded(style);
    155 }
    156 
    157 bool SVGForeignObjectElement::selfHasRelativeLengths() const
    158 {
    159     return m_x->currentValue()->isRelative()
    160         || m_y->currentValue()->isRelative()
    161         || m_width->currentValue()->isRelative()
    162         || m_height->currentValue()->isRelative();
    163 }
    164 
    165 }
    166