summaryrefslogtreecommitdiff
path: root/font
diff options
context:
space:
mode:
Diffstat (limited to 'font')
-rw-r--r--font/CMakeLists.txt15
-rw-r--r--font/font.c45
-rw-r--r--font/font.h40
3 files changed, 100 insertions, 0 deletions
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 @@
1cmake_minimum_required(VERSION 3.0)
2
3project(font)
4
5set(CMAKE_C_STANDARD 17)
6set(CMAKE_C_STANDARD_REQUIRED On)
7set(CMAKE_C_EXTENSIONS Off)
8
9add_library(font
10 font.c)
11
12target_include_directories(font PUBLIC
13 .)
14
15target_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 @@
1#include <font.h>
2
3#include <assert.h>
4#include <stdbool.h>
5#include <stdio.h>
6#include <stdlib.h>
7
8static size_t GetFileSize(FILE* file) {
9 fseek(file, 0, SEEK_END);
10 const size_t size = ftell(file);
11 fseek(file, 0, SEEK_SET);
12 return size;
13}
14
15FontAtlas* LoadFontAtlas(const char* path) {
16 assert(path);
17
18 FILE* file = NULL;
19 FontAtlas* atlas = 0;
20
21 if ((file = fopen(path, "rb")) == NULL) {
22 goto cleanup;
23 }
24
25 const size_t size = GetFileSize(file);
26 if (size == (size_t)-1) {
27 goto cleanup;
28 }
29
30 atlas = calloc(1, size);
31 if (!atlas) {
32 goto cleanup;
33 }
34
35 if (fread(atlas, size, 1, file) != 1) {
36 free(atlas);
37 atlas = 0;
38 }
39
40cleanup:
41 if (file != NULL) {
42 fclose(file);
43 }
44 return atlas;
45}
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 @@
1#pragma once
2
3#include <assert.h>
4#include <stdint.h>
5
6static const unsigned char FontGlyphStart = 32; // Space.
7static const unsigned char FontGlyphEnd = 127; // One past tilde.
8static const int FontAtlasNumGlyphs = FontGlyphEnd - FontGlyphStart;
9
10/// Font atlas header.
11typedef struct FontHeader {
12 uint16_t glyph_width;
13 uint16_t glyph_height;
14 uint16_t num_glyphs;
15} FontHeader;
16
17/// Font atlas.
18///
19/// Pixels are stored in "glyph-major" order. First the rows of the first glyph,
20/// followed by the rows of the second glyph, etc. Thus, pixels should be viewed
21/// as a linear array, not a 2d array. This arrangement allows an application to
22/// render glyphs by scanning atlas memory linearly.
23typedef struct FontAtlas {
24 FontHeader header;
25 unsigned char pixels[1];
26} FontAtlas;
27
28/// Load a font atlas from a file.
29FontAtlas* LoadFontAtlas(const char* path);
30
31/// Get the glyph into the atlas.
32static inline const unsigned char* FontGetGlyph(
33 const FontAtlas* atlas, unsigned char c) {
34 assert(atlas);
35 const int index = c - FontGlyphStart;
36 assert(index >= 0);
37 assert(index < FontAtlasNumGlyphs);
38 return atlas->pixels +
39 index * (atlas->header.glyph_width * atlas->header.glyph_height);
40}