mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-21 06:53:01 +08:00
radius mask: left side works
This commit is contained in:
parent
8d7c9315cb
commit
aa092bc353
@ -108,7 +108,7 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s
|
|||||||
|
|
||||||
lv_mask_radius_param_t param1;
|
lv_mask_radius_param_t param1;
|
||||||
lv_area_copy(¶m1.rect, coords);
|
lv_area_copy(¶m1.rect, coords);
|
||||||
param1.radius = 8;
|
param1.radius = 20;
|
||||||
|
|
||||||
|
|
||||||
// line_mask_param1.origo.x = 0;
|
// line_mask_param1.origo.x = 0;
|
||||||
|
@ -179,11 +179,107 @@ void lv_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_co
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 * param)
|
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)
|
||||||
{
|
{
|
||||||
|
int32_t k = abs_x - p->rect.x1; /*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);
|
||||||
|
abs_x -= p->rect.x1;
|
||||||
|
abs_y -= p->rect.y1;
|
||||||
|
|
||||||
|
uint32_t r2 = p->radius * p->radius;
|
||||||
|
|
||||||
|
|
||||||
|
/*Handle upper corner area*/
|
||||||
|
if(abs_y < p->radius || abs_y > h - p->radius) {
|
||||||
|
/* y = 0 should mean the top of the circle */
|
||||||
|
lv_coord_t y;
|
||||||
|
if(abs_y < p->radius) {
|
||||||
|
y = p->radius - abs_y;
|
||||||
|
} else {
|
||||||
|
y = p->radius - (h - abs_y);
|
||||||
|
}
|
||||||
|
/* Get the x intersection points for `abs_y` and `abs_y+1`
|
||||||
|
* Use the circle's equation x = sqrt(r^2 - y^2) */
|
||||||
|
lv_sqrt_res_t x0;
|
||||||
|
lv_sqrt(r2 - (y * y), &x0);
|
||||||
|
|
||||||
|
lv_sqrt_res_t x1;
|
||||||
|
lv_sqrt(r2 - ((y-1) * (y-1)), &x1);
|
||||||
|
|
||||||
|
printf("y:%d, x0: %d.%02d, x1: %d.%02d\n", y, x0.i, x0.f * 100 / 255, x1.i, x1.f * 100 / 255);
|
||||||
|
|
||||||
|
/*If the two x intersections are on the same x then just get average of the fractionals*/
|
||||||
|
if(x0.i == x1.i) {
|
||||||
|
lv_opa_t m = (x0.f + x1.f) >> 1;
|
||||||
|
k += p->radius - x0.i - 1;
|
||||||
|
mask_buf[k] = m; /*Left corner*/
|
||||||
|
|
||||||
|
memset(&mask_buf[0], 0x00, k);
|
||||||
|
|
||||||
|
}
|
||||||
|
/* If x1 is on the next round coordinate (e.g. x0: 3.5, x1:4.0)
|
||||||
|
* then treat x1 as x1: 3.99 to handle them as they were on the same pixel*/
|
||||||
|
else if(x0.i == x1.i - 1 && x1.f == 0) {
|
||||||
|
x1.f = 0xFF;
|
||||||
|
lv_opa_t m = (x0.f + x1.f) >> 1;
|
||||||
|
k += p->radius - x0.i - 1;
|
||||||
|
mask_buf[k] = m;
|
||||||
|
|
||||||
|
memset(&mask_buf[0], 0x00, k);
|
||||||
|
}
|
||||||
|
/*Multiple pixels are affected. Get y intersection of the pixels*/
|
||||||
|
else {
|
||||||
|
k += p->radius - (x0.i + 1);
|
||||||
|
uint32_t i = x0.i + 1;
|
||||||
|
lv_opa_t m;
|
||||||
|
lv_sqrt_res_t y_prev;
|
||||||
|
lv_sqrt_res_t y_next;
|
||||||
|
|
||||||
|
lv_sqrt(r2 - (x0.i * x0.i), &y_prev);
|
||||||
|
|
||||||
|
if(y_prev.f == 0) {
|
||||||
|
y_prev.i--;
|
||||||
|
y_prev.f = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*The first y intersection is special as it might be in the previous line*/
|
||||||
|
if(y_prev.i >= y) {
|
||||||
|
lv_sqrt(r2 - (i * i), &y_next);
|
||||||
|
printf("x_first: %d, y_inters:%d.%02d\n", i, y_next.i, y_next.f * 100 / 255);
|
||||||
|
|
||||||
|
m = 255 - (((255-x0.f) * (255 - y_next.f)) >> 9);
|
||||||
|
mask_buf[k] = m;
|
||||||
|
k--;
|
||||||
|
y_prev.f = y_next.f;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Set all points which are crossed by the circle*/
|
||||||
|
for(; i <= x1.i; i++) {
|
||||||
|
lv_sqrt(r2 - (i * i), &y_next);
|
||||||
|
|
||||||
|
printf("x: %d, y_inters:%d.%02d\n", i, y_next.i, y_next.f * 100 / 255);
|
||||||
|
|
||||||
|
m = (y_prev.f + y_next.f) >> 1;
|
||||||
|
mask_buf[k] = m;
|
||||||
|
k--;
|
||||||
|
y_prev.f = y_next.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*If the last pixel was left in its middle therefore
|
||||||
|
* the circle still has parts on the next one*/
|
||||||
|
if(y_prev.f) {
|
||||||
|
m = (y_prev.f * x1.f) >> 9;
|
||||||
|
mask_buf[k] = m;
|
||||||
|
k--;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&mask_buf[0], 0x00, k+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +61,9 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
lv_area_t rect;
|
lv_area_t rect;
|
||||||
lv_coord_t radius;
|
lv_coord_t radius;
|
||||||
|
|
||||||
|
/* Invert the mask. The default is: Keep the are inside.*/
|
||||||
|
uint8_t inv:1;
|
||||||
}lv_mask_radius_param_t;
|
}lv_mask_radius_param_t;
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "lv_math.h"
|
#include "lv_math.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
@ -99,12 +100,17 @@ int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3)
|
|||||||
|
|
||||||
void lv_sqrt(uint32_t x, lv_sqrt_res_t * q)
|
void lv_sqrt(uint32_t x, lv_sqrt_res_t * q)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Source:
|
||||||
|
* http://web.archive.org/web/20080303101624/http://c.snippets.org/snip_lister.php?fname=isqrt.c
|
||||||
|
* https://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2
|
||||||
|
*/
|
||||||
|
|
||||||
uint32_t a = 0L; /* accumulator */
|
uint32_t a = 0L; /* accumulator */
|
||||||
uint32_t r = 0L; /* remainder */
|
uint32_t r = 0L; /* remainder */
|
||||||
uint32_t e = 0L; /* trial product */
|
uint32_t e = 0L; /* trial product */
|
||||||
|
|
||||||
int i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < BITSPERLONG / 2 + 8; i++) {
|
for (i = 0; i < BITSPERLONG / 2 + 8; i++) {
|
||||||
r = (r << 2) + TOP2BITS(x); x <<= 2;
|
r = (r << 2) + TOP2BITS(x); x <<= 2;
|
||||||
a <<= 1;
|
a <<= 1;
|
||||||
@ -115,7 +121,8 @@ void lv_sqrt(uint32_t x, lv_sqrt_res_t * q)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(q, &a, sizeof(lv_sqrt_res_t));
|
q->f = a & 0xFF;
|
||||||
|
q->i = a >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
|
@ -33,8 +33,8 @@ extern "C" {
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t f:8;
|
uint16_t i;
|
||||||
uint32_t i:16;
|
uint16_t f;
|
||||||
}lv_sqrt_res_t;
|
}lv_sqrt_res_t;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user