luat_ufont.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include "luat_base.h"
  2. #include "luat_ufont.h"
  3. #define LUAT_LOG_TAG "fonts"
  4. #include "luat_log.h"
  5. extern const uint16_t luat_font_map_gb2312_data[];
  6. static int binsearch(const uint16_t *sortedSeq, int seqLength, uint16_t keyData) {
  7. int low = 0, mid, high = seqLength - 1;
  8. while (low <= high) {
  9. mid = (low + high)>>1;//右移1位等于是/2,奇数,无论奇偶,有个值就行
  10. if (keyData < sortedSeq[mid]) {
  11. high = mid - 1;//是mid-1,因为mid已经比较过了
  12. }
  13. else if (keyData > sortedSeq[mid]) {
  14. low = mid + 1;
  15. }
  16. else {
  17. return mid;
  18. }
  19. }
  20. return -1;
  21. }
  22. int luat_font_get_bitmap(luat_font_header_t *font, luat_font_char_desc_t *dsc_out, uint32_t letter) {
  23. if (font == NULL) {
  24. LLOGW("font is NULL");
  25. return -1;
  26. }
  27. if (dsc_out == NULL) {
  28. LLOGW("dsc_out is NULL");
  29. return -2;
  30. }
  31. // 暂时只支持内存访问模式, 就先拦截掉其他的吧
  32. //LLOGD("font search letter %04X", letter);
  33. //LLOGD("font access_mode %02X", font->access_mode);
  34. //LLOGD("font font_data_count %02X", font->font_data_count);
  35. if (font->access_mode != 0x01) {
  36. LLOGW("only ram access mode is supported, for now");
  37. return -3;
  38. }
  39. int data_count = font->font_data_count;
  40. luat_font_data_t* font_data = ((luat_font_desc_t*)font)->datas;
  41. // 准备2个指针数组, 把map和bitmap的位置先指出来
  42. // uint8_t *map_ptr[4] = {0};
  43. // uint8_t *bitmap_ptr = NULL;
  44. // size_t map_data_count = 0;
  45. // for (size_t i = 0; i < data_count; i++)
  46. // {
  47. // if (font_data->map_type == 0x0001) {
  48. // // 仅map_type == 1 时自带映射数据
  49. // map_data_count += font_data->unicode_size * font_data->count;
  50. // }
  51. // }
  52. // bitmap_ptr = ((uint8_t*)font + sizeof(luat_font_header_t) + sizeof(luat_font_data_t) * data_count + map_data_count);
  53. // 根据unicode的范围, 看看letter在哪个
  54. int map_offset = 0;
  55. for (size_t i = 0; i < data_count; i++)
  56. {
  57. // 暂时只支持2字节的unicode map
  58. //LLOGD("font_data->unicode_min %04X", font_data->unicode_min);
  59. //LLOGD("font_data->unicode_max %04X", font_data->unicode_max);
  60. //LLOGD("font_data->map_type %04X", font_data->map_type);
  61. if (font_data->unicode_min <= letter && font_data->unicode_max >= letter) {
  62. // 范围以内, 开始找索引值
  63. if (font_data->map_type == 0x01) {
  64. LLOGD("map_type 0x01 not support yet");
  65. return -12;
  66. }
  67. // 英文字符
  68. else if (font_data->map_type == 0x02) {
  69. // letter必然在 32 ~ 127 之间, 直接索引到点阵数据就行
  70. //dsc_out->data = bitmap_ptr + (font_data->bitmap_size * (letter - 32));
  71. dsc_out->len = font_data->bitmap_size;
  72. dsc_out->char_w = font_data->char_w_bit;
  73. dsc_out->data = font_data->bitmap_data + (font_data->bitmap_size * (letter - 32));
  74. return 0;
  75. }
  76. else if (font_data->map_type == 0x03) {
  77. map_offset = binsearch(luat_font_map_gb2312_data, font_data->count, (uint16_t)letter);
  78. if (map_offset < 0) {
  79. LLOGD("font map-data NOT match %04X", letter);
  80. return -11;
  81. }
  82. // else {
  83. // LLOGD("font gb2312 %04X %04X", letter, map_offset);
  84. // }
  85. dsc_out->len = font_data->bitmap_size;
  86. dsc_out->char_w = font_data->char_w_bit;
  87. dsc_out->data = font_data->bitmap_data + (map_offset * ((font->line_height * font->line_height + 7) / 8));
  88. return 0;
  89. }
  90. else {
  91. LLOGD("map_type 0x%02X not support yet", font_data->map_type);
  92. return -33;
  93. }
  94. }
  95. // bitmap_ptr += font_data->count * font_data->bitmap_size;
  96. font_data ++;
  97. }
  98. //LLOGW("not such unicode in font %p %04X", font, letter);
  99. // 找不到
  100. return -32;
  101. }
  102. uint16_t luat_utf8_next(uint8_t b, uint8_t *utf8_state, uint16_t *encoding)
  103. {
  104. if ( b == 0 ) /* '\n' terminates the string to support the string list procedures */
  105. return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
  106. if ( *utf8_state == 0 )
  107. {
  108. if ( b >= 0xfc ) /* 6 byte sequence */
  109. {
  110. *utf8_state = 5;
  111. b &= 1;
  112. }
  113. else if ( b >= 0xf8 )
  114. {
  115. *utf8_state = 4;
  116. b &= 3;
  117. }
  118. else if ( b >= 0xf0 )
  119. {
  120. *utf8_state = 3;
  121. b &= 7;
  122. }
  123. else if ( b >= 0xe0 )
  124. {
  125. *utf8_state = 2;
  126. b &= 15;
  127. }
  128. else if ( b >= 0xc0 )
  129. {
  130. *utf8_state = 1;
  131. b &= 0x01f;
  132. }
  133. else
  134. {
  135. /* do nothing, just use the value as encoding */
  136. return b;
  137. }
  138. *encoding = b;
  139. return 0x0fffe;
  140. }
  141. else
  142. {
  143. *utf8_state = *utf8_state - 1;
  144. /* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
  145. *encoding= (*encoding) << 6;
  146. b &= 0x03f;
  147. *encoding = (*encoding) | b;
  148. if ( *utf8_state != 0 )
  149. return 0x0fffe; /* nothing to do yet */
  150. }
  151. return *encoding;
  152. }
  153. int luat_ufont_drawUTF8(ui_draw_str_ctx_t* ctx) {
  154. size_t sz = 0;
  155. uint32_t letter = 0;
  156. uint32_t str_offset;
  157. int ret = 0;
  158. uint16_t draw_offset = 0;
  159. char bitmap_buff[512] = {0}; // 不会真的有人用64以上的字号吧?
  160. int draw_x = 0;
  161. int draw_y = 0;
  162. // luat_font_char_desc_t desc = {0};
  163. lv_font_glyph_dsc_t dsc = {
  164. .data = bitmap_buff
  165. };
  166. // 左上角坐标x,y
  167. int x = ctx->x;
  168. int y = ctx->y;
  169. // 待绘制的字符串
  170. const char* data = (const char*)ctx->utf8_letters;
  171. sz = strlen(data);
  172. // 字体指针
  173. lv_font_t* lfont = ctx->font;
  174. if (lfont == NULL) {
  175. LLOGW("draw without font?!");
  176. return 0;
  177. }
  178. // 是否填充背景
  179. bool draw_bg = ctx->draw_mode == 0 ? false : true;
  180. // 没内容, 不需要画了
  181. if (sz == 0) {
  182. // 直接返回原坐标
  183. LLOGD("emtry str");
  184. return 0;
  185. }
  186. // 超边界了没? 超了就没必要绘制了
  187. if (ctx->ui_h < y || ctx->ui_w < x) {
  188. //LLOGD("draw y %d h % font->line_height %d", y, default_conf->h, font->line_height);
  189. // 直接返回原坐标
  190. return 0;
  191. }
  192. int offset = 0;
  193. uint8_t *data_ptr = data;
  194. uint8_t utf8_state = 0;
  195. uint16_t utf8_tmp = 0;
  196. uint16_t utf8_out = 0;
  197. uint16_t color = (uint16_t)ctx->front_color;
  198. uint8_t is_mark = 0;
  199. for (size_t i = 0; i < sz; i++)
  200. {
  201. utf8_out = luat_utf8_next(data[i], &utf8_state, &utf8_tmp);
  202. if (utf8_out == 0x0ffff)
  203. break; // 结束了
  204. if (utf8_out == 0x0fffe)
  205. continue; // 没读完一个字符,继续下一个循环
  206. letter = (uint32_t)utf8_out;
  207. dsc.data_ready = 0;
  208. //LLOGD("draw letter %04X", letter);
  209. if (!luat_fonts_lvgl_get_glyph_dsc(lfont, &dsc, letter, 0)) {
  210. LLOGD("not such char in font %04X", letter);
  211. //draw_offset += font->line_height / 2; // 找不到字符, 默认跳过半个字
  212. continue;
  213. }
  214. if (dsc.data_ready == 0) {
  215. LLOGW("dsc.data_ready NOT support for this font?!");
  216. continue;
  217. }
  218. if (dsc.box_w > 64) {
  219. LLOGW("font size too big %d", dsc.box_w);
  220. continue;
  221. }
  222. draw_x = x + draw_offset;
  223. draw_offset += dsc.box_w;
  224. offset = 0;
  225. for (size_t j = 0; j < dsc.box_h; j++){
  226. for (size_t k = 0; k < dsc.box_w; k++) {
  227. is_mark = (dsc.data[offset / 8] >> (7 - (offset % 8))) & 0x01;
  228. ctx->opts.draw_point(ctx->userdata, draw_x+k, y+j, is_mark ? ctx->front_color : ctx->bg_color);
  229. offset ++;
  230. }
  231. }
  232. }
  233. //ctx->opts.draw_flush(ctx->userdata);
  234. return 0;
  235. }