1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "draw/draw_utils.h"
17a3e0fd82Sopenharmony_ci
18a3e0fd82Sopenharmony_ci#include "color_fill.h"
19a3e0fd82Sopenharmony_ci#include "draw/draw_triangle.h"
20a3e0fd82Sopenharmony_ci#include "engines/gfx/gfx_engine_manager.h"
21a3e0fd82Sopenharmony_ci#include "font/ui_font.h"
22a3e0fd82Sopenharmony_ci#include "gfx_utils/color.h"
23a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h"
24a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_math.h"
25a3e0fd82Sopenharmony_ci#include "graphic_performance.h"
26a3e0fd82Sopenharmony_ci#include "securec.h"
27a3e0fd82Sopenharmony_ci#include "common/typed_text.h"
28a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
29a3e0fd82Sopenharmony_ci#include "graphic_neon_pipeline.h"
30a3e0fd82Sopenharmony_ci#include "graphic_neon_utils.h"
31a3e0fd82Sopenharmony_ci#endif
32a3e0fd82Sopenharmony_ci
33a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
34a3e0fd82Sopenharmony_ci#include "arm_math.h"
35a3e0fd82Sopenharmony_ci#endif
36a3e0fd82Sopenharmony_ci
37a3e0fd82Sopenharmony_cinamespace OHOS {
38a3e0fd82Sopenharmony_ci// Preprocess operation for draw
39a3e0fd82Sopenharmony_ci#define DRAW_UTILS_PREPROCESS(gfxBufferInfo, opa)                         \
40a3e0fd82Sopenharmony_ci    if ((opa) == OPA_TRANSPARENT) {                                       \
41a3e0fd82Sopenharmony_ci        return;                                                           \
42a3e0fd82Sopenharmony_ci    }                                                                     \
43a3e0fd82Sopenharmony_ci    uint8_t* screenBuffer = static_cast<uint8_t*>(gfxBufferInfo.virAddr); \
44a3e0fd82Sopenharmony_ci    if (screenBuffer == nullptr) {                                        \
45a3e0fd82Sopenharmony_ci        return;                                                           \
46a3e0fd82Sopenharmony_ci    }                                                                     \
47a3e0fd82Sopenharmony_ci    ColorMode bufferMode = gfxBufferInfo.mode;                            \
48a3e0fd82Sopenharmony_ci    uint8_t bufferPxSize = GetByteSizeByColorMode(bufferMode);            \
49a3e0fd82Sopenharmony_ci    uint16_t screenBufferWidth = gfxBufferInfo.width;
50a3e0fd82Sopenharmony_ci
51a3e0fd82Sopenharmony_cinamespace {
52a3e0fd82Sopenharmony_cistatic constexpr uint8_t OPACITY_STEP_A1 = 255;
53a3e0fd82Sopenharmony_cistatic constexpr uint8_t OPACITY_STEP_A2 = 85;
54a3e0fd82Sopenharmony_cistatic constexpr uint8_t OPACITY_STEP_A4 = 17;
55a3e0fd82Sopenharmony_ci} // namespace
56a3e0fd82Sopenharmony_ci
57a3e0fd82Sopenharmony_ciTriangleEdge::TriangleEdge(int16_t x1, int16_t y1, int16_t x2, int16_t y2)
58a3e0fd82Sopenharmony_ci{
59a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
60a3e0fd82Sopenharmony_ci    curX = FO_TRANS_INTEGER_TO_FIXED(x1);
61a3e0fd82Sopenharmony_ci    curY = FO_TRANS_INTEGER_TO_FIXED(y1);
62a3e0fd82Sopenharmony_ci    du = FO_TRANS_INTEGER_TO_FIXED(x2 - x1);
63a3e0fd82Sopenharmony_ci    dv = FO_TRANS_INTEGER_TO_FIXED(y2 - y1);
64a3e0fd82Sopenharmony_ci#else
65a3e0fd82Sopenharmony_ci    curX = static_cast<float>(x1);
66a3e0fd82Sopenharmony_ci    curY = static_cast<float>(y1);
67a3e0fd82Sopenharmony_ci    du = static_cast<float>(x2 - x1);
68a3e0fd82Sopenharmony_ci    dv = static_cast<float>(y2 - y1);
69a3e0fd82Sopenharmony_ci#endif
70a3e0fd82Sopenharmony_ci}
71a3e0fd82Sopenharmony_ci
72a3e0fd82Sopenharmony_ciTriangleEdge::~TriangleEdge() {}
73a3e0fd82Sopenharmony_ci
74a3e0fd82Sopenharmony_ciDrawUtils* DrawUtils::GetInstance()
75a3e0fd82Sopenharmony_ci{
76a3e0fd82Sopenharmony_ci    static DrawUtils instance;
77a3e0fd82Sopenharmony_ci    return &instance;
78a3e0fd82Sopenharmony_ci}
79a3e0fd82Sopenharmony_ci
80a3e0fd82Sopenharmony_civoid DrawUtils::DrawColorAreaBySides(BufferInfo& gfxDstBuffer,
81a3e0fd82Sopenharmony_ci                                     const Rect& mask,
82a3e0fd82Sopenharmony_ci                                     const ColorType& color,
83a3e0fd82Sopenharmony_ci                                     OpacityType opa,
84a3e0fd82Sopenharmony_ci                                     const EdgeSides& sides) const
85a3e0fd82Sopenharmony_ci{
86a3e0fd82Sopenharmony_ci    Rect area(sides.left, sides.top, sides.right, sides.bottom);
87a3e0fd82Sopenharmony_ci    DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, area, mask, color, opa);
88a3e0fd82Sopenharmony_ci}
89a3e0fd82Sopenharmony_ci
90a3e0fd82Sopenharmony_civoid DrawUtils::DrawColorArea(BufferInfo& gfxDstBuffer,
91a3e0fd82Sopenharmony_ci                              const Rect& area,
92a3e0fd82Sopenharmony_ci                              const Rect& mask,
93a3e0fd82Sopenharmony_ci                              const ColorType& color,
94a3e0fd82Sopenharmony_ci                              OpacityType opa) const
95a3e0fd82Sopenharmony_ci{
96a3e0fd82Sopenharmony_ci    if (opa == OPA_TRANSPARENT) {
97a3e0fd82Sopenharmony_ci        return;
98a3e0fd82Sopenharmony_ci    }
99a3e0fd82Sopenharmony_ci
100a3e0fd82Sopenharmony_ci    Rect maskedArea;
101a3e0fd82Sopenharmony_ci    if (!maskedArea.Intersect(area, mask)) {
102a3e0fd82Sopenharmony_ci        return;
103a3e0fd82Sopenharmony_ci    }
104a3e0fd82Sopenharmony_ci
105a3e0fd82Sopenharmony_ci    BaseGfxEngine::GetInstance()->Fill(gfxDstBuffer, maskedArea, color, opa);
106a3e0fd82Sopenharmony_ci}
107a3e0fd82Sopenharmony_ci
108a3e0fd82Sopenharmony_ciuint8_t DrawUtils::GetPxSizeByColorMode(uint8_t colorMode)
109a3e0fd82Sopenharmony_ci{
110a3e0fd82Sopenharmony_ci    switch (colorMode) {
111a3e0fd82Sopenharmony_ci        case TSC6:
112a3e0fd82Sopenharmony_ci        case TSC6A:
113a3e0fd82Sopenharmony_ci        case ARGB8888:
114a3e0fd82Sopenharmony_ci        case XRGB8888:
115a3e0fd82Sopenharmony_ci            return 32; // 32: 32 bit
116a3e0fd82Sopenharmony_ci        case RGB888:
117a3e0fd82Sopenharmony_ci            return 24; // 24: 24 bit
118a3e0fd82Sopenharmony_ci        case RGB565:
119a3e0fd82Sopenharmony_ci        case ARGB1555:
120a3e0fd82Sopenharmony_ci        case ARGB4444:
121a3e0fd82Sopenharmony_ci            return 16; // 16: 16 bit
122a3e0fd82Sopenharmony_ci        case L1:
123a3e0fd82Sopenharmony_ci        case A1:
124a3e0fd82Sopenharmony_ci            return 1; // 1: 1 bit
125a3e0fd82Sopenharmony_ci        case L2:
126a3e0fd82Sopenharmony_ci        case A2:
127a3e0fd82Sopenharmony_ci            return 2; // 2: 2 bit
128a3e0fd82Sopenharmony_ci        case L4:
129a3e0fd82Sopenharmony_ci        case A4:
130a3e0fd82Sopenharmony_ci            return 4; // 4: 4 bit
131a3e0fd82Sopenharmony_ci        case L8:
132a3e0fd82Sopenharmony_ci        case A8:
133a3e0fd82Sopenharmony_ci            return 8; // 8: 8 bit
134a3e0fd82Sopenharmony_ci        default:
135a3e0fd82Sopenharmony_ci            return 0;
136a3e0fd82Sopenharmony_ci    }
137a3e0fd82Sopenharmony_ci}
138a3e0fd82Sopenharmony_ci
139a3e0fd82Sopenharmony_ciuint8_t DrawUtils::GetByteSizeByColorMode(uint8_t colorMode)
140a3e0fd82Sopenharmony_ci{
141a3e0fd82Sopenharmony_ci    switch (colorMode) {
142a3e0fd82Sopenharmony_ci        case ARGB8888:
143a3e0fd82Sopenharmony_ci        case XRGB8888:
144a3e0fd82Sopenharmony_ci            return 4; // 4: 4 Byte
145a3e0fd82Sopenharmony_ci        case RGB888:
146a3e0fd82Sopenharmony_ci            return 3; // 3: 3 Byte
147a3e0fd82Sopenharmony_ci        case RGB565:
148a3e0fd82Sopenharmony_ci        case ARGB1555:
149a3e0fd82Sopenharmony_ci        case ARGB4444:
150a3e0fd82Sopenharmony_ci            return 2; // 2: 2 Byte
151a3e0fd82Sopenharmony_ci        default:
152a3e0fd82Sopenharmony_ci            return 0;
153a3e0fd82Sopenharmony_ci    }
154a3e0fd82Sopenharmony_ci}
155a3e0fd82Sopenharmony_ci
156a3e0fd82Sopenharmony_civoid DrawUtils::DrawPixel(BufferInfo& gfxDstBuffer,
157a3e0fd82Sopenharmony_ci                          int16_t x,
158a3e0fd82Sopenharmony_ci                          int16_t y,
159a3e0fd82Sopenharmony_ci                          const Rect& mask,
160a3e0fd82Sopenharmony_ci                          const ColorType& color,
161a3e0fd82Sopenharmony_ci                          OpacityType opa) const
162a3e0fd82Sopenharmony_ci{
163a3e0fd82Sopenharmony_ci    if ((x < mask.GetLeft()) || (x > mask.GetRight()) || (y < mask.GetTop()) || (y > mask.GetBottom())) {
164a3e0fd82Sopenharmony_ci        return;
165a3e0fd82Sopenharmony_ci    }
166a3e0fd82Sopenharmony_ci
167a3e0fd82Sopenharmony_ci    DRAW_UTILS_PREPROCESS(gfxDstBuffer, opa);
168a3e0fd82Sopenharmony_ci
169a3e0fd82Sopenharmony_ci    Color32 fillColor;
170a3e0fd82Sopenharmony_ci    fillColor.full = Color::ColorTo32(color);
171a3e0fd82Sopenharmony_ci
172a3e0fd82Sopenharmony_ci    screenBuffer += (y * screenBufferWidth + x) * bufferPxSize;
173a3e0fd82Sopenharmony_ci    COLOR_FILL_BLEND(screenBuffer, bufferMode, &fillColor, ARGB8888, opa);
174a3e0fd82Sopenharmony_ci}
175a3e0fd82Sopenharmony_ci
176a3e0fd82Sopenharmony_civoid DrawUtils::DrawColorLetter(BufferInfo& gfxDstBuffer,
177a3e0fd82Sopenharmony_ci                                const LabelLetterInfo& letterInfo,
178a3e0fd82Sopenharmony_ci                                uint8_t* fontMap,
179a3e0fd82Sopenharmony_ci                                GlyphNode node,
180a3e0fd82Sopenharmony_ci                                int16_t lineHeight) const
181a3e0fd82Sopenharmony_ci{
182a3e0fd82Sopenharmony_ci    if (fontMap == nullptr) {
183a3e0fd82Sopenharmony_ci        return;
184a3e0fd82Sopenharmony_ci    }
185a3e0fd82Sopenharmony_ci    UIFont* fontEngine = UIFont::GetInstance();
186a3e0fd82Sopenharmony_ci    uint16_t letterW = node.cols;
187a3e0fd82Sopenharmony_ci    uint16_t letterH = node.rows;
188a3e0fd82Sopenharmony_ci    int16_t posX;
189a3e0fd82Sopenharmony_ci    int16_t posY;
190a3e0fd82Sopenharmony_ci    if (letterInfo.baseLine) {
191a3e0fd82Sopenharmony_ci        // 2:Half the size between lineHeight and node.rows of emoji
192a3e0fd82Sopenharmony_ci        posY = letterInfo.pos.y + (lineHeight - letterH) / 2 + letterInfo.offsetY;
193a3e0fd82Sopenharmony_ci    } else {
194a3e0fd82Sopenharmony_ci        FontHeader head;
195a3e0fd82Sopenharmony_ci        if (fontEngine->GetFontHeader(head, letterInfo.fontId, letterInfo.fontSize) != 0) {
196a3e0fd82Sopenharmony_ci            return;
197a3e0fd82Sopenharmony_ci        }
198a3e0fd82Sopenharmony_ci        posY = letterInfo.pos.y + head.ascender - letterInfo.offsetY;
199a3e0fd82Sopenharmony_ci    }
200a3e0fd82Sopenharmony_ci    if (letterInfo.direct == TEXT_DIRECT_RTL) {
201a3e0fd82Sopenharmony_ci        /* RTL */
202a3e0fd82Sopenharmony_ci        posX = letterInfo.pos.x- node.advance + letterInfo.offsetX;
203a3e0fd82Sopenharmony_ci    } else {
204a3e0fd82Sopenharmony_ci        /* LTR */
205a3e0fd82Sopenharmony_ci        posX = letterInfo.pos.x;
206a3e0fd82Sopenharmony_ci    }
207a3e0fd82Sopenharmony_ci
208a3e0fd82Sopenharmony_ci    uint16_t rowStart = (posY >= letterInfo.mask.GetTop()) ? 0 : (letterInfo.mask.GetTop() - posY);
209a3e0fd82Sopenharmony_ci    uint16_t rowEnd =
210a3e0fd82Sopenharmony_ci        (posY + letterH <= letterInfo.mask.GetBottom()) ? letterH : (letterInfo.mask.GetBottom() - posY + 1);
211a3e0fd82Sopenharmony_ci    uint16_t colStart = (posX >= letterInfo.mask.GetLeft()) ? 0 : (letterInfo.mask.GetLeft() - posX);
212a3e0fd82Sopenharmony_ci    uint16_t colEnd =
213a3e0fd82Sopenharmony_ci        (posX + letterW <= letterInfo.mask.GetRight()) ? letterW : (letterInfo.mask.GetRight() - posX + 1);
214a3e0fd82Sopenharmony_ci
215a3e0fd82Sopenharmony_ci    Rect srcRect(posX, posY, posX + letterW - 1, posY + letterH - 1);
216a3e0fd82Sopenharmony_ci    Rect subRect(posX + colStart, posY + rowStart, colEnd - 1 + posX, rowEnd - 1 + posY);
217a3e0fd82Sopenharmony_ci
218a3e0fd82Sopenharmony_ci    uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(gfxDstBuffer.mode);
219a3e0fd82Sopenharmony_ci    DrawImage(gfxDstBuffer, srcRect, letterInfo.mask, fontMap, letterInfo.opa, pxSize, ARGB8888);
220a3e0fd82Sopenharmony_ci}
221a3e0fd82Sopenharmony_ci
222a3e0fd82Sopenharmony_civoid DrawUtils::DrawNormalLetter(BufferInfo& gfxDstBuffer,
223a3e0fd82Sopenharmony_ci                                 const LabelLetterInfo& letterInfo,
224a3e0fd82Sopenharmony_ci                                 uint8_t* fontMap,
225a3e0fd82Sopenharmony_ci                                 GlyphNode node,
226a3e0fd82Sopenharmony_ci                                 uint8_t maxLetterSize) const
227a3e0fd82Sopenharmony_ci{
228a3e0fd82Sopenharmony_ci    if (fontMap == nullptr) {
229a3e0fd82Sopenharmony_ci        return;
230a3e0fd82Sopenharmony_ci    }
231a3e0fd82Sopenharmony_ci
232a3e0fd82Sopenharmony_ci    UIFont* fontEngine = UIFont::GetInstance();
233a3e0fd82Sopenharmony_ci    uint16_t letterW = node.cols;
234a3e0fd82Sopenharmony_ci    uint16_t letterH = node.rows;
235a3e0fd82Sopenharmony_ci    int16_t posX;
236a3e0fd82Sopenharmony_ci    int16_t posY;
237a3e0fd82Sopenharmony_ci
238a3e0fd82Sopenharmony_ci    if (letterInfo.baseLine) {
239a3e0fd82Sopenharmony_ci        posY = letterInfo.pos.y + maxLetterSize - node.top + letterInfo.offsetY;
240a3e0fd82Sopenharmony_ci    } else {
241a3e0fd82Sopenharmony_ci        FontHeader head;
242a3e0fd82Sopenharmony_ci        if (fontEngine->GetFontHeader(head, letterInfo.fontId, letterInfo.fontSize) != 0) {
243a3e0fd82Sopenharmony_ci            return;
244a3e0fd82Sopenharmony_ci        }
245a3e0fd82Sopenharmony_ci        posY = letterInfo.pos.y + head.ascender - node.top - letterInfo.offsetY;
246a3e0fd82Sopenharmony_ci    }
247a3e0fd82Sopenharmony_ci    if (letterInfo.direct == TEXT_DIRECT_RTL) {
248a3e0fd82Sopenharmony_ci        /* RTL */
249a3e0fd82Sopenharmony_ci        posX = letterInfo.pos.x - node.advance + node.left + letterInfo.offsetX;
250a3e0fd82Sopenharmony_ci    } else {
251a3e0fd82Sopenharmony_ci        /* LTR */
252a3e0fd82Sopenharmony_ci        posX = letterInfo.pos.x + node.left + letterInfo.offsetX;
253a3e0fd82Sopenharmony_ci    }
254a3e0fd82Sopenharmony_ci    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
255a3e0fd82Sopenharmony_ci    if (letterInfo.haveLineBackgroundColor) {
256a3e0fd82Sopenharmony_ci        Rect lineBackgroundRect(posX - node.left, letterInfo.mask.GetTop(),
257a3e0fd82Sopenharmony_ci            posX + node.advance + letterInfo.letterSpace_ - node.left,
258a3e0fd82Sopenharmony_ci            letterInfo.mask.GetBottom() - letterInfo.lineSpace_);
259a3e0fd82Sopenharmony_ci        Style lineStyle;
260a3e0fd82Sopenharmony_ci        lineStyle.bgColor_ = letterInfo.lineBackgroundColor;
261a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawRect(gfxDstBuffer, lineBackgroundRect,
262a3e0fd82Sopenharmony_ci                                lineBackgroundRect, lineStyle, lineStyle.bgColor_.alpha);
263a3e0fd82Sopenharmony_ci    }
264a3e0fd82Sopenharmony_ci    if (letterInfo.havebackgroundColor) {
265a3e0fd82Sopenharmony_ci        Rect backgroundRect(posX, letterInfo.mask.GetTop(), posX + letterW + letterInfo.letterSpace_ - 1,
266a3e0fd82Sopenharmony_ci                            letterInfo.mask.GetBottom() - letterInfo.lineSpace_);
267a3e0fd82Sopenharmony_ci        Style style;
268a3e0fd82Sopenharmony_ci        style.bgColor_ = letterInfo.backgroundColor;
269a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawRect(gfxDstBuffer, backgroundRect,
270a3e0fd82Sopenharmony_ci                                backgroundRect, style, style.bgColor_.alpha);
271a3e0fd82Sopenharmony_ci    }
272a3e0fd82Sopenharmony_ci
273a3e0fd82Sopenharmony_ci    if ((posX + letterW < letterInfo.mask.GetLeft()) || (posX > letterInfo.mask.GetRight()) ||
274a3e0fd82Sopenharmony_ci        (posY + letterH < letterInfo.mask.GetTop()) || (posY > letterInfo.mask.GetBottom())) {
275a3e0fd82Sopenharmony_ci        return;
276a3e0fd82Sopenharmony_ci    }
277a3e0fd82Sopenharmony_ci
278a3e0fd82Sopenharmony_ci    uint16_t rowStart = (posY >= letterInfo.mask.GetTop()) ? 0 : (letterInfo.mask.GetTop() - posY);
279a3e0fd82Sopenharmony_ci    uint16_t rowEnd =
280a3e0fd82Sopenharmony_ci        (posY + letterH <= letterInfo.mask.GetBottom()) ? letterH : (letterInfo.mask.GetBottom() - posY + 1);
281a3e0fd82Sopenharmony_ci    uint16_t colStart = (posX >= letterInfo.mask.GetLeft()) ? 0 : (letterInfo.mask.GetLeft() - posX);
282a3e0fd82Sopenharmony_ci    uint16_t colEnd =
283a3e0fd82Sopenharmony_ci        (posX + letterW <= letterInfo.mask.GetRight()) ? letterW : (letterInfo.mask.GetRight() - posX + 1);
284a3e0fd82Sopenharmony_ci
285a3e0fd82Sopenharmony_ci    Rect srcRect(posX, posY, posX + letterW - 1, posY + letterH - 1);
286a3e0fd82Sopenharmony_ci    Rect subRect(posX + colStart, posY + rowStart, colEnd - 1 + posX, rowEnd - 1 + posY);
287a3e0fd82Sopenharmony_ci
288a3e0fd82Sopenharmony_ci    uint8_t fontWeight = fontEngine->GetFontWeight(letterInfo.fontId);
289a3e0fd82Sopenharmony_ci    baseGfxEngine->DrawLetter(gfxDstBuffer, fontMap, srcRect, subRect,
290a3e0fd82Sopenharmony_ci                              fontWeight, letterInfo.color, letterInfo.opa);
291a3e0fd82Sopenharmony_ci}
292a3e0fd82Sopenharmony_ci
293a3e0fd82Sopenharmony_civoid DrawUtils::DrawLetter(BufferInfo& gfxDstBuffer,
294a3e0fd82Sopenharmony_ci                           const uint8_t* fontMap,
295a3e0fd82Sopenharmony_ci                           const Rect& fontRect,
296a3e0fd82Sopenharmony_ci                           const Rect& subRect,
297a3e0fd82Sopenharmony_ci                           const uint8_t fontWeight,
298a3e0fd82Sopenharmony_ci                           const ColorType& color,
299a3e0fd82Sopenharmony_ci                           const OpacityType opa) const
300a3e0fd82Sopenharmony_ci{
301a3e0fd82Sopenharmony_ci    Color32 fillColor;
302a3e0fd82Sopenharmony_ci    fillColor.full = Color::ColorTo32(color);
303a3e0fd82Sopenharmony_ci    uint8_t opacityMask;
304a3e0fd82Sopenharmony_ci    uint8_t opacityStep = 1;
305a3e0fd82Sopenharmony_ci    switch (fontWeight) {
306a3e0fd82Sopenharmony_ci        case FONT_WEIGHT_1:
307a3e0fd82Sopenharmony_ci            opacityStep = OPACITY_STEP_A1;
308a3e0fd82Sopenharmony_ci            opacityMask = 0x01;
309a3e0fd82Sopenharmony_ci            break;
310a3e0fd82Sopenharmony_ci        case FONT_WEIGHT_2:
311a3e0fd82Sopenharmony_ci            opacityStep = OPACITY_STEP_A2;
312a3e0fd82Sopenharmony_ci            opacityMask = 0x03;
313a3e0fd82Sopenharmony_ci            break;
314a3e0fd82Sopenharmony_ci        case FONT_WEIGHT_4:
315a3e0fd82Sopenharmony_ci            opacityStep = OPACITY_STEP_A4;
316a3e0fd82Sopenharmony_ci            opacityMask = 0x0F;
317a3e0fd82Sopenharmony_ci            break;
318a3e0fd82Sopenharmony_ci        case FONT_WEIGHT_8:
319a3e0fd82Sopenharmony_ci            opacityMask = 0xFF;
320a3e0fd82Sopenharmony_ci            break;
321a3e0fd82Sopenharmony_ci        case FONT_WEIGHT_32:
322a3e0fd82Sopenharmony_ci            opacityMask = 0xFF;
323a3e0fd82Sopenharmony_ci            break;
324a3e0fd82Sopenharmony_ci        default:
325a3e0fd82Sopenharmony_ci            return;
326a3e0fd82Sopenharmony_ci    }
327a3e0fd82Sopenharmony_ci
328a3e0fd82Sopenharmony_ci    uint8_t letterWidthInByte = (fontRect.GetWidth() * fontWeight) >> SHIFT_3;
329a3e0fd82Sopenharmony_ci    if ((fontRect.GetWidth() * fontWeight) & 0x7) { // 0x7 : less than 1 byte is counted as 1 byte
330a3e0fd82Sopenharmony_ci        letterWidthInByte++;
331a3e0fd82Sopenharmony_ci    }
332a3e0fd82Sopenharmony_ci    int16_t rowStart = subRect.GetY() - fontRect.GetY();
333a3e0fd82Sopenharmony_ci    int16_t rowEnd = rowStart + subRect.GetHeight();
334a3e0fd82Sopenharmony_ci    int16_t colStart = subRect.GetX() - fontRect.GetX();
335a3e0fd82Sopenharmony_ci    int16_t colEnd = colStart + subRect.GetWidth();
336a3e0fd82Sopenharmony_ci
337a3e0fd82Sopenharmony_ci    DRAW_UTILS_PREPROCESS(gfxDstBuffer, opa);
338a3e0fd82Sopenharmony_ci    screenBuffer += ((subRect.GetY() * screenBufferWidth) + subRect.GetX()) * bufferPxSize;
339a3e0fd82Sopenharmony_ci    fontMap += (rowStart * letterWidthInByte) + ((colStart * fontWeight) >> SHIFT_3);
340a3e0fd82Sopenharmony_ci
341a3e0fd82Sopenharmony_ci    uint8_t offsetInFont = (colStart * fontWeight) % FONT_WEIGHT_8;
342a3e0fd82Sopenharmony_ci    int16_t temp = subRect.GetWidth() * fontWeight - FONT_WEIGHT_8 + offsetInFont;
343a3e0fd82Sopenharmony_ci    if (temp < 0) {
344a3e0fd82Sopenharmony_ci        temp = 0;
345a3e0fd82Sopenharmony_ci    }
346a3e0fd82Sopenharmony_ci    int16_t validWidthInByte = temp / FONT_WEIGHT_8 + 1;
347a3e0fd82Sopenharmony_ci    if (temp % FONT_WEIGHT_8 != 0) {
348a3e0fd82Sopenharmony_ci        validWidthInByte++;
349a3e0fd82Sopenharmony_ci    }
350a3e0fd82Sopenharmony_ci    for (int16_t i = rowStart; i < rowEnd; i++) {
351a3e0fd82Sopenharmony_ci        int16_t col = colStart;
352a3e0fd82Sopenharmony_ci        uint8_t tempOffset = offsetInFont;
353a3e0fd82Sopenharmony_ci        uint8_t tempFontByte = (*fontMap++) >> offsetInFont;
354a3e0fd82Sopenharmony_ci        while (col < colEnd) {
355a3e0fd82Sopenharmony_ci            while ((tempOffset < FONT_WEIGHT_8) && (col < colEnd)) {
356a3e0fd82Sopenharmony_ci                uint8_t validOpacity = tempFontByte & opacityMask;
357a3e0fd82Sopenharmony_ci                if (validOpacity != 0) {
358a3e0fd82Sopenharmony_ci                    validOpacity *= opacityStep;
359a3e0fd82Sopenharmony_ci                    if (opa != OPA_OPAQUE) {
360a3e0fd82Sopenharmony_ci                        validOpacity =
361a3e0fd82Sopenharmony_ci                            static_cast<OpacityType>((static_cast<uint16_t>(validOpacity) * opa) >> FONT_WEIGHT_8);
362a3e0fd82Sopenharmony_ci                    }
363a3e0fd82Sopenharmony_ci                    COLOR_FILL_BLEND(screenBuffer, bufferMode, &fillColor, ARGB8888, validOpacity);
364a3e0fd82Sopenharmony_ci                }
365a3e0fd82Sopenharmony_ci                screenBuffer += bufferPxSize;
366a3e0fd82Sopenharmony_ci                tempFontByte = tempFontByte >> fontWeight;
367a3e0fd82Sopenharmony_ci                tempOffset += fontWeight;
368a3e0fd82Sopenharmony_ci                col++;
369a3e0fd82Sopenharmony_ci            }
370a3e0fd82Sopenharmony_ci            tempOffset = 0;
371a3e0fd82Sopenharmony_ci            tempFontByte = *(fontMap++);
372a3e0fd82Sopenharmony_ci        }
373a3e0fd82Sopenharmony_ci        fontMap += letterWidthInByte - validWidthInByte - 1;
374a3e0fd82Sopenharmony_ci        screenBuffer += (screenBufferWidth - (colEnd - colStart)) * bufferPxSize;
375a3e0fd82Sopenharmony_ci    }
376a3e0fd82Sopenharmony_ci}
377a3e0fd82Sopenharmony_ci
378a3e0fd82Sopenharmony_civoid DrawUtils::DrawImage(BufferInfo& gfxDstBuffer,
379a3e0fd82Sopenharmony_ci                          const Rect& area,
380a3e0fd82Sopenharmony_ci                          const Rect& mask,
381a3e0fd82Sopenharmony_ci                          const uint8_t* image,
382a3e0fd82Sopenharmony_ci                          OpacityType opa,
383a3e0fd82Sopenharmony_ci                          uint8_t pxBitSize,
384a3e0fd82Sopenharmony_ci                          ColorMode colorMode) const
385a3e0fd82Sopenharmony_ci{
386a3e0fd82Sopenharmony_ci    if (image == nullptr) {
387a3e0fd82Sopenharmony_ci        return;
388a3e0fd82Sopenharmony_ci    }
389a3e0fd82Sopenharmony_ci    Rect maskedArea;
390a3e0fd82Sopenharmony_ci    if (!maskedArea.Intersect(area, mask)) {
391a3e0fd82Sopenharmony_ci        return;
392a3e0fd82Sopenharmony_ci    }
393a3e0fd82Sopenharmony_ci    int16_t mapWidth = area.GetWidth();
394a3e0fd82Sopenharmony_ci    int16_t imageX = maskedArea.GetLeft() - area.GetLeft();
395a3e0fd82Sopenharmony_ci    int16_t imageY = maskedArea.GetTop() - area.GetTop();
396a3e0fd82Sopenharmony_ci    uint32_t imageWidthInByte = (static_cast<uint32_t>(mapWidth) * pxBitSize) >> SHIFT_3;
397a3e0fd82Sopenharmony_ci    if ((mapWidth * pxBitSize) & 0x7) { // 0x7 : less than 1 byte is counted as 1 byte
398a3e0fd82Sopenharmony_ci        imageWidthInByte++;
399a3e0fd82Sopenharmony_ci    }
400a3e0fd82Sopenharmony_ci
401a3e0fd82Sopenharmony_ci    BufferInfo src;
402a3e0fd82Sopenharmony_ci    src.rect = {imageX, imageY, static_cast<int16_t>(imageX + maskedArea.GetWidth() - 1),
403a3e0fd82Sopenharmony_ci                static_cast<int16_t>(imageY + maskedArea.GetHeight() - 1)};
404a3e0fd82Sopenharmony_ci
405a3e0fd82Sopenharmony_ci    src.virAddr = static_cast<void*>(const_cast<uint8_t*>(image));
406a3e0fd82Sopenharmony_ci    src.stride = imageWidthInByte;
407a3e0fd82Sopenharmony_ci    src.mode = colorMode;
408a3e0fd82Sopenharmony_ci    src.color = 0;
409a3e0fd82Sopenharmony_ci
410a3e0fd82Sopenharmony_ci    Point dstPos = {maskedArea.GetLeft(), maskedArea.GetTop()};
411a3e0fd82Sopenharmony_ci    BlendOption blendOption;
412a3e0fd82Sopenharmony_ci    blendOption.opacity = opa;
413a3e0fd82Sopenharmony_ci    blendOption.mode = BLEND_SRC_OVER;
414a3e0fd82Sopenharmony_ci    BaseGfxEngine::GetInstance()->Blit(gfxDstBuffer, dstPos, src, maskedArea, blendOption);
415a3e0fd82Sopenharmony_ci}
416a3e0fd82Sopenharmony_ci
417a3e0fd82Sopenharmony_civoid DrawUtils::FillAreaWithSoftWare(BufferInfo& gfxDstBuffer,
418a3e0fd82Sopenharmony_ci                                     const Rect& fillArea,
419a3e0fd82Sopenharmony_ci                                     const ColorType& color,
420a3e0fd82Sopenharmony_ci                                     const OpacityType& opa) const
421a3e0fd82Sopenharmony_ci{
422a3e0fd82Sopenharmony_ci    if (gfxDstBuffer.virAddr == nullptr) {
423a3e0fd82Sopenharmony_ci        return;
424a3e0fd82Sopenharmony_ci    }
425a3e0fd82Sopenharmony_ci    ColorMode mode = gfxDstBuffer.mode;
426a3e0fd82Sopenharmony_ci    uint8_t destByteSize = GetByteSizeByColorMode(mode);
427a3e0fd82Sopenharmony_ci    int16_t destWidth = gfxDstBuffer.width;
428a3e0fd82Sopenharmony_ci    int32_t halBufferDeltaByteLen = static_cast<int32_t>(destWidth) * destByteSize;
429a3e0fd82Sopenharmony_ci    int16_t width = fillArea.GetWidth();
430a3e0fd82Sopenharmony_ci    int16_t height = fillArea.GetHeight();
431a3e0fd82Sopenharmony_ci    uint8_t* dest = static_cast<uint8_t*>(gfxDstBuffer.virAddr);
432a3e0fd82Sopenharmony_ci    int32_t offset = static_cast<int32_t>(fillArea.GetTop()) * destWidth + fillArea.GetLeft();
433a3e0fd82Sopenharmony_ci    dest += offset * destByteSize;
434a3e0fd82Sopenharmony_ci
435a3e0fd82Sopenharmony_ci    int32_t dstMaxSize = (gfxDstBuffer.width * gfxDstBuffer.height - offset) * destByteSize;
436a3e0fd82Sopenharmony_ci    Color32 fillColor;
437a3e0fd82Sopenharmony_ci    fillColor.full = Color::ColorTo32(color);
438a3e0fd82Sopenharmony_ci    uint8_t* dstTmp = nullptr;
439a3e0fd82Sopenharmony_ci
440a3e0fd82Sopenharmony_ci    if ((fillColor.alpha == OPA_TRANSPARENT) || (opa == OPA_TRANSPARENT)) {
441a3e0fd82Sopenharmony_ci        return;
442a3e0fd82Sopenharmony_ci    }
443a3e0fd82Sopenharmony_ci    /* cover mode */
444a3e0fd82Sopenharmony_ci    if ((opa == OPA_OPAQUE) && (fillColor.alpha == OPA_OPAQUE)) {
445a3e0fd82Sopenharmony_ci        for (int16_t col = 0; col < width; ++col) {
446a3e0fd82Sopenharmony_ci            dstTmp = dest + (col * destByteSize);
447a3e0fd82Sopenharmony_ci            COLOR_FILL_COVER(dstTmp, mode, fillColor.red, fillColor.green, fillColor.blue, ARGB8888);
448a3e0fd82Sopenharmony_ci        }
449a3e0fd82Sopenharmony_ci        uint8_t* memStart = dest;
450a3e0fd82Sopenharmony_ci        int32_t memSize = static_cast<int32_t>(width) * destByteSize;
451a3e0fd82Sopenharmony_ci        dest += halBufferDeltaByteLen;
452a3e0fd82Sopenharmony_ci        dstMaxSize -= halBufferDeltaByteLen;
453a3e0fd82Sopenharmony_ci        for (int16_t row = 1; row < height; ++row) {
454a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
455a3e0fd82Sopenharmony_ci            {
456a3e0fd82Sopenharmony_ci                DEBUG_PERFORMANCE_TRACE("memcpy_neon");
457a3e0fd82Sopenharmony_ci                NeonMemcpy(dest, dstMaxSize, memStart, memSize);
458a3e0fd82Sopenharmony_ci            }
459a3e0fd82Sopenharmony_ci#else
460a3e0fd82Sopenharmony_ci            {
461a3e0fd82Sopenharmony_ci                DEBUG_PERFORMANCE_TRACE("memcpy");
462a3e0fd82Sopenharmony_ci                if (memcpy_s(dest, dstMaxSize, memStart, memSize) != EOK) {
463a3e0fd82Sopenharmony_ci                    GRAPHIC_LOGE("DrawUtils::FillAreaWithSoftWare memcpy failed!\n");
464a3e0fd82Sopenharmony_ci                    return;
465a3e0fd82Sopenharmony_ci                }
466a3e0fd82Sopenharmony_ci            }
467a3e0fd82Sopenharmony_ci#endif
468a3e0fd82Sopenharmony_ci            dest += halBufferDeltaByteLen;
469a3e0fd82Sopenharmony_ci            dstMaxSize -= halBufferDeltaByteLen;
470a3e0fd82Sopenharmony_ci        }
471a3e0fd82Sopenharmony_ci    } else {
472a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
473a3e0fd82Sopenharmony_ci        {
474a3e0fd82Sopenharmony_ci            DEBUG_PERFORMANCE_TRACE("FillAreaWithSoftWare_neon");
475a3e0fd82Sopenharmony_ci            NeonBlendPipeLine pipeLine;
476a3e0fd82Sopenharmony_ci            pipeLine.Construct(mode, ARGB8888, &fillColor, opa);
477a3e0fd82Sopenharmony_ci            int16_t step = NEON_STEP_8 * GetByteSizeByColorMode(mode);
478a3e0fd82Sopenharmony_ci            for (int16_t row = 0; row < height; ++row) {
479a3e0fd82Sopenharmony_ci                uint8_t* buf = dest;
480a3e0fd82Sopenharmony_ci                int16_t tmpWidth = width;
481a3e0fd82Sopenharmony_ci                while (tmpWidth >= NEON_STEP_8) {
482a3e0fd82Sopenharmony_ci                    pipeLine.Invoke(buf);
483a3e0fd82Sopenharmony_ci                    buf += step;
484a3e0fd82Sopenharmony_ci                    tmpWidth -= NEON_STEP_8;
485a3e0fd82Sopenharmony_ci                }
486a3e0fd82Sopenharmony_ci                for (int16_t i = 0; i < tmpWidth; ++i) {
487a3e0fd82Sopenharmony_ci                    COLOR_FILL_BLEND(buf, mode, &fillColor, ARGB8888, opa);
488a3e0fd82Sopenharmony_ci                    buf += destByteSize;
489a3e0fd82Sopenharmony_ci                }
490a3e0fd82Sopenharmony_ci                dest += halBufferDeltaByteLen;
491a3e0fd82Sopenharmony_ci            }
492a3e0fd82Sopenharmony_ci        }
493a3e0fd82Sopenharmony_ci#else
494a3e0fd82Sopenharmony_ci        {
495a3e0fd82Sopenharmony_ci            DEBUG_PERFORMANCE_TRACE("FillAreaWithSoftWare");
496a3e0fd82Sopenharmony_ci            for (int16_t row = 0; row < height; row++) {
497a3e0fd82Sopenharmony_ci                for (int16_t col = 0; col < width; col++) {
498a3e0fd82Sopenharmony_ci                    dstTmp = dest + (col * destByteSize);
499a3e0fd82Sopenharmony_ci                    COLOR_FILL_BLEND(dstTmp, mode, &fillColor, ARGB8888, opa);
500a3e0fd82Sopenharmony_ci                }
501a3e0fd82Sopenharmony_ci                dest += destWidth * destByteSize;
502a3e0fd82Sopenharmony_ci            }
503a3e0fd82Sopenharmony_ci        }
504a3e0fd82Sopenharmony_ci#endif
505a3e0fd82Sopenharmony_ci    }
506a3e0fd82Sopenharmony_ci}
507a3e0fd82Sopenharmony_ci
508a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
509a3e0fd82Sopenharmony_civoid DrawUtils::BlendLerpPix(uint8_t* color, uint8_t red, uint8_t green, uint8_t blue,
510a3e0fd82Sopenharmony_ci                             uint8_t alpha, uint8_t cover)
511a3e0fd82Sopenharmony_ci{
512a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
513a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonLerpARGB8888(color, red, green, blue, alpha, cover);
514a3e0fd82Sopenharmony_ci}
515a3e0fd82Sopenharmony_ci
516a3e0fd82Sopenharmony_civoid DrawUtils::BlendLerpPix(uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
517a3e0fd82Sopenharmony_ci{
518a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
519a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonLerpARGB8888(color, red, green, blue, alpha);
520a3e0fd82Sopenharmony_ci}
521a3e0fd82Sopenharmony_ci
522a3e0fd82Sopenharmony_civoid DrawUtils::BlendLerpPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t srcCover)
523a3e0fd82Sopenharmony_ci{
524a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
525a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonLerpARGB8888(dstColors, srcColors, srcCover);
526a3e0fd82Sopenharmony_ci}
527a3e0fd82Sopenharmony_ci
528a3e0fd82Sopenharmony_civoid DrawUtils::BlendLerpPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t* srcCovers)
529a3e0fd82Sopenharmony_ci{
530a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
531a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonLerpARGB8888(dstColors, srcColors, srcCovers);
532a3e0fd82Sopenharmony_ci}
533a3e0fd82Sopenharmony_ci
534a3e0fd82Sopenharmony_civoid DrawUtils::BlendLerpPix(uint8_t* color, uint8_t red, uint8_t green, uint8_t blue,
535a3e0fd82Sopenharmony_ci                             uint8_t alpha, uint8_t* covers)
536a3e0fd82Sopenharmony_ci{
537a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
538a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonLerpARGB8888(color, red, green, blue, alpha, covers);
539a3e0fd82Sopenharmony_ci}
540a3e0fd82Sopenharmony_ci
541a3e0fd82Sopenharmony_civoid DrawUtils::BlendPreLerpPix(uint8_t* color, uint8_t red, uint8_t green, uint8_t blue,
542a3e0fd82Sopenharmony_ci                                uint8_t alpha, uint8_t cover)
543a3e0fd82Sopenharmony_ci{
544a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
545a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonPrelerpARGB8888(color, red, green, blue, alpha, cover);
546a3e0fd82Sopenharmony_ci}
547a3e0fd82Sopenharmony_ci
548a3e0fd82Sopenharmony_civoid DrawUtils::BlendPreLerpPix(uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
549a3e0fd82Sopenharmony_ci{
550a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
551a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonPrelerpARGB8888(color, red, green, blue, alpha);
552a3e0fd82Sopenharmony_ci}
553a3e0fd82Sopenharmony_civoid DrawUtils::BlendPreLerpPix(uint8_t *dstColors, uint8_t *srcColors, uint8_t srcCover)
554a3e0fd82Sopenharmony_ci{
555a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
556a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonLerpARGB8888(dstColors, srcColors, srcCover);
557a3e0fd82Sopenharmony_ci}
558a3e0fd82Sopenharmony_ci
559a3e0fd82Sopenharmony_civoid DrawUtils::BlendPreLerpPix(uint8_t *dstColors, uint8_t *srcColors, uint8_t *srcCovers)
560a3e0fd82Sopenharmony_ci{
561a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
562a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonLerpARGB8888(dstColors, srcColors, srcCovers);
563a3e0fd82Sopenharmony_ci}
564a3e0fd82Sopenharmony_ci
565a3e0fd82Sopenharmony_civoid DrawUtils::BlendPreLerpPix(uint8_t *color, uint8_t red, uint8_t green, uint8_t blue,
566a3e0fd82Sopenharmony_ci                                uint8_t alpha, uint8_t *covers)
567a3e0fd82Sopenharmony_ci{
568a3e0fd82Sopenharmony_ci    NeonBlendPipeLine mNeonBlendPipeLine;
569a3e0fd82Sopenharmony_ci    mNeonBlendPipeLine.NeonPreLerpARGB8888(color, red, green, blue, alpha, covers);
570a3e0fd82Sopenharmony_ci}
571a3e0fd82Sopenharmony_ci#endif
572a3e0fd82Sopenharmony_ci
573a3e0fd82Sopenharmony_civoid DrawUtils::BlendWithSoftWare(const uint8_t* src1,
574a3e0fd82Sopenharmony_ci                                  const Rect& srcRect,
575a3e0fd82Sopenharmony_ci                                  uint32_t srcStride,
576a3e0fd82Sopenharmony_ci                                  uint32_t srcLineNumber,
577a3e0fd82Sopenharmony_ci                                  ColorMode srcMode,
578a3e0fd82Sopenharmony_ci                                  uint32_t color,
579a3e0fd82Sopenharmony_ci                                  OpacityType opa,
580a3e0fd82Sopenharmony_ci                                  uint8_t* dst,
581a3e0fd82Sopenharmony_ci                                  uint32_t destStride,
582a3e0fd82Sopenharmony_ci                                  ColorMode destMode,
583a3e0fd82Sopenharmony_ci                                  uint32_t x,
584a3e0fd82Sopenharmony_ci                                  uint32_t y) const
585a3e0fd82Sopenharmony_ci{
586a3e0fd82Sopenharmony_ci    if ((dst == nullptr) || (src1 == nullptr)) {
587a3e0fd82Sopenharmony_ci        return;
588a3e0fd82Sopenharmony_ci    }
589a3e0fd82Sopenharmony_ci    uint8_t destByteSize = GetByteSizeByColorMode(destMode);
590a3e0fd82Sopenharmony_ci    uint8_t srcByteSize = GetByteSizeByColorMode(srcMode);
591a3e0fd82Sopenharmony_ci
592a3e0fd82Sopenharmony_ci    uint8_t* dest = dst + destStride * y;
593a3e0fd82Sopenharmony_ci    dest += destByteSize * x;
594a3e0fd82Sopenharmony_ci
595a3e0fd82Sopenharmony_ci    uint8_t pxByteSize = GetPxSizeByColorMode(srcMode) >> 3; // 3 : right shift 3 bits
596a3e0fd82Sopenharmony_ci    uint8_t* src = const_cast<uint8_t*>(src1) + srcStride * srcRect.GetY() + pxByteSize * srcRect.GetX();
597a3e0fd82Sopenharmony_ci    uint32_t width = srcRect.GetWidth();
598a3e0fd82Sopenharmony_ci    uint32_t height = srcRect.GetHeight();
599a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
600a3e0fd82Sopenharmony_ci    GetInstance()->SetDestAndSrc(srcMode, destMode, height, src, width, opa, dest,
601a3e0fd82Sopenharmony_ci                                 destStride, srcStride, destByteSize, srcByteSize);
602a3e0fd82Sopenharmony_ci#else
603a3e0fd82Sopenharmony_ci    {
604a3e0fd82Sopenharmony_ci        DEBUG_PERFORMANCE_TRACE("BlendWithSoftWare");
605a3e0fd82Sopenharmony_ci        for (uint32_t row = 0; row < height; ++row) {
606a3e0fd82Sopenharmony_ci            uint8_t* destTmp = dest;
607a3e0fd82Sopenharmony_ci            uint8_t* srcTmp = const_cast<uint8_t*>(src);
608a3e0fd82Sopenharmony_ci            for (uint32_t col = 0; col < width; ++col) {
609a3e0fd82Sopenharmony_ci                COLOR_FILL_BLEND(destTmp, destMode, srcTmp, srcMode, opa);
610a3e0fd82Sopenharmony_ci                destTmp += destByteSize;
611a3e0fd82Sopenharmony_ci                srcTmp += srcByteSize;
612a3e0fd82Sopenharmony_ci            }
613a3e0fd82Sopenharmony_ci            dest += destStride;
614a3e0fd82Sopenharmony_ci            src += srcStride;
615a3e0fd82Sopenharmony_ci        }
616a3e0fd82Sopenharmony_ci    }
617a3e0fd82Sopenharmony_ci#endif
618a3e0fd82Sopenharmony_ci}
619a3e0fd82Sopenharmony_ci
620a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
621a3e0fd82Sopenharmony_civoid DrawUtils::SetDestAndSrc(ColorMode& srcMode, ColorMode& destMode, uint32_t height, uint8_t* src,
622a3e0fd82Sopenharmony_ci                              uint32_t width, OpacityType opa, uint8_t* dest, uint32_t destStride,
623a3e0fd82Sopenharmony_ci                              uint32_t srcStride, uint8_t destByteSize, uint8_t srcByteSize) const
624a3e0fd82Sopenharmony_ci{
625a3e0fd82Sopenharmony_ci    DEBUG_PERFORMANCE_TRACE("BlendWithSoftWare_neon");
626a3e0fd82Sopenharmony_ci    NeonBlendPipeLine pipeLine;
627a3e0fd82Sopenharmony_ci    pipeLine.Construct(destMode, srcMode);
628a3e0fd82Sopenharmony_ci    int16_t dstStep = NEON_STEP_8 * GetByteSizeByColorMode(destMode);
629a3e0fd82Sopenharmony_ci    int16_t srcStep = NEON_STEP_8 * GetByteSizeByColorMode(srcMode);
630a3e0fd82Sopenharmony_ci    for (uint32_t row = 0; row < height; ++row) {
631a3e0fd82Sopenharmony_ci        uint8_t* dstBuf = dest;
632a3e0fd82Sopenharmony_ci        uint8_t* srcBuf = const_cast<uint8_t*>(src);
633a3e0fd82Sopenharmony_ci        int16_t tmpWidth = width;
634a3e0fd82Sopenharmony_ci        while (tmpWidth >= NEON_STEP_8) {
635a3e0fd82Sopenharmony_ci            pipeLine.Invoke(dstBuf, srcBuf, opa);
636a3e0fd82Sopenharmony_ci            dstBuf += dstStep;
637a3e0fd82Sopenharmony_ci            srcBuf += srcStep;
638a3e0fd82Sopenharmony_ci            tmpWidth -= NEON_STEP_8;
639a3e0fd82Sopenharmony_ci        }
640a3e0fd82Sopenharmony_ci        for (int16_t i = 0; i < tmpWidth; ++i) {
641a3e0fd82Sopenharmony_ci            COLOR_FILL_BLEND(dstBuf, destMode, srcBuf, srcMode, opa);
642a3e0fd82Sopenharmony_ci            dstBuf += destByteSize;
643a3e0fd82Sopenharmony_ci            srcBuf += srcByteSize;
644a3e0fd82Sopenharmony_ci        }
645a3e0fd82Sopenharmony_ci        dest += destStride;
646a3e0fd82Sopenharmony_ci        src += srcStride;
647a3e0fd82Sopenharmony_ci    }
648a3e0fd82Sopenharmony_ci}
649a3e0fd82Sopenharmony_ci#endif
650a3e0fd82Sopenharmony_ci
651a3e0fd82Sopenharmony_civoid DrawUtils::GetXAxisErrForJunctionLine(bool ignoreJunctionPoint,
652a3e0fd82Sopenharmony_ci                                           bool isRightPart,
653a3e0fd82Sopenharmony_ci                                           int16_t& xMinErr,
654a3e0fd82Sopenharmony_ci                                           int16_t& xMaxErr)
655a3e0fd82Sopenharmony_ci{
656a3e0fd82Sopenharmony_ci    xMinErr = 0;
657a3e0fd82Sopenharmony_ci    xMaxErr = 0;
658a3e0fd82Sopenharmony_ci    if (ignoreJunctionPoint) {
659a3e0fd82Sopenharmony_ci        if (isRightPart) {
660a3e0fd82Sopenharmony_ci            xMinErr = 1;
661a3e0fd82Sopenharmony_ci        } else {
662a3e0fd82Sopenharmony_ci            xMaxErr = -1;
663a3e0fd82Sopenharmony_ci        }
664a3e0fd82Sopenharmony_ci    }
665a3e0fd82Sopenharmony_ci}
666a3e0fd82Sopenharmony_ci
667a3e0fd82Sopenharmony_civoid DrawUtils::GetTransformInitState(const TransformMap& transMap,
668a3e0fd82Sopenharmony_ci                                      const Point& position,
669a3e0fd82Sopenharmony_ci                                      const Rect& trans,
670a3e0fd82Sopenharmony_ci                                      TransformInitState& init)
671a3e0fd82Sopenharmony_ci{
672a3e0fd82Sopenharmony_ci    int16_t x = trans.GetLeft();
673a3e0fd82Sopenharmony_ci    int16_t y = trans.GetTop();
674a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
675a3e0fd82Sopenharmony_ci    init.duHorizon = FO_TRANS_FLOAT_TO_FIXED(transMap.invMatrix_.GetData()[0]);
676a3e0fd82Sopenharmony_ci    init.dvHorizon = FO_TRANS_FLOAT_TO_FIXED(transMap.invMatrix_.GetData()[1]);
677a3e0fd82Sopenharmony_ci    init.duVertical = FO_TRANS_FLOAT_TO_FIXED(transMap.invMatrix_.GetData()[3]); // 3:RSxy
678a3e0fd82Sopenharmony_ci    init.dvVertical = FO_TRANS_FLOAT_TO_FIXED(transMap.invMatrix_.GetData()[4]); // 4:RSyy
679a3e0fd82Sopenharmony_ci    init.verticalU = (x - position.x) * init.duHorizon + (y - position.y) * init.duVertical +
680a3e0fd82Sopenharmony_ci                     FO_TRANS_FLOAT_TO_FIXED(transMap.invMatrix_.GetData()[6]); // 6:TRSx
681a3e0fd82Sopenharmony_ci    init.verticalV = (x - position.x) * init.dvHorizon + (y - position.y) * init.dvVertical +
682a3e0fd82Sopenharmony_ci                     FO_TRANS_FLOAT_TO_FIXED(transMap.invMatrix_.GetData()[7]); // 7:TRSy
683a3e0fd82Sopenharmony_ci#else
684a3e0fd82Sopenharmony_ci    init.duHorizon = transMap.invMatrix_.GetData()[0];
685a3e0fd82Sopenharmony_ci    init.dvHorizon = transMap.invMatrix_.GetData()[1];
686a3e0fd82Sopenharmony_ci    init.duVertical = transMap.invMatrix_.GetData()[3]; // 3:RSxy
687a3e0fd82Sopenharmony_ci    init.dvVertical = transMap.invMatrix_.GetData()[4]; // 4:RSyy
688a3e0fd82Sopenharmony_ci    init.verticalU = (x - position.x) * init.duHorizon + (y - position.y) * init.duVertical +
689a3e0fd82Sopenharmony_ci                     transMap.invMatrix_.GetData()[6]; // 6:TRSx
690a3e0fd82Sopenharmony_ci    init.verticalV = (x - position.x) * init.dvHorizon + (y - position.y) * init.dvVertical +
691a3e0fd82Sopenharmony_ci                     transMap.invMatrix_.GetData()[7]; // 7:TRSy
692a3e0fd82Sopenharmony_ci#endif
693a3e0fd82Sopenharmony_ci}
694a3e0fd82Sopenharmony_ci
695a3e0fd82Sopenharmony_ciinline void DrawUtils::StepToNextLine(TriangleEdge& edge1, TriangleEdge& edge2)
696a3e0fd82Sopenharmony_ci{
697a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
698a3e0fd82Sopenharmony_ci    edge1.curY += FIXED_NUM_1;
699a3e0fd82Sopenharmony_ci    edge2.curY += FIXED_NUM_1;
700a3e0fd82Sopenharmony_ci    edge1.curX += FO_DIV(edge1.du, edge1.dv);
701a3e0fd82Sopenharmony_ci    edge2.curX += FO_DIV(edge2.du, edge2.dv);
702a3e0fd82Sopenharmony_ci#else
703a3e0fd82Sopenharmony_ci    edge1.curY++;
704a3e0fd82Sopenharmony_ci    edge2.curY++;
705a3e0fd82Sopenharmony_ci    edge1.curX += edge1.du / edge1.dv;
706a3e0fd82Sopenharmony_ci    edge2.curX += edge2.du / edge2.dv;
707a3e0fd82Sopenharmony_ci#endif
708a3e0fd82Sopenharmony_ci}
709a3e0fd82Sopenharmony_ci
710a3e0fd82Sopenharmony_civoid DrawUtils::DrawTriangleAlphaBilinear(const TriangleScanInfo& in, const ColorMode bufferMode)
711a3e0fd82Sopenharmony_ci{
712a3e0fd82Sopenharmony_ci    int16_t maskLeft = in.mask.GetLeft();
713a3e0fd82Sopenharmony_ci    int16_t maskRight = in.mask.GetRight();
714a3e0fd82Sopenharmony_ci    for (int16_t y = in.yMin; y <= in.yMax; y++) {
715a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
716a3e0fd82Sopenharmony_ci        int16_t tempV = FO_TO_INTEGER(in.edge1.curX);
717a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(tempV, maskLeft);
718a3e0fd82Sopenharmony_ci        tempV = FO_TO_INTEGER(in.edge2.curX);
719a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(tempV, maskRight);
720a3e0fd82Sopenharmony_ci        int16_t diffX = xMin - FO_TO_INTEGER(in.edge1.curX);
721a3e0fd82Sopenharmony_ci#else
722a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(static_cast<int16_t>(in.edge1.curX), maskLeft);
723a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(static_cast<int16_t>(in.edge2.curX), maskRight);
724a3e0fd82Sopenharmony_ci        int16_t diffX = (xMin - static_cast<int32_t>(in.edge1.curX));
725a3e0fd82Sopenharmony_ci#endif
726a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * diffX;
727a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * diffX;
728a3e0fd82Sopenharmony_ci        uint8_t* screenBuffer = in.screenBuffer + (y * in.screenBufferWidth + xMin) * in.bufferPxSize;
729a3e0fd82Sopenharmony_ci
730a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
731a3e0fd82Sopenharmony_ci        // parameters below are Q15 fixed-point number
732a3e0fd82Sopenharmony_ci        int64_t u = in.init.verticalU;
733a3e0fd82Sopenharmony_ci        int64_t v = in.init.verticalV;
734a3e0fd82Sopenharmony_ci        // parameters above are Q15 fixed-point number
735a3e0fd82Sopenharmony_ci#else
736a3e0fd82Sopenharmony_ci        float u = in.init.verticalU;
737a3e0fd82Sopenharmony_ci        float v = in.init.verticalV;
738a3e0fd82Sopenharmony_ci#endif
739a3e0fd82Sopenharmony_ci        for (int16_t x = xMin; x <= xMax; x++) {
740a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
741a3e0fd82Sopenharmony_ci            int16_t intU = FO_TO_INTEGER(u);
742a3e0fd82Sopenharmony_ci            int16_t intV = FO_TO_INTEGER(v);
743a3e0fd82Sopenharmony_ci            if ((u >= 0) && (intU < (in.info.header.width - 1)) && (v >= 0) && (intV < (in.info.header.height - 1))) {
744a3e0fd82Sopenharmony_ci                int16_t intUPlus1 = intU + 1;
745a3e0fd82Sopenharmony_ci                int16_t intVPlus1 = intV + 1;
746a3e0fd82Sopenharmony_ci#else
747a3e0fd82Sopenharmony_ci            const int16_t intU = static_cast<int16_t>(u);
748a3e0fd82Sopenharmony_ci            const int16_t intV = static_cast<int16_t>(v);
749a3e0fd82Sopenharmony_ci            if ((u >= 0) && (intU < in.info.header.width - 1) && (v >= 0) && (intV < in.info.header.height - 1)) {
750a3e0fd82Sopenharmony_ci                const int16_t intUPlus1 = intU + 1;
751a3e0fd82Sopenharmony_ci                const int16_t intVPlus1 = intV + 1;
752a3e0fd82Sopenharmony_ci#endif
753a3e0fd82Sopenharmony_ci                OpacityType p1 = GetPxAlphaForAlphaImg(in.info, {intU, intV});
754a3e0fd82Sopenharmony_ci                OpacityType p2 = GetPxAlphaForAlphaImg(in.info, {intUPlus1, intV});
755a3e0fd82Sopenharmony_ci                OpacityType p3 = GetPxAlphaForAlphaImg(in.info, {intU, intVPlus1});
756a3e0fd82Sopenharmony_ci                OpacityType p4 = GetPxAlphaForAlphaImg(in.info, {intUPlus1, intVPlus1});
757a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
758a3e0fd82Sopenharmony_ci                // parameters below are Q15 fixed-point number
759a3e0fd82Sopenharmony_ci                int64_t decU = FO_DECIMAL(u);
760a3e0fd82Sopenharmony_ci                int64_t decV = FO_DECIMAL(v);
761a3e0fd82Sopenharmony_ci                int64_t decUMinus1 = FIXED_NUM_1 - decU;
762a3e0fd82Sopenharmony_ci                int64_t decVMinus1 = FIXED_NUM_1 - decV;
763a3e0fd82Sopenharmony_ci                int64_t w1 = FO_MUL(decUMinus1, decVMinus1);
764a3e0fd82Sopenharmony_ci                int64_t w2 = FO_MUL(decU, decVMinus1);
765a3e0fd82Sopenharmony_ci                int64_t w3 = FO_MUL(decUMinus1, decV);
766a3e0fd82Sopenharmony_ci                int64_t w4 = FO_MUL(decU, decV);
767a3e0fd82Sopenharmony_ci                // parameters above are Q15 fixed-point number
768a3e0fd82Sopenharmony_ci#else
769a3e0fd82Sopenharmony_ci                const float decU = u - intU;
770a3e0fd82Sopenharmony_ci                const float decV = v - intV;
771a3e0fd82Sopenharmony_ci                const float decUMinus1 = 1.0f - decU;
772a3e0fd82Sopenharmony_ci                const float decVMinus1 = 1.0f - decV;
773a3e0fd82Sopenharmony_ci
774a3e0fd82Sopenharmony_ci                const int32_t w1 = static_cast<int32_t>(decUMinus1 * decVMinus1 * 256.0f); // 256:shift 8 bit left
775a3e0fd82Sopenharmony_ci                const int32_t w2 = static_cast<int32_t>(decU * decVMinus1 * 256.0f);       // 256:shift 8 bit left
776a3e0fd82Sopenharmony_ci                const int32_t w3 = static_cast<int32_t>(decUMinus1 * decV * 256.0f);       // 256:shift 8 bit left
777a3e0fd82Sopenharmony_ci                const int32_t w4 = static_cast<int32_t>(decU * decV * 256.0f);             // 256:shift 8 bit left
778a3e0fd82Sopenharmony_ci#endif
779a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
780a3e0fd82Sopenharmony_ci                const int64_t outA = __SMUAD(p1, w1) + __SMUAD(p2, w2) + __SMUAD(p3, w3) + __SMUAD(p4, w4);
781a3e0fd82Sopenharmony_ci#else
782a3e0fd82Sopenharmony_ci                const int64_t outA = p1 * w1 + p2 * w2 + p3 * w3 + p4 * w4;
783a3e0fd82Sopenharmony_ci#endif
784a3e0fd82Sopenharmony_ci                Color32 result;
785a3e0fd82Sopenharmony_ci                result.full = Color::ColorTo32(in.color);
786a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
787a3e0fd82Sopenharmony_ci                result.alpha = FO_TO_INTEGER(outA);
788a3e0fd82Sopenharmony_ci#else
789a3e0fd82Sopenharmony_ci                result.alpha = static_cast<uint8_t>(outA >> 8); // 8:shift 8 bit right
790a3e0fd82Sopenharmony_ci#endif
791a3e0fd82Sopenharmony_ci                COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, in.opaScale);
792a3e0fd82Sopenharmony_ci            }
793a3e0fd82Sopenharmony_ci            u += in.init.duHorizon;
794a3e0fd82Sopenharmony_ci            v += in.init.dvHorizon;
795a3e0fd82Sopenharmony_ci            screenBuffer += in.bufferPxSize;
796a3e0fd82Sopenharmony_ci        }
797a3e0fd82Sopenharmony_ci        StepToNextLine(in.edge1, in.edge2);
798a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duVertical;
799a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvVertical;
800a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
801a3e0fd82Sopenharmony_ci        int16_t deltaX = FO_TO_INTEGER(in.edge1.curX) - xMin;
802a3e0fd82Sopenharmony_ci#else
803a3e0fd82Sopenharmony_ci        int16_t deltaX = static_cast<int16_t>(in.edge1.curX) - xMin;
804a3e0fd82Sopenharmony_ci#endif
805a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * deltaX;
806a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * deltaX;
807a3e0fd82Sopenharmony_ci    }
808a3e0fd82Sopenharmony_ci}
809a3e0fd82Sopenharmony_ci
810a3e0fd82Sopenharmony_civoid DrawUtils::DrawTriangleTrueColorBilinear565(const TriangleScanInfo& in, const ColorMode bufferMode)
811a3e0fd82Sopenharmony_ci{
812a3e0fd82Sopenharmony_ci    int16_t maskLeft = in.mask.GetLeft();
813a3e0fd82Sopenharmony_ci    int16_t maskRight = in.mask.GetRight();
814a3e0fd82Sopenharmony_ci    int16_t xMinErr = 0;
815a3e0fd82Sopenharmony_ci    int16_t xMaxErr = 0;
816a3e0fd82Sopenharmony_ci    GetXAxisErrForJunctionLine(in.ignoreJunctionPoint, in.isRightPart, xMinErr, xMaxErr);
817a3e0fd82Sopenharmony_ci    for (int16_t y = in.yMin; y <= in.yMax; y++) {
818a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
819a3e0fd82Sopenharmony_ci        int16_t tempV = FO_TO_INTEGER(in.edge1.curX) + xMinErr;
820a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(tempV, maskLeft);
821a3e0fd82Sopenharmony_ci        tempV = FO_TO_INTEGER(in.edge2.curX) + xMaxErr;
822a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(tempV, maskRight);
823a3e0fd82Sopenharmony_ci        int16_t diffX = xMin - FO_TO_INTEGER(in.edge1.curX);
824a3e0fd82Sopenharmony_ci#else
825a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(static_cast<int16_t>(in.edge1.curX + xMinErr), maskLeft);
826a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(static_cast<int16_t>(in.edge2.curX + xMaxErr), maskRight);
827a3e0fd82Sopenharmony_ci        int16_t diffX = (xMin - static_cast<int32_t>(in.edge1.curX));
828a3e0fd82Sopenharmony_ci#endif
829a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * diffX;
830a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * diffX;
831a3e0fd82Sopenharmony_ci        uint8_t* screenBuffer = in.screenBuffer + (y * in.screenBufferWidth + xMin) * in.bufferPxSize;
832a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
833a3e0fd82Sopenharmony_ci        // parameters below are Q15 fixed-point number
834a3e0fd82Sopenharmony_ci        int64_t u = in.init.verticalU;
835a3e0fd82Sopenharmony_ci        int64_t v = in.init.verticalV;
836a3e0fd82Sopenharmony_ci        // parameters above are Q15 fixed-point number
837a3e0fd82Sopenharmony_ci#else
838a3e0fd82Sopenharmony_ci        float u = in.init.verticalU;
839a3e0fd82Sopenharmony_ci        float v = in.init.verticalV;
840a3e0fd82Sopenharmony_ci#endif
841a3e0fd82Sopenharmony_ci        for (int16_t x = xMin; x <= xMax; x++) {
842a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
843a3e0fd82Sopenharmony_ci            int16_t intU = FO_TO_INTEGER(u);
844a3e0fd82Sopenharmony_ci            int16_t intV = FO_TO_INTEGER(v);
845a3e0fd82Sopenharmony_ci            if ((u >= 0) && (intU < (in.info.header.width - 1)) && (v >= 0) && (intV < (in.info.header.height - 1))) {
846a3e0fd82Sopenharmony_ci#else
847a3e0fd82Sopenharmony_ci            const int16_t intU = static_cast<int16_t>(u);
848a3e0fd82Sopenharmony_ci            const int16_t intV = static_cast<int16_t>(v);
849a3e0fd82Sopenharmony_ci            if ((u >= 0) && (intU < in.info.header.width - 1) && (v >= 0) && (intV < in.info.header.height - 1)) {
850a3e0fd82Sopenharmony_ci#endif
851a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
852a3e0fd82Sopenharmony_ci                uint32_t val1 = __SMUAD(intV, in.srcLineWidth);
853a3e0fd82Sopenharmony_ci                uint32_t val2 = __SMUAD(intU, in.pixelSize);
854a3e0fd82Sopenharmony_ci                uint32_t px1 = val1 + val2;
855a3e0fd82Sopenharmony_ci#else
856a3e0fd82Sopenharmony_ci                uint32_t px1 = intV * in.srcLineWidth + intU * in.pixelSize;
857a3e0fd82Sopenharmony_ci#endif
858a3e0fd82Sopenharmony_ci                uint8_t* imgHead = const_cast<uint8_t*>(in.info.data);
859a3e0fd82Sopenharmony_ci                const Color16 p1 = *(reinterpret_cast<Color16*>(&imgHead[px1]));
860a3e0fd82Sopenharmony_ci                const Color16 p2 = *(reinterpret_cast<Color16*>(&imgHead[px1 + in.pixelSize]));
861a3e0fd82Sopenharmony_ci                const Color16 p3 = *(reinterpret_cast<Color16*>(&imgHead[px1 + in.srcLineWidth]));
862a3e0fd82Sopenharmony_ci                const Color16 p4 = *(reinterpret_cast<Color16*>(&imgHead[px1 + in.srcLineWidth + in.pixelSize]));
863a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
864a3e0fd82Sopenharmony_ci                // parameters below are Q15 fixed-point number
865a3e0fd82Sopenharmony_ci                int64_t decU = FO_DECIMAL(u);
866a3e0fd82Sopenharmony_ci                int64_t decV = FO_DECIMAL(v);
867a3e0fd82Sopenharmony_ci                int64_t decUMinus1 = FIXED_NUM_1 - decU;
868a3e0fd82Sopenharmony_ci                int64_t decVMinus1 = FIXED_NUM_1 - decV;
869a3e0fd82Sopenharmony_ci                int64_t w1 = FO_MUL(decUMinus1, decVMinus1);
870a3e0fd82Sopenharmony_ci                int64_t w2 = FO_MUL(decU, decVMinus1);
871a3e0fd82Sopenharmony_ci                int64_t w3 = FO_MUL(decUMinus1, decV);
872a3e0fd82Sopenharmony_ci                int64_t w4 = FO_MUL(decU, decV);
873a3e0fd82Sopenharmony_ci                // parameters above are Q15 fixed-point number
874a3e0fd82Sopenharmony_ci#else
875a3e0fd82Sopenharmony_ci                const float decU = u - intU;
876a3e0fd82Sopenharmony_ci                const float decV = v - intV;
877a3e0fd82Sopenharmony_ci                const float decUMinus1 = 1 - decU;
878a3e0fd82Sopenharmony_ci                const float decVMinus1 = 1 - decV;
879a3e0fd82Sopenharmony_ci                const int32_t w1 = static_cast<int32_t>(decUMinus1 * decVMinus1 * 256.0f); // 256:shift 8 bit left
880a3e0fd82Sopenharmony_ci                const int32_t w2 = static_cast<int32_t>(decU * decVMinus1 * 256.0f);       // 256:shift 8 bit left
881a3e0fd82Sopenharmony_ci                const int32_t w3 = static_cast<int32_t>(decUMinus1 * decV * 256.0f);       // 256:shift 8 bit left
882a3e0fd82Sopenharmony_ci                const int32_t w4 = static_cast<int32_t>(decU * decV * 256.0f);             // 256:shift 8 bit left
883a3e0fd82Sopenharmony_ci#endif
884a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
885a3e0fd82Sopenharmony_ci                const int64_t outR =
886a3e0fd82Sopenharmony_ci                    __SMUAD(p1.red, w1) + __SMUAD(p2.red, w2) + __SMUAD(p3.red, w3) + __SMUAD(p4.red, w4);
887a3e0fd82Sopenharmony_ci                const int64_t outG =
888a3e0fd82Sopenharmony_ci                    __SMUAD(p1.green, w1) + __SMUAD(p2.green, w2) + __SMUAD(p3.green, w3) + __SMUAD(p4.green, w4);
889a3e0fd82Sopenharmony_ci                const int64_t outB =
890a3e0fd82Sopenharmony_ci                    __SMUAD(p1.blue, w1) + __SMUAD(p2.blue, w2) + __SMUAD(p3.blue, w3) + __SMUAD(p4.blue, w4);
891a3e0fd82Sopenharmony_ci#else
892a3e0fd82Sopenharmony_ci                const int64_t outR = p1.red * w1 + p2.red * w2 + p3.red * w3 + p4.red * w4;
893a3e0fd82Sopenharmony_ci                const int64_t outG = p1.green * w1 + p2.green * w2 + p3.green * w3 + p4.green * w4;
894a3e0fd82Sopenharmony_ci                const int64_t outB = p1.blue * w1 + p2.blue * w2 + p3.blue * w3 + p4.blue * w4;
895a3e0fd82Sopenharmony_ci#endif
896a3e0fd82Sopenharmony_ci
897a3e0fd82Sopenharmony_ci                Color16 result;
898a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
899a3e0fd82Sopenharmony_ci                result.red = static_cast<uint8_t>(outR >> FIXED_Q_NUM);
900a3e0fd82Sopenharmony_ci                result.green = static_cast<uint8_t>(outG >> FIXED_Q_NUM);
901a3e0fd82Sopenharmony_ci                result.blue = static_cast<uint8_t>(outB >> FIXED_Q_NUM);
902a3e0fd82Sopenharmony_ci#else
903a3e0fd82Sopenharmony_ci                result.red = static_cast<uint8_t>(outR >> 5);   // 5:shift 5 bit right
904a3e0fd82Sopenharmony_ci                result.green = static_cast<uint8_t>(outG >> 6); // 6:shift 6 bit right
905a3e0fd82Sopenharmony_ci                result.blue = static_cast<uint8_t>(outB >> 5);  // 5:shift 5 bit right
906a3e0fd82Sopenharmony_ci#endif
907a3e0fd82Sopenharmony_ci                if (in.opaScale == OPA_OPAQUE) {
908a3e0fd82Sopenharmony_ci                    COLOR_FILL_COVER(screenBuffer, bufferMode, result.red, result.green, result.blue, RGB565);
909a3e0fd82Sopenharmony_ci                } else {
910a3e0fd82Sopenharmony_ci                    COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, RGB565, in.opaScale);
911a3e0fd82Sopenharmony_ci                }
912a3e0fd82Sopenharmony_ci            }
913a3e0fd82Sopenharmony_ci            u += in.init.duHorizon;
914a3e0fd82Sopenharmony_ci            v += in.init.dvHorizon;
915a3e0fd82Sopenharmony_ci            screenBuffer += in.bufferPxSize;
916a3e0fd82Sopenharmony_ci        }
917a3e0fd82Sopenharmony_ci        StepToNextLine(in.edge1, in.edge2);
918a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duVertical;
919a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvVertical;
920a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
921a3e0fd82Sopenharmony_ci        int16_t deltaX = FO_TO_INTEGER(in.edge1.curX) - xMin;
922a3e0fd82Sopenharmony_ci#else
923a3e0fd82Sopenharmony_ci        int16_t deltaX = static_cast<int16_t>(in.edge1.curX) - xMin;
924a3e0fd82Sopenharmony_ci#endif
925a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * deltaX;
926a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * deltaX;
927a3e0fd82Sopenharmony_ci    }
928a3e0fd82Sopenharmony_ci}
929a3e0fd82Sopenharmony_ci
930a3e0fd82Sopenharmony_civoid DrawUtils::DrawTriangleTrueColorBilinear888(const TriangleScanInfo& in, const ColorMode bufferMode)
931a3e0fd82Sopenharmony_ci{
932a3e0fd82Sopenharmony_ci    int16_t maskLeft = in.mask.GetLeft();
933a3e0fd82Sopenharmony_ci    int16_t maskRight = in.mask.GetRight();
934a3e0fd82Sopenharmony_ci    int16_t xMinErr = 0;
935a3e0fd82Sopenharmony_ci    int16_t xMaxErr = 0;
936a3e0fd82Sopenharmony_ci    GetXAxisErrForJunctionLine(in.ignoreJunctionPoint, in.isRightPart, xMinErr, xMaxErr);
937a3e0fd82Sopenharmony_ci    for (int16_t y = in.yMin; y <= in.yMax; y++) {
938a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
939a3e0fd82Sopenharmony_ci        int16_t tempV = FO_TO_INTEGER(in.edge1.curX) + xMinErr;
940a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(tempV, maskLeft);
941a3e0fd82Sopenharmony_ci        tempV = FO_TO_INTEGER(in.edge2.curX) + xMaxErr;
942a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(tempV, maskRight);
943a3e0fd82Sopenharmony_ci        int16_t diffX = xMin - FO_TO_INTEGER(in.edge1.curX);
944a3e0fd82Sopenharmony_ci#else
945a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(static_cast<int16_t>(in.edge1.curX + xMinErr), maskLeft);
946a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(static_cast<int16_t>(in.edge2.curX + xMaxErr), maskRight);
947a3e0fd82Sopenharmony_ci        int16_t diffX = (xMin - static_cast<int32_t>(in.edge1.curX));
948a3e0fd82Sopenharmony_ci#endif
949a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * diffX;
950a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * diffX;
951a3e0fd82Sopenharmony_ci        uint8_t* screenBuffer = in.screenBuffer + (y * in.screenBufferWidth + xMin) * in.bufferPxSize;
952a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
953a3e0fd82Sopenharmony_ci        // parameters below are Q15 fixed-point number
954a3e0fd82Sopenharmony_ci        int64_t u = in.init.verticalU;
955a3e0fd82Sopenharmony_ci        int64_t v = in.init.verticalV;
956a3e0fd82Sopenharmony_ci        // parameters above are Q15 fixed-point number
957a3e0fd82Sopenharmony_ci#else
958a3e0fd82Sopenharmony_ci        float u = in.init.verticalU;
959a3e0fd82Sopenharmony_ci        float v = in.init.verticalV;
960a3e0fd82Sopenharmony_ci#endif
961a3e0fd82Sopenharmony_ci        for (int16_t x = xMin; x <= xMax; x++) {
962a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
963a3e0fd82Sopenharmony_ci            int16_t intU = FO_TO_INTEGER(u);
964a3e0fd82Sopenharmony_ci            int16_t intV = FO_TO_INTEGER(v);
965a3e0fd82Sopenharmony_ci#else
966a3e0fd82Sopenharmony_ci            const int16_t intU = static_cast<int16_t>(u);
967a3e0fd82Sopenharmony_ci            const int16_t intV = static_cast<int16_t>(v);
968a3e0fd82Sopenharmony_ci#endif
969a3e0fd82Sopenharmony_ci            if ((u >= 0) && (intU < in.info.header.width - 1) && (v >= 0) && (intV < in.info.header.height - 1)) {
970a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
971a3e0fd82Sopenharmony_ci                uint32_t val1 = __SMUAD(intV, in.srcLineWidth);
972a3e0fd82Sopenharmony_ci                uint32_t val2 = __SMUAD(intU, in.pixelSize);
973a3e0fd82Sopenharmony_ci                uint32_t px1 = val1 + val2;
974a3e0fd82Sopenharmony_ci#else
975a3e0fd82Sopenharmony_ci                uint32_t px1 = intV * in.srcLineWidth + intU * in.pixelSize;
976a3e0fd82Sopenharmony_ci#endif
977a3e0fd82Sopenharmony_ci                uint8_t* imgHead = const_cast<uint8_t*>(in.info.data);
978a3e0fd82Sopenharmony_ci                const Color24 p1 = *(reinterpret_cast<Color24*>(&imgHead[px1]));
979a3e0fd82Sopenharmony_ci                const Color24 p2 = *(reinterpret_cast<Color24*>(&imgHead[px1 + in.pixelSize]));
980a3e0fd82Sopenharmony_ci                const Color24 p3 = *(reinterpret_cast<Color24*>(&imgHead[px1 + in.srcLineWidth]));
981a3e0fd82Sopenharmony_ci                const Color24 p4 = *(reinterpret_cast<Color24*>(&imgHead[px1 + in.srcLineWidth + in.pixelSize]));
982a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
983a3e0fd82Sopenharmony_ci                // parameters below are Q15 fixed-point number
984a3e0fd82Sopenharmony_ci                int64_t decU = FO_DECIMAL(u);
985a3e0fd82Sopenharmony_ci                int64_t decV = FO_DECIMAL(v);
986a3e0fd82Sopenharmony_ci                int64_t decUMinus1 = FIXED_NUM_1 - decU;
987a3e0fd82Sopenharmony_ci                int64_t decVMinus1 = FIXED_NUM_1 - decV;
988a3e0fd82Sopenharmony_ci                int64_t w1 = FO_MUL(decUMinus1, decVMinus1);
989a3e0fd82Sopenharmony_ci                int64_t w2 = FO_MUL(decU, decVMinus1);
990a3e0fd82Sopenharmony_ci                int64_t w3 = FO_MUL(decUMinus1, decV);
991a3e0fd82Sopenharmony_ci                int64_t w4 = FO_MUL(decU, decV);
992a3e0fd82Sopenharmony_ci                // parameters above are Q15 fixed-point number
993a3e0fd82Sopenharmony_ci#else
994a3e0fd82Sopenharmony_ci                const float decU = u - intU;
995a3e0fd82Sopenharmony_ci                const float decV = v - intV;
996a3e0fd82Sopenharmony_ci                const float decUMinus1 = 1 - decU;
997a3e0fd82Sopenharmony_ci                const float decVMinus1 = 1 - decV;
998a3e0fd82Sopenharmony_ci                const int32_t w1 = static_cast<int32_t>(decUMinus1 * decVMinus1 * 256.0f); // 256:shift 8 bit left
999a3e0fd82Sopenharmony_ci                const int32_t w2 = static_cast<int32_t>(decU * decVMinus1 * 256.0f);       // 256:shift 8 bit left
1000a3e0fd82Sopenharmony_ci                const int32_t w3 = static_cast<int32_t>(decUMinus1 * decV * 256.0f);       // 256:shift 8 bit left
1001a3e0fd82Sopenharmony_ci                const int32_t w4 = static_cast<int32_t>(decU * decV * 256.0f);             // 256:shift 8 bit left
1002a3e0fd82Sopenharmony_ci#endif
1003a3e0fd82Sopenharmony_ci
1004a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1005a3e0fd82Sopenharmony_ci                const int64_t outR =
1006a3e0fd82Sopenharmony_ci                    __SMUAD(p1.red, w1) + __SMUAD(p2.red, w2) + __SMUAD(p3.red, w3) + __SMUAD(p4.red, w4);
1007a3e0fd82Sopenharmony_ci                const int64_t outG =
1008a3e0fd82Sopenharmony_ci                    __SMUAD(p1.green, w1) + __SMUAD(p2.green, w2) + __SMUAD(p3.green, w3) + __SMUAD(p4.green, w4);
1009a3e0fd82Sopenharmony_ci                const int64_t outB =
1010a3e0fd82Sopenharmony_ci                    __SMUAD(p1.blue, w1) + __SMUAD(p2.blue, w2) + __SMUAD(p3.blue, w3) + __SMUAD(p4.blue, w4);
1011a3e0fd82Sopenharmony_ci#else
1012a3e0fd82Sopenharmony_ci                const int64_t outR = p1.red * w1 + p2.red * w2 + p3.red * w3 + p4.red * w4;
1013a3e0fd82Sopenharmony_ci                const int64_t outG = p1.green * w1 + p2.green * w2 + p3.green * w3 + p4.green * w4;
1014a3e0fd82Sopenharmony_ci                const int64_t outB = p1.blue * w1 + p2.blue * w2 + p3.blue * w3 + p4.blue * w4;
1015a3e0fd82Sopenharmony_ci#endif
1016a3e0fd82Sopenharmony_ci
1017a3e0fd82Sopenharmony_ci                Color24 result;
1018a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1019a3e0fd82Sopenharmony_ci                result.red = static_cast<uint8_t>(outR >> FIXED_Q_NUM);
1020a3e0fd82Sopenharmony_ci                result.green = static_cast<uint8_t>(outG >> FIXED_Q_NUM);
1021a3e0fd82Sopenharmony_ci                result.blue = static_cast<uint8_t>(outB >> FIXED_Q_NUM);
1022a3e0fd82Sopenharmony_ci#else
1023a3e0fd82Sopenharmony_ci                result.red = static_cast<uint8_t>(outR >> 8);   // 8:shift 8 bit right
1024a3e0fd82Sopenharmony_ci                result.green = static_cast<uint8_t>(outG >> 8); // 8:shift 8 bit right
1025a3e0fd82Sopenharmony_ci                result.blue = static_cast<uint8_t>(outB >> 8);  // 8:shift 8 bit right
1026a3e0fd82Sopenharmony_ci#endif
1027a3e0fd82Sopenharmony_ci                if (in.opaScale == OPA_OPAQUE) {
1028a3e0fd82Sopenharmony_ci                    COLOR_FILL_COVER(screenBuffer, bufferMode, result.red, result.green, result.blue, RGB888);
1029a3e0fd82Sopenharmony_ci                } else {
1030a3e0fd82Sopenharmony_ci                    COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, RGB888, in.opaScale);
1031a3e0fd82Sopenharmony_ci                }
1032a3e0fd82Sopenharmony_ci            }
1033a3e0fd82Sopenharmony_ci            u += in.init.duHorizon;
1034a3e0fd82Sopenharmony_ci            v += in.init.dvHorizon;
1035a3e0fd82Sopenharmony_ci            screenBuffer += in.bufferPxSize;
1036a3e0fd82Sopenharmony_ci        }
1037a3e0fd82Sopenharmony_ci        StepToNextLine(in.edge1, in.edge2);
1038a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duVertical;
1039a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvVertical;
1040a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1041a3e0fd82Sopenharmony_ci        int16_t deltaX = FO_TO_INTEGER(in.edge1.curX) - xMin;
1042a3e0fd82Sopenharmony_ci#else
1043a3e0fd82Sopenharmony_ci        int16_t deltaX = static_cast<int16_t>(in.edge1.curX) - xMin;
1044a3e0fd82Sopenharmony_ci#endif
1045a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * deltaX;
1046a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * deltaX;
1047a3e0fd82Sopenharmony_ci    }
1048a3e0fd82Sopenharmony_ci}
1049a3e0fd82Sopenharmony_ci
1050a3e0fd82Sopenharmony_ci#if !ENABLE_FIXED_POINT
1051a3e0fd82Sopenharmony_cistatic void DrawTriangleTrueColorBilinear8888Inner(const TriangleScanInfo& in,
1052a3e0fd82Sopenharmony_ci                                                   uint8_t* screenBuffer,
1053a3e0fd82Sopenharmony_ci                                                   int16_t len,
1054a3e0fd82Sopenharmony_ci                                                   const ColorMode bufferMode,
1055a3e0fd82Sopenharmony_ci                                                   float u,
1056a3e0fd82Sopenharmony_ci                                                   float v)
1057a3e0fd82Sopenharmony_ci{
1058a3e0fd82Sopenharmony_ci    for (int16_t x = 0; x < len; ++x) {
1059a3e0fd82Sopenharmony_ci        const int16_t intU = static_cast<int16_t>(u);
1060a3e0fd82Sopenharmony_ci        const int16_t intV = static_cast<int16_t>(v);
1061a3e0fd82Sopenharmony_ci        if ((u >= 0) && (intU < in.info.header.width - 1) && (v >= 0) && (intV < in.info.header.height - 1)) {
1062a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1063a3e0fd82Sopenharmony_ci            uint32_t val1 = __SMUAD(intV, in.srcLineWidth);
1064a3e0fd82Sopenharmony_ci            uint32_t val2 = __SMUAD(intU, in.pixelSize);
1065a3e0fd82Sopenharmony_ci            uint32_t px1 = val1 + val2;
1066a3e0fd82Sopenharmony_ci#else
1067a3e0fd82Sopenharmony_ci            uint32_t px1 = intV * in.srcLineWidth + intU * in.pixelSize;
1068a3e0fd82Sopenharmony_ci#endif
1069a3e0fd82Sopenharmony_ci            uint8_t* imgHead = const_cast<uint8_t*>(in.info.data);
1070a3e0fd82Sopenharmony_ci            const ColorType p1 = *(reinterpret_cast<ColorType*>(&imgHead[px1]));
1071a3e0fd82Sopenharmony_ci            const ColorType p2 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.pixelSize]));
1072a3e0fd82Sopenharmony_ci            const ColorType p3 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.srcLineWidth]));
1073a3e0fd82Sopenharmony_ci            const ColorType p4 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.srcLineWidth + in.pixelSize]));
1074a3e0fd82Sopenharmony_ci
1075a3e0fd82Sopenharmony_ci            const float decU = u - intU;
1076a3e0fd82Sopenharmony_ci            const float decV = v - intV;
1077a3e0fd82Sopenharmony_ci            const float decUMinus1 = 1 - decU;
1078a3e0fd82Sopenharmony_ci            const float decVMinus1 = 1 - decV;
1079a3e0fd82Sopenharmony_ci
1080a3e0fd82Sopenharmony_ci            const int32_t w1 = static_cast<int32_t>(decUMinus1 * decVMinus1 * 256.0f); // 256:shift 8 bit left
1081a3e0fd82Sopenharmony_ci            const int32_t w2 = static_cast<int32_t>(decU * decVMinus1 * 256.0f);       // 256:shift 8 bit left
1082a3e0fd82Sopenharmony_ci            const int32_t w3 = static_cast<int32_t>(decUMinus1 * decV * 256.0f);       // 256:shift 8 bit left
1083a3e0fd82Sopenharmony_ci            const int32_t w4 = static_cast<int32_t>(decU * decV * 256.0f);             // 256:shift 8 bit left
1084a3e0fd82Sopenharmony_ci
1085a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1086a3e0fd82Sopenharmony_ci            const int32_t outR = __SMUAD(p1.red, w1) + __SMUAD(p2.red, w2) + __SMUAD(p3.red, w3) + __SMUAD(p4.red, w4);
1087a3e0fd82Sopenharmony_ci            const int32_t outG =
1088a3e0fd82Sopenharmony_ci                __SMUAD(p1.green, w1) + __SMUAD(p2.green, w2) + __SMUAD(p3.green, w3) + __SMUAD(p4.green, w4);
1089a3e0fd82Sopenharmony_ci            const int32_t outB =
1090a3e0fd82Sopenharmony_ci                __SMUAD(p1.blue, w1) + __SMUAD(p2.blue, w2) + __SMUAD(p3.blue, w3) + __SMUAD(p4.blue, w4);
1091a3e0fd82Sopenharmony_ci            const int32_t outA =
1092a3e0fd82Sopenharmony_ci                __SMUAD(p1.alpha, w1) + __SMUAD(p2.alpha, w2) + __SMUAD(p3.alpha, w3) + __SMUAD(p4.alpha, w4);
1093a3e0fd82Sopenharmony_ci#else
1094a3e0fd82Sopenharmony_ci            const int32_t outR = p1.red * w1 + p2.red * w2 + p3.red * w3 + p4.red * w4;
1095a3e0fd82Sopenharmony_ci            const int32_t outG = p1.green * w1 + p2.green * w2 + p3.green * w3 + p4.green * w4;
1096a3e0fd82Sopenharmony_ci            const int32_t outB = p1.blue * w1 + p2.blue * w2 + p3.blue * w3 + p4.blue * w4;
1097a3e0fd82Sopenharmony_ci            const int32_t outA = p1.alpha * w1 + p2.alpha * w2 + p3.alpha * w3 + p4.alpha * w4;
1098a3e0fd82Sopenharmony_ci#endif
1099a3e0fd82Sopenharmony_ci
1100a3e0fd82Sopenharmony_ci            Color32 result;
1101a3e0fd82Sopenharmony_ci            result.red = static_cast<uint8_t>(outR >> 8);   // 8:shift 8 bit right
1102a3e0fd82Sopenharmony_ci            result.green = static_cast<uint8_t>(outG >> 8); // 8:shift 8 bit right
1103a3e0fd82Sopenharmony_ci            result.blue = static_cast<uint8_t>(outB >> 8);  // 8:shift 8 bit right
1104a3e0fd82Sopenharmony_ci            result.alpha = static_cast<uint8_t>(outA >> 8); // 8:shift 8 bit right
1105a3e0fd82Sopenharmony_ci            if ((in.opaScale == OPA_OPAQUE) && (result.alpha == OPA_OPAQUE)) {
1106a3e0fd82Sopenharmony_ci                COLOR_FILL_COVER(screenBuffer, bufferMode, result.red, result.green, result.blue, ARGB8888);
1107a3e0fd82Sopenharmony_ci            } else {
1108a3e0fd82Sopenharmony_ci                COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, in.opaScale);
1109a3e0fd82Sopenharmony_ci            }
1110a3e0fd82Sopenharmony_ci        }
1111a3e0fd82Sopenharmony_ci        u += in.init.duHorizon;
1112a3e0fd82Sopenharmony_ci        v += in.init.dvHorizon;
1113a3e0fd82Sopenharmony_ci        screenBuffer += in.bufferPxSize;
1114a3e0fd82Sopenharmony_ci    }
1115a3e0fd82Sopenharmony_ci}
1116a3e0fd82Sopenharmony_ci#endif
1117a3e0fd82Sopenharmony_ci
1118a3e0fd82Sopenharmony_ci#if defined(ENABLE_FIXED_POINT) && ENABLE_FIXED_POINT
1119a3e0fd82Sopenharmony_cistatic void DrawFixedTriangleTrueColorBilinear8888Inner(const TriangleScanInfo& in,
1120a3e0fd82Sopenharmony_ci                                                        uint8_t* screenBuffer,
1121a3e0fd82Sopenharmony_ci                                                        int16_t len,
1122a3e0fd82Sopenharmony_ci                                                        const ColorMode bufferMode,
1123a3e0fd82Sopenharmony_ci                                                        int64_t u,
1124a3e0fd82Sopenharmony_ci                                                        int64_t v)
1125a3e0fd82Sopenharmony_ci{
1126a3e0fd82Sopenharmony_ci    for (int16_t x = 0; x < len; ++x) {
1127a3e0fd82Sopenharmony_ci        int16_t intU = FO_TO_INTEGER(u);
1128a3e0fd82Sopenharmony_ci        int16_t intV = FO_TO_INTEGER(v);
1129a3e0fd82Sopenharmony_ci        if ((u >= 0) && (intU < in.info.header.width - 1) && (v >= 0) && (intV < in.info.header.height - 1)) {
1130a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1131a3e0fd82Sopenharmony_ci            uint32_t val1 = __SMUAD(intV, in.srcLineWidth);
1132a3e0fd82Sopenharmony_ci            uint32_t val2 = __SMUAD(intU, in.pixelSize);
1133a3e0fd82Sopenharmony_ci            uint32_t px1 = val1 + val2;
1134a3e0fd82Sopenharmony_ci#else
1135a3e0fd82Sopenharmony_ci            uint32_t px1 = intV * in.srcLineWidth + intU * in.pixelSize;
1136a3e0fd82Sopenharmony_ci#endif
1137a3e0fd82Sopenharmony_ci            uint8_t* imgHead = const_cast<uint8_t*>(in.info.data);
1138a3e0fd82Sopenharmony_ci            const ColorType p1 = *(reinterpret_cast<ColorType*>(&imgHead[px1]));
1139a3e0fd82Sopenharmony_ci            const ColorType p2 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.pixelSize]));
1140a3e0fd82Sopenharmony_ci            const ColorType p3 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.srcLineWidth]));
1141a3e0fd82Sopenharmony_ci            const ColorType p4 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.srcLineWidth + in.pixelSize]));
1142a3e0fd82Sopenharmony_ci
1143a3e0fd82Sopenharmony_ci            // parameters below are Q15 fixed-point number
1144a3e0fd82Sopenharmony_ci            int64_t decU = FO_DECIMAL(u);
1145a3e0fd82Sopenharmony_ci            int64_t decV = FO_DECIMAL(v);
1146a3e0fd82Sopenharmony_ci            int64_t decUMinus1 = FIXED_NUM_1 - decU;
1147a3e0fd82Sopenharmony_ci            int64_t decVMinus1 = FIXED_NUM_1 - decV;
1148a3e0fd82Sopenharmony_ci            int64_t w1 = FO_MUL(decUMinus1, decVMinus1);
1149a3e0fd82Sopenharmony_ci            int64_t w2 = FO_MUL(decU, decVMinus1);
1150a3e0fd82Sopenharmony_ci            int64_t w3 = FO_MUL(decUMinus1, decV);
1151a3e0fd82Sopenharmony_ci            int64_t w4 = FO_MUL(decU, decV);
1152a3e0fd82Sopenharmony_ci            // parameters above are Q15 fixed-point number
1153a3e0fd82Sopenharmony_ci
1154a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1155a3e0fd82Sopenharmony_ci            const int64_t outR = __SMUAD(p1.red, w1) + __SMUAD(p2.red, w2) + __SMUAD(p3.red, w3) + __SMUAD(p4.red, w4);
1156a3e0fd82Sopenharmony_ci            const int64_t outG =
1157a3e0fd82Sopenharmony_ci                __SMUAD(p1.green, w1) + __SMUAD(p2.green, w2) + __SMUAD(p3.green, w3) + __SMUAD(p4.green, w4);
1158a3e0fd82Sopenharmony_ci            const int64_t outB =
1159a3e0fd82Sopenharmony_ci                __SMUAD(p1.blue, w1) + __SMUAD(p2.blue, w2) + __SMUAD(p3.blue, w3) + __SMUAD(p4.blue, w4);
1160a3e0fd82Sopenharmony_ci            const int64_t outA =
1161a3e0fd82Sopenharmony_ci                __SMUAD(p1.alpha, w1) + __SMUAD(p2.alpha, w2) + __SMUAD(p3.alpha, w3) + __SMUAD(p4.alpha, w4);
1162a3e0fd82Sopenharmony_ci#else
1163a3e0fd82Sopenharmony_ci            const int64_t outR = p1.red * w1 + p2.red * w2 + p3.red * w3 + p4.red * w4;
1164a3e0fd82Sopenharmony_ci            const int64_t outG = p1.green * w1 + p2.green * w2 + p3.green * w3 + p4.green * w4;
1165a3e0fd82Sopenharmony_ci            const int64_t outB = p1.blue * w1 + p2.blue * w2 + p3.blue * w3 + p4.blue * w4;
1166a3e0fd82Sopenharmony_ci            const int64_t outA = p1.alpha * w1 + p2.alpha * w2 + p3.alpha * w3 + p4.alpha * w4;
1167a3e0fd82Sopenharmony_ci#endif
1168a3e0fd82Sopenharmony_ci
1169a3e0fd82Sopenharmony_ci            Color32 result;
1170a3e0fd82Sopenharmony_ci            result.red = static_cast<uint8_t>(outR >> FIXED_Q_NUM);
1171a3e0fd82Sopenharmony_ci            result.green = static_cast<uint8_t>(outG >> FIXED_Q_NUM);
1172a3e0fd82Sopenharmony_ci            result.blue = static_cast<uint8_t>(outB >> FIXED_Q_NUM);
1173a3e0fd82Sopenharmony_ci            result.alpha = static_cast<uint8_t>(outA >> FIXED_Q_NUM);
1174a3e0fd82Sopenharmony_ci            if ((in.opaScale == OPA_OPAQUE) && (result.alpha == OPA_OPAQUE)) {
1175a3e0fd82Sopenharmony_ci                COLOR_FILL_COVER(screenBuffer, bufferMode, result.red, result.green, result.blue, ARGB8888);
1176a3e0fd82Sopenharmony_ci            } else {
1177a3e0fd82Sopenharmony_ci                COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, in.opaScale);
1178a3e0fd82Sopenharmony_ci            }
1179a3e0fd82Sopenharmony_ci        }
1180a3e0fd82Sopenharmony_ci        u += in.init.duHorizon;
1181a3e0fd82Sopenharmony_ci        v += in.init.dvHorizon;
1182a3e0fd82Sopenharmony_ci        screenBuffer += in.bufferPxSize;
1183a3e0fd82Sopenharmony_ci    }
1184a3e0fd82Sopenharmony_ci}
1185a3e0fd82Sopenharmony_ci#endif
1186a3e0fd82Sopenharmony_ci
1187a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
1188a3e0fd82Sopenharmony_cistatic void DrawTriangleTrueColorBilinear8888InnerNeon(const TriangleScanInfo& in,
1189a3e0fd82Sopenharmony_ci                                                       uint8_t* screenBuffer,
1190a3e0fd82Sopenharmony_ci                                                       int16_t len,
1191a3e0fd82Sopenharmony_ci                                                       float u,
1192a3e0fd82Sopenharmony_ci                                                       float v,
1193a3e0fd82Sopenharmony_ci                                                       NeonBlendPipeLine& pipeLine,
1194a3e0fd82Sopenharmony_ci                                                       const ColorMode bufferMode)
1195a3e0fd82Sopenharmony_ci{
1196a3e0fd82Sopenharmony_ci    ColorType arrayp1[NEON_STEP_8] = {};
1197a3e0fd82Sopenharmony_ci    ColorType arrayp2[NEON_STEP_8] = {};
1198a3e0fd82Sopenharmony_ci    ColorType arrayp3[NEON_STEP_8] = {};
1199a3e0fd82Sopenharmony_ci    ColorType arrayp4[NEON_STEP_8] = {};
1200a3e0fd82Sopenharmony_ci    float arrayU[NEON_STEP_8] = {0};
1201a3e0fd82Sopenharmony_ci    float arrayV[NEON_STEP_8] = {0};
1202a3e0fd82Sopenharmony_ci    int32_t arrayPx1[NEON_STEP_8] = {0};
1203a3e0fd82Sopenharmony_ci    int16_t step = in.bufferPxSize * NEON_STEP_8;
1204a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1205a3e0fd82Sopenharmony_ci    float duHorizon = static_cast<float>(in.init.duHorizon) / FIXED_NUM_1;
1206a3e0fd82Sopenharmony_ci    float dvHorizon = static_cast<float>(in.init.dvHorizon) / FIXED_NUM_1;
1207a3e0fd82Sopenharmony_ci#endif
1208a3e0fd82Sopenharmony_ci    while (len >= NEON_STEP_8) {
1209a3e0fd82Sopenharmony_ci        for (uint32_t i = 0; i < NEON_STEP_8; ++i) {
1210a3e0fd82Sopenharmony_ci            arrayU[i] = u;
1211a3e0fd82Sopenharmony_ci            arrayV[i] = v;
1212a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1213a3e0fd82Sopenharmony_ci            u += duHorizon;
1214a3e0fd82Sopenharmony_ci            v += dvHorizon;
1215a3e0fd82Sopenharmony_ci#else
1216a3e0fd82Sopenharmony_ci            u += in.init.duHorizon;
1217a3e0fd82Sopenharmony_ci            v += in.init.dvHorizon;
1218a3e0fd82Sopenharmony_ci#endif
1219a3e0fd82Sopenharmony_ci        }
1220a3e0fd82Sopenharmony_ci        // Monotonically increasing or decreasing, so only judge the beginning and end.
1221a3e0fd82Sopenharmony_ci        if ((arrayU[0] >= 0) && (arrayU[0] < in.info.header.width - 1) && (arrayV[0] >= 0) &&
1222a3e0fd82Sopenharmony_ci            (arrayV[0] < in.info.header.height - 1) && (arrayU[NEON_STEP_8 - 1] >= 0) &&
1223a3e0fd82Sopenharmony_ci            (arrayU[NEON_STEP_8 - 1] < in.info.header.width - 1) && (arrayV[NEON_STEP_8 - 1] >= 0) &&
1224a3e0fd82Sopenharmony_ci            (arrayV[NEON_STEP_8 - 1] < in.info.header.height - 1)) {
1225a3e0fd82Sopenharmony_ci            // Process the lower half of arrayU and arrayV
1226a3e0fd82Sopenharmony_ci            float32x4_t vU = vld1q_f32(arrayU);
1227a3e0fd82Sopenharmony_ci            float32x4_t vV = vld1q_f32(arrayV);
1228a3e0fd82Sopenharmony_ci            int32x4_t vIntU = vcvtq_s32_f32(vU);
1229a3e0fd82Sopenharmony_ci            int32x4_t vIntV = vcvtq_s32_f32(vV);
1230a3e0fd82Sopenharmony_ci            int32x4_t vPx1 =
1231a3e0fd82Sopenharmony_ci                vaddq_s32(vmulq_s32(vIntV, vdupq_n_s32(in.srcLineWidth)), vmulq_s32(vIntU, vdupq_n_s32(in.pixelSize)));
1232a3e0fd82Sopenharmony_ci            vst1q_s32(arrayPx1, vPx1);
1233a3e0fd82Sopenharmony_ci            float32x4_t vDecU = vsubq_f32(vU, vcvtq_f32_s32(vIntU));
1234a3e0fd82Sopenharmony_ci            float32x4_t vDecV = vsubq_f32(vV, vcvtq_f32_s32(vIntV));
1235a3e0fd82Sopenharmony_ci            float32x4_t vDecUMinus1 = vsubq_f32(vdupq_n_f32(1.0), vDecU);
1236a3e0fd82Sopenharmony_ci            float32x4_t vDecVMinus1 = vsubq_f32(vdupq_n_f32(1.0), vDecV);
1237a3e0fd82Sopenharmony_ci            // 256:shift 8 bit left
1238a3e0fd82Sopenharmony_ci            uint32x4_t vLowW1 = vcvtq_u32_f32(vmulq_f32(vmulq_f32(vDecUMinus1, vDecVMinus1), vdupq_n_f32(256.0)));
1239a3e0fd82Sopenharmony_ci            uint32x4_t vLowW2 = vcvtq_u32_f32(vmulq_f32(vmulq_f32(vDecU, vDecVMinus1), vdupq_n_f32(256.0)));
1240a3e0fd82Sopenharmony_ci            uint32x4_t vLowW3 = vcvtq_u32_f32(vmulq_f32(vmulq_f32(vDecUMinus1, vDecV), vdupq_n_f32(256.0)));
1241a3e0fd82Sopenharmony_ci            uint32x4_t vLowW4 = vcvtq_u32_f32(vmulq_f32(vmulq_f32(vDecU, vDecV), vdupq_n_f32(256.0)));
1242a3e0fd82Sopenharmony_ci            // Process the higher half of arrayU and arrayV
1243a3e0fd82Sopenharmony_ci            vU = vld1q_f32(arrayU + NEON_STEP_4);
1244a3e0fd82Sopenharmony_ci            vV = vld1q_f32(arrayV + NEON_STEP_4);
1245a3e0fd82Sopenharmony_ci            vIntU = vcvtq_s32_f32(vU);
1246a3e0fd82Sopenharmony_ci            vIntV = vcvtq_s32_f32(vV);
1247a3e0fd82Sopenharmony_ci            vPx1 =
1248a3e0fd82Sopenharmony_ci                vaddq_s32(vmulq_s32(vIntV, vdupq_n_s32(in.srcLineWidth)), vmulq_s32(vIntU, vdupq_n_s32(in.pixelSize)));
1249a3e0fd82Sopenharmony_ci            vst1q_s32(arrayPx1 + NEON_STEP_4, vPx1);
1250a3e0fd82Sopenharmony_ci            vDecU = vsubq_f32(vU, vcvtq_f32_s32(vIntU));
1251a3e0fd82Sopenharmony_ci            vDecV = vsubq_f32(vV, vcvtq_f32_s32(vIntV));
1252a3e0fd82Sopenharmony_ci            vDecUMinus1 = vsubq_f32(vdupq_n_f32(1.0), vDecU);
1253a3e0fd82Sopenharmony_ci            vDecVMinus1 = vsubq_f32(vdupq_n_f32(1.0), vDecV);
1254a3e0fd82Sopenharmony_ci            // 256:shift 8 bit left
1255a3e0fd82Sopenharmony_ci            uint32x4_t vHighW1 = vcvtq_u32_f32(vmulq_f32(vmulq_f32(vDecUMinus1, vDecVMinus1), vdupq_n_f32(256.0)));
1256a3e0fd82Sopenharmony_ci            uint32x4_t vHighW2 = vcvtq_u32_f32(vmulq_f32(vmulq_f32(vDecU, vDecVMinus1), vdupq_n_f32(256.0)));
1257a3e0fd82Sopenharmony_ci            uint32x4_t vHighW3 = vcvtq_u32_f32(vmulq_f32(vmulq_f32(vDecUMinus1, vDecV), vdupq_n_f32(256.0)));
1258a3e0fd82Sopenharmony_ci            uint32x4_t vHighW4 = vcvtq_u32_f32(vmulq_f32(vmulq_f32(vDecU, vDecV), vdupq_n_f32(256.0)));
1259a3e0fd82Sopenharmony_ci
1260a3e0fd82Sopenharmony_ci            // joins two uint32x4_t vectors into a uint16x8_t vector
1261a3e0fd82Sopenharmony_ci            uint16x8_t vW1 = vcombine_u16(vmovn_u32(vLowW1), vmovn_u32(vHighW1));
1262a3e0fd82Sopenharmony_ci            uint16x8_t vW2 = vcombine_u16(vmovn_u32(vLowW2), vmovn_u32(vHighW2));
1263a3e0fd82Sopenharmony_ci            uint16x8_t vW3 = vcombine_u16(vmovn_u32(vLowW3), vmovn_u32(vHighW3));
1264a3e0fd82Sopenharmony_ci            uint16x8_t vW4 = vcombine_u16(vmovn_u32(vLowW4), vmovn_u32(vHighW4));
1265a3e0fd82Sopenharmony_ci
1266a3e0fd82Sopenharmony_ci            uint8_t* imgHead = const_cast<uint8_t*>(in.info.data);
1267a3e0fd82Sopenharmony_ci            for (uint32_t i = 0; i < NEON_STEP_8; ++i) {
1268a3e0fd82Sopenharmony_ci                int32_t px1 = arrayPx1[i];
1269a3e0fd82Sopenharmony_ci                arrayp1[i] = *(reinterpret_cast<ColorType*>(&imgHead[px1]));
1270a3e0fd82Sopenharmony_ci                arrayp2[i] = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.pixelSize]));
1271a3e0fd82Sopenharmony_ci                arrayp3[i] = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.srcLineWidth]));
1272a3e0fd82Sopenharmony_ci                arrayp4[i] = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.srcLineWidth + in.pixelSize]));
1273a3e0fd82Sopenharmony_ci            }
1274a3e0fd82Sopenharmony_ci
1275a3e0fd82Sopenharmony_ci            uint8x8x4_t v4p1 = vld4_u8(reinterpret_cast<uint8_t*>(arrayp1));
1276a3e0fd82Sopenharmony_ci            uint8x8x4_t v4p2 = vld4_u8(reinterpret_cast<uint8_t*>(arrayp2));
1277a3e0fd82Sopenharmony_ci            uint8x8x4_t v4p3 = vld4_u8(reinterpret_cast<uint8_t*>(arrayp3));
1278a3e0fd82Sopenharmony_ci            uint8x8x4_t v4p4 = vld4_u8(reinterpret_cast<uint8_t*>(arrayp4));
1279a3e0fd82Sopenharmony_ci            uint8x8_t vOutB =
1280a3e0fd82Sopenharmony_ci                vshrn_n_u16(vmulq_u16(vmovl_u8(v4p1.val[NEON_B]), vW1) + vmulq_u16(vmovl_u8(v4p2.val[NEON_B]), vW2) +
1281a3e0fd82Sopenharmony_ci                                vmulq_u16(vmovl_u8(v4p3.val[NEON_B]), vW3) + vmulq_u16(vmovl_u8(v4p4.val[NEON_B]), vW4),
1282a3e0fd82Sopenharmony_ci                            8); // 8:shift 8 bit right
1283a3e0fd82Sopenharmony_ci            uint8x8_t vOutG =
1284a3e0fd82Sopenharmony_ci                vshrn_n_u16(vmulq_u16(vmovl_u8(v4p1.val[NEON_G]), vW1) + vmulq_u16(vmovl_u8(v4p2.val[NEON_G]), vW2) +
1285a3e0fd82Sopenharmony_ci                                vmulq_u16(vmovl_u8(v4p3.val[NEON_G]), vW3) + vmulq_u16(vmovl_u8(v4p4.val[NEON_G]), vW4),
1286a3e0fd82Sopenharmony_ci                            8); // 8:shift 8 bit right
1287a3e0fd82Sopenharmony_ci            uint8x8_t vOutR =
1288a3e0fd82Sopenharmony_ci                vshrn_n_u16(vmulq_u16(vmovl_u8(v4p1.val[NEON_R]), vW1) + vmulq_u16(vmovl_u8(v4p2.val[NEON_R]), vW2) +
1289a3e0fd82Sopenharmony_ci                                vmulq_u16(vmovl_u8(v4p3.val[NEON_R]), vW3) + vmulq_u16(vmovl_u8(v4p4.val[NEON_R]), vW4),
1290a3e0fd82Sopenharmony_ci                            8); // 8:shift 8 bit right
1291a3e0fd82Sopenharmony_ci            uint8x8_t vOutA =
1292a3e0fd82Sopenharmony_ci                vshrn_n_u16(vmulq_u16(vmovl_u8(v4p1.val[NEON_A]), vW1) + vmulq_u16(vmovl_u8(v4p2.val[NEON_A]), vW2) +
1293a3e0fd82Sopenharmony_ci                                vmulq_u16(vmovl_u8(v4p3.val[NEON_A]), vW3) + vmulq_u16(vmovl_u8(v4p4.val[NEON_A]), vW4),
1294a3e0fd82Sopenharmony_ci                            8); // 8:shift 8 bit right
1295a3e0fd82Sopenharmony_ci            vOutA = NeonMulDiv255(vdup_n_u8(in.opaScale), vOutA);
1296a3e0fd82Sopenharmony_ci            pipeLine.Invoke(screenBuffer, vOutR, vOutG, vOutB, vOutA);
1297a3e0fd82Sopenharmony_ci        } else {
1298a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1299a3e0fd82Sopenharmony_ci            int64_t fixedU = FO_TRANS_FLOAT_TO_FIXED(arrayU[0]);
1300a3e0fd82Sopenharmony_ci            int64_t fixedV = FO_TRANS_FLOAT_TO_FIXED(arrayV[0]);
1301a3e0fd82Sopenharmony_ci            DrawFixedTriangleTrueColorBilinear8888Inner(in, screenBuffer, NEON_STEP_8, bufferMode, fixedU, fixedV);
1302a3e0fd82Sopenharmony_ci#else
1303a3e0fd82Sopenharmony_ci            DrawTriangleTrueColorBilinear8888Inner(in, screenBuffer, NEON_STEP_8, bufferMode, arrayU[0], arrayV[0]);
1304a3e0fd82Sopenharmony_ci#endif
1305a3e0fd82Sopenharmony_ci        }
1306a3e0fd82Sopenharmony_ci        screenBuffer += step;
1307a3e0fd82Sopenharmony_ci        len -= NEON_STEP_8;
1308a3e0fd82Sopenharmony_ci    }
1309a3e0fd82Sopenharmony_ci    if (len > 0) {
1310a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1311a3e0fd82Sopenharmony_ci        int64_t fixedU = FO_TRANS_FLOAT_TO_FIXED(u);
1312a3e0fd82Sopenharmony_ci        int64_t fixedV = FO_TRANS_FLOAT_TO_FIXED(v);
1313a3e0fd82Sopenharmony_ci        DrawFixedTriangleTrueColorBilinear8888Inner(in, screenBuffer, len, bufferMode, fixedU, fixedV);
1314a3e0fd82Sopenharmony_ci#else
1315a3e0fd82Sopenharmony_ci        DrawTriangleTrueColorBilinear8888Inner(in, screenBuffer, len, bufferMode, u, v);
1316a3e0fd82Sopenharmony_ci#endif
1317a3e0fd82Sopenharmony_ci    }
1318a3e0fd82Sopenharmony_ci}
1319a3e0fd82Sopenharmony_ci#endif
1320a3e0fd82Sopenharmony_ci
1321a3e0fd82Sopenharmony_civoid DrawUtils::Draw3DTriangleTrueColorBilinear8888(const TriangleScanInfo& in, const ColorMode bufferMode)
1322a3e0fd82Sopenharmony_ci{
1323a3e0fd82Sopenharmony_ci    int16_t maskLeft = in.mask.GetLeft();
1324a3e0fd82Sopenharmony_ci    int16_t maskRight = in.mask.GetRight();
1325a3e0fd82Sopenharmony_ci    int16_t xMinErr = 0;
1326a3e0fd82Sopenharmony_ci    int16_t xMaxErr = 0;
1327a3e0fd82Sopenharmony_ci    GetXAxisErrForJunctionLine(in.ignoreJunctionPoint, in.isRightPart, xMinErr, xMaxErr);
1328a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1329a3e0fd82Sopenharmony_ci    int64_t invMatrix00 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[0]);
1330a3e0fd82Sopenharmony_ci    int64_t invMatrix01 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[1]);
1331a3e0fd82Sopenharmony_ci    int64_t invMatrix02 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[2]);
1332a3e0fd82Sopenharmony_ci    int64_t invMatrix20 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[3]);
1333a3e0fd82Sopenharmony_ci    int64_t invMatrix21 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[4]);
1334a3e0fd82Sopenharmony_ci    int64_t invMatrix22 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[5]);
1335a3e0fd82Sopenharmony_ci    int64_t invMatrix30 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[6]);
1336a3e0fd82Sopenharmony_ci    int64_t invMatrix31 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[7]);
1337a3e0fd82Sopenharmony_ci    int64_t invMatrix32 = FO_TRANS_FLOAT_TO_FIXED(in.matrix.GetData()[8]);
1338a3e0fd82Sopenharmony_ci#else  // ENABLE_FIXED_POINT
1339a3e0fd82Sopenharmony_ci    float invMatrix00 = in.matrix.GetData()[0];
1340a3e0fd82Sopenharmony_ci    float invMatrix01 = in.matrix.GetData()[1];
1341a3e0fd82Sopenharmony_ci    float invMatrix02 = in.matrix.GetData()[2];
1342a3e0fd82Sopenharmony_ci    float invMatrix20 = in.matrix.GetData()[3];
1343a3e0fd82Sopenharmony_ci    float invMatrix21 = in.matrix.GetData()[4];
1344a3e0fd82Sopenharmony_ci    float invMatrix22 = in.matrix.GetData()[5];
1345a3e0fd82Sopenharmony_ci    float invMatrix30 = in.matrix.GetData()[6];
1346a3e0fd82Sopenharmony_ci    float invMatrix31 = in.matrix.GetData()[7];
1347a3e0fd82Sopenharmony_ci    float invMatrix32 = in.matrix.GetData()[8];
1348a3e0fd82Sopenharmony_ci#endif // ENABLE_FIXED_POINT
1349a3e0fd82Sopenharmony_ci    for (int16_t y = in.yMin; y <= in.yMax; ++y) {
1350a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1351a3e0fd82Sopenharmony_ci        int16_t tempV = FO_TO_INTEGER(in.edge1.curX) + xMinErr;
1352a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(tempV, maskLeft);
1353a3e0fd82Sopenharmony_ci        tempV = FO_TO_INTEGER(in.edge2.curX) + xMaxErr;
1354a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(tempV, maskRight);
1355a3e0fd82Sopenharmony_ci#else  // ENABLE_FIXED_POINT
1356a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(static_cast<int16_t>(in.edge1.curX + xMinErr), maskLeft);
1357a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(static_cast<int16_t>(in.edge2.curX + xMaxErr), maskRight);
1358a3e0fd82Sopenharmony_ci#endif // ENABLE_FIXED_POINT
1359a3e0fd82Sopenharmony_ci        uint8_t* screenBuffer = in.screenBuffer + (y * in.screenBufferWidth + xMin) * in.bufferPxSize;
1360a3e0fd82Sopenharmony_ci        // move to current position
1361a3e0fd82Sopenharmony_ci        for (int16_t x = xMin; x <= xMax; x++) {
1362a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1363a3e0fd82Sopenharmony_ci            int64_t w = invMatrix02 * x + invMatrix22 * y + invMatrix32;
1364a3e0fd82Sopenharmony_ci            int64_t u = FO_DIV((invMatrix00 * x + invMatrix20 * y + invMatrix30), w);
1365a3e0fd82Sopenharmony_ci            int64_t v = FO_DIV((invMatrix01 * x + invMatrix21 * y + invMatrix31), w);
1366a3e0fd82Sopenharmony_ci            int16_t intU = FO_TO_INTEGER(u);
1367a3e0fd82Sopenharmony_ci            int16_t intV = FO_TO_INTEGER(v);
1368a3e0fd82Sopenharmony_ci#else  // ENABLE_FIXED_POINT
1369a3e0fd82Sopenharmony_ci            float w = invMatrix02 * x + invMatrix22 * y + invMatrix32;
1370a3e0fd82Sopenharmony_ci            float u = (invMatrix00 * x + invMatrix20 * y + invMatrix30) / w;
1371a3e0fd82Sopenharmony_ci            float v = (invMatrix01 * x + invMatrix21 * y + invMatrix31) / w;
1372a3e0fd82Sopenharmony_ci            int16_t intU = static_cast<int16_t>(u);
1373a3e0fd82Sopenharmony_ci            int16_t intV = static_cast<int16_t>(v);
1374a3e0fd82Sopenharmony_ci#endif // ENABLE_FIXED_POINT
1375a3e0fd82Sopenharmony_ci            if ((u >= 0) && (intU < in.info.header.width - 1) && (v >= 0) && (intV < in.info.header.height - 1)) {
1376a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1377a3e0fd82Sopenharmony_ci                uint32_t val1 = __SMUAD(intV, in.srcLineWidth);
1378a3e0fd82Sopenharmony_ci                uint32_t val2 = __SMUAD(intU, in.pixelSize);
1379a3e0fd82Sopenharmony_ci                uint32_t px1 = val1 + val2;
1380a3e0fd82Sopenharmony_ci#else  // ENABLE_ARM_MATH
1381a3e0fd82Sopenharmony_ci                uint32_t px1 = intV * in.srcLineWidth + intU * in.pixelSize;
1382a3e0fd82Sopenharmony_ci#endif // ENABLE_ARM_MATH
1383a3e0fd82Sopenharmony_ci                uint8_t* imgHead = const_cast<uint8_t*>(in.info.data);
1384a3e0fd82Sopenharmony_ci                const ColorType p1 = *(reinterpret_cast<ColorType*>(&imgHead[px1]));
1385a3e0fd82Sopenharmony_ci                const ColorType p2 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.pixelSize]));
1386a3e0fd82Sopenharmony_ci                const ColorType p3 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.srcLineWidth]));
1387a3e0fd82Sopenharmony_ci                const ColorType p4 = *(reinterpret_cast<ColorType*>(&imgHead[px1 + in.srcLineWidth + in.pixelSize]));
1388a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1389a3e0fd82Sopenharmony_ci                int64_t decU = FO_DECIMAL(u);
1390a3e0fd82Sopenharmony_ci                int64_t decV = FO_DECIMAL(v);
1391a3e0fd82Sopenharmony_ci                int64_t decUMinus1 = FIXED_NUM_1 - decU;
1392a3e0fd82Sopenharmony_ci                int64_t decVMinus1 = FIXED_NUM_1 - decV;
1393a3e0fd82Sopenharmony_ci                int64_t w1 = FO_MUL(decUMinus1, decVMinus1);
1394a3e0fd82Sopenharmony_ci                int64_t w2 = FO_MUL(decU, decVMinus1);
1395a3e0fd82Sopenharmony_ci                int64_t w3 = FO_MUL(decUMinus1, decV);
1396a3e0fd82Sopenharmony_ci                int64_t w4 = FO_MUL(decU, decV);
1397a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1398a3e0fd82Sopenharmony_ci                const int64_t outR =
1399a3e0fd82Sopenharmony_ci                    __SMUAD(p1.red, w1) + __SMUAD(p2.red, w2) + __SMUAD(p3.red, w3) + __SMUAD(p4.red, w4);
1400a3e0fd82Sopenharmony_ci                const int64_t outG =
1401a3e0fd82Sopenharmony_ci                    __SMUAD(p1.green, w1) + __SMUAD(p2.green, w2) + __SMUAD(p3.green, w3) + __SMUAD(p4.green, w4);
1402a3e0fd82Sopenharmony_ci                const int64_t outB =
1403a3e0fd82Sopenharmony_ci                    __SMUAD(p1.blue, w1) + __SMUAD(p2.blue, w2) + __SMUAD(p3.blue, w3) + __SMUAD(p4.blue, w4);
1404a3e0fd82Sopenharmony_ci                const int64_t outA =
1405a3e0fd82Sopenharmony_ci                    __SMUAD(p1.alpha, w1) + __SMUAD(p2.alpha, w2) + __SMUAD(p3.alpha, w3) + __SMUAD(p4.alpha, w4);
1406a3e0fd82Sopenharmony_ci#else
1407a3e0fd82Sopenharmony_ci                const int64_t outR = p1.red * w1 + p2.red * w2 + p3.red * w3 + p4.red * w4;
1408a3e0fd82Sopenharmony_ci                const int64_t outG = p1.green * w1 + p2.green * w2 + p3.green * w3 + p4.green * w4;
1409a3e0fd82Sopenharmony_ci                const int64_t outB = p1.blue * w1 + p2.blue * w2 + p3.blue * w3 + p4.blue * w4;
1410a3e0fd82Sopenharmony_ci                const int64_t outA = p1.alpha * w1 + p2.alpha * w2 + p3.alpha * w3 + p4.alpha * w4;
1411a3e0fd82Sopenharmony_ci#endif
1412a3e0fd82Sopenharmony_ci                Color32 result;
1413a3e0fd82Sopenharmony_ci                result.red = static_cast<uint8_t>(outR >> FIXED_Q_NUM);
1414a3e0fd82Sopenharmony_ci                result.green = static_cast<uint8_t>(outG >> FIXED_Q_NUM);
1415a3e0fd82Sopenharmony_ci                result.blue = static_cast<uint8_t>(outB >> FIXED_Q_NUM);
1416a3e0fd82Sopenharmony_ci                result.alpha = static_cast<uint8_t>(outA >> FIXED_Q_NUM);
1417a3e0fd82Sopenharmony_ci#else // ENABLE_FIXED_POINT
1418a3e0fd82Sopenharmony_ci                const float decU = u - intU;
1419a3e0fd82Sopenharmony_ci                const float decV = v - intV;
1420a3e0fd82Sopenharmony_ci                const float decUMinus1 = 1 - decU;
1421a3e0fd82Sopenharmony_ci                const float decVMinus1 = 1 - decV;
1422a3e0fd82Sopenharmony_ci                const int32_t w1 = static_cast<int32_t>(decUMinus1 * decVMinus1 * 256.0f); // 256:shift 8 bit left
1423a3e0fd82Sopenharmony_ci                const int32_t w2 = static_cast<int32_t>(decU * decVMinus1 * 256.0f);       // 256:shift 8 bit left
1424a3e0fd82Sopenharmony_ci                const int32_t w3 = static_cast<int32_t>(decUMinus1 * decV * 256.0f);       // 256:shift 8 bit left
1425a3e0fd82Sopenharmony_ci                const int32_t w4 = static_cast<int32_t>(decU * decV * 256.0f);
1426a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1427a3e0fd82Sopenharmony_ci                const int32_t outR =
1428a3e0fd82Sopenharmony_ci                    __SMUAD(p1.red, w1) + __SMUAD(p2.red, w2) + __SMUAD(p3.red, w3) + __SMUAD(p4.red, w4);
1429a3e0fd82Sopenharmony_ci                const int32_t outG =
1430a3e0fd82Sopenharmony_ci                    __SMUAD(p1.green, w1) + __SMUAD(p2.green, w2) + __SMUAD(p3.green, w3) + __SMUAD(p4.green, w4);
1431a3e0fd82Sopenharmony_ci                const int32_t outB =
1432a3e0fd82Sopenharmony_ci                    __SMUAD(p1.blue, w1) + __SMUAD(p2.blue, w2) + __SMUAD(p3.blue, w3) + __SMUAD(p4.blue, w4);
1433a3e0fd82Sopenharmony_ci                const int32_t outA =
1434a3e0fd82Sopenharmony_ci                    __SMUAD(p1.alpha, w1) + __SMUAD(p2.alpha, w2) + __SMUAD(p3.alpha, w3) + __SMUAD(p4.alpha, w4);
1435a3e0fd82Sopenharmony_ci#else  // ENABLE_ARM_MATH
1436a3e0fd82Sopenharmony_ci                const int32_t outR = p1.red * w1 + p2.red * w2 + p3.red * w3 + p4.red * w4;
1437a3e0fd82Sopenharmony_ci                const int32_t outG = p1.green * w1 + p2.green * w2 + p3.green * w3 + p4.green * w4;
1438a3e0fd82Sopenharmony_ci                const int32_t outB = p1.blue * w1 + p2.blue * w2 + p3.blue * w3 + p4.blue * w4;
1439a3e0fd82Sopenharmony_ci                const int32_t outA = p1.alpha * w1 + p2.alpha * w2 + p3.alpha * w3 + p4.alpha * w4;
1440a3e0fd82Sopenharmony_ci#endif // ENABLE_ARM_MATH
1441a3e0fd82Sopenharmony_ci                Color32 result;
1442a3e0fd82Sopenharmony_ci                result.red = static_cast<uint8_t>(outR >> 8);   // 8:shift 8 bit right
1443a3e0fd82Sopenharmony_ci                result.green = static_cast<uint8_t>(outG >> 8); // 8:shift 8 bit right
1444a3e0fd82Sopenharmony_ci                result.blue = static_cast<uint8_t>(outB >> 8);  // 8:shift 8 bit right
1445a3e0fd82Sopenharmony_ci                result.alpha = static_cast<uint8_t>(outA >> 8); // 8:shift 8 bit right
1446a3e0fd82Sopenharmony_ci#endif // ENABLE_FIXED_POINT
1447a3e0fd82Sopenharmony_ci                if ((in.opaScale == OPA_OPAQUE) && (result.alpha == OPA_OPAQUE)) {
1448a3e0fd82Sopenharmony_ci                    COLOR_FILL_COVER(screenBuffer, bufferMode, result.red, result.green, result.blue, ARGB8888);
1449a3e0fd82Sopenharmony_ci                } else {
1450a3e0fd82Sopenharmony_ci                    COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, in.opaScale);
1451a3e0fd82Sopenharmony_ci                }
1452a3e0fd82Sopenharmony_ci            }
1453a3e0fd82Sopenharmony_ci            screenBuffer += in.bufferPxSize;
1454a3e0fd82Sopenharmony_ci        }
1455a3e0fd82Sopenharmony_ci        StepToNextLine(in.edge1, in.edge2);
1456a3e0fd82Sopenharmony_ci    }
1457a3e0fd82Sopenharmony_ci}
1458a3e0fd82Sopenharmony_ci
1459a3e0fd82Sopenharmony_civoid DrawUtils::DrawTriangleTrueColorBilinear8888(const TriangleScanInfo& in, const ColorMode bufferMode)
1460a3e0fd82Sopenharmony_ci{
1461a3e0fd82Sopenharmony_ci    int16_t maskLeft = in.mask.GetLeft();
1462a3e0fd82Sopenharmony_ci    int16_t maskRight = in.mask.GetRight();
1463a3e0fd82Sopenharmony_ci    int16_t xMinErr = 0;
1464a3e0fd82Sopenharmony_ci    int16_t xMaxErr = 0;
1465a3e0fd82Sopenharmony_ci    GetXAxisErrForJunctionLine(in.ignoreJunctionPoint, in.isRightPart, xMinErr, xMaxErr);
1466a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
1467a3e0fd82Sopenharmony_ci    NeonBlendPipeLine pipeLine;
1468a3e0fd82Sopenharmony_ci    pipeLine.Construct(bufferMode, ARGB8888);
1469a3e0fd82Sopenharmony_ci#endif
1470a3e0fd82Sopenharmony_ci    for (int16_t y = in.yMin; y <= in.yMax; ++y) {
1471a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1472a3e0fd82Sopenharmony_ci        int16_t tempV = FO_TO_INTEGER(in.edge1.curX) + xMinErr;
1473a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(tempV, maskLeft);
1474a3e0fd82Sopenharmony_ci        tempV = FO_TO_INTEGER(in.edge2.curX) + xMaxErr;
1475a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(tempV, maskRight);
1476a3e0fd82Sopenharmony_ci        int16_t diffX = xMin - FO_TO_INTEGER(in.edge1.curX);
1477a3e0fd82Sopenharmony_ci#else
1478a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(static_cast<int16_t>(in.edge1.curX + xMinErr), maskLeft);
1479a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(static_cast<int16_t>(in.edge2.curX + xMaxErr), maskRight);
1480a3e0fd82Sopenharmony_ci        int16_t diffX = (xMin - static_cast<int32_t>(in.edge1.curX));
1481a3e0fd82Sopenharmony_ci#endif
1482a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * diffX;
1483a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * diffX;
1484a3e0fd82Sopenharmony_ci        uint8_t* screenBuffer = in.screenBuffer + (y * in.screenBufferWidth + xMin) * in.bufferPxSize;
1485a3e0fd82Sopenharmony_ci#ifdef ARM_NEON_OPT
1486a3e0fd82Sopenharmony_ci        {
1487a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1488a3e0fd82Sopenharmony_ci            float u = static_cast<float>(in.init.verticalU) / FIXED_NUM_1;
1489a3e0fd82Sopenharmony_ci            float v = static_cast<float>(in.init.verticalV) / FIXED_NUM_1;
1490a3e0fd82Sopenharmony_ci#else
1491a3e0fd82Sopenharmony_ci            float u = in.init.verticalU;
1492a3e0fd82Sopenharmony_ci            float v = in.init.verticalV;
1493a3e0fd82Sopenharmony_ci#endif
1494a3e0fd82Sopenharmony_ci            DEBUG_PERFORMANCE_TRACE("DrawTriangleTrueColorBilinear8888_neon");
1495a3e0fd82Sopenharmony_ci            DrawTriangleTrueColorBilinear8888InnerNeon(in, screenBuffer, xMax - xMin + 1, u, v, pipeLine, bufferMode);
1496a3e0fd82Sopenharmony_ci        }
1497a3e0fd82Sopenharmony_ci#else
1498a3e0fd82Sopenharmony_ci        {
1499a3e0fd82Sopenharmony_ci            DEBUG_PERFORMANCE_TRACE("DrawTriangleTrueColorBilinear8888");
1500a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1501a3e0fd82Sopenharmony_ci            DrawFixedTriangleTrueColorBilinear8888Inner(in, screenBuffer, xMax - xMin + 1, bufferMode,
1502a3e0fd82Sopenharmony_ci                                                        in.init.verticalU, in.init.verticalV);
1503a3e0fd82Sopenharmony_ci#else
1504a3e0fd82Sopenharmony_ci            DrawTriangleTrueColorBilinear8888Inner(in, screenBuffer, xMax - xMin + 1, bufferMode, in.init.verticalU,
1505a3e0fd82Sopenharmony_ci                                                   in.init.verticalV);
1506a3e0fd82Sopenharmony_ci#endif
1507a3e0fd82Sopenharmony_ci        }
1508a3e0fd82Sopenharmony_ci#endif
1509a3e0fd82Sopenharmony_ci        StepToNextLine(in.edge1, in.edge2);
1510a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duVertical;
1511a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvVertical;
1512a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1513a3e0fd82Sopenharmony_ci        int16_t deltaX = FO_TO_INTEGER(in.edge1.curX) - xMin;
1514a3e0fd82Sopenharmony_ci#else
1515a3e0fd82Sopenharmony_ci        int16_t deltaX = static_cast<int16_t>(in.edge1.curX) - xMin;
1516a3e0fd82Sopenharmony_ci#endif
1517a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * deltaX;
1518a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * deltaX;
1519a3e0fd82Sopenharmony_ci    }
1520a3e0fd82Sopenharmony_ci}
1521a3e0fd82Sopenharmony_ci
1522a3e0fd82Sopenharmony_civoid DrawUtils::DrawTriangleTrueColorNearest(const TriangleScanInfo& in, const ColorMode bufferMode)
1523a3e0fd82Sopenharmony_ci{
1524a3e0fd82Sopenharmony_ci    int16_t maskLeft = in.mask.GetLeft();
1525a3e0fd82Sopenharmony_ci    int16_t maskRight = in.mask.GetRight();
1526a3e0fd82Sopenharmony_ci    int16_t xMinErr = 0;
1527a3e0fd82Sopenharmony_ci    int16_t xMaxErr = 0;
1528a3e0fd82Sopenharmony_ci    GetXAxisErrForJunctionLine(in.ignoreJunctionPoint, in.isRightPart, xMinErr, xMaxErr);
1529a3e0fd82Sopenharmony_ci    for (int16_t y = in.yMin; y <= in.yMax; y++) {
1530a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1531a3e0fd82Sopenharmony_ci        int16_t tempV = FO_TO_INTEGER(in.edge1.curX) + xMinErr;
1532a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(tempV, maskLeft);
1533a3e0fd82Sopenharmony_ci        tempV = FO_TO_INTEGER(in.edge2.curX) + xMaxErr;
1534a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(tempV, maskRight);
1535a3e0fd82Sopenharmony_ci        int16_t diffX = xMin - FO_TO_INTEGER(in.edge1.curX);
1536a3e0fd82Sopenharmony_ci#else
1537a3e0fd82Sopenharmony_ci        int16_t xMin = MATH_MAX(static_cast<int16_t>(in.edge1.curX + xMinErr), maskLeft);
1538a3e0fd82Sopenharmony_ci        int16_t xMax = MATH_MIN(static_cast<int16_t>(in.edge2.curX + xMaxErr), maskRight);
1539a3e0fd82Sopenharmony_ci        int16_t diffX = (xMin - static_cast<int32_t>(in.edge1.curX));
1540a3e0fd82Sopenharmony_ci#endif
1541a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * diffX;
1542a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * diffX;
1543a3e0fd82Sopenharmony_ci        uint8_t* screenBuffer = in.screenBuffer + (y * in.screenBufferWidth + xMin) * in.bufferPxSize;
1544a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1545a3e0fd82Sopenharmony_ci        // parameters below are Q15 fixed-point number
1546a3e0fd82Sopenharmony_ci        int64_t u = in.init.verticalU;
1547a3e0fd82Sopenharmony_ci        int64_t v = in.init.verticalV;
1548a3e0fd82Sopenharmony_ci        // parameters above are Q15 fixed-point number
1549a3e0fd82Sopenharmony_ci#else
1550a3e0fd82Sopenharmony_ci        float u = in.init.verticalU;
1551a3e0fd82Sopenharmony_ci        float v = in.init.verticalV;
1552a3e0fd82Sopenharmony_ci#endif
1553a3e0fd82Sopenharmony_ci        for (int16_t x = xMin; x <= xMax; x++) {
1554a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1555a3e0fd82Sopenharmony_ci            int16_t intU = FO_TO_INTEGER(u);
1556a3e0fd82Sopenharmony_ci            int16_t intV = FO_TO_INTEGER(v);
1557a3e0fd82Sopenharmony_ci            if ((u >= 0) && (intU < (in.info.header.width - 1)) && (v >= 0) && (intV < (in.info.header.height - 1))) {
1558a3e0fd82Sopenharmony_ci#else
1559a3e0fd82Sopenharmony_ci            const int16_t intU = static_cast<int16_t>(u);
1560a3e0fd82Sopenharmony_ci            const int16_t intV = static_cast<int16_t>(v);
1561a3e0fd82Sopenharmony_ci            if ((u >= 0) && (intU < in.info.header.width - 1) && (v >= 0) && (intV < in.info.header.height - 1)) {
1562a3e0fd82Sopenharmony_ci#endif
1563a3e0fd82Sopenharmony_ci#if ENABLE_ARM_MATH
1564a3e0fd82Sopenharmony_ci                uint32_t val1 = __SMUAD(intV, in.srcLineWidth);
1565a3e0fd82Sopenharmony_ci                uint32_t val2 = __SMUAD(intU, in.pixelSize);
1566a3e0fd82Sopenharmony_ci                uint32_t px1 = val1 + val2;
1567a3e0fd82Sopenharmony_ci#else
1568a3e0fd82Sopenharmony_ci                uint32_t px1 = intV * in.srcLineWidth + intU * in.pixelSize;
1569a3e0fd82Sopenharmony_ci#endif
1570a3e0fd82Sopenharmony_ci                uint8_t* imgHead = const_cast<uint8_t*>(in.info.data);
1571a3e0fd82Sopenharmony_ci                OpacityType opa = in.opaScale;
1572a3e0fd82Sopenharmony_ci
1573a3e0fd82Sopenharmony_ci                switch (in.info.header.colorMode) {
1574a3e0fd82Sopenharmony_ci                    case RGB888: {
1575a3e0fd82Sopenharmony_ci                        Color24 p24 = *(reinterpret_cast<Color24*>(&imgHead[px1]));
1576a3e0fd82Sopenharmony_ci                        if (opa == OPA_OPAQUE) {
1577a3e0fd82Sopenharmony_ci                            COLOR_FILL_COVER(screenBuffer, bufferMode, p24.red, p24.green, p24.blue, RGB888);
1578a3e0fd82Sopenharmony_ci                        } else {
1579a3e0fd82Sopenharmony_ci                            COLOR_FILL_BLEND(screenBuffer, bufferMode, &p24, RGB888, opa);
1580a3e0fd82Sopenharmony_ci                        }
1581a3e0fd82Sopenharmony_ci                        break;
1582a3e0fd82Sopenharmony_ci                    }
1583a3e0fd82Sopenharmony_ci                    case RGB565: {
1584a3e0fd82Sopenharmony_ci                        Color16 p16 = *(reinterpret_cast<Color16*>(&imgHead[px1]));
1585a3e0fd82Sopenharmony_ci                        if (opa == OPA_OPAQUE) {
1586a3e0fd82Sopenharmony_ci                            COLOR_FILL_COVER(screenBuffer, bufferMode, p16.red, p16.green, p16.blue, RGB565);
1587a3e0fd82Sopenharmony_ci                        } else {
1588a3e0fd82Sopenharmony_ci                            COLOR_FILL_BLEND(screenBuffer, bufferMode, &p16, RGB565, opa);
1589a3e0fd82Sopenharmony_ci                        }
1590a3e0fd82Sopenharmony_ci                        break;
1591a3e0fd82Sopenharmony_ci                    }
1592a3e0fd82Sopenharmony_ci                    case ARGB8888: {
1593a3e0fd82Sopenharmony_ci                        Color32 p32 = *(reinterpret_cast<Color32*>(&imgHead[px1]));
1594a3e0fd82Sopenharmony_ci                        if ((in.opaScale == OPA_OPAQUE) && (p32.alpha == OPA_OPAQUE)) {
1595a3e0fd82Sopenharmony_ci                            COLOR_FILL_COVER(screenBuffer, bufferMode, p32.red, p32.green, p32.blue, ARGB8888);
1596a3e0fd82Sopenharmony_ci                        } else {
1597a3e0fd82Sopenharmony_ci                            COLOR_FILL_BLEND(screenBuffer, bufferMode, &p32, ARGB8888, in.opaScale);
1598a3e0fd82Sopenharmony_ci                        }
1599a3e0fd82Sopenharmony_ci                        break;
1600a3e0fd82Sopenharmony_ci                    }
1601a3e0fd82Sopenharmony_ci                    case XRGB8888: {
1602a3e0fd82Sopenharmony_ci                        Color32 p32 = *(reinterpret_cast<Color32*>(&imgHead[px1]));
1603a3e0fd82Sopenharmony_ci                        if ((in.opaScale == OPA_OPAQUE) && (p32.alpha == OPA_OPAQUE)) {
1604a3e0fd82Sopenharmony_ci                            COLOR_FILL_COVER(screenBuffer, bufferMode, p32.red, p32.green, p32.blue, XRGB8888);
1605a3e0fd82Sopenharmony_ci                        } else {
1606a3e0fd82Sopenharmony_ci                            COLOR_FILL_BLEND(screenBuffer, bufferMode, &p32, XRGB8888, in.opaScale);
1607a3e0fd82Sopenharmony_ci                        }
1608a3e0fd82Sopenharmony_ci                        break;
1609a3e0fd82Sopenharmony_ci                    }
1610a3e0fd82Sopenharmony_ci                    default:
1611a3e0fd82Sopenharmony_ci                        return;
1612a3e0fd82Sopenharmony_ci                }
1613a3e0fd82Sopenharmony_ci            }
1614a3e0fd82Sopenharmony_ci            u += in.init.duHorizon;
1615a3e0fd82Sopenharmony_ci            v += in.init.dvHorizon;
1616a3e0fd82Sopenharmony_ci            screenBuffer += in.bufferPxSize;
1617a3e0fd82Sopenharmony_ci        }
1618a3e0fd82Sopenharmony_ci        StepToNextLine(in.edge1, in.edge2);
1619a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duVertical;
1620a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvVertical;
1621a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1622a3e0fd82Sopenharmony_ci        int16_t deltaX = FO_TO_INTEGER(in.edge1.curX) - xMin;
1623a3e0fd82Sopenharmony_ci#else
1624a3e0fd82Sopenharmony_ci        int16_t deltaX = static_cast<int16_t>(in.edge1.curX) - xMin;
1625a3e0fd82Sopenharmony_ci#endif
1626a3e0fd82Sopenharmony_ci        in.init.verticalU += in.init.duHorizon * deltaX;
1627a3e0fd82Sopenharmony_ci        in.init.verticalV += in.init.dvHorizon * deltaX;
1628a3e0fd82Sopenharmony_ci    }
1629a3e0fd82Sopenharmony_ci}
1630a3e0fd82Sopenharmony_ci
1631a3e0fd82Sopenharmony_civoid DrawUtils::DrawTriangleTransformPart(BufferInfo& gfxDstBuffer, const TrianglePartInfo& part)
1632a3e0fd82Sopenharmony_ci{
1633a3e0fd82Sopenharmony_ci#if ENABLE_FIXED_POINT
1634a3e0fd82Sopenharmony_ci    // parameters below are Q15 fixed-point number
1635a3e0fd82Sopenharmony_ci    int64_t yMin = FO_TRANS_INTEGER_TO_FIXED(part.yMin);
1636a3e0fd82Sopenharmony_ci    part.edge1.curX += (static_cast<int64_t>(part.edge1.du) * (yMin - part.edge1.curY) / part.edge1.dv);
1637a3e0fd82Sopenharmony_ci    part.edge1.curY = yMin;
1638a3e0fd82Sopenharmony_ci    part.edge2.curX += (static_cast<int64_t>(part.edge2.du) * (yMin - part.edge2.curY) / part.edge2.dv);
1639a3e0fd82Sopenharmony_ci    part.edge2.curY = yMin;
1640a3e0fd82Sopenharmony_ci    Rect line;
1641a3e0fd82Sopenharmony_ci    line.SetLeft(FO_TO_INTEGER(part.edge1.curX));
1642a3e0fd82Sopenharmony_ci    line.SetRight(FO_TO_INTEGER(part.edge1.curX));
1643a3e0fd82Sopenharmony_ci    line.SetTop(FO_TO_INTEGER(part.edge1.curY));
1644a3e0fd82Sopenharmony_ci    line.SetBottom(FO_TO_INTEGER(part.edge1.curY));
1645a3e0fd82Sopenharmony_ci    // parameters above are Q15 fixed-point number
1646a3e0fd82Sopenharmony_ci#else
1647a3e0fd82Sopenharmony_ci    part.edge1.curX += part.edge1.du * (part.yMin - part.edge1.curY) / part.edge1.dv;
1648a3e0fd82Sopenharmony_ci    part.edge1.curY = part.yMin;
1649a3e0fd82Sopenharmony_ci    part.edge2.curX += part.edge2.du * (part.yMin - part.edge2.curY) / part.edge2.dv;
1650a3e0fd82Sopenharmony_ci    part.edge2.curY = part.yMin;
1651a3e0fd82Sopenharmony_ci    Rect line;
1652a3e0fd82Sopenharmony_ci    line.SetLeft(static_cast<int16_t>(part.edge1.curX));
1653a3e0fd82Sopenharmony_ci    line.SetRight(static_cast<int16_t>(part.edge1.curX));
1654a3e0fd82Sopenharmony_ci    line.SetTop(static_cast<int16_t>(part.edge1.curY));
1655a3e0fd82Sopenharmony_ci    line.SetBottom(static_cast<int16_t>(part.edge1.curY));
1656a3e0fd82Sopenharmony_ci#endif
1657a3e0fd82Sopenharmony_ci    TransformInitState init;
1658a3e0fd82Sopenharmony_ci    GetTransformInitState(part.transMap, part.position, line, init);
1659a3e0fd82Sopenharmony_ci
1660a3e0fd82Sopenharmony_ci    uint8_t* screenBuffer = static_cast<uint8_t*>(gfxDstBuffer.virAddr);
1661a3e0fd82Sopenharmony_ci    if (screenBuffer == nullptr) {
1662a3e0fd82Sopenharmony_ci        return;
1663a3e0fd82Sopenharmony_ci    }
1664a3e0fd82Sopenharmony_ci    GetInstance()->SetFucInfo(gfxDstBuffer, part, screenBuffer, init);
1665a3e0fd82Sopenharmony_ci}
1666a3e0fd82Sopenharmony_ci
1667a3e0fd82Sopenharmony_civoid DrawUtils::SetFucInfo(BufferInfo& gfxDstBuffer, const TrianglePartInfo& part,
1668a3e0fd82Sopenharmony_ci                           uint8_t* screenBuffer, TransformInitState& init)
1669a3e0fd82Sopenharmony_ci{
1670a3e0fd82Sopenharmony_ci    ColorMode bufferMode = gfxDstBuffer.mode;
1671a3e0fd82Sopenharmony_ci    uint8_t bufferPxSize = GetByteSizeByColorMode(bufferMode);
1672a3e0fd82Sopenharmony_ci
1673a3e0fd82Sopenharmony_ci    uint8_t pixelSize;
1674a3e0fd82Sopenharmony_ci    DrawTriangleTransformFuc fuc;
1675a3e0fd82Sopenharmony_ci    bool isTrueColor = (part.info.header.colorMode == ARGB8888) || (part.info.header.colorMode == RGB888) ||
1676a3e0fd82Sopenharmony_ci                       (part.info.header.colorMode == RGB565) || (part.info.header.colorMode == XRGB8888);
1677a3e0fd82Sopenharmony_ci    if (isTrueColor) {
1678a3e0fd82Sopenharmony_ci        pixelSize = part.info.pxSize >> SHIFT_3;
1679a3e0fd82Sopenharmony_ci        if (part.info.algorithm == TransformAlgorithm::NEAREST_NEIGHBOR) {
1680a3e0fd82Sopenharmony_ci            fuc = DrawTriangleTrueColorNearest;
1681a3e0fd82Sopenharmony_ci        } else if (part.info.header.colorMode == ARGB8888 || part.info.header.colorMode == XRGB8888) {
1682a3e0fd82Sopenharmony_ci            if (part.transMap.Is3DTransform()) {
1683a3e0fd82Sopenharmony_ci                fuc = Draw3DTriangleTrueColorBilinear8888;
1684a3e0fd82Sopenharmony_ci            } else {
1685a3e0fd82Sopenharmony_ci                fuc = DrawTriangleTrueColorBilinear8888;
1686a3e0fd82Sopenharmony_ci            }
1687a3e0fd82Sopenharmony_ci        } else if (part.info.header.colorMode == RGB888) {
1688a3e0fd82Sopenharmony_ci            fuc = DrawTriangleTrueColorBilinear888;
1689a3e0fd82Sopenharmony_ci        } else {
1690a3e0fd82Sopenharmony_ci            fuc = DrawTriangleTrueColorBilinear565;
1691a3e0fd82Sopenharmony_ci        }
1692a3e0fd82Sopenharmony_ci    } else {
1693a3e0fd82Sopenharmony_ci        pixelSize = part.info.pxSize;
1694a3e0fd82Sopenharmony_ci        fuc = DrawTriangleAlphaBilinear;
1695a3e0fd82Sopenharmony_ci    }
1696a3e0fd82Sopenharmony_ci    const int32_t srcLineWidth = part.info.header.width * pixelSize;
1697a3e0fd82Sopenharmony_ci    TriangleScanInfo input{part.yMin,
1698a3e0fd82Sopenharmony_ci                           part.yMax,
1699a3e0fd82Sopenharmony_ci                           part.edge1,
1700a3e0fd82Sopenharmony_ci                           part.edge2,
1701a3e0fd82Sopenharmony_ci                           screenBuffer,
1702a3e0fd82Sopenharmony_ci                           bufferPxSize,
1703a3e0fd82Sopenharmony_ci                           part.color,
1704a3e0fd82Sopenharmony_ci                           part.opaScale,
1705a3e0fd82Sopenharmony_ci                           init,
1706a3e0fd82Sopenharmony_ci                           gfxDstBuffer.width,
1707a3e0fd82Sopenharmony_ci                           pixelSize,
1708a3e0fd82Sopenharmony_ci                           srcLineWidth,
1709a3e0fd82Sopenharmony_ci                           part.info,
1710a3e0fd82Sopenharmony_ci                           part.mask,
1711a3e0fd82Sopenharmony_ci                           part.isRightPart,
1712a3e0fd82Sopenharmony_ci                           part.ignoreJunctionPoint,
1713a3e0fd82Sopenharmony_ci                           part.transMap.invMatrix_};
1714a3e0fd82Sopenharmony_ci    fuc(input, gfxDstBuffer.mode);
1715a3e0fd82Sopenharmony_ci}
1716a3e0fd82Sopenharmony_ci
1717a3e0fd82Sopenharmony_civoid DrawUtils::DrawTriangleTransform(BufferInfo& gfxDstBuffer,
1718a3e0fd82Sopenharmony_ci                                      const Rect& mask,
1719a3e0fd82Sopenharmony_ci                                      const Point& position,
1720a3e0fd82Sopenharmony_ci                                      const ColorType& color,
1721a3e0fd82Sopenharmony_ci                                      OpacityType opaScale,
1722a3e0fd82Sopenharmony_ci                                      const TransformMap& transMap,
1723a3e0fd82Sopenharmony_ci                                      const TriangleTransformDataInfo& triangleInfo)
1724a3e0fd82Sopenharmony_ci{
1725a3e0fd82Sopenharmony_ci    bool p3IsInRight = ((triangleInfo.p1.y - triangleInfo.p2.y) * triangleInfo.p3.x +
1726a3e0fd82Sopenharmony_ci                        (triangleInfo.p2.x - triangleInfo.p1.x) * triangleInfo.p3.y +
1727a3e0fd82Sopenharmony_ci                        triangleInfo.p1.x * triangleInfo.p2.y - triangleInfo.p2.x * triangleInfo.p1.y) < 0;
1728a3e0fd82Sopenharmony_ci    TriangleEdge edge1;
1729a3e0fd82Sopenharmony_ci    TriangleEdge edge2;
1730a3e0fd82Sopenharmony_ci    TrianglePartInfo part{
1731a3e0fd82Sopenharmony_ci        mask,
1732a3e0fd82Sopenharmony_ci        transMap,
1733a3e0fd82Sopenharmony_ci        position,
1734a3e0fd82Sopenharmony_ci        edge1,
1735a3e0fd82Sopenharmony_ci        edge2,
1736a3e0fd82Sopenharmony_ci        0,
1737a3e0fd82Sopenharmony_ci        0,
1738a3e0fd82Sopenharmony_ci        triangleInfo.info,
1739a3e0fd82Sopenharmony_ci        color,
1740a3e0fd82Sopenharmony_ci        opaScale,
1741a3e0fd82Sopenharmony_ci        triangleInfo.isRightPart,
1742a3e0fd82Sopenharmony_ci        triangleInfo.ignoreJunctionPoint,
1743a3e0fd82Sopenharmony_ci    };
1744a3e0fd82Sopenharmony_ci
1745a3e0fd82Sopenharmony_ci    uint8_t yErr = 1;
1746a3e0fd82Sopenharmony_ci    if (triangleInfo.p2.y == triangleInfo.p1.y) {
1747a3e0fd82Sopenharmony_ci        yErr = 0;
1748a3e0fd82Sopenharmony_ci        GetInstance()->SetPartEdge(gfxDstBuffer, triangleInfo, edge1, edge2, p3IsInRight, mask, yErr, part);
1749a3e0fd82Sopenharmony_ci        return;
1750a3e0fd82Sopenharmony_ci    }
1751a3e0fd82Sopenharmony_ci    if (p3IsInRight) {
1752a3e0fd82Sopenharmony_ci        edge1 = TriangleEdge(triangleInfo.p1.x, triangleInfo.p1.y, triangleInfo.p2.x, triangleInfo.p2.y);
1753a3e0fd82Sopenharmony_ci        edge2 = TriangleEdge(triangleInfo.p1.x, triangleInfo.p1.y, triangleInfo.p3.x, triangleInfo.p3.y);
1754a3e0fd82Sopenharmony_ci    } else {
1755a3e0fd82Sopenharmony_ci        edge2 = TriangleEdge(triangleInfo.p1.x, triangleInfo.p1.y, triangleInfo.p2.x, triangleInfo.p2.y);
1756a3e0fd82Sopenharmony_ci        edge1 = TriangleEdge(triangleInfo.p1.x, triangleInfo.p1.y, triangleInfo.p3.x, triangleInfo.p3.y);
1757a3e0fd82Sopenharmony_ci    }
1758a3e0fd82Sopenharmony_ci
1759a3e0fd82Sopenharmony_ci    part.yMin = MATH_MAX(mask.GetTop(), triangleInfo.p1.y);
1760a3e0fd82Sopenharmony_ci    part.yMax = MATH_MIN(mask.GetBottom(), triangleInfo.p2.y);
1761a3e0fd82Sopenharmony_ci    part.edge1 = edge1;
1762a3e0fd82Sopenharmony_ci    part.edge2 = edge2;
1763a3e0fd82Sopenharmony_ci    DrawTriangleTransformPart(gfxDstBuffer, part);
1764a3e0fd82Sopenharmony_ci    GetInstance()->SetPartEdge(gfxDstBuffer, triangleInfo, edge1, edge2, p3IsInRight, mask, yErr, part);
1765a3e0fd82Sopenharmony_ci}
1766a3e0fd82Sopenharmony_ci
1767a3e0fd82Sopenharmony_civoid DrawUtils::SetPartEdge(BufferInfo& gfxDstBuffer, const TriangleTransformDataInfo& triangleInfo,
1768a3e0fd82Sopenharmony_ci                            TriangleEdge& edge1, TriangleEdge& edge2, bool p3IsInRight,
1769a3e0fd82Sopenharmony_ci                            const Rect& mask, uint8_t yErr, TrianglePartInfo& part) const
1770a3e0fd82Sopenharmony_ci{
1771a3e0fd82Sopenharmony_ci    if (triangleInfo.p2.y == triangleInfo.p3.y) {
1772a3e0fd82Sopenharmony_ci        return;
1773a3e0fd82Sopenharmony_ci    }
1774a3e0fd82Sopenharmony_ci
1775a3e0fd82Sopenharmony_ci    if (triangleInfo.p2.y == triangleInfo.p1.y) {
1776a3e0fd82Sopenharmony_ci        if (triangleInfo.p1.x < triangleInfo.p2.x) {
1777a3e0fd82Sopenharmony_ci            edge1 = TriangleEdge(triangleInfo.p1.x, triangleInfo.p1.y, triangleInfo.p3.x, triangleInfo.p3.y);
1778a3e0fd82Sopenharmony_ci            edge2 = TriangleEdge(triangleInfo.p2.x, triangleInfo.p2.y, triangleInfo.p3.x, triangleInfo.p3.y);
1779a3e0fd82Sopenharmony_ci        } else {
1780a3e0fd82Sopenharmony_ci            edge2 = TriangleEdge(triangleInfo.p1.x, triangleInfo.p1.y, triangleInfo.p3.x, triangleInfo.p3.y);
1781a3e0fd82Sopenharmony_ci            edge1 = TriangleEdge(triangleInfo.p2.x, triangleInfo.p2.y, triangleInfo.p3.x, triangleInfo.p3.y);
1782a3e0fd82Sopenharmony_ci        }
1783a3e0fd82Sopenharmony_ci    } else {
1784a3e0fd82Sopenharmony_ci        if (p3IsInRight) {
1785a3e0fd82Sopenharmony_ci            edge1 = TriangleEdge(triangleInfo.p2.x, triangleInfo.p2.y, triangleInfo.p3.x, triangleInfo.p3.y);
1786a3e0fd82Sopenharmony_ci        } else {
1787a3e0fd82Sopenharmony_ci            edge2 = TriangleEdge(triangleInfo.p2.x, triangleInfo.p2.y, triangleInfo.p3.x, triangleInfo.p3.y);
1788a3e0fd82Sopenharmony_ci        }
1789a3e0fd82Sopenharmony_ci    }
1790a3e0fd82Sopenharmony_ci
1791a3e0fd82Sopenharmony_ci    part.yMin = MATH_MAX(mask.GetTop(), triangleInfo.p2.y + yErr);
1792a3e0fd82Sopenharmony_ci    part.yMax = MATH_MIN(mask.GetBottom(), triangleInfo.p3.y);
1793a3e0fd82Sopenharmony_ci    part.edge1 = edge1;
1794a3e0fd82Sopenharmony_ci    part.edge2 = edge2;
1795a3e0fd82Sopenharmony_ci    DrawTriangleTransformPart(gfxDstBuffer, part);
1796a3e0fd82Sopenharmony_ci}
1797a3e0fd82Sopenharmony_ci
1798a3e0fd82Sopenharmony_civoid DrawUtils::AddBorderToImageData(TransformDataInfo& newDataInfo, ImageInfo& imageinfo)
1799a3e0fd82Sopenharmony_ci{
1800a3e0fd82Sopenharmony_ci    int16_t border = 1;          // 1 : border width
1801a3e0fd82Sopenharmony_ci    int16_t offset = border * 2; // 2 : offset
1802a3e0fd82Sopenharmony_ci    uint16_t width = newDataInfo.header.width;
1803a3e0fd82Sopenharmony_ci    uint16_t height = newDataInfo.header.height;
1804a3e0fd82Sopenharmony_ci    int16_t diff = 0;
1805a3e0fd82Sopenharmony_ci    if (newDataInfo.pxSize > FONT_WEIGHT_8) {
1806a3e0fd82Sopenharmony_ci        width += offset;
1807a3e0fd82Sopenharmony_ci        height += offset;
1808a3e0fd82Sopenharmony_ci        diff = border * newDataInfo.pxSize / FONT_WEIGHT_8;
1809a3e0fd82Sopenharmony_ci    } else {
1810a3e0fd82Sopenharmony_ci        width += offset * FONT_WEIGHT_8 / newDataInfo.pxSize;
1811a3e0fd82Sopenharmony_ci        height += offset;
1812a3e0fd82Sopenharmony_ci        diff = border;
1813a3e0fd82Sopenharmony_ci    }
1814a3e0fd82Sopenharmony_ci    uint16_t widthInByte = width * newDataInfo.pxSize / FONT_WEIGHT_8;
1815a3e0fd82Sopenharmony_ci    if ((width * newDataInfo.pxSize) % FONT_WEIGHT_8 != 0) {
1816a3e0fd82Sopenharmony_ci        widthInByte++;
1817a3e0fd82Sopenharmony_ci    }
1818a3e0fd82Sopenharmony_ci    imageinfo.header.width = newDataInfo.header.width;
1819a3e0fd82Sopenharmony_ci    imageinfo.header.height = newDataInfo.header.height;
1820a3e0fd82Sopenharmony_ci    imageinfo.dataSize = widthInByte * height;
1821a3e0fd82Sopenharmony_ci    uint8_t* newData = static_cast<uint8_t*>(ImageCacheMalloc(imageinfo));
1822a3e0fd82Sopenharmony_ci    if (newData == nullptr) {
1823a3e0fd82Sopenharmony_ci        return;
1824a3e0fd82Sopenharmony_ci    }
1825a3e0fd82Sopenharmony_ci    imageinfo.data = newData;
1826a3e0fd82Sopenharmony_ci    if (memset_s(newData, widthInByte * height, 0, widthInByte * height) != EOK) {
1827a3e0fd82Sopenharmony_ci        ImageCacheFree(imageinfo);
1828a3e0fd82Sopenharmony_ci        newData = nullptr;
1829a3e0fd82Sopenharmony_ci        return;
1830a3e0fd82Sopenharmony_ci    }
1831a3e0fd82Sopenharmony_ci    uint8_t* tmp = newData;
1832a3e0fd82Sopenharmony_ci    uint8_t* data = const_cast<uint8_t*>(newDataInfo.data);
1833a3e0fd82Sopenharmony_ci    tmp += widthInByte * border + diff;
1834a3e0fd82Sopenharmony_ci    for (int i = 0; i < newDataInfo.header.height; ++i) {
1835a3e0fd82Sopenharmony_ci        // 2 : double
1836a3e0fd82Sopenharmony_ci        if (memcpy_s(tmp, widthInByte - diff * 2, data, widthInByte - diff * 2) != EOK) {
1837a3e0fd82Sopenharmony_ci        ImageCacheFree(imageinfo);
1838a3e0fd82Sopenharmony_ci            newData = nullptr;
1839a3e0fd82Sopenharmony_ci            return;
1840a3e0fd82Sopenharmony_ci        }
1841a3e0fd82Sopenharmony_ci        tmp += widthInByte;
1842a3e0fd82Sopenharmony_ci        data += widthInByte - diff * 2; // 2 : double
1843a3e0fd82Sopenharmony_ci    }
1844a3e0fd82Sopenharmony_ci    newDataInfo.header.width = width;
1845a3e0fd82Sopenharmony_ci    newDataInfo.header.height = height;
1846a3e0fd82Sopenharmony_ci    newDataInfo.data = newData;
1847a3e0fd82Sopenharmony_ci}
1848a3e0fd82Sopenharmony_ci
1849a3e0fd82Sopenharmony_civoid DrawUtils::UpdateTransMap(int16_t width, int16_t height, TransformMap& transMap)
1850a3e0fd82Sopenharmony_ci{
1851a3e0fd82Sopenharmony_ci    Rect rect = transMap.GetTransMapRect();
1852a3e0fd82Sopenharmony_ci    Matrix4<float> matrix = transMap.GetTransformMatrix();
1853a3e0fd82Sopenharmony_ci    matrix = matrix * (Matrix4<float>::Translate(Vector3<float>(-rect.GetX(), -rect.GetY(), 0)));
1854a3e0fd82Sopenharmony_ci    int16_t offsetX = (width - rect.GetWidth()) / 2;   //  2 : half;
1855a3e0fd82Sopenharmony_ci    int16_t offsetY = (height - rect.GetHeight()) / 2; //  2 : half;
1856a3e0fd82Sopenharmony_ci    rect.SetPosition(rect.GetX() - offsetX, rect.GetY() - offsetY);
1857a3e0fd82Sopenharmony_ci    rect.Resize(width, height);
1858a3e0fd82Sopenharmony_ci    Polygon polygon = Polygon(rect);
1859a3e0fd82Sopenharmony_ci    uint8_t vertexNum = transMap.GetPolygon().GetVertexNum();
1860a3e0fd82Sopenharmony_ci    Vector4<float> imgPoint4;
1861a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < vertexNum; i++) {
1862a3e0fd82Sopenharmony_ci        Vector4<float> point(polygon[i].x_, polygon[i].y_, 0, 1);
1863a3e0fd82Sopenharmony_ci        imgPoint4 = matrix * point;
1864a3e0fd82Sopenharmony_ci        if (imgPoint4.x_ < COORD_MIN) {
1865a3e0fd82Sopenharmony_ci            polygon[i].x_ = COORD_MIN;
1866a3e0fd82Sopenharmony_ci        } else if (imgPoint4.x_ > COORD_MAX) {
1867a3e0fd82Sopenharmony_ci            polygon[i].x_ = COORD_MAX;
1868a3e0fd82Sopenharmony_ci        } else {
1869a3e0fd82Sopenharmony_ci            polygon[i].x_ = MATH_ROUND(imgPoint4.x_);
1870a3e0fd82Sopenharmony_ci        }
1871a3e0fd82Sopenharmony_ci
1872a3e0fd82Sopenharmony_ci        if (imgPoint4.y_ < COORD_MIN) {
1873a3e0fd82Sopenharmony_ci            polygon[i].y_ = COORD_MIN;
1874a3e0fd82Sopenharmony_ci        } else if (imgPoint4.y_ > COORD_MAX) {
1875a3e0fd82Sopenharmony_ci            polygon[i].y_ = COORD_MAX;
1876a3e0fd82Sopenharmony_ci        } else {
1877a3e0fd82Sopenharmony_ci            polygon[i].y_ = MATH_ROUND(imgPoint4.y_);
1878a3e0fd82Sopenharmony_ci        }
1879a3e0fd82Sopenharmony_ci    }
1880a3e0fd82Sopenharmony_ci    transMap.SetPolygon(polygon);
1881a3e0fd82Sopenharmony_ci    Matrix3<float> matrix3(matrix[0][0], matrix[0][1], matrix[0][3], matrix[1][0], matrix[1][1], matrix[1][3],
1882a3e0fd82Sopenharmony_ci                           matrix[3][0], matrix[3][1], matrix[3][3]);
1883a3e0fd82Sopenharmony_ci    transMap.invMatrix_ = (matrix3 * (Matrix3<float>::Translate(Vector2<float>(rect.GetX(), rect.GetY())))).Inverse();
1884a3e0fd82Sopenharmony_ci}
1885a3e0fd82Sopenharmony_ci
1886a3e0fd82Sopenharmony_civoid DrawUtils::DrawTransform(BufferInfo& gfxDstBuffer,
1887a3e0fd82Sopenharmony_ci                              const Rect& mask,
1888a3e0fd82Sopenharmony_ci                              const Point& position,
1889a3e0fd82Sopenharmony_ci                              const ColorType& color,
1890a3e0fd82Sopenharmony_ci                              OpacityType opaScale,
1891a3e0fd82Sopenharmony_ci                              const TransformMap& transMap,
1892a3e0fd82Sopenharmony_ci                              const TransformDataInfo& dataInfo) const
1893a3e0fd82Sopenharmony_ci{
1894a3e0fd82Sopenharmony_ci    if (opaScale == OPA_TRANSPARENT) {
1895a3e0fd82Sopenharmony_ci        return;
1896a3e0fd82Sopenharmony_ci    }
1897a3e0fd82Sopenharmony_ci    if ((gfxDstBuffer.virAddr == nullptr) || (dataInfo.data == nullptr)) {
1898a3e0fd82Sopenharmony_ci        return;
1899a3e0fd82Sopenharmony_ci    }
1900a3e0fd82Sopenharmony_ci    ImageInfo imageinfo;
1901a3e0fd82Sopenharmony_ci    TransformDataInfo newDataInfo = dataInfo;
1902a3e0fd82Sopenharmony_ci    TransformMap newTransMap = transMap;
1903a3e0fd82Sopenharmony_ci    // If the width and height of the rectangle of transMap are not equal to the width and height of the ImageHeader,
1904a3e0fd82Sopenharmony_ci    // a border of transparency values to the data cannot be added.
1905a3e0fd82Sopenharmony_ci    if ((transMap.GetTransMapRect().GetWidth() == dataInfo.header.width) &&
1906a3e0fd82Sopenharmony_ci        (transMap.GetTransMapRect().GetHeight() == dataInfo.header.height)) {
1907a3e0fd82Sopenharmony_ci        // Add a border of transparency values to the data
1908a3e0fd82Sopenharmony_ci        AddBorderToImageData(newDataInfo, imageinfo);
1909a3e0fd82Sopenharmony_ci        // Update the transMap according to new rect width and height
1910a3e0fd82Sopenharmony_ci        UpdateTransMap(newDataInfo.header.width, newDataInfo.header.height, newTransMap);
1911a3e0fd82Sopenharmony_ci    }
1912a3e0fd82Sopenharmony_ci
1913a3e0fd82Sopenharmony_ci    Rect trans = newTransMap.GetBoxRect();
1914a3e0fd82Sopenharmony_ci    trans.SetX(trans.GetX() + position.x);
1915a3e0fd82Sopenharmony_ci    trans.SetY(trans.GetY() + position.y);
1916a3e0fd82Sopenharmony_ci    imageinfo.data = newDataInfo.data;
1917a3e0fd82Sopenharmony_ci    if (!trans.Intersect(trans, mask)) {
1918a3e0fd82Sopenharmony_ci        if (newDataInfo.data != dataInfo.data) {
1919a3e0fd82Sopenharmony_ci            ImageCacheFree(imageinfo);
1920a3e0fd82Sopenharmony_ci        }
1921a3e0fd82Sopenharmony_ci        return;
1922a3e0fd82Sopenharmony_ci    }
1923a3e0fd82Sopenharmony_ci
1924a3e0fd82Sopenharmony_ci    TriangleTransformDataInfo triangleInfo{
1925a3e0fd82Sopenharmony_ci        newDataInfo,
1926a3e0fd82Sopenharmony_ci    };
1927a3e0fd82Sopenharmony_ci    Polygon polygon = newTransMap.GetPolygon();
1928a3e0fd82Sopenharmony_ci    Point p1;
1929a3e0fd82Sopenharmony_ci    p1.x = polygon[0].x_ + position.x; // 0:first point
1930a3e0fd82Sopenharmony_ci    p1.y = polygon[0].y_ + position.y; // 0:first point
1931a3e0fd82Sopenharmony_ci    Point p2;
1932a3e0fd82Sopenharmony_ci    p2.x = polygon[1].x_ + position.x; // 1:second point
1933a3e0fd82Sopenharmony_ci    p2.y = polygon[1].y_ + position.y; // 1:second point
1934a3e0fd82Sopenharmony_ci    Point p3;
1935a3e0fd82Sopenharmony_ci    p3.x = polygon[2].x_ + position.x; // 2:third point
1936a3e0fd82Sopenharmony_ci    p3.y = polygon[2].y_ + position.y; // 2:third point
1937a3e0fd82Sopenharmony_ci    triangleInfo.isRightPart = ((p1.y - p3.y) * p2.x + (p3.x - p1.x) * p2.y + p1.x * p3.y - p3.x * p1.y) < 0;
1938a3e0fd82Sopenharmony_ci    triangleInfo.isRightPart = (p1.y < p3.y) ? triangleInfo.isRightPart : !triangleInfo.isRightPart;
1939a3e0fd82Sopenharmony_ci    DrawTriangle::SortVertexs(p1, p2, p3);
1940a3e0fd82Sopenharmony_ci    triangleInfo.ignoreJunctionPoint = false;
1941a3e0fd82Sopenharmony_ci    triangleInfo.p1 = p1;
1942a3e0fd82Sopenharmony_ci    triangleInfo.p2 = p2;
1943a3e0fd82Sopenharmony_ci    triangleInfo.p3 = p3;
1944a3e0fd82Sopenharmony_ci    if ((triangleInfo.p1.y <= mask.GetBottom()) && (triangleInfo.p3.y >= mask.GetTop())) {
1945a3e0fd82Sopenharmony_ci        DrawTriangleTransform(gfxDstBuffer, mask, position, color, opaScale, newTransMap, triangleInfo);
1946a3e0fd82Sopenharmony_ci    }
1947a3e0fd82Sopenharmony_ci
1948a3e0fd82Sopenharmony_ci    triangleInfo.ignoreJunctionPoint = true;
1949a3e0fd82Sopenharmony_ci    triangleInfo.isRightPart = !triangleInfo.isRightPart;
1950a3e0fd82Sopenharmony_ci    p1.x = polygon[0].x_ + position.x; // 0:first point
1951a3e0fd82Sopenharmony_ci    p1.y = polygon[0].y_ + position.y; // 0:first point
1952a3e0fd82Sopenharmony_ci    p3.x = polygon[2].x_ + position.x; // 2:third point
1953a3e0fd82Sopenharmony_ci    p3.y = polygon[2].y_ + position.y; // 2:third point
1954a3e0fd82Sopenharmony_ci    Point p4;
1955a3e0fd82Sopenharmony_ci    p4.x = polygon[3].x_ + position.x; // 3:fourth point
1956a3e0fd82Sopenharmony_ci    p4.y = polygon[3].y_ + position.y; // 3:fourth point
1957a3e0fd82Sopenharmony_ci    DrawTriangle::SortVertexs(p1, p3, p4);
1958a3e0fd82Sopenharmony_ci    triangleInfo.p1 = p1;
1959a3e0fd82Sopenharmony_ci    triangleInfo.p2 = p3;
1960a3e0fd82Sopenharmony_ci    triangleInfo.p3 = p4;
1961a3e0fd82Sopenharmony_ci    if ((triangleInfo.p1.y <= mask.GetBottom()) && (triangleInfo.p3.y >= mask.GetTop())) {
1962a3e0fd82Sopenharmony_ci        DrawTriangleTransform(gfxDstBuffer, mask, position, color, opaScale, newTransMap, triangleInfo);
1963a3e0fd82Sopenharmony_ci    }
1964a3e0fd82Sopenharmony_ci    if (newDataInfo.data != dataInfo.data) {
1965a3e0fd82Sopenharmony_ci        ImageCacheFree(imageinfo);
1966a3e0fd82Sopenharmony_ci    }
1967a3e0fd82Sopenharmony_ci}
1968a3e0fd82Sopenharmony_ci
1969a3e0fd82Sopenharmony_ciOpacityType DrawUtils::GetPxAlphaForAlphaImg(const TransformDataInfo& dataInfo, const Point& point)
1970a3e0fd82Sopenharmony_ci{
1971a3e0fd82Sopenharmony_ci    Point tmpPoint = point;
1972a3e0fd82Sopenharmony_ci    const uint8_t* bufU8 = const_cast<uint8_t*>(dataInfo.data);
1973a3e0fd82Sopenharmony_ci#if ENABLE_SPEC_FONT
1974a3e0fd82Sopenharmony_ci    if (dataInfo.header.colorMode == A1) {
1975a3e0fd82Sopenharmony_ci        uint8_t bit = tmpPoint.x & 0x7; // 0x7: 1 byte is 8 bit,
1976a3e0fd82Sopenharmony_ci        tmpPoint.x = tmpPoint.x >> SHIFT_3;
1977a3e0fd82Sopenharmony_ci
1978a3e0fd82Sopenharmony_ci        uint32_t px = (dataInfo.header.width >> SHIFT_3) * tmpPoint.y + tmpPoint.x;
1979a3e0fd82Sopenharmony_ci        // 1: A1 means 1 bit, 7: maximum offset in bytes
1980a3e0fd82Sopenharmony_ci        uint8_t pxOpa = (bufU8[px] & (1 << (7 - bit))) >> (7 - bit);
1981a3e0fd82Sopenharmony_ci        return pxOpa ? OPA_TRANSPARENT : OPA_OPAQUE;
1982a3e0fd82Sopenharmony_ci    } else if (dataInfo.header.colorMode == A2) {
1983a3e0fd82Sopenharmony_ci        uint8_t bit = (tmpPoint.x & 0x3) * 2; // 0x3: 0b0011, 2: A2 color mode
1984a3e0fd82Sopenharmony_ci        tmpPoint.x = tmpPoint.x >> SHIFT_2;
1985a3e0fd82Sopenharmony_ci
1986a3e0fd82Sopenharmony_ci        uint32_t px = (dataInfo.header.width >> SHIFT_2) * tmpPoint.y + tmpPoint.x;
1987a3e0fd82Sopenharmony_ci        // 3: the value of 0b0011
1988a3e0fd82Sopenharmony_ci        uint8_t pxOpa = (bufU8[px] & (3 << (SHIFT_6 - bit))) >> (SHIFT_6 - bit);
1989a3e0fd82Sopenharmony_ci        return pxOpa * OPACITY_STEP_A2;
1990a3e0fd82Sopenharmony_ci    } else if (dataInfo.header.colorMode == A8) {
1991a3e0fd82Sopenharmony_ci        uint32_t px = dataInfo.header.width * tmpPoint.y + tmpPoint.x;
1992a3e0fd82Sopenharmony_ci        return bufU8[px];
1993a3e0fd82Sopenharmony_ci    }
1994a3e0fd82Sopenharmony_ci#else
1995a3e0fd82Sopenharmony_ci    uint8_t letterWidthInByte = (dataInfo.header.width * dataInfo.pxSize) >> SHIFT_3;
1996a3e0fd82Sopenharmony_ci    // 0x7: for rounding
1997a3e0fd82Sopenharmony_ci    if ((dataInfo.header.width * dataInfo.pxSize) & 0x7) {
1998a3e0fd82Sopenharmony_ci        letterWidthInByte++;
1999a3e0fd82Sopenharmony_ci    }
2000a3e0fd82Sopenharmony_ci    uint8_t bit = (tmpPoint.x & 0x1) << SHIFT_2;
2001a3e0fd82Sopenharmony_ci    bufU8 += (tmpPoint.y * letterWidthInByte) + ((tmpPoint.x * dataInfo.pxSize) >> SHIFT_3);
2002a3e0fd82Sopenharmony_ci    // 0xF: 0b1111, get the data of the A4 color mode
2003a3e0fd82Sopenharmony_ci    uint8_t pxOpa = (*bufU8 & (0xF << bit)) >> (bit);
2004a3e0fd82Sopenharmony_ci    return pxOpa * OPACITY_STEP_A4;
2005a3e0fd82Sopenharmony_ci#endif // ENABLE_SPEC_FONT
2006a3e0fd82Sopenharmony_ci}
2007a3e0fd82Sopenharmony_ci
2008a3e0fd82Sopenharmony_civoid DrawUtils::DrawTranspantArea(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& mask)
2009a3e0fd82Sopenharmony_ci{
2010a3e0fd82Sopenharmony_ci    FillArea(gfxDstBuffer, rect, mask, true, nullptr);
2011a3e0fd82Sopenharmony_ci}
2012a3e0fd82Sopenharmony_ci
2013a3e0fd82Sopenharmony_civoid DrawUtils::DrawWithBuffer(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& mask, const ColorType* colorBuf)
2014a3e0fd82Sopenharmony_ci{
2015a3e0fd82Sopenharmony_ci    FillArea(gfxDstBuffer, rect, mask, false, colorBuf);
2016a3e0fd82Sopenharmony_ci}
2017a3e0fd82Sopenharmony_ci
2018a3e0fd82Sopenharmony_civoid DrawUtils::FillArea(BufferInfo& gfxDstBuffer,
2019a3e0fd82Sopenharmony_ci                         const Rect& rect,
2020a3e0fd82Sopenharmony_ci                         const Rect& mask,
2021a3e0fd82Sopenharmony_ci                         bool isTransparent,
2022a3e0fd82Sopenharmony_ci                         const ColorType* colorBuf)
2023a3e0fd82Sopenharmony_ci{
2024a3e0fd82Sopenharmony_ci    Rect maskedArea;
2025a3e0fd82Sopenharmony_ci    if (!maskedArea.Intersect(rect, mask)) {
2026a3e0fd82Sopenharmony_ci        return;
2027a3e0fd82Sopenharmony_ci    }
2028a3e0fd82Sopenharmony_ci
2029a3e0fd82Sopenharmony_ci    int16_t left = maskedArea.GetLeft();
2030a3e0fd82Sopenharmony_ci    int16_t right = maskedArea.GetRight();
2031a3e0fd82Sopenharmony_ci    int16_t top = maskedArea.GetTop();
2032a3e0fd82Sopenharmony_ci    int16_t bottom = maskedArea.GetBottom();
2033a3e0fd82Sopenharmony_ci
2034a3e0fd82Sopenharmony_ci    DRAW_UTILS_PREPROCESS(gfxDstBuffer, OPA_OPAQUE);
2035a3e0fd82Sopenharmony_ci    uint8_t* mem = screenBuffer;
2036a3e0fd82Sopenharmony_ci    mem += top * screenBufferWidth * bufferPxSize;
2037a3e0fd82Sopenharmony_ci    if (isTransparent) {
2038a3e0fd82Sopenharmony_ci        uint16_t sz = (right - left + 1) * bufferPxSize;
2039a3e0fd82Sopenharmony_ci        for (int16_t row = top; row <= bottom; row++) {
2040a3e0fd82Sopenharmony_ci            if (memset_s(mem + (left * bufferPxSize), sz, 0, sz) != EOK) {
2041a3e0fd82Sopenharmony_ci                return;
2042a3e0fd82Sopenharmony_ci            }
2043a3e0fd82Sopenharmony_ci            mem += screenBufferWidth * bufferPxSize;
2044a3e0fd82Sopenharmony_ci        }
2045a3e0fd82Sopenharmony_ci    } else {
2046a3e0fd82Sopenharmony_ci        if (colorBuf == nullptr) {
2047a3e0fd82Sopenharmony_ci            return;
2048a3e0fd82Sopenharmony_ci        }
2049a3e0fd82Sopenharmony_ci        for (int16_t row = top; row <= bottom; row++) {
2050a3e0fd82Sopenharmony_ci            for (int16_t col = left; col <= right; col++) {
2051a3e0fd82Sopenharmony_ci#if COLOR_DEPTH == 32
2052a3e0fd82Sopenharmony_ci                COLOR_FILL_COVER(mem[col * bufferPxSize], bufferMode, colorBuf[row * screenBufferWidth + col].red,
2053a3e0fd82Sopenharmony_ci                                 colorBuf[row * screenBufferWidth + col].green,
2054a3e0fd82Sopenharmony_ci                                 colorBuf[row * screenBufferWidth + col].blue, ARGB8888);
2055a3e0fd82Sopenharmony_ci#else
2056a3e0fd82Sopenharmony_ci                COLOR_FILL_COVER(mem[col * bufferPxSize], bufferMode, colorBuf[row * screenBufferWidth + col].red,
2057a3e0fd82Sopenharmony_ci                                 colorBuf[row * screenBufferWidth + col].green,
2058a3e0fd82Sopenharmony_ci                                 colorBuf[row * screenBufferWidth + col].blue, RGB565);
2059a3e0fd82Sopenharmony_ci#endif
2060a3e0fd82Sopenharmony_ci            }
2061a3e0fd82Sopenharmony_ci            mem += screenBufferWidth * bufferPxSize;
2062a3e0fd82Sopenharmony_ci        }
2063a3e0fd82Sopenharmony_ci    }
2064a3e0fd82Sopenharmony_ci}
2065a3e0fd82Sopenharmony_ci
2066a3e0fd82Sopenharmony_civoid DrawUtils::DrawAdjPixelInLine(BufferInfo& gfxDstBuffer,
2067a3e0fd82Sopenharmony_ci                                   int16_t x1,
2068a3e0fd82Sopenharmony_ci                                   int16_t y1,
2069a3e0fd82Sopenharmony_ci                                   int16_t x2,
2070a3e0fd82Sopenharmony_ci                                   int16_t y2,
2071a3e0fd82Sopenharmony_ci                                   const Rect& mask,
2072a3e0fd82Sopenharmony_ci                                   const ColorType& color,
2073a3e0fd82Sopenharmony_ci                                   OpacityType opa,
2074a3e0fd82Sopenharmony_ci                                   uint16_t weight) const
2075a3e0fd82Sopenharmony_ci{
2076a3e0fd82Sopenharmony_ci    DRAW_UTILS_PREPROCESS(gfxDstBuffer, opa);
2077a3e0fd82Sopenharmony_ci    Color32 result;
2078a3e0fd82Sopenharmony_ci    result.full = Color::ColorTo32(color);
2079a3e0fd82Sopenharmony_ci    if ((x1 >= mask.GetLeft()) && (x1 <= mask.GetRight()) && (y1 >= mask.GetTop()) && (y1 <= mask.GetBottom())) {
2080a3e0fd82Sopenharmony_ci        screenBuffer += (y1 * screenBufferWidth + x1) * bufferPxSize;
2081a3e0fd82Sopenharmony_ci        OpacityType fillOpa = (weight ^ OPA_OPAQUE) * opa / OPA_OPAQUE;
2082a3e0fd82Sopenharmony_ci        COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, fillOpa);
2083a3e0fd82Sopenharmony_ci    }
2084a3e0fd82Sopenharmony_ci    if ((x2 >= mask.GetLeft()) && (x2 <= mask.GetRight()) && (y2 >= mask.GetTop()) && (y2 <= mask.GetBottom())) {
2085a3e0fd82Sopenharmony_ci        screenBuffer = static_cast<uint8_t*>(gfxDstBuffer.virAddr);
2086a3e0fd82Sopenharmony_ci        screenBuffer += (y2 * screenBufferWidth + x2) * bufferPxSize;
2087a3e0fd82Sopenharmony_ci        OpacityType fillOpa = weight * opa / OPA_OPAQUE;
2088a3e0fd82Sopenharmony_ci        COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, fillOpa);
2089a3e0fd82Sopenharmony_ci    }
2090a3e0fd82Sopenharmony_ci}
2091a3e0fd82Sopenharmony_ci
2092a3e0fd82Sopenharmony_civoid DrawUtils::DrawPixelInLine(BufferInfo& gfxDstBuffer,
2093a3e0fd82Sopenharmony_ci                                int16_t x,
2094a3e0fd82Sopenharmony_ci                                int16_t y,
2095a3e0fd82Sopenharmony_ci                                const Rect& mask,
2096a3e0fd82Sopenharmony_ci                                const ColorType& color,
2097a3e0fd82Sopenharmony_ci                                OpacityType opa,
2098a3e0fd82Sopenharmony_ci                                uint16_t weight) const
2099a3e0fd82Sopenharmony_ci{
2100a3e0fd82Sopenharmony_ci    DRAW_UTILS_PREPROCESS(gfxDstBuffer, opa);
2101a3e0fd82Sopenharmony_ci    Color32 result;
2102a3e0fd82Sopenharmony_ci    result.full = Color::ColorTo32(color);
2103a3e0fd82Sopenharmony_ci    if ((x >= mask.GetLeft()) && (x <= mask.GetRight()) && (y >= mask.GetTop()) && (y <= mask.GetBottom())) {
2104a3e0fd82Sopenharmony_ci        screenBuffer += (y * screenBufferWidth + x) * bufferPxSize;
2105a3e0fd82Sopenharmony_ci        OpacityType fillOpa = weight * opa / OPA_OPAQUE;
2106a3e0fd82Sopenharmony_ci        COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, fillOpa);
2107a3e0fd82Sopenharmony_ci    }
2108a3e0fd82Sopenharmony_ci}
2109a3e0fd82Sopenharmony_ci
2110a3e0fd82Sopenharmony_civoid DrawUtils::DrawVerPixelInLine(BufferInfo& gfxDstBuffer,
2111a3e0fd82Sopenharmony_ci                                   int16_t x,
2112a3e0fd82Sopenharmony_ci                                   int16_t y,
2113a3e0fd82Sopenharmony_ci                                   int8_t dir,
2114a3e0fd82Sopenharmony_ci                                   const Rect& mask,
2115a3e0fd82Sopenharmony_ci                                   const ColorType& color,
2116a3e0fd82Sopenharmony_ci                                   OpacityType opa,
2117a3e0fd82Sopenharmony_ci                                   uint16_t weight) const
2118a3e0fd82Sopenharmony_ci{
2119a3e0fd82Sopenharmony_ci    DRAW_UTILS_PREPROCESS(gfxDstBuffer, opa);
2120a3e0fd82Sopenharmony_ci    if ((y < mask.GetTop()) || (y > mask.GetBottom())) {
2121a3e0fd82Sopenharmony_ci        return;
2122a3e0fd82Sopenharmony_ci    }
2123a3e0fd82Sopenharmony_ci    Color32 result;
2124a3e0fd82Sopenharmony_ci    result.full = Color::ColorTo32(color);
2125a3e0fd82Sopenharmony_ci    int16_t x0 = x + dir;
2126a3e0fd82Sopenharmony_ci    int16_t x1 = x - dir;
2127a3e0fd82Sopenharmony_ci    if ((x0 >= mask.GetLeft()) && (x0 <= mask.GetRight())) {
2128a3e0fd82Sopenharmony_ci        screenBuffer += (y * screenBufferWidth + x0) * bufferPxSize;
2129a3e0fd82Sopenharmony_ci        OpacityType fillOpa = weight * opa / OPA_OPAQUE;
2130a3e0fd82Sopenharmony_ci        COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, fillOpa);
2131a3e0fd82Sopenharmony_ci    }
2132a3e0fd82Sopenharmony_ci    if ((x >= mask.GetLeft()) && (x <= mask.GetRight())) {
2133a3e0fd82Sopenharmony_ci        screenBuffer = static_cast<uint8_t*>(gfxDstBuffer.virAddr);
2134a3e0fd82Sopenharmony_ci        screenBuffer += (y * screenBufferWidth + x) * bufferPxSize;
2135a3e0fd82Sopenharmony_ci        if (opa == OPA_OPAQUE) {
2136a3e0fd82Sopenharmony_ci            COLOR_FILL_COVER(screenBuffer, bufferMode, result.red, result.green, result.blue, ARGB8888);
2137a3e0fd82Sopenharmony_ci        } else {
2138a3e0fd82Sopenharmony_ci            COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, opa);
2139a3e0fd82Sopenharmony_ci        }
2140a3e0fd82Sopenharmony_ci    }
2141a3e0fd82Sopenharmony_ci    if ((x1 >= mask.GetLeft()) && (x1 <= mask.GetRight())) {
2142a3e0fd82Sopenharmony_ci        screenBuffer = static_cast<uint8_t*>(gfxDstBuffer.virAddr);
2143a3e0fd82Sopenharmony_ci        screenBuffer += (y * screenBufferWidth + x1) * bufferPxSize;
2144a3e0fd82Sopenharmony_ci        OpacityType fillOpa = (weight ^ OPA_OPAQUE) * opa / OPA_OPAQUE;
2145a3e0fd82Sopenharmony_ci        COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, fillOpa);
2146a3e0fd82Sopenharmony_ci    }
2147a3e0fd82Sopenharmony_ci}
2148a3e0fd82Sopenharmony_ci
2149a3e0fd82Sopenharmony_civoid DrawUtils::DrawHorPixelInLine(BufferInfo& gfxDstBuffer,
2150a3e0fd82Sopenharmony_ci                                   int16_t x,
2151a3e0fd82Sopenharmony_ci                                   int16_t y,
2152a3e0fd82Sopenharmony_ci                                   int8_t dir,
2153a3e0fd82Sopenharmony_ci                                   const Rect& mask,
2154a3e0fd82Sopenharmony_ci                                   const ColorType& color,
2155a3e0fd82Sopenharmony_ci                                   OpacityType opa,
2156a3e0fd82Sopenharmony_ci                                   uint16_t weight) const
2157a3e0fd82Sopenharmony_ci{
2158a3e0fd82Sopenharmony_ci    DRAW_UTILS_PREPROCESS(gfxDstBuffer, opa);
2159a3e0fd82Sopenharmony_ci    if ((x < mask.GetLeft()) || (x > mask.GetRight())) {
2160a3e0fd82Sopenharmony_ci        return;
2161a3e0fd82Sopenharmony_ci    }
2162a3e0fd82Sopenharmony_ci    Color32 result;
2163a3e0fd82Sopenharmony_ci    result.full = Color::ColorTo32(color);
2164a3e0fd82Sopenharmony_ci    int16_t y0 = y + dir;
2165a3e0fd82Sopenharmony_ci    int16_t y1 = y - dir;
2166a3e0fd82Sopenharmony_ci    if ((y0 >= mask.GetTop()) && (y0 <= mask.GetBottom())) {
2167a3e0fd82Sopenharmony_ci        screenBuffer += (y0 * screenBufferWidth + x) * bufferPxSize;
2168a3e0fd82Sopenharmony_ci        OpacityType fillOpa = weight * opa / OPA_OPAQUE;
2169a3e0fd82Sopenharmony_ci        COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, fillOpa);
2170a3e0fd82Sopenharmony_ci    }
2171a3e0fd82Sopenharmony_ci    if ((y >= mask.GetTop()) && (y <= mask.GetBottom())) {
2172a3e0fd82Sopenharmony_ci        screenBuffer = static_cast<uint8_t*>(gfxDstBuffer.virAddr);
2173a3e0fd82Sopenharmony_ci        screenBuffer += (y * screenBufferWidth + x) * bufferPxSize;
2174a3e0fd82Sopenharmony_ci        if (opa == OPA_OPAQUE) {
2175a3e0fd82Sopenharmony_ci            COLOR_FILL_COVER(screenBuffer, bufferMode, result.red, result.green, result.blue, ARGB8888);
2176a3e0fd82Sopenharmony_ci        } else {
2177a3e0fd82Sopenharmony_ci            COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, opa);
2178a3e0fd82Sopenharmony_ci        }
2179a3e0fd82Sopenharmony_ci    }
2180a3e0fd82Sopenharmony_ci    if ((y1 >= mask.GetTop()) && (y1 <= mask.GetBottom())) {
2181a3e0fd82Sopenharmony_ci        screenBuffer = static_cast<uint8_t*>(gfxDstBuffer.virAddr);
2182a3e0fd82Sopenharmony_ci        screenBuffer += (y1 * screenBufferWidth + x) * bufferPxSize;
2183a3e0fd82Sopenharmony_ci        OpacityType fillOpa = (weight ^ OPA_OPAQUE) * opa / OPA_OPAQUE;
2184a3e0fd82Sopenharmony_ci        COLOR_FILL_BLEND(screenBuffer, bufferMode, &result, ARGB8888, fillOpa);
2185a3e0fd82Sopenharmony_ci    }
2186a3e0fd82Sopenharmony_ci}
2187a3e0fd82Sopenharmony_ci} // namespace OHOS
2188