Initial fontawesome support

This commit is contained in:
fvanroie 2020-01-26 16:44:49 +01:00
parent 167f45e630
commit 0bb5e7a3c8
2 changed files with 206 additions and 82 deletions

View File

@ -66,16 +66,14 @@ static bool lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_gly
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
// static uint8_t * charBitmap_p[32 * 32]; uint32_t charInBuffer = 0; // Last Character ID in the Bitmap Buffer
uint32_t charInBuffer = 0;
// uint8_t filecharBitmap_p[20 * 1024]; // uint8_t filecharBitmap_p[20 * 1024];
static lv_zifont_char_t lastCharInfo; // Holds the last Glyph DSC
#if ESP32 #if ESP32
// uint8_t charBitmap_p[32 * 32]; static lv_zifont_char_t charCache[256 - 32]; // glyphID DSC cache
static lv_zifont_char_t charCache[256 - 32];
#else #else
// uint8_t charBitmap_p[32 * 32]; static lv_zifont_char_t charCache[256 - 32]; // glyphID DSC cache
static lv_zifont_char_t charCache[256 - 32];
#endif #endif
static uint8_t * charBitmap_p; static uint8_t * charBitmap_p;
@ -106,6 +104,12 @@ int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size)
if(dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY; if(dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY;
int error = 0; int error = 0;
/* Initialize Last Glyph DSC */
dsc->last_glyph_dsc = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t));
if(dsc->last_glyph_dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY;
dsc->last_glyph_dsc->width = 0;
dsc->last_glyph_id = 0;
/* Open the font for reading */ /* Open the font for reading */
File file = SPIFFS.open(font_path, "r"); File file = SPIFFS.open(font_path, "r");
if(!file) { if(!file) {
@ -165,6 +169,10 @@ int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size)
dsc->Totaldatalength, dsc->Startdataaddress, dsc->CodeT0, dsc->CodeDec); dsc->Totaldatalength, dsc->Startdataaddress, dsc->CodeT0, dsc->CodeDec);
Serial.printf(msg);*/ Serial.printf(msg);*/
/* Init Glyph Cache */
dsc->last_glyph_dsc = NULL;
dsc->last_glyph_id = 0;
font->get_glyph_dsc = lv_font_get_glyph_dsc_fmt_zifont; /*Function pointer to get glyph's data*/ font->get_glyph_dsc = lv_font_get_glyph_dsc_fmt_zifont; /*Function pointer to get glyph's data*/
font->get_glyph_bitmap = lv_font_get_bitmap_fmt_zifont; /*Function pointer to get glyph's bitmap*/ font->get_glyph_bitmap = lv_font_get_bitmap_fmt_zifont; /*Function pointer to get glyph's bitmap*/
font->line_height = dsc->CharHeight; /*The maximum line height required by the font*/ font->line_height = dsc->CharHeight; /*The maximum line height required by the font*/
@ -188,47 +196,65 @@ int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size)
*/ */
static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uint32_t unicode_letter) static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uint32_t unicode_letter)
{ {
// ulong startMillis = millis();
lv_font_fmt_zifont_dsc_t * fdsc = (lv_font_fmt_zifont_dsc_t *)font->dsc; /* header data struct */ lv_font_fmt_zifont_dsc_t * fdsc = (lv_font_fmt_zifont_dsc_t *)font->dsc; /* header data struct */
int error = 0; int error = 0;
uint32_t charNum = unicode_letter - 0x20; // simple unicode to ascii - space is charNum=0 uint32_t glyphID;
/* Bitmap still in buffer */
if(charInBuffer == unicode_letter && charBitmap_p) { if(charInBuffer == unicode_letter && charBitmap_p) {
Serial.printf("CacheLetter %c\n", (char)(uint8_t)unicode_letter); Serial.printf("CacheLetter %c\n", (char)(uint8_t)unicode_letter);
return charBitmap_p; return charBitmap_p;
} }
/* Open the font for reading */ File file;
File file = SPIFFS.open((char *)font->user_data, "r"); uint16_t charmap_position;
if(unicode_letter >= 0xF000) {
file = SPIFFS.open("/fontawesome24.zi", "r");
charmap_position = 25 + sizeof(lv_font_fmt_zifont_dsc_t);
glyphID = unicode_letter - 0xf000; // start of fontawesome
} else {
file = SPIFFS.open((char *)font->user_data, "r");
charmap_position = fdsc->Descriptionlength + sizeof(lv_font_fmt_zifont_dsc_t);
glyphID = unicode_letter - 0x20; // simple unicode to ascii - space is charNum=0
}
if(!file) { if(!file) {
debugPrintln(PSTR("FONT: [ERROR] while opening font:")); debugPrintln(PSTR("FONT: [ERROR] while opening font:"));
debugPrintln((char *)font->user_data); debugPrintln((char *)font->user_data);
return NULL; return NULL;
} }
/* Read Character Table */ lv_zifont_char_t * charInfo;
lv_zifont_char_t * charInfo = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t)); /* Check Last Glyph in chache is valid and Matches currentGlyphID */
file.seek(charNum * 10 + fdsc->Descriptionlength + 0x2C, SeekSet); if(fdsc->last_glyph_id == glyphID && fdsc->last_glyph_dsc && fdsc->last_glyph_dsc->width > 0) {
size_t readSize = file.readBytes((char *)charInfo, sizeof(lv_zifont_char_t)); Serial.print("@");
charInfo = fdsc->last_glyph_dsc;
} else {
Serial.print("-");
/* Read Character Table */
charInfo = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t));
uint32_t char_position = glyphID * sizeof(lv_zifont_char_t) + charmap_position;
file.seek(char_position, SeekSet);
size_t readSize = file.readBytes((char *)charInfo, sizeof(lv_zifont_char_t));
/* Check that we read the correct size */ /* Check that we read the correct size */
if(readSize != sizeof(lv_zifont_char_t)) { if(readSize != sizeof(lv_zifont_char_t)) {
file.close(); file.close();
lv_mem_free(charInfo); lv_mem_free(charInfo);
debugPrintln(PSTR("FONT: [ERROR] Wrong number of bytes read from flash")); debugPrintln(PSTR("FONT: [ERROR] Wrong number of bytes read from flash"));
return NULL; return NULL;
}
/* Double-check that we got the correct letter */
if(charInfo->character != unicode_letter) {
// file.close();
// lv_mem_free(charInfo);
// debugPrintln(PSTR("FONT: [ERROR] Incorrect letter read from flash"));
// return NULL;
}
} }
/* Double-check that we got the correct letter */ long datapos = charmap_position + (charInfo->pos[2] << 16) + (charInfo->pos[1] << 8) + charInfo->pos[0];
if(charInfo->character != unicode_letter) {
file.close();
lv_mem_free(charInfo);
debugPrintln(PSTR("FONT: [ERROR] Incorrect letter read from flash"));
return NULL;
}
long datapos =
fdsc->Descriptionlength + 0x2C + (charInfo->pos[2] << 16) + (charInfo->pos[1] << 8) + charInfo->pos[0];
/* Allocate & Initialize Buffer for 4bpp */ /* Allocate & Initialize Buffer for 4bpp */
uint32_t size = (charInfo->width * fdsc->CharHeight + 1) / 2; // add 1 for rounding up uint32_t size = (charInfo->width * fdsc->CharHeight + 1) / 2; // add 1 for rounding up
@ -236,16 +262,20 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
charBitmap_p = (uint8_t *)lv_mem_alloc(size); charBitmap_p = (uint8_t *)lv_mem_alloc(size);
memset(charBitmap_p, 0, size); // init the bitmap to white memset(charBitmap_p, 0, size); // init the bitmap to white
char ch[10]; char ch[1];
file.seek(datapos, SeekSet); file.seek(datapos, SeekSet);
// Serial.printf("Data start position :%d = %d\n", datapos, ftell(file));
file.readBytes(ch, 1); /* check first byte = bpp */ file.readBytes(ch, 1); /* check first byte = bpp */
uint8_t b = ch[0];
if(b != 3) { if(ch[0] != 3) {
file.close(); file.close();
lv_mem_free(charInfo); lv_mem_free(charInfo);
debugPrintln(PSTR("FONT: [ERROR] Character is not 3bpp encoded")); debugPrintln(PSTR("FONT: [ERROR] Character is not 3bpp encoded"));
// Serial.printf(" adv_w %u (%u) - bpp %u - ", dsc_out->adv_w, charInfo->width, dsc_out->bpp);
// Serial.printf(" box_w %u - box_h %u - ", dsc_out->box_w, dsc_out->box_h);
// Serial.printf(" kernL %u - kernR %u \n", charInfo->kerningL, charInfo->kerningR);
// Serial.printf(" ofs_x %u - ofs_y %u \n\n", dsc_out->ofs_x, dsc_out->ofs_x);
return NULL; return NULL;
} }
@ -254,9 +284,10 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
uint16_t fileindex = 0; uint16_t fileindex = 0;
char data[256]; char data[256];
int len; int len = 1;
while((fileindex < charInfo->length)) { //} && !feof(file)) { // while((fileindex < charInfo->length) && len > 0) { //} && !feof(file)) {
while(arrindex < size && len > 0) { // read untill the bitmap is full, no need for datalength
if(sizeof(data) < charInfo->length - fileindex) { if(sizeof(data) < charInfo->length - fileindex) {
len = file.readBytes(data, sizeof(data)); len = file.readBytes(data, sizeof(data));
} else { } else {
@ -271,9 +302,6 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
uint8_t repeats = b & 0b00011111; /* last 5 bits indicate repetition as the same color */ uint8_t repeats = b & 0b00011111; /* last 5 bits indicate repetition as the same color */
switch((uint8_t)b >> 5) { switch((uint8_t)b >> 5) {
case(0b000): case(0b000):
// for(int i = 0; i < repeats; i++) {
// arrindex += colorsAdd(charBitmap_p, ColorWhite, w, arrindex);
// }
arrindex += repeats; arrindex += repeats;
break; break;
@ -284,17 +312,11 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
break; break;
case(0b010): case(0b010):
// for(int i = 0; i < repeats; i++) {
// arrindex += colorsAdd(charBitmap_p, ColorWhite, w, arrindex);
// }
arrindex += repeats; arrindex += repeats;
arrindex += colorsAdd(charBitmap_p, ColorBlack, w, arrindex); arrindex += colorsAdd(charBitmap_p, ColorBlack, w, arrindex);
break; break;
case(0b011): case(0b011):
// for(int i = 0; i < repeats; i++) {
// arrindex += colorsAdd(charBitmap_p, ColorWhite, w, arrindex);
// }
arrindex += repeats; arrindex += repeats;
arrindex += colorsAdd(charBitmap_p, ColorBlack, w, arrindex); arrindex += colorsAdd(charBitmap_p, ColorBlack, w, arrindex);
arrindex += colorsAdd(charBitmap_p, ColorBlack, w, arrindex); arrindex += colorsAdd(charBitmap_p, ColorBlack, w, arrindex);
@ -304,9 +326,6 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
case(0b101): { case(0b101): {
repeats = (uint8_t)((b & (0b111000)) >> 3); /* 3 bits indicate repetition as the same color */ repeats = (uint8_t)((b & (0b111000)) >> 3); /* 3 bits indicate repetition as the same color */
uint8_t color = (uint8_t)(b & (0b0111)); uint8_t color = (uint8_t)(b & (0b0111));
// for(int i = 0; i < repeats; i++) {
// arrindex += colorsAdd(charBitmap_p, ColorWhite, w, arrindex);
// }
arrindex += repeats; arrindex += repeats;
arrindex += colorsAdd(charBitmap_p, color, w, arrindex); arrindex += colorsAdd(charBitmap_p, color, w, arrindex);
break; break;
@ -323,7 +342,7 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
} }
default: default:
debugPrintln(PSTR("FONT: [ERROR] Invalid drawing mode encounterd")); errorPrintln(PSTR("FONT: %sInvalid drawing mode"));
file.close(); file.close();
lv_mem_free(charInfo); lv_mem_free(charInfo);
return NULL; return NULL;
@ -336,8 +355,6 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
file.close(); file.close();
// debugPrintln("FONT: Bitmap " + String((char)charInfo->character) + " took " + String(millis() - startMillis) +
// "ms");
lv_mem_free(charInfo); lv_mem_free(charInfo);
charInBuffer = unicode_letter; charInBuffer = unicode_letter;
@ -357,17 +374,38 @@ static bool lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_gly
{ {
// ulong startMillis = millis(); // ulong startMillis = millis();
lv_font_fmt_zifont_dsc_t * fdsc = (lv_font_fmt_zifont_dsc_t *)font->dsc; /* header data struct */ lv_font_fmt_zifont_dsc_t * fdsc = (lv_font_fmt_zifont_dsc_t *)font->dsc; /* header data struct */
uint16_t charNum = unicode2codepoint(unicode_letter, fdsc->Codepageid); uint16_t glyphID;
int error = 0; int error = 0;
/* Only ascii characteres supported for now */ /* Only ascii characteres supported for now */
if(charNum < 0x20 || charNum > 0xff) return false; if(unicode_letter < 0x20) return false;
if(unicode_letter > 0xff && unicode_letter < 0xf000) return false;
if(unicode_letter > 0xff) Serial.printf("Char# %u\n", unicode_letter);
charNum -= 32; File file;
if(charCache[charNum].width == 0) { uint8_t charmap_position;
uint8_t charwidth;
if(unicode_letter >= 0xF000) {
charmap_position = 25 + sizeof(lv_font_fmt_zifont_dsc_t);
glyphID = unicode_letter - 0xf000; // start of fontawesome
charwidth = 0;
} else {
charmap_position = fdsc->Descriptionlength + sizeof(lv_font_fmt_zifont_dsc_t);
glyphID = unicode_letter - 0x20; // simple unicode to ascii - space is charNum=0
if(glyphID < sizeof(charCache) / sizeof(charCache[0]))
charwidth = charCache[glyphID].width;
else
charwidth = 0;
}
if(charwidth == 0 || glyphID >= sizeof(charCache) / sizeof(charCache[0])) {
/* Open the font for reading */ /* Open the font for reading */
File file = SPIFFS.open((char *)font->user_data, "r"); if(unicode_letter >= 0xF000) {
file = SPIFFS.open("/fontawesome24.zi", "r");
} else {
file = SPIFFS.open((char *)font->user_data, "r");
}
if(!file) { if(!file) {
Serial.printf("Error %d in opening file: %s\n", error, (char *)font->user_data); Serial.printf("Error %d in opening file: %s\n", error, (char *)font->user_data);
return false; return false;
@ -375,9 +413,8 @@ static bool lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_gly
/* read 10 bytes charmap */ /* read 10 bytes charmap */
lv_zifont_char_t * myCharIndex = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t)); lv_zifont_char_t * myCharIndex = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t));
file.seek((charNum - 32) * sizeof(lv_zifont_char_t) + fdsc->Descriptionlength + uint32_t char_position = glyphID * sizeof(lv_zifont_char_t) + charmap_position;
sizeof(lv_font_fmt_zifont_dsc_t), file.seek(char_position, SeekSet);
SeekSet);
size_t readSize = file.readBytes((char *)myCharIndex, sizeof(lv_zifont_char_t)); size_t readSize = file.readBytes((char *)myCharIndex, sizeof(lv_zifont_char_t));
file.close(); file.close();
@ -388,20 +425,30 @@ static bool lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_gly
} }
/* Double-check that we got the correct letter */ /* Double-check that we got the correct letter */
if(myCharIndex->character != unicode_letter) { if(fdsc->last_glyph_dsc->character != unicode_letter) {
lv_mem_free(myCharIndex); // lv_mem_free(myCharIndex);
return false; // return false;
} }
charCache[charNum] = *myCharIndex; if(unicode_letter <= 0xff && glyphID < sizeof(charCache) / sizeof(charCache[0]))
charCache[glyphID] = *myCharIndex;
lastCharInfo = *myCharIndex;
lv_mem_free(myCharIndex); lv_mem_free(myCharIndex);
} else { } else {
lastCharInfo = charCache[glyphID];
} }
dsc_out->adv_w = charCache[charNum].width; //-myCharIndex->righroverlap)*16; /* 8 bit integer 4 bit fractional*/ uint8_t w = lastCharInfo.width + lastCharInfo.kerningL + lastCharInfo.kerningR;
dsc_out->box_w = charCache[charNum].width + charCache[charNum].kerningL + charCache[charNum].kerningR;
/*cache glyph data*/
// fdsc->last_glyph_id = glyphID;
// fdsc->last_glyph_dsc = lastCharInfo;
dsc_out->adv_w = lastCharInfo.width; //-myCharIndex->righroverlap)*16; /* 8 bit integer 4 bit fractional*/
dsc_out->box_w = lastCharInfo.width + lastCharInfo.kerningL + lastCharInfo.kerningR;
dsc_out->box_h = fdsc->CharHeight; dsc_out->box_h = fdsc->CharHeight;
dsc_out->ofs_x = -charCache[charNum].kerningL; dsc_out->ofs_x = -lastCharInfo.kerningL;
dsc_out->ofs_y = 0; dsc_out->ofs_y = 0;
dsc_out->bpp = 4; /**< Bit-per-pixel: 1, 2, 4, 8*/ dsc_out->bpp = 4; /**< Bit-per-pixel: 1, 2, 4, 8*/
@ -419,8 +466,8 @@ static bool lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_gly
uint16_t colorsAdd(uint8_t * charBitmap_p, uint8_t color1, uint8_t w, uint16_t pos) uint16_t colorsAdd(uint8_t * charBitmap_p, uint8_t color1, uint8_t w, uint16_t pos)
{ {
uint16_t map_p = pos >> 1; uint16_t map_p = pos >> 1; // devide by 2
uint8_t col = pos % 2; uint8_t col = pos % 2; // remainder
color1 = color1 & 0b1111; color1 = color1 & 0b1111;
if(color1 != ColorBlack) { if(color1 != ColorBlack) {
@ -491,6 +538,7 @@ void printBuffer(uint8_t * charBitmap_p, uint8_t w, uint8_t h)
uint16_t unicode2codepoint(uint32_t unicode, uint8_t codepage) uint16_t unicode2codepoint(uint32_t unicode, uint8_t codepage)
{ {
return (uint16_t)unicode;
#ifdef ESP8266 #ifdef ESP8266
// ESP8266 needs the memory // ESP8266 needs the memory
if(unicode < 128) return unicode; if(unicode < 128) return unicode;
@ -689,6 +737,81 @@ uint16_t unicode2codepoint(uint32_t unicode, uint8_t codepage)
*/ */
default: default:
return 0; return 0;

View File

@ -24,6 +24,18 @@ extern "C" {
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
typedef uint8_t lv_zifont_char_offset_t[3];
typedef struct
{
uint16_t character;
uint8_t width;
uint8_t kerningL;
uint8_t kerningR;
lv_zifont_char_offset_t pos;
uint16_t length;
} lv_zifont_char_t;
typedef struct typedef struct
{ {
uint8_t Password; uint8_t Password;
@ -50,9 +62,9 @@ typedef struct
uint8_t Variablewidth; uint8_t Variablewidth;
uint8_t Namelength; uint8_t Namelength;
uint8_t Fontdataadd8byte; uint8_t Fontdataadd8byte;
uint16_t Res1; uint16_t last_glyph_id; // Reserved 1
uint32_t Actualnumchars; uint32_t Actualnumchars;
uint32_t Res3; lv_zifont_char_t * last_glyph_dsc; // Reserved 3
} lv_font_fmt_zifont_dsc_t; } lv_font_fmt_zifont_dsc_t;
/********************** /**********************
@ -64,17 +76,6 @@ int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size)
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/
typedef uint8_t lv_zifont_char_offset_t[3];
typedef struct
{
uint16_t character;
uint8_t width;
uint8_t kerningL;
uint8_t kerningR;
lv_zifont_char_offset_t pos;
uint16_t length;
} lv_zifont_char_t;
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */