1 /**
2 * MIT License
3 *
4 * -----------------------------------------------------------------------------
5 * Copyright (c) 2008-24 Think Silicon Single Member PC
6 * -----------------------------------------------------------------------------
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights to
11 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 * the Software, and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next paragraph)
16 * shall be included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
19 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
22 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
23 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 /**
28 * @file lv_draw_nema_gfx_fill.c
29 *
30 */
31
32 /*********************
33 * INCLUDES
34 *********************/
35 #include "lv_draw_nema_gfx.h"
36
37 #if LV_USE_NEMA_GFX
38 #include <math.h>
39
40 /**********************
41 * GLOBAL FUNCTIONS
42 **********************/
lv_draw_nema_gfx_border(lv_draw_unit_t * draw_unit,const lv_draw_border_dsc_t * dsc,const lv_area_t * coords)43 void lv_draw_nema_gfx_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords)
44 {
45 if(dsc->opa <= LV_OPA_MIN)
46 return;
47 if(dsc->width == 0)
48 return;
49 if(dsc->side == LV_BORDER_SIDE_NONE)
50 return;
51
52 lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit;
53
54 lv_layer_t * layer = draw_unit->target_layer;
55 lv_area_t inward_coords;
56 int32_t width = dsc->width;
57
58 /* Move border inwards to align with software rendered border */
59 inward_coords.x1 = coords->x1 + ceil(width / 2.0f);
60 inward_coords.x2 = coords->x2 - floor(width / 2.0f);
61 inward_coords.y1 = coords->y1 + ceil(width / 2.0f);
62 inward_coords.y2 = coords->y2 - floor(width / 2.0f);
63
64 lv_area_move(&inward_coords, -layer->buf_area.x1, -layer->buf_area.y1);
65
66 lv_area_t clip_area;
67 lv_area_copy(&clip_area, draw_unit->clip_area);
68 lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
69
70 nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area));
71
72 lv_area_t clipped_coords;
73 if(!lv_area_intersect(&clipped_coords, &inward_coords, &clip_area))
74 return; /*Fully clipped, nothing to do*/
75
76 lv_color_format_t dst_cf = layer->draw_buf->header.cf;
77 uint32_t dst_nema_cf = lv_nemagfx_cf_to_nema(dst_cf);
78
79 nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(layer->draw_buf->data), lv_area_get_width(&(layer->buf_area)),
80 lv_area_get_height(&(layer->buf_area)), dst_nema_cf,
81 lv_area_get_width(&(layer->buf_area))*lv_color_format_get_size(dst_cf));
82
83 /* Recalculate float Dimensions */
84 float x1 = (float)coords->x1 + ((float)width / 2.0f) - (float)layer->buf_area.x1;
85 float x2 = (float)coords->x2 - ((float)width / 2.0f) - (float)layer->buf_area.x1;
86 float y1 = (float)coords->y1 + ((float)width / 2.0f) - (float)layer->buf_area.y1;
87 float y2 = (float)coords->y2 - ((float)width / 2.0f) - (float)layer->buf_area.y1;
88 float coords_bg_w = x2 - x1 + 1;
89 float coords_bg_h = y2 - y1 + 1;
90 int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h);
91 float radius = (float)LV_MIN(dsc->radius, short_side >> 1);
92
93 lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
94 uint32_t bg_color = nema_rgba(col32.red, col32.green, col32.blue, col32.alpha);
95
96 if(col32.alpha < 255U) {
97 nema_set_blend_fill(NEMA_BL_SRC_OVER);
98 bg_color = nema_premultiply_rgba(bg_color);
99 }
100 else {
101 nema_set_blend_fill(NEMA_BL_SRC);
102 }
103
104 if(radius > 0.0f) {
105 nema_draw_rounded_rect_aa(x1, y1, coords_bg_w, coords_bg_h, radius, width, bg_color);
106 }
107 else {
108 lv_area_t rect_coords = *coords;
109 lv_area_move(&rect_coords, -layer->buf_area.x1, -layer->buf_area.y1);
110 int32_t border_width = lv_area_get_width(&rect_coords);
111 int32_t border_height = lv_area_get_height(&rect_coords);
112
113 if(dsc->side & LV_BORDER_SIDE_TOP) {
114 float x = rect_coords.x1 + width;
115 float y = rect_coords.y1;
116 float w = border_width - 2 * width;
117 float h = width;
118 nema_enable_aa(1, 0, 1, 0);
119 nema_fill_rect_f(x, y, w, h, bg_color);
120 }
121
122 if(dsc->side & LV_BORDER_SIDE_BOTTOM) {
123 float x = rect_coords.x1 + width;
124 float y = rect_coords.y1 + border_height - width;
125 float w = border_width - 2 * width;
126 float h = width;
127 nema_enable_aa(1, 0, 1, 0);
128 nema_fill_rect_f(x, y, w, h, bg_color);
129 }
130
131 if(dsc->side & LV_BORDER_SIDE_LEFT) {
132 float x = rect_coords.x1;
133 float y = rect_coords.y1 + width;
134 float w = width;
135 float h = border_height - 2 * width;
136 nema_enable_aa(0, 1, 0, 1);
137 nema_fill_rect_f(x, y, w, h, bg_color);
138 }
139
140 if(dsc->side & LV_BORDER_SIDE_RIGHT) {
141 float x = rect_coords.x1 + border_width - width;
142 float y = rect_coords.y1 + width;
143 float w = width;
144 float h = border_height - 2 * width;
145 nema_enable_aa(0, 1, 0, 1);
146 nema_fill_rect_f(x, y, w, h, bg_color);
147 }
148
149 /*Draw small corner rectangles
150 Top Left*/
151 if(dsc->side & LV_BORDER_SIDE_TOP || dsc->side & LV_BORDER_SIDE_LEFT) {
152 float x = rect_coords.x1;
153 float y = rect_coords.y1;
154 float w = width;
155 float h = width;
156
157 if(!(dsc->side & LV_BORDER_SIDE_TOP))
158 nema_enable_aa(1, 1, 0, 1);
159 else if(!(dsc->side & LV_BORDER_SIDE_LEFT))
160 nema_enable_aa(1, 0, 1, 1);
161 else
162 nema_enable_aa(1, 0, 0, 1);
163
164 nema_fill_rect_f(x, y, w, h, bg_color);
165 }
166
167 /*Top Right*/
168 if(dsc->side & LV_BORDER_SIDE_TOP || dsc->side & LV_BORDER_SIDE_RIGHT) {
169 float x = rect_coords.x1 + border_width - width;
170 float y = rect_coords.y1;
171 float w = width;
172 float h = width;
173
174 if(!(dsc->side & LV_BORDER_SIDE_TOP))
175 nema_enable_aa(1, 1, 0, 1);
176 else if(!(dsc->side & LV_BORDER_SIDE_RIGHT))
177 nema_enable_aa(1, 1, 1, 0);
178 else
179 nema_enable_aa(1, 1, 0, 0);
180
181 nema_fill_rect_f(x, y, w, h, bg_color);
182 }
183
184 /*Bottom Right*/
185 if(dsc->side & LV_BORDER_SIDE_BOTTOM || dsc->side & LV_BORDER_SIDE_RIGHT) {
186 float x = rect_coords.x1 + border_width - width;
187 float y = rect_coords.y1 + border_height - width;
188 float w = width;
189 float h = width;
190
191 if(!(dsc->side & LV_BORDER_SIDE_BOTTOM))
192 nema_enable_aa(0, 1, 1, 1);
193 else if(!(dsc->side & LV_BORDER_SIDE_RIGHT))
194 nema_enable_aa(1, 1, 1, 0);
195 else
196 nema_enable_aa(0, 1, 1, 0);
197
198 nema_fill_rect_f(x, y, w, h, bg_color);
199 }
200
201 /*Bottom Left*/
202 if(dsc->side & LV_BORDER_SIDE_BOTTOM || dsc->side & LV_BORDER_SIDE_LEFT) {
203 float x = rect_coords.x1;
204 float y = rect_coords.y1 + border_height - width;
205 float w = width;
206 float h = width;
207
208 if(!(dsc->side & LV_BORDER_SIDE_BOTTOM))
209 nema_enable_aa(0, 1, 1, 1);
210 else if(!(dsc->side & LV_BORDER_SIDE_LEFT))
211 nema_enable_aa(1, 0, 1, 1);
212 else
213 nema_enable_aa(0, 0, 1, 1);
214
215 nema_fill_rect_f(x, y, w, h, bg_color);
216 }
217
218 }
219
220 nema_cl_submit(&(draw_nema_gfx_unit->cl));
221
222 }
223 #endif
224