#include "led_lyric.h" #include "res/resfile.h" #include "font/font_all.h" #include "system/timer.h" #include "board_config.h" #include "os/os_api.h" #include "ui/ui_style.h" #include "system/includes.h" #include "fm/fm_manage.h" #include "uart_update.h" #include "lyrics_api.h" #if LED_LYRICS_ENABLE typedef struct { u8 *pixelbuf; u8 width; u8 height; u8 offsetx; u16 nbytes; } FONT_CHAR_INFO; typedef struct { u8 scroll_speed; u8 center_offset; u16 scroll_offset; LRC_FONT_ROTATE rotate; LRC_FONT_FLIP flip; } FONT_LYRICS_INFO; typedef struct { u8 *str; u16 len; u16 offset; u16 sum_width; FONT_LYRICS_INFO lyrics_info; } LYRICS_UPDATE_INFO; struct lrc_font_header { u8 magic[4]; u32 version; u32 timestamp; u8 fontsize; u8 bitdepth; u8 reserved[18]; }; typedef struct { u32 width : 6; u32 height : 7; s32 top : 8; u32 size : 11; s32 left : 7; u32 addr : 25; } __attribute__((packed, aligned(1))) LRC_UnicInfo; #define Font_NumPages 1024 #define Font_PageSize (0x10000 / Font_NumPages) #define Code_Size 7 #define Colon_Size 3 typedef struct { u16 charIndex; u8 codesMask[Font_PageSize / 8]; } LRC_Font_PageEntry_t; #define IMAGE_BUF_SIZE ((LED_WIDTH * LED_HEIGHT + 7) / 8) static u8 *image_buf = NULL; //整屏点阵缓存buffer static u8 *image_buf_out = NULL; static u8 lrc_check_online_flag = 1; static u8 lrc_sleep_flag = 0; static struct lrc_font_header header = {0}; static struct font_info f_info; static FONT_CHAR_INFO char_info; static u16 font_lyrics_scroll_timer_id = 0; static LYRICS_UPDATE_INFO lrc_update_info; static OS_MUTEX mutex; static OS_MUTEX show_mutex; static struct lrc_show_status lrc_status = { .lrc_rotate = 0, .lrc_flip = 0, .lrc_scroll_speed = 100, .lrc_show_status_update_flag = 0, .lrc_record_len = 0, .lrc_record_str = NULL, }; void lyrics_show_status_set(u16 scroll_speed, u8 rotate, u8 flip) { lrc_status.lrc_scroll_speed = scroll_speed; lrc_status.lrc_rotate = rotate; lrc_status.lrc_flip = flip; lrc_status.lrc_show_status_update_flag = 1; lyrics_update_font(lrc_status.lrc_record_str, lrc_status.lrc_record_len, NULL); } static bool LRC_InitFont_Unicode(struct font_info *info) { info->pixel.file.fd = fopen(info->pixel.file.name, "r"); if (!info->pixel.file.fd) { info->sta |= FT_ERROR_NOPIXFILE; printf("unicode file not open!"); return FALSE; } fseek(info->pixel.file.fd, 0, SEEK_SET); fread(info->pixel.file.fd, &header, sizeof(struct lrc_font_header)); printf("magic : %s\n", header.magic); printf("version : 0x%x\n", header.version); printf("timestamp : %d\n", header.timestamp); printf("fontsize : %d\n", header.fontsize); printf("bitdepth : %d\n", header.bitdepth); if (memcmp(header.magic, "unic", 4)) { info->sta |= FT_ERROR_NOPIXFILE; printf("unicode magic not paired!"); return FALSE; } info->pixel.size = header.fontsize; if (header.bitdepth == 0) { info->pixel.nbytes = (info->pixel.size * info->pixel.size + 7) / 8; } else if (header.bitdepth == 1) { info->pixel.nbytes = (info->pixel.size * info->pixel.size * 2 + 7) / 8; } else if (header.bitdepth == 2) { info->pixel.nbytes = (info->pixel.size * info->pixel.size * 4 + 7) / 8; } else { // header.bitdepth == 8 info->pixel.nbytes = info->pixel.size * info->pixel.size; } return TRUE; } /* 获取字符索引 */ static int LRC_Font_GetCharIndex(struct font_info *info, u16 unicode) { LRC_Font_PageEntry_t pageEntry; u16 m = unicode / Font_PageSize; u16 n = unicode % Font_PageSize; u16 i, j; fseek(info->pixel.file.fd, sizeof(struct lrc_font_header) + m * sizeof(LRC_Font_PageEntry_t), SEEK_SET); fread(info->pixel.file.fd, &pageEntry, sizeof(LRC_Font_PageEntry_t)); if (!(pageEntry.codesMask[n / 8] & (1 << (n % 8)))) { return -1; } for (i = j = 0; i < n; i++) { if (pageEntry.codesMask[i / 8] & (1 << (i % 8))) { j++; } } i = pageEntry.charIndex + j; return i; } /* 获取字符宽度 */ static int LRC_Font_GetCharWidth(struct font_info *info, u16 unicode) { int charIndex; u16 nbytes; if ((charIndex = LRC_Font_GetCharIndex(info, unicode)) < 0) { printf("unicode : 0x%x, charIndex = %d, char index not exist!\n", unicode, charIndex); return 0; } LRC_UnicInfo codeinfo = {0}; u32 file_offset = 0; fseek(info->pixel.file.fd, sizeof(struct lrc_font_header) + Font_NumPages * \ sizeof(LRC_Font_PageEntry_t) + charIndex * sizeof(LRC_UnicInfo), SEEK_SET); fread(info->pixel.file.fd, &codeinfo, sizeof(LRC_UnicInfo)); if (unicode == 0x20) { codeinfo.width = info->pixel.size / 3; codeinfo.height = info->pixel.size / 3; } if (unicode == 0x10) { codeinfo.width = Code_Size; codeinfo.height = Code_Size; memset(info->pixel.pixelbuf, 0, (codeinfo.width * codeinfo.height + 7) / 8); } if (unicode == 0x11) { codeinfo.width = Colon_Size; codeinfo.height = Colon_Size; memset(info->pixel.pixelbuf, 0, (codeinfo.width * codeinfo.height + 7) / 8); } u8 width = codeinfo.width; char_info.width = codeinfo.width; char_info.height = codeinfo.height; return width; } /* 获取字符位图数据 */ static int LRC_Font_GetCharBits(struct font_info *info, u16 unicode) { int charIndex; u16 nbytes, width; if ((charIndex = LRC_Font_GetCharIndex(info, unicode)) < 0) { printf("unicode : 0x%x, charIndex = %d, char index not exist!\n", unicode, charIndex); return 0; } LRC_UnicInfo codeinfo = {0}; fseek(info->pixel.file.fd, sizeof(struct lrc_font_header) + Font_NumPages * \ sizeof(LRC_Font_PageEntry_t) + charIndex * sizeof(LRC_UnicInfo), SEEK_SET); fread(info->pixel.file.fd, &codeinfo, sizeof(LRC_UnicInfo)); const u8 bit[] = {1, 2, 4, 8}; nbytes = (codeinfo.width * codeinfo.height * bit[header.bitdepth] + 7) / 8; if (info->pixel.pixelbuf != NULL) { if (nbytes > info->pixel.nbytes) { puts("error:pixelbuf overlay!\n"); printf("info.width = %d, info->ascpixel.size = %d, nbytes = %d\n", width, info->pixel.size, nbytes); free(info->pixel.pixelbuf); info->pixel.pixelbuf = (u8 *)malloc(nbytes); info->pixel.nbytes = nbytes; char_info.pixelbuf = info->pixel.pixelbuf; char_info.nbytes = info->pixel.nbytes; } fseek(info->pixel.file.fd, codeinfo.addr, SEEK_SET); fread(info->pixel.file.fd, info->pixel.pixelbuf, nbytes); } if (unicode == 0x20) { codeinfo.width = info->pixel.size / 3; codeinfo.height = info->pixel.size / 3; } if (unicode == 0x10) { codeinfo.width = Code_Size; codeinfo.height = Code_Size; memset(info->pixel.pixelbuf, 0, (codeinfo.width * codeinfo.height + 7) / 8); } if (unicode == 0x11) { codeinfo.width = Colon_Size; codeinfo.height = Colon_Size; memset(info->pixel.pixelbuf, 0, (codeinfo.width * codeinfo.height + 7) / 8); } width = codeinfo.width; char_info.width = codeinfo.width; char_info.height = codeinfo.height; char_info.pixelbuf = info->pixel.pixelbuf; return width; } bool lyrics_font_init(char *file_name) { bool ret; if (f_info.pixel.file.fd == NULL) { f_info.pixel.file.name = file_name; f_info.bigendian = 0; ret = LRC_InitFont_Unicode(&f_info); if (ret == FALSE) { return FALSE; } f_info.pixel.pixelbuf = (u8 *)malloc(f_info.pixel.nbytes); char_info.pixelbuf = f_info.pixel.pixelbuf; char_info.nbytes = f_info.pixel.nbytes; image_buf = (u8 *)malloc(IMAGE_BUF_SIZE); image_buf_out = (u8 *)malloc(IMAGE_BUF_SIZE); os_mutex_create(&mutex); os_mutex_create(&show_mutex); } return TRUE; } void lyrics_font_release() { if (f_info.pixel.file.fd) { fclose(f_info.pixel.file.fd); f_info.pixel.file.fd = NULL; } if (f_info.pixel.pixelbuf) { free(f_info.pixel.pixelbuf); f_info.pixel.pixelbuf = NULL; } if (font_lyrics_scroll_timer_id) { sys_timer_del(font_lyrics_scroll_timer_id); font_lyrics_scroll_timer_id = 0; } if (lrc_update_info.str) { free(lrc_update_info.str); lrc_update_info.str = NULL; } if (image_buf) { free(image_buf); image_buf = NULL; } if (image_buf_out) { free(image_buf_out); image_buf_out = NULL; } } static void Font_CharBit_to_Image(FONT_CHAR_INFO *info, u8 *image, u8 x, u8 y) { u8 image_width = LED_WIDTH; u8 char_width = info->width; u8 char_height = info->height; u8 *char_buf = info->pixelbuf; u8 char_byte_idx, char_bit_idx; u8 image_byte_idx, image_bit_idx; u8 inc_ofs = info->offsetx; for (u16 i = 0; i < char_height; i++) { for (u16 j = 0; j < char_width; j++) { if (x + j >= LED_WIDTH) { break; } if (j + inc_ofs >= char_width) { break; } char_byte_idx = (i * char_width + j + inc_ofs) / 8; char_bit_idx = (i * char_width + j + inc_ofs) % 8; image_byte_idx = ((i + y) * image_width + j + x) / 8; image_bit_idx = ((i + y) * image_width + j + x) % 8; image[image_byte_idx] |= (((char_buf[char_byte_idx] >> (7 - char_bit_idx)) & 0x1) << (7 - image_bit_idx)); } } } static void Font_Char_Rotate_90Reverse(FONT_CHAR_INFO *info) { u8 *in = info->pixelbuf; u8 *out = image_buf_out; u8 in_byte_idx, in_bit_idx; u8 out_byte_idx, out_bit_idx; u8 char_width = info->width; u8 char_height = info->height; memset(image_buf_out, 0, IMAGE_BUF_SIZE); for (u16 h = 0; h < char_height; h++) { for (u16 w = 0; w < char_width; w++) { in_byte_idx = (h * char_width + w) / 8; in_bit_idx = (h * char_width + w) % 8; out_byte_idx = ((char_width - 1 - w) * char_height + h) / 8; out_bit_idx = ((char_width - 1 - w) * char_height + h) % 8; out[out_byte_idx] |= (((in[in_byte_idx] >> (7 - in_bit_idx)) & 0x1) << (7 - out_bit_idx)); } } u8 tmp = info->width; info->width = info->height; info->height = tmp; memcpy(info->pixelbuf, image_buf_out, info->nbytes); } static void Font_Image_Rotate_180() { u8 *in = image_buf; u8 *out = image_buf_out; u8 in_byte_idx, in_bit_idx; u8 out_byte_idx, out_bit_idx; memset(image_buf_out, 0, IMAGE_BUF_SIZE); for (u16 h = 0; h < LED_HEIGHT; h++) { for (u16 w = 0; w < LED_WIDTH; w++) { in_byte_idx = (h * LED_WIDTH + w) / 8; in_bit_idx = (h * LED_WIDTH + w) % 8; out_byte_idx = (LED_WIDTH * LED_HEIGHT / 8) - 1 - in_byte_idx; out_bit_idx = (7 - in_bit_idx); out[out_byte_idx] |= (((in[in_byte_idx] >> (7 - in_bit_idx)) & 0x1) << (7 - out_bit_idx)); } } } static void Font_Image_Mirror_Horizontal_Flip(u8 *image) { u8 *in, *out; if (image == image_buf) { in = image_buf; out = image_buf_out; } else { in = image_buf_out; out = image_buf; } memset(out, 0, IMAGE_BUF_SIZE); u8 in_byte_idx, in_bit_idx; u8 out_byte_idx, out_bit_idx; u16 in_bit, out_bit; for (u16 h = 0; h < LED_HEIGHT; h++) { for (u16 w = 0; w < LED_WIDTH; w++) { in_bit = h * LED_WIDTH + w; out_bit = h * LED_WIDTH + (LED_WIDTH - 1 - w); in_byte_idx = in_bit / 8; in_bit_idx = in_bit % 8; out_byte_idx = out_bit / 8; out_bit_idx = out_bit % 8; out[out_byte_idx] |= (((in[in_byte_idx] >> (7 - in_bit_idx)) & 0x1) << (7 - out_bit_idx)); } } memcpy(in, out, IMAGE_BUF_SIZE); } static void Font_Image_Mirror_Vertical_Flip(u8 *image) { u8 *in, *out; if (image == image_buf) { in = image_buf; out = image_buf_out; } else { in = image_buf_out; out = image_buf; } memset(out, 0, IMAGE_BUF_SIZE); u8 in_byte_idx, in_bit_idx; u8 out_byte_idx, out_bit_idx; u16 in_bit, out_bit; for (u16 h = 0; h < LED_HEIGHT; h++) { for (u16 w = 0; w < LED_WIDTH; w++) { in_bit = h * LED_WIDTH + w; out_bit = (LED_HEIGHT - 1 - h) * LED_WIDTH + w; in_byte_idx = in_bit / 8; in_bit_idx = in_bit % 8; out_byte_idx = out_bit / 8; out_bit_idx = out_bit % 8; out[out_byte_idx] |= (((in[in_byte_idx] >> (7 - in_bit_idx)) & 0x1) << (7 - out_bit_idx)); } } memcpy(in, out, IMAGE_BUF_SIZE); } static u16 Font_GetStringWidth(u8 *utf8_buf, u16 len, FONT_LYRICS_INFO *lyrics_info) { u16 unicode, width; u16 utf8_len = len; u16 *utf16_buf = zalloc(utf8_len * 2); u16 utf16_len = font_utf8toutf16(&f_info, utf8_buf, utf8_len, utf16_buf); u16 unic_num = utf16_len / 2; u16 sum_width = 0; for (u16 n = 0; n < unic_num; n++) { unicode = utf16_buf[n]; width = LRC_Font_GetCharWidth(&f_info, unicode); if (width == 0) { continue; } if (lyrics_info->rotate == LRC_FONT_ROTATE_90 || lyrics_info->rotate == LRC_FONT_ROTATE_270) { width = char_info.height; } sum_width += width; } free(utf16_buf); return sum_width; } void lrc_buf_push(u8 *buf, u16 size) { u8 *uartbuf = malloc(size + 1); #if UI_LED_LRC_DECODE_FONT uartbuf[0] = CMD_UART_UI_PIXEL_MATRIX; #else uartbuf[0] = CMD_UART_UI_STRING; #endif memcpy(uartbuf + 1, buf, size); #if MUTIL_CPU_UART_UPDATE_ENABLE if (!lrc_sleep_flag) { uart_update_tx_packet(0, uartbuf, 0, size + 1, 0); } #endif free(uartbuf); } void lrc_show_slepp_push(void) { u8 buf[1]; buf[0] = CMD_UART_SLEEP; #if MUTIL_CPU_UART_UPDATE_ENABLE if (!lrc_sleep_flag) { uart_update_tx_packet(0, buf, 0, sizeof(buf), 1); } #endif lrc_sleep_flag = 1; } void lrc_wake_up_push(void) { u8 buf[1]; buf[0] = 0XFF; #if MUTIL_CPU_UART_UPDATE_ENABLE uart_update_tx_packet(0, buf, 0, sizeof(buf), 1); #endif lrc_sleep_flag = 0; } #if (AD10X_WITHOUT_FLASH && LED_LYRICS_SH50_CHECK_ONLINE) static u8 lrc_dev_check_online() { u8 ret = 0; u8 packet = CMD_UART_CHECK_ONLINE; #if MUTIL_CPU_UART_UPDATE_ENABLE lrc_check_online_flag = 1; if (!lrc_sleep_flag) { ret = uart_update_tx_packet(CMD_UART_CHECK_ONLINE, &packet, 0, 1, 1); } #endif if (ret != 0) { if (!lrc_sleep_flag) { ret = uart_update_tx_packet(CMD_UART_CHECK_ONLINE, &packet, 0, 1, 1); } if (ret != 0) { lrc_check_online_flag = 0; sh50_isp_up_code(); } } return ret; } static u16 online_timer_id = 0; void lrc_check_online_timer_init() { if (online_timer_id == 0) { online_timer_id = sys_timer_add(NULL, lrc_dev_check_online, 3000); } } void lrc_check_online_timer_release() { if (online_timer_id) { sys_timer_del(online_timer_id); online_timer_id = 0; } } #endif void lrc_show_mode_push(LRC_SHOW_INFO *show_info) { u8 buf[5]; u8 rotate, flip, speed, brightness; if (show_info) { rotate = show_info->rotate; flip = show_info->flip; speed = show_info->scroll_speed / 50; brightness = show_info->brightness; } else { rotate = 0; flip = 0; speed = 3; brightness = 0; } buf[0] = CMD_UART_UI_CMD; buf[1] = rotate; buf[2] = flip; buf[3] = speed; buf[4] = brightness; #if MUTIL_CPU_UART_UPDATE_ENABLE if (!lrc_sleep_flag) { uart_update_tx_packet(0, buf, 0, sizeof(buf), 1); } #endif } static void Font_GetStringBits(u8 *utf8_buf, u16 len, FONT_LYRICS_INFO *lyrics_info) { u8 curr_x = lyrics_info->center_offset; u8 offset_y = 0; u16 unicode, width; u16 rec_scr_ofs = 0; u8 curr_char_offset = 0; u8 *font_ptr = image_buf; u16 sum_char_offset = lyrics_info->scroll_offset; memset(image_buf, 0, IMAGE_BUF_SIZE); u16 utf8_len = len; u16 *utf16_buf = zalloc(utf8_len * 2); u16 utf16_len = font_utf8toutf16(&f_info, utf8_buf, utf8_len, utf16_buf); u16 unic_num = utf16_len / 2; for (u16 n = 0; n < unic_num; n++) { unicode = utf16_buf[n]; width = LRC_Font_GetCharBits(&f_info, unicode); if (width == 0) { continue; } if (lyrics_info->rotate == LRC_FONT_ROTATE_0 || lyrics_info->rotate == LRC_FONT_ROTATE_180) { curr_char_offset = width; } else { curr_char_offset = char_info.height; } rec_scr_ofs += curr_char_offset; if (rec_scr_ofs < sum_char_offset) { continue; } if (curr_x == 0) { char_info.offsetx = sum_char_offset + curr_char_offset - rec_scr_ofs; } else { char_info.offsetx = 0; } if (curr_x > LED_WIDTH) { break; } if (lyrics_info->rotate == LRC_FONT_ROTATE_90 || lyrics_info->rotate == LRC_FONT_ROTATE_270) { Font_Char_Rotate_90Reverse(&char_info); } offset_y = (f_info.pixel.size - char_info.height) / 2; Font_CharBit_to_Image(&char_info, image_buf, curr_x, offset_y); curr_x += (char_info.width - char_info.offsetx); } if (lyrics_info->rotate == LRC_FONT_ROTATE_180 || lyrics_info->rotate == LRC_FONT_ROTATE_270) { Font_Image_Rotate_180(); font_ptr = image_buf_out; } if (lyrics_info->flip == LRC_FONT_HORIZONTAL_FLIP) { Font_Image_Mirror_Horizontal_Flip(font_ptr); } if (lyrics_info->flip == LRC_FONT_VERTICAL_FLIP) { Font_Image_Mirror_Vertical_Flip(font_ptr); } lrc_buf_push(font_ptr, IMAGE_BUF_SIZE); free(utf16_buf); } void lyrics_scroll_timer_del() { if (font_lyrics_scroll_timer_id) { sys_timer_del(font_lyrics_scroll_timer_id); font_lyrics_scroll_timer_id = 0; } } static u8 lyrics_scroll_flag = 1; static void lyrics_scroll_font(void *ptr) { os_mutex_pend(&show_mutex, 0); LYRICS_UPDATE_INFO *info = (LYRICS_UPDATE_INFO *)ptr; if (info->lyrics_info.scroll_offset > info->sum_width - LED_WIDTH + 3) { info->lyrics_info.scroll_offset = 0; /* 不从头滚动 */ if (info->sum_width > LED_WIDTH) { lyrics_scroll_timer_del(); os_mutex_post(&show_mutex); return; } /* 不从头滚动 */ } Font_GetStringBits((u8 *)(info->str), info->len, &(info->lyrics_info)); if (info->sum_width > LED_WIDTH && lyrics_scroll_flag) { info->lyrics_info.scroll_offset++; } os_mutex_post(&show_mutex); } void lyrics_scroll_control(u8 flag) { lyrics_scroll_flag = flag; } void lyrics_update_font(u8 *str, u16 len, LRC_SHOW_INFO *show_info) { #if UI_LED_LRC_DECODE_FONT if (f_info.pixel.file.fd == NULL) { printf("err, font file not open\n"); return; } #endif u16 str_curr_crc; static u16 str_last_crc = 0; str_curr_crc = CRC16(str, len); if (str_last_crc == str_curr_crc && lrc_status.lrc_show_status_update_flag == 0 && lrc_check_online_flag) { return; } if (len == 0) { lrc_status.lrc_show_status_update_flag = 0; return; } os_mutex_pend(&show_mutex, 0); /* 记录当前字符串内容和长度,在更新显示参数实时刷新时需要用到 */ if (lrc_status.lrc_record_str && lrc_status.lrc_show_status_update_flag == 0) { free(lrc_status.lrc_record_str); lrc_status.lrc_record_str = NULL; } if (lrc_status.lrc_record_str == NULL) { lrc_status.lrc_record_str = zalloc(len); } lrc_status.lrc_record_len = len; memcpy(lrc_status.lrc_record_str, str, len); /* 记录当前字符串内容和长度,在更新显示参数实时刷新时需要用到 */ str_last_crc = str_curr_crc; #if (UI_LED_LRC_DECODE_FONT == 0) lrc_buf_push(str, len); lrc_status.lrc_show_status_update_flag = 0; os_mutex_post(&show_mutex); return; #endif u16 scroll_speed; u8 rotate, flip; os_mutex_pend(&mutex, 0); if (show_info == NULL) { rotate = lrc_status.lrc_rotate; flip = lrc_status.lrc_flip; scroll_speed = lrc_status.lrc_scroll_speed; } else { rotate = show_info->rotate; flip = show_info->flip; scroll_speed = show_info->scroll_speed; } if (font_lyrics_scroll_timer_id) { sys_timer_del(font_lyrics_scroll_timer_id); font_lyrics_scroll_timer_id = 0; } if (lrc_update_info.str) { free(lrc_update_info.str); lrc_update_info.str = NULL; } lrc_update_info.str = malloc(len); memcpy(lrc_update_info.str, str, len); lrc_update_info.len = len; lrc_update_info.lyrics_info.scroll_offset = 0; lrc_update_info.lyrics_info.rotate = rotate; lrc_update_info.lyrics_info.flip = flip; lrc_update_info.sum_width = Font_GetStringWidth(lrc_update_info.str, len, &(lrc_update_info.lyrics_info)); lrc_update_info.lyrics_info.center_offset = (lrc_update_info.sum_width < LED_WIDTH) ? ((LED_WIDTH - lrc_update_info.sum_width) / 2) : 0; os_mutex_post(&show_mutex); if (lrc_update_info.sum_width <= LED_WIDTH) { lyrics_scroll_font((void *)&lrc_update_info); } else { if (font_lyrics_scroll_timer_id == 0) { font_lyrics_scroll_timer_id = sys_timer_add((void *)&lrc_update_info, lyrics_scroll_font, scroll_speed); } } lrc_status.lrc_show_status_update_flag = 0; os_mutex_post(&mutex); } int UnicodeToUtf8(u8 *pInput, u16 in_len, u8 *pOutput) { int len = 0; //记录转换后的Utf8字符串的字节数 int unic_cnt = 0; while (unic_cnt < in_len) { //处理一个unicode字符 u8 low = *pInput;//取出unicode字符的低8位 pInput++; unic_cnt++; u8 high = *pInput;//取出unicode字符的高8位 u16 w = high << 8; u16 wchar = (high << 8) + low; //高8位和低8位组成一个unicode字符,加法运算级别高 if (wchar <= 0x7F) { //英文字符 pOutput[len] = (char)wchar; //取wchar的低8位 len++; } else if (wchar >= 0x80 && wchar <= 0x7FF) { //可以转换成双字节pOutput字符 pOutput[len] = 0xc0 | ((wchar >> 6) & 0x1f); //取出unicode编码低6位后的5位,填充到110yyyyy 10zzzzzz 的yyyyy中 len++; pOutput[len] = 0x80 | (wchar & 0x3f); //取出unicode编码的低6位,填充到110yyyyy 10zzzzzz 的zzzzzz中 len++; } else if (wchar >= 0x800 && wchar < 0xFFFF) { //可以转换成3个字节的pOutput字符 pOutput[len] = 0xe0 | ((wchar >> 12) & 0x0f); //高四位填入1110xxxx 10yyyyyy 10zzzzzz中的xxxx len++; pOutput[len] = 0x80 | ((wchar >> 6) & 0x3f); //中间6位填入1110xxxx 10yyyyyy 10zzzzzz中的yyyyyy len++; pOutput[len] = 0x80 | (wchar & 0x3f); //低6位填入1110xxxx 10yyyyyy 10zzzzzz中的zzzzzz len++; } else { //对于其他字节数的unicode字符不进行处理 return -1; } pInput ++;//处理下一个unicode字符 unic_cnt++; } //utf8字符串后面,有个\0 pOutput [len] = 0; return len; } void lyrics_update_unicbuf(u8 *unic, u16 len) { if (len == 0 || unic == NULL) { return; } u8 *utf8 = (u8 *)zalloc(len * 2); int utf8_len = UnicodeToUtf8(unic, len, utf8); lyrics_update_font(utf8, utf8_len, NULL); free(utf8); } void lyrics_update_gbk_to_utf8(u8 *gbk, u16 len) { if (len == 0 || gbk == NULL) { return; } u8 *utf8 = (u8 *)zalloc(len * 2); int utf8_len = gbk_2_utf8(gbk, len, utf8, len * 2); lyrics_update_font(utf8, utf8_len, NULL); free(utf8); } #endif