/* * fontLibrary.c * * Created on: Feb 9, 2022 * Author: Brian.Bailey */ #include #include #include "fontLibrary.h" #include "translate.h" #include "lcd.h" #include "System/system.h" //UTF8 Decode // Copyright (c) 2008-2009 Bjoern Hoehrmann // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. #define UTF8_ACCEPT 0 #define UTF8_REJECT 1 static const uint8_t utf8d[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 }; uint32_t FL_Decode(uint32_t* state, uint32_t* codep, uint32_t byte) //removed inline to make compiler happy { uint32_t type = utf8d[byte]; *codep = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte); *state = utf8d[256 + *state*16 + type]; return *state; } /** * Get information about first codepoint in a UTF8-encoded string * * \param str UTF8-encoded string * \param codepoint Font to draw string in * \param charCount number of characters in the codepoint * \return UTF8_ACCEPT if valid, UTF8_REJECT otherwise */ uint32_t FL_GetCodepointInfo(const char * str, uint32_t * codepoint, uint32_t * charCount) { uint32_t state = 0; uint32_t count = 0; //character count for(; *str; ++str) { count++; if(!FL_Decode(&state, codepoint, *str)) { //found the codepoint *charCount = count; return state; } } } uint32_t FL_GetFontHeight(const BFC_FONT * font) { return font->FontHeight; } // void FL_DrawTranslatedString(const char *str, int16_t x, int16_t y, const BFC_FONT *pFont, LCD_DRAWMODE_t drawMode, FL_ALIGN align) { if(SYS_GetLanguage() < LANG_CHINESE) //Use normal fonts if language NOT Chinese or Korean { FL_DrawString(Translate(str), x, y, pFont, drawMode, align); } else //Chinese or Korean - Use simsun font { //if translate returns different pointer, the translation was not found. char * strTranslated = 0; strTranslated = (char *)Translate(str); if(strTranslated == str) { //Translation string not found. Use English (So we can see the problem!) FL_DrawString(Translate(str), x, y, pFont, drawMode, align); } else { //Translation successful FL_DrawString(Translate(str), x, y, fontSimsun, drawMode, align); } } //FL_DrawString(Translate(str), x, y, pFont, drawMode, align); } //Draw a null terminated UTF8 encoded string void FL_DrawString(const char *str, int16_t x, int16_t y, const BFC_FONT *pFont, LCD_DRAWMODE_t drawMode, FL_ALIGN align) { switch(align) { case FL_ALIGN_LEFT: break; case FL_ALIGN_CENTER: x -= (FL_GetStringLengthInPixels(str, pFont)) >> 1; break; case FL_ALIGN_RIGHT: x -= FL_GetStringLengthInPixels(str, pFont); break; default: break; } uint32_t error = 0; uint32_t index = 0; while(str[index] != '\0' && !error) { uint32_t codepoint; //UTF8 code uint32_t charCount; //number of chars in the current codepoint if(FL_GetCodepointInfo(&str[index], &codepoint, &charCount)) { codepoint = 0x000A; //not valid UTF8 codepoint so return a distinctive char charCount = 1; //assume 1 byte consumed. It might be wrong but we won't skip any bytes } index += charCount; //Advance index by number of chars consumed from string x += FL_DrawChar(codepoint, x, y, pFont, drawMode); //advance x coordinate by glyph width } } /* Draw a character to the framebuffer * Encode: Unicode * Data length: 8 bits * Invert bits: No * 1 bpp * Data format: Big Endian, Row based, Row preferred, Packed */ uint32_t FL_DrawChar(uint16_t codepoint, int x0, int y0, const BFC_FONT *pFont, LCD_DRAWMODE_t drawMode) { // 1. find the character information first const BFC_CHARINFO *pCharInfo = FL_GetCharInfo(pFont, (unsigned short)codepoint); //cast for this function if( pCharInfo != 0 ) { int height = pFont->FontHeight; int width = pCharInfo->Width; int data_size = pCharInfo->DataSize; // # bytes of the data array const unsigned char *pData = pCharInfo->p.pData8; // pointer to data array int x, y; //pixel coordinates within the glyph unsigned char data; uint32_t packedDataSize = 8; //8-bit data ONLY uint32_t bitPosition = packedDataSize-1; //bit position in the byte uint32_t byteIndex = 0; unsigned char bitMask[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; // 2. draw all the pixels in this character for(y=0; yWidth; } return widthInPixels; } const BFC_CHARINFO* FL_GetCharInfo(const BFC_FONT *pFont, unsigned short ch) { const BFC_CHARINFO *pCharInfo = 0; const BFC_FONT_PROP *pProp = pFont->p.pProp; unsigned short first_char, last_char; if(pFont == 0 || pFont->p.pProp == 0) return 0; while(pProp != 0) { first_char = pProp->FirstChar; last_char = pProp->LastChar; pCharInfo = pProp->pFirstCharInfo; if( ch >= first_char && ch <= last_char ) { // the character "ch" is inside this range, // return this char info, and not search anymore. pCharInfo = pCharInfo + (ch - first_char); return pCharInfo; } else { // the character "ch" is not in this range // so search it in the next range pProp = pProp->pNextProp; } } // if the character "ch" is not rendered in this font, // we use the first character in this font as the default one. if( pCharInfo == 0 ) { pProp = pFont->p.pProp; pCharInfo = pProp->pFirstCharInfo; } return pCharInfo; }