added stb, more binaryout changes"
[henge/apc.git] / stb / tools / easy_font_maker.c
diff --git a/stb/tools/easy_font_maker.c b/stb/tools/easy_font_maker.c
new file mode 100644 (file)
index 0000000..f1b4836
--- /dev/null
@@ -0,0 +1,211 @@
+// 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;
+}