std1.0.0-beta-7 SafeC docs

Source gui/gui_font.h

View in the repository

#pragma once
// SafeC Standard Library — GUI: loadable/serializable bitmap fonts.
//
// GuiWindow::draw_text() (gui.h) always uses the single built-in 8x8 font
// baked into the binary. This header adds a real font *asset*: a generic
// bit-packed glyph bitmap (any glyph size, not just 8x8) that can be
// built programmatically, saved to disk, and reloaded — and a
// drawing API on the font itself (font.draw_text(&win, ...)), for UIs that want
// a custom look instead of (or alongside) the built-in font.
//
// On-disk format ("SCXF", version 1) — little-endian, no external
// dependency (not TTF/OTF — a font must already be rasterized to a
// GuiFont, e.g. via GuiFont::new()+font.set_bit(), before it can be
// saved):
//   offset 0  (4 bytes)  magic "SCXF"
//   offset 4  (1 byte)   version = 1
//   offset 5  (1 byte)   glyphW (pixels, 1-255)
//   offset 6  (1 byte)   glyphH (pixels, 1-255)
//   offset 7  (1 byte)   reserved = 0
//   offset 8  (4 bytes)  first codepoint (uint32 LE)
//   offset 12 (4 bytes)  glyph count (uint32 LE)
//   offset 16 ...        count * ceil(glyphW*glyphH/8) bytes: each glyph's
//                        pixels, row-major, MSB-first-per-byte, packed
//                        with no padding between rows or glyphs.

#include <std/gui/gui.h>

namespace std {

struct GuiFont {
    int glyphW;
    int glyphH;
    int first;                  // first codepoint this font covers
    int count;                  // number of glyphs (codepoints first..first+count-1)
    &heap unsigned char bitmap; // count * bytesPerGlyph(glyphW,glyphH) bytes

    // Allocates a blank (all-zero) font of the given shape, ready for
    // set_bit() calls to draw each glyph programmatically.
    static struct GuiFont new(int glyphW, int glyphH, int first, int count);

    // A heap-owned copy of the built-in 8x8 font (see gui_draw.sc), in the
    // same generic GuiFont representation — e.g. as a starting point to edit
    // with set_bit() and save a modified variant. Release it with free().
    static struct GuiFont default();

    // Bit accessors, (0,0) = top-left of the glyph for codepoint 'cp'.
    // Reads return 0 for an out-of-range codepoint or pixel; writes are a
    // no-op in that case.
    int  get_bit(int cp, int px, int py) const;
    void set_bit(int cp, int px, int py, int value);

    // Serialization. save() writes this font as an SCXF file; load()
    // reads one into this font in place (overwriting it without freeing —
    // call it on a fresh 'struct GuiFont f;', or free() first). On failure
    // load() leaves the font untouched. Both return 1 = ok.
    int  save(const &char path) const;
    int  load(const &char path);
    void drop();

    void free() consume;   // = drop()

    // Drawing with this font (mirrors GuiWindow::draw_text() and
    // gui_draw.h's gui_text_width()/gui_text_height() for the built-in
    // font): each glyph cell is glyphW*scale by glyphH*scale pixels;
    // codepoints the font doesn't cover draw as a blank cell. draw_text()
    // returns the total pixel width drawn.
    int  draw_text(&GuiWindow win, int x, int y, const &char text,
                   struct GuiColor color, int scale) const;
    int  text_width(const &char text, int scale) const;
    int  text_height(int scale) const;
};

} // namespace std