// Smolhershey font library. Copyright 02024 Kragen Javier Sitaker. // See smolhershey.md for license. #include "smolhershey.h" int sh_load_font(sh_font *f, u8 *p, int n) { int m = 0; // Number of lines read. u8 *e = p + n; // End of buffer. for (;;) { if (m < f->n) f->lines[m] = p; // Add line pointer to array if possible m++; if (p == e) break; while (p != e) { if (*p++ == '\n') break; } } if (m < f->n) f->n = m; // Update glyph array length if possible. return m; } static inline sh_point displace(sh_point a, sh_point b) { return (sh_point){ a.x + b.x, a.y + b.y }; } void sh_show(sh_gc *gc, unsigned glyph_index) { // An example line from a JHF file is // 12345 14G\KFK[ RKFTFWGXHYJYMXOWPTQKQ\n // 0123456789 123456789 123456789 123456 <- byte offset // This means glyph 12345 has 14 points, with left boundary at G, // right boundary at \, first line from KF to K[, followed by // lifting the pen, a line from KF to TF, a line from TF to WG, etc. // Each character represents a coordinate in offset-'R' form; 'R' is // 0, 'S' is 1, 'T' is 2, 'Q' is -1, 'P' is -2, etc, so to get the // numeric value we subtract 'R'. So KF is (-7, -12), K[ is (-7, // 9), G is -11, \ is 10, etc. As a special case, the " R" escape // means to lift the pen. // For our purposes we don’t care about the glyph number, and we can // infer the number of points from the line length (because Kamal // Mostafa has joined the lines of text originally broken at 72 // columns). We only care about the left and right boundaries and // the points. // Bias current point by JHF bias value 'R' to decode the bytes. // The x-bias is implicit in the later cp.x -= line[8] step. sh_point cp = displace(gc->cp, (sh_point){0, -'R'}); if (glyph_index + 1 >= gc->font->n) return; // Out of bounds! u8 **lines = gc->font->lines, *line = lines[glyph_index], *end = lines[glyph_index+1] - 1; cp.x -= line[8]; // Move to center of glyph by adding left width for (u8 *p = &line[12]; p < end; p += 2) { if (p[-2] == ' ' || p[0] == ' ') continue; gc->draw_line(displace(cp, (sh_point){ p[-2], p[-1] }), displace(cp, (sh_point){ p[0], p[1] }), gc->userdata); } cp.x += line[9] - 'R'; // Move to right edge of glyph by adding right width gc->cp = displace(cp, (sh_point){'R', 'R'}); }