#include "text.h" #include "renderer.h" #include #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) #define MAX_LINES 2 #define TEXT_HEIGHT 8 #define TEXT_SCALE 0.025 #define LETTER_WIDTH 3 #define SPACE_WIDTH 1 #define MAX_SCORE_CHARS 4 typedef struct { unsigned line_count; unsigned line_lens[MAX_LINES]; vec2_t lines[MAX_LINES][MAX_VERTS]; } glyph_t; static const mat3_t text_transform = { { TEXT_SCALE, 0, 0 }, { 0, TEXT_SCALE, 0 }, { 0, 0, 1 }, }; static const glyph_t font[] = { ['0'] = { .line_count = 1, .line_lens = { 5 }, .lines = { { { -1, 4 }, { -1, -4 }, { 1, -4 }, { 1, 4 }, { -1, 4 } }, }, }, ['1'] = { .line_count = 2, .line_lens = { 3, 2 }, .lines = { { { -1, 4 }, { 0, 4 }, { 0, -4 } }, { { -1, -4 }, { 1, -4 } }, }, }, ['2'] = { .line_count = 1, .line_lens = { 6 }, .lines = { { { -1, 4 }, { 1, 4 }, { 1, -2 }, { -1, -2 }, { -1, -4 }, { 1, -4 }, }, }, }, ['3'] = { .line_count = 1, .line_lens = { 6 }, .lines = { { { -1, 4 }, { 1, 4 }, { 0, -2 }, { 1, -2 }, { 1, -4 }, { -1, -4 }, }, }, }, ['4'] = { .line_count = 1, .line_lens = { 4 }, .lines = { { { 1, -2 }, { -1, -2 }, { 1, 4 }, { 1, -4 } } }, }, ['5'] = { .line_count = 1, .line_lens = { 6 }, .lines = { { { 1, 4 }, { -1, 4 }, { -1, -2 }, { 1, -2 }, { 1, -4 }, { -1, -4 }, }, }, }, ['6'] = { .line_count = 1, .line_lens = { 6 }, .lines = { { { 1, 4 }, { -1, 4 }, { -1, -4 }, { 1, -4 }, { 1, -2 }, { -1, -2 }, }, }, }, ['7'] = { .line_count = 1, .line_lens = { 3 }, .lines = { { { -1, 4 }, { 1, 4 }, { 0, -4 } }, }, }, ['8'] = { .line_count = 2, .line_lens = { 5, 2 }, .lines = { { { -1, 4 }, { -1, -4 }, { 1, -4 }, { 1, 4 }, { -1, 4 } }, { { -1, -2 }, { 1, -2 } }, }, }, ['9'] = { .line_count = 1, .line_lens = { 6 }, .lines = { { { 1, -2 }, { -1, -2 }, { -1, 4 }, { 1, 4 }, { 1, -4 }, { -1, -4 }, }, }, }, ['A'] = { .line_count = 2, .line_lens = { 3, 2 }, .lines = { { { -1, -4 }, { 0, 4 }, { 1, -4 } }, { { -0.75, -2 }, { 0.75, -2 } }, }, }, ['C'] = { .line_count = 1, .line_lens = { 4 }, .lines = { { { 1, 4 }, { -1, 4 }, { -1, -4 }, { 1, -4 } }, }, }, ['D'] = { .line_count = 1, .line_lens = { 5 }, .lines = { { { -1, 4 }, { -1, -4 }, { 1, -4 }, { 0, 4 }, { -1, 4 } }, }, }, ['E'] = { .line_count = 2, .line_lens = { 4, 2 }, .lines = { { { 1, 4 }, { -1, 4 }, { -1, -4 }, { 1, -4 } }, { { -1, -2 }, { 0, -2 } }, }, }, ['G'] = { .line_count = 1, .line_lens = { 5 }, .lines = { { { 1, 4 }, { -1, 4 }, { -1, -4 }, { 1, -4 }, { 1, -2 } }, }, }, ['L'] = { .line_count = 1, .line_lens = { 3 }, .lines = { { { -1, 4 }, { -1, -4 }, { 1, -4 } }, }, }, ['M'] = { .line_count = 1, .line_lens = { 5 }, .lines = { { { -1, -4 }, { -1, 4 }, { 0, -4 }, { 1, 4 }, { 1, -4 } }, }, }, ['O'] = { .line_count = 1, .line_lens = { 5 }, .lines = { { { -1, 4 }, { -1, -4 }, { 1, -4 }, { 1, 4 }, { -1, 4 } }, }, }, ['P'] = { .line_count = 1, .line_lens = { 5 }, .lines = { { { -1, -4 }, { -1, 4 }, { 1, 4 }, { 1, -2 }, { -1, -2 } }, }, }, ['R'] = { .line_count = 1, .line_lens = { 6 }, .lines = { { { -1, -4 }, { -1, 4 }, { 1, 4 }, { 1, -2 }, { -1, -2 }, { 1, -4 }, }, }, }, ['S'] = { .line_count = 1, .line_lens = { 6 }, .lines = { { { 1, 4 }, { -1, 4 }, { -1, -2 }, { 1, -2 }, { 1, -4 }, { -1, -4 }, }, }, }, ['U'] = { .line_count = 1, .line_lens = { 4 }, .lines = { { { -1, 4 }, { -1, -4 }, { 1, -4 }, { 1, 4 } }, }, }, ['V'] = { .line_count = 1, .line_lens = { 3 }, .lines = { { { -1, 4 }, { 0, -4 }, { 1, 4 } }, }, }, }; static void draw_glyph(unsigned c, vec2_t pos) { assert(c < NELEMS(font) && font[c].line_count != 0); const glyph_t *g = font + c; const mat3_t m = mat3_mul_mat3(mat3_translation(pos), text_transform); for (unsigned i = 0; i < g->line_count; ++i) renderer_draw(g->lines[i], g->line_lens[i], m, false); } static void draw_text(const char *s, vec2_t pos) { for (const char *p = s; *p != '\0'; ++p) { if (*p == ' ') { pos.x += TEXT_SCALE * SPACE_WIDTH; } else { draw_glyph((unsigned)*p, pos); pos.x += TEXT_SCALE * LETTER_WIDTH; } } } void text_draw_centre(const char *s) { int width = 0; for (const char *p = s; *p != '\0'; ++p) width += *p == ' ' ? SPACE_WIDTH : LETTER_WIDTH; --width; const vec2_t bg_size = { .x = TEXT_SCALE * (width + 2), .y = TEXT_SCALE * (TEXT_HEIGHT + 2), }; renderer_clear_rect((vec2_t) { 0, 0 }, bg_size); const vec2_t pos = { TEXT_SCALE * (-width / 2.0f + 1), 0 }; draw_text(s, pos); } void text_draw_score(unsigned score) { char buf[MAX_SCORE_CHARS + 1]; buf[MAX_SCORE_CHARS] = '\0'; for (unsigned i = 0; i < MAX_SCORE_CHARS; ++i) { const unsigned v = score % 10; score /= 10; buf[MAX_SCORE_CHARS - 1 - i] = '0' + v; } const int width = LETTER_WIDTH * MAX_SCORE_CHARS - 1; const vec2_t bg_centre = { .x = TEXT_SCALE * (width / 2.0f + 2) - aspect, .y = 1.0f - TEXT_SCALE * (TEXT_HEIGHT / 2.0f + 2), }; const vec2_t bg_size = { .x = TEXT_SCALE * (width + 2), .y = TEXT_SCALE * (TEXT_HEIGHT + 2), }; renderer_clear_rect(bg_centre, bg_size); const vec2_t text_pos = { .x = TEXT_SCALE * 3 - aspect, .y = bg_centre.y, }; draw_text(buf, text_pos); }