|
|
// This program was used to encode the data for stb_simple_font.h
#define STB_DEFINE
#include "stb.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
int w,h; uint8 *data;
int last_x[2], last_y[2]; int num_seg[2], non_empty; #if 0
typedef struct { unsigned short first_segment; unsigned char advance; } chardata;
typedef struct { unsigned char x:4; unsigned char y:4; unsigned char len:3; unsigned char dir:1; } segment;
segment *segments;
void add_seg(int x, int y, int len, int horizontal) { segment s; s.x = x; s.y = y; s.len = len; s.dir = horizontal; assert(s.x == x); assert(s.y == y); assert(s.len == len); stb_arr_push(segments, s); } #else
typedef struct { unsigned char first_segment:8; unsigned char first_v_segment:8; unsigned char advance:5; unsigned char voff:1; } chardata;
#define X_LIMIT 1
#define LEN_LIMIT 7
typedef struct { unsigned char dx:1; unsigned char y:4; unsigned char len:3; } segment;
segment *segments; segment *vsegments;
void add_seg(int x, int y, int len, int horizontal) { segment s;
while (x - last_x[horizontal] > X_LIMIT) { add_seg(last_x[horizontal] + X_LIMIT, 0, 0, horizontal); } while (len > LEN_LIMIT) { add_seg(x, y, LEN_LIMIT, horizontal); len -= LEN_LIMIT; x += LEN_LIMIT*horizontal; y += LEN_LIMIT*!horizontal; }
s.dx = x - last_x[horizontal]; s.y = y; s.len = len; non_empty += len != 0; //assert(s.x == x);
assert(s.y == y); assert(s.len == len); ++num_seg[horizontal]; if (horizontal) stb_arr_push(segments, s); else stb_arr_push(vsegments, s); last_x[horizontal] = x; }
void print_segments(segment *s) { int i, hpos; printf(" "); hpos = 4; for (i=0; i < stb_arr_len(s); ++i) { // repack for portability
unsigned char seg = s[i].len + s[i].dx*8 + s[i].y*16; hpos += printf("%d,", seg); if (hpos > 72 && i+1 < stb_arr_len(s)) { hpos = 4; printf("\n "); } } printf("\n"); }
#endif
chardata charinfo[128];
int parse_char(int x, chardata *c, int offset) { int start_x = x, end_x, top_y = 0, y;
c->first_segment = stb_arr_len(segments); c->first_v_segment = stb_arr_len(vsegments) - offset; assert(c->first_segment == stb_arr_len(segments)); assert(c->first_v_segment + offset == stb_arr_len(vsegments));
// find advance distance
end_x = x+1; while (data[end_x*3] == 255) ++end_x; c->advance = end_x - start_x + 1;
last_x[0] = last_x[1] = 0; last_y[0] = last_y[1] = 0;
for (y=2; y < h; ++y) { for (x=start_x; x < end_x; ++x) { if (data[y*3*w+x*3+1] < 255) { top_y = y; break; } } if (top_y) break; } c->voff = top_y > 2; if (top_y > 2) top_y = 3;
for (x=start_x; x < end_x; ++x) { int y; for (y=2; y < h; ++y) { if (data[y*3*w+x*3+1] < 255) { if (data[y*3*w+x*3+0] == 255) { // red
int len=0; while (y+len < h && data[(y+len)*3*w+x*3+0] == 255 && data[(y+len)*3*w+x*3+1] == 0) { data[(y+len)*3*w+x*3+0] = 0; ++len; } add_seg(x-start_x,y-top_y,len,0); } if (data[y*3*w+x*3+2] == 255) { // blue
int len=0; while (x+len < end_x && data[y*3*w+(x+len)*3+2] == 255 && data[y*3*w+(x+len)*3+1] == 0) { data[y*3*w+(x+len)*3+2] = 0; ++len; } add_seg(x-start_x,y-top_y,len,1); } } } } return end_x; }
int main(int argc, char **argv) { int c, x=0; data = stbi_load("easy_font_raw.png", &w, &h, 0, 3); for (c=32; c < 127; ++c) { x = parse_char(x, &charinfo[c], 0); printf("%3d -- %3d %3d\n", c, charinfo[c].first_segment, charinfo[c].first_v_segment); } printf("===\n"); printf("%d %d %d\n", num_seg[0], num_seg[1], non_empty); printf("%d\n", sizeof(segments[0]) * stb_arr_len(segments)); printf("%d\n", sizeof(segments[0]) * stb_arr_len(segments) + sizeof(segments[0]) * stb_arr_len(vsegments) + sizeof(charinfo[32])*95);
printf("struct {\n" " unsigned char advance;\n" " unsigned char h_seg;\n" " unsigned char v_seg;\n" "} stb_easy_font_charinfo[96] = {\n"); charinfo[c].first_segment = stb_arr_len(segments); charinfo[c].first_v_segment = stb_arr_len(vsegments); for (c=32; c < 128; ++c) { if ((c & 3) == 0) printf(" "); printf("{ %2d,%3d,%3d },", charinfo[c].advance + 16*charinfo[c].voff, charinfo[c].first_segment, charinfo[c].first_v_segment); if ((c & 3) == 3) printf("\n"); else printf(" "); } printf("};\n\n");
printf("unsigned char stb_easy_font_hseg[%d] = {\n", stb_arr_len(segments)); print_segments(segments); printf("};\n\n");
printf("unsigned char stb_easy_font_vseg[%d] = {\n", stb_arr_len(vsegments)); print_segments(vsegments); printf("};\n"); return 0; }
|