1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-21 06:53:01 +08:00

add real draw functions

This commit is contained in:
Gabor Kiss-Vamosi 2019-08-21 15:44:35 +02:00
parent 82e3ee3e76
commit 1b5b2bfb4f
9 changed files with 623 additions and 826 deletions

View File

@ -126,7 +126,7 @@ void lv_style_init(void)
lv_style_pretty.text.color = lv_color_make(0x20, 0x20, 0x20);
lv_style_pretty.image.color = lv_color_make(0x20, 0x20, 0x20);
lv_style_pretty.line.color = lv_color_make(0x20, 0x20, 0x20);
lv_style_pretty.body.main_color = LV_COLOR_RED;
lv_style_pretty.body.main_color = LV_COLOR_WHITE;
lv_style_pretty.body.grad_color = LV_COLOR_SILVER;
lv_style_pretty.body.radius = LV_DPI / 15;
lv_style_pretty.body.border.color = lv_color_make(0x40, 0x40, 0x40);

79
src/lv_draw/lv_blend.c Normal file
View File

@ -0,0 +1,79 @@
/**
* @file lv_blend.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_blend.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_blend_color(lv_color_t * dest_buf, lv_img_cf_t dest_cf, lv_coord_t len,
lv_color_t color, lv_img_cf_t src_cf,
lv_opa_t * mask, lv_mask_res_t mask_res, lv_opa_t opa, lv_blend_mode_t mode)
{
if(opa < LV_OPA_MIN) return;
if(mask_res == LV_MASK_RES_FULL_TRANSP) return;
lv_coord_t i;
if(dest_cf == LV_IMG_CF_TRUE_COLOR && src_cf == LV_IMG_CF_TRUE_COLOR) {
/*Simple fill (maybe with opacity), no masking*/
if(mask_res == LV_MASK_RES_FULL_COVER) {
if(opa > LV_OPA_MAX) {
for(i = 0; i < len; i++) {
dest_buf[i].full = color.full;
}
}
else {
for(i = 0; i < len; i++) {
dest_buf[i] = lv_color_mix(color, dest_buf[i], opa);
}
}
}
/*Masked*/
else {
/*Only the mask matters*/
if(opa > LV_OPA_MAX) {
for(i = 0; i < len; i++) {
dest_buf[i] = lv_color_mix(color, dest_buf[i], mask[i]);
}
} else {
for(i = 0; i < len; i++) {
if(mask[i] > LV_OPA_MAX) {
dest_buf[i] = lv_color_mix(color, dest_buf[i], opa);
} else {
dest_buf[i] = lv_color_mix(color, dest_buf[i], (mask[i] * opa) >> 8);
}
}
}
}
}
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@ -15,6 +15,8 @@ extern "C" {
*********************/
#include "../lv_misc/lv_color.h"
#include "../lv_misc/lv_area.h"
#include "lv_img_decoder.h"
#include "lv_mask.h"
/*********************
* DEFINES
@ -26,12 +28,15 @@ extern "C" {
typedef enum {
LV_BLIT_MODE_NORMAL,
LV_BLIT_MODE_ADDITIVE,
}lv_blit_mode_t;
}lv_blend_mode_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_blit_color(lv_color_t * dest_buf, lv_color_t * bg_buf, lv_coord_t len, lv_color_t color, lv_blit_mode_t mode);
void lv_blend_color(lv_color_t * dest_buf, lv_img_cf_t dest_cf, lv_coord_t len,
lv_color_t color, lv_img_cf_t src_cf,
lv_opa_t * mask, lv_mask_res_t mask_res, lv_opa_t opa, lv_blend_mode_t mode);
/**********************
* MACROS

View File

@ -1,46 +0,0 @@
/**
* @file lv_blit.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_blit.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_blit_color(lv_color_t * dest_buf, lv_color_t * bg_buf, lv_coord_t len, lv_color_t color, lv_blit_mode_t mode)
{
uint32_t i;
for(i = 0; i < len; i++) {
dest_buf[i].full = color.full;
}
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@ -9,6 +9,8 @@
#include <stdio.h>
#include <stdbool.h>
#include "lv_draw.h"
#include "lv_mask.h"
#include "lv_blend.h"
#include "../lv_core/lv_refr.h"
#include "../lv_misc/lv_math.h"
@ -20,111 +22,16 @@
* TYPEDEFS
**********************/
/*
* 8192
8193
8196
8201
8208
8217
8228
8241
8256
8273
8291
8312
8335
8359
8386
8414
8444
8476
8510
8545
8583
8622
8662
8705
8749
8795
8842
8891
8942
8994
9047
9102
9159
9217
9276
9337
9399
9462
9527
9593
9660
9729
9798
9869
9941
10014
10088
10164
10240
10317
10396
10475
10555
10636
10718
10801
10885
10970
11056
11142
11229
11317
11406
11495
11585
*
*
* */
typedef struct
{
lv_point_t p1;
lv_point_t p2;
lv_point_t p_act;
lv_coord_t dx;
lv_coord_t sx; /*-1: x1 < x2; 1: x2 >= x1*/
lv_coord_t dy;
lv_coord_t sy; /*-1: y1 < y2; 1: y2 >= y1*/
lv_coord_t err;
lv_coord_t e2;
bool hor; /*Rather horizontal or vertical*/
} line_draw_t;
typedef struct
{
lv_coord_t width;
lv_coord_t width_1;
lv_coord_t width_half;
} line_width_t;
/**********************
* STATIC PROTOTYPES
**********************/
static void line_draw_hor(line_draw_t * main_line, const lv_area_t * mask, const lv_style_t * style,
lv_opa_t opa_scale);
static void line_draw_ver(line_draw_t * main_line, const lv_area_t * mask, const lv_style_t * style,
lv_opa_t opa_scale);
static void line_draw_skew(line_draw_t * main_line, bool dir_ori, const lv_area_t * mask, const lv_style_t * style,
lv_opa_t opa_scale);
static void line_init(line_draw_t * line, const lv_point_t * p1, const lv_point_t * p2);
static bool line_next(line_draw_t * line);
static bool line_next_y(line_draw_t * line);
static bool line_next_x(line_draw_t * line);
static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
const lv_style_t * style, lv_opa_t opa_scale);
static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
const lv_style_t * style, lv_opa_t opa_scale);
static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
const lv_style_t * style, lv_opa_t opa_scale);
/**********************
* STATIC VARIABLES
@ -146,563 +53,285 @@ static bool line_next_x(line_draw_t * line);
* @param style pointer to a line's style
* @param opa_scale scale down all opacities by the factor
*/
void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * mask,
const lv_style_t * style, lv_opa_t opa_scale)
void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
const lv_style_t * style, lv_opa_t opa_scale)
{
if(style->line.width == 0) return;
if(point1->x == point2->x && point1->y == point2->y) return;
/*Return if the points are out of the mask*/
if(point1->x < mask->x1 - style->line.width && point2->x < mask->x1 - style->line.width) return;
if(point1->x > mask->x2 + style->line.width && point2->x > mask->x2 + style->line.width) return;
if(point1->y < mask->y1 - style->line.width && point2->y < mask->y1 - style->line.width) return;
if(point1->y > mask->y2 + style->line.width && point2->y > mask->y2 + style->line.width) return;
line_draw_t main_line;
lv_point_t p1;
lv_point_t p2;
/*If the line if rather vertical then be sure y1 < y2 else x1 < x2*/
if(LV_MATH_ABS(point1->x - point2->x) > LV_MATH_ABS(point1->y - point2->y)) {
/*Steps less in y then x -> rather horizontal*/
if(point1->x < point2->x) {
p1.x = point1->x;
p1.y = point1->y;
p2.x = point2->x;
p2.y = point2->y;
} else {
p1.x = point2->x;
p1.y = point2->y;
p2.x = point1->x;
p2.y = point1->y;
}
} else {
/*Steps less in x then y -> rather vertical*/
if(point1->y < point2->y) {
p1.x = point1->x;
p1.y = point1->y;
p2.x = point2->x;
p2.y = point2->y;
} else {
p1.x = point2->x;
p1.y = point2->y;
p2.x = point1->x;
p2.y = point1->y;
}
}
line_init(&main_line, &p1, &p2);
/*Special case draw a horizontal line*/
if(main_line.p1.y == main_line.p2.y) {
line_draw_hor(&main_line, mask, style, opa_scale);
}
/*Special case draw a vertical line*/
else if(main_line.p1.x == main_line.p2.x) {
line_draw_ver(&main_line, mask, style, opa_scale);
}
/*Arbitrary skew line*/
else {
bool dir_ori = false;
#if LV_ANTIALIAS
bool aa = lv_disp_get_antialiasing(lv_refr_get_disp_refreshing());
if(aa) {
lv_point_t p_tmp;
if(main_line.hor) {
if(main_line.p1.y < main_line.p2.y) {
dir_ori = true;
p_tmp.x = main_line.p2.x;
p_tmp.y = main_line.p2.y - 1;
line_init(&main_line, &p1, &p_tmp);
main_line.sy = LV_MATH_ABS(main_line.sy); /*The sign can change if the line becomes horizontal*/
} else if(main_line.p1.y > main_line.p2.y) {
dir_ori = false;
p_tmp.x = main_line.p2.x;
p_tmp.y = main_line.p2.y + 1;
line_init(&main_line, &p1, &p_tmp);
main_line.sy = -LV_MATH_ABS(main_line.sy); /*The sign can change if the line becomes horizontal*/
}
} else {
if(main_line.p1.x < main_line.p2.x) {
dir_ori = true;
p_tmp.x = main_line.p2.x - 1;
p_tmp.y = main_line.p2.y;
line_init(&main_line, &p1, &p_tmp);
main_line.sx = LV_MATH_ABS(main_line.sx); /*The sign can change if the line becomes vertical*/
} else if(main_line.p1.x > main_line.p2.x) {
dir_ori = false;
p_tmp.x = main_line.p2.x + 1;
p_tmp.y = main_line.p2.y;
line_init(&main_line, &p1, &p_tmp);
main_line.sx = -LV_MATH_ABS(main_line.sx); /*The sign can change if the line becomes vertical*/
}
}
}
#endif
line_draw_skew(&main_line, dir_ori, mask, style, opa_scale);
}
if(point1->y == point2->y) draw_line_hor(point1, point2, clip, style, opa_scale);
else if(point1->x == point2->x) draw_line_ver(point1, point2, clip, style, opa_scale);
else draw_line_skew(point1, point2, clip, style, opa_scale);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void line_draw_hor(line_draw_t * main_line, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale)
static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
const lv_style_t * style, lv_opa_t opa_scale)
{
lv_coord_t width = style->line.width - 1;
lv_coord_t width_half = width >> 1;
lv_coord_t width_1 = width & 0x1;
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->line.opa : (uint16_t)((uint16_t)style->line.opa * opa_scale) >> 8;
lv_opa_t opa = style->body.opa;
lv_area_t act_area;
act_area.x1 = main_line->p1.x;
act_area.x2 = main_line->p2.x;
act_area.y1 = main_line->p1.y - width_half - width_1;
act_area.y2 = main_line->p2.y + width_half;
/*Keep the great y in p1*/
lv_point_t p1;
lv_point_t p2;
if(point1->y < point2->y) {
p1.y = point1->y;
p2.y = point2->y;
p1.x = point1->x;
p2.x = point2->x;
} else {
p1.y = point2->y;
p2.y = point1->y;
p1.x = point2->x;
p2.x = point1->x;
}
lv_area_t draw_area;
draw_area.x1 = LV_MATH_MIN(act_area.x1, act_area.x2);
draw_area.x2 = LV_MATH_MAX(act_area.x1, act_area.x2);
draw_area.y1 = LV_MATH_MIN(act_area.y1, act_area.y2);
draw_area.y2 = LV_MATH_MAX(act_area.y1, act_area.y2);
lv_draw_fill(&draw_area, mask, style->line.color, opa);
lv_coord_t xdiff = p2.x - p1.x;
lv_coord_t ydiff = p2.y - p1.y;
lv_coord_t w = style->line.width - 1;
lv_coord_t w_half0 = w >> 1;
lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/
lv_area_t draw_a;
draw_a.x1 = LV_MATH_MIN(p1.x, p2.x);
draw_a.x2 = LV_MATH_MAX(p1.x, p2.x);
draw_a.y1 = LV_MATH_MIN(p1.y, p2.y) - w_half1;
draw_a.y2 = LV_MATH_MAX(p1.y, p2.y) + w_half0;
/* Get the union of `coords` and `clip`*/
/* `clip` is already truncated to the `vdb` size
* in 'lv_refr_area' function */
bool union_ok = lv_area_intersect(&draw_a, &draw_a, clip);
/*If there are common part of `clip` and `vdb` then draw*/
if(union_ok == false) return;
lv_disp_t * disp = lv_refr_get_disp_refreshing();
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
/*Store the coordinates of the `draw_a` relative to the VDB */
lv_area_t draw_rel_a;
draw_rel_a.x1 = draw_a.x1 - vdb->area.x1;
draw_rel_a.y1 = draw_a.y1 - vdb->area.y1;
draw_rel_a.x2 = draw_a.x2 - vdb->area.x1;
draw_rel_a.y2 = draw_a.y2 - vdb->area.y1;
uint32_t vdb_width = lv_area_get_width(&vdb->area);
uint32_t draw_a_width = lv_area_get_width(&draw_rel_a);
/*Move the vdb_buf_tmp to the first row*/
lv_color_t * vdb_buf_tmp = vdb->buf_act;
vdb_buf_tmp += vdb_width * draw_rel_a.y1;
lv_opa_t mask_buf[LV_HOR_RES_MAX];
/*Draw line by line*/
lv_coord_t h;
lv_mask_res_t mask_res;
/*Fill the first row with 'color'*/
for(h = draw_rel_a.y1; h <= draw_rel_a.y2; h++) {
memset(mask_buf, LV_OPA_COVER, draw_a_width);
mask_res = lv_mask_apply(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width);
lv_blend_color(&vdb_buf_tmp[draw_rel_a.x1], LV_IMG_CF_TRUE_COLOR, draw_a_width,
style->line.color, LV_IMG_CF_TRUE_COLOR,
mask_buf, mask_res, style->body.opa, LV_BLIT_MODE_NORMAL);
vdb_buf_tmp += vdb_width;
}
}
static void line_draw_ver(line_draw_t * main_line, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale)
static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
const lv_style_t * style, lv_opa_t opa_scale)
{
lv_coord_t width = style->line.width - 1;
lv_coord_t width_half = width >> 1;
lv_coord_t width_1 = width & 0x1;
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->line.opa : (uint16_t)((uint16_t)style->line.opa * opa_scale) >> 8;
lv_opa_t opa = style->body.opa;
lv_area_t act_area;
act_area.x1 = main_line->p1.x - width_half;
act_area.x2 = main_line->p2.x + width_half + width_1;
act_area.y1 = main_line->p1.y;
act_area.y2 = main_line->p2.y;
/*Keep the great y in p1*/
lv_point_t p1;
lv_point_t p2;
if(point1->y < point2->y) {
p1.y = point1->y;
p2.y = point2->y;
p1.x = point1->x;
p2.x = point2->x;
} else {
p1.y = point2->y;
p2.y = point1->y;
p1.x = point2->x;
p2.x = point1->x;
}
lv_area_t draw_area;
draw_area.x1 = LV_MATH_MIN(act_area.x1, act_area.x2);
draw_area.x2 = LV_MATH_MAX(act_area.x1, act_area.x2);
draw_area.y1 = LV_MATH_MIN(act_area.y1, act_area.y2);
draw_area.y2 = LV_MATH_MAX(act_area.y1, act_area.y2);
lv_draw_fill(&draw_area, mask, style->line.color, opa);
lv_coord_t w = style->line.width - 1;
lv_coord_t w_half0 = w >> 1;
lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/
lv_area_t draw_a;
draw_a.x1 = LV_MATH_MIN(p1.x, p2.x) - w_half0;
draw_a.x2 = LV_MATH_MAX(p1.x, p2.x) + w_half1;
draw_a.y1 = LV_MATH_MIN(p1.y, p2.y);
draw_a.y2 = LV_MATH_MAX(p1.y, p2.y);
/* Get the union of `coords` and `clip`*/
/* `clip` is already truncated to the `vdb` size
* in 'lv_refr_area' function */
bool union_ok = lv_area_intersect(&draw_a, &draw_a, clip);
/*If there are common part of `clip` and `vdb` then draw*/
if(union_ok == false) return;
lv_disp_t * disp = lv_refr_get_disp_refreshing();
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
/*Store the coordinates of the `draw_a` relative to the VDB */
lv_area_t draw_rel_a;
draw_rel_a.x1 = draw_a.x1 - vdb->area.x1;
draw_rel_a.y1 = draw_a.y1 - vdb->area.y1;
draw_rel_a.x2 = draw_a.x2 - vdb->area.x1;
draw_rel_a.y2 = draw_a.y2 - vdb->area.y1;
uint32_t vdb_width = lv_area_get_width(&vdb->area);
uint32_t draw_a_width = lv_area_get_width(&draw_rel_a);
/*Move the vdb_buf_tmp to the first row*/
lv_color_t * vdb_buf_tmp = vdb->buf_act;
vdb_buf_tmp += vdb_width * draw_rel_a.y1;
lv_opa_t mask_buf[LV_HOR_RES_MAX];
/*Draw the background line by line*/
lv_coord_t h;
lv_mask_res_t mask_res;
/*Fill the first row with 'color'*/
for(h = draw_rel_a.y1; h <= draw_rel_a.y2; h++) {
memset(mask_buf, LV_OPA_COVER, draw_a_width);
mask_res = lv_mask_apply(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width);
lv_blend_color(&vdb_buf_tmp[draw_rel_a.x1], LV_IMG_CF_TRUE_COLOR, draw_a_width,
style->line.color, LV_IMG_CF_TRUE_COLOR,
mask_buf, mask_res, style->body.opa, LV_BLIT_MODE_NORMAL);
vdb_buf_tmp += vdb_width;
}
}
static void line_draw_skew(line_draw_t * main_line, bool dir_ori, const lv_area_t * mask, const lv_style_t * style,
lv_opa_t opa_scale)
static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
const lv_style_t * style, lv_opa_t opa_scale)
{
lv_opa_t opa = style->body.opa;
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->line.opa : (uint16_t)((uint16_t)style->line.opa * opa_scale) >> 8;
#if LV_ANTIALIAS
bool aa = lv_disp_get_antialiasing(lv_refr_get_disp_refreshing());
#endif
lv_point_t vect_main, vect_norm;
vect_main.x = main_line->p2.x - main_line->p1.x;
vect_main.y = main_line->p2.y - main_line->p1.y;
/*Keep the great y in p1*/
lv_point_t p1;
lv_point_t p2;
if(point1->y < point2->y) {
p1.y = point1->y;
p2.y = point2->y;
p1.x = point1->x;
p2.x = point2->x;
} else {
p1.y = point2->y;
p2.y = point1->y;
p1.x = point2->x;
p2.x = point1->x;
}
if(main_line->hor) {
if(main_line->p1.y < main_line->p2.y + dir_ori) {
vect_norm.x = -vect_main.y;
vect_norm.y = vect_main.x;
lv_coord_t xdiff = p2.x - p1.x;
lv_coord_t ydiff = p2.y - p1.y;
bool flat = LV_MATH_ABS(xdiff) > LV_MATH_ABS(ydiff) ? true : false;
static const uint8_t wcorr[] = {
128, 128, 128, 129, 129, 130, 130, 131,
132, 133, 134, 135, 137, 138, 140, 141,
143, 145, 147, 149, 151, 153, 155, 158,
160, 162, 165, 167, 170, 173, 175, 178,
181,
};
lv_coord_t w = style->line.width;
lv_coord_t wcorr_i = 0;
if(flat) wcorr_i = (LV_MATH_ABS(ydiff) << 5) / LV_MATH_ABS(xdiff);
else wcorr_i = (LV_MATH_ABS(xdiff) << 5) / LV_MATH_ABS(ydiff);
w = (w * wcorr[wcorr_i]) >> 7;
printf("w:%d\n", w);
lv_coord_t w_half0 = w >> 1;
lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/
lv_area_t draw_a;
draw_a.x1 = LV_MATH_MIN(p1.x, p2.x) - w;
draw_a.x2 = LV_MATH_MAX(p1.x, p2.x) + w;
draw_a.y1 = LV_MATH_MIN(p1.y, p2.y) - w;
draw_a.y2 = LV_MATH_MAX(p1.y, p2.y) + w;
/* Get the union of `coords` and `clip`*/
/* `clip` is already truncated to the `vdb` size
* in 'lv_refr_area' function */
bool union_ok = lv_area_intersect(&draw_a, &draw_a, clip);
/*If there are common part of `clip` and `vdb` then draw*/
if(union_ok == false) return;
lv_mask_param_t mask_left_param;
lv_mask_param_t mask_right_param;
lv_mask_param_t mask_top_param;
lv_mask_param_t mask_bottom_param;
if(flat) {
if(xdiff > 0) {
lv_mask_line_points_init(&mask_left_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, LV_LINE_MASK_SIDE_LEFT);
lv_mask_line_points_init(&mask_right_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, LV_LINE_MASK_SIDE_RIGHT);
} else {
vect_norm.x = vect_main.y;
vect_norm.y = -vect_main.x;
lv_mask_line_points_init(&mask_left_param, p1.x, p1.y + w_half0, p2.x, p2.y + w_half0, LV_LINE_MASK_SIDE_LEFT);
lv_mask_line_points_init(&mask_right_param, p1.x, p1.y - w_half1, p2.x, p2.y - w_half1, LV_LINE_MASK_SIDE_RIGHT);
}
} else {
if(main_line->p1.x < main_line->p2.x + dir_ori) {
vect_norm.x = vect_main.y;
vect_norm.y = -vect_main.x;
} else {
vect_norm.x = -vect_main.y;
vect_norm.y = vect_main.x;
}
lv_mask_line_points_init(&mask_left_param, p1.x + w_half0, p1.y, p2.x + w_half0, p2.y, LV_LINE_MASK_SIDE_LEFT);
lv_mask_line_points_init(&mask_right_param, p1.x - w_half1, p1.y, p2.x - w_half1, p2.y, LV_LINE_MASK_SIDE_RIGHT);
}
/*Use the normal vector for the endings*/
lv_mask_line_points_init(&mask_top_param, p1.x, p1.y, p1.x - ydiff, p1.y + xdiff, LV_LINE_MASK_SIDE_BOTTOM);
lv_mask_line_points_init(&mask_bottom_param, p2.x, p2.y,p2.x - ydiff, p2.y + xdiff, LV_LINE_MASK_SIDE_TOP);
int16_t mask_left_id = lv_mask_add(lv_mask_line, &mask_left_param, NULL);
int16_t mask_right_id = lv_mask_add(lv_mask_line, &mask_right_param, NULL);
int16_t mask_top_id = lv_mask_add(lv_mask_line, &mask_top_param, NULL);
int16_t mask_bottom_id = lv_mask_add(lv_mask_line, &mask_bottom_param, NULL);
lv_disp_t * disp = lv_refr_get_disp_refreshing();
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
/*Store the coordinates of the `draw_a` relative to the VDB */
lv_area_t draw_rel_a;
draw_rel_a.x1 = draw_a.x1 - vdb->area.x1;
draw_rel_a.y1 = draw_a.y1 - vdb->area.y1;
draw_rel_a.x2 = draw_a.x2 - vdb->area.x1;
draw_rel_a.y2 = draw_a.y2 - vdb->area.y1;
uint32_t vdb_width = lv_area_get_width(&vdb->area);
uint32_t draw_a_width = lv_area_get_width(&draw_rel_a);
/*Move the vdb_buf_tmp to the first row*/
lv_color_t * vdb_buf_tmp = vdb->buf_act;
vdb_buf_tmp += vdb_width * draw_rel_a.y1;
lv_opa_t mask_buf[LV_HOR_RES_MAX];
/*Draw the background line by line*/
lv_coord_t h;
lv_mask_res_t mask_res;
/*Fill the first row with 'color'*/
for(h = draw_rel_a.y1; h <= draw_rel_a.y2; h++) {
memset(mask_buf, LV_OPA_COVER, draw_a_width);
mask_res = lv_mask_apply(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width);
lv_blend_color(&vdb_buf_tmp[draw_rel_a.x1], LV_IMG_CF_TRUE_COLOR, draw_a_width,
style->line.color, LV_IMG_CF_TRUE_COLOR,
mask_buf, mask_res, style->body.opa, LV_BLIT_MODE_NORMAL);
vdb_buf_tmp += vdb_width;
}
/* In case of a short but tick line the perpendicular ending is longer then the real line.
* it would break the calculations so make the normal vector larger*/
vect_norm.x = vect_norm.x << 4;
vect_norm.y = vect_norm.y << 4;
lv_coord_t width;
width = style->line.width;
/* The pattern stores the points of the line ending. It has the good direction and length.
* The worth case is the 45° line where pattern can have 1.41 x `width` points*/
lv_coord_t pattern_size = width * 2;
lv_point_t * pattern = lv_draw_get_buf(pattern_size * sizeof(lv_point_t));
lv_coord_t i = 0;
/*Create a perpendicular pattern (a small line)*/
if(width != 0) {
line_draw_t pattern_line;
lv_point_t p0 = {0, 0};
line_init(&pattern_line, &p0, &vect_norm);
uint32_t width_sqr = width * width;
/* Run for a lot of times. Meanwhile the real width will be determined as well */
for(i = 0; i < (lv_coord_t)pattern_size - 1; i++) {
pattern[i].x = pattern_line.p_act.x;
pattern[i].y = pattern_line.p_act.y;
/*Finish the pattern line if it's length equal to the desired width (Use Pythagoras
* theorem)*/
uint32_t sqr = pattern_line.p_act.x * pattern_line.p_act.x + pattern_line.p_act.y * pattern_line.p_act.y;
if(sqr >= width_sqr) {
width = i;
#if LV_ANTIALIAS
if(aa) width--;
#endif
break;
}
line_next(&pattern_line);
}
}
#if LV_ANTIALIAS
lv_coord_t aa_last_corner;
lv_coord_t width_safe = width;
if(aa) {
if(width == 0) width_safe = 1;
aa_last_corner = 0;
}
#endif
lv_coord_t x_center_ofs = 0;
lv_coord_t y_center_ofs = 0;
if(width != 0) {
x_center_ofs = pattern[width - 1].x / 2;
y_center_ofs = pattern[width - 1].y / 2;
} else {
if(main_line->hor && main_line->p1.y >= main_line->p2.y + dir_ori) pattern[0].y--;
if(!main_line->hor && main_line->p1.x >= main_line->p2.x + dir_ori) pattern[0].x--;
}
/* Make the coordinates relative to the center */
for(i = 0; i < width; i++) {
pattern[i].x -= x_center_ofs;
pattern[i].y -= y_center_ofs;
#if LV_ANTIALIAS
if(aa) {
if(i != 0) {
if(main_line->hor) {
if(pattern[i - 1].x != pattern[i].x) {
lv_coord_t seg_w = pattern[i].y - pattern[aa_last_corner].y;
if(main_line->sy < 0) {
lv_draw_aa_ver_seg(main_line->p1.x + pattern[aa_last_corner].x - 1,
main_line->p1.y + pattern[aa_last_corner].y + seg_w + 1, seg_w, mask,
style->line.color, opa);
lv_draw_aa_ver_seg(main_line->p2.x + pattern[aa_last_corner].x + 1,
main_line->p2.y + pattern[aa_last_corner].y + seg_w + 1, -seg_w, mask,
style->line.color, opa);
} else {
lv_draw_aa_ver_seg(main_line->p1.x + pattern[aa_last_corner].x - 1,
main_line->p1.y + pattern[aa_last_corner].y, seg_w, mask,
style->line.color, opa);
lv_draw_aa_ver_seg(main_line->p2.x + pattern[aa_last_corner].x + 1,
main_line->p2.y + pattern[aa_last_corner].y, -seg_w, mask,
style->line.color, opa);
}
aa_last_corner = i;
}
} else {
if(pattern[i - 1].y != pattern[i].y) {
lv_coord_t seg_w = pattern[i].x - pattern[aa_last_corner].x;
if(main_line->sx < 0) {
lv_draw_aa_hor_seg(main_line->p1.x + pattern[aa_last_corner].x + seg_w + 1,
main_line->p1.y + pattern[aa_last_corner].y - 1, seg_w, mask,
style->line.color, opa);
lv_draw_aa_hor_seg(main_line->p2.x + pattern[aa_last_corner].x + seg_w + 1,
main_line->p2.y + pattern[aa_last_corner].y + 1, -seg_w, mask,
style->line.color, opa);
} else {
lv_draw_aa_hor_seg(main_line->p1.x + pattern[aa_last_corner].x,
main_line->p1.y + pattern[aa_last_corner].y - 1, seg_w, mask,
style->line.color, opa);
lv_draw_aa_hor_seg(main_line->p2.x + pattern[aa_last_corner].x,
main_line->p2.y + pattern[aa_last_corner].y + 1, -seg_w, mask,
style->line.color, opa);
}
aa_last_corner = i;
}
}
}
}
#endif
}
#if LV_ANTIALIAS
/*Add the last part of anti-aliasing for the perpendicular ending*/
if(width != 0 && aa) { /*Due to rounding error with very thin lines it looks ugly*/
if(main_line->hor) {
lv_coord_t seg_w = pattern[width_safe - 1].y - pattern[aa_last_corner].y;
if(main_line->sy < 0) {
lv_draw_aa_ver_seg(main_line->p1.x + pattern[aa_last_corner].x - 1,
main_line->p1.y + pattern[aa_last_corner].y + seg_w, seg_w + main_line->sy, mask,
style->line.color, opa);
lv_draw_aa_ver_seg(main_line->p2.x + pattern[aa_last_corner].x + 1,
main_line->p2.y + pattern[aa_last_corner].y + seg_w, -(seg_w + main_line->sy), mask,
style->line.color, opa);
} else {
lv_draw_aa_ver_seg(main_line->p1.x + pattern[aa_last_corner].x - 1,
main_line->p1.y + pattern[aa_last_corner].y, seg_w + main_line->sy, mask,
style->line.color, opa);
lv_draw_aa_ver_seg(main_line->p2.x + pattern[aa_last_corner].x + 1,
main_line->p2.y + pattern[aa_last_corner].y, -(seg_w + main_line->sy), mask,
style->line.color, opa);
}
} else {
lv_coord_t seg_w = pattern[width_safe - 1].x - pattern[aa_last_corner].x;
if(main_line->sx < 0) {
lv_draw_aa_hor_seg(main_line->p1.x + pattern[aa_last_corner].x + seg_w,
main_line->p1.y + pattern[aa_last_corner].y - 1, seg_w + main_line->sx, mask,
style->line.color, opa);
lv_draw_aa_hor_seg(main_line->p2.x + pattern[aa_last_corner].x + seg_w,
main_line->p2.y + pattern[aa_last_corner].y + 1, -(seg_w + main_line->sx), mask,
style->line.color, opa);
} else {
lv_draw_aa_hor_seg(main_line->p1.x + pattern[aa_last_corner].x,
main_line->p1.y + pattern[aa_last_corner].y - 1, seg_w + main_line->sx, mask,
style->line.color, opa);
lv_draw_aa_hor_seg(main_line->p2.x + pattern[aa_last_corner].x,
main_line->p2.y + pattern[aa_last_corner].y + 1, -(seg_w + main_line->sx), mask,
style->line.color, opa);
}
}
}
#endif
#if LV_ANTIALIAS
/*Shift the anti aliasing on the edges (-1, 1 or 0 (zero only in case width == 0))*/
lv_coord_t aa_shift1 = 0;
lv_coord_t aa_shift2 = 0;
if(aa) {
if(main_line->hor == false) {
if(main_line->sx < 0) {
aa_shift1 = -1;
aa_shift2 = width == 0 ? 0 : aa_shift1;
} else {
aa_shift2 = 1;
aa_shift1 = width == 0 ? 0 : aa_shift2;
}
} else {
if(main_line->sy < 0) {
aa_shift1 = -1;
aa_shift2 = width == 0 ? 0 : aa_shift1;
} else {
aa_shift2 = 1;
aa_shift1 = width == 0 ? 0 : aa_shift2;
}
}
}
#endif
volatile lv_point_t prev_p;
prev_p.x = main_line->p1.x;
prev_p.y = main_line->p1.y;
lv_area_t draw_area;
bool first_run = true;
if(main_line->hor) {
while(line_next_y(main_line)) {
for(i = 0; i < width; i++) {
draw_area.x1 = prev_p.x + pattern[i].x;
draw_area.y1 = prev_p.y + pattern[i].y;
draw_area.x2 = draw_area.x1 + main_line->p_act.x - prev_p.x - 1;
draw_area.y2 = draw_area.y1;
lv_draw_fill(&draw_area, mask, style->line.color, opa);
/* Fill the gaps
* When stepping in y one pixel remains empty on every corner (don't do this on the
* first segment ) */
if(i != 0 && pattern[i].x != pattern[i - 1].x && !first_run) {
lv_draw_px(draw_area.x1, draw_area.y1 - main_line->sy, mask, style->line.color, opa);
}
}
#if LV_ANTIALIAS
if(aa) {
lv_draw_aa_hor_seg(prev_p.x + pattern[0].x, prev_p.y + pattern[0].y - aa_shift1,
-(main_line->p_act.x - prev_p.x), mask, style->line.color, opa);
lv_draw_aa_hor_seg(prev_p.x + pattern[width_safe - 1].x,
prev_p.y + pattern[width_safe - 1].y + aa_shift2, main_line->p_act.x - prev_p.x,
mask, style->line.color, opa);
}
#endif
first_run = false;
prev_p.x = main_line->p_act.x;
prev_p.y = main_line->p_act.y;
}
for(i = 0; i < width; i++) {
draw_area.x1 = prev_p.x + pattern[i].x;
draw_area.y1 = prev_p.y + pattern[i].y;
draw_area.x2 = draw_area.x1 + main_line->p_act.x - prev_p.x;
draw_area.y2 = draw_area.y1;
lv_draw_fill(&draw_area, mask, style->line.color, opa);
/* Fill the gaps
* When stepping in y one pixel remains empty on every corner */
if(i != 0 && pattern[i].x != pattern[i - 1].x && !first_run) {
lv_draw_px(draw_area.x1, draw_area.y1 - main_line->sy, mask, style->line.color, opa);
}
}
#if LV_ANTIALIAS
if(aa) {
lv_draw_aa_hor_seg(prev_p.x + pattern[0].x, prev_p.y + pattern[0].y - aa_shift1,
-(main_line->p_act.x - prev_p.x + 1), mask, style->line.color, opa);
lv_draw_aa_hor_seg(prev_p.x + pattern[width_safe - 1].x, prev_p.y + pattern[width_safe - 1].y + aa_shift2,
main_line->p_act.x - prev_p.x + 1, mask, style->line.color, opa);
}
#endif
}
/*Rather a vertical line*/
else {
while(line_next_x(main_line)) {
for(i = 0; i < width; i++) {
draw_area.x1 = prev_p.x + pattern[i].x;
draw_area.y1 = prev_p.y + pattern[i].y;
draw_area.x2 = draw_area.x1;
draw_area.y2 = draw_area.y1 + main_line->p_act.y - prev_p.y - 1;
lv_draw_fill(&draw_area, mask, style->line.color, opa);
/* Fill the gaps
* When stepping in x one pixel remains empty on every corner (don't do this on the
* first segment ) */
if(i != 0 && pattern[i].y != pattern[i - 1].y && !first_run) {
lv_draw_px(draw_area.x1 - main_line->sx, draw_area.y1, mask, style->line.color, opa);
}
}
#if LV_ANTIALIAS
if(aa) {
lv_draw_aa_ver_seg(prev_p.x + pattern[0].x - aa_shift1, prev_p.y + pattern[0].y,
-(main_line->p_act.y - prev_p.y), mask, style->line.color, opa);
lv_draw_aa_ver_seg(prev_p.x + pattern[width_safe - 1].x + aa_shift2,
prev_p.y + pattern[width_safe - 1].y, main_line->p_act.y - prev_p.y, mask,
style->line.color, opa);
}
#endif
first_run = false;
prev_p.x = main_line->p_act.x;
prev_p.y = main_line->p_act.y;
}
/*Draw the last part*/
for(i = 0; i < width; i++) {
draw_area.x1 = prev_p.x + pattern[i].x;
draw_area.y1 = prev_p.y + pattern[i].y;
draw_area.x2 = draw_area.x1;
draw_area.y2 = draw_area.y1 + main_line->p_act.y - prev_p.y;
lv_draw_fill(&draw_area, mask, style->line.color, opa);
/* Fill the gaps
* When stepping in x one pixel remains empty on every corner */
if(i != 0 && pattern[i].y != pattern[i - 1].y && !first_run) {
lv_draw_px(draw_area.x1 - main_line->sx, draw_area.y1, mask, style->line.color, opa);
}
}
#if LV_ANTIALIAS
if(aa) {
lv_draw_aa_ver_seg(prev_p.x + pattern[0].x - aa_shift1, prev_p.y + pattern[0].y,
-(main_line->p_act.y - prev_p.y + 1), mask, style->line.color, opa);
lv_draw_aa_ver_seg(prev_p.x + pattern[width_safe - 1].x + aa_shift2, prev_p.y + pattern[width_safe - 1].y,
main_line->p_act.y - prev_p.y + 1, mask, style->line.color, opa);
}
#endif
}
}
static void line_init(line_draw_t * line, const lv_point_t * p1, const lv_point_t * p2)
{
line->p1.x = p1->x;
line->p1.y = p1->y;
line->p2.x = p2->x;
line->p2.y = p2->y;
line->dx = LV_MATH_ABS(line->p2.x - line->p1.x);
line->sx = line->p1.x < line->p2.x ? 1 : -1;
line->dy = LV_MATH_ABS(line->p2.y - line->p1.y);
line->sy = line->p1.y < line->p2.y ? 1 : -1;
line->err = (line->dx > line->dy ? line->dx : -line->dy) / 2;
line->e2 = 0;
line->hor = line->dx > line->dy ? true : false; /*Rather horizontal or vertical*/
line->p_act.x = line->p1.x;
line->p_act.y = line->p1.y;
}
static bool line_next(line_draw_t * line)
{
if(line->p_act.x == line->p2.x && line->p_act.y == line->p2.y) return false;
line->e2 = line->err;
if(line->e2 > -line->dx) {
line->err -= line->dy;
line->p_act.x += line->sx;
}
if(line->e2 < line->dy) {
line->err += line->dx;
line->p_act.y += line->sy;
}
return true;
}
/**
* Iterate until step one in y direction.
* @param line
* @return
*/
static bool line_next_y(line_draw_t * line)
{
lv_coord_t last_y = line->p_act.y;
do {
if(!line_next(line)) return false;
} while(last_y == line->p_act.y);
return true;
}
/**
* Iterate until step one in x direction.
* @param line
* @return
*/
static bool line_next_x(line_draw_t * line)
{
lv_coord_t last_x = line->p_act.x;
do {
if(!line_next(line)) return false;
} while(last_x == line->p_act.x);
return true;
lv_mask_remove_id(mask_left_id);
lv_mask_remove_id(mask_right_id);
lv_mask_remove_id(mask_top_id);
lv_mask_remove_id(mask_bottom_id);
}

View File

@ -6,11 +6,11 @@
/*********************
* INCLUDES
*********************/
#include <lvgl/src/lv_draw/lv_blend.h>
#include "lv_draw_rect.h"
#include "../lv_misc/lv_circ.h"
#include "../lv_misc/lv_math.h"
#include "../lv_core/lv_refr.h"
#include "lv_blit.h"
#include "lv_mask.h"
/*********************
@ -63,7 +63,6 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s
{
lv_opa_t opa = style->body.opa;
if(opa < LV_OPA_MIN) return;
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
lv_area_t draw_a;
@ -87,81 +86,97 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s
draw_rel_a.x2 = draw_a.x2 - vdb->area.x1;
draw_rel_a.y2 = draw_a.y2 - vdb->area.y1;
lv_color_t * vdb_buf_tmp = vdb->buf_act;
uint32_t vdb_width = lv_area_get_width(&vdb->area);
uint32_t draw_a_width = lv_area_get_width(&draw_rel_a);
/*Move the vdb_buf_tmp to the first row*/
lv_color_t * vdb_buf_tmp = vdb->buf_act;
vdb_buf_tmp += vdb_width * draw_rel_a.y1;
lv_color_t line_buf[LV_HOR_RES_MAX];
lv_opa_t mask_buf[LV_HOR_RES_MAX];
lv_mask_line_param_t line_mask_param1;
// lv_mask_line_points_init(&line_mask_param1, 100, 0, -50, 100, LV_LINE_MASK_SIDE_LEFT);
lv_mask_line_angle_init(&line_mask_param1, 0, 0, 60, LV_LINE_MASK_SIDE_LEFT);
lv_coord_t short_side = LV_MATH_MIN(lv_area_get_width(coords), lv_area_get_height(coords));
lv_coord_t rout = style->body.radius;
if(rout > short_side >> 1) rout = short_side >> 1;
lv_mask_line_param_t line_mask_param2;
lv_mask_line_points_init(&line_mask_param2, 100, 0, 0, 100, LV_LINE_MASK_SIDE_LEFT);
// lv_mask_line_angle_init(&line_mask_param2, 0, 0, 45, LV_LINE_MASK_SIDE_LEFT);
/*Create the outer mask*/
lv_mask_param_t mask_rout_param;
lv_mask_radius_init(&mask_rout_param, coords, rout, false);
int16_t mask_rout_id = lv_mask_add(lv_mask_radius, &mask_rout_param, NULL);
lv_area_t t;
t.x1 = 10;
t.y1 = 20;
t.x2 = 30;
t.y2 = 50;
lv_mask_param_t tp;
lv_mask_radius_init(&tp, &t, 5, false);
// int16_t tpid = lv_mask_add(lv_mask_radius, &tp, NULL);
lv_mask_radius_param_t param1;
lv_area_copy(&param1.rect, coords);
param1.radius = 50;
param1.inv = 0;
lv_coord_t w = 20;
lv_mask_radius_param_t param2;
lv_area_copy(&param2.rect, coords);
param2.rect.x1 += w;
param2.rect.x2 -= w;
param2.rect.y1 += w;
param2.rect.y2 -= w;
param2.radius = param1.radius - w;
param2.inv = 1;
lv_mask_angle_param_t pa;
lv_mask_angle_init(&pa, coords->x1 + lv_area_get_width(coords) / 2, coords->y1 + lv_area_get_height(coords) / 2, 60, 30);
// lv_mask_angle_init(&pa, 0, 0, 60, 30);
// line_mask_param1.origo.x = 0;
// line_mask_param1.origo.y = 0;
// line_mask_param1.steep = 300;
// line_mask_param1.flat = 1;
// line_mask_param1.side = LV_LINE_MASK_SIDE_RIGHT;
// line_mask_param1.inv = 0;
/*Fill with a color line-by-line*/
/*Draw the background line by line*/
lv_coord_t h;
lv_mask_res_t mask_res;
lv_color_t grad_color;
/*Fill the first row with 'color'*/
for(h = draw_rel_a.y1; h <= draw_rel_a.y2; h++) {
if(opa >= LV_OPA_MIN) {
for(h = draw_rel_a.y1; h <= draw_rel_a.y2; h++) {
if(style->body.main_color.full != style->body.grad_color.full) {
// 3
lv_blit_color(line_buf, &vdb_buf_tmp[draw_rel_a.x1], draw_a_width, style->body.main_color, LV_BLIT_MODE_NORMAL);
lv_opa_t mix = ((uint32_t)((uint32_t)h + vdb->area.y1-coords->y1)*255) / lv_area_get_height(coords);
grad_color = lv_color_mix(style->body.grad_color, style->body.main_color, mix);
if(style->body.main_color.full != style->body.grad_color.full) {
memset(mask_buf, LV_OPA_COVER, draw_a_width);
mask_res = lv_mask_apply(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width);
lv_blend_color(&vdb_buf_tmp[draw_rel_a.x1], LV_IMG_CF_TRUE_COLOR, draw_a_width,
grad_color, LV_IMG_CF_TRUE_COLOR,
mask_buf, mask_res, style->body.opa, LV_BLIT_MODE_NORMAL);
} else {
lv_blend_color(&vdb_buf_tmp[draw_rel_a.x1], LV_IMG_CF_TRUE_COLOR, draw_a_width,
style->body.main_color, LV_IMG_CF_TRUE_COLOR,
NULL, LV_MASK_RES_FULL_COVER, style->body.opa, LV_BLIT_MODE_NORMAL);
}
vdb_buf_tmp += vdb_width;
}
}
/*Draw the border if any*/
lv_coord_t border_width = style->body.border.width;
if(border_width) {
/*Move the vdb_buf_tmp to the first row*/
vdb_buf_tmp = vdb->buf_act;
vdb_buf_tmp += vdb_width * draw_rel_a.y1;
lv_mask_param_t mask_rsmall_param;
lv_coord_t rin = rout - border_width;
if(rin < 0) rin = 0;
lv_area_t area_small;
lv_area_copy(&area_small, coords);
area_small.x1 += border_width;
area_small.x2 -= border_width;
area_small.y1 += border_width;
area_small.y2 -= border_width;
lv_mask_radius_init(&mask_rsmall_param, &area_small, style->body.radius - border_width, true);
int16_t mask_rsmall_id = lv_mask_add(lv_mask_radius, &mask_rsmall_param, NULL);
/*Fill the first row with 'color'*/
for(h = draw_rel_a.y1; h <= draw_rel_a.y2; h++) {
memset(mask_buf, LV_OPA_COVER, draw_a_width);
// lv_mask_line(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width, &line_mask_param1);
// lv_mask_line(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width, &line_mask_param2);
mask_res = lv_mask_apply(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width);
//4
lv_mask_radius(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width, &param1);
lv_mask_radius(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width, &param2);
lv_blend_color(&vdb_buf_tmp[draw_rel_a.x1], LV_IMG_CF_TRUE_COLOR, draw_a_width,
style->body.border.color, LV_IMG_CF_TRUE_COLOR,
mask_buf, mask_res, style->body.border.opa, LV_BLIT_MODE_NORMAL);
lv_mask_angle(mask_buf, vdb->area.x1 + draw_rel_a.x1, vdb->area.y1 + h, draw_a_width, &pa);
//9
lv_mask_apply(&vdb_buf_tmp[draw_rel_a.x1], line_buf, mask_buf, draw_a_width);
// memcpy(&vdb_buf_tmp[draw_rel_a.x1], line_buf, draw_a_width * sizeof(lv_color_t));
} else {
//1
lv_blit_color(&vdb_buf_tmp[draw_rel_a.x1], &vdb_buf_tmp[draw_rel_a.x1], draw_a_width, style->body.main_color, LV_BLIT_MODE_NORMAL);
// memcpy(&vdb_buf_tmp[draw_rel_a.x1], line_buf, draw_a_width * sizeof(lv_color_t));
vdb_buf_tmp += vdb_width;
}
vdb_buf_tmp += vdb_width;
lv_mask_remove_id(mask_rsmall_id);
}
lv_mask_remove_id(mask_rout_id);
// lv_mask_remove_id(tpid);
}

View File

@ -8,26 +8,36 @@
*********************/
#include "lv_mask.h"
#include "../lv_misc/lv_math.h"
#include "../lv_misc/lv_log.h"
/*********************
* DEFINES
*********************/
#define LV_MASK_MAX_NUM 8
/**********************
* TYPEDEFS
**********************/
typedef struct
{
lv_mask_cb_t cb;
lv_mask_param_t param;
void * custom_id;
}lv_mask_saved_t;
/**********************
* STATIC PROTOTYPES
**********************/
static void line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_line_param_t * p);
static void line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_line_param_t * p);
static lv_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_line_param_t * p);
static lv_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_line_param_t * p);
static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new);
/**********************
* STATIC VARIABLES
**********************/
static lv_mask_saved_t mask_list[LV_MASK_MAX_NUM];
/**********************
* MACROS
@ -37,20 +47,64 @@ static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new);
* GLOBAL FUNCTIONS
**********************/
void lv_mask_apply(lv_color_t * dest_buf, lv_color_t * src_buf, lv_opa_t * mask_buf, lv_coord_t len)
int16_t lv_mask_add(lv_mask_cb_t mask_cb, lv_mask_param_t * param, void * custom_id)
{
lv_coord_t i;
for(i = 0; i < len; i++) {
// if(mask_buf[i] > LV_OPA_MAX) dest_buf[i] = src_buf[i];
// else if(mask_buf[i] > LV_OPA_MIN) dest_buf[i] = lv_color_mix(src_buf[i], dest_buf[i], mask_buf[i]);
dest_buf[i] = lv_color_mix(src_buf[i], dest_buf[i], mask_buf[i]);
/*Search a free entry*/
uint8_t i;
for(i = 0; i < LV_MASK_MAX_NUM; i++) {
if(mask_list[i].cb == NULL) break;
}
if(i >= LV_MASK_MAX_NUM) {
LV_LOG_WARN("lv_mask_add: no place to add the mask");
return LV_MASK_ID_INV;
}
mask_list[i].cb = mask_cb;
memcpy(&mask_list[i].param, param, sizeof(lv_mask_param_t));
mask_list[i].custom_id = custom_id;
return i;
}
void lv_mask_line_points_init(lv_mask_line_param_t * p, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_line_mask_side_t side)
lv_mask_res_t lv_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len)
{
bool changed = false;
lv_mask_res_t res;
uint8_t i;
for(i = 0; i < LV_MASK_MAX_NUM; i++) {
if(mask_list[i].cb) {
res = mask_list[i].cb(mask_buf, abs_x, abs_y, len, (void*)&mask_list[i].param);
if(res == LV_MASK_RES_FULL_TRANSP) return LV_MASK_RES_FULL_TRANSP;
else if(res == LV_MASK_RES_CHANGED) changed = true;
}
}
return changed ? LV_MASK_RES_CHANGED : LV_MASK_RES_FULL_COVER;
}
void lv_mask_remove_id(int16_t id)
{
if(id != LV_MASK_ID_INV) {
mask_list[id].cb = NULL;
}
}
void lv_mask_remove_custom(void * custom_id)
{
uint8_t i;
for(i = 0; i < LV_MASK_MAX_NUM; i++) {
if(mask_list[i].custom_id == custom_id) {
mask_list[i].cb = NULL;
}
}
}
void lv_mask_line_points_init(lv_mask_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_line_mask_side_t side)
{
lv_mask_line_param_t * p = &param->line;
memset(p, 0x00, sizeof(lv_mask_line_param_t));
if(p1y > p2y) {
@ -107,13 +161,13 @@ void lv_mask_line_points_init(lv_mask_line_param_t * p, lv_coord_t p1x, lv_coord
if(p->side == LV_LINE_MASK_SIDE_LEFT) p->inv = 0;
else if(p->side == LV_LINE_MASK_SIDE_RIGHT) p->inv = 1;
else if(p->side == LV_LINE_MASK_SIDE_TOP) {
if(p->steep > 0) p->inv = 0;
else p->inv = 1;
}
else if(p->side == LV_LINE_MASK_SIDE_BOTTOM) {
if(p->steep > 0) p->inv = 1;
else p->inv = 0;
}
else if(p->side == LV_LINE_MASK_SIDE_BOTTOM) {
if(p->steep > 0) p->inv = 0;
else p->inv = 1;
}
p->spx = p->steep >> 2;
if(p->steep < 0) p->spx = -p->spx;
@ -127,8 +181,11 @@ void lv_mask_line_points_init(lv_mask_line_param_t * p, lv_coord_t p1x, lv_coord
* @param deg right 0 deg, bottom: 90
* @param side
*/
void lv_mask_line_angle_init(lv_mask_line_param_t * p, lv_coord_t p1x, lv_coord_t p1y, int16_t deg, lv_line_mask_side_t side)
void lv_mask_line_angle_init(lv_mask_param_t * param, lv_coord_t p1x, lv_coord_t p1y, int16_t deg, lv_line_mask_side_t side)
{
lv_mask_angle_param_t * p = &param->angle;
/* Find an optimal degree.
* lv_mask_line_points_init will swap the points to keep the smaller y in p1
* Theoretically a line with `deg` or `deg+180` is the same only the points are swapped
@ -147,9 +204,9 @@ void lv_mask_line_angle_init(lv_mask_line_param_t * p, lv_coord_t p1x, lv_coord_
lv_mask_line_points_init(p, p1x, p1y, p2x, p2y, side);
}
void lv_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, void * param)
lv_mask_res_t lv_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_param_t * param)
{
lv_mask_line_param_t * p = (lv_mask_line_param_t *)param;
lv_mask_line_param_t * p = &param->line;
/*Make to points relative to the origo*/
abs_y -= p->origo.y;
@ -160,44 +217,48 @@ void lv_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_co
/*Horizontal*/
if(p->flat) {
/*Non sense: Can't be on the right/left of a horizontal line*/
if(p->side == LV_LINE_MASK_SIDE_LEFT || p->side == LV_LINE_MASK_SIDE_RIGHT) return;
else if(p->side == LV_LINE_MASK_SIDE_TOP && abs_y+1 < p->origo.y) return;
else if(p->side == LV_LINE_MASK_SIDE_BOTTOM && abs_y > p->origo.y) return;
if(p->side == LV_LINE_MASK_SIDE_LEFT || p->side == LV_LINE_MASK_SIDE_RIGHT) return LV_MASK_RES_FULL_COVER;
else if(p->side == LV_LINE_MASK_SIDE_TOP && abs_y+1 < p->origo.y) return LV_MASK_RES_FULL_COVER;
else if(p->side == LV_LINE_MASK_SIDE_BOTTOM && abs_y > p->origo.y) return LV_MASK_RES_FULL_COVER;
else {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
}
}
/*Vertical*/
else {
/*Non sense: Can't be on the top/bottom of a vertical line*/
if(p->side == LV_LINE_MASK_SIDE_TOP || p->side == LV_LINE_MASK_SIDE_BOTTOM) return;
else if(p->side == LV_LINE_MASK_SIDE_RIGHT && abs_x > 0) return;
if(p->side == LV_LINE_MASK_SIDE_TOP || p->side == LV_LINE_MASK_SIDE_BOTTOM) return LV_MASK_RES_FULL_COVER;
else if(p->side == LV_LINE_MASK_SIDE_RIGHT && abs_x > 0) return LV_MASK_RES_FULL_COVER;
else if(p->side == LV_LINE_MASK_SIDE_LEFT) {
if(abs_x + len < 0) return;
if(abs_x + len < 0) return LV_MASK_RES_FULL_COVER;
else {
int32_t k = - abs_x;
if(k < 0) k = 0;
if(k >= 0 && k < len) memset(&mask_buf[k], 0x00, len - k);
return;
return LV_MASK_RES_CHANGED;
}
}
else {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
}
}
}
lv_mask_res_t res;
if(p->flat) {
line_mask_flat(mask_buf, abs_x, abs_y, len, p);
res = line_mask_flat(mask_buf, abs_x, abs_y, len, p);
} else {
line_mask_steep(mask_buf, abs_x, abs_y, len, p);
res = line_mask_steep(mask_buf, abs_x, abs_y, len, p);
}
return res;
}
void lv_mask_angle_init(lv_mask_angle_param_t * p, lv_coord_t origo_x, lv_coord_t origo_y, lv_coord_t start_angle, lv_coord_t end_angle)
void lv_mask_angle_init(lv_mask_param_t * param, lv_coord_t origo_x, lv_coord_t origo_y, lv_coord_t start_angle, lv_coord_t end_angle)
{
lv_mask_angle_param_t * p = &param->line;
lv_line_mask_side_t start_side;
lv_line_mask_side_t end_side;
@ -224,13 +285,14 @@ void lv_mask_angle_init(lv_mask_angle_param_t * p, lv_coord_t origo_x, lv_coord_
}
}
lv_mask_line_angle_init(&p->start_line, origo_x, origo_y, start_angle, start_side);
lv_mask_line_angle_init(&p->end_line, origo_x, origo_y, end_angle, end_side);
lv_mask_line_angle_init((lv_mask_param_t*)&p->start_line, origo_x, origo_y, start_angle, start_side);
lv_mask_line_angle_init((lv_mask_param_t*)&p->end_line, origo_x, origo_y, end_angle, end_side);
}
void lv_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_angle_param_t * p)
lv_mask_res_t lv_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_param_t * param)
{
lv_mask_angle_param_t * p = &param->line;
// if(p->delta_deg <= 180) {
// if((p->start_angle <= 180 && abs_y >= p->origo.y) ||
// (p->start_angle >= 180 && abs_y <= p->origo.y)) {
@ -238,7 +300,7 @@ void lv_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_c
if(abs_y < p->origo.y) {
// memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_COVER;
}
@ -251,36 +313,68 @@ void lv_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_c
int32_t dist = (end_angle_first - start_angle_last) >> 1;
lv_mask_res_t res1 = LV_MASK_RES_FULL_COVER;
lv_mask_res_t res2 = LV_MASK_RES_FULL_COVER;
int32_t tmp = start_angle_last + dist - rel_x;
if(tmp > len) tmp = len;
if(tmp > 0) {
lv_mask_line(&mask_buf[0], abs_x, abs_y, tmp, &p->start_line);
res1 = lv_mask_line(&mask_buf[0], abs_x, abs_y, tmp, (lv_mask_param_t*)&p->start_line);
if(res1 == LV_MASK_RES_FULL_TRANSP) {
memset(&mask_buf[0], 0x00, tmp);
}
}
if(tmp > len) tmp = len;
if(tmp < 0) tmp = 0;
lv_mask_line(&mask_buf[tmp], abs_x+tmp, abs_y, len-tmp, &p->end_line);
res2 = lv_mask_line(&mask_buf[tmp], abs_x+tmp, abs_y, len-tmp, (lv_mask_param_t*)&p->end_line);
if(res2 == LV_MASK_RES_FULL_TRANSP) {
memset(&mask_buf[tmp], 0x00, len-tmp);
}
if(res1 == res2) return res1;
else return LV_MASK_RES_CHANGED;
}
void lv_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_radius_param_t * p)
void lv_mask_radius_init(lv_mask_param_t * param, lv_area_t * rect, lv_coord_t radius, bool inv)
{
lv_mask_radius_param_t * p = &param->radius;
lv_area_copy(&p->rect, rect);
p->radius = radius;
p->inv = inv ? 1 : 0;
}
lv_mask_res_t lv_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_param_t * param)
{
lv_mask_radius_param_t * p = &param->radius;
if(p->inv == 0) {
if(abs_y < p->rect.y1 || abs_y > p->rect.y2) {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
}
} else {
if(abs_y < p->rect.y1 || abs_y > p->rect.y2) {
return;
return LV_MASK_RES_FULL_COVER;
}
}
if((abs_x >= p->rect.x1 + p->radius && abs_x + len <= p->rect.x2 - p->radius) ||
(abs_y >= p->rect.y1 + p->radius && abs_y <= p->rect.y2 - p->radius+1)) {
if(p->inv == 0) return;
if(p->inv == 0) {
/*Remove the edges*/
int32_t last = p->rect.x1 - abs_x;
if(last > len) last = len;
if(last >= 0) {
memset(&mask_buf[0], 0x00, last);
}
int32_t first = p->rect.x2 - abs_x + 1;
if(first < len) {
memset(&mask_buf[first], 0x00, len-first);
}
return LV_MASK_RES_CHANGED;
}
else {
int32_t first = p->rect.x1 - abs_x;
if(first < 0) first = 0;
@ -292,12 +386,9 @@ void lv_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_
}
}
}
return;
return LV_MASK_RES_CHANGED;
}
int32_t k = p->rect.x1 -abs_x; /*First relevant coordinate on the of the mask*/
lv_coord_t w = lv_area_get_width(&p->rect);
lv_coord_t h = lv_area_get_height(&p->rect);
@ -446,18 +537,16 @@ void lv_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_
if(kr < len) memset(&mask_buf[kr], 0x00, len - kr);
}
}
return;
}
return LV_MASK_RES_CHANGED;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_line_param_t * p)
static lv_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_line_param_t * p)
{
lv_coord_t y_at_x;
@ -468,19 +557,17 @@ static void line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs
if(p->yx_steep > 0) {
if(y_at_x > abs_y) {
if(p->inv) {
return;
return LV_MASK_RES_FULL_COVER;
} else {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
}
}
} else {
if(y_at_x < abs_y) {
if(p->inv) {
return;
return LV_MASK_RES_FULL_COVER;
} else {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
}
}
}
@ -491,19 +578,17 @@ static void line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs
if(p->yx_steep > 0) {
if(y_at_x < abs_y) {
if(p->inv) {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
} else {
return;
return LV_MASK_RES_FULL_COVER;
}
}
} else {
if(y_at_x > abs_y) {
if(p->inv) {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
} else {
return;
return LV_MASK_RES_FULL_COVER;
}
}
}
@ -562,9 +647,11 @@ static void line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs
memset(&mask_buf[k], 0x00, len - k);
}
}
return LV_MASK_RES_CHANGED;
}
static void line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_line_param_t * p)
static lv_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_line_param_t * p)
{
int32_t k;
lv_coord_t x_at_y;
@ -574,10 +661,9 @@ static void line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t ab
if(p->xy_steep > 0) x_at_y++;
if(x_at_y < abs_x) {
if(p->inv) {
return;
return LV_MASK_RES_FULL_COVER;
} else {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
}
}
@ -586,10 +672,9 @@ static void line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t ab
x_at_y = (int32_t)((int32_t)p->xy_steep * (abs_y)) >> 10;
if(x_at_y > abs_x + len) {
if(p->inv) {
memset(mask_buf, 0x00, len);
return;
return LV_MASK_RES_FULL_TRANSP;
} else {
return;
return LV_MASK_RES_FULL_COVER;
}
}
@ -690,6 +775,8 @@ static void line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t ab
}
}
return LV_MASK_RES_CHANGED;
}
static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new)

View File

@ -20,10 +20,21 @@ extern "C" {
/*********************
* DEFINES
*********************/
#define LV_MASK_ID_INV (-1)
/**********************
* TYPEDEFS
**********************/
enum {
LV_MASK_RES_FULL_COVER,
LV_MASK_RES_FULL_TRANSP,
LV_MASK_RES_CHANGED,
};
typedef uint8_t lv_mask_res_t;
enum {
LV_LINE_MASK_SIDE_LEFT = 0,
LV_LINE_MASK_SIDE_RIGHT,
@ -36,13 +47,13 @@ typedef uint8_t lv_line_mask_side_t;
typedef struct {
lv_point_t origo;
/* X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/
lv_coord_t xy_steep;
int32_t xy_steep;
/* Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/
lv_coord_t yx_steep;
int32_t yx_steep;
/*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines */
lv_coord_t steep;
int32_t steep;
/*Steepness in 1 px in 0..255 range. Used only by flat lines. */
int32_t spx;
@ -68,7 +79,6 @@ typedef struct {
uint16_t delta_deg;
}lv_mask_angle_param_t;
typedef struct {
lv_area_t rect;
lv_coord_t radius;
@ -77,18 +87,36 @@ typedef struct {
uint8_t inv:1;
}lv_mask_radius_param_t;
typedef union {
lv_mask_line_param_t line;
lv_mask_radius_param_t radius;
lv_mask_angle_param_t angle;
}lv_mask_param_t;
typedef lv_mask_res_t (*lv_mask_cb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_param_t * p);
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_mask_apply(lv_color_t * dest_buf, lv_color_t * src_buf, lv_opa_t * mask_buf, lv_coord_t len);
void lv_mask_line_points_init(lv_mask_line_param_t * p, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_line_mask_side_t side);
void lv_mask_line_angle_init(lv_mask_line_param_t * p, lv_coord_t p1x, lv_coord_t p1y, int16_t deg, lv_line_mask_side_t side);
void lv_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, void * param);
int16_t lv_mask_add(lv_mask_cb_t mask_cb, lv_mask_param_t * param, void * custom_id);
void lv_mask_remove_id(int16_t id);
void lv_mask_remove_custom(void * custom_id);
lv_mask_res_t lv_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len);
void lv_mask_line_points_init(lv_mask_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_line_mask_side_t side);
void lv_mask_line_angle_init(lv_mask_param_t * param, lv_coord_t p1x, lv_coord_t p1y, int16_t deg, lv_line_mask_side_t side);
lv_mask_res_t lv_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_param_t * param);
void lv_mask_angle_init(lv_mask_angle_param_t * p, lv_coord_t origio_x, lv_coord_t origo_y, lv_coord_t start_angle, lv_coord_t end_angle);
void lv_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_angle_param_t * p);
void lv_mask_radius_init(lv_mask_param_t * param, lv_area_t * rect, lv_coord_t radius, bool inv);
lv_mask_res_t lv_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_param_t * param);
void lv_mask_angle_init(lv_mask_param_t * param, lv_coord_t origio_x, lv_coord_t origo_y, lv_coord_t start_angle, lv_coord_t end_angle);
lv_mask_res_t lv_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_mask_param_t * param);
/**********************
* MACROS

View File

@ -75,8 +75,8 @@ enum {
LV_OPA_COVER = 255,
};
#define LV_OPA_MIN 16 /*Opacities below this will be transparent*/
#define LV_OPA_MAX 251 /*Opacities above this will fully cover*/
#define LV_OPA_MIN 5 /*Opacities below this will be transparent*/
#define LV_OPA_MAX 250 /*Opacities above this will fully cover*/
#if LV_COLOR_DEPTH == 1
#define LV_COLOR_SIZE 8