Full gradient support for primitives

Hello, newbie here
I’ve been looking into new styles system and old one, crazy design!
The question - is it possible to add gradient styles to line, arc (maybe other primitives too)?
Check paint dot net, there few basic gradient styles:
Linear, linear reflected, diamond, circular and conic

For example arc could be faded at the beginning and bright at the end, or faded to circle center
I want to see something like that to be possible to make using standard library primitives, without making ‘png’ overlays with transparency: youtube id d3lXrqpA4oQ
radial

It should be possible already using masks. Documentation for them is rather limited at the moment, but it’s designed for use cases like these.

I’ll play around with it a bit and see if I can give you an example.

Here you go:

#define MASK_WIDTH 100
#define MASK_HEIGHT 100

static void arc_mask_test(void) {
    /* Create the mask of an arc by drawing it to a canvas*/
    static lv_opa_t mask_map[MASK_WIDTH * MASK_HEIGHT];

    /*Create a "8 bit alpha" canvas and clear it*/
    lv_obj_t * canvas = lv_canvas_create(lv_scr_act(), NULL);
    lv_canvas_set_buffer(canvas, mask_map, MASK_WIDTH, MASK_HEIGHT, LV_IMG_CF_ALPHA_8BIT);
    lv_canvas_fill_bg(canvas, LV_COLOR_BLACK, LV_OPA_TRANSP);

    /*Draw an arc to the canvas. The result "image" will be used as mask*/
    lv_draw_line_dsc_t arc_dsc;
    lv_draw_line_dsc_init(&arc_dsc);
    arc_dsc.color = LV_COLOR_WHITE;
    arc_dsc.width = 10;
    lv_canvas_draw_arc(canvas, MASK_WIDTH / 2, MASK_HEIGHT / 2, MASK_WIDTH / 2, 180, 360, &arc_dsc);

    /*The mask is reads the canvas is not required anymore*/
    lv_obj_del(canvas);

    /*Create an object mask which will use the created mask*/
    lv_obj_t * om = lv_objmask_create(lv_scr_act(), NULL);
    lv_obj_set_size(om, MASK_WIDTH, MASK_HEIGHT);
    lv_obj_align(om, NULL, LV_ALIGN_CENTER, 0, 0);

    /*Add the created mask map to the object mask*/
    lv_draw_mask_map_param_t m;
    lv_area_t a;
    a.x1 = 0;
    a.y1 = 0;
    a.x2 = MASK_WIDTH - 1;
    a.y2 = MASK_HEIGHT - 1;
    lv_draw_mask_map_init(&m, &a, mask_map);
    lv_objmask_add_mask(om, &m);

    /*Create a style with gradient*/
    static lv_style_t style_bg;
    lv_style_init(&style_bg);
    lv_style_set_bg_opa(&style_bg, LV_STATE_DEFAULT, LV_OPA_COVER);
    lv_style_set_bg_color(&style_bg, LV_STATE_DEFAULT, LV_COLOR_RED);
    lv_style_set_bg_grad_color(&style_bg, LV_STATE_DEFAULT, LV_COLOR_BLUE);
    lv_style_set_bg_grad_dir(&style_bg, LV_STATE_DEFAULT, LV_GRAD_DIR_HOR);

    /* Create and object with the gradient style on the object mask.
     * The arc will be masked from the gradient*/
    lv_obj_t * bg = lv_obj_create(om, NULL);
    lv_obj_reset_style_list(bg, LV_OBJ_PART_MAIN);
    lv_obj_add_style(bg, LV_OBJ_PART_MAIN, &style_bg);
    lv_obj_set_size(bg, MASK_WIDTH, MASK_HEIGHT);
}
1 Like

Thanks for example!
Basically that what i mean by ‘png’ overlay haha
%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA
Do i understand correctly that gradients are limited atm to this:
enum {
LV_GRAD_DIR_NONE,
LV_GRAD_DIR_VER,
LV_GRAD_DIR_HOR,
_LV_GRAD_DIR_LAST //not a gradient
};
And it is actually a linear filled, for natural look needs conic fill with ability to setup angles
How i would make a left side example on my picture in fist mesage? i understand i could use shadows somehow on this canvas

We don’t have support for conic gradients at the moment, unfortunately. For that I would suggest just using an image, especially if it’s for a small widget.

You shouldn’t need the canvas for that one, because you don’t necessarily need to mask anything by hand. Creating a standard blue lv_arc and then creating a black circular lv_obj with a shadow should work.

@embeddedt I’m currently in the process of understanding how to effectively implement this on a meter arc, but I’m encountering some challenges. Could you provide assistance and guidance to help me navigate through this?

To have a gradient on arcs you can use an image and apply it as:

      lv_obj_set_style_arc_img_src(arc1, &my_image, LV_PART_MAIN);

      //OR
      lv_obj_set_style_arc_img_src(arc1, &my_image, LV_PART_INDICATOR);

can it be made without using a image, something like rendering it with a canvas?

In LVGL v8 there is not built in conic gradient support, however you can use a custom algorithm to draw to a canvas too.

In v9 we have already integrated ThorVG, a feature rich vector graphics library. See an example here.