Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (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 
     23 #include "core/svg/SVGFEBlendElement.h"
     24 
     25 #include "core/SVGNames.h"
     26 #include "platform/graphics/filters/FilterEffect.h"
     27 #include "core/svg/graphics/filters/SVGFilterBuilder.h"
     28 
     29 namespace WebCore {
     30 
     31 template<> const SVGEnumerationStringEntries& getStaticStringEntries<BlendModeType>()
     32 {
     33     DEFINE_STATIC_LOCAL(SVGEnumerationStringEntries, entries, ());
     34     if (entries.isEmpty()) {
     35         entries.append(std::make_pair(FEBLEND_MODE_NORMAL, "normal"));
     36         entries.append(std::make_pair(FEBLEND_MODE_MULTIPLY, "multiply"));
     37         entries.append(std::make_pair(FEBLEND_MODE_SCREEN, "screen"));
     38         entries.append(std::make_pair(FEBLEND_MODE_DARKEN, "darken"));
     39         entries.append(std::make_pair(FEBLEND_MODE_LIGHTEN, "lighten"));
     40     }
     41     return entries;
     42 }
     43 
     44 inline SVGFEBlendElement::SVGFEBlendElement(Document& document)
     45     : SVGFilterPrimitiveStandardAttributes(SVGNames::feBlendTag, document)
     46     , m_in1(SVGAnimatedString::create(this, SVGNames::inAttr, SVGString::create()))
     47     , m_in2(SVGAnimatedString::create(this, SVGNames::in2Attr, SVGString::create()))
     48     , m_mode(SVGAnimatedEnumeration<BlendModeType>::create(this, SVGNames::modeAttr, FEBLEND_MODE_NORMAL))
     49 {
     50     ScriptWrappable::init(this);
     51     addToPropertyMap(m_in1);
     52     addToPropertyMap(m_in2);
     53     addToPropertyMap(m_mode);
     54 }
     55 
     56 DEFINE_NODE_FACTORY(SVGFEBlendElement)
     57 
     58 bool SVGFEBlendElement::isSupportedAttribute(const QualifiedName& attrName)
     59 {
     60     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
     61     if (supportedAttributes.isEmpty()) {
     62         supportedAttributes.add(SVGNames::modeAttr);
     63         supportedAttributes.add(SVGNames::inAttr);
     64         supportedAttributes.add(SVGNames::in2Attr);
     65     }
     66     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
     67 }
     68 
     69 void SVGFEBlendElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
     70 {
     71     if (!isSupportedAttribute(name)) {
     72         SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
     73         return;
     74     }
     75 
     76     SVGParsingError parseError = NoError;
     77 
     78     if (name == SVGNames::inAttr)
     79         m_in1->setBaseValueAsString(value, parseError);
     80     else if (name == SVGNames::in2Attr)
     81         m_in2->setBaseValueAsString(value, parseError);
     82     else if (name == SVGNames::modeAttr)
     83         m_mode->setBaseValueAsString(value, parseError);
     84     else
     85         ASSERT_NOT_REACHED();
     86 
     87     reportAttributeParsingError(parseError, name, value);
     88 }
     89 
     90 bool SVGFEBlendElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName)
     91 {
     92     FEBlend* blend = static_cast<FEBlend*>(effect);
     93     if (attrName == SVGNames::modeAttr)
     94         return blend->setBlendMode(m_mode->currentValue()->enumValue());
     95 
     96     ASSERT_NOT_REACHED();
     97     return false;
     98 }
     99 
    100 void SVGFEBlendElement::svgAttributeChanged(const QualifiedName& attrName)
    101 {
    102     if (!isSupportedAttribute(attrName)) {
    103         SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
    104         return;
    105     }
    106 
    107     SVGElement::InvalidationGuard invalidationGuard(this);
    108 
    109     if (attrName == SVGNames::modeAttr) {
    110         primitiveAttributeChanged(attrName);
    111         return;
    112     }
    113 
    114     if (attrName == SVGNames::inAttr || attrName == SVGNames::in2Attr) {
    115         invalidate();
    116         return;
    117     }
    118 
    119     ASSERT_NOT_REACHED();
    120 }
    121 
    122 PassRefPtr<FilterEffect> SVGFEBlendElement::build(SVGFilterBuilder* filterBuilder, Filter* filter)
    123 {
    124     FilterEffect* input1 = filterBuilder->getEffectById(AtomicString(m_in1->currentValue()->value()));
    125     FilterEffect* input2 = filterBuilder->getEffectById(AtomicString(m_in2->currentValue()->value()));
    126 
    127     if (!input1 || !input2)
    128         return nullptr;
    129 
    130     RefPtr<FilterEffect> effect = FEBlend::create(filter, m_mode->currentValue()->enumValue());
    131     FilterEffectVector& inputEffects = effect->inputEffects();
    132     inputEffects.reserveCapacity(2);
    133     inputEffects.append(input1);
    134     inputEffects.append(input2);
    135     return effect.release();
    136 }
    137 
    138 }
    139