]> git.lizzy.rs Git - nothing.git/blob - src/game/sprite_font.c
Merge pull request #235 from tsoding/234
[nothing.git] / src / game / sprite_font.c
1 #include <SDL2/SDL.h>
2 #include <assert.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "sprite_font.h"
7 #include "system/lt.h"
8 #include "system/error.h"
9
10 #define FONT_ROW_SIZE 18
11 #define CHAR_WIDTH 7
12 #define CHAR_HEIGHT 9
13
14 struct sprite_font_t
15 {
16     lt_t *lt;
17     SDL_Surface *surface;
18     SDL_Texture *texture;
19 };
20
21 sprite_font_t *create_sprite_font_from_file(const char *bmp_file_path,
22                                             SDL_Renderer *renderer)
23 {
24     assert(bmp_file_path);
25
26     lt_t *lt = create_lt();
27     if (lt == NULL) {
28         return NULL;
29     }
30
31     sprite_font_t *sprite_font = PUSH_LT(lt, malloc(sizeof(sprite_font_t)), free);
32     if (sprite_font == NULL) {
33         throw_error(ERROR_TYPE_LIBC);
34         RETURN_LT(lt, NULL);
35     }
36
37     sprite_font->surface = PUSH_LT(lt, SDL_LoadBMP(bmp_file_path), SDL_FreeSurface);
38     if (sprite_font->surface == NULL) {
39         throw_error(ERROR_TYPE_SDL2);
40         RETURN_LT(lt, NULL);
41     }
42
43     sprite_font->texture = PUSH_LT(
44         lt,
45         SDL_CreateTextureFromSurface(renderer, sprite_font->surface),
46         SDL_DestroyTexture);
47     if (sprite_font->texture == NULL) {
48         throw_error(ERROR_TYPE_SDL2);
49         RETURN_LT(lt, NULL);
50     }
51
52     sprite_font->lt = lt;
53
54     return sprite_font;
55 }
56
57 void destroy_sprite_font(sprite_font_t *sprite_font)
58 {
59     assert(sprite_font);
60     RETURN_LT0(sprite_font->lt);
61 }
62
63 static SDL_Rect sprite_font_char_rect(const sprite_font_t *sprite_font, char x)
64 {
65     assert(sprite_font);
66
67     if (32 <= x && x <= 126) {
68         const SDL_Rect rect = {
69             .x = ((x - 32) % FONT_ROW_SIZE) * CHAR_WIDTH,
70             .y = ((x - 32) / FONT_ROW_SIZE) * CHAR_HEIGHT,
71             .w = CHAR_WIDTH,
72             .h = CHAR_HEIGHT
73         };
74         return rect;
75     } else {
76         return sprite_font_char_rect(sprite_font, '?');
77     }
78 }
79
80 int sprite_font_render_text(const sprite_font_t *sprite_font,
81                             SDL_Renderer *renderer,
82                             vec_t position,
83                             int size,
84                             const char *text)
85 {
86     assert(sprite_font);
87     assert(renderer);
88     assert(text);
89
90     const size_t text_size = strlen(text);
91     const int px = (int) roundf(position.x);
92     const int py = (int) roundf(position.y);
93     for (size_t i = 0; i < text_size; ++i) {
94         const SDL_Rect char_rect = sprite_font_char_rect(sprite_font, text[i]);
95         const SDL_Rect dest_rect = {
96             .x = px + CHAR_WIDTH * (int) i * size,
97             .y = py,
98             .w = char_rect.w * size,
99             .h = char_rect.h * size
100         };
101         if (SDL_RenderCopy(renderer, sprite_font->texture, &char_rect, &dest_rect) < 0) {
102             return -1;
103         }
104     }
105     return 0;
106 }
107
108 int sprite_font_debug_render_whole_texture(const sprite_font_t *sprite_font,
109                                            SDL_Renderer *renderer,
110                                            vec_t position)
111 {
112     int texW = 0;
113     int texH = 0;
114
115     if (SDL_QueryTexture(sprite_font->texture, NULL, NULL, &texW, &texH) < 0) {
116         throw_error(ERROR_TYPE_SDL2);
117         return -1;
118     }
119
120     const SDL_Rect dstrect = { (int) position.x, (int) position.y, texW, texH };
121
122     if (SDL_RenderCopy(renderer, sprite_font->texture, NULL, &dstrect) < 0) {
123         throw_error(ERROR_TYPE_SDL2);
124         return -1;
125     }
126
127     return 0;
128 }