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