1 /**
2  * @file lv_draw_vglite_line.c
3  *
4  */
5 
6 /**
7  * Copyright 2022-2024 NXP
8  *
9  * SPDX-License-Identifier: MIT
10  */
11 
12 /*********************
13  *      INCLUDES
14  *********************/
15 
16 #include "lv_draw_vglite.h"
17 
18 #if LV_USE_DRAW_VGLITE
19 #include "lv_vglite_buf.h"
20 #include "lv_vglite_utils.h"
21 
22 /*********************
23  *      DEFINES
24  *********************/
25 
26 /**********************
27  *      TYPEDEFS
28  **********************/
29 
30 /**********************
31  *  STATIC PROTOTYPES
32  **********************/
33 
34 /**
35  * Draw line shape with effects
36  *
37  * @param[in] point1 Starting point with relative coordinates
38  * @param[in] point2 Ending point with relative coordinates
39  * @param[in] clip_area Clip area with relative coordinates to dest buff
40  * @param[in] dsc Line description structure (width, rounded ending, opacity, ...)
41  *
42  */
43 static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
44                               const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc);
45 
46 /**********************
47  *  STATIC VARIABLES
48  **********************/
49 
50 /**********************
51  *      MACROS
52  **********************/
53 
54 /**********************
55  *   GLOBAL FUNCTIONS
56  **********************/
57 
lv_draw_vglite_line(lv_draw_unit_t * draw_unit,const lv_draw_line_dsc_t * dsc)58 void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc)
59 {
60     if(dsc->width == 0)
61         return;
62     if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
63         return;
64     if(dsc->p1.x == dsc->p2.x && dsc->p1.y == dsc->p2.y)
65         return;
66 
67     lv_layer_t * layer = draw_unit->target_layer;
68     lv_area_t clip_area;
69     clip_area.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2;
70     clip_area.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2;
71     clip_area.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2;
72     clip_area.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2;
73 
74     if(!lv_area_intersect(&clip_area, &clip_area, draw_unit->clip_area))
75         return; /*Fully clipped, nothing to do*/
76 
77     lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
78 
79     lv_point_t point1 = {dsc->p1.x - layer->buf_area.x1, dsc->p1.y - layer->buf_area.y1};
80     lv_point_t point2 = {dsc->p2.x - layer->buf_area.x1, dsc->p2.y - layer->buf_area.y1};
81 
82     _vglite_draw_line(&point1, &point2, &clip_area, dsc);
83 }
84 
85 /**********************
86  *   STATIC FUNCTIONS
87  **********************/
88 
_vglite_draw_line(const lv_point_t * point1,const lv_point_t * point2,const lv_area_t * clip_area,const lv_draw_line_dsc_t * dsc)89 static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
90                               const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc)
91 {
92     vg_lite_path_t path;
93     vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
94     vg_lite_cap_style_t cap_style = (dsc->round_start || dsc->round_end) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
95     vg_lite_join_style_t join_style = (dsc->round_start || dsc->round_end) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER;
96 
97     bool is_dashed = (dsc->dash_width && dsc->dash_gap);
98 
99     vg_lite_float_t stroke_dash_pattern[2] = {0, 0};
100     uint32_t stroke_dash_count = 0;
101     vg_lite_float_t stroke_dash_phase = 0;
102     if(is_dashed) {
103         stroke_dash_pattern[0] = (vg_lite_float_t)dsc->dash_width;
104         stroke_dash_pattern[1] = (vg_lite_float_t)dsc->dash_gap;
105         stroke_dash_count = sizeof(stroke_dash_pattern) / sizeof(vg_lite_float_t);
106         stroke_dash_phase = (vg_lite_float_t)dsc->dash_width / 2;
107     }
108 
109     vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode);
110 
111     /*** Init path ***/
112     int32_t width = dsc->width;
113 
114     int32_t line_path[] = { /*VG line path*/
115         VLC_OP_MOVE, point1->x, point1->y,
116         VLC_OP_LINE, point2->x, point2->y,
117         VLC_OP_END
118     };
119 
120     VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path,
121                                          (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
122                                          ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
123 
124     lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
125     vg_lite_color_t vgcol = vglite_get_color(col32, false);
126 
127     /*** Draw line ***/
128     VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH));
129 
130     VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count,
131                                           stroke_dash_phase, vgcol));
132 
133     VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path));
134 
135     VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, NULL, vgblend, vgcol));
136 
137     vglite_run();
138 
139     VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
140 }
141 
142 #endif /*LV_USE_DRAW_VGLITE*/
143