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