1/*
2 * Copyright (C) 2006 Oliver Hunt <oliver@nerget.com>
3 * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
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 "SVGFEDisplacementMapElement.h"
23
24#include "FilterEffect.h"
25#include "SVGFilterBuilder.h"
26#include "SVGNames.h"
27#include <wtf/IsoMallocInlines.h>
28
29namespace WebCore {
30
31WTF_MAKE_ISO_ALLOCATED_IMPL(SVGFEDisplacementMapElement);
32
33inline SVGFEDisplacementMapElement::SVGFEDisplacementMapElement(const QualifiedName& tagName, Document& document)
34 : SVGFilterPrimitiveStandardAttributes(tagName, document)
35{
36 ASSERT(hasTagName(SVGNames::feDisplacementMapTag));
37
38 static std::once_flag onceFlag;
39 std::call_once(onceFlag, [] {
40 PropertyRegistry::registerProperty<SVGNames::inAttr, &SVGFEDisplacementMapElement::m_in1>();
41 PropertyRegistry::registerProperty<SVGNames::in2Attr, &SVGFEDisplacementMapElement::m_in2>();
42 PropertyRegistry::registerProperty<SVGNames::xChannelSelectorAttr, ChannelSelectorType, &SVGFEDisplacementMapElement::m_xChannelSelector>();
43 PropertyRegistry::registerProperty<SVGNames::yChannelSelectorAttr, ChannelSelectorType, &SVGFEDisplacementMapElement::m_yChannelSelector>();
44 PropertyRegistry::registerProperty<SVGNames::scaleAttr, &SVGFEDisplacementMapElement::m_scale>();
45 });
46}
47
48Ref<SVGFEDisplacementMapElement> SVGFEDisplacementMapElement::create(const QualifiedName& tagName, Document& document)
49{
50 return adoptRef(*new SVGFEDisplacementMapElement(tagName, document));
51}
52
53void SVGFEDisplacementMapElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
54{
55 if (name == SVGNames::xChannelSelectorAttr) {
56 auto propertyValue = SVGPropertyTraits<ChannelSelectorType>::fromString(value);
57 if (propertyValue > 0)
58 m_xChannelSelector->setBaseValInternal<ChannelSelectorType>(propertyValue);
59 return;
60 }
61
62 if (name == SVGNames::yChannelSelectorAttr) {
63 auto propertyValue = SVGPropertyTraits<ChannelSelectorType>::fromString(value);
64 if (propertyValue > 0)
65 m_yChannelSelector->setBaseValInternal<ChannelSelectorType>(propertyValue);
66 return;
67 }
68
69 if (name == SVGNames::inAttr) {
70 m_in1->setBaseValInternal(value);
71 return;
72 }
73
74 if (name == SVGNames::in2Attr) {
75 m_in2->setBaseValInternal(value);
76 return;
77 }
78
79 if (name == SVGNames::scaleAttr) {
80 m_scale->setBaseValInternal(value.toFloat());
81 return;
82 }
83
84 SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
85}
86
87bool SVGFEDisplacementMapElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName)
88{
89 FEDisplacementMap* displacementMap = static_cast<FEDisplacementMap*>(effect);
90 if (attrName == SVGNames::xChannelSelectorAttr)
91 return displacementMap->setXChannelSelector(xChannelSelector());
92 if (attrName == SVGNames::yChannelSelectorAttr)
93 return displacementMap->setYChannelSelector(yChannelSelector());
94 if (attrName == SVGNames::scaleAttr)
95 return displacementMap->setScale(scale());
96
97 ASSERT_NOT_REACHED();
98 return false;
99}
100
101void SVGFEDisplacementMapElement::svgAttributeChanged(const QualifiedName& attrName)
102{
103 if (attrName == SVGNames::xChannelSelectorAttr || attrName == SVGNames::yChannelSelectorAttr || attrName == SVGNames::scaleAttr) {
104 InstanceInvalidationGuard guard(*this);
105 primitiveAttributeChanged(attrName);
106 return;
107 }
108
109 if (attrName == SVGNames::inAttr || attrName == SVGNames::in2Attr) {
110 InstanceInvalidationGuard guard(*this);
111 invalidate();
112 return;
113 }
114
115 SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
116}
117
118RefPtr<FilterEffect> SVGFEDisplacementMapElement::build(SVGFilterBuilder* filterBuilder, Filter& filter) const
119{
120 auto input1 = filterBuilder->getEffectById(in1());
121 auto input2 = filterBuilder->getEffectById(in2());
122
123 if (!input1 || !input2)
124 return nullptr;
125
126 auto effect = FEDisplacementMap::create(filter, xChannelSelector(), yChannelSelector(), scale());
127 FilterEffectVector& inputEffects = effect->inputEffects();
128 inputEffects.reserveCapacity(2);
129 inputEffects.append(input1);
130 inputEffects.append(input2);
131 return effect;
132}
133
134}
135