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 #include "core/svg/SVGElementInstance.h"
     30 
     31 namespace WebCore {
     32 
     33 // Animated property definitions
     34 DEFINE_ANIMATED_ENUMERATION(SVGMaskElement, SVGNames::maskUnitsAttr, MaskUnits, maskUnits, SVGUnitTypes::SVGUnitType)
     35 DEFINE_ANIMATED_ENUMERATION(SVGMaskElement, SVGNames::maskContentUnitsAttr, MaskContentUnits, maskContentUnits, SVGUnitTypes::SVGUnitType)
     36 DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::xAttr, X, x)
     37 DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::yAttr, Y, y)
     38 DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::widthAttr, Width, width)
     39 DEFINE_ANIMATED_LENGTH(SVGMaskElement, SVGNames::heightAttr, Height, height)
     40 DEFINE_ANIMATED_BOOLEAN(SVGMaskElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
     41 
     42 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGMaskElement)
     43     REGISTER_LOCAL_ANIMATED_PROPERTY(maskUnits)
     44     REGISTER_LOCAL_ANIMATED_PROPERTY(maskContentUnits)
     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(externalResourcesRequired)
     50     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGElement)
     51     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests)
     52 END_REGISTER_ANIMATED_PROPERTIES
     53 
     54 inline SVGMaskElement::SVGMaskElement(Document& document)
     55     : SVGElement(SVGNames::maskTag, document)
     56     , m_maskUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
     57     , m_maskContentUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
     58     , m_x(LengthModeWidth, "-10%")
     59     , m_y(LengthModeHeight, "-10%")
     60     , m_width(LengthModeWidth, "120%")
     61     , m_height(LengthModeHeight, "120%")
     62 {
     63     // Spec: If the x/y attribute is not specified, the effect is as if a value of "-10%" were specified.
     64     // Spec: If the width/height attribute is not specified, the effect is as if a value of "120%" were specified.
     65     ScriptWrappable::init(this);
     66     registerAnimatedPropertiesForSVGMaskElement();
     67 }
     68 
     69 PassRefPtr<SVGMaskElement> SVGMaskElement::create(Document& document)
     70 {
     71     return adoptRef(new SVGMaskElement(document));
     72 }
     73 
     74 bool SVGMaskElement::isSupportedAttribute(const QualifiedName& attrName)
     75 {
     76     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
     77     if (supportedAttributes.isEmpty()) {
     78         SVGTests::addSupportedAttributes(supportedAttributes);
     79         SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
     80         supportedAttributes.add(SVGNames::maskUnitsAttr);
     81         supportedAttributes.add(SVGNames::maskContentUnitsAttr);
     82         supportedAttributes.add(SVGNames::xAttr);
     83         supportedAttributes.add(SVGNames::yAttr);
     84         supportedAttributes.add(SVGNames::widthAttr);
     85         supportedAttributes.add(SVGNames::heightAttr);
     86     }
     87     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
     88 }
     89 
     90 void SVGMaskElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
     91 {
     92     SVGParsingError parseError = NoError;
     93 
     94     if (!isSupportedAttribute(name))
     95         SVGElement::parseAttribute(name, value);
     96     else if (name == SVGNames::maskUnitsAttr) {
     97         SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
     98         if (propertyValue > 0)
     99             setMaskUnitsBaseValue(propertyValue);
    100         return;
    101     } else if (name == SVGNames::maskContentUnitsAttr) {
    102         SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
    103         if (propertyValue > 0)
    104             setMaskContentUnitsBaseValue(propertyValue);
    105         return;
    106     } else if (name == SVGNames::xAttr)
    107         setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
    108     else if (name == SVGNames::yAttr)
    109         setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
    110     else if (name == SVGNames::widthAttr)
    111         setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
    112     else if (name == SVGNames::heightAttr)
    113         setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
    114     else if (SVGTests::parseAttribute(name, value)
    115              || SVGExternalResourcesRequired::parseAttribute(name, value)) {
    116     } else
    117         ASSERT_NOT_REACHED();
    118 
    119     reportAttributeParsingError(parseError, name, value);
    120 }
    121 
    122 void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName)
    123 {
    124     if (!isSupportedAttribute(attrName)) {
    125         SVGElement::svgAttributeChanged(attrName);
    126         return;
    127     }
    128 
    129     SVGElementInstance::InvalidationGuard invalidationGuard(this);
    130 
    131     if (attrName == SVGNames::xAttr
    132         || attrName == SVGNames::yAttr
    133         || attrName == SVGNames::widthAttr
    134         || attrName == SVGNames::heightAttr)
    135         updateRelativeLengthsInformation();
    136 
    137     RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
    138     if (renderer)
    139         renderer->invalidateCacheAndMarkForLayout();
    140 }
    141 
    142 void SVGMaskElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
    143 {
    144     SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
    145 
    146     if (changedByParser)
    147         return;
    148 
    149     if (RenderObject* object = renderer())
    150         object->setNeedsLayout();
    151 }
    152 
    153 RenderObject* SVGMaskElement::createRenderer(RenderStyle*)
    154 {
    155     return new RenderSVGResourceMasker(this);
    156 }
    157 
    158 bool SVGMaskElement::selfHasRelativeLengths() const
    159 {
    160     return xCurrentValue().isRelative()
    161         || yCurrentValue().isRelative()
    162         || widthCurrentValue().isRelative()
    163         || heightCurrentValue().isRelative();
    164 }
    165 
    166 }
    167