mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-21 22:52:46 +08:00
feat(vector): add API to append arc (#5510)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
@@ -189,6 +189,37 @@ static void draw_blend(lv_vector_dsc_t * ctx, lv_vector_path_t * path)
|
||||
lv_vector_dsc_add_path(ctx, path); // draw a path
|
||||
}
|
||||
|
||||
static void draw_arc(lv_vector_dsc_t * ctx, lv_vector_path_t * path)
|
||||
{
|
||||
lv_vector_path_clear(path);
|
||||
lv_vector_dsc_identity(ctx);
|
||||
|
||||
lv_area_t rect = {100, 0, 150, 50};
|
||||
lv_vector_dsc_set_fill_color(ctx, lv_color_lighten(lv_color_black(), 50));
|
||||
lv_vector_clear_area(ctx, &rect); // clear screen
|
||||
|
||||
lv_fpoint_t p = {100, 50}; /* Center */
|
||||
lv_vector_dsc_set_stroke_color(ctx, lv_color_make(0x00, 0xff, 0xff));
|
||||
lv_vector_dsc_set_stroke_opa(ctx, LV_OPA_COVER);
|
||||
lv_vector_dsc_set_stroke_width(ctx, 2.0f);
|
||||
lv_vector_dsc_set_stroke_dash(ctx, NULL, 0);
|
||||
lv_vector_dsc_set_fill_color32(ctx, lv_color32_make(0xFF, 0x00, 0x00, 0x80));
|
||||
|
||||
lv_vector_path_move_to(path, &p);
|
||||
lv_fpoint_t temp = {p.x + 50, p.y};
|
||||
lv_vector_path_line_to(path, &temp);
|
||||
lv_vector_path_append_arc(path, &p, 50, 0, -90, false);
|
||||
lv_vector_path_line_to(path, &p);
|
||||
lv_vector_path_close(path);
|
||||
|
||||
lv_vector_dsc_add_path(ctx, path);
|
||||
|
||||
/* Below code has same effect as above one. */
|
||||
lv_vector_path_clear(path);
|
||||
lv_vector_path_append_arc(path, &p, 50, 45, 45, true);
|
||||
lv_vector_dsc_add_path(ctx, path); // draw a path
|
||||
}
|
||||
|
||||
static void draw_vector(lv_layer_t * layer)
|
||||
{
|
||||
lv_vector_dsc_t * ctx = lv_vector_dsc_create(layer);
|
||||
@@ -205,7 +236,7 @@ static void draw_vector(lv_layer_t * layer)
|
||||
draw_radial_gradient(ctx, path);
|
||||
draw_gradient(ctx, path);
|
||||
draw_blend(ctx, path);
|
||||
|
||||
draw_arc(ctx, path);
|
||||
lv_draw_vector(ctx); // submit draw
|
||||
lv_vector_path_delete(path);
|
||||
lv_vector_dsc_delete(ctx);
|
||||
|
||||
@@ -47,3 +47,5 @@
|
||||
--exclude=../tests/unity/unity_support.c
|
||||
--exclude=../tests/unity/unity_support.h
|
||||
--exclude=../tests/test_images
|
||||
--exclude=../tests/build_test_defheap
|
||||
--exclude=../tests/build_test_sysheap
|
||||
|
||||
@@ -14,6 +14,16 @@
|
||||
#include "../stdlib/lv_string.h"
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#define MATH_PI 3.14159265358979323846f
|
||||
#define MATH_HALF_PI 1.57079632679489661923f
|
||||
|
||||
#define DEG_TO_RAD 0.017453292519943295769236907684886f
|
||||
#define RAD_TO_DEG 57.295779513082320876798154814105f
|
||||
|
||||
#define MATH_RADIANS(deg) ((deg) * DEG_TO_RAD)
|
||||
#define MATH_DEGRESS(rad) ((rad) * RAD_TO_DEG)
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -470,6 +480,92 @@ void lv_vector_path_append_circle(lv_vector_path_t * path, const lv_fpoint_t * c
|
||||
lv_vector_path_close(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a arc to the path
|
||||
* @param path pointer to a path
|
||||
* @param c pointer to a `lv_fpoint_t` variable for center of the circle
|
||||
* @param radius the radius for arc
|
||||
* @param start_angle the start angle for arc
|
||||
* @param sweep the sweep angle for arc, could be negative
|
||||
* @param pie true: draw a pie, false: draw a arc
|
||||
*/
|
||||
void lv_vector_path_append_arc(lv_vector_path_t * path, const lv_fpoint_t * c, float radius, float start_angle,
|
||||
float sweep, bool pie)
|
||||
{
|
||||
float cx = c->x;
|
||||
float cy = c->y;
|
||||
|
||||
/* just circle */
|
||||
if(sweep >= 360.0f || sweep <= -360.0f) {
|
||||
lv_vector_path_append_circle(path, c, radius, radius);
|
||||
return;
|
||||
}
|
||||
|
||||
start_angle = MATH_RADIANS(start_angle);
|
||||
sweep = MATH_RADIANS(sweep);
|
||||
|
||||
int n_curves = (int)ceil(fabsf(sweep / MATH_HALF_PI));
|
||||
float sweep_sign = sweep < 0 ? -1.f : 1.f;
|
||||
float fract = fmodf(sweep, MATH_HALF_PI);
|
||||
fract = (fabsf(fract) < FLT_EPSILON) ? MATH_HALF_PI * sweep_sign : fract;
|
||||
|
||||
/* Start from here */
|
||||
lv_fpoint_t start = {
|
||||
.x = radius * cosf(start_angle),
|
||||
.y = radius * sinf(start_angle),
|
||||
};
|
||||
|
||||
if(pie) {
|
||||
lv_vector_path_move_to(path, &(lv_fpoint_t) {
|
||||
cx, cy
|
||||
});
|
||||
lv_vector_path_line_to(path, &(lv_fpoint_t) {
|
||||
start.x + cx, start.y + cy
|
||||
});
|
||||
}
|
||||
else {
|
||||
lv_vector_path_move_to(path, &(lv_fpoint_t) {
|
||||
start.x + cx, start.y + cy
|
||||
});
|
||||
}
|
||||
|
||||
for(int i = 0; i < n_curves; ++i) {
|
||||
float end_angle = start_angle + ((i != n_curves - 1) ? MATH_HALF_PI * sweep_sign : fract);
|
||||
float end_x = radius * cosf(end_angle);
|
||||
float end_y = radius * sinf(end_angle);
|
||||
|
||||
/* variables needed to calculate bezier control points */
|
||||
|
||||
/** get bezier control points using article:
|
||||
* (http://itc.ktu.lt/index.php/ITC/article/view/11812/6479)
|
||||
*/
|
||||
float ax = start.x;
|
||||
float ay = start.y;
|
||||
float bx = end_x;
|
||||
float by = end_y;
|
||||
float q1 = ax * ax + ay * ay;
|
||||
float q2 = ax * bx + ay * by + q1;
|
||||
float k2 = (4.0f / 3.0f) * ((sqrtf(2 * q1 * q2) - q2) / (ax * by - ay * bx));
|
||||
|
||||
/* Next start point is the current end point */
|
||||
start.x = end_x;
|
||||
start.y = end_y;
|
||||
|
||||
end_x += cx;
|
||||
end_y += cy;
|
||||
|
||||
lv_fpoint_t ctrl1 = {ax - k2 * ay + cx, ay + k2 * ax + cy};
|
||||
lv_fpoint_t ctrl2 = {bx + k2 * by + cx, by - k2 * bx + cy};
|
||||
lv_fpoint_t end = {end_x, end_y};
|
||||
lv_vector_path_cubic_to(path, &ctrl1, &ctrl2, &end);
|
||||
start_angle = end_angle;
|
||||
}
|
||||
|
||||
if(pie) {
|
||||
lv_vector_path_close(path);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_vector_path_append_path(lv_vector_path_t * path, const lv_vector_path_t * subpath)
|
||||
{
|
||||
uint32_t ops_size = lv_array_size(&path->ops);
|
||||
|
||||
@@ -308,6 +308,18 @@ void lv_vector_path_append_rect(lv_vector_path_t * path, const lv_area_t * rect,
|
||||
*/
|
||||
void lv_vector_path_append_circle(lv_vector_path_t * path, const lv_fpoint_t * c, float rx, float ry);
|
||||
|
||||
/**
|
||||
* Add a arc to the path
|
||||
* @param path pointer to a path
|
||||
* @param c pointer to a `lv_fpoint_t` variable for center of the circle
|
||||
* @param radius the radius for arc
|
||||
* @param start_angle the start angle for arc
|
||||
* @param sweep the sweep angle for arc, could be negative
|
||||
* @param pie true: draw a pie, false: draw a arc
|
||||
*/
|
||||
void lv_vector_path_append_arc(lv_vector_path_t * path, const lv_fpoint_t * c, float radius, float start_angle,
|
||||
float sweep, bool pie);
|
||||
|
||||
/**
|
||||
* Add an sub path to the path
|
||||
* @param path pointer to a path
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
@@ -94,6 +94,38 @@ static void draw_shapes(lv_layer_t * layer)
|
||||
lv_vector_dsc_set_fill_rule(ctx, LV_VECTOR_FILL_EVENODD);
|
||||
lv_vector_dsc_add_path(ctx, path);
|
||||
|
||||
lv_vector_path_clear(path);
|
||||
lv_vector_dsc_identity(ctx);
|
||||
lv_vector_dsc_set_blend_mode(ctx, LV_VECTOR_BLEND_SRC_OVER);
|
||||
|
||||
rect = (lv_area_t) {
|
||||
500, 50, 550, 100
|
||||
};
|
||||
lv_vector_dsc_set_fill_color(ctx, lv_color_lighten(lv_color_black(), 50));
|
||||
lv_vector_clear_area(ctx, &rect); // clear screen
|
||||
|
||||
lv_fpoint_t p = {500, 100}; /* Center */
|
||||
lv_vector_dsc_set_stroke_color(ctx, lv_color_make(0x00, 0xff, 0xff));
|
||||
lv_vector_dsc_set_stroke_opa(ctx, LV_OPA_COVER);
|
||||
lv_vector_dsc_set_stroke_width(ctx, 2.0f);
|
||||
lv_vector_dsc_set_stroke_dash(ctx, NULL, 0);
|
||||
lv_vector_dsc_set_fill_opa(ctx, LV_OPA_TRANSP);
|
||||
lv_vector_path_move_to(path, &p);
|
||||
lv_fpoint_t temp = {p.x + 50, p.y};
|
||||
lv_vector_path_line_to(path, &temp);
|
||||
lv_vector_path_append_arc(path, &p, 50, 0, -90, false);
|
||||
lv_vector_path_line_to(path, &p);
|
||||
lv_vector_path_close(path);
|
||||
|
||||
lv_vector_dsc_add_path(ctx, path);
|
||||
|
||||
/* Below code has same effect as above one but with solid fill */
|
||||
lv_vector_dsc_set_fill_color(ctx, lv_color_make(0xFF, 0x00, 0x00));
|
||||
lv_vector_dsc_set_fill_opa(ctx, LV_OPA_COVER);
|
||||
lv_vector_path_clear(path);
|
||||
lv_vector_path_append_arc(path, &p, 50, 45, 45, true);
|
||||
lv_vector_dsc_add_path(ctx, path); // draw a path
|
||||
|
||||
lv_draw_vector(ctx);
|
||||
lv_vector_path_delete(path);
|
||||
lv_vector_dsc_delete(ctx);
|
||||
|
||||
Reference in New Issue
Block a user