Geometry Rounded Rectangle
Overview
The Rounded Rectangle widget is a lightweight GUI drawing component specifically designed for rendering rectangles with rounded corners in user interfaces. It offers a simple and user-friendly API that allows customization of the rounded rectangle's size, corner radius, and color, enabling the creation of modern UI elements.

Core Features
Description |
API |
|---|---|
Create Widget |
|
Set Style |
|
Set Position |
|
Set Size |
|
Set Color |
|
Set Stroke |
|
Clear Stroke |
|
Set Glow |
|
Clear Glow |
|
Set Opacity |
|
Register Click Event Callback |
|
Rotation Transform |
|
Scale Transform |
|
Translation Transform |
|
Set Linear Gradient |
|
Add Gradient Stop |
|
Clear Gradient |
Corner Radius Description
The rounded rectangle supports the same corner radius for all four corners:
radius = 0: Draw a rectangle with sharp corners
radius > 0: Draw a rounded rectangle, with the radius determining the arc of the corners
Inset Stroke: Draws the stroke inside the rectangle without changing widget size
Outer Glow
An optional outer glow can be drawn around the widget. It is a separate layer painted under the body: the body's own fill, stroke and gradient are untouched, and changing the glow does not rebuild them.
gui_color_t glow = gui_rgba(255, 200, 80, 160);
gui_rect_set_glow(rect, glow, 12); /* 12 px blur radius */
gui_rect_clear_glow(rect);
Parameters
The colour's alpha is the strength: alpha 0 switches the glow off.
blur_radiusis in pixels, clamped to 1..32. 0 switches the glow off.Changing colour or strength re-paints without rebuilding the mask; changing size, corner radius or blur radius rebuilds it.
How It Works
The glow mask is an A8 signed-distance field sampled from the same rounded
rectangle distance the body's anti-aliasing uses, so the two edges line up
exactly. The stored value is F(d) * (1 - c) / (1 - c * a), which composes
with the body's own SRC_OVER instead of multiplying the edge coverage in twice.
Without that compensation the seam between body and glow shows as a dark ring
about one pixel wide.
The mask is stored split, not as one bounding box: one corner block drawn four times through mirroring, plus one horizontal and one vertical band. Only the ring around the outline is non-zero, so a body's interior costs nothing and the memory depends on the corner radius and blur radius rather than on the widget's area. Blocks are shared through the geometry cache, so two rects with the same corner and blur radius share one set of pixels regardless of colour.
Limitations
The glow may extend past a parent container: it is clipped to the display section only, never to the parent's bounds. Hit testing still uses the body.
When the body leaves the screen, the part of the glow still on screen is not erased until something else redraws that area.
Gradient Fill
The rounded rectangle widget supports linear gradient color filling, enabling smooth color transitions along different directions.

Gradient Directions
Supports 4 linear gradient directions:
RECT_GRADIENT_HORIZONTAL: Horizontal gradient (left to right)
RECT_GRADIENT_VERTICAL: Vertical gradient (top to bottom)
RECT_GRADIENT_DIAGONAL_TL_BR: Diagonal gradient (top-left to bottom-right)
RECT_GRADIENT_DIAGONAL_TR_BL: Diagonal gradient (top-right to bottom-left)
How Gradient Works
Gradient colors are linearly interpolated along the specified direction
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
Create a rounded rectangle widget
Call
gui_rect_set_linear_gradient()to set the gradient directionCall
gui_rect_add_gradient_stop()to add color stops (minimum 2 required)Optional: Call
gui_rect_clear_gradient()to clear gradient settings
Key Points
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 rendering algorithms for smooth performance
Anti-Aliasing: Supports anti-aliasing for smooth rounded corner effects
Flexible Configuration: Allows customization of size, corner radius, and color
Transparency Support: Uses ARGB color format for semi-transparent effects
Lightweight: Minimal memory footprint, suitable for embedded systems and resource-constrained environments
Dynamic Updates: Supports runtime dynamic modification of position and style
Matrix Transforms: Supports rotation, scale, and translation matrix transforms for complex geometric effects
Use Cases
Rounded Rectangle widgets are applicable in scenarios such as:
Modern Buttons: Create interactive buttons with rounded corner effects
Card Layouts: Implement card-style UI design elements
Dialogs and Panels: Render rounded corner dialogs and information panels
Icon Backgrounds: Serve as background for application icons or functional icons
Progress Bar Containers: Create rounded containers for progress bars
List Items: Implement rounded list items or menu items
Animated Elements: Support animation effects with dynamic position changes
Transform Animations: Leverage rotation, scale, and translation for complex animation effects
Configuration Instructions
To use the rounded rectangle widget, enable the corresponding macro in the configuration file:
Enable the Kconfig option via menuconfig:
cd simulator/win32
menuconfig ../../Kconfig.gui
Select Geometry RECT Demo ( CONFIG_REALTEK_BUILD_REAL_LITE_RECT ), then save to simulator/win32/.config.
#define CONFIG_REALTEK_BUILD_REAL_LITE_RECT 1
Complete Example
#include "gui_components_init.h"
#include "gui_rect.h"
#include "gui_view.h"
#include "gui_view_instance.h"
#define RECT_VIEW_NAME "rect_round_view"
gui_rounded_rect_t *round_rect = NULL;
void round_rect_timer_cb(void *arg)
{
gui_rect_set_position(arg, 100, 100);
gui_fb_change();
}
void rect_click_demo(void)
{
round_rect = gui_rect_create(gui_obj_get_root(), "round_rect", 0, 0, 200, 200, 10,
gui_rgba(255, 0, 0, 255));
gui_rect_set_style(round_rect, 200, 200, 200, 200, 10, gui_rgba(255, 0, 0, 255));
gui_rect_on_click(round_rect, round_rect_timer_cb, NULL);
}
// Gradient rectangle examples
void example_rect_gradient(void *parent)
{
// Example 1: Horizontal gradient (red to blue)
gui_rounded_rect_t *rect1 = gui_rect_create(parent, "rect_h_gradient",
20, 20, 200, 80, 10,
gui_rgba(255, 0, 0, 255));
gui_rect_set_linear_gradient(rect1, RECT_GRADIENT_HORIZONTAL);
gui_rect_add_gradient_stop(rect1, 0.0f, gui_rgba(255, 0, 0, 255)); // Red
gui_rect_add_gradient_stop(rect1, 1.0f, gui_rgba(0, 0, 255, 255)); // Blue
// Example 2: Vertical gradient (green to yellow)
gui_rounded_rect_t *rect2 = gui_rect_create(parent, "rect_v_gradient",
240, 20, 200, 80, 10,
gui_rgba(0, 255, 0, 255));
gui_rect_set_linear_gradient(rect2, RECT_GRADIENT_VERTICAL);
gui_rect_add_gradient_stop(rect2, 0.0f, gui_rgba(0, 255, 0, 255)); // Green
gui_rect_add_gradient_stop(rect2, 1.0f, gui_rgba(255, 255, 0, 255)); // Yellow
// Example 3: Diagonal gradient (top-left to bottom-right)
gui_rounded_rect_t *rect3 = gui_rect_create(parent, "rect_d1_gradient",
20, 120, 200, 120, 15,
gui_rgba(255, 0, 255, 255));
gui_rect_set_linear_gradient(rect3, RECT_GRADIENT_DIAGONAL_TL_BR);
gui_rect_add_gradient_stop(rect3, 0.0f, gui_rgba(255, 0, 255, 255)); // Magenta
gui_rect_add_gradient_stop(rect3, 0.5f, gui_rgba(255, 255, 255, 255)); // White
gui_rect_add_gradient_stop(rect3, 1.0f, gui_rgba(0, 255, 255, 255)); // Cyan
// Example 4: Diagonal gradient (top-right to bottom-left)
gui_rounded_rect_t *rect4 = gui_rect_create(parent, "rect_d2_gradient",
240, 120, 200, 120, 15,
gui_rgba(255, 128, 0, 255));
gui_rect_set_linear_gradient(rect4, RECT_GRADIENT_DIAGONAL_TR_BL);
gui_rect_add_gradient_stop(rect4, 0.0f, gui_rgba(255, 128, 0, 255)); // Orange
gui_rect_add_gradient_stop(rect4, 1.0f, gui_rgba(128, 0, 255, 255)); // Purple
// Example 5: Multi-color rainbow horizontal gradient
gui_rounded_rect_t *rect5 = gui_rect_create(parent, "rect_rainbow",
20, 260, 420, 60, 20,
gui_rgba(255, 0, 0, 255));
gui_rect_set_linear_gradient(rect5, RECT_GRADIENT_HORIZONTAL);
gui_rect_add_gradient_stop(rect5, 0.00f, gui_rgba(255, 0, 0, 255)); // Red
gui_rect_add_gradient_stop(rect5, 0.17f, gui_rgba(255, 127, 0, 255)); // Orange
gui_rect_add_gradient_stop(rect5, 0.33f, gui_rgba(255, 255, 0, 255)); // Yellow
gui_rect_add_gradient_stop(rect5, 0.50f, gui_rgba(0, 255, 0, 255)); // Green
gui_rect_add_gradient_stop(rect5, 0.67f, gui_rgba(0, 0, 255, 255)); // Blue
gui_rect_add_gradient_stop(rect5, 0.83f, gui_rgba(75, 0, 130, 255)); // Indigo
gui_rect_add_gradient_stop(rect5, 1.00f, gui_rgba(148, 0, 211, 255)); // Violet
// Example 6: Gradient with transparency
gui_rounded_rect_t *rect6 = gui_rect_create(parent, "rect_alpha_gradient",
20, 340, 200, 80, 10,
gui_rgba(0, 128, 255, 255));
gui_rect_set_linear_gradient(rect6, RECT_GRADIENT_HORIZONTAL);
gui_rect_add_gradient_stop(rect6, 0.0f, gui_rgba(0, 128, 255, 255)); // Opaque blue
gui_rect_add_gradient_stop(rect6, 1.0f, gui_rgba(0, 128, 255, 50)); // Transparent blue
}
static void app_rect_round_design(gui_view_t *view)
{
gui_view_switch_on_event(view, "rect_view", SWITCH_OUT_ANIMATION_FADE,
SWITCH_IN_ANIMATION_FADE,
GUI_EVENT_TOUCH_CLICKED);
gui_view_set_animate_step(view, 500);
uint8_t alpha = 200;
gui_rect_create(gui_obj_get_root(), "bg", 0, 0, 480, 480, 0, gui_rgba(255, 200, 200,
255));
gui_rounded_rect_t *geometry1 = gui_rect_create(gui_obj_get_root(), "geometry1",
20, 20, 200, 200, 20,
gui_rgba(255, 0, 0, alpha));
gui_rect_set_stroke(geometry1, 6.0f, gui_rgba(255, 255, 255, 255));
gui_rect_create(gui_obj_get_root(), "geometry2", 50, 50, 200, 200, 20, gui_rgba(0, 255,
0, alpha));
gui_rect_create(gui_obj_get_root(), "geometry3", 80, 80, 200, 200, 20, gui_rgba(0, 0,
255, alpha));
gui_rect_create(gui_obj_get_root(), "geometry4", 150, 150, 200, 200, 20, gui_rgba(255, 0,
0, alpha));
gui_rect_create(gui_obj_get_root(), "geometry5", 210, 210, 200, 200, 20, gui_rgba(0, 255,
0, alpha));
// rect_click_demo();
// example_rect_gradient(gui_obj_get_root());
}
static int geometry_rect_demo_init(void)
{
gui_view_create(gui_obj_get_root(), RECT_VIEW_NAME, 0, 0, 0, 0);
// Uncomment to show gradient examples
return 0;
}
GUI_VIEW_INSTANCE(RECT_VIEW_NAME, false, app_rect_round_design, 0);
GUI_INIT_APP_EXPORT(geometry_rect_demo_init);
API
Enums
Functions
-
gui_rounded_rect_t *gui_rect_create(void *parent, const char *name, int x, int y, int w, int h, int radius, gui_color_t color)
Create a new rect widget.
- Parameters:
parent -- Parent widget or NULL for root widget.
name -- Widget name or NULL for default name.
x -- X coordinate relative to widget.
y -- Y coordinate relative to widget.
w -- Rect width.
h -- Rect height.
radius -- Rect radius.
color -- Rect color.
- Returns:
Pointer to the created rect widget.
-
void gui_rect_set_style(gui_rounded_rect_t *rect, int x, int y, int w, int h, int radius, gui_color_t color)
Set the style of the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
x -- X coordinate relative to widget.
y -- Y coordinate relative to widget.
w -- Rect width.
h -- Rect height.
radius -- Rect radius.
color -- Rect color.
-
void gui_rect_set_opacity(gui_rounded_rect_t *rect, uint8_t opacity)
Set the opacity of the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
opacity -- Opacity value (0-255).
-
void gui_rect_set_position(gui_rounded_rect_t *rect, int x, int y)
Set the position of the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
x -- X coordinate relative to widget.
y -- Y coordinate relative to widget.
-
void gui_rect_set_size(gui_rounded_rect_t *rect, int w, int h)
Set the size of the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
w -- Rect width.
h -- Rect height.
-
void gui_rect_set_radius(gui_rounded_rect_t *rect, int radius)
Set the radius of the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
radius -- Rect radius.
-
void gui_rect_set_color(gui_rounded_rect_t *rect, gui_color_t color)
Set the color of the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
color -- Rect color.
-
void gui_rect_set_stroke(gui_rounded_rect_t *rect, float width, gui_color_t color)
Set an inset stroke for the rect.
- Parameters:
rect -- Pointer to the rect widget.
width -- Stroke width in pixels. A non-positive value disables stroke.
color -- Stroke color.
-
void gui_rect_clear_stroke(gui_rounded_rect_t *rect)
Disable the rect stroke.
- Parameters:
rect -- Pointer to the rect widget.
-
void gui_rect_set_glow(gui_rounded_rect_t *rect, gui_color_t color, uint8_t blur_radius)
Draw an outer glow around the rect.
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 size, radius or blur radius rebuilds it.
- Parameters:
rect -- Pointer to the rect widget.
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_rect_clear_glow(gui_rounded_rect_t *rect)
Remove the rect's outer glow.
- Parameters:
rect -- Pointer to the rect widget.
-
void gui_rect_on_click(gui_rounded_rect_t *rect, void *callback, void *parameter)
Register a click event callback for the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
callback -- Callback function pointer.
parameter -- Optional parameter to pass to the callback.
-
void gui_rect_rotate(gui_rounded_rect_t *rect, float degrees)
Apply rotation transformation to the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
degrees -- Rotation angle in degrees (clockwise).
-
void gui_rect_scale(gui_rounded_rect_t *rect, float scale_x, float scale_y)
Apply scale transformation to the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
scale_x -- Scale factor in X direction.
scale_y -- Scale factor in Y direction.
-
void gui_rect_translate(gui_rounded_rect_t *rect, float tx, float ty)
Apply translation transformation to the rect widget.
- Parameters:
rect -- Pointer to the rect widget.
tx -- Translation in X direction (pixels).
ty -- Translation in Y direction (pixels).
-
void gui_rect_set_linear_gradient(gui_rounded_rect_t *rect, gui_rect_gradient_dir_t direction)
Set linear gradient for rect widget.
- Parameters:
rect -- Pointer to the rect widget.
direction -- Gradient direction (horizontal, vertical, diagonal).
-
void gui_rect_add_gradient_stop(gui_rounded_rect_t *rect, float position, gui_color_t color)
Add color stop to rect gradient.
- Parameters:
rect -- Pointer to the rect widget.
position -- Position of color stop (0.0 to 1.0).
color -- Color at rect stop.
-
void gui_rect_clear_gradient(gui_rounded_rect_t *rect)
Clear gradient and use solid color.
- Parameters:
rect -- Pointer to the rect widget.
-
void gui_rect_set_dither(gui_rounded_rect_t *rect, bool enable)
Enable or disable dithering for gradient.
Note
Dithering reduces color banding but may impact performance.
- Parameters:
rect -- Pointer to the rect widget.
enable -- true to enable dithering, false to disable.
-
struct gui_rounded_rect_t
Rect widget structure.
Public Members
-
gui_obj_t base
Base widget.
-
gui_geometry_parts_t parts
Non-overlapping pieces: four corners, up to three runs (stroke, stroke/fill edge, fill) along each of the four sides, and the centre.
-
uint8_t opacity_value
Opacity value.
-
int radius
Rect radius.
-
gui_color_t color
Rect color.
-
float stroke_width
Inset stroke width. Zero disables stroke.
-
gui_color_t stroke_color
Stroke color.
-
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 rect fill.
-
bool use_gradient
Flag to enable gradient rendering.
-
bool enable_dither
Flag to enable dithering for gradient.
-
gui_rect_gradient_dir_t gradient_dir
Gradient direction.
-
gui_matrix_t last_matrix
Cached matrix for change detection.
-
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.
-
gui_obj_t base
-
struct rect_desc_t
Identity of a cached rect payload.
Everything that changes a pixel goes in here and nothing else does; 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 rect_desc_len().
Public Members
-
uint32_t part
gui_rect_part_t.
-
int32_t size_a
Width, or side length for a corner.
-
int32_t size_b
Height, or corner index for a corner.
-
int32_t radius
Corner radius.
-
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 flags
Dither on/off, and gradient direction plus 1.
-
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 flags say a gradient is used.
-
uint32_t part
-
struct rect_geom_t
Geometry shared by every piece of one rect.
straightis where the edges stop curving: past it, rows and columns are uniform along the edge, which is what lets the split draw them as solid rectangles.Public Members
-
int w
Rect width.
-
int h
Rect height.
-
int radius
Effective corner radius.
-
float stroke
Stroke width, clamped to the rect.
-
float inner_w
Width inside the stroke.
-
float inner_h
Height inside the stroke.
-
float inner_radius
Corner radius inside the stroke.
-
int straight
Corner square side: max(radius, stroke), rounded up.
-
int w