xolatilization/xommon.h

667 lines
30 KiB
C
Executable File

/// __ _____ _ __ ___ _ __ ___ ___ _ __
/// \ \/ / _ \| '_ ` _ \| '_ ` _ \ / _ \| '_ \
/// > < (_) | | | | | | | | | | | (_) | | | |
/// /_/\_\___/|_| |_| |_|_| |_| |_|\___/|_| |_|
///
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
///
/// xolatile@chud.cyou - xommon - Tiny and elegant XCB wrapper library so I don't have to deal with other people decisions.
///
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
///
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
/// for more details, if you dare, it is a lot of text that nobody wants to read...
#include <xcb/xcb.h>
#include <xcb/xcb_atom.h>
#include <xcb/xcb_image.h>
//~#include <xcb/composite.h>
#define common_font_width (8)
#define common_font_height (16)
#define common_font_tabulator (4)
#ifndef common_gameplay_framerate
#define common_gameplay_framerate (60)
#endif
#ifndef common_animation_framerate
#define common_animation_framerate (3)
#endif
typedef enum {
common_window_fullscreen = 0x1,
common_window_transparent = 0x2,
common_window_resizable = 0x4,
common_window_decorated = 0x8
} common_window_flag;
typedef struct {
xcb_connection_t * connection;
xcb_screen_t * screen;
xcb_image_t * image;
xcb_window_t window;
xcb_gcontext_t context;
xcb_pixmap_t pixmap;
boolean signal [signal_count];
boolean cursor [cursor_count];
boolean active;
natural window_width;
natural window_height;
natural framerate;
natural_64 frame_time;
natural_64 frame_begin;
natural_64 frame_end;
natural * framebuffer;
natural global_tick;
natural gameplay_tick;
natural animation_tick;
integer cursor_x;
integer cursor_y;
boolean freeze_cursor;
boolean freeze_signal;
natural sprite_count;
natural font_count;
natural dummy; /// TODO USE ME PLEASE
natural * * sprite_data;
natural * sprite_width;
natural * sprite_height;
natural * * font_index;
natural * * font_width;
natural * * font_height;
character * font_begin;
character * font_end;
} common_structure;
static natural common_center_x (common_structure * common, natural size) {
return ((common->window_width - size) / 2);
}
static natural common_center_y (common_structure * common, natural size) {
return ((common->window_height - size) / 2);
}
static boolean common_cursor_inside (common_structure * common, integer x, integer y, natural width, natural height) {
return ((common->cursor_x > x)
&& (common->cursor_y > y)
&& (common->cursor_x < x + (integer) width)
&& (common->cursor_y < y + (integer) height));
}
static boolean common_cursor_left_click (common_structure * common, integer x, integer y, natural width, natural height) {
if (common->cursor [cursor_left] == true) {
common->freeze_cursor = true;
return (common_cursor_inside (common, x, y, width, height) == true);
}
return (false);
}
static boolean common_cursor_right_click (common_structure * common, integer x, integer y, natural width, natural height) {
if (common->cursor [cursor_right]) {
common->freeze_cursor = true;
return (common_cursor_inside (common, x, y, width, height));
}
return (false);
}
static natural common_sprite_raw_import (common_structure * common, natural * data, natural width, natural height) {
++common->sprite_count;
common->sprite_data = reallocate (common->sprite_data, common->sprite_count * sizeof (* common->sprite_data));
common->sprite_width = reallocate (common->sprite_width, common->sprite_count * sizeof (* common->sprite_width));
common->sprite_height = reallocate (common->sprite_height, common->sprite_count * sizeof (* common->sprite_height));
common->sprite_data [common->sprite_count - 1] = data;
common->sprite_width [common->sprite_count - 1] = width;
common->sprite_height [common->sprite_count - 1] = height;
return (common->sprite_count - 1);
}
static natural common_font_raw_import (common_structure * common, natural * data, natural image_width, character begin, character end, natural empty) {
natural pointer = 0;
natural width = 0;
natural height = 0;
natural * buffer = null;
++common->font_count;
common->font_index = reallocate (common->font_index, common->font_count * sizeof (* common->font_index));
common->font_width = reallocate (common->font_width, common->font_count * sizeof (* common->font_width));
common->font_height = reallocate (common->font_height, common->font_count * sizeof (* common->font_height));
common->font_begin = reallocate (common->font_begin, common->font_count * sizeof (* common->font_begin));
common->font_end = reallocate (common->font_end, common->font_count * sizeof (* common->font_end));
common->font_begin [common->font_count - 1] = begin;
common->font_end [common->font_count - 1] = end;
common->font_index [common->font_count - 1] = allocate ((caliber) (end - begin + 1) * sizeof (* * common->font_index));
common->font_width [common->font_count - 1] = allocate ((caliber) (end - begin + 1) * sizeof (* * common->font_width));
common->font_height [common->font_count - 1] = allocate ((caliber) (end - begin + 1) * sizeof (* * common->font_height));
for (character index = begin; index <= end; ++index) {
for ( ; data [pointer] == empty; ++pointer);
for (width = 0; data [pointer + width] != empty; ++width);
for (height = 0; data [pointer + height * image_width] != empty; ++height);
buffer = allocate (width * height * sizeof (* buffer));
for (natural y = 0; y < height; ++y) {
for (natural x = 0; x < width; ++x) {
buffer [y * width + x] = data [pointer + (y * image_width) + x];
}
}
common->font_index [common->font_count - 1] [index - begin] = common_sprite_raw_import (common, buffer, width, height);
common->font_width [common->font_count - 1] [index - begin] = width;
common->font_height [common->font_count - 1] [index - begin] = height;
pointer += width;
for (; data [pointer] == empty; ++pointer);
if (pointer % image_width == 2) {
pointer += height * image_width;
}
}
return (common->font_count - 1);
}
static natural common_sprite_import (common_structure * common, character * path) {
natural width = 0;
natural height = 0;
natural * data = null;
character buffer [256] = "";
#ifdef use_png_library
if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true)) {
data = png_image_import (buffer, & width, & height);
}
#endif
#ifdef use_jxl_library
if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true)) {
data = jxl_image_import (buffer, & width, & height);
}
#endif
fatal_failure (data == null, "opengl_sprite_import: Unsupported image format.");
return (common_sprite_raw_import (common, data, width, height));
}
static natural common_font_import (common_structure * common, character * path, character begin, character end, natural colour) {
natural width = 0;
natural height = 0;
natural result = 0;
natural * data = null;
character buffer [256] = "";
#ifdef use_png_library
if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true)) {
data = png_image_import (buffer, & width, & height);
}
#endif
#ifdef use_jxl_library
if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true)) {
data = jxl_image_import (buffer, & width, & height);
}
#endif
fatal_failure (data == null, "opengl_font_import: Unsupported image format.");
result = common_font_raw_import (common, data, width, begin, end, colour);
data = deallocate (data);
return (result);
}
static natural common_sprite_width (common_structure * common, natural sprite) {
return (common->sprite_width [sprite]);
}
static natural common_sprite_height (common_structure * common, natural sprite) {
return (common->sprite_height [sprite]);
}
static common_structure * common_initialize (none) {
common_structure * common = allocate (sizeof (* common));
return (common);
}
static common_structure * common_deinitialize (common_structure * common) {
for (natural index = 0; index < common->sprite_count; ++index) {
common->sprite_data [index] = deallocate (common->sprite_data [index]);
}
for (natural index = 0; index < common->font_count; ++index) {
common->font_index [index] = deallocate (common->font_index [index]);
common->font_width [index] = deallocate (common->font_width [index]);
common->font_height [index] = deallocate (common->font_height [index]);
}
common->font_index = deallocate (common->font_index);
common->font_width = deallocate (common->font_width);
common->font_height = deallocate (common->font_height);
common->font_begin = deallocate (common->font_begin);
common->font_end = deallocate (common->font_end);
common->sprite_data = deallocate (common->sprite_data);
common->sprite_width = deallocate (common->sprite_width);
common->sprite_height = deallocate (common->sprite_height);
common->framebuffer = deallocate (common->framebuffer);
xcb_free_gc (common->connection, common->context);
xcb_free_pixmap (common->connection, common->pixmap);
xcb_destroy_window (common->connection, common->window);
xcb_disconnect (common->connection);
return (deallocate (common));
}
static procedure common_configure (common_structure * common, natural width, natural height, character * title, natural window_flags) {
natural_64 font_bitmap [190] = {
0x0000000000000000, 0x0000000000000000, 0x0000101010101010, 0x1000101000000000, 0x0024242400000000, 0x0000000000000000,
0x00002424247e2424, 0x7e24242400000000, 0x0010107c9290907c, 0x1212927character0100000, 0x0000649468081010, 0x202c524c00000000,
0x000018242418304a, 0x4444443a00000000, 0x0010101000000000, 0x0000000000000000, 0x0000081020202020, 0x2020100800000000,
0x0000201008080808, 0x0808102000000000, 0x000000000024187e, 0x1824000000000000, 0x000000000010107c, 0x1010000000000000,
0x0000000000000000, 0x0000101020000000, 0x000000000000007e, 0x0000000000000000, 0x0000000000000000, 0x0000101000000000,
0x0000040408081010, 0x2020404000000000, 0x00003c4242464a52, 0x6242423c00000000, 0x0000081828080808, 0x0808083e00000000,
0x00003c4242020408, 0x1020407e00000000, 0x00003c4242021c02, 0x0242423c00000000, 0x000002060a122242, 0x7e02020200000000,
0x00007e4040407c02, 0x0202423c00000000, 0x00001c2040407c42, 0x4242423c00000000, 0x00007e0202040408, 0x0810101000000000,
0x00003c4242423c42, 0x4242423c00000000, 0x00003c424242423e, 0x0202043800000000, 0x0000000000101000, 0x0000101000000000,
0x0000000000101000, 0x0000101020000000, 0x0000000408102040, 0x2010080400000000, 0x00000000007e0000, 0x7e00000000000000,
0x0000004020100804, 0x0810204000000000, 0x00003c4242420408, 0x0800080800000000, 0x00007c829ea2a2a2, 0xa69a807e00000000,
0x00003c424242427e, 0x4242424200000000, 0x00007c4242427c42, 0x4242427c00000000, 0x00003c4242404040, 0x4042423c00000000,
0x0000784442424242, 0x4242447800000000, 0x00007e4040407840, 0x4040407e00000000, 0x00007e4040407840, 0x4040404000000000,
0x00003c424240404e, 0x4242423c00000000, 0x0000424242427e42, 0x4242424200000000, 0x0000381010101010, 0x1010103800000000,
0x00000e0404040404, 0x0444443800000000, 0x0000424448506060, 0x5048444200000000, 0x0000404040404040, 0x4040407e00000000,
0x000082c6aa929282, 0x8282828200000000, 0x000042424262524a, 0x4642424200000000, 0x00003c4242424242, 0x4242423c00000000,
0x00007c424242427c, 0x4040404000000000, 0x00003c4242424242, 0x42424a3c02000000, 0x00007c424242427c, 0x5048444200000000,
0x00003c4240403c02, 0x0242423c00000000, 0x0000fe1010101010, 0x1010101000000000, 0x0000424242424242, 0x4242423c00000000,
0x0000424242424224, 0x2424181800000000, 0x0000828282828292, 0x92aac68200000000, 0x0000424224241818, 0x2424424200000000,
0x0000828244442810, 0x1010101000000000, 0x00007e0202040810, 0x2040407e00000000, 0x0000382020202020, 0x2020203800000000,
0x0000404020201010, 0x0808040400000000, 0x0000380808080808, 0x0808083800000000, 0x0000102844000000, 0x0000000000000000,
0x0000000000000000, 0x0000007e00000000, 0x1008000000000000, 0x0000000000000000, 0x00000000003c023e, 0x4242423e00000000,
0x00004040407c4242, 0x4242427c00000000, 0x00000000003c4240, 0x4040423c00000000, 0x00000202023e4242, 0x4242423e00000000,
0x00000000003c4242, 0x7e40403c00000000, 0x00000e10107character010, 0x1010101000000000, 0x00000000003e4242, 0x4242423e02023c00,
0x00004040407c4242, 0x4242424200000000, 0x0000101000301010, 0x1010103800000000, 0x00000404000c0404, 0x0404040444443800,
0x0000404040424448, 0x7048444200000000, 0x0000301010101010, 0x1010103800000000, 0x0000000000fc9292, 0x9292929200000000,
0x00000000007c4242, 0x4242424200000000, 0x00000000003c4242, 0x4242423c00000000, 0x00000000007c4242, 0x4242427c40404000,
0x00000000003e4242, 0x4242423e02020200, 0x00000000005e6040, 0x4040404000000000, 0x00000000003e4040, 0x3c02027c00000000,
0x00001010107character010, 0x1010100e00000000, 0x0000000000424242, 0x4242423e00000000, 0x0000000000424242, 0x2424181800000000,
0x0000000000828292, 0x9292927c00000000, 0x0000000000424224, 0x1824424200000000, 0x0000000000424242, 0x4242423e02023c00,
0x00000000007e0408, 0x1020407e00000000, 0x00000character010102010, 0x1010100c00000000, 0x0000101010101010, 0x1010101000000000,
0x0000300808080408, 0x0808083000000000, 0x000000000062928c, 0x0000000000000000
};
natural event_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
natural mask_window_flags [2] = { 0 };
(none) window_flags;
natural * dumb_buffer = allocate (256 * sizeof (* dumb_buffer));
for (natural index = 0; index < 256; ++index) {
dumb_buffer [index] = 0xffffffff;
}
++common->font_count;
common->font_index = reallocate (common->font_index, common->font_count * sizeof (* common->font_index));
common->font_width = reallocate (common->font_width, common->font_count * sizeof (* common->font_width));
common->font_height = reallocate (common->font_height, common->font_count * sizeof (* common->font_height));
common->font_begin = reallocate (common->font_begin, common->font_count * sizeof (* common->font_begin));
common->font_end = reallocate (common->font_end, common->font_count * sizeof (* common->font_end));
common->font_begin [common->font_count - 1] = ' ';
common->font_end [common->font_count - 1] = '~';
common->font_index [common->font_count - 1] = allocate (95 * sizeof (* * common->font_index));
common->font_width [common->font_count - 1] = allocate (95 * sizeof (* * common->font_width));
common->font_height [common->font_count - 1] = allocate (95 * sizeof (* * common->font_height));
for (natural index = 0; index < 95; ++index) {
natural * buffer = allocate (common_font_width * common_font_height * sizeof (* buffer));
for (natural value = 0; value < 2; ++value) {
for (natural bit = 64; bit > 0; --bit) {
natural destination = ((value << 3) - ((bit - 1) >> 3) + 7) * common_font_width - ((bit - 1) & 7) + 7;
natural source = (font_bitmap [2 * index + value] >> (bit - 1)) & 1;
buffer [destination] = (source) ? 0xffffffff : 0x00000000;
}
}
common->font_index [common->font_count - 1] [index] = common_sprite_raw_import (common, buffer, common_font_width, common_font_height);
common->font_width [common->font_count - 1] [index] = common_font_width;
common->font_height [common->font_count - 1] [index] = common_font_height;
}
common_sprite_raw_import (common, dumb_buffer, 16, 16);
common->window_width = width;
common->window_height = height;
//~if (window_flags == ~ 0u) {
//~flags = common_window_decorated | common_window_resizable;
//~} else {
//~flags = window_flags;
//~}
common->connection = xcb_connect (null, null);
common->screen = xcb_setup_roots_iterator (xcb_get_setup (common->connection)).data;
common->window = xcb_generate_id (common->connection);
common->context = xcb_generate_id (common->connection);
common->pixmap = xcb_generate_id (common->connection);
mask_window_flags [0] = common->screen->black_pixel;
mask_window_flags [1] = XCB_EVENT_MASK_NO_EVENT |
XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_RESIZE_REDIRECT |
XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS;
xcb_create_window (common->connection, common->screen->root_depth, common->window, common->screen->root, 0, 0, (natural_16) width,
(natural_16) height, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, common->screen->root_visual, event_mask, mask_window_flags);
xcb_map_window (common->connection, common->window);
//~xcb_composite_redirect_window (common->connection, common->window, XCB_COMPOSITE_REDIRECT_MANUAL);
xcb_change_property (common->connection, XCB_PROP_MODE_REPLACE, common->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
(natural) string_length (title), title);
xcb_create_pixmap (common->connection, common->screen->root_depth, common->pixmap, common->window, (natural_16) width, (natural_16 ) height);
xcb_create_gc (common->connection, common->context, common->pixmap, 0, null);
xcb_flush (common->connection);
common->framebuffer = allocate (width * height * sizeof (* common->framebuffer));
common->active = true;
common->frame_begin = nano_time ();
}
static procedure common_synchronize (common_structure * common, natural colour) {
natural signal_code [signal_count] = {
0,
38, 56, 54, 40, 26, 41, 42, 43, 31, 44, 45, 46, 58, 57, 32, 33,
24, 27, 39, 28, 30, 55, 25, 53, 29, 52, 19, 10, 11, 12, 13, 14,
15, 16, 17, 18, 9, 23, 36, 36, 61, 51, 47, 49, 65, 22, 60, 59,
48, 66, 20, 21, 34, 35, 37, 105, 50, 62, 64, 108, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76, 95, 96, 111, 116, 113, 114, 77, 127, 118, 110,
112, 119, 115, 117, 86, 82, 63, 106, 104, 91, 90, 87, 88, 89, 83, 84,
85, 79, 80, 81
};
xcb_generic_event_t * generic_event = xcb_wait_for_event (common->connection);
//~xcb_generic_event_t * generic_event = null;
(none) colour;
//~for (; ; ) {
//~generic_event = xcb_poll_for_event (common->connection);
//~if (generic_event != null) {
//~if ((generic_event->response_type & 127) != 14) break;
//~}
//~}
xcb_flush (common->connection);
print ("%i\n", generic_event->response_type & 127);
//~XCB_NO_EXPOSURE = 14
//~if (generic_event != null) {
switch (generic_event->response_type & 127) {
//~case XCB_EXPOSE: {
//~xcb_flush (common->connection);
//~} break;
//~case XCB_MOTION_NOTIFY: {
//~;
//~} break;
case (XCB_BUTTON_PRESS): {
xcb_button_press_event_t * button_press = (xcb_button_press_event_t *) generic_event;
if (button_press->detail == 1) common->cursor [cursor_left] = true;
if (button_press->detail == 2) common->cursor [cursor_middle] = true;
if (button_press->detail == 3) common->cursor [cursor_right] = true;
common->cursor_x = button_press->event_x;
common->cursor_y = button_press->event_y;
} break;
case (XCB_BUTTON_RELEASE): {
xcb_button_release_event_t * button_release = (xcb_button_release_event_t *) generic_event;
if (button_release->detail == 1) common->cursor [cursor_left] = false;
if (button_release->detail == 2) common->cursor [cursor_middle] = false;
if (button_release->detail == 3) common->cursor [cursor_right] = false;
common->cursor_x = button_release->event_x;
common->cursor_y = button_release->event_y;
} break;
case (XCB_KEY_PRESS): {
xcb_key_press_event_t * key_press = (xcb_key_press_event_t *) generic_event;
for (natural index = 0; index < signal_count; ++index) {
if (key_press->detail == signal_code [index]) {
common->signal [index] = true;
}
}
} break;
case (XCB_KEY_RELEASE): {
xcb_key_release_event_t * key_release = (xcb_key_release_event_t *) generic_event;
for (natural index = 0; index < signal_count; ++index) {
if (key_release->detail == signal_code [index]) {
common->signal [index] = false;
}
}
} break;
default: {
} break;
}
generic_event = deallocate (generic_event);
//~}
for (natural pixel = 0; pixel < common->window_width * common->window_height; ++pixel) {
natural r = (common->framebuffer [pixel] & 0x00ff0000) >> 16;
natural b = (common->framebuffer [pixel] & 0x000000ff) << 16;
common->framebuffer [pixel] = (common->framebuffer [pixel] & 0xff00ff00) | b | r;
}
common->image = xcb_image_create_native (common->connection, (natural_16) common->window_width, (natural_16) common->window_height,
XCB_IMAGE_FORMAT_Z_PIXMAP, common->screen->root_depth, common->framebuffer,
(natural) (common->window_width * common->window_height * sizeof (* common->framebuffer)),
(natural_8 *) common->framebuffer);
xcb_image_put (common->connection, common->pixmap, common->context, common->image, 0, 0, 0);
xcb_image_destroy (common->image);
xcb_copy_area (common->connection, common->pixmap, common->window, common->context, 0, 0, 0, 0, (natural_16) common->window_width,
(natural_16) common->window_height);
common->framebuffer = allocate (common->window_width * common->window_height * sizeof (* common->framebuffer));
common->frame_end = nano_time ();
common->frame_time = common->frame_end - common->frame_begin;
if (common->frame_time < 1000000000ul / common_gameplay_framerate) {
nano_wait (1000000000ul / common_gameplay_framerate - common->frame_time);
}
if (common->global_tick % common_gameplay_framerate == 0) {
common->framerate = (natural) (1000000000ul / common->frame_time);
}
++common->global_tick;
common->global_tick = common->global_tick % (common_gameplay_framerate * common_animation_framerate);
common->gameplay_tick = common->global_tick % (common_gameplay_framerate);
common->animation_tick = common->global_tick / (common_gameplay_framerate / common_animation_framerate);
common->frame_begin = nano_time ();
}
static procedure common_render_base (common_structure * common, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height, real scale_x, real scale_y, integer flip_x,
integer flip_y, natural upper_left, natural upper_right, natural lower_left, natural lower_right) {
(none) scale_x;
(none) scale_y;
(none) flip_x;
(none) flip_y;
/// FIX TO INTERPOLATE ALL 4 COLOURS
//~(none) upper_left;
(none) upper_right;
(none) lower_left;
(none) lower_right;
/// COLOUR INTERPOLATION WITH RBGA-ABGR CONVERSION
natural interpolate_pixels (natural pixel, natural modifier) {
natural r = (((pixel & 0xff000000) >> 24) * ((modifier & 0x000000ff) >> 0)) / 0xff;
natural g = (((pixel & 0x00ff0000) >> 16) * ((modifier & 0x0000ff00) >> 8)) / 0xff;
natural b = (((pixel & 0x0000ff00) >> 8) * ((modifier & 0x00ff0000) >> 16)) / 0xff;
natural a = (((pixel & 0x000000ff) >> 0) * ((modifier & 0xff000000) >> 24)) / 0xff;
return ((r << 24) | (g << 16) | (b << 8) | a);
}
if ((x + (integer) width < 0) || (y + (integer) height < 0) || (x > (integer) common->window_width) || (y > (integer) common->window_height)) return;
for (natural vertical = 0; vertical < height; ++vertical) {
if (vertical + y >= common->window_height) break;
if (vertical + v >= common->sprite_height [sprite]) break;
for (natural horizontal = 0; horizontal < width; ++horizontal) {
if (horizontal + x >= common->window_width) break;
if (horizontal + u >= common->sprite_width [sprite]) break;
natural pixel = common->sprite_data [sprite] [(vertical + v) * common->sprite_width [sprite] + horizontal + u];
natural at = (y + vertical) * common->window_width + (x + horizontal);
common->framebuffer [at] = (((pixel & 0xff000000) >> 24) > 0x77) ? interpolate_pixels (pixel, upper_left) : common->framebuffer [at];
}
}
}
static procedure common_render_rectangle (common_structure * common, integer x, integer y, natural width, natural height, natural colour) {
common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour, colour,
colour, colour);
}
static procedure common_render_rectangle_gradient_v (common_structure * common, integer x, integer y, natural width, natural height, natural colour_up, natural colour_down) {
common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour_up, colour_up,
colour_down, colour_down);
}
static procedure common_render_rectangle_gradient_h (common_structure * common, integer x, integer y, natural width, natural height, natural colour_left, natural colour_right) {
common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour_left,
colour_right, colour_left, colour_right);
}
static procedure common_render_sprite (common_structure * common, natural sprite, integer x, integer y) {
common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu,
0xffffffffu);
}
static procedure common_render_sprite_crop (common_structure * common, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height) {
common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
}
static procedure common_render_sprite_colour (common_structure * common, natural sprite, natural colour, integer x, integer y) {
common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, 0, 0, colour, colour, colour, colour);
}
static procedure common_render_sprite_crop_colour (common_structure * common, natural sprite, natural colour, integer x, integer y, natural u, natural v, natural width, natural height) {
common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, 0, 0, colour, colour, colour, colour);
}
static procedure common_render_sprite_flip (common_structure * common, natural sprite, integer x, integer y, integer flip_x, integer flip_y) {
common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
}
static procedure common_render_sprite_animation (common_structure * common, natural sprite, integer x, integer y, natural frames, natural state, natural states) {
natural width = common->sprite_width [sprite] / states;
natural height = common->sprite_height [sprite] / frames;
natural u = width * (state % states);
natural v = height * (common->animation_tick % frames);
common_render_sprite_crop (common, sprite, x, y, u, v, width, height);
}
static procedure common_render_sprite_preview (common_structure * common, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height, real zoom) {
common_render_base (common, sprite, x, y, u, v, width, height, zoom, zoom, false, false, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
}
static procedure common_render_sprite_control (common_structure * common, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height, integer flip_x, integer flip_y) {
common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
}
static natural common_render_string_width (common_structure * common, character * string, natural font, real scale) {
natural length = 0;
if (string == null) {
return (0);
}
for (natural index = 0; string [index] != '\0'; ++index) {
natural character = common->font_index [font] [string [index] - common->font_begin [font]];
length += (natural) ((real) common->sprite_width [character] * scale);
}
return (length);
}
static procedure common_render_string (common_structure * common, character * string, natural font, integer x, integer y, real scale, natural colour) {
integer offset = x;
if (string == null) return;
if (font == 0xffffffffu) {
font = common->font_count - 1;
}
for (natural index = 0; string [index] != '\0'; ++index) {
natural character = 0;
if (string [index] == '\t') {
x += (integer) (scale * (real) common_font_tabulator * (real) common->sprite_width [common->font_index [font] [' ' - common->font_begin [font]]]);
continue;
} else if (string [index] == '\n') {
x = offset;
y += (integer) (scale * (real) common->sprite_height [common->font_index [font] [' ' - common->font_begin [font]]]);
continue;
} else if ((string [index] >= common->font_begin [font]) && (string [index] <= common->font_end [font])) {
character = common->font_index [font] [string [index] - common->font_begin [font]];
} else {
continue;
}
common_render_base (common, character, x, y, 0, 0, common->sprite_width [character], common->sprite_height [character],
scale, scale, 0, 0, colour, colour, colour, colour);
x += (integer) (scale * (real) common->sprite_width [character]);
}
}