bdf_parser.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. #include <assert.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "bdf_font.h"
  5. static int bf_curr(bf_t * bf)
  6. {
  7. if ( bf->line_pos >= BDF_LINE_LEN )
  8. return '\0';
  9. return bf->line_buf[bf->line_pos];
  10. }
  11. static void bf_next(bf_t *bf)
  12. {
  13. if ( bf_curr(bf) == '\0' )
  14. return;
  15. if ( bf->line_pos >= BDF_LINE_LEN )
  16. return;
  17. bf->line_pos++;
  18. }
  19. static void bf_skipspace(bf_t *bf)
  20. {
  21. int c;
  22. for(;;)
  23. {
  24. c = bf_curr(bf);
  25. if ( c == '\0' )
  26. return;
  27. if ( c > ' ' )
  28. return;
  29. bf_next(bf);
  30. }
  31. }
  32. static const char *bf_get_identifier(bf_t *bf)
  33. {
  34. static char buf[BDF_LINE_LEN];
  35. int c;
  36. int i = 0;
  37. buf[0] = '\0';
  38. for(;;)
  39. {
  40. c = bf_curr(bf);
  41. if ( c <= ' ' )
  42. break;
  43. if ( i >= BDF_LINE_LEN-2 )
  44. break;
  45. buf[i++] = c;
  46. buf[i] = '\0';
  47. bf_next(bf);
  48. }
  49. bf_skipspace(bf);
  50. return buf;
  51. }
  52. static const char *bf_get_string(bf_t *bf)
  53. {
  54. static char buf[BDF_LINE_LEN];
  55. int i = 0;
  56. int c;
  57. buf[0] = '\0';
  58. if ( bf_curr(bf) != '\"' )
  59. return bf_get_identifier(bf);
  60. bf_next(bf);
  61. for(;;)
  62. {
  63. c = bf_curr(bf);
  64. if ( c == '\0' )
  65. break;
  66. if ( c == '\"' )
  67. break;
  68. if ( i >= BDF_LINE_LEN-2 )
  69. break;
  70. if ( c != '\r' && c != '\n' ) /* skip \r and \n, see https://github.com/olikraus/u8g2/pull/1361, https://github.com/olikraus/u8g2/issues/1379 */
  71. {
  72. buf[i++] = c;
  73. buf[i] = '\0';
  74. }
  75. bf_next(bf);
  76. }
  77. if ( bf_curr(bf) == '\"' )
  78. bf_next(bf);
  79. bf_skipspace(bf);
  80. return buf;
  81. }
  82. static const char *bf_get_eol_string(bf_t *bf)
  83. {
  84. static char buf[BDF_LINE_LEN];
  85. int i = 0;
  86. int c;
  87. buf[0] = '\0';
  88. if ( bf_curr(bf) == '\"' )
  89. return bf_get_string(bf);
  90. //bf_next(bf);
  91. for(;;)
  92. {
  93. c = bf_curr(bf);
  94. if ( c == '\0' )
  95. break;
  96. if ( c == '\n' || c == '\r' )
  97. break;
  98. if ( i >= BDF_LINE_LEN-2 )
  99. break;
  100. buf[i++] = c;
  101. buf[i] = '\0';
  102. bf_next(bf);
  103. }
  104. bf_skipspace(bf);
  105. return buf;
  106. }
  107. static long bf_get_long(bf_t *bf)
  108. {
  109. int c;
  110. long v = 0;
  111. long sign = 1;
  112. if ( bf_curr(bf) == '-' )
  113. {
  114. sign = -1;
  115. bf_next(bf);
  116. bf_skipspace(bf);
  117. }
  118. for(;;)
  119. {
  120. c = bf_curr(bf);
  121. if ( c < '0' )
  122. break;
  123. if ( c > '9' )
  124. break;
  125. v *= 10L;
  126. v += (long)(c-'0');
  127. bf_next(bf);
  128. }
  129. bf_skipspace(bf);
  130. return v*sign;
  131. }
  132. /*
  133. static long bf_get_mul(bf_t *bf)
  134. {
  135. long v;
  136. v = bf_get_long(bf);
  137. if ( bf_curr(bf) == '*' )
  138. {
  139. bf_next(bf);
  140. bf_skipspace(bf);
  141. v *= bf_get_long(bf);
  142. }
  143. return v;
  144. }
  145. static long bf_get_add(bf_t *bf)
  146. {
  147. long v;
  148. v = bf_get_mul(bf);
  149. if ( bf_curr(bf) == '+' )
  150. {
  151. bf_next(bf);
  152. bf_skipspace(bf);
  153. v += bf_get_mul(bf);
  154. }
  155. return v;
  156. }
  157. */
  158. static int bf_add_glyph_to_list(bf_t *bf)
  159. {
  160. bg_t *bg;
  161. bf->glyph_pos = bf_AddGlyph(bf);
  162. if ( bf->glyph_pos < 0 )
  163. {
  164. bf_Error(bf, "Can not add glyph (memory error?)");
  165. return 0;
  166. }
  167. bg = bf->glyph_list[bf->glyph_pos];
  168. /* copy the values from the parser to the glyph record */
  169. bg->encoding = bf->encoding;
  170. bg->dwidth_x = bf->dwidth_x;
  171. bg->dwidth_y = bf->dwidth_y;
  172. bg->bbx.w = bf->bbx_w;
  173. bg->bbx.h = bf->bbx_h;
  174. bg->bbx.x = bf->bbx_x;
  175. bg->bbx.y = bf->bbx_y;
  176. if ( bg_SetBitmapSize(bg, bf->bbx_w, bf->bbx_h) == 0 )
  177. {
  178. bf_Error(bf, "Can not create bitmap (memory error?)");
  179. return 0;
  180. }
  181. bg->bitmap_width = bf->bbx_w;
  182. bg->bitmap_height = bf->bbx_h;
  183. // bg->actual_bitmap_width = bf->bbx_w;
  184. // bg->actual_bitmap_height = bf->bbx_h;
  185. //bf_Log(bf, "BDF File: Create glyph glyph_pos=%d bbx_w=%d bbx_h=%d bbx_x=%d bbx_y=%d", bf->glyph_pos, bf->bbx_w, bf->bbx_h, bf->bbx_x, bf->bbx_y);
  186. return 1;
  187. }
  188. static void bf_set_pixel_by_halfbyte(bf_t *bf, int halfbyte)
  189. {
  190. int i;
  191. bg_t *bg;
  192. assert( bf->glyph_list != NULL );
  193. bg = bf->glyph_list[bf->glyph_pos];
  194. for ( i = 0; i < 4; i++ )
  195. {
  196. if ( (halfbyte & 8) != 0 )
  197. {
  198. bg_SetBitmapPixel(bg, bf->bitmap_x, bf->bitmap_y, 1);
  199. }
  200. halfbyte<<=1;
  201. bf->bitmap_x++;
  202. }
  203. }
  204. static void bf_set_pixel_by_hex_char(bf_t *bf, int hex)
  205. {
  206. if ( hex >= '0' && hex <= '9' )
  207. return bf_set_pixel_by_halfbyte(bf, hex-'0');
  208. if ( hex >= 'a' && hex <= 'f' )
  209. return bf_set_pixel_by_halfbyte(bf, hex-'a'+10);
  210. if ( hex >= 'A' && hex <= 'F' )
  211. return bf_set_pixel_by_halfbyte(bf, hex-'A'+10);
  212. return bf_set_pixel_by_halfbyte(bf, 0);
  213. }
  214. static int bf_parse_line(bf_t *bf)
  215. {
  216. static char cmd[BDF_LINE_LEN];
  217. bf->line_pos = 0;
  218. bf_skipspace(bf);
  219. if ( bf->is_bitmap_parsing == 0 )
  220. {
  221. /* regular command */
  222. bf->bitmap_y = 0;
  223. strcpy(cmd, bf_get_string(bf));
  224. if ( strcmp(cmd, "" ) == 0 )
  225. {
  226. return 1;
  227. }
  228. else if ( strcmp(cmd, "STARTFONT" ) == 0 ) /* args: s */
  229. {
  230. }
  231. else if ( strcmp(cmd, "FONT" ) == 0 ) /* args: s */
  232. {
  233. if ( bf->str_font != NULL )
  234. free(bf->str_font);
  235. bf->str_font = strdup(bf_get_eol_string(bf));
  236. }
  237. else if ( strcmp(cmd, "SIZE" ) == 0 ) /* args: lll */
  238. {
  239. }
  240. else if ( strcmp(cmd, "FONTBOUNDINGBOX" ) == 0 ) /* args: llll */
  241. {
  242. }
  243. else if ( strcmp(cmd, "STARTPROPERTIES" ) == 0 ) /* args: l */
  244. {
  245. }
  246. else if ( strcmp(cmd, "FONTNAME_REGISTRY" ) == 0 ) /* args: s */
  247. {
  248. }
  249. else if ( strcmp(cmd, "FOUNDRY" ) == 0 ) /* args: s */
  250. {
  251. }
  252. else if ( strcmp(cmd, "FAMILY_NAME" ) == 0 ) /* args: s */
  253. {
  254. }
  255. else if ( strcmp(cmd, "WEIGHT_NAME" ) == 0 ) /* args: s */
  256. {
  257. }
  258. else if ( strcmp(cmd, "SLANT" ) == 0 ) /* args: s */
  259. {
  260. }
  261. else if ( strcmp(cmd, "SETWIDTH_NAME" ) == 0 ) /* args: s */
  262. {
  263. }
  264. else if ( strcmp(cmd, "ADD_STYLE_NAME" ) == 0 ) /* args: s */
  265. {
  266. }
  267. else if ( strcmp(cmd, "PIXEL_SIZE" ) == 0 ) /* args: l */
  268. {
  269. }
  270. else if ( strcmp(cmd, "POINT_SIZE" ) == 0 ) /* args: l */
  271. {
  272. }
  273. else if ( strcmp(cmd, "RESOLUTION_X" ) == 0 ) /* args: l */
  274. {
  275. }
  276. else if ( strcmp(cmd, "RESOLUTION_Y" ) == 0 ) /* args: l */
  277. {
  278. }
  279. else if ( strcmp(cmd, "SPACING" ) == 0 ) /* args: s */
  280. {
  281. }
  282. else if ( strcmp(cmd, "AVERAGE_WIDTH" ) == 0 ) /* args: l */
  283. {
  284. }
  285. else if ( strcmp(cmd, "CHARSET_REGISTRY" ) == 0 ) /* args: s */
  286. {
  287. }
  288. else if ( strcmp(cmd, "CHARSET_ENCODING" ) == 0 ) /* args: s */
  289. {
  290. }
  291. else if ( strcmp(cmd, "DESTINATION" ) == 0 ) /* args: l */
  292. {
  293. }
  294. else if ( strcmp(cmd, "COPYRIGHT" ) == 0 ) /* args: s */
  295. {
  296. if ( bf->str_copyright != NULL )
  297. free(bf->str_copyright);
  298. bf->str_copyright = strdup(bf_get_eol_string(bf));
  299. }
  300. else if ( strcmp(cmd, "_XMBDFED_INFO" ) == 0 ) /* args: s */
  301. {
  302. }
  303. else if ( strcmp(cmd, "CAP_HEIGHT" ) == 0 ) /* args: l */
  304. {
  305. }
  306. else if ( strcmp(cmd, "X_HEIGHT" ) == 0 ) /* args: l */
  307. {
  308. }
  309. else if ( strcmp(cmd, "WEIGHT" ) == 0 ) /* args: l */
  310. {
  311. }
  312. else if ( strcmp(cmd, "QUAD_WIDTH" ) == 0 ) /* args: l */
  313. {
  314. }
  315. else if ( strcmp(cmd, "DEFAULT_CHAR" ) == 0 ) /* args: l */
  316. {
  317. }
  318. else if ( strcmp(cmd, "FONT_DESCENT" ) == 0 ) /* args: l */
  319. {
  320. }
  321. else if ( strcmp(cmd, "FONT_ASCENT" ) == 0 ) /* args: l */
  322. {
  323. }
  324. else if ( strcmp(cmd, "ENDPROPERTIES" ) == 0 ) /* args: - */
  325. {
  326. }
  327. else if ( strcmp(cmd, "CHARS" ) == 0 ) /* args: l */
  328. {
  329. }
  330. else if ( strcmp(cmd, "STARTCHAR" ) == 0 ) /* args: s */
  331. {
  332. }
  333. else if ( strcmp(cmd, "ENCODING" ) == 0 ) /* args: l */
  334. {
  335. bf->encoding = bf_get_long(bf);
  336. //bf_Log(bf, "BDF File: ENCODING %d", bf->encoding);
  337. }
  338. else if ( strcmp(cmd, "SWIDTH" ) == 0 ) /* args: ll */
  339. {
  340. }
  341. else if ( strcmp(cmd, "DWIDTH" ) == 0 ) /* args: ll */
  342. {
  343. bf->dwidth_x = bf_get_long(bf);
  344. bf->dwidth_y = bf_get_long(bf);
  345. }
  346. else if ( strcmp(cmd, "BBX" ) == 0 ) /* args: llll */
  347. {
  348. bf->bbx_w = bf_get_long(bf);
  349. bf->bbx_h = bf_get_long(bf);
  350. bf->bbx_x = bf_get_long(bf);
  351. bf->bbx_y = bf_get_long(bf);
  352. }
  353. else if ( strcmp(cmd, "BITMAP" ) == 0 ) /* args: - */
  354. {
  355. if ( bf_add_glyph_to_list(bf) == 0 )
  356. return 0;
  357. bf->is_bitmap_parsing = 1;
  358. }
  359. else if ( strcmp(cmd, "ENDCHAR" ) == 0 ) /* args: - */
  360. {
  361. bf_Error(bf, "Unexpected ENDCHAR found");
  362. return 0;
  363. }
  364. }
  365. else
  366. {
  367. /* a line of the glyph bitmap */
  368. int c;
  369. strcpy(cmd, bf_get_string(bf));
  370. if ( cmd[0] != '\0' )
  371. {
  372. if ( strcmp(cmd, "ENDCHAR" ) == 0 ) /* args: - */
  373. {
  374. bf->is_bitmap_parsing = 0;
  375. /* bg_ShowBitmap(bf->glyph_list[bf->glyph_pos]); */
  376. }
  377. else
  378. {
  379. bf->line_pos = 0;
  380. bf_skipspace(bf);
  381. bf->bitmap_x = 0;
  382. for(;;)
  383. {
  384. c = bf_curr(bf);
  385. if ( c < '0' )
  386. break;
  387. bf_set_pixel_by_hex_char(bf, c);
  388. bf_next(bf);
  389. }
  390. bf->bitmap_y++;
  391. }
  392. }
  393. }
  394. return 1;
  395. }
  396. static int bf_parse_file(bf_t *bf)
  397. {
  398. long line_cnt = 0;
  399. bf->is_bitmap_parsing = 0;
  400. for(;;)
  401. {
  402. line_cnt++;
  403. if ( fgets(bf->line_buf, BDF_LINE_LEN, bf->fp) == NULL )
  404. break;
  405. if ( bf_parse_line(bf) == 0 )
  406. {
  407. bf_Error(bf, "perse error in line %ld", line_cnt);
  408. return 0;
  409. }
  410. }
  411. return 1;
  412. }
  413. int bf_ParseFile(bf_t *bf, const char *name)
  414. {
  415. int r;
  416. bf->fp = fopen(name, "r");
  417. if ( bf->fp == NULL )
  418. {
  419. bf_Error(bf, "Can not open bdf file '%s'", name);
  420. return 0;
  421. }
  422. r = bf_parse_file(bf);
  423. fclose(bf->fp);
  424. bf_Log(bf, "Parse File %s: %d glyph(s) found", name, bf->glyph_cnt);
  425. return r;
  426. }