1 /*
2  * Copyright (c) 2020-2022 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 GRAPHIC_LITE_COLOR_FILL_H
17 #define GRAPHIC_LITE_COLOR_FILL_H
18 namespace OHOS {
19 /* cover mode, src alpha is 255 */
20 #define COLOR_FILL_COVER(d, dm, r2, g2, b2, sm)               \
21     if ((dm) == ARGB8888 || (dm) == XRGB8888) {               \
22         reinterpret_cast<Color32*>(d)->alpha = OPA_OPAQUE;    \
23         if ((sm) == RGB565) {                                   \
24             reinterpret_cast<Color32*>(d)->red = (r2) << 3;   \
25             reinterpret_cast<Color32*>(d)->green = (g2) << 2; \
26             reinterpret_cast<Color32*>(d)->blue = (b2) << 3;  \
27         } else {                                              \
28             reinterpret_cast<Color32*>(d)->red = (r2);        \
29             reinterpret_cast<Color32*>(d)->green = (g2);      \
30             reinterpret_cast<Color32*>(d)->blue = (b2);       \
31         }                                                     \
32     } else if ((dm) == RGB888) {                              \
33         if ((sm) == RGB565) {                                   \
34             reinterpret_cast<Color24*>(d)->red = (r2) << 3;   \
35             reinterpret_cast<Color24*>(d)->green = (g2) << 2; \
36             reinterpret_cast<Color24*>(d)->blue = (b2) << 3;  \
37         } else {                                              \
38             reinterpret_cast<Color24*>(d)->red = (r2);        \
39             reinterpret_cast<Color24*>(d)->green = (g2);      \
40             reinterpret_cast<Color24*>(d)->blue = (b2);       \
41         }                                                     \
42     } else if ((dm) == RGB565) {                              \
43         if ((sm) == ARGB8888 || (sm) == RGB888 || (sm) == XRGB8888) {  \
44             reinterpret_cast<Color16*>(d)->red = (r2) >> 3;   \
45             reinterpret_cast<Color16*>(d)->green = (g2) >> 2; \
46             reinterpret_cast<Color16*>(d)->blue = (b2) >> 3;  \
47         } else {                                              \
48             reinterpret_cast<Color16*>(d)->red = (r2);        \
49             reinterpret_cast<Color16*>(d)->green = (g2);      \
50             reinterpret_cast<Color16*>(d)->blue = (b2);       \
51         }                                                     \
52     } else {                                                  \
53         ASSERT(0);                                            \
54     }
55 
56 #if defined(ENABLE_FIXED_POINT) && ENABLE_FIXED_POINT
57 #define COLOR_BLEND_RGBA(r1, g1, b1, a1, r2, g2, b2, a2)                                                      \
58     const uint16_t Alpha3 = 65025 - (OPA_OPAQUE - (a1)) * (OPA_OPAQUE - (a2));                                \
59     if ( Alpha3 != 0 )                                                                                             \
60     {                                                                                                         \
61         (r1) = static_cast<uint8_t>(((a2) * (r2) * OPA_OPAQUE + (OPA_OPAQUE - (a2)) * (a1) * (r1)) / Alpha3); \
62         (g1) = static_cast<uint8_t>(((a2) * (g2) * OPA_OPAQUE + (OPA_OPAQUE - (a2)) * (a1) * (g1)) / Alpha3); \
63         (b1) = static_cast<uint8_t>(((a2) * (b2) * OPA_OPAQUE + (OPA_OPAQUE - (a2)) * (a1) * (b1)) / Alpha3); \
64         (a1) = static_cast<uint8_t>(Alpha3 / OPA_OPAQUE);                                                     \
65     }
66 #else
67 #define COLOR_BLEND_RGBA(r1, g1, b1, a1, r2, g2, b2, a2)                                  \
68     const float Alpha1 = static_cast<float>(a1) / OPA_OPAQUE;                             \
69     const float Alpha2 = static_cast<float>(a2) / OPA_OPAQUE;                             \
70     const float Alpha3 = 1 - (1 - Alpha1) * (1 - Alpha2);                                 \
71     (r1) = static_cast<uint8_t>((Alpha2 * (r2) + (1 - Alpha2) * Alpha1 * (r1)) / Alpha3); \
72     (g1) = static_cast<uint8_t>((Alpha2 * (g2) + (1 - Alpha2) * Alpha1 * (g1)) / Alpha3); \
73     (b1) = static_cast<uint8_t>((Alpha2 * (b2) + (1 - Alpha2) * Alpha1 * (b1)) / Alpha3); \
74     (a1) = static_cast<uint8_t>(Alpha3 * OPA_OPAQUE)
75 #endif
76 
77 #define COLOR_BLEND_XRGB(r1, g1, b1, a1, r2, g2, b2, a2)                               \
78     (r1) = (((r2) * (a2)) / OPA_OPAQUE) + (((r1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE); \
79     (g1) = (((g2) * (a2)) / OPA_OPAQUE) + (((g1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE); \
80     (b1) = (((b2) * (a2)) / OPA_OPAQUE) + (((b1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE); \
81     (a1) = static_cast<uint8_t>(OPA_OPAQUE)
82 
83 #define COLOR_BLEND_RGB(r1, g1, b1, r2, g2, b2, a2)                                    \
84     (r1) = (((r2) * (a2)) / OPA_OPAQUE) + (((r1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE); \
85     (g1) = (((g2) * (a2)) / OPA_OPAQUE) + (((g1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE); \
86     (b1) = (((b2) * (a2)) / OPA_OPAQUE) + (((b1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE)
87 
88 // 565
89 #define COLOR_FILL_BLEND(d, dm, s, sm, a)                                                                           \
90     if ((dm) == ARGB8888) {                                                                                         \
91         Color32* p = reinterpret_cast<Color32*>(d);                                                                 \
92         if ((sm) == ARGB8888 || (sm) == XRGB8888) {                                                                 \
93             Color32* sTmp = reinterpret_cast<Color32*>(s);                                                          \
94             uint8_t alpha = (sTmp->alpha * (a)) / OPA_OPAQUE;                                                       \
95             COLOR_BLEND_RGBA(p->red, p->green, p->blue, p->alpha, sTmp->red, sTmp->green, sTmp->blue, alpha);       \
96         } else if ((sm) == RGB888) {                                                                                \
97             Color24* sTmp = reinterpret_cast<Color24*>(s);                                                          \
98             COLOR_BLEND_RGBA(p->red, p->green, p->blue, p->alpha, sTmp->red, sTmp->green, sTmp->blue, a);           \
99         } else if ((sm) == RGB565) {                                                                                \
100             Color16* sTmp = reinterpret_cast<Color16*>(s);                                                          \
101             COLOR_BLEND_RGBA(p->red, p->green, p->blue, p->alpha, (sTmp->red) << 3, (sTmp->green) << 2,             \
102                              (sTmp->blue) << 3, a);                                                                 \
103         }                                                                                                           \
104     } else if ((dm) == XRGB8888) {                                                                                  \
105         Color32* p = reinterpret_cast<Color32*>(d);                                                                 \
106         if ((sm) == ARGB8888 || (sm) == XRGB8888) {                                                                 \
107             Color32* sTmp = reinterpret_cast<Color32*>(s);                                                          \
108             uint8_t alpha = (sTmp->alpha * (a)) / OPA_OPAQUE;                                                       \
109             COLOR_BLEND_XRGB(p->red, p->green, p->blue, p->alpha, sTmp->red, sTmp->green, sTmp->blue, alpha);       \
110         } else if ((sm) == RGB888) {                                                                                \
111             Color24* sTmp = reinterpret_cast<Color24*>(s);                                                          \
112             COLOR_BLEND_XRGB(p->red, p->green, p->blue, p->alpha, sTmp->red, sTmp->green, sTmp->blue, a);           \
113         } else if ((sm) == RGB565) {                                                                                \
114             Color16* sTmp = reinterpret_cast<Color16*>(s);                                                          \
115             COLOR_BLEND_XRGB(p->red, p->green, p->blue, p->alpha, (sTmp->red) << 3, (sTmp->green) << 2,             \
116                              (sTmp->blue) << 3, a);                                                                 \
117         }                                                                                                           \
118     } else if ((dm) == RGB888) {                                                                                    \
119         Color24* p = reinterpret_cast<Color24*>(d);                                                                 \
120         if ((sm) == ARGB8888 || (sm) == XRGB8888) {                                                                 \
121             Color32* sTmp = reinterpret_cast<Color32*>(s);                                                          \
122             uint8_t alpha = (sTmp->alpha * (a)) / OPA_OPAQUE;                                                       \
123             COLOR_BLEND_RGB(p->red, p->green, p->blue, sTmp->red, sTmp->green, sTmp->blue, alpha);                  \
124         } else if ((sm) == RGB888) {                                                                                \
125             Color24* sTmp = reinterpret_cast<Color24*>(s);                                                          \
126             COLOR_BLEND_RGB(p->red, p->green, p->blue, sTmp->red, sTmp->green, sTmp->blue, a);                      \
127         } else if ((sm) == RGB565) {                                                                                \
128             Color16* sTmp = reinterpret_cast<Color16*>(s);                                                          \
129             COLOR_BLEND_RGB(p->red, p->green, p->blue, (sTmp->red) << 3, (sTmp->green) << 2, (sTmp->blue) << 3, a); \
130         }                                                                                                           \
131     } else if ((dm) == RGB565) {                                                                                    \
132         Color16* p = reinterpret_cast<Color16*>(d);                                                                 \
133         if ((sm) == ARGB8888 || (sm) == XRGB8888) {                                                                 \
134             Color32* sTmp = reinterpret_cast<Color32*>(s);                                                          \
135             uint8_t alpha = (sTmp->alpha * (a)) / OPA_OPAQUE;                                                       \
136             COLOR_BLEND_RGB(p->red, p->green, p->blue, (sTmp->red) >> 3, (sTmp->green) >> 2, (sTmp->blue) >> 3,     \
137                             alpha);                                                                                 \
138         } else if ((sm) == RGB888) {                                                                                \
139             Color24* sTmp = reinterpret_cast<Color24*>(s);                                                          \
140             COLOR_BLEND_RGB(p->red, p->green, p->blue, (sTmp->red) >> 3, (sTmp->green) >> 2, (sTmp->blue) >> 3, a); \
141         } else if ((sm) == RGB565) {                                                                                \
142             Color16* sTmp = reinterpret_cast<Color16*>(s);                                                          \
143             COLOR_BLEND_RGB(p->red, p->green, p->blue, sTmp->red, sTmp->green, sTmp->blue, a);                      \
144         }                                                                                                           \
145     } else {                                                                                                        \
146         ASSERT(0);                                                                                                  \
147     }
148 }
149 #endif