1 /**
2  * @file lv_vglite_path.c
3  *
4  */
5 
6 /**
7  * Copyright 2023 NXP
8  *
9  * SPDX-License-Identifier: MIT
10  */
11 
12 /*********************
13  *      INCLUDES
14  *********************/
15 
16 #include "lv_vglite_path.h"
17 
18 #if LV_USE_DRAW_VGLITE
19 #include "vg_lite.h"
20 
21 /*********************
22  *      DEFINES
23  *********************/
24 
25 /**********************
26  *      TYPEDEFS
27  **********************/
28 
29 /**********************
30  *  STATIC PROTOTYPES
31  **********************/
32 
33 /**********************
34  *  STATIC VARIABLES
35  **********************/
36 
37 /**********************
38  *      MACROS
39  **********************/
40 
41 /**********************
42  *   GLOBAL FUNCTIONS
43  **********************/
44 
vglite_create_rect_path_data(int32_t * path_data,uint32_t * path_data_size,int32_t radius,const lv_area_t * coords)45 void vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size,
46                                   int32_t radius,
47                                   const lv_area_t * coords)
48 {
49     int32_t rect_width = lv_area_get_width(coords);
50     int32_t rect_height = lv_area_get_height(coords);
51 
52     /* Get the final radius. Can't be larger than the half of the shortest side */
53     int32_t shortest_side = LV_MIN(rect_width, rect_height);
54     int32_t final_radius = LV_MIN(radius, shortest_side / 2);
55 
56     /* Path data element index */
57     uint8_t pidx = 0;
58 
59     if((radius == (int32_t)LV_RADIUS_CIRCLE) && (rect_width == rect_height)) {
60 
61         /* Get the control point offset for rounded cases */
62         int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE);
63 
64         /* Circle case */
65         /* Starting point */
66         path_data[pidx++] = VLC_OP_MOVE;
67         path_data[pidx++] = coords->x1 + final_radius;
68         path_data[pidx++] = coords->y1;
69 
70         /* Top-right arc */
71         path_data[pidx++] = VLC_OP_CUBIC_REL;
72         path_data[pidx++] = cpoff;
73         path_data[pidx++] = 0;
74         path_data[pidx++] = final_radius;
75         path_data[pidx++] = final_radius - cpoff;
76         path_data[pidx++] = final_radius;
77         path_data[pidx++] = final_radius;
78 
79         /* Bottom-right arc*/
80         path_data[pidx++] = VLC_OP_CUBIC_REL;
81         path_data[pidx++] = 0;
82         path_data[pidx++] = cpoff;
83         path_data[pidx++] = cpoff - final_radius;
84         path_data[pidx++] = final_radius;
85         path_data[pidx++] = 0 - final_radius;
86         path_data[pidx++] = final_radius;
87 
88         /* Bottom-left arc */
89         path_data[pidx++] = VLC_OP_CUBIC_REL;
90         path_data[pidx++] = 0 - cpoff;
91         path_data[pidx++] = 0;
92         path_data[pidx++] = 0 - final_radius;
93         path_data[pidx++] = cpoff - final_radius;
94         path_data[pidx++] = 0 - final_radius;
95         path_data[pidx++] = 0 - final_radius;
96 
97         /* Top-left arc*/
98         path_data[pidx++] = VLC_OP_CUBIC_REL;
99         path_data[pidx++] = 0;
100         path_data[pidx++] = 0 - cpoff;
101         path_data[pidx++] = final_radius - cpoff;
102         path_data[pidx++] = 0 - final_radius;
103         path_data[pidx++] = final_radius;
104         path_data[pidx++] = 0 - final_radius;
105 
106         /* Ending point */
107         path_data[pidx++] = VLC_OP_END;
108     }
109     else if(radius > 0) {
110         /* Get the control point offset for rounded cases */
111         int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE);
112 
113         /* Rounded rectangle case */
114         /* Starting point */
115         path_data[pidx++] = VLC_OP_MOVE;
116         path_data[pidx++] = coords->x1 + final_radius;
117         path_data[pidx++] = coords->y1;
118 
119         /* Top side */
120         path_data[pidx++] = VLC_OP_LINE;
121         path_data[pidx++] = coords->x2 - final_radius + 1;  /*Extended for VGLite*/
122         path_data[pidx++] = coords->y1;
123 
124         /* Top-right corner */
125         path_data[pidx++] = VLC_OP_CUBIC_REL;
126         path_data[pidx++] = cpoff;
127         path_data[pidx++] = 0;
128         path_data[pidx++] = final_radius;
129         path_data[pidx++] = final_radius - cpoff;
130         path_data[pidx++] = final_radius;
131         path_data[pidx++] = final_radius;
132 
133         /* Right side */
134         path_data[pidx++] = VLC_OP_LINE;
135         path_data[pidx++] = coords->x2 + 1;                 /*Extended for VGLite*/
136         path_data[pidx++] = coords->y2 - final_radius + 1;  /*Extended for VGLite*/
137 
138         /* Bottom-right corner*/
139         path_data[pidx++] = VLC_OP_CUBIC_REL;
140         path_data[pidx++] = 0;
141         path_data[pidx++] = cpoff;
142         path_data[pidx++] = cpoff - final_radius;
143         path_data[pidx++] = final_radius;
144         path_data[pidx++] = 0 - final_radius;
145         path_data[pidx++] = final_radius;
146 
147         /* Bottom side */
148         path_data[pidx++] = VLC_OP_LINE;
149         path_data[pidx++] = coords->x1 + final_radius;
150         path_data[pidx++] = coords->y2 + 1;                 /*Extended for VGLite*/
151 
152         /* Bottom-left corner */
153         path_data[pidx++] = VLC_OP_CUBIC_REL;
154         path_data[pidx++] = 0 - cpoff;
155         path_data[pidx++] = 0;
156         path_data[pidx++] = 0 - final_radius;
157         path_data[pidx++] = cpoff - final_radius;
158         path_data[pidx++] = 0 - final_radius;
159         path_data[pidx++] = 0 - final_radius;
160 
161         /* Left side*/
162         path_data[pidx++] = VLC_OP_LINE;
163         path_data[pidx++] = coords->x1;
164         path_data[pidx++] = coords->y1 + final_radius;
165 
166         /* Top-left corner */
167         path_data[pidx++] = VLC_OP_CUBIC_REL;
168         path_data[pidx++] = 0;
169         path_data[pidx++] = 0 - cpoff;
170         path_data[pidx++] = final_radius - cpoff;
171         path_data[pidx++] = 0 - final_radius;
172         path_data[pidx++] = final_radius;
173         path_data[pidx++] = 0 - final_radius;
174 
175         /* Ending point */
176         path_data[pidx++] = VLC_OP_END;
177     }
178     else {
179         /* Non-rounded rectangle case */
180         /* Starting point */
181         path_data[pidx++] = VLC_OP_MOVE;
182         path_data[pidx++] = coords->x1;
183         path_data[pidx++] = coords->y1;
184 
185         /* Top side */
186         path_data[pidx++] = VLC_OP_LINE;
187         path_data[pidx++] = coords->x2 + 1; /*Extended for VGLite*/
188         path_data[pidx++] = coords->y1;
189 
190         /* Right side */
191         path_data[pidx++] = VLC_OP_LINE;
192         path_data[pidx++] = coords->x2 + 1; /*Extended for VGLite*/
193         path_data[pidx++] = coords->y2 + 1; /*Extended for VGLite*/
194 
195         /* Bottom side */
196         path_data[pidx++] = VLC_OP_LINE;
197         path_data[pidx++] = coords->x1;
198         path_data[pidx++] = coords->y2 + 1; /*Extended for VGLite*/
199 
200         /* Left side*/
201         path_data[pidx++] = VLC_OP_LINE;
202         path_data[pidx++] = coords->x1;
203         path_data[pidx++] = coords->y1;
204 
205         /* Ending point */
206         path_data[pidx++] = VLC_OP_END;
207     }
208 
209     /* Resulting path size */
210     *path_data_size = pidx * sizeof(int32_t);
211 }
212 
213 /**********************
214  *   STATIC FUNCTIONS
215  **********************/
216 
217 #endif /*LV_USE_DRAW_VGLITE*/
218