System/Utilities/TrueType: Add TrueType font support via stb_truetype.h

This commit is contained in:
Alec Murphy 2025-04-04 18:20:36 -04:00
parent 172b4ce7a3
commit 356c16580c
5 changed files with 5212 additions and 1 deletions

View file

@ -28,6 +28,10 @@ WinToTop(adam_task);
#include "Utilities/Image";
load_elf("M:/build/bin/image");
// stb_truetype library
#include "Utilities/TrueType";
load_elf("M:/build/bin/truetype");
// Jakt support files
#include "Jakt/OS";
#include "Jakt/IOPort";

View file

@ -0,0 +1,50 @@
class stbtt__buf {
U8* data;
I32 cursor;
I32 size;
};
class stbtt_fontinfo {
U8* userdata;
U8* data; // pointer to .ttf file
I32 fontstart; // offset of start of font
I32 numGlyphs; // number of glyphs, needed for range checking
I32 loca, head, glyf, hhea, hmtx, kern, gpos, svg; // table locations as offset from start of .ttf
I32 index_map; // a cmap mapping for our chosen character encoding
I32 indexToLocFormat; // format needed to map from glyph index to glyph
stbtt__buf cff; // cff font data
stbtt__buf charstrings; // the charstring index
stbtt__buf gsubrs; // global charstring subroutines index
stbtt__buf subrs; // private charstring subroutines index
stbtt__buf fontdicts; // array of font dicts
stbtt__buf fdselect; // map from glyph to fontdict
};
I32 @stbtt_InitFont(stbtt_fontinfo* info, U8* data, I32 offset)
{
U64 reg RDI rdi = info;
U64 reg RSI rsi = data;
U64 reg RDX rdx = offset;
no_warn rdi, rsi, rdx;
asm {
MOV RAX, STBTT_INITFONT
CALL RAX
}
}
U8* @stbtt_RenderText(stbtt_fontinfo* info, I32 b_w, I32 b_h, I32 l_h, U8* word)
{
U64 reg RDI rdi = info;
U64 reg RSI rsi = b_w;
U64 reg RDX rdx = b_h;
U64 reg RCX rcx = l_h;
U64 reg R8 r8 = word;
no_warn rdi, rsi, rdx, rcx, r8;
asm {
MOV RAX, STBTT_RENDERTEXT
CALL RAX
}
}
"truetype ";

View file

@ -33,7 +33,7 @@ qemu_run_cmd = qemu_bin_path + ' ' + qemu_display + ' -enable-kvm -smp cores=4 -
def clang_format_src_files():
print("build-all: clang-format-src-files")
exclude_paths = ["stb_", "tlse", ".iso.c"]
exclude_paths = ["stb_", "openlibm", "tlse", ".iso.c"]
format_file_extensions = [".c", ".cpp", ".h", ".hc"]
for src_file in glob.glob(project_path + "**", recursive=True):
exclude_file = False
@ -62,12 +62,25 @@ def build_image():
if res:
raise ValueError("build-all: step 'build-image' failed, error code " + str(res))
def build_truetype():
print("build-all: build-truetype")
build_specific_options = '-Wl,--section-start=.text=0x1104000 -Wl,--section-start=.plt=0x1102020 -no-pie'
res = os.system('cd ' + project_path + '&& cd src/truetype && gcc -o ../../build/bin/truetype ' + build_specific_options + ' -O0 -mno-mmx -mno-red-zone truetype.c ../openlibm/libopenlibm.a')
if res:
raise ValueError("build-all: step 'build-image' failed, error code " + str(res))
def build_libtemple():
print("build-all: build-libtemple")
res = os.system('cd ' + project_path + 'src/libtemple && g++ -c -o ../../build/libtemple.o libtemple.cpp && gcc -shared -o ../../build/lib/libtemple.so ../../build/libtemple.o && rm ' + project_path + 'build/libtemple.o')
if res:
raise ValueError("build-all: step 'build-libtemple' failed, error code " + str(res))
def build_openlibm():
print("build-all: build-openlibm")
res = os.system('cd ' + project_path + 'src/openlibm && make clean && make ARCH=amd64')
if res:
raise ValueError("build-all: step 'build-openlibm' failed, error code " + str(res))
def build_tlse():
print("build-all: build-tlse")
build_specific_options = '-Wl,--section-start=.text=0x1204000 -Wl,--section-start=.plt=0x1202020 -no-pie'
@ -96,6 +109,10 @@ def image_hc_fixup(macro, symbol, image_bin_path, image_hc_path):
os.system('echo -e "#define ' + macro + ' ' + address_string_for_symbol(image_bin_path, symbol) + '\n" | cat - ' + image_hc_path + ' | sponge ' + image_hc_path)
return
def truetype_hc_fixup(macro, symbol, truetype_bin_path, truetype_hc_path):
os.system('echo -e "#define ' + macro + ' ' + address_string_for_symbol(truetype_bin_path, symbol) + '\n" | cat - ' + truetype_hc_path + ' | sponge ' + truetype_hc_path)
return
def tlse_hc_fixup(macro, symbol, tlse_bin_path, tlse_hc_path):
os.system('echo -e "#define ' + macro + ' ' + address_string_for_symbol(tlse_bin_path, symbol) + '\n" | cat - ' + tlse_hc_path + ' | sponge ' + tlse_hc_path)
return
@ -138,6 +155,13 @@ def generate_iso_c_file():
image_hc_fixup('STBI_FAILURE_REASON', 'stbi_failure_reason', image_bin_path, image_hc_path)
image_hc_fixup('RENDER_4BIT_FLOYDSTEIN', 'render_4bit_floydstein', image_bin_path, image_hc_path)
# Fixup addresses for TrueType.HC
truetype_bin_path = redsea_path + '/build/bin/truetype'
truetype_hc_path = redsea_path + '/System/Utilities/TrueType.HC'
truetype_hc_fixup('STBTT_INITFONT', 'stbtt_InitFont', truetype_bin_path, truetype_hc_path)
truetype_hc_fixup('STBTT_RENDERTEXT', 'stbtt_RenderText', truetype_bin_path, truetype_hc_path)
# Fixup addresses for Tlse.HC
rsa_hc_path = redsea_path + '/System/Libraries/Rsa.HC'
@ -180,6 +204,8 @@ def build_all():
clang_format_src_files()
refresh_build_path()
build_image()
build_openlibm()
build_truetype()
build_libtemple()
build_tlse()
transpile_net_to_sepples()

5079
src/truetype/stb_truetype.h Normal file

File diff suppressed because it is too large Load diff

52
src/truetype/truetype.c Normal file
View file

@ -0,0 +1,52 @@
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
unsigned char* stbtt_RenderText(stbtt_fontinfo* info, int b_w, int b_h, int l_h, char* word)
{
// https://github.com/justinmeiners/stb-truetype-example
/* create a bitmap for the phrase */
unsigned char* bitmap = calloc(b_w * b_h, sizeof(unsigned char));
/* calculate font scaling */
float scale = stbtt_ScaleForPixelHeight(info, l_h);
int x = 0;
int ascent, descent, lineGap;
stbtt_GetFontVMetrics(info, &ascent, &descent, &lineGap);
ascent = roundf(ascent * scale);
descent = roundf(descent * scale);
int i;
for (i = 0; i < strlen(word); ++i) {
/* how wide is this character */
int ax;
int lsb;
stbtt_GetCodepointHMetrics(info, word[i], &ax, &lsb);
/* (Note that each Codepoint call has an alternative Glyph version which caches the work required to lookup the character word[i].) */
/* get bounding box for character (may be offset to account for chars that dip above or below the line) */
int c_x1, c_y1, c_x2, c_y2;
stbtt_GetCodepointBitmapBox(info, word[i], scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);
/* compute y (different characters have different heights) */
int y = ascent + c_y1;
/* render character (stride and offset is important here) */
int byteOffset = x + roundf(lsb * scale) + (y * b_w);
stbtt_MakeCodepointBitmap(info, bitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, b_w, scale, scale, word[i]);
/* advance x */
x += roundf(ax * scale);
/* add kerning */
int kern;
kern = stbtt_GetCodepointKernAdvance(info, word[i], word[i + 1]);
x += roundf(kern * scale);
}
return bitmap;
}
int main() { return 0; }