1
0
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:
Gabor Kiss-Vamosi 2019-08-14 22:09:56 +02:00
parent 8d7c9315cb
commit aa092bc353
5 changed files with 113 additions and 7 deletions

View File

@ -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_area_copy(&param1.rect, coords);
param1.radius = 8;
param1.radius = 20;
// line_mask_param1.origo.x = 0;

View File

@ -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;
}
}

View File

@ -61,6 +61,9 @@ typedef struct {
typedef struct {
lv_area_t rect;
lv_coord_t radius;
/* Invert the mask. The default is: Keep the are inside.*/
uint8_t inv:1;
}lv_mask_radius_param_t;
/**********************

View File

@ -9,6 +9,7 @@
#include "lv_math.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/*********************
* 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)
{
/*
* 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 r = 0L; /* remainder */
uint32_t e = 0L; /* trial product */
int i;
uint32_t i;
for (i = 0; i < BITSPERLONG / 2 + 8; i++) {
r = (r << 2) + TOP2BITS(x); x <<= 2;
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;
}
/**********************

View File

@ -33,8 +33,8 @@ extern "C" {
**********************/
typedef struct {
uint32_t f:8;
uint32_t i:16;
uint16_t i;
uint16_t f;
}lv_sqrt_res_t;