| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #include "luat_base.h"
- #include "luat_ufont.h"
- #define LUAT_LOG_TAG "fonts"
- #include "luat_log.h"
- extern const uint16_t luat_font_map_gb2312_data[];
- static int binsearch(const uint16_t *sortedSeq, int seqLength, uint16_t keyData) {
- int low = 0, mid, high = seqLength - 1;
- while (low <= high) {
- mid = (low + high)>>1;//右移1位等于是/2,奇数,无论奇偶,有个值就行
- if (keyData < sortedSeq[mid]) {
- high = mid - 1;//是mid-1,因为mid已经比较过了
- }
- else if (keyData > sortedSeq[mid]) {
- low = mid + 1;
- }
- else {
- return mid;
- }
- }
- return -1;
- }
- int luat_font_get_bitmap(luat_font_header_t *font, luat_font_char_desc_t *dsc_out, uint32_t letter) {
- if (font == NULL) {
- LLOGW("font is NULL");
- return -1;
- }
- if (dsc_out == NULL) {
- LLOGW("dsc_out is NULL");
- return -2;
- }
-
- // 暂时只支持内存访问模式, 就先拦截掉其他的吧
- //LLOGD("font search letter %04X", letter);
- //LLOGD("font access_mode %02X", font->access_mode);
- //LLOGD("font font_data_count %02X", font->font_data_count);
- if (font->access_mode != 0x01) {
- LLOGW("only ram access mode is supported, for now");
- return -3;
- }
- int data_count = font->font_data_count;
- luat_font_data_t* font_data = ((luat_font_desc_t*)font)->datas;
- // 准备2个指针数组, 把map和bitmap的位置先指出来
- // uint8_t *map_ptr[4] = {0};
- // uint8_t *bitmap_ptr = NULL;
- // size_t map_data_count = 0;
- // for (size_t i = 0; i < data_count; i++)
- // {
- // if (font_data->map_type == 0x0001) {
- // // 仅map_type == 1 时自带映射数据
- // map_data_count += font_data->unicode_size * font_data->count;
- // }
- // }
- // bitmap_ptr = ((uint8_t*)font + sizeof(luat_font_header_t) + sizeof(luat_font_data_t) * data_count + map_data_count);
- // 根据unicode的范围, 看看letter在哪个
- int map_offset = 0;
- for (size_t i = 0; i < data_count; i++)
- {
- // 暂时只支持2字节的unicode map
- //LLOGD("font_data->unicode_min %04X", font_data->unicode_min);
- //LLOGD("font_data->unicode_max %04X", font_data->unicode_max);
- //LLOGD("font_data->map_type %04X", font_data->map_type);
- if (font_data->unicode_min <= letter && font_data->unicode_max >= letter) {
- // 范围以内, 开始找索引值
- if (font_data->map_type == 0x01) {
- LLOGD("map_type 0x01 not support yet");
- return -12;
- }
- // 英文字符
- else if (font_data->map_type == 0x02) {
- // letter必然在 32 ~ 127 之间, 直接索引到点阵数据就行
- //dsc_out->data = bitmap_ptr + (font_data->bitmap_size * (letter - 32));
- dsc_out->len = font_data->bitmap_size;
- dsc_out->char_w = font_data->char_w_bit;
- dsc_out->data = font_data->bitmap_data + (font_data->bitmap_size * (letter - 32));
- return 0;
- }
- else if (font_data->map_type == 0x03) {
- map_offset = binsearch(luat_font_map_gb2312_data, font_data->count, (uint16_t)letter);
- if (map_offset < 0) {
- LLOGD("font map-data NOT match %04X", letter);
- return -11;
- }
- // else {
- // LLOGD("font gb2312 %04X %04X", letter, map_offset);
- // }
- dsc_out->len = font_data->bitmap_size;
- dsc_out->char_w = font_data->char_w_bit;
- dsc_out->data = font_data->bitmap_data + (map_offset * ((font->line_height * font->line_height + 7) / 8));
- return 0;
- }
- else {
- LLOGD("map_type 0x%02X not support yet", font_data->map_type);
- return -33;
- }
- }
- // bitmap_ptr += font_data->count * font_data->bitmap_size;
- font_data ++;
- }
- //LLOGW("not such unicode in font %p %04X", font, letter);
- // 找不到
- return -32;
- }
- uint16_t luat_utf8_next(uint8_t b, uint8_t *utf8_state, uint16_t *encoding)
- {
- if ( b == 0 ) /* '\n' terminates the string to support the string list procedures */
- return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
- if ( *utf8_state == 0 )
- {
- if ( b >= 0xfc ) /* 6 byte sequence */
- {
- *utf8_state = 5;
- b &= 1;
- }
- else if ( b >= 0xf8 )
- {
- *utf8_state = 4;
- b &= 3;
- }
- else if ( b >= 0xf0 )
- {
- *utf8_state = 3;
- b &= 7;
- }
- else if ( b >= 0xe0 )
- {
- *utf8_state = 2;
- b &= 15;
- }
- else if ( b >= 0xc0 )
- {
- *utf8_state = 1;
- b &= 0x01f;
- }
- else
- {
- /* do nothing, just use the value as encoding */
- return b;
- }
- *encoding = b;
- return 0x0fffe;
- }
- else
- {
- *utf8_state = *utf8_state - 1;
- /* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
- *encoding= (*encoding) << 6;
- b &= 0x03f;
- *encoding = (*encoding) | b;
- if ( *utf8_state != 0 )
- return 0x0fffe; /* nothing to do yet */
- }
- return *encoding;
- }
- int luat_ufont_drawUTF8(ui_draw_str_ctx_t* ctx) {
- size_t sz = 0;
- uint32_t letter = 0;
- uint32_t str_offset;
- int ret = 0;
- uint16_t draw_offset = 0;
- char bitmap_buff[512] = {0}; // 不会真的有人用64以上的字号吧?
- int draw_x = 0;
- int draw_y = 0;
- // luat_font_char_desc_t desc = {0};
- lv_font_glyph_dsc_t dsc = {
- .data = bitmap_buff
- };
- // 左上角坐标x,y
- int x = ctx->x;
- int y = ctx->y;
- // 待绘制的字符串
- const char* data = (const char*)ctx->utf8_letters;
- sz = strlen(data);
- // 字体指针
- lv_font_t* lfont = ctx->font;
- if (lfont == NULL) {
- LLOGW("draw without font?!");
- return 0;
- }
- // 是否填充背景
- bool draw_bg = ctx->draw_mode == 0 ? false : true;
- // 没内容, 不需要画了
- if (sz == 0) {
- // 直接返回原坐标
- LLOGD("emtry str");
- return 0;
- }
- // 超边界了没? 超了就没必要绘制了
- if (ctx->ui_h < y || ctx->ui_w < x) {
- //LLOGD("draw y %d h % font->line_height %d", y, default_conf->h, font->line_height);
- // 直接返回原坐标
- return 0;
- }
- int offset = 0;
- uint8_t *data_ptr = data;
- uint8_t utf8_state = 0;
- uint16_t utf8_tmp = 0;
- uint16_t utf8_out = 0;
- uint16_t color = (uint16_t)ctx->front_color;
- uint8_t is_mark = 0;
- for (size_t i = 0; i < sz; i++)
- {
- utf8_out = luat_utf8_next(data[i], &utf8_state, &utf8_tmp);
- if (utf8_out == 0x0ffff)
- break; // 结束了
- if (utf8_out == 0x0fffe)
- continue; // 没读完一个字符,继续下一个循环
- letter = (uint32_t)utf8_out;
- dsc.data_ready = 0;
- //LLOGD("draw letter %04X", letter);
- if (!luat_fonts_lvgl_get_glyph_dsc(lfont, &dsc, letter, 0)) {
- LLOGD("not such char in font %04X", letter);
- //draw_offset += font->line_height / 2; // 找不到字符, 默认跳过半个字
- continue;
- }
- if (dsc.data_ready == 0) {
- LLOGW("dsc.data_ready NOT support for this font?!");
- continue;
- }
- if (dsc.box_w > 64) {
- LLOGW("font size too big %d", dsc.box_w);
- continue;
- }
- draw_x = x + draw_offset;
- draw_offset += dsc.box_w;
- offset = 0;
- for (size_t j = 0; j < dsc.box_h; j++){
- for (size_t k = 0; k < dsc.box_w; k++) {
- is_mark = (dsc.data[offset / 8] >> (7 - (offset % 8))) & 0x01;
- ctx->opts.draw_point(ctx->userdata, draw_x+k, y+j, is_mark ? ctx->front_color : ctx->bg_color);
- offset ++;
- }
- }
- }
- //ctx->opts.draw_flush(ctx->userdata);
- return 0;
- }
|