xhads/source/xcb.c

261 lines
8.0 KiB
C

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include <png.h>
#include <xcb/xcb.h>
#include <xcb/xcb_atom.h>
#include <xcb/xcb_image.h>
#define FONT_WIDTH ( 9)
#define FONT_HEIGHT (18)
static unsigned int * * render_texture = NULL;
static int * render_texture_w = NULL;
static int * render_texture_h = NULL;
static int render_texture_count = 0;
static unsigned int * font = NULL;
static unsigned int * mono = NULL;
static int screen_width = 1800;
static int screen_height = 900;
static xcb_window_t window = 0;
static xcb_gcontext_t context = 0;
static xcb_pixmap_t pixmap = 0;
static xcb_connection_t * connection = NULL;
static xcb_screen_t * screen = NULL;
static xcb_image_t * image = NULL;
static unsigned int * framebuffer = NULL;
static unsigned int * import_png (char * path, int * w, int * h) {
unsigned int buffer [1024*1024] = { 0 };
unsigned int * data = NULL;
png_image temporary = { 0 };
temporary.version = PNG_IMAGE_VERSION;
if (! png_image_begin_read_from_file (& temporary, path)) printf ("PNG: image begin read from file fuck up!\n");
temporary.format = PNG_FORMAT_BGRA;
if (! png_image_finish_read (& temporary, NULL, buffer, 0, NULL)) printf ("PNG: image finish read fuck up!\n");
if (w != NULL) * w = temporary.width;
if (h != NULL) * h = temporary.height;
if (buffer == NULL) printf ("PNG: empty buffer fuck up!\n");
png_image_free (& temporary);
data = calloc (temporary.width * temporary.height, sizeof (* data));
if (data == NULL) printf ("PNG: empty data fuck up!\n");
memcpy (data, buffer, temporary.width * temporary.height * sizeof (* data));
return (data);
}
static void render_clean_up (void) {
int i;
printf ("Deinitializing graphical components...\n");
for (i = 0; i < render_texture_count; ++i)
free (render_texture [i]);
free (render_texture);
free (font);
free (mono);
xcb_free_gc (connection, context);
xcb_free_pixmap (connection, pixmap);
xcb_destroy_window (connection, window);
xcb_disconnect (connection);
}
extern int signal_x;
extern int signal_y;
extern int cursor_mode;
extern int signal_mode;
extern int engine_active;
extern int window_width (void);
extern int window_height (void);
extern void render_sprite (int sprite, int x, int y, int u, int v, int width, int height);
extern void render_string (char * string, int x, int y, int colour, char monospace);
extern void engine_configure (void);
extern void engine_synchronize (void);
extern int sprite_import (char * path);
extern int sprite_width (int index);
extern int sprite_height (int index);
int signal_x = 0;
int signal_y = 0;
int cursor_mode = 0;
int signal_mode = 0;
int engine_active = 0;
int window_width (void) { return (screen_width); }
int window_height (void) { return (screen_height); }
void render_sprite (int sprite, int x, int y, int u, int v, int width, int height) {
int sprite_x, sprite_y;
width = (width < 0) ? -width : width;
height = (height < 0) ? -height : height;
if ((x < 0) || (y < 0)
|| (x > window_width () - width) || (y > window_height () - height)) {
return;
}
for (sprite_y = 0; sprite_y < height; ++sprite_y) {
for (sprite_x = 0; sprite_x < width; ++sprite_x) {
int o = (sprite_y + y) * window_width () + (sprite_x + x);
int s = (sprite_y + v) * sprite_width (sprite) + (sprite_x + u);
framebuffer [o] = ((render_texture [sprite] [s] & 0XFF000000) < 0X04) ?
framebuffer [o] : render_texture [sprite] [s];
}
}
}
void render_string (char * string, int x, int y, int colour, char monospace) {
/*Vector2 position = { 4, 4 };
Color new_tint = { 255, 255, 255, 255 };
position.x += x;
position.y += y;
new_tint.r = ((colour & 0XFF0000) >> 16) % 256;
new_tint.g = ((colour & 0X00FF00) >> 8) % 256;
new_tint.b = ((colour & 0X0000FF) >> 0) % 256;
DrawTextPro ((monospace != 0) ? mono : font, string, position, dump, 0.0, 24, 6, new_tint);
*/
(void) string;
(void) x;
(void) y;
(void) colour;
(void) monospace;
}
void engine_configure (void) {
unsigned int values [2] = {
0,
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_EVENT_MASK_POINTER_MOTION
};
engine_active = 1;
printf ("Initializing graphical components...\n");
font = import_png ("./sprite/font/font.png", NULL, NULL);
mono = import_png ("./sprite/font/mono.png", NULL, NULL);
connection = xcb_connect (NULL, NULL);
screen = xcb_setup_roots_iterator (xcb_get_setup (connection)) . data;
values [0] = screen -> black_pixel;
window = xcb_generate_id (connection);
context = xcb_generate_id (connection);
pixmap = xcb_generate_id (connection);
xcb_create_window (connection, screen -> root_depth, window, screen -> root, 0, 0, (uint16_t) window_width (), (uint16_t) window_height (), 10,
XCB_WINDOW_CLASS_INPUT_OUTPUT, screen -> root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values);
xcb_map_window (connection, window);
xcb_change_property (connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
sizeof ("-- Chads of Might & Magic --"), "-- Chads of Might & Magic --");
xcb_create_pixmap (connection, screen -> root_depth, pixmap, window, (uint16_t) window_width (), (uint16_t) window_height ());
xcb_create_gc (connection, context, pixmap, 0, NULL);
xcb_flush (connection);
atexit (render_clean_up);
}
void engine_synchronize (void) {
xcb_generic_event_t * event = NULL;
if (framebuffer != NULL) {
image = xcb_image_create_native (connection, (uint16_t) screen_width, (uint16_t) screen_height, XCB_IMAGE_FORMAT_Z_PIXMAP, screen -> root_depth,
framebuffer, (uint32_t) (screen_width * screen_height * (int32_t) sizeof (* framebuffer)), (uint8_t *) framebuffer);
xcb_image_put (connection, pixmap, context, image, 0, 0, 0);
xcb_image_destroy (image);
xcb_copy_area (connection, pixmap, window, context, 0, 0, 0, 0, (uint16_t) screen_width, (uint16_t) screen_height);
}
event = xcb_wait_for_event (connection);
if (event == NULL) {
return;
} else if ((event->response_type & 127) == XCB_EXPOSE) {
xcb_flush (connection);
} else if ((event->response_type & 127) == XCB_KEY_PRESS) {
printf ("Key: %i\n", ((xcb_key_press_event_t *) event)->detail);
switch (((xcb_key_press_event_t *) event)->detail) {
case 24: engine_active = 0; break;
case 25: cursor_mode = 4; break;
case 26: cursor_mode = 5; break;
case 27: cursor_mode = 6; break;
case 28: cursor_mode = 7; break;
default: break;
}
} else if ((event->response_type & 127) == XCB_BUTTON_PRESS) {
xcb_button_press_event_t * button_press_event = (xcb_button_press_event_t *) event;
cursor_mode = button_press_event->detail;
} else if ((event->response_type & 127) == XCB_MOTION_NOTIFY) {
xcb_motion_notify_event_t * button_press_event = (xcb_motion_notify_event_t *) event;
signal_x = button_press_event->event_x;
signal_y = button_press_event->event_y;
}
free (event);
framebuffer = calloc ((size_t) (screen_width * screen_height), sizeof (* framebuffer));
signal_mode = 0;
}
int import_sprite (char * path) {
++render_texture_count;
render_texture = realloc (render_texture, (unsigned long int) render_texture_count * sizeof (* render_texture));
render_texture_w = realloc (render_texture_w, (unsigned long int) render_texture_count * sizeof (* render_texture_w));
render_texture_h = realloc (render_texture_h, (unsigned long int) render_texture_count * sizeof (* render_texture_h));
render_texture [render_texture_count - 1] = import_png (path, & render_texture_w [render_texture_count - 1], & render_texture_h [render_texture_count - 1]);
if (render_texture [render_texture_count - 1] == NULL) {
printf ("\033[1;31m%3i : '%60s';\033[0m\n", render_texture_count - 1, path);
}
return (render_texture_count - 1);
}
int sprite_width (int index) {
return (render_texture_w [index]);
}
int sprite_height (int index) {
return (render_texture_h [index]);
}