aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/lcd/dogm/u8g_fontutf8.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/lcd/dogm/u8g_fontutf8.cpp')
-rw-r--r--Marlin/src/lcd/dogm/u8g_fontutf8.cpp315
1 files changed, 315 insertions, 0 deletions
diff --git a/Marlin/src/lcd/dogm/u8g_fontutf8.cpp b/Marlin/src/lcd/dogm/u8g_fontutf8.cpp
new file mode 100644
index 0000000..89bdb09
--- /dev/null
+++ b/Marlin/src/lcd/dogm/u8g_fontutf8.cpp
@@ -0,0 +1,315 @@
+/**
+ * @file u8g_fontutf8.cpp
+ * @brief font api for u8g lib
+ * @author Yunhui Fu (yhfudev@gmail.com)
+ * @version 1.0
+ * @date 2015-02-19
+ * @copyright GPL/BSD
+ */
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB
+
+#include <string.h>
+#include "../fontutils.h"
+#include "u8g_fontutf8.h"
+
+typedef void font_t;
+
+/**
+ * @brief the callback function to draw something
+ *
+ * @param userdata : User's data
+ * @param msg : the u8g's string
+ * @param fnt_current : the font
+ *
+ * @return 0 on success, 1 to force quit, <0 on error
+ *
+ * Get the screen pixel width of a ROM UTF-8 string
+ */
+typedef int (* fontgroup_cb_draw_t)(void *userdata, const font_t *fnt_current, const char *msg);
+
+/* return v1 - v2 */
+static int fontinfo_compare(uxg_fontinfo_t * v1, uxg_fontinfo_t * v2) {
+ if (v1->page < v2->page) return -1;
+ else if (v1->page > v2->page) return 1;
+
+ if (v1->end < v2->begin) return -1;
+ else if (v1->begin > v2->end) return 1;
+
+ return 0;
+}
+
+/*"data_list[idx] - *data_pin"*/
+static int pf_bsearch_cb_comp_fntifo_pgm (void *userdata, size_t idx, void *data_pin) {
+ uxg_fontinfo_t *fntinfo = (uxg_fontinfo_t*)userdata;
+ uxg_fontinfo_t localval;
+ memcpy_P(&localval, fntinfo + idx, sizeof(localval));
+ return fontinfo_compare(&localval, (uxg_fontinfo_t*)data_pin);
+}
+
+typedef struct _font_group_t {
+ const uxg_fontinfo_t * m_fntifo;
+ int m_fntinfo_num;
+} font_group_t;
+
+static int fontgroup_init(font_group_t * root, const uxg_fontinfo_t * fntinfo, int number) {
+ root->m_fntifo = fntinfo;
+ root->m_fntinfo_num = number;
+ return 0;
+}
+
+static const font_t* fontgroup_find(font_group_t * root, wchar_t val) {
+ uxg_fontinfo_t vcmp = {(uint16_t)(val / 128), (uint8_t)(val % 128 + 128), (uint8_t)(val % 128 + 128), 0, 0};
+ size_t idx = 0;
+
+ if (val < 256) return nullptr;
+
+ if (pf_bsearch_r((void*)root->m_fntifo, root->m_fntinfo_num, pf_bsearch_cb_comp_fntifo_pgm, (void*)&vcmp, &idx) < 0)
+ return nullptr;
+
+ memcpy_P(&vcmp, root->m_fntifo + idx, sizeof(vcmp));
+ return vcmp.fntdata;
+}
+
+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) {
+ uint8_t buf[2] = {0, 0};
+ const font_t * fntpqm = (font_t*)fontgroup_find(group, val);
+ if (!fntpqm) {
+ // Unknown char, use default font
+ buf[0] = (uint8_t)(val & 0xFF);
+ fntpqm = fnt_default;
+ }
+ if (fnt_default != fntpqm) {
+ buf[0] = (uint8_t)(val & 0x7F);
+ buf[0] |= 0x80; // use upper page to avoid 0x00 error in C. you may want to generate the font data
+ }
+
+ cb_draw_ram (userdata, fntpqm, (char*) buf);
+}
+
+/**
+ * @brief try to process a utf8 string
+ *
+ * @param pu8g : U8G pointer
+ * @param fnt_default : the default font
+ * @param utf8_msg : the UTF-8 string
+ * @param cb_read_byte : how to read the utf8_msg, from RAM or ROM (call read_byte_ram or pgm_read_byte)
+ * @param userdata : User's data
+ * @param cb_draw_ram : the callback function of userdata to draw a !RAM! string (actually it is to draw a one byte string in RAM)
+ *
+ * @return N/A
+ *
+ * Get the screen pixel width of a ROM UTF-8 string
+ */
+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) {
+ uint8_t *p = (uint8_t*)utf8_msg;
+ for (;;) {
+ wchar_t val = 0;
+ p = get_utf8_value_cb(p, cb_read_byte, &val);
+ if (!val) break;
+ fontgroup_drawwchar(group, fnt_default, val, userdata, cb_draw_ram);
+ }
+}
+
+static bool flag_fontgroup_was_inited = false;
+static font_group_t g_fontgroup_root = { nullptr, 0 };
+
+/**
+ * @brief check if font is loaded
+ */
+static inline bool uxg_Utf8FontIsInited() { return flag_fontgroup_was_inited; }
+
+int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number) {
+ flag_fontgroup_was_inited = 1;
+ return fontgroup_init(&g_fontgroup_root, fntinfo, number);
+}
+
+struct _uxg_drawu8_data_t {
+ u8g_t *pu8g;
+ unsigned int x;
+ unsigned int y;
+ unsigned int adv;
+ unsigned int max_width; // the max pixel width of the string allowed
+ const void * fnt_prev;
+};
+
+static int fontgroup_cb_draw_u8g(void *userdata, const font_t *fnt_current, const char *msg) {
+ struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
+
+ if (pdata->fnt_prev != fnt_current) {
+ u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
+ pdata->fnt_prev = fnt_current;
+ }
+ if ((pdata->max_width != PIXEL_LEN_NOLIMIT) && (pdata->adv + u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg) > pdata->max_width))
+ return 1;
+ pdata->adv += u8g_DrawStr(pdata->pu8g, pdata->x + pdata->adv, pdata->y, (char*) msg);
+ return 0;
+}
+
+/**
+ * @brief Draw a wchar_t at the specified position
+ *
+ * @param pu8g : U8G pointer
+ * @param x : position x axis
+ * @param y : position y axis
+ * @param ch : the wchar_t
+ * @param max_width : the pixel width of the string allowed
+ *
+ * @return number of pixels advanced
+ *
+ * Draw a UTF-8 string at the specified position
+ */
+unsigned int uxg_DrawWchar(u8g_t *pu8g, unsigned int x, unsigned int y, wchar_t ch, pixel_len_t max_width) {
+ struct _uxg_drawu8_data_t data;
+ font_group_t *group = &g_fontgroup_root;
+ const font_t *fnt_default = uxg_GetFont(pu8g);
+
+ if (!uxg_Utf8FontIsInited()) {
+ u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
+ return 0;
+ }
+ data.pu8g = pu8g;
+ data.x = x;
+ data.y = y;
+ data.adv = 0;
+ data.max_width = max_width;
+ data.fnt_prev = nullptr;
+ fontgroup_drawwchar(group, fnt_default, ch, (void*)&data, fontgroup_cb_draw_u8g);
+ u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
+
+ return data.adv;
+}
+
+/**
+ * @brief Draw a UTF-8 string at the specified position
+ *
+ * @param pu8g : U8G pointer
+ * @param x : position x axis
+ * @param y : position y axis
+ * @param utf8_msg : the UTF-8 string
+ * @param max_width : the pixel width of the string allowed
+ *
+ * @return number of pixels advanced
+ *
+ * Draw a UTF-8 string at the specified position
+ */
+unsigned int uxg_DrawUtf8Str(u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_width) {
+ struct _uxg_drawu8_data_t data;
+ font_group_t *group = &g_fontgroup_root;
+ const font_t *fnt_default = uxg_GetFont(pu8g);
+
+ if (!uxg_Utf8FontIsInited()) {
+ u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
+ return 0;
+ }
+ data.pu8g = pu8g;
+ data.x = x;
+ data.y = y;
+ data.adv = 0;
+ data.max_width = max_width;
+ data.fnt_prev = nullptr;
+ fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_ram, (void*)&data, fontgroup_cb_draw_u8g);
+ u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
+
+ return data.adv;
+}
+
+/**
+ * @brief Draw a ROM UTF-8 string at the specified position
+ *
+ * @param pu8g : U8G pointer
+ * @param x : position x axis
+ * @param y : position y axis
+ * @param utf8_msg : the UTF-8 string
+ * @param max_width : the pixel width of the string allowed
+ *
+ * @return number of pixels advanced
+ *
+ * Draw a ROM UTF-8 string at the specified position
+ */
+unsigned int uxg_DrawUtf8StrP(u8g_t *pu8g, unsigned int x, unsigned int y, PGM_P utf8_msg, pixel_len_t max_width) {
+ struct _uxg_drawu8_data_t data;
+ font_group_t *group = &g_fontgroup_root;
+ const font_t *fnt_default = uxg_GetFont(pu8g);
+
+ if (!uxg_Utf8FontIsInited()) {
+ u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
+ return 0;
+ }
+ data.pu8g = pu8g;
+ data.x = x;
+ data.y = y;
+ data.adv = 0;
+ data.max_width = max_width;
+ data.fnt_prev = nullptr;
+ fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_rom, (void*)&data, fontgroup_cb_draw_u8g);
+ u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
+
+ return data.adv;
+}
+
+static int fontgroup_cb_draw_u8gstrlen(void *userdata, const font_t *fnt_current, const char *msg) {
+ struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
+
+ if (pdata->fnt_prev != fnt_current) {
+ u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
+ pdata->fnt_prev = fnt_current;
+ }
+ pdata->adv += u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg);
+ return 0;
+}
+
+/**
+ * @brief Get the screen pixel width of a UTF-8 string
+ *
+ * @param pu8g : U8G pointer
+ * @param utf8_msg : the UTF-8 string
+ *
+ * @return the pixel width
+ *
+ * Get the screen pixel width of a UTF-8 string
+ */
+int uxg_GetUtf8StrPixelWidth(u8g_t *pu8g, const char *utf8_msg) {
+ struct _uxg_drawu8_data_t data;
+ font_group_t *group = &g_fontgroup_root;
+ const font_t *fnt_default = uxg_GetFont(pu8g);
+
+ if (!uxg_Utf8FontIsInited()) return -1;
+
+ memset(&data, 0, sizeof(data));
+ data.pu8g = pu8g;
+ data.adv = 0;
+ fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_ram, (void*)&data, fontgroup_cb_draw_u8gstrlen);
+ u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
+
+ return data.adv;
+}
+
+/**
+ * @brief Get the screen pixel width of a ROM UTF-8 string
+ *
+ * @param pu8g : U8G pointer
+ * @param utf8_msg : the UTF-8 string
+ *
+ * @return the pixel width
+ *
+ * Get the screen pixel width of a ROM UTF-8 string
+ */
+int uxg_GetUtf8StrPixelWidthP(u8g_t *pu8g, PGM_P utf8_msg) {
+ struct _uxg_drawu8_data_t data;
+ font_group_t *group = &g_fontgroup_root;
+ const font_t *fnt_default = uxg_GetFont(pu8g);
+
+ if (!uxg_Utf8FontIsInited()) return -1;
+
+ memset(&data, 0, sizeof(data));
+ data.pu8g = pu8g;
+ data.adv = 0;
+ fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_rom, (void*)&data, fontgroup_cb_draw_u8gstrlen);
+ u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
+ return data.adv;
+}
+
+#endif // HAS_MARLINUI_U8GLIB