Geometry Circle

Overview

The Circle widget is a lightweight GUI drawing component designed specifically for rendering circle shapes in user interfaces. This component provides a simple and easy-to-use API for customizing the circle's center position, radius, color, etc., allowing the creation of various circular UI elements.



Core Features

Description

API

Create Widget

gui_circle_create()

Set Style

gui_circle_set_style()

Set Position

gui_circle_set_position()

Set Radius

gui_circle_set_radius()

Set Color

gui_circle_set_color()

Set Stroke

gui_circle_set_stroke()

Clear Stroke

gui_circle_clear_stroke()

Set Glow

gui_circle_set_glow()

Clear Glow

gui_circle_clear_glow()

Set Opacity

gui_circle_set_opacity()

Register Click Event Callback

gui_circle_on_click()

Rotation Transform

gui_circle_rotate()

Scale Transform

gui_circle_scale()

Translation Transform

gui_circle_translate()

Set Radial Gradient

gui_circle_set_radial_gradient()

Set Angular Gradient

gui_circle_set_angular_gradient()

Add Gradient Stop

gui_circle_add_gradient_stop()

Clear Gradient

gui_circle_clear_gradient()

Circle Characteristics

The circle widget has the following geometric characteristics:

  • Center Positioning: Precisely locate through center point coordinates

  • Radius Control: Support any size radius value

  • Perfect Circle: Ensure perfect geometric circular rendering

  • Boundary Handling: Automatically handle clipping with boundaries

  • Inset Stroke: Draws the stroke inside the circle without changing widget size

Outer Glow

An optional outer glow can be drawn around the circle. It is a separate layer painted under the body, so the body's fill and stroke are untouched.

gui_color_t glow = gui_rgba(80, 200, 255, 160);
gui_circle_set_glow(circle, glow, 12);   /* 12 px blur radius */
gui_circle_clear_glow(circle);

The colour's alpha is the strength; blur_radius is in pixels, clamped to 1..32, and 0 switches the glow off. Changing colour or strength re-paints without rebuilding the mask.

The mask is stored as one radial strip turned four times around the centre, so its size depends on the radius and blur radius together, not on the circle's area. The centre is empty and is not stored at all.

The same limitations as the rounded rectangle apply: the glow may overflow a parent container, and a glow left on screen after the body scrolls away is only cleared by the next redraw of that area.

Gradient Fill

The circle widget supports both radial and angular gradient color filling, enabling rich visual effects.



Gradient Types

Supports 2 gradient types:

  • CIRCLE_GRADIENT_RADIAL: Radial gradient (from center to edge)

  • CIRCLE_GRADIENT_ANGULAR: Angular gradient (along the circumference)

How Gradient Works

  • Radial gradient: Colors are linearly interpolated from center to edge

  • Angular gradient: Colors are linearly interpolated along the circumference

  • Supports up to 8 color stops

  • Color stop positions are represented as normalized values from 0.0 to 1.0

  • Pixel colors are computed through linear interpolation between adjacent color stops

  • Uses ordered dithering algorithm to eliminate banding artifacts on RGB565 displays

Usage Steps

  1. Create a circle widget

  2. Call gui_circle_set_radial_gradient() for radial gradient, or gui_circle_set_angular_gradient() for angular gradient

  3. Call gui_circle_add_gradient_stop() to add color stops (minimum 2 required)

  4. Optional: Call gui_circle_clear_gradient() to clear gradient settings

Key Points

  • Radial Gradient: Ideal for creating glow, sun, and other center-to-edge effects

  • Angular Gradient: Ideal for creating rainbow rings, color wheels, and other circumferential effects

  • Seamless Loop: For angular gradients, start and end colors should be identical for seamless color cycling

  • Color Interpolation: Supports linear interpolation in RGBA color space, including the alpha channel

  • Anti-Banding: Optimized for RGB565 displays using dithering algorithm to eliminate color banding

  • Performance Optimization: Minimal performance impact on non-gradient scenarios

Feature Highlights

  • High Performance: Utilizes optimized circle drawing algorithms to ensure smooth rendering performance

  • Anti-Aliasing: Supports anti-aliasing for smooth circular edge effects

  • Flexible Configuration: Supports custom radius, position, and color

  • Transparency Support: Supports ARGB color format for semi-transparent circle effects

  • Lightweight: Minimal memory usage, suitable for embedded systems and resource-limited environments

  • Dynamic Updates: Allows for runtime dynamic modification of position and style

  • Matrix Transforms: Supports rotation, scale, and translation matrix transforms to create ellipses and complex transform effects

Use Cases

The circle widget is suitable for the following scenarios:

  • Status Indicators: Create circular status indicator lights

  • User Avatar: Implement circular user avatar display

  • Icon Design: Draw various circular icon elements

  • Progress Indication: Create circular progress bars or loading animations

  • Button Design: Implement circular interactive buttons

  • Decorative Elements: Serve as decorative circular elements in the UI

  • Data Visualization: Used in pie charts, radar charts, etc., for data visualization components

  • Ellipse Drawing: Create ellipse shapes using scale transforms

  • Transform Animations: Leverage rotation, scale, and translation for complex animation effects

Configuration Instructions

To use the circle widget, enable the corresponding macro definition in the configuration file:

Enable the Kconfig option via menuconfig:

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

Select Geometry CIRCLE Demo ( CONFIG_REALTEK_BUILD_REAL_LITE_CIRCLE ), then save to simulator/win32/.config.

#define CONFIG_REALTEK_BUILD_REAL_LITE_CIRCLE 1

Complete Example

#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.

Parameters:
  • parent -- Parent widget.

  • name -- Widget name.

  • x -- X coordinate of circle center.

  • y -- Y coordinate of circle center.

  • radius -- Circle radius.

  • color -- Circle color.

Returns:

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.

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:

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.

Parameters:
  • 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.

Parameters:

circle -- Circle widget pointer.

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

Set click callback for the circle.

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:
  • 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).

Parameters:

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).

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:

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.