1/*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "draw/draw_rect.h"
17#include "draw/draw_utils.h"
18#include "engines/gfx/gfx_engine_manager.h"
19#include "gfx_utils/graphic_log.h"
20#include "gfx_utils/graphic_math.h"
21#include "gfx_utils/style.h"
22
23namespace OHOS {
24void DrawRect::Draw(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
25                    const Style& style, OpacityType opaScale)
26{
27    if ((rect.GetWidth() <= 0) || (rect.GetHeight() <= 0)) {
28        GRAPHIC_LOGD("DrawRect::Draw width or height is zero\n");
29        return;
30    }
31
32    /**
33     * no border
34     *      radius = 0 (1/4)
35     *      radius > 0 (2/4)
36     *          rect width > rect height
37     *              radius >= rect height / 2
38     *              radius < rect height / 2
39     *          rect width <= rect height
40     *              radius >= rect width / 2
41     *              radius < rect width / 2
42     * have border
43     *      radius = 0 (3/4)
44     *      radius > 0 (4/4)
45     *          radius < border width (4.1/4)
46     *          radius = border width (4.2/4)
47     *          radius > border width (4.3/4)
48     *             rect width <= rect height
49     *                  radius >= border width + rect height / 2
50     *                  radius < border width + rect height / 2
51     *             rect width > rect height
52     *                  radius >= border width + rect height / 2
53     *                  radius < border width + rect height / 2
54     */
55    if (style.borderWidth_ == 0) {
56        if (style.borderRadius_ == 0) {
57            /* no border no radius (1/4) */
58            OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
59            DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, rect, dirtyRect, style.bgColor_, opa);
60            return;
61        } else {
62            /* [2/4] no border with radius (2/4) */
63            DrawRectRadiusWithoutBorder(gfxDstBuffer, rect, dirtyRect, style, opaScale);
64        }
65    } else {
66        if (style.borderRadius_ == 0) {
67            /* [3/4] border without radius (3/4) */
68            DrawRectBorderWithoutRadius(gfxDstBuffer, rect, dirtyRect, style, opaScale);
69        } else if (style.borderRadius_ < style.borderWidth_) {
70            /* [4.1/4] radius < border width */
71            DrawRectRadiusSmallThanBorder(gfxDstBuffer, rect, dirtyRect, style, opaScale);
72        } else if (style.borderRadius_ == style.borderWidth_) {
73            /* [4.2/4] radius = border width */
74            DrawRectRadiusEqualBorder(gfxDstBuffer, rect, dirtyRect, style, opaScale);
75        } else {
76            /* [4.3/4] radius >= border width + rect height_or_width / 2 */
77            DrawRectRadiusBiggerThanBorder(gfxDstBuffer, rect, dirtyRect, style, opaScale);
78        }
79    }
80}
81
82void DrawRect::DrawRectRadiusWithoutBorder(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
83                                           const Style& style, OpacityType opaScale)
84{
85    // 2 : half
86    if ((rect.GetWidth() > rect.GetHeight()) && (style.borderRadius_ >= rect.GetHeight() / 2)) {
87        DrawRectRadiusWithoutBorderCon1(gfxDstBuffer, rect, dirtyRect, style, opaScale);
88    } else if ((rect.GetWidth() < rect.GetHeight()) && (style.borderRadius_ >= rect.GetWidth() / 2)) {
89        DrawRectRadiusWithoutBorderCon2(gfxDstBuffer, rect, dirtyRect, style, opaScale);
90    } else if ((rect.GetWidth() == rect.GetHeight()) && (style.borderRadius_ >= rect.GetWidth() / 2)) {
91        DrawRectRadiusWithoutBorderCon3(gfxDstBuffer, rect, dirtyRect, style, opaScale);
92    } else {
93        DrawRectRadiusWithoutBorderCon4(gfxDstBuffer, rect, dirtyRect, style, opaScale);
94    }
95}
96
97void DrawRect::DrawRectRadiusWithoutBorderCon1(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
98                                               const Style& style, OpacityType opaScale)
99{
100    int16_t radius = rect.GetHeight() / 2;
101    int16_t col2X = rect.GetLeft() + radius - 1;
102    int16_t col3X = rect.GetRight() - radius + 1;
103
104    int16_t row1Y = rect.GetTop();
105    int16_t row2Y = rect.GetTop() + radius - 1;
106    int16_t row3Y = rect.GetBottom();
107
108    Style arcStyle = style;
109    arcStyle.lineWidth_ = radius;
110    arcStyle.lineColor_ = style.bgColor_;
111    arcStyle.lineOpa_ = style.bgOpa_;
112    // draw left sector
113    ArcInfo arcInfo;
114    arcInfo.center = {col2X, row2Y};
115    arcInfo.radius = radius;
116    arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
117    arcInfo.endAngle = CIRCLE_IN_DEGREE;
118    arcInfo.imgPos = {0, 0};
119    arcInfo.imgSrc = nullptr;
120    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
121    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
122
123    // draw right sector
124    arcInfo.center = {col3X, row2Y};
125    arcInfo.startAngle = 0;
126    arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
127    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
128
129    // draw top rectangle
130    DrawUtils* drawUtils = DrawUtils::GetInstance();
131    Rect topRect(col2X, row1Y, col3X - 1, row2Y - 1);
132    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
133    drawUtils->DrawColorArea(gfxDstBuffer, topRect, dirtyRect, style.bgColor_, opa);
134
135    // draw bottom rectangle
136    Rect bottomRect(col2X + 1, row2Y, col3X - 1, row3Y);
137    drawUtils->DrawColorArea(gfxDstBuffer, bottomRect, dirtyRect, style.bgColor_, opa);
138}
139
140void DrawRect::DrawRectRadiusWithoutBorderCon2(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
141                                               const Style& style, OpacityType opaScale)
142{
143    int16_t radius = rect.GetWidth() / 2;
144    int16_t col1X = rect.GetLeft();
145    int16_t col2X = rect.GetLeft() + radius - 1;
146    int16_t col3X = rect.GetRight();
147
148    int16_t row2Y = rect.GetTop() + radius - 1;
149    int16_t row3Y = rect.GetBottom() - radius + 1;
150
151    Style arcStyle = style;
152    arcStyle.lineWidth_ = radius;
153    arcStyle.lineColor_ = style.bgColor_;
154    arcStyle.lineOpa_ = style.bgOpa_;
155    // draw top sector
156    ArcInfo arcInfo;
157    arcInfo.center = {col2X, row2Y};
158    arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
159    arcInfo.endAngle = QUARTER_IN_DEGREE;
160    arcInfo.radius = radius;
161    arcInfo.imgPos = {0, 0};
162    arcInfo.imgSrc = nullptr;
163    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
164    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
165
166    // draw bottom sector
167    arcInfo.center = {col2X, row3Y};
168    arcInfo.startAngle = QUARTER_IN_DEGREE;
169    arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
170    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
171
172    // draw middle rectangle
173    Rect middleRect(col1X, row2Y + 1, col3X, row3Y - 1);
174    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
175    DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, middleRect, dirtyRect, style.bgColor_, opa);
176}
177
178void DrawRect::DrawRectRadiusWithoutBorderCon3(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
179                                               const Style& style, OpacityType opaScale)
180{
181    int16_t radius = rect.GetWidth() / 2;
182    int16_t col1X = rect.GetLeft() + radius - 1;
183    int16_t row1Y = rect.GetTop() + radius - 1;
184
185    Style arcStyle = style;
186    arcStyle.lineWidth_ = radius;
187    arcStyle.lineColor_ = style.bgColor_;
188    arcStyle.lineOpa_ = style.bgOpa_;
189    // draw circle
190    ArcInfo arcInfo;
191    arcInfo.center = {col1X, row1Y};
192    arcInfo.startAngle = 0;
193    arcInfo.endAngle = CIRCLE_IN_DEGREE;
194    arcInfo.radius = radius;
195    arcInfo.imgPos = {0, 0};
196    arcInfo.imgSrc = nullptr;
197    BaseGfxEngine::GetInstance()->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
198}
199
200void DrawRect::DrawRectRadiusWithoutBorderCon4(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
201                                               const Style& style, OpacityType opaScale)
202{
203    int16_t radius = style.borderRadius_;
204    int16_t col1X = rect.GetLeft();
205    int16_t col2X = rect.GetLeft() + radius - 1;
206    int16_t col3X = rect.GetRight() - radius + 1;
207    int16_t col4X = rect.GetRight();
208
209    int16_t row1Y = rect.GetTop();
210    int16_t row2Y = rect.GetTop() + radius - 1;
211    int16_t row3Y = rect.GetBottom() - radius + 1;
212    int16_t row4Y = rect.GetBottom();
213
214    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
215    // draw top rectangle
216    Rect topRect(col2X, row1Y, col3X - 1, row2Y);
217    DrawUtils* drawUtils = DrawUtils::GetInstance();
218    drawUtils->DrawColorArea(gfxDstBuffer, topRect, dirtyRect, style.bgColor_, opa);
219
220    // draw middle rectangle
221    Rect middleRect(col1X, row2Y + 1, col4X, row3Y - 1);
222    drawUtils->DrawColorArea(gfxDstBuffer, middleRect, dirtyRect, style.bgColor_, opa);
223
224    // draw bottom rectangle
225    Rect bottomRect(col2X + 1, row3Y, col3X - 1, row4Y);
226    drawUtils->DrawColorArea(gfxDstBuffer, bottomRect, dirtyRect, style.bgColor_, opa);
227
228    Style arcStyle = style;
229    arcStyle.lineWidth_ = radius;
230    arcStyle.lineColor_ = style.bgColor_;
231    arcStyle.lineOpa_ = style.bgOpa_;
232    // top left sector
233    ArcInfo arcInfo;
234    arcInfo.center = {col2X, row2Y};
235    arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
236    arcInfo.endAngle = CIRCLE_IN_DEGREE;
237    arcInfo.radius = radius;
238    arcInfo.imgPos = {0, 0};
239    arcInfo.imgSrc = nullptr;
240    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
241    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
242
243    // top right sector
244    arcInfo.center = {col3X, row2Y};
245    arcInfo.startAngle = 0;
246    arcInfo.endAngle = QUARTER_IN_DEGREE;
247    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
248
249    // bottom left sector
250    arcInfo.center = {col2X, row3Y};
251    arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
252    arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
253    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
254
255    // bottom right sector
256    arcInfo.center = {col3X, row3Y};
257    arcInfo.startAngle = QUARTER_IN_DEGREE;
258    arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
259    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
260}
261
262void DrawRect::DrawRectBorderWithoutRadius(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
263                                           const Style& style, OpacityType opaScale)
264{
265    int16_t col1X = rect.GetLeft();
266    int16_t col2X = rect.GetLeft() + style.borderWidth_ - 1;
267    int16_t col3X = rect.GetRight() - style.borderWidth_ + 1;
268    int16_t col4X = rect.GetRight();
269
270    int16_t row1Y = rect.GetTop();
271    int16_t row2Y = rect.GetTop() + style.borderWidth_ - 1;
272    int16_t row3Y = rect.GetBottom() - style.borderWidth_ + 1;
273    int16_t row4Y = rect.GetBottom();
274
275    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
276    // draw top border
277    Rect topRect(col1X, row1Y, col4X, row2Y);
278    DrawUtils* drawUtils = DrawUtils::GetInstance();
279    drawUtils->DrawColorArea(gfxDstBuffer, topRect, dirtyRect, style.borderColor_, opa);
280
281    // draw left border
282    Rect leftRect(col1X, row2Y + 1, col2X, row3Y - 1);
283    drawUtils->DrawColorArea(gfxDstBuffer, leftRect, dirtyRect, style.borderColor_, opa);
284
285    OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
286    // draw middle rectangle
287    Rect middleRect(col2X + 1, row2Y + 1, col3X - 1, row3Y - 1);
288    drawUtils->DrawColorArea(gfxDstBuffer, middleRect, dirtyRect, style.bgColor_, opaBg);
289
290    // draw right border
291    Rect rightRect(col3X, row2Y + 1, col4X, row3Y - 1);
292    drawUtils->DrawColorArea(gfxDstBuffer, rightRect, dirtyRect, style.borderColor_, opa);
293
294    // draw bottom border
295    Rect bottomRect(col1X, row3Y, col4X, row4Y);
296    drawUtils->DrawColorArea(gfxDstBuffer, bottomRect, dirtyRect, style.borderColor_, opa);
297}
298
299void DrawRect::DrawRectRadiusEqualBorder(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
300                                         const Style& style, OpacityType opaScale)
301{
302    int16_t col1X = rect.GetLeft();
303    int16_t col2X = rect.GetLeft() + style.borderRadius_ - 1;
304    int16_t col3X = rect.GetRight() - style.borderRadius_ + 1;
305    int16_t col4X = rect.GetRight();
306
307    int16_t row1Y = rect.GetTop();
308    int16_t row2Y = rect.GetTop() + style.borderRadius_ - 1;
309    int16_t row3Y = rect.GetBottom() - style.borderRadius_ + 1;
310    int16_t row4Y = rect.GetBottom();
311
312    Style arcStyle = style;
313    arcStyle.lineWidth_ = style.borderWidth_;
314    arcStyle.lineColor_ = style.borderColor_;
315    arcStyle.lineOpa_ = style.borderOpa_;
316    // draw top left sector in border
317    ArcInfo arcInfo;
318    arcInfo.center = {col2X, row2Y};
319    arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
320    arcInfo.endAngle = CIRCLE_IN_DEGREE;
321    arcInfo.radius = style.borderRadius_;
322    arcInfo.imgPos = {0, 0};
323    arcInfo.imgSrc = nullptr;
324    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
325    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
326
327    // draw top right sector in border
328    arcInfo.center = {col3X, row2Y};
329    arcInfo.startAngle = 0;
330    arcInfo.endAngle = QUARTER_IN_DEGREE;
331    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
332
333    // draw bottom left sector in border
334    arcInfo.center = {col2X, row3Y};
335    arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
336    arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
337    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
338
339    // draw bottom right sector in border
340    arcInfo.center = {col3X, row3Y};
341    arcInfo.startAngle = QUARTER_IN_DEGREE;
342    arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
343    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
344
345    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
346    // draw top rectangle in border
347    Rect topRect(col2X, row1Y, col3X - 1, row2Y);
348    DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, topRect, dirtyRect, style.borderColor_, opa);
349
350    // draw left rectangle in border
351    Rect leftRect(col1X, row2Y + 1, col2X, row3Y - 1);
352    DrawUtils* drawUtils = DrawUtils::GetInstance();
353    drawUtils->DrawColorArea(gfxDstBuffer, leftRect, dirtyRect, style.borderColor_, opa);
354
355    OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
356    // draw middle rectangle
357    Rect middleRect(col2X + 1, row2Y + 1, col3X - 1, row3Y - 1);
358    drawUtils->DrawColorArea(gfxDstBuffer, middleRect, dirtyRect, style.bgColor_, opaBg);
359
360    // draw right rectangle in border
361    Rect rightRect(col3X, row2Y + 1, col4X, row3Y - 1);
362    drawUtils->DrawColorArea(gfxDstBuffer, rightRect, dirtyRect, style.borderColor_, opa);
363
364    // draw bottom rectangle in border
365    Rect bottomRect(col2X + 1, row3Y, col3X - 1, row4Y);
366    drawUtils->DrawColorArea(gfxDstBuffer, bottomRect, dirtyRect, style.borderColor_, opa);
367}
368
369void DrawRect::DrawRectRadiusSmallThanBorder(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
370                                             const Style& style, OpacityType opaScale)
371{
372    int16_t radiusCol1X = rect.GetLeft();
373    int16_t radiusCol2X = rect.GetLeft() + style.borderRadius_ - 1;
374    int16_t radiusCol3X = rect.GetRight() - style.borderRadius_ + 1;
375    int16_t radiusCol4X = rect.GetRight();
376
377    int16_t radiusRow1Y = rect.GetTop();
378    int16_t radiusRow2Y = rect.GetTop() + style.borderRadius_ - 1;
379    int16_t radiusRow3Y = rect.GetBottom() - style.borderRadius_ + 1;
380    int16_t radiusRow4Y = rect.GetBottom();
381
382    int16_t rectCol1X = radiusCol1X;
383    int16_t rectCol2X = rect.GetLeft() + style.borderWidth_ - 1;
384    int16_t rectCol3X = rect.GetRight() - style.borderWidth_ + 1;
385    int16_t rectCol4X = radiusCol4X;
386
387    int16_t rectRow1Y = radiusRow2Y;
388    int16_t rectRow2Y = rect.GetTop() + style.borderWidth_ - 1;
389    int16_t rectRow3Y = rect.GetBottom() - style.borderWidth_ + 1;
390
391    Style arcStyle = style;
392    arcStyle.lineWidth_ = style.borderWidth_;
393    arcStyle.lineColor_ = style.borderColor_;
394    arcStyle.lineOpa_ = style.borderOpa_;
395    // draw top left sector in border
396    ArcInfo arcInfo;
397    arcInfo.center = {radiusCol2X, radiusRow2Y};
398    arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
399    arcInfo.endAngle = CIRCLE_IN_DEGREE;
400    arcInfo.radius = style.borderRadius_;
401    arcInfo.imgPos = {0, 0};
402    arcInfo.imgSrc = nullptr;
403    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
404    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
405
406    // draw top right sector in border
407    arcInfo.center = {radiusCol3X, radiusRow2Y};
408    arcInfo.startAngle = 0;
409    arcInfo.endAngle = QUARTER_IN_DEGREE;
410    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
411
412    // draw bottom left sector in border
413    arcInfo.center = {radiusCol2X, radiusRow3Y};
414    arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
415    arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
416    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
417
418    // draw bottom right sector in border
419    arcInfo.center = {radiusCol3X, radiusRow3Y};
420    arcInfo.startAngle = QUARTER_IN_DEGREE;
421    arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
422    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
423
424    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
425    // draw top rectangle in border
426    Rect topRect(radiusCol2X, radiusRow1Y, radiusCol3X - 1, radiusRow2Y);
427    DrawUtils* drawUtils = DrawUtils::GetInstance();
428    drawUtils->DrawColorArea(gfxDstBuffer, topRect, dirtyRect, style.borderColor_, opa);
429    Rect topRect2(rectCol1X, rectRow1Y + 1, rectCol4X, rectRow2Y);
430    drawUtils->DrawColorArea(gfxDstBuffer, topRect2, dirtyRect, style.borderColor_, opa);
431
432    // draw left rectangle in border
433    Rect leftRect(rectCol1X, rectRow2Y + 1, rectCol2X, rectRow3Y - 1);
434    drawUtils->DrawColorArea(gfxDstBuffer, leftRect, dirtyRect, style.borderColor_, opa);
435
436    OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
437    // draw middle rectangle
438    Rect middleRect(rectCol2X + 1, rectRow2Y + 1, rectCol3X - 1, rectRow3Y - 1);
439    drawUtils->DrawColorArea(gfxDstBuffer, middleRect, dirtyRect, style.bgColor_, opaBg);
440
441    // draw right rectangle in border
442    Rect rightRect(rectCol3X, rectRow2Y + 1, rectCol4X, rectRow3Y - 1);
443    drawUtils->DrawColorArea(gfxDstBuffer, rightRect, dirtyRect, style.borderColor_, opa);
444
445    // draw bottom rectangle in border
446    Rect bottomRect(radiusCol2X + 1, radiusRow3Y, radiusCol3X - 1, radiusRow4Y);
447    drawUtils->DrawColorArea(gfxDstBuffer, bottomRect, dirtyRect, style.borderColor_, opa);
448    Rect bottomRect2(rectCol1X, rectRow3Y, rectCol4X, radiusRow3Y - 1);
449    drawUtils->DrawColorArea(gfxDstBuffer, bottomRect2, dirtyRect, style.borderColor_, opa);
450}
451
452void DrawRect::DrawRectRadiusBiggerThanBorder(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
453                                              const Style& style, OpacityType opaScale)
454{
455    // 2 : half
456    if ((rect.GetWidth() > rect.GetHeight()) && (style.borderRadius_ >= rect.GetHeight() / 2)) {
457        DrawRectRadiusBiggerThanBorderCon1(gfxDstBuffer, rect, dirtyRect, style, opaScale);
458    } else if ((rect.GetWidth() < rect.GetHeight()) && (style.borderRadius_ >= rect.GetWidth() / 2)) {
459        DrawRectRadiusBiggerThanBorderCon2(gfxDstBuffer, rect, dirtyRect, style, opaScale);
460    } else if ((rect.GetWidth() == rect.GetHeight()) && (style.borderRadius_ >= rect.GetWidth() / 2)) {
461        DrawRectRadiusBiggerThanBorderCon3(gfxDstBuffer, rect, dirtyRect, style, opaScale);
462    } else {
463        DrawRectRadiusBiggerThanBorderCon4(gfxDstBuffer, rect, dirtyRect, style, opaScale);
464    }
465}
466
467void DrawRect::DrawRectRadiusBiggerThanBorderCon1(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
468                                                  const Style& style, OpacityType opaScale)
469{
470    int16_t radius = rect.GetHeight() / 2;
471    int16_t borderWidth = style.borderWidth_;
472    int16_t col2X = rect.GetLeft() + radius - 1;
473    int16_t col3X = rect.GetRight() - radius + 1;
474
475    int16_t row1Y = rect.GetTop();
476    int16_t row2Y = rect.GetTop() + borderWidth - 1;
477    int16_t row3Y = rect.GetTop() + radius - 1;
478    int16_t row4Y = rect.GetBottom() - borderWidth + 1;
479    int16_t row5Y = rect.GetBottom();
480
481    Style arcStyle = style;
482    arcStyle.lineWidth_ = borderWidth;
483    arcStyle.lineColor_ = style.borderColor_;
484    arcStyle.lineOpa_ = style.borderOpa_;
485    // draw left arc in border
486    ArcInfo arcInfo;
487    arcInfo.center = {col2X, row3Y};
488    arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
489    arcInfo.endAngle = CIRCLE_IN_DEGREE;
490    arcInfo.radius = radius;
491    arcInfo.imgPos = {0, 0};
492    arcInfo.imgSrc = nullptr;
493
494    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
495    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
496    // draw right arc in border
497    arcInfo.center = {col3X, row3Y};
498    arcInfo.startAngle = 0;
499    arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
500    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
501
502    radius = radius - borderWidth;
503    arcStyle.lineWidth_ = radius;
504    arcStyle.lineColor_ = style.bgColor_;
505    arcStyle.lineOpa_ = style.bgOpa_;
506
507    // draw left sector in rectangle
508    arcInfo.center = {col2X, row3Y};
509    arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
510    arcInfo.endAngle = CIRCLE_IN_DEGREE;
511    arcInfo.radius = radius;
512    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
513    // draw right sector in rectangle
514    arcInfo.center = {col3X, row3Y};
515    arcInfo.startAngle = 0;
516    arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
517    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
518
519    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
520    // top rectangle in border
521    Rect topBorderRect(col2X, row1Y, col3X - 1, row2Y);
522    DrawUtils* drawUtils = DrawUtils::GetInstance();
523    drawUtils->DrawColorArea(gfxDstBuffer, topBorderRect, dirtyRect, style.borderColor_, opa);
524    OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
525    // middle rectangle inner
526    Rect middleInnerRect(col2X, row2Y + 1, col3X - 1, row3Y);
527    drawUtils->DrawColorArea(gfxDstBuffer, middleInnerRect, dirtyRect, style.bgColor_, opaBg);
528    Rect middleInnerRect2(col2X + 1, row3Y + 1, col3X - 1, row4Y - 1);
529    drawUtils->DrawColorArea(gfxDstBuffer, middleInnerRect2, dirtyRect, style.bgColor_, opaBg);
530
531    // bottom rectangle in border
532    Rect bottomBorderRect(col2X + 1, row4Y, col3X - 1, row5Y);
533    drawUtils->DrawColorArea(gfxDstBuffer, bottomBorderRect, dirtyRect, style.borderColor_, opa);
534}
535
536void DrawRect::DrawRectRadiusBiggerThanBorderCon2(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
537                                                  const Style& style, OpacityType opaScale)
538{
539    int16_t radius = rect.GetWidth() / 2;
540    int16_t borderWidth = style.borderWidth_;
541    int16_t col1X = rect.GetLeft();
542    int16_t col2X = rect.GetLeft() + borderWidth - 1;
543    int16_t col3X = rect.GetLeft() + radius - 1;
544    int16_t col4X = rect.GetRight() - borderWidth + 1;
545    int16_t col5X = rect.GetRight();
546
547    int16_t row2Y = rect.GetTop() + radius - 1;
548    int16_t row3Y = rect.GetBottom() - radius + 1;
549
550    Style arcStyle = style;
551    arcStyle.lineWidth_ = borderWidth;
552    arcStyle.lineColor_ = style.borderColor_;
553    arcStyle.lineOpa_ = style.borderOpa_;
554    // draw top arc in border
555    ArcInfo arcInfo;
556    arcInfo.center = {col3X, row2Y};
557    arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
558    arcInfo.endAngle = QUARTER_IN_DEGREE;
559    arcInfo.radius = radius;
560    arcInfo.imgPos = {0, 0};
561    arcInfo.imgSrc = nullptr;
562    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
563    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
564    // draw bottom arc in border
565    arcInfo.center = {col3X, row3Y};
566    arcInfo.startAngle = QUARTER_IN_DEGREE;
567    arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
568    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
569
570    radius = radius - borderWidth;
571    arcStyle.lineWidth_ = radius;
572    arcStyle.lineColor_ = style.bgColor_;
573    arcStyle.lineOpa_ = style.bgOpa_;
574
575    // draw top sector in rectangle
576    arcInfo.center = {col3X, row2Y};
577    arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
578    arcInfo.endAngle = QUARTER_IN_DEGREE;
579    arcInfo.radius = radius;
580    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
581    // draw bottom sector in rectangle
582    arcInfo.center = {col3X, row3Y};
583    arcInfo.startAngle = QUARTER_IN_DEGREE;
584    arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
585    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
586
587    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
588    // left rectangle in border
589    Rect topBorderRect(col1X, row2Y + 1, col2X, row3Y - 1);
590    DrawUtils* drawUtils = DrawUtils::GetInstance();
591    drawUtils->DrawColorArea(gfxDstBuffer, topBorderRect, dirtyRect, style.borderColor_, opa);
592
593    OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
594    // middle rectangle inner
595    Rect middleInnerRect(col2X + 1, row2Y + 1, col4X - 1, row3Y - 1);
596    drawUtils->DrawColorArea(gfxDstBuffer, middleInnerRect, dirtyRect, style.bgColor_, opaBg);
597
598    // right rectangle in border
599    Rect bottomBorderRect(col4X, row2Y + 1, col5X, row3Y - 1);
600    drawUtils->DrawColorArea(gfxDstBuffer, bottomBorderRect, dirtyRect, style.borderColor_, opa);
601}
602
603void DrawRect::DrawRectRadiusBiggerThanBorderCon3(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
604                                                  const Style& style, OpacityType opaScale)
605{
606    int16_t radius = rect.GetWidth() / 2;
607    int16_t borderWidth = style.borderWidth_;
608    int16_t col2X = rect.GetLeft() + radius - 1;
609    int16_t row2Y = rect.GetTop() + radius - 1;
610
611    Style arcStyle = style;
612    arcStyle.lineWidth_ = borderWidth;
613    arcStyle.lineColor_ = style.borderColor_;
614    arcStyle.lineOpa_ = style.borderOpa_;
615    // draw circle in border
616    ArcInfo arcInfo;
617    arcInfo.center = {col2X, row2Y};
618    arcInfo.startAngle = 0;
619    arcInfo.endAngle = CIRCLE_IN_DEGREE;
620    arcInfo.radius = radius;
621    arcInfo.imgPos = {0, 0};
622    arcInfo.imgSrc = nullptr;
623    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
624    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
625
626    radius = radius - borderWidth;
627    arcStyle.lineWidth_ = radius;
628    arcStyle.lineColor_ = style.bgColor_;
629    arcStyle.lineOpa_ = style.bgOpa_;
630
631    // draw circle in rectangle
632    arcInfo.center = {col2X, row2Y};
633    arcInfo.startAngle = 0;
634    arcInfo.endAngle = CIRCLE_IN_DEGREE;
635    arcInfo.radius = radius;
636    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
637}
638
639void DrawRect::DrawRectRadiusBiggerThanBorderCon4(BufferInfo& gfxDstBuffer, const Rect& rect, const Rect& dirtyRect,
640                                                  const Style& style, OpacityType opaScale)
641{
642    int16_t radius = style.borderRadius_;
643    int16_t borderWidth = style.borderWidth_;
644    int16_t col1X = rect.GetLeft();
645    int16_t col2X = rect.GetLeft() + borderWidth - 1;
646    int16_t col3X = rect.GetLeft() + radius - 1;
647    int16_t col4X = rect.GetRight() - radius + 1;
648    int16_t col5X = rect.GetRight() - borderWidth + 1;
649    int16_t col6X = rect.GetRight();
650
651    int16_t row1Y = rect.GetTop();
652    int16_t row2Y = rect.GetTop() + borderWidth - 1;
653    int16_t row3Y = rect.GetTop() + radius - 1;
654    int16_t row4Y = rect.GetBottom() - radius + 1;
655    int16_t row5Y = rect.GetBottom() - borderWidth + 1;
656    int16_t row6Y = rect.GetBottom();
657
658    Style arcStyle = style;
659    arcStyle.lineWidth_ = borderWidth;
660    arcStyle.lineColor_ = style.borderColor_;
661    arcStyle.lineOpa_ = style.borderOpa_;
662
663    // draw top left arc in border
664    ArcInfo arcInfo;
665    arcInfo.center = {col3X, row3Y};
666    arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
667    arcInfo.endAngle = CIRCLE_IN_DEGREE;
668    arcInfo.radius = radius;
669    arcInfo.imgPos = {0, 0};
670    arcInfo.imgSrc = nullptr;
671    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
672    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
673    // draw top right arc in border
674    arcInfo.center = {col4X, row3Y};
675    arcInfo.startAngle = 0;
676    arcInfo.endAngle = QUARTER_IN_DEGREE;
677    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
678    // draw bottom left arc in border
679    arcInfo.center = {col3X, row4Y};
680    arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
681    arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
682    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
683    // draw bottom right arc in border
684    arcInfo.center = {col4X, row4Y};
685    arcInfo.startAngle = QUARTER_IN_DEGREE;
686    arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
687    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
688
689    radius = radius - borderWidth;
690    arcStyle.lineWidth_ = radius;
691    arcStyle.lineColor_ = style.bgColor_;
692    arcStyle.lineOpa_ = style.bgOpa_;
693
694    // draw top left sector in rectangle
695    arcInfo.center = {col3X, row3Y};
696    arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
697    arcInfo.endAngle = CIRCLE_IN_DEGREE;
698    arcInfo.radius = radius;
699    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
700    // draw top right sector in rectangle
701    arcInfo.center = {col4X, row3Y};
702    arcInfo.startAngle = 0;
703    arcInfo.endAngle = QUARTER_IN_DEGREE;
704    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
705    // draw bottom left sector in rectangle
706    arcInfo.center = {col3X, row4Y};
707    arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
708    arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
709    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
710    // draw bottom right sector in rectangle
711    arcInfo.center = {col4X, row4Y};
712    arcInfo.startAngle = QUARTER_IN_DEGREE;
713    arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
714    baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
715
716    OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
717    // top rectangle in border
718    Rect topBorderRect(col3X, row1Y, col4X - 1, row2Y);
719    DrawUtils::GetInstance()->DrawColorArea(gfxDstBuffer, topBorderRect, dirtyRect, style.borderColor_, opa);
720
721    OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
722    // top rectangle inner
723    Rect topInnerRect(col3X, row2Y + 1, col4X - 1, row3Y);
724    DrawUtils* drawUtils = DrawUtils::GetInstance();
725    drawUtils->DrawColorArea(gfxDstBuffer, topInnerRect, dirtyRect, style.bgColor_, opaBg);
726
727    // left rectangle in border
728    Rect leftBorderRect(col1X, row3Y + 1, col2X, row4Y - 1);
729    drawUtils->DrawColorArea(gfxDstBuffer, leftBorderRect, dirtyRect, style.borderColor_, opa);
730
731    // middle rectangle inner
732    Rect middleInnerRect(col2X + 1, row3Y + 1, col5X - 1, row4Y - 1);
733    drawUtils->DrawColorArea(gfxDstBuffer, middleInnerRect, dirtyRect, style.bgColor_, opaBg);
734
735    // right rectangle in border
736    Rect rightBorderRect(col5X, row3Y + 1, col6X, row4Y - 1);
737    drawUtils->DrawColorArea(gfxDstBuffer, rightBorderRect, dirtyRect, style.borderColor_, opa);
738
739    // bottom rectangle inner
740    Rect bottomInnerRect(col3X + 1, row4Y, col4X - 1, row5Y - 1);
741    drawUtils->DrawColorArea(gfxDstBuffer, bottomInnerRect, dirtyRect, style.bgColor_, opaBg);
742
743    // bottom rectangle in border
744    Rect bottomBorderRect(col3X + 1, row5Y, col4X - 1, row6Y);
745    drawUtils->DrawColorArea(gfxDstBuffer, bottomBorderRect, dirtyRect, style.borderColor_, opa);
746}
747} // namespace OHOS
748