Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2009 Dirk Schulze <krit (at) webkit.org>
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  */
     19 
     20 #include "config.h"
     21 
     22 #if ENABLE(SVG) && ENABLE(FILTERS)
     23 #include "SVGFEConvolveMatrixElement.h"
     24 
     25 #include "Attr.h"
     26 #include "FilterEffect.h"
     27 #include "FloatPoint.h"
     28 #include "IntPoint.h"
     29 #include "IntSize.h"
     30 #include "SVGFilterBuilder.h"
     31 #include "SVGNames.h"
     32 #include "SVGParserUtilities.h"
     33 
     34 namespace WebCore {
     35 
     36 // Animated property definitions
     37 DEFINE_ANIMATED_STRING(SVGFEConvolveMatrixElement, SVGNames::inAttr, In1, in1)
     38 DEFINE_ANIMATED_INTEGER_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::orderAttr, orderXIdentifier(), OrderX, orderX)
     39 DEFINE_ANIMATED_INTEGER_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::orderAttr, orderYIdentifier(), OrderY, orderY)
     40 DEFINE_ANIMATED_NUMBER_LIST(SVGFEConvolveMatrixElement, SVGNames::kernelMatrixAttr, KernelMatrix, kernelMatrix)
     41 DEFINE_ANIMATED_NUMBER(SVGFEConvolveMatrixElement, SVGNames::divisorAttr, Divisor, divisor)
     42 DEFINE_ANIMATED_NUMBER(SVGFEConvolveMatrixElement, SVGNames::biasAttr, Bias, bias)
     43 DEFINE_ANIMATED_INTEGER(SVGFEConvolveMatrixElement, SVGNames::targetXAttr, TargetX, targetX)
     44 DEFINE_ANIMATED_INTEGER(SVGFEConvolveMatrixElement, SVGNames::targetYAttr, TargetY, targetY)
     45 DEFINE_ANIMATED_ENUMERATION(SVGFEConvolveMatrixElement, SVGNames::operatorAttr, EdgeMode, edgeMode)
     46 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::kernelUnitLengthAttr, kernelUnitLengthXIdentifier(), KernelUnitLengthX, kernelUnitLengthX)
     47 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::kernelUnitLengthAttr, kernelUnitLengthYIdentifier(), KernelUnitLengthY, kernelUnitLengthY)
     48 DEFINE_ANIMATED_BOOLEAN(SVGFEConvolveMatrixElement, SVGNames::preserveAlphaAttr, PreserveAlpha, preserveAlpha)
     49 
     50 inline SVGFEConvolveMatrixElement::SVGFEConvolveMatrixElement(const QualifiedName& tagName, Document* document)
     51     : SVGFilterPrimitiveStandardAttributes(tagName, document)
     52     , m_edgeMode(EDGEMODE_DUPLICATE)
     53 {
     54 }
     55 
     56 PassRefPtr<SVGFEConvolveMatrixElement> SVGFEConvolveMatrixElement::create(const QualifiedName& tagName, Document* document)
     57 {
     58     return adoptRef(new SVGFEConvolveMatrixElement(tagName, document));
     59 }
     60 
     61 const AtomicString& SVGFEConvolveMatrixElement::kernelUnitLengthXIdentifier()
     62 {
     63     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthX"));
     64     return s_identifier;
     65 }
     66 
     67 const AtomicString& SVGFEConvolveMatrixElement::kernelUnitLengthYIdentifier()
     68 {
     69     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthY"));
     70     return s_identifier;
     71 }
     72 
     73 const AtomicString& SVGFEConvolveMatrixElement::orderXIdentifier()
     74 {
     75     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGOrderX"));
     76     return s_identifier;
     77 }
     78 
     79 const AtomicString& SVGFEConvolveMatrixElement::orderYIdentifier()
     80 {
     81     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGOrderY"));
     82     return s_identifier;
     83 }
     84 
     85 void SVGFEConvolveMatrixElement::parseMappedAttribute(Attribute* attr)
     86 {
     87     const String& value = attr->value();
     88     if (attr->name() == SVGNames::inAttr)
     89         setIn1BaseValue(value);
     90     else if (attr->name() == SVGNames::orderAttr) {
     91         float x, y;
     92         if (parseNumberOptionalNumber(value, x, y)) {
     93             setOrderXBaseValue(x);
     94             setOrderYBaseValue(y);
     95         }
     96     } else if (attr->name() == SVGNames::edgeModeAttr) {
     97         if (value == "duplicate")
     98             setEdgeModeBaseValue(EDGEMODE_DUPLICATE);
     99         else if (value == "wrap")
    100             setEdgeModeBaseValue(EDGEMODE_WRAP);
    101         else if (value == "none")
    102             setEdgeModeBaseValue(EDGEMODE_NONE);
    103     } else if (attr->name() == SVGNames::kernelMatrixAttr) {
    104         SVGNumberList newList;
    105         newList.parse(value);
    106         detachAnimatedKernelMatrixListWrappers(newList.size());
    107         setKernelMatrixBaseValue(newList);
    108     } else if (attr->name() == SVGNames::divisorAttr)
    109         setDivisorBaseValue(value.toFloat());
    110     else if (attr->name() == SVGNames::biasAttr)
    111         setBiasBaseValue(value.toFloat());
    112     else if (attr->name() == SVGNames::targetXAttr)
    113         setTargetXBaseValue(value.toUIntStrict());
    114     else if (attr->name() == SVGNames::targetYAttr)
    115         setTargetYBaseValue(value.toUIntStrict());
    116     else if (attr->name() == SVGNames::kernelUnitLengthAttr) {
    117         float x, y;
    118         if (parseNumberOptionalNumber(value, x, y)) {
    119             setKernelUnitLengthXBaseValue(x);
    120             setKernelUnitLengthYBaseValue(y);
    121         }
    122     } else if (attr->name() == SVGNames::preserveAlphaAttr) {
    123         if (value == "true")
    124             setPreserveAlphaBaseValue(true);
    125         else if (value == "false")
    126             setPreserveAlphaBaseValue(false);
    127     } else
    128         SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(attr);
    129 }
    130 
    131 bool SVGFEConvolveMatrixElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName)
    132 {
    133     FEConvolveMatrix* convolveMatrix = static_cast<FEConvolveMatrix*>(effect);
    134     if (attrName == SVGNames::edgeModeAttr)
    135         return convolveMatrix->setEdgeMode(static_cast<EdgeModeType>(edgeMode()));
    136     if (attrName == SVGNames::divisorAttr)
    137         return convolveMatrix->setDivisor(divisor());
    138     if (attrName == SVGNames::biasAttr)
    139         return convolveMatrix->setBias(bias());
    140     if (attrName == SVGNames::targetXAttr)
    141        return convolveMatrix->setTargetOffset(IntPoint(targetX(), targetY()));
    142     if (attrName == SVGNames::targetYAttr)
    143        return convolveMatrix->setTargetOffset(IntPoint(targetX(), targetY()));
    144     if (attrName == SVGNames::kernelUnitLengthAttr)
    145        return convolveMatrix->setKernelUnitLength(FloatPoint(kernelUnitLengthX(), kernelUnitLengthY()));
    146     if (attrName == SVGNames::preserveAlphaAttr)
    147         return convolveMatrix->setPreserveAlpha(preserveAlpha());
    148 
    149     ASSERT_NOT_REACHED();
    150     return false;
    151 }
    152 
    153 void SVGFEConvolveMatrixElement::setOrder(float x, float y)
    154 {
    155     setOrderXBaseValue(x);
    156     setOrderYBaseValue(y);
    157     invalidate();
    158 }
    159 
    160 void SVGFEConvolveMatrixElement::setKernelUnitLength(float x, float y)
    161 {
    162     setKernelUnitLengthXBaseValue(x);
    163     setKernelUnitLengthYBaseValue(y);
    164     invalidate();
    165 }
    166 
    167 void SVGFEConvolveMatrixElement::svgAttributeChanged(const QualifiedName& attrName)
    168 {
    169     SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
    170 
    171     if (attrName == SVGNames::edgeModeAttr
    172         || attrName == SVGNames::divisorAttr
    173         || attrName == SVGNames::biasAttr
    174         || attrName == SVGNames::targetXAttr
    175         || attrName == SVGNames::targetYAttr
    176         || attrName == SVGNames::kernelUnitLengthAttr
    177         || attrName == SVGNames::preserveAlphaAttr)
    178         primitiveAttributeChanged(attrName);
    179 
    180     if (attrName == SVGNames::inAttr
    181         || attrName == SVGNames::orderAttr
    182         || attrName == SVGNames::kernelMatrixAttr)
    183         invalidate();
    184 }
    185 
    186 AttributeToPropertyTypeMap& SVGFEConvolveMatrixElement::attributeToPropertyTypeMap()
    187 {
    188     DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
    189     return s_attributeToPropertyTypeMap;
    190 }
    191 
    192 void SVGFEConvolveMatrixElement::fillAttributeToPropertyTypeMap()
    193 {
    194     AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap();
    195 
    196     SVGFilterPrimitiveStandardAttributes::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap);
    197     attributeToPropertyTypeMap.set(SVGNames::inAttr, AnimatedString);
    198     attributeToPropertyTypeMap.set(SVGNames::orderAttr, AnimatedNumberOptionalNumber);
    199     attributeToPropertyTypeMap.set(SVGNames::kernelMatrixAttr, AnimatedNumberList);
    200     attributeToPropertyTypeMap.set(SVGNames::divisorAttr, AnimatedNumber);
    201     attributeToPropertyTypeMap.set(SVGNames::biasAttr, AnimatedNumber);
    202     attributeToPropertyTypeMap.set(SVGNames::targetXAttr, AnimatedInteger);
    203     attributeToPropertyTypeMap.set(SVGNames::targetYAttr, AnimatedInteger);
    204     attributeToPropertyTypeMap.set(SVGNames::operatorAttr, AnimatedEnumeration);
    205     attributeToPropertyTypeMap.set(SVGNames::kernelUnitLengthAttr, AnimatedNumberOptionalNumber);
    206     attributeToPropertyTypeMap.set(SVGNames::preserveAlphaAttr, AnimatedBoolean);
    207 }
    208 
    209 PassRefPtr<FilterEffect> SVGFEConvolveMatrixElement::build(SVGFilterBuilder* filterBuilder, Filter* filter)
    210 {
    211     FilterEffect* input1 = filterBuilder->getEffectById(in1());
    212 
    213     if (!input1)
    214         return 0;
    215 
    216     int orderXValue = orderX();
    217     int orderYValue = orderY();
    218     if (!hasAttribute(SVGNames::orderAttr)) {
    219         orderXValue = 3;
    220         orderYValue = 3;
    221     }
    222     SVGNumberList& kernelMatrix = this->kernelMatrix();
    223     int kernelMatrixSize = kernelMatrix.size();
    224     // The spec says this is a requirement, and should bail out if fails
    225     if (orderXValue * orderYValue != kernelMatrixSize)
    226         return 0;
    227 
    228     int targetXValue = targetX();
    229     int targetYValue = targetY();
    230     if (hasAttribute(SVGNames::targetXAttr) && (targetXValue < 0 || targetXValue >= orderXValue))
    231         return 0;
    232     // The spec says the default value is: targetX = floor ( orderX / 2 ))
    233     if (!hasAttribute(SVGNames::targetXAttr))
    234         targetXValue = static_cast<int>(floorf(orderXValue / 2));
    235     if (hasAttribute(SVGNames::targetYAttr) && (targetYValue < 0 || targetYValue >= orderYValue))
    236         return 0;
    237     // The spec says the default value is: targetY = floor ( orderY / 2 ))
    238     if (!hasAttribute(SVGNames::targetYAttr))
    239         targetYValue = static_cast<int>(floorf(orderYValue / 2));
    240 
    241     float divisorValue = divisor();
    242     if (hasAttribute(SVGNames::divisorAttr) && !divisorValue)
    243         return 0;
    244     if (!hasAttribute(SVGNames::divisorAttr)) {
    245         for (int i = 0; i < kernelMatrixSize; ++i)
    246             divisorValue += kernelMatrix.at(i);
    247         if (!divisorValue)
    248             divisorValue = 1;
    249     }
    250 
    251     RefPtr<FilterEffect> effect = FEConvolveMatrix::create(filter,
    252                     IntSize(orderXValue, orderYValue), divisorValue,
    253                     bias(), IntPoint(targetXValue, targetYValue), static_cast<EdgeModeType>(edgeMode()),
    254                     FloatPoint(kernelUnitLengthX(), kernelUnitLengthX()), preserveAlpha(), kernelMatrix);
    255     effect->inputEffects().append(input1);
    256     return effect.release();
    257 }
    258 
    259 } // namespace WebCore
    260 
    261 #endif // ENABLE(SVG)
    262