luat_lib_fonts.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. @module fonts
  3. @summary 字体库
  4. @version 1.0
  5. @date 2022.07.11
  6. @tag LUAT_USE_FONTS
  7. */
  8. #include "luat_base.h"
  9. #include "luat_mem.h"
  10. #include "luat_fs.h"
  11. #define LUAT_LOG_TAG "fonts"
  12. #include "luat_log.h"
  13. #include "u8g2.h"
  14. #include "u8g2_luat_fonts.h"
  15. #include "luat_fonts_custom.h"
  16. typedef struct u8g2_font
  17. {
  18. const char* name;
  19. const uint8_t* font;
  20. }u8g2_font_t;
  21. static const u8g2_font_t u8g2_fonts[] = {
  22. #ifdef USE_U8G2_OPPOSANSM_ENGLISH
  23. {.name="unifont_t_symbols", .font=u8g2_font_unifont_t_symbols},
  24. {.name="open_iconic_weather_6x_t", .font=u8g2_font_open_iconic_weather_6x_t},
  25. {.name="opposansm10", .font=u8g2_font_opposansm10},
  26. {.name="opposansm12", .font=u8g2_font_opposansm12},
  27. {.name="opposansm16", .font=u8g2_font_opposansm16},
  28. {.name="opposansm20", .font=u8g2_font_opposansm20},
  29. {.name="opposansm24", .font=u8g2_font_opposansm24},
  30. {.name="opposansm32", .font=u8g2_font_opposansm32},
  31. #endif
  32. #ifdef USE_U8G2_OPPOSANSM12_CHINESE
  33. {.name="opposansm12_chinese", .font=u8g2_font_opposansm12_chinese},
  34. #endif
  35. #ifdef USE_U8G2_OPPOSANSM14_CHINESE
  36. {.name="opposansm14_chinese", .font=u8g2_font_opposansm14_chinese},
  37. #endif
  38. #ifdef USE_U8G2_OPPOSANSM16_CHINESE
  39. {.name="opposansm16_chinese", .font=u8g2_font_opposansm16_chinese},
  40. #endif
  41. #ifdef USE_U8G2_OPPOSANSM18_CHINESE
  42. {.name="opposansm18_chinese", .font=u8g2_font_opposansm18_chinese},
  43. #endif
  44. #ifdef USE_U8G2_OPPOSANSM20_CHINESE
  45. {.name="opposansm20_chinese", .font=u8g2_font_opposansm20_chinese},
  46. #endif
  47. #ifdef USE_U8G2_OPPOSANSM22_CHINESE
  48. {.name="opposansm22_chinese", .font=u8g2_font_opposansm22_chinese},
  49. #endif
  50. #ifdef USE_U8G2_OPPOSANSM24_CHINESE
  51. {.name="opposansm24_chinese", .font=u8g2_font_opposansm24_chinese},
  52. #endif
  53. #ifdef USE_U8G2_OPPOSANSM32_CHINESE
  54. {.name="opposansm32_chinese", .font=u8g2_font_opposansm32_chinese},
  55. #endif
  56. #ifdef USE_U8G2_SARASA_ENGLISH
  57. { .name="sarasa_m12_ascii", .font=u8g2_font_sarasa_m12_ascii},
  58. { .name="sarasa_m14_ascii", .font=u8g2_font_sarasa_m14_ascii},
  59. { .name="sarasa_m16_ascii", .font=u8g2_font_sarasa_m16_ascii},
  60. { .name="sarasa_m18_ascii", .font=u8g2_font_sarasa_m18_ascii},
  61. { .name="sarasa_m20_ascii", .font=u8g2_font_sarasa_m20_ascii},
  62. { .name="sarasa_m22_ascii", .font=u8g2_font_sarasa_m22_ascii},
  63. //再大的很少用到先不加了
  64. #endif
  65. // #ifdef USE_U8G2_SARASA_M8_CHINESE
  66. // { .name="sarasa_m8_chinese", .font=u8g2_font_sarasa_m8_chinese},
  67. // #endif
  68. #ifdef USE_U8G2_SARASA_M10_CHINESE
  69. { .name="sarasa_m10_chinese", .font=u8g2_font_sarasa_m10_chinese},
  70. #endif
  71. #ifdef USE_U8G2_SARASA_M12_CHINESE
  72. { .name="sarasa_m12_chinese", .font=u8g2_font_sarasa_m12_chinese},
  73. #endif
  74. #ifdef USE_U8G2_SARASA_M14_CHINESE
  75. { .name="sarasa_m14_chinese", .font=u8g2_font_sarasa_m14_chinese},
  76. #endif
  77. #ifdef USE_U8G2_SARASA_M16_CHINESE
  78. { .name="sarasa_m16_chinese", .font=u8g2_font_sarasa_m16_chinese},
  79. #endif
  80. #ifdef USE_U8G2_SARASA_M18_CHINESE
  81. { .name="sarasa_m18_chinese", .font=u8g2_font_sarasa_m18_chinese},
  82. #endif
  83. #ifdef USE_U8G2_SARASA_M20_CHINESE
  84. { .name="sarasa_m20_chinese", .font=u8g2_font_sarasa_m20_chinese},
  85. #endif
  86. #ifdef USE_U8G2_SARASA_M22_CHINESE
  87. { .name="sarasa_m22_chinese", .font=u8g2_font_sarasa_m22_chinese},
  88. #endif
  89. #ifdef USE_U8G2_SARASA_M24_CHINESE
  90. { .name="sarasa_m24_chinese", .font=u8g2_font_sarasa_m24_chinese},
  91. #endif
  92. #ifdef USE_U8G2_SARASA_M26_CHINESE
  93. { .name="sarasa_m26_chinese", .font=u8g2_font_sarasa_m26_chinese},
  94. #endif
  95. #ifdef USE_U8G2_SARASA_M28_CHINESE
  96. { .name="sarasa_m28_chinese", .font=u8g2_font_sarasa_m28_chinese},
  97. #endif
  98. #ifdef LUAT_FONTS_CUSTOM_U8G2
  99. LUAT_FONTS_CUSTOM_U8G2
  100. #endif
  101. {.name="", .font=NULL},
  102. };
  103. static int l_fonts_u8g2_get(lua_State *L) {
  104. const char* name = luaL_checkstring(L, 1);
  105. const u8g2_font_t *font = u8g2_fonts;
  106. while (font->font != NULL) {
  107. if (!strcmp(name, font->name)) {
  108. lua_pushlightuserdata(L, font->font);
  109. return 1;
  110. }
  111. font ++;
  112. }
  113. return 0;
  114. }
  115. static int l_fonts_u8g2_load(lua_State *L) {
  116. char* ptr = NULL;
  117. // 从文件加载
  118. const char* path = luaL_checkstring(L, 1);
  119. size_t flen = luat_fs_fsize(path);
  120. if (flen < 16) {
  121. LLOGE("not a good font file %s", path);
  122. return 0;
  123. }
  124. FILE* fd = luat_fs_fopen(path, "rb");
  125. if (fd == NULL) {
  126. LLOGE("no such file %s", path);
  127. return 0;
  128. }
  129. #ifdef LUAT_USE_FS_VFS
  130. //LLOGD("try mmap");
  131. ptr = (char*)luat_fs_mmap(fd);
  132. if (ptr != NULL) {
  133. LLOGD("load by mmap %s %p", path, ptr);
  134. lua_pushlightuserdata(L, ptr);
  135. luat_fs_fclose(fd);
  136. return 1;
  137. }
  138. #endif
  139. ptr = lua_newuserdata(L, flen);
  140. if (ptr == NULL) {
  141. luat_fs_fclose(fd);
  142. LLOGE("no engouh memory for font %s", path);
  143. return 0;
  144. }
  145. char buff[256];
  146. int len = 0;
  147. int count = 0;
  148. while (count < flen)
  149. {
  150. len = luat_fs_fread(buff, 256, 1, fd);
  151. if (len < 0)
  152. break;
  153. if (len > 0) {
  154. memcpy(ptr + count, buff, len);
  155. count += len;
  156. }
  157. }
  158. luat_fs_fclose(fd);
  159. lua_pushlightuserdata(L, ptr);
  160. return 1;
  161. }
  162. static int l_fonts_u8g2_list(lua_State *L) {
  163. const u8g2_font_t *font = u8g2_fonts;
  164. lua_createtable(L, 10, 0);
  165. int index = 1;
  166. while (font->font != NULL) {
  167. lua_pushinteger(L, index);
  168. lua_pushstring(L, font->name);
  169. lua_settable(L, -3);
  170. index ++;
  171. font ++;
  172. }
  173. return 1;
  174. }
  175. //----------------------------------------------
  176. // LVGL 相关
  177. //----------------------------------------------
  178. #ifdef LUAT_USE_LVGL
  179. #include "lvgl.h"
  180. #include "lv_font/lv_font.h"
  181. typedef struct lv_font_reg
  182. {
  183. const char* name;
  184. lv_font_t* font;
  185. }lv_font_reg_t;
  186. static const lv_font_reg_t lv_regs[] = {
  187. #ifdef LV_FONT_MONTSERRAT_14
  188. {.name="montserrat_14", .font=&lv_font_montserrat_14},
  189. #endif
  190. #ifdef LV_FONT_OPPOSANS_M_8
  191. {.name="opposans_m_8", .font=&lv_font_opposans_m_8},
  192. #endif
  193. #ifdef LV_FONT_OPPOSANS_M_10
  194. {.name="opposans_m_10", .font=&lv_font_opposans_m_10},
  195. #endif
  196. #ifdef LV_FONT_OPPOSANS_M_12
  197. {.name="opposans_m_12", .font=&lv_font_opposans_m_12},
  198. #endif
  199. #ifdef LV_FONT_OPPOSANS_M_14
  200. {.name="opposans_m_14", .font=&lv_font_opposans_m_14},
  201. #endif
  202. #ifdef LV_FONT_OPPOSANS_M_16
  203. {.name="opposans_m_16", .font=&lv_font_opposans_m_16},
  204. #endif
  205. #ifdef LV_FONT_OPPOSANS_M_18
  206. {.name="opposans_m_18", .font=&lv_font_opposans_m_18},
  207. #endif
  208. #ifdef LV_FONT_OPPOSANS_M_20
  209. {.name="opposans_m_20", .font=&lv_font_opposans_m_20},
  210. #endif
  211. #ifdef LV_FONT_OPPOSANS_M_22
  212. {.name="opposans_m_22", .font=&lv_font_opposans_m_22},
  213. #endif
  214. #ifdef LUAT_FONTS_CUSTOM_LVGL
  215. LUAT_FONTS_CUSTOM_LVGL
  216. #endif
  217. {.name="", .font=NULL},
  218. };
  219. static int l_fonts_lvgl_get(lua_State *L) {
  220. const char* name = luaL_checkstring(L, 1);
  221. const lv_font_reg_t *font = lv_regs;
  222. while (font->font != NULL) {
  223. if (!strcmp(name, font->name)) {
  224. lua_pushlightuserdata(L, font->font);
  225. return 1;
  226. }
  227. font ++;
  228. }
  229. return 0;
  230. }
  231. static int l_fonts_lvgl_list(lua_State *L) {
  232. const lv_font_reg_t *font = lv_regs;
  233. lua_createtable(L, 10, 0);
  234. int index = 1;
  235. while (font->font != NULL) {
  236. lua_pushinteger(L, index);
  237. lua_pushstring(L, font->name);
  238. lua_settable(L, -3);
  239. index ++;
  240. }
  241. return 1;
  242. }
  243. #endif
  244. /*
  245. 返回固件支持的字体列表
  246. @api fonts.list(tp)
  247. @string 类型, 默认 u8g2, 还可以是lvgl
  248. @return table 字体列表
  249. @usage
  250. -- API新增于2022-07-12
  251. if fonts.list then
  252. log.info("fonts", "u8g2", json.encode(fonts.list("u8g2")))
  253. end
  254. */
  255. static int l_fonts_list(lua_State *L) {
  256. #ifdef LUAT_USE_LVGL
  257. const char* tp = luaL_optstring(L, 1, "u8g2");
  258. if (!strcmp("lvgl", tp)) {
  259. return l_fonts_lvgl_list(L);
  260. }
  261. #endif
  262. return l_fonts_u8g2_list(L);
  263. }
  264. /*
  265. 获取字体
  266. @api fonts.u8g2_get(name, tp)
  267. @string 字体名称, 例如opposansm8_chinese unifont_t_symbols
  268. @string 类型, 默认 u8g2, 还可以是lvgl
  269. @return userdata 若字体存放,返回字体指针, 否则返回nil
  270. @usage
  271. oppo_8 = fonts.get("opposansm8_chinese", "u8g2")
  272. if oppo_8 then
  273. u8g2.SetFont(oppo_8)
  274. else
  275. log.warn("fonts", "no such font opposansm8_chinese")
  276. end
  277. -- 若使用云编译的自定义字库, 使用方式如下
  278. oppo_8 = fonts.get("oppo_bold_8", "u8g2") -- oppo_bold_8 是云编译界面的字库命名
  279. if oppo_8 then
  280. u8g2.SetFont(oppo_8)
  281. else
  282. log.warn("fonts", "no such font opposansm8_chinese")
  283. end
  284. */
  285. static int l_fonts_get(lua_State *L) {
  286. #ifdef LUAT_USE_LVGL
  287. const char* tp = luaL_optstring(L, 2, "u8g2");
  288. if (!strcmp("lvgl", tp)) {
  289. return l_fonts_lvgl_get(L);
  290. }
  291. #endif
  292. return l_fonts_u8g2_get(L);
  293. }
  294. /*
  295. 从文件加载字体
  296. @api fonts.u8g2_load(path, path)
  297. @string 字体路径, 例如 /luadb/abc.bin
  298. @string 类型, 默认 u8g2. 也支持lvgl
  299. @return userdata 若字体存放,返回字体指针, 否则返回nil
  300. @usage
  301. -- API新增于2022-07-11
  302. -- 提醒: 若文件位于/luadb下, 不需要占用内存
  303. -- 若文件处于其他路径, 例如tf/sd卡, spi flash, 会自动加载到内存, 消耗lua vm的内存空间
  304. -- 加载后请适当引用, 不必反复加载同一个字体文件
  305. oppo12 = fonts.load("/luadb/oppo12.bin")
  306. if oppo12 then
  307. u8g2.SetFont(oppo12)
  308. else
  309. log.warn("fonts", "no such font file oppo12.bin")
  310. end
  311. */
  312. static int l_fonts_load(lua_State *L) {
  313. #ifdef LUAT_USE_LVGL
  314. const char* tp = luaL_optstring(L, 2, "u8g2");
  315. if (!strcmp("lvgl", tp)) {
  316. const char* fontname = luaL_checkstring(L, 1);
  317. lv_font_t* font = lv_font_load(fontname);
  318. if (font == NULL) {
  319. return 0;
  320. }
  321. lua_pushlightuserdata(L, font);
  322. return 1;
  323. }
  324. #endif
  325. return l_fonts_u8g2_load(L);
  326. }
  327. #include "rotable2.h"
  328. static const rotable_Reg_t reg_fonts[] =
  329. {
  330. { "get" , ROREG_FUNC(l_fonts_get)},
  331. { "list" , ROREG_FUNC(l_fonts_list)},
  332. { "load" , ROREG_FUNC(l_fonts_load)},
  333. { NULL, ROREG_INT(0)},
  334. };
  335. LUAMOD_API int luaopen_fonts( lua_State *L ) {
  336. luat_newlib2(L, reg_fonts);
  337. return 1;
  338. }