Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Effects.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
16
17#include <algorithm>
18#include <cstdint>
19#include <cstring>
20#include <iterator>
21#include <limits>
22#include <utility>
23
24namespace skottie {
25namespace internal {
26
28 const SkSize& layer_size,
29 CompositionBuilder* cbuilder)
30 : fBuilder(abuilder)
31 , fCompBuilder(cbuilder)
32 , fLayerSize(layer_size) {}
33
34EffectBuilder::EffectBuilderT EffectBuilder::findBuilder(const skjson::ObjectValue& jeffect) const {
35 static constexpr struct BuilderInfo {
36 const char* fName;
37 EffectBuilderT fBuilder;
38 } gBuilderInfo[] = {
39 // alphabetized for binary search lookup
40 { "ADBE Black&White" , &EffectBuilder::attachBlackAndWhiteEffect },
41 { "ADBE Brightness & Contrast 2", &EffectBuilder::attachBrightnessContrastEffect },
42 { "ADBE Bulge" , &EffectBuilder::attachBulgeEffect },
43 { "ADBE Corner Pin" , &EffectBuilder::attachCornerPinEffect },
44 { "ADBE Displacement Map" , &EffectBuilder::attachDisplacementMapEffect },
45 { "ADBE Drop Shadow" , &EffectBuilder::attachDropShadowEffect },
46 { "ADBE Easy Levels2" , &EffectBuilder::attachEasyLevelsEffect },
47 { "ADBE Fill" , &EffectBuilder::attachFillEffect },
48 { "ADBE Fractal Noise" , &EffectBuilder::attachFractalNoiseEffect },
49 { "ADBE Gaussian Blur 2" , &EffectBuilder::attachGaussianBlurEffect },
50 { "ADBE Geometry2" , &EffectBuilder::attachTransformEffect },
51 { "ADBE HUE SATURATION" , &EffectBuilder::attachHueSaturationEffect },
52 { "ADBE Invert" , &EffectBuilder::attachInvertEffect },
53 { "ADBE Linear Wipe" , &EffectBuilder::attachLinearWipeEffect },
54 { "ADBE Motion Blur" , &EffectBuilder::attachDirectionalBlurEffect },
55 { "ADBE Pro Levels2" , &EffectBuilder::attachProLevelsEffect },
56 { "ADBE Radial Wipe" , &EffectBuilder::attachRadialWipeEffect },
57 { "ADBE Ramp" , &EffectBuilder::attachGradientEffect },
58 { "ADBE Sharpen" , &EffectBuilder::attachSharpenEffect },
59 { "ADBE Shift Channels" , &EffectBuilder::attachShiftChannelsEffect },
60 { "ADBE Threshold2" , &EffectBuilder::attachThresholdEffect },
61 { "ADBE Tile" , &EffectBuilder::attachMotionTileEffect },
62 { "ADBE Tint" , &EffectBuilder::attachTintEffect },
63 { "ADBE Tritone" , &EffectBuilder::attachTritoneEffect },
64 { "ADBE Venetian Blinds" , &EffectBuilder::attachVenetianBlindsEffect },
65 { "CC Sphere" , &EffectBuilder::attachSphereEffect },
66 { "CC Toner" , &EffectBuilder::attachCCTonerEffect },
67 { "SkSL Color Filter" , &EffectBuilder::attachSkSLColorFilter },
68 { "SkSL Shader" , &EffectBuilder::attachSkSLShader },
69 };
70
71 const skjson::StringValue* mn = jeffect["mn"];
72 if (mn) {
73 const BuilderInfo key { mn->begin(), nullptr };
74 const auto* binfo = std::lower_bound(std::begin(gBuilderInfo),
75 std::end (gBuilderInfo),
76 key,
77 [](const BuilderInfo& a, const BuilderInfo& b) {
78 return strcmp(a.fName, b.fName) < 0;
79 });
80 if (binfo != std::end(gBuilderInfo) && !strcmp(binfo->fName, key.fName)) {
81 return binfo->fBuilder;
82 }
83 }
84
85 // Some legacy clients rely solely on the 'ty' field and generate (non-BM) JSON
86 // without a valid 'mn' string. TODO: we should update them and remove this fallback.
87 enum : int32_t {
88 kTint_Effect = 20,
89 kFill_Effect = 21,
90 kTritone_Effect = 23,
91 kDropShadow_Effect = 25,
92 kRadialWipe_Effect = 26,
93 kGaussianBlur_Effect = 29,
94 };
95
96 switch (ParseDefault<int>(jeffect["ty"], -1)) {
97 case kTint_Effect: return &EffectBuilder::attachTintEffect;
98 case kFill_Effect: return &EffectBuilder::attachFillEffect;
99 case kTritone_Effect: return &EffectBuilder::attachTritoneEffect;
100 case kDropShadow_Effect: return &EffectBuilder::attachDropShadowEffect;
101 case kRadialWipe_Effect: return &EffectBuilder::attachRadialWipeEffect;
102 case kGaussianBlur_Effect: return &EffectBuilder::attachGaussianBlurEffect;
103 default: break;
104 }
105
106 fBuilder->log(Logger::Level::kWarning, &jeffect,
107 "Unsupported layer effect: %s", mn ? mn->begin() : "(unknown)");
108
109 return nullptr;
110}
111
113 sk_sp<sksg::RenderNode> layer) const {
114 if (!layer) {
115 return nullptr;
116 }
117
118 for (const skjson::ObjectValue* jeffect : jeffects) {
119 if (!jeffect) {
120 continue;
121 }
122
123 const auto builder = this->findBuilder(*jeffect);
124 const skjson::ArrayValue* jprops = (*jeffect)["ef"];
125 if (!builder || !jprops) {
126 continue;
127 }
128
130 layer = (this->*builder)(*jprops, std::move(layer));
131
132 if (!layer) {
133 fBuilder->log(Logger::Level::kError, jeffect, "Invalid layer effect.");
134 return nullptr;
135 }
136 }
137
138 return layer;
139}
140
142 sk_sp<sksg::RenderNode> layer) const {
143#if !defined(SKOTTIE_DISABLE_STYLES)
144 if (!layer) {
145 return nullptr;
146 }
147
148 using StyleBuilder =
151 static constexpr StyleBuilder gStyleBuilders[] = {
152 nullptr, // 'ty': 0 -> stroke
153 &EffectBuilder::attachDropShadowStyle, // 'ty': 1 -> drop shadow
154 &EffectBuilder::attachInnerShadowStyle, // 'ty': 2 -> inner shadow
155 &EffectBuilder::attachOuterGlowStyle, // 'ty': 3 -> outer glow
156 &EffectBuilder::attachInnerGlowStyle, // 'ty': 4 -> inner glow
157 };
158
159 for (const skjson::ObjectValue* jstyle : jstyles) {
160 if (!jstyle) {
161 continue;
162 }
163
164 const auto style_type =
165 ParseDefault<size_t>((*jstyle)["ty"], std::numeric_limits<size_t>::max());
166 auto builder = style_type < std::size(gStyleBuilders) ? gStyleBuilders[style_type]
167 : nullptr;
168
169 if (!builder) {
170 fBuilder->log(Logger::Level::kWarning, jstyle, "Unsupported layer style.");
171 continue;
172 }
173
174 layer = (this->*builder)(*jstyle, std::move(layer));
175 }
176#endif // !defined(SKOTTIE_DISABLE_STYLES)
177
178 return layer;
179}
180
182 size_t prop_index) {
183 static skjson::NullValue kNull;
184
185 if (prop_index >= jprops.size()) {
186 return kNull;
187 }
188
189 const skjson::ObjectValue* jprop = jprops[prop_index];
190
191 return jprop ? (*jprop)["v"] : kNull;
192}
193
195 : fMaskEffectNode(sksg::MaskShaderEffect::Make(std::move(child)))
196 , fLayerSize(ls) {}
197
199 const auto minfo = this->onMakeMask();
200
201 fMaskEffectNode->setVisible(minfo.fVisible);
202 fMaskEffectNode->setShader(std::move(minfo.fMaskShader));
203}
204
205} // namespace internal
206} // namespace skottie
const char * fName
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
const char * begin() const
Definition SkJSON.h:315
size_t size() const
Definition SkJSON.h:262
void log(Logger::Level, const skjson::Value *, const char fmt[],...) const SK_PRINTF_LIKE(4
Definition Skottie.cpp:71
sk_sp< sksg::RenderNode > attachEffects(const skjson::ArrayValue &, sk_sp< sksg::RenderNode >) const
Definition Effects.cpp:112
EffectBuilder(const AnimationBuilder *, const SkSize &, CompositionBuilder *)
Definition Effects.cpp:27
static const skjson::Value & GetPropValue(const skjson::ArrayValue &jprops, size_t prop_index)
Definition Effects.cpp:181
sk_sp< sksg::RenderNode > attachStyles(const skjson::ArrayValue &, sk_sp< sksg::RenderNode >) const
Definition Effects.cpp:141
MaskShaderEffectBase(sk_sp< sksg::RenderNode >, const SkSize &)
Definition Effects.cpp:194
virtual MaskInfo onMakeMask() const =0
static bool b
struct MyStruct a[10]
Definition Skottie.h:32
Definition ref_ptr.h:256