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