easy_font_maker.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // This program was used to encode the data for stb_simple_font.h
  2. #define STB_DEFINE
  3. #include "stb.h"
  4. #define STB_IMAGE_IMPLEMENTATION
  5. #include "stb_image.h"
  6. int w,h;
  7. uint8 *data;
  8. int last_x[2], last_y[2];
  9. int num_seg[2], non_empty;
  10. #if 0
  11. typedef struct
  12. {
  13. unsigned short first_segment;
  14. unsigned char advance;
  15. } chardata;
  16. typedef struct
  17. {
  18. unsigned char x:4;
  19. unsigned char y:4;
  20. unsigned char len:3;
  21. unsigned char dir:1;
  22. } segment;
  23. segment *segments;
  24. void add_seg(int x, int y, int len, int horizontal)
  25. {
  26. segment s;
  27. s.x = x;
  28. s.y = y;
  29. s.len = len;
  30. s.dir = horizontal;
  31. assert(s.x == x);
  32. assert(s.y == y);
  33. assert(s.len == len);
  34. stb_arr_push(segments, s);
  35. }
  36. #else
  37. typedef struct
  38. {
  39. unsigned char first_segment:8;
  40. unsigned char first_v_segment:8;
  41. unsigned char advance:5;
  42. unsigned char voff:1;
  43. } chardata;
  44. #define X_LIMIT 1
  45. #define LEN_LIMIT 7
  46. typedef struct
  47. {
  48. unsigned char dx:1;
  49. unsigned char y:4;
  50. unsigned char len:3;
  51. } segment;
  52. segment *segments;
  53. segment *vsegments;
  54. void add_seg(int x, int y, int len, int horizontal)
  55. {
  56. segment s;
  57. while (x - last_x[horizontal] > X_LIMIT) {
  58. add_seg(last_x[horizontal] + X_LIMIT, 0, 0, horizontal);
  59. }
  60. while (len > LEN_LIMIT) {
  61. add_seg(x, y, LEN_LIMIT, horizontal);
  62. len -= LEN_LIMIT;
  63. x += LEN_LIMIT*horizontal;
  64. y += LEN_LIMIT*!horizontal;
  65. }
  66. s.dx = x - last_x[horizontal];
  67. s.y = y;
  68. s.len = len;
  69. non_empty += len != 0;
  70. //assert(s.x == x);
  71. assert(s.y == y);
  72. assert(s.len == len);
  73. ++num_seg[horizontal];
  74. if (horizontal)
  75. stb_arr_push(segments, s);
  76. else
  77. stb_arr_push(vsegments, s);
  78. last_x[horizontal] = x;
  79. }
  80. void print_segments(segment *s)
  81. {
  82. int i, hpos;
  83. printf(" ");
  84. hpos = 4;
  85. for (i=0; i < stb_arr_len(s); ++i) {
  86. // repack for portability
  87. unsigned char seg = s[i].len + s[i].dx*8 + s[i].y*16;
  88. hpos += printf("%d,", seg);
  89. if (hpos > 72 && i+1 < stb_arr_len(s)) {
  90. hpos = 4;
  91. printf("\n ");
  92. }
  93. }
  94. printf("\n");
  95. }
  96. #endif
  97. chardata charinfo[128];
  98. int parse_char(int x, chardata *c, int offset)
  99. {
  100. int start_x = x, end_x, top_y = 0, y;
  101. c->first_segment = stb_arr_len(segments);
  102. c->first_v_segment = stb_arr_len(vsegments) - offset;
  103. assert(c->first_segment == stb_arr_len(segments));
  104. assert(c->first_v_segment + offset == stb_arr_len(vsegments));
  105. // find advance distance
  106. end_x = x+1;
  107. while (data[end_x*3] == 255)
  108. ++end_x;
  109. c->advance = end_x - start_x + 1;
  110. last_x[0] = last_x[1] = 0;
  111. last_y[0] = last_y[1] = 0;
  112. for (y=2; y < h; ++y) {
  113. for (x=start_x; x < end_x; ++x) {
  114. if (data[y*3*w+x*3+1] < 255) {
  115. top_y = y;
  116. break;
  117. }
  118. }
  119. if (top_y)
  120. break;
  121. }
  122. c->voff = top_y > 2;
  123. if (top_y > 2)
  124. top_y = 3;
  125. for (x=start_x; x < end_x; ++x) {
  126. int y;
  127. for (y=2; y < h; ++y) {
  128. if (data[y*3*w+x*3+1] < 255) {
  129. if (data[y*3*w+x*3+0] == 255) { // red
  130. int len=0;
  131. while (y+len < h && data[(y+len)*3*w+x*3+0] == 255 && data[(y+len)*3*w+x*3+1] == 0) {
  132. data[(y+len)*3*w+x*3+0] = 0;
  133. ++len;
  134. }
  135. add_seg(x-start_x,y-top_y,len,0);
  136. }
  137. if (data[y*3*w+x*3+2] == 255) { // blue
  138. int len=0;
  139. while (x+len < end_x && data[y*3*w+(x+len)*3+2] == 255 && data[y*3*w+(x+len)*3+1] == 0) {
  140. data[y*3*w+(x+len)*3+2] = 0;
  141. ++len;
  142. }
  143. add_seg(x-start_x,y-top_y,len,1);
  144. }
  145. }
  146. }
  147. }
  148. return end_x;
  149. }
  150. int main(int argc, char **argv)
  151. {
  152. int c, x=0;
  153. data = stbi_load("easy_font_raw.png", &w, &h, 0, 3);
  154. for (c=32; c < 127; ++c) {
  155. x = parse_char(x, &charinfo[c], 0);
  156. printf("%3d -- %3d %3d\n", c, charinfo[c].first_segment, charinfo[c].first_v_segment);
  157. }
  158. printf("===\n");
  159. printf("%d %d %d\n", num_seg[0], num_seg[1], non_empty);
  160. printf("%d\n", sizeof(segments[0]) * stb_arr_len(segments));
  161. printf("%d\n", sizeof(segments[0]) * stb_arr_len(segments) + sizeof(segments[0]) * stb_arr_len(vsegments) + sizeof(charinfo[32])*95);
  162. printf("struct {\n"
  163. " unsigned char advance;\n"
  164. " unsigned char h_seg;\n"
  165. " unsigned char v_seg;\n"
  166. "} stb_easy_font_charinfo[96] = {\n");
  167. charinfo[c].first_segment = stb_arr_len(segments);
  168. charinfo[c].first_v_segment = stb_arr_len(vsegments);
  169. for (c=32; c < 128; ++c) {
  170. if ((c & 3) == 0) printf(" ");
  171. printf("{ %2d,%3d,%3d },",
  172. charinfo[c].advance + 16*charinfo[c].voff,
  173. charinfo[c].first_segment,
  174. charinfo[c].first_v_segment);
  175. if ((c & 3) == 3) printf("\n"); else printf(" ");
  176. }
  177. printf("};\n\n");
  178. printf("unsigned char stb_easy_font_hseg[%d] = {\n", stb_arr_len(segments));
  179. print_segments(segments);
  180. printf("};\n\n");
  181. printf("unsigned char stb_easy_font_vseg[%d] = {\n", stb_arr_len(vsegments));
  182. print_segments(vsegments);
  183. printf("};\n");
  184. return 0;
  185. }