1 /**
2  * @file lv_mask.h
3  *
4  */
5 
6 #ifndef LV_MASK_H
7 #define LV_MASK_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /*********************
14  *      INCLUDES
15  *********************/
16 #include <stdbool.h>
17 #include "../lv_misc/lv_area.h"
18 #include "../lv_misc/lv_color.h"
19 
20 /*********************
21  *      DEFINES
22  *********************/
23 #define LV_MASK_ID_INV  (-1)
24 #define _LV_MASK_MAX_NUM     16
25 
26 /**********************
27  *      TYPEDEFS
28  **********************/
29 
30 enum {
31     LV_DRAW_MASK_RES_TRANSP,
32     LV_DRAW_MASK_RES_FULL_COVER,
33     LV_DRAW_MASK_RES_CHANGED,
34     LV_DRAW_MASK_RES_UNKNOWN
35 };
36 
37 typedef uint8_t lv_draw_mask_res_t;
38 
39 
40 enum {
41     LV_DRAW_MASK_TYPE_LINE,
42     LV_DRAW_MASK_TYPE_ANGLE,
43     LV_DRAW_MASK_TYPE_RADIUS,
44     LV_DRAW_MASK_TYPE_FADE,
45     LV_DRAW_MASK_TYPE_MAP,
46 };
47 
48 typedef uint8_t lv_draw_mask_type_t;
49 
50 enum {
51     LV_DRAW_MASK_LINE_SIDE_LEFT = 0,
52     LV_DRAW_MASK_LINE_SIDE_RIGHT,
53     LV_DRAW_MASK_LINE_SIDE_TOP,
54     LV_DRAW_MASK_LINE_SIDE_BOTTOM,
55 };
56 
57 /**
58  * A common callback type for every mask type.
59  * Used internally by the library.
60  */
61 typedef lv_draw_mask_res_t (*lv_draw_mask_xcb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
62                                                  lv_coord_t len,
63                                                  void * p);
64 
65 typedef uint8_t lv_draw_mask_line_side_t;
66 
67 typedef struct {
68     lv_draw_mask_xcb_t cb;
69     lv_draw_mask_type_t type;
70 } lv_draw_mask_common_dsc_t;
71 
72 typedef struct {
73     /*The first element must be the common descriptor*/
74     lv_draw_mask_common_dsc_t dsc;
75 
76     struct {
77         /*First point */
78         lv_point_t p1;
79 
80         /*Second point*/
81         lv_point_t p2;
82 
83         /*Which side to keep?*/
84         lv_draw_mask_line_side_t side : 2;
85     } cfg;
86 
87     /*A point of the line*/
88     lv_point_t origo;
89 
90     /* X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/
91     int32_t xy_steep;
92 
93     /* Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/
94     int32_t yx_steep;
95 
96     /*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines */
97     int32_t steep;
98 
99     /*Steepness in 1 px in 0..255 range. Used only by flat lines. */
100     int32_t spx;
101 
102     /*1: It's a flat line? (Near to horizontal)*/
103     uint8_t flat : 1;
104 
105 
106     /* Invert the mask. The default is: Keep the left part.
107      * It is used to select left/right/top/bottom*/
108     uint8_t inv: 1;
109 } lv_draw_mask_line_param_t;
110 
111 typedef struct {
112     /*The first element must be the common descriptor*/
113     lv_draw_mask_common_dsc_t dsc;
114 
115     struct {
116         lv_point_t vertex_p;
117         lv_coord_t start_angle;
118         lv_coord_t end_angle;
119     } cfg;
120 
121     lv_draw_mask_line_param_t start_line;
122     lv_draw_mask_line_param_t end_line;
123     uint16_t delta_deg;
124 } lv_draw_mask_angle_param_t;
125 
126 typedef struct {
127     /*The first element must be the common descriptor*/
128     lv_draw_mask_common_dsc_t dsc;
129 
130     struct {
131         lv_area_t rect;
132         lv_coord_t radius;
133         /* Invert the mask. 0: Keep the pixels inside.*/
134         uint8_t outer: 1;
135     } cfg;
136     int32_t y_prev;
137     lv_sqrt_res_t y_prev_x;
138 
139 } lv_draw_mask_radius_param_t;
140 
141 typedef struct {
142     /*The first element must be the common descriptor*/
143     lv_draw_mask_common_dsc_t dsc;
144 
145     struct {
146         lv_area_t coords;
147         lv_coord_t y_top;
148         lv_coord_t y_bottom;
149         lv_opa_t opa_top;
150         lv_opa_t opa_bottom;
151     } cfg;
152 
153 } lv_draw_mask_fade_param_t;
154 
155 typedef struct _lv_draw_mask_map_param_t {
156     /*The first element must be the common descriptor*/
157     lv_draw_mask_common_dsc_t dsc;
158 
159     struct {
160         lv_area_t coords;
161         const lv_opa_t * map;
162     } cfg;
163 } lv_draw_mask_map_param_t;
164 
165 typedef struct {
166     void * param;
167     void * custom_id;
168 } _lv_draw_mask_saved_t;
169 
170 typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM];
171 
172 /**********************
173  * GLOBAL PROTOTYPES
174  **********************/
175 
176 /**
177  * Add a draw mask. Everything drawn after it (until removing the mask) will be affected by the mask.
178  * @param param an initialized mask parameter. Only the pointer is saved.
179  * @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`.
180  * @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`.
181  */
182 int16_t lv_draw_mask_add(void * param, void * custom_id);
183 
184 
185 //! @cond Doxygen_Suppress
186 
187 /**
188  * Apply the added buffers on a line. Used internally by the library's drawing routines.
189  * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`.
190  * @param abs_x absolute X coordinate where the line to calculate start
191  * @param abs_y absolute Y coordinate where the line to calculate start
192  * @param len length of the line to calculate (in pixel count)
193  * @return One of these values:
194  * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero
195  * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
196  * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
197  */
198 LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
199                                                             lv_coord_t len);
200 
201 
202 //! @endcond
203 
204 /**
205  * Remove a mask with a given ID
206  * @param id the ID of the mask.  Returned by `lv_draw_mask_add`
207  * @return the parameter of the removed mask.
208  * If more masks have `custom_id` ID then the last mask's parameter will be returned
209  */
210 void * lv_draw_mask_remove_id(int16_t id);
211 
212 /**
213  * Remove all mask with a given custom ID
214  * @param custom_id a pointer used in `lv_draw_mask_add`
215  * @return return the parameter of the removed mask.
216  * If more masks have `custom_id` ID then the last mask's parameter will be returned
217  */
218 void * lv_draw_mask_remove_custom(void * custom_id);
219 
220 //! @cond Doxygen_Suppress
221 
222 /**
223  * Count the currently added masks
224  * @return number of active masks
225  */
226 LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void);
227 
228 
229 //! @endcond
230 
231 /**
232  *Initialize a line mask from two points.
233  * @param param pointer to a `lv_draw_mask_param_t` to initialize
234  * @param p1x X coordinate of the first point of the line
235  * @param p1y Y coordinate of the first point of the line
236  * @param p2x X coordinate of the second point of the line
237  * @param p2y y coordinate of the second point of the line
238  * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep.
239  * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
240  * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
241  */
242 void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x,
243                                    lv_coord_t p2y, lv_draw_mask_line_side_t side);
244 
245 /**
246  *Initialize a line mask from a point and an angle.
247  * @param param pointer to a `lv_draw_mask_param_t` to initialize
248  * @param px X coordinate of a point of the line
249  * @param py X coordinate of a point of the line
250  * @param angle right 0 deg, bottom: 90
251  * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep.
252  * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
253  * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
254  */
255 void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle,
256                                   lv_draw_mask_line_side_t side);
257 
258 /**
259  * Initialize an angle mask.
260  * @param param pointer to a `lv_draw_mask_param_t` to initialize
261  * @param vertex_x X coordinate of the angle vertex (absolute coordinates)
262  * @param vertex_y Y coordinate of the angle vertex (absolute coordinates)
263  * @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom
264  * @param end_angle end angle
265  */
266 void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y,
267                              lv_coord_t start_angle, lv_coord_t end_angle);
268 
269 /**
270  * Initialize a fade mask.
271  * @param param param pointer to a `lv_draw_mask_param_t` to initialize
272  * @param rect coordinates of the rectangle to affect (absolute coordinates)
273  * @param radius radius of the rectangle
274  * @param inv: true: keep the pixels inside the rectangle; keep the pixels outside of the rectangle
275  */
276 void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv);
277 
278 /**
279  * Initialize a fade mask.
280  * @param param pointer to a `lv_draw_mask_param_t` to initialize
281  * @param coords coordinates of the area to affect (absolute coordinates)
282  * @param opa_top opacity on the top
283  * @param y_top at which coordinate start to change to opacity to `opa_bottom`
284  * @param opa_bottom opacity at the bottom
285  * @param y_bottom at which coordinate reach `opa_bottom`.
286  */
287 void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top,
288                             lv_coord_t y_top,
289                             lv_opa_t opa_bottom, lv_coord_t y_bottom);
290 
291 /**
292  * Initialize a map mask.
293  * @param param pointer to a `lv_draw_mask_param_t` to initialize
294  * @param coords coordinates of the map (absolute coordinates)
295  * @param map array of bytes with the mask values
296  */
297 void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map);
298 
299 /**********************
300  *      MACROS
301  **********************/
302 
303 #ifdef __cplusplus
304 } /* extern "C" */
305 #endif
306 
307 #endif /*LV_MASK_H*/
308