圆形 (Geometry Circle)

概述

圆形控件是一个轻量级的 GUI 绘图组件,专门用于在用户界面中绘制圆形图形。该控件提供了简洁易用的 API ,支持自定义圆形的中心位置、半径、颜色等属性,能够创建各种圆形 UI 元素。



核心功能

描述

API

创建控件

gui_circle_create()

设置属性

gui_circle_set_style()

设置位置

gui_circle_set_position()

设置半径

gui_circle_set_radius()

设置颜色

gui_circle_set_color()

设置描边

gui_circle_set_stroke()

清除描边

gui_circle_clear_stroke()

设置外发光

gui_circle_set_glow()

清除外发光

gui_circle_clear_glow()

设置不透明度

gui_circle_set_opacity()

注册点击事件回调

gui_circle_on_click()

旋转变换

gui_circle_rotate()

缩放变换

gui_circle_scale()

平移变换

gui_circle_translate()

设置径向渐变

gui_circle_set_radial_gradient()

设置角度渐变

gui_circle_set_angular_gradient()

添加渐变色点

gui_circle_add_gradient_stop()

清除渐变色

gui_circle_clear_gradient()

圆形特性

圆形控件具有以下几何特性:

  • 圆心定位: 通过中心点坐标精确定位

  • 半径控制: 支持任意大小的半径值

  • 完美圆形: 确保绘制完美的几何圆形

  • 边界处理: 自动处理圆形与边界的裁剪

  • 内部描边: 描边向圆形内部扩展,不改变控件尺寸

外发光

控件可选地绘制一圈外发光。它是独立的一层,画在本体下方,本体的填充和描边 都不受影响。

gui_color_t glow = gui_rgba(80, 200, 255, 160);
gui_circle_set_glow(circle, glow, 12);   /* 12 像素模糊半径 */
gui_circle_clear_glow(circle);

颜色的 alpha 即发光强度;blur_radius 单位为像素,钳到 1..32,传 0 等同 关闭。改颜色或强度只重绘,不重建掩膜。

掩膜按一条径向条块绕中心旋转四次存储,所以大小取决于半径和模糊半径, 而不是圆的面积。中心区域为空,完全不存储。

限制与圆角矩形相同:发光可以溢出父容器;本体滚出屏幕后留在屏内的发光, 要等该区域下一次重绘才会清掉。

渐变色填充

圆形控件支持径向渐变和角度渐变两种渐变色填充方式,可以创建丰富的视觉效果。



渐变类型

支持 2 种渐变类型:

  • CIRCLE_GRADIENT_RADIAL: 径向渐变(从圆心向外)

  • CIRCLE_GRADIENT_ANGULAR: 角度渐变(沿圆周方向)

渐变色工作原理

  • 径向渐变:颜色从圆心向边缘线性插值

  • 角度渐变:颜色沿圆周角度方向线性插值

  • 支持最多 8 个颜色停止点(color stops)

  • 颜色停止点的位置用 0.0 ~ 1.0 的归一化值表示

  • 像素颜色通过在相邻颜色停止点之间进行线性插值计算得出

  • 采用有序抖动(Ordered Dithering)算法消除 RGB565 格式的色阶问题

使用步骤

  1. 创建圆形控件

  2. 调用 gui_circle_set_radial_gradient() 设置径向渐变,或调用 gui_circle_set_angular_gradient() 设置角度渐变

  3. 调用 gui_circle_add_gradient_stop() 添加颜色停止点(至少需要 2 个)

  4. 可选:调用 gui_circle_clear_gradient() 清除渐变设置

关键要点

  • 径向渐变: 适合创建光晕、太阳等从中心向外发散的效果

  • 角度渐变: 适合创建彩虹圆环、色轮等沿圆周变化的效果

  • 无缝循环: 对于角度渐变,起始颜色和结束颜色应相同,以实现无缝的颜色循环

  • 颜色插值: 支持 RGBA 颜色空间的线性插值,包括透明度通道

  • 抗色阶: 针对 RGB565 显示屏优化,使用抖动算法消除色阶

  • 性能优化: 对非渐变场景几乎无性能影响

特性亮点

  • 高性能: 采用优化的圆形绘制算法,确保流畅的渲染性能

  • 抗锯齿: 支持边缘抗锯齿,提供平滑的圆形边缘效果

  • 灵活配置: 支持自定义半径、位置和颜色

  • 透明度支持: 支持 RGBA 颜色格式,可创建半透明圆形效果

  • 轻量级: 内存占用小,适合嵌入式系统和资源受限环境

  • 动态更新: 支持运行时动态修改位置和样式

  • 矩阵变换: 支持旋转、缩放、平移等矩阵变换操作,可创建椭圆和复杂变换效果

应用场景

圆形控件适用于以下场景:

  • 状态指示器: 创建圆形状态指示灯

  • 用户头像: 实现圆形用户头像显示

  • 图标设计: 绘制各种圆形图标元素

  • 进度指示: 创建圆形进度条或加载动画

  • 按钮设计: 实现圆形交互按钮

  • 装饰元素: 作为 UI 界面的装饰性圆形元素

  • 数据可视化: 用于饼图、雷达图等数据可视化组件

  • 椭圆绘制: 利用缩放变换创建椭圆形状

  • 变换动画: 利用旋转、缩放、平移实现复杂的动画效果

配置说明

要使用圆形控件,需要在配置文件中启用相应的宏定义:

通过 menuconfig 启用 Kconfig 选项:

cd simulator/win32
menuconfig ../../Kconfig.gui

选择 Geometry CIRCLE Demo ( CONFIG_REALTEK_BUILD_REAL_LITE_CIRCLE ),保存到 simulator/win32/.config。

#define CONFIG_REALTEK_BUILD_REAL_LITE_CIRCLE 1

完整示例

#include "gui_components_init.h"
#include "gui_circle.h"
static void gui_circle_cb(gui_obj_t *obj)
{
    gui_log("gui_circle_cb: %s\n", obj->name);
}

// Gradient circle examples
void example_circle_gradient(void *parent)
{
    // Example 1: Radial gradient (center to edge, white to blue)
    gui_circle_t *circle1 = gui_circle_create(parent, "circle_radial",
                                              120, 120, 80,
                                              gui_rgba(255, 255, 255, 255));
    gui_circle_set_radial_gradient(circle1);
    gui_circle_add_gradient_stop(circle1, 0.0f, gui_rgba(255, 255, 255, 255)); // White center
    gui_circle_add_gradient_stop(circle1, 1.0f, gui_rgba(0, 0, 255, 255));     // Blue edge

    // Example 2: Radial gradient with multiple colors (sun effect)
    gui_circle_t *circle2 = gui_circle_create(parent, "circle_sun",
                                              320, 120, 80,
                                              gui_rgba(255, 255, 0, 255));
    gui_circle_set_radial_gradient(circle2);
    gui_circle_add_gradient_stop(circle2, 0.0f, gui_rgba(255, 255, 255, 255)); // White center
    gui_circle_add_gradient_stop(circle2, 0.3f, gui_rgba(255, 255, 0, 255));   // Yellow
    gui_circle_add_gradient_stop(circle2, 0.7f, gui_rgba(255, 128, 0, 255));   // Orange
    gui_circle_add_gradient_stop(circle2, 1.0f, gui_rgba(255, 0, 0, 255));     // Red edge

    // Example 3: Angular gradient (rainbow around circle)
    gui_circle_t *circle3 = gui_circle_create(parent, "circle_angular",
                                              120, 320, 80,
                                              gui_rgba(255, 0, 0, 255));
    gui_circle_set_angular_gradient(circle3, 0, 360);
    gui_circle_add_gradient_stop(circle3, 0.00f, gui_rgba(255, 0, 0, 255));    // Red
    gui_circle_add_gradient_stop(circle3, 0.17f, gui_rgba(255, 127, 0, 255));  // Orange
    gui_circle_add_gradient_stop(circle3, 0.33f, gui_rgba(255, 255, 0, 255));  // Yellow
    gui_circle_add_gradient_stop(circle3, 0.50f, gui_rgba(0, 255, 0, 255));    // Green
    gui_circle_add_gradient_stop(circle3, 0.67f, gui_rgba(0, 0, 255, 255));    // Blue
    gui_circle_add_gradient_stop(circle3, 0.83f, gui_rgba(75, 0, 130, 255));   // Indigo
    gui_circle_add_gradient_stop(circle3, 1.00f, gui_rgba(255, 0, 0, 255));    // Red (seamless)

    // Example 4: Radial gradient with transparency (glow effect)
    gui_circle_t *circle4 = gui_circle_create(parent, "circle_glow",
                                              320, 320, 80,
                                              gui_rgba(0, 255, 0, 255));
    gui_circle_set_radial_gradient(circle4);
    gui_circle_add_gradient_stop(circle4, 0.0f, gui_rgba(0, 255, 0, 255));     // Opaque green
    gui_circle_add_gradient_stop(circle4, 0.5f, gui_rgba(0, 255, 0, 180));     // Semi-transparent
    gui_circle_add_gradient_stop(circle4, 1.0f, gui_rgba(0, 255, 0, 50));      // Nearly transparent
}

static int geometry_circle_demo_init(void)
{
    const uint32_t W = 480, H = 480;
    const uint32_t big_d   = 368;
    const uint32_t small_d = 66;
    const uint32_t margin  = 36;

    gui_circle_t *big_circle = gui_circle_create(gui_obj_get_root(), "big_circle", W / 2,
                                                 H / 2, big_d / 2, gui_rgba(0, 255,
                                                                            0, 255));
    gui_circle_set_stroke(big_circle, 8.0f, gui_rgba(255, 255, 255, 255));

    gui_circle_create(gui_obj_get_root(), "top_left", margin + small_d / 2, margin + small_d / 2,
                      small_d / 2,
                      gui_rgba(255, 0, 0, 255));


    gui_circle_create(gui_obj_get_root(), "top_right", W - margin - small_d / 2,
                      margin + small_d / 2, small_d / 2,
                      gui_rgba(0, 255, 0, 255));


    gui_circle_create(gui_obj_get_root(), "bottom_left", margin + small_d / 2,
                      H - margin - small_d / 2, small_d / 2,
                      gui_rgba(0, 0, 255, 255));


    gui_circle_create(gui_obj_get_root(), "bottom_right", W - margin - small_d / 2,
                      H - margin - small_d / 2, small_d / 2,
                      gui_rgba(0, 0, 255, 150));
    gui_obj_add_event_cb(big_circle, (gui_event_cb_t)gui_circle_cb, GUI_EVENT_TOUCH_CLICKED, NULL);

    // Uncomment to show gradient examples
    // example_circle_gradient(gui_obj_get_root());
    return 0;
}

GUI_INIT_APP_EXPORT(geometry_circle_demo_init);

API

Defines

M_SQRT1_2 0.707106781186547524401f

1/sqrt(2)

Enums

enum gui_circle_gradient_type_t

Circle gradient type

Values:

enumerator CIRCLE_GRADIENT_RADIAL

From center to edge

enumerator CIRCLE_GRADIENT_ANGULAR

Along the circumference

enum gui_circle_part_t

Which rasterised part a cached payload holds.

Values:

enumerator CIRCLE_PART_FULL

Whole circle in one buffer.

enumerator CIRCLE_PART_STRIP

Top strip; the other three are it turned.

Functions

gui_circle_t *gui_circle_create(void *parent, const char *name, int x, int y, int radius, gui_color_t color)

Create a circle widget.

参数:
  • parent -- Parent widget.

  • name -- Widget name.

  • x -- X coordinate of circle center.

  • y -- Y coordinate of circle center.

  • radius -- Circle radius.

  • color -- Circle color.

返回:

Pointer to the created circle widget.

void gui_circle_set_style(gui_circle_t *circle, int x, int y, int radius, gui_color_t color)

Set circle style.

参数:
  • circle -- Circle widget pointer.

  • x -- X coordinate of circle center.

  • y -- Y coordinate of circle center.

  • radius -- Circle radius.

  • color -- Circle color.

void gui_circle_set_position(gui_circle_t *circle, int x, int y)

Set circle position.

参数:
  • circle -- Circle widget pointer.

  • x -- X coordinate of circle center.

  • y -- Y coordinate of circle center.

void gui_circle_set_radius(gui_circle_t *circle, int radius)

Set circle radius.

参数:
  • circle -- Circle widget pointer.

  • radius -- Circle radius.

void gui_circle_set_opacity(gui_circle_t *circle, uint8_t opacity)

Set the opacity of the circle widget.

参数:
  • circle -- Pointer to the circle widget.

  • opacity -- Opacity value (0-255).

void gui_circle_set_color(gui_circle_t *circle, gui_color_t color)

Set circle color.

参数:
  • circle -- Circle widget pointer.

  • color -- Circle color.

void gui_circle_set_stroke(gui_circle_t *circle, float width, gui_color_t color)

Set an inset stroke for the circle.

参数:
  • circle -- Circle widget pointer.

  • width -- Stroke width in pixels. A non-positive value disables stroke.

  • color -- Stroke color.

void gui_circle_clear_stroke(gui_circle_t *circle)

Disable the circle stroke.

参数:

circle -- Circle widget pointer.

void gui_circle_set_glow(gui_circle_t *circle, gui_color_t color, uint8_t blur_radius)

Draw an outer glow around the circle.

The glow is a separate layer drawn under the body: the body's own fill and stroke are untouched, and changing the glow does not rebuild them.

Its colour's alpha is the strength, so a dimmer glow is a lower alpha rather than a different blur. Changing colour or strength repaints without rebuilding the mask; changing the radius or blur radius rebuilds it.

参数:
  • circle -- Circle widget pointer.

  • color -- Glow colour; alpha 0 switches the glow off.

  • blur_radius -- Blur radius in pixels, clamped to 1..32. 0 switches the glow off.

void gui_circle_clear_glow(gui_circle_t *circle)

Remove the circle's outer glow.

参数:

circle -- Circle widget pointer.

void gui_circle_on_click(gui_circle_t *circle, void *callback, void *parameter)

Set click callback for the circle.

参数:
  • circle -- Circle widget pointer.

  • callback -- Callback function.

  • parameter -- Callback parameter.

void gui_circle_rotate(gui_circle_t *circle, float degrees)

Apply rotation transformation to the circle widget.

参数:
  • circle -- Circle widget pointer.

  • degrees -- Rotation angle in degrees (clockwise).

void gui_circle_scale(gui_circle_t *circle, float scale_x, float scale_y)

Apply scale transformation to the circle widget.

参数:
  • circle -- Circle widget pointer.

  • scale_x -- Scale factor in X direction.

  • scale_y -- Scale factor in Y direction.

void gui_circle_translate(gui_circle_t *circle, float tx, float ty)

Apply translation transformation to the circle widget.

参数:
  • circle -- Circle widget pointer.

  • tx -- Translation in X direction (pixels).

  • ty -- Translation in Y direction (pixels).

void gui_circle_set_radial_gradient(gui_circle_t *circle)

Set radial gradient for circle widget (from center to edge).

参数:

circle -- Circle widget pointer.

void gui_circle_set_angular_gradient(gui_circle_t *circle, float start_angle, float end_angle)

Set angular gradient for circle widget (along circumference).

参数:
  • circle -- Circle widget pointer.

  • start_angle -- Start angle in degrees.

  • end_angle -- End angle in degrees.

void gui_circle_add_gradient_stop(gui_circle_t *circle, float position, gui_color_t color)

Add color stop to circle gradient.

参数:
  • circle -- Circle widget pointer.

  • position -- Position of color stop (0.0 to 1.0).

  • color -- Color at circle stop.

void gui_circle_clear_gradient(gui_circle_t *circle)

Clear gradient and use solid color.

参数:

circle -- Circle widget pointer.

struct gui_circle_t

Circle widget structure.

Public Members

gui_obj_t base

Base widget.

gui_geometry_parts_t parts

Non-overlapping pieces: the solid centre square and four strips drawn from one payload — or one image.

int x

Center X coordinate relative to widget.

int y

Center Y coordinate relative to widget.

int radius

Circle radius.

gui_color_t color

Circle color.

float stroke_width

Inset stroke width. Zero disables stroke.

gui_color_t stroke_color

Stroke color.

uint8_t opacity_value

Opacity value.

uint32_t checksum

Checksum for change detection.

float degrees

Rotation angle in degrees.

float scale_x

Scale factor in X direction.

float scale_y

Scale factor in Y direction.

float offset_x

Translation offset in X direction.

float offset_y

Translation offset in Y direction.

Gradient *gradient

Optional gradient for circle fill.

bool use_gradient

Flag to enable gradient rendering.

gui_circle_gradient_type_t gradient_type

Gradient type.

gui_matrix_t last_matrix
gui_color_t glow_color

Glow colour; its alpha is the strength.

uint8_t glow_blur

Glow blur radius; 0 disables the glow.

struct gui_geometry_glow *glow

Glow state, allocated on first use.

struct circle_desc_t

Identity of a cached circle payload.

Everything that changes a pixel goes in here and nothing else does; notably position stays out, since it only ever reaches the draw_img matrix. Gradient parts pass the whole struct, solid ones stop short of the gradient — see circle_desc_len().

Public Members

uint32_t part

gui_circle_part_t.

int32_t radius

Circle radius.

int32_t size_a

Payload width.

int32_t size_b

Payload height.

uint32_t color

ARGB baked into the pixels; alpha only when A8.

uint32_t is_a8

Non-zero when the payload is a coverage mask.

uint32_t gradient_type

CIRCLE_GRADIENT_*, or UINT32_MAX for none.

float stroke_width

Inset stroke width, 0 for none.

uint32_t stroke_color

ARGB stroke baked into the pixels; 0 for none.

Gradient gradient

Only present when gradient_type is set.

struct circle_geom_t

Geometry shared by every piece of one circle, centred at (radius, radius).

The split is a solid centre square of side 2 * half, and around it four strips of band x (2 * half + band) laid out like a pinwheel. half is the largest value whose square still lies fully inside the fill, so the centre is one solid colour.

Public Members

int radius

Circle radius.

float stroke

Stroke width, clamped to the radius.

float inner_radius

Fill radius inside the stroke.

int half

Half side of the solid centre square.

int band

radius - half: depth of the edge bands.