5 ex_gui_round_8c example
gullradriel edited this page 2026-10-09 00:51:57 +02:00

ex_gui_round.c

n_gui: a round GUI rounds the widgets that have no shape of their own Buttons and comboboxes have a shape; text areas, checkboxes, a frameless window's body and the combobox dropdown did not, and stayed square under n_gui_set_shape_mode(N_GUI_SHAPE_ROUNDED): a round GUI still had square fields, square check boxes, and card windows whose square fill showed its corners outside their rounded outline. They now round when, and only when, the context asks for a round GUI.

Headless: the window is drawn into a memory bitmap and read back. Each shape is painted in a colour of its own; the check finds that colour's bounding box and looks at the box's own corner pixel, which is the colour when the shape is square and is not when it is rounded. Every case runs twice, in the default shape mode (where it must stay square: no existing program may change under it) and in N_GUI_SHAPE_ROUNDED. ```c

#define ALLEGRO_UNSTABLE 1

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>

#include "nilorea/n_common.h" #include "nilorea/n_log.h" #include "nilorea/n_gui.h"

#include <allegro5/allegro_primitives.h>

static int log_level = LOG_ERR; static int failures = 0;

static void expect_true(const char* what, int ok) { if (!ok) { n_log(LOG_ERR, "FAIL: %s", what); failures++; } else { n_log(LOG_INFO, "ok: %s", what); } }

static int process_args(int argc, char** argv) { int opt = 0;

while ((opt = getopt(argc, argv, "V:")) != -1) {
    if (opt == 'V') {
        log_level = atoi(optarg);
    } else {
        return -1;
    }
}
return 0;

}

static N_GUI_THEME flat(unsigned char r, unsigned char g, unsigned char b) { ALLEGRO_COLOR c = al_map_rgb(r, g, b); return n_gui_make_theme(c, c, c, c, c, c, al_map_rgb(0, 0, 0), al_map_rgb(0, 0, 0), al_map_rgb(0, 0, 0), 1.0f, 10.0f, 10.0f); }

static int is_rgb(ALLEGRO_BITMAP* bmp, int x, int y, unsigned char r, unsigned char g, unsigned char b) { unsigned char pr = 0, pg = 0, pb = 0; al_unmap_rgb(al_get_pixel(bmp, x, y), &pr, &pg, &pb); return pr == r && pg == g && pb == b; }

static int corner_is_colour(ALLEGRO_BITMAP* bmp, int x0, int y0, int x1, int y1, unsigned char r, unsigned char g, unsigned char b) { int minx = x1, miny = y1, x, y; for (y = y0; y < y1; y++) for (x = x0; x < x1; x++) if (is_rgb(bmp, x, y, r, g, b)) { if (x < minx) minx = x; if (y < miny) miny = y; } if (minx == x1 || miny == y1) return -1; /* one pixel in from the box's corner: an outline drawn on the shape's * edge reaches half a pixel past a square fill, so the exact corner can * be neither; one pixel in is inside a square shape and, at the radius * of 10 used here (12.7 px from the arc's centre), outside a rounded one */ return is_rgb(bmp, minx + 1, miny + 1, r, g, b); }

static void run(ALLEGRO_FONT* font, int mode, const char* name) { char what[128]; int rounded = (mode == N_GUI_SHAPE_ROUNDED); N_GUI_CTX* gui = n_gui_new_ctx(font); ALLEGRO_BITMAP* target = NULL; int old = al_get_new_bitmap_flags(); int win, ta, cb, r;

if (!gui) {
    expect_true("context", 0);
    return;
}
if (mode != -1) n_gui_set_shape_mode(gui, mode);
n_gui_set_display_size(gui, 400.0f, 300.0f);
n_gui_set_default_theme(gui, flat(0, 160, 0)); /* the window: green */
win = n_gui_add_window(gui, "", 50.0f, 50.0f, 300.0f, 200.0f);
n_gui_window_set_flags(gui, win, N_GUI_WIN_FRAMELESS | N_GUI_WIN_FIXED_POSITION);
ta = n_gui_add_textarea(gui, win, 20.0f, 20.0f, 200.0f, 40.0f, 0, 32, NULL, NULL);
n_gui_set_widget_theme(gui, ta, flat(200, 0, 0)); /* red */
cb = n_gui_add_checkbox(gui, win, "", 20.0f, 100.0f, 200.0f, 40.0f, 0, NULL, NULL);
n_gui_set_widget_theme(gui, cb, flat(220, 220, 0)); /* yellow */

al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
target = al_create_bitmap(400, 300);
al_set_new_bitmap_flags(old);
if (!target) {
    expect_true("memory bitmap", 0);
    n_gui_destroy_ctx(&gui);
    return;
}
al_set_target_bitmap(target);
al_clear_to_color(al_map_rgb(0, 0, 160)); /* the screen: blue */
n_gui_draw(gui);

/* the window body: its own top-left corner */
r = corner_is_colour(target, 40, 40, 360, 260, 0, 160, 0);
snprintf(what, sizeof(what), "%s: window body %s", name, rounded ? "rounded" : "square");
expect_true(what, r == (rounded ? 0 : 1));
/* the text area, inside the window */
r = corner_is_colour(target, 60, 60, 300, 120, 200, 0, 0);
snprintf(what, sizeof(what), "%s: text area %s", name, rounded ? "rounded" : "square");
expect_true(what, r == (rounded ? 0 : 1));
/* the checkbox's box */
r = corner_is_colour(target, 60, 140, 300, 200, 220, 220, 0);
snprintf(what, sizeof(what), "%s: checkbox %s", name, rounded ? "rounded" : "square");
expect_true(what, r == (rounded ? 0 : 1));

al_set_target_bitmap(NULL);
al_destroy_bitmap(target);
n_gui_destroy_ctx(&gui);

}

int main(int argc, char** argv) { set_log_level(LOG_ERR); if (process_args(argc, argv) != 0) { fprintf(stderr, "usage: %s [-V LOG_LEVEL]\n", argv[0]); return 1; } set_log_level(log_level);

if (!al_init() || !al_init_font_addon() || !al_init_primitives_addon()) {
    n_log(LOG_ERR, "allegro init failed");
    return 1;
}
ALLEGRO_FONT* font = al_create_builtin_font();
if (!font) return 1;

run(font, -1, "default mode");
run(font, N_GUI_SHAPE_RECT, "RECT mode");
run(font, N_GUI_SHAPE_ROUNDED, "ROUNDED mode");

al_destroy_font(font);
if (failures) {
    fprintf(stderr, "ex_gui_round: %d failure(s)\n", failures);
    return 1;
}
printf("ex_gui_round: all checks passed\n");
return 0;

}


_Filename: ex_gui_round.c_