[Request dev-7.0] another type of lv_draw_mask_param_t : lv_draw_mask_text_param_t

Wish lv_draw_mask_param_t has lv_draw_mask_text_param_t too,
for colorizing gradian text, rainbow text, etc…

It was my dream too the make possible to create things like that. However, it’d be very expensive to calculate this kind of mask real-time. Instead you can draw a text to a LV_IMG_CF_ALPHA_8BIT canvas and use lv_draw_mask_map.

1 Like

Oh, I see, I will try by lv_draw_mask_map(..)

I’ve created an example:
image

/*Create a mask map with a canvas*/
static uint8_t buf[LV_IMG_BUF_SIZE_ALPHA_8BIT(200, 30)];
lv_obj_t * canvas = lv_canvas_create(lv_scr_act(), NULL);
lv_canvas_set_buffer(canvas, buf, 200, 30, LV_IMG_CF_ALPHA_8BIT);
memset(buf, 0x00, sizeof(buf));
lv_canvas_draw_text(canvas, 0, 0, 200, &style, "Hello world", LV_LABEL_ALIGN_LEFT);

lv_obj_del(canvas);  /*Not required anymore, only `buf` will be used*/

/*Create a masker object. Everything is drawn on this object will be masked*/
lv_obj_t * mask = lv_objmask_create(lv_scr_act(), NULL);

/*Add a the mask map to the masking object.*/
lv_draw_mask_param_t mp;
lv_area_t area;
area.x1 = 0;
area.x1 = 0;
area.x2 = 199;
area.y2 = 29;
lv_draw_mask_map_init(&mp, &area, buf);
lv_objmask_add_mask(mask, &mp, 1);
lv_obj_set_size(mask, 200, 30);

/* Create a simple object with a gradient style.
 * (Image can be used too)*/
lv_obj_t * obj = lv_obj_create(mask, NULL);
lv_obj_set_size(obj, 200, 30);
lv_obj_set_style(obj, &style);

I’ll add some updates soon:

  • the mask coordinates are always absolute but it should be translated to relative by lv_objmask
  • now the whole lv_draw_mask_param_t is saved by the masking system. Later only it’s pointer will be saved.
1 Like

@kisvegabor
Thank you.

I’ve just tried by the following code. But the result is so strange. What is wrong? How to fix the code?

uint8_t buf[ 200* 50];

void create_text_gradian() {
  static lv_style_t style; 
    lv_style_copy(&style, &lv_style_plain);
    style.body.main_color = LV_COLOR_RED;
    style.body.grad_color = LV_COLOR_BLUE;
  
  const char* str = "Hello Lvgl-007";

  /*Create a mask map with a canvas*/
  lv_obj_t * canvas = lv_canvas_create(lv_scr_act(), NULL);
  lv_canvas_set_buffer(canvas, buf, 200,50, LV_IMG_CF_ALPHA_8BIT);
  memset(buf, 0x00, sizeof(buf));
  lv_canvas_draw_text(canvas, 0, 0, 200, &style, str, LV_LABEL_ALIGN_LEFT);
  lv_obj_del(canvas);  /*Not required anymore, only `buf` will be used*/

  /*Create a masker object. Everything is drawn on this object will be masked*/
  lv_obj_t * mask = lv_objmask_create(lv_scr_act(), NULL);

  /*Add a the mask map to the masking object.*/
  lv_draw_mask_param_t mp;
  lv_area_t area;
  area.x1 = 0;
  area.y1 = 0;
  area.x2 = 199;
  area.y2 = 49;
  lv_draw_mask_map_init(&mp, &area, buf);
  lv_objmask_add_mask(mask, &mp, 1);
  lv_obj_set_size(mask, 200, 50);

  /* Create a simple object with a gradient style.
     (Image can be used too)*/
  lv_obj_t * obj = lv_obj_create(mask, NULL);
  lv_obj_set_size(obj, 200, 50);
  lv_obj_set_style(obj, &style);
}

capture_00065

Sorry, I forget to add the code of style initialization.
You should set style.text.color=LV_COLOR_WHITE. Higher brightness makes more visible pixels in the mask.

You should also set lv_objmask_set_style(mask, LV_OBJMASK_STYLE_BG, &lv_style_transp);.
It’s already the default in the latest dev-7.0

1 Like

Already tft can display right now.

And I’ve tried to set align for the object and/or the mask.
But tft can’t display align correctly.

How to set align for the mask + obj ?
Or lv_objmask should change the area from absolute position to relative position ?

Now all the mask coordinates are absolute.
I’m planning to translate the coordinates relative in lv_objmask as I’ve mentioned here (I’ll add it probably next week)

1 Like

Oh, sorry for I didn’t got you mention in the second comment.

Waiting for the coordinates relative objmask.

I’ve just updated lv_objmask to translate to mask coordinates to relative. There were minor API changes as well.

Here are two example:

void text_mask(void)
{
    static lv_style_t style;
    lv_style_copy(&style, &lv_style_plain);
    style.text.color = LV_COLOR_WHITE;
    style.text.font = &lv_font_roboto_28;
    style.body.main_color = LV_COLOR_RED;
    style.body.grad_color = LV_COLOR_LIME;

    /*Create a mask map with a canvas*/
    static uint8_t buf[LV_IMG_BUF_SIZE_ALPHA_8BIT(200, 30)];
    lv_obj_t * canvas = lv_canvas_create(lv_scr_act(), NULL);
    lv_canvas_set_buffer(canvas, buf, 200, 30, LV_IMG_CF_ALPHA_8BIT);
    memset(buf, 0x00, sizeof(buf));
    lv_canvas_draw_text(canvas, 0, 0, 200, &style, "Hello world", LV_LABEL_ALIGN_LEFT);

    lv_obj_del(canvas);  /*Not required anymore, only `buf` will be used*/

    /*Create a masker object. Everything is drawn on this object will be masked*/
    lv_obj_t * mask = lv_objmask_create(lv_scr_act(), NULL);

    /*Add a the mask map to the masking object.*/
    lv_draw_mask_map_param_t mp;
    lv_area_t area;
    area.x1 = 0;
    area.y1 = 0;
    area.x2 = 199;
    area.y2 = 29;
    lv_draw_mask_map_init(&mp, &area, buf);
    lv_objmask_add_mask(mask, &mp);
    lv_obj_set_size(mask, 200, 30);
    lv_obj_set_drag(mask, true);

    /* Create a simple object with a gradient style.
     * (Image can be used too)*/
    lv_obj_t * obj = lv_obj_create(mask, NULL);
    lv_obj_set_size(obj, 200, 30);
    lv_obj_set_style(obj, &style);
    lv_obj_set_click(obj, false);
}

lv_objmask_mask_t * m1;
void angle_mask_anim(lv_obj_t * objmask, lv_anim_value_t v)
{
    lv_draw_mask_angle_param_t mp;
    lv_draw_mask_angle_init(&mp, 100, 100, 0, v);

    lv_objmask_upadte_mask(objmask, m1, &mp);
}

void angle_mask(void)
{
    static lv_style_t style;
    lv_style_copy(&style, &lv_style_plain);
    style.body.main_color = LV_COLOR_RED;
    style.body.grad_color = LV_COLOR_LIME;

    /*Create a masker object. Everything is drawn on this object will be masked*/
    lv_obj_t * mask = lv_objmask_create(lv_scr_act(), NULL);

    /*Add a the mask map to the masking object.*/
    lv_draw_mask_angle_param_t mp;
    lv_draw_mask_angle_init(&mp, 100, 100, 0, 30);
    m1 = lv_objmask_add_mask(mask, &mp);
    lv_obj_set_size(mask, 200, 200);
    lv_obj_set_drag(mask, true);

    /* Create a simple object with a gradient style.
     * (Image can be used too)*/
    lv_obj_t * obj = lv_obj_create(mask, NULL);
    lv_obj_set_size(obj, 200, 200);
    lv_obj_set_style(obj, &style);
    lv_obj_set_click(obj, false);

    lv_anim_t a;
    lv_anim_init(&a);
    lv_anim_set_exec_cb(&a, mask, (lv_anim_exec_xcb_t)angle_mask_anim);
    lv_anim_set_values(&a, 10, 330);
    lv_anim_set_time(&a, 2000, 0);
    lv_anim_set_playback(&a, 200);
    lv_anim_set_repeat(&a, 200);
    lv_anim_create(&a);
}


...

    text_mask();
    angle_mask();

msk

2 Likes

Wow! Must try!

BTW, mis-typo
lv_objmask_upadte_mask(..)

This is really going to open up the doors to a lot of cool effects! I’m excited to see what can be done with this!

1 Like

If I wish to clear all masks in lv_objmask’s linked-list mask,
how to clear all ?

I’ve updated lv_objmask_remove_mask to remove all masks if the mask parameter is NULL.

Also fixed the typo of lv_objmask_update_mask, thanks.

1 Like