Commit 61dfb2b4 authored by Bodmer's avatar Bodmer

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.
parent 7479f7e6
......@@ -246,6 +246,7 @@ void TFT_eSPI::unloadFont( void )
** Function name: decodeUTF8
** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII
*************************************************************************************x*/
/* Function moved to TFT_eSPI.cpp
#define DECODE_UTF8
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
}
*/
/***************************************************************************************
** Function name: decodeUTF8
** Description: Serial UTF-8 decoder with fall-back to extended ASCII
*************************************************************************************x*/
/* Function moved to TFT_eSPI.cpp
uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
{
......@@ -329,6 +332,7 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
decoderState = 0;
return (uint16_t)c; // fall-back to extended ASCII
}
*/
......
......@@ -13,6 +13,7 @@
Bodmer: Added RPi 16 bit display support
****************************************************/
#include "TFT_eSPI.h"
#if defined (ESP32)
......@@ -85,7 +86,7 @@ inline void TFT_eSPI::spi_end_read(void){
#if !defined(ESP32_PARALLEL)
spi.setFrequency(SPI_FREQUENCY);
#endif
CS_H;
if(!inTransaction) CS_H;
#endif
#ifdef ESP8266
SPI1U = SPI1U_WRITE;
......@@ -342,17 +343,6 @@ void TFT_eSPI::init(uint8_t tc)
writecommand(TFT_SWRST); // Software reset
#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();
delay(150); // Wait for reset to complete
......@@ -407,6 +397,17 @@ void TFT_eSPI::init(uint8_t tc)
spi_end();
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)
{
uniCode = *(string++);
uniCode = decodeUTF8(*string++);
if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last )))
{
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
** Description: draw characters piped through serial stream
......@@ -4008,6 +4098,8 @@ size_t TFT_eSPI::write(uint8_t utf8)
} // Custom GFX font
else
{
uniCode = (uint8_t)decodeUTF8(utf8);
if (!uniCode) return 1;
if(utf8 == '\n') {
cursor_x = 0;
......@@ -4046,14 +4138,17 @@ size_t TFT_eSPI::write(uint8_t utf8)
** Function name: drawChar
** 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)
{
#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;
// 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) ))
{
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
#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
// Switch on debugging for the padding areas
//#define PADDING_DEBUG
......
/*
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);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"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",
"description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32",
"repository":
......
name=TFT_eSPI
version=1.4.2
version=1.4.3
author=Bodmer
maintainer=Bodmer
sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment