From af641426fad35cd857c1f14bda523db3d85a70cd Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 4 May 2024 16:44:28 -0700 Subject: Initial commit. --- font/CMakeLists.txt | 15 +++++++++++++++ font/font.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ font/font.h | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 font/CMakeLists.txt create mode 100644 font/font.c create mode 100644 font/font.h (limited to 'font') diff --git a/font/CMakeLists.txt b/font/CMakeLists.txt new file mode 100644 index 0000000..6eb6fc0 --- /dev/null +++ b/font/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.0) + +project(font) + +set(CMAKE_C_STANDARD 17) +set(CMAKE_C_STANDARD_REQUIRED On) +set(CMAKE_C_EXTENSIONS Off) + +add_library(font + font.c) + +target_include_directories(font PUBLIC + .) + +target_compile_options(font PRIVATE -Wall -Wextra -Wpedantic) diff --git a/font/font.c b/font/font.c new file mode 100644 index 0000000..2d30c50 --- /dev/null +++ b/font/font.c @@ -0,0 +1,45 @@ +#include + +#include +#include +#include +#include + +static size_t GetFileSize(FILE* file) { + fseek(file, 0, SEEK_END); + const size_t size = ftell(file); + fseek(file, 0, SEEK_SET); + return size; +} + +FontAtlas* LoadFontAtlas(const char* path) { + assert(path); + + FILE* file = NULL; + FontAtlas* atlas = 0; + + if ((file = fopen(path, "rb")) == NULL) { + goto cleanup; + } + + const size_t size = GetFileSize(file); + if (size == (size_t)-1) { + goto cleanup; + } + + atlas = calloc(1, size); + if (!atlas) { + goto cleanup; + } + + if (fread(atlas, size, 1, file) != 1) { + free(atlas); + atlas = 0; + } + +cleanup: + if (file != NULL) { + fclose(file); + } + return atlas; +} diff --git a/font/font.h b/font/font.h new file mode 100644 index 0000000..13ff1c3 --- /dev/null +++ b/font/font.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +static const unsigned char FontGlyphStart = 32; // Space. +static const unsigned char FontGlyphEnd = 127; // One past tilde. +static const int FontAtlasNumGlyphs = FontGlyphEnd - FontGlyphStart; + +/// Font atlas header. +typedef struct FontHeader { + uint16_t glyph_width; + uint16_t glyph_height; + uint16_t num_glyphs; +} FontHeader; + +/// Font atlas. +/// +/// Pixels are stored in "glyph-major" order. First the rows of the first glyph, +/// followed by the rows of the second glyph, etc. Thus, pixels should be viewed +/// as a linear array, not a 2d array. This arrangement allows an application to +/// render glyphs by scanning atlas memory linearly. +typedef struct FontAtlas { + FontHeader header; + unsigned char pixels[1]; +} FontAtlas; + +/// Load a font atlas from a file. +FontAtlas* LoadFontAtlas(const char* path); + +/// Get the glyph into the atlas. +static inline const unsigned char* FontGetGlyph( + const FontAtlas* atlas, unsigned char c) { + assert(atlas); + const int index = c - FontGlyphStart; + assert(index >= 0); + assert(index < FontAtlasNumGlyphs); + return atlas->pixels + + index * (atlas->header.glyph_width * atlas->header.glyph_height); +} -- cgit v1.2.3