6 ex__gui__round_8c
gullradriel edited this page 2026-10-09 00:55:18 +02:00

examples/ex_gui_round.c

Functions

Name
void run(ALLEGRO_FONT * font, int mode, const char * name)
draw one frameless window holding a text area and a checkbox, in the given shape mode, and check each shape's corner
int process_args(int argc, char ** argv)
parse -V LOG_LEVEL
int main(int argc, char ** argv)
int is_rgb(ALLEGRO_BITMAP * bmp, int x, int y, unsigned char r, unsigned char g, unsigned char b)
is pixel (x, y) exactly this colour?
N_GUI_THEME flat(unsigned char r, unsigned char g, unsigned char b)
a flat theme in one colour: fill and border alike, so a shape is one colour and its bounding box is the shape
void expect_true(const char * what, int ok)
record one check
int corner_is_colour(ALLEGRO_BITMAP * bmp, int x0, int y0, int x1, int y1, unsigned char r, unsigned char g, unsigned char b)
whether the top-left corner of a colour's bounding box (searched in a region) is that colour: 1 square, 0 rounded, -1 colour absent

Attributes

Name
int log_level
int failures

Defines

Name
ALLEGRO_UNSTABLE

Functions Documentation

function run

static void run(
    ALLEGRO_FONT * font,
    int mode,
    const char * name
)

draw one frameless window holding a text area and a checkbox, in the given shape mode, and check each shape's corner

function process_args

static int process_args(
    int argc,
    char ** argv
)

parse -V LOG_LEVEL

function main

int main(
    int argc,
    char ** argv
)

function is_rgb

static int is_rgb(
    ALLEGRO_BITMAP * bmp,
    int x,
    int y,
    unsigned char r,
    unsigned char g,
    unsigned char b
)

is pixel (x, y) exactly this colour?

function flat

static N_GUI_THEME flat(
    unsigned char r,
    unsigned char g,
    unsigned char b
)

a flat theme in one colour: fill and border alike, so a shape is one colour and its bounding box is the shape

function expect_true

static void expect_true(
    const char * what,
    int ok
)

record one check

function corner_is_colour

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
)

whether the top-left corner of a colour's bounding box (searched in a region) is that colour: 1 square, 0 rounded, -1 colour absent

Attributes Documentation

variable log_level

static int log_level = 3;

variable failures

static int failures = 0;

Macros Documentation

define ALLEGRO_UNSTABLE

#define ALLEGRO_UNSTABLE 1

Source code



#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;
}