Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions include/iui.h
Original file line number Diff line number Diff line change
Expand Up @@ -3245,14 +3245,16 @@ int iui_a11y_describe(const iui_a11y_hint *hint, char *buf, size_t buf_size);

/* Performance Optimization API
*
* Three core performance systems (always available, disabled by default):
* Four core performance systems (always available, disabled by default):
* 1. Draw Call Batching - buffers draw commands to reduce state changes
* 2. Dirty Rectangle Tracking - skips redrawing unchanged regions
* 3. Text Width Caching - caches text measurement results
* 3. Ink-Bounds Tracking - tracks union bounding box of all draw calls
* 4. Text Width Caching - caches text measurement results
*
* Usage:
* iui_batch_enable(ctx, true); // Enable draw batching
* iui_dirty_enable(ctx, true); // Enable dirty rect tracking
* iui_ink_bounds_enable(ctx, true); // Enable ink-bounds tracking
* iui_text_cache_enable(ctx, true); // Enable text cache
*/

Expand Down Expand Up @@ -3291,6 +3293,21 @@ void iui_dirty_invalidate_all(iui_context *ctx);
*/
int iui_dirty_count(const iui_context *ctx);

/* Ink-Bounds Tracking
* Tracks the union bounding box of all draw calls within a frame.
* When enabled, backends can query the drawn region to blit only the
* ink-bounds area instead of the full framebuffer.
*/
void iui_ink_bounds_enable(iui_context *ctx, bool enable);

/* Query the ink-bounds rectangle for the current frame.
* Returns false if no draw calls were made this frame.
*/
bool iui_ink_bounds_get(const iui_context *ctx, iui_rect_t *out);

/* Check if any draw calls were made this frame */
bool iui_ink_bounds_valid(const iui_context *ctx);

/* Text Width Caching
* Enable/disable text measurement caching. When enabled, text width
* calculations are cached to avoid redundant measurements.
Expand Down
18 changes: 9 additions & 9 deletions src/appbar.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ bool iui_top_app_bar(iui_context *ctx,

/* Draw background (no corner radius for app bar) */
iui_rect_t bar_rect = {bar_x, bar_y, bar_width, bar_height};
ctx->renderer.draw_box(bar_rect, 0.f, bg_color, ctx->renderer.user);
iui_emit_box(ctx, bar_rect, 0.f, bg_color);

/* Draw elevation shadow if scrolled (Level 2) */
if (collapse_progress > 0.f) {
Expand Down Expand Up @@ -108,13 +108,13 @@ bool iui_top_app_bar(iui_context *ctx,
if (nav_pressed) {
uint32_t state_color =
iui_state_layer(icon_color, IUI_STATE_PRESS_ALPHA);
ctx->renderer.draw_box(nav_rect, IUI_APPBAR_ICON_BUTTON_SIZE * 0.5f,
state_color, ctx->renderer.user);
iui_emit_box(ctx, nav_rect, IUI_APPBAR_ICON_BUTTON_SIZE * 0.5f,
state_color);
} else if (nav_hovered) {
uint32_t state_color =
iui_state_layer(icon_color, IUI_STATE_HOVER_ALPHA);
ctx->renderer.draw_box(nav_rect, IUI_APPBAR_ICON_BUTTON_SIZE * 0.5f,
state_color, ctx->renderer.user);
iui_emit_box(ctx, nav_rect, IUI_APPBAR_ICON_BUTTON_SIZE * 0.5f,
state_color);
}

/* Draw menu icon */
Expand Down Expand Up @@ -237,13 +237,13 @@ bool iui_top_app_bar_action(iui_context *ctx, const char *icon)
if (pressed) {
uint32_t state_color =
iui_state_layer(icon_color, IUI_STATE_PRESS_ALPHA);
ctx->renderer.draw_box(action_rect, IUI_APPBAR_ICON_BUTTON_SIZE * 0.5f,
state_color, ctx->renderer.user);
iui_emit_box(ctx, action_rect, IUI_APPBAR_ICON_BUTTON_SIZE * 0.5f,
state_color);
} else if (hovered) {
uint32_t state_color =
iui_state_layer(icon_color, IUI_STATE_HOVER_ALPHA);
ctx->renderer.draw_box(action_rect, IUI_APPBAR_ICON_BUTTON_SIZE * 0.5f,
state_color, ctx->renderer.user);
iui_emit_box(ctx, action_rect, IUI_APPBAR_ICON_BUTTON_SIZE * 0.5f,
state_color);
}

/* Draw action icon */
Expand Down
78 changes: 37 additions & 41 deletions src/basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ void iui_segmented(iui_context *ctx,
*selected = 0;

/* MD3: Draw unified pill background (visible container for all segments) */
ctx->renderer.draw_box(
(iui_rect_t) {seg_x_start, seg_y, ctx->layout.width, seg_height},
pill_radius, ctx->colors.surface_container_highest, ctx->renderer.user);
iui_emit_box(
ctx, (iui_rect_t) {seg_x_start, seg_y, ctx->layout.width, seg_height},
pill_radius, ctx->colors.surface_container_highest);

/* Track component for MD3 validation */
IUI_MD3_TRACK_SEGMENTED(
Expand All @@ -63,9 +63,8 @@ void iui_segmented(iui_context *ctx,
if (*selected == 0 || *selected == num_entries - 1)
corner = pill_radius;

ctx->renderer.draw_box(
(iui_rect_t) {sel_x, seg_y, seg_width, seg_height}, corner,
ctx->colors.secondary_container, ctx->renderer.user);
iui_emit_box(ctx, (iui_rect_t) {sel_x, seg_y, seg_width, seg_height},
corner, ctx->colors.secondary_container);
}

/* Draw each segment */
Expand All @@ -92,9 +91,9 @@ void iui_segmented(iui_context *ctx,
uint32_t hover_color = iui_state_layer(
ctx->colors.on_surface, iui_state_get_alpha(seg_state));
float corner = (i == 0 || i == num_entries - 1) ? pill_radius : 0.f;
ctx->renderer.draw_box(
(iui_rect_t) {seg_x, seg_y, seg_width, seg_height}, corner,
hover_color, ctx->renderer.user);
iui_emit_box(ctx,
(iui_rect_t) {seg_x, seg_y, seg_width, seg_height},
corner, hover_color);
}

/* Handle selection change */
Expand Down Expand Up @@ -288,16 +287,15 @@ float iui_slider_ex(iui_context *ctx,
iui_get_component_state(ctx, touch_rect, disabled);

/* Draw inactive track (full width, behind active track) */
ctx->renderer.draw_box(track_rect, track_rect.height * .5f, inactive_color,
ctx->renderer.user);
iui_emit_box(ctx, track_rect, track_rect.height * .5f, inactive_color);

/* Draw active track (left side up to thumb) */
float active_width = thumb_x - track_rect.x;
if (active_width > 0) {
ctx->renderer.draw_box((iui_rect_t) {track_rect.x, track_rect.y,
active_width, track_rect.height},
track_rect.height * .5f, active_color,
ctx->renderer.user);
iui_emit_box(ctx,
(iui_rect_t) {track_rect.x, track_rect.y, active_width,
track_rect.height},
track_rect.height * .5f, active_color);
}

/* Handle thumb interaction */
Expand Down Expand Up @@ -379,9 +377,9 @@ float iui_slider_ex(iui_context *ctx,
uint8_t alpha =
is_dragging ? IUI_STATE_DRAG_ALPHA : IUI_STATE_HOVER_ALPHA;
uint32_t state_color = iui_state_layer(handle_color, alpha);
ctx->renderer.draw_box(
(iui_rect_t) {state_x, state_y, state_size, state_size},
state_size * 0.5f, state_color, ctx->renderer.user);
iui_emit_box(ctx,
(iui_rect_t) {state_x, state_y, state_size, state_size},
state_size * 0.5f, state_color);
}

/* Draw value indicator bubble during drag */
Expand Down Expand Up @@ -415,10 +413,10 @@ float iui_slider_ex(iui_context *ctx,
}

/* Draw indicator background (pill shape with primary color) */
ctx->renderer.draw_box((iui_rect_t) {indicator_x, indicator_y,
indicator_width, indicator_height},
indicator_height * 0.5f, active_color,
ctx->renderer.user);
iui_emit_box(ctx,
(iui_rect_t) {indicator_x, indicator_y, indicator_width,
indicator_height},
indicator_height * 0.5f, active_color);

/* Draw value text centered in indicator */
iui_rect_t indicator_text_rect = {
Expand All @@ -439,8 +437,7 @@ float iui_slider_ex(iui_context *ctx,
}

/* Draw thumb (circle) */
ctx->renderer.draw_box(thumb_rect, half_size, handle_color,
ctx->renderer.user);
iui_emit_box(ctx, thumb_rect, half_size, handle_color);

iui_newline(ctx);

Expand Down Expand Up @@ -636,16 +633,15 @@ bool iui_range_slider(iui_context *ctx,
thumb_high_x = norm_high * track_rect.width + track_rect.x;

/* Draw inactive track (full width) */
ctx->renderer.draw_box(track_rect, track_height * 0.5f, inactive_color,
ctx->renderer.user);
iui_emit_box(ctx, track_rect, track_height * 0.5f, inactive_color);

/* Draw active track (between thumbs) */
float active_x = thumb_low_x;
float active_w = thumb_high_x - thumb_low_x;
if (active_w > 0.f) {
ctx->renderer.draw_box(
(iui_rect_t) {active_x, track_rect.y, active_w, track_height},
track_height * 0.5f, active_color, ctx->renderer.user);
iui_emit_box(
ctx, (iui_rect_t) {active_x, track_rect.y, active_w, track_height},
track_height * 0.5f, active_color);
}

/* State layers on hover/drag */
Expand All @@ -660,9 +656,10 @@ bool iui_range_slider(iui_context *ctx,
uint8_t alpha =
dragging ? IUI_STATE_DRAG_ALPHA : IUI_STATE_HOVER_ALPHA;
uint32_t sc = iui_state_layer(handle_color, alpha);
ctx->renderer.draw_box(
iui_emit_box(
ctx,
(iui_rect_t) {tx - ss * 0.5f, center_y - ss * 0.5f, ss, ss},
ss * 0.5f, sc, ctx->renderer.user);
ss * 0.5f, sc);
}
}

Expand All @@ -672,14 +669,16 @@ bool iui_range_slider(iui_context *ctx,
float draw_size_low = draw_half_low * 2.f;
float draw_size_high = draw_half_high * 2.f;

ctx->renderer.draw_box(
iui_emit_box(
ctx,
(iui_rect_t) {thumb_low_x - draw_half_low, center_y - draw_half_low,
draw_size_low, draw_size_low},
draw_half_low, handle_color, ctx->renderer.user);
ctx->renderer.draw_box(
draw_half_low, handle_color);
iui_emit_box(
ctx,
(iui_rect_t) {thumb_high_x - draw_half_high, center_y - draw_half_high,
draw_size_high, draw_size_high},
draw_half_high, handle_color, ctx->renderer.user);
draw_half_high, handle_color);

/* MD3 validation */
IUI_MD3_TRACK_SLIDER(touch_low, touch_low.height * 0.5f);
Expand Down Expand Up @@ -883,17 +882,14 @@ bool iui_button_styled(iui_context *ctx,
iui_draw_focus_ring(ctx, button_rect, corner);

if (bg_color != 0) {
ctx->renderer.draw_box(button_rect, corner, bg_color,
ctx->renderer.user);
iui_emit_box(ctx, button_rect, corner, bg_color);
} else if (is_focused && focus_layer != 0) {
/* MD3: Show focus state layer for text/outlined buttons (no bg) */
ctx->renderer.draw_box(button_rect, corner, focus_layer,
ctx->renderer.user);
iui_emit_box(ctx, button_rect, corner, focus_layer);
} else if (state == IUI_STATE_HOVERED && hover_layer != 0) {
/* MD3: Text buttons show state layer on hover (no bg, but visible
* hover) */
ctx->renderer.draw_box(button_rect, corner, hover_layer,
ctx->renderer.user);
iui_emit_box(ctx, button_rect, corner, hover_layer);
}

/* Draw border if specified (for outlined buttons) */
Expand Down
Loading
Loading