1 /*
2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@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 "third_party/blink/renderer/core/svg/svg_fe_blend_element.h"
22
23 #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h"
24 #include "third_party/blink/renderer/core/svg/svg_enumeration_map.h"
25 #include "third_party/blink/renderer/core/svg_names.h"
26 #include "third_party/blink/renderer/platform/graphics/filters/fe_blend.h"
27 #include "third_party/blink/renderer/platform/heap/heap.h"
28
29 namespace blink {
30
ToBlendMode(SVGFEBlendElement::Mode mode)31 static BlendMode ToBlendMode(SVGFEBlendElement::Mode mode) {
32 #define MAP_BLEND_MODE(MODENAME) \
33 case SVGFEBlendElement::kMode##MODENAME: \
34 return BlendMode::k##MODENAME
35
36 switch (mode) {
37 MAP_BLEND_MODE(Normal);
38 MAP_BLEND_MODE(Multiply);
39 MAP_BLEND_MODE(Screen);
40 MAP_BLEND_MODE(Darken);
41 MAP_BLEND_MODE(Lighten);
42 MAP_BLEND_MODE(Overlay);
43 MAP_BLEND_MODE(ColorDodge);
44 MAP_BLEND_MODE(ColorBurn);
45 MAP_BLEND_MODE(HardLight);
46 MAP_BLEND_MODE(SoftLight);
47 MAP_BLEND_MODE(Difference);
48 MAP_BLEND_MODE(Exclusion);
49 MAP_BLEND_MODE(Hue);
50 MAP_BLEND_MODE(Saturation);
51 MAP_BLEND_MODE(Color);
52 MAP_BLEND_MODE(Luminosity);
53 default:
54 NOTREACHED();
55 return BlendMode::kNormal;
56 }
57 #undef MAP_BLEND_MODE
58 }
59
60 template <>
GetEnumerationMap()61 const SVGEnumerationMap& GetEnumerationMap<SVGFEBlendElement::Mode>() {
62 static const SVGEnumerationMap::Entry enum_items[] = {
63 {SVGFEBlendElement::kModeNormal, "normal"},
64 {SVGFEBlendElement::kModeMultiply, "multiply"},
65 {SVGFEBlendElement::kModeScreen, "screen"},
66 {SVGFEBlendElement::kModeDarken, "darken"},
67 {SVGFEBlendElement::kModeLighten, "lighten"},
68 {SVGFEBlendElement::kModeOverlay, "overlay"},
69 {SVGFEBlendElement::kModeColorDodge, "color-dodge"},
70 {SVGFEBlendElement::kModeColorBurn, "color-burn"},
71 {SVGFEBlendElement::kModeHardLight, "hard-light"},
72 {SVGFEBlendElement::kModeSoftLight, "soft-light"},
73 {SVGFEBlendElement::kModeDifference, "difference"},
74 {SVGFEBlendElement::kModeExclusion, "exclusion"},
75 {SVGFEBlendElement::kModeHue, "hue"},
76 {SVGFEBlendElement::kModeSaturation, "saturation"},
77 {SVGFEBlendElement::kModeColor, "color"},
78 {SVGFEBlendElement::kModeLuminosity, "luminosity"},
79 };
80 static const SVGEnumerationMap entries(enum_items);
81 return entries;
82 }
83
SVGFEBlendElement(Document & document)84 SVGFEBlendElement::SVGFEBlendElement(Document& document)
85 : SVGFilterPrimitiveStandardAttributes(svg_names::kFEBlendTag, document),
86 in1_(MakeGarbageCollected<SVGAnimatedString>(this, svg_names::kInAttr)),
87 in2_(MakeGarbageCollected<SVGAnimatedString>(this, svg_names::kIn2Attr)),
88 mode_(MakeGarbageCollected<SVGAnimatedEnumeration<Mode>>(
89 this,
90 svg_names::kModeAttr,
91 SVGFEBlendElement::kModeNormal)) {
92 AddToPropertyMap(in1_);
93 AddToPropertyMap(in2_);
94 AddToPropertyMap(mode_);
95 }
96
Trace(Visitor * visitor)97 void SVGFEBlendElement::Trace(Visitor* visitor) {
98 visitor->Trace(in1_);
99 visitor->Trace(in2_);
100 visitor->Trace(mode_);
101 SVGFilterPrimitiveStandardAttributes::Trace(visitor);
102 }
103
SetFilterEffectAttribute(FilterEffect * effect,const QualifiedName & attr_name)104 bool SVGFEBlendElement::SetFilterEffectAttribute(
105 FilterEffect* effect,
106 const QualifiedName& attr_name) {
107 FEBlend* blend = static_cast<FEBlend*>(effect);
108 if (attr_name == svg_names::kModeAttr)
109 return blend->SetBlendMode(ToBlendMode(mode_->CurrentValue()->EnumValue()));
110
111 return SVGFilterPrimitiveStandardAttributes::SetFilterEffectAttribute(
112 effect, attr_name);
113 }
114
SvgAttributeChanged(const QualifiedName & attr_name)115 void SVGFEBlendElement::SvgAttributeChanged(const QualifiedName& attr_name) {
116 if (attr_name == svg_names::kModeAttr) {
117 SVGElement::InvalidationGuard invalidation_guard(this);
118 PrimitiveAttributeChanged(attr_name);
119 return;
120 }
121
122 if (attr_name == svg_names::kInAttr || attr_name == svg_names::kIn2Attr) {
123 SVGElement::InvalidationGuard invalidation_guard(this);
124 Invalidate();
125 return;
126 }
127
128 SVGFilterPrimitiveStandardAttributes::SvgAttributeChanged(attr_name);
129 }
130
Build(SVGFilterBuilder * filter_builder,Filter * filter)131 FilterEffect* SVGFEBlendElement::Build(SVGFilterBuilder* filter_builder,
132 Filter* filter) {
133 FilterEffect* input1 = filter_builder->GetEffectById(
134 AtomicString(in1_->CurrentValue()->Value()));
135 FilterEffect* input2 = filter_builder->GetEffectById(
136 AtomicString(in2_->CurrentValue()->Value()));
137 DCHECK(input1);
138 DCHECK(input2);
139
140 auto* effect = MakeGarbageCollected<FEBlend>(
141 filter, ToBlendMode(mode_->CurrentValue()->EnumValue()));
142 FilterEffectVector& input_effects = effect->InputEffects();
143 input_effects.ReserveCapacity(2);
144 input_effects.push_back(input1);
145 input_effects.push_back(input2);
146 return effect;
147 }
148
149 } // namespace blink
150