Support extended font formats

Adafruit_GFX font support extended to Unidode Basic Multilingual Plane
Print stream deocdes UTF-8
Smooth font ascent and descent (affects line spacing) changed to rely on
metrics provided by Processing IDE (issue #303)
Bug fix for font rendering with no background on RLE native fonts
This commit is contained in:
Bodmer
2019-02-10 21:36:40 +00:00
parent 6a42e4b16d
commit 1e1e888fa0
11 changed files with 188 additions and 142 deletions

View File

@@ -97,7 +97,7 @@ void TFT_eSPI::loadFont(String fontName)
gFont.ascent = (uint16_t)readInt32(); // top of "d" gFont.ascent = (uint16_t)readInt32(); // top of "d"
gFont.descent = (uint16_t)readInt32(); // bottom of "p" gFont.descent = (uint16_t)readInt32(); // bottom of "p"
// These next gFont values will be updated when the Metrics are fetched // These next gFont values might be updated when the Metrics are fetched
gFont.maxAscent = gFont.ascent; // Determined from metrics gFont.maxAscent = gFont.ascent; // Determined from metrics
gFont.maxDescent = gFont.descent; // Determined from metrics gFont.maxDescent = gFont.descent; // Determined from metrics
gFont.yAdvance = gFont.ascent + gFont.descent; gFont.yAdvance = gFont.ascent + gFont.descent;
@@ -147,11 +147,19 @@ void TFT_eSPI::loadMetrics(uint16_t gCount)
gdX[gNum] = (int8_t)readInt32(); // x delta from cursor gdX[gNum] = (int8_t)readInt32(); // x delta from cursor
readInt32(); // ignored readInt32(); // ignored
// Different glyph sets have different ascent values not always based on "d", so get maximum glyph ascent //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gHeight = "); Serial.println(gHeight[gNum]);
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gWidth = "); Serial.println(gWidth[gNum]);
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gxAdvance = "); Serial.println(gxAdvance[gNum]);
//Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gdY = "); Serial.println(gdY[gNum]);
// Different glyph sets have different ascent values not always based on "d", so we could get
// the maximum glyph ascent by checking all characters. BUT this method can generate bad values
// for non-existant glyphs, so we will reply on processing for the value and disable this code for now...
/*
if (gdY[gNum] > gFont.maxAscent) if (gdY[gNum] > gFont.maxAscent)
{ {
// Avoid UTF coding values and characters that tend to give duff values // Try to avoid UTF coding values and characters that tend to give duff values
if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0xA0) && (gUnicode[gNum] != 0x7F)) || (gUnicode[gNum] > 0xFF)) if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0x7F)) || (gUnicode[gNum] > 0xA0))
{ {
gFont.maxAscent = gdY[gNum]; gFont.maxAscent = gdY[gNum];
#ifdef SHOW_ASCENT_DESCENT #ifdef SHOW_ASCENT_DESCENT
@@ -159,6 +167,7 @@ void TFT_eSPI::loadMetrics(uint16_t gCount)
#endif #endif
} }
} }
*/
// Different glyph sets have different descent values not always based on "p", so get maximum glyph descent // Different glyph sets have different descent values not always based on "p", so get maximum glyph descent
if (((int16_t)gHeight[gNum] - (int16_t)gdY[gNum]) > gFont.maxDescent) if (((int16_t)gHeight[gNum] - (int16_t)gdY[gNum]) > gFont.maxDescent)

View File

@@ -8,9 +8,6 @@
void unloadFont( void ); void unloadFont( void );
bool getUnicodeIndex(uint16_t unicode, uint16_t *index); bool getUnicodeIndex(uint16_t unicode, uint16_t *index);
uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining);
uint16_t decodeUTF8(uint8_t c);
uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc);
virtual void drawGlyph(uint16_t code); virtual void drawGlyph(uint16_t code);
@@ -44,9 +41,6 @@ fontMetrics gFont = { 0, 0, 0, 0, 0, 0, 0 };
String _gFontFilename; String _gFontFilename;
uint8_t decoderState = 0; // UTF8 decoder state
uint16_t decoderBuffer; // Unicode code-point buffer
bool fontLoaded = false; // Flags when a anti-aliased font is loaded bool fontLoaded = false; // Flags when a anti-aliased font is loaded
private: private:

View File

@@ -1312,13 +1312,16 @@ void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t
*************************************************************************************x*/ *************************************************************************************x*/
size_t TFT_eSprite::write(uint8_t utf8) size_t TFT_eSprite::write(uint8_t utf8)
{ {
uint16_t uniCode = decodeUTF8(utf8);
if (!uniCode) return 1;
if (utf8 == '\r') return 1; if (utf8 == '\r') return 1;
#ifdef SMOOTH_FONT #ifdef SMOOTH_FONT
if(this->fontLoaded) if(this->fontLoaded)
{ {
uint16_t unicode = decodeUTF8(utf8); if (uniCode < 32 && utf8 != '\n') return 1;
if (unicode < 32 && utf8 != '\n') return 1;
//fontFile = SPIFFS.open( _gFontFilename, "r" ); //fontFile = SPIFFS.open( _gFontFilename, "r" );
//fontFile = SPIFFS.open( this->_gFontFilename, "r" ); //fontFile = SPIFFS.open( this->_gFontFilename, "r" );
@@ -1330,7 +1333,8 @@ size_t TFT_eSprite::write(uint8_t utf8)
//} //}
//Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); //Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX);
drawGlyph(unicode); drawGlyph(uniCode);
//fontFile.close(); //fontFile.close();
return 1; return 1;
} }
@@ -1338,10 +1342,8 @@ size_t TFT_eSprite::write(uint8_t utf8)
if (!_created ) return 1; if (!_created ) return 1;
if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors
uint8_t uniCode = utf8; // Work with a copy else if (uniCode < 32) return 1;
if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors
else if (utf8 < 32) return 1;
uint16_t width = 0; uint16_t width = 0;
uint16_t height = 0; uint16_t height = 0;
@@ -1362,7 +1364,7 @@ size_t TFT_eSprite::write(uint8_t utf8)
if (textfont == 2) if (textfont == 2)
{ {
if (utf8 > 127) return 1; if (utf8 > 127) return 1;
// This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms)
width = pgm_read_byte(widtbl_f16 + uniCode-32); width = pgm_read_byte(widtbl_f16 + uniCode-32);
height = chr_hgt_f16; height = chr_hgt_f16;
// Font 2 is rendered in whole byte widths so we must allow for this // Font 2 is rendered in whole byte widths so we must allow for this
@@ -1380,7 +1382,6 @@ size_t TFT_eSprite::write(uint8_t utf8)
{ {
if (utf8 > 127) return 1; if (utf8 > 127) return 1;
// Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements
// A tad slower than above but this is not significant and is more convenient for the RLE fonts
width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 );
height= pgm_read_byte( &fontdata[textfont].height ); height= pgm_read_byte( &fontdata[textfont].height );
} }
@@ -1420,15 +1421,14 @@ size_t TFT_eSprite::write(uint8_t utf8)
} // Custom GFX font } // Custom GFX font
else else
{ {
if(utf8 == '\n') { if(utf8 == '\n') {
this->cursor_x = 0; this->cursor_x = 0;
this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
} else { } else {
if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 1; if (uniCode > pgm_read_word(&gfxFont->last )) return 1;
if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 1; if (uniCode < pgm_read_word(&gfxFont->first)) return 1;
uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); uint8_t c2 = uniCode - pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
uint8_t w = pgm_read_byte(&glyph->width), uint8_t w = pgm_read_byte(&glyph->width),
h = pgm_read_byte(&glyph->height); h = pgm_read_byte(&glyph->height);
@@ -1456,7 +1456,7 @@ size_t TFT_eSprite::write(uint8_t utf8)
** Function name: drawChar ** Function name: drawChar
** Description: draw a single character in the Adafruit GLCD or freefont ** Description: draw a single character in the Adafruit GLCD or freefont
*************************************************************************************x*/ *************************************************************************************x*/
void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) void TFT_eSprite::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size)
{ {
if (!_created ) return; if (!_created ) return;
@@ -1466,6 +1466,7 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color
((y + 8 * size - 1) < 0)) // Clip top ((y + 8 * size - 1) < 0)) // Clip top
return; return;
if (c < 32) return;
#ifdef LOAD_GLCD #ifdef LOAD_GLCD
//>>>>>>>>>>>>>>>>>> //>>>>>>>>>>>>>>>>>>
#ifdef LOAD_GFXFF #ifdef LOAD_GFXFF
@@ -1534,15 +1535,15 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color
#ifdef LOAD_GFXFF #ifdef LOAD_GFXFF
// Filter out bad characters not present in font // Filter out bad characters not present in font
if ((c >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last )))
{ {
//>>>>>>>>>>>>>>>>>>>>>>>>>>> //>>>>>>>>>>>>>>>>>>>>>>>>>>>
c -= pgm_read_byte(&gfxFont->first); c -= pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]);
uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap); uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap);
uint16_t bo = pgm_read_word(&glyph->bitmapOffset); uint32_t bo = pgm_read_word(&glyph->bitmapOffset);
uint8_t w = pgm_read_byte(&glyph->width), uint8_t w = pgm_read_byte(&glyph->width),
h = pgm_read_byte(&glyph->height); h = pgm_read_byte(&glyph->height);
//xa = pgm_read_byte(&glyph->xAdvance); //xa = pgm_read_byte(&glyph->xAdvance);
@@ -1597,15 +1598,19 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color
** Function name: drawChar ** Function name: drawChar
** Description: draw a unicode onto the screen ** Description: draw a unicode onto the screen
*************************************************************************************x*/ *************************************************************************************x*/
// Any UTF-8 decoding must be done before calling drawChar()
int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y) int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y)
{ {
return drawChar(uniCode, x, y, textfont); return drawChar(uniCode, x, y, textfont);
} }
// Any UTF-8 decoding must be done before calling drawChar()
int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
{ {
if (!_created ) return 0; if (!_created ) return 0;
if (!uniCode) return 0;
if (font==1) if (font==1)
{ {
#ifdef LOAD_GLCD #ifdef LOAD_GLCD
@@ -1630,9 +1635,9 @@ int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t fo
} }
else else
{ {
if((uniCode >= pgm_read_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) if((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last) ))
{ {
uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
return pgm_read_byte(&glyph->xAdvance) * textsize; return pgm_read_byte(&glyph->xAdvance) * textsize;
} }

View File

@@ -31,7 +31,7 @@ class TFT_eSprite : public TFT_eSPI {
void drawPixel(int32_t x, int32_t y, uint32_t color); void drawPixel(int32_t x, int32_t y, uint32_t color);
void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), void drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size),
fillSprite(uint32_t color), fillSprite(uint32_t color),

View File

@@ -12,7 +12,7 @@
#ifdef LOAD_GFXFF #ifdef LOAD_GFXFF
typedef struct { // Data stored PER GLYPH typedef struct { // Data stored PER GLYPH
uint16_t bitmapOffset; // Pointer into GFXfont->bitmap uint32_t bitmapOffset; // Pointer into GFXfont->bitmap
uint8_t width, height; // Bitmap dimensions in pixels uint8_t width, height; // Bitmap dimensions in pixels
uint8_t xAdvance; // Distance to advance cursor (x axis) uint8_t xAdvance; // Distance to advance cursor (x axis)
int8_t xOffset, yOffset; // Dist from cursor pos to UL corner int8_t xOffset, yOffset; // Dist from cursor pos to UL corner
@@ -21,7 +21,7 @@ typedef struct { // Data stored PER GLYPH
typedef struct { // Data stored for FONT AS A WHOLE: typedef struct { // Data stored for FONT AS A WHOLE:
uint8_t *bitmap; // Glyph bitmaps, concatenated uint8_t *bitmap; // Glyph bitmaps, concatenated
GFXglyph *glyph; // Glyph array GFXglyph *glyph; // Glyph array
uint8_t first, last; // ASCII extents uint16_t first, last; // ASCII extents
uint8_t yAdvance; // Newline distance (y axis) uint8_t yAdvance; // Newline distance (y axis)
} GFXfont; } GFXfont;

View File

@@ -2272,21 +2272,22 @@ int16_t TFT_eSPI::textWidth(const char *string)
int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) int16_t TFT_eSPI::textWidth(const char *string, uint8_t font)
{ {
int32_t str_width = 0; int32_t str_width = 0;
uint16_t uniCode = 0;
#ifdef SMOOTH_FONT #ifdef SMOOTH_FONT
if(fontLoaded) if(fontLoaded)
{ {
while (*string) while (*string)
{ {
uint16_t unicode = decodeUTF8(*string++); uniCode = decodeUTF8(*string++);
if (unicode) if (uniCode)
{ {
if (unicode == 0x20) str_width += gFont.spaceWidth; if (uniCode == 0x20) str_width += gFont.spaceWidth;
else else
{ {
uint16_t gNum = 0; uint16_t gNum = 0;
bool found = getUnicodeIndex(unicode, &gNum); bool found = getUnicodeIndex(uniCode, &gNum);
if (found) if (found)
{ {
if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum]; if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum];
@@ -2302,18 +2303,15 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font)
} }
#endif #endif
unsigned char uniCode;
char *widthtable;
if (font>1 && font<9) if (font>1 && font<9)
{ {
widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop char *widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop
while (*string) while (*string)
{ {
uniCode = *(string++); uniCode = *(string++);
if (uniCode > 31 && uniCode < 128) if (uniCode > 31 && uniCode < 128)
str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subract 32 from uniCode str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subtract 32 from uniCode
else str_width += pgm_read_byte( widthtable + 32); // Set illegal character = space width else str_width += pgm_read_byte( widthtable + 32); // Set illegal character = space width
} }
} }
@@ -2326,9 +2324,9 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font)
while (*string) while (*string)
{ {
uniCode = decodeUTF8(*string++); uniCode = decodeUTF8(*string++);
if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last ))) if ((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last )))
{ {
uniCode -= pgm_read_byte(&gfxFont->first); uniCode -= pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]);
// If this is not the last character or is a digit then use xAdvance // If this is not the last character or is a digit then use xAdvance
if (*string || isDigits) str_width += pgm_read_byte(&glyph->xAdvance); if (*string || isDigits) str_width += pgm_read_byte(&glyph->xAdvance);
@@ -2393,7 +2391,7 @@ int16_t TFT_eSPI::fontHeight(void)
** Function name: drawChar ** Function name: drawChar
** Description: draw a single character in the Adafruit GLCD font ** Description: draw a single character in the Adafruit GLCD font
***************************************************************************************/ ***************************************************************************************/
void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size)
{ {
if ((x >= _width) || // Clip right if ((x >= _width) || // Clip right
(y >= _height) || // Clip bottom (y >= _height) || // Clip bottom
@@ -2498,17 +2496,17 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u
#ifdef LOAD_GFXFF #ifdef LOAD_GFXFF
// Filter out bad characters not present in font // Filter out bad characters not present in font
if ((c >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last )))
{ {
spi_begin(); spi_begin();
inTransaction = true; inTransaction = true;
//>>>>>>>>>>>>>>>>>>>>>>>>>>> //>>>>>>>>>>>>>>>>>>>>>>>>>>>
c -= pgm_read_byte(&gfxFont->first); c -= pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]);
uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap); uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap);
uint16_t bo = pgm_read_word(&glyph->bitmapOffset); uint32_t bo = pgm_read_word(&glyph->bitmapOffset);
uint8_t w = pgm_read_byte(&glyph->width), uint8_t w = pgm_read_byte(&glyph->width),
h = pgm_read_byte(&glyph->height); h = pgm_read_byte(&glyph->height);
//xa = pgm_read_byte(&glyph->xAdvance); //xa = pgm_read_byte(&glyph->xAdvance);
@@ -3991,18 +3989,18 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
***************************************************************************************/ ***************************************************************************************/
size_t TFT_eSPI::write(uint8_t utf8) size_t TFT_eSPI::write(uint8_t utf8)
{ {
uint16_t uniCode = decodeUTF8(utf8);
if (!uniCode) return 1;
if (utf8 == '\r') return 1; if (utf8 == '\r') return 1;
#ifdef SMOOTH_FONT #ifdef SMOOTH_FONT
if(fontLoaded) if(fontLoaded)
{ {
uint16_t unicode = decodeUTF8(utf8); //Serial.print("UniCode="); Serial.println(uniCode);
//Serial.print("UniCode="); Serial.println(unicode);
//Serial.print("UTF8 ="); Serial.println(utf8); //Serial.print("UTF8 ="); Serial.println(utf8);
if (!unicode) return 1;
//fontFile = SPIFFS.open( _gFontFilename, "r" ); //fontFile = SPIFFS.open( _gFontFilename, "r" );
//if(!fontFile) //if(!fontFile)
@@ -4011,16 +4009,15 @@ size_t TFT_eSPI::write(uint8_t utf8)
// return 1; // return 1;
//} //}
drawGlyph(unicode); drawGlyph(uniCode);
//fontFile.close(); //fontFile.close();
return 1; return 1;
} }
#endif #endif
uint8_t uniCode = utf8; // Work with a copy if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors
if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors else if (uniCode < 32) return 1;
else if (utf8 < 32) return 1;
uint16_t width = 0; uint16_t width = 0;
uint16_t height = 0; uint16_t height = 0;
@@ -4040,8 +4037,8 @@ size_t TFT_eSPI::write(uint8_t utf8)
#ifdef LOAD_FONT2 #ifdef LOAD_FONT2
if (textfont == 2) if (textfont == 2)
{ {
if (utf8 > 127) return 1; if (uniCode > 127) return 1;
// This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms)
width = pgm_read_byte(widtbl_f16 + uniCode-32); width = pgm_read_byte(widtbl_f16 + uniCode-32);
height = chr_hgt_f16; height = chr_hgt_f16;
// Font 2 is rendered in whole byte widths so we must allow for this // Font 2 is rendered in whole byte widths so we must allow for this
@@ -4057,9 +4054,8 @@ size_t TFT_eSPI::write(uint8_t utf8)
{ {
if ((textfont>2) && (textfont<9)) if ((textfont>2) && (textfont<9))
{ {
if (utf8 > 127) return 1; if (uniCode > 127) return 1;
// Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements
// A tad slower than above but this is not significant and is more convenient for the RLE fonts
width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 );
height= pgm_read_byte( &fontdata[textfont].height ); height= pgm_read_byte( &fontdata[textfont].height );
} }
@@ -4098,18 +4094,15 @@ size_t TFT_eSPI::write(uint8_t utf8)
} // Custom GFX font } // Custom GFX font
else else
{ {
uniCode = (uint8_t)decodeUTF8(utf8);
if (!uniCode) return 1;
if(utf8 == '\n') { if(utf8 == '\n') {
cursor_x = 0; cursor_x = 0;
cursor_y += (int16_t)textsize * cursor_y += (int16_t)textsize *
(uint8_t)pgm_read_byte(&gfxFont->yAdvance); (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
} else { } else {
if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 1; if (uniCode > pgm_read_word(&gfxFont->last )) return 1;
if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 1; if (uniCode < pgm_read_word(&gfxFont->first)) return 1;
uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
uint8_t w = pgm_read_byte(&glyph->width), uint8_t w = pgm_read_byte(&glyph->width),
h = pgm_read_byte(&glyph->height); h = pgm_read_byte(&glyph->height);
@@ -4136,17 +4129,17 @@ size_t TFT_eSPI::write(uint8_t utf8)
/*************************************************************************************** /***************************************************************************************
** Function name: drawChar ** Function name: drawChar
** Description: draw a Unicode onto the screen ** Description: draw a Unicode glyph onto the screen
***************************************************************************************/ ***************************************************************************************/
int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y) // Any UTF-8 decoding must be done before calling drawChar()
int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y)
{ {
return drawChar(utf8, x, y, textfont); return drawChar(uniCode, x, y, textfont);
} }
int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font) // Any UTF-8 decoding must be done before calling drawChar()
int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
{ {
uint16_t uniCode = decodeUTF8(utf8);
if (!uniCode) return 0; if (!uniCode) return 0;
if (font==1) if (font==1)
@@ -4173,9 +4166,9 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font)
} }
else else
{ {
if((uniCode >= pgm_read_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) if((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last) ))
{ {
uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
return pgm_read_byte(&glyph->xAdvance) * textsize; return pgm_read_byte(&glyph->xAdvance) * textsize;
} }
@@ -4197,7 +4190,6 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font)
#ifdef LOAD_FONT2 #ifdef LOAD_FONT2
if (font == 2) if (font == 2)
{ {
// This is faster than using the fontdata structure
flash_address = pgm_read_dword(&chrtbl_f16[uniCode]); flash_address = pgm_read_dword(&chrtbl_f16[uniCode]);
width = pgm_read_byte(widtbl_f16 + uniCode); width = pgm_read_byte(widtbl_f16 + uniCode);
height = chr_hgt_f16; height = chr_hgt_f16;
@@ -4211,7 +4203,6 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font)
{ {
if ((font>2) && (font<9)) if ((font>2) && (font<9))
{ {
// This is slower than above but is more convenient for the RLE fonts
flash_address = pgm_read_dword( pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *) ); flash_address = pgm_read_dword( pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *) );
width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode ); width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode );
height= pgm_read_byte( &fontdata[font].height ); height= pgm_read_byte( &fontdata[font].height );
@@ -4309,6 +4300,7 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font)
// Font is not 2 and hence is RLE encoded // Font is not 2 and hence is RLE encoded
{ {
spi_begin(); spi_begin();
inTransaction = true;
w *= height; // Now w is total number of pixels in the character w *= height; // Now w is total number of pixels in the character
if ((textsize != 1) || (textcolor == textbgcolor)) { if ((textsize != 1) || (textcolor == textbgcolor)) {
@@ -4360,6 +4352,7 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font)
} }
} }
inTransaction = false;
spi_end(); spi_end();
} }
else // Text colour != background && textsize = 1 else // Text colour != background && textsize = 1
@@ -4442,7 +4435,7 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY)
return drawString(string, poX, poY, textfont); return drawString(string, poX, poY, textfont);
} }
// With font number // With font number. Note: font number is over-ridden if a smooth font is loaded
int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font) int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font)
{ {
int16_t sumX = 0; int16_t sumX = 0;
@@ -4553,15 +4546,15 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
{ {
cheight = (glyph_ab + glyph_bb) * textsize; cheight = (glyph_ab + glyph_bb) * textsize;
// Get the offset for the first character only to allow for negative offsets // Get the offset for the first character only to allow for negative offsets
uint8_t c2 = 0; uint16_t c2 = 0;
uint16_t len = strlen(string); uint16_t len = strlen(string);
uint16_t n = 0; uint16_t n = 0;
while (n < len && c2 == 0) c2 = decodeUTF8((uint8_t*)string, &n, len - n); while (n < len && c2 == 0) c2 = decodeUTF8((uint8_t*)string, &n, len - n);
if((c2 >= pgm_read_byte(&gfxFont->first)) && (c2 <= pgm_read_byte(&gfxFont->last) )) if((c2 >= pgm_read_word(&gfxFont->first)) && (c2 <= pgm_read_word(&gfxFont->last) ))
{ {
c2 -= pgm_read_byte(&gfxFont->first); c2 -= pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
xo = pgm_read_byte(&glyph->xOffset) * textsize; xo = pgm_read_byte(&glyph->xOffset) * textsize;
// Adjust for negative xOffset // Adjust for negative xOffset
@@ -4576,6 +4569,9 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
} }
#endif #endif
uint16_t len = strlen(string);
uint16_t n = 0;
#ifdef SMOOTH_FONT #ifdef SMOOTH_FONT
if(fontLoaded) if(fontLoaded)
{ {
@@ -4584,14 +4580,13 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
//drawLine(poX, poY - 5, poX, poY + 5, TFT_GREEN); //drawLine(poX, poY - 5, poX, poY + 5, TFT_GREEN);
//fontFile = SPIFFS.open( _gFontFilename, "r"); //fontFile = SPIFFS.open( _gFontFilename, "r");
if(!fontFile) return 0; if(!fontFile) return 0;
uint16_t len = strlen(string);
uint16_t n = 0;
setCursor(poX, poY); setCursor(poX, poY);
while (n < len) while (n < len)
{ {
uint16_t unicode = decodeUTF8((uint8_t*)string, &n, len - n); uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n);
drawGlyph(unicode); drawGlyph(uniCode);
} }
sumX += cwidth; sumX += cwidth;
//fontFile.close(); //fontFile.close();
@@ -4599,7 +4594,11 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
else else
#endif #endif
{ {
while (*string) sumX += drawChar(*(string++), poX+sumX, poY, font); while (n < len)
{
uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n);
sumX += drawChar(uniCode, poX+sumX, poY, font);
}
} }
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
@@ -4669,7 +4668,7 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
#endif #endif
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return sumX; return sumX + poX;
} }
@@ -4782,7 +4781,7 @@ int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t
// No chance of overflow from here on // No chance of overflow from here on
// Get integer part // Get integer part
unsigned long temp = (unsigned long)floatNumber; uint32_t temp = (uint32_t)floatNumber;
// Put integer part into array // Put integer part into array
ltoa(temp, str + ptr, 10); ltoa(temp, str + ptr, 10);
@@ -4830,7 +4829,7 @@ void TFT_eSPI::setFreeFont(const GFXfont *f)
glyph_ab = 0; glyph_ab = 0;
glyph_bb = 0; glyph_bb = 0;
uint8_t numChars = pgm_read_byte(&gfxFont->last) - pgm_read_byte(&gfxFont->first); uint16_t numChars = pgm_read_word(&gfxFont->last) - pgm_read_word(&gfxFont->first);
// Find the biggest above and below baseline offsets // Find the biggest above and below baseline offsets
for (uint8_t c = 0; c < numChars; c++) for (uint8_t c = 0; c < numChars; c++)

View File

@@ -668,7 +668,7 @@ class TFT_eSPI : public Print {
// These are virtual so the TFT_eSprite class can override them with sprite specific functions // These are virtual so the TFT_eSprite class can override them with sprite specific functions
virtual void drawPixel(int32_t x, int32_t y, uint32_t color), virtual void drawPixel(int32_t x, int32_t y, uint32_t color),
drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size),
drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color),
drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color),
drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color),
@@ -813,6 +813,8 @@ class TFT_eSPI : public Print {
void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead
void endWrite(void); // End SPI transaction void endWrite(void); // End SPI transaction
uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining);
uint16_t decodeUTF8(uint8_t c);
size_t write(uint8_t); size_t write(uint8_t);
#ifdef TFT_SDA_READ #ifdef TFT_SDA_READ
@@ -838,6 +840,9 @@ class TFT_eSPI : public Print {
int16_t _xpivot; // x pivot point coordinate int16_t _xpivot; // x pivot point coordinate
int16_t _ypivot; // x pivot point coordinate int16_t _ypivot; // x pivot point coordinate
uint8_t decoderState = 0; // UTF8 decoder state
uint16_t decoderBuffer; // Unicode code-point buffer
private: private:
inline void spi_begin() __attribute__((always_inline)); inline void spi_begin() __attribute__((always_inline));

View File

@@ -1,6 +1,8 @@
// This is a Processing sketch, see https://processing.org/ to download the IDE // This is a Processing sketch, see https://processing.org/ to download the IDE
// Select the character range in the user configure section starting at line 100 // Select the font, size and character ranges in the user configuration section
// of this sketch, which starts at line 120. Instructions start at line 50.
/* /*
Software License Agreement (FreeBSD License) Software License Agreement (FreeBSD License)
@@ -36,47 +38,61 @@ Software License Agreement (FreeBSD License)
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
// This is a processing sketch to create font files for the TFT_eSPI library: // This is a processing sketch to create font files for the TFT_eSPI library:
// https://github.com/Bodmer/TFT_eSPI // https://github.com/Bodmer/TFT_eSPI
// Coded by Bodmer January 2018 // Coded by Bodmer January 2018, updated 10/2/19
// Version 0.8
// See comments below in code for specifying the font parameters // >>>>>>>>>>>>>>>>>>>> INSTRUCTIONS <<<<<<<<<<<<<<<<<<<<
// (point size, unicode blocks to include etc). Ranges of characers or
// specific individual unicodes can be included in the created font file/ // See comments below in code for specifying the font parameters (point size,
// unicode blocks to include etc). Ranges of characters (glyphs) and specific
// individual glyphs can be included in the created "*.vlw" font file.
// Created fonts are saved in the sketches "FontFiles" folder. Press Ctrl+K to // Created fonts are saved in the sketches "FontFiles" folder. Press Ctrl+K to
// see that folder. // see that folder location.
// 16 bit unicodes in the range 0x0000 - 0xFFFF are supported. // 16 bit Unicode point codes in the range 0x0000 - 0xFFFF are supported.
// Codes 0-31 are control codes such as "tab" and "carraige return" etc.
// and 32 is a "space", these should NOT be included.
// The sketch will convert True Type (a .ttf or .otf file) file stored in the // The sketch will convert True Type (a .ttf or .otf file) file stored in the
// sketches "Data" folder as well as your computers system fonts. // sketches "Data" folder as well as your computers' system fonts.
// To maximise rendering performance only include the characters you will use. // To maximise rendering performance and the memory consumed only include the characters
// Characters at the start of the file will render faster than those at the end. // you will use. Characters at the start of the file will render faster than those at
// the end due to the buffering and file seeking overhead.
// The inclusion of "non-existant" characters in a font may give unpredicatable results
// when rendering with the TFT_eSPI library. The Processing sketch window that pops up
// to show the font characters will print "boxes" (also known as Tofu!) for non existant
// characters.
// Once created the files must be loaded into the ESP32 or ESP8266 SPIFFS memory // Once created the files must be loaded into the ESP32 or ESP8266 SPIFFS memory
// using the Arduino IDE plugin detailed here: // using the Arduino IDE plugin detailed here:
// https://github.com/esp8266/arduino-esp8266fs-plugin // https://github.com/esp8266/arduino-esp8266fs-plugin
// https://github.com/me-no-dev/arduino-esp32fs-plugin // https://github.com/me-no-dev/arduino-esp32fs-plugin
// The sketch list all the available PC fonts to the console, you may need to increase // When the sketch is run it will generate a file called "System_Font_List.txt" in the
// console line count (in preferences.txt) to stop some fonts scrolling out of view. // sketch "FontFiles" folder, press Ctrl+K to see it. Open the file in a text editor to
// view it. This list provides the font reference number needed below to locate that
// font on your system.
// The sketch also lists all the available system fonts to the console, you can increase
// the console line count (in preferences.txt) to stop some fonts scrolling out of view.
// See link in File>Preferences to locate "preferences.txt" file. You must close // See link in File>Preferences to locate "preferences.txt" file. You must close
// Processing then edit the file lines. If Processing is not closed first then the // Processing then edit the file lines. If Processing is not closed first then the
// edits will be overwritten by defaults! Edit "preferences.txt" as follows for // edits will be overwritten by defaults! Edit "preferences.txt" as follows for
// 1000 lines, then save, then run Processing again: // 3000 lines, then save, then run Processing again:
// console.length=3000; // Line 4 in file
// console.scrollback.lines=3000; // Line 7 in file
/*
console.length=1000 // Line 4 in file
console.scrollback.lines=1000 // Line 7 in file
*/
// Useful links: // Useful links:
/* /*
https://en.wikipedia.org/wiki/Unicode_font https://en.wikipedia.org/wiki/Unicode_font
@@ -86,33 +102,39 @@ Software License Agreement (FreeBSD License)
http://savannah.gnu.org/projects/freefont/ http://savannah.gnu.org/projects/freefont/
http://www.google.com/get/noto/ http://www.google.com/get/noto/
https://github.com/Bodmer/TFT_eSPI https://github.com/Bodmer/TFT_eSPI
https://github.com/esp8266/arduino-esp8266fs-plugin https://github.com/esp8266/arduino-esp8266fs-plugin
https://github.com/me-no-dev/arduino-esp32fs-plugin https://github.com/me-no-dev/arduino-esp32fs-plugin
*/ >>>>>>>>>>>>>>>>>>>> END OF INSTRUCTIONS <<<<<<<<<<<<<<<<<<<< */
////////////////////////////////////////////////////////////////////////////////////////////////
import java.awt.Desktop;
import java.awt.Desktop; // Required to allow sketch to open file windows
////////////////////////////////////////////////////////////////////////////////////////////////
// >>>>>>>>>> USER CONFIGURED PARAMETERS START HERE <<<<<<<<<< // >>>>>>>>>> USER CONFIGURED PARAMETERS START HERE <<<<<<<<<<
// Use font number or name, -1 for fontNumber means use fontName below, a value >=0 means use system font number from list.
// When the sketch is run it will generate a file called "systemFontList.txt" in the sketch folder, press Ctrl+K to see it.
// Open the "systemFontList.txt" in a text editor to view the font files and reference numbers for your system.
// Use font name for ttf files placed in the "Data" folder or the font number seen in IDE Console for system fonts int fontNumber = -1; // << Use [Number] in brackets from the fonts listed.
// OR use font name for ttf files placed in the "Data" folder or the font number seen in IDE Console for system fonts
// the font numbers are listed when the sketch is run. // the font numbers are listed when the sketch is run.
// | 1 2 | Maximum filename size for SPIFFS is 32 including leading / // | 1 2 | Maximum filename size for SPIFFS is 31 including leading /
// 1234567890123456789012345 and added point size and .vlw extension, so max is 25 // 1234567890123456789012345 and added point size and .vlw extension, so max is 25
String fontName = "Final-Frontier"; //Manually crop the filename length later after creation if needed String fontName = "Final-Frontier"; // Manually crop the filename length later after creation if needed
// Note: SPIFFS does NOT accept underscore in a filename!
String fontType = ".ttf"; //SPIFFS does not accept underscore in filename! String fontType = ".ttf";
//String fontType = ".otf"; //String fontType = ".otf";
// Use font number instead of name, -1 means use name above, or a value >=0 means use system font number from list.
int fontNumber = -1; // << Use [Number] in brackets from the fonts listed in console window
// Define the font size in points for the created font file // Define the font size in points for the TFT_eSPI font file
int fontSize = 28; int fontSize = 20;
// Font size to use in the Processing sketch display window that pops up (can be different to above) // Font size to use in the Processing sketch display window that pops up (can be different to above)
int displayFontSize = 28; int displayFontSize = 28;
@@ -125,7 +147,7 @@ int displayFontSize = 28;
static final int[] unicodeBlocks = { static final int[] unicodeBlocks = {
// The list below has been created from the table here: https://en.wikipedia.org/wiki/Unicode_block // The list below has been created from the table here: https://en.wikipedia.org/wiki/Unicode_block
// Remove // at start of lines below to include that unicode block, different code ranges can also be specified by // Remove // at start of lines below to include that unicode block, different code ranges can also be specified by
// editting the start and end of range values. Multiple lines from the list below can be included, limited only by // editting the start and end-of-range values. Multiple lines from the list below can be included, limited only by
// the final font file size! // the final font file size!
// Block range, //Block name, Code points, Assigned characters, Scripts // Block range, //Block name, Code points, Assigned characters, Scripts
@@ -298,20 +320,20 @@ static final int[] unicodeBlocks = {
//0x0061, 0x007A, //Example custom range (Lower case a-z) //0x0061, 0x007A, //Example custom range (Lower case a-z)
}; };
// Here we specify specific individual Unicodes to be included (appended at end of selected range) // Here we specify particular individual Unicodes to be included (appended at end of selected range)
static final int[] specificUnicodes = { static final int[] specificUnicodes = {
// Commonly used codes, add or remove // in next line // Commonly used codes, add or remove // in next line
// 0x00A3, 0x00B0, 0x00B5, 0x03A9, 0x20AC, // £ ° µ Ω € // 0x00A3, 0x00B0, 0x00B5, 0x03A9, 0x20AC, // £ ° µ Ω €
// Numbers and characters for showing time, change next line to //* to use // Numbers and characters for showing time, change next line to //* to use
/* /*
0x002B, 0x002D, 0x002E, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, // - + . 0 1 2 3 4 0x002B, 0x002D, 0x002E, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, // - + . 0 1 2 3 4
0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x0061, 0x006D, // 5 6 7 8 9 : a m 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x0061, 0x006D, // 5 6 7 8 9 : a m
0x0070, // p 0x0070, // p
//*/ //*/
// More characters, change next line to //* to use // More characters for TFT_eSPI test sketches, change next line to //* to use
/* /*
0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x010C, 0x010D, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x010C, 0x010D,
0x010E, 0x010F, 0x0110, 0x0111, 0x0118, 0x0119, 0x011A, 0x011B, 0x010E, 0x010F, 0x0110, 0x0111, 0x0118, 0x0119, 0x011A, 0x011B,
@@ -337,8 +359,8 @@ static final int[] specificUnicodes = {
//*/ //*/
}; };
// >>>>>>>>>> USER CONFIGURED PARAMETERS END HERE <<<<<<<<<< // >>>>>>>>>> USER CONFIGURED PARAMETERS END HERE <<<<<<<<<<
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
// Variable to hold the inclusive Unicode range (16 bit values only for this sketch) // Variable to hold the inclusive Unicode range (16 bit values only for this sketch)
@@ -347,7 +369,10 @@ int lastUnicode = 0;
PFont myFont; PFont myFont;
PrintWriter logOutput;
void setup() { void setup() {
logOutput = createWriter("FontFiles/System_Font_List.txt");
size(1000, 800); size(1000, 800);
@@ -355,6 +380,15 @@ void setup() {
String[] fontList = PFont.list(); String[] fontList = PFont.list();
printArray(fontList); printArray(fontList);
// Save font list to file
for (int x = 0; x < fontList.length; x++)
{
logOutput.print("[" + x + "] ");
logOutput.println(fontList[x]);
}
logOutput.flush(); // Writes the remaining data to the file
logOutput.close(); // Finishes the file
// Set the fontName from the array number or the defined fontName // Set the fontName from the array number or the defined fontName
if (fontNumber >= 0) if (fontNumber >= 0)
{ {
@@ -410,19 +444,19 @@ void setup() {
} }
} }
// loading the range specified // loading the specific point codes
for (int i = 0; i < specificUnicodes.length; i++) { for (int i = 0; i < specificUnicodes.length; i++) {
charset[index] = Character.toChars(specificUnicodes[i])[0]; charset[index] = Character.toChars(specificUnicodes[i])[0];
index++; index++;
} }
// Make font smooth // Make font smooth (anti-aliased)
boolean smooth = true; boolean smooth = true;
// Create the font in memory // Create the font in memory
myFont = createFont(fontName+fontType, displayFontSize, smooth, charset); myFont = createFont(fontName+fontType, displayFontSize, smooth, charset);
// Print a few characters to the sketch window // Print characters to the sketch window
fill(0, 0, 0); fill(0, 0, 0);
textFont(myFont); textFont(myFont);
@@ -444,10 +478,10 @@ void setup() {
int unicode = charset[index]; int unicode = charset[index];
float cwidth = textWidth((char)unicode) + 2; float cwidth = textWidth((char)unicode) + 2;
if ( (x + cwidth) > (width - gapx) ) break; if ( (x + cwidth) > (width - gapx) ) break;
// Draw the letter to the screen // Draw the glyph to the screen
text(new String(Character.toChars(unicode)), x, y); text(new String(Character.toChars(unicode)), x, y);
// Move cursor // Move cursor
x += cwidth; x += cwidth;
// Increment the counter // Increment the counter
@@ -458,12 +492,12 @@ void setup() {
} }
// creating font // creating font to save as a file
PFont font; PFont font;
font = createFont(fontName+fontType, fontSize, smooth, charset); font = createFont(fontName+fontType, fontSize, smooth, charset);
println("Created font " + fontName + str(fontSize) + ".vlw"); println("Created font " + fontName + str(fontSize) + ".vlw");
// creating file // creating file
try { try {
@@ -486,4 +520,4 @@ void setup() {
catch(IOException e) { catch(IOException e) {
println("Doh! Failed to create the file"); println("Doh! Failed to create the file");
} }
} }

View File

@@ -41,8 +41,8 @@ void loop(void) {
tft.getSetup(user); // tft.getSetup(user); //
Serial.printf("\n[code]\n"); Serial.printf("\n[code]\n");
String ver = user.version;
Serial.println("TFT_eSPI ver = " + ver +"\n"); Serial.printf("TFT_eSPI ver = " + user.version) +"\n");
Serial.printf("Processor = ESP%i\n", user.esp, HEX); Serial.printf("Processor = ESP%i\n", user.esp, HEX);
Serial.printf("Frequency = %i MHz\n", ESP.getCpuFreqMHz()); Serial.printf("Frequency = %i MHz\n", ESP.getCpuFreqMHz());
#ifdef ESP8266 #ifdef ESP8266

View File

@@ -1,6 +1,6 @@
{ {
"name": "TFT_eSPI", "name": "TFT_eSPI",
"version": "1.4.3", "version": "1.4.4",
"keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789",
"description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32",
"repository": "repository":

View File

@@ -1,5 +1,5 @@
name=TFT_eSPI name=TFT_eSPI
version=1.4.3 version=1.4.4
author=Bodmer author=Bodmer
maintainer=Bodmer maintainer=Bodmer
sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE