diff --git a/Kconfig b/Kconfig index 322ec110f..3fa162c96 100644 --- a/Kconfig +++ b/Kconfig @@ -393,19 +393,14 @@ menu "LVGL configuration" which usually improves performance, but does not guarantee the same rendering quality as the software. - config LV_VG_LITE_LINEAR_GRAD_CACHE_CNT - int "VG-Lite linear gradient image maximum cache number." + config LV_VG_LITE_GRAD_CACHE_CNT + int "VG-Lite gradient maximum cache number." default 32 depends on LV_USE_DRAW_VG_LITE help - The memory usage of a single gradient image is 4K bytes. - - config LV_VG_LITE_RADIAL_GRAD_CACHE_CNT - int "VG-Lite radial gradient image maximum cache number." - default 32 - depends on LV_USE_DRAW_VG_LITE - help - The memory usage of a single gradient image is radial grad radius * 4 bytes. + The memory usage of a single gradient: + linear: 4K bytes. + radial: radius * 4K bytes. config LV_USE_VECTOR_GRAPHIC bool "Use Vector Graphic APIs" @@ -653,6 +648,11 @@ menu "LVGL configuration" default n depends on LV_USE_VG_LITE_THORVG + config LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT + bool "Enable linear gradient extension support" + default n + depends on LV_USE_VG_LITE_THORVG + config LV_VG_LITE_THORVG_16PIXELS_ALIGN bool "Enable 16 pixels alignment" default y diff --git a/demos/vector_graphic/lv_demo_vector_graphic.c b/demos/vector_graphic/lv_demo_vector_graphic.c index b74a623a1..be5ae5728 100644 --- a/demos/vector_graphic/lv_demo_vector_graphic.c +++ b/demos/vector_graphic/lv_demo_vector_graphic.c @@ -58,25 +58,23 @@ static void draw_gradient(lv_vector_dsc_t * ctx, lv_vector_path_t * path) lv_vector_path_quad_to(path, &pts[1], &pts[2]); lv_vector_path_close(path); - lv_grad_dsc_t grad; - grad.dir = LV_GRAD_DIR_HOR; - grad.stops_count = 2; - grad.stops[0].color = lv_color_hex(0xff0000); - grad.stops[0].opa = LV_OPA_COVER; - grad.stops[0].frac = 0; - grad.stops[1].color = lv_color_hex(0x00ff00); - grad.stops[1].opa = LV_OPA_COVER; - grad.stops[1].frac = 255; - // grad.stops[2].color = lv_color_hex(0x0000ff); - // grad.stops[2].opa = LV_OPA_COVER; - // grad.stops[2].frac = 255; + lv_gradient_stop_t stops[2]; + lv_memzero(stops, sizeof(stops)); + stops[0].color = lv_color_hex(0xff0000); + stops[0].opa = LV_OPA_COVER; + stops[0].frac = 0; + stops[1].color = lv_color_hex(0x00ff00); + stops[1].opa = LV_OPA_COVER; + stops[1].frac = 255; lv_matrix_t mt; lv_matrix_identity(&mt); lv_matrix_rotate(&mt, 30); lv_vector_dsc_set_fill_transform(ctx, &mt); - lv_vector_dsc_set_fill_linear_gradient(ctx, &grad, LV_VECTOR_GRADIENT_SPREAD_PAD); + lv_vector_dsc_set_fill_linear_gradient(ctx, 200, 200, 400, 400); + lv_vector_dsc_set_fill_gradient_color_stops(ctx, stops, 2); + lv_vector_dsc_set_fill_gradient_spread(ctx, LV_VECTOR_GRADIENT_SPREAD_PAD); lv_vector_dsc_add_path(ctx, path); // draw a path } @@ -92,20 +90,18 @@ static void draw_radial_gradient(lv_vector_dsc_t * ctx, lv_vector_path_t * path) lv_vector_path_line_to(path, &pts[3]); lv_vector_path_close(path); - lv_grad_dsc_t grad; - grad.dir = LV_GRAD_DIR_HOR; - grad.stops_count = 2; - grad.stops[0].color = lv_color_hex(0xff0000); - grad.stops[0].opa = LV_OPA_COVER; - grad.stops[0].frac = 0; - grad.stops[1].color = lv_color_hex(0x0000ff); - grad.stops[1].opa = LV_OPA_COVER; - grad.stops[1].frac = 255; - // grad.stops[2].color = lv_color_hex(0x0000ff); - // grad.stops[2].opa = LV_OPA_COVER; - // grad.stops[2].frac = 255; + lv_gradient_stop_t stops[2]; + lv_memzero(stops, sizeof(stops)); + stops[0].color = lv_color_hex(0xff0000); + stops[0].opa = LV_OPA_COVER; + stops[0].frac = 0; + stops[1].color = lv_color_hex(0x0000ff); + stops[1].opa = LV_OPA_COVER; + stops[1].frac = 255; - lv_vector_dsc_set_fill_radial_gradient(ctx, &grad, 50, 50, 20, LV_VECTOR_GRADIENT_SPREAD_REFLECT); + lv_vector_dsc_set_fill_radial_gradient(ctx, 450, 100, 20); + lv_vector_dsc_set_fill_gradient_color_stops(ctx, stops, 2); + lv_vector_dsc_set_fill_gradient_spread(ctx, LV_VECTOR_GRADIENT_SPREAD_REFLECT); lv_vector_dsc_add_path(ctx, path); // draw a path } diff --git a/lv_conf_template.h b/lv_conf_template.h index c079f29fe..488a770ed 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -224,15 +224,10 @@ * but does not guarantee the same rendering quality as the software. */ #define LV_VG_LITE_USE_BOX_SHADOW 0 -/* VG-Lite linear gradient image maximum cache number. +/* VG-Lite gradient maximum cache number. * NOTE: The memory usage of a single gradient image is 4K bytes. */ -#define LV_VG_LITE_LINEAR_GRAD_CACHE_CNT 32 - -/* VG-Lite radial gradient image maximum cache size. - * NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes. - */ -#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32 +#define LV_VG_LITE_GRAD_CACHE_CNT 32 #endif @@ -382,6 +377,9 @@ /*Enable YUV color format support*/ #define LV_VG_LITE_THORVG_YUV_SUPPORT 0 + /*Enable Linear gradient extension support*/ + #define LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT 0 + /*Enable 16 pixels alignment*/ #define LV_VG_LITE_THORVG_16PIXELS_ALIGN 1 diff --git a/src/draw/lv_draw_vector.c b/src/draw/lv_draw_vector.c index 9ff61622b..375ad0a2a 100644 --- a/src/draw/lv_draw_vector.c +++ b/src/draw/lv_draw_vector.c @@ -85,18 +85,7 @@ static void _multiply_matrix(lv_matrix_t * matrix, const lv_matrix_t * mul) static void _copy_draw_dsc(lv_vector_draw_dsc_t * dst, const lv_vector_draw_dsc_t * src) { - dst->fill_dsc.style = src->fill_dsc.style; - dst->fill_dsc.color = src->fill_dsc.color; - dst->fill_dsc.opa = src->fill_dsc.opa; - dst->fill_dsc.fill_rule = src->fill_dsc.fill_rule; - dst->fill_dsc.gradient.style = src->fill_dsc.gradient.style; - dst->fill_dsc.gradient.cx = src->fill_dsc.gradient.cx; - dst->fill_dsc.gradient.cy = src->fill_dsc.gradient.cy; - dst->fill_dsc.gradient.cr = src->fill_dsc.gradient.cr; - dst->fill_dsc.gradient.spread = src->fill_dsc.gradient.spread; - lv_memcpy(&(dst->fill_dsc.gradient.grad), &(src->fill_dsc.gradient.grad), sizeof(lv_grad_dsc_t)); - lv_memcpy(&(dst->fill_dsc.img_dsc), &(src->fill_dsc.img_dsc), sizeof(lv_draw_image_dsc_t)); - lv_memcpy(&(dst->fill_dsc.matrix), &(src->fill_dsc.matrix), sizeof(lv_matrix_t)); + lv_memcpy(&(dst->fill_dsc), &(src->fill_dsc), sizeof(lv_vector_fill_dsc_t)); dst->stroke_dsc.style = src->stroke_dsc.style; dst->stroke_dsc.color = src->stroke_dsc.color; @@ -111,7 +100,7 @@ static void _copy_draw_dsc(lv_vector_draw_dsc_t * dst, const lv_vector_draw_dsc_ dst->stroke_dsc.gradient.cy = src->stroke_dsc.gradient.cy; dst->stroke_dsc.gradient.cr = src->stroke_dsc.gradient.cr; dst->stroke_dsc.gradient.spread = src->fill_dsc.gradient.spread; - lv_memcpy(&(dst->stroke_dsc.gradient.grad), &(src->stroke_dsc.gradient.grad), sizeof(lv_grad_dsc_t)); + lv_memcpy(&(dst->stroke_dsc.gradient), &(src->stroke_dsc.gradient), sizeof(lv_vector_gradient_t)); lv_memcpy(&(dst->stroke_dsc.matrix), &(src->stroke_dsc.matrix), sizeof(lv_matrix_t)); dst->blend_mode = src->blend_mode; @@ -666,25 +655,40 @@ void lv_vector_dsc_set_fill_image(lv_vector_dsc_t * dsc, const lv_draw_image_dsc lv_memcpy(&(dsc->current_dsc.fill_dsc.img_dsc), img_dsc, sizeof(lv_draw_image_dsc_t)); } -void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, - lv_vector_gradient_spread_t spread) +void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, float x1, float y1, float x2, float y2) { dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT; dsc->current_dsc.fill_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_LINEAR; - dsc->current_dsc.fill_dsc.gradient.spread = spread; - lv_memcpy(&(dsc->current_dsc.fill_dsc.gradient.grad), grad, sizeof(lv_grad_dsc_t)); + dsc->current_dsc.fill_dsc.gradient.x1 = x1; + dsc->current_dsc.fill_dsc.gradient.y1 = y1; + dsc->current_dsc.fill_dsc.gradient.x2 = x2; + dsc->current_dsc.fill_dsc.gradient.y2 = y2; } -void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, - float radius, lv_vector_gradient_spread_t spread) +void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, float cx, float cy, float radius) { dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT; dsc->current_dsc.fill_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_RADIAL; dsc->current_dsc.fill_dsc.gradient.cx = cx; dsc->current_dsc.fill_dsc.gradient.cy = cy; dsc->current_dsc.fill_dsc.gradient.cr = radius; +} + +void lv_vector_dsc_set_fill_gradient_spread(lv_vector_dsc_t * dsc, lv_vector_gradient_spread_t spread) +{ dsc->current_dsc.fill_dsc.gradient.spread = spread; - lv_memcpy(&(dsc->current_dsc.fill_dsc.gradient.grad), grad, sizeof(lv_grad_dsc_t)); +} + +void lv_vector_dsc_set_fill_gradient_color_stops(lv_vector_dsc_t * dsc, const lv_gradient_stop_t * stops, + uint16_t count) +{ + if(count > LV_GRADIENT_MAX_STOPS) { + LV_LOG_WARN("Too many gradient stops. Truncating to %d", LV_GRADIENT_MAX_STOPS); + count = LV_GRADIENT_MAX_STOPS; + } + + lv_memcpy(&(dsc->current_dsc.fill_dsc.gradient.stops), stops, sizeof(lv_gradient_stop_t) * count); + dsc->current_dsc.fill_dsc.gradient.stops_count = count; } void lv_vector_dsc_set_fill_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix) @@ -754,25 +758,40 @@ void lv_vector_dsc_set_stroke_miter_limit(lv_vector_dsc_t * dsc, uint16_t miter_ dsc->current_dsc.stroke_dsc.miter_limit = miter_limit; } -void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, - lv_vector_gradient_spread_t spread) +void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, float x1, float y1, float x2, float y2) { dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT; dsc->current_dsc.stroke_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_LINEAR; - dsc->current_dsc.stroke_dsc.gradient.spread = spread; - lv_memcpy(&(dsc->current_dsc.stroke_dsc.gradient.grad), grad, sizeof(lv_grad_dsc_t)); + dsc->current_dsc.stroke_dsc.gradient.x1 = x1; + dsc->current_dsc.stroke_dsc.gradient.y1 = y1; + dsc->current_dsc.stroke_dsc.gradient.x2 = x2; + dsc->current_dsc.stroke_dsc.gradient.y2 = y2; } -void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, - float radius, lv_vector_gradient_spread_t spread) +void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, float cx, float cy, float radius) { dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT; dsc->current_dsc.stroke_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_RADIAL; dsc->current_dsc.stroke_dsc.gradient.cx = cx; dsc->current_dsc.stroke_dsc.gradient.cy = cy; dsc->current_dsc.stroke_dsc.gradient.cr = radius; +} + +void lv_vector_dsc_set_stroke_gradient_spread(lv_vector_dsc_t * dsc, lv_vector_gradient_spread_t spread) +{ dsc->current_dsc.stroke_dsc.gradient.spread = spread; - lv_memcpy(&(dsc->current_dsc.stroke_dsc.gradient.grad), grad, sizeof(lv_grad_dsc_t)); +} + +void lv_vector_dsc_set_stroke_gradient_color_stops(lv_vector_dsc_t * dsc, const lv_gradient_stop_t * stops, + uint16_t count) +{ + if(count > LV_GRADIENT_MAX_STOPS) { + LV_LOG_WARN("Too many gradient stops. Truncating to %d", LV_GRADIENT_MAX_STOPS); + count = LV_GRADIENT_MAX_STOPS; + } + + lv_memcpy(&(dsc->current_dsc.stroke_dsc.gradient.stops), stops, sizeof(lv_gradient_stop_t) * count); + dsc->current_dsc.stroke_dsc.gradient.stops_count = count; } /* draw functions */ diff --git a/src/draw/lv_draw_vector.h b/src/draw/lv_draw_vector.h index 675359d3d..103c473b0 100644 --- a/src/draw/lv_draw_vector.h +++ b/src/draw/lv_draw_vector.h @@ -107,7 +107,12 @@ typedef struct { typedef struct { lv_vector_gradient_style_t style; - lv_grad_dsc_t grad; + lv_gradient_stop_t stops[LV_GRADIENT_MAX_STOPS]; /**< A gradient stop array */ + uint16_t stops_count; /**< The number of used stops in the array */ + float x1; + float y1; + float x2; + float y2; float cx; float cy; float cr; @@ -391,24 +396,39 @@ void lv_vector_dsc_set_fill_image(lv_vector_dsc_t * dsc, const lv_draw_image_dsc /** * Set fill linear gradient for descriptor - * @param dsc pointer to a vector graphic descriptor - * @param grad pointer to a `lv_grad_dsc_t` variable - * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format + * @param dsc pointer to a vector graphic descriptor + * @param x1 the x for start point + * @param y1 the y for start point + * @param x2 the x for end point + * @param y2 the y for end point */ -void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, - lv_vector_gradient_spread_t spread); +void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, float x1, float y1, float x2, float y2); /** - * Set fill radial gradient for descriptor - * @param dsc pointer to a vector graphic descriptor - * @param grad pointer to a `lv_grad_dsc_t` variable - * @param cx the x for center of the circle - * @param cy the y for center of the circle - * @param radius the radius for circle - * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format + + * Set fill radial gradient radius for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param cx the x for center of the circle + * @param cy the y for center of the circle + * @param radius the radius for circle */ -void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, - float radius, lv_vector_gradient_spread_t spread); +void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, float cx, float cy, float radius); + +/** + * Set fill radial gradient spread for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format + */ +void lv_vector_dsc_set_fill_gradient_spread(lv_vector_dsc_t * dsc, lv_vector_gradient_spread_t spread); + +/** + * Set fill gradient color stops for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param stops an array of `lv_gradient_stop_t` variables + * @param count the number of stops in the array + */ +void lv_vector_dsc_set_fill_gradient_color_stops(lv_vector_dsc_t * dsc, const lv_gradient_stop_t * stops, + uint16_t count); /** * Set a matrix to current fill transformation matrix @@ -477,22 +497,37 @@ void lv_vector_dsc_set_stroke_miter_limit(lv_vector_dsc_t * dsc, uint16_t miter_ /** * Set stroke linear gradient for descriptor * @param dsc pointer to a vector graphic descriptor - * @param grad pointer to a `lv_grad_dsc_t` variable - * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format + * @param x1 the x for start point + * @param y1 the y for start point + * @param x2 the x for end point + * @param y2 the y for end point */ -void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, - lv_vector_gradient_spread_t spread); +void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, float x1, float y1, float x2, float y2); /** * Set stroke radial gradient for descriptor * @param dsc pointer to a vector graphic descriptor - * @param grad pointer to a `lv_grad_dsc_t` variable * @param cx the x for center of the circle * @param cy the y for center of the circle * @param radius the radius for circle + */ +void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, float cx, float cy, float radius); + +/** + * Set stroke color stops for descriptor + * @param dsc pointer to a vector graphic descriptor * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format */ -void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, - float radius, lv_vector_gradient_spread_t spread); +void lv_vector_dsc_set_stroke_gradient_spread(lv_vector_dsc_t * dsc, lv_vector_gradient_spread_t spread); + +/** + * Set stroke color stops for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param stops an array of `lv_gradient_stop_t` variables + * @param count the number of stops in the array + */ +void lv_vector_dsc_set_stroke_gradient_color_stops(lv_vector_dsc_t * dsc, const lv_gradient_stop_t * stops, + uint16_t count); + /** * Set a matrix to current stroke transformation matrix * @param dsc pointer to a vector graphic descriptor diff --git a/src/draw/sw/lv_draw_sw_vector.c b/src/draw/sw/lv_draw_sw_vector.c index b5f36f559..79d3dd7db 100644 --- a/src/draw/sw/lv_draw_sw_vector.c +++ b/src/draw/sw/lv_draw_sw_vector.c @@ -180,10 +180,10 @@ static Tvg_Stroke_Fill _lv_spread_to_tvg(lv_vector_gradient_spread_t sp) static void _setup_gradient(Tvg_Gradient * gradient, const lv_vector_gradient_t * grad, const lv_matrix_t * matrix) { - const lv_grad_dsc_t * g = &grad->grad; - Tvg_Color_Stop * stops = (Tvg_Color_Stop *)lv_malloc(sizeof(Tvg_Color_Stop) * g->stops_count); - for(uint8_t i = 0; i < g->stops_count; i++) { - const lv_gradient_stop_t * s = &(g->stops[i]); + Tvg_Color_Stop * stops = (Tvg_Color_Stop *)lv_malloc(sizeof(Tvg_Color_Stop) * grad->stops_count); + LV_ASSERT_MALLOC(stops); + for(uint16_t i = 0; i < grad->stops_count; i++) { + const lv_gradient_stop_t * s = &(grad->stops[i]); stops[i].offset = s->frac / 255.0f; stops[i].r = s->color.red; @@ -192,7 +192,7 @@ static void _setup_gradient(Tvg_Gradient * gradient, const lv_vector_gradient_t stops[i].a = s->opa; } - tvg_gradient_set_color_stops(gradient, stops, g->stops_count); + tvg_gradient_set_color_stops(gradient, stops, grad->stops_count); tvg_gradient_set_spread(gradient, _lv_spread_to_tvg(grad->spread)); Tvg_Matrix mtx; _lv_matrix_to_tvg(&mtx, matrix); @@ -202,26 +202,16 @@ static void _setup_gradient(Tvg_Gradient * gradient, const lv_vector_gradient_t static void _set_paint_stroke_gradient(Tvg_Paint * obj, const lv_vector_gradient_t * g, const lv_matrix_t * m) { - float x, y, w, h; - tvg_paint_get_bounds(obj, &x, &y, &w, &h, false); - Tvg_Gradient * grad = NULL; if(g->style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { grad = tvg_radial_gradient_new(); - tvg_radial_gradient_set(grad, g->cx + x, g->cy + y, g->cr); + tvg_radial_gradient_set(grad, g->cx, g->cy, g->cr); _setup_gradient(grad, g, m); tvg_shape_set_stroke_radial_gradient(obj, grad); } else { grad = tvg_linear_gradient_new(); - - if(g->grad.dir == LV_GRAD_DIR_VER) { - tvg_linear_gradient_set(grad, x, y, x, y + h); - } - else { - tvg_linear_gradient_set(grad, x, y, x + w, y); - } - + tvg_linear_gradient_set(grad, g->x1, g->y1, g->x2, g->y2); _setup_gradient(grad, g, m); tvg_shape_set_stroke_linear_gradient(obj, grad); } @@ -263,26 +253,16 @@ static Tvg_Fill_Rule _lv_fill_rule_to_tvg(lv_vector_fill_t rule) static void _set_paint_fill_gradient(Tvg_Paint * obj, const lv_vector_gradient_t * g, const lv_matrix_t * m) { - float x, y, w, h; - tvg_paint_get_bounds(obj, &x, &y, &w, &h, false); - Tvg_Gradient * grad = NULL; if(g->style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { grad = tvg_radial_gradient_new(); - tvg_radial_gradient_set(grad, g->cx + x, g->cy + y, g->cr); + tvg_radial_gradient_set(grad, g->cx, g->cy, g->cr); _setup_gradient(grad, g, m); tvg_shape_set_radial_gradient(obj, grad); } else { grad = tvg_linear_gradient_new(); - - if(g->grad.dir == LV_GRAD_DIR_VER) { - tvg_linear_gradient_set(grad, x, y, x, y + h); - } - else { - tvg_linear_gradient_set(grad, x, y, x + w, y); - } - + tvg_linear_gradient_set(grad, g->x1, g->y1, g->x2, g->y2); _setup_gradient(grad, g, m); tvg_shape_set_linear_gradient(obj, grad); } diff --git a/src/draw/vg_lite/lv_draw_vg_lite.c b/src/draw/vg_lite/lv_draw_vg_lite.c index 24c4c9701..6d16e2dbd 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite.c +++ b/src/draw/vg_lite/lv_draw_vg_lite.c @@ -72,7 +72,9 @@ void lv_draw_vg_lite_init(void) unit->base_unit.delete_cb = draw_delete; lv_vg_lite_image_dsc_init(unit); - lv_vg_lite_grad_init(unit, LV_VG_LITE_LINEAR_GRAD_CACHE_CNT, LV_VG_LITE_RADIAL_GRAD_CACHE_CNT); +#if LV_USE_VECTOR_GRAPHIC + lv_vg_lite_grad_init(unit, LV_VG_LITE_GRAD_CACHE_CNT); +#endif lv_vg_lite_path_init(unit); lv_vg_lite_decoder_init(); } @@ -250,7 +252,9 @@ static int32_t draw_delete(lv_draw_unit_t * draw_unit) lv_draw_vg_lite_unit_t * unit = (lv_draw_vg_lite_unit_t *)draw_unit; lv_vg_lite_image_dsc_deinit(unit); +#if LV_USE_VECTOR_GRAPHIC lv_vg_lite_grad_deinit(unit); +#endif lv_vg_lite_path_deinit(unit); lv_vg_lite_decoder_deinit(); return 1; diff --git a/src/draw/vg_lite/lv_draw_vg_lite_fill.c b/src/draw/vg_lite/lv_draw_vg_lite_fill.c index 094219282..5e429f9ff 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_fill.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_fill.c @@ -81,17 +81,19 @@ void lv_draw_vg_lite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * LV_VG_LITE_ASSERT_MATRIX(&matrix); if(dsc->grad.dir != LV_GRAD_DIR_NONE) { - vg_lite_matrix_t grad_matrix; - lv_vg_lite_grad_area_to_matrix(&grad_matrix, coords, dsc->grad.dir); - lv_vg_lite_draw_linear_grad( +#if LV_USE_VECTOR_GRAPHIC + lv_vg_lite_draw_grad_helper( u, &u->target_buffer, vg_lite_path, + coords, &dsc->grad, - &grad_matrix, &matrix, VG_LITE_FILL_EVEN_ODD, VG_LITE_BLEND_SRC_OVER); +#else + LV_LOG_WARN("Gradient fill is not supported without VECTOR_GRAPHIC"); +#endif } else { /* normal fill */ vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true); diff --git a/src/draw/vg_lite/lv_draw_vg_lite_triangle.c b/src/draw/vg_lite/lv_draw_vg_lite_triangle.c index 760f695ff..b41b1aa11 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_triangle.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_triangle.c @@ -76,17 +76,19 @@ void lv_draw_vg_lite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle LV_VG_LITE_ASSERT_MATRIX(&matrix); if(dsc->bg_grad.dir != LV_GRAD_DIR_NONE) { - vg_lite_matrix_t grad_matrix; - lv_vg_lite_grad_area_to_matrix(&grad_matrix, &tri_area, dsc->bg_grad.dir); - lv_vg_lite_draw_linear_grad( +#if LV_USE_VECTOR_GRAPHIC + lv_vg_lite_draw_grad_helper( u, &u->target_buffer, vg_lite_path, + &tri_area, &dsc->bg_grad, - &grad_matrix, &matrix, VG_LITE_FILL_EVEN_ODD, VG_LITE_BLEND_SRC_OVER); +#else + LV_LOG_WARN("Gradient fill is not supported without VECTOR_GRAPHIC"); +#endif } else { /* normal fill */ vg_lite_color_t color = lv_vg_lite_color(dsc->bg_color, dsc->bg_opa, true); diff --git a/src/draw/vg_lite/lv_draw_vg_lite_type.h b/src/draw/vg_lite/lv_draw_vg_lite_type.h index 36f096be8..8767491cd 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_type.h +++ b/src/draw/vg_lite/lv_draw_vg_lite_type.h @@ -43,11 +43,8 @@ struct _lv_draw_vg_lite_unit_t { struct _lv_vg_lite_pending_t * image_dsc_pending; - lv_cache_t * linear_grad_cache; - struct _lv_vg_lite_pending_t * linear_grad_pending; - - lv_cache_t * radial_grad_cache; - struct _lv_vg_lite_pending_t * radial_grad_pending; + lv_cache_t * grad_cache; + struct _lv_vg_lite_pending_t * grad_pending; uint16_t flush_count; vg_lite_buffer_t target_buffer; diff --git a/src/draw/vg_lite/lv_draw_vg_lite_vector.c b/src/draw/vg_lite/lv_draw_vg_lite_vector.c index 86536b266..4dda2fa9e 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_vector.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -203,48 +203,18 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec } break; case LV_VECTOR_DRAW_STYLE_GRADIENT: { - /* draw gradient */ - lv_vector_gradient_style_t style = dsc->fill_dsc.gradient.style; + vg_lite_matrix_t grad_matrix; + lv_matrix_to_vg(&grad_matrix, &dsc->fill_dsc.matrix); - if(style == LV_VECTOR_GRADIENT_STYLE_LINEAR) { - vg_lite_matrix_t grad_matrix, fill_matrix; - lv_area_t grad_area; - lv_area_set(&grad_area, (int32_t)min_x, (int32_t)min_y, (int32_t)max_x, (int32_t)max_y); - lv_vg_lite_grad_area_to_matrix(&grad_matrix, &grad_area, LV_GRAD_DIR_HOR); - - lv_matrix_to_vg(&fill_matrix, &dsc->fill_dsc.matrix); - lv_vg_lite_matrix_multiply(&grad_matrix, &matrix); - lv_vg_lite_matrix_multiply(&grad_matrix, &fill_matrix); - - lv_vg_lite_draw_linear_grad( - u, - &u->target_buffer, - vg_path, - &dsc->fill_dsc.gradient.grad, - &grad_matrix, - &matrix, - fill, - blend); - } - else if(style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { - vg_lite_matrix_t grad_matrix; - lv_matrix_to_vg(&grad_matrix, &dsc->fill_dsc.matrix); - - /* add min_x, min_y to gradient center */ - lv_vector_gradient_t new_grad = dsc->fill_dsc.gradient; - new_grad.cx += min_x; - new_grad.cy += min_y; - - lv_vg_lite_draw_radial_grad( - u, - &u->target_buffer, - vg_path, - &new_grad, - &grad_matrix, - &matrix, - fill, - blend); - } + lv_vg_lite_draw_grad( + u, + &u->target_buffer, + vg_path, + &dsc->fill_dsc.gradient, + &grad_matrix, + &matrix, + fill, + blend); } break; default: diff --git a/src/draw/vg_lite/lv_vg_lite_grad.c b/src/draw/vg_lite/lv_vg_lite_grad.c index ce415e977..9e84cbfd9 100644 --- a/src/draw/vg_lite/lv_vg_lite_grad.c +++ b/src/draw/vg_lite/lv_vg_lite_grad.c @@ -9,7 +9,7 @@ #include "lv_vg_lite_grad.h" -#if LV_USE_DRAW_VG_LITE +#if LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC #include "lv_draw_vg_lite_type.h" #include "lv_vg_lite_pending.h" @@ -21,52 +21,47 @@ * DEFINES *********************/ +#define SQUARE(x) ((x)*(x)) + +#ifndef M_PI + #define M_PI 3.1415926f +#endif + /********************** * TYPEDEFS **********************/ -typedef struct { - lv_grad_dsc_t lv_grad; - vg_lite_linear_gradient_t vg_grad; -} linear_grad_item_t; - -#if LV_USE_VECTOR_GRAPHIC +typedef enum { + GRAD_TYPE_UNKNOWN, + GRAD_TYPE_LINEAR, + GRAD_TYPE_LINEAR_EXT, + GRAD_TYPE_RADIAL, +} grad_type_t; typedef struct { - lv_vector_gradient_t lv_grad; - vg_lite_radial_gradient_t vg_grad; -} radial_grad_item_t; - -#endif /* LV_USE_VECTOR_GRAPHIC */ + grad_type_t type; + lv_vector_gradient_t lv; + union { + vg_lite_linear_gradient_t linear; + vg_lite_ext_linear_gradient_t linear_ext; + vg_lite_radial_gradient_t radial; + } vg; +} grad_item_t; /********************** * STATIC PROTOTYPES **********************/ +static grad_item_t * grad_get(struct _lv_draw_vg_lite_unit_t * u, const lv_vector_gradient_t * grad); static void grad_cache_release_cb(void * entry, void * user_data); +static bool grad_create_cb(grad_item_t * item, void * user_data); +static void grad_free_cb(grad_item_t * item, void * user_data); +static lv_cache_compare_res_t grad_compare_cb(const grad_item_t * lhs, const grad_item_t * rhs); -/* Linear gradient */ - -static vg_lite_linear_gradient_t * linear_grad_get(struct _lv_draw_vg_lite_unit_t * u, - const lv_grad_dsc_t * grad); -static bool linear_grad_create_cb(linear_grad_item_t * item, void * user_data); -static void linear_grad_free_cb(linear_grad_item_t * item, void * user_data); -static lv_cache_compare_res_t linear_grad_compare_cb(const linear_grad_item_t * lhs, const linear_grad_item_t * rhs); - -#if LV_USE_VECTOR_GRAPHIC - -/* Radial gradient */ - -static vg_lite_radial_gradient_t * radial_grad_get(struct _lv_draw_vg_lite_unit_t * u, - const lv_vector_gradient_t * grad); -static bool radial_grad_create_cb(radial_grad_item_t * item, void * user_data); -static void radial_grad_free_cb(radial_grad_item_t * item, void * user_data); -static lv_cache_compare_res_t radial_grad_compare_cb(const radial_grad_item_t * lhs, const radial_grad_item_t * rhs); - +static grad_type_t lv_grad_style_to_type(lv_vector_gradient_style_t style); +static void grad_point_to_matrix(vg_lite_matrix_t * grad_matrix, float x1, float y1, float x2, float y2); static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread); -#endif /* LV_USE_VECTOR_GRAPHIC */ - /********************** * STATIC VARIABLES **********************/ @@ -79,142 +74,33 @@ static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t * GLOBAL FUNCTIONS **********************/ -void lv_vg_lite_grad_init( - struct _lv_draw_vg_lite_unit_t * u, - uint32_t linear_grad_cache_cnt, - uint32_t radial_grad_cache_cnt) +void lv_vg_lite_grad_init(struct _lv_draw_vg_lite_unit_t * u, uint32_t cache_cnt) { LV_ASSERT_NULL(u); - LV_UNUSED(radial_grad_cache_cnt); - /* Create the cache for linear gradients */ - { - lv_cache_ops_t ops = { - .compare_cb = (lv_cache_compare_cb_t)linear_grad_compare_cb, - .create_cb = (lv_cache_create_cb_t)linear_grad_create_cb, - .free_cb = (lv_cache_free_cb_t)linear_grad_free_cb, - }; + lv_cache_ops_t ops = { + .compare_cb = (lv_cache_compare_cb_t)grad_compare_cb, + .create_cb = (lv_cache_create_cb_t)grad_create_cb, + .free_cb = (lv_cache_free_cb_t)grad_free_cb, + }; - u->linear_grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(linear_grad_item_t), - linear_grad_cache_cnt, - ops); - lv_cache_set_name(u->linear_grad_cache, "LINEAR_GRAD"); - u->linear_grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4); - lv_vg_lite_pending_set_free_cb(u->linear_grad_pending, grad_cache_release_cb, u->linear_grad_cache); - } - -#if LV_USE_VECTOR_GRAPHIC - - /* Create the cache for radial gradients */ - if(vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) { - lv_cache_ops_t ops = { - .compare_cb = (lv_cache_compare_cb_t)radial_grad_compare_cb, - .create_cb = (lv_cache_create_cb_t)radial_grad_create_cb, - .free_cb = (lv_cache_free_cb_t)radial_grad_free_cb, - }; - - u->radial_grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(radial_grad_item_t), - radial_grad_cache_cnt, - ops); - u->radial_grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4); - lv_vg_lite_pending_set_free_cb(u->radial_grad_pending, grad_cache_release_cb, u->radial_grad_cache); - } - -#endif /* LV_USE_VECTOR_GRAPHIC */ + u->grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(grad_item_t), cache_cnt, ops); + lv_cache_set_name(u->grad_cache, "VG_GRAD"); + u->grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4); + lv_vg_lite_pending_set_free_cb(u->grad_pending, grad_cache_release_cb, u->grad_cache); } void lv_vg_lite_grad_deinit(struct _lv_draw_vg_lite_unit_t * u) { LV_ASSERT_NULL(u); - lv_vg_lite_pending_destroy(u->linear_grad_pending); - u->linear_grad_pending = NULL; - lv_cache_destroy(u->linear_grad_cache, NULL); - u->linear_grad_cache = NULL; - - if(u->radial_grad_pending) { - lv_vg_lite_pending_destroy(u->radial_grad_pending); - u->radial_grad_pending = NULL; - lv_cache_destroy(u->radial_grad_cache, NULL); - u->radial_grad_cache = NULL; - } + LV_ASSERT_NULL(u->grad_pending) + lv_vg_lite_pending_destroy(u->grad_pending); + u->grad_pending = NULL; + lv_cache_destroy(u->grad_cache, NULL); + u->grad_cache = NULL; } -void lv_vg_lite_grad_area_to_matrix(vg_lite_matrix_t * grad_matrix, const lv_area_t * area, lv_grad_dir_t dir) -{ - LV_ASSERT_NULL(grad_matrix); - LV_ASSERT_NULL(area); - - vg_lite_identity(grad_matrix); - vg_lite_translate(area->x1, area->y1, grad_matrix); - - switch(dir) { - case LV_GRAD_DIR_VER: - vg_lite_scale(1, lv_area_get_height(area) / 256.0f, grad_matrix); - vg_lite_rotate(90, grad_matrix); - break; - - case LV_GRAD_DIR_HOR: - vg_lite_scale(lv_area_get_width(area) / 256.0f, 1, grad_matrix); - break; - - default: - break; - } -} - -void lv_vg_lite_draw_linear_grad( - struct _lv_draw_vg_lite_unit_t * u, - vg_lite_buffer_t * buffer, - vg_lite_path_t * path, - const lv_grad_dsc_t * grad, - const vg_lite_matrix_t * grad_matrix, - const vg_lite_matrix_t * matrix, - vg_lite_fill_t fill, - vg_lite_blend_t blend) -{ - LV_ASSERT_NULL(u); - LV_ASSERT_NULL(buffer); - LV_ASSERT_NULL(path); - LV_ASSERT_NULL(grad); - LV_ASSERT_NULL(grad_matrix); - LV_ASSERT_NULL(matrix); - - LV_PROFILER_BEGIN; - - vg_lite_linear_gradient_t * linear_grad = linear_grad_get(u, grad); - LV_ASSERT_NULL(linear_grad); - if(!linear_grad) { - LV_LOG_ERROR("Failed to get linear gradient"); - LV_PROFILER_END; - return; - } - - vg_lite_matrix_t * grad_mat_p = vg_lite_get_grad_matrix(linear_grad); - LV_ASSERT_NULL(grad_mat_p); - *grad_mat_p = *grad_matrix; - - LV_VG_LITE_ASSERT_DEST_BUFFER(buffer); - LV_VG_LITE_ASSERT_SRC_BUFFER(&linear_grad->image); - LV_VG_LITE_ASSERT_PATH(path); - LV_VG_LITE_ASSERT_MATRIX(grad_mat_p); - LV_VG_LITE_ASSERT_MATRIX(matrix); - - LV_PROFILER_BEGIN_TAG("vg_lite_draw_grad"); - LV_VG_LITE_CHECK_ERROR(vg_lite_draw_grad( - buffer, - path, - fill, - (vg_lite_matrix_t *)matrix, - linear_grad, - blend)); - LV_PROFILER_END_TAG("vg_lite_draw_grad"); - - LV_PROFILER_END; -} - -#if LV_USE_VECTOR_GRAPHIC - -void lv_vg_lite_draw_radial_grad( +bool lv_vg_lite_draw_grad( struct _lv_draw_vg_lite_unit_t * u, vg_lite_buffer_t * buffer, vg_lite_path_t * path, @@ -225,81 +111,239 @@ void lv_vg_lite_draw_radial_grad( vg_lite_blend_t blend) { LV_ASSERT_NULL(u); - LV_ASSERT_NULL(buffer); - LV_ASSERT_NULL(path); + LV_VG_LITE_ASSERT_DEST_BUFFER(buffer); + LV_VG_LITE_ASSERT_PATH(path); LV_ASSERT_NULL(grad); - LV_ASSERT_NULL(grad_matrix); - LV_ASSERT_NULL(matrix); + LV_VG_LITE_ASSERT_MATRIX(grad_matrix); + LV_VG_LITE_ASSERT_MATRIX(matrix); - if(!vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) { - LV_LOG_INFO("radial gradient is not supported"); - return; - } + /* check radial gradient is supported */ + if(grad->style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { + if(!vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) { + LV_LOG_INFO("radial gradient is not supported"); + return false; + } - if(grad->spread == LV_VECTOR_GRADIENT_SPREAD_REPEAT || grad->spread == LV_VECTOR_GRADIENT_SPREAD_REFLECT) { - if(!vg_lite_query_feature(gcFEATURE_BIT_VG_IM_REPEAT_REFLECT)) { - LV_LOG_INFO("repeat/reflect spread(%d) is not supported", (int)grad->spread); - return; + /* check if the radius is valid */ + if(grad->cr <= 0) { + LV_LOG_INFO("radius: %f is not valid", grad->cr); + return false; } } - LV_PROFILER_BEGIN; + /* check spread mode is supported */ + if(grad->spread == LV_VECTOR_GRADIENT_SPREAD_REPEAT || grad->spread == LV_VECTOR_GRADIENT_SPREAD_REFLECT) { + if(!vg_lite_query_feature(gcFEATURE_BIT_VG_IM_REPEAT_REFLECT)) { + LV_LOG_INFO("repeat/reflect spread(%d) is not supported", grad->spread); + return false; + } + } - vg_lite_radial_gradient_t * radial_grad = radial_grad_get(u, grad); + LV_PROFILER_BEGIN_TAG("grad_get"); + grad_item_t * grad_item = grad_get(u, grad); + LV_PROFILER_END_TAG("grad_get"); + if(!grad_item) { + LV_LOG_WARN("Failed to get gradient, style: %d", grad->style); + return false; + } + LV_ASSERT(grad_item->lv.style == grad->style); - vg_lite_matrix_t * grad_mat_p = vg_lite_get_radial_grad_matrix(radial_grad); - LV_ASSERT_NULL(grad_mat_p); - *grad_mat_p = *grad_matrix; + switch(grad_item->type) { + case GRAD_TYPE_LINEAR: { + vg_lite_linear_gradient_t * linear_grad = &grad_item->vg.linear; + vg_lite_matrix_t * grad_mat_p = vg_lite_get_grad_matrix(linear_grad); + LV_ASSERT_NULL(grad_mat_p); - LV_VG_LITE_ASSERT_DEST_BUFFER(buffer); - LV_VG_LITE_ASSERT_SRC_BUFFER(&radial_grad->image); - LV_VG_LITE_ASSERT_PATH(path); - LV_VG_LITE_ASSERT_MATRIX(grad_mat_p); - LV_VG_LITE_ASSERT_MATRIX(matrix); + grad_point_to_matrix(grad_mat_p, grad->x1, grad->y1, grad->x2, grad->y2); + lv_vg_lite_matrix_multiply(grad_mat_p, grad_matrix); - LV_PROFILER_BEGIN_TAG("vg_lite_draw_radial_grad"); - LV_VG_LITE_CHECK_ERROR( - vg_lite_draw_radial_grad( - buffer, - path, - fill, - (vg_lite_matrix_t *)matrix, - radial_grad, - 0, - blend, - VG_LITE_FILTER_LINEAR)); - LV_PROFILER_END_TAG("vg_lite_draw_radial_grad"); + LV_VG_LITE_ASSERT_SRC_BUFFER(&linear_grad->image); - LV_PROFILER_END; + LV_PROFILER_BEGIN_TAG("vg_lite_draw_grad"); + LV_VG_LITE_CHECK_ERROR(vg_lite_draw_grad( + buffer, + path, + fill, + (vg_lite_matrix_t *)matrix, + linear_grad, + blend)); + LV_PROFILER_END_TAG("vg_lite_draw_grad"); + } + break; + case GRAD_TYPE_LINEAR_EXT: { + vg_lite_ext_linear_gradient_t * linear_grad = &grad_item->vg.linear_ext; + vg_lite_matrix_t * grad_mat_p = vg_lite_get_linear_grad_matrix(linear_grad); + LV_ASSERT_NULL(grad_mat_p); + *grad_mat_p = *grad_matrix; + + LV_VG_LITE_ASSERT_SRC_BUFFER(&linear_grad->image); + + LV_PROFILER_BEGIN_TAG("vg_lite_draw_linear_grad"); + LV_VG_LITE_CHECK_ERROR(vg_lite_draw_linear_grad( + buffer, + path, + fill, + (vg_lite_matrix_t *)matrix, + linear_grad, + 0, + blend, + VG_LITE_FILTER_LINEAR)); + LV_PROFILER_END_TAG("vg_lite_draw_linear_grad"); + } + break; + + case GRAD_TYPE_RADIAL: { + vg_lite_radial_gradient_t * radial = &grad_item->vg.radial; + vg_lite_matrix_t * grad_mat_p = vg_lite_get_radial_grad_matrix(radial); + LV_ASSERT_NULL(grad_mat_p); + *grad_mat_p = *grad_matrix; + + LV_VG_LITE_ASSERT_SRC_BUFFER(&grad_item->vg.radial.image); + + LV_PROFILER_BEGIN_TAG("vg_lite_draw_radial_grad"); + LV_VG_LITE_CHECK_ERROR( + vg_lite_draw_radial_grad( + buffer, + path, + fill, + (vg_lite_matrix_t *)matrix, + &grad_item->vg.radial, + 0, + blend, + VG_LITE_FILTER_LINEAR)); + LV_PROFILER_END_TAG("vg_lite_draw_radial_grad"); + } + break; + + default: + LV_LOG_ERROR("Unsupported gradient type: %d", grad_item->type); + return false; + } + + return true; } -#endif /* LV_USE_VECTOR_GRAPHIC */ +bool lv_vg_lite_draw_grad_helper( + struct _lv_draw_vg_lite_unit_t * u, + vg_lite_buffer_t * buffer, + vg_lite_path_t * path, + const lv_area_t * area, + const lv_grad_dsc_t * grad_dsc, + const vg_lite_matrix_t * matrix, + vg_lite_fill_t fill, + vg_lite_blend_t blend) +{ + LV_ASSERT_NULL(u); + LV_VG_LITE_ASSERT_DEST_BUFFER(buffer); + LV_VG_LITE_ASSERT_PATH(path); + LV_ASSERT_NULL(area); + LV_ASSERT_NULL(grad_dsc); + LV_VG_LITE_ASSERT_MATRIX(matrix); + + lv_vector_gradient_t grad; + lv_memzero(&grad, sizeof(grad)); + + grad.style = LV_VECTOR_GRADIENT_STYLE_LINEAR; + grad.stops_count = grad_dsc->stops_count; + lv_memcpy(grad.stops, grad_dsc->stops, sizeof(lv_gradient_stop_t) * grad_dsc->stops_count); + + /*convert to spread mode*/ +#if LV_USE_DRAW_SW_COMPLEX_GRADIENTS + switch(grad_dsc->extend) { + case LV_GRAD_EXTEND_PAD: + grad.spread = LV_VECTOR_GRADIENT_SPREAD_PAD; + break; + case LV_GRAD_EXTEND_REPEAT: + grad.spread = LV_VECTOR_GRADIENT_SPREAD_REPEAT; + break; + case LV_GRAD_EXTEND_REFLECT: + grad.spread = LV_VECTOR_GRADIENT_SPREAD_REFLECT; + break; + default: + LV_LOG_WARN("Unsupported gradient extend mode: %d", grad_dsc->extend); + grad.spread = LV_VECTOR_GRADIENT_SPREAD_PAD; + break; + } +#else + grad.spread = LV_VECTOR_GRADIENT_SPREAD_PAD; +#endif + + switch(grad_dsc->dir) { + case LV_GRAD_DIR_VER: + grad.x1 = area->x1; + grad.y1 = area->y1; + grad.x2 = area->x1; + grad.y2 = area->y2 + 1; + break; + + case LV_GRAD_DIR_HOR: + grad.x1 = area->x1; + grad.y1 = area->y1; + grad.x2 = area->x2 + 1; + grad.y2 = area->y1; + break; + +#if LV_USE_DRAW_SW_COMPLEX_GRADIENTS + case LV_GRAD_DIR_LINEAR: { + int32_t w = lv_area_get_width(area); + int32_t h = lv_area_get_height(area); + + grad.x1 = lv_pct_to_px(grad_dsc->params.linear.start.x, w) + area->x1; + grad.y1 = lv_pct_to_px(grad_dsc->params.linear.start.y, h) + area->y1; + grad.x2 = lv_pct_to_px(grad_dsc->params.linear.end.x, w) + area->x1; + grad.y2 = lv_pct_to_px(grad_dsc->params.linear.end.y, h) + area->y1; + } + break; + + case LV_GRAD_DIR_RADIAL: { + grad.style = LV_VECTOR_GRADIENT_STYLE_RADIAL; + int32_t w = lv_area_get_width(area); + int32_t h = lv_area_get_height(area); + + grad.cx = lv_pct_to_px(grad_dsc->params.radial.focal.x, w) + area->x1; + grad.cy = lv_pct_to_px(grad_dsc->params.radial.focal.y, h) + area->y1; + int32_t end_extent_x = lv_pct_to_px(grad_dsc->params.radial.end_extent.x, w) + area->x1; + int32_t end_extent_y = lv_pct_to_px(grad_dsc->params.radial.end_extent.y, h) + area->y1; + grad.cr = LV_MAX(end_extent_x - grad.cx, end_extent_y - grad.cy); + } + break; +#endif + + default: + LV_LOG_WARN("Unsupported gradient direction: %d", grad_dsc->dir); + return false; + } + + vg_lite_matrix_t grad_matrix; + vg_lite_identity(&grad_matrix); + + return lv_vg_lite_draw_grad(u, buffer, path, &grad, &grad_matrix, matrix, fill, blend); +} /********************** * STATIC FUNCTIONS **********************/ -static void * grad_get( - struct _lv_draw_vg_lite_unit_t * u, - lv_cache_t * cache, - lv_vg_lite_pending_t * pending, - const void * key) +static grad_item_t * grad_get(struct _lv_draw_vg_lite_unit_t * u, const lv_vector_gradient_t * grad) { LV_ASSERT_NULL(u); - LV_ASSERT_NULL(cache); - LV_ASSERT_NULL(pending); - LV_ASSERT_NULL(key); + LV_ASSERT_NULL(grad); - lv_cache_entry_t * cache_node_entry = lv_cache_acquire(cache, key, NULL); + grad_item_t search_key; + lv_memzero(&search_key, sizeof(search_key)); + search_key.type = lv_grad_style_to_type(grad->style); + search_key.lv = *grad; + + lv_cache_entry_t * cache_node_entry = lv_cache_acquire(u->grad_cache, &search_key, NULL); if(cache_node_entry == NULL) { /* check if the cache is full */ - size_t free_size = lv_cache_get_free_size(cache, NULL); + size_t free_size = lv_cache_get_free_size(u->grad_cache, NULL); if(free_size == 0) { LV_LOG_INFO("grad cache is full, release all pending cache entries"); lv_vg_lite_finish(u); } - cache_node_entry = lv_cache_acquire_or_create(cache, key, NULL); + cache_node_entry = lv_cache_acquire_or_create(u->grad_cache, &search_key, NULL); if(cache_node_entry == NULL) { LV_LOG_ERROR("grad cache creating failed"); return NULL; @@ -307,7 +351,7 @@ static void * grad_get( } /* Add the new entry to the pending list */ - lv_vg_lite_pending_add(pending, &cache_node_entry); + lv_vg_lite_pending_add(u->grad_pending, &cache_node_entry); return lv_cache_entry_get_data(cache_node_entry); } @@ -316,33 +360,38 @@ static void grad_cache_release_cb(void * entry, void * user_data) { lv_cache_entry_t ** entry_p = entry; lv_cache_t * cache = user_data; - lv_cache_release(cache, *entry_p, NULL); + lv_cache_release(cache, * entry_p, NULL); } -/* Linear gradient */ - -static vg_lite_linear_gradient_t * linear_grad_get(struct _lv_draw_vg_lite_unit_t * u, - const lv_grad_dsc_t * grad) +static vg_lite_color_ramp_t * grad_create_color_ramp(const lv_vector_gradient_t * grad) { - linear_grad_item_t search_key; - lv_memzero(&search_key, sizeof(search_key)); - search_key.lv_grad = *grad; + LV_ASSERT_NULL(grad); - linear_grad_item_t * item = grad_get(u, u->linear_grad_cache, u->linear_grad_pending, &search_key); - if(!item) { + vg_lite_color_ramp_t * color_ramp = lv_malloc(sizeof(vg_lite_color_ramp_t) * grad->stops_count); + LV_ASSERT_MALLOC(color_ramp); + if(!color_ramp) { + LV_LOG_ERROR("malloc failed for color_ramp"); return NULL; } - return &item->vg_grad; + for(uint16_t i = 0; i < grad->stops_count; i++) { + color_ramp[i].stop = grad->stops[i].frac / 255.0f; + lv_color_t c = grad->stops[i].color; + + color_ramp[i].red = c.red / 255.0f; + color_ramp[i].green = c.green / 255.0f; + color_ramp[i].blue = c.blue / 255.0f; + color_ramp[i].alpha = grad->stops[i].opa / 255.0f; + } + + return color_ramp; } -static bool linear_grad_create_cb(linear_grad_item_t * item, void * user_data) +static bool linear_grad_create(grad_item_t * item) { - LV_UNUSED(user_data); - LV_PROFILER_BEGIN; - vg_lite_error_t err = vg_lite_init_grad(&item->vg_grad); + vg_lite_error_t err = vg_lite_init_grad(&item->vg.linear); if(err != VG_LITE_SUCCESS) { LV_PROFILER_END; LV_LOG_ERROR("init grad error(%d): %s", (int)err, lv_vg_lite_error_string(err)); @@ -353,99 +402,104 @@ static bool linear_grad_create_cb(linear_grad_item_t * item, void * user_data) vg_lite_uint32_t stops[VLC_MAX_GRADIENT_STOPS]; /* Gradient setup */ - uint8_t cnt = item->lv_grad.stops_count; - LV_ASSERT(cnt < VLC_MAX_GRADIENT_STOPS); - for(uint8_t i = 0; i < cnt; i++) { - stops[i] = item->lv_grad.stops[i].frac; - const lv_color_t * c = &item->lv_grad.stops[i].color; - lv_opa_t opa = item->lv_grad.stops[i].opa; + if(item->lv.stops_count > VLC_MAX_GRADIENT_STOPS) { + LV_LOG_WARN("Too many gradient stops, max is %d", VLC_MAX_GRADIENT_STOPS); + item->lv.stops_count = VLC_MAX_GRADIENT_STOPS; + } + + for(uint16_t i = 0; i < item->lv.stops_count; i++) { + stops[i] = item->lv.stops[i].frac; + const lv_color_t * c = &item->lv.stops[i].color; + lv_opa_t opa = item->lv.stops[i].opa; /* lvgl color -> gradient color */ lv_color_t grad_color = lv_color_make(c->blue, c->green, c->red); colors[i] = lv_vg_lite_color(grad_color, opa, true); } - LV_VG_LITE_CHECK_ERROR(vg_lite_set_grad(&item->vg_grad, cnt, colors, stops)); + LV_VG_LITE_CHECK_ERROR(vg_lite_set_grad(&item->vg.linear, item->lv.stops_count, colors, stops)); LV_PROFILER_BEGIN_TAG("vg_lite_update_grad"); - LV_VG_LITE_CHECK_ERROR(vg_lite_update_grad(&item->vg_grad)); + LV_VG_LITE_CHECK_ERROR(vg_lite_update_grad(&item->vg.linear)); LV_PROFILER_END_TAG("vg_lite_update_grad"); LV_PROFILER_END; return true; } -static void linear_grad_free_cb(linear_grad_item_t * item, void * user_data) +static bool linear_ext_grad_create(grad_item_t * item) { - LV_UNUSED(user_data); - LV_VG_LITE_CHECK_ERROR(vg_lite_clear_grad(&item->vg_grad)); -} - -static lv_cache_compare_res_t linear_grad_compare_cb(const linear_grad_item_t * lhs, const linear_grad_item_t * rhs) -{ - if(lhs->lv_grad.stops_count != rhs->lv_grad.stops_count) { - return lhs->lv_grad.stops_count > rhs->lv_grad.stops_count ? 1 : -1; - } - - int cmp_res = lv_memcmp(lhs->lv_grad.stops, rhs->lv_grad.stops, - sizeof(lv_gradient_stop_t) * lhs->lv_grad.stops_count); - if(cmp_res != 0) { - return cmp_res > 0 ? 1 : -1; - } - - return 0; -} - -#if LV_USE_VECTOR_GRAPHIC - -/* Radial gradient */ - -static vg_lite_radial_gradient_t * radial_grad_get(struct _lv_draw_vg_lite_unit_t * u, - const lv_vector_gradient_t * grad) -{ - radial_grad_item_t search_key; - lv_memzero(&search_key, sizeof(search_key)); - search_key.lv_grad = *grad; - - radial_grad_item_t * item = grad_get(u, u->radial_grad_cache, u->radial_grad_pending, &search_key); - if(!item) { - return NULL; - } - - return &item->vg_grad; -} - -static bool radial_grad_create_cb(radial_grad_item_t * item, void * user_data) -{ - LV_UNUSED(user_data); - LV_PROFILER_BEGIN; - lv_vector_gradient_t * grad = &item->lv_grad; - uint8_t stops_count = grad->grad.stops_count; - vg_lite_color_ramp_t * color_ramp = lv_malloc(sizeof(vg_lite_color_ramp_t) * stops_count); - LV_ASSERT_MALLOC(color_ramp); + if(item->lv.stops_count > VLC_MAX_COLOR_RAMP_STOPS) { + LV_LOG_WARN("Too many gradient stops, max is %d", VLC_MAX_COLOR_RAMP_STOPS); + item->lv.stops_count = VLC_MAX_COLOR_RAMP_STOPS; + } + + vg_lite_color_ramp_t * color_ramp = grad_create_color_ramp(&item->lv); if(!color_ramp) { - LV_LOG_ERROR("malloc failed for color_ramp"); + LV_PROFILER_END; return false; } - for(uint8_t i = 0; i < stops_count; i++) { - color_ramp[i].stop = grad->grad.stops[i].frac / 255.0f; - lv_color_t c = grad->grad.stops[i].color; + const vg_lite_linear_gradient_parameter_t grad_param = { + .X0 = item->lv.x1, + .Y0 = item->lv.y1, + .X1 = item->lv.x2, + .Y1 = item->lv.y2, + }; - color_ramp[i].red = c.red / 255.0f; - color_ramp[i].green = c.green / 255.0f; - color_ramp[i].blue = c.blue / 255.0f; - color_ramp[i].alpha = grad->grad.stops[i].opa / 255.0f; + vg_lite_ext_linear_gradient_t linear_grad; + lv_memzero(&linear_grad, sizeof(linear_grad)); + + LV_PROFILER_BEGIN_TAG("vg_lite_set_linear_grad"); + LV_VG_LITE_CHECK_ERROR( + vg_lite_set_linear_grad( + &linear_grad, + item->lv.stops_count, + color_ramp, + grad_param, + lv_spread_to_vg(item->lv.spread), + 1)); + LV_PROFILER_END_TAG("vg_lite_set_linear_grad"); + + LV_PROFILER_BEGIN_TAG("vg_lite_update_linear_grad"); + vg_lite_error_t err = vg_lite_update_linear_grad(&linear_grad); + LV_PROFILER_END_TAG("vg_lite_update_linear_grad"); + if(err == VG_LITE_SUCCESS) { + item->vg.linear_ext = linear_grad; + } + else { + LV_LOG_ERROR("update grad error(%d): %s", (int)err, lv_vg_lite_error_string(err)); + } + + lv_free(color_ramp); + + LV_PROFILER_END; + return err == VG_LITE_SUCCESS; +} + +static bool radial_grad_create(grad_item_t * item) +{ + LV_PROFILER_BEGIN; + + if(item->lv.stops_count > VLC_MAX_COLOR_RAMP_STOPS) { + LV_LOG_WARN("Too many gradient stops, max is %d", VLC_MAX_COLOR_RAMP_STOPS); + item->lv.stops_count = VLC_MAX_COLOR_RAMP_STOPS; + } + + vg_lite_color_ramp_t * color_ramp = grad_create_color_ramp(&item->lv); + if(!color_ramp) { + LV_PROFILER_END; + return false; } const vg_lite_radial_gradient_parameter_t grad_param = { - .cx = grad->cx, - .cy = grad->cy, - .r = grad->cr, - .fx = grad->cx, - .fy = grad->cy, + .cx = item->lv.cx, + .cy = item->lv.cy, + .r = item->lv.cr, + .fx = item->lv.cx, + .fy = item->lv.cy, }; vg_lite_radial_gradient_t radial_grad; @@ -455,18 +509,18 @@ static bool radial_grad_create_cb(radial_grad_item_t * item, void * user_data) LV_VG_LITE_CHECK_ERROR( vg_lite_set_radial_grad( &radial_grad, - stops_count, + item->lv.stops_count, color_ramp, grad_param, - lv_spread_to_vg(grad->spread), + lv_spread_to_vg(item->lv.spread), 1)); LV_PROFILER_END_TAG("vg_lite_set_radial_grad"); LV_PROFILER_BEGIN_TAG("vg_lite_update_radial_grad"); vg_lite_error_t err = vg_lite_update_radial_grad(&radial_grad); LV_PROFILER_END_TAG("vg_lite_update_radial_grad"); - if(!err) { - item->vg_grad = radial_grad; + if(err == VG_LITE_SUCCESS) { + item->vg.radial = radial_grad; } else { LV_LOG_ERROR("update radial grad error(%d): %s", (int)err, lv_vg_lite_error_string(err)); @@ -478,41 +532,29 @@ static bool radial_grad_create_cb(radial_grad_item_t * item, void * user_data) return err == VG_LITE_SUCCESS; } -static void radial_grad_free_cb(radial_grad_item_t * item, void * user_data) +static grad_type_t lv_grad_style_to_type(lv_vector_gradient_style_t style) { - LV_UNUSED(user_data); - LV_VG_LITE_CHECK_ERROR(vg_lite_clear_radial_grad(&item->vg_grad)); + if(style == LV_VECTOR_GRADIENT_STYLE_LINEAR) { + return vg_lite_query_feature(gcFEATURE_BIT_VG_LINEAR_GRADIENT_EXT) ? GRAD_TYPE_LINEAR_EXT : GRAD_TYPE_LINEAR; + } + + if(style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { + return GRAD_TYPE_RADIAL; + } + + LV_LOG_WARN("unknown gradient style: %d", style); + return GRAD_TYPE_UNKNOWN; } -static lv_cache_compare_res_t radial_grad_compare_cb(const radial_grad_item_t * lhs, const radial_grad_item_t * rhs) +static void grad_point_to_matrix(vg_lite_matrix_t * grad_matrix, float x1, float y1, float x2, float y2) { - if(!math_equal(lhs->lv_grad.cx, rhs->lv_grad.cx)) { - return lhs->lv_grad.cx > rhs->lv_grad.cx ? 1 : -1; - } + vg_lite_identity(grad_matrix); + vg_lite_translate(x1, y1, grad_matrix); - if(!math_equal(lhs->lv_grad.cy, rhs->lv_grad.cy)) { - return lhs->lv_grad.cy > rhs->lv_grad.cy ? 1 : -1; - } - - if(!math_equal(lhs->lv_grad.cr, rhs->lv_grad.cr)) { - return lhs->lv_grad.cr > rhs->lv_grad.cr ? 1 : -1; - } - - if(lhs->lv_grad.spread != rhs->lv_grad.spread) { - return lhs->lv_grad.spread > rhs->lv_grad.spread ? 1 : -1; - } - - if(lhs->lv_grad.grad.stops_count != rhs->lv_grad.grad.stops_count) { - return lhs->lv_grad.grad.stops_count > rhs->lv_grad.grad.stops_count ? 1 : -1; - } - - int cmp_res = lv_memcmp(lhs->lv_grad.grad.stops, rhs->lv_grad.grad.stops, - sizeof(lv_gradient_stop_t) * lhs->lv_grad.grad.stops_count); - if(cmp_res != 0) { - return cmp_res > 0 ? 1 : -1; - } - - return 0; + float angle = atan2f(y2 - y1, x2 - x1) * 180.0f / (float)M_PI; + vg_lite_rotate(angle, grad_matrix); + float length = sqrtf(SQUARE(x2 - x1) + SQUARE(y2 - y1)); + vg_lite_scale(length / 256.0f, 1, grad_matrix); } static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread) @@ -525,10 +567,124 @@ static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t case LV_VECTOR_GRADIENT_SPREAD_REFLECT: return VG_LITE_GRADIENT_SPREAD_REFLECT; default: - return VG_LITE_GRADIENT_SPREAD_FILL; + LV_LOG_WARN("unknown spread mode: %d", spread); + break; + } + + return VG_LITE_GRADIENT_SPREAD_FILL; +} + +static bool grad_create_cb(grad_item_t * item, void * user_data) +{ + LV_UNUSED(user_data); + item->type = lv_grad_style_to_type(item->lv.style); + switch(item->type) { + case GRAD_TYPE_LINEAR: + return linear_grad_create(item); + + case GRAD_TYPE_LINEAR_EXT: + return linear_ext_grad_create(item); + + case GRAD_TYPE_RADIAL: + return radial_grad_create(item); + + default: + LV_LOG_ERROR("unknown gradient type: %d", item->type); + break; + } + + return false; +} + +static void grad_free_cb(grad_item_t * item, void * user_data) +{ + LV_UNUSED(user_data); + switch(item->type) { + case GRAD_TYPE_LINEAR: + LV_VG_LITE_CHECK_ERROR(vg_lite_clear_grad(&item->vg.linear)); + break; + + case GRAD_TYPE_LINEAR_EXT: + LV_VG_LITE_CHECK_ERROR(vg_lite_clear_linear_grad(&item->vg.linear_ext)); + break; + + case GRAD_TYPE_RADIAL: + LV_VG_LITE_CHECK_ERROR(vg_lite_clear_radial_grad(&item->vg.radial)); + break; + + default: + LV_LOG_ERROR("unknown gradient type: %d", item->type); + break; } } -#endif /* LV_USE_VECTOR_GRAPHIC */ +static lv_cache_compare_res_t grad_compare_cb(const grad_item_t * lhs, const grad_item_t * rhs) +{ + /* compare type first */ + if(lhs->type != rhs->type) { + return lhs->type > rhs->type ? 1 : -1; + } -#endif /*LV_USE_DRAW_VG_LITE*/ + /* compare spread mode */ + if(lhs->lv.spread != rhs->lv.spread) { + return lhs->lv.spread > rhs->lv.spread ? 1 : -1; + } + + /* compare gradient parameters */ + switch(lhs->type) { + case GRAD_TYPE_LINEAR: + /* no extra compare needed */ + break; + + case GRAD_TYPE_LINEAR_EXT: + if(!math_equal(lhs->lv.x1, rhs->lv.x1)) { + return lhs->lv.x1 > rhs->lv.x1 ? 1 : -1; + } + + if(!math_equal(lhs->lv.y1, rhs->lv.y1)) { + return lhs->lv.y1 > rhs->lv.y1 ? 1 : -1; + } + + if(!math_equal(lhs->lv.x2, rhs->lv.x2)) { + return lhs->lv.x2 > rhs->lv.x2 ? 1 : -1; + } + + if(!math_equal(lhs->lv.y2, rhs->lv.y2)) { + return lhs->lv.y2 > rhs->lv.y2 ? 1 : -1; + } + break; + + case GRAD_TYPE_RADIAL: + if(!math_equal(lhs->lv.cx, rhs->lv.cx)) { + return lhs->lv.cx > rhs->lv.cx ? 1 : -1; + } + + if(!math_equal(lhs->lv.cy, rhs->lv.cy)) { + return lhs->lv.cy > rhs->lv.cy ? 1 : -1; + } + + if(!math_equal(lhs->lv.cr, rhs->lv.cr)) { + return lhs->lv.cr > rhs->lv.cr ? 1 : -1; + } + break; + + default: + LV_LOG_ERROR("unknown gradient type: %d", lhs->type); + break; + } + + /* compare stops count and stops */ + if(lhs->lv.stops_count != rhs->lv.stops_count) { + return lhs->lv.stops_count > rhs->lv.stops_count ? 1 : -1; + } + + int cmp_res = lv_memcmp(lhs->lv.stops, rhs->lv.stops, + sizeof(lv_gradient_stop_t) * lhs->lv.stops_count); + if(cmp_res != 0) { + return cmp_res > 0 ? 1 : -1; + } + + return 0; +} + +#endif /*LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC*/ diff --git a/src/draw/vg_lite/lv_vg_lite_grad.h b/src/draw/vg_lite/lv_vg_lite_grad.h index e3e4b052d..d9bde91e9 100644 --- a/src/draw/vg_lite/lv_vg_lite_grad.h +++ b/src/draw/vg_lite/lv_vg_lite_grad.h @@ -16,7 +16,7 @@ extern "C" { #include "../../lvgl.h" -#if LV_USE_DRAW_VG_LITE +#if LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC #include "lv_vg_lite_utils.h" @@ -32,28 +32,11 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -void lv_vg_lite_grad_init( - struct _lv_draw_vg_lite_unit_t * u, - uint32_t linear_grad_cache_cnt, - uint32_t radial_grad_cache_cnt); +void lv_vg_lite_grad_init(struct _lv_draw_vg_lite_unit_t * u, uint32_t cache_cnt); void lv_vg_lite_grad_deinit(struct _lv_draw_vg_lite_unit_t * u); -void lv_vg_lite_grad_area_to_matrix(vg_lite_matrix_t * grad_matrix, const lv_area_t * area, lv_grad_dir_t dir); - -void lv_vg_lite_draw_linear_grad( - struct _lv_draw_vg_lite_unit_t * u, - vg_lite_buffer_t * buffer, - vg_lite_path_t * path, - const lv_grad_dsc_t * grad, - const vg_lite_matrix_t * grad_matrix, - const vg_lite_matrix_t * matrix, - vg_lite_fill_t fill, - vg_lite_blend_t blend); - -#if LV_USE_VECTOR_GRAPHIC - -void lv_vg_lite_draw_radial_grad( +bool lv_vg_lite_draw_grad( struct _lv_draw_vg_lite_unit_t * u, vg_lite_buffer_t * buffer, vg_lite_path_t * path, @@ -63,13 +46,21 @@ void lv_vg_lite_draw_radial_grad( vg_lite_fill_t fill, vg_lite_blend_t blend); -#endif /* LV_USE_VECTOR_GRAPHIC */ +bool lv_vg_lite_draw_grad_helper( + struct _lv_draw_vg_lite_unit_t * u, + vg_lite_buffer_t * buffer, + vg_lite_path_t * path, + const lv_area_t * area, + const lv_grad_dsc_t * grad_dsc, + const vg_lite_matrix_t * matrix, + vg_lite_fill_t fill, + vg_lite_blend_t blend); /********************** * MACROS **********************/ -#endif /*LV_USE_DRAW_VG_LITE*/ +#endif /*LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/src/draw/vg_lite/lv_vg_lite_utils.c b/src/draw/vg_lite/lv_vg_lite_utils.c index 63dde06f6..ee0c7b9f5 100644 --- a/src/draw/vg_lite/lv_vg_lite_utils.c +++ b/src/draw/vg_lite/lv_vg_lite_utils.c @@ -1079,10 +1079,8 @@ void lv_vg_lite_finish(struct _lv_draw_vg_lite_unit_t * u) LV_VG_LITE_CHECK_ERROR(vg_lite_finish()); /* Clear all gradient caches reference */ - lv_vg_lite_pending_remove_all(u->linear_grad_pending); - - if(u->radial_grad_pending) { - lv_vg_lite_pending_remove_all(u->radial_grad_pending); + if(u->grad_pending) { + lv_vg_lite_pending_remove_all(u->grad_pending); } /* Clear image decoder dsc reference */ diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 501915464..4496d9a6c 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -657,25 +657,14 @@ #endif #endif -/* VG-Lite linear gradient image maximum cache number. +/* VG-Lite gradient maximum cache number. * NOTE: The memory usage of a single gradient image is 4K bytes. */ -#ifndef LV_VG_LITE_LINEAR_GRAD_CACHE_CNT - #ifdef CONFIG_LV_VG_LITE_LINEAR_GRAD_CACHE_CNT - #define LV_VG_LITE_LINEAR_GRAD_CACHE_CNT CONFIG_LV_VG_LITE_LINEAR_GRAD_CACHE_CNT +#ifndef LV_VG_LITE_GRAD_CACHE_CNT + #ifdef CONFIG_LV_VG_LITE_GRAD_CACHE_CNT + #define LV_VG_LITE_GRAD_CACHE_CNT CONFIG_LV_VG_LITE_GRAD_CACHE_CNT #else - #define LV_VG_LITE_LINEAR_GRAD_CACHE_CNT 32 - #endif -#endif - -/* VG-Lite radial gradient image maximum cache size. - * NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes. - */ -#ifndef LV_VG_LITE_RADIAL_GRAD_CACHE_CNT - #ifdef CONFIG_LV_VG_LITE_RADIAL_GRAD_CACHE_CNT - #define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT CONFIG_LV_VG_LITE_RADIAL_GRAD_CACHE_CNT - #else - #define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32 + #define LV_VG_LITE_GRAD_CACHE_CNT 32 #endif #endif @@ -1121,6 +1110,15 @@ #endif #endif + /*Enable Linear gradient extension support*/ + #ifndef LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT + #ifdef CONFIG_LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT + #define LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT CONFIG_LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT + #else + #define LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT 0 + #endif + #endif + /*Enable 16 pixels alignment*/ #ifndef LV_VG_LITE_THORVG_16PIXELS_ALIGN #ifdef _LV_KCONFIG_PRESENT diff --git a/src/others/vg_lite_tvg/vg_lite_tvg.cpp b/src/others/vg_lite_tvg/vg_lite_tvg.cpp index 27f56ead6..9d12835ae 100644 --- a/src/others/vg_lite_tvg/vg_lite_tvg.cpp +++ b/src/others/vg_lite_tvg/vg_lite_tvg.cpp @@ -463,10 +463,13 @@ extern "C" { vg_lite_uint32_t stride = VG_LITE_ALIGN((buffer->width * mul / div), align); buffer->stride = stride; + + /* Size must be multiple of align, See: https://en.cppreference.com/w/c/memory/aligned_alloc */ + size_t size = VG_LITE_ALIGN(buffer->height * stride, LV_VG_LITE_THORVG_BUF_ADDR_ALIGN); #ifndef _WIN32 - buffer->memory = aligned_alloc(LV_VG_LITE_THORVG_BUF_ADDR_ALIGN, stride * buffer->height); + buffer->memory = aligned_alloc(LV_VG_LITE_THORVG_BUF_ADDR_ALIGN, size); #else - buffer->memory = _aligned_malloc(stride * buffer->height, LV_VG_LITE_THORVG_BUF_ADDR_ALIGN); + buffer->memory = _aligned_malloc(size, LV_VG_LITE_THORVG_BUF_ADDR_ALIGN); #endif LV_ASSERT(buffer->memory); buffer->address = (vg_lite_uint32_t)(uintptr_t)buffer->memory; @@ -829,6 +832,10 @@ extern "C" { case gcFEATURE_BIT_VG_YUV_INPUT: #endif +#if LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT + case gcFEATURE_BIT_VG_LINEAR_GRADIENT_EXT: +#endif + #if LV_VG_LITE_THORVG_16PIXELS_ALIGN case gcFEATURE_BIT_VG_16PIXELS_ALIGN: #endif @@ -1264,6 +1271,49 @@ Empty_sequence_handler: return VG_LITE_SUCCESS; } + vg_lite_error_t vg_lite_draw_linear_grad(vg_lite_buffer_t * target, + vg_lite_path_t * path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t * path_matrix, + vg_lite_ext_linear_gradient_t * grad, + vg_lite_color_t paint_color, + vg_lite_blend_t blend, + vg_lite_filter_t filter) + { + LV_UNUSED(paint_color); + LV_UNUSED(filter); + + auto ctx = vg_lite_ctx::get_instance(); + TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target)); + + auto shape = Shape::gen(); + TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, path_matrix)); + TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(path_matrix))); + TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule));); + TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend))); + + auto linearGrad = LinearGradient::gen(); + TVG_CHECK_RETURN_VG_ERROR(linearGrad->linear(grad->linear_grad.X0, grad->linear_grad.Y0, grad->linear_grad.X1, + grad->linear_grad.Y1)); + TVG_CHECK_RETURN_VG_ERROR(linearGrad->transform(matrix_conv(&grad->matrix))); + TVG_CHECK_RETURN_VG_ERROR(linearGrad->spread(fill_spread_conv(grad->spread_mode))); + + tvg::Fill::ColorStop colorStops[VLC_MAX_COLOR_RAMP_STOPS]; + for(vg_lite_uint32_t i = 0; i < grad->ramp_length; i++) { + colorStops[i].offset = grad->color_ramp[i].stop; + colorStops[i].r = grad->color_ramp[i].red * 255.0f; + colorStops[i].g = grad->color_ramp[i].green * 255.0f; + colorStops[i].b = grad->color_ramp[i].blue * 255.0f; + colorStops[i].a = grad->color_ramp[i].alpha * 255.0f; + } + TVG_CHECK_RETURN_VG_ERROR(linearGrad->colorStops(colorStops, grad->ramp_length)); + + TVG_CHECK_RETURN_VG_ERROR(shape->fill(std::move(linearGrad))); + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape))); + + return VG_LITE_SUCCESS; + } + vg_lite_error_t vg_lite_set_radial_grad(vg_lite_radial_gradient_t * grad, vg_lite_uint32_t count, vg_lite_color_ramp_t * color_ramp, @@ -1720,8 +1770,8 @@ Empty_sequence_handler: float y_max = y_min + dlen * sinf(angle); LV_LOG_TRACE("linear gradient {%.2f, %.2f} ~ {%.2f, %.2f}", x_min, y_min, x_max, y_max); auto linearGrad = LinearGradient::gen(); - linearGrad->linear(x_min, y_min, x_max, y_max); - linearGrad->spread(FillSpread::Pad); + TVG_CHECK_RETURN_VG_ERROR(linearGrad->linear(x_min, y_min, x_max, y_max)); + TVG_CHECK_RETURN_VG_ERROR(linearGrad->spread(FillSpread::Pad)); tvg::Fill::ColorStop colorStops[VLC_MAX_GRADIENT_STOPS]; for(vg_lite_uint32_t i = 0; i < grad->count; i++) { diff --git a/tests/ref_imgs/draw/vector_draw_lines.png b/tests/ref_imgs/draw/vector_draw_lines.png index c0868d786..0ac257a37 100644 Binary files a/tests/ref_imgs/draw/vector_draw_lines.png and b/tests/ref_imgs/draw/vector_draw_lines.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_conical_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_conical_gradient_opa_128.png index 7215d62b7..c34820c5f 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_conical_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_conical_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_conical_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_conical_gradient_opa_255.png index 7215d62b7..c34820c5f 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_conical_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_conical_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_linear_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_linear_gradient_opa_128.png index 7215d62b7..9b43470cf 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_linear_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_linear_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_linear_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_linear_gradient_opa_255.png index 7215d62b7..9b43470cf 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_linear_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_linear_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_radial_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_radial_gradient_opa_128.png index 7215d62b7..693fe0cf8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_radial_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_radial_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_radial_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_radial_gradient_opa_255.png index 7215d62b7..693fe0cf8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_radial_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_radial_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_conical_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_conical_gradient_opa_128.png index b1100505c..9373f70b6 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_conical_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_conical_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_conical_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_conical_gradient_opa_255.png index b1100505c..9373f70b6 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_conical_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_conical_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_linear_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_linear_gradient_opa_128.png index b1100505c..80369a3e8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_linear_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_linear_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_linear_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_linear_gradient_opa_255.png index b1100505c..80369a3e8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_linear_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_linear_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_radial_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_radial_gradient_opa_128.png index b1100505c..fecad268b 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_radial_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_radial_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_radial_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_radial_gradient_opa_255.png index b1100505c..fecad268b 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_radial_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_radial_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_conical_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_conical_gradient_opa_128.png index 7215d62b7..c34820c5f 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_conical_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_conical_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_conical_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_conical_gradient_opa_255.png index 7215d62b7..c34820c5f 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_conical_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_conical_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_linear_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_linear_gradient_opa_128.png index 7215d62b7..9b43470cf 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_linear_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_linear_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_linear_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_linear_gradient_opa_255.png index 7215d62b7..9b43470cf 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_linear_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_linear_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_radial_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_radial_gradient_opa_128.png index 7215d62b7..693fe0cf8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_radial_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_radial_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_radial_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_radial_gradient_opa_255.png index 7215d62b7..693fe0cf8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_radial_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_radial_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_conical_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_conical_gradient_opa_128.png index 7215d62b7..c34820c5f 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_conical_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_conical_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_conical_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_conical_gradient_opa_255.png index 7215d62b7..c34820c5f 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_conical_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_conical_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_linear_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_linear_gradient_opa_128.png index 7215d62b7..9b43470cf 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_linear_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_linear_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_linear_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_linear_gradient_opa_255.png index 7215d62b7..9b43470cf 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_linear_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_linear_gradient_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_radial_gradient_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_radial_gradient_opa_128.png index 7215d62b7..693fe0cf8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_radial_gradient_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_radial_gradient_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_radial_gradient_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_radial_gradient_opa_255.png index 7215d62b7..693fe0cf8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_radial_gradient_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_radial_gradient_opa_255.png differ diff --git a/tests/src/lv_test_conf_vg_lite.h b/tests/src/lv_test_conf_vg_lite.h index fa56bcc18..62a000e4a 100644 --- a/tests/src/lv_test_conf_vg_lite.h +++ b/tests/src/lv_test_conf_vg_lite.h @@ -15,15 +15,10 @@ * but does not guarantee the same rendering quality as the software. */ #define LV_VG_LITE_USE_BOX_SHADOW 1 -/* VG-Lite linear gradient image maximum cache number. +/* VG-Lite gradient maximum cache number. * NOTE: The memory usage of a single gradient image is 4K bytes. */ -#define LV_VG_LITE_LINEAR_GRAD_CACHE_CNT 32 - -/* VG-Lite radial gradient image maximum cache size. - * NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes. - */ -#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32 +#define LV_VG_LITE_GRAD_CACHE_CNT 32 /* Disable 16 pixels alignment */ #define LV_VG_LITE_THORVG_16PIXELS_ALIGN 0 diff --git a/tests/src/test_cases/draw/test_draw_vector.c b/tests/src/test_cases/draw/test_draw_vector.c index ca1d135f6..cb729cd33 100644 --- a/tests/src/test_cases/draw/test_draw_vector.c +++ b/tests/src/test_cases/draw/test_draw_vector.c @@ -47,20 +47,21 @@ static void draw_shapes(lv_layer_t * layer) lv_vector_dsc_identity(ctx); lv_vector_dsc_translate(ctx, 0, 150); - lv_grad_dsc_t grad; - grad.dir = LV_GRAD_DIR_HOR; - grad.stops_count = 2; - grad.stops[0].color = lv_color_hex(0xffffff); - grad.stops[0].opa = LV_OPA_COVER; - grad.stops[0].frac = 0; - grad.stops[1].color = lv_color_hex(0x000000); - grad.stops[1].opa = LV_OPA_COVER; - grad.stops[1].frac = 255; + lv_gradient_stop_t stops[2]; + lv_memzero(stops, sizeof(stops)); + stops[0].color = lv_color_hex(0xffffff); + stops[0].opa = LV_OPA_COVER; + stops[0].frac = 0; + stops[1].color = lv_color_hex(0x000000); + stops[1].opa = LV_OPA_COVER; + stops[1].frac = 255; lv_matrix_t mt; lv_matrix_identity(&mt); lv_vector_dsc_set_fill_transform(ctx, &mt); - lv_vector_dsc_set_fill_radial_gradient(ctx, &grad, 50, 50, 50, LV_VECTOR_GRADIENT_SPREAD_PAD); + lv_vector_dsc_set_fill_radial_gradient(ctx, 100, 100, 50); + lv_vector_dsc_set_fill_gradient_color_stops(ctx, stops, 2); + lv_vector_dsc_set_fill_gradient_spread(ctx, LV_VECTOR_GRADIENT_SPREAD_PAD); lv_vector_dsc_add_path(ctx, path); lv_vector_dsc_identity(ctx); @@ -208,15 +209,14 @@ static void draw_lines(lv_layer_t * layer) lv_vector_path_clear(path); lv_vector_path_append_rect(path, &rect1, 0, 0); - lv_grad_dsc_t grad; - grad.dir = LV_GRAD_DIR_HOR; - grad.stops_count = 2; - grad.stops[0].color = lv_color_hex(0xff0000); - grad.stops[0].opa = LV_OPA_COVER; - grad.stops[0].frac = 0; - grad.stops[1].color = lv_color_hex(0x00ff00); - grad.stops[1].opa = LV_OPA_COVER; - grad.stops[1].frac = 255; + lv_gradient_stop_t stops[2]; + lv_memzero(stops, sizeof(stops)); + stops[0].color = lv_color_hex(0xff0000); + stops[0].opa = LV_OPA_COVER; + stops[0].frac = 0; + stops[1].color = lv_color_hex(0x00ff00); + stops[1].opa = LV_OPA_COVER; + stops[1].frac = 255; lv_matrix_t mt; lv_matrix_identity(&mt); @@ -224,7 +224,9 @@ static void draw_lines(lv_layer_t * layer) lv_matrix_translate(&mt, 20, 20); lv_vector_dsc_set_stroke_transform(ctx, &mt); lv_vector_dsc_set_stroke_join(ctx, LV_VECTOR_STROKE_JOIN_MITER); - lv_vector_dsc_set_stroke_linear_gradient(ctx, &grad, LV_VECTOR_GRADIENT_SPREAD_REFLECT); + lv_vector_dsc_set_stroke_linear_gradient(ctx, 250, 300, 350, 300); + lv_vector_dsc_set_stroke_gradient_color_stops(ctx, stops, 2); + lv_vector_dsc_set_stroke_gradient_spread(ctx, LV_VECTOR_GRADIENT_SPREAD_REFLECT); lv_vector_dsc_add_path(ctx, path); // draw a path lv_draw_vector(ctx);