1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_EVALUATOR_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_EVALUATOR_H
18 
19 #include <cmath>
20 
21 #include "animator.h"
22 
23 #include "base/geometry/transform_util.h"
24 #include "base/memory/ace_type.h"
25 #include "core/components/common/layout/constants.h"
26 #include "core/components/common/properties/color.h"
27 #include "core/components/common/properties/shadow.h"
28 
29 namespace OHOS::Ace {
30 
31 template<typename T>
32 class Evaluator : public AceType {
33 public:
34     virtual T Evaluate(const T& begin, const T& end, float fraction) = 0;
35 };
36 
37 template<typename T>
38 class LinearEvaluator : public Evaluator<T> {
39 public:
40     LinearEvaluator() = default;
41 
42     ~LinearEvaluator() override = default;
43 
Evaluate(const T & begin,const T & end,float fraction)44     T Evaluate(const T& begin, const T& end, float fraction) override
45     {
46         return begin + (end - begin) * fraction;
47     }
48 };
49 
50 template<>
51 class LinearEvaluator<Color> : public Evaluator<Color> {
52 public:
Evaluate(const Color & begin,const Color & end,float fraction)53     Color Evaluate(const Color& begin, const Color& end, float fraction) override
54     {
55         // convert begin color from ARGB to linear
56         double beginLinearRed = 0.0;
57         double beginLinearGreen = 0.0;
58         double beginLinearBlue = 0.0;
59         double beginAlpha = begin.GetAlpha();
60         ConvertGammaToLinear(begin, beginLinearRed, beginLinearGreen, beginLinearBlue);
61 
62         // convert end color from ARGB to linear
63         double endLinearRed = 0.0;
64         double endLinearGreen = 0.0;
65         double endLinearBlue = 0.0;
66         double endAlpha = end.GetAlpha();
67         ConvertGammaToLinear(end, endLinearRed, endLinearGreen, endLinearBlue);
68 
69         // evaluate the result
70         double linearRed = beginLinearRed + (endLinearRed - beginLinearRed) * fraction;
71         double linearGreen = beginLinearGreen + (endLinearGreen - beginLinearGreen) * fraction;
72         double linearBlue = beginLinearBlue + (endLinearBlue - beginLinearBlue) * fraction;
73         double alpha = beginAlpha + (endAlpha - beginAlpha) * fraction;
74 
75         return ConvertLinearToGamma(alpha, linearRed, linearGreen, linearBlue);
76     }
77 
78 private:
79     const double GAMMA_FACTOR = 2.2;
80 
ConvertGammaToLinear(uint8_t value)81     double ConvertGammaToLinear(uint8_t value)
82     {
83         return pow(value, GAMMA_FACTOR);
84     }
85 
ConvertGammaToLinear(const Color & gammaColor,double & linearRed,double & linearGreen,double & linearBlue)86     void ConvertGammaToLinear(const Color& gammaColor, double& linearRed, double& linearGreen, double& linearBlue)
87     {
88         linearRed = ConvertGammaToLinear(gammaColor.GetRed());
89         linearGreen = ConvertGammaToLinear(gammaColor.GetGreen());
90         linearBlue = ConvertGammaToLinear(gammaColor.GetBlue());
91     }
92 
ConvertLinearToGamma(double value)93     uint8_t ConvertLinearToGamma(double value)
94     {
95         return std::clamp(static_cast<int32_t>(std::pow(value, 1.0 / GAMMA_FACTOR)), 0, UINT8_MAX);
96     }
97 
ConvertLinearToGamma(double alpha,double linearRed,double linearGreen,double linearBlue)98     Color ConvertLinearToGamma(double alpha, double linearRed, double linearGreen, double linearBlue)
99     {
100         uint8_t gammaRed = ConvertLinearToGamma(linearRed);
101         uint8_t gammaGreen = ConvertLinearToGamma(linearGreen);
102         uint8_t gammaBlue = ConvertLinearToGamma(linearBlue);
103         uint8_t gammaAlpha = std::clamp(static_cast<int32_t>(alpha), 0, UINT8_MAX);
104 
105         return Color::FromARGB(gammaAlpha, gammaRed, gammaGreen, gammaBlue);
106     }
107 };
108 
109 template<>
110 class LinearEvaluator<BorderStyle> : public Evaluator<BorderStyle> {
111 public:
Evaluate(const BorderStyle & begin,const BorderStyle & end,float fraction)112     BorderStyle Evaluate(const BorderStyle& begin, const BorderStyle& end, float fraction) override
113     {
114         if (fraction >= HALF_PERCENT) {
115             return end;
116         }
117         return begin;
118     }
119 
120 private:
121     constexpr static float HALF_PERCENT = 0.5f;
122 };
123 
124 template<>
125 class LinearEvaluator<TransformOperation> : public Evaluator<TransformOperation> {
Evaluate(const TransformOperation & begin,const TransformOperation & end,float fraction)126     TransformOperation Evaluate(const TransformOperation& begin, const TransformOperation& end, float fraction) override
127     {
128         return TransformOperation::Blend(end, begin, fraction);
129     }
130 };
131 
132 template<>
133 class LinearEvaluator<Shadow> : public Evaluator<Shadow> {
Evaluate(const Shadow & begin,const Shadow & end,float fraction)134     Shadow Evaluate(const Shadow& begin, const Shadow& end, float fraction) override
135     {
136         return Shadow::Blend(end, begin, fraction);
137     }
138 };
139 
140 template<>
141 class LinearEvaluator<TransformOperations> : public Evaluator<TransformOperations> {
142 public:
Evaluate(const TransformOperations & begin,const TransformOperations & end,float fraction)143     TransformOperations Evaluate(
144         const TransformOperations& begin, const TransformOperations& end, float fraction) override
145     {
146         return TransformOperations::Blend(end, begin, fraction);
147     }
148 };
149 
150 } // namespace OHOS::Ace
151 
152 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_EVALUATOR_H
153