More to come...
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
11KB

  1. /*
  2. Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic
  3. Xhartae is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation.
  4. And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version.
  5. It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3.
  6. */
  7. #ifndef CHAPTER_5_SOURCE
  8. #define CHAPTER_5_SOURCE
  9. #include "chapter_5.h"
  10. #define BLESSES_FONT_WIDTH (8)
  11. #define BLESSES_FONT_HEIGHT (8)
  12. #define BLESSES_FONT_TABULATOR (4)
  13. char * blesses_window_title = "xolatile";
  14. int blesses_window_width = 1800;
  15. int blesses_window_height = 900;
  16. int blesses_active = 1;
  17. int blesses_cursor_x = 0;
  18. int blesses_cursor_y = 0;
  19. int blesses_signal = 0;
  20. int * blesses_sub_framebuffer = NULL;
  21. int * blesses_framebuffer = NULL;
  22. void (* blesses_action [BLESSES_SIGNAL_COUNT]) (void) = { NULL };
  23. xcb_window_t blesses_window = 0;
  24. xcb_gcontext_t blesses_context = 0;
  25. xcb_pixmap_t blesses_pixmap = 0;
  26. xcb_connection_t * blesses_connection = NULL;
  27. xcb_screen_t * blesses_screen = NULL;
  28. xcb_image_t * blesses_image = NULL;
  29. void blesses_initialize (void) {
  30. unsigned int window_flags [2] = {
  31. 0,
  32. XCB_EVENT_MASK_NO_EVENT |
  33. XCB_EVENT_MASK_EXPOSURE |
  34. XCB_EVENT_MASK_RESIZE_REDIRECT |
  35. XCB_EVENT_MASK_KEY_RELEASE |
  36. XCB_EVENT_MASK_KEY_PRESS |
  37. XCB_EVENT_MASK_BUTTON_RELEASE |
  38. XCB_EVENT_MASK_BUTTON_PRESS
  39. };
  40. unsigned short int window_width = (unsigned short int) blesses_window_width;
  41. unsigned short int window_height = (unsigned short int) blesses_window_height;
  42. blesses_connection = xcb_connect (NULL, NULL);
  43. fatal_failure (blesses_connection == NULL, "blesses : blesses_initialize : XCB connection is null pointer.");
  44. blesses_screen = xcb_setup_roots_iterator (xcb_get_setup (blesses_connection)).data;
  45. blesses_window = xcb_generate_id (blesses_connection);
  46. blesses_context = xcb_generate_id (blesses_connection);
  47. blesses_pixmap = xcb_generate_id (blesses_connection);
  48. window_flags [0] = blesses_screen->black_pixel;
  49. xcb_create_window (blesses_connection, blesses_screen->root_depth, blesses_window, blesses_screen->root, 0, 0, window_width, window_height, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT,
  50. blesses_screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, window_flags);
  51. xcb_map_window (blesses_connection, blesses_window);
  52. xcb_change_property (blesses_connection, XCB_PROP_MODE_REPLACE, blesses_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, string_length (blesses_window_title), blesses_window_title);
  53. xcb_create_pixmap (blesses_connection, blesses_screen->root_depth, blesses_pixmap, blesses_window, window_width, window_height);
  54. xcb_create_gc (blesses_connection, blesses_context, blesses_pixmap, 0, NULL);
  55. xcb_flush (blesses_connection);
  56. /*blesses_sub_framebuffer = allocate (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_sub_framebuffer) / 4);*/
  57. blesses_sub_framebuffer = allocate (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_sub_framebuffer));
  58. blesses_framebuffer = allocate (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_framebuffer));
  59. }
  60. void blesses_deinitialize (void) {
  61. blesses_sub_framebuffer = deallocate (blesses_sub_framebuffer);
  62. blesses_framebuffer = deallocate (blesses_framebuffer);
  63. xcb_free_gc (blesses_connection, blesses_context);
  64. xcb_free_pixmap (blesses_connection, blesses_pixmap);
  65. xcb_destroy_window (blesses_connection, blesses_window);
  66. xcb_disconnect (blesses_connection);
  67. }
  68. void blesses_synchronize (void) {
  69. int i = 0;
  70. xcb_generic_event_t * generic_event = NULL;
  71. /*
  72. for (i = 0; i != blesses_window_width * blesses_window_height; i++) {
  73. blesses_framebuffer [i] = blesses_sub_framebuffer [((i / blesses_window_width) / 2) * (blesses_window_width / 2) + (i % blesses_window_width) / 2];
  74. }
  75. */
  76. for (i = 0; i != blesses_window_width * blesses_window_height; i++) {
  77. blesses_framebuffer [i] = blesses_sub_framebuffer [i];
  78. }
  79. blesses_sub_framebuffer = deallocate (blesses_sub_framebuffer);
  80. blesses_image = xcb_image_create_native (blesses_connection, blesses_window_width, blesses_window_height, XCB_IMAGE_FORMAT_Z_PIXMAP, blesses_screen->root_depth,
  81. blesses_framebuffer, (unsigned int) (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_framebuffer)),
  82. (unsigned char *) blesses_framebuffer);
  83. xcb_image_put (blesses_connection, blesses_pixmap, blesses_context, blesses_image, 0, 0, 0);
  84. xcb_image_destroy (blesses_image);
  85. xcb_copy_area (blesses_connection, blesses_pixmap, blesses_window, blesses_context, 0, 0, 0, 0, blesses_window_width, blesses_window_height);
  86. blesses_framebuffer = NULL;
  87. generic_event = xcb_wait_for_event (blesses_connection);
  88. switch (generic_event->response_type & 127) {
  89. case XCB_EXPOSE: {
  90. xcb_flush (blesses_connection);
  91. } break;
  92. case XCB_KEY_PRESS: {
  93. blesses_signal = (int) ((xcb_key_press_event_t *) generic_event)->detail;
  94. if (blesses_signal == 24) {
  95. blesses_active = 0;
  96. }
  97. } break;
  98. default: {
  99. } break;
  100. }
  101. generic_event = deallocate (generic_event);
  102. if ((blesses_sub_framebuffer == NULL) && (blesses_framebuffer == NULL)) {
  103. /*blesses_sub_framebuffer = allocate (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_sub_framebuffer) / 4);*/
  104. blesses_sub_framebuffer = allocate (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_sub_framebuffer));
  105. blesses_framebuffer = allocate (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_framebuffer));
  106. }
  107. }
  108. void blesses_render_background_colour (int background) {
  109. int x, y;
  110. for (y = 0; y != blesses_window_height/* / 2*/; ++y) {
  111. for (x = 0; x != blesses_window_width/* / 2*/; ++x) {
  112. blesses_sub_framebuffer [y * (blesses_window_width/* / 2*/) + x] = 0XFF000000 | colour;
  113. }
  114. }
  115. }
  116. void blesses_render_character (char character, int foreground, int background, int x, int y) {
  117. const unsigned long int font_code ['~' - ' ' + 2] = {
  118. 0X0000000000000000, 0X00180018183C3C18, 0X0000000000363636, 0X006C6CFE6CFE6C6C, 0X00187ED07C16FC30, 0X0060660C18306606, 0X00DC66B61C36361C, 0X0000000000181818,
  119. 0X0030180C0C0C1830, 0X000C18303030180C, 0X0000187E3C7E1800, 0X000018187E181800, 0X0C18180000000000, 0X000000007E000000, 0X0018180000000000, 0X0000060C18306000,
  120. 0X003C666E7E76663C, 0X007E181818181C18, 0X007E0C183060663C, 0X003C66603860663C, 0X0030307E363C3830, 0X003C6660603E067E, 0X003C66663E060C38, 0X000C0C0C1830607E,
  121. 0X003C66663C66663C, 0X001C30607C66663C, 0X0018180018180000, 0X0C18180018180000, 0X0030180C060C1830, 0X0000007E007E0000, 0X000C18306030180C, 0X001800181830663C,
  122. 0X003C06765676663C, 0X006666667E66663C, 0X003E66663E66663E, 0X003C66060606663C, 0X001E36666666361E, 0X007E06063E06067E, 0X000606063E06067E, 0X003C66667606663C,
  123. 0X006666667E666666, 0X007E18181818187E, 0X001C36303030307C, 0X0066361E0E1E3666, 0X007E060606060606, 0X00C6C6D6D6FEEEC6, 0X006666767E6E6666, 0X003C66666666663C,
  124. 0X000606063E66663E, 0X006C36566666663C, 0X006666363E66663E, 0X003C66603C06663C, 0X001818181818187E, 0X003C666666666666, 0X00183C6666666666, 0X00C6EEFED6D6C6C6,
  125. 0X0066663C183C6666, 0X001818183C666666, 0X007E060C1830607E, 0X003E06060606063E, 0X00006030180C0600, 0X007C60606060607C, 0X000000000000663C, 0XFFFF000000000000,
  126. 0X000000000030180C, 0X007C667C603C0000, 0X003E6666663E0606, 0X003C6606663C0000, 0X007C6666667C6060, 0X003C067E663C0000, 0X000C0C0C3E0C0C38, 0X3C607C66667C0000,
  127. 0X00666666663E0606, 0X003C1818181C0018, 0X0E181818181C0018, 0X0066361E36660606, 0X003C18181818181C, 0X00C6D6D6FE6C0000, 0X00666666663E0000, 0X003C6666663C0000,
  128. 0X06063E66663E0000, 0XE0607C66667C0000, 0X000606066E360000, 0X003E603C067C0000, 0X00380C0C0C3E0C0C, 0X007C666666660000, 0X00183C6666660000, 0X006CFED6D6C60000,
  129. 0X00663C183C660000, 0X3C607C6666660000, 0X007E0C18307E0000, 0X003018180E181830, 0X0018181818181818, 0X000C18187018180C, 0X000000000062D68C, 0X0000000000000000
  130. };
  131. int offset;
  132. if ((x <= -1) || (x >= blesses_window_width/* / 2*/ - BLESSES_FONT_WIDTH)) return;
  133. if ((y <= -1) || (y >= blesses_window_height/* / 2*/ - BLESSES_FONT_HEIGHT)) return;
  134. fatal_failure (blesses_sub_framebuffer == NULL, "blesses : render_character : Sub framebuffer was not allocated.");
  135. fatal_failure (blesses_framebuffer == NULL, "blesses : render_character : Framebuffer was not allocated.");
  136. fatal_failure (character_is_invisible (character), "blesses : render_character : Character is not in visible ASCII range.");
  137. fatal_failure (x <= -1, "blesses : render_character : X position is under lower limit.");
  138. fatal_failure (y <= -1, "blesses : render_character : Y position is under lower limit.");
  139. fatal_failure (x >= blesses_window_width - BLESSES_FONT_WIDTH, "blesses : render_character : X position is above upper limit.");
  140. fatal_failure (y >= blesses_window_height - BLESSES_FONT_HEIGHT, "blesses : render_character : Y position is above upper limit.");
  141. for (offset = 0; offset != BLESSES_FONT_WIDTH * BLESSES_FONT_HEIGHT; ++offset) {
  142. int u = offset / BLESSES_FONT_WIDTH + y;
  143. int v = offset % BLESSES_FONT_WIDTH + x;
  144. blesses_sub_framebuffer [u * (blesses_window_width/* / 2*/) + v] = ((font_code [(int) (character - ' ')] >> offset) % 2) ? foreground : background;
  145. }
  146. }
  147. void blesses_render_string (char * string, int foreground, int background, int x, int y) {
  148. blesses_render_string_limit (string, string_length (string), foreground, background, x, y);
  149. }
  150. void blesses_render_number (int number, int foreground, int background, int x, int y) {
  151. blesses_render_string (number_to_string (number), foreground, background, x, y);
  152. }
  153. void blesses_render_string_limit (char * string, int limit, int foreground, int background, int x, int y) {
  154. int offset;
  155. for (offset = 0; offset != limit; ++offset) {
  156. if (string [offset] == '\n') {
  157. x *= 0;
  158. y += BLESSES_FONT_HEIGHT;
  159. } else if (string [offset] == '\t') {
  160. x += BLESSES_FONT_WIDTH * BLESSES_FONT_TABULATOR;
  161. } else {
  162. blesses_render_character (string [offset], foreground, background, x, y);
  163. x += BLESSES_FONT_WIDTH;
  164. }
  165. }
  166. }
  167. void blesses_render_number_limit (int number, int limit, int foreground, int background, int x, int y) {
  168. blesses_render_string_limit (number_to_string (number), limit, foreground, background, x, y);
  169. }
  170. #endif