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 uint8_t * charBitmap_p[32 * 32];
uint32_t charInBuffer = 0;
uint32_t charInBuffer = 0; // Last Character ID in the Bitmap Buffer
// uint8_t filecharBitmap_p[20 * 1024];
static lv_zifont_char_t lastCharInfo; // Holds the last Glyph DSC
#if ESP32
// uint8_t charBitmap_p[32 * 32];
static lv_zifont_char_t charCache[256 - 32];
static lv_zifont_char_t charCache[256 - 32]; // glyphID DSC cache
#else
// uint8_t charBitmap_p[32 * 32];
static lv_zifont_char_t charCache[256 - 32];
static lv_zifont_char_t charCache[256 - 32]; // glyphID DSC cache
#endif
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;
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 */
File file = SPIFFS.open(font_path, "r");
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);
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_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*/
@ -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)
{
// ulong startMillis = millis();
lv_font_fmt_zifont_dsc_t * fdsc = (lv_font_fmt_zifont_dsc_t *)font->dsc; /* header data struct */
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) {
Serial.printf("CacheLetter %c\n", (char)(uint8_t)unicode_letter);
return charBitmap_p;
}
/* Open the font for reading */
File file = SPIFFS.open((char *)font->user_data, "r");
File file;
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) {
debugPrintln(PSTR("FONT: [ERROR] while opening font:"));
debugPrintln((char *)font->user_data);
return NULL;
}
/* Read Character Table */
lv_zifont_char_t * charInfo = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t));
file.seek(charNum * 10 + fdsc->Descriptionlength + 0x2C, SeekSet);
size_t readSize = file.readBytes((char *)charInfo, sizeof(lv_zifont_char_t));
lv_zifont_char_t * charInfo;
/* Check Last Glyph in chache is valid and Matches currentGlyphID */
if(fdsc->last_glyph_id == glyphID && fdsc->last_glyph_dsc && fdsc->last_glyph_dsc->width > 0) {
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 */
if(readSize != sizeof(lv_zifont_char_t)) {
file.close();
lv_mem_free(charInfo);
debugPrintln(PSTR("FONT: [ERROR] Wrong number of bytes read from flash"));
return NULL;
/* Check that we read the correct size */
if(readSize != sizeof(lv_zifont_char_t)) {
file.close();
lv_mem_free(charInfo);
debugPrintln(PSTR("FONT: [ERROR] Wrong number of bytes read from flash"));
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 */
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];
long datapos = charmap_position + (charInfo->pos[2] << 16) + (charInfo->pos[1] << 8) + charInfo->pos[0];
/* Allocate & Initialize Buffer for 4bpp */
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);
memset(charBitmap_p, 0, size); // init the bitmap to white
char ch[10];
char ch[1];
file.seek(datapos, SeekSet);
// Serial.printf("Data start position :%d = %d\n", datapos, ftell(file));
file.readBytes(ch, 1); /* check first byte = bpp */
uint8_t b = ch[0];
if(b != 3) {
if(ch[0] != 3) {
file.close();
lv_mem_free(charInfo);
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;
}
@ -254,9 +284,10 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
uint16_t fileindex = 0;
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) {
len = file.readBytes(data, sizeof(data));
} 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 */
switch((uint8_t)b >> 5) {
case(0b000):
// for(int i = 0; i < repeats; i++) {
// arrindex += colorsAdd(charBitmap_p, ColorWhite, w, arrindex);
// }
arrindex += repeats;
break;
@ -284,17 +312,11 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
break;
case(0b010):
// for(int i = 0; i < repeats; i++) {
// arrindex += colorsAdd(charBitmap_p, ColorWhite, w, arrindex);
// }
arrindex += repeats;
arrindex += colorsAdd(charBitmap_p, ColorBlack, w, arrindex);
break;
case(0b011):
// for(int i = 0; i < repeats; i++) {
// arrindex += colorsAdd(charBitmap_p, ColorWhite, w, arrindex);
// }
arrindex += repeats;
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): {
repeats = (uint8_t)((b & (0b111000)) >> 3); /* 3 bits indicate repetition as the same color */
uint8_t color = (uint8_t)(b & (0b0111));
// for(int i = 0; i < repeats; i++) {
// arrindex += colorsAdd(charBitmap_p, ColorWhite, w, arrindex);
// }
arrindex += repeats;
arrindex += colorsAdd(charBitmap_p, color, w, arrindex);
break;
@ -323,7 +342,7 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
}
default:
debugPrintln(PSTR("FONT: [ERROR] Invalid drawing mode encounterd"));
errorPrintln(PSTR("FONT: %sInvalid drawing mode"));
file.close();
lv_mem_free(charInfo);
return NULL;
@ -336,8 +355,6 @@ static const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uin
file.close();
// debugPrintln("FONT: Bitmap " + String((char)charInfo->character) + " took " + String(millis() - startMillis) +
// "ms");
lv_mem_free(charInfo);
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();
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);
int error = 0;
uint16_t glyphID;
int error = 0;
/* 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;
if(charCache[charNum].width == 0) {
File file;
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 */
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) {
Serial.printf("Error %d in opening file: %s\n", error, (char *)font->user_data);
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 */
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 +
sizeof(lv_font_fmt_zifont_dsc_t),
SeekSet);
uint32_t char_position = glyphID * sizeof(lv_zifont_char_t) + charmap_position;
file.seek(char_position, SeekSet);
size_t readSize = file.readBytes((char *)myCharIndex, sizeof(lv_zifont_char_t));
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 */
if(myCharIndex->character != unicode_letter) {
lv_mem_free(myCharIndex);
return false;
if(fdsc->last_glyph_dsc->character != unicode_letter) {
// lv_mem_free(myCharIndex);
// return false;
}
charCache[charNum] = *myCharIndex;
if(unicode_letter <= 0xff && glyphID < sizeof(charCache) / sizeof(charCache[0]))
charCache[glyphID] = *myCharIndex;
lastCharInfo = *myCharIndex;
lv_mem_free(myCharIndex);
} else {
lastCharInfo = charCache[glyphID];
}
dsc_out->adv_w = charCache[charNum].width; //-myCharIndex->righroverlap)*16; /* 8 bit integer 4 bit fractional*/
dsc_out->box_w = charCache[charNum].width + charCache[charNum].kerningL + charCache[charNum].kerningR;
uint8_t w = lastCharInfo.width + lastCharInfo.kerningL + lastCharInfo.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->ofs_x = -charCache[charNum].kerningL;
dsc_out->ofs_x = -lastCharInfo.kerningL;
dsc_out->ofs_y = 0;
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 map_p = pos >> 1;
uint8_t col = pos % 2;
uint16_t map_p = pos >> 1; // devide by 2
uint8_t col = pos % 2; // remainder
color1 = color1 & 0b1111;
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)
{
return (uint16_t)unicode;
#ifdef ESP8266
// ESP8266 needs the memory
if(unicode < 128) return unicode;
@ -689,6 +737,81 @@ uint16_t unicode2codepoint(uint32_t unicode, uint8_t codepage)
*/
default:
return 0;

View File

@ -24,6 +24,18 @@ extern "C" {
/**********************
* 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
{
uint8_t Password;
@ -50,9 +62,9 @@ typedef struct
uint8_t Variablewidth;
uint8_t Namelength;
uint8_t Fontdataadd8byte;
uint16_t Res1;
uint16_t last_glyph_id; // Reserved 1
uint32_t Actualnumchars;
uint32_t Res3;
lv_zifont_char_t * last_glyph_dsc; // Reserved 3
} 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
**********************/
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
} /* extern "C" */