bdf_map.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /*
  2. bdf_map.c
  3. select and map glyphs
  4. Syntax:
  5. maplist := <mapcmd> { "," <mapcmd> }
  6. mapcmd := <default> | <maprange> | <exclude>
  7. default := "*"
  8. maprange := <range> [ ">" <num> ]
  9. exclude := "~" <range>
  10. kern_exclude := "x" <range>
  11. range := <num> [ "-" <num> ]
  12. num := <hexnum> | <decnum>
  13. hexnum := "$" <hexdigit> { <hexdigit> }
  14. decnum := <decdigit> { <decdigit> }
  15. decdigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
  16. hexdigit := "a" | "b" | "c" | "d" | "e" | "f" | "A" | "B" | "C" | "D" | "E" | "F" | <decdigit>
  17. { }: zero, one ore more
  18. [ ]: zero or once
  19. |: alternative
  20. */
  21. #include "bdf_font.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <unistd.h>
  28. static long range_from;
  29. static long range_to;
  30. static int is_exclude;
  31. static int is_kern_exclude;
  32. static long map_to;
  33. static void skip_space(const char **s)
  34. {
  35. for(;;)
  36. {
  37. if ( **s == '\0' )
  38. break;
  39. if ( **s > ' ' )
  40. break;
  41. (*s)++;
  42. }
  43. }
  44. static long get_dec(const char **s)
  45. {
  46. long v = 0;
  47. for(;;)
  48. {
  49. if ( (**s) >= '0' && (**s) <= '9' )
  50. {
  51. v*=10;
  52. v+= (**s)-'0';
  53. (*s)++;
  54. }
  55. else
  56. {
  57. break;
  58. }
  59. }
  60. skip_space(s);
  61. return v;
  62. }
  63. static long get_hex(const char **s)
  64. {
  65. long v = 0;
  66. for(;;)
  67. {
  68. if ( (**s) >= '0' && (**s) <= '9' )
  69. {
  70. v*=16;
  71. v+= (**s)-'0';
  72. (*s)++;
  73. }
  74. else if ( (**s) >= 'a' && (**s) <= 'f' )
  75. {
  76. v*=16;
  77. v+= (**s)-'a'+10;
  78. (*s)++;
  79. }
  80. else if ( (**s) >= 'A' && (**s) <= 'F' )
  81. {
  82. v*=16;
  83. v+= (**s)-'A'+10;
  84. (*s)++;
  85. }
  86. else
  87. {
  88. break;
  89. }
  90. }
  91. skip_space(s);
  92. return v;
  93. }
  94. static long get_num(const char **s)
  95. {
  96. if ( (**s) != '$' )
  97. return get_dec(s);
  98. (*s)++;
  99. skip_space(s);
  100. return get_hex(s);
  101. }
  102. static long get_mul(const char **s)
  103. {
  104. long v;
  105. v = get_num(s);
  106. while ( (**s) == '*' )
  107. {
  108. (*s)++;
  109. skip_space(s);
  110. v *= get_num(s);
  111. }
  112. return v;
  113. }
  114. static long get_add(const char **s)
  115. {
  116. long v;
  117. v = get_mul(s);
  118. while ( (**s) == '+' )
  119. {
  120. (*s)++;
  121. skip_space(s);
  122. v += get_mul(s);
  123. }
  124. return v;
  125. }
  126. static long get_addsub(const char **s)
  127. {
  128. long v;
  129. int op;
  130. v = get_mul(s);
  131. while ( (**s) == '+' || (**s) == '-' )
  132. {
  133. op = **s;
  134. (*s)++;
  135. skip_space(s);
  136. if ( op == '+' )
  137. v += get_mul(s);
  138. else
  139. v -= get_mul(s);
  140. }
  141. return v;
  142. }
  143. static void get_range(const char **s)
  144. {
  145. range_from = get_add(s);
  146. if ( **s != '-' )
  147. {
  148. range_to = range_from;
  149. }
  150. else
  151. {
  152. (*s)++;
  153. skip_space(s);
  154. range_to = get_add(s);
  155. }
  156. }
  157. static void map_cmd(const char **s)
  158. {
  159. if ( **s == '*' )
  160. {
  161. range_from = 32;
  162. range_to = 255;
  163. map_to = 32;
  164. is_exclude = 0;
  165. is_kern_exclude = 0;
  166. (*s)++;
  167. skip_space(s);
  168. }
  169. else if ( **s == '~' )
  170. {
  171. is_exclude = 1;
  172. map_to = 0; /*will be ignored */
  173. (*s)++;
  174. skip_space(s);
  175. get_range(s);
  176. }
  177. else if ( **s == 'x' )
  178. {
  179. is_kern_exclude = 1;
  180. map_to = 0; /*will be ignored */
  181. (*s)++;
  182. skip_space(s);
  183. get_range(s);
  184. }
  185. else
  186. {
  187. is_exclude = 0;
  188. get_range(s);
  189. map_to = range_from;
  190. if ( **s == '>')
  191. {
  192. (*s)++;
  193. skip_space(s);
  194. map_to = get_addsub(s);
  195. }
  196. }
  197. }
  198. void bf_map_cmd(bf_t *bf, const char **s)
  199. {
  200. int i;
  201. bg_t *bg;
  202. static int is_log_disabled_for_single_glyphs = 0;
  203. if ( **s == ',' || **s == '\0' )
  204. return;
  205. map_cmd(s);
  206. if ( range_from != range_to )
  207. {
  208. bf_Log(bf, "Map: exclude=%d from=%ld/$%lx to=%ld/$%lx map=%ld/$%lx", is_exclude, range_from, range_from, range_to, range_to, map_to, map_to);
  209. }
  210. else if ( is_log_disabled_for_single_glyphs == 0 )
  211. {
  212. bf_Log(bf, "Map: exclude=%d from=%ld/$%lx to=%ld/$%lx map=%ld/$%lx (further single glyph logs disabled)", is_exclude, range_from, range_from, range_to, range_to, map_to, map_to);
  213. is_log_disabled_for_single_glyphs = 1;
  214. }
  215. for( i = 0; i < bf->glyph_cnt; i++ )
  216. {
  217. bg = bf->glyph_list[i];
  218. if ( bg->encoding >= range_from && bg->encoding <= range_to )
  219. {
  220. if ( is_kern_exclude != 0 )
  221. {
  222. bg->is_excluded_from_kerning = 1;
  223. }
  224. else
  225. {
  226. if ( is_exclude != 0 )
  227. {
  228. bg->map_to = -1;
  229. }
  230. else
  231. {
  232. bg->map_to = bg->encoding - range_from + map_to;
  233. }
  234. }
  235. }
  236. }
  237. }
  238. void bf_map_list(bf_t *bf, const char **s)
  239. {
  240. int i;
  241. bg_t *bg;
  242. /* exclude everything first */
  243. for( i = 0; i < bf->glyph_cnt; i++ )
  244. {
  245. bg = bf->glyph_list[i];
  246. bg->map_to = -1;
  247. }
  248. /* process the mapping list list */
  249. skip_space(s);
  250. for(;;)
  251. {
  252. bf_map_cmd(bf, s);
  253. if ( **s != ',' )
  254. break;
  255. (*s)++;
  256. skip_space(s);
  257. }
  258. }
  259. void bf_Map(bf_t *bf, const char *map_cmd_list)
  260. {
  261. if ( strlen(map_cmd_list) < 1024 )
  262. bf_Log(bf, "Map: map_cmd_list='%s'", map_cmd_list);
  263. bf_map_list(bf, &map_cmd_list);
  264. }
  265. int bf_MapFile(bf_t *bf, const char *map_file_name)
  266. {
  267. struct stat buf;
  268. char *s;
  269. FILE *fp;
  270. if ( map_file_name == NULL )
  271. return 1;
  272. if ( map_file_name[0] == '\0' )
  273. return 1;
  274. if ( stat(map_file_name, &buf) != 0 )
  275. return 0;
  276. fp = fopen(map_file_name, "r");
  277. if ( fp == NULL )
  278. return 0;
  279. s = malloc(buf.st_size+1);
  280. if ( s == NULL )
  281. return 0;
  282. if ( fread(s, buf.st_size, 1, fp) != 1 ) {
  283. free(s);
  284. return 0;
  285. }
  286. s[buf.st_size] = '\0';
  287. fclose(fp);
  288. bf_Map(bf, s);
  289. free(s);
  290. return 1;
  291. }
  292. /* add all characters in utf8 text file to font */
  293. int bf_Utf8File(bf_t *bf, const char *utf8_file_name) {
  294. static const int utf8_verbose = 0;
  295. struct stat buf;
  296. FILE *fp;
  297. int byte = 0;
  298. uint32_t code = 0;
  299. int more_bytes = 0;
  300. int utf8_errs = 0;
  301. int i;
  302. bg_t *bg;
  303. if (utf8_file_name == NULL)
  304. return 1;
  305. if (utf8_file_name[0] == '\0')
  306. return 1;
  307. if (stat(utf8_file_name, &buf) != 0)
  308. return 0;
  309. fp = fopen(utf8_file_name, "r");
  310. if (fp == NULL)
  311. return 0;
  312. while ((byte = getc(fp)) != EOF) {
  313. code = 0;
  314. more_bytes = 0;
  315. if (byte <= 0x7F) {
  316. code = byte;
  317. more_bytes = 0;
  318. } else if ((byte & 0xE0) == 0xC0) {
  319. code = byte & 0x1F;
  320. more_bytes = 1;
  321. } else if ((byte & 0xF0) == 0xE0) {
  322. code = byte & 0x0F;
  323. more_bytes = 2;
  324. } else if ((byte & 0xF8) == 0xF0) {
  325. code = byte & 0x07;
  326. more_bytes = 3;
  327. } else if ((byte & 0xFC) == 0xF8) {
  328. code = byte & 0x03;
  329. more_bytes = 4;
  330. } else if ((byte & 0xFE) == 0xFC) {
  331. code = byte & 0x01;
  332. more_bytes = 5;
  333. } else {
  334. if (utf8_verbose)
  335. printf("? 0x%X\r\n", byte);
  336. utf8_errs++;
  337. continue;
  338. }
  339. while (more_bytes > 0) {
  340. byte = getc(fp);
  341. if (byte == EOF)
  342. break;
  343. if ((byte & 0xC0) != 0x80) {
  344. utf8_errs++;
  345. break;
  346. }
  347. code = (code << 6) | (byte & 0x3F);
  348. --more_bytes;
  349. }
  350. if (more_bytes == 0) {
  351. /* find glyph in font */
  352. for (i = 0; i < bf->glyph_cnt; i++) {
  353. bg = bf->glyph_list[i];
  354. if (bg->encoding == code) {
  355. if (utf8_verbose)
  356. printf("glyph found: 0x%X\r\n", code);
  357. bg->map_to = bg->encoding;
  358. break;
  359. }
  360. }
  361. if (utf8_verbose && (i == bf->glyph_cnt))
  362. printf("glyph not found: 0x%X\r\n", code);
  363. }
  364. }
  365. if (utf8_errs != 0)
  366. printf("%u utf8 errors\r\n", utf8_errs);
  367. fclose(fp);
  368. return 1;
  369. }