/* * 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/text/RangeSelector.h" #include "include/core/SkCubicMap.h" #include "include/private/base/SkAssert.h" #include "include/private/base/SkFloatingPoint.h" #include "include/private/base/SkPoint_impl.h" #include "include/private/base/SkTPin.h" #include "include/private/base/SkTo.h" #include "modules/skottie/include/Skottie.h" #include "modules/skottie/src/SkottieJson.h" #include "modules/skottie/src/SkottiePriv.h" #include "modules/skottie/src/animator/Animator.h" #include "src/utils/SkJSON.h" #include <algorithm> #include <limits> #include <vector> namespace skottie { namespace internal { namespace { // Maps a 1-based JSON enum to one of the values in the array. template <typename T, typename TArray> T ParseEnum(const TArray& arr, const skjson::Value& jenum, const AnimationBuilder* abuilder, const char* warn_name) { … } template <RangeSelector::Units> struct UnitTraits; template <> struct UnitTraits<RangeSelector::Units::kPercentage> { … }; template <> struct UnitTraits<RangeSelector::Units::kIndex> { … }; class CoverageProcessor { … }; /* Selector shapes can be generalized as a signal generator with the following parameters/properties: 1 + ------------------------- | /. . .\ | / . . . \ | / . . . \ | / . . . \ | / . . . \ | / . . . \ | / . . . \ | / . . . \ 0 +---------------------------------------------------------- ^ <-----> ^ <-----> ^ e0 crs sp crs e1 * e0, e1: left/right edges * sp : symmetry/reflection point (sp == (e0+e1)/2) * crs : cubic ramp size (transitional portion mapped using a Bezier easing function) Based on these, | 0 , t <= e0 | | Bez((t-e0)/crs) , e0 < t < e0+crs F(t) = | | 1 , e0 + crs <= t <= sp | | F(reflect(t,sp)) , t > sp Tweaking this function's parameters, we can achieve all range selectors shapes: - square -> e0: 0, e1: 1, crs: 0 - ramp up -> e0: 0, e1: +inf, crs: 1 - ramp down -> e0: -inf, e1: 1, crs: 1 - triangle -> e0: 0, e1: 1, crs: 0.5 - round -> e0: 0, e1: 1, crs: 0.5 (nonlinear cubic mapper) - smooth -> e0: 0, e1: 1, crs: 0.5 (nonlinear cubic mapper) */ struct ShapeInfo { … }; SkVector EaseVec(float ease) { … } struct ShapeGenerator { … }; static constexpr ShapeInfo gShapeInfo[] = …; } // namespace sk_sp<RangeSelector> RangeSelector::Make(const skjson::ObjectValue* jrange, const AnimationBuilder* abuilder, AnimatablePropertyContainer* acontainer) { … } RangeSelector::RangeSelector(Units u, Domain d, Mode m, Shape sh) : … { … } std::tuple<float, float> RangeSelector::resolve(size_t len) const { … } /* * General RangeSelector operation: * * 1) The range is resolved to a target domain (characters, words, etc) interval, based on * |start|, |end|, |offset|, |units|. * * 2) A shape generator is mapped to this interval and applied across the whole domain, yielding * coverage values in [0..1]. * * 3) The coverage is then scaled by the |amount| parameter. * * 4) Finally, the resulting coverage is accumulated to existing fragment coverage based on * the specified Mode (add, difference, etc). */ void RangeSelector::modulateCoverage(const TextAnimator::DomainMaps& maps, TextAnimator::ModulatorBuffer& mbuf) const { … } } // namespace internal } // namespace skottie