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

gui_rect_create()

Set Style

gui_rect_set_style()

Set Position

gui_rect_set_position()

Set Size

gui_rect_set_size()

Set Color

gui_rect_set_color()

Set Stroke

gui_rect_set_stroke()

Clear Stroke

gui_rect_clear_stroke()

Set Glow

gui_rect_set_glow()

Clear Glow

gui_rect_clear_glow()

Set Opacity

gui_rect_set_opacity()

Register Click Event Callback

gui_rect_on_click()

Rotation Transform

gui_rect_rotate()

Scale Transform

gui_rect_scale()

Translation Transform

gui_rect_translate()

Set Linear Gradient

gui_rect_set_linear_gradient()

Add Gradient Stop

gui_rect_add_gradient_stop()

Clear Gradient

gui_rect_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_radius is 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

  1. Create a rounded rectangle widget

  2. Call gui_rect_set_linear_gradient() to set the gradient direction

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

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

enum gui_rect_gradient_dir_t

Rect gradient direction

Values:

enumerator RECT_GRADIENT_HORIZONTAL

Left to right

enumerator RECT_GRADIENT_VERTICAL

Top to bottom

enumerator RECT_GRADIENT_DIAGONAL_TL_BR

Top-left to bottom-right

enumerator RECT_GRADIENT_DIAGONAL_TR_BL

Top-right to bottom-left

enum gui_rect_part_t

Which rasterised part a cached payload holds.

Values:

enumerator RECT_PART_ROUNDED

Whole rounded rect in one buffer.

enumerator RECT_PART_CORNER

One rounded corner, keyed by corner index.

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.

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.

struct rect_geom_t

Geometry shared by every piece of one rect.

straight is 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.