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_COMPONENTS_BASE_PROPERTIES_COLOR_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_COLOR_H
18 
19 #include <cstdint>
20 #include <string>
21 
22 #include "base/utils/macros.h"
23 #include "base/utils/string_utils.h"
24 
25 namespace OHOS::Ace {
26 
27 constexpr uint32_t COLOR_ALPHA_MASK = 0xff000000;
28 
29 union ColorParam {
30 #if BIG_ENDIANNESS
31     struct {
32         uint8_t alpha;
33         uint8_t red;
34         uint8_t green;
35         uint8_t blue;
36     } argb;
37 #else
38     struct {
39         uint8_t blue;
40         uint8_t green;
41         uint8_t red;
42         uint8_t alpha;
43     } argb;
44 #endif
45     uint32_t value;
46 };
47 
48 enum class ForegroundColorStrategy : char {
49     NONE,
50     INVERT,
51 };
52 
53 // A color value present by 32 bit.
54 class ACE_FORCE_EXPORT Color {
55 public:
56     Color() = default;
Color(uint32_t value)57     constexpr explicit Color(uint32_t value) : colorValue_(ColorParam { .value = value }) {}
Color(uint32_t value,uint32_t resId)58     constexpr explicit Color(uint32_t value, uint32_t resId)
59         : colorValue_(ColorParam { .value = value }), resourceId_(resId) {}
60     ~Color() = default;
61 
62     static Color FromARGB(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue);
63     static Color FromRGBO(uint8_t red, uint8_t green, uint8_t blue, double opacity);
64     static Color FromRGB(uint8_t red, uint8_t green, uint8_t blue);
65     // Need to change the input parameters, it is more appropriate to use the passed value here.
66     static Color FromString(std::string colorStr, uint32_t maskAlpha = COLOR_ALPHA_MASK,
67         Color defaultColor = Color::BLACK);
68     static bool ParseColorString(std::string colorStr, Color& color, uint32_t maskAlpha = COLOR_ALPHA_MASK);
69     static bool ParseColorString(const std::string& colorStr, Color& color, const Color& defaultColor,
70         uint32_t maskAlpha = COLOR_ALPHA_MASK);
71     // Return the linear transition color from startColor to endColor.
72     static const Color LineColorTransition(const Color& startColor, const Color& endColor, double percent);
73 
74     static const Color TRANSPARENT;
75     static const Color WHITE;
76     static const Color BLACK;
77     static const Color RED;
78     static const Color GREEN;
79     static const Color BLUE;
80     static const Color GRAY;
81     static const Color FOREGROUND;
82 
83     Color BlendColor(const Color& overlayColor) const;
84 
85     Color BlendColorWithAlpha(const Color& overlayColor) const;
86     Color BlendOpacity(double opacityRatio) const;
87     Color ChangeOpacity(double opacity) const;
88     Color ChangeAlpha(uint8_t alpha) const;
89 
SetValue(uint32_t value)90     void SetValue(uint32_t value)
91     {
92         colorValue_.value = value;
93     }
94 
GetValue()95     uint32_t GetValue() const
96     {
97         return colorValue_.value;
98     }
99 
SetResourceId(uint32_t id)100     void SetResourceId(uint32_t id)
101     {
102         resourceId_ = id;
103     }
104 
GetResourceId()105     uint32_t GetResourceId() const
106     {
107         return resourceId_;
108     }
109 
GetAlpha()110     uint8_t GetAlpha() const
111     {
112         return colorValue_.argb.alpha;
113     }
114 
GetRed()115     uint8_t GetRed() const
116     {
117         return colorValue_.argb.red;
118     }
119 
GetGreen()120     uint8_t GetGreen() const
121     {
122         return colorValue_.argb.green;
123     }
124 
GetBlue()125     uint8_t GetBlue() const
126     {
127         return colorValue_.argb.blue;
128     }
129 
130     void UpdateColorByResourceId();
131 
132     bool operator==(const Color& color) const
133     {
134         return colorValue_.value == color.GetValue();
135     }
136 
137     bool operator!=(const Color& color) const
138     {
139         return !operator==(color);
140     }
141 
142     Color operator+(const Color& color) const;
143 
144     Color operator-(const Color& color) const;
145 
146     Color operator*(double value) const;
147 
148     Color operator/(double value) const;
149 
150     std::string ColorToString() const;
151 
152     static Color ColorFromString(const std::string& str);
153 
154     std::string ToString() const;
155 
156 private:
Color(ColorParam colorValue)157     constexpr explicit Color(ColorParam colorValue) : colorValue_(colorValue) {}
158 
159     static double ConvertGammaToLinear(uint8_t value);
160     static void ConvertGammaToLinear(
161         const Color& gammaColor, double& linearRed, double& linearGreen, double& linearBlue);
162     static uint8_t ConvertLinearToGamma(double value);
163     static Color ConvertLinearToGamma(double alpha, double linearRed, double linearGreen, double linearBlue);
164     static bool MatchColorWithMagic(std::string& colorStr, uint32_t maskAlpha, Color& color);
165     static bool MatchColorWithMagicMini(std::string& colorStr, uint32_t maskAlpha, Color& color);
166     static bool MatchColorWithRGB(const std::string& colorStr, Color& color);
167     static bool MatchColorWithRGBA(const std::string& colorStr, Color& color);
168     static bool MatchColorSpecialString(const std::string& colorStr, Color& color);
169     static bool ParseUintColorString(const std::string& colorStr, Color& color);
170     static bool ParseUintColorString(const std::string& colorStr, Color& color, const Color& defaultColor);
171     static bool IsRGBValid(int value);
172     static bool IsOpacityValid(double value);
173     static bool FastCheckColorType(const std::string& colorStr, const std::string& expectPrefix,
174         const std::vector<size_t>& expectLengths);
175     static bool IsHexNumber(std::string& colorStr);
176 
177     float CalculateBlend(float alphaLeft, float alphaRight, float valueLeft, float valueRight) const;
178     ColorParam colorValue_ { .value = 0xff000000 };
179     uint32_t resourceId_ = 0;
180 };
181 
182 namespace StringUtils {
183 
StringSplitter(const std::string & source,char delimiter,std::vector<Color> & out)184 inline void StringSplitter(const std::string& source, char delimiter, std::vector<Color>& out)
185 {
186     using Func = Color (*)(const std::string&);
187     Func func = [](const std::string& value) { return Color::FromString(value); };
188     StringSplitter(source, delimiter, func, out);
189 }
190 
191 } // namespace StringUtils
192 
193 class ACE_FORCE_EXPORT LinearColor {
194 public:
195     LinearColor() = default;
LinearColor(uint32_t argb)196     explicit LinearColor(uint32_t argb)
197     {
198         alpha_ = static_cast<int16_t>((argb & 0xFF000000) >> 24);
199         red_ = static_cast<int16_t>((argb & 0x00FF0000) >> 16);
200         green_ = static_cast<int16_t>((argb & 0x0000FF00) >> 8);
201         blue_ = static_cast<int16_t>(argb & 0xFF);
202     }
LinearColor(const Color & color)203     explicit LinearColor(const Color& color)
204         : alpha_(color.GetAlpha()), red_(color.GetRed()), green_(color.GetGreen()), blue_(color.GetBlue())
205     {}
LinearColor(int16_t alpha,int16_t red,int16_t green,int16_t blue)206     LinearColor(int16_t alpha, int16_t red, int16_t green, int16_t blue)
207         : alpha_(alpha), red_(red), green_(green), blue_(blue)
208     {}
209     ~LinearColor() = default;
210 
211     static const LinearColor TRANSPARENT;
212     static const LinearColor WHITE;
213     static const LinearColor BLACK;
214     static const LinearColor RED;
215     static const LinearColor GREEN;
216     static const LinearColor BLUE;
217     static const LinearColor GRAY;
218 
219     LinearColor operator+(const LinearColor& color) const
220     {
221         return LinearColor(GetAlpha() + color.GetAlpha(), GetRed() + color.GetRed(),
222             GetGreen() + color.GetGreen(), GetBlue() + color.GetBlue());
223     }
224 
225     LinearColor operator-(const LinearColor& color) const
226     {
227         return LinearColor(GetAlpha() - color.GetAlpha(), GetRed() - color.GetRed(),
228             GetGreen() - color.GetGreen(), GetBlue() - color.GetBlue());
229     }
230 
231     LinearColor operator*(double value) const
232     {
233         return LinearColor(static_cast<int16_t>(round(GetAlpha() * value)),
234             static_cast<int16_t>(round(GetRed() * value)), static_cast<int16_t>(round(GetGreen() * value)),
235             static_cast<int16_t>(round(GetBlue() * value)));
236     }
237 
238     bool operator==(const LinearColor& color) const
239     {
240         return alpha_ == color.GetAlpha() && red_ == color.GetRed() && green_ == color.GetGreen() &&
241                blue_ == color.GetBlue();
242     }
243 
GetRed()244     int16_t GetRed() const
245     {
246         return red_;
247     }
248 
GetGreen()249     int16_t GetGreen() const
250     {
251         return green_;
252     }
253 
GetBlue()254     int16_t GetBlue() const
255     {
256         return blue_;
257     }
258 
GetAlpha()259     int16_t GetAlpha() const
260     {
261         return alpha_;
262     }
263 
GetValue()264     uint32_t GetValue() const
265     {
266         return (static_cast<uint32_t>(std::clamp<int16_t>(blue_, 0, UINT8_MAX))) |
267                (static_cast<uint32_t>((std::clamp<int16_t>(green_, 0, UINT8_MAX)) << 8)) |
268                (static_cast<uint32_t>((std::clamp<int16_t>(red_, 0, UINT8_MAX)) << 16)) |
269                (static_cast<uint32_t>((std::clamp<int16_t>(alpha_, 0, UINT8_MAX)) << 24));
270     }
271 
BlendOpacity(double opacityRatio)272     Color BlendOpacity(double opacityRatio) const
273     {
274         auto alpha = static_cast<int16_t>(GetAlpha() * opacityRatio);
275         return Color::FromARGB(
276             static_cast<uint8_t>(std::clamp<int16_t>(alpha, 0, UINT8_MAX)),
277             static_cast<uint8_t>(std::clamp<int16_t>(red_, 0, UINT8_MAX)),
278             static_cast<uint8_t>(std::clamp<int16_t>(green_, 0, UINT8_MAX)),
279             static_cast<uint8_t>(std::clamp<int16_t>(blue_, 0, UINT8_MAX)));
280     }
281 
ToColor()282     Color ToColor() const
283     {
284         return Color::FromARGB(
285             static_cast<uint8_t>(std::clamp<int16_t>(alpha_, 0, UINT8_MAX)),
286             static_cast<uint8_t>(std::clamp<int16_t>(red_, 0, UINT8_MAX)),
287             static_cast<uint8_t>(std::clamp<int16_t>(green_, 0, UINT8_MAX)),
288             static_cast<uint8_t>(std::clamp<int16_t>(blue_, 0, UINT8_MAX)));
289     }
290 
291 private:
292     int16_t alpha_;
293     int16_t red_;
294     int16_t green_;
295     int16_t blue_;
296 };
297 
298 } // namespace OHOS::Ace
299 
300 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_COLOR_H
301