An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
86 lines
3.7 KiB
C
86 lines
3.7 KiB
C
#pragma once
|
|
|
|
// Text rendering.
|
|
//
|
|
// The console draws text by indexing `font_data[256][16]` and stepping the
|
|
// cursor eight pixels. That is a *character cell grid*, and it is the thing in
|
|
// the way -- not the font. A grid cannot do variable-width glyphs, cannot
|
|
// position text anywhere except on a multiple of eight, cannot anti-alias, and
|
|
// cannot represent a codepoint above 255. Swapping the bitmap for a nicer
|
|
// bitmap changes none of that.
|
|
//
|
|
// So this is a layer, not a font. Three things it fixes:
|
|
//
|
|
// *Glyphs have metrics.* A glyph knows its own size, its bearing and how far
|
|
// to advance afterwards. That is what variable-width text is; everything else
|
|
// follows from it.
|
|
//
|
|
// *It draws into a surface, not into the screen.* A compositor draws into an
|
|
// off-screen buffer and presents it. Rendering that writes straight to the
|
|
// VGA aperture is unusable to it, which is why this takes a target.
|
|
//
|
|
// *The font is behind an interface.* The bitmap font is one implementation.
|
|
// A TrueType rasteriser is another, and arrives without any caller changing:
|
|
// glyphs carry 8-bit coverage, so an anti-aliased outline renderer already
|
|
// has somewhere to put its output.
|
|
|
|
struct font;
|
|
|
|
// Somewhere to draw. Deliberately not a `struct device` or a framebuffer: the
|
|
// same code has to work on the virtio-gpu back buffer, on a window's own
|
|
// buffer, and on the VGA aperture, and none of those know about each other.
|
|
struct surface {
|
|
void *pixels; // 32-bit 0x00RRGGBB, the format everything here uses
|
|
uint32 stride; // bytes per row, not pixels -- they differ on real hardware
|
|
int width, height;
|
|
};
|
|
|
|
// One rendered glyph. `cov` is 8-bit coverage, not a bitmap: 0 is background,
|
|
// 255 is solid, and everything between is an anti-aliased edge. A bitmap font
|
|
// fills it with 0 and 255 only, and costs nothing for the generality.
|
|
struct glyph {
|
|
const unsigned char *cov; // w*h bytes, row-major
|
|
int w, h; // size of the coverage bitmap
|
|
int bearing_x, bearing_y; // offset from the pen to the top-left of `cov`
|
|
int advance; // how far the pen moves afterwards
|
|
};
|
|
|
|
struct font_ops {
|
|
// Fill `out` for `cp`. Returns 0, or -1 if the font has no such glyph --
|
|
// callers substitute rather than failing, because a missing glyph must not
|
|
// stop a line of text.
|
|
int (*glyph)(struct font *, uint32 cp, struct glyph *out);
|
|
int (*height)(struct font *); // line height
|
|
int (*baseline)(struct font *); // pen offset from the top of the line
|
|
};
|
|
|
|
struct font {
|
|
const struct font_ops *ops;
|
|
void *priv;
|
|
};
|
|
|
|
// The built-in bitmap font, as a font provider. Always available, needs no
|
|
// allocation, and is what the console falls back to before any filesystem
|
|
// exists to load a real typeface from.
|
|
struct font *font_builtin(void);
|
|
|
|
// Draw one UTF-8 string. Returns the x advance.
|
|
//
|
|
// `x, y` is the pen position on the *baseline*, which is how every text API
|
|
// that is not a terminal works -- glyphs of different heights then sit on a
|
|
// common line instead of being top-aligned.
|
|
int text_draw(struct surface *, struct font *, int x, int y,
|
|
const char *utf8, uint32 color);
|
|
|
|
// Width the same string would occupy, without drawing it. Needed before you
|
|
// draw, for centring and for laying out anything at all.
|
|
int text_measure(struct font *, const char *utf8);
|
|
|
|
// One glyph, for callers doing their own layout.
|
|
int text_draw_glyph(struct surface *, struct font *, int x, int y,
|
|
uint32 cp, uint32 color);
|
|
|
|
// Decode one UTF-8 sequence. Returns the codepoint and advances *p.
|
|
// Malformed input yields U+FFFD and consumes one byte, so a decoder loop
|
|
// always terminates.
|
|
uint32 utf8_next(const char **p);
|