1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "modules/skottie/src/SkottieJson.h"
9cb93a386Sopenharmony_ci#include "modules/skottie/src/SkottieValue.h"
10cb93a386Sopenharmony_ci#include "modules/skottie/src/animator/KeyframeAnimator.h"
11cb93a386Sopenharmony_ci#include "modules/skottie/src/text/TextValue.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_cinamespace skottie::internal {
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_cinamespace  {
16cb93a386Sopenharmony_ciclass TextKeyframeAnimator final : public KeyframeAnimator {
17cb93a386Sopenharmony_cipublic:
18cb93a386Sopenharmony_ci    TextKeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms,
19cb93a386Sopenharmony_ci                         std::vector<TextValue> vs, TextValue* target_value)
20cb93a386Sopenharmony_ci        : INHERITED(std::move(kfs), std::move(cms))
21cb93a386Sopenharmony_ci        , fValues(std::move(vs))
22cb93a386Sopenharmony_ci        , fTarget(target_value) {}
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ciprivate:
25cb93a386Sopenharmony_ci    StateChanged onSeek(float t) override {
26cb93a386Sopenharmony_ci        const auto& lerp_info = this->getLERPInfo(t);
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ci        // Text value keyframes are treated as selectors, not as interpolated values.
29cb93a386Sopenharmony_ci        if (*fTarget != fValues[SkToSizeT(lerp_info.vrec0.idx)]) {
30cb93a386Sopenharmony_ci            *fTarget = fValues[SkToSizeT(lerp_info.vrec0.idx)];
31cb93a386Sopenharmony_ci            return true;
32cb93a386Sopenharmony_ci        }
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci        return false;
35cb93a386Sopenharmony_ci    }
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci    const std::vector<TextValue> fValues;
38cb93a386Sopenharmony_ci    TextValue*                   fTarget;
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_ci    using INHERITED = KeyframeAnimator;
41cb93a386Sopenharmony_ci};
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ciclass TextExpressionAnimator final : public Animator {
44cb93a386Sopenharmony_cipublic:
45cb93a386Sopenharmony_ci    TextExpressionAnimator(sk_sp<ExpressionEvaluator<SkString>> expression_evaluator,
46cb93a386Sopenharmony_ci        TextValue* target_value)
47cb93a386Sopenharmony_ci        : fExpressionEvaluator(std::move(expression_evaluator))
48cb93a386Sopenharmony_ci        , fTarget(target_value) {}
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ciprivate:
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci    StateChanged onSeek(float t) override {
53cb93a386Sopenharmony_ci        SkString old_value = fTarget->fText;
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_ci        fTarget->fText = fExpressionEvaluator->evaluate(t);
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci        return fTarget->fText != old_value;
58cb93a386Sopenharmony_ci    }
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ci    sk_sp<ExpressionEvaluator<SkString>> fExpressionEvaluator;
61cb93a386Sopenharmony_ci    TextValue* fTarget;
62cb93a386Sopenharmony_ci};
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ciclass TextAnimatorBuilder final : public AnimatorBuilder {
65cb93a386Sopenharmony_cipublic:
66cb93a386Sopenharmony_ci    explicit TextAnimatorBuilder(TextValue* target)
67cb93a386Sopenharmony_ci        : INHERITED(Keyframe::Value::Type::kIndex)
68cb93a386Sopenharmony_ci        , fTarget(target) {}
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder& abuilder,
71cb93a386Sopenharmony_ci                                    const skjson::ArrayValue& jkfs) override {
72cb93a386Sopenharmony_ci        SkASSERT(jkfs.size() > 0);
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_ci        fValues.reserve(jkfs.size());
75cb93a386Sopenharmony_ci        if (!this->parseKeyframes(abuilder, jkfs)) {
76cb93a386Sopenharmony_ci            return nullptr;
77cb93a386Sopenharmony_ci        }
78cb93a386Sopenharmony_ci        fValues.shrink_to_fit();
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci        return sk_sp<TextKeyframeAnimator>(
81cb93a386Sopenharmony_ci                    new TextKeyframeAnimator(std::move(fKFs),
82cb93a386Sopenharmony_ci                                                std::move(fCMs),
83cb93a386Sopenharmony_ci                                                std::move(fValues),
84cb93a386Sopenharmony_ci                                                fTarget));
85cb93a386Sopenharmony_ci    }
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ci    sk_sp<Animator> makeFromExpression(ExpressionManager& em, const char* expr) override {
88cb93a386Sopenharmony_ci         sk_sp<ExpressionEvaluator<SkString>> expression_evaluator =
89cb93a386Sopenharmony_ci                em.createStringExpressionEvaluator(expr);
90cb93a386Sopenharmony_ci            return sk_make_sp<TextExpressionAnimator>(expression_evaluator, fTarget);
91cb93a386Sopenharmony_ci    }
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    bool parseValue(const AnimationBuilder& abuilder, const skjson::Value& jv) const override {
94cb93a386Sopenharmony_ci        return Parse(jv, abuilder, fTarget);
95cb93a386Sopenharmony_ci    }
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ciprivate:
98cb93a386Sopenharmony_ci    bool parseKFValue(const AnimationBuilder& abuilder,
99cb93a386Sopenharmony_ci                        const skjson::ObjectValue&,
100cb93a386Sopenharmony_ci                        const skjson::Value& jv,
101cb93a386Sopenharmony_ci                        Keyframe::Value* v) override {
102cb93a386Sopenharmony_ci        TextValue val;
103cb93a386Sopenharmony_ci        if (!Parse(jv, abuilder, &val)) {
104cb93a386Sopenharmony_ci            return false;
105cb93a386Sopenharmony_ci        }
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ci        // TODO: full deduping?
108cb93a386Sopenharmony_ci        if (fValues.empty() || val != fValues.back()) {
109cb93a386Sopenharmony_ci            fValues.push_back(std::move(val));
110cb93a386Sopenharmony_ci        }
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci        v->idx = SkToU32(fValues.size() - 1);
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci        return true;
115cb93a386Sopenharmony_ci    }
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    std::vector<TextValue> fValues;
118cb93a386Sopenharmony_ci    TextValue*             fTarget;
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci    using INHERITED = AnimatorBuilder;
121cb93a386Sopenharmony_ci};
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci} // namespace
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_citemplate <>
126cb93a386Sopenharmony_cibool AnimatablePropertyContainer::bind<TextValue>(const AnimationBuilder& abuilder,
127cb93a386Sopenharmony_ci                                                  const skjson::ObjectValue* jprop,
128cb93a386Sopenharmony_ci                                                  TextValue* v) {
129cb93a386Sopenharmony_ci    TextAnimatorBuilder builder(v);
130cb93a386Sopenharmony_ci    return this->bindImpl(abuilder, jprop, builder);
131cb93a386Sopenharmony_ci}
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci} // namespace skottie::internal
134