[skottie] Add support for Transform distort effect
Yet another way to transform a layer, disguised as a distort effect.
TBR=
Change-Id: Ic2d5479fa6ae27b460de60875924f73f77fc7f71
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/221001
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/modules/skottie/skottie.gni b/modules/skottie/skottie.gni
index dc9c418..342860b 100644
--- a/modules/skottie/skottie.gni
+++ b/modules/skottie/skottie.gni
@@ -28,6 +28,10 @@
"$_src/SkottieValue.cpp",
"$_src/SkottieValue.h",
+ "$_src/effects/Effects.cpp",
+ "$_src/effects/Effects.h",
+ "$_src/effects/TransformEffect.cpp",
+
"$_src/text/RangeSelector.cpp",
"$_src/text/RangeSelector.h",
"$_src/text/SkottieShaper.cpp",
diff --git a/modules/skottie/src/SkottieLayerEffect.cpp b/modules/skottie/src/SkottieLayerEffect.cpp
index 5f3e8f8..995c4de 100644
--- a/modules/skottie/src/SkottieLayerEffect.cpp
+++ b/modules/skottie/src/SkottieLayerEffect.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "modules/skottie/src/SkottiePriv.h"
+#include "modules/skottie/src/effects/Effects.h"
#include "modules/skottie/src/SkottieAdapter.h"
#include "modules/skottie/src/SkottieJson.h"
@@ -440,6 +440,9 @@
if (!strcmp(mn->begin(), "ADBE Easy Levels2")) {
return AttachLevelsLayerEffect;
}
+ if (!strcmp(mn->begin(), "ADBE Geometry2")) {
+ return AttachTransformEffect;
+ }
}
abuilder->log(Logger::Level::kWarning, nullptr, "Unsupported layer effect type: %d.", ty);
diff --git a/modules/skottie/src/effects/Effects.cpp b/modules/skottie/src/effects/Effects.cpp
new file mode 100644
index 0000000..f6c62c8
--- /dev/null
+++ b/modules/skottie/src/effects/Effects.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "modules/skottie/src/effects/Effects.h"
+
+#include "src/utils/SkJSON.h"
+
+namespace skottie {
+namespace internal {
+
+const skjson::Value& EffectBuilder::GetPropValue(const skjson::ArrayValue& jprops,
+ size_t prop_index) {
+ static skjson::NullValue kNull;
+
+ if (prop_index >= jprops.size()) {
+ return kNull;
+ }
+
+ const skjson::ObjectValue* jprop = jprops[prop_index];
+
+ return jprop ? (*jprop)["v"] : kNull;
+}
+
+} // namespace internal
+} // namespace skottie
diff --git a/modules/skottie/src/effects/Effects.h b/modules/skottie/src/effects/Effects.h
new file mode 100644
index 0000000..f3d5883
--- /dev/null
+++ b/modules/skottie/src/effects/Effects.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkottieEffects_DEFINED
+#define SkottieEffects_DEFINED
+
+#include "modules/skottie/src/SkottiePriv.h"
+
+namespace skottie {
+namespace internal {
+
+class AnimationBuilder;
+
+// TODO: relocate SkottieLayerEffect builder logic here.
+class EffectBuilder final : public SkNoncopyable {
+public:
+ static const skjson::Value& GetPropValue(const skjson::ArrayValue& jprops, size_t prop_index);
+};
+
+sk_sp<sksg::RenderNode> AttachTransformEffect(const skjson::ArrayValue&,
+ const AnimationBuilder*,
+ AnimatorScope*,
+ sk_sp<sksg::RenderNode>);
+
+
+} // namespace internal
+} // namespace skottie
+
+#endif // SkottieEffects_DEFINED
diff --git a/modules/skottie/src/effects/TransformEffect.cpp b/modules/skottie/src/effects/TransformEffect.cpp
new file mode 100644
index 0000000..7dfb134
--- /dev/null
+++ b/modules/skottie/src/effects/TransformEffect.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "modules/skottie/src/effects/Effects.h"
+
+#include "modules/skottie/src/SkottieAdapter.h"
+#include "modules/skottie/src/SkottieJson.h"
+#include "modules/sksg/include/SkSGOpacityEffect.h"
+#include "modules/sksg/include/SkSGTransform.h"
+
+namespace skottie {
+namespace internal {
+
+namespace {
+
+// Transform effects can operate in either uniform or anisotropic mode, with each
+// component (including mode) animated separately.
+class ScaleAdapter final : public SkNVRefCnt<ScaleAdapter> {
+public:
+ explicit ScaleAdapter(sk_sp<TransformAdapter2D> tadapter)
+ : fTransformAdapter(std::move(tadapter)) {}
+
+ ADAPTER_PROPERTY(IsUniform , bool , false)
+ ADAPTER_PROPERTY(ScaleWidth , SkScalar, 100)
+ ADAPTER_PROPERTY(ScaleHeight, SkScalar, 100)
+
+private:
+ void apply() {
+ // In uniform mode, the scale is based solely in ScaleHeight.
+ const auto scale = SkVector::Make(fIsUniform ? fScaleHeight : fScaleWidth,
+ fScaleHeight);
+ fTransformAdapter->setScale(scale);
+ }
+
+ const sk_sp<TransformAdapter2D> fTransformAdapter;
+};
+
+} // anonymous ns
+
+sk_sp<sksg::RenderNode> AttachTransformEffect(const skjson::ArrayValue& jprops,
+ const AnimationBuilder* abuilder,
+ AnimatorScope* ascope,
+ sk_sp<sksg::RenderNode> layer) {
+ 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 matrix = sksg::Matrix<SkMatrix>::Make(SkMatrix::I());
+ auto t_adapter = sk_make_sp<TransformAdapter2D>(matrix);
+ auto s_adapter = sk_make_sp<ScaleAdapter>(t_adapter);
+
+ abuilder->bindProperty<VectorValue>(EffectBuilder::GetPropValue(jprops, kAnchorPoint_Index),
+ ascope,
+ [t_adapter](const VectorValue& ap) {
+ t_adapter->setAnchorPoint(ValueTraits<VectorValue>::As<SkPoint>(ap));
+ });
+ abuilder->bindProperty<VectorValue>(EffectBuilder::GetPropValue(jprops, kPosition_Index),
+ ascope,
+ [t_adapter](const VectorValue& p) {
+ t_adapter->setPosition(ValueTraits<VectorValue>::As<SkPoint>(p));
+ });
+ abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops, kRotation_Index),
+ ascope,
+ [t_adapter](const ScalarValue& r) {
+ t_adapter->setRotation(r);
+ });
+ abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops, kSkew_Index),
+ ascope,
+ [t_adapter](const ScalarValue& s) {
+ t_adapter->setSkew(s);
+ });
+ abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops, kSkewAxis_Index),
+ ascope,
+ [t_adapter](const ScalarValue& sa) {
+ t_adapter->setSkewAxis(sa);
+ });
+
+ abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops, kUniformScale_Index),
+ ascope,
+ [s_adapter](const ScalarValue& u) {
+ s_adapter->setIsUniform(SkScalarRoundToInt(u));
+ });
+ abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops, kScaleHeight_Index),
+ ascope,
+ [s_adapter](const ScalarValue& sh) {
+ s_adapter->setScaleHeight(sh);
+ });
+ abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops, kScaleWidth_Index),
+ ascope,
+ [s_adapter](const ScalarValue& sw) {
+ s_adapter->setScaleWidth(sw);
+ });
+
+ auto opacity_node = sksg::OpacityEffect::Make(sksg::TransformEffect::Make(std::move(layer),
+ std::move(matrix)));
+
+ abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops, kOpacity_Index),
+ ascope,
+ [opacity_node](const ScalarValue& o) {
+ opacity_node->setOpacity(o * 0.01f);
+ });
+
+ return std::move(opacity_node);
+}
+
+} // namespace internal
+} // namespace skottie
diff --git a/public.bzl b/public.bzl
index 0d69b34..f3f56af 100644
--- a/public.bzl
+++ b/public.bzl
@@ -700,6 +700,8 @@
[
"modules/skottie/src/*.cpp",
"modules/skottie/src/*.h",
+ "modules/skottie/src/effects/*.cpp",
+ "modules/skottie/src/effects/*.h",
"modules/skottie/src/text/*.cpp",
"modules/skottie/src/text/*.h",
],
diff --git a/resources/skottie/skottie-transform-effect.json b/resources/skottie/skottie-transform-effect.json
new file mode 100644
index 0000000..a34d3d2
--- /dev/null
+++ b/resources/skottie/skottie-transform-effect.json
@@ -0,0 +1 @@
+{"v":"5.5.2","fr":60,"ip":0,"op":300,"w":500,"h":500,"nm":"transform effect","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[650,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Transform","np":14,"mn":"ADBE Geometry2","ix":1,"en":1,"ef":[{"ty":3,"nm":"Anchor Point","mn":"ADBE Geometry2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[250,250],"to":[33.333,0],"ti":[-33.333,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":60,"s":[450,250],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":239,"s":[450,250],"to":[-33.333,0],"ti":[33.333,0]},{"t":299,"s":[250,250]}],"ix":1}},{"ty":3,"nm":"Position","mn":"ADBE Geometry2-0002","ix":2,"v":{"a":0,"k":[250,250],"ix":2}},{"ty":7,"nm":"Uniform Scale","mn":"ADBE Geometry2-0011","ix":3,"v":{"a":1,"k":[{"t":0,"s":[1],"h":1},{"t":150,"s":[0],"h":1}],"ix":3}},{"ty":0,"nm":"Scale","mn":"ADBE Geometry2-0003","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[300]},{"t":239,"s":[100]}],"ix":4}},{"ty":0,"nm":" ","mn":"ADBE Geometry2-0004","ix":5,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[300]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":239,"s":[300]},{"t":299,"s":[100]}],"ix":5}},{"ty":0,"nm":"Skew","mn":"ADBE Geometry2-0005","ix":6,"v":{"a":0,"k":0,"ix":6}},{"ty":0,"nm":"Skew Axis","mn":"ADBE Geometry2-0006","ix":7,"v":{"a":0,"k":0,"ix":7}},{"ty":0,"nm":"Rotation","mn":"ADBE Geometry2-0007","ix":8,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[0]},{"t":239,"s":[360]}],"ix":8}},{"ty":0,"nm":"Opacity","mn":"ADBE Geometry2-0008","ix":9,"v":{"a":0,"k":100,"ix":9}},{"ty":7,"nm":"Use Composition’s Shutter Angle","mn":"ADBE Geometry2-0009","ix":10,"v":{"a":0,"k":1,"ix":10}},{"ty":0,"nm":"Shutter Angle","mn":"ADBE Geometry2-0010","ix":11,"v":{"a":0,"k":0,"ix":11}},{"ty":7,"nm":"Sampling","mn":"ADBE Geometry2-0012","ix":12,"v":{"a":0,"k":1,"ix":12}}]}],"shapes":[{"d":1,"ty":"el","s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[-200,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"rc","d":1,"s":{"a":0,"k":[140,10],"ix":2},"p":{"a":0,"k":[-200,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.834589481354,0.295220583677,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":8,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.511764705181,0.350321680307,0.746308207512,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file