• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "modules/skottie/src/effects/Effects.h"
9 
10 #include "modules/skottie/src/SkottieJson.h"
11 #include "modules/sksg/include/SkSGRenderEffect.h"
12 #include "src/utils/SkJSON.h"
13 
14 namespace skottie {
15 namespace internal {
16 
EffectBuilder(const AnimationBuilder * abuilder,const SkSize & layer_size)17 EffectBuilder::EffectBuilder(const AnimationBuilder* abuilder, const SkSize& layer_size)
18     : fBuilder(abuilder)
19     , fLayerSize(layer_size) {}
20 
findBuilder(const skjson::ObjectValue & jeffect) const21 EffectBuilder::EffectBuilderT EffectBuilder::findBuilder(const skjson::ObjectValue& jeffect) const {
22     // First, try assigned types.
23     enum : int32_t {
24         kTint_Effect         = 20,
25         kFill_Effect         = 21,
26         kTritone_Effect      = 23,
27         kDropShadow_Effect   = 25,
28         kRadialWipe_Effect   = 26,
29         kGaussianBlur_Effect = 29,
30     };
31 
32     const auto ty = ParseDefault<int>(jeffect["ty"], -1);
33 
34     switch (ty) {
35     case kTint_Effect:
36         return &EffectBuilder::attachTintEffect;
37     case kFill_Effect:
38         return &EffectBuilder::attachFillEffect;
39     case kTritone_Effect:
40         return &EffectBuilder::attachTritoneEffect;
41     case kDropShadow_Effect:
42         return &EffectBuilder::attachDropShadowEffect;
43     case kRadialWipe_Effect:
44         return &EffectBuilder::attachRadialWipeEffect;
45     case kGaussianBlur_Effect:
46         return &EffectBuilder::attachGaussianBlurEffect;
47     default:
48         break;
49     }
50 
51     // Some effects don't have an assigned type, but the data is still present.
52     // Try a name-based lookup.
53 
54     static constexpr char kGradientEffectMN[] = "ADBE Ramp",
55                            kHueSaturationMN[] = "ADBE HUE SATURATION",
56                             kLevelsEffectMN[] = "ADBE Easy Levels2",
57                         kLinearWipeEffectMN[] = "ADBE Linear Wipe",
58                         kMotionTileEffectMN[] = "ADBE Tile",
59                          kTransformEffectMN[] = "ADBE Geometry2",
60                     kVenetianBlindsEffectMN[] = "ADBE Venetian Blinds";
61 
62     if (const skjson::StringValue* mn = jeffect["mn"]) {
63         if (!strcmp(mn->begin(), kGradientEffectMN)) {
64             return &EffectBuilder::attachGradientEffect;
65         }
66         if (!strcmp(mn->begin(), kHueSaturationMN)) {
67             return &EffectBuilder::attachHueSaturationEffect;
68         }
69         if (!strcmp(mn->begin(), kLevelsEffectMN)) {
70             return &EffectBuilder::attachLevelsEffect;
71         }
72         if (!strcmp(mn->begin(), kLinearWipeEffectMN)) {
73             return &EffectBuilder::attachLinearWipeEffect;
74         }
75         if (!strcmp(mn->begin(), kMotionTileEffectMN)) {
76             return &EffectBuilder::attachMotionTileEffect;
77         }
78         if (!strcmp(mn->begin(), kTransformEffectMN)) {
79             return &EffectBuilder::attachTransformEffect;
80         }
81         if (!strcmp(mn->begin(), kVenetianBlindsEffectMN)) {
82             return &EffectBuilder::attachVenetianBlindsEffect;
83         }
84     }
85 
86     fBuilder->log(Logger::Level::kWarning, nullptr, "Unsupported layer effect type: %d.", ty);
87 
88     return nullptr;
89 }
90 
attachEffects(const skjson::ArrayValue & jeffects,sk_sp<sksg::RenderNode> layer) const91 sk_sp<sksg::RenderNode> EffectBuilder::attachEffects(const skjson::ArrayValue& jeffects,
92                                                      sk_sp<sksg::RenderNode> layer) const {
93     if (!layer) {
94         return nullptr;
95     }
96 
97     for (const skjson::ObjectValue* jeffect : jeffects) {
98         if (!jeffect) {
99             continue;
100         }
101 
102         const auto builder = this->findBuilder(*jeffect);
103         const skjson::ArrayValue* jprops = (*jeffect)["ef"];
104         if (!builder || !jprops) {
105             continue;
106         }
107 
108         const AnimationBuilder::AutoPropertyTracker apt(fBuilder, *jeffect);
109         layer = (this->*builder)(*jprops, std::move(layer));
110 
111         if (!layer) {
112             fBuilder->log(Logger::Level::kError, jeffect, "Invalid layer effect.");
113             return nullptr;
114         }
115     }
116 
117     return layer;
118 }
119 
GetPropValue(const skjson::ArrayValue & jprops,size_t prop_index)120 const skjson::Value& EffectBuilder::GetPropValue(const skjson::ArrayValue& jprops,
121                                                  size_t prop_index) {
122     static skjson::NullValue kNull;
123 
124     if (prop_index >= jprops.size()) {
125         return kNull;
126     }
127 
128     const skjson::ObjectValue* jprop = jprops[prop_index];
129 
130     return jprop ? (*jprop)["v"] : kNull;
131 }
132 
MaskFilterEffectBase(sk_sp<sksg::RenderNode> child,const SkSize & ls)133 MaskFilterEffectBase::MaskFilterEffectBase(sk_sp<sksg::RenderNode> child, const SkSize& ls)
134     : fMaskNode(sksg::MaskFilter::Make(nullptr))
135     , fMaskEffectNode(sksg::MaskFilterEffect::Make(std::move(child), fMaskNode))
136     , fLayerSize(ls) {}
137 
138 MaskFilterEffectBase::~MaskFilterEffectBase() = default;
139 
apply() const140 void MaskFilterEffectBase::apply() const {
141     const auto minfo = this->onMakeMask();
142 
143     fMaskEffectNode->setVisible(minfo.fVisible);
144     fMaskNode->setMaskFilter(std::move(minfo.fMask));
145 }
146 
147 } // namespace internal
148 } // namespace skottie
149