1 /*
2  * Copyright (c) 2023 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 #include "sec_comp_tool.h"
16 
17 #include <cmath>
18 #include <cstdint>
19 #include "sec_comp_log.h"
20 
21 namespace OHOS {
22 namespace Security {
23 namespace SecurityComponent {
24 namespace {
25 static constexpr double PI_CIRCLE = 3.1415926;
26 static constexpr double MIN_HSV_DISTANCE = 25.0;
27 static constexpr double MAX_RGB_VALUE = 255.0;
28 static constexpr uint8_t MAX_TRANSPARENT = 0x99; // 60%
29 static constexpr double ZERO_DOUBLE = 0.0;
30 static constexpr double THIRTY_ANGLE = 30.0;
31 static constexpr double SIXTY_ANGLE = 60.0;
32 static constexpr double ONE_HUNDRED_TWEENTY_ANGLE = 120.0;
33 static constexpr double ONE_HUNDRED_EIGHTY_ANGLE = 180.0;
34 static constexpr double TWO_HUNDREDS_FORTY_ANGLE = 240.0;
35 static constexpr double THREE_HUNDREDS_SIXTY_ANGLE = 360.0;
36 static constexpr double DEFAULT_R = 100.0;
37 static const uint8_t MAX_ALPHA = 0xFF;
38 static const double MIN_CONTRACST_ALPHA = 0.5;
39 
40 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_SECURITY_COMPONENT, "SecCompTool"};
41 }
42 
MaxValue(double a,double b,double c)43 static inline double MaxValue(double a, double b, double c)
44 {
45     return ((a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c));
46 }
47 
MinValue(double a,double b,double c)48 static inline double MinValue(double a, double b, double c)
49 {
50     return ((a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c));
51 }
52 
53 struct HsvColor {
54     double h;
55     double s;
56     double v;
57 };
58 
RgbToHsv(uint8_t r,uint8_t g,uint8_t b)59 static HsvColor RgbToHsv(uint8_t r, uint8_t g, uint8_t b)
60 {
61     HsvColor hsv;
62     double red = static_cast<double>(r) / MAX_RGB_VALUE;
63     double green = static_cast<double>(g) / MAX_RGB_VALUE;
64     double blue = static_cast<double>(b) / MAX_RGB_VALUE;
65     double max = MaxValue(red, green, blue);
66     double min = MinValue(red, green, blue);
67     double delta = max - min;
68     if (max == min) {
69         hsv.h = ZERO_DOUBLE;
70     } else if (max == red) {
71         hsv.h = fmod((SIXTY_ANGLE * ((green - blue) / delta) + THREE_HUNDREDS_SIXTY_ANGLE),
72             THREE_HUNDREDS_SIXTY_ANGLE);
73     } else if (max == green) {
74         hsv.h = fmod((SIXTY_ANGLE * ((blue - red) / delta) + ONE_HUNDRED_TWEENTY_ANGLE), THREE_HUNDREDS_SIXTY_ANGLE);
75     } else if (max == blue) {
76         hsv.h = fmod((SIXTY_ANGLE * ((red - green) / delta) + TWO_HUNDREDS_FORTY_ANGLE), THREE_HUNDREDS_SIXTY_ANGLE);
77     }
78 
79     if (max == 0) {
80         hsv.s = ZERO_DOUBLE;
81     } else {
82         hsv.s = delta / max;
83     }
84 
85     hsv.v = max;
86     return hsv;
87 }
88 
GetHsvDisX(const HsvColor & hsv,double r)89 static inline double GetHsvDisX(const HsvColor& hsv, double r)
90 {
91     return r * hsv.v * hsv.s * cos(hsv.h / ONE_HUNDRED_EIGHTY_ANGLE * PI_CIRCLE);
92 }
93 
GetHsvDisY(const HsvColor & hsv,double r)94 static inline double GetHsvDisY(const HsvColor& hsv, double r)
95 {
96     return r * hsv.v * hsv.s * sin(hsv.h / ONE_HUNDRED_EIGHTY_ANGLE * PI_CIRCLE);
97 }
98 
GetHsvDisZ(const HsvColor & hsv,double h)99 static inline double GetHsvDisZ(const HsvColor& hsv, double h)
100 {
101     return h * (1 - hsv.v);
102 }
103 
HsvDistance(const HsvColor & hsv1,const HsvColor & hsv2)104 static double HsvDistance(const HsvColor& hsv1, const HsvColor& hsv2)
105 {
106     double rDef = DEFAULT_R;
107     double angle = THIRTY_ANGLE;
108     double h = rDef * cos(angle / ONE_HUNDRED_EIGHTY_ANGLE * PI_CIRCLE);
109     double r = rDef * sin(angle / ONE_HUNDRED_EIGHTY_ANGLE * PI_CIRCLE);
110 
111     double x1 = GetHsvDisX(hsv1, r);
112     double y1 = GetHsvDisY(hsv1, r);
113     double z1 = GetHsvDisZ(hsv1, h);
114 
115     double x2 = GetHsvDisX(hsv2, r);
116     double y2 = GetHsvDisY(hsv2, r);
117     double z2 = GetHsvDisZ(hsv2, h);
118 
119     double dx = x1 - x2;
120     double dy = y1 - y2;
121     double dz = z1 - z2;
122 
123     return sqrt((dx * dx) + (dy * dy) + (dz * dz));
124 }
125 
IsColorAplhaSimilar(const SecCompColor & fgColor,const SecCompColor & bgColor)126 static bool IsColorAplhaSimilar(const SecCompColor& fgColor, const SecCompColor& bgColor)
127 {
128     double fgAlpha = static_cast<double>(fgColor.argb.alpha) / MAX_ALPHA;
129     double bgAlpha = static_cast<double>(bgColor.argb.alpha) / MAX_ALPHA;
130 
131     double mixAlpha = fgAlpha + bgAlpha - fgAlpha * bgAlpha;
132     if (GreatNotEqual(bgAlpha / mixAlpha, MIN_CONTRACST_ALPHA)) {
133         SC_LOG_ERROR(LABEL, "FgAlpha=%{public}x BgAlpha=%{public}x is similar, check failed",
134             fgColor.argb.alpha, bgColor.argb.alpha);
135         return true;
136     }
137     return false;
138 }
139 
IsColorSimilar(const SecCompColor & color1,const SecCompColor & color2)140 bool IsColorSimilar(const SecCompColor& color1, const SecCompColor& color2)
141 {
142     HsvColor hsv1 = RgbToHsv(color1.argb.red, color1.argb.green, color1.argb.blue);
143     HsvColor hsv2 = RgbToHsv(color2.argb.red, color2.argb.green, color2.argb.blue);
144 
145     double distance = HsvDistance(hsv1, hsv2);
146     SC_LOG_DEBUG(LABEL, "Compare color %{public}x %{public}x distance %{public}f",
147         color1.value, color2.value, distance);
148     return (distance < MIN_HSV_DISTANCE) && IsColorAplhaSimilar(color1, color2);
149 }
150 
IsColorTransparent(const SecCompColor & color)151 bool IsColorTransparent(const SecCompColor& color)
152 {
153     SC_LOG_DEBUG(LABEL, "Color %{public}x alpha %{public}x", color.value, color.argb.alpha);
154     return color.argb.alpha < MAX_TRANSPARENT;
155 }
156 
IsColorFullTransparent(const SecCompColor & color)157 bool IsColorFullTransparent(const SecCompColor& color)
158 {
159     return color.argb.alpha == 0;
160 }
161 }  // namespace SecurityComponent
162 }  // namespace Security
163 }  // namespace OHOS
164