bdf_kern.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. bdf_kern.c
  3. */
  4. #include "bdf_font.h"
  5. #include <assert.h>
  6. #define BDF_KERNING_MAX (1024*60)
  7. /* the following tables contain the first encodings if they do contain any kernings */
  8. uint16_t bdf_first_table_cnt;
  9. uint16_t bdf_first_encoding_table[BDF_KERNING_MAX];
  10. uint16_t bdf_index_to_second_table[BDF_KERNING_MAX];
  11. /* the index from bdf_index_to_second_table can be used to jump into the following table */
  12. uint16_t bdf_second_table_cnt;
  13. uint16_t bdf_second_encoding_table[BDF_KERNING_MAX];
  14. uint8_t bdf_kerning_values[BDF_KERNING_MAX];
  15. /*
  16. struct u8g2_kerning
  17. {
  18. uint16_t first_table_cnt;
  19. uint16_t second_table_cnt;
  20. uint16_t *first_encoding_table;
  21. uint16_t *index_to_second_table;
  22. uin16_t *second_encoding_table;
  23. uint8_t *kerning_values;
  24. }
  25. */
  26. static void bdf_write_uint16_array(FILE *fp, const char *pre, const char *post, uint16_t cnt, const uint16_t *a)
  27. {
  28. uint16_t i;
  29. fprintf(fp, "static const uint16_t %s_%s[%u] = {\n ", pre, post, cnt);
  30. for( i = 0; i < cnt; i++ )
  31. {
  32. fprintf(fp, "%u", a[i]);
  33. if ( i+1 < cnt )
  34. {
  35. fprintf(fp, ", ");
  36. if ( i % 16 == 0 && i > 0 )
  37. {
  38. fprintf(fp, "\n ");
  39. }
  40. }
  41. }
  42. fprintf(fp, "};\n");
  43. }
  44. static void bdf_write_uint8_array(FILE *fp, const char *pre, const char *post, uint16_t cnt, const uint8_t *a)
  45. {
  46. uint16_t i;
  47. fprintf(fp, "static const uint8_t %s_%s[%u] = {\n ", pre, post, cnt);
  48. for( i = 0; i < cnt; i++ )
  49. {
  50. fprintf(fp, "%u", a[i]);
  51. if ( i+1 < cnt )
  52. {
  53. fprintf(fp, ", ");
  54. if ( i % 16 == 0 && i > 0 )
  55. {
  56. fprintf(fp, "\n ");
  57. }
  58. }
  59. }
  60. fprintf(fp, "};\n");
  61. }
  62. void bdf_write_kerning_file(const char *kernfile, const char *name)
  63. {
  64. FILE *fp;
  65. fp = fopen(kernfile, "w");
  66. fprintf(fp, "/* %s, Size: %u Bytes */\n", name, bdf_first_table_cnt*4 + bdf_second_table_cnt*3 + 4 + 8); // size calculation for 16 bit controller
  67. bdf_write_uint16_array(fp, name, "first_encoding_table", bdf_first_table_cnt, bdf_first_encoding_table);
  68. bdf_write_uint16_array(fp, name, "index_to_second_table", bdf_first_table_cnt, bdf_index_to_second_table);
  69. bdf_write_uint16_array(fp, name, "second_encoding_table", bdf_second_table_cnt, bdf_second_encoding_table);
  70. bdf_write_uint8_array(fp, name, "kerning_values", bdf_second_table_cnt, bdf_kerning_values);
  71. fprintf(fp, "u8g2_kerning_t %s_k = {\n", name);
  72. fprintf(fp, " %u, %u,\n", bdf_first_table_cnt, bdf_second_table_cnt);
  73. fprintf(fp, " %s_%s,\n", name, "first_encoding_table");
  74. fprintf(fp, " %s_%s,\n", name, "index_to_second_table");
  75. fprintf(fp, " %s_%s,\n", name, "second_encoding_table");
  76. fprintf(fp, " %s_%s};\n\n", name, "kerning_values");
  77. fclose(fp);
  78. }
  79. /*
  80. assumes
  81. tga_set_font(font);
  82. and
  83. tga_init((tga_get_char_width()+16)*3, ((tga_get_char_height()+8)*2));
  84. is called before
  85. */
  86. static int bdf_is_glyph_overlap(uint8_t *font, uint16_t e1, uint16_t e2, uint8_t kerning_test, int is_save)
  87. {
  88. unsigned int x, y;
  89. tga_clear();
  90. x = 8;
  91. y = tga_get_char_height();
  92. x += tga_draw_glyph(x, y, e1, 0);
  93. x -= kerning_test;
  94. tga_clear_pixel_intersection();
  95. x += tga_draw_glyph(x, y, e2, 0);
  96. if ( is_save )
  97. {
  98. //char buf[64];
  99. //sprintf(buf, "glyph_intersection_%u_%u_%u.tga", e1, e2, kerning_test);
  100. //tga_save(buf);
  101. }
  102. return tga_is_pixel_intersection();
  103. }
  104. unsigned bdf_calculate_kerning(uint8_t *font, uint16_t e1, uint16_t e2, uint8_t min_distance_in_per_cent_of_char_width)
  105. {
  106. uint8_t upper_bound;
  107. uint8_t kerning;
  108. uint8_t min_distance_in_pixel;
  109. tga_set_font(font);
  110. tga_init((tga_get_char_width()+16)*3, ((tga_get_char_height()+8)*2));
  111. min_distance_in_pixel = ((unsigned)tga_get_char_width()*(unsigned)min_distance_in_per_cent_of_char_width) / 100;
  112. upper_bound = tga_get_char_width();
  113. for( kerning = 0; kerning < upper_bound; kerning++ )
  114. {
  115. if ( bdf_is_glyph_overlap(font, e1, e2, kerning, 0) != 0 )
  116. break;
  117. }
  118. if ( kerning >= upper_bound )
  119. kerning = 0; /* maybe "." compared against "-" */
  120. if ( kerning < min_distance_in_pixel )
  121. kerning = 0;
  122. else
  123. kerning -= min_distance_in_pixel;
  124. if ( kerning != 0 )
  125. {
  126. bdf_is_glyph_overlap(font, e1, e2, kerning, 1);
  127. //printf("bdf_calculate_kerning %u %u ", e1, e2);
  128. //printf("result: %d\n", kerning);
  129. }
  130. return kerning;
  131. }
  132. void bdf_calculate_all_kerning(bf_t *bf, const char *filename, const char *fontname, uint8_t min_distance_in_per_cent_of_char_width)
  133. {
  134. int first, second;
  135. bg_t *bg_first;
  136. bg_t *bg_second;
  137. uint8_t kerning;
  138. int is_first_encoding_added;
  139. bdf_first_table_cnt = 0;
  140. bdf_second_table_cnt = 0;
  141. for( first= 0; first < bf->glyph_cnt; first++ )
  142. {
  143. is_first_encoding_added = 0;
  144. bg_first = bf->glyph_list[first];
  145. if ( bg_first->target_data != NULL && bg_first->is_excluded_from_kerning == 0 )
  146. {
  147. for( second= 0; second < bf->glyph_cnt; second++ )
  148. {
  149. bg_second = bf->glyph_list[second];
  150. if ( bg_second->target_data != NULL && bg_second->is_excluded_from_kerning == 0 )
  151. {
  152. kerning = bdf_calculate_kerning(bf->target_data, bg_first->encoding, bg_second->encoding, min_distance_in_per_cent_of_char_width);
  153. if ( kerning > 1 )
  154. {
  155. if ( is_first_encoding_added == 0 )
  156. {
  157. bdf_first_encoding_table[bdf_first_table_cnt] = bg_first->encoding;
  158. bdf_index_to_second_table[bdf_first_table_cnt] = bdf_second_table_cnt;
  159. bdf_first_table_cnt++;
  160. if (bdf_first_table_cnt > BDF_KERNING_MAX)
  161. {
  162. fprintf(stderr, "Kerning calculation aborted: bdf_first_table_cnt > BDF_KERNING_MAX\n");
  163. return;
  164. }
  165. is_first_encoding_added = 1;
  166. }
  167. bdf_second_encoding_table[bdf_second_table_cnt] = bg_second->encoding;
  168. bdf_kerning_values[bdf_second_table_cnt] = kerning;
  169. bdf_second_table_cnt++;
  170. if (bdf_second_table_cnt > BDF_KERNING_MAX)
  171. {
  172. fprintf(stderr, "Kerning calculation aborted: bdf_second_table_cnt > BDF_KERNING_MAX\n");
  173. return;
  174. }
  175. }
  176. }
  177. }
  178. }
  179. }
  180. /* add a final entry for more easier calculation in u8g2 */
  181. bdf_first_encoding_table[bdf_first_table_cnt] = 0x0ffff;
  182. bdf_index_to_second_table[bdf_first_table_cnt] = bdf_second_table_cnt;
  183. bdf_first_table_cnt++;
  184. bdf_write_kerning_file(filename, fontname);
  185. }