]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/sprite_font.c
Merge pull request #618 from tsoding/broadcast
[nothing.git] / src / game / sprite_font.c
index b79f05aad5d6b850a7b8390efb6b73dc54d05a1b..56c4aaff5757649d56fe4f8716d105fa6cf1f8ba 100644 (file)
 #include <SDL2/SDL.h>
-#include <assert.h>
+#include "system/stacktrace.h"
 #include <stdio.h>
 #include <string.h>
 
+#include "math/rect.h"
 #include "sdl/renderer.h"
 #include "sprite_font.h"
-#include "system/error.h"
 #include "system/lt.h"
+#include "system/nth_alloc.h"
+#include "system/log.h"
 
 #define FONT_ROW_SIZE 18
-#define CHAR_WIDTH 7
-#define CHAR_HEIGHT 9
 
-struct sprite_font_t
+struct Sprite_font
 {
-    lt_t *lt;
-    SDL_Surface *surface;
+    Lt *lt;
     SDL_Texture *texture;
 };
 
-sprite_font_t *create_sprite_font_from_file(const char *bmp_file_path,
-                                            color_t color,
+Sprite_font *create_sprite_font_from_file(const char *bmp_file_path,
                                             SDL_Renderer *renderer)
 {
-    assert(bmp_file_path);
+    trace_assert(bmp_file_path);
+    trace_assert(renderer);
 
-    (void) color;
-
-    lt_t *lt = create_lt();
+    Lt * const lt = create_lt();
     if (lt == NULL) {
         return NULL;
     }
 
-    sprite_font_t *sprite_font = PUSH_LT(lt, malloc(sizeof(sprite_font_t)), free);
+    Sprite_font * const sprite_font = PUSH_LT(lt, nth_alloc(sizeof(Sprite_font)), free);
     if (sprite_font == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
         RETURN_LT(lt, NULL);
     }
 
-    sprite_font->surface = PUSH_LT(lt, SDL_LoadBMP(bmp_file_path), SDL_FreeSurface);
-    if (sprite_font->surface == NULL) {
-        throw_error(ERROR_TYPE_SDL2);
+    SDL_Surface * const surface = PUSH_LT(lt, SDL_LoadBMP(bmp_file_path), SDL_FreeSurface);
+    if (surface == NULL) {
+        log_fail("Could not load %s: %s\n", bmp_file_path, SDL_GetError());
         RETURN_LT(lt, NULL);
     }
 
-    if (SDL_SetColorKey(sprite_font->surface,
+    if (SDL_SetColorKey(surface,
                         SDL_TRUE,
-                        SDL_MapRGB(sprite_font->surface->format,
+                        SDL_MapRGB(surface->format,
                                    0, 0, 0)) < 0) {
-        throw_error(ERROR_TYPE_SDL2);
+        log_fail("SDL_SetColorKey: %s\n", SDL_GetError());
         RETURN_LT(lt, NULL);
     }
 
-    const SDL_Color text_color = color_for_sdl(color);
-    const Uint32 actual_text_color =
-        SDL_MapRGB(sprite_font->surface->format,
-                   text_color.r,
-                   text_color.g,
-                   text_color.b);
-    SDL_LockSurface(sprite_font->surface);
-    for (int y = 0; y < sprite_font->surface->h; ++y) {
-        for (int x = 0; x < sprite_font->surface->w; ++x) {
-            if (getpixel(sprite_font->surface, x, y) == SDL_MapRGB(sprite_font->surface->format, 255, 255, 255)) {
-                putpixel(sprite_font->surface, x, y, actual_text_color);
-            }
-        }
-    }
-    SDL_UnlockSurface(sprite_font->surface);
-
     sprite_font->texture = PUSH_LT(
         lt,
-        SDL_CreateTextureFromSurface(renderer, sprite_font->surface),
+        SDL_CreateTextureFromSurface(renderer, surface),
         SDL_DestroyTexture);
     if (sprite_font->texture == NULL) {
-        throw_error(ERROR_TYPE_SDL2);
+        log_fail("SDL_CreateTextureFromSurface: %s\n", SDL_GetError());
         RETURN_LT(lt, NULL);
     }
 
+    SDL_FreeSurface(RELEASE_LT(lt, surface));
+
     sprite_font->lt = lt;
 
     return sprite_font;
 }
 
-void destroy_sprite_font(sprite_font_t *sprite_font)
+void destroy_sprite_font(Sprite_font *sprite_font)
 {
-    assert(sprite_font);
+    trace_assert(sprite_font);
     RETURN_LT0(sprite_font->lt);
 }
 
-static SDL_Rect sprite_font_char_rect(const sprite_font_t *sprite_font, char x)
+static SDL_Rect sprite_font_char_rect(const Sprite_font *sprite_font, char x)
 {
-    assert(sprite_font);
+    trace_assert(sprite_font);
 
     if (32 <= x && x <= 126) {
         const SDL_Rect rect = {
-            .x = ((x - 32) % FONT_ROW_SIZE) * CHAR_WIDTH,
-            .y = ((x - 32) / FONT_ROW_SIZE) * CHAR_HEIGHT,
-            .w = CHAR_WIDTH,
-            .h = CHAR_HEIGHT
+            .x = ((x - 32) % FONT_ROW_SIZE) * FONT_CHAR_WIDTH,
+            .y = ((x - 32) / FONT_ROW_SIZE) * FONT_CHAR_HEIGHT,
+            .w = FONT_CHAR_WIDTH,
+            .h = FONT_CHAR_HEIGHT
         };
         return rect;
     } else {
@@ -105,30 +87,55 @@ static SDL_Rect sprite_font_char_rect(const sprite_font_t *sprite_font, char x)
     }
 }
 
-int sprite_font_render_text(const sprite_font_t *sprite_font,
+int sprite_font_render_text(const Sprite_font *sprite_font,
                             SDL_Renderer *renderer,
-                            vec_t position,
-                            int size,
+                            Vec position,
+                            Vec size,
+                            Color color,
                             const char *text)
 {
-    assert(sprite_font);
-    assert(renderer);
-    assert(text);
+    trace_assert(sprite_font);
+    trace_assert(renderer);
+    trace_assert(text);
+
+    const SDL_Color sdl_color = color_for_sdl(color);
+
+    if (SDL_SetTextureColorMod(sprite_font->texture, sdl_color.r, sdl_color.g, sdl_color.b) < 0) {
+        log_fail("SDL_SetTextureColorMod: %s\n", SDL_GetError());
+        return -1;
+    }
+
+    if (SDL_SetTextureAlphaMod(sprite_font->texture, sdl_color.a) < 0) {
+        log_fail("SDL_SetTextureAlphaMod: %s\n", SDL_GetError());
+        return -1;
+    }
 
     const size_t text_size = strlen(text);
-    const int px = (int) roundf(position.x);
-    const int py = (int) roundf(position.y);
     for (size_t i = 0; i < text_size; ++i) {
         const SDL_Rect char_rect = sprite_font_char_rect(sprite_font, text[i]);
-        const SDL_Rect dest_rect = {
-            .x = px + CHAR_WIDTH * (int) i * size,
-            .y = py,
-            .w = char_rect.w * size,
-            .h = char_rect.h * size
-        };
+        const SDL_Rect dest_rect = rect_for_sdl(
+            rect(
+                position.x + (float) FONT_CHAR_WIDTH * (float) i * size.x,
+                position.y,
+                (float) char_rect.w * size.x,
+                (float) char_rect.h * size.y));
         if (SDL_RenderCopy(renderer, sprite_font->texture, &char_rect, &dest_rect) < 0) {
             return -1;
         }
     }
+
     return 0;
 }
+
+Rect sprite_font_boundary_box(const Sprite_font *sprite_font,
+                                Vec position,
+                                Vec size,
+                                const char *text)
+{
+    trace_assert(sprite_font);
+    trace_assert(text);
+    return rect(
+        position.x, position.y,
+        size.x * FONT_CHAR_WIDTH * (float) strlen(text),
+        size.y * FONT_CHAR_HEIGHT);
+}