feat(draw): add lv_draw_letter support (#7490)
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
@@ -51,3 +51,15 @@ Draw a vector graphic to the canvas
|
||||
|
||||
.. lv_example:: widgets/canvas/lv_example_canvas_8
|
||||
:language: c
|
||||
|
||||
Draw Fancy Letter Effects
|
||||
-------------------------
|
||||
|
||||
.. lv_example:: widgets/canvas/lv_example_canvas_9
|
||||
:language: c
|
||||
|
||||
Draw Fancy Letter Effects 2
|
||||
---------------------------
|
||||
|
||||
.. lv_example:: widgets/canvas/lv_example_canvas_10
|
||||
:language: c
|
||||
|
||||
68
examples/widgets/canvas/lv_example_canvas_10.c
Normal file
68
examples/widgets/canvas/lv_example_canvas_10.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "../../lv_examples.h"
|
||||
#if LV_USE_CANVAS && LV_BUILD_EXAMPLES
|
||||
|
||||
#define CANVAS_WIDTH 300
|
||||
#define CANVAS_HEIGHT 200
|
||||
|
||||
static void timer_cb(lv_timer_t * timer)
|
||||
{
|
||||
static int32_t counter = 0;
|
||||
const char * string = "windstorrrrrrrrrrrrrrrrm~>>>";
|
||||
const int16_t string_len = lv_strlen(string);
|
||||
|
||||
lv_obj_t * canvas = lv_timer_get_user_data(timer);
|
||||
lv_layer_t layer;
|
||||
lv_canvas_init_layer(canvas, &layer);
|
||||
|
||||
lv_canvas_fill_bg(canvas, lv_color_white(), LV_OPA_COVER);
|
||||
|
||||
lv_draw_letter_dsc_t letter_dsc;
|
||||
lv_draw_letter_dsc_init(&letter_dsc);
|
||||
letter_dsc.color = lv_color_hex(0xff0000);
|
||||
letter_dsc.font = lv_font_default();
|
||||
|
||||
{
|
||||
#define CURVE2_X(t) ((t) * 2 + lv_trigo_cos((t) * 5) * 40 / 32767 - 10)
|
||||
#define CURVE2_Y(t, T) ((t) * lv_trigo_sin(((t) + (T)) * 5) * 40 / 32767 / 80 + CANVAS_HEIGHT / 2)
|
||||
|
||||
int32_t pre_x = CURVE2_X(-1);
|
||||
int32_t pre_y = CURVE2_Y(-1, 0);
|
||||
for(int16_t i = 0; i < string_len; i++) {
|
||||
const int32_t angle = i * 5;
|
||||
const int32_t x = CURVE2_X(angle);
|
||||
const int32_t y = CURVE2_Y(angle + 30, counter / 2);
|
||||
|
||||
letter_dsc.unicode = (uint32_t)string[i % string_len];
|
||||
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x) * 10;
|
||||
letter_dsc.color = lv_color_hsv_to_rgb(i * 10, 100, 100);
|
||||
lv_draw_letter(&layer, &letter_dsc, &(lv_point_t) {
|
||||
.x = x, .y = y
|
||||
});
|
||||
|
||||
pre_x = x;
|
||||
pre_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
lv_canvas_finish_layer(canvas, &layer);
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
void lv_example_canvas_10(void)
|
||||
{
|
||||
/*Create a buffer for the canvas*/
|
||||
LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
|
||||
LV_DRAW_BUF_INIT_STATIC(draw_buf);
|
||||
|
||||
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
|
||||
lv_obj_set_size(canvas, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||
|
||||
lv_obj_center(canvas);
|
||||
|
||||
lv_canvas_set_draw_buf(canvas, &draw_buf);
|
||||
|
||||
lv_timer_create(timer_cb, 16, canvas);
|
||||
}
|
||||
|
||||
#endif
|
||||
68
examples/widgets/canvas/lv_example_canvas_9.c
Normal file
68
examples/widgets/canvas/lv_example_canvas_9.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "../../lv_examples.h"
|
||||
#if LV_USE_CANVAS && LV_BUILD_EXAMPLES
|
||||
|
||||
#define CANVAS_WIDTH 300
|
||||
#define CANVAS_HEIGHT 200
|
||||
|
||||
static void timer_cb(lv_timer_t * timer)
|
||||
{
|
||||
static int32_t counter = 0;
|
||||
const char * string = "lol~ I'm wavvvvvvving~>>>";
|
||||
const int16_t string_len = lv_strlen(string);
|
||||
|
||||
lv_obj_t * canvas = lv_timer_get_user_data(timer);
|
||||
lv_layer_t layer;
|
||||
lv_canvas_init_layer(canvas, &layer);
|
||||
|
||||
lv_canvas_fill_bg(canvas, lv_color_white(), LV_OPA_COVER);
|
||||
|
||||
lv_draw_letter_dsc_t letter_dsc;
|
||||
lv_draw_letter_dsc_init(&letter_dsc);
|
||||
letter_dsc.color = lv_color_hex(0xff0000);
|
||||
letter_dsc.font = lv_font_default();
|
||||
|
||||
{
|
||||
#define CURVE2_X(t) (t * 2 + 10)
|
||||
#define CURVE2_Y(t) (lv_trigo_sin((t) * 5) * 40 / 32767 + CANVAS_HEIGHT / 2)
|
||||
|
||||
int32_t pre_x = CURVE2_X(-1);
|
||||
int32_t pre_y = CURVE2_Y(-1);
|
||||
for(int16_t i = 0; i < string_len; i++) {
|
||||
const int32_t angle = i * 5;
|
||||
const int32_t x = CURVE2_X(angle);
|
||||
const int32_t y = CURVE2_Y(angle + counter / 2);
|
||||
|
||||
letter_dsc.unicode = (uint32_t)string[i % string_len];
|
||||
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x) * 10;
|
||||
letter_dsc.color = lv_color_hsv_to_rgb(i * 10, 100, 100);
|
||||
lv_draw_letter(&layer, &letter_dsc, &(lv_point_t) {
|
||||
.x = x, .y = y
|
||||
});
|
||||
|
||||
pre_x = x;
|
||||
pre_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
lv_canvas_finish_layer(canvas, &layer);
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
void lv_example_canvas_9(void)
|
||||
{
|
||||
/*Create a buffer for the canvas*/
|
||||
LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
|
||||
LV_DRAW_BUF_INIT_STATIC(draw_buf);
|
||||
|
||||
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
|
||||
lv_obj_set_size(canvas, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||
|
||||
lv_obj_center(canvas);
|
||||
|
||||
lv_canvas_set_draw_buf(canvas, &draw_buf);
|
||||
|
||||
lv_timer_create(timer_cb, 16, canvas);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -57,6 +57,8 @@ void lv_example_canvas_5(void);
|
||||
void lv_example_canvas_6(void);
|
||||
void lv_example_canvas_7(void);
|
||||
void lv_example_canvas_8(void);
|
||||
void lv_example_canvas_9(void);
|
||||
void lv_example_canvas_10(void);
|
||||
|
||||
void lv_example_chart_1(void);
|
||||
void lv_example_chart_2(void);
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef enum {
|
||||
LV_DRAW_TASK_TYPE_FILL,
|
||||
LV_DRAW_TASK_TYPE_BORDER,
|
||||
LV_DRAW_TASK_TYPE_BOX_SHADOW,
|
||||
LV_DRAW_TASK_TYPE_LETTER,
|
||||
LV_DRAW_TASK_TYPE_LABEL,
|
||||
LV_DRAW_TASK_TYPE_IMAGE,
|
||||
LV_DRAW_TASK_TYPE_LAYER,
|
||||
|
||||
@@ -43,8 +43,6 @@ typedef unsigned char cmd_state_t;
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static uint8_t hex_char_to_num(char hex);
|
||||
static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos,
|
||||
const lv_font_t * font, uint32_t letter, lv_draw_glyph_cb_t cb);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -62,6 +60,18 @@ static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc,
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_letter_dsc_init(lv_draw_letter_dsc_t * dsc)
|
||||
{
|
||||
lv_memzero(dsc, sizeof(lv_draw_letter_dsc_t));
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
dsc->font = LV_FONT_DEFAULT;
|
||||
dsc->rotation = 0;
|
||||
dsc->scale_x = LV_SCALE_NONE;
|
||||
dsc->scale_y = LV_SCALE_NONE;
|
||||
dsc->base.dsc_size = sizeof(lv_draw_letter_dsc_t);
|
||||
}
|
||||
|
||||
void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc)
|
||||
{
|
||||
lv_memzero(dsc, sizeof(lv_draw_label_dsc_t));
|
||||
@@ -155,6 +165,42 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_character(lv_layer_t * layer, lv_draw_label_d
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void LV_ATTRIBUTE_FAST_MEM lv_draw_letter(lv_layer_t * layer, lv_draw_letter_dsc_t * dsc, const lv_point_t * point)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
if(dsc->font == NULL) {
|
||||
LV_LOG_WARN("dsc->font == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
const lv_font_t * font = dsc->font;
|
||||
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
lv_font_glyph_dsc_t g;
|
||||
lv_font_get_glyph_dsc(font, &g, dsc->unicode, 0);
|
||||
|
||||
font = g.resolved_font ? g.resolved_font : dsc->font;
|
||||
|
||||
lv_area_t a;
|
||||
a.x1 = point->x;
|
||||
a.y1 = point->y;
|
||||
a.x2 = a.x1 + g.adv_w;
|
||||
a.y2 = a.y1 + lv_font_get_line_height(font);
|
||||
|
||||
dsc->pivot.x = g.adv_w / 2 ;
|
||||
dsc->pivot.y = font->line_height - font->base_line;
|
||||
|
||||
lv_draw_task_t * t = lv_draw_add_task(layer, &a);
|
||||
|
||||
t->draw_dsc = lv_malloc(sizeof(*dsc));
|
||||
LV_ASSERT_MALLOC(t->draw_dsc);
|
||||
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
|
||||
t->type = LV_DRAW_TASK_TYPE_LETTER;
|
||||
|
||||
lv_draw_finalize_task_creation(layer, t);
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords,
|
||||
lv_draw_glyph_cb_t cb)
|
||||
@@ -266,6 +312,7 @@ void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_
|
||||
draw_letter_dsc.opa = dsc->opa;
|
||||
draw_letter_dsc.bg_coords = &bg_coords;
|
||||
draw_letter_dsc.color = dsc->color;
|
||||
draw_letter_dsc.rotation = dsc->rotation;
|
||||
|
||||
lv_draw_fill_dsc_t fill_dsc;
|
||||
lv_draw_fill_dsc_init(&fill_dsc);
|
||||
@@ -432,7 +479,7 @@ void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_
|
||||
draw_letter_dsc.color = dsc->color;
|
||||
}
|
||||
|
||||
draw_letter(draw_unit, &draw_letter_dsc, &pos, font, letter, cb);
|
||||
lv_draw_unit_draw_letter(draw_unit, &draw_letter_dsc, &pos, font, letter, cb);
|
||||
|
||||
if(letter_w > 0) {
|
||||
pos.x += letter_w + dsc->letter_space;
|
||||
@@ -491,8 +538,9 @@ static uint8_t hex_char_to_num(char hex)
|
||||
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
|
||||
return 'A' <= hex && hex <= 'F' ? hex - 'A' + 10 : 0;
|
||||
}
|
||||
static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos,
|
||||
const lv_font_t * font, uint32_t letter, lv_draw_glyph_cb_t cb)
|
||||
|
||||
void lv_draw_unit_draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos,
|
||||
const lv_font_t * font, uint32_t letter, lv_draw_glyph_cb_t cb)
|
||||
{
|
||||
lv_font_glyph_dsc_t g;
|
||||
|
||||
@@ -517,9 +565,11 @@ static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc,
|
||||
letter_coords.x2 = letter_coords.x1 + g.box_w - 1;
|
||||
letter_coords.y1 = pos->y + (font->line_height - font->base_line) - g.box_h - g.ofs_y;
|
||||
letter_coords.y2 = letter_coords.y1 + g.box_h - 1;
|
||||
lv_area_move(&letter_coords, -dsc->pivot.x, -dsc->pivot.y);
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(lv_area_is_out(&letter_coords, draw_unit->clip_area, 0) &&
|
||||
dsc->bg_coords &&
|
||||
lv_area_is_out(dsc->bg_coords, draw_unit->clip_area, 0)) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
|
||||
@@ -44,6 +44,7 @@ typedef struct {
|
||||
int32_t letter_space;
|
||||
int32_t ofs_x;
|
||||
int32_t ofs_y;
|
||||
int32_t rotation;
|
||||
lv_opa_t opa;
|
||||
lv_base_dir_t bidi_dir;
|
||||
lv_text_align_t align;
|
||||
@@ -62,6 +63,25 @@ typedef struct {
|
||||
lv_draw_label_hint_t * hint;
|
||||
} lv_draw_label_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_dsc_base_t base;
|
||||
|
||||
uint32_t unicode;
|
||||
const lv_font_t * font;
|
||||
lv_color_t color;
|
||||
|
||||
int32_t rotation;
|
||||
int32_t scale_x;
|
||||
int32_t scale_y;
|
||||
int32_t skew_x;
|
||||
int32_t skew_y;
|
||||
lv_point_t pivot;
|
||||
|
||||
lv_opa_t opa;
|
||||
lv_text_decor_t decor : 3;
|
||||
lv_blend_mode_t blend_mode : 3;
|
||||
} lv_draw_letter_dsc_t;
|
||||
|
||||
/**
|
||||
* Passed as a parameter to `lv_draw_label_iterate_characters` to
|
||||
* draw the characters one by one
|
||||
@@ -81,6 +101,8 @@ typedef void(*lv_draw_glyph_cb_t)(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_letter_dsc_init(lv_draw_letter_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Initialize a label draw descriptor
|
||||
* @param dsc pointer to a draw descriptor
|
||||
@@ -120,6 +142,15 @@ void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_label(lv_layer_t * layer, const lv_draw
|
||||
void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_character(lv_layer_t * layer, lv_draw_label_dsc_t * dsc,
|
||||
const lv_point_t * point, uint32_t unicode_letter);
|
||||
|
||||
/**
|
||||
* Draw a single letter
|
||||
* @param layer pointer to a layer
|
||||
* @param dsc pointer to draw descriptor
|
||||
* @param point position of the label
|
||||
*/
|
||||
void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_letter(lv_layer_t * layer, lv_draw_letter_dsc_t * dsc,
|
||||
const lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Should be used during rendering the characters to get the position and other
|
||||
* parameters of the characters
|
||||
@@ -131,6 +162,25 @@ void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_character(lv_layer_t * layer, lv_draw_l
|
||||
void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords, lv_draw_glyph_cb_t cb);
|
||||
|
||||
/**
|
||||
* @brief Draw a single letter using the provided draw unit, glyph descriptor, position, font, and callback.
|
||||
*
|
||||
* This function is responsible for rendering a single character from a text string,
|
||||
* applying the necessary styling described by the glyph descriptor (`dsc`). It handles
|
||||
* the retrieval of the glyph's description, checks its visibility within the clipping area,
|
||||
* and invokes the callback (`cb`) to render the glyph at the specified position (`pos`)
|
||||
* using the given font (`font`).
|
||||
*
|
||||
* @param draw_unit Pointer to the drawing unit handling the rendering context.
|
||||
* @param dsc Pointer to the descriptor containing styling for the glyph to be drawn.
|
||||
* @param pos Pointer to the point coordinates where the letter should be drawn.
|
||||
* @param font Pointer to the font containing the glyph.
|
||||
* @param letter The Unicode code point of the letter to be drawn.
|
||||
* @param cb Callback function to execute the actual rendering of the glyph.
|
||||
*/
|
||||
void lv_draw_unit_draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos,
|
||||
const lv_font_t * font, uint32_t letter, lv_draw_glyph_cb_t cb);
|
||||
|
||||
/***********************
|
||||
* GLOBAL VARIABLES
|
||||
***********************/
|
||||
|
||||
@@ -50,6 +50,8 @@ struct _lv_draw_glyph_dsc_t {
|
||||
lv_font_glyph_dsc_t * g;
|
||||
lv_color_t color;
|
||||
lv_opa_t opa;
|
||||
int32_t rotation;
|
||||
lv_point_t pivot; /**< Rotation pivot point associated with total glyph including line_height */
|
||||
lv_draw_buf_t * _draw_buf; /**< a shared draw buf for get_bitmap, do not use it directly, use glyph_data instead */
|
||||
};
|
||||
|
||||
|
||||
@@ -261,6 +261,9 @@ static void execute_drawing(lv_draw_sw_unit_t * u)
|
||||
case LV_DRAW_TASK_TYPE_BOX_SHADOW:
|
||||
lv_draw_sw_box_shadow((lv_draw_unit_t *)u, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LETTER:
|
||||
lv_draw_sw_letter((lv_draw_unit_t *)u, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
lv_draw_sw_label((lv_draw_unit_t *)u, t->draw_dsc, &t->area);
|
||||
break;
|
||||
|
||||
@@ -81,6 +81,8 @@ void lv_draw_sw_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_
|
||||
void lv_draw_sw_image(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_sw_letter(lv_draw_unit_t * draw_unit, const lv_draw_letter_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
/**
|
||||
* Draw a label with SW render.
|
||||
* @param draw_unit pointer to a draw unit
|
||||
|
||||
@@ -51,6 +51,32 @@ static void /* LV_ATTRIBUTE_FAST_MEM */ draw_letter_cb(lv_draw_unit_t * draw_uni
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sw_letter(lv_draw_unit_t * draw_unit, const lv_draw_letter_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
lv_draw_glyph_dsc_t glyph_dsc;
|
||||
lv_draw_glyph_dsc_init(&glyph_dsc);
|
||||
glyph_dsc.opa = dsc->opa;
|
||||
glyph_dsc.bg_coords = NULL;
|
||||
glyph_dsc.color = dsc->color;
|
||||
glyph_dsc.rotation = dsc->rotation;
|
||||
glyph_dsc.pivot = dsc->pivot;
|
||||
|
||||
LV_PROFILER_BEGIN;
|
||||
lv_draw_unit_draw_letter(draw_unit, &glyph_dsc, &(lv_point_t) {
|
||||
.x = coords->x1, .y = coords->y1
|
||||
},
|
||||
dsc->font, dsc->unicode, draw_letter_cb);
|
||||
LV_PROFILER_END;
|
||||
|
||||
if(glyph_dsc._draw_buf) {
|
||||
lv_draw_buf_destroy(glyph_dsc._draw_buf);
|
||||
glyph_dsc._draw_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_draw_sw_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
@@ -89,40 +115,45 @@ static void LV_ATTRIBUTE_FAST_MEM draw_letter_cb(lv_draw_unit_t * draw_unit, lv_
|
||||
case LV_FONT_GLYPH_FORMAT_A1_ALIGNED:
|
||||
case LV_FONT_GLYPH_FORMAT_A2_ALIGNED:
|
||||
case LV_FONT_GLYPH_FORMAT_A4_ALIGNED:
|
||||
case LV_FONT_GLYPH_FORMAT_A8_ALIGNED: {
|
||||
glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf);
|
||||
lv_area_t mask_area = *glyph_draw_dsc->letter_coords;
|
||||
mask_area.x2 = mask_area.x1 + lv_draw_buf_width_to_stride(lv_area_get_width(&mask_area), LV_COLOR_FORMAT_A8) - 1;
|
||||
lv_draw_sw_blend_dsc_t blend_dsc;
|
||||
lv_memzero(&blend_dsc, sizeof(blend_dsc));
|
||||
blend_dsc.color = glyph_draw_dsc->color;
|
||||
blend_dsc.opa = glyph_draw_dsc->opa;
|
||||
const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
|
||||
blend_dsc.mask_buf = draw_buf->data;
|
||||
blend_dsc.mask_area = &mask_area;
|
||||
blend_dsc.mask_stride = draw_buf->header.stride;
|
||||
blend_dsc.blend_area = glyph_draw_dsc->letter_coords;
|
||||
blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED;
|
||||
|
||||
lv_draw_sw_blend(draw_unit, &blend_dsc);
|
||||
}
|
||||
break;
|
||||
case LV_FONT_GLYPH_FORMAT_A8_ALIGNED:
|
||||
case LV_FONT_GLYPH_FORMAT_IMAGE: {
|
||||
glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf);
|
||||
lv_draw_image_dsc_t img_dsc;
|
||||
lv_draw_image_dsc_init(&img_dsc);
|
||||
img_dsc.rotation = 0;
|
||||
img_dsc.scale_x = LV_SCALE_NONE;
|
||||
img_dsc.scale_y = LV_SCALE_NONE;
|
||||
img_dsc.opa = glyph_draw_dsc->opa;
|
||||
img_dsc.src = glyph_draw_dsc->glyph_data;
|
||||
lv_draw_sw_image(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
|
||||
if(glyph_draw_dsc->rotation % 3600 == 0 && glyph_draw_dsc->format != LV_FONT_GLYPH_FORMAT_IMAGE) {
|
||||
glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf);
|
||||
lv_area_t mask_area = *glyph_draw_dsc->letter_coords;
|
||||
mask_area.x2 = mask_area.x1 + lv_draw_buf_width_to_stride(lv_area_get_width(&mask_area), LV_COLOR_FORMAT_A8) - 1;
|
||||
lv_draw_sw_blend_dsc_t blend_dsc;
|
||||
lv_memzero(&blend_dsc, sizeof(blend_dsc));
|
||||
blend_dsc.color = glyph_draw_dsc->color;
|
||||
blend_dsc.opa = glyph_draw_dsc->opa;
|
||||
const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
|
||||
blend_dsc.mask_buf = draw_buf->data;
|
||||
blend_dsc.mask_area = &mask_area;
|
||||
blend_dsc.mask_stride = draw_buf->header.stride;
|
||||
blend_dsc.blend_area = glyph_draw_dsc->letter_coords;
|
||||
blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED;
|
||||
lv_draw_sw_blend(draw_unit, &blend_dsc);
|
||||
}
|
||||
else {
|
||||
glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf);
|
||||
lv_draw_image_dsc_t img_dsc;
|
||||
lv_draw_image_dsc_init(&img_dsc);
|
||||
img_dsc.rotation = glyph_draw_dsc->rotation;
|
||||
img_dsc.scale_x = LV_SCALE_NONE;
|
||||
img_dsc.scale_y = LV_SCALE_NONE;
|
||||
img_dsc.opa = glyph_draw_dsc->opa;
|
||||
img_dsc.src = glyph_draw_dsc->glyph_data;
|
||||
img_dsc.recolor = glyph_draw_dsc->color;
|
||||
img_dsc.pivot = (lv_point_t) {
|
||||
.x = glyph_draw_dsc->pivot.x,
|
||||
.y = glyph_draw_dsc->g->box_h + glyph_draw_dsc->g->ofs_y
|
||||
};
|
||||
lv_draw_sw_image(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(fill_draw_dsc && fill_area) {
|
||||
|
||||
@@ -143,6 +143,9 @@ static void draw_execute(lv_draw_vg_lite_unit_t * u)
|
||||
#endif
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_LETTER:
|
||||
lv_draw_vg_lite_letter(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
lv_draw_vg_lite_label(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
@@ -240,6 +243,7 @@ static int32_t draw_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task)
|
||||
}
|
||||
|
||||
switch(task->type) {
|
||||
case LV_DRAW_TASK_TYPE_LETTER:
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
case LV_DRAW_TASK_TYPE_BORDER:
|
||||
|
||||
@@ -62,6 +62,8 @@ void lv_draw_vg_lite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t *
|
||||
|
||||
void lv_draw_vg_lite_label_init(lv_draw_unit_t * draw_unit);
|
||||
|
||||
void lv_draw_vg_lite_letter(lv_draw_unit_t * draw_unit, const lv_draw_letter_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
void lv_draw_vg_lite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "lv_vg_lite_utils.h"
|
||||
#include "lv_vg_lite_path.h"
|
||||
#include "lv_draw_vg_lite_type.h"
|
||||
#include <float.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -80,6 +81,32 @@ void lv_draw_vg_lite_label_init(lv_draw_unit_t * draw_unit)
|
||||
#endif /* LV_USE_FREETYPE */
|
||||
}
|
||||
|
||||
void lv_draw_vg_lite_letter(lv_draw_unit_t * draw_unit, const lv_draw_letter_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
lv_draw_glyph_dsc_t glyph_dsc;
|
||||
lv_draw_glyph_dsc_init(&glyph_dsc);
|
||||
glyph_dsc.opa = dsc->opa;
|
||||
glyph_dsc.bg_coords = NULL;
|
||||
glyph_dsc.color = dsc->color;
|
||||
glyph_dsc.rotation = dsc->rotation;
|
||||
glyph_dsc.pivot = dsc->pivot;
|
||||
|
||||
LV_PROFILER_BEGIN;
|
||||
lv_draw_unit_draw_letter(draw_unit, &glyph_dsc, &(lv_point_t) {
|
||||
.x = coords->x1, .y = coords->y1
|
||||
},
|
||||
dsc->font, dsc->unicode, draw_letter_cb);
|
||||
LV_PROFILER_END;
|
||||
|
||||
if(glyph_dsc._draw_buf) {
|
||||
lv_draw_buf_destroy(glyph_dsc._draw_buf);
|
||||
glyph_dsc._draw_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_draw_vg_lite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
@@ -128,6 +155,7 @@ static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * gly
|
||||
lv_draw_image_dsc_init(&image_dsc);
|
||||
image_dsc.opa = glyph_draw_dsc->opa;
|
||||
image_dsc.src = glyph_draw_dsc->glyph_data;
|
||||
image_dsc.rotation = glyph_draw_dsc->rotation;
|
||||
lv_draw_vg_lite_img(draw_unit, &image_dsc, glyph_draw_dsc->letter_coords, false);
|
||||
}
|
||||
break;
|
||||
@@ -170,17 +198,26 @@ static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_d
|
||||
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
|
||||
lv_area_t image_area = *dsc->letter_coords;
|
||||
const lv_area_t image_area = *dsc->letter_coords;
|
||||
|
||||
vg_lite_matrix_t matrix = u->global_matrix;
|
||||
vg_lite_translate(image_area.x1, image_area.y1, &matrix);
|
||||
|
||||
const bool is_rotated = dsc->rotation % 3600 != 0;
|
||||
|
||||
if(!is_rotated) {
|
||||
vg_lite_translate(image_area.x1, image_area.y1, &matrix);
|
||||
}
|
||||
else {
|
||||
vg_lite_translate(image_area.x1 + dsc->pivot.x, image_area.y1 + (dsc->g->box_h + dsc->g->ofs_y), &matrix);
|
||||
vg_lite_rotate(dsc->rotation / 10.0f, &matrix);
|
||||
vg_lite_translate(-dsc->pivot.x, -dsc->g->box_h - dsc->g->ofs_y, &matrix);
|
||||
}
|
||||
|
||||
vg_lite_buffer_t src_buf;
|
||||
const lv_draw_buf_t * draw_buf = dsc->glyph_data;
|
||||
lv_vg_lite_buffer_from_draw_buf(&src_buf, draw_buf);
|
||||
|
||||
vg_lite_color_t color;
|
||||
color = lv_vg_lite_color(dsc->color, dsc->opa, true);
|
||||
const vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true);
|
||||
|
||||
LV_VG_LITE_ASSERT_SRC_BUFFER(&src_buf);
|
||||
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||
@@ -220,6 +257,7 @@ static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_d
|
||||
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||
|
||||
vg_lite_matrix_t path_matrix = u->global_matrix;
|
||||
if(is_rotated) vg_lite_rotate(dsc->rotation / 10.0f, &path_matrix);
|
||||
LV_VG_LITE_ASSERT_MATRIX(&path_matrix);
|
||||
|
||||
LV_PROFILER_DRAW_BEGIN_TAG("vg_lite_draw_pattern");
|
||||
@@ -265,32 +303,61 @@ static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_
|
||||
path_clip_area.y2++;
|
||||
|
||||
lv_vg_lite_path_t * outline = (lv_vg_lite_path_t *)dsc->glyph_data;
|
||||
lv_point_t pos = {dsc->letter_coords->x1, dsc->letter_coords->y1};
|
||||
const lv_point_t pos = {dsc->letter_coords->x1, dsc->letter_coords->y1};
|
||||
/* scale size */
|
||||
float scale = FT_F26DOT6_TO_PATH_SCALE(lv_freetype_outline_get_scale(dsc->g->resolved_font));
|
||||
const float scale = FT_F26DOT6_TO_PATH_SCALE(lv_freetype_outline_get_scale(dsc->g->resolved_font));
|
||||
const bool is_rotated = dsc->rotation % 3600 != 0;
|
||||
|
||||
/* calc convert matrix */
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
vg_lite_translate(pos.x - dsc->g->ofs_x, pos.y + dsc->g->box_h + dsc->g->ofs_y, &matrix);
|
||||
vg_lite_scale(scale, scale, &matrix);
|
||||
|
||||
/* calc inverse matrix */
|
||||
vg_lite_matrix_t result;
|
||||
if(!lv_vg_lite_matrix_inverse(&result, &matrix)) {
|
||||
LV_LOG_ERROR("no inverse matrix");
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
if(!is_rotated) {
|
||||
vg_lite_translate(pos.x - dsc->g->ofs_x, pos.y + dsc->g->box_h + dsc->g->ofs_y, &matrix);
|
||||
vg_lite_scale(scale, scale, &matrix);
|
||||
}
|
||||
else {
|
||||
vg_lite_translate(pos.x - dsc->g->ofs_x + dsc->pivot.x, pos.y + dsc->g->box_h + dsc->g->ofs_y, &matrix);
|
||||
vg_lite_rotate(dsc->rotation / 10.0f, &matrix);
|
||||
vg_lite_translate(-dsc->pivot.x, 0, &matrix);
|
||||
vg_lite_scale(scale, scale, &matrix);
|
||||
}
|
||||
|
||||
lv_point_precise_t p1 = { path_clip_area.x1, path_clip_area.y1 };
|
||||
lv_point_precise_t p1_res = lv_vg_lite_matrix_transform_point(&result, &p1);
|
||||
if(vg_lite_query_feature(gcFEATURE_BIT_VG_SCISSOR)) {
|
||||
/* set scissor area */
|
||||
lv_vg_lite_set_scissor_area(u->base_unit.clip_area);
|
||||
|
||||
lv_point_precise_t p2 = { path_clip_area.x2, path_clip_area.y2 };
|
||||
lv_point_precise_t p2_res = lv_vg_lite_matrix_transform_point(&result, &p2);
|
||||
/* no bounding box */
|
||||
lv_vg_lite_path_set_bounding_box(outline,
|
||||
(float)PATH_COORD_MIN, (float)PATH_COORD_MIN,
|
||||
(float)PATH_COORD_MAX, (float)PATH_COORD_MAX);
|
||||
}
|
||||
else {
|
||||
if(is_rotated) {
|
||||
LV_LOG_WARN("clip may be incorrect when vg_lite_query_feature(gcFEATURE_BIT_VG_SCISSOR) is false");
|
||||
}
|
||||
|
||||
/* Since the font uses Cartesian coordinates, the y coordinates need to be reversed */
|
||||
lv_vg_lite_path_set_bounding_box(outline, p1_res.x, p2_res.y, p2_res.x, p1_res.y);
|
||||
/* calc inverse matrix */
|
||||
vg_lite_matrix_t result;
|
||||
if(!lv_vg_lite_matrix_inverse(&result, &matrix)) {
|
||||
LV_LOG_ERROR("no inverse matrix");
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
const lv_point_precise_t p1 = { path_clip_area.x1, path_clip_area.y1 };
|
||||
const lv_point_precise_t p1_res = lv_vg_lite_matrix_transform_point(&result, &p1);
|
||||
|
||||
const lv_point_precise_t p2 = { path_clip_area.x2, path_clip_area.y2 };
|
||||
const lv_point_precise_t p2_res = lv_vg_lite_matrix_transform_point(&result, &p2);
|
||||
|
||||
/* Since the font uses Cartesian coordinates, the y coordinates need to be reversed */
|
||||
if(is_rotated)
|
||||
lv_vg_lite_path_set_bounding_box(outline,
|
||||
(float)PATH_COORD_MIN, (float)PATH_COORD_MIN,
|
||||
(float)PATH_COORD_MAX, (float)PATH_COORD_MAX);
|
||||
else lv_vg_lite_path_set_bounding_box(outline, p1_res.x, p2_res.y, p2_res.x, p1_res.y);
|
||||
}
|
||||
|
||||
/* matrix for drawing, different from matrix for calculating the bounding box */
|
||||
vg_lite_matrix_t draw_matrix = u->global_matrix;
|
||||
|
||||
@@ -25,20 +25,6 @@
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_USE_VG_LITE_THORVG
|
||||
/**
|
||||
* It is found that thorvg cannot handle large coordinates well.
|
||||
* When the coordinates are larger than 4096, the calculation of tvgSwRle module will overflow in 32-bit system.
|
||||
* So we use FLT_MAX and FLT_MIN to write the mark to bounding_box to tell vg_lite_tvg not to add clip path to the current path.
|
||||
*/
|
||||
#define PATH_COORD_MAX FLT_MAX
|
||||
#define PATH_COORD_MIN FLT_MIN
|
||||
#else
|
||||
/* 18 bits is enough to represent the coordinates of path bounding box */
|
||||
#define PATH_COORD_MAX (1 << 18)
|
||||
#define PATH_COORD_MIN (-PATH_COORD_MAX)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
@@ -22,6 +22,20 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_USE_VG_LITE_THORVG
|
||||
/**
|
||||
* It is found that thorvg cannot handle large coordinates well.
|
||||
* When the coordinates are larger than 4096, the calculation of tvgSwRle module will overflow in 32-bit system.
|
||||
* So we use FLT_MAX and FLT_MIN to write the mark to bounding_box to tell vg_lite_tvg not to add clip path to the current path.
|
||||
*/
|
||||
#define PATH_COORD_MAX FLT_MAX
|
||||
#define PATH_COORD_MIN FLT_MIN
|
||||
#else
|
||||
/* 18 bits is enough to represent the coordinates of path bounding box */
|
||||
#define PATH_COORD_MAX (1 << 18)
|
||||
#define PATH_COORD_MIN (-PATH_COORD_MAX)
|
||||
#endif
|
||||
|
||||
#define LV_VG_LITE_PATH_SET_OP_CODE(PTR, TYPE, OP_CODE) (*((TYPE*)PTR) = (OP_CODE))
|
||||
#define LV_VG_LITE_PATH_GET_OP_CODE(PTR) (*((uint8_t*)PTR))
|
||||
|
||||
|
||||
BIN
tests/ref_imgs/draw/letter_0.png
Normal file
BIN
tests/ref_imgs/draw/letter_0.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
tests/ref_imgs_vg_lite/draw/letter_0.png
Normal file
BIN
tests/ref_imgs_vg_lite/draw/letter_0.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
107
tests/src/test_cases/draw/test_draw_letter.c
Normal file
107
tests/src/test_cases/draw/test_draw_letter.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
#include "../../lvgl_private.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
/* Function run before every test */
|
||||
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
|
||||
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
/* Function run after every test */
|
||||
lv_obj_clean(lv_screen_active());
|
||||
}
|
||||
|
||||
static lv_obj_t * canvas_create(void)
|
||||
{
|
||||
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
|
||||
lv_obj_set_size(canvas, 500, 360);
|
||||
|
||||
lv_draw_buf_t * draw_buf = lv_draw_buf_create(500, 360, LV_COLOR_FORMAT_ARGB8888, LV_STRIDE_AUTO);
|
||||
lv_draw_buf_clear(draw_buf, NULL);
|
||||
lv_canvas_set_draw_buf(canvas, draw_buf);
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
static void canvas_destroy(lv_obj_t * canvas)
|
||||
{
|
||||
lv_draw_buf_destroy(lv_canvas_get_draw_buf(canvas));
|
||||
lv_obj_delete(canvas);
|
||||
}
|
||||
|
||||
void test_draw_sin_wave(void)
|
||||
{
|
||||
const char * string = "lol~ I'm wavvvvvvving~";
|
||||
const uint32_t string_len = lv_strlen(string);
|
||||
|
||||
LV_FONT_DECLARE(test_font_montserrat_ascii_4bpp);
|
||||
lv_obj_t * canvas = canvas_create();
|
||||
|
||||
lv_layer_t layer;
|
||||
lv_canvas_init_layer(canvas, &layer);
|
||||
|
||||
lv_draw_letter_dsc_t letter_dsc;
|
||||
lv_draw_letter_dsc_init(&letter_dsc);
|
||||
letter_dsc.color = lv_color_hex(0xff0000);
|
||||
letter_dsc.font = &test_font_montserrat_ascii_4bpp;
|
||||
|
||||
{
|
||||
#define CURVE1_X(t) (t * 2 + 20)
|
||||
#define CURVE1_Y(t) (lv_trigo_sin(t) * 40 / 32767 + 80)
|
||||
int32_t pre_x = CURVE1_X(-1);
|
||||
int32_t pre_y = CURVE1_Y(-1);
|
||||
|
||||
for(int16_t i = 0; i < 30; i++) {
|
||||
const int32_t angle = i * 10;
|
||||
const int32_t x = CURVE1_X(angle);
|
||||
const int32_t y = CURVE1_Y(angle);
|
||||
letter_dsc.unicode = (uint32_t)string[i % string_len];
|
||||
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x);
|
||||
letter_dsc.rotation = (letter_dsc.rotation > 180 ? letter_dsc.rotation - 360 : letter_dsc.rotation) * 5;
|
||||
lv_draw_letter(&layer, &letter_dsc, &(lv_point_t) {
|
||||
.x = x, .y = y
|
||||
});
|
||||
pre_x = x;
|
||||
pre_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
#define CURVE2_X(t) (t * 3 + 20)
|
||||
#define CURVE2_Y(t) (lv_trigo_sin((t) * 4) * 40 / 32767 + 230)
|
||||
|
||||
int32_t pre_x = CURVE2_X(-1);
|
||||
int32_t pre_y = CURVE2_Y(-1);
|
||||
for(int16_t i = 0; i < 30; i++) {
|
||||
const int32_t angle = i * 5;
|
||||
const int32_t x = CURVE2_X(angle);
|
||||
const int32_t y = CURVE2_Y(angle);
|
||||
|
||||
letter_dsc.unicode = (uint32_t)string[i % string_len];
|
||||
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x) * 10;
|
||||
letter_dsc.color = lv_color_hsv_to_rgb(i * 10, 100, 100);
|
||||
lv_draw_letter(&layer, &letter_dsc, &(lv_point_t) {
|
||||
.x = x, .y = y
|
||||
});
|
||||
|
||||
pre_x = x;
|
||||
pre_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
lv_canvas_finish_layer(canvas, &layer);
|
||||
|
||||
#ifndef NON_AMD64_BUILD
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("draw/letter_0.png");
|
||||
#endif
|
||||
|
||||
canvas_destroy(canvas);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user