]> git.lizzy.rs Git - nothing.git/blob - src/game/sprite_font.c
(#532) Proper SDL2 includes
[nothing.git] / src / game / sprite_font.c
1 #include <SDL.h>
2 #include "system/stacktrace.h"
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "math/rect.h"
7 #include "sdl/renderer.h"
8 #include "sprite_font.h"
9 #include "system/lt.h"
10 #include "system/nth_alloc.h"
11 #include "system/log.h"
12
13 #define FONT_ROW_SIZE 18
14
15 struct Sprite_font
16 {
17     Lt *lt;
18     SDL_Texture *texture;
19 };
20
21 Sprite_font *create_sprite_font_from_file(const char *bmp_file_path,
22                                             SDL_Renderer *renderer)
23 {
24     trace_assert(bmp_file_path);
25     trace_assert(renderer);
26
27     Lt *lt = create_lt();
28
29     Sprite_font * const sprite_font = PUSH_LT(lt, nth_calloc(1, sizeof(Sprite_font)), free);
30     if (sprite_font == NULL) {
31         RETURN_LT(lt, NULL);
32     }
33
34     SDL_Surface * const surface = PUSH_LT(lt, SDL_LoadBMP(bmp_file_path), SDL_FreeSurface);
35     if (surface == NULL) {
36         log_fail("Could not load %s: %s\n", bmp_file_path, SDL_GetError());
37         RETURN_LT(lt, NULL);
38     }
39
40     if (SDL_SetColorKey(surface,
41                         SDL_TRUE,
42                         SDL_MapRGB(surface->format,
43                                    0, 0, 0)) < 0) {
44         log_fail("SDL_SetColorKey: %s\n", SDL_GetError());
45         RETURN_LT(lt, NULL);
46     }
47
48     sprite_font->texture = PUSH_LT(
49         lt,
50         SDL_CreateTextureFromSurface(renderer, surface),
51         SDL_DestroyTexture);
52     if (sprite_font->texture == NULL) {
53         log_fail("SDL_CreateTextureFromSurface: %s\n", SDL_GetError());
54         RETURN_LT(lt, NULL);
55     }
56
57     SDL_FreeSurface(RELEASE_LT(lt, surface));
58
59     sprite_font->lt = lt;
60
61     return sprite_font;
62 }
63
64 void destroy_sprite_font(Sprite_font *sprite_font)
65 {
66     trace_assert(sprite_font);
67     RETURN_LT0(sprite_font->lt);
68 }
69
70 static SDL_Rect sprite_font_char_rect(const Sprite_font *sprite_font, char x)
71 {
72     trace_assert(sprite_font);
73
74     if (32 <= x && x <= 126) {
75         const SDL_Rect rect = {
76             .x = ((x - 32) % FONT_ROW_SIZE) * FONT_CHAR_WIDTH,
77             .y = ((x - 32) / FONT_ROW_SIZE) * FONT_CHAR_HEIGHT,
78             .w = FONT_CHAR_WIDTH,
79             .h = FONT_CHAR_HEIGHT
80         };
81         return rect;
82     } else {
83         return sprite_font_char_rect(sprite_font, '?');
84     }
85 }
86
87 int sprite_font_render_text(const Sprite_font *sprite_font,
88                             SDL_Renderer *renderer,
89                             Vec position,
90                             Vec size,
91                             Color color,
92                             const char *text)
93 {
94     trace_assert(sprite_font);
95     trace_assert(renderer);
96     trace_assert(text);
97
98     const SDL_Color sdl_color = color_for_sdl(color);
99
100     if (SDL_SetTextureColorMod(sprite_font->texture, sdl_color.r, sdl_color.g, sdl_color.b) < 0) {
101         log_fail("SDL_SetTextureColorMod: %s\n", SDL_GetError());
102         return -1;
103     }
104
105     if (SDL_SetTextureAlphaMod(sprite_font->texture, sdl_color.a) < 0) {
106         log_fail("SDL_SetTextureAlphaMod: %s\n", SDL_GetError());
107         return -1;
108     }
109
110     const size_t text_size = strlen(text);
111     for (size_t i = 0; i < text_size; ++i) {
112         const SDL_Rect char_rect = sprite_font_char_rect(sprite_font, text[i]);
113         const SDL_Rect dest_rect = rect_for_sdl(
114             rect(
115                 position.x + (float) FONT_CHAR_WIDTH * (float) i * size.x,
116                 position.y,
117                 (float) char_rect.w * size.x,
118                 (float) char_rect.h * size.y));
119         if (SDL_RenderCopy(renderer, sprite_font->texture, &char_rect, &dest_rect) < 0) {
120             return -1;
121         }
122     }
123
124     return 0;
125 }
126
127 Rect sprite_font_boundary_box(const Sprite_font *sprite_font,
128                                 Vec position,
129                                 Vec size,
130                                 const char *text)
131 {
132     trace_assert(sprite_font);
133     trace_assert(text);
134     return rect(
135         position.x, position.y,
136         size.x * FONT_CHAR_WIDTH * (float) strlen(text),
137         size.y * FONT_CHAR_HEIGHT);
138 }