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

calnvas: create draw function which uses lv_draw_... function

This commit is contained in:
Gabor Kiss-Vamosi 2019-06-02 20:35:33 +02:00
parent 23dc884f35
commit 33bb0d8004
8 changed files with 321 additions and 285 deletions

View File

@ -69,15 +69,20 @@ void lv_refr_init(void)
* Normally the redrawing is periodically executed in `lv_task_handler` but a long blocking process * Normally the redrawing is periodically executed in `lv_task_handler` but a long blocking process
* can prevent the call of `lv_task_handler`. In this case if the the GUI is updated in the process * can prevent the call of `lv_task_handler`. In this case if the the GUI is updated in the process
* (e.g. progress bar) this function can be called when the screen should be updated. * (e.g. progress bar) this function can be called when the screen should be updated.
* @param disp pointer to display to refresh. NULL to refresh all displays.
*/ */
void lv_refr_now(void) void lv_refr_now(lv_disp_t * disp)
{ {
if(disp) {
lv_disp_refr_task(disp->refr_task);
} else {
lv_disp_t * d; lv_disp_t * d;
d = lv_disp_get_next(NULL); d = lv_disp_get_next(NULL);
while(d) { while(d) {
lv_disp_refr_task(d->refr_task); lv_disp_refr_task(d->refr_task);
d = lv_disp_get_next(d); d = lv_disp_get_next(d);
} }
}
} }
/** /**
@ -138,6 +143,18 @@ lv_disp_t * lv_refr_get_disp_refreshing(void)
return disp_refr; return disp_refr;
} }
/**
* Set the display which is being refreshed.
* It shouldn1t be used directly by the user.
* It can be used to trick the drawing functions about there is an active display.
* @param the display being refreshed
*/
void lv_refr_set_disp_refreshing(lv_disp_t * disp)
{
disp_refr = disp;
}
/** /**
* Called periodically to handle the refreshing * Called periodically to handle the refreshing
* @param task pointer to the task itself * @param task pointer to the task itself

View File

@ -50,8 +50,9 @@ void lv_refr_init(void);
* Normally the redrawing is periodically executed in `lv_task_handler` but a long blocking process * Normally the redrawing is periodically executed in `lv_task_handler` but a long blocking process
* can prevent the call of `lv_task_handler`. In this case if the the GUI is updated in the process * can prevent the call of `lv_task_handler`. In this case if the the GUI is updated in the process
* (e.g. progress bar) this function can be called when the screen should be updated. * (e.g. progress bar) this function can be called when the screen should be updated.
* @param disp pointer to display to refresh. NULL to refresh all displays.
*/ */
void lv_refr_now(void); void lv_refr_now(lv_disp_t * disp);
/** /**
* Invalidate an area on display to redraw it * Invalidate an area on display to redraw it
@ -67,6 +68,14 @@ void lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p);
*/ */
lv_disp_t * lv_refr_get_disp_refreshing(void); lv_disp_t * lv_refr_get_disp_refreshing(void);
/**
* Set the display which is being refreshed.
* It shouldn1t be used directly by the user.
* It can be used to trick the drawing functions about there is an active display.
* @param the display being refreshed
*/
void lv_refr_set_disp_refreshing(lv_disp_t * disp);
/** /**
* Called periodically to handle the refreshing * Called periodically to handle the refreshing
* @param task pointer to the task itself * @param task pointer to the task itself

View File

@ -89,6 +89,7 @@ void lv_draw_aa_hor_seg(lv_coord_t x, lv_coord_t y, lv_coord_t length, const lv_
#include "lv_draw_img.h" #include "lv_draw_img.h"
#include "lv_draw_line.h" #include "lv_draw_line.h"
#include "lv_draw_triangle.h" #include "lv_draw_triangle.h"
#include "lv_draw_arc.h"
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -42,7 +42,7 @@ static uint8_t corr_value;
* @param points pointer to an array with 3 points * @param points pointer to an array with 3 points
* @param mask the triangle will be drawn only in this mask * @param mask the triangle will be drawn only in this mask
* @param style style for of the triangle * @param style style for of the triangle
* @param opa_scale scale down all opacities by the factor * @param opa_scale scale down all opacities by the factor (0..255)
*/ */
void lv_draw_triangle(const lv_point_t * points, const lv_area_t * mask, const lv_style_t * style, void lv_draw_triangle(const lv_point_t * points, const lv_area_t * mask, const lv_style_t * style,
lv_opa_t opa_scale) lv_opa_t opa_scale)
@ -89,10 +89,39 @@ void lv_draw_triangle(const lv_point_t * points, const lv_area_t * mask, const l
} }
} }
/**
* Draw a polygon from triangles. Only convex polygons are supported
* @param points an array of points
* @param point_cnt number of points
* @param mask polygon will be drawn only in this mask
* @param style style of the polygon
* @param opa_scale scale down all opacities by the factor (0..255)
*/
void lv_draw_polygon(const lv_point_t * points, uint32_t point_cnt, const lv_area_t * mask, const lv_style_t * style,
lv_opa_t opa_scale)
{
if(point_cnt < 3) return;
if(points == NULL) return;
uint32_t i;
lv_point_t tri[3];
tri[0].x = points[0].x;
tri[0].y = points[0].y;
for(i = 0; i < point_cnt - 1; i++) {
tri[1].x = points[i].x;
tri[1].y = points[i].y;
tri[2].x = points[i+1].x;
tri[2].y = points[i+1].y;
lv_draw_triangle(tri, mask, style, opa_scale);
}
}
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
void tri_draw_flat(const lv_point_t * points, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa) void tri_draw_flat(const lv_point_t * points, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa)
{ {
/*Return if the points are out of the mask*/ /*Return if the points are out of the mask*/

View File

@ -32,11 +32,23 @@ extern "C" {
* @param points pointer to an array with 3 points * @param points pointer to an array with 3 points
* @param mask the triangle will be drawn only in this mask * @param mask the triangle will be drawn only in this mask
* @param style style for of the triangle * @param style style for of the triangle
* @param opa_scale scale down all opacities by the factor * @param opa_scale scale down all opacities by the factor (0..255)
*/ */
void lv_draw_triangle(const lv_point_t * points, const lv_area_t * mask, const lv_style_t * style, void lv_draw_triangle(const lv_point_t * points, const lv_area_t * mask, const lv_style_t * style,
lv_opa_t opa_scale); lv_opa_t opa_scale);
/**
* Draw a polygon from triangles. Only convex polygons are supported
* @param points an array of points
* @param point_cnt number of points
* @param mask polygon will be drawn only in this mask
* @param style style of the polygon
* @param opa_scale scale down all opacities by the factor (0..255)
*/
void lv_draw_polygon(const lv_point_t * points, uint32_t point_cnt, const lv_area_t * mask, const lv_style_t * style,
lv_opa_t opa_scale);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/

View File

@ -40,6 +40,7 @@ extern "C" {
#define LV_COLOR_WHITE LV_COLOR_MAKE(0xFF, 0xFF, 0xFF) #define LV_COLOR_WHITE LV_COLOR_MAKE(0xFF, 0xFF, 0xFF)
#define LV_COLOR_SILVER LV_COLOR_MAKE(0xC0, 0xC0, 0xC0) #define LV_COLOR_SILVER LV_COLOR_MAKE(0xC0, 0xC0, 0xC0)
#define LV_COLOR_GRAY LV_COLOR_MAKE(0x80, 0x80, 0x80) #define LV_COLOR_GRAY LV_COLOR_MAKE(0x80, 0x80, 0x80)
#define LV_COLOR_LIGHT_GRAY LV_COLOR_MAKE(0xC0, 0xC0, 0xC0)
#define LV_COLOR_BLACK LV_COLOR_MAKE(0x00, 0x00, 0x00) #define LV_COLOR_BLACK LV_COLOR_MAKE(0x00, 0x00, 0x00)
#define LV_COLOR_RED LV_COLOR_MAKE(0xFF, 0x00, 0x00) #define LV_COLOR_RED LV_COLOR_MAKE(0xFF, 0x00, 0x00)
#define LV_COLOR_MAROON LV_COLOR_MAKE(0x80, 0x00, 0x00) #define LV_COLOR_MAROON LV_COLOR_MAKE(0x80, 0x00, 0x00)

View File

@ -9,7 +9,9 @@
#include <stdlib.h> #include <stdlib.h>
#include "lv_canvas.h" #include "lv_canvas.h"
#include "../lv_misc/lv_math.h" #include "../lv_misc/lv_math.h"
#include "../lv_draw/lv_draw_img.h" #include "../lv_draw/lv_draw.h"
#include "../lv_core/lv_refr.h"
#if LV_USE_CANVAS != 0 #if LV_USE_CANVAS != 0
/********************* /*********************
@ -232,79 +234,6 @@ void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t w, l
} }
} }
/**
* Multiply a buffer with the canvas
* @param canvas pointer to a canvas object
* @param to_copy buffer to copy (multiply). LV_IMG_CF_TRUE_COLOR_ALPHA is not supported
* @param w width of the buffer to copy
* @param h height of the buffer to copy
* @param x left side of the destination position
* @param y top side of the destination position
*/
void lv_canvas_mult_buf(lv_obj_t * canvas, void * to_copy, lv_coord_t w, lv_coord_t h, lv_coord_t x,
lv_coord_t y)
{
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
if(x + w >= ext->dsc.header.w || y + h >= ext->dsc.header.h) {
LV_LOG_WARN("lv_canvas_mult_buf: x or y out of the canvas");
return;
}
if(ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
LV_LOG_WARN("lv_canvas_mult_buf: LV_IMG_CF_TRUE_COLOR_ALPHA is not supported");
return;
}
uint32_t px_size = lv_img_color_format_get_px_size(ext->dsc.header.cf) >> 3;
uint32_t px = ext->dsc.header.w * y * px_size + x * px_size;
lv_color_t * copy_buf_color = (lv_color_t *)to_copy;
lv_color_t * canvas_buf_color = (lv_color_t *)&ext->dsc.data[px];
lv_coord_t i;
lv_coord_t j;
for(i = 0; i < h; i++) {
for(j = 0; j < w; j++) {
#if LV_COLOR_DEPTH == 32
canvas_buf_color[j].ch.red =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.red * copy_buf_color[j].ch.red) >> 8;
canvas_buf_color[j].ch.green =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.green * copy_buf_color[j].ch.green) >>
8;
canvas_buf_color[j].ch.blue =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.blue * copy_buf_color[j].ch.blue) >> 8;
#elif LV_COLOR_DEPTH == 16
canvas_buf_color[j].ch.red =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.red * copy_buf_color[j].ch.red) >> 5;
canvas_buf_color[j].ch.blue =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.blue * copy_buf_color[j].ch.blue) >> 5;
#if LV_COLOR_16_SWAP == 0
canvas_buf_color[j].ch.green =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.green * copy_buf_color[j].ch.green) >>
6;
#else
uint8_t green_canvas = (canvas_buf_color[j].ch.green_h << 3) + (canvas_buf_color[j].ch.green_l);
uint8_t green_buf = (copy_buf_color[j].ch.green_h << 3) + (copy_buf_color[j].ch.green_l);
uint8_t green_res = (uint16_t)((uint16_t)green_canvas * green_buf) >> 6;
canvas_buf_color[j].ch.green_h = (green_res >> 3) & 0x07;
canvas_buf_color[j].ch.green_l = green_res & 0x07;
#endif /*LV_COLOR_16_SWAP*/
#elif LV_COLOR_DEPTH == 8
canvas_buf_color[j].ch.red =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.red * copy_buf_color[j].ch.red) >> 3;
canvas_buf_color[j].ch.green =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.green * copy_buf_color[j].ch.green) >>
3;
canvas_buf_color[j].ch.blue =
(uint16_t)((uint16_t)canvas_buf_color[j].ch.blue * copy_buf_color[j].ch.blue) >> 2;
#endif
}
copy_buf_color += w;
canvas_buf_color += ext->dsc.header.w;
}
}
/** /**
* Rotate and image and store the result on a canvas. * Rotate and image and store the result on a canvas.
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
@ -488,193 +417,262 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c
} }
/** /**
* Draw circle function of the canvas * Fill the canvas with color
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas
* @param x0 x coordinate of the circle * @param color the background color
* @param y0 y coordinate of the circle
* @param radius radius of the circle
* @param color border color of the circle
*/ */
void lv_canvas_draw_circle(lv_obj_t * canvas, lv_coord_t x0, lv_coord_t y0, lv_coord_t radius, void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color)
lv_color_t color)
{ {
int x = radius; lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
int y = 0;
int err = 0;
while(x >= y) { uint32_t x = dsc->header.w * dsc->header.h;
lv_canvas_set_px(canvas, x0 + x, y0 + y, color); uint32_t y;
lv_canvas_set_px(canvas, x0 + y, y0 + x, color); for(y = 0; y < dsc->header.h; y++) {
lv_canvas_set_px(canvas, x0 - y, y0 + x, color); for(x = 0; x < dsc->header.w; x++) {
lv_canvas_set_px(canvas, x0 - x, y0 + y, color); lv_img_buf_set_px_color(dsc, x, y, color);
lv_canvas_set_px(canvas, x0 - x, y0 - y, color);
lv_canvas_set_px(canvas, x0 - y, y0 - x, color);
lv_canvas_set_px(canvas, x0 + y, y0 - x, color);
lv_canvas_set_px(canvas, x0 + x, y0 - y, color);
if(err <= 0) {
y += 1;
err += 2 * y + 1;
}
if(err > 0) {
x -= 1;
err -= 2 * x + 1;
} }
} }
} }
/** /**
* Draw line function of the canvas * Draw a rectangle on the canvas
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param point1 start point of the line * @param x left coordinate of the rectangle
* @param point2 end point of the line * @param y top coordinate of the rectangle
* @param color color of the line * @param w width of the rectangle
* * @param h height of the rectangle
* NOTE: The lv_canvas_draw_line function originates from https://github.com/jb55/bresenham-line.c. * @param style style of the rectangle (`body` properties are used except `padding`)
*/ */
void lv_canvas_draw_line(lv_obj_t * canvas, lv_point_t point1, lv_point_t point2, lv_color_t color) void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h, const lv_style_t * style)
{ {
lv_coord_t x0, y0, x1, y1; lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
x0 = point1.x; /* Create a dummy display to fool the lv_draw function.
y0 = point1.y; * It will think it draws to real screen. */
x1 = point2.x; lv_area_t mask;
y1 = point2.y; mask.x1 = 0;
mask.x2 = dsc->header.w - 1;
mask.y1 = 0;
mask.y2 = dsc->header.h - 1;
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; lv_area_t coords;
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1; coords.x1 = x;
int err = (dx > dy ? dx : -dy) / 2, e2; coords.y1 = y;
coords.x2 = x + w - 1;
coords.y2 = y + h - 1;
for(;;) { lv_disp_t disp;
lv_canvas_set_px(canvas, x0, y0, color); memset(&disp, 0, sizeof(lv_disp_t));
if(x0 == x1 && y0 == y1) break; lv_disp_buf_t disp_buf;
e2 = err; lv_disp_buf_init(&disp_buf, (void*)dsc->data, NULL, dsc->header.w * dsc->header.h);
if(e2 > -dx) { lv_area_copy(&disp_buf.area, &mask);
err -= dy;
x0 += sx; lv_disp_drv_init(&disp.driver);
}
if(e2 < dy) { disp.driver.buffer = &disp_buf;
err += dx; disp.driver.hor_res = dsc->header.w;
y0 += sy; disp.driver.ver_res = dsc->header.h;
}
} lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
lv_refr_set_disp_refreshing(&disp);
lv_draw_rect(&coords, &mask, style, LV_OPA_COVER);
lv_refr_set_disp_refreshing(refr_ori);
} }
/** /**
* Draw triangle function of the canvas * Draw a text on the canvas.
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param points edge points of the triangle * @param x left coordinate of the text
* @param color line color of the triangle * @param y top coordinate of the text
* @param max_w max width of the text. The text will be wrapped to fit into this size
* @param style style of the text (`text` properties are used)
* @param txt text to display
* @param align align of the text (`LV_LABEL_ALIGN_LEFT/RIGHT/CENTER`)
*/ */
void lv_canvas_draw_triangle(lv_obj_t * canvas, lv_point_t * points, lv_color_t color) void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t max_w, const lv_style_t * style, const char * txt, lv_label_align_t align)
{ {
lv_canvas_draw_polygon(canvas, points, 3, color); lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
}
/** /* Create a dummy display to fool the lv_draw function.
* Draw rectangle function of the canvas * It will think it draws to real screen. */
* @param canvas pointer to a canvas object lv_area_t mask;
* @param points edge points of the rectangle mask.x1 = 0;
* @param color line color of the rectangle mask.x2 = dsc->header.w - 1;
*/ mask.y1 = 0;
void lv_canvas_draw_rect(lv_obj_t * canvas, lv_point_t * points, lv_color_t color) mask.y2 = dsc->header.h - 1;
{
lv_canvas_draw_polygon(canvas, points, 4, color);
}
/** lv_area_t coords;
* Draw polygon function of the canvas coords.x1 = x;
* @param canvas pointer to a canvas object coords.y1 = y;
* @param points edge points of the polygon coords.x2 = x + max_w - 1;
* @param size edge count of the polygon coords.y2 = dsc->header.h - 1;
* @param color line color of the polygon
*/
void lv_canvas_draw_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, lv_color_t color)
{
uint8_t i;
for(i = 0; i < (size - 1); i++) { lv_disp_t disp;
lv_canvas_draw_line(canvas, points[i], points[i + 1], color); memset(&disp, 0, sizeof(lv_disp_t));
lv_disp_buf_t disp_buf;
lv_disp_buf_init(&disp_buf, (void*)dsc->data, NULL, dsc->header.w * dsc->header.h);
lv_area_copy(&disp_buf.area, &mask);
lv_disp_drv_init(&disp.driver);
disp.driver.buffer = &disp_buf;
disp.driver.hor_res = dsc->header.w;
disp.driver.ver_res = dsc->header.h;
lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
lv_refr_set_disp_refreshing(&disp);
lv_txt_flag_t flag;
switch(align) {
case LV_LABEL_ALIGN_LEFT:
flag = LV_TXT_FLAG_NONE;
break;
case LV_LABEL_ALIGN_RIGHT:
flag = LV_TXT_FLAG_RIGHT;
break;
case LV_LABEL_ALIGN_CENTER:
flag = LV_TXT_FLAG_CENTER;
break;
default:
flag = LV_TXT_FLAG_NONE;
break;
} }
lv_canvas_draw_line(canvas, points[size - 1], points[0], color); lv_draw_label(&coords, &mask, style, LV_OPA_COVER, txt, flag, NULL, LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF);
lv_refr_set_disp_refreshing(refr_ori);
} }
/** /**
* Fill polygon function of the canvas * Draw a line on the canvas
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param points edge points of the polygon * @param points point of the line
* @param size edge count of the polygon * @param point_cnt number of points
* @param boundary_color line color of the polygon * @param style style of the line (`line` properties are used)
* @param fill_color fill color of the polygon
*/ */
void lv_canvas_fill_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t * points, uint32_t point_cnt, const lv_style_t * style)
lv_color_t boundary_color, lv_color_t fill_color)
{ {
uint32_t x = 0, y = 0; lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
uint8_t i;
for(i = 0; i < size; i++) { /* Create a dummy display to fool the lv_draw function.
x += points[i].x; * It will think it draws to real screen. */
y += points[i].y; lv_area_t mask;
mask.x1 = 0;
mask.x2 = dsc->header.w - 1;
mask.y1 = 0;
mask.y2 = dsc->header.h - 1;
lv_disp_t disp;
memset(&disp, 0, sizeof(lv_disp_t));
lv_disp_buf_t disp_buf;
lv_disp_buf_init(&disp_buf, (void*)dsc->data, NULL, dsc->header.w * dsc->header.h);
lv_area_copy(&disp_buf.area, &mask);
lv_disp_drv_init(&disp.driver);
disp.driver.buffer = &disp_buf;
disp.driver.hor_res = dsc->header.w;
disp.driver.ver_res = dsc->header.h;
lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
lv_refr_set_disp_refreshing(&disp);
uint32_t i;
for(i = 0; i < point_cnt - 1; i++) {
lv_draw_line(&points[i], &points[i + 1], &mask, style, LV_OPA_COVER);
} }
x = x / size; lv_refr_set_disp_refreshing(refr_ori);
y = y / size;
lv_canvas_boundary_fill4(canvas, (lv_coord_t)x, (lv_coord_t)y, boundary_color, fill_color);
} }
/** /**
* Boundary fill function of the canvas * Draw a polygon on the canvas
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param x x coordinate of the start position (seed) * @param points point of the polygon
* @param y y coordinate of the start position (seed) * @param point_cnt number of points
* @param boundary_color edge/boundary color of the area * @param style style of the polygon (`body.main_color` and `body.opa` is used)
* @param fill_color fill color of the area
*/ */
void lv_canvas_boundary_fill4(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t * points, uint32_t point_cnt, const lv_style_t * style)
lv_color_t boundary_color, lv_color_t fill_color)
{ {
lv_color_t c; lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
c = lv_canvas_get_px(canvas, x, y); /* Create a dummy display to fool the lv_draw function.
* It will think it draws to real screen. */
lv_area_t mask;
mask.x1 = 0;
mask.x2 = dsc->header.w - 1;
mask.y1 = 0;
mask.y2 = dsc->header.h - 1;
if(c.full != boundary_color.full && c.full != fill_color.full) { lv_disp_t disp;
lv_canvas_set_px(canvas, x, y, fill_color); memset(&disp, 0, sizeof(lv_disp_t));
lv_canvas_boundary_fill4(canvas, x + 1, y, boundary_color, fill_color); lv_disp_buf_t disp_buf;
lv_canvas_boundary_fill4(canvas, x, y + 1, boundary_color, fill_color); lv_disp_buf_init(&disp_buf, (void*)dsc->data, NULL, dsc->header.w * dsc->header.h);
lv_canvas_boundary_fill4(canvas, x - 1, y, boundary_color, fill_color); lv_area_copy(&disp_buf.area, &mask);
lv_canvas_boundary_fill4(canvas, x, y - 1, boundary_color, fill_color);
} lv_disp_drv_init(&disp.driver);
disp.driver.buffer = &disp_buf;
disp.driver.hor_res = dsc->header.w;
disp.driver.ver_res = dsc->header.h;
lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
lv_refr_set_disp_refreshing(&disp);
lv_draw_polygon(points, point_cnt, &mask, style, LV_OPA_COVER);
lv_refr_set_disp_refreshing(refr_ori);
} }
/** /**
* Flood fill function of the canvas * Draw an arc on the canvas
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param x x coordinate of the start position (seed) * @param x origo x of the arc
* @param y y coordinate of the start position (seed) * @param y origo y of the arc
* @param fill_color fill color of the area * @param r radius of the arc
* @param bg_color background color of the area * @param start_angle start angle in degrees
* @param end_angle end angle in degrees
* @param style style of the polygon (`body.main_color` and `body.opa` is used)
*/ */
void lv_canvas_flood_fill(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t fill_color, void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t r, int32_t start_angle, int32_t end_angle, const lv_style_t * style)
lv_color_t bg_color)
{ {
lv_color_t c; lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
c = lv_canvas_get_px(canvas, x, y); /* Create a dummy display to fool the lv_draw function.
* It will think it draws to real screen. */
lv_area_t mask;
mask.x1 = 0;
mask.x2 = dsc->header.w - 1;
mask.y1 = 0;
mask.y2 = dsc->header.h - 1;
if(c.full == bg_color.full) { lv_disp_t disp;
lv_canvas_set_px(canvas, x, y, fill_color); memset(&disp, 0, sizeof(lv_disp_t));
lv_canvas_flood_fill(canvas, x + 1, y, fill_color, bg_color); lv_disp_buf_t disp_buf;
lv_canvas_flood_fill(canvas, x, y + 1, fill_color, bg_color); lv_disp_buf_init(&disp_buf, (void*)dsc->data, NULL, dsc->header.w * dsc->header.h);
lv_canvas_flood_fill(canvas, x - 1, y, fill_color, bg_color); lv_area_copy(&disp_buf.area, &mask);
lv_canvas_flood_fill(canvas, x, y - 1, fill_color, bg_color);
} lv_disp_drv_init(&disp.driver);
disp.driver.buffer = &disp_buf;
disp.driver.hor_res = dsc->header.w;
disp.driver.ver_res = dsc->header.h;
lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
lv_refr_set_disp_refreshing(&disp);
lv_draw_arc(x, y, r, &mask, start_angle, end_angle, style, LV_OPA_COVER);
lv_refr_set_disp_refreshing(refr_ori);
} }
/********************** /**********************

View File

@ -139,18 +139,6 @@ const lv_style_t * lv_canvas_get_style(const lv_obj_t * canvas, lv_canvas_style_
void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t w, lv_coord_t h, void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t w, lv_coord_t h,
lv_coord_t x, lv_coord_t y); lv_coord_t x, lv_coord_t y);
/**
* Multiply a buffer with the canvas
* @param canvas pointer to a canvas object
* @param to_copy buffer to copy (multiply). LV_IMG_CF_TRUE_COLOR_ALPHA is not supported
* @param w width of the buffer to copy
* @param h height of the buffer to copy
* @param x left side of the destination position
* @param y top side of the destination position
*/
void lv_canvas_mult_buf(lv_obj_t * canvas, void * to_copy, lv_coord_t w, lv_coord_t h, lv_coord_t x,
lv_coord_t y);
/** /**
* Rotate and image and store the result on a canvas. * Rotate and image and store the result on a canvas.
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
@ -168,83 +156,64 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c
lv_coord_t offset_y, int32_t pivot_x, int32_t pivot_y); lv_coord_t offset_y, int32_t pivot_x, int32_t pivot_y);
/** /**
* Draw circle function of the canvas * Fill the canvas with color
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas
* @param x0 x coordinate of the circle * @param color the background color
* @param y0 y coordinate of the circle
* @param radius radius of the circle
* @param color border color of the circle
*/ */
void lv_canvas_draw_circle(lv_obj_t * canvas, lv_coord_t x0, lv_coord_t y0, lv_coord_t radius, void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color);
lv_color_t color);
/** /**
* Draw line function of the canvas * Draw a rectangle on the canvas
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param point1 start point of the line * @param x left coordinate of the rectangle
* @param point2 end point of the line * @param y top coordinate of the rectangle
* @param color color of the line * @param w width of the rectangle
* * @param h height of the rectangle
* NOTE: The lv_canvas_draw_line function originates from https://github.com/jb55/bresenham-line.c. * @param style style of the rectangle (`body` properties are used except `padding`)
*/ */
void lv_canvas_draw_line(lv_obj_t * canvas, lv_point_t point1, lv_point_t point2, lv_color_t color); void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h, const lv_style_t * style);
/** /**
* Draw triangle function of the canvas * Draw a text on the canvas.
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param points edge points of the triangle * @param x left coordinate of the text
* @param color line color of the triangle * @param y top coordinate of the text
* @param max_w max width of the text. The text will be wrapped to fit into this size
* @param style style of the text (`text` properties are used)
* @param txt text to display
* @param align align of the text (`LV_LABEL_ALIGN_LEFT/RIGHT/CENTER`)
*/ */
void lv_canvas_draw_triangle(lv_obj_t * canvas, lv_point_t * points, lv_color_t color); void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t max_w, const lv_style_t * style, const char * txt, lv_label_align_t align);
/** /**
* Draw rectangle function of the canvas * Draw a line on the canvas
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param points edge points of the rectangle * @param points point of the line
* @param color line color of the rectangle * @param point_cnt number of points
* @param style style of the line (`line` properties are used)
*/ */
void lv_canvas_draw_rect(lv_obj_t * canvas, lv_point_t * points, lv_color_t color); void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t * points, uint32_t point_cnt, const lv_style_t * style);
/** /**
* Draw polygon function of the canvas * Draw a polygon on the canvas
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param points edge points of the polygon * @param points point of the polygon
* @param size edge count of the polygon * @param point_cnt number of points
* @param color line color of the polygon * @param style style of the polygon (`body.main_color` and `body.opa` is used)
*/ */
void lv_canvas_draw_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, lv_color_t color); void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t * points, uint32_t point_cnt, const lv_style_t * style);
/** /**
* Fill polygon function of the canvas * Draw an arc on the canvas
* @param canvas pointer to a canvas object * @param canvas pointer to a canvas object
* @param points edge points of the polygon * @param x origo x of the arc
* @param size edge count of the polygon * @param y origo y of the arc
* @param boundary_color line color of the polygon * @param r radius of the arc
* @param fill_color fill color of the polygon * @param start_angle start angle in degrees
* @param end_angle end angle in degrees
* @param style style of the polygon (`body.main_color` and `body.opa` is used)
*/ */
void lv_canvas_fill_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t r, int32_t start_angle, int32_t end_angle, const lv_style_t * style);
lv_color_t boundary_color, lv_color_t fill_color);
/**
* Boundary fill function of the canvas
* @param canvas pointer to a canvas object
* @param x x coordinate of the start position (seed)
* @param y y coordinate of the start position (seed)
* @param boundary_color edge/boundary color of the area
* @param fill_color fill color of the area
*/
void lv_canvas_boundary_fill4(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y,
lv_color_t boundary_color, lv_color_t fill_color);
/**
* Flood fill function of the canvas
* @param canvas pointer to a canvas object
* @param x x coordinate of the start position (seed)
* @param y y coordinate of the start position (seed)
* @param fill_color fill color of the area
* @param bg_color background color of the area
*/
void lv_canvas_flood_fill(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t fill_color,
lv_color_t bg_color);
/********************** /**********************
* MACROS * MACROS