aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorCalvin Rose <calsrose@gmail.com>2025-12-14 09:27:30 -0600
committerCalvin Rose <calsrose@gmail.com>2025-12-14 09:27:30 -0600
commitf787752517441046f07bdbb3bd5ad18c270cdc4b (patch)
tree9f43c4364b198a9970d46eb2111d1eab5c728eb4 /tools
parentMore work on simple text rendering. (diff)
Add more bitmap fonts.
Currently three variants. Each font is embedded into the binary and costs about 4KB of ram. Worth considering making them loadable.
Diffstat (limited to 'tools')
-rw-r--r--tools/make-font.janet79
1 files changed, 59 insertions, 20 deletions
diff --git a/tools/make-font.janet b/tools/make-font.janet
index 2938632..bcd7905 100644
--- a/tools/make-font.janet
+++ b/tools/make-font.janet
@@ -1,5 +1,13 @@
(use spork/cjanet)
+###
+### Generate bitmaps for the built-in retro console fonts encoded in TTFs.
+### We seek to minimize memory usage for these fonts. Technically, this should be
+### similar to how these fonts were stored in BIOS roms but it is much easier to find
+### TTF extractions/reproductions of these fonts and build an internal representation
+### ourselves.
+###
+
(begin-jit
:module-name "make-font"
:cflags @["-Ideps/stb" "-Ideps"])
@@ -15,15 +23,18 @@
(include "stb_truetype.h")
(include "stb_image_write.h")
+(include <string.h>)
(cfunction load-font
"Load a font from disk and create compressed font"
- [path:cstring gw:int gh:int] -> int
+ [header-dest:cstring cname:cstring path:cstring gw:int gh:int] -> int
(def fnt:stbtt-fontinfo)
- (def font-buffer (malloc (<< 1 23)))
+ (def font-buffer (malloc (<< 1 24)))
(def f (fopen path "rb"))
- (assert (fread font-buffer 1 (<< 1 23) f))
+ (unless f
+ (janet-panic "no font file found"))
+ (assert (fread font-buffer 1 (<< 1 24) f))
(fclose f)
# Raster pixel data from stb truetype
@@ -35,36 +46,59 @@
(def scale:float (stbtt-ScaleForPixelHeight ;fnt gh))
(printf "scale: %f\n" scale)
+ # Iterate glyphs to find the overall offset for characters
+ (var x0min:int 10000)
+ (var y0min:int 10000)
+ (var x1max:int -10000)
+ (var y1max:int -10000)
+ (for [(var glyph:int 1) (<= glyph 0x100) (++ glyph)]
+ (var x0:int 0)
+ (var y0:int 0)
+ (var x1:int 0)
+ (var y1:int 0)
+ (stbtt-GetGlyphBitmapBox ;fnt glyph scale scale ;x0 ;y0 ;x1 ;y1)
+ # (printf "glyph %d (x0, y0, x1, y1) = (%d, %d, %d, %d)\n" glyph x0 y0 x1 y1)
+ (set x0min (? (< x0 x0min) x0 x0min))
+ (set y0min (? (< y0 y0min) y0 y0min))
+ (set x1max (? (> x1 x1max) x1 x1max))
+ (set y1max (? (> y1 y1max) y1 y1max)))
+
+ (assert (>= gw (- x1max x0min)))
+ (assert (>= gh (- y1max y0min)))
+ (assert (< 0 (- x1max x0min)))
+ (assert (< 0 (- y1max y0min)))
+ (def xoff:int (- x0min))
+ (def yoff:int (- y0min))
+ (printf "xoff, yoff = %d, %d\n" xoff yoff)
+
# Iterate glyphs
(for [(var glyph:int 1) (<= glyph 0x100) (++ glyph)]
- #(def glyph:int (stbtt-FindGlyphIndex ;fnt codepoint))
- #(if (= 0 glyph) (continue))
- (var lsb:int 0)
- (var advance:int 0)
- (var ascent:int 0)
- (var descent 0)
(var x0:int 0)
(var y0:int 0)
(var x1:int 0)
(var y1:int 0)
- (stbtt-GetGlyphHMetrics ;fnt glyph ;advance ;lsb)
(stbtt-GetGlyphBitmapBox ;fnt glyph scale scale ;x0 ;y0 ;x1 ;y1)
- (printf "glyph %d (x0, y0, x1, y1, advance, lsb) = (%d, %d, %d, %d, %d, %d)\n" glyph x0 y0 x1 y1 advance lsb)
(def pw:int (* 16 gw))
- #(def x:int (* gw (% codepoint 16)))
- #(def y:int (* gh (/ codepoint 16)))
- (def x:int (+ x0 (* gw (% (- glyph 1) 16))))
- (def y:int (+ y0 -1 gh (* gh (/ (- glyph 1) 16))))
+ (def x:int (+ x0 xoff (* gw (% (- glyph 1) 16))))
+ (def y:int (+ y0 yoff (* gh (/ (- glyph 1) 16))))
+ # (printf "rendering at (x, y) = (%d, %d)\n" x y)
(stbtt-MakeGlyphBitmap ;fnt (+ img-data x (* pw y)) gw gh pw scale scale glyph))
+
+ # Clean up font data
(free font-buffer)
# Write image for debugging
- (stbi-write-png "deps/cp437_font.png" (* 16 gw) (* 16 gh) 1 img-data (* 16 gw))
+ (def pngname (malloc 1000))
+ (memset pngname 0 1000)
+ (strcat pngname header-dest)
+ (strcat pngname ".png")
+ (stbi-write-png pngname (* 16 gw) (* 16 gh) 1 img-data (* 16 gw))
+ (free pngname)
# Now extract pixels into 1 bit per pixel buffer.
# Print the buffer as a C array
- (def fp (fopen "deps/cp437_font.h" "wb"))
- (fprintf fp "unsigned char cp437_font_data[] = {\n")
+ (def fp (fopen header-dest "wb"))
+ (fprintf fp "unsigned char %s_data[] = {\n" cname)
(for [(var y:int 0) (< y (* 16 gh)) (set y (+ y gh))]
(for [(var x:int 0) (< x (* 16 gw)) (set x (+ x gw))]
(fprintf fp "\n")
@@ -77,6 +111,10 @@
(set next-byte (<< next-byte 1))))
(fprintf fp "0x%.2X, " next-byte))))
(fprintf fp "\n\n};\n")
+ (fprintf fp "const BitmapFont %s = {\n" cname)
+ (fprintf fp " .gw = %d,\n" gw)
+ (fprintf fp " .gh = %d,\n" gh)
+ (fprintf fp " .data = %s_data\n};\n" cname)
(fclose fp)
(printf "Made font %s\n" path)
@@ -86,5 +124,6 @@
(end-jit)
### Save the font to a file so we can look at it
-(load-font "deps/fonts/Px437_DG_One.ttf" 8 8)
-#(load-font "deps/fonts/Px437_Nix8810_M16.ttf" 8 16)
+(load-font "deps/default_font.h" "default_font" "deps/fonts/Px437_DG_One.ttf" 8 8)
+(load-font "deps/tall_font.h" "tall_font" "deps/fonts/Px437_Nix8810_M16.ttf" 8 16)
+(load-font "deps/olive_font.h" "olive_font" "deps/fonts/Px437_OlivettiThin_8x16.ttf" 8 16)