diff --git a/src/draw/vg_lite/lv_draw_vg_lite_label.c b/src/draw/vg_lite/lv_draw_vg_lite_label.c index 081fbb7082..9ab37bfc4d 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_label.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_label.c @@ -20,6 +20,7 @@ #include "../../misc/lv_area_private.h" #include "../../libs/freetype/lv_freetype_private.h" #include "../lv_draw_label_private.h" +#include "../lv_draw_image_private.h" /********************* @@ -60,6 +61,7 @@ static void bitmap_cache_release_cb(void * entry, void * user_data); #if LV_USE_FREETYPE static void freetype_outline_event_cb(lv_event_t * e); static void draw_letter_outline(lv_draw_task_t * t, const lv_draw_glyph_dsc_t * dsc); + static void outline_iter_cb(void * user_data, uint8_t op_code, const float * data, uint32_t len); #endif /* LV_USE_FREETYPE */ /********************** @@ -244,53 +246,120 @@ static void draw_letter_cb(lv_draw_task_t * t, lv_draw_glyph_dsc_t * glyph_draw_ } } -static void draw_letter_bitmap(lv_draw_task_t * t, const lv_draw_glyph_dsc_t * dsc, vg_lite_buffer_t * src_buf) +static inline void convert_letter_matrix(vg_lite_matrix_t * matrix, const lv_draw_glyph_dsc_t * dsc) { - lv_area_t clip_area; - lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)t->draw_unit; - if(!lv_area_intersect(&clip_area, &t->clip_area, dsc->letter_coords)) { + vg_lite_translate(dsc->letter_coords->x1, dsc->letter_coords->y1, matrix); + + if(!dsc->rotation) { return; } + const lv_point_t pivot = { + .x = dsc->pivot.x, + .y = dsc->g->box_h + dsc->g->ofs_y + }; + vg_lite_translate(pivot.x, pivot.y, matrix); + vg_lite_rotate(dsc->rotation / 10.0f, matrix); + vg_lite_translate(-pivot.x, -pivot.y, matrix); +} + +static bool draw_letter_clip_areas(lv_draw_task_t * t, const lv_draw_glyph_dsc_t * dsc, lv_area_t * letter_area, + lv_area_t * cliped_area) +{ + *letter_area = *dsc->letter_coords; + + if(dsc->rotation) { + const lv_point_t pivot = { + .x = dsc->pivot.x, + .y = dsc->g->box_h + dsc->g->ofs_y + }; + + lv_image_buf_get_transformed_area( + letter_area, + lv_area_get_width(dsc->letter_coords), + lv_area_get_height(dsc->letter_coords), + dsc->rotation, + LV_SCALE_NONE, + LV_SCALE_NONE, + &pivot); + lv_area_move(letter_area, dsc->letter_coords->x1, dsc->letter_coords->y1); + } + + if(!lv_area_intersect(cliped_area, &t->clip_area, letter_area)) { + return false; + } + + return true; +} + +static void draw_letter_bitmap(lv_draw_task_t * t, const lv_draw_glyph_dsc_t * dsc, vg_lite_buffer_t * src_buf) +{ LV_PROFILER_DRAW_BEGIN; - const lv_area_t image_area = *dsc->letter_coords; + lv_area_t image_area; + lv_area_t clip_area; + if(!draw_letter_clip_areas(t, dsc, &image_area, &clip_area)) { + LV_PROFILER_DRAW_END; + return; + } + + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)t->draw_unit; vg_lite_matrix_t matrix = u->global_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); - } + convert_letter_matrix(&matrix, dsc); const vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true); - vg_lite_rectangle_t rect = { - .x = clip_area.x1 - image_area.x1, - .y = clip_area.y1 - image_area.y1, - .width = lv_area_get_width(&clip_area), - .height = lv_area_get_height(&clip_area) - }; + /* If rotation is not required, blit directly */ + if(!dsc->rotation) { + vg_lite_rectangle_t rect = { + .x = clip_area.x1 - image_area.x1, + .y = clip_area.y1 - image_area.y1, + .width = lv_area_get_width(&clip_area), + .height = lv_area_get_height(&clip_area) + }; - /* add offset for clipped area */ - if(rect.x || rect.y) { - vg_lite_translate(rect.x, rect.y, &matrix); + /* add offset for clipped area */ + if(rect.x || rect.y) { + vg_lite_translate(rect.x, rect.y, &matrix); + } + + lv_vg_lite_blit_rect( + &u->target_buffer, + src_buf, + &rect, + &matrix, + VG_LITE_BLEND_SRC_OVER, + color, + VG_LITE_FILTER_LINEAR); } + else { + lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16); + lv_vg_lite_path_append_rect( + path, + image_area.x1, image_area.y1, + lv_area_get_width(&image_area), lv_area_get_height(&image_area), + 0); + lv_vg_lite_path_end(path); + lv_vg_lite_path_set_bounding_box_area(path, &clip_area); - lv_vg_lite_blit_rect( - &u->target_buffer, - src_buf, - &rect, - &matrix, - VG_LITE_BLEND_SRC_OVER, - color, - VG_LITE_FILTER_LINEAR); + vg_lite_matrix_t path_matrix = u->global_matrix; + + lv_vg_lite_draw_pattern( + &u->target_buffer, + lv_vg_lite_path_get_path(path), + VG_LITE_FILL_EVEN_ODD, + &path_matrix, + src_buf, + &matrix, + VG_LITE_BLEND_SRC_OVER, + VG_LITE_PATTERN_COLOR, + 0, + color, + VG_LITE_FILTER_LINEAR); + + lv_vg_lite_path_drop(u, path); + } /* Check if the data has cache and add it to the pending list */ if(dsc->g->entry) { @@ -317,80 +386,118 @@ static void bitmap_cache_release_cb(void * entry, void * user_data) static void draw_letter_outline(lv_draw_task_t * t, const lv_draw_glyph_dsc_t * dsc) { - lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)t->draw_unit; - /* get clip area */ + LV_PROFILER_DRAW_BEGIN; + + lv_area_t letter_area; lv_area_t path_clip_area; - if(!lv_area_intersect(&path_clip_area, &t->clip_area, dsc->letter_coords)) { + if(!draw_letter_clip_areas(t, dsc, &letter_area, &path_clip_area)) { + LV_PROFILER_DRAW_END; return; } - LV_PROFILER_DRAW_BEGIN; + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)t->draw_unit; /* vg-lite bounding_box will crop the pixels on the edge, so +1px is needed here */ path_clip_area.x2++; path_clip_area.y2++; lv_vg_lite_path_t * outline = (lv_vg_lite_path_t *)dsc->glyph_data; - const lv_point_t pos = {dsc->letter_coords->x1, dsc->letter_coords->y1}; + const lv_point_t glyph_pos = { + dsc->letter_coords->x1 - dsc->g->ofs_x, + dsc->letter_coords->y1 + dsc->g->box_h + dsc->g->ofs_y + }; /* scale size */ 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; + + const bool has_rotation_with_cliped = dsc->rotation && !lv_area_is_in(&letter_area, &t->clip_area, false); /* calc convert matrix */ vg_lite_matrix_t matrix; vg_lite_identity(&matrix); - 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); + if(!has_rotation_with_cliped && dsc->rotation) { + vg_lite_translate(glyph_pos.x + dsc->pivot.x, glyph_pos.y, &matrix); vg_lite_rotate(dsc->rotation / 10.0f, &matrix); vg_lite_translate(-dsc->pivot.x, 0, &matrix); - vg_lite_scale(scale, scale, &matrix); - } - - if(vg_lite_query_feature(gcFEATURE_BIT_VG_SCISSOR)) { - /* set scissor area */ - lv_vg_lite_set_scissor_area(u, &t->clip_area); - - /* 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"); - } - - /* 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); + vg_lite_translate(glyph_pos.x, glyph_pos.y, &matrix); } + vg_lite_scale(scale, scale, &matrix); + /* matrix for drawing, different from matrix for calculating the bounding box */ vg_lite_matrix_t draw_matrix = u->global_matrix; lv_vg_lite_matrix_multiply(&draw_matrix, &matrix); + /* calc inverse matrix */ + vg_lite_matrix_t result; + if(!lv_vg_lite_matrix_inverse(&result, &matrix)) { + LV_LOG_ERROR("no inverse matrix"); + lv_vg_lite_matrix_dump_info(&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); + + if(has_rotation_with_cliped) { + /** + * When intersecting the clipping region, + * rotate the path contents without rotating the bounding box for cropping + */ + vg_lite_matrix_t internal_matrix; + vg_lite_identity(&internal_matrix); + const float pivot_x = dsc->pivot.x / scale; + const float pivot_y = dsc->g->box_h + dsc->g->ofs_y; + vg_lite_translate(pivot_x, pivot_y, &internal_matrix); + vg_lite_rotate(dsc->rotation / 10.0f, &internal_matrix); + vg_lite_translate(-pivot_x, -pivot_y, &internal_matrix); + + lv_vg_lite_path_t * outline_transformed = lv_vg_lite_path_get(u, VG_LITE_FP32); + lv_vg_lite_path_set_transform(outline_transformed, &internal_matrix); + lv_vg_lite_path_for_each_data(lv_vg_lite_path_get_path(outline), outline_iter_cb, outline_transformed); + lv_vg_lite_path_set_bounding_box(outline_transformed, p1_res.x, p2_res.y, p2_res.x, p1_res.y); + + lv_vg_lite_draw( + &u->target_buffer, + lv_vg_lite_path_get_path(outline_transformed), + VG_LITE_FILL_NON_ZERO, + &draw_matrix, + VG_LITE_BLEND_SRC_OVER, + lv_vg_lite_color(dsc->color, dsc->opa, true)); + + lv_vg_lite_path_drop(u, outline_transformed); + + LV_PROFILER_DRAW_END; + return; + } + + if(dsc->rotation) { + /* The bounding rectangle before scaling relative to the original coordinates of the path */ + lv_area_t box_area; + box_area.x1 = dsc->g->ofs_x; + box_area.y1 = -dsc->g->box_h - dsc->g->ofs_y; + lv_area_set_width(&box_area, dsc->g->box_w); + lv_area_set_height(&box_area, dsc->g->box_h); + + /* Workaround for loss of rotation precision */ + lv_area_increase(&box_area, 5, 5); + + /* Scale the path area to fit the original path data */ + lv_vg_lite_path_set_bounding_box(outline, + box_area.x1 / scale, + box_area.y1 / scale, + box_area.x2 / scale, + box_area.y2 / scale); + } + else { + lv_vg_lite_path_set_bounding_box(outline, p1_res.x, p2_res.y, p2_res.x, p1_res.y); + } + lv_vg_lite_draw( &u->target_buffer, lv_vg_lite_path_get_path(outline), @@ -463,6 +570,42 @@ static void freetype_outline_event_cb(lv_event_t * e) LV_PROFILER_DRAW_END; } +static void outline_iter_cb(void * user_data, uint8_t op_code, const float * data, uint32_t len) +{ + LV_UNUSED(len); + typedef struct { + float x; + float y; + } point_t; + + lv_vg_lite_path_t * path = user_data; + const point_t * pt = (point_t *)data; + + switch(op_code) { + case VLC_OP_MOVE: + lv_vg_lite_path_move_to(path, pt->x, pt->y); + break; + case VLC_OP_LINE: + lv_vg_lite_path_line_to(path, pt->x, pt->y); + break; + case VLC_OP_QUAD: + lv_vg_lite_path_quad_to(path, pt[0].x, pt[0].y, pt[1].x, pt[1].y); + break; + case VLC_OP_CUBIC: + lv_vg_lite_path_cubic_to(path, pt[0].x, pt[0].y, pt[1].x, pt[1].y, pt[2].x, pt[2].y); + break; + case VLC_OP_CLOSE: + lv_vg_lite_path_close(path); + break; + case VLC_OP_END: + lv_vg_lite_path_end(path); + break; + default: + LV_ASSERT_FORMAT_MSG(false, "unknown op_code: %d", op_code); + break; + } +} + #endif /* LV_USE_FREETYPE */ #endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/src/draw/vg_lite/lv_vg_lite_path.c b/src/draw/vg_lite/lv_vg_lite_path.c index 5fe4e1726b..3fa5ebe8b0 100644 --- a/src/draw/vg_lite/lv_vg_lite_path.c +++ b/src/draw/vg_lite/lv_vg_lite_path.c @@ -647,6 +647,7 @@ void lv_vg_lite_path_for_each_data(const vg_lite_path_t * path, lv_vg_lite_path_ { LV_ASSERT_NULL(path); LV_ASSERT_NULL(cb); + LV_PROFILER_DRAW_BEGIN; uint8_t fmt_len = lv_vg_lite_path_format_len(path->format); uint8_t * cur = path->path; @@ -688,6 +689,8 @@ void lv_vg_lite_path_for_each_data(const vg_lite_path_t * path, lv_vg_lite_path_ cb(user_data, op_code, tmp_data, arg_len); } + + LV_PROFILER_DRAW_END; } void lv_vg_lite_path_append_path(lv_vg_lite_path_t * dest, const lv_vg_lite_path_t * src) diff --git a/src/draw/vg_lite/lv_vg_lite_path.h b/src/draw/vg_lite/lv_vg_lite_path.h index a9ffee3dc6..09ac1d2780 100644 --- a/src/draw/vg_lite/lv_vg_lite_path.h +++ b/src/draw/vg_lite/lv_vg_lite_path.h @@ -23,20 +23,6 @@ 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)) diff --git a/tests/ref_imgs/draw/letter_bitmap_A_rotated_0.png b/tests/ref_imgs/draw/letter_bitmap_A_rotated_0.png new file mode 100644 index 0000000000..2b0435ff1a Binary files /dev/null and b/tests/ref_imgs/draw/letter_bitmap_A_rotated_0.png differ diff --git a/tests/ref_imgs/draw/letter_bitmap_A_rotated_180.png b/tests/ref_imgs/draw/letter_bitmap_A_rotated_180.png new file mode 100644 index 0000000000..ea7da872f8 Binary files /dev/null and b/tests/ref_imgs/draw/letter_bitmap_A_rotated_180.png differ diff --git a/tests/ref_imgs/draw/letter_bitmap_A_rotated_45.png b/tests/ref_imgs/draw/letter_bitmap_A_rotated_45.png new file mode 100644 index 0000000000..0d85be51b6 Binary files /dev/null and b/tests/ref_imgs/draw/letter_bitmap_A_rotated_45.png differ diff --git a/tests/ref_imgs/draw/letter_bitmap_A_rotated_90.png b/tests/ref_imgs/draw/letter_bitmap_A_rotated_90.png new file mode 100644 index 0000000000..13d88ea8ca Binary files /dev/null and b/tests/ref_imgs/draw/letter_bitmap_A_rotated_90.png differ diff --git a/tests/ref_imgs/draw/letter_bitmap_g_rotated_0.png b/tests/ref_imgs/draw/letter_bitmap_g_rotated_0.png new file mode 100644 index 0000000000..4bb9013257 Binary files /dev/null and b/tests/ref_imgs/draw/letter_bitmap_g_rotated_0.png differ diff --git a/tests/ref_imgs/draw/letter_bitmap_g_rotated_180.png b/tests/ref_imgs/draw/letter_bitmap_g_rotated_180.png new file mode 100644 index 0000000000..b1d7bc39dc Binary files /dev/null and b/tests/ref_imgs/draw/letter_bitmap_g_rotated_180.png differ diff --git a/tests/ref_imgs/draw/letter_bitmap_g_rotated_45.png b/tests/ref_imgs/draw/letter_bitmap_g_rotated_45.png new file mode 100644 index 0000000000..90ba9995e3 Binary files /dev/null and b/tests/ref_imgs/draw/letter_bitmap_g_rotated_45.png differ diff --git a/tests/ref_imgs/draw/letter_bitmap_g_rotated_90.png b/tests/ref_imgs/draw/letter_bitmap_g_rotated_90.png new file mode 100644 index 0000000000..eb14e5844a Binary files /dev/null and b/tests/ref_imgs/draw/letter_bitmap_g_rotated_90.png differ diff --git a/tests/ref_imgs/draw/letter_outline_A_rotated_0.png b/tests/ref_imgs/draw/letter_outline_A_rotated_0.png new file mode 100644 index 0000000000..de807fccdf Binary files /dev/null and b/tests/ref_imgs/draw/letter_outline_A_rotated_0.png differ diff --git a/tests/ref_imgs/draw/letter_outline_A_rotated_180.png b/tests/ref_imgs/draw/letter_outline_A_rotated_180.png new file mode 100644 index 0000000000..de807fccdf Binary files /dev/null and b/tests/ref_imgs/draw/letter_outline_A_rotated_180.png differ diff --git a/tests/ref_imgs/draw/letter_outline_A_rotated_45.png b/tests/ref_imgs/draw/letter_outline_A_rotated_45.png new file mode 100644 index 0000000000..de807fccdf Binary files /dev/null and b/tests/ref_imgs/draw/letter_outline_A_rotated_45.png differ diff --git a/tests/ref_imgs/draw/letter_outline_A_rotated_90.png b/tests/ref_imgs/draw/letter_outline_A_rotated_90.png new file mode 100644 index 0000000000..de807fccdf Binary files /dev/null and b/tests/ref_imgs/draw/letter_outline_A_rotated_90.png differ diff --git a/tests/ref_imgs/draw/letter_outline_g_rotated_0.png b/tests/ref_imgs/draw/letter_outline_g_rotated_0.png new file mode 100644 index 0000000000..de807fccdf Binary files /dev/null and b/tests/ref_imgs/draw/letter_outline_g_rotated_0.png differ diff --git a/tests/ref_imgs/draw/letter_outline_g_rotated_180.png b/tests/ref_imgs/draw/letter_outline_g_rotated_180.png new file mode 100644 index 0000000000..de807fccdf Binary files /dev/null and b/tests/ref_imgs/draw/letter_outline_g_rotated_180.png differ diff --git a/tests/ref_imgs/draw/letter_outline_g_rotated_45.png b/tests/ref_imgs/draw/letter_outline_g_rotated_45.png new file mode 100644 index 0000000000..de807fccdf Binary files /dev/null and b/tests/ref_imgs/draw/letter_outline_g_rotated_45.png differ diff --git a/tests/ref_imgs/draw/letter_outline_g_rotated_90.png b/tests/ref_imgs/draw/letter_outline_g_rotated_90.png new file mode 100644 index 0000000000..de807fccdf Binary files /dev/null and b/tests/ref_imgs/draw/letter_outline_g_rotated_90.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_0.png b/tests/ref_imgs_vg_lite/draw/letter_0.png index 1958787611..879c7b63dd 100644 Binary files a/tests/ref_imgs_vg_lite/draw/letter_0.png and b/tests/ref_imgs_vg_lite/draw/letter_0.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_0.png b/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_0.png new file mode 100644 index 0000000000..797ba6161e Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_0.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_180.png b/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_180.png new file mode 100644 index 0000000000..3ead79a198 Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_180.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_45.png b/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_45.png new file mode 100644 index 0000000000..c3efd4c1ed Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_45.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_90.png b/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_90.png new file mode 100644 index 0000000000..e7aefef67d Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_bitmap_A_rotated_90.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_0.png b/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_0.png new file mode 100644 index 0000000000..1f2cdb6b40 Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_0.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_180.png b/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_180.png new file mode 100644 index 0000000000..49b4b0c840 Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_180.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_45.png b/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_45.png new file mode 100644 index 0000000000..8f8b5a13fe Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_45.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_90.png b/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_90.png new file mode 100644 index 0000000000..ed80e1d736 Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_bitmap_g_rotated_90.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_0.png b/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_0.png new file mode 100644 index 0000000000..45021c9e05 Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_0.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_180.png b/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_180.png new file mode 100644 index 0000000000..98c67802a9 Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_180.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_45.png b/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_45.png new file mode 100644 index 0000000000..1a0c9180dc Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_45.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_90.png b/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_90.png new file mode 100644 index 0000000000..50b8461fa9 Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_outline_A_rotated_90.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_0.png b/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_0.png new file mode 100644 index 0000000000..5905b392da Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_0.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_180.png b/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_180.png new file mode 100644 index 0000000000..36c54ce207 Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_180.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_45.png b/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_45.png new file mode 100644 index 0000000000..1bd5943b9b Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_45.png differ diff --git a/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_90.png b/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_90.png new file mode 100644 index 0000000000..2d62fda16d Binary files /dev/null and b/tests/ref_imgs_vg_lite/draw/letter_outline_g_rotated_90.png differ diff --git a/tests/ref_imgs_vg_lite/libs/freetype_render_outline.png b/tests/ref_imgs_vg_lite/libs/freetype_render_outline.png index 84f186b2fe..176265da58 100644 Binary files a/tests/ref_imgs_vg_lite/libs/freetype_render_outline.png and b/tests/ref_imgs_vg_lite/libs/freetype_render_outline.png differ diff --git a/tests/src/test_cases/draw/test_draw_letter.c b/tests/src/test_cases/draw/test_draw_letter.c index 2159aacaf2..093faed9c7 100644 --- a/tests/src/test_cases/draw/test_draw_letter.c +++ b/tests/src/test_cases/draw/test_draw_letter.c @@ -4,6 +4,12 @@ #include "unity/unity.h" +#ifndef NON_AMD64_BUILD + #define TEST_ASSERT_EQUAL_LETTER_SCREENSHOT(path) TEST_ASSERT_EQUAL_SCREENSHOT(path) +#else + #define TEST_ASSERT_EQUAL_LETTER_SCREENSHOT(path) LV_UNUSED(path) +#endif + void setUp(void) { /* Function run before every test */ @@ -17,31 +23,34 @@ void tearDown(void) lv_obj_clean(lv_screen_active()); } -static lv_obj_t * canvas_create(void) +static void on_canvas_delete(lv_event_t * e) +{ + lv_obj_t * canvas = lv_event_get_current_target(e); + lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(canvas); + TEST_ASSERT_NOT_NULL(draw_buf); + lv_draw_buf_destroy(draw_buf); +} + +static lv_obj_t * canvas_create(uint32_t w, uint32_t h) { lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_obj_set_size(canvas, 500, 360); + lv_obj_set_size(canvas, w, h); - lv_draw_buf_t * draw_buf = lv_draw_buf_create(500, 360, LV_COLOR_FORMAT_ARGB8888, LV_STRIDE_AUTO); + lv_draw_buf_t * draw_buf = lv_draw_buf_create(w, h, LV_COLOR_FORMAT_ARGB8888, LV_STRIDE_AUTO); lv_draw_buf_clear(draw_buf, NULL); lv_canvas_set_draw_buf(canvas, draw_buf); + lv_obj_add_event_cb(canvas, on_canvas_delete, LV_EVENT_DELETE, NULL); 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_obj_t * canvas = canvas_create(500, 360); lv_layer_t layer; lv_canvas_init_layer(canvas, &layer); @@ -97,11 +106,89 @@ void test_draw_sin_wave(void) lv_canvas_finish_layer(canvas, &layer); -#ifndef NON_AMD64_BUILD - TEST_ASSERT_EQUAL_SCREENSHOT("draw/letter_0.png"); -#endif + TEST_ASSERT_EQUAL_LETTER_SCREENSHOT("draw/letter_0.png"); - canvas_destroy(canvas); + lv_obj_delete(canvas); +} + +static void draw_letter_with_rotation(lv_obj_t * canvas, lv_layer_t * layer, uint32_t unicode, int32_t rotation, + int32_t x, int32_t y) +{ + 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_obj_get_style_text_font(canvas, 0); + letter_dsc.unicode = unicode; + letter_dsc.rotation = rotation; + lv_draw_letter(layer, &letter_dsc, &(lv_point_t) { + .x = x, .y = y + }); +} + +static void test_draw_letter(lv_freetype_font_render_mode_t render_mode, uint32_t unicode, int32_t rotation, + const char * ref_img_path) +{ + lv_obj_t * canvas = canvas_create(240, 240); + + lv_font_t * font_normal = lv_freetype_font_create("./src/test_files/fonts/noto/NotoSansSC-Regular.ttf", + render_mode, + 80, + LV_FREETYPE_FONT_STYLE_NORMAL); + TEST_ASSERT_NOT_NULL(font_normal); + lv_obj_set_style_text_font(canvas, font_normal, 0); + + lv_layer_t layer; + lv_canvas_init_layer(canvas, &layer); + lv_canvas_fill_bg(canvas, lv_color_white(), LV_OPA_COVER); + + /* drawing letter with clipping */ + lv_area_t clip_area; + lv_area_set(&clip_area, 40, 40, 200 - 1, 200 - 1); + layer._clip_area = clip_area; + + const int32_t offset_x = 40; + const int32_t offset_y = 70; + + for(int i = 0; i < 9; i++) { + draw_letter_with_rotation(canvas, &layer, unicode, rotation, (i % 3) * 80 + offset_x, (i / 3) * 80 + offset_y); + } + + lv_draw_border_dsc_t draw_border_dsc; + lv_draw_border_dsc_init(&draw_border_dsc); + draw_border_dsc.width = 1; + draw_border_dsc.color = lv_color_black(); + lv_draw_border(&layer, &draw_border_dsc, &clip_area); + + lv_canvas_finish_layer(canvas, &layer); + + TEST_ASSERT_EQUAL_LETTER_SCREENSHOT(ref_img_path); + + lv_obj_delete(canvas); + lv_freetype_font_delete(font_normal); +} + +void test_draw_letter_bitmap(void) +{ + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 'A', 0, "draw/letter_bitmap_A_rotated_0.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 'A', 450, "draw/letter_bitmap_A_rotated_45.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 'A', 900, "draw/letter_bitmap_A_rotated_90.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 'A', 1800, "draw/letter_bitmap_A_rotated_180.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 'g', 0, "draw/letter_bitmap_g_rotated_0.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 'g', 450, "draw/letter_bitmap_g_rotated_45.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 'g', 900, "draw/letter_bitmap_g_rotated_90.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 'g', 1800, "draw/letter_bitmap_g_rotated_180.png"); +} + +void test_draw_letter_outline(void) +{ + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, 'A', 0, "draw/letter_outline_A_rotated_0.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, 'A', 450, "draw/letter_outline_A_rotated_45.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, 'A', 900, "draw/letter_outline_A_rotated_90.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, 'A', 1800, "draw/letter_outline_A_rotated_180.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, 'g', 0, "draw/letter_outline_g_rotated_0.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, 'g', 450, "draw/letter_outline_g_rotated_45.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, 'g', 900, "draw/letter_outline_g_rotated_90.png"); + test_draw_letter(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, 'g', 1800, "draw/letter_outline_g_rotated_180.png"); } #endif