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 Rob Buis <buis (at) kde.org>
      4  * Copyright (C) 2005 Alexander Kellett <lypanov (at) kde.org>
      5  * Copyright (C) 2009 Dirk Schulze <krit (at) webkit.org>
      6  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  */
     23 
     24 #include "config.h"
     25 
     26 #include "core/svg/SVGMaskElement.h"
     27 
     28 #include "core/rendering/svg/RenderSVGResourceMasker.h"
     29 
     30 namespace WebCore {
     31 
     32 inline SVGMaskElement::SVGMaskElement(Document& document)
     33     : SVGElement(SVGNames::maskTag, document)
     34     , SVGTests(this)
     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     , m_maskUnits(SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>::create(this, SVGNames::maskUnitsAttr, SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX))
     40     , m_maskContentUnits(SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>::create(this, SVGNames::maskContentUnitsAttr, SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE))
     41 {
     42     ScriptWrappable::init(this);
     43 
     44     // Spec: If the x/y attribute is not specified, the effect is as if a value of "-10%" were specified.
     45     m_x->setDefaultValueAsString("-10%");
     46     m_y->setDefaultValueAsString("-10%");
     47 
     48     // Spec: If the width/height attribute is not specified, the effect is as if a value of "120%" were specified.
     49     m_width->setDefaultValueAsString("120%");
     50     m_height->setDefaultValueAsString("120%");
     51 
     52     addToPropertyMap(m_x);
     53     addToPropertyMap(m_y);
     54     addToPropertyMap(m_width);
     55     addToPropertyMap(m_height);
     56     addToPropertyMap(m_maskUnits);
     57     addToPropertyMap(m_maskContentUnits);
     58 }
     59 
     60 DEFINE_NODE_FACTORY(SVGMaskElement)
     61 
     62 bool SVGMaskElement::isSupportedAttribute(const QualifiedName& attrName)
     63 {
     64     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
     65     if (supportedAttributes.isEmpty()) {
     66         SVGTests::addSupportedAttributes(supportedAttributes);
     67         supportedAttributes.add(SVGNames::maskUnitsAttr);
     68         supportedAttributes.add(SVGNames::maskContentUnitsAttr);
     69         supportedAttributes.add(SVGNames::xAttr);
     70         supportedAttributes.add(SVGNames::yAttr);
     71         supportedAttributes.add(SVGNames::widthAttr);
     72         supportedAttributes.add(SVGNames::heightAttr);
     73     }
     74     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
     75 }
     76 
     77 void SVGMaskElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
     78 {
     79     SVGParsingError parseError = NoError;
     80 
     81     if (!isSupportedAttribute(name))
     82         SVGElement::parseAttribute(name, value);
     83     else if (name == SVGNames::maskUnitsAttr)
     84         m_maskUnits->setBaseValueAsString(value, parseError);
     85     else if (name == SVGNames::maskContentUnitsAttr)
     86         m_maskContentUnits->setBaseValueAsString(value, parseError);
     87     else if (name == SVGNames::xAttr)
     88         m_x->setBaseValueAsString(value, parseError);
     89     else if (name == SVGNames::yAttr)
     90         m_y->setBaseValueAsString(value, parseError);
     91     else if (name == SVGNames::widthAttr)
     92         m_width->setBaseValueAsString(value, parseError);
     93     else if (name == SVGNames::heightAttr)
     94         m_height->setBaseValueAsString(value, parseError);
     95     else if (SVGTests::parseAttribute(name, value)) {
     96     } else
     97         ASSERT_NOT_REACHED();
     98 
     99     reportAttributeParsingError(parseError, name, value);
    100 }
    101 
    102 void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName)
    103 {
    104     if (!isSupportedAttribute(attrName)) {
    105         SVGElement::svgAttributeChanged(attrName);
    106         return;
    107     }
    108 
    109     SVGElement::InvalidationGuard invalidationGuard(this);
    110 
    111     if (attrName == SVGNames::xAttr
    112         || attrName == SVGNames::yAttr
    113         || attrName == SVGNames::widthAttr
    114         || attrName == SVGNames::heightAttr)
    115         updateRelativeLengthsInformation();
    116 
    117     RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
    118     if (renderer)
    119         renderer->invalidateCacheAndMarkForLayout();
    120 }
    121 
    122 void SVGMaskElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
    123 {
    124     SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
    125 
    126     if (changedByParser)
    127         return;
    128 
    129     if (RenderObject* object = renderer())
    130         object->setNeedsLayoutAndFullPaintInvalidation();
    131 }
    132 
    133 RenderObject* SVGMaskElement::createRenderer(RenderStyle*)
    134 {
    135     return new RenderSVGResourceMasker(this);
    136 }
    137 
    138 bool SVGMaskElement::selfHasRelativeLengths() const
    139 {
    140     return m_x->currentValue()->isRelative()
    141         || m_y->currentValue()->isRelative()
    142         || m_width->currentValue()->isRelative()
    143         || m_height->currentValue()->isRelative();
    144 }
    145 
    146 }
    147