mirror of
https://github.com/Bodmer/TFT_eSPI.git
synced 2025-08-09 23:54:43 +02:00
Extended character set suport for Adafruit_GFX format fonts
Supports Adafruit_GFX compatible font format with characters in the range 32-255. Note that the font rendering functions expect UTF-8 encoded characters/strings.
This commit is contained in:
@@ -246,6 +246,7 @@ void TFT_eSPI::unloadFont( void )
|
|||||||
** Function name: decodeUTF8
|
** Function name: decodeUTF8
|
||||||
** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII
|
** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII
|
||||||
*************************************************************************************x*/
|
*************************************************************************************x*/
|
||||||
|
/* Function moved to TFT_eSPI.cpp
|
||||||
#define DECODE_UTF8
|
#define DECODE_UTF8
|
||||||
uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
|
uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
|
||||||
{
|
{
|
||||||
@@ -273,11 +274,13 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
|
|||||||
|
|
||||||
return c; // fall-back to extended ASCII
|
return c; // fall-back to extended ASCII
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: decodeUTF8
|
** Function name: decodeUTF8
|
||||||
** Description: Serial UTF-8 decoder with fall-back to extended ASCII
|
** Description: Serial UTF-8 decoder with fall-back to extended ASCII
|
||||||
*************************************************************************************x*/
|
*************************************************************************************x*/
|
||||||
|
/* Function moved to TFT_eSPI.cpp
|
||||||
uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
|
uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -329,6 +332,7 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
|
|||||||
decoderState = 0;
|
decoderState = 0;
|
||||||
return (uint16_t)c; // fall-back to extended ASCII
|
return (uint16_t)c; // fall-back to extended ASCII
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
142
TFT_eSPI.cpp
142
TFT_eSPI.cpp
@@ -13,6 +13,7 @@
|
|||||||
Bodmer: Added RPi 16 bit display support
|
Bodmer: Added RPi 16 bit display support
|
||||||
****************************************************/
|
****************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include "TFT_eSPI.h"
|
#include "TFT_eSPI.h"
|
||||||
|
|
||||||
#if defined (ESP32)
|
#if defined (ESP32)
|
||||||
@@ -85,7 +86,7 @@ inline void TFT_eSPI::spi_end_read(void){
|
|||||||
#if !defined(ESP32_PARALLEL)
|
#if !defined(ESP32_PARALLEL)
|
||||||
spi.setFrequency(SPI_FREQUENCY);
|
spi.setFrequency(SPI_FREQUENCY);
|
||||||
#endif
|
#endif
|
||||||
CS_H;
|
if(!inTransaction) CS_H;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
SPI1U = SPI1U_WRITE;
|
SPI1U = SPI1U_WRITE;
|
||||||
@@ -342,17 +343,6 @@ void TFT_eSPI::init(uint8_t tc)
|
|||||||
writecommand(TFT_SWRST); // Software reset
|
writecommand(TFT_SWRST); // Software reset
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON)
|
|
||||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
|
|
||||||
pinMode(TFT_BL, OUTPUT);
|
|
||||||
#else
|
|
||||||
#if defined (TFT_BL) && defined (M5STACK)
|
|
||||||
// Turn on the back-light LED
|
|
||||||
digitalWrite(TFT_BL, HIGH);
|
|
||||||
pinMode(TFT_BL, OUTPUT);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
spi_end();
|
spi_end();
|
||||||
|
|
||||||
delay(150); // Wait for reset to complete
|
delay(150); // Wait for reset to complete
|
||||||
@@ -407,6 +397,17 @@ void TFT_eSPI::init(uint8_t tc)
|
|||||||
spi_end();
|
spi_end();
|
||||||
|
|
||||||
setRotation(rotation);
|
setRotation(rotation);
|
||||||
|
|
||||||
|
#if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON)
|
||||||
|
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
|
||||||
|
pinMode(TFT_BL, OUTPUT);
|
||||||
|
#else
|
||||||
|
#if defined (TFT_BL) && defined (M5STACK)
|
||||||
|
// Turn on the back-light LED
|
||||||
|
digitalWrite(TFT_BL, HIGH);
|
||||||
|
pinMode(TFT_BL, OUTPUT);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2324,7 +2325,7 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font)
|
|||||||
{
|
{
|
||||||
while (*string)
|
while (*string)
|
||||||
{
|
{
|
||||||
uniCode = *(string++);
|
uniCode = decodeUTF8(*string++);
|
||||||
if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last )))
|
if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last )))
|
||||||
{
|
{
|
||||||
uniCode -= pgm_read_byte(&gfxFont->first);
|
uniCode -= pgm_read_byte(&gfxFont->first);
|
||||||
@@ -3895,6 +3896,95 @@ void TFT_eSPI::invertDisplay(boolean i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: decodeUTF8
|
||||||
|
** Description: Serial UTF-8 decoder with fall-back to extended ASCII
|
||||||
|
*************************************************************************************x*/
|
||||||
|
#define DECODE_UTF8 // Test only, comment out to stop decoding
|
||||||
|
uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
|
||||||
|
{
|
||||||
|
#ifdef DECODE_UTF8
|
||||||
|
// 7 bit Unicode Code Point
|
||||||
|
if ((c & 0x80) == 0x00) {
|
||||||
|
decoderState = 0;
|
||||||
|
return (uint16_t)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoderState == 0)
|
||||||
|
{
|
||||||
|
// 11 bit Unicode Code Point
|
||||||
|
if ((c & 0xE0) == 0xC0)
|
||||||
|
{
|
||||||
|
decoderBuffer = ((c & 0x1F)<<6);
|
||||||
|
decoderState = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 16 bit Unicode Code Point
|
||||||
|
if ((c & 0xF0) == 0xE0)
|
||||||
|
{
|
||||||
|
decoderBuffer = ((c & 0x0F)<<12);
|
||||||
|
decoderState = 2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 21 bit Unicode Code Point not supported so fall-back to extended ASCII
|
||||||
|
if ((c & 0xF8) == 0xF0) return (uint16_t)c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (decoderState == 2)
|
||||||
|
{
|
||||||
|
decoderBuffer |= ((c & 0x3F)<<6);
|
||||||
|
decoderState--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decoderBuffer |= (c & 0x3F);
|
||||||
|
decoderState = 0;
|
||||||
|
return decoderBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decoderState = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (uint16_t)c; // fall-back to extended ASCII
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: decodeUTF8
|
||||||
|
** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII
|
||||||
|
*************************************************************************************x*/
|
||||||
|
uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
|
||||||
|
{
|
||||||
|
byte c = buf[(*index)++];
|
||||||
|
//Serial.print("Byte from string = 0x"); Serial.println(c, HEX);
|
||||||
|
|
||||||
|
#ifdef DECODE_UTF8
|
||||||
|
// 7 bit Unicode
|
||||||
|
if ((c & 0x80) == 0x00) return c;
|
||||||
|
|
||||||
|
// 11 bit Unicode
|
||||||
|
if (((c & 0xE0) == 0xC0) && (remaining > 1))
|
||||||
|
return ((c & 0x1F)<<6) | (buf[(*index)++]&0x3F);
|
||||||
|
|
||||||
|
// 16 bit Unicode
|
||||||
|
if (((c & 0xF0) == 0xE0) && (remaining > 2))
|
||||||
|
{
|
||||||
|
c = ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6);
|
||||||
|
return c | ((buf[(*index)++]&0x3F));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 21 bit Unicode not supported so fall-back to extended ASCII
|
||||||
|
// if ((c & 0xF8) == 0xF0) return c;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c; // fall-back to extended ASCII
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: write
|
** Function name: write
|
||||||
** Description: draw characters piped through serial stream
|
** Description: draw characters piped through serial stream
|
||||||
@@ -4008,6 +4098,8 @@ 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;
|
||||||
@@ -4046,14 +4138,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 onto the screen
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y)
|
int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
return drawChar(uniCode, x, y, textfont);
|
return drawChar(utf8, x, y, textfont);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
uint16_t uniCode = decodeUTF8(utf8);
|
||||||
|
if (!uniCode) return 0;
|
||||||
|
|
||||||
if (font==1)
|
if (font==1)
|
||||||
{
|
{
|
||||||
#ifdef LOAD_GLCD
|
#ifdef LOAD_GLCD
|
||||||
@@ -4458,7 +4553,12 @@ 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 = *string;
|
uint8_t c2 = 0;
|
||||||
|
uint16_t len = strlen(string);
|
||||||
|
uint16_t n = 0;
|
||||||
|
|
||||||
|
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_byte(&gfxFont->first)) && (c2 <= pgm_read_byte(&gfxFont->last) ))
|
||||||
{
|
{
|
||||||
c2 -= pgm_read_byte(&gfxFont->first);
|
c2 -= pgm_read_byte(&gfxFont->first);
|
||||||
@@ -4498,8 +4598,12 @@ 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);
|
Serial.print("sumX=");
|
||||||
|
while (*string) {
|
||||||
|
sumX += drawChar(*(string++), poX+sumX, poY, font);
|
||||||
|
Serial.print(sumX);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||||
// Switch on debugging for the padding areas
|
// Switch on debugging for the padding areas
|
||||||
//#define PADDING_DEBUG
|
//#define PADDING_DEBUG
|
||||||
|
123
examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino
Normal file
123
examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
Example for TFT_eSPI library
|
||||||
|
|
||||||
|
This example shows the use of a Adafruit_GFX custom font with a
|
||||||
|
character code range of 32 - 255, this means accented characters
|
||||||
|
(amongst others) are available.
|
||||||
|
|
||||||
|
The custom font file is attached to this sketch as a header file. The
|
||||||
|
font data has been created following the instructions here:
|
||||||
|
https://www.youtube.com/watch?v=L8MmTISmwZ8
|
||||||
|
|
||||||
|
Note that online converters for Adafruit_GFX compatible fonts are
|
||||||
|
available but these typically only use characters in the range 32-127,
|
||||||
|
and thus do not include the accented characters. These online converters
|
||||||
|
can however still be used with this sketch but the example characters
|
||||||
|
used must be changed.
|
||||||
|
|
||||||
|
The Arduino IDE uses UTF8 encoding for these characters. The TFT_eSPI
|
||||||
|
library also expects characters in the range 128 to 255 to be UTF-8
|
||||||
|
encoded. See link here for details:
|
||||||
|
|
||||||
|
https://playground.arduino.cc/Code/UTF-8
|
||||||
|
|
||||||
|
To sumarise, UTF-8 characters are encoded as mor than 1 byte so care must
|
||||||
|
be taken:
|
||||||
|
|
||||||
|
char c = 'µ'; // Wrong
|
||||||
|
char bad[4] = "5µA"; // Wrong
|
||||||
|
char good[] = "5µA"; // Good
|
||||||
|
String okay = "5µA"; // Good
|
||||||
|
|
||||||
|
Created by Bodmer 08/02/19
|
||||||
|
|
||||||
|
Make sure LOAD_GFXFF is defined in the used User_Setup file
|
||||||
|
within the library folder.
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
|
||||||
|
###### TO SELECT YOUR DISPLAY TYPE, PINS USED AND ENABLE FONTS ######
|
||||||
|
#########################################################################
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TEST_TEXT "ßäöü ñâàå" // Text that will be printed on screen in the font
|
||||||
|
//#define TEST_TEXT "Hello" // Text that will be printed on screen in the font
|
||||||
|
|
||||||
|
#include "SPI.h"
|
||||||
|
#include "TFT_eSPI.h"
|
||||||
|
#include "TFT_eFEX.h"
|
||||||
|
|
||||||
|
// The custom font file attached to this sketch must be included
|
||||||
|
#include "MyFont.h"
|
||||||
|
|
||||||
|
// Stock font and GFXFF reference handle
|
||||||
|
#define GFXFF 1
|
||||||
|
|
||||||
|
// Easily remembered name for the font
|
||||||
|
#define MYFONT32 &myFont32pt8b
|
||||||
|
|
||||||
|
// Use hardware SPI
|
||||||
|
TFT_eSPI tft = TFT_eSPI();
|
||||||
|
TFT_eFEX fex = TFT_eFEX(&tft);
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
|
||||||
|
Serial.begin(250000);
|
||||||
|
|
||||||
|
tft.begin();
|
||||||
|
|
||||||
|
tft.setRotation(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||||
|
// Show custom fonts
|
||||||
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||||
|
|
||||||
|
// Where font sizes increase the screen is not cleared as the larger fonts overwrite
|
||||||
|
// the smaller one with the background colour.
|
||||||
|
|
||||||
|
// We can set the text datum to be Top, Middle, Bottom vertically and Left, Centre
|
||||||
|
// and Right horizontally. These are the text datums that can be used:
|
||||||
|
// TL_DATUM = Top left (default)
|
||||||
|
// TC_DATUM = Top centre
|
||||||
|
// TR_DATUM = Top right
|
||||||
|
// ML_DATUM = Middle left
|
||||||
|
// MC_DATUM = Middle centre <<< This is used below
|
||||||
|
// MR_DATUM = Middle right
|
||||||
|
// BL_DATUM = Bottom left
|
||||||
|
// BC_DATUM = Bottom centre
|
||||||
|
// BR_DATUM = Bottom right
|
||||||
|
// L_BASELINE = Left character baseline (Line the 'A' character would sit on)
|
||||||
|
// C_BASELINE = Centre character baseline
|
||||||
|
// R_BASELINE = Right character baseline
|
||||||
|
|
||||||
|
//Serial.println();
|
||||||
|
|
||||||
|
// Set text datum to middle centre (MC_DATUM)
|
||||||
|
tft.setTextDatum(MC_DATUM);
|
||||||
|
|
||||||
|
// Set text colour to white with black background
|
||||||
|
// Unlike the stock Adafruit_GFX library, the TFT_eSPI library DOES optionally draw
|
||||||
|
// the background colour for the custom and Free Fonts when using drawString()
|
||||||
|
tft.setTextColor(TFT_WHITE, TFT_BLACK); // White characters on black background
|
||||||
|
//tft.setTextColor(TFT_WHITE); // or white characters, no background
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLUE); // Clear screen
|
||||||
|
tft.setFreeFont(MYFONT32); // Select the font
|
||||||
|
tft.drawString("MyFont 32", 160, 60, GFXFF); // Print the name of the font
|
||||||
|
tft.setFreeFont(MYFONT32); // Select the font
|
||||||
|
tft.drawString(TEST_TEXT, 160, 140, GFXFF); // Print the test text in the custom font
|
||||||
|
delay(2000);
|
||||||
|
fex.screenServer();
|
||||||
|
// Setting textDatum does nothing when using tft.print
|
||||||
|
tft.fillScreen(TFT_BLUE); // Clear screen
|
||||||
|
tft.setCursor(0,60); // To be compatible with Adafruit_GFX the cursor datum is always bottom left
|
||||||
|
tft.print("âäàå"); // Using tft.print means text background is NEVER rendered
|
||||||
|
delay(2000);
|
||||||
|
|
||||||
|
// Reset text padding to zero (default)
|
||||||
|
tft.setTextPadding(0);
|
||||||
|
}
|
3366
examples/Generic/Local_Custom_Fonts/MyFont.h
Normal file
3366
examples/Generic/Local_Custom_Fonts/MyFont.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "TFT_eSPI",
|
"name": "TFT_eSPI",
|
||||||
"version": "1.4.2",
|
"version": "1.4.3",
|
||||||
"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":
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
name=TFT_eSPI
|
name=TFT_eSPI
|
||||||
version=1.4.2
|
version=1.4.3
|
||||||
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
|
||||||
|
Reference in New Issue
Block a user