| /* | |
| * Copyright 2019 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "include/core/SkPoint.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkScalar.h" | |
| #include "modules/skottie/src/Adapter.h" | |
| #include "modules/skottie/src/SkottiePriv.h" | |
| #include "modules/skottie/src/SkottieValue.h" | |
| #include "modules/skottie/src/Transform.h" | |
| #include "modules/skottie/src/animator/Animator.h" | |
| #include "modules/skottie/src/effects/Effects.h" | |
| #include "modules/sksg/include/SkSGOpacityEffect.h" | |
| #include "modules/sksg/include/SkSGRenderNode.h" | |
| #include "modules/sksg/include/SkSGTransform.h" | |
| #include <cstddef> | |
| #include <utility> | |
| namespace skjson { | |
| class ArrayValue; | |
| class ObjectValue; | |
| } // namespace skjson | |
| namespace skottie { | |
| namespace internal { | |
| namespace { | |
| class TransformEffectAdapter final : public DiscardableAdapterBase<TransformEffectAdapter, | |
| sksg::OpacityEffect> { | |
| 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) | |
| : INHERITED(sksg::OpacityEffect::Make(std::move(child))) | |
| , fTransformAdapter(std::move(tadapter)) { | |
| this->bind(abuilder, jopacity , fOpacity ); | |
| this->bind(abuilder, jscale_uniform, fUniformScale); | |
| this->bind(abuilder, jscale_width , fScaleWidth ); | |
| this->bind(abuilder, jscale_height , fScaleHeight ); | |
| this->attachDiscardableAdapter(fTransformAdapter); | |
| } | |
| private: | |
| void onSync() override { | |
| this->node()->setOpacity(fOpacity * 0.01f); | |
| // In uniform mode, the scale is based solely in ScaleHeight. | |
| const auto scale = SkVector::Make(SkScalarRoundToInt(fUniformScale) ? fScaleHeight | |
| : fScaleWidth, | |
| fScaleHeight); | |
| // NB: this triggers an transform adapter -> SG sync. | |
| fTransformAdapter->setScale(scale); | |
| } | |
| const sk_sp<TransformAdapter2D> fTransformAdapter; | |
| ScalarValue fOpacity = 100, | |
| fUniformScale = 0, // bool | |
| fScaleWidth = 100, | |
| fScaleHeight = 100; | |
| using INHERITED = DiscardableAdapterBase<TransformEffectAdapter, sksg::OpacityEffect>; | |
| }; | |
| } // namespace | |
| sk_sp<sksg::RenderNode> EffectBuilder::attachTransformEffect(const skjson::ArrayValue& jprops, | |
| sk_sp<sksg::RenderNode> layer) const { | |
| enum : size_t { | |
| kAnchorPoint_Index = 0, | |
| kPosition_Index = 1, | |
| kUniformScale_Index = 2, | |
| kScaleHeight_Index = 3, | |
| kScaleWidth_Index = 4, | |
| kSkew_Index = 5, | |
| kSkewAxis_Index = 6, | |
| kRotation_Index = 7, | |
| kOpacity_Index = 8, | |
| // kUseCompShutterAngle_Index = 9, | |
| // kShutterAngle_Index = 10, | |
| // kSampling_Index = 11, | |
| }; | |
| auto transform_adapter = TransformAdapter2D::Make(*fBuilder, | |
| GetPropValue(jprops, kAnchorPoint_Index), | |
| GetPropValue(jprops, kPosition_Index), | |
| nullptr, // scale is handled externally | |
| GetPropValue(jprops, kRotation_Index), | |
| GetPropValue(jprops, kSkew_Index), | |
| GetPropValue(jprops, kSkewAxis_Index)); | |
| if (!transform_adapter) { | |
| return nullptr; | |
| } | |
| auto transform_effect_node = sksg::TransformEffect::Make(std::move(layer), | |
| transform_adapter->node()); | |
| return fBuilder->attachDiscardableAdapter<TransformEffectAdapter> | |
| (*fBuilder, | |
| GetPropValue(jprops, kOpacity_Index), | |
| GetPropValue(jprops, kUniformScale_Index), | |
| GetPropValue(jprops, kScaleWidth_Index), | |
| GetPropValue(jprops, kScaleHeight_Index), | |
| std::move(transform_adapter), | |
| std::move(transform_effect_node) | |
| ); | |
| } | |
| } // namespace internal | |
| } // namespace skottie |