blob: da00beb2fef7639708ebe999c4b00d516ca5b2fd [file] [log] [blame]
Florin Malita094ccde2017-12-30 12:27:00 -05001/*
2 * Copyright 2017 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
Florin Malita54f65c42018-01-16 17:04:30 -05008#include "SkottieAnimator.h"
Florin Malita094ccde2017-12-30 12:27:00 -05009
Florin Malita54f65c42018-01-16 17:04:30 -050010namespace skottie {
Florin Malita094ccde2017-12-30 12:27:00 -050011
12namespace {
13
Florin Malita9e1c58c2018-01-08 19:23:08 -050014SkScalar lerp_scalar(float v0, float v1, float t) {
Florin Malita094ccde2017-12-30 12:27:00 -050015 SkASSERT(t >= 0 && t <= 1);
16 return v0 * (1 - t) + v1 * t;
17}
18
Florin Malitaad335bb2018-01-22 23:27:21 -050019static inline SkPoint ParsePoint(const Json::Value& v, const SkPoint& defaultValue) {
20 if (!v.isObject())
21 return defaultValue;
22
23 const auto& vx = v["x"];
24 const auto& vy = v["y"];
25
26 // Some BM versions seem to store x/y as single-element arrays.
27 return SkPoint::Make(ParseScalar(vx.isArray() ? vx[0] : vx, defaultValue.x()),
28 ParseScalar(vy.isArray() ? vy[0] : vy, defaultValue.y()));
29}
30
Florin Malita094ccde2017-12-30 12:27:00 -050031} // namespace
32
Florin Malita9e1c58c2018-01-08 19:23:08 -050033bool KeyframeIntervalBase::parse(const Json::Value& k, KeyframeIntervalBase* prev) {
34 SkASSERT(k.isObject());
35
36 fT0 = fT1 = ParseScalar(k["t"], SK_ScalarMin);
37 if (fT0 == SK_ScalarMin) {
38 return false;
39 }
40
41 if (prev) {
42 if (prev->fT1 >= fT0) {
43 LOG("!! Dropping out-of-order key frame (t: %f < t: %f)\n", fT0, prev->fT1);
44 return false;
45 }
46 // Back-fill t1 in prev interval. Note: we do this even if we end up discarding
47 // the current interval (to support "t"-only final frames).
48 prev->fT1 = fT0;
49 }
50
Florin Malita7b3415c2018-01-24 11:17:42 -050051 fHold = ParseBool(k["h"], false);
Florin Malita9e1c58c2018-01-08 19:23:08 -050052
Florin Malita7b3415c2018-01-24 11:17:42 -050053 if (!fHold) {
54 // default is linear lerp
55 static constexpr SkPoint kDefaultC0 = { 0, 0 },
56 kDefaultC1 = { 1, 1 };
57 const auto c0 = ParsePoint(k["i"], kDefaultC0),
58 c1 = ParsePoint(k["o"], kDefaultC1);
59
60 if (c0 != kDefaultC0 || c1 != kDefaultC1) {
61 fCubicMap = skstd::make_unique<SkCubicMap>();
62 // TODO: why do we have to plug these inverted?
63 fCubicMap->setPts(c1, c0);
64 }
Florin Malita9e1c58c2018-01-08 19:23:08 -050065 }
66
67 return true;
68}
69
70float KeyframeIntervalBase::localT(float t) const {
71 SkASSERT(this->isValid());
Florin Malita7b3415c2018-01-24 11:17:42 -050072
73 // 'hold' pins to v0
74 if (fHold) {
75 return 0;
76 }
77
Florin Malita9e1c58c2018-01-08 19:23:08 -050078 auto lt = (t - fT0) / (fT1 - fT0);
79
80 if (fCubicMap) {
81 lt = fCubicMap->computeYFromX(lt);
82 }
83
84 return SkTPin<float>(lt, 0, 1);
85}
86
Florin Malita094ccde2017-12-30 12:27:00 -050087template <>
88void KeyframeInterval<ScalarValue>::lerp(float t, ScalarValue* v) const {
Florin Malita9e1c58c2018-01-08 19:23:08 -050089 const auto lt = this->localT(t);
90 *v = lerp_scalar(fV0, fV1, lt);
Florin Malita094ccde2017-12-30 12:27:00 -050091}
92
93template <>
94void KeyframeInterval<VectorValue>::lerp(float t, VectorValue* v) const {
Florin Malita9e1c58c2018-01-08 19:23:08 -050095 SkASSERT(fV0.size() == fV1.size());
96 SkASSERT(v->size() == 0);
Florin Malita094ccde2017-12-30 12:27:00 -050097
Florin Malita9e1c58c2018-01-08 19:23:08 -050098 const auto lt = this->localT(t);
99
100 v->reserve(fV0.size());
101 for (size_t i = 0; i < fV0.size(); ++i) {
102 v->push_back(lerp_scalar(fV0[i], fV1[i], lt));
Florin Malita094ccde2017-12-30 12:27:00 -0500103 }
104}
105
106template <>
107void KeyframeInterval<ShapeValue>::lerp(float t, ShapeValue* v) const {
Florin Malita9e1c58c2018-01-08 19:23:08 -0500108 SkASSERT(fV0.countVerbs() == fV1.countVerbs());
109 SkASSERT(v->isEmpty());
Florin Malita094ccde2017-12-30 12:27:00 -0500110
Florin Malita9e1c58c2018-01-08 19:23:08 -0500111 const auto lt = this->localT(t);
112 SkAssertResult(fV1.interpolate(fV0, lt, v));
113 v->setIsVolatile(true);
Florin Malitad6c4f8f2018-01-04 13:11:14 -0500114}
115
Florin Malita54f65c42018-01-16 17:04:30 -0500116} // namespace skottie