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 blink {
     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     addToPropertyMap(m_x);
     41     addToPropertyMap(m_y);
     42     addToPropertyMap(m_width);
     43     addToPropertyMap(m_height);
     44 
     45     UseCounter::count(document, UseCounter::SVGForeignObjectElement);
     46 }
     47 
     48 DEFINE_NODE_FACTORY(SVGForeignObjectElement)
     49 
     50 bool SVGForeignObjectElement::isSupportedAttribute(const QualifiedName& attrName)
     51 {
     52     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
     53     if (supportedAttributes.isEmpty()) {
     54         supportedAttributes.add(SVGNames::xAttr);
     55         supportedAttributes.add(SVGNames::yAttr);
     56         supportedAttributes.add(SVGNames::widthAttr);
     57         supportedAttributes.add(SVGNames::heightAttr);
     58     }
     59     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
     60 }
     61 
     62 void SVGForeignObjectElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
     63 {
     64     parseAttributeNew(name, value);
     65 }
     66 
     67 bool SVGForeignObjectElement::isPresentationAttribute(const QualifiedName& name) const
     68 {
     69     if (name == SVGNames::widthAttr || name == SVGNames::heightAttr)
     70         return true;
     71     return SVGGraphicsElement::isPresentationAttribute(name);
     72 }
     73 
     74 void SVGForeignObjectElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
     75 {
     76     if (name == SVGNames::widthAttr || name == SVGNames::heightAttr) {
     77         RefPtr<SVGLength> length = SVGLength::create(LengthModeOther);
     78         TrackExceptionState exceptionState;
     79         length->setValueAsString(value, exceptionState);
     80         if (!exceptionState.hadException()) {
     81             if (name == SVGNames::widthAttr)
     82                 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value);
     83             else if (name == SVGNames::heightAttr)
     84                 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, value);
     85         }
     86     } else {
     87         SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style);
     88     }
     89 }
     90 
     91 void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName)
     92 {
     93     if (!isSupportedAttribute(attrName)) {
     94         SVGGraphicsElement::svgAttributeChanged(attrName);
     95         return;
     96     }
     97 
     98     if (attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
     99         invalidateSVGPresentationAttributeStyle();
    100         setNeedsStyleRecalc(LocalStyleChange);
    101     }
    102 
    103     SVGElement::InvalidationGuard invalidationGuard(this);
    104 
    105     bool isLengthAttribute = attrName == SVGNames::xAttr
    106                           || attrName == SVGNames::yAttr
    107                           || attrName == SVGNames::widthAttr
    108                           || attrName == SVGNames::heightAttr;
    109 
    110     if (isLengthAttribute)
    111         updateRelativeLengthsInformation();
    112 
    113     if (RenderObject* renderer = this->renderer())
    114         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
    115 }
    116 
    117 RenderObject* SVGForeignObjectElement::createRenderer(RenderStyle*)
    118 {
    119     return new RenderSVGForeignObject(this);
    120 }
    121 
    122 bool SVGForeignObjectElement::rendererIsNeeded(const RenderStyle& style)
    123 {
    124     // Suppress foreignObject renderers in SVG hidden containers.
    125     // (https://bugs.webkit.org/show_bug.cgi?id=87297)
    126     // Note that we currently do not support foreignObject instantiation via <use>, hence it is safe
    127     // to use parentElement() here. If that changes, this method should be updated to use
    128     // parentOrShadowHostElement() instead.
    129     Element* ancestor = parentElement();
    130     while (ancestor && ancestor->isSVGElement()) {
    131         if (ancestor->renderer() && ancestor->renderer()->isSVGHiddenContainer())
    132             return false;
    133 
    134         ancestor = ancestor->parentElement();
    135     }
    136 
    137     return SVGGraphicsElement::rendererIsNeeded(style);
    138 }
    139 
    140 bool SVGForeignObjectElement::selfHasRelativeLengths() const
    141 {
    142     return m_x->currentValue()->isRelative()
    143         || m_y->currentValue()->isRelative()
    144         || m_width->currentValue()->isRelative()
    145         || m_height->currentValue()->isRelative();
    146 }
    147 
    148 } // namespace blink
    149