Home | History | Annotate | Download | only in src
      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 
     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 
     69 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