Просмотр исходного кода

merge: 合并hzfont分支, Merge branch 'feat/hzfont'

zengeshuai 1 месяц назад
Родитель
Сommit
68ee7b5fe3

+ 7 - 2
components/hzfont/binding/luat_lib_hzfont.c

@@ -25,9 +25,10 @@ hzfont.init("/sd/font.ttf")
 
 /**
 初始化HzFont字体库
-@api hzfont.init([ttf_path][, cache_size])
+@api hzfont.init([ttf_path][, cache_size][, load_to_psram])
 @string ttf_path TTF字体文件路径,可选;留空则回退到内置字库(若启用)
 @int cache_size 可选,位图与码点缓存容量(支持常量 HZFONT_CACHE_128/256/512/1024/2048),默认 HZFONT_CACHE_256
+@bool load_to_psram 可选,true 时将字库整包拷贝到 PSRAM 后再解析,减少后续 IO
 @return boolean 成功返回true,失败返回false
 @usage
 -- 从文件加载,使用默认缓存 256
@@ -52,7 +53,11 @@ static int l_hzfont_init(lua_State* L) {
     if (!lua_isnoneornil(L, 2)) {
         cache_size = (uint32_t)luaL_checkinteger(L, 2);
     }
-    int result = luat_hzfont_init(ttf_path, cache_size);
+    int load_to_psram = 0;
+    if (!lua_isnoneornil(L, 3)) {
+        load_to_psram = lua_toboolean(L, 3);
+    }
+    int result = luat_hzfont_init(ttf_path, cache_size, load_to_psram);
     lua_pushboolean(L, result);
     return 1;
 }

+ 1 - 1
components/hzfont/inc/luat_hzfont.h

@@ -14,7 +14,7 @@ typedef enum {
     LUAT_HZFONT_STATE_ERROR  = 2,
 } luat_hzfont_state_t;
 
-int luat_hzfont_init(const char *ttf_path, uint32_t cache_size);
+int luat_hzfont_init(const char *ttf_path, uint32_t cache_size, int load_to_psram);
 void luat_hzfont_deinit(void);
 luat_hzfont_state_t luat_hzfont_get_state(void);
 uint32_t luat_hzfont_get_str_width(const char *utf8, unsigned char font_size);

+ 90 - 11
components/hzfont/src/luat_hzfont.c

@@ -5,8 +5,10 @@
 #include "luat_lcd.h"
 #include "luat_mem.h"
 #include "luat_mcu.h"
+#include "luat_fs.h"
 
 #include <math.h>
+#include <stdio.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <string.h>
@@ -172,6 +174,48 @@ static int hzfont_is_allowed_capacity(uint32_t cap) {
     return 0;
 }
 
+/* 将字体文件完整读入内存(PSRAM),用于后续内存解析 */
+static int hzfont_load_file_to_ram(const char *path, uint8_t **out_data, size_t *out_size) {
+    if (!path || !out_data || !out_size) {
+        return TTF_ERR_RANGE;
+    }
+    *out_data = NULL;
+    *out_size = 0;
+
+    FILE *fp = luat_fs_fopen(path, "rb");
+    if (!fp) {
+        return TTF_ERR_IO;
+    }
+
+    if (luat_fs_fseek(fp, 0, SEEK_END) != 0) {
+        luat_fs_fclose(fp);
+        return TTF_ERR_IO;
+    }
+    long vsize = luat_fs_ftell(fp);
+    if (vsize <= 0) {
+        luat_fs_fclose(fp);
+        return TTF_ERR_IO;
+    }
+    if (luat_fs_fseek(fp, 0, SEEK_SET) != 0) {
+        luat_fs_fclose(fp);
+        return TTF_ERR_IO;
+    }
+    uint8_t *buf = (uint8_t *)luat_heap_malloc((size_t)vsize);
+    if (!buf) {
+        luat_fs_fclose(fp);
+        return TTF_ERR_OOM;
+    }
+    size_t n = luat_fs_fread(buf, 1, (size_t)vsize, fp);
+    luat_fs_fclose(fp);
+    if (n != (size_t)vsize) {
+        luat_heap_free(buf);
+        return TTF_ERR_IO;
+    }
+    *out_data = buf;
+    *out_size = (size_t)vsize;
+    return TTF_OK;
+}
+
 static void hzfont_cache_destroy(void) {
     if (g_hzfont_cache && g_hzfont_cache_capacity) {
         for (size_t i = 0; i < g_hzfont_cache_capacity; ++i) {
@@ -535,12 +579,11 @@ static luat_color_t hzfont_coverage_to_color(uint8_t coverage, const luat_lcd_co
 }
 
 /* 初始化字体库
- * What: 加载 TTF(外部/内置),建立码点与位图缓存。
- * Pre: 需要有效的 ttf_path 或启用内置字库宏;cache_size 仅允许 128/256/512/1024/2048。
+ * What: 加载 TTF(外部/内置),可选整包读入 PSRAM,建立码点与位图缓存。
+ * Pre: 需要有效的 ttf_path 或启用内置字库宏;cache_size 仅允许 128/256/512/1024/2048;load_to_psram=1 时需有足够 RAM
  * Post: 状态置为 READY,后续方可测宽/绘制;失败时状态为 ERROR。
- * TODO: 增加 init 参数,支持选择将字库整包拷贝到 PSRAM,避免后续 IO(外部/内置均可)。
  */
-int luat_hzfont_init(const char *ttf_path, uint32_t cache_size) {
+int luat_hzfont_init(const char *ttf_path, uint32_t cache_size, int load_to_psram) {
     if (g_ft_ctx.state == LUAT_HZFONT_STATE_READY) {
         LLOGE("font already initialized");
         return 0;
@@ -555,17 +598,53 @@ int luat_hzfont_init(const char *ttf_path, uint32_t cache_size) {
     memset(&g_ft_ctx.font, 0, sizeof(g_ft_ctx.font));
 
     int rc = TTF_ERR_RANGE;
+    uint8_t *ram_buf = NULL;
+    size_t ram_size = 0;
     if (ttf_path && ttf_path[0]) {
-        rc = ttf_load_from_file(ttf_path, &g_ft_ctx.font);
-        if (rc == TTF_OK) {
-            strncpy(g_ft_ctx.font_path, ttf_path, sizeof(g_ft_ctx.font_path) - 1);
-            g_ft_ctx.font_path[sizeof(g_ft_ctx.font_path) - 1] = 0;
+        if (load_to_psram) {
+            rc = hzfont_load_file_to_ram(ttf_path, &ram_buf, &ram_size);
+            if (rc == TTF_OK) {
+                rc = ttf_load_from_memory(ram_buf, ram_size, &g_ft_ctx.font);
+                if (rc == TTF_OK) {
+                    g_ft_ctx.font.ownsData = 1; /* 允许 ttf_unload 释放 */
+                    g_ft_ctx.font_path[0] = 0;
+                    strncpy(g_ft_ctx.font_path, ttf_path, sizeof(g_ft_ctx.font_path) - 1);
+                    g_ft_ctx.font_path[sizeof(g_ft_ctx.font_path) - 1] = 0;
+                } else {
+                    luat_heap_free(ram_buf);
+                    ram_buf = NULL;
+                }
+            }
+        } else {
+            rc = ttf_load_from_file(ttf_path, &g_ft_ctx.font);
+            if (rc == TTF_OK) {
+                strncpy(g_ft_ctx.font_path, ttf_path, sizeof(g_ft_ctx.font_path) - 1);
+                g_ft_ctx.font_path[sizeof(g_ft_ctx.font_path) - 1] = 0;
+            }
         }
     } else {
 #ifdef LUAT_CONF_USE_HZFONT_BUILTIN_TTF
-        rc = ttf_load_from_memory(hzfont_builtin_ttf, (size_t)hzfont_builtin_ttf_len, &g_ft_ctx.font);
-        if (rc == TTF_OK) {
-            g_ft_ctx.font_path[0] = '\0';
+        if (load_to_psram) {
+            ram_buf = (uint8_t *)luat_heap_malloc((size_t)hzfont_builtin_ttf_len);
+            if (!ram_buf) {
+                rc = TTF_ERR_OOM;
+            } else {
+                memcpy(ram_buf, hzfont_builtin_ttf, (size_t)hzfont_builtin_ttf_len);
+                ram_size = (size_t)hzfont_builtin_ttf_len;
+                rc = ttf_load_from_memory(ram_buf, ram_size, &g_ft_ctx.font);
+                if (rc == TTF_OK) {
+                    g_ft_ctx.font.ownsData = 1;
+                    g_ft_ctx.font_path[0] = '\0';
+                } else {
+                    luat_heap_free(ram_buf);
+                    ram_buf = NULL;
+                }
+            }
+        } else {
+            rc = ttf_load_from_memory(hzfont_builtin_ttf, (size_t)hzfont_builtin_ttf_len, &g_ft_ctx.font);
+            if (rc == TTF_OK) {
+                g_ft_ctx.font_path[0] = '\0';
+            }
         }
 #else
         LLOGE("empty ttf path and no builtin ttf");