• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 "SkottiePriv.h"
9 
10 #include "SkJSON.h"
11 #include "SkottieJson.h"
12 #include "SkottieValue.h"
13 #include "SkSGColor.h"
14 #include "SkSGColorFilter.h"
15 
16 namespace skottie {
17 namespace internal {
18 
19 namespace {
20 
AttachFillLayerEffect(const skjson::ArrayValue * jeffect_props,const AnimationBuilder * abuilder,AnimatorScope * ascope,sk_sp<sksg::RenderNode> layer)21 sk_sp<sksg::RenderNode> AttachFillLayerEffect(const skjson::ArrayValue* jeffect_props,
22                                               const AnimationBuilder* abuilder,
23                                               AnimatorScope* ascope,
24                                               sk_sp<sksg::RenderNode> layer) {
25     if (!jeffect_props) return nullptr;
26 
27     // Effect properties are index-based.
28     enum {
29         kFillMask_Index = 0,
30         kAllMasks_Index = 1,
31         kColor_Index    = 2,
32         kInvert_Index   = 3,
33         kHFeather_Index = 4,
34         kVFeather_Index = 5,
35         kOpacity_Index  = 6,
36 
37         kMax_Index      = kOpacity_Index,
38     };
39 
40     if (jeffect_props->size() <= kMax_Index) {
41         return nullptr;
42     }
43 
44     const skjson::ObjectValue*   color_prop = (*jeffect_props)[  kColor_Index];
45     const skjson::ObjectValue* opacity_prop = (*jeffect_props)[kOpacity_Index];
46     if (!color_prop || !opacity_prop) {
47         return nullptr;
48     }
49 
50     sk_sp<sksg::Color> color_node = abuilder->attachColor(*color_prop, ascope, "v");
51     if (!color_node) {
52         return nullptr;
53     }
54 
55     abuilder->bindProperty<ScalarValue>((*opacity_prop)["v"], ascope,
56         [color_node](const ScalarValue& o) {
57             const auto c = color_node->getColor();
58             const auto a = sk_float_round2int_no_saturate(SkTPin(o, 0.0f, 1.0f) * 255);
59             color_node->setColor(SkColorSetA(c, a));
60         });
61 
62     return sksg::ColorModeFilter::Make(std::move(layer),
63                                        std::move(color_node),
64                                        SkBlendMode::kSrcIn);
65 }
66 
67 } // namespace
68 
attachLayerEffects(const skjson::ArrayValue & jeffects,AnimatorScope * ascope,sk_sp<sksg::RenderNode> layer) const69 sk_sp<sksg::RenderNode> AnimationBuilder::attachLayerEffects(const skjson::ArrayValue& jeffects,
70                                                              AnimatorScope* ascope,
71                                                              sk_sp<sksg::RenderNode> layer) const {
72     for (const skjson::ObjectValue* jeffect : jeffects) {
73         if (!jeffect) continue;
74 
75         switch (const auto ty = ParseDefault<int>((*jeffect)["ty"], -1)) {
76         case 21: // Fill
77             layer = AttachFillLayerEffect((*jeffect)["ef"], this, ascope, std::move(layer));
78             break;
79         default:
80             this->log(Logger::Level::kWarning, nullptr, "Unsupported layer effect type: %d.", ty);
81             break;
82         }
83 
84         if (!layer) {
85             this->log(Logger::Level::kError, jeffect, "Invalid layer effect.");
86             return nullptr;
87         }
88     }
89 
90     return layer;
91 }
92 
93 } // namespace internal
94 } // namespace skottie
95