improve ffr_draw_rounded_rect

This commit is contained in:
lixianjing 2021-06-17 10:55:42 +08:00
parent 7e5653ba06
commit 70a389c7d5
3 changed files with 335 additions and 608 deletions

View File

@ -4,6 +4,7 @@
* 完善awtk\_main.inc感谢朝泽提供补丁
* 修改控件动画的刷新时间和最高帧率绑定一起(感谢智明提供补丁)
* 增加lcd的接口并且完善其他的类型lcd的接口感谢智明提供补丁
* 修复圆角矩形依赖宏来判断lcd类型来打点的问题感谢智明提供补丁
2021/06/16
* 支持[极简键盘 (3 键键盘、5 键键盘和旋转按钮)](docs/how_to_support_5keys_3keys.md)

View File

@ -12,16 +12,6 @@
#include "../tkc/darray.h"
#include "../tkc/types_def.h"
#ifdef FRAGMENT_FRAME_BUFFER_SIZE
#include "../lcd/lcd_mem_fragment.h"
#else
#ifdef WITH_LCD_MONO
#include "../lcd/lcd_mono.h"
#else
#include "../lcd/lcd_mem.h"
#endif
#endif
/*
把二维坐标的象限通过45度分为上下区域一共8个区域
*/
@ -57,26 +47,11 @@ typedef struct _frr_point_pix_t {
typedef struct _frr_draw_info_t {
int32_t x;
int32_t y;
int32_t v;
int32_t h;
uint32_t radius;
float_t angle_v;
float_t angle_h;
} frr_draw_info_t;
typedef struct _frr_image_info_t {
uint32_t w;
uint32_t h;
uint32_t dx;
uint32_t dy;
uint32_t dw;
uint32_t dh;
uint32_t bpp;
uint32_t stride;
unsigned char* dst;
bitmap_format_t format;
} frr_image_info_t;
typedef struct _frr_draw_arc_info_table_t {
frr_quadrant_t quadrant_v;
frr_quadrant_t quadrant_h;
@ -112,46 +87,6 @@ typedef struct _frr_draw_arc_info_table_t {
#define ANGLE2SIZE(angle, r) ((int)(sinf(angle) * (r)))
#define BLEND_DATA(d1, d2, a) ((((d1) * (a)) + ((d2) * (0xff - (a)))) >> 8)
#define FFR_LIMIT_UINT8(tmp, out) { \
if((tmp) > 0xff) { \
(out) = 0xff; \
} else if((tmp) < 0) { \
(out) = 0; \
} else { \
(out) = (tmp); \
} \
}
#define IMAGE_COLOR2COLOR_BLEND(c1, c2, a) { \
if (a < 0x8) { \
c1.r = c2.r; \
c1.g = c2.g; \
c1.b = c2.b; \
c1.a = c2.a; \
} else if (a < 0xfa) { \
if (c2.a > 0xf4) { \
c1.r = BLEND_DATA(c1.r, c2.r, a); \
c1.g = BLEND_DATA(c1.g, c2.g, a); \
c1.b = BLEND_DATA(c1.b, c2.b, a); \
c1.a = 0xff; \
} else { \
uint8_t out_a = 0x0; \
FFR_LIMIT_UINT8(a + c2.a - ((a * c2.a) >> 8), out_a); \
if(out_a > 0) { \
uint8_t d_a = (c2.a * (0xff - a)) >> 8; \
c1.r = (c1.r * a + c2.r * d_a) / out_a; \
c1.g = (c1.g * a + c2.g * d_a) / out_a; \
c1.b = (c1.b * a + c2.b * d_a) / out_a; \
c1.a = out_a; \
} else { \
c1.r = c1.g = c1.b = c1.a = 0x0; \
} \
} \
} \
}
#define FFR_SET_STANDARD_RADIUS(is_h, w, h, radius) { \
if ((is_h && *radius > h)) { \
*radius = h; \
@ -161,9 +96,6 @@ typedef struct _frr_draw_arc_info_table_t {
*radius = *radius <= FFR_SUPPORT_MIN_RADIUS ? 0 : *radius; \
}
#ifndef WITH_NANOVG_GPU
static frr_point_pix_t frr_point_pix_cache_list[FRR_POINT_PIX_CACHE_SIZE];
const static frr_draw_arc_info_table_t WIDGET_DRAW_ARC_INFO_TABLE[FRR_VERTEXT_TYPE_COUNT] = {
@ -172,221 +104,13 @@ const static frr_draw_arc_info_table_t WIDGET_DRAW_ARC_INFO_TABLE[FRR_VERTEXT_TY
{FRR_QUADRANT_THIRD_F, FRR_QUADRANT_THIRD_S}, //左下角
{FRR_QUADRANT_FOURTH_F, FRR_QUADRANT_FOURTH_S}}; //右下角
static inline int32_t frr_image_get_buff_point(frr_image_info_t* info, int32_t x,
int32_t y) {
#if defined(WITH_LCD_MONO)
return 0;
#else
int32_t p = -1;
int32_t dx = 0;
int32_t dy = 0;
return_value_if_fail(info != NULL, -1);
if (x < 0 || x >= (int32_t)info->w || y < 0 || y >= (int32_t)info->h || info->stride == 0 ||
info->bpp == 0) {
return p;
static void ffr_draw_antialiasing_for_point(canvas_t* c, int px, int py, float_t e, color_t color) {
color.rgba.a = (unsigned char)(e * color.rgba.a);
canvas_set_stroke_color(c, color);
canvas_draw_vline(c, px, py, 1);
}
dx = x - info->dx;
dy = y - info->dy;
if (dx < 0 || dx >= (int32_t)info->dw || dy < 0 || dy >= (int32_t)info->dh) {
return p;
}
p = dx * info->bpp + dy * info->stride;
return p;
#endif
}
static inline frr_image_info_t* ffr_image_info_create(frr_image_info_t* info, canvas_t* c) {
vgcanvas_t* vg = canvas_get_vgcanvas(c);
if (info == NULL) {
info = TKMEM_ZALLOC(frr_image_info_t);
return_value_if_fail(info != NULL, NULL);
}
if (vg != NULL) {
info->dx = 0;
info->dy = 0;
info->dw = info->w = vg->w;
info->dh = info->h = vg->h;
info->stride = vg->stride;
info->format = vg->format;
info->dst = (unsigned char*)vg->buff;
} else {
#ifdef FRAGMENT_FRAME_BUFFER_SIZE
info->w = c->lcd->w;
info->h = c->lcd->h;
info->dx = c->lcd->dirty_rect.x;
info->dy = c->lcd->dirty_rect.y;
info->dw = c->lcd->dirty_rect.w;
info->dh = c->lcd->dirty_rect.h;
info->dst = lcd_mem_fragment_get_buff(c->lcd);
info->format = lcd_get_desired_bitmap_format(c->lcd);
info->stride = info->dw * bitmap_get_bpp_of_format(info->format);
#elif defined(WITH_LCD_MONO)
lcd_mono_t* mem = (lcd_mono_t*)c->lcd;
info->dx = 0;
info->dy = 0;
info->dst = mem->data;
info->dw = info->w = c->lcd->w;
info->dh = info->h = c->lcd->h;
info->format = BITMAP_FMT_MONO;
#else
lcd_mem_t* mem = (lcd_mem_t*)c->lcd;
info->dx = 0;
info->dy = 0;
info->dst = mem->offline_fb;
info->dw = info->w = c->lcd->w;
info->dh = info->h = c->lcd->h;
info->stride = mem->line_length;
info->format = lcd_get_desired_bitmap_format(c->lcd);
#endif
}
info->bpp = bitmap_get_bpp_of_format(info->format);
return info;
}
static inline void ffr_image_data2color(unsigned char* d, int32_t x, int32_t y, int32_t w, int32_t h, bitmap_format_t format, rgba_t* rgb) {
uint32_t c_16 = 0;
switch (format) {
case BITMAP_FMT_RGBA8888:
rgb->r = *d++;
rgb->g = *d++;
rgb->b = *d++;
rgb->a = *d++;
break;
case BITMAP_FMT_ABGR8888:
rgb->a = *d++;
rgb->b = *d++;
rgb->g = *d++;
rgb->r = *d++;
break;
case BITMAP_FMT_BGRA8888:
rgb->b = *d++;
rgb->g = *d++;
rgb->r = *d++;
rgb->a = *d++;
break;
case BITMAP_FMT_ARGB8888:
rgb->a = *d++;
rgb->r = *d++;
rgb->g = *d++;
rgb->b = *d++;
break;
case BITMAP_FMT_RGB565:
c_16 = (d[1] << 8) | d[0];
rgb->b = (c_16 >> 11) << 3;
rgb->g = ((c_16 >> 5) & 0x3f) << 2;
rgb->r = (c_16 & 0x1f) << 3;
rgb->a = 0xff;
break;
case BITMAP_FMT_BGR565:
c_16 = (d[1] << 8) | d[0];
rgb->r = (c_16 >> 11) << 3;
rgb->g = ((c_16 >> 5) & 0x3f) << 2;
rgb->b = (c_16 & 0x1f) << 3;
rgb->a = 0xff;
break;
case BITMAP_FMT_RGB888:
rgb->r = *d++;
rgb->g = *d++;
rgb->b = *d++;
rgb->a = 255;
break;
case BITMAP_FMT_BGR888:
rgb->b = *d++;
rgb->g = *d++;
rgb->r = *d++;
rgb->a = 255;
break;
#ifdef WITH_LCD_MONO
case BITMAP_FMT_MONO: {
uint8_t p = bitmap_mono_get_pixel(d, w, h, x, y);
color_t c = color_from_mono(p);
rgb->b = c.rgba.b;
rgb->g = c.rgba.g;
rgb->r = c.rgba.r;
rgb->a = c.rgba.a;
break;
}
#endif
default:
break;
}
}
static inline void ffr_image_color2data(unsigned char* d, int32_t x, int32_t y, int32_t w, int32_t h, bitmap_format_t format, rgba_t rgb) {
switch (format) {
case BITMAP_FMT_RGBA8888:
*d++ = rgb.r;
*d++ = rgb.g;
*d++ = rgb.b;
*d++ = rgb.a;
break;
case BITMAP_FMT_ABGR8888:
*d++ = rgb.a;
*d++ = rgb.b;
*d++ = rgb.g;
*d++ = rgb.r;
break;
case BITMAP_FMT_BGRA8888:
*d++ = rgb.b;
*d++ = rgb.g;
*d++ = rgb.r;
*d++ = rgb.a;
break;
case BITMAP_FMT_ARGB8888:
*d++ = rgb.a;
*d++ = rgb.r;
*d++ = rgb.g;
*d++ = rgb.b;
break;
case BITMAP_FMT_BGR565:
*(uint16_t*)d = ((rgb.r >> 3) << 11) | ((rgb.g >> 2) << 5) | (rgb.b >> 3);
break;
case BITMAP_FMT_RGB565:
*(uint16_t*)d = ((rgb.b >> 3) << 11) | ((rgb.g >> 2) << 5) | (rgb.r >> 3);
break;
case BITMAP_FMT_RGB888:
*d++ = rgb.r;
*d++ = rgb.g;
*d++ = rgb.b;
break;
case BITMAP_FMT_BGR888:
*d++ = rgb.b;
*d++ = rgb.g;
*d++ = rgb.r;
break;
#ifdef WITH_LCD_MONO
case BITMAP_FMT_MONO:
bitmap_mono_set_pixel(d, w, h, x, y, rgb.r);
break;
#endif
default:
break;
}
}
static inline void ffr_draw_antialiasing_for_point(frr_image_info_t* image_info,
canvas_t* canvas, int px, int py, float_t e,
rgba_t n_color, rgba_t o_color) {
int32_t p = 0;
unsigned char a = (unsigned char)(e * n_color.a);
if (canvas->clip_left <= px && px <= canvas->clip_right && canvas->clip_top <= py &&
py <= canvas->clip_bottom) {
IMAGE_COLOR2COLOR_BLEND(n_color, o_color, a);
p = frr_image_get_buff_point(image_info, px, py);
if (p >= 0) {
ffr_image_color2data(image_info->dst + p, px, py, image_info->w, image_info->h, image_info->format, n_color);
}
}
}
static inline bool_t ffr_get_circluar_point_to_quadrant(int32_t xc, int32_t yc, int32_t px,
static bool_t ffr_get_circluar_point_to_quadrant(int32_t xc, int32_t yc, int32_t px,
int32_t py, frr_quadrant_t type,
int32_t* out_x, int32_t* out_y) {
int32_t tmp_x = 0;
@ -434,17 +158,16 @@ static inline bool_t ffr_get_circluar_point_to_quadrant(int32_t xc, int32_t yc,
return TRUE;
}
static inline void ffr_draw_circluar_point_to_quadrant(frr_image_info_t* image_info, canvas_t* c,
static void ffr_draw_circluar_point_to_quadrant(canvas_t* c,
int32_t x_h, int32_t y_v, int32_t xc,
int32_t yc, int32_t px, int32_t py,
float_t e, frr_quadrant_t type,
rgba_t color) {
color_t color) {
int32_t p = 0;
int32_t x = 0;
int32_t y = 0;
int32_t w = 0;
int32_t h = 0;
rgba_t o_color = {0};
if (ffr_get_circluar_point_to_quadrant(xc, yc, px, py, type, &x, &y)) {
if (x_h > x) {
w = x_h - x;
@ -462,37 +185,27 @@ static inline void ffr_draw_circluar_point_to_quadrant(frr_image_info_t* image_i
y--;
}
x += c->ox;
y += c->oy;
if (w > 0 && h > 0) {
p = frr_image_get_buff_point(image_info, x, y);
if (p >= 0) {
ffr_image_data2color(image_info->dst + p, x, y, image_info->w, image_info->h, image_info->format, &o_color);
ffr_draw_antialiasing_for_point(image_info, c, x, y, e, color, o_color);
}
ffr_draw_antialiasing_for_point(c, x, y, e, color);
}
}
}
static inline void ffr_draw_circluar_point_to_quadrant_hline(frr_image_info_t* image_info,
canvas_t* c, int32_t x_h,
static void ffr_draw_circluar_point_to_quadrant_hline(canvas_t* c, int32_t x_h,
int32_t y_v, int32_t xc, int32_t yc,
int32_t px, int32_t py, float_t e,
frr_quadrant_t type, rgba_t color) {
frr_quadrant_t type, color_t color) {
int32_t p = 0;
int32_t x = 0;
int32_t y = 0;
int32_t w = 0;
int32_t h = 0;
rgba_t o_color = {0};
if (ffr_get_circluar_point_to_quadrant(xc, yc, px, py, type, &x, &y)) {
if (x_h > x) {
w = x_h - x;
x_h = x;
w = x_h - x - 1;
x_h = x + 1;
} else {
w = x - x_h;
w = x - x_h - 1;
x--;
}
@ -505,17 +218,14 @@ static inline void ffr_draw_circluar_point_to_quadrant_hline(frr_image_info_t* i
}
if (w > 0 && h > 0) {
p = frr_image_get_buff_point(image_info, x + c->ox, y + c->oy);
if (p >= 0) {
ffr_image_data2color(image_info->dst + p, x + c->ox, y + c->oy, image_info->w, image_info->h, image_info->format, &o_color);
}
canvas_set_fill_color(c, color);
canvas_fill_rect(c, x_h, y, w, 1);
ffr_draw_antialiasing_for_point(image_info, c, x + c->ox, y + c->oy, e, color, o_color);
ffr_draw_antialiasing_for_point(c, x, y, e, color);
}
}
}
static inline void Wu_D_Circle(int32_t r, darray_t* point_list,
static void Wu_D_Circle(int32_t r, darray_t* point_list,
frr_point_pix_t* point_pix_cache_list) {
int32_t x = 0;
int32_t y = r;
@ -539,35 +249,35 @@ static inline void Wu_D_Circle(int32_t r, darray_t* point_list,
}
}
static void ffr_draw_stroke_arc_point_list(frr_image_info_t* image_info, canvas_t* c, int32_t x_h,
static void ffr_draw_stroke_arc_point_list(canvas_t* c, int32_t x_h,
int32_t y_v, int32_t xc, int32_t yc,
frr_quadrant_t type, const color_t* color,
frr_quadrant_t type, color_t color,
darray_t* point_list, bool_t is_last_antialiasing) {
uint32_t i = 0;
void** elms = point_list->elms;
for (i = 0; i < point_list->size; i++) {
frr_point_pix_t* iter = (frr_point_pix_t*)elms[i];
ffr_draw_circluar_point_to_quadrant(image_info, c, x_h, y_v, xc, yc, iter->x, iter->y,
1 - iter->e, type, color->rgba);
ffr_draw_circluar_point_to_quadrant(c, x_h, y_v, xc, yc, iter->x, iter->y,
1 - iter->e, type, color);
if (point_list->size > i + 1 || is_last_antialiasing) {
ffr_draw_circluar_point_to_quadrant(image_info, c, x_h, y_v, xc, yc, iter->x, iter->y - 1,
iter->e, type, color->rgba);
ffr_draw_circluar_point_to_quadrant(c, x_h, y_v, xc, yc, iter->x, iter->y - 1,
iter->e, type, color);
}
}
}
static void ffr_draw_fill_arc_point_list(frr_image_info_t* image_info, canvas_t* c, int32_t x_h,
static void ffr_draw_fill_arc_point_list(canvas_t* c, int32_t x_h,
int32_t y_v, int32_t xc, int32_t yc, frr_quadrant_t type,
const color_t* color, darray_t* point_list) {
color_t color, darray_t* point_list) {
uint32_t i = 0;
void** elms = point_list->elms;
for (i = 0; i < point_list->size; i++) {
frr_point_pix_t* iter = (frr_point_pix_t*)elms[i];
ffr_draw_circluar_point_to_quadrant_hline(image_info, c, x_h, y_v, xc, yc, iter->x, iter->y,
1 - iter->e, type, color->rgba);
ffr_draw_circluar_point_to_quadrant_hline(c, x_h, y_v, xc, yc, iter->x, iter->y,
1 - iter->e, type, color);
}
}
@ -606,10 +316,10 @@ static void ffr_push_arc_point_list(float_t angle_1, float_t angle_2, int32_t r,
}
}
static void ffr_draw_arc_point_list(frr_image_info_t* image_info, canvas_t* c, int32_t x_h,
static void ffr_draw_arc_point_list(canvas_t* c, int32_t x_h,
int32_t y_v, int32_t xc, int32_t yc, float_t angle_h,
float_t angle_v, int32_t r, uint32_t quadrant_id,
const color_t* color, darray_t* point_list,
color_t color, darray_t* point_list,
darray_t* point_list_45, bool_t is_fill) {
float_t angle_v_1 = 0.0f;
float_t angle_h_1 = 0.0f;
@ -636,11 +346,11 @@ static void ffr_draw_arc_point_list(frr_image_info_t* image_info, canvas_t* c, i
if (angle_v > M_FRR_PI_4) {
ffr_push_arc_point_list(angle_v_1, angle_v_2, r, point_list, point_list_45, TRUE);
if (is_fill) {
ffr_draw_fill_arc_point_list(image_info, c, x_h, y_v, xc, yc,
ffr_draw_fill_arc_point_list(c, x_h, y_v, xc, yc,
WIDGET_DRAW_ARC_INFO_TABLE[quadrant_id].quadrant_v, color,
point_list);
} else {
ffr_draw_stroke_arc_point_list(image_info, c, x_h, y_v, xc, yc,
ffr_draw_stroke_arc_point_list(c, x_h, y_v, xc, yc,
WIDGET_DRAW_ARC_INFO_TABLE[quadrant_id].quadrant_v, color,
point_list, TRUE);
}
@ -653,11 +363,11 @@ static void ffr_draw_arc_point_list(frr_image_info_t* image_info, canvas_t* c, i
point_list->size--;
}
if (is_fill) {
ffr_draw_fill_arc_point_list(image_info, c, x_h, y_v, xc, yc,
ffr_draw_fill_arc_point_list(c, x_h, y_v, xc, yc,
WIDGET_DRAW_ARC_INFO_TABLE[quadrant_id].quadrant_h, color,
point_list);
} else {
ffr_draw_stroke_arc_point_list(image_info, c, x_h, y_v, xc, yc,
ffr_draw_stroke_arc_point_list(c, x_h, y_v, xc, yc,
WIDGET_DRAW_ARC_INFO_TABLE[quadrant_id].quadrant_h, color,
point_list, angle_v <= M_FRR_PI_4);
}
@ -677,39 +387,6 @@ static bool_t ffr_draw_rounded_radius_equal(uint32_t radius_tl, uint32_t radius_
return TRUE;
}
#endif
#ifndef WITH_NANOVG_GPU
static void ffr_draw_rounded_rect_draw_circle_limit(frr_vertex_type_t type, int32_t x, int32_t y, float_t w1, float_t w2, float_t h1, float_t h2, int32_t mid_lenght_v, int32_t mid_lenght_h, int32_t* v, int32_t* h) {
int32_t h_x1 = x + (int32_t)w2;
int32_t h_x2 = x + (int32_t)w2 + mid_lenght_h;
int32_t v_y1 = y + (int32_t)h1;
int32_t v_y2 = y + (int32_t)h1 + mid_lenght_v;
switch (type)
{
case FRR_VERTEXT_TYPE_TOP_REIGHT:
*h = h_x2;
*v = v_y1;
break;
case FRR_VERTEXT_TYPE_TOP_LEFT:
*h = h_x1;
*v = v_y1;
break;
case FRR_VERTEXT_TYPE_BOTTOM_LEFT:
*h = h_x1;
*v = v_y2;
break;
case FRR_VERTEXT_TYPE_BOTTOM_REIGHT:
*h = h_x2;
*v = v_y2;
break;
default:
break;
}
}
#endif
static float_t ffr_draw_rounded_get_vertex_angle_by_border_model(int32_t border_model, frr_vertex_type_t type, bool_t is_h, float_t default_angle) {
int32_t num = (int32_t)type;
@ -726,11 +403,11 @@ static float_t ffr_draw_rounded_get_vertex_angle_by_border_model(int32_t border_
}
}
static void ffr_draw_rounded_rect_draw_fill_with_vg(canvas_t* c, vgcanvas_t* vg, const color_t* color, frr_draw_info_t draw_infos[FRR_VERTEXT_TYPE_COUNT]) {
static void ffr_draw_rounded_rect_draw_fill_with_vg(canvas_t* c, vgcanvas_t* vg, color_t color, frr_draw_info_t draw_infos[FRR_VERTEXT_TYPE_COUNT]) {
vgcanvas_save(vg);
vgcanvas_set_fill_color(vg, *color);
vgcanvas_set_fill_color(vg, color);
vgcanvas_translate(vg, (float_t)c->ox, (float_t)c->oy);
vgcanvas_begin_path(vg);
@ -900,13 +577,13 @@ static void ffr_draw_rounded_rect_draw_stroke_bottom_right_with_vg(vgcanvas_t* v
}
}
static void ffr_draw_rounded_rect_draw_stroke_with_vg(canvas_t* c, vgcanvas_t* vg, uint32_t border_width, const color_t* color, frr_draw_info_t draw_infos[FRR_VERTEXT_TYPE_COUNT], int32_t border_model) {
static void ffr_draw_rounded_rect_draw_stroke_with_vg(canvas_t* c, vgcanvas_t* vg, uint32_t border_width, color_t color, frr_draw_info_t draw_infos[FRR_VERTEXT_TYPE_COUNT], int32_t border_model) {
uint32_t i = 0;
uint32_t n = 0;
frr_vertex_type_t start_vertext = ffr_draw_rounded_rect_get_stroke_start_vertext(border_model);
vgcanvas_save(vg);
vgcanvas_set_stroke_color(vg, *color);
vgcanvas_set_stroke_color(vg, color);
vgcanvas_set_line_width(vg, (float_t)border_width);
vgcanvas_translate(vg, (float_t)c->ox, (float_t)c->oy);
@ -946,7 +623,7 @@ static void ffr_draw_rounded_rect_draw_stroke_with_vg(canvas_t* c, vgcanvas_t* v
vgcanvas_restore(vg);
}
static inline void ffr_get_standard_rounded_rect_radius(const rect_t* r, uint32_t* radius_tl, uint32_t* radius_tr,
static void ffr_get_standard_rounded_rect_radius(const rect_t* r, uint32_t* radius_tl, uint32_t* radius_tr,
uint32_t* radius_bl, uint32_t* radius_br) {
int32_t w = r->w / 2;
int32_t h = r->h / 2;
@ -1019,58 +696,43 @@ static void ffr_draw_rounded_rect_draw_info_init(frr_draw_info_t draw_infos[FRR_
draw_infos[i].radius = radius;
mid_lenght_v = ffr_get_rounded_rect_mid_length(radius, r->h, &w1, &h1, &(draw_infos[i].angle_v), TRUE);
mid_lenght_h = ffr_get_rounded_rect_mid_length(radius, r->w, &h2, &w2, &(draw_infos[i].angle_h), TRUE);
#ifndef WITH_NANOVG_GPU
ffr_draw_rounded_rect_draw_circle_limit((frr_vertex_type_t)i, x, y, w1, w2, h1, h2, mid_lenght_v, mid_lenght_h, &(draw_infos[i].v), &(draw_infos[i].h));
#else
(void)mid_lenght_v;
(void)mid_lenght_h;
#endif
for(j = i; j < FRR_VERTEXT_TYPE_COUNT; j++) {
if (i != j && radius_list[j] == radius) {
draw_infos[j].radius = radius;
draw_infos[j].angle_v = draw_infos[i].angle_v;
draw_infos[j].angle_h = draw_infos[i].angle_h;
#ifndef WITH_NANOVG_GPU
ffr_draw_rounded_rect_draw_circle_limit((frr_vertex_type_t)j, x, y, w1, w2, h1, h2, mid_lenght_v, mid_lenght_h, &(draw_infos[j].v), &(draw_infos[j].h));
#endif
}
}
}
}
static ret_t ffr_draw_fill_rounded_rect(canvas_t* c, const rect_t* r, const color_t* color, uint32_t radius_tl, uint32_t radius_tr, uint32_t radius_bl, uint32_t radius_br) {
uint32_t radius = radius_tl != 0 ? radius_tl : (radius_tr != 0 ? radius_tr : (radius_bl != 0 ? radius_bl : radius_br));
#ifndef WITH_NANOVG_GPU
int32_t x = r->x;
int32_t y = r->y;
int32_t x1 = x + radius;
int32_t y1 = y + radius;
int32_t x2 = x + r->w - radius;
int32_t y2 = y + r->h - radius;
darray_t point_list_45 = {0};
darray_t tmp_point_list_45 = {0};
frr_image_info_t image_info = {0};
frr_point_pix_t* point_pix_cache_list = NULL;
if (radius != 0 && ffr_draw_rounded_radius_equal(radius_tl, radius_tr, radius_bl, radius_br)) {
static void ffr_draw_rounded_rect_draw_fill_with_canvas(canvas_t* c, const rect_t* r, color_t color, uint32_t radius, uint32_t radius_tl, uint32_t radius_tr, uint32_t radius_bl, uint32_t radius_br) {
float_t w1 = 0.0f;
float_t w2 = 0.0f;
float_t h1 = 0.0f;
float_t h2 = 0.0f;
float_t angle_v = 0.0f;
float_t angle_h = 0.0f;
int32_t mid_lenght_v = ffr_get_rounded_rect_mid_length(radius, r->h, &w1, &h1, &angle_v, TRUE);
int32_t mid_lenght_h = ffr_get_rounded_rect_mid_length(radius, r->w, &h2, &w2, &angle_h, TRUE);
int32_t x = r->x;
int32_t y = r->y;
int32_t x1 = x + radius;
int32_t y1 = y + radius;
int32_t x2 = x + r->w - radius;
int32_t y2 = y + r->h - radius;
int32_t v_x1 = x + (int32_t)w2;
int32_t v_y1 = y + (int32_t)h1;
int32_t v_x2 = x + (int32_t)w2 + mid_lenght_h;
int32_t v_y2 = y + (int32_t)h1 + mid_lenght_v;
darray_t point_list_45 = {0};
darray_t tmp_point_list_45 = {0};
frr_point_pix_t* point_pix_cache_list = NULL;
uint32_t size = ANGLE2SIZE(M_FRR_PI_4, radius) * 1.5f;
if (size <= FRR_POINT_PIX_CACHE_SIZE) {
point_pix_cache_list = frr_point_pix_cache_list;
@ -1083,26 +745,25 @@ static ret_t ffr_draw_fill_rounded_rect(canvas_t* c, const rect_t* r, const colo
Wu_D_Circle(radius, &point_list_45, point_pix_cache_list);
canvas_set_fill_color(c, *color);
ffr_image_info_create(&image_info, c);
canvas_set_fill_color(c, color);
if (radius_tr > 0) {
ffr_draw_arc_point_list(&image_info, c, v_x2, v_y1, x2, y1, angle_h, angle_v, radius, FRR_VERTEXT_TYPE_TOP_REIGHT, color,
ffr_draw_arc_point_list(c, v_x2, v_y1, x2, y1, angle_h, angle_v, radius, FRR_VERTEXT_TYPE_TOP_REIGHT, color,
&tmp_point_list_45, &point_list_45, TRUE); // 右上角
}
if (radius_tl > 0) {
ffr_draw_arc_point_list(&image_info, c, v_x1, v_y1, x1, y1, angle_h, angle_v, radius, FRR_VERTEXT_TYPE_TOP_LEFT, color,
ffr_draw_arc_point_list(c, v_x1, v_y1, x1, y1, angle_h, angle_v, radius, FRR_VERTEXT_TYPE_TOP_LEFT, color,
&tmp_point_list_45, &point_list_45, TRUE); // 左上角
}
if (radius_bl > 0) {
ffr_draw_arc_point_list(&image_info, c, v_x1, v_y2, x1, y2, angle_h, angle_v, radius, FRR_VERTEXT_TYPE_BOTTOM_LEFT, color,
ffr_draw_arc_point_list(c, v_x1, v_y2, x1, y2, angle_h, angle_v, radius, FRR_VERTEXT_TYPE_BOTTOM_LEFT, color,
&tmp_point_list_45, &point_list_45, TRUE); // 左下角
}
if (radius_br > 0) {
ffr_draw_arc_point_list(&image_info, c, v_x2, v_y2, x2, y2, angle_h, angle_v, radius, FRR_VERTEXT_TYPE_BOTTOM_REIGHT, color,
ffr_draw_arc_point_list(c, v_x2, v_y2, x2, y2, angle_h, angle_v, radius, FRR_VERTEXT_TYPE_BOTTOM_REIGHT, color,
&tmp_point_list_45, &point_list_45, TRUE); // 右下角
}
@ -1155,9 +816,15 @@ static ret_t ffr_draw_fill_rounded_rect(canvas_t* c, const rect_t* r, const colo
TKMEM_FREE(point_pix_cache_list);
point_pix_cache_list = NULL;
}
} else
#endif
{
}
static ret_t ffr_draw_fill_rounded_rect(canvas_t* c, const rect_t* r, color_t color, uint32_t radius_tl, uint32_t radius_tr, uint32_t radius_bl, uint32_t radius_br) {
lcd_type_t lcd_type = lcd_get_curr_lcd_type(c->lcd);
bool_t is_cpu_lcd = lcd_type != LCD_VGCANVAS && lcd_type != LCD_REGISTER;
uint32_t radius = radius_tl != 0 ? radius_tl : (radius_tr != 0 ? radius_tr : (radius_bl != 0 ? radius_bl : radius_br));
if (is_cpu_lcd && radius != 0 && ffr_draw_rounded_radius_equal(radius_tl, radius_tr, radius_bl, radius_br)) {
ffr_draw_rounded_rect_draw_fill_with_canvas(c, r, color, radius, radius_tl, radius_tr, radius_bl, radius_br);
} else {
vgcanvas_t* vg = canvas_get_vgcanvas(c);
if (radius != 0 && vg != NULL) {
frr_draw_info_t draw_infos[FRR_VERTEXT_TYPE_COUNT] = {0};
@ -1170,12 +837,8 @@ static ret_t ffr_draw_fill_rounded_rect(canvas_t* c, const rect_t* r, const colo
return RET_OK;
}
static ret_t ffr_draw_stroke_rounded_rect(canvas_t* c, const rect_t* r, const color_t* color, uint32_t radius_tl, uint32_t radius_tr, uint32_t radius_bl, uint32_t radius_br,
static void ffr_draw_rounded_rect_draw_stroke_with_canvas(canvas_t* c, const rect_t* r, color_t color, uint32_t radius, uint32_t radius_tl, uint32_t radius_tr, uint32_t radius_bl, uint32_t radius_br,
uint32_t border_width, int32_t border_model) {
uint32_t radius = radius_tl != 0 ? radius_tl : (radius_tr != 0 ? radius_tr : (radius_bl != 0 ? radius_bl : radius_br));
#ifndef WITH_NANOVG_GPU
float_t w1 = 0.0f;
float_t w2 = 0.0f;
float_t h1 = 0.0f;
@ -1183,20 +846,12 @@ static ret_t ffr_draw_stroke_rounded_rect(canvas_t* c, const rect_t* r, const co
float_t angle_v = 0.0f;
float_t angle_h = 0.0f;
darray_t point_list_45 = {0};
darray_t tmp_point_list_45 = {0};
frr_image_info_t image_info = {0};
frr_point_pix_t* point_pix_cache_list = NULL;
if (border_width == 1 && radius != 0 && ffr_draw_rounded_radius_equal(radius_tl, radius_tr, radius_bl, radius_br)) {
int32_t x = r->x;
int32_t y = r->y;
int32_t x1 = x + radius;
int32_t y1 = y + radius;
int32_t x2 = x + r->w - radius;
int32_t y2 = y + r->h - radius;
int32_t mid_lenght_v = ffr_get_rounded_rect_mid_length(radius, r->h, &w1, &h1, &angle_v, TRUE);
int32_t mid_lenght_h = ffr_get_rounded_rect_mid_length(radius, r->w, &h2, &w2, &angle_h, TRUE);
@ -1205,6 +860,10 @@ static ret_t ffr_draw_stroke_rounded_rect(canvas_t* c, const rect_t* r, const co
int32_t v_y1 = y + (int32_t)h1;
int32_t v_y2 = y + (int32_t)h1 + mid_lenght_v;
darray_t point_list_45 = {0};
darray_t tmp_point_list_45 = {0};
frr_point_pix_t* point_pix_cache_list = NULL;
uint32_t size = ANGLE2SIZE(M_FRR_PI_4, radius) + 1;
if (size <= FRR_POINT_PIX_CACHE_SIZE) {
point_pix_cache_list = frr_point_pix_cache_list;
@ -1217,36 +876,35 @@ static ret_t ffr_draw_stroke_rounded_rect(canvas_t* c, const rect_t* r, const co
Wu_D_Circle(radius, &point_list_45, point_pix_cache_list);
canvas_set_stroke_color(c, *color);
ffr_image_info_create(&image_info, c);
canvas_set_stroke_color(c, color);
if (radius_tr > 0) {
float_t tmp_angle_h = ffr_draw_rounded_get_vertex_angle_by_border_model(border_model, FRR_VERTEXT_TYPE_TOP_REIGHT, TRUE, angle_h);
float_t tmp_angle_v = ffr_draw_rounded_get_vertex_angle_by_border_model(border_model, FRR_VERTEXT_TYPE_TOP_REIGHT, FALSE, angle_v);
ffr_draw_arc_point_list(&image_info, c, v_x2, v_y1, x2, y1, tmp_angle_h, tmp_angle_v, radius, FRR_VERTEXT_TYPE_TOP_REIGHT,
ffr_draw_arc_point_list(c, v_x2, v_y1, x2, y1, tmp_angle_h, tmp_angle_v, radius, FRR_VERTEXT_TYPE_TOP_REIGHT,
color, &tmp_point_list_45, &point_list_45, FALSE); // 右上角
}
if (radius_tl > 0) {
float_t tmp_angle_h = ffr_draw_rounded_get_vertex_angle_by_border_model(border_model, FRR_VERTEXT_TYPE_TOP_LEFT, TRUE, angle_h);
float_t tmp_angle_v = ffr_draw_rounded_get_vertex_angle_by_border_model(border_model, FRR_VERTEXT_TYPE_TOP_LEFT, FALSE, angle_v);
ffr_draw_arc_point_list(&image_info, c, v_x1, v_y1, x1, y1, tmp_angle_h, tmp_angle_v, radius, FRR_VERTEXT_TYPE_TOP_LEFT,
ffr_draw_arc_point_list(c, v_x1, v_y1, x1, y1, tmp_angle_h, tmp_angle_v, radius, FRR_VERTEXT_TYPE_TOP_LEFT,
color, &tmp_point_list_45, &point_list_45, FALSE); // 左上角
}
if (radius_bl > 0) {
float_t tmp_angle_h = ffr_draw_rounded_get_vertex_angle_by_border_model(border_model, FRR_VERTEXT_TYPE_BOTTOM_LEFT, TRUE, angle_h);
float_t tmp_angle_v = ffr_draw_rounded_get_vertex_angle_by_border_model(border_model, FRR_VERTEXT_TYPE_BOTTOM_LEFT, FALSE, angle_v);
ffr_draw_arc_point_list(&image_info, c, v_x1, v_y2, x1, y2, tmp_angle_h, tmp_angle_v, radius, FRR_VERTEXT_TYPE_BOTTOM_LEFT,
ffr_draw_arc_point_list(c, v_x1, v_y2, x1, y2, tmp_angle_h, tmp_angle_v, radius, FRR_VERTEXT_TYPE_BOTTOM_LEFT,
color, &tmp_point_list_45, &point_list_45, FALSE); // 左下角
}
if (radius_br > 0) {
float_t tmp_angle_h = ffr_draw_rounded_get_vertex_angle_by_border_model(border_model, FRR_VERTEXT_TYPE_BOTTOM_REIGHT, TRUE, angle_h);
float_t tmp_angle_v = ffr_draw_rounded_get_vertex_angle_by_border_model(border_model, FRR_VERTEXT_TYPE_BOTTOM_REIGHT, FALSE, angle_v);
ffr_draw_arc_point_list(&image_info, c, v_x2, v_y2, x2, y2, tmp_angle_h, tmp_angle_v, radius, FRR_VERTEXT_TYPE_BOTTOM_REIGHT,
ffr_draw_arc_point_list(c, v_x2, v_y2, x2, y2, tmp_angle_h, tmp_angle_v, radius, FRR_VERTEXT_TYPE_BOTTOM_REIGHT,
color, &tmp_point_list_45, &point_list_45, FALSE); // 右下角
}
canvas_set_stroke_color(c, color);
if (mid_lenght_v != 0 || radius_tl != 0 || radius_bl != 0 || radius_tr != 0 || radius_br != 0) {
uint32_t tmp_y1 = v_y1;
uint32_t tmp_y2 = v_y1;
@ -1330,9 +988,16 @@ static ret_t ffr_draw_stroke_rounded_rect(canvas_t* c, const rect_t* r, const co
TKMEM_FREE(point_pix_cache_list);
point_pix_cache_list = NULL;
}
} else
#endif // WITH_NANOVG_GPU
{
}
static ret_t ffr_draw_stroke_rounded_rect(canvas_t* c, const rect_t* r, color_t color, uint32_t radius_tl, uint32_t radius_tr, uint32_t radius_bl, uint32_t radius_br,
uint32_t border_width, int32_t border_model) {
lcd_type_t lcd_type = lcd_get_curr_lcd_type(c->lcd);
bool_t is_cpu_lcd = lcd_type != LCD_VGCANVAS && lcd_type != LCD_REGISTER;
uint32_t radius = radius_tl != 0 ? radius_tl : (radius_tr != 0 ? radius_tr : (radius_bl != 0 ? radius_bl : radius_br));
if (is_cpu_lcd && border_width == 1 && radius != 0 && ffr_draw_rounded_radius_equal(radius_tl, radius_tr, radius_bl, radius_br)) {
ffr_draw_rounded_rect_draw_stroke_with_canvas(c, r, color, radius, radius_tl, radius_tr, radius_bl, radius_br, border_width, border_model);
} else {
vgcanvas_t* vg = canvas_get_vgcanvas(c);
if (radius != 0 && vg != NULL) {
frr_draw_info_t draw_infos[FRR_VERTEXT_TYPE_COUNT] = {0};
@ -1346,16 +1011,18 @@ static ret_t ffr_draw_stroke_rounded_rect(canvas_t* c, const rect_t* r, const co
return RET_OK;
}
static inline ret_t ffr_draw_fill_rounded_rect_ex(canvas_t* c, const rect_t* r, const rect_t* bg_r,
static ret_t ffr_draw_fill_rounded_rect_ex(canvas_t* c, const rect_t* r, const rect_t* bg_r,
const color_t* color, uint32_t radius_tl, uint32_t radius_tr,
uint32_t radius_bl, uint32_t radius_br) {
color_t tc;
uint32_t radius = 0;
xy_t x = r->x + c->ox;
xy_t y = r->y + c->oy;
xy_t x2 = x + r->w - 1;
xy_t y2 = y + r->h - 1;
color_t tc = *color;
return_value_if_fail(c != NULL && r != NULL && color != NULL, RET_BAD_PARAMS);
tc = *color;
if (x > c->clip_right || x2 < c->clip_left ||
y > c->clip_bottom || y2 < c->clip_top) {
return RET_OK;
@ -1373,19 +1040,20 @@ static inline ret_t ffr_draw_fill_rounded_rect_ex(canvas_t* c, const rect_t* r,
}
tc.rgba.a = tc.rgba.a * c->global_alpha / 0xff;
return ffr_draw_fill_rounded_rect(c, r, &tc, radius_tl, radius_tr, radius_bl, radius_br);
return ffr_draw_fill_rounded_rect(c, r, tc, radius_tl, radius_tr, radius_bl, radius_br);
}
static inline ret_t ffr_draw_stroke_rounded_rect_ex(canvas_t* c, const rect_t* r, const rect_t* bg_r,
static ret_t ffr_draw_stroke_rounded_rect_ex(canvas_t* c, const rect_t* r, const rect_t* bg_r,
const color_t* color, uint32_t radius_tl, uint32_t radius_tr,
uint32_t radius_bl, uint32_t radius_br, uint32_t border_width, int32_t border_model) {
color_t tc;
uint32_t radius = 0;
xy_t x = r->x + c->ox;
xy_t y = r->y + c->oy;
xy_t x2 = x + r->w - 1;
xy_t y2 = y + r->h - 1;
color_t tc = *color;
return_value_if_fail(c != NULL && r != NULL && color != NULL, RET_BAD_PARAMS);
tc = *color;
if (x > c->clip_right || x2 < c->clip_left ||
y > c->clip_bottom || y2 < c->clip_top || border_model == BORDER_NONE) {
return RET_OK;
@ -1406,5 +1074,6 @@ static inline ret_t ffr_draw_stroke_rounded_rect_ex(canvas_t* c, const rect_t* r
if (border_model == (BORDER_LEFT | BORDER_RIGHT | BORDER_TOP | BORDER_BOTTOM)) {
border_model = BORDER_ALL;
}
return ffr_draw_stroke_rounded_rect(c, r, &tc, radius_tl, radius_tr, radius_bl, radius_br, border_width, border_model);
return ffr_draw_stroke_rounded_rect(c, r, tc, radius_tl, radius_tr, radius_bl, radius_br, border_width, border_model);
}

57
tests/lcd_test.cc Normal file
View File

@ -0,0 +1,57 @@
#include "base/lcd.h"
#include "tkc/utils.h"
#include "gtest/gtest.h"
static rect_t s_dirty_rect;
static int32_t s_canvas_ptr = 0;
static uint32_t s_line_length = 0;
static ret_t lcd_log_set_line_length(lcd_t* lcd, uint32_t line_length) {
s_line_length = line_length;
return RET_OK;
}
static ret_t lcd_log_set_canvas(lcd_t* lcd, canvas_t* c) {
s_canvas_ptr = tk_pointer_to_int(c);
return RET_OK;
}
static ret_t lcd_log_begin_frame(lcd_t* lcd, const rect_t* dirty_rect) {
s_dirty_rect.x = dirty_rect->x;
s_dirty_rect.y = dirty_rect->y;
s_dirty_rect.w = dirty_rect->w;
s_dirty_rect.h = dirty_rect->h;
return RET_OK;
}
TEST(lcd, base) {
rect_t r;
rect_t r1;
lcd_t lcd;
memset(&lcd, 0x0, sizeof(lcd_t));
r = rect_init(100, 100, 200, 200);
lcd.w = 800;
lcd.h = 480;
lcd.type = LCD_COMPOSITOR;
lcd.set_canvas = lcd_log_set_canvas;
lcd.begin_frame = lcd_log_begin_frame;
lcd.set_line_length = lcd_log_set_line_length;
ASSERT_EQ(lcd_is_compositor(&lcd) == TRUE, true);
ASSERT_EQ(lcd_get_curr_lcd_type(&lcd) == LCD_COMPOSITOR, true);
ASSERT_EQ(lcd_set_line_length(&lcd, 100), RET_OK);
ASSERT_EQ(s_line_length, 100);
ASSERT_EQ(lcd_set_canvas(&lcd, (canvas_t*)tk_pointer_from_int(0xee)), RET_OK);
ASSERT_EQ(s_canvas_ptr, 0xee);
ASSERT_EQ(lcd_begin_frame(&lcd, &r, LCD_DRAW_OFFLINE), RET_OK);
ASSERT_EQ(lcd_get_dirty_rect(&lcd, &r1), RET_OK);
ASSERT_EQ(s_dirty_rect.x, r1.x);
ASSERT_EQ(s_dirty_rect.y, r1.y);
ASSERT_EQ(s_dirty_rect.w, r1.w);
ASSERT_EQ(s_dirty_rect.h, r1.h);
}