My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /**
  2. * @file fontutf8.c
  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/MarlinConfig.h"
  10. #if ENABLED(ULTRA_LCD)
  11. #include <string.h>
  12. #include "fontutils.h"
  13. #include "u8g_fontutf8.h"
  14. ////////////////////////////////////////////////////////////
  15. typedef void font_t;
  16. #ifndef PSTR
  17. #define PSTR(a) a
  18. void* memcpy_from_rom(void *dest, const void * rom_src, size_t sz) {
  19. uint8_t * p;
  20. uint8_t * s;
  21. FU_ASSERT(NULL != dest);
  22. p = (uint8_t*)dest;
  23. s = (uint8_t*)rom_src;
  24. uint8_t c;
  25. while ((p - (uint8_t *)dest) < sz) {
  26. *p = pgm_read_byte(s);
  27. p ++;
  28. s ++;
  29. }
  30. return p;
  31. }
  32. #else
  33. #define memcpy_from_rom memcpy_P
  34. #endif
  35. /**
  36. * @brief the callback function to draw something
  37. *
  38. * @param userdata : User's data
  39. * @param msg : the u8g's string
  40. * @param fnt_current : the font
  41. *
  42. * @return 0 on success, 1 to force quit, <0 on error
  43. *
  44. * Get the screen pixel width of a ROM UTF-8 string
  45. */
  46. typedef int (* fontgroup_cb_draw_t)(void *userdata, const font_t *fnt_current, const char *msg);
  47. //extern int fontgroup_init(font_group_t * root, const uxg_fontinfo_t * fntinfo, int number);
  48. //extern int fontgroup_drawstring(font_group_t *group, const font_t *fnt_default, const char *utf8_msg, void *userdata, fontgroup_cb_draw_t cb_draw);
  49. //extern uxg_fontinfo_t* fontgroup_first(font_group_t * root);
  50. ////////////////////////////////////////////////////////////
  51. /* return v1 - v2 */
  52. static int fontinfo_compare(uxg_fontinfo_t * v1, uxg_fontinfo_t * v2) {
  53. FU_ASSERT(NULL != v1);
  54. FU_ASSERT(NULL != v2);
  55. if (v1->page < v2->page)
  56. return -1;
  57. else if (v1->page > v2->page)
  58. return 1;
  59. if (v1->end < v2->begin)
  60. return -1;
  61. else if (v1->begin > v2->end)
  62. return 1;
  63. return 0;
  64. }
  65. /*"data_list[idx] - *data_pin"*/
  66. static int pf_bsearch_cb_comp_fntifo_pgm (void *userdata, size_t idx, void *data_pin) {
  67. uxg_fontinfo_t *fntinfo = (uxg_fontinfo_t*)userdata;
  68. uxg_fontinfo_t localval;
  69. memcpy_from_rom(&localval, fntinfo + idx, sizeof(localval));
  70. return fontinfo_compare(&localval, (uxg_fontinfo_t*)data_pin);
  71. }
  72. typedef struct _font_group_t {
  73. const uxg_fontinfo_t * m_fntifo;
  74. int m_fntinfo_num;
  75. } font_group_t;
  76. static int fontgroup_init(font_group_t * root, const uxg_fontinfo_t * fntinfo, int number) {
  77. root->m_fntifo = fntinfo;
  78. root->m_fntinfo_num = number;
  79. return 0;
  80. }
  81. static const font_t* fontgroup_find(font_group_t * root, wchar_t val) {
  82. uxg_fontinfo_t vcmp = {(uint16_t)(val / 128), (uint8_t)(val % 128 + 128), (uint8_t)(val % 128 + 128), 0, 0};
  83. size_t idx = 0;
  84. if (val < 256) return NULL;
  85. if (pf_bsearch_r((void*)root->m_fntifo, root->m_fntinfo_num, pf_bsearch_cb_comp_fntifo_pgm, (void*)&vcmp, &idx) < 0)
  86. return NULL;
  87. memcpy_from_rom(&vcmp, root->m_fntifo + idx, sizeof(vcmp));
  88. return vcmp.fntdata;
  89. }
  90. 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) {
  91. uint8_t buf[2] = {0, 0};
  92. const font_t * fntpqm = NULL;
  93. TRACE("fontgroup_drawwchar char=%d(0x%X)", (int)val, (int)val);
  94. fntpqm = (font_t*)fontgroup_find(group, val);
  95. if (NULL == fntpqm) {
  96. buf[0] = (uint8_t)(val & 0xFF);
  97. fntpqm = fnt_default;
  98. TRACE("Unknown char %d(0x%X), use default font", (int)val, (int)val);
  99. }
  100. if (fnt_default != fntpqm) {
  101. buf[0] = (uint8_t)(val & 0x7F);
  102. buf[0] |= 0x80; // use upper page to avoid 0x00 error in C. you may want to generate the font data
  103. }
  104. //TRACE("set font: %p; (default=%p)", fntpqm, UXG_DEFAULT_FONT);
  105. cb_draw_ram (userdata, fntpqm, (char*) buf);
  106. }
  107. /**
  108. * @brief try to process a utf8 string
  109. *
  110. * @param pu8g : U8G pointer
  111. * @param fnt_default : the default font
  112. * @param utf8_msg : the UTF-8 string
  113. * @param cb_read_byte : how to read the utf8_msg, from RAM or ROM (call read_byte_ram or pgm_read_byte)
  114. * @param userdata : User's data
  115. * @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)
  116. *
  117. * @return N/A
  118. *
  119. * Get the screen pixel width of a ROM UTF-8 string
  120. */
  121. static void fontgroup_drawstring(font_group_t *group, const font_t *fnt_default, const char *utf8_msg, int len_msg, read_byte_cb_t cb_read_byte, void * userdata, fontgroup_cb_draw_t cb_draw_ram) {
  122. uint8_t *pend = (uint8_t*)utf8_msg + len_msg;
  123. for (uint8_t *p = (uint8_t*)utf8_msg; p < pend; ) {
  124. wchar_t val = 0;
  125. p = get_utf8_value_cb(p, cb_read_byte, &val);
  126. if (NULL == p) {
  127. TRACE("No more char, break ...");
  128. break;
  129. }
  130. fontgroup_drawwchar(group, fnt_default, val, userdata, cb_draw_ram);
  131. }
  132. }
  133. ////////////////////////////////////////////////////////////
  134. static char flag_fontgroup_inited1 = 0;
  135. #define flag_fontgroup_inited flag_fontgroup_inited1
  136. static font_group_t g_fontgroup_root = {NULL, 0};
  137. /**
  138. * @brief check if font is loaded
  139. */
  140. char uxg_Utf8FontIsInited(void) { return flag_fontgroup_inited; }
  141. int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number) {
  142. flag_fontgroup_inited = 1;
  143. return fontgroup_init(&g_fontgroup_root, fntinfo, number);
  144. }
  145. struct _uxg_drawu8_data_t {
  146. u8g_t *pu8g;
  147. unsigned int x;
  148. unsigned int y;
  149. unsigned int adv;
  150. unsigned int max_width; // the max pixel width of the string allowed
  151. const void * fnt_prev;
  152. };
  153. static int fontgroup_cb_draw_u8g (void *userdata, const font_t *fnt_current, const char *msg) {
  154. struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
  155. FU_ASSERT(NULL != userdata);
  156. if (pdata->fnt_prev != fnt_current) {
  157. u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
  158. //u8g_SetFontPosBottom(pdata->pu8g);
  159. pdata->fnt_prev = fnt_current;
  160. }
  161. if ((pdata->max_width != PIXEL_LEN_NOLIMIT) && (pdata->adv + u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg) > pdata->max_width)) {
  162. TRACE("return end, adv=%d, width=%d, maxlen=%d", pdata->adv, u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg), pdata->max_width);
  163. return 1;
  164. }
  165. TRACE("Draw string 0x%X", (int)msg[0]);
  166. pdata->adv += u8g_DrawStr(pdata->pu8g, pdata->x + pdata->adv, pdata->y, (char*) msg);
  167. //TRACE("adv pos= %d", pdata->adv);
  168. return 0;
  169. }
  170. /**
  171. * @brief Draw a wchar_t at the specified position
  172. *
  173. * @param pu8g : U8G pointer
  174. * @param x : position x axis
  175. * @param y : position y axis
  176. * @param ch : the wchar_t
  177. * @param max_width : the pixel width of the string allowed
  178. *
  179. * @return number of pixels advanced
  180. *
  181. * Draw a UTF-8 string at the specified position
  182. */
  183. unsigned int uxg_DrawWchar(u8g_t *pu8g, unsigned int x, unsigned int y, wchar_t ch, pixel_len_t max_width) {
  184. struct _uxg_drawu8_data_t data;
  185. font_group_t *group = &g_fontgroup_root;
  186. const font_t *fnt_default = uxg_GetFont(pu8g);
  187. if (!uxg_Utf8FontIsInited()) {
  188. u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
  189. return 0;
  190. }
  191. data.pu8g = pu8g;
  192. data.x = x;
  193. data.y = y;
  194. data.adv = 0;
  195. data.max_width = max_width;
  196. data.fnt_prev = NULL;
  197. fontgroup_drawwchar(group, fnt_default, ch, (void*)&data, fontgroup_cb_draw_u8g);
  198. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  199. return data.adv;
  200. }
  201. /**
  202. * @brief Draw a UTF-8 string at the specified position
  203. *
  204. * @param pu8g : U8G pointer
  205. * @param x : position x axis
  206. * @param y : position y axis
  207. * @param utf8_msg : the UTF-8 string
  208. * @param max_width : the pixel width of the string allowed
  209. *
  210. * @return number of pixels advanced
  211. *
  212. * Draw a UTF-8 string at the specified position
  213. */
  214. unsigned int uxg_DrawUtf8Str(u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_width) {
  215. struct _uxg_drawu8_data_t data;
  216. font_group_t *group = &g_fontgroup_root;
  217. const font_t *fnt_default = uxg_GetFont(pu8g);
  218. if (!uxg_Utf8FontIsInited()) {
  219. u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
  220. return 0;
  221. }
  222. data.pu8g = pu8g;
  223. data.x = x;
  224. data.y = y;
  225. data.adv = 0;
  226. data.max_width = max_width;
  227. data.fnt_prev = NULL;
  228. fontgroup_drawstring(group, fnt_default, utf8_msg, strlen(utf8_msg), read_byte_ram, (void*)&data, fontgroup_cb_draw_u8g);
  229. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  230. return data.adv;
  231. }
  232. /**
  233. * @brief Draw a ROM UTF-8 string at the specified position
  234. *
  235. * @param pu8g : U8G pointer
  236. * @param x : position x axis
  237. * @param y : position y axis
  238. * @param utf8_msg : the UTF-8 string
  239. * @param max_width : the pixel width of the string allowed
  240. *
  241. * @return number of pixels advanced
  242. *
  243. * Draw a ROM UTF-8 string at the specified position
  244. */
  245. unsigned int uxg_DrawUtf8StrP(u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_width) {
  246. struct _uxg_drawu8_data_t data;
  247. font_group_t *group = &g_fontgroup_root;
  248. const font_t *fnt_default = uxg_GetFont(pu8g);
  249. if (!uxg_Utf8FontIsInited()) {
  250. TRACE("Error, utf8string not inited!");
  251. u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
  252. return 0;
  253. }
  254. data.pu8g = pu8g;
  255. data.x = x;
  256. data.y = y;
  257. data.adv = 0;
  258. data.max_width = max_width;
  259. data.fnt_prev = NULL;
  260. TRACE("call fontgroup_drawstring");
  261. fontgroup_drawstring(group, fnt_default, utf8_msg, my_strlen_P(utf8_msg), read_byte_rom, (void*)&data, fontgroup_cb_draw_u8g);
  262. TRACE("restore font");
  263. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  264. TRACE("return %d", data.adv);
  265. return data.adv;
  266. }
  267. static int fontgroup_cb_draw_u8gstrlen(void *userdata, const font_t *fnt_current, const char *msg) {
  268. struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
  269. FU_ASSERT(NULL != userdata);
  270. if (pdata->fnt_prev != fnt_current) {
  271. u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
  272. u8g_SetFontPosBottom(pdata->pu8g);
  273. pdata->fnt_prev = fnt_current;
  274. }
  275. pdata->adv += u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg);
  276. return 0;
  277. }
  278. /**
  279. * @brief Get the screen pixel width of a UTF-8 string
  280. *
  281. * @param pu8g : U8G pointer
  282. * @param utf8_msg : the UTF-8 string
  283. *
  284. * @return the pixel width
  285. *
  286. * Get the screen pixel width of a UTF-8 string
  287. */
  288. int uxg_GetUtf8StrPixelWidth(u8g_t *pu8g, const char *utf8_msg) {
  289. struct _uxg_drawu8_data_t data;
  290. font_group_t *group = &g_fontgroup_root;
  291. const font_t *fnt_default = uxg_GetFont(pu8g);
  292. if (!uxg_Utf8FontIsInited()) {
  293. TRACE("Err: utf8 font not initialized.");
  294. return -1;
  295. }
  296. memset(&data, 0, sizeof(data));
  297. data.pu8g = pu8g;
  298. data.adv = 0;
  299. fontgroup_drawstring(group, fnt_default, utf8_msg, strlen(utf8_msg), read_byte_ram, (void*)&data, fontgroup_cb_draw_u8gstrlen);
  300. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  301. return data.adv;
  302. }
  303. /**
  304. * @brief Get the screen pixel width of a ROM UTF-8 string
  305. *
  306. * @param pu8g : U8G pointer
  307. * @param utf8_msg : the UTF-8 string
  308. *
  309. * @return the pixel width
  310. *
  311. * Get the screen pixel width of a ROM UTF-8 string
  312. */
  313. int uxg_GetUtf8StrPixelWidthP(u8g_t *pu8g, const char *utf8_msg) {
  314. struct _uxg_drawu8_data_t data;
  315. font_group_t *group = &g_fontgroup_root;
  316. const font_t *fnt_default = uxg_GetFont(pu8g);
  317. if (!uxg_Utf8FontIsInited()) {
  318. TRACE("Err: utf8 font not initialized.");
  319. return -1;
  320. }
  321. memset(&data, 0, sizeof(data));
  322. data.pu8g = pu8g;
  323. data.adv = 0;
  324. fontgroup_drawstring(group, fnt_default, utf8_msg, my_strlen_P(utf8_msg), read_byte_rom, (void*)&data, fontgroup_cb_draw_u8gstrlen);
  325. u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
  326. return data.adv;
  327. }
  328. #endif // ENABLED(ULTRA_LCD)