examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

commit a9a3d1db2af2ca9a43e1884bfda67dfc32afc665
parent c980f07c3d481ee40e06b33b603da5010838b965
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Wed, 26 Jun 2024 23:01:37 +0100

sdl-gl: Load console raster font and draw test string

Diffstat:
Msrc/sdl-gl.cpp | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 110 insertions(+), 5 deletions(-)

diff --git a/src/sdl-gl.cpp b/src/sdl-gl.cpp @@ -17,6 +17,9 @@ #include <random> #include <ranges> #include <vector> +#include <unistd.h> +#include <sys/wait.h> +#include <err.h> extern "C" char const* __asan_default_options() { return "detect_leaks=0"; } @@ -279,11 +282,7 @@ void panel::draw() const glEnd(); } -void draw_UI() -{ - panel{50, 50, 99, 49}.draw(); - panel{50, 100, 99, 49}.draw(); -} + void key(SDL_KeyboardEvent& e) { @@ -466,12 +465,118 @@ void init_shape() shape_wireframe = shape_wireframe.subspan(1, shape.size() - 2); } +struct psf2 +{ + unsigned int magic, version, hdr_size, flags, length, g_size, height, width; +}; +struct font +{ + psf2 hdr; + GLuint tex; + font(char const* filename) + { + int fds[2]; + if (pipe(fds)) + err(1, "pipe"); + pid_t child = fork(); + if (child < 0) + err(1, "fork"); + if (!child) + { + if (dup2(fds[1], 1) == -1) + err(1, "dup2"); + if (close(fds[0])) + err(1, "close"); + if (close(fds[1])) + err(1, "close"); + execlp("gunzip", "gunzip", "--stdout", filename, nullptr); + err(1, "execlp"); + } + close(fds[1]); + + if (read(fds[0], &hdr, sizeof(hdr)) != sizeof(hdr)) + err(1, "read"); + if (hdr.magic != 0x864AB572) + errx(1, "Not a PSF2 file"); + + std::vector<unsigned char> storage(hdr.length * hdr.g_size); + + for (ssize_t read = 0; read < (ssize_t)storage.size(); ) + { + int n = ::read(fds[0], storage.data() + read, storage.size() - read); + if (n < 0) + err(1, "read"); + if (n == 0) + errx(1, "not enough data from font"); + read += n; + } + close(fds[0]); + assert(wait(nullptr) == child); + std::vector<unsigned char> pix(hdr.length * hdr.height * hdr.width); + + for (size_t i = 0; i < pix.size(); ++i) + pix[i] = ((storage[i / 8] >> (7 - i % 8)) & 1) * 255; + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, hdr.width, hdr.height * hdr.length, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pix.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + screen_coord draw(unsigned char c, screen_coord pos) + { + screen_coord br_screen{pos.x + (int)hdr.width, pos.y + (int)hdr.height}; + float text = (float)c / hdr.length; + float texb = (float)(c + 1u) / hdr.length; + auto tl = window_to_gl(pos); + auto tr = window_to_gl({br_screen.x, pos.y}); + auto bl = window_to_gl({pos.x, br_screen.y}); + auto br = window_to_gl(br_screen); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2f(0,text); + glVertex(tl); + glTexCoord2f(1,text); + glVertex(tr); + glTexCoord2f(0,texb); + glVertex(bl); + glTexCoord2f(1,texb); + glVertex(br); + glEnd(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + + return br_screen; + } + screen_coord draw(char const* str, screen_coord pos) + { + while (*str) + pos.x = draw(*str++, pos).x; + return pos; + } +}; + +font* fnt; + +void draw_UI() +{ + panel{50, 50, 149, 49}.draw(); + glColor3f(1,1,1); + fnt->draw("Hello, World!", {51, 51}); + panel{50, 100, 149, 49}.draw(); +} + int main() { init_shape(); mouse_task(); initSDL(); atexit(SDL_Quit); + + fnt = new font{"/usr/share/kbd/consolefonts/lat9-16.psf.gz"}; + for (;;) { doInput();