Add Multiple Font Support

This commit is contained in:
fvanroie 2020-02-10 21:57:12 +01:00
parent 3bded8bfc3
commit d6f0025f68
2 changed files with 104 additions and 60 deletions

View File

@ -71,9 +71,11 @@ uint32_t charInBuffer = 0; // Last Character ID in the Bitmap Buffer
static lv_zifont_char_t lastCharInfo; // Holds the last Glyph DSC static lv_zifont_char_t lastCharInfo; // Holds the last Glyph DSC
#if ESP32 #if ESP32
static lv_zifont_char_t charCache[256 - 32]; // glyphID DSC cache // static lv_zifont_char_t charCache[256 - 32]; // glyphID DSC cache
#define CHAR_CACHE_SIZE 224
#else #else
static lv_zifont_char_t charCache[256 - 32]; // glyphID DSC cache #define CHAR_CACHE_SIZE 1
// static lv_zifont_char_t charCache[256 - 32]; // glyphID DSC cache
#endif #endif
static uint8_t * charBitmap_p; static uint8_t * charBitmap_p;
@ -95,12 +97,27 @@ int lv_zifont_init(void)
return LV_RES_OK; // OK return LV_RES_OK; // OK
} }
bool openFont(File & file, const char * filename)
{
file = SPIFFS.open(filename, "r");
if(!file) {
errorPrintln(String(F("FONT: %sOpening font: ")) + String(filename));
return false;
}
return true;
}
int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size) int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size)
{ {
charInBuffer = 0; // invalidate any previous cache charInBuffer = 0; // invalidate any previous cache
lv_font_fmt_zifont_dsc_t * dsc = (lv_font_fmt_zifont_dsc_t *)lv_mem_alloc(sizeof(lv_font_fmt_zifont_dsc_t)); lv_font_fmt_zifont_dsc_t * dsc;
LV_ASSERT_MEM(dsc); if(!font->dsc) {
dsc = (lv_font_fmt_zifont_dsc_t *)lv_mem_alloc(sizeof(lv_font_fmt_zifont_dsc_t));
LV_ASSERT_MEM(dsc);
} else {
dsc = (lv_font_fmt_zifont_dsc_t *)font->dsc;
}
if(dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY; if(dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY;
int error = 0; int error = 0;
@ -111,47 +128,63 @@ int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size)
dsc->last_glyph_id = 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;
if(!file) { if(!openFont(file, font_path)) return ZIFONT_ERROR_OPENING_FILE;
char msg[64];
sprintf(msg, PSTR("FONT: Error %d while opening font: %s\n"), error, font_path);
debugPrintln(msg);
return ZIFONT_ERROR_OPENING_FILE;
}
/* Read file header as dsc */ /* Read file header as dsc */
size_t readSize = file.readBytes((char *)dsc, sizeof(lv_font_fmt_zifont_dsc_t)); zi_font_header_t header;
size_t readSize = file.readBytes((char *)&header, sizeof(zi_font_header_t));
/* Check that we read the correct size */ /* Check that we read the correct size */
if(readSize != sizeof(lv_font_fmt_zifont_dsc_t)) { if(readSize != sizeof(zi_font_header_t)) {
debugPrintln(PSTR("FONT: Error reading ziFont Header")); debugPrintln(PSTR("FONT: Error reading ziFont Header"));
file.close();
return ZIFONT_ERROR_READING_DATA; return ZIFONT_ERROR_READING_DATA;
} }
/* Check ziFile Header Format */ /* Check ziFile Header Format */
if(dsc->Password != 4 || dsc->Version != 5) { if(header.Password != 4 || header.Version != 5) {
debugPrintln(PSTR("FONT: Unknown font file format")); debugPrintln(PSTR("FONT: Unknown font file format"));
file.close();
return ZIFONT_ERROR_UNKNOWN_HEADER; return ZIFONT_ERROR_UNKNOWN_HEADER;
} }
dsc->CharHeight = header.CharHeight;
dsc->CharWidth = header.CharWidth;
dsc->Maximumnumchars = header.Maximumnumchars;
dsc->Actualnumchars = header.Actualnumchars;
dsc->Totaldatalength = header.Totaldatalength;
dsc->Startdataaddress = header.Startdataaddress + header.Descriptionlength;
dsc->Fontdataadd8byte = header.Fontdataadd8byte;
if(!dsc->ascii_glyph_dsc) {
dsc->ascii_glyph_dsc = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE);
LV_ASSERT_MEM(dsc->ascii_glyph_dsc);
}
if(dsc->ascii_glyph_dsc == NULL) {
file.close();
return ZIFONT_ERROR_OUT_OF_MEMORY;
}
/* read charmap into cache */ /* read charmap into cache */
file.seek(0 * sizeof(lv_zifont_char_t) + dsc->Descriptionlength + sizeof(lv_font_fmt_zifont_dsc_t), SeekSet); file.seek(0 * sizeof(zi_font_header_t) + dsc->Startdataaddress, SeekSet);
//* read and fill charmap cache //* read and fill charmap cache
readSize = file.readBytes((char *)charCache, sizeof(charCache)); readSize = file.readBytes((char *)dsc->ascii_glyph_dsc, sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE);
//* Check that we read the correct size //* Check that we read the correct size
if(readSize != sizeof(charCache)) { if(readSize != sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE) {
debugPrintln(PSTR("FONT: Error reading ziFont character map")); debugPrintln(PSTR("FONT: Error reading ziFont character map"));
file.close();
return ZIFONT_ERROR_READING_DATA; return ZIFONT_ERROR_READING_DATA;
} }
file.close();
char msg[128]; char msg[128];
sprintf_P(msg, PSTR("FONT: Loaded V%d Font File: %s containing %d characters"), dsc->Version, font_path, sprintf_P(msg, PSTR("FONT: Loaded V%d Font File: %s containing %d characters"), header.Version, font_path,
dsc->Maximumnumchars); header.Maximumnumchars);
debugPrintln(msg); debugPrintln(msg);
file.close();
/* /*
sprintf_P(msg, PSTR("password: %u - skipL0: %u - skipLH: %u - state: %u\n"), dsc->Password, dsc->SkipL0, sprintf_P(msg, PSTR("password: %u - skipL0: %u - skipLH: %u - state: %u\n"), dsc->Password, dsc->SkipL0,
dsc->SkipLH, dsc->State); dsc->SkipLH, dsc->State);
@ -162,12 +195,10 @@ int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size)
sprintf_P(msg, PSTR("CodepageStart0: %u - CodepageEnd0: %u - CodepageStart1: %u - CodepageEnd1: %u\n"), sprintf_P(msg, PSTR("CodepageStart0: %u - CodepageEnd0: %u - CodepageStart1: %u - CodepageEnd1: %u\n"),
dsc->SecondByteStart, dsc->SecondByteEnd, dsc->FirstByteStart, dsc->FirstByteEnd); dsc->SecondByteStart, dsc->SecondByteEnd, dsc->FirstByteStart, dsc->FirstByteEnd);
Serial.printf(msg); Serial.printf(msg);
sprintf_P(msg, PSTR("CharCount: %u - FileVersion: %u - FontnameLength: %u - tbd: %u\n"), dsc->Maximumnumchars, , sprintf_P(msg, PSTR("CharCount: %u - FileVersion: %u - FontnameLength: %u - tbd: %u\n"),
dsc->Descriptionlength, dsc->Zimobinbeg); dsc->Maximumnumchars, , dsc->Descriptionlength, dsc->Zimobinbeg); Serial.printf(msg); sprintf_P(msg,
Serial.printf(msg); PSTR("FontnameAndCmapLength: %u - FontnameStartAddr: %u - temp0: %u - temp1: %u\n"), dsc->Totaldatalength,
sprintf_P(msg, PSTR("FontnameAndCmapLength: %u - FontnameStartAddr: %u - temp0: %u - temp1: %u\n"), dsc->Startdataaddress, dsc->CodeT0, dsc->CodeDec); Serial.printf(msg);*/
dsc->Totaldatalength, dsc->Startdataaddress, dsc->CodeT0, dsc->CodeDec);
Serial.printf(msg);*/
/* Init Glyph Cache */ /* Init Glyph Cache */
dsc->last_glyph_dsc = NULL; dsc->last_glyph_dsc = NULL;
@ -180,7 +211,10 @@ int lv_zifont_font_init(lv_font_t * font, const char * font_path, uint16_t size)
font->dsc = dsc; /* header data struct */ /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ font->dsc = dsc; /* header data struct */ /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */
font->subpx = 0; font->subpx = 0;
font->user_data = (char *)font_path; if(font->user_data != (char *)font_path) {
if(font->user_data) free(font->user_data);
font->user_data = (char *)font_path;
}
return ZIFONT_NO_ERROR; return ZIFONT_NO_ERROR;
} }
@ -212,20 +246,15 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
uint16_t charmap_position; uint16_t charmap_position;
if(unicode_letter >= 0xF000) { if(unicode_letter >= 0xF000) {
sprintf_P(filename, PSTR("/fontawesome%u.zi"), fdsc->CharHeight); sprintf_P(filename, PSTR("/fontawesome%u.zi"), fdsc->CharHeight);
charmap_position = 25 + sizeof(lv_font_fmt_zifont_dsc_t); charmap_position = 25 + sizeof(zi_font_header_t);
glyphID = unicode_letter - 0xf000; // start of fontawesome glyphID = unicode_letter - 0xf000; // start of fontawesome
} else { } else {
strcpy(filename, (char *)font->user_data); strcpy(filename, (char *)font->user_data);
charmap_position = fdsc->Descriptionlength + sizeof(lv_font_fmt_zifont_dsc_t); charmap_position = fdsc->Startdataaddress;
glyphID = unicode_letter - 0x20; // simple unicode to ascii - space is charNum=0 glyphID = unicode_letter - 0x20; // simple unicode to ascii - space is charNum=0
} }
file = SPIFFS.open(filename, "r"); if(!openFont(file, filename)) return NULL;
if(!file) {
debugPrintln(String(F("FONT: [ERROR] while opening font:")) + String(filename));
// debugPrintln((char *)font->user_data);
return NULL;
}
lv_zifont_char_t * charInfo; lv_zifont_char_t * charInfo;
/* Check Last Glyph in chache is valid and Matches currentGlyphID */ /* Check Last Glyph in chache is valid and Matches currentGlyphID */
@ -233,7 +262,7 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
// Serial.print("@"); // Serial.print("@");
charInfo = fdsc->last_glyph_dsc; charInfo = fdsc->last_glyph_dsc;
} else { } else {
Serial.print("-"); Serial.print("%");
/* Read Character Table */ /* Read Character Table */
charInfo = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t)); 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; uint32_t char_position = glyphID * sizeof(lv_zifont_char_t) + charmap_position;
@ -389,41 +418,42 @@ static bool lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_gly
uint8_t charmap_position; uint8_t charmap_position;
uint8_t charwidth; uint8_t charwidth;
if(unicode_letter >= 0xF000) { if(unicode_letter >= 0xF000) {
charmap_position = 25 + sizeof(lv_font_fmt_zifont_dsc_t); charmap_position = 25 + sizeof(zi_font_header_t);
glyphID = unicode_letter - 0xf000; // start of fontawesome glyphID = unicode_letter - 0xf000; // start of fontawesome
charwidth = 0; charwidth = 0;
} else { } else {
charmap_position = fdsc->Descriptionlength + sizeof(lv_font_fmt_zifont_dsc_t); charmap_position = fdsc->Startdataaddress; // Descriptionlength + sizeof(lv_font_fmt_zifont_dsc_t);
glyphID = unicode_letter - 0x20; // simple unicode to ascii - space is charNum=0 glyphID = unicode_letter - 0x20; // simple unicode to ascii - space is charNum=0
if(glyphID < sizeof(charCache) / sizeof(charCache[0])) // if(glyphID < sizeof(fdsc->ascii_glyph_dsc) / sizeof(lv_zifont_char_t))
charwidth = charCache[glyphID].width; if(glyphID < CHAR_CACHE_SIZE)
charwidth = fdsc->ascii_glyph_dsc[glyphID].width;
else else
charwidth = 0; charwidth = 0;
} }
if(charwidth == 0 || glyphID >= sizeof(charCache) / sizeof(charCache[0])) { // if(charwidth == 0 || glyphID >= sizeof(fdsc->ascii_glyph_dsc) / sizeof(lv_zifont_char_t)) {
if(charwidth == 0 || glyphID >= CHAR_CACHE_SIZE) {
/* Open the font for reading */ /* Open the font for reading */
if(unicode_letter >= 0xF000) { if(unicode_letter >= 0xF000) {
file = SPIFFS.open("/fontawesome24.zi", "r"); char filename[32];
sprintf_P(filename, PSTR("/fontawesome%u.zi"), fdsc->CharHeight);
if(!openFont(file, filename)) return false;
} else { } else {
file = SPIFFS.open((char *)font->user_data, "r"); if(!openFont(file, (char *)font->user_data)) return false;
}
if(!file) {
Serial.printf("Error %d in opening file: %s\n", error, (char *)font->user_data);
return false;
} }
/* 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));
uint32_t char_position = glyphID * sizeof(lv_zifont_char_t) + charmap_position; lv_zifont_char_t myCharIndex;
uint32_t char_position = glyphID * sizeof(lv_zifont_char_t) + charmap_position;
file.seek(char_position, SeekSet); file.seek(char_position, 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();
/* 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)) {
lv_mem_free(myCharIndex); // lv_mem_free(myCharIndex);
return false; return false;
} }
@ -433,13 +463,12 @@ static bool lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_gly
// return false; // return false;
} }
if(unicode_letter <= 0xff && glyphID < sizeof(charCache) / sizeof(charCache[0])) if(unicode_letter <= 0xff && glyphID < CHAR_CACHE_SIZE) fdsc->ascii_glyph_dsc[glyphID] = myCharIndex;
charCache[glyphID] = *myCharIndex; lastCharInfo = myCharIndex;
lastCharInfo = *myCharIndex; // lv_mem_free(myCharIndex);
lv_mem_free(myCharIndex);
} else { } else {
lastCharInfo = charCache[glyphID]; lastCharInfo = fdsc->ascii_glyph_dsc[glyphID];
} }
uint8_t w = lastCharInfo.width + lastCharInfo.kerningL + lastCharInfo.kerningR; uint8_t w = lastCharInfo.width + lastCharInfo.kerningL + lastCharInfo.kerningR;

View File

@ -62,9 +62,24 @@ typedef struct
uint8_t Variablewidth; uint8_t Variablewidth;
uint8_t Namelength; uint8_t Namelength;
uint8_t Fontdataadd8byte; uint8_t Fontdataadd8byte;
uint16_t last_glyph_id; // Reserved 1 uint16_t reserved1; // Reserved 1
uint32_t Actualnumchars; uint32_t Actualnumchars;
lv_zifont_char_t * last_glyph_dsc; // Reserved 3 uint32_t * reserved3; // Reserved 3
} zi_font_header_t;
typedef struct
{
uint8_t Codepageid;
uint8_t CharWidth;
uint8_t CharHeight;
uint32_t Maximumnumchars;
uint32_t Actualnumchars;
uint32_t Totaldatalength;
uint32_t Startdataaddress;
uint8_t Fontdataadd8byte;
uint16_t last_glyph_id;
lv_zifont_char_t * last_glyph_dsc;
lv_zifont_char_t * ascii_glyph_dsc;
} lv_font_fmt_zifont_dsc_t; } lv_font_fmt_zifont_dsc_t;
/********************** /**********************