From 6fb2733bfbbee2c8c0c3cec334c872851a45a962 Mon Sep 17 00:00:00 2001 From: JiXieShi Date: Tue, 25 Jun 2024 18:17:14 +0800 Subject: [PATCH] =?UTF-8?q?UP=20LVGL=E5=AD=97=E5=BA=93=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demo/oled/test.c | 7 +- lib/CMakeLists.txt | 5 +- lib/inc/font/font.h | 44 +++ lib/inc/font/lvgl_font.h | 20 -- lib/inc/oled/oled.h | 4 + lib/src/font/font.cpp | 216 +++++++++++++++ lib/src/font/lvgl_font.c | 558 --------------------------------------- lib/src/oled/oled.cpp | 47 ++-- 8 files changed, 304 insertions(+), 597 deletions(-) create mode 100644 lib/inc/font/font.h delete mode 100644 lib/inc/font/lvgl_font.h create mode 100644 lib/src/font/font.cpp delete mode 100644 lib/src/font/lvgl_font.c diff --git a/demo/oled/test.c b/demo/oled/test.c index c54e0bb..4dfa63c 100644 --- a/demo/oled/test.c +++ b/demo/oled/test.c @@ -114,9 +114,12 @@ void Test_OLED() { int s = 0; char buf[30] = {0x5B, 0x57, 0x5E, 0x93, 0x75, 0x1F, 0x62, 0x10, 0x6D, 0x4B, 0x8B, 0xD5}; - OLED_ShowCHString(&oled, 15, 16, buf); - OLED_Refresh(&oled); +// OLED_ShowCHString(&oled, 15, 16, buf); + extern lv_font_t myFont; + OLED_DisplayString(&oled, &myFont, "你好", 0, 0); + + OLED_Refresh(&oled); _beginthread(Get_Key, 0, NULL); pageinit(); Sleep(5000); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 7e81f2c..f2cfe88 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -4,11 +4,11 @@ set(LIBRARIES HW_LIB_Task src/task inc/task HW_LIB_Printf src/printf inc/printf HW_LIB_Utils src/utils inc/utils + HW_LIB_Font src/font inc/font HW_LIB_Iic src/iic inc/iic HW_LIB_Spi src/spi inc/spi HW_LIB_Key src/key inc/key HW_LIB_Oled src/oled inc/oled - HW_LIB_Font src/font inc/font ) # 循环浏览库列表以创建它们 @@ -28,4 +28,5 @@ foreach (INDEX RANGE 0 ${LIBRARIES_LENGTH} 3) endforeach () # 链接必要的库 -target_link_libraries(HW_LIB_Spi HW_LIB_Utils) \ No newline at end of file +target_link_libraries(HW_LIB_Spi HW_LIB_Utils) +target_link_libraries(HW_LIB_Oled HW_LIB_Font) \ No newline at end of file diff --git a/lib/inc/font/font.h b/lib/inc/font/font.h new file mode 100644 index 0000000..61f3f66 --- /dev/null +++ b/lib/inc/font/font.h @@ -0,0 +1,44 @@ + +#pragma once + +#ifndef HW_LIB_FONT_H +#define HW_LIB_FONT_H + +#ifdef __cplusplus +extern "C" { +#endif +#include "stdlib.h" +#include "string.h" +#include +#include +#include +#include "lvgl.h" + +// 定义像素颜色的位数 +#define PIX_COLOR_SIZE 1 + +// 启用单行刷新 +#define LINE_FAST_SHOW + +typedef struct Font Font_f_t; +typedef void (*Font_Show_t)(Font_f_t *font, uint8_t *data, size_t len); +struct Font { + void *dev; + uint8_t dev_w; + uint16_t x, y, w, h; + Font_Show_t show; +#if PIX_COLOR_SIZE == 16 + uint16_t pixcolor; + uint16_t backgroundcolor; +#endif +}; + +char Font_utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter); + +char Font_draw_letter(const lv_font_t *font, Font_f_t *fd, uint32_t letter, int16_t pos_x, int16_t pos_y); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/lib/inc/font/lvgl_font.h b/lib/inc/font/lvgl_font.h deleted file mode 100644 index 7bb7406..0000000 --- a/lib/inc/font/lvgl_font.h +++ /dev/null @@ -1,20 +0,0 @@ - -#pragma once - -#ifndef __lvgl_font_H -#define __lvgl_font_H - -#include "stdlib.h" -#include "string.h" -#include -#include -#include -#include "lvgl.h" - -#define LV_ANTIALIAS 0 //抗锯齿 - -char utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter); - -char lv_draw_letter(const lv_font_t *font, uint32_t letter, int16_t pos_x, int16_t pos_y); - -#endif \ No newline at end of file diff --git a/lib/inc/oled/oled.h b/lib/inc/oled/oled.h index 594ab14..0a687a1 100644 --- a/lib/inc/oled/oled.h +++ b/lib/inc/oled/oled.h @@ -6,6 +6,7 @@ extern "C" { #endif #include "stdint.h" +#include "lvgl.h" #define REFRESH_CALL_ENABLE 1 //使用DMA或者整体刷新函数 @@ -278,6 +279,9 @@ void OLED_Fill(OLED_T *dev, uint8_t data); */ void OLED_CLS(OLED_T *dev); + +void OLED_DisplayString(OLED_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y); + #ifdef __cplusplus } #endif diff --git a/lib/src/font/font.cpp b/lib/src/font/font.cpp new file mode 100644 index 0000000..22d318d --- /dev/null +++ b/lib/src/font/font.cpp @@ -0,0 +1,216 @@ + +#include "lvgl.h" +#include "font.h" + +char Font_utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter) { + char outputSize = 0; + char ppOutput[8] = {0}; + + char *tmp = ppOutput; //临时变量,用于遍历输出字符串 + + if (*pInput > 0x00 && *pInput <= 0x7F) //处理单字节UTF8字符(英文字母、数字) + { + + *tmp = *pInput; + tmp++; + *tmp = 0; //小端法表示,在高地址填补0 + outputSize = 1; + } else if (((*pInput) & 0xE0) == 0xC0) //处理双字节UTF8字符 + { + + char high = *pInput; + + pInput++; + + char low = *pInput; + + if ((low & 0xC0) != 0x80) //检查是否为合法的UTF8字符表示 + return 0; //如果不是则报错 + + *tmp = (high << 6) + (low & 0x3F); + tmp++; + *tmp = (high >> 2) & 0x07; + outputSize = 2; + } else if (((*pInput) & 0xF0) == 0xE0) //处理三字节UTF8字符 + { + + char high = *pInput; + pInput++; + char middle = *pInput; + pInput++; + char low = *pInput; + + if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80)) + return 0; + + *tmp = (middle << 6) + (low & 0x7F); + tmp++; + *tmp = (high << 4) + ((middle >> 2) & 0x0F); + outputSize = 3; + } else //对于其他字节数的UTF8字符不进行处理 + { + return 0; + } + unicode_letter[0] = ppOutput[1]; + unicode_letter[0] <<= 8; + unicode_letter[0] |= ppOutput[0]; + + return outputSize; +} + +void draw_letter_normal(Font_f_t *fd, uint16_t pos_x, uint16_t pos_y, lv_font_glyph_dsc_t *g, const uint8_t *map_p) { + uint32_t bitmask_init; + uint32_t bitmask; + uint32_t bpp = g->bpp; + + if (bpp == 3) + bpp = 4; + + switch (bpp) { + case 1: + bitmask_init = 0x80; + break; + case 2: + bitmask_init = 0xC0; + break; + case 4: + bitmask_init = 0xF0; + break; + case 8: + bitmask_init = 0xFF; + break; + default: + return; /*Invalid bpp. Can't render the letter*/ + } + + int32_t col, row; + int32_t box_w = g->box_w; + int32_t box_h = g->box_h; + int32_t width_bit = box_w * bpp; /*Letter width in bits*/ + + /* Calculate the col/row start/end on the map*/ + int32_t col_start = 0; + int32_t col_end = box_w; + int32_t row_start = 0; + int32_t row_end = box_h; + + /*Move on the map too*/ + uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp); + map_p += bit_ofs >> 3; + + uint8_t letter_px; + uint32_t col_bit; + col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */ + + // uint32_t mask_buf_size = box_w * box_h > LV_HOR_RES_MAX ? LV_HOR_RES_MAX : box_w * box_h; +// unsigned short mask_buf[LV_HOR_RES_MAX / 2]; +#if PIX_COLOR_SIZE == 1 + uint8_t fd_buf[fd->dev_w / 2]; +#endif +#if PIX_COLOR_SIZE == 16 + uint16_t fd_buf[fd->dev_w / 8]; +#endif + int32_t mask_p = 0; + + uint32_t col_bit_max = 8 - bpp; + uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp; + uint16_t index = 0; + for (row = row_start; row < row_end; row++) { + int32_t mask_p_start = mask_p; + + bitmask = bitmask_init >> col_bit; + for (col = col_start; col < col_end; col++) { + /*Load the pixel's opacity into the mask*/ + letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit); + + +#if PIX_COLOR_SIZE == 1 + if (letter_px) { + fd_buf[index / 8] |= (1 << (index % 8)); + } else { + fd_buf[index / 8] &= ~(1 << (index % 8)); + } + index++; +#endif + +#if PIX_COLOR_SIZE == 16 + if (letter_px) { + fd_buf[index] = fd->pixcolor; + } else { + fd_buf[index] = fd->backgroundcolor; + } + index++; +#endif + /*Go to the next column*/ + if (col_bit < col_bit_max) { + col_bit += bpp; + bitmask >>= bpp; + } else { + col_bit = 0; + bitmask = bitmask_init; + map_p++; + } + + /*Next mask byte*/ + mask_p++; + } + + { + + // LCD_fill_fast(pos_x, pos_y, box_w, 1, (uint8_t *)mask_buf, box_w); +#ifdef LINE_FAST_SHOW + fd->x = pos_x; + fd->y = pos_y; + fd->w = box_w; + fd->h = 1; + fd->show(fd, fd_buf, box_w); +#endif + + pos_y++; + mask_p = 0; + } //避免大字体,大缓存 ,单行即刻刷入 + + col_bit += col_bit_row_ofs; + map_p += (col_bit >> 3); + col_bit = col_bit & 0x7; + } +#ifndef LINE_FAST_SHOW + fd->x=pos_x; + fd->y=pos_y; + fd->w=box_w; + fd->h=box_h; + fd->show(fd, fd_buf, box_w * box_h); +#endif + // LCD_fill_fast(pos_x, pos_y, box_w, box_h, (uint8_t *)mask_buf, box_w * box_h); // 如果 大缓存 一次刷入 +} + +char Font_draw_letter(const lv_font_t *font, Font_f_t *fd, uint32_t letter, int16_t pos_x, int16_t pos_y) { + const uint8_t *map_p; + + lv_font_glyph_dsc_t g; + if (!font->get_glyph_dsc(font, &g, letter, '\0')) //获取字体 信息 + return 0; + + if (letter == ' ') // lvgl 空格没有实际数据 直接跳过 + return g.box_w; + + /* Don't draw anything if the character is empty. E.g. space */ + if ((g.box_h == 0) || (g.box_w == 0)) + return 0; + + map_p = font->get_glyph_bitmap(font, letter); //获取字体 实际数据 + if (map_p == NULL) + return 0; + + pos_x += g.ofs_x; //偏移修正 + pos_y += font->line_height - g.box_h - g.ofs_y; + + if (pos_x < 1) //有的时候会为负 + pos_x = 1; + if (pos_y < 1) //有的时候会为负 + pos_y = 1; + + draw_letter_normal(fd, pos_x, pos_y, &g, map_p); + + return g.box_w; +} \ No newline at end of file diff --git a/lib/src/font/lvgl_font.c b/lib/src/font/lvgl_font.c deleted file mode 100644 index f2d9824..0000000 --- a/lib/src/font/lvgl_font.c +++ /dev/null @@ -1,558 +0,0 @@ - -#include "lvgl.h" -#include "lvgl_font.h" - -#define LV_HOR_RES_MAX 128 - -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// Show utf8_to_unicode -// -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -char utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter) { - char outputSize = 0; - char ppOutput[8] = {0}; - - char *tmp = ppOutput; //临时变量,用于遍历输出字符串 - - if (*pInput > 0x00 && *pInput <= 0x7F) //处理单字节UTF8字符(英文字母、数字) - { - - *tmp = *pInput; - tmp++; - *tmp = 0; //小端法表示,在高地址填补0 - outputSize = 1; - } else if (((*pInput) & 0xE0) == 0xC0) //处理双字节UTF8字符 - { - - char high = *pInput; - - pInput++; - - char low = *pInput; - - if ((low & 0xC0) != 0x80) //检查是否为合法的UTF8字符表示 - return 0; //如果不是则报错 - - *tmp = (high << 6) + (low & 0x3F); - tmp++; - *tmp = (high >> 2) & 0x07; - outputSize = 2; - } else if (((*pInput) & 0xF0) == 0xE0) //处理三字节UTF8字符 - { - - char high = *pInput; - pInput++; - char middle = *pInput; - pInput++; - char low = *pInput; - - if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80)) - return 0; - - *tmp = (middle << 6) + (low & 0x7F); - tmp++; - *tmp = (high << 4) + ((middle >> 2) & 0x0F); - outputSize = 3; - } else //对于其他字节数的UTF8字符不进行处理 - { - return 0; - } - unicode_letter[0] = ppOutput[1]; - unicode_letter[0] <<= 8; - unicode_letter[0] |= ppOutput[0]; - - return outputSize; -} - -void -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// Show draw_letter_normal -// lv_opa_t opa ; //透明度 0-255 -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -void draw_letter_normal(uint16_t pos_x, uint16_t pos_y, lv_font_glyph_dsc_t *g, const uint8_t *map_p) { - uint32_t bitmask_init; - uint32_t bitmask; - uint32_t bpp = g->bpp; - - if (bpp == 3) - bpp = 4; - - switch (bpp) { - case 1: - bitmask_init = 0x80; - break; - case 2: - bitmask_init = 0xC0; - break; - case 4: - bitmask_init = 0xF0; - break; - case 8: - bitmask_init = 0xFF; - break; - default: - return; /*Invalid bpp. Can't render the letter*/ - } - - int32_t col, row; - int32_t box_w = g->box_w; - int32_t box_h = g->box_h; - int32_t width_bit = box_w * bpp; /*Letter width in bits*/ - - /* Calculate the col/row start/end on the map*/ - int32_t col_start = 0; - int32_t col_end = box_w; - int32_t row_start = 0; - int32_t row_end = box_h; - - /*Move on the map too*/ - uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp); - map_p += bit_ofs >> 3; - - uint8_t letter_px; - uint32_t col_bit; - col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */ - - // uint32_t mask_buf_size = box_w * box_h > LV_HOR_RES_MAX ? LV_HOR_RES_MAX : box_w * box_h; -// unsigned short mask_buf[LV_HOR_RES_MAX / 2]; - uint8_t fbuf[128 / 8]; - int32_t mask_p = 0; - - uint32_t col_bit_max = 8 - bpp; - uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp; - uint8_t index = 0; - for (row = row_start; row < row_end; row++) { - int32_t mask_p_start = mask_p; - - bitmask = bitmask_init >> col_bit; - for (col = col_start; col < col_end; col++) { - /*Load the pixel's opacity into the mask*/ - letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit); - -// if (letter_px) 1; -// else 0; - - if (letter_px) { - fbuf[index / 8] |= (1 << (index % 8)); - } else { - fbuf[index / 8] &= ~(1 << (index % 8)); - } - index++; - - /*Go to the next column*/ - if (col_bit < col_bit_max) { - col_bit += bpp; - bitmask >>= bpp; - } else { - col_bit = 0; - bitmask = bitmask_init; - map_p++; - } - - /*Next mask byte*/ - mask_p++; - } - - { - - // LCD_fill_fast(pos_x, pos_y, box_w, 1, (uint8_t *)mask_buf, box_w); - - //// 读取fbuf的当前位置的二进制位 - //bool read_bit = (fbuf[pos / 8] >> (pos % 8)) & 1; - - pos_y++; - mask_p = 0; - } //避免大字体,大缓存 ,单行即刻刷入 - - col_bit += col_bit_row_ofs; - map_p += (col_bit >> 3); - col_bit = col_bit & 0x7; - } - // LCD_fill_fast(pos_x, pos_y, box_w, box_h, (uint8_t *)mask_buf, box_w * box_h); // 如果 大缓存 一次刷入 -} - -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// Show lv_draw_letter -// -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -char lv_draw_letter(const lv_font_t *font, uint32_t letter, int16_t pos_x, int16_t pos_y) { - const uint8_t *map_p; - - lv_font_glyph_dsc_t g; - if (!font->get_glyph_dsc(font, &g, letter, '\0')) //获取字体 信息 - return 0; - - if (letter == ' ') // lvgl 空格没有实际数据 直接跳过 - return g.box_w; - - /* Don't draw anything if the character is empty. E.g. space */ - if ((g.box_h == 0) || (g.box_w == 0)) - return 0; - - map_p = font->get_glyph_bitmap(font, letter); //获取字体 实际数据 - if (map_p == NULL) - return 0; - - pos_x += g.ofs_x; //偏移修正 - pos_y += font->line_height - g.box_h - g.ofs_y; - - if (pos_x < 1) //有的时候会为负 - pos_x = 1; - if (pos_y < 1) //有的时候会为负 - pos_y = 1; - - draw_letter_normal(pos_x, pos_y, &g, map_p); - - return g.box_w; -} - -#if LV_FONT_UNSCII_8 - -/** Searches base[0] to base[n - 1] for an item that matches *key. - * - * @note The function cmp must return negative if its first - * argument (the search key) is less that its second (a table entry), - * zero if equal, and positive if greater. - * - * @note Items in the array must be in ascending order. - * - * @param key Pointer to item being searched for - * @param base Pointer to first element to search - * @param n Number of elements - * @param size Size of each element - * @param cmp Pointer to comparison function (see #lv_font_codeCompare as a comparison function - * example) - * - * @return a pointer to a matching item, or NULL if none exists. - */ -void *_lv_utils_bsearch(const void *key, const void *base, uint32_t n, uint32_t size, - int32_t (*cmp)(const void *pRef, const void *pElement)) -{ - const char *middle; - int32_t c; - - for (middle = base; n != 0;) - { - middle += (n / 2) * size; - if ((c = (*cmp)(key, middle)) > 0) - { - n = (n / 2) - ((n & 1) == 0); - base = (middle += size); - } - else if (c < 0) - { - n /= 2; - middle = base; - } - else - { - return (char *)middle; - } - } - return NULL; -} -/** Code Comparator. - * - * Compares the value of both input arguments. - * - * @param[in] pRef Pointer to the reference. - * @param[in] pElement Pointer to the element to compare. - * - * @return Result of comparison. - * @retval < 0 Reference is greater than element. - * @retval = 0 Reference is equal to element. - * @retval > 0 Reference is less than element. - * - */ -static int32_t unicode_list_compare(const void *ref, const void *element) -{ - return ((int32_t)(*(uint16_t *)ref)) - ((int32_t)(*(uint16_t *)element)); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static uint32_t get_glyph_dsc_id(const lv_font_t *font, uint32_t letter) -{ - if (letter == '\0') - return 0; - - lv_font_fmt_txt_dsc_t *fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; - - /*Check the cache first*/ - if (letter == fdsc->last_letter) - return fdsc->last_glyph_id; - - uint16_t i; - for (i = 0; i < fdsc->cmap_num; i++) - { - - /*Relative code point*/ - uint32_t rcp = letter - fdsc->cmaps[i].range_start; - if (rcp > fdsc->cmaps[i].range_length) - continue; - uint32_t glyph_id = 0; - if (fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY) - { - glyph_id = fdsc->cmaps[i].glyph_id_start + rcp; - } - else if (fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL) - { - const uint8_t *gid_ofs_8 = fdsc->cmaps[i].glyph_id_ofs_list; - glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_8[rcp]; - } - else if (fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) - { - uint16_t key = rcp; - uint8_t *p = _lv_utils_bsearch(&key, fdsc->cmaps[i].unicode_list, fdsc->cmaps[i].list_length, - sizeof(fdsc->cmaps[i].unicode_list[0]), unicode_list_compare); - - if (p) - { - lv_uintptr_t ofs = (lv_uintptr_t)(p - (uint8_t *)fdsc->cmaps[i].unicode_list); - ofs = ofs >> 1; /*The list stores `uint16_t` so the get the index divide by 2*/ - glyph_id = fdsc->cmaps[i].glyph_id_start + ofs; - } - } - else if (fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL) - { - uint16_t key = rcp; - uint8_t *p = _lv_utils_bsearch(&key, fdsc->cmaps[i].unicode_list, fdsc->cmaps[i].list_length, - sizeof(fdsc->cmaps[i].unicode_list[0]), unicode_list_compare); - - if (p) - { - lv_uintptr_t ofs = (lv_uintptr_t)(p - (uint8_t *)fdsc->cmaps[i].unicode_list); - ofs = ofs >> 1; /*The list stores `uint16_t` so the get the index divide by 2*/ - const uint8_t *gid_ofs_16 = fdsc->cmaps[i].glyph_id_ofs_list; - glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_16[ofs]; - } - } - - /*Update the cache*/ - fdsc->last_letter = letter; - fdsc->last_glyph_id = glyph_id; - return glyph_id; - } - - fdsc->last_letter = letter; - fdsc->last_glyph_id = 0; - return 0; -} -/** - * Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed. - * @param font pointer to font - * @param unicode_letter an unicode letter which bitmap should be get - * @return pointer to the bitmap or NULL if not found - */ -const uint8_t *lv_font_get_bitmap_fmt_txt(const lv_font_t *font, uint32_t unicode_letter) -{ - if (unicode_letter == '\t') - unicode_letter = ' '; - - lv_font_fmt_txt_dsc_t *fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; - uint32_t gid = get_glyph_dsc_id(font, unicode_letter); - if (!gid) - return NULL; - - const lv_font_fmt_txt_glyph_dsc_t *gdsc = &fdsc->glyph_dsc[gid]; - - if (fdsc->bitmap_format == LV_FONT_FMT_TXT_PLAIN) - { - if (gdsc) - return &fdsc->glyph_bitmap[gdsc->bitmap_index]; - } - /*Handle compressed bitmap*/ - else - { -#if LV_USE_FONT_COMPRESSED - uint32_t gsize = gdsc->box_w * gdsc->box_h; - if (gsize == 0) - return NULL; - - uint32_t buf_size = gsize; - /*Compute memory size needed to hold decompressed glyph, rounding up*/ - switch (fdsc->bpp) - { - case 1: - buf_size = (gsize + 7) >> 3; - break; - case 2: - buf_size = (gsize + 3) >> 2; - break; - case 3: - buf_size = (gsize + 1) >> 1; - break; - case 4: - buf_size = (gsize + 1) >> 1; - break; - } - - if (_lv_mem_get_size(LV_GC_ROOT(_lv_font_decompr_buf)) < buf_size) - { - LV_GC_ROOT(_lv_font_decompr_buf) = lv_mem_realloc(LV_GC_ROOT(_lv_font_decompr_buf), buf_size); - LV_ASSERT_MEM(LV_GC_ROOT(_lv_font_decompr_buf)); - if (LV_GC_ROOT(_lv_font_decompr_buf) == NULL) - return NULL; - } - - bool prefilter = fdsc->bitmap_format == LV_FONT_FMT_TXT_COMPRESSED ? true : false; - decompress(&fdsc->glyph_bitmap[gdsc->bitmap_index], LV_GC_ROOT(_lv_font_decompr_buf), gdsc->box_w, gdsc->box_h, - (uint8_t)fdsc->bpp, - prefilter); - return LV_GC_ROOT(_lv_font_decompr_buf); -#else /* !LV_USE_FONT_COMPRESSED */ - return NULL; -#endif - } - - /*If not returned earlier then the letter is not found in this font*/ - return NULL; -} - -static int32_t kern_pair_8_compare(const void *ref, const void *element) -{ - const uint8_t *ref8_p = ref; - const uint8_t *element8_p = element; - - /*If the MSB is different it will matter. If not return the diff. of the LSB*/ - if (ref8_p[0] != element8_p[0]) - return (int32_t)ref8_p[0] - element8_p[0]; - else - return (int32_t)ref8_p[1] - element8_p[1]; -} - -static int32_t kern_pair_16_compare(const void *ref, const void *element) -{ - const uint16_t *ref16_p = ref; - const uint16_t *element16_p = element; - - /*If the MSB is different it will matter. If not return the diff. of the LSB*/ - if (ref16_p[0] != element16_p[0]) - return (int32_t)ref16_p[0] - element16_p[0]; - else - return (int32_t)ref16_p[1] - element16_p[1]; -} -static int8_t get_kern_value(const lv_font_t *font, uint32_t gid_left, uint32_t gid_right) -{ - lv_font_fmt_txt_dsc_t *fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; - - int8_t value = 0; - - if (fdsc->kern_classes == 0) - { - /*Kern pairs*/ - const lv_font_fmt_txt_kern_pair_t *kdsc = fdsc->kern_dsc; - if (kdsc->glyph_ids_size == 0) - { - /* Use binary search to find the kern value. - * The pairs are ordered left_id first, then right_id secondly. */ - const uint8_t *g_ids = kdsc->glyph_ids; - uint16_t g_id_both = (gid_right << 8) + gid_left; /*Create one number from the ids*/ - uint8_t *kid_p = _lv_utils_bsearch(&g_id_both, g_ids, kdsc->pair_cnt, 2, kern_pair_8_compare); - - /*If the `g_id_both` were found get its index from the pointer*/ - if (kid_p) - { - lv_uintptr_t ofs = (lv_uintptr_t)(kid_p - g_ids); - ofs = ofs >> 1; /*ofs is for pair, divide by 2 to refer as a single value*/ - value = kdsc->values[ofs]; - } - } - else if (kdsc->glyph_ids_size == 1) - { - /* Use binary search to find the kern value. - * The pairs are ordered left_id first, then right_id secondly. */ - const uint16_t *g_ids = kdsc->glyph_ids; - lv_uintptr_t g_id_both = (uint32_t)((uint32_t)gid_right << 8) + gid_left; /*Create one number from the ids*/ - uint8_t *kid_p = _lv_utils_bsearch(&g_id_both, g_ids, kdsc->pair_cnt, 4, kern_pair_16_compare); - - /*If the `g_id_both` were found get its index from the pointer*/ - if (kid_p) - { - lv_uintptr_t ofs = (lv_uintptr_t)(kid_p - (const uint8_t *)g_ids); - ofs = ofs >> 4; /*ofs is 4 byte pairs, divide by 4 to refer as a single value*/ - value = kdsc->values[ofs]; - } - } - else - { - /*Invalid value*/ - } - } - else - { - /*Kern classes*/ - const lv_font_fmt_txt_kern_classes_t *kdsc = fdsc->kern_dsc; - uint8_t left_class = kdsc->left_class_mapping[gid_left]; - uint8_t right_class = kdsc->right_class_mapping[gid_right]; - - /* If class = 0, kerning not exist for that glyph - * else got the value form `class_pair_values` 2D array*/ - if (left_class > 0 && right_class > 0) - { - value = kdsc->class_pair_values[(left_class - 1) * kdsc->right_class_cnt + (right_class - 1)]; - } - } - return value; -} - -/** - * Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed. - * @param font_p pointer to font - * @param dsc_out store the result descriptor here - * @param letter an UNICODE letter code - * @return true: descriptor is successfully loaded into `dsc_out`. - * false: the letter was not found, no data is loaded to `dsc_out` - */ -bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t *font, lv_font_glyph_dsc_t *dsc_out, uint32_t unicode_letter, - uint32_t unicode_letter_next) -{ - bool is_tab = false; - if (unicode_letter == '\t') - { - unicode_letter = ' '; - is_tab = true; - } - lv_font_fmt_txt_dsc_t *fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; - uint32_t gid = get_glyph_dsc_id(font, unicode_letter); - if (!gid) - return false; - - int8_t kvalue = 0; - if (fdsc->kern_dsc) - { - uint32_t gid_next = get_glyph_dsc_id(font, unicode_letter_next); - if (gid_next) - { - kvalue = get_kern_value(font, gid, gid_next); - } - } - - /*Put together a glyph dsc*/ - const lv_font_fmt_txt_glyph_dsc_t *gdsc = &fdsc->glyph_dsc[gid]; - - int32_t kv = ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4); - - uint32_t adv_w = gdsc->adv_w; - if (is_tab) - adv_w *= 2; - - adv_w += kv; - adv_w = (adv_w + (1 << 3)) >> 4; - - dsc_out->adv_w = adv_w; - dsc_out->box_h = gdsc->box_h; - dsc_out->box_w = gdsc->box_w; - dsc_out->ofs_x = gdsc->ofs_x; - dsc_out->ofs_y = gdsc->ofs_y; - dsc_out->bpp = (uint8_t)fdsc->bpp; - - if (is_tab) - dsc_out->box_w = dsc_out->box_w * 2; - - return true; -} - -#endif diff --git a/lib/src/oled/oled.cpp b/lib/src/oled/oled.cpp index ccf1e1c..00e25d3 100644 --- a/lib/src/oled/oled.cpp +++ b/lib/src/oled/oled.cpp @@ -1,7 +1,7 @@ #include "oled.h" #include "oled_font.h" #include "oled_font_chuc.h" -#include "../../inc/font/lvgl_font.h" +#include "font.h" #define BUFPOINT(x, y) (*(dev->buf + x + (y * dev->width))) #define GET_BIT(x, bit) ((x & (1 << bit)) >> bit) @@ -248,21 +248,38 @@ void OLED_ShowCHString(OLED_T *dev, uint8_t x, uint8_t y, uint8_t *str) { } } } + +void draw_rect(Font_f_t *fd, uint8_t *data, size_t len) { + size_t index; + uint16_t x = fd->x, y = fd->y; + uint8_t bit; + for (index = 0; index < len; index++) { + bit = (data[index / 8] >> (index % 8)) & 1; + if (bit)OLED_Set((OLED_T *) fd->dev, x, y); + else OLED_RSet((OLED_T *) fd->dev, x, y); + x++; + if ((x - fd->x) == fd->w) { + y++; + x = fd->x; + } + } +} // -//void OLED_DisplayString(OLED_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y) { -// uint32_t unicode_letter; -// while (*s) { -// if (font) { -// s += utf8_to_unicode(s, &unicode_letter); -// x += lv_draw_letter(font, unicode_letter, x, y); -// x += 2; //字间距 -// } else { -// OLED_ShowChar(dev, x, y, *s, 6); -// x += 6; -// s++; -// } -// } -//} +void OLED_DisplayString(OLED_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y) { + uint32_t unicode_letter; + Font_f_t fd = {.dev=dev, .dev_w=dev->width, .show=draw_rect}; + while (*s) { + if (font) { + s += Font_utf8_to_unicode(s, &unicode_letter); + x += Font_draw_letter(font, &fd, unicode_letter, x, y); + x += 2; //字间距 + } else { + OLED_ShowChar(dev, x, y, *s, 12); + x += 6; + s++; + } + } +} uint32_t OLED_Pow(uint8_t m, uint8_t n) { uint32_t result = 1;