/// __ _____ _ __ ___ _ __ ___ ___ _ __ /// \ \/ / _ \| '_ ` _ \| '_ ` _ \ / _ \| '_ \ /// > < (_) | | | | | | | | | | | (_) | | | | /// /_/\_\___/|_| |_| |_|_| |_| |_|\___/|_| |_| /// /// 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 #include #include //~#include #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]); } }