My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

u8g_fontutf8.cpp 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /**
  2. * @file u8g_fontutf8.cpp
  3. * @brief font api for u8g lib
  4. * @author Yunhui Fu (yhfudev@gmail.com)
  5. * @version 1.0
  6. * @date 2015-02-19
  7. * @copyright GPL/BSD
  8. */
  9. #include "../inc/MarlinConfigPre.h"
  10. #if ENABLED(DOGLCD)
  11. #include <string.h>
  12. #include "fontutils.h"
  13. #include "u8g_fontutf8.h"
  14. ////////////////////////////////////////////////////////////
  15. typedef void font_t;
  16. /**
  17. * @brief the callback function to draw something
  18. *
  19. * @param userdata : User's data
  20. * @param msg : the u8g's string
  21. * @param fnt_current : the font
  22. *
  23. * @return 0 on success, 1 to force quit, <0 on error
  24. *
  25. * Get the screen pixel width of a ROM UTF-8 string
  26. */
  27. typedef int (* fontgroup_cb_draw_t)(void *userdata, const font_t *fnt_current, const char *msg);
  28. ////////////////////////////////////////////////////////////
  29. /* return v1 - v2 */
  30. static int fontinfo_compare(uxg_fontinfo_t * v1, uxg_fontinfo_t * v2) {
  31. if (v1->page < v2->page) return -1;
  32. else if (v1->page > v2->page) return 1;
  33. if (v1->end < v2->begin) return -1;
  34. else if (v1->begin > v2->end) return 1;
  35. return 0;
  36. }
  37. /*"data_list[idx] - *data_pin"*/
  38. static int pf_bsearch_cb_comp_fntifo_pgm (void *userdata, size_t idx, void *data_pin) {
  39. uxg_fontinfo_t *fntinfo = (uxg_fontinfo_t*)userdata;
  40. uxg_fontinfo_t localval;
  41. memcpy_P(&localval, fntinfo + idx, sizeof(localval));
  42. return fontinfo_compare(&localval, (uxg_fontinfo_t*)data_pin);
  43. }
  44. typedef struct _font_group_t {
  45. const uxg_fontinfo_t * m_fntifo;
  46. int m_fntinfo_num;
  47. } font_group_t;
  48. static int fontgroup_init(font_group_t * root, const uxg_fontinfo_t * fntinfo, int number) {
  49. root->m_fntifo = fntinfo;
  50. root->m_fntinfo_num = number;
  51. return 0;
  52. }
  53. static const font_t* fontgroup_find(font_group_t * root, wchar_t val) {
  54. uxg_fontinfo_t vcmp = {(uint16_t)(val / 128), (uint8_t)(val % 128 + 128), (uint8_t)(val % 128 + 128), 0, 0};
  55. size_t idx = 0;
  56. if (val < 256) return NULL;
  57. if (pf_bsearch_r((void*)root->m_fntifo, root->m_fntinfo_num, pf_bsearch_cb_comp_fntifo_pgm, (void*)&vcmp, &idx) < 0)
  58. return NULL;
  59. memcpy_P(&vcmp, root->m_fntifo + idx, sizeof(vcmp));
  60. return vcmp.fntdata;
  61. }
  62. static void fontgroup_drawwchar(font_group_t *group, const font_t *fnt_default, wchar_t val, void * userdata, fontgroup_cb_draw_t cb_draw_ram) {
  63. uint8_t buf[2] = {0, 0};
  64. const font_t * fntpqm = (font_t*)fontgroup_find(group, val);
  65. if (!fntpqm) {
  66. // Unknown char, use default font
  67. buf[0] = (uint8_t)(val & 0xFF);
  68. fntpqm = fnt_default;
  69. }
  70. if (fnt_default != fntpqm) {
  71. buf[0] = (uint8_t)(val & 0x7F);
  72. buf[0] |= 0x80; // use upper page to avoid 0x00 error in C. you may want to generate the font data
  73. }
  74. cb_draw_ram (userdata, fntpqm, (char*) buf);
  75. }
  76. /**
  77. * @brief try to process a utf8 string
  78. *
  79. * @param pu8g : U8G pointer
  80. * @param fnt_default : the default font
  81. * @param utf8_msg : the UTF-8 string
  82. * @param cb_read_byte : how to read the utf8_msg, from RAM or ROM (call read_byte_ram or pgm_read_byte)
  83. * @param userdata : User's data
  84. * @param cb_draw_ram : the callback function of userdata to draw a !RAM! string (actural it is to draw a one byte string in RAM)
  85. *
  86. * @return N/A
  87. *
  88. * Get the screen pixel width of a ROM UTF-8 string
  89. */
  90. static void fontgroup_drawstring(font_group_t *group, const font_t *fnt_default, const char *utf8_msg, read_byte_cb_t cb_read_byte, void * userdata, fontgroup_cb_draw_t cb_draw_ram) {
  91. uint8_t *p = (uint8_t*)utf8_msg;
  92. for (;;) {
  93. wchar_t val = 0;
  94. p = get_utf8_value_cb(p, cb_read_byte, &val);
  95. if (!val) break;
  96. fontgroup_drawwchar(group, fnt_default, val, userdata, cb_draw_ram);
  97. }
  98. }
  99. ////////////////////////////////////////////////////////////
  100. static bool flag_fontgroup_was_inited = false;
  101. static font_group_t g_fontgroup_root = {NULL, 0};
  102. /**
  103. * @brief check if font is loaded
  104. */
  105. static inline bool uxg_Utf8FontIsInited(void) { return flag_fontgroup_was_inited; }
  106. int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number) {
  107. flag_fontgroup_was_inited = 1;
  108. return fontgroup_init(&g_fontgroup_root, fntinfo, number);
  109. }
  110. struct _uxg_drawu8_data_t {
  111. u8g_t *pu8g;
  112. unsigned int x;
  113. unsigned int y;
  114. unsigned int adv;
  115. unsigned int max_width; // the max pixel width of the string allowed
  116. const void * fnt_prev;
  117. };
  118. static int fontgroup_cb_draw_u8g(void *userdata, const font_t *fnt_current, const char *msg) {
  119. struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
  120. if (pdata->fnt_prev != fnt_current) {
  121. u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
  122. //u8g_SetFontPosBottom(pdata->pu8g);
  123. pdata->fnt_prev = fnt_current;
  124. }
  125. if ((pdata->max_width != PIXEL_LEN_NOLIMIT) && (pdata->adv + u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg) > pdata->max_width))
  126. return 1;
  127. pdata->adv += u8g_DrawStr(pdata->pu8g, pdata->x + pdata->adv, pdata->y, (char*) msg);
  128. return 0;
  129. }
  130. /**
  131. * @brief Draw a wchar_t at the specified position
  132. *
  133. * @param pu8g : U8G pointer
  134. * @param x : position x axis
  135. * @param y : position y axis
  136. * @param ch : the wchar_t
  137. * @param max_width : the pixel width of the string allowed
  138. *
  139. * @return number of pixels advanced
  140. *
  141. * Draw a UTF-8 string at the specified position
  142. */
  143. unsigned int uxg_DrawWchar(u8g_t *pu8g, unsigned int x, unsigned int y, wchar_t ch, pixel_len_t max_width) {
  144. struct _uxg_drawu8_data_t data;
  145. font_group_t *group = &g_fontgroup_root;
  146. const font_t *fnt_default = uxg_GetFont(pu8g);
  147. if (!uxg_Utf8FontIsInited()) {
  148. u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
  149. return 0;
  150. }
  151. data.pu8g = pu8g;
  152. data.x = x;
  153. data.y = y;
  154. data.adv = 0;
  155. data.max_width = max_width;
  156. data.fnt_prev = NULL;
  157. fontgroup_drawwchar(group, fnt_default, ch, (void*)&data, fontgroup_cb_draw_u8g);
  158. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  159. return data.adv;
  160. }
  161. /**
  162. * @brief Draw a UTF-8 string at the specified position
  163. *
  164. * @param pu8g : U8G pointer
  165. * @param x : position x axis
  166. * @param y : position y axis
  167. * @param utf8_msg : the UTF-8 string
  168. * @param max_width : the pixel width of the string allowed
  169. *
  170. * @return number of pixels advanced
  171. *
  172. * Draw a UTF-8 string at the specified position
  173. */
  174. unsigned int uxg_DrawUtf8Str(u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_width) {
  175. struct _uxg_drawu8_data_t data;
  176. font_group_t *group = &g_fontgroup_root;
  177. const font_t *fnt_default = uxg_GetFont(pu8g);
  178. if (!uxg_Utf8FontIsInited()) {
  179. u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
  180. return 0;
  181. }
  182. data.pu8g = pu8g;
  183. data.x = x;
  184. data.y = y;
  185. data.adv = 0;
  186. data.max_width = max_width;
  187. data.fnt_prev = NULL;
  188. fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_ram, (void*)&data, fontgroup_cb_draw_u8g);
  189. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  190. return data.adv;
  191. }
  192. /**
  193. * @brief Draw a ROM UTF-8 string at the specified position
  194. *
  195. * @param pu8g : U8G pointer
  196. * @param x : position x axis
  197. * @param y : position y axis
  198. * @param utf8_msg : the UTF-8 string
  199. * @param max_width : the pixel width of the string allowed
  200. *
  201. * @return number of pixels advanced
  202. *
  203. * Draw a ROM UTF-8 string at the specified position
  204. */
  205. unsigned int uxg_DrawUtf8StrP(u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_width) {
  206. struct _uxg_drawu8_data_t data;
  207. font_group_t *group = &g_fontgroup_root;
  208. const font_t *fnt_default = uxg_GetFont(pu8g);
  209. if (!uxg_Utf8FontIsInited()) {
  210. u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
  211. return 0;
  212. }
  213. data.pu8g = pu8g;
  214. data.x = x;
  215. data.y = y;
  216. data.adv = 0;
  217. data.max_width = max_width;
  218. data.fnt_prev = NULL;
  219. fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_rom, (void*)&data, fontgroup_cb_draw_u8g);
  220. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  221. return data.adv;
  222. }
  223. static int fontgroup_cb_draw_u8gstrlen(void *userdata, const font_t *fnt_current, const char *msg) {
  224. struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
  225. if (pdata->fnt_prev != fnt_current) {
  226. u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
  227. u8g_SetFontPosBottom(pdata->pu8g);
  228. pdata->fnt_prev = fnt_current;
  229. }
  230. pdata->adv += u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg);
  231. return 0;
  232. }
  233. /**
  234. * @brief Get the screen pixel width of a UTF-8 string
  235. *
  236. * @param pu8g : U8G pointer
  237. * @param utf8_msg : the UTF-8 string
  238. *
  239. * @return the pixel width
  240. *
  241. * Get the screen pixel width of a UTF-8 string
  242. */
  243. int uxg_GetUtf8StrPixelWidth(u8g_t *pu8g, const char *utf8_msg) {
  244. struct _uxg_drawu8_data_t data;
  245. font_group_t *group = &g_fontgroup_root;
  246. const font_t *fnt_default = uxg_GetFont(pu8g);
  247. if (!uxg_Utf8FontIsInited()) return -1;
  248. memset(&data, 0, sizeof(data));
  249. data.pu8g = pu8g;
  250. data.adv = 0;
  251. fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_ram, (void*)&data, fontgroup_cb_draw_u8gstrlen);
  252. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  253. return data.adv;
  254. }
  255. /**
  256. * @brief Get the screen pixel width of a ROM UTF-8 string
  257. *
  258. * @param pu8g : U8G pointer
  259. * @param utf8_msg : the UTF-8 string
  260. *
  261. * @return the pixel width
  262. *
  263. * Get the screen pixel width of a ROM UTF-8 string
  264. */
  265. int uxg_GetUtf8StrPixelWidthP(u8g_t *pu8g, const char *utf8_msg) {
  266. struct _uxg_drawu8_data_t data;
  267. font_group_t *group = &g_fontgroup_root;
  268. const font_t *fnt_default = uxg_GetFont(pu8g);
  269. if (!uxg_Utf8FontIsInited()) return -1;
  270. memset(&data, 0, sizeof(data));
  271. data.pu8g = pu8g;
  272. data.adv = 0;
  273. fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_rom, (void*)&data, fontgroup_cb_draw_u8gstrlen);
  274. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  275. return data.adv;
  276. }
  277. #endif // DOGLCD