blob: 13f14dbf75db7d12c1f7a55354d31558ae1b1627 [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 Malita2d5fb122018-01-24 14:30:12 -050072 SkASSERT(!this->isHold());
73 SkASSERT(t > fT0 && t < fT1);
Florin Malita7b3415c2018-01-24 11:17:42 -050074
Florin Malita9e1c58c2018-01-08 19:23:08 -050075 auto lt = (t - fT0) / (fT1 - fT0);
76
Florin Malita2d5fb122018-01-24 14:30:12 -050077 return fCubicMap ? fCubicMap->computeYFromX(lt) : lt;
Florin Malita9e1c58c2018-01-08 19:23:08 -050078}
79
Florin Malita094ccde2017-12-30 12:27:00 -050080template <>
81void KeyframeInterval<ScalarValue>::lerp(float t, ScalarValue* v) const {
Florin Malita9e1c58c2018-01-08 19:23:08 -050082 const auto lt = this->localT(t);
83 *v = lerp_scalar(fV0, fV1, lt);
Florin Malita094ccde2017-12-30 12:27:00 -050084}
85
86template <>
87void KeyframeInterval<VectorValue>::lerp(float t, VectorValue* v) const {
Florin Malita9e1c58c2018-01-08 19:23:08 -050088 SkASSERT(fV0.size() == fV1.size());
89 SkASSERT(v->size() == 0);
Florin Malita094ccde2017-12-30 12:27:00 -050090
Florin Malita9e1c58c2018-01-08 19:23:08 -050091 const auto lt = this->localT(t);
92
93 v->reserve(fV0.size());
94 for (size_t i = 0; i < fV0.size(); ++i) {
95 v->push_back(lerp_scalar(fV0[i], fV1[i], lt));
Florin Malita094ccde2017-12-30 12:27:00 -050096 }
97}
98
99template <>
100void KeyframeInterval<ShapeValue>::lerp(float t, ShapeValue* v) const {
Florin Malita9e1c58c2018-01-08 19:23:08 -0500101 SkASSERT(fV0.countVerbs() == fV1.countVerbs());
102 SkASSERT(v->isEmpty());
Florin Malita094ccde2017-12-30 12:27:00 -0500103
Florin Malita9e1c58c2018-01-08 19:23:08 -0500104 const auto lt = this->localT(t);
105 SkAssertResult(fV1.interpolate(fV0, lt, v));
106 v->setIsVolatile(true);
Florin Malitad6c4f8f2018-01-04 13:11:14 -0500107}
108
Florin Malita54f65c42018-01-16 17:04:30 -0500109} // namespace skottie