1/*
2 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "components/ui_canvas.h"
17
18#include "draw/clip_utils.h"
19#include "draw/draw_arc.h"
20#include "draw/draw_image.h"
21#include "gfx_utils/graphic_log.h"
22#include "render/render_buffer.h"
23#include "render/render_pixfmt_rgba_blend.h"
24#include "render/render_scanline.h"
25#if ( (defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND) )
26#include "draw/draw_canvas.h"
27#endif
28
29namespace OHOS {
30UICanvas::UICanvasPath::~UICanvasPath()
31{
32    points_.Clear();
33    cmd_.Clear();
34    arcParam_.Clear();
35}
36
37BufferInfo* UICanvas::gfxMapBuffer_ = nullptr;
38
39void RenderSolid(const Paint& paint,
40                 RasterizerScanlineAntialias& rasterizer,
41                 RenderBase& renBase,
42                 const bool& isStroke);
43
44void UICanvas::BeginPath()
45{
46#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
47    /* If the previous path is not added to the drawing linked list, it should be destroyed directly. */
48    if (vertices_ != nullptr && vertices_->GetTotalVertices() == 0) {
49        delete vertices_;
50        vertices_ = nullptr;
51    }
52
53    vertices_ = new UICanvasVertices();
54    if (vertices_ == nullptr) {
55        GRAPHIC_LOGE("new UICanvasVertices fail");
56        return;
57    }
58#else
59    if (path_ != nullptr && path_->strokeCount_ == 0) {
60        delete path_;
61        path_ = nullptr;
62    }
63
64    path_ = new UICanvasPath();
65    if (path_ == nullptr) {
66        GRAPHIC_LOGE("new UICanvasPath fail");
67        return;
68    }
69#endif
70}
71
72void UICanvas::MoveTo(const Point& point)
73{
74#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
75    if (vertices_ == nullptr) {
76        return;
77    }
78    vertices_->MoveTo(point.x, point.y);
79#else
80    if (path_ == nullptr) {
81        return;
82    }
83
84    path_->startPos_ = point;
85    /* If the previous command is also CMD_MOVE_TO, the previous command is overwritten. */
86    if ((path_->cmd_.Size() != 0) && (path_->cmd_.Tail()->data_ == CMD_MOVE_TO)) {
87        path_->points_.Tail()->data_ = point;
88        return;
89    }
90    path_->points_.PushBack(point);
91    path_->cmd_.PushBack(CMD_MOVE_TO);
92#endif
93}
94
95void UICanvas::LineTo(const Point& point)
96{
97#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
98    if (vertices_ == nullptr) {
99        return;
100    }
101    vertices_->LineTo(point.x, point.y);
102#else
103    if (path_ == nullptr) {
104        return;
105    }
106
107    path_->points_.PushBack(point);
108    if (path_->cmd_.Size() == 0) {
109        path_->startPos_ = point;
110        path_->cmd_.PushBack(CMD_MOVE_TO);
111    } else {
112        path_->cmd_.PushBack(CMD_LINE_TO);
113    }
114#endif
115}
116
117void UICanvas::ArcTo(const Point& center, uint16_t radius, int16_t startAngle, int16_t endAngle)
118{
119#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
120    if (vertices_ == nullptr || startAngle == endAngle) {
121        return;
122    }
123    float sinma = radius * Sin(startAngle);
124    float cosma = radius * Sin(QUARTER_IN_DEGREE - startAngle);
125    if (vertices_->GetTotalVertices() != 0) {
126        vertices_->LineTo(float(center.x + sinma), float(center.y - cosma));
127    } else {
128        vertices_->MoveTo(float(center.x + sinma), float(center.y - cosma));
129    }
130    if (MATH_ABS(startAngle - endAngle) < CIRCLE_IN_DEGREE) {
131        sinma = radius * Sin(endAngle);
132        cosma = radius * Sin(QUARTER_IN_DEGREE - endAngle);
133    }
134    int16_t angle = endAngle - startAngle;
135    bool largeArcFlag = false;
136    if (angle > SEMICIRCLE_IN_DEGREE || angle <= 0) {
137        largeArcFlag = true;
138    }
139    vertices_->ArcTo(radius, radius, angle, largeArcFlag, 1, float(center.x + sinma), float(center.y - cosma));
140#else
141    if (path_ == nullptr) {
142        return;
143    }
144
145    /*
146     * If there is no command before CMD_ARC, only the arc is drawn. If there is a command in front of
147     * CMD_ARC, the start point of arc must be connected to the end point of the path.
148     */
149    float sinma = radius * Sin(startAngle);
150    float cosma = radius * Sin(QUARTER_IN_DEGREE - startAngle);
151    if (path_->cmd_.Size() != 0) {
152        path_->points_.PushBack({MATH_ROUND(center.x + sinma), MATH_ROUND(center.y - cosma)});
153        path_->cmd_.PushBack(CMD_LINE_TO);
154    } else {
155        path_->startPos_ = {MATH_ROUND(center.x + sinma), MATH_ROUND(center.y - cosma)};
156    }
157
158    /* If the ARC scan range exceeds 360 degrees, the end point of the path is the position of the start angle. */
159    if (MATH_ABS(startAngle - endAngle) < CIRCLE_IN_DEGREE) {
160        sinma = radius * Sin(endAngle);
161        cosma = radius * Sin(QUARTER_IN_DEGREE - endAngle);
162    }
163    path_->points_.PushBack({MATH_ROUND(center.x + sinma), MATH_ROUND(center.y - cosma)});
164    path_->cmd_.PushBack(CMD_ARC);
165
166    SetArcParamInfo(center, radius, startAngle, endAngle);
167#endif
168}
169
170void UICanvas::SetArcParamInfo(const Point& center, uint16_t radius, int16_t startAngle, int16_t endAngle)
171{
172    int16_t start;
173    int16_t end;
174    if (startAngle > endAngle) {
175        start = endAngle;
176        end = startAngle;
177    } else {
178        start = startAngle;
179        end = endAngle;
180    }
181
182    DrawArc::GetInstance()->GetDrawRange(start, end);
183    ArcParam param;
184    param.center = center;
185    param.radius = radius;
186    param.startAngle = start;
187    param.endAngle = end;
188    path_->arcParam_.PushBack(param);
189}
190
191void UICanvas::AddRect(const Point& point, int16_t height, int16_t width)
192{
193#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
194    if (vertices_ == nullptr) {
195        return;
196    }
197
198    int16_t right = static_cast<int16_t>(point.x + width);
199    int16_t bottom = point.y + height;
200
201    float fRight = static_cast<float>(width) + static_cast<float>(point.x);
202    float fBottom = static_cast<float>(height) + static_cast<float>(point.y);
203    const int16_t setup = 3;
204    if (fRight > INT16_MAX) {
205        right += setup;
206    }
207    if (fBottom > INT16_MAX) {
208        bottom += setup;
209    }
210
211    MoveTo(point);
212    LineTo({right, point.y});
213    LineTo({right, bottom});
214    LineTo({point.x, bottom});
215#else
216    if (path_ == nullptr) {
217        return;
218    }
219
220    MoveTo(point);
221    LineTo({static_cast<int16_t>(point.x + width), point.y});
222    LineTo({static_cast<int16_t>(point.x + width), static_cast<int16_t>(point.y + height)});
223    LineTo({point.x, static_cast<int16_t>(point.y + height)});
224
225#endif
226    ClosePath();
227}
228
229void UICanvas::ClosePath()
230{
231#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
232    if (vertices_ == nullptr) {
233        return;
234    }
235    vertices_->ClosePolygon();
236#else
237    if ((path_ == nullptr) || (path_->cmd_.Size() == 0)) {
238        return;
239    }
240
241    path_->points_.PushBack(path_->startPos_);
242    path_->cmd_.PushBack(CMD_CLOSE);
243#endif
244}
245
246UICanvas::~UICanvas()
247{
248    if ((path_ != nullptr) && (path_->strokeCount_ == 0)) {
249        delete path_;
250        path_ = nullptr;
251    }
252    void* param = nullptr;
253    ListNode<DrawCmd>* curDraw = drawCmdList_.Begin();
254    for (; curDraw != drawCmdList_.End(); curDraw = curDraw->next_) {
255        param = curDraw->data_.param;
256        curDraw->data_.DeleteParam(param);
257        curDraw->data_.param = nullptr;
258    }
259    drawCmdList_.Clear();
260    if (vertices_ != nullptr) {
261        delete vertices_;
262        vertices_ = nullptr;
263    }
264    DestroyMapBufferInfo();
265}
266
267void UICanvas::Clear()
268{
269    if ((path_ != nullptr) && (path_->strokeCount_ == 0)) {
270        delete path_;
271        path_ = nullptr;
272    }
273    void* param = nullptr;
274    ListNode<DrawCmd>* curDraw = drawCmdList_.Begin();
275    for (; curDraw != drawCmdList_.End(); curDraw = curDraw->next_) {
276        param = curDraw->data_.param;
277        curDraw->data_.DeleteParam(param);
278        curDraw->data_.param = nullptr;
279    }
280    drawCmdList_.Clear();
281    if (vertices_ != nullptr) {
282        delete vertices_;
283        vertices_ = nullptr;
284    }
285    Invalidate();
286}
287
288void UICanvas::DeleteImageParam(void* param)
289{
290    ImageParam* imageParam = static_cast<ImageParam*>(param);
291    if (imageParam->image != nullptr) {
292        delete imageParam->image;
293        imageParam->image = nullptr;
294    }
295    delete imageParam;
296    imageParam = nullptr;
297}
298
299void UICanvas::DeletePathParam(void* param)
300{
301    PathParam* pathParam = static_cast<PathParam*>(param);
302#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
303    if (pathParam->vertices != nullptr) {
304        pathParam->vertices->FreeAll();
305        pathParam->vertices = nullptr;
306    }
307    if (pathParam->imageParam != nullptr) {
308        DeleteImageParam(pathParam->imageParam);
309    }
310#else
311    pathParam->path->strokeCount_--;
312    if (pathParam->path->strokeCount_ == 0) {
313        delete pathParam->path;
314    }
315#endif
316    delete pathParam;
317    pathParam = nullptr;
318}
319
320void UICanvas::DrawLine(const Point& endPoint, const Paint& paint)
321{
322    DrawLine(startPoint_, endPoint, paint);
323}
324
325void UICanvas::DrawLine(const Point& startPoint, const Point& endPoint, const Paint& paint)
326{
327    LineParam* lineParam = new LineParam;
328    if (lineParam == nullptr) {
329        GRAPHIC_LOGE("new LineParam fail");
330        return;
331    }
332    lineParam->start = startPoint;
333    lineParam->end = endPoint;
334
335    DrawCmd cmd;
336    cmd.paint = paint;
337    cmd.param = lineParam;
338    cmd.DeleteParam = DeleteLineParam;
339    cmd.DrawGraphics = DoDrawLine;
340    drawCmdList_.PushBack(cmd);
341
342    Invalidate();
343    SetStartPosition(endPoint);
344}
345
346void UICanvas::DrawCurve(const Point& control1, const Point& control2, const Point& endPoint, const Paint& paint)
347{
348    DrawCurve(startPoint_, control1, control2, endPoint, paint);
349}
350
351void UICanvas::DrawCurve(const Point& startPoint,
352                         const Point& control1,
353                         const Point& control2,
354                         const Point& endPoint,
355                         const Paint& paint)
356{
357    CurveParam* curveParam = new CurveParam;
358    if (curveParam == nullptr) {
359        GRAPHIC_LOGE("new CurveParam fail");
360        return;
361    }
362    curveParam->start = startPoint;
363    curveParam->control1 = control1;
364    curveParam->control2 = control2;
365    curveParam->end = endPoint;
366
367    DrawCmd cmd;
368    cmd.paint = paint;
369    if (paint.GetStrokeWidth() > MAX_CURVE_WIDTH) {
370        cmd.paint.SetStrokeWidth(MAX_CURVE_WIDTH);
371    }
372    cmd.param = curveParam;
373    cmd.DeleteParam = DeleteCurveParam;
374    cmd.DrawGraphics = DoDrawCurve;
375    drawCmdList_.PushBack(cmd);
376
377    Invalidate();
378    SetStartPosition(endPoint);
379}
380
381void UICanvas::DrawRect(const Point& startPoint, int16_t height, int16_t width, const Paint& paint)
382{
383#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
384    SetDrawLinePath(startPoint, height, width, paint);
385#else
386    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE) {
387        RectParam* rectParam = new RectParam;
388        if (rectParam == nullptr) {
389            GRAPHIC_LOGE("new RectParam fail");
390            return;
391        }
392        rectParam->start = startPoint;
393        rectParam->height = height;
394        rectParam->width = width;
395
396        DrawCmd cmd;
397        cmd.paint = paint;
398        cmd.param = rectParam;
399        cmd.DeleteParam = DeleteRectParam;
400        cmd.DrawGraphics = DoDrawRect;
401        drawCmdList_.PushBack(cmd);
402    }
403
404    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
405        RectParam* rectParam = new RectParam;
406        if (rectParam == nullptr) {
407            GRAPHIC_LOGE("new RectParam fail");
408            return;
409        }
410        rectParam->start = startPoint;
411        rectParam->height = height;
412        rectParam->width = width;
413
414        DrawCmd cmd;
415        cmd.paint = paint;
416        cmd.param = rectParam;
417        cmd.DeleteParam = DeleteRectParam;
418        cmd.DrawGraphics = DoFillRect;
419        drawCmdList_.PushBack(cmd);
420    }
421#endif
422    Invalidate();
423}
424
425#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
426void UICanvas::SetDrawLinePath(const Point& startPoint, int16_t height, int16_t width, const Paint& paint)
427{
428    if (!paint.GetChangeFlag()) {
429        if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE) {
430            DrawRectSetCmd(startPoint, height, width, paint, Paint::PaintStyle::STROKE_STYLE);
431        }
432
433        if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
434            DrawRectSetCmd(startPoint, height, width, paint, Paint::PaintStyle::FILL_STYLE);
435        }
436    } else {
437        BeginPath();
438        MoveTo(startPoint);
439        LineTo({static_cast<int16_t>(startPoint.x + width), startPoint.y});
440        LineTo({static_cast<int16_t>(startPoint.x + width), static_cast<int16_t>(startPoint.y + height)});
441        LineTo({startPoint.x, static_cast<int16_t>(startPoint.y + height)});
442        ClosePath();
443        FillPath(paint);
444        DrawPath(paint);
445    }
446}
447#endif
448
449void UICanvas::DrawRectSetCmd(const Point& startPoint, int16_t height, int16_t width, const Paint& paint,
450                              Paint::PaintStyle paintStyle)
451{
452    RectParam* rectParam = new RectParam;
453    if (rectParam == nullptr) {
454        GRAPHIC_LOGE("new RectParam fail");
455        return;
456    }
457    rectParam->start = startPoint;
458    rectParam->height = height;
459    rectParam->width = width;
460
461    DrawCmd cmd;
462    cmd.paint = paint;
463    cmd.param = rectParam;
464    cmd.DeleteParam = DeleteRectParam;
465    if (paintStyle == Paint::PaintStyle::STROKE_STYLE) {
466        cmd.DrawGraphics = DoDrawRect;
467    } else if (paintStyle == Paint::PaintStyle::FILL_STYLE) {
468        cmd.DrawGraphics = DoFillRect;
469    }
470    drawCmdList_.PushBack(cmd);
471}
472
473#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
474void UICanvas::StrokeRect(const Point& startPoint, int16_t height, int16_t width, const Paint& paint)
475{
476    if (!paint.GetChangeFlag()) {
477        RectParam* rectParam = new RectParam;
478        if (rectParam == nullptr) {
479            GRAPHIC_LOGE("new RectParam fail");
480            return;
481        }
482        rectParam->start = startPoint;
483        rectParam->height = height;
484        rectParam->width = width;
485
486        DrawCmd cmd;
487        cmd.paint = paint;
488        cmd.param = rectParam;
489        cmd.DeleteParam = DeleteRectParam;
490        cmd.DrawGraphics = DoDrawRect;
491        drawCmdList_.PushBack(cmd);
492    } else {
493        BeginPath();
494        MoveTo(startPoint);
495        LineTo({static_cast<int16_t>(startPoint.x + width), startPoint.y});
496        LineTo({static_cast<int16_t>(startPoint.x + width), static_cast<int16_t>(startPoint.y + height)});
497        LineTo({startPoint.x, static_cast<int16_t>(startPoint.y + height)});
498        ClosePath();
499        DrawPath(paint);
500    }
501    SetStartPosition(startPoint);
502}
503
504void UICanvas::ClearRect(const Point& startPoint, int16_t height, int16_t width)
505{
506    Paint paint;
507    paint.SetFillColor(this->style_->bgColor_);
508    paint.SetStyle(Paint::FILL_STYLE);
509    BeginPath();
510    MoveTo(startPoint);
511    LineTo({static_cast<int16_t>(startPoint.x + width), startPoint.y});
512    LineTo({static_cast<int16_t>(startPoint.x + width), static_cast<int16_t>(startPoint.y + height)});
513    LineTo({startPoint.x, static_cast<int16_t>(startPoint.y + height)});
514    ClosePath();
515    FillPath(paint);
516}
517#endif
518
519void UICanvas::DrawCircle(const Point& center, uint16_t radius, const Paint& paint)
520{
521#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
522    if (paint.GetChangeFlag()) {
523#if defined(GRAPHIC_ENABLE_BEZIER_ARC_FLAG) && GRAPHIC_ENABLE_BEZIER_ARC_FLAG
524        if (vertices_ == nullptr) {
525            vertices_ = new UICanvasVertices();
526        }
527        vertices_->RemoveAll();
528        BezierArc arc(center.x, center.y, radius, radius, 0, TWO_TIMES * PI);
529        vertices_->ConcatPath(arc, 0);
530        vertices_->ClosePolygon();
531        if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE) {
532            DrawPath(paint);
533        }
534        if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
535            FillPath(paint);
536        }
537#endif
538    } else {
539        CircleParam* circleParam = new CircleParam;
540        if (circleParam == nullptr) {
541            GRAPHIC_LOGE("new CircleParam fail");
542            return;
543        }
544        circleParam->center = center;
545        circleParam->radius = radius;
546
547        DrawCmd cmd;
548        cmd.paint = paint;
549        cmd.param = circleParam;
550        cmd.DeleteParam = DeleteCircleParam;
551        cmd.DrawGraphics = DoDrawCircle;
552        drawCmdList_.PushBack(cmd);
553    }
554#else
555    CircleParam* circleParam = new CircleParam;
556    if (circleParam == nullptr) {
557        GRAPHIC_LOGE("new CircleParam fail");
558        return;
559    }
560    circleParam->center = center;
561    circleParam->radius = radius;
562
563    DrawCmd cmd;
564    cmd.paint = paint;
565    cmd.param = circleParam;
566    cmd.DeleteParam = DeleteCircleParam;
567    cmd.DrawGraphics = DoDrawCircle;
568    drawCmdList_.PushBack(cmd);
569#endif
570    Invalidate();
571}
572
573void UICanvas::DrawSector(const Point& center,
574                          uint16_t radius,
575                          int16_t startAngle,
576                          int16_t endAngle,
577                          const Paint& paint)
578{
579#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
580    BeginPath();
581    MoveTo(center);
582    ArcTo(center, radius, startAngle, endAngle);
583    ClosePath();
584    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE) {
585        DrawPath(paint);
586    }
587    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
588        FillPath(paint);
589    }
590#else
591    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
592        Paint innerPaint = paint;
593        innerPaint.SetStyle(Paint::PaintStyle::STROKE_STYLE);
594        innerPaint.SetStrokeWidth(radius);
595        innerPaint.SetStrokeColor(paint.GetFillColor());
596        radius >>= 1;
597        DrawArc(center, radius, startAngle, endAngle, innerPaint);
598    }
599#endif
600}
601
602void UICanvas::DrawArc(const Point& center, uint16_t radius, int16_t startAngle,
603                       int16_t endAngle, const Paint& paint)
604{
605    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE) {
606#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
607        if (paint.GetChangeFlag()) {
608            ArcTo(center, radius, startAngle, endAngle);
609            DrawPath(paint);
610        } else
611#endif
612        {
613            ArcParam* arcParam = new ArcParam;
614            if (arcParam == nullptr) {
615                GRAPHIC_LOGE("new ArcParam fail");
616                return;
617            }
618            arcParam->center = center;
619            arcParam->radius = radius;
620
621            int16_t start;
622            int16_t end;
623            if (startAngle > endAngle) {
624                start = endAngle;
625                end = startAngle;
626            } else {
627                start = startAngle;
628                end = endAngle;
629            }
630
631            DrawArc::GetInstance()->GetDrawRange(start, end);
632            arcParam->startAngle = start;
633            arcParam->endAngle = end;
634
635            DrawCmd cmd;
636            cmd.paint = paint;
637            cmd.param = arcParam;
638            cmd.DeleteParam = DeleteArcParam;
639            cmd.DrawGraphics = DoDrawArc;
640            drawCmdList_.PushBack(cmd);
641        }
642        Invalidate();
643    }
644}
645
646void UICanvas::DrawLabel(const Point& startPoint,
647                         const char* text,
648                         uint16_t maxWidth,
649                         const FontStyle& fontStyle,
650                         const Paint& paint)
651{
652    if (text == nullptr) {
653        return;
654    }
655    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
656        UILabel* label = new UILabel();
657        if (label == nullptr) {
658            GRAPHIC_LOGE("new UILabel fail");
659            return;
660        }
661        label->SetLineBreakMode(UILabel::LINE_BREAK_CLIP);
662        label->SetPosition(startPoint.x, startPoint.y);
663        label->SetWidth(maxWidth);
664        label->SetHeight(GetHeight());
665        label->SetText(text);
666        label->SetFont(fontStyle.fontName, fontStyle.fontSize);
667        label->SetAlign(fontStyle.align);
668        label->SetDirect(fontStyle.direct);
669        label->SetStyle(STYLE_LETTER_SPACE, fontStyle.letterSpace);
670        label->SetStyle(STYLE_TEXT_COLOR, paint.GetFillColor().full);
671        label->SetStyle(STYLE_TEXT_OPA, paint.GetOpacity());
672
673        DrawCmd cmd;
674        cmd.param = label;
675        cmd.DeleteParam = DeleteLabel;
676        cmd.DrawGraphics = DoDrawLabel;
677        drawCmdList_.PushBack(cmd);
678
679        Invalidate();
680    }
681}
682#if defined(GRAPHIC_ENABLE_DRAW_IMAGE_FLAG) && GRAPHIC_ENABLE_DRAW_IMAGE_FLAG
683void UICanvas::DrawImage(const Point &startPoint, const char* image, const Paint& paint)
684{
685    if (image == nullptr) {
686        return;
687    }
688    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
689        UIExtendImageView* imageView = new UIExtendImageView();
690        if (imageView == nullptr) {
691            GRAPHIC_LOGE("new UIImageView fail");
692            return;
693        }
694        imageView->SetCanvas(this);
695        imageView->SetPosition(startPoint.x, startPoint.y);
696        imageView->SetSrc(image);
697
698        DrawCmd cmd;
699        cmd.paint = paint;
700        cmd.param = imageView;
701        cmd.DeleteParam = DeleteImageView;
702        cmd.DrawGraphics = DoDrawImage;
703        drawCmdList_.PushBack(cmd);
704
705        Invalidate();
706        SetStartPosition(startPoint);
707    }
708}
709
710void UICanvas::DrawImage(const Point& startPoint, const char* image,
711                         const Paint& paint, int16_t width, int16_t height)
712{
713    if (image == nullptr) {
714        return;
715    }
716    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
717        UIExtendImageView* imageView = new UIExtendImageView();
718        if (imageView == nullptr) {
719            GRAPHIC_LOGE("new UIImageView fail");
720            return;
721        }
722        imageView->SetCanvas(this);
723        imageView->SetPosition(startPoint.x, startPoint.y);
724        imageView->SetSrc(image);
725        float scaleX = 1.0;
726        float scaleY = 1.0;
727        if (width > 0 && imageView->GetWidth() > 0) {
728            scaleX = (float)width / (float)imageView->GetWidth();
729        }
730        if (height > 0 && imageView->GetHeight() > 0) {
731            scaleY = (float)height / (float)imageView->GetHeight();
732        }
733        DrawCmd cmd;
734        cmd.paint = paint;
735        cmd.paint.Scale(scaleX, scaleY);
736        cmd.param = imageView;
737        cmd.DeleteParam = DeleteImageView;
738        cmd.DrawGraphics = DoDrawImage;
739        drawCmdList_.PushBack(cmd);
740
741        Invalidate();
742        SetStartPosition(startPoint);
743    }
744
745    Invalidate();
746    SetStartPosition(startPoint);
747}
748#endif
749
750#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
751#if defined(GRAPHIC_ENABLE_PATTERN_FILL_FLAG) && GRAPHIC_ENABLE_PATTERN_FILL_FLAG
752void SetImageParamInfo(ImageParam* imageParam, const Paint& paint, PathParam* pathParam)
753{
754    imageParam->image->SetSrc(paint.GetPatternImage());
755    ImageHeader header = {0};
756    imageParam->image->GetHeader(header);
757    imageParam->start = {0, 0};
758    imageParam->height = header.height;
759    imageParam->width = header.width;
760
761    pathParam->imageParam = imageParam;
762}
763#endif
764#endif
765
766void UICanvas::DrawPath(const Paint& paint)
767{
768#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
769    if (vertices_ == nullptr) {
770        return;
771    }
772
773    PathParam* pathParam = new PathParam;
774    if (pathParam == nullptr) {
775        GRAPHIC_LOGE("new LineParam fail");
776        return;
777    }
778
779    pathParam->vertices = vertices_;
780    pathParam->isStroke = true;
781#if defined(GRAPHIC_ENABLE_PATTERN_FILL_FLAG) && GRAPHIC_ENABLE_PATTERN_FILL_FLAG
782    if (paint.GetStyle() == Paint::PATTERN) {
783        ImageParam* imageParam = new ImageParam;
784        if (imageParam == nullptr) {
785            GRAPHIC_LOGE("new ImageParam fail");
786            return;
787        }
788
789        imageParam->image = new Image();
790        if (imageParam->image == nullptr) {
791            delete imageParam;
792            imageParam = nullptr;
793            return;
794        }
795
796        SetImageParamInfo(imageParam, paint, pathParam);
797    }
798#endif
799#else
800    if ((path_ == nullptr) || (path_->cmd_.Size() == 0)) {
801        return;
802    }
803
804    path_->strokeCount_++;
805    PathParam* pathParam = new PathParam;
806    if (pathParam == nullptr) {
807        GRAPHIC_LOGE("new PathParam fail");
808        return;
809    }
810    pathParam->path = path_;
811    pathParam->count = path_->cmd_.Size();
812#endif
813    DrawCmd cmd;
814    cmd.paint = paint;
815    cmd.param = pathParam;
816    cmd.DeleteParam = DeletePathParam;
817    cmd.DrawGraphics = DoDrawPath;
818    drawCmdList_.PushBack(cmd);
819    Invalidate();
820}
821
822#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
823void UICanvas::FillPath(const Paint& paint)
824{
825    if (vertices_ == nullptr) {
826        return;
827    }
828
829    PathParam* pathParam = new PathParam;
830    if (pathParam == nullptr) {
831        GRAPHIC_LOGE("new LineParam fail");
832        return;
833    }
834
835    pathParam->vertices = vertices_;
836    pathParam->isStroke = false;
837#if defined(GRAPHIC_ENABLE_PATTERN_FILL_FLAG) && GRAPHIC_ENABLE_PATTERN_FILL_FLAG
838    if (paint.GetStyle() == Paint::PATTERN) {
839        ImageParam* imageParam = new ImageParam;
840        if (imageParam == nullptr) {
841            GRAPHIC_LOGE("new ImageParam fail");
842            return;
843        }
844
845        imageParam->image = new Image();
846        if (imageParam->image == nullptr) {
847            delete imageParam;
848            imageParam = nullptr;
849            return;
850        }
851
852        SetImageParamInfo(imageParam, paint, pathParam);
853    }
854#endif
855    DrawCmd cmd;
856    cmd.paint = paint;
857    cmd.param = pathParam;
858    cmd.DeleteParam = DeletePathParam;
859    cmd.DrawGraphics = DoFillPath;
860    drawCmdList_.PushBack(cmd);
861    Invalidate();
862}
863#endif
864
865void UICanvas::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
866{
867    Rect rect = GetOrigRect();
868    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, rect, invalidatedArea, *style_, opaScale_);
869
870    void* param = nullptr;
871    ListNode<DrawCmd>* curDraw = drawCmdList_.Begin();
872    Rect coords = GetOrigRect();
873    Rect trunc = invalidatedArea;
874    if (!trunc.Intersect(trunc, coords)) {
875        return;
876    }
877#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
878    bool haveComposite = false;
879    for (; curDraw != drawCmdList_.End(); curDraw = curDraw->next_) {
880        if (curDraw->data_.paint.HaveComposite()) {
881            haveComposite = true;
882            break;
883        }
884    }
885
886    if (haveComposite) {
887        OnBlendDraw(gfxDstBuffer, trunc);
888    } else
889#endif
890    {
891        curDraw = drawCmdList_.Begin();
892        for (; curDraw != drawCmdList_.End(); curDraw = curDraw->next_) {
893            param = curDraw->data_.param;
894            curDraw->data_.DrawGraphics(gfxDstBuffer, param, curDraw->data_.paint, rect, trunc, *style_);
895        }
896    }
897}
898
899#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
900void OnBlendDrawPattern(ListNode<UICanvas::DrawCmd>* curDraw,
901                        UICanvas::DrawCmd& drawCmd,
902                        Rect& rect,
903                        const Rect& trunc,
904                        RasterizerScanlineAntialias& blendRasterizer,
905                        RasterizerScanlineAntialias& rasterizer,
906                        RenderBase& renBase,
907                        TransAffine& transform,
908                        PathParam* pathParamBlend)
909{
910#if defined(GRAPHIC_ENABLE_PATTERN_FILL_FLAG) && GRAPHIC_ENABLE_PATTERN_FILL_FLAG
911    if (curDraw->data_.paint.GetStyle() == Paint::PATTERN) {
912        if (curDraw->data_.param == nullptr) {
913            return;
914        }
915        PathParam* pathParam = static_cast<PathParam*>(curDraw->data_.param);
916        ImageParam* imageParam = static_cast<ImageParam*>(pathParam->imageParam);
917        if (imageParam->image == nullptr) {
918            return;
919        }
920        FillPatternRgba spanPattern(imageParam->image->GetImageInfo(), curDraw->data_.paint.GetPatternRepeatMode(),
921                                    rect.GetLeft(), rect.GetTop());
922        UICanvas::BlendRaster(drawCmd.paint, drawCmd.param, blendRasterizer, rasterizer, renBase, transform,
923                              spanPattern, trunc, pathParamBlend->isStroke);
924    }
925#endif
926}
927
928void OnBlendDrawGradient(ListNode<UICanvas::DrawCmd>* curDraw,
929                         UICanvas::DrawCmd& drawCmd,
930                         const Rect& trunc,
931                         RasterizerScanlineAntialias& blendRasterizer,
932                         RasterizerScanlineAntialias& rasterizer,
933                         RenderBase& renBase,
934                         TransAffine& transform,
935                         PathParam* pathParamBlend)
936{
937#if defined(GRAPHIC_ENABLE_GRADIENT_FILL_FLAG) && GRAPHIC_ENABLE_GRADIENT_FILL_FLAG
938    if (curDraw->data_.paint.GetStyle() == Paint::GRADIENT) {
939        TransAffine gradientMatrix;
940        FillInterpolator interpolatorType(gradientMatrix);
941        FillGradientLut gradientColorMode;
942        DrawCanvas::BuildGradientColor(curDraw->data_.paint, gradientColorMode);
943        if (curDraw->data_.paint.GetGradient() == Paint::Linear) {
944            float distance = 0;
945            DrawCanvas::BuildLineGradientMatrix(drawCmd.paint, gradientMatrix, transform, distance);
946            GradientLinearCalculate gradientLinearCalculate;
947            FillGradient span(interpolatorType, gradientLinearCalculate, gradientColorMode, 0, distance);
948            UICanvas::BlendRaster(drawCmd.paint, drawCmd.param, blendRasterizer, rasterizer, renBase,
949                                  transform, span, trunc, pathParamBlend->isStroke);
950        }
951        if (curDraw->data_.paint.GetGradient() == Paint::Radial) {
952            Paint::RadialGradientPoint radialPoint = drawCmd.paint.GetRadialGradientPoint();
953            float startRadius = 0;
954            float endRadius = 0;
955            DrawCanvas::BuildRadialGradientMatrix(drawCmd.paint, gradientMatrix, transform, startRadius, endRadius);
956            GradientRadialCalculate gradientRadialCalculate(endRadius, radialPoint.x0 - radialPoint.x1,
957                                                            radialPoint.y0 - radialPoint.y1);
958            FillGradient span(interpolatorType, gradientRadialCalculate, gradientColorMode, startRadius, endRadius);
959            UICanvas::BlendRaster(drawCmd.paint, drawCmd.param, blendRasterizer, rasterizer, renBase,
960                                  transform, span, trunc, pathParamBlend->isStroke);
961        }
962    }
963#endif
964}
965
966void UICanvas::OnBlendDraw(BufferInfo& gfxDstBuffer, const Rect& trunc)
967{
968    Rect rect = GetOrigRect();
969    RenderBuffer renderBuffer;
970    TransAffine transform;
971    ListNode<DrawCmd>* curDrawEnd = drawCmdList_.Begin();
972    RasterizerScanlineAntialias blendRasterizer;
973    DrawCmd drawCmd;
974    int count = 0;
975    for (; curDrawEnd != drawCmdList_.End(); curDrawEnd = curDrawEnd->next_) {
976        if (curDrawEnd->data_.paint.HaveComposite()) {
977            drawCmd = curDrawEnd->data_;
978            count++;
979        }
980    }
981    if (drawCmd.param == nullptr) {
982        return;
983    }
984    PathParam* pathParamBlend = static_cast<PathParam*>(drawCmd.param);
985    ListNode<DrawCmd>* curDraw = drawCmdList_.Begin();
986    DrawCanvas::InitRenderAndTransform(gfxDstBuffer, renderBuffer, rect, transform, *style_, curDraw->data_.paint);
987    DrawCanvas::SetRasterizer(*pathParamBlend->vertices, drawCmd.paint, blendRasterizer, transform,
988                              pathParamBlend->isStroke);
989    RasterizerScanlineAntialias scanline;
990    RenderPixfmtRgbaBlend pixFormat(renderBuffer);
991    RenderBase renBase(pixFormat);
992    renBase.ResetClipping(true);
993    renBase.ClipBox(trunc.GetLeft(), trunc.GetTop(), trunc.GetRight(), trunc.GetBottom());
994    for (; curDraw != drawCmdList_.End(); curDraw = curDraw->next_) {
995        if (curDraw->data_.paint.HaveComposite()) {
996            drawCmd = curDraw->data_;
997            count--;
998        }
999        if (count <= 0) {
1000            continue;
1001        }
1002        RasterizerScanlineAntialias rasterizer;
1003        if (curDraw->data_.param == nullptr) {
1004            continue;
1005        }
1006        PathParam* pathParam = static_cast<PathParam*>(curDraw->data_.param);
1007#if defined(GRAPHIC_ENABLE_BLUR_EFFECT_FLAG) && GRAPHIC_ENABLE_BLUR_EFFECT_FLAG
1008        if (curDraw->data_.paint.HaveShadow()) {
1009            DrawCanvas::DoDrawShadow(gfxDstBuffer, curDraw->data_.param, curDraw->data_.paint, rect, trunc, *style_,
1010                                     pathParam->isStroke);
1011        }
1012#endif
1013        DrawCanvas::InitRenderAndTransform(gfxDstBuffer, renderBuffer, rect, transform, *style_, curDraw->data_.paint);
1014        rasterizer.ClipBox(0, 0, gfxDstBuffer.width, gfxDstBuffer.height);
1015        DrawCanvas::SetRasterizer(*pathParam->vertices, curDraw->data_.paint, rasterizer, transform,
1016                                  pathParam->isStroke);
1017        if (IsSoild(curDraw->data_.paint)) {
1018            Rgba8T color;
1019            DrawCanvas::RenderBlendSolid(curDraw->data_.paint, color, pathParam->isStroke);
1020            SpanSoildColor spanSoildColor(color);
1021            BlendRaster(drawCmd.paint, drawCmd.param, blendRasterizer, rasterizer, renBase, transform,
1022                        spanSoildColor, rect, pathParamBlend->isStroke);
1023        }
1024
1025        OnBlendDrawGradient(curDraw, drawCmd, trunc, blendRasterizer,
1026                            rasterizer, renBase, transform, pathParamBlend);
1027
1028        OnBlendDrawPattern(curDraw, drawCmd, rect, trunc, blendRasterizer,
1029                           rasterizer, renBase, transform, pathParamBlend);
1030    }
1031}
1032#endif
1033
1034void UICanvas::GetAbsolutePosition(const Point& prePoint, const Rect& rect, const Style& style, Point& point)
1035{
1036    point.x = prePoint.x + rect.GetLeft() + style.paddingLeft_ + style.borderWidth_;
1037    point.y = prePoint.y + rect.GetTop() + style.paddingTop_ + style.borderWidth_;
1038}
1039
1040void UICanvas::DoDrawLine(BufferInfo& gfxDstBuffer,
1041                          void* param,
1042                          const Paint& paint,
1043                          const Rect& rect,
1044                          const Rect& invalidatedArea,
1045                          const Style& style)
1046{
1047    if (param == nullptr) {
1048        return;
1049    }
1050    LineParam* lineParam = static_cast<LineParam*>(param);
1051    Point start;
1052    Point end;
1053    GetAbsolutePosition(lineParam->start, rect, style, start);
1054    GetAbsolutePosition(lineParam->end, rect, style, end);
1055
1056    BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, start, end, invalidatedArea, paint.GetStrokeWidth(),
1057                                           paint.GetStrokeColor(), paint.GetOpacity());
1058}
1059
1060void UICanvas::DoDrawCurve(BufferInfo& gfxDstBuffer,
1061                           void* param,
1062                           const Paint& paint,
1063                           const Rect& rect,
1064                           const Rect& invalidatedArea,
1065                           const Style& style)
1066{
1067    if (param == nullptr) {
1068        return;
1069    }
1070    CurveParam* curveParam = static_cast<CurveParam*>(param);
1071    Point start;
1072    Point end;
1073    Point control1;
1074    Point control2;
1075    GetAbsolutePosition(curveParam->start, rect, style, start);
1076    GetAbsolutePosition(curveParam->end, rect, style, end);
1077    GetAbsolutePosition(curveParam->control1, rect, style, control1);
1078    GetAbsolutePosition(curveParam->control2, rect, style, control2);
1079
1080    BaseGfxEngine::GetInstance()->DrawCubicBezier(gfxDstBuffer,
1081                                                  start,
1082                                                  control1,
1083                                                  control2,
1084                                                  end,
1085                                                  invalidatedArea,
1086                                                  paint.GetStrokeWidth(),
1087                                                  paint.GetStrokeColor(),
1088                                                  paint.GetOpacity());
1089}
1090
1091void UICanvas::DoDrawRect(BufferInfo& gfxDstBuffer,
1092                          void* param,
1093                          const Paint& paint,
1094                          const Rect& rect,
1095                          const Rect& invalidatedArea,
1096                          const Style& style)
1097{
1098    if (param == nullptr) {
1099        return;
1100    }
1101    RectParam* rectParam = static_cast<RectParam*>(param);
1102    Style drawStyle = StyleDefault::GetDefaultStyle();
1103    drawStyle.bgColor_ = paint.GetStrokeColor();
1104    drawStyle.bgOpa_ = paint.GetOpacity();
1105    drawStyle.borderRadius_ = 0;
1106
1107    int16_t lineWidth = static_cast<int16_t>(paint.GetStrokeWidth());
1108    Point start;
1109    GetAbsolutePosition(rectParam->start, rect, style, start);
1110
1111    int16_t x = start.x - lineWidth / 2; // 2: half
1112    int16_t y = start.y - lineWidth / 2; // 2: half
1113    Rect coords;
1114    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
1115    if ((rectParam->height <= lineWidth) || (rectParam->width <= lineWidth)) {
1116        coords.SetPosition(x, y);
1117        coords.SetHeight(rectParam->height + lineWidth);
1118        coords.SetWidth(rectParam->width + lineWidth);
1119        baseGfxEngine->DrawRect(gfxDstBuffer, coords, invalidatedArea, drawStyle, OPA_OPAQUE);
1120        return;
1121    }
1122
1123    coords.SetPosition(x, y);
1124    coords.SetHeight(lineWidth);
1125    coords.SetWidth(rectParam->width);
1126    baseGfxEngine->DrawRect(gfxDstBuffer, coords, invalidatedArea, drawStyle, OPA_OPAQUE);
1127
1128    coords.SetPosition(x + rectParam->width, y);
1129    coords.SetHeight(rectParam->height);
1130    coords.SetWidth(lineWidth);
1131    baseGfxEngine->DrawRect(gfxDstBuffer, coords, invalidatedArea, drawStyle, OPA_OPAQUE);
1132
1133    coords.SetPosition(x, y + lineWidth);
1134    coords.SetHeight(rectParam->height);
1135    coords.SetWidth(lineWidth);
1136    baseGfxEngine->DrawRect(gfxDstBuffer, coords, invalidatedArea, drawStyle, OPA_OPAQUE);
1137
1138    coords.SetPosition(x + lineWidth, y + rectParam->height);
1139    coords.SetHeight(lineWidth);
1140    coords.SetWidth(rectParam->width);
1141    baseGfxEngine->DrawRect(gfxDstBuffer, coords, invalidatedArea, drawStyle, OPA_OPAQUE);
1142}
1143
1144void UICanvas::DoFillRect(BufferInfo& gfxDstBuffer,
1145                          void* param,
1146                          const Paint& paint,
1147                          const Rect& rect,
1148                          const Rect& invalidatedArea,
1149                          const Style& style)
1150{
1151    if (param == nullptr) {
1152        return;
1153    }
1154    RectParam* rectParam = static_cast<RectParam*>(param);
1155    uint8_t enableStroke = static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE;
1156    int16_t lineWidth = enableStroke ? paint.GetStrokeWidth() : 0;
1157    if ((rectParam->height <= lineWidth) || (rectParam->width <= lineWidth)) {
1158        return;
1159    }
1160    Point start;
1161    GetAbsolutePosition(rectParam->start, rect, style, start);
1162
1163    Rect coords;
1164    coords.SetPosition(start.x + (lineWidth + 1) / 2, start.y + (lineWidth + 1) / 2); // 2: half
1165    coords.SetHeight(rectParam->height - lineWidth);
1166    coords.SetWidth(rectParam->width - lineWidth);
1167
1168    Style drawStyle = StyleDefault::GetDefaultStyle();
1169    drawStyle.bgColor_ = paint.GetFillColor();
1170    drawStyle.bgOpa_ = paint.GetOpacity();
1171    drawStyle.borderRadius_ = 0;
1172    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, coords, invalidatedArea, drawStyle, OPA_OPAQUE);
1173}
1174
1175void UICanvas::DoDrawCircle(BufferInfo& gfxDstBuffer,
1176                            void* param,
1177                            const Paint& paint,
1178                            const Rect& rect,
1179                            const Rect& invalidatedArea,
1180                            const Style& style)
1181{
1182    if (param == nullptr) {
1183        return;
1184    }
1185    CircleParam* circleParam = static_cast<CircleParam*>(param);
1186
1187    Style drawStyle = StyleDefault::GetDefaultStyle();
1188    drawStyle.lineOpa_ = paint.GetOpacity();
1189
1190    ArcInfo arcInfo = {{0}};
1191    arcInfo.imgPos = {0, 0};
1192    arcInfo.startAngle = 0;
1193    arcInfo.endAngle = CIRCLE_IN_DEGREE;
1194    GetAbsolutePosition(circleParam->center, rect, style, arcInfo.center);
1195    uint8_t enableStroke = static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE;
1196    uint16_t halfLineWidth = enableStroke ? (paint.GetStrokeWidth() >> 1) : 0;
1197    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
1198    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
1199        arcInfo.radius = circleParam->radius - halfLineWidth;
1200        drawStyle.lineWidth_ = arcInfo.radius;
1201        drawStyle.lineColor_ = paint.GetFillColor();
1202        baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, invalidatedArea, drawStyle, OPA_OPAQUE,
1203                               CapType::CAP_NONE);
1204    }
1205
1206    if (enableStroke) {
1207        arcInfo.radius = circleParam->radius + halfLineWidth - 1;
1208        drawStyle.lineWidth_ = static_cast<int16_t>(paint.GetStrokeWidth());
1209        drawStyle.lineColor_ = paint.GetStrokeColor();
1210        baseGfxEngine->DrawArc(gfxDstBuffer, arcInfo, invalidatedArea, drawStyle, OPA_OPAQUE,
1211                               CapType::CAP_NONE);
1212    }
1213}
1214
1215void UICanvas::DoDrawArc(BufferInfo& gfxDstBuffer,
1216                         void* param,
1217                         const Paint& paint,
1218                         const Rect& rect,
1219                         const Rect& invalidatedArea,
1220                         const Style& style)
1221{
1222    if (param == nullptr) {
1223        return;
1224    }
1225    ArcParam* arcParam = static_cast<ArcParam*>(param);
1226
1227    ArcInfo arcInfo = {{0}};
1228    arcInfo.imgPos = {0, 0};
1229    arcInfo.startAngle = arcParam->startAngle;
1230    arcInfo.endAngle = arcParam->endAngle;
1231    Style drawStyle = StyleDefault::GetDefaultStyle();
1232    drawStyle.lineWidth_ = static_cast<int16_t>(paint.GetStrokeWidth());
1233    drawStyle.lineColor_ = paint.GetStrokeColor();
1234    drawStyle.lineOpa_ = paint.GetOpacity();
1235    arcInfo.radius = arcParam->radius + ((paint.GetStrokeWidth() + 1) >> 1);
1236
1237    GetAbsolutePosition(arcParam->center, rect, style, arcInfo.center);
1238    BaseGfxEngine::GetInstance()->DrawArc(gfxDstBuffer, arcInfo, invalidatedArea, drawStyle, OPA_OPAQUE,
1239                                          CapType::CAP_NONE);
1240}
1241#if defined(GRAPHIC_ENABLE_DRAW_IMAGE_FLAG) && GRAPHIC_ENABLE_DRAW_IMAGE_FLAG
1242void UICanvas::DoDrawImage(BufferInfo& gfxDstBuffer,
1243                           void* param,
1244                           const Paint& paint,
1245                           const Rect& rect,
1246                           const Rect& invalidatedArea,
1247                           const Style& style)
1248{
1249    if (param == nullptr) {
1250        return;
1251    }
1252    UIImageView* imageView = static_cast<UIImageView*>(param);
1253    Point startPos = {imageView->GetX(), imageView->GetY()};
1254    Point start;
1255    GetAbsolutePosition({startPos.x, startPos.y}, rect, style, start);
1256    imageView->SetPosition(start.x, start.y);
1257    if (!paint.GetTransAffine().IsIdentity()) {
1258        float angle = paint.GetRotateAngle();
1259        imageView->Rotate(MATH_ROUND(angle), Vector2<float>(0, 0));
1260        imageView->Translate(Vector3<int16_t>(paint.GetTranslateX(), paint.GetTranslateY(), 1));
1261        Vector2<float> scale(static_cast<float>(paint.GetScaleX()), static_cast<float>(paint.GetScaleY()));
1262        imageView->Scale(scale, Vector2<float>(0, 0));
1263    }
1264    imageView->OnDraw(gfxDstBuffer, invalidatedArea);
1265    imageView->SetPosition(startPos.x, startPos.y);
1266}
1267#endif
1268
1269void UICanvas::DoDrawLabel(BufferInfo& gfxDstBuffer,
1270                           void* param,
1271                           const Paint& paint,
1272                           const Rect& rect,
1273                           const Rect& invalidatedArea,
1274                           const Style& style)
1275{
1276    if (param == nullptr) {
1277        return;
1278    }
1279    UILabel* label = static_cast<UILabel*>(param);
1280    Point startPos = {label->GetX(), label->GetY()};
1281    Point start;
1282    GetAbsolutePosition({startPos.x, startPos.y}, rect, style, start);
1283    label->SetPosition(start.x, start.y);
1284    label->OnDraw(gfxDstBuffer, invalidatedArea);
1285    label->SetPosition(startPos.x, startPos.y);
1286}
1287
1288void UICanvas::DoDrawLineJoin(BufferInfo& gfxDstBuffer,
1289                              const Point& center,
1290                              const Rect& invalidatedArea,
1291                              const Paint& paint)
1292{
1293    ArcInfo arcinfo = {{0}};
1294    arcinfo.center = center;
1295    arcinfo.imgPos = {0, 0};
1296    arcinfo.radius = (paint.GetStrokeWidth() + 1) >> 1;
1297    arcinfo.startAngle = 0;
1298    arcinfo.endAngle = CIRCLE_IN_DEGREE;
1299
1300    Style style;
1301    style.lineColor_ = paint.GetStrokeColor();
1302    style.lineWidth_ = static_cast<int16_t>(paint.GetStrokeWidth());
1303    style.lineOpa_ = OPA_OPAQUE;
1304    BaseGfxEngine::GetInstance()->DrawArc(gfxDstBuffer, arcinfo, invalidatedArea,
1305                                          style, OPA_OPAQUE, CapType::CAP_NONE);
1306}
1307
1308void UICanvas::DoDrawPath(BufferInfo& gfxDstBuffer,
1309                          void* param,
1310                          const Paint& paint,
1311                          const Rect& rect,
1312                          const Rect& invalidatedArea,
1313                          const Style& style)
1314{
1315#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
1316    BaseGfxEngine::GetInstance()->DrawPath(gfxDstBuffer, param, paint, rect, invalidatedArea, style);
1317#else
1318    if (param == nullptr) {
1319        return;
1320    }
1321    PathParam* pathParam = static_cast<PathParam*>(param);
1322    const UICanvasPath* path = pathParam->path;
1323    if (path == nullptr) {
1324        return;
1325    }
1326    Point pathEnd = {COORD_MIN, COORD_MIN};
1327
1328    ListNode<Point>* pointIter = path->points_.Begin();
1329    ListNode<ArcParam>* arcIter = path->arcParam_.Begin();
1330    ListNode<PathCmd>* iter = path->cmd_.Begin();
1331    for (uint16_t i = 0; (i < pathParam->count) && (iter != path->cmd_.End()); i++, iter = iter->next_) {
1332        switch (iter->data_) {
1333            case CMD_MOVE_TO: {
1334                pointIter = pointIter->next_;
1335                break;
1336            }
1337            case CMD_LINE_TO: {
1338                Point start = pointIter->prev_->data_;
1339                Point end = pointIter->data_;
1340                pointIter = pointIter->next_;
1341                if ((start.x == end.x) && (start.y == end.y)) {
1342                    break;
1343                }
1344
1345                GetAbsolutePosition(start, rect, style, start);
1346                GetAbsolutePosition(end, rect, style, end);
1347                BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, start, end, invalidatedArea,
1348                                                       paint.GetStrokeWidth(), paint.GetStrokeColor(), OPA_OPAQUE);
1349                if ((pathEnd.x == start.x) && (pathEnd.y == start.y)) {
1350                    DoDrawLineJoin(gfxDstBuffer, start, invalidatedArea, paint);
1351                }
1352                pathEnd = end;
1353                break;
1354            }
1355            case CMD_ARC: {
1356                ArcInfo arcInfo = {{0}};
1357                arcInfo.imgPos = Point{0, 0};
1358                arcInfo.startAngle = arcIter->data_.startAngle;
1359                arcInfo.endAngle = arcIter->data_.endAngle;
1360                Style drawStyle = StyleDefault::GetDefaultStyle();
1361                drawStyle.lineWidth_ = static_cast<int16_t>(paint.GetStrokeWidth());
1362                drawStyle.lineColor_ = paint.GetStrokeColor();
1363                drawStyle.lineOpa_ = OPA_OPAQUE;
1364                arcInfo.radius = arcIter->data_.radius + ((paint.GetStrokeWidth() + 1) >> 1);
1365
1366                GetAbsolutePosition(arcIter->data_.center, rect, style, arcInfo.center);
1367                BaseGfxEngine::GetInstance()->DrawArc(gfxDstBuffer, arcInfo, invalidatedArea, drawStyle, OPA_OPAQUE,
1368                                                      CapType::CAP_NONE);
1369                if (pointIter != path->points_.Begin()) {
1370                    DoDrawLineJoin(gfxDstBuffer, pathEnd, invalidatedArea, paint);
1371                }
1372
1373                GetAbsolutePosition(pointIter->data_, rect, style, pathEnd);
1374                pointIter = pointIter->next_;
1375                arcIter = arcIter->next_;
1376                break;
1377            }
1378            case CMD_CLOSE: {
1379                Point start = pointIter->prev_->data_;
1380                Point end = pointIter->data_;
1381                GetAbsolutePosition(start, rect, style, start);
1382                GetAbsolutePosition(end, rect, style, end);
1383                if ((start.x != end.x) || (start.y != end.y)) {
1384                    BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, start, end, invalidatedArea,
1385                                                           paint.GetStrokeWidth(), paint.GetStrokeColor(), OPA_OPAQUE);
1386                    if ((pathEnd.x == start.x) && (pathEnd.y == start.y)) {
1387                        DoDrawLineJoin(gfxDstBuffer, start, invalidatedArea, paint);
1388                    }
1389                    pathEnd = end;
1390                }
1391
1392                if ((pathEnd.x == end.x) && (pathEnd.y == end.y)) {
1393                    DoDrawLineJoin(gfxDstBuffer, end, invalidatedArea, paint);
1394                }
1395                pointIter = pointIter->next_;
1396                break;
1397            }
1398            default:
1399                break;
1400        }
1401    }
1402#endif
1403}
1404
1405void UICanvas::DoFillPath(BufferInfo& gfxDstBuffer,
1406                          void* param,
1407                          const Paint& paint,
1408                          const Rect& rect,
1409                          const Rect& invalidatedArea,
1410                          const Style& style)
1411{
1412    BaseGfxEngine::GetInstance()->FillPath(gfxDstBuffer, param, paint, rect, invalidatedArea, style);
1413}
1414
1415#if defined(GRAPHIC_ENABLE_DRAW_TEXT_FLAG) && GRAPHIC_ENABLE_DRAW_TEXT_FLAG
1416void UICanvas::StrokeText(const char* text, const Point& point, const FontStyle& fontStyle, const Paint& paint)
1417{
1418    if (text == nullptr) {
1419        return;
1420    }
1421    if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
1422        TextParam* textParam = new TextParam;
1423        if (textParam == nullptr) {
1424            GRAPHIC_LOGE("new TextParam fail");
1425            return;
1426        }
1427        textParam->text = text;
1428        textParam->fontStyle = fontStyle;
1429        textParam->fontOpa = paint.GetOpacity();
1430        textParam->fontColor = paint.GetFillColor();
1431        textParam->position = point;
1432        DrawCmd cmd;
1433        cmd.param = textParam;
1434        cmd.DeleteParam = DeleteTextParam;
1435        cmd.DrawGraphics = DoDrawText;
1436        cmd.paint = paint;
1437        drawCmdList_.PushBack(cmd);
1438        Invalidate();
1439        SetStartPosition(point);
1440    }
1441}
1442#endif
1443
1444Point UICanvas::MeasureText(const char* text, const FontStyle& fontStyle)
1445{
1446    Text* textCompent = new Text;
1447    textCompent->SetText(text);
1448    textCompent->SetFont(fontStyle.fontName, fontStyle.fontSize);
1449    textCompent->SetDirect(static_cast<UITextLanguageDirect>(fontStyle.direct));
1450    textCompent->SetAlign(static_cast<UITextLanguageAlignment>(fontStyle.align));
1451    Style drawStyle;
1452    drawStyle.SetStyle(STYLE_LETTER_SPACE, fontStyle.letterSpace);
1453    textCompent->ReMeasureTextSize(this->GetRect(), drawStyle);
1454    Point textSize = textCompent->GetTextSize();
1455    delete textCompent;
1456    return textSize;
1457}
1458
1459void UICanvas::BlitMapBuffer(BufferInfo &gfxDstBuffer, BufferInfo& gfxMapBuffer, Rect& textRect,
1460                             TransformMap& transMap, const Rect& invalidatedArea)
1461{
1462    Rect invalidRect = textRect;
1463    transMap.SetTransMapRect(textRect);
1464    if (invalidRect.Intersect(invalidRect, transMap.GetBoxRect())) {
1465        uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(gfxDstBuffer.mode);
1466        ImageInfo imageInfo;
1467        imageInfo.header.colorMode = gfxDstBuffer.mode;
1468        imageInfo.dataSize = gfxMapBuffer.width * gfxMapBuffer.height *
1469                DrawUtils::GetByteSizeByColorMode(gfxDstBuffer.mode);
1470        imageInfo.header.width = gfxMapBuffer.width;
1471        imageInfo.header.height = gfxMapBuffer.height;
1472        imageInfo.header.reserved = 0;
1473        uint8_t* addr = reinterpret_cast<uint8_t*>(gfxMapBuffer.virAddr);
1474        imageInfo.data = addr;
1475        TransformDataInfo imageTranDataInfo = {imageInfo.header, imageInfo.data, pxSize,
1476                                               BlurLevel::LEVEL0, TransformAlgorithm::BILINEAR};
1477        BaseGfxEngine::GetInstance()->DrawTransform(gfxDstBuffer, invalidatedArea, {0, 0}, Color::Black(),
1478                                                    OPA_OPAQUE, transMap, imageTranDataInfo);
1479    }
1480}
1481
1482#if defined(GRAPHIC_ENABLE_DRAW_TEXT_FLAG) && GRAPHIC_ENABLE_DRAW_TEXT_FLAG
1483void UICanvas::DoDrawText(BufferInfo& gfxDstBuffer,
1484                          void* param,
1485                          const Paint& paint,
1486                          const Rect& rect,
1487                          const Rect& invalidatedArea,
1488                          const Style& style)
1489{
1490    TextParam* textParam = static_cast<TextParam*>(param);
1491    if (textParam == nullptr) {
1492        return;
1493    }
1494    if (textParam->fontStyle.fontSize <= 0) {
1495        return;
1496    }
1497    Text* text = textParam->textComment;
1498    text->SetText(textParam->text);
1499    text->SetFont(textParam->fontStyle.fontName, textParam->fontStyle.fontSize);
1500    text->SetDirect(static_cast<UITextLanguageDirect>(textParam->fontStyle.direct));
1501    text->SetAlign(static_cast<UITextLanguageAlignment>(textParam->fontStyle.align));
1502
1503    Point start;
1504    Rect textRect = invalidatedArea;
1505    GetAbsolutePosition(textParam->position, rect, style, start);
1506    textRect.SetPosition(start.x, start.y);
1507    Style drawStyle = style;
1508    drawStyle.textColor_ = textParam->fontColor;
1509    drawStyle.lineColor_ = textParam->fontColor;
1510    drawStyle.bgColor_ = textParam->fontColor;
1511    drawStyle.SetStyle(STYLE_LETTER_SPACE, textParam->fontStyle.letterSpace);
1512    text->ReMeasureTextSize(textRect, drawStyle);
1513    if (text->GetTextSize().x == 0 || text->GetTextSize().y == 0) {
1514        return;
1515    }
1516    textRect.SetWidth(text->GetTextSize().x + 1);
1517    textRect.SetHeight(text->GetTextSize().y + 1);
1518    OpacityType opa = DrawUtils::GetMixOpacity(textParam->fontOpa, style.bgOpa_);
1519    if (!paint.GetTransAffine().IsIdentity()) {
1520        Rect textImageRect(0, 0, textRect.GetWidth(), textRect.GetHeight());
1521        BufferInfo* mapBufferInfo = UpdateMapBufferInfo(gfxDstBuffer, textImageRect);
1522        text->OnDraw(*mapBufferInfo, textImageRect, textImageRect, textImageRect, 0, drawStyle,
1523                     Text::TEXT_ELLIPSIS_END_INV, opa);
1524        TransformMap trans;
1525        trans.SetTransMapRect(textRect);
1526        trans.Scale(Vector2<float>(static_cast<float>(paint.GetScaleX()), static_cast<float>(paint.GetScaleY())),
1527                    Vector2<float>(0, 0));
1528        float angle = paint.GetRotateAngle();
1529        trans.Rotate(MATH_ROUND(angle),  Vector2<float>(0, 0));
1530        trans.Translate(Vector2<int16_t>(paint.GetTranslateX(), paint.GetTranslateY()));
1531        BlitMapBuffer(gfxDstBuffer, *mapBufferInfo, textRect, trans, invalidatedArea);
1532    } else {
1533        text->OnDraw(gfxDstBuffer, invalidatedArea, textRect, textRect, 0,
1534                     drawStyle, Text::TEXT_ELLIPSIS_END_INV, opa);
1535    }
1536}
1537#endif
1538
1539void UICanvas::InitGfxMapBuffer(const BufferInfo& srcBuff, const Rect& rect)
1540{
1541    gfxMapBuffer_ = new BufferInfo();
1542    gfxMapBuffer_->rect = rect;
1543    gfxMapBuffer_->mode = srcBuff.mode;
1544    gfxMapBuffer_->color = srcBuff.color;
1545    gfxMapBuffer_->width = static_cast<uint16_t>(rect.GetWidth());
1546    gfxMapBuffer_->height = static_cast<uint16_t>(rect.GetHeight());
1547    uint8_t destByteSize = DrawUtils::GetByteSizeByColorMode(srcBuff.mode);
1548    gfxMapBuffer_->stride = static_cast<int32_t>(gfxMapBuffer_->width) * static_cast<int32_t>(destByteSize);
1549    uint32_t buffSize = gfxMapBuffer_->height * gfxMapBuffer_->stride;
1550    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
1551    gfxMapBuffer_->virAddr = baseGfxEngine->AllocBuffer(buffSize, BUFFER_MAP_SURFACE);
1552    gfxMapBuffer_->phyAddr = gfxMapBuffer_->virAddr;
1553
1554    errno_t err = memset_s(gfxMapBuffer_->virAddr, buffSize, 0, buffSize);
1555    if (err != EOK) {
1556        baseGfxEngine->FreeBuffer(static_cast<uint8_t*>(gfxMapBuffer_->virAddr), BUFFER_MAP_SURFACE);
1557        GRAPHIC_LOGE("memset_s gfxMapBuffer_ fail");
1558        return;
1559    }
1560}
1561
1562BufferInfo* UICanvas::UpdateMapBufferInfo(const BufferInfo& srcBuff, const Rect& rect)
1563{
1564    if (gfxMapBuffer_ == nullptr) {
1565        InitGfxMapBuffer(srcBuff, rect);
1566        return gfxMapBuffer_;
1567    }
1568
1569    if (rect.GetWidth() != gfxMapBuffer_->width ||
1570        rect.GetHeight() != gfxMapBuffer_->height ||
1571        srcBuff.mode != gfxMapBuffer_->mode) {
1572        DestroyMapBufferInfo();
1573        InitGfxMapBuffer(srcBuff, rect);
1574    } else {
1575        uint32_t buffSize = gfxMapBuffer_->height * gfxMapBuffer_->stride;
1576        errno_t err = memset_s(gfxMapBuffer_->virAddr, buffSize, 0, buffSize);
1577        if (err != EOK) {
1578            BaseGfxEngine::GetInstance()->FreeBuffer(static_cast<uint8_t*>(gfxMapBuffer_->virAddr), BUFFER_MAP_SURFACE);
1579            GRAPHIC_LOGE("memset_s gfxMapBuffer_ fail");
1580        }
1581    }
1582    return gfxMapBuffer_;
1583}
1584
1585void UICanvas::DestroyMapBufferInfo()
1586{
1587    if (gfxMapBuffer_ != nullptr) {
1588        BaseGfxEngine::GetInstance()->FreeBuffer(static_cast<uint8_t*>(gfxMapBuffer_->virAddr), BUFFER_MAP_SURFACE);
1589        gfxMapBuffer_->virAddr = nullptr;
1590        gfxMapBuffer_->phyAddr = nullptr;
1591        delete gfxMapBuffer_;
1592        gfxMapBuffer_ = nullptr;
1593    }
1594}
1595
1596#if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
1597void UICanvas::BlendRaster(const Paint& paint,
1598                           void* param,
1599                           RasterizerScanlineAntialias& blendRasterizer,
1600                           RasterizerScanlineAntialias& rasterizer,
1601                           RenderBase& renBase,
1602                           TransAffine& transform,
1603                           SpanBase& spanGen,
1604                           const Rect& rect,
1605                           bool isStroke)
1606{
1607    TransAffine gradientMatrixBlend;
1608    GeometryScanline scanline1;
1609    GeometryScanline scanline2;
1610    FillBase allocator1;
1611
1612    if (IsSoild(paint)) {
1613        Rgba8T blendColor;
1614        DrawCanvas::RenderBlendSolid(paint, blendColor, isStroke);
1615        SpanSoildColor spanBlendSoildColor(blendColor);
1616        BlendScanLine(paint.GetGlobalCompositeOperation(), blendRasterizer, rasterizer,
1617                      scanline1, scanline2, renBase, allocator1, spanBlendSoildColor, spanGen);
1618    }
1619#if defined(GRAPHIC_ENABLE_GRADIENT_FILL_FLAG) && GRAPHIC_ENABLE_GRADIENT_FILL_FLAG
1620    FillInterpolator interpolatorTypeBlend(gradientMatrixBlend);
1621    FillGradientLut gradientColorModeBlend;
1622    if (paint.GetStyle() == Paint::GRADIENT) {
1623        DrawCanvas::BuildGradientColor(paint, gradientColorModeBlend);
1624        if (paint.GetGradient() == Paint::Linear) {
1625            float distance = 0;
1626            DrawCanvas::BuildLineGradientMatrix(paint, gradientMatrixBlend, transform, distance);
1627            GradientLinearCalculate gradientLinearCalculate;
1628            FillGradient span(interpolatorTypeBlend, gradientLinearCalculate,
1629                                    gradientColorModeBlend, 0, distance);
1630            BlendScanLine(paint.GetGlobalCompositeOperation(), blendRasterizer, rasterizer,
1631                          scanline1, scanline2, renBase, allocator1, span, spanGen);
1632        } else if (paint.GetGradient() == Paint::Radial) {
1633            Paint::RadialGradientPoint radialPoint = paint.GetRadialGradientPoint();
1634            float startRadius = 0;
1635            float endRadius = 0;
1636            DrawCanvas::BuildRadialGradientMatrix(paint, gradientMatrixBlend, transform, startRadius, endRadius);
1637            GradientRadialCalculate gradientRadialCalculate(endRadius, radialPoint.x0 - radialPoint.x1,
1638                                                            radialPoint.y0 - radialPoint.y1);
1639            FillGradient span(interpolatorTypeBlend, gradientRadialCalculate, gradientColorModeBlend,
1640                                    startRadius, endRadius);
1641            BlendScanLine(paint.GetGlobalCompositeOperation(), blendRasterizer, rasterizer,
1642                          scanline1, scanline2, renBase, allocator1, span, spanGen);
1643        }
1644    }
1645#endif
1646#if defined(GRAPHIC_ENABLE_PATTERN_FILL_FLAG) && GRAPHIC_ENABLE_PATTERN_FILL_FLAG
1647    if (paint.GetStyle() == Paint::PATTERN) {
1648        if (param == nullptr) {
1649            return;
1650        }
1651
1652        PathParam* pathParam = static_cast<PathParam*>(param);
1653
1654        ImageParam* imageParam = static_cast<ImageParam*>(pathParam->imageParam);
1655
1656        if (imageParam->image == nullptr) {
1657            return;
1658        }
1659        FillPatternRgba spanPattern(imageParam->image->GetImageInfo(), paint.GetPatternRepeatMode(), rect.GetLeft(),
1660                                    rect.GetTop());
1661        BlendScanLine(paint.GetGlobalCompositeOperation(), blendRasterizer, rasterizer,
1662                      scanline1, scanline2, renBase, allocator1, spanPattern, spanGen);
1663    }
1664#endif
1665}
1666#endif // ENABLE_CANVAS_EXTEND
1667} // namespace OHOS
1668