1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "modules/skottie/src/effects/Effects.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "modules/skottie/src/SkottieJson.h"
11cb93a386Sopenharmony_ci#include "modules/skottie/src/Transform.h"
12cb93a386Sopenharmony_ci#include "modules/sksg/include/SkSGOpacityEffect.h"
13cb93a386Sopenharmony_ci#include "modules/sksg/include/SkSGTransform.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_cinamespace skottie {
16cb93a386Sopenharmony_cinamespace internal {
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_cinamespace  {
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ciclass TransformEffectAdapter final : public DiscardableAdapterBase<TransformEffectAdapter,
21cb93a386Sopenharmony_ci                                                                   sksg::OpacityEffect> {
22cb93a386Sopenharmony_cipublic:
23cb93a386Sopenharmony_ci    TransformEffectAdapter(const AnimationBuilder& abuilder,
24cb93a386Sopenharmony_ci                           const skjson::ObjectValue* jopacity,
25cb93a386Sopenharmony_ci                           const skjson::ObjectValue* jscale_uniform,
26cb93a386Sopenharmony_ci                           const skjson::ObjectValue* jscale_width,
27cb93a386Sopenharmony_ci                           const skjson::ObjectValue* jscale_height,
28cb93a386Sopenharmony_ci                           sk_sp<TransformAdapter2D> tadapter,
29cb93a386Sopenharmony_ci                           sk_sp<sksg::RenderNode> child)
30cb93a386Sopenharmony_ci        : INHERITED(sksg::OpacityEffect::Make(std::move(child)))
31cb93a386Sopenharmony_ci        , fTransformAdapter(std::move(tadapter)) {
32cb93a386Sopenharmony_ci        this->bind(abuilder, jopacity      , fOpacity     );
33cb93a386Sopenharmony_ci        this->bind(abuilder, jscale_uniform, fUniformScale);
34cb93a386Sopenharmony_ci        this->bind(abuilder, jscale_width  , fScaleWidth  );
35cb93a386Sopenharmony_ci        this->bind(abuilder, jscale_height , fScaleHeight );
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci        this->attachDiscardableAdapter(fTransformAdapter);
38cb93a386Sopenharmony_ci    }
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_ciprivate:
41cb93a386Sopenharmony_ci    void onSync() override {
42cb93a386Sopenharmony_ci        this->node()->setOpacity(fOpacity * 0.01f);
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci        // In uniform mode, the scale is based solely in ScaleHeight.
45cb93a386Sopenharmony_ci        const auto scale = SkVector::Make(SkScalarRoundToInt(fUniformScale) ? fScaleHeight
46cb93a386Sopenharmony_ci                                                                            : fScaleWidth,
47cb93a386Sopenharmony_ci                                          fScaleHeight);
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci        // NB: this triggers an transform adapter -> SG sync.
50cb93a386Sopenharmony_ci        fTransformAdapter->setScale(scale);
51cb93a386Sopenharmony_ci    }
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci    const sk_sp<TransformAdapter2D> fTransformAdapter;
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_ci    ScalarValue fOpacity      = 100,
56cb93a386Sopenharmony_ci                fUniformScale =   0, // bool
57cb93a386Sopenharmony_ci                fScaleWidth   = 100,
58cb93a386Sopenharmony_ci                fScaleHeight  = 100;
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ci    using INHERITED = DiscardableAdapterBase<TransformEffectAdapter, sksg::OpacityEffect>;
61cb93a386Sopenharmony_ci};
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci}  // namespace
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_cisk_sp<sksg::RenderNode> EffectBuilder::attachTransformEffect(const skjson::ArrayValue& jprops,
66cb93a386Sopenharmony_ci                                                             sk_sp<sksg::RenderNode> layer) const {
67cb93a386Sopenharmony_ci    enum : size_t {
68cb93a386Sopenharmony_ci        kAnchorPoint_Index            =  0,
69cb93a386Sopenharmony_ci        kPosition_Index               =  1,
70cb93a386Sopenharmony_ci        kUniformScale_Index           =  2,
71cb93a386Sopenharmony_ci        kScaleHeight_Index            =  3,
72cb93a386Sopenharmony_ci        kScaleWidth_Index             =  4,
73cb93a386Sopenharmony_ci        kSkew_Index                   =  5,
74cb93a386Sopenharmony_ci        kSkewAxis_Index               =  6,
75cb93a386Sopenharmony_ci        kRotation_Index               =  7,
76cb93a386Sopenharmony_ci        kOpacity_Index                =  8,
77cb93a386Sopenharmony_ci        // kUseCompShutterAngle_Index =  9,
78cb93a386Sopenharmony_ci        // kShutterAngle_Index        = 10,
79cb93a386Sopenharmony_ci        // kSampling_Index            = 11,
80cb93a386Sopenharmony_ci    };
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ci    auto transform_adapter = TransformAdapter2D::Make(*fBuilder,
83cb93a386Sopenharmony_ci                                                      GetPropValue(jprops, kAnchorPoint_Index),
84cb93a386Sopenharmony_ci                                                      GetPropValue(jprops, kPosition_Index),
85cb93a386Sopenharmony_ci                                                      nullptr, // scale is handled externally
86cb93a386Sopenharmony_ci                                                      GetPropValue(jprops, kRotation_Index),
87cb93a386Sopenharmony_ci                                                      GetPropValue(jprops, kSkew_Index),
88cb93a386Sopenharmony_ci                                                      GetPropValue(jprops, kSkewAxis_Index));
89cb93a386Sopenharmony_ci    if (!transform_adapter) {
90cb93a386Sopenharmony_ci        return nullptr;
91cb93a386Sopenharmony_ci    }
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    auto transform_effect_node = sksg::TransformEffect::Make(std::move(layer),
94cb93a386Sopenharmony_ci                                                             transform_adapter->node());
95cb93a386Sopenharmony_ci    return fBuilder->attachDiscardableAdapter<TransformEffectAdapter>
96cb93a386Sopenharmony_ci            (*fBuilder,
97cb93a386Sopenharmony_ci             GetPropValue(jprops, kOpacity_Index),
98cb93a386Sopenharmony_ci             GetPropValue(jprops, kUniformScale_Index),
99cb93a386Sopenharmony_ci             GetPropValue(jprops, kScaleWidth_Index),
100cb93a386Sopenharmony_ci             GetPropValue(jprops, kScaleHeight_Index),
101cb93a386Sopenharmony_ci             std::move(transform_adapter),
102cb93a386Sopenharmony_ci             std::move(transform_effect_node)
103cb93a386Sopenharmony_ci             );
104cb93a386Sopenharmony_ci}
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci} // namespace internal
107cb93a386Sopenharmony_ci} // namespace skottie
108