Commit 1a0b3709 authored by Bodmer's avatar Bodmer

Add new anti-aliased (smooth) font examples + bug fixes

Four new examples have been added to show different methods of rendering
the anta-aliased fonts.  A few minor bugs have been corrected associated
with the font rendering. drawNumber and drawFloat handle fixed width
mono fonts with no digit movement.
parent 22177cf2
......@@ -424,7 +424,7 @@ void TFT_eSPI::drawGlyph(uint16_t code)
uint8_t pbuffer[gWidth[gNum]];
uint16_t xs = 0;
int16_t xs = 0;
uint32_t dl = 0;
int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum];
......
......@@ -13,7 +13,8 @@
uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc);
void drawGlyph(uint16_t code);
virtual void drawGlyph(uint16_t code);
void showFont(uint32_t td);
fs::File fontFile;
......
......@@ -1511,7 +1511,7 @@ void TFT_eSprite::drawGlyph(uint16_t code)
uint8_t pbuffer[this->gWidth[gNum]];
uint16_t xs = 0;
int16_t xs = 0;
uint16_t dl = 0;
for (int y = 0; y < this->gHeight[gNum]; y++)
......@@ -1525,7 +1525,8 @@ void TFT_eSprite::drawGlyph(uint16_t code)
if (pixel != 0xFF)
{
if (dl) { drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); dl = 0; }
if (pixel>127) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], alphaBlend(pixel, fg, bg));
if (_bpp != 1) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], alphaBlend(pixel, fg, bg));
else if (pixel>127) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], fg);
}
else
{
......
......@@ -172,6 +172,7 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
textcolor = bitmap_fg = 0xFFFF; // White
textbgcolor = bitmap_bg = 0x0000; // Black
padX = 0; // No padding
isDigits = false; // No bounding box adjustment
textwrapX = true; // Wrap text at end of line when using print stream
textwrapY = false; // Wrap text at bottom of screen when using print stream
textdatum = TL_DATUM; // Top Left text alignment is default
......@@ -1548,7 +1549,7 @@ void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t corne
** Function name: drawEllipse
** Description: Draw a ellipse outline
***************************************************************************************/
void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color)
void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color)
{
if (rx<2) return;
if (ry<2) return;
......@@ -1603,7 +1604,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint1
** Function name: fillEllipse
** Description: draw a filled ellipse
***************************************************************************************/
void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color)
void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color)
{
if (rx<2) return;
if (ry<2) return;
......@@ -2102,13 +2103,14 @@ int16_t TFT_eSPI::textWidth(const char *string, int font)
if (found)
{
if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum];
if (*string) str_width += gxAdvance[gNum];
if (*string || isDigits) str_width += gxAdvance[gNum];
else str_width += (gdX[gNum] + gWidth[gNum]);
}
else str_width += gFont.spaceWidth + 1;
}
}
}
isDigits = false;
return str_width;
}
#endif
......@@ -2141,8 +2143,8 @@ int16_t TFT_eSPI::textWidth(const char *string, int font)
{
uniCode -= pgm_read_byte(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]);
// If this is not the last character then use xAdvance
if (*string) str_width += pgm_read_byte(&glyph->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);
// Else use the offset plus width since this can be bigger than xAdvance
else str_width += ((int8_t)pgm_read_byte(&glyph->xOffset) + pgm_read_byte(&glyph->width));
}
......@@ -2156,6 +2158,7 @@ int16_t TFT_eSPI::textWidth(const char *string, int font)
#endif
}
}
isDigits = false;
return str_width * textsize;
}
......@@ -3715,11 +3718,11 @@ size_t TFT_eSPI::write(uint8_t utf8)
//fontFile = SPIFFS.open( _gFontFilename, "r" );
if(!fontFile)
{
fontLoaded = false;
return 0;
}
//if(!fontFile)
//{
// fontLoaded = false;
// return 0;
//}
drawGlyph(unicode);
......@@ -4147,6 +4150,7 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY)
{
return drawString(string, poX, poY, textfont);
}
// With font number
int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font)
{
......@@ -4171,16 +4175,13 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font)
}
#endif
if (textdatum || padX)
{
// If it is not font 1 (GLCD or free font) get the baseline and pixel height of the font
#ifdef SMOOTH_FONT
if(fontLoaded) {
baseline = gFont.maxAscent;
cheight = fontHeight(0);
cheight = fontHeight();
}
else
#endif
if (font!=1) {
......@@ -4188,6 +4189,9 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font)
cheight = fontHeight(font);
}
if (textdatum || padX)
{
switch(textdatum) {
case TC_DATUM:
poX -= cwidth/2;
......@@ -4418,6 +4422,7 @@ int16_t TFT_eSPI::drawRightString(const char *string, int dX, int poY, int font)
***************************************************************************************/
int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY)
{
isDigits = true; // Eliminate jiggle in monospaced fonts
char str[12];
ltoa(long_num, str, 10);
return drawString(str, poX, poY, textfont);
......@@ -4425,6 +4430,7 @@ int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY)
int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY, int font)
{
isDigits = true; // Eliminate jiggle in monospaced fonts
char str[12];
ltoa(long_num, str, 10);
return drawString(str, poX, poY, font);
......@@ -4444,6 +4450,7 @@ int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY)
int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY, int font)
{
isDigits = true;
char str[14]; // Array to contain decimal string
uint8_t ptr = 0; // Initialise pointer for array
int8_t digits = 1; // Count the digits to avoid array overflow
......@@ -4572,7 +4579,7 @@ void TFT_eSPI::setTextFont(uint8_t f)
/***************************************************************************************
** Function name: spiBlockWrite
** Function name: writeBlock
** Description: Write a block of pixels of the same colour
***************************************************************************************/
//Clear screen test 76.8ms theoretical. 81.5ms TFT_eSPI, 967ms Adafruit_ILI9341
......@@ -4964,6 +4971,10 @@ void TFT_eSPI::getSetup(setup_t &tft_settings)
#include "Extensions/Sprite.cpp"
// #ifdef ESP32
// #include "Extensions/pSprite.cpp"
// #endif
#ifdef SMOOTH_FONT
#include "Extensions/Smooth_font.cpp"
#endif
......
......@@ -562,8 +562,8 @@ class TFT_eSPI : public Print {
fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color),
fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, int32_t delta, uint32_t color),
drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color),
fillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color),
drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color),
fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color),
drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color),
fillTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color),
......@@ -719,6 +719,7 @@ class TFT_eSPI : public Print {
uint8_t glyph_ab, // glyph height above baseline
glyph_bb; // glyph height below baseline
bool isDigits; // adjust bounding box for numbers to reduce visual jiggling
bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display
bool _swapBytes; // Swap the byte order for TFT pushImage()
bool locked, inTransaction; // Transaction and mutex lock flags for ESP32
......@@ -749,4 +750,9 @@ class TFT_eSPI : public Print {
// Load the Sprite Class
#include "Extensions/Sprite.h"
// #ifdef ESP32
// // Load the Sprite Class
// #include "Extensions/pSprite.h"
// #endif
#endif
......@@ -236,7 +236,8 @@
// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS
// #define SPI_FREQUENCY 80000000
#define SPI_READ_FREQUENCY 20000000 // Optional reduced SPI frequency for reading TFT
// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY 20000000
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY 2500000
......
......@@ -43,6 +43,8 @@
//#include <User_Setups/Setup20_ILI9488.h> // Setup file for ESP8266 and ILI9488 SPI bus TFT
//#include <User_Setups/Setup21_ILI9488.h> // Setup file for ESP32 and ILI9488 SPI bus TFT
//#include <User_Setups/Setup43_ST7735.h> // Setup file configured for my ST7735S 80x160
//#include <User_Setups/SetupX_Template.h>
......
......@@ -197,10 +197,12 @@
// #define SPI_FREQUENCY 5000000
// #define SPI_FREQUENCY 10000000
// #define SPI_FREQUENCY 20000000
#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS
// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
#define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS
// #define SPI_FREQUENCY 80000000
#define SPI_READ_FREQUENCY 20000000
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY 2500000
......
......@@ -19,6 +19,9 @@
//#define ILI9163_DRIVER
//#define S6D02A1_DRIVER
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
//#define HX8357D_DRIVER
//#define ILI9481_DRIVER
//#define ILI9486_DRIVER
#define ILI9488_DRIVER
// For M5Stack ESP32 module with integrated display ONLY, remove // in line below
......
/*
There are four different methods of plotting anti-aliased fonts to the screen.
This sketch uses method 1, using tft.print() and tft.println() calls.
In some cases the sketch shows what can go wrong too, so read the comments!
The font is rendered WITHOUT a background, but a background colour needs to be
set so the anti-aliasing of the character is performed correctly. This is because
characters are drawn one by one.
This method is good for static text that does not change often because changing
values may flicker. The text appears at the tft cursor coordinates.
It is also possible to "print" text directly into a created sprite, for example using
spr.println("Hello"); and then push the sprite to the screen. That method is not
demonstrated in this sketch.
*/
// The fonts used are in the sketch data folder, press Ctrl+K to view.
// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the
// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE.
// To add this option follow instructions here for the ESP8266:
// https://github.com/esp8266/arduino-esp8266fs-plugin
// or for the ESP32:
// https://github.com/me-no-dev/arduino-esp32fs-plugin
// Close the IDE and open again to see the new menu option.
// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI
// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font
// This sketch uses font files created from the Noto family of fonts:
// https://www.google.com/get/noto/
#define AA_FONT_SMALL "NotoSansBold15"
#define AA_FONT_LARGE "NotoSansBold36"
// Font files are stored in SPIFFS, so load the linbrary
#include <FS.h>
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();
void setup(void) {
Serial.begin(250000);
tft.begin();
tft.setRotation(0);
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nSPIFFS available!");
}
void loop() {
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour AND the background colour
// so the anti-aliasing works
tft.setCursor(0, 0); // Set cursor at top left of screen
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Small font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tft.loadFont(AA_FONT_SMALL); // Must load the font first
tft.println("Small 15pt font"); // println moves cursor down for a new line
tft.println(); // New line
tft.print("ABC"); // print leaves cursor at end of line
tft.setTextColor(TFT_CYAN, TFT_BLACK);
tft.println("1234"); // Added to line after ABC
tft.setTextColor(TFT_YELLOW, TFT_BLACK);
// print stream formatting can be used,see:
// https://www.arduino.cc/en/Serial/Print
int ivalue = 1234;
tft.println(ivalue); // print as an ASCII-encoded decimal
tft.println(ivalue, DEC); // print as an ASCII-encoded decimal
tft.println(ivalue, HEX); // print as an ASCII-encoded hexadecimal
tft.println(ivalue, OCT); // print as an ASCII-encoded octal
tft.println(ivalue, BIN); // print as an ASCII-encoded binary
tft.println(); // New line
tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
float fvalue = 1.23456;
tft.println(fvalue, 0); // no decimal places
tft.println(fvalue, 1); // 1 decimal place
tft.println(fvalue, 2); // 2 decimal places
tft.println(fvalue, 5); // 5 decimal places
delay(5000);
// Get ready for the next demo while we have this font loaded
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0); // Set cursor at top left of screen
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println("Wrong and right ways to");
tft.println("print changing values...");
tft.unloadFont(); // Remove the font to recover memory used
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Large font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tft.loadFont(AA_FONT_LARGE); // Load another different font
//tft.fillScreen(TFT_BLACK);
// Draw changing numbers - does not work unless a filled rectangle is drawn over the old text
for (int i = 0; i <= 20; i++)
{
tft.setCursor(50, 50);
tft.print(" "); // Overprinting old number with spaces DOES NOT WORK!
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.setCursor(50, 50);
tft.print(i / 10.0, 1);
tft.fillRect (50, 90, 60, 40, TFT_BLACK); // Overprint with a filled rectangle
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.setCursor(50, 90);
tft.print(i / 10.0, 1);
delay (200);
}
delay(5000);
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Large font text wrapping
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_YELLOW, TFT_BLACK); // Change the font colour and the background colour
tft.setCursor(0, 0); // Set cursor at top left of screen
tft.println("Large font!");
tft.setTextWrap(true); // Wrap on width
tft.setTextColor(TFT_CYAN, TFT_BLACK);
tft.println("Long lines wrap to the next line");
tft.setTextWrap(false, false); // Wrap on width and height switched off
tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
tft.println("Unless text wrap is switched off");
tft.unloadFont(); // Remove the font to recover memory used
delay(8000);
}
/*
Information notes only:
======================
//These are the text plotting alignment (reference datum point)
TL_DATUM = Top left (default)
TC_DATUM = Top centre
TR_DATUM = Top right
ML_DATUM = Middle left
MC_DATUM = Middle centre
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
// Basic colours already defined:
TFT_BLACK 0x0000
TFT_NAVY 0x000F
TFT_DARKGREEN 0x03E0
TFT_DARKCYAN 0x03EF
TFT_MAROON 0x7800
TFT_PURPLE 0x780F
TFT_OLIVE 0x7BE0
TFT_LIGHTGREY 0xC618
TFT_DARKGREY 0x7BEF
TFT_BLUE 0x001F
TFT_GREEN 0x07E0
TFT_CYAN 0x07FF
TFT_RED 0xF800
TFT_MAGENTA 0xF81F
TFT_YELLOW 0xFFE0
TFT_WHITE 0xFFFF
TFT_ORANGE 0xFDA0
TFT_GREENYELLOW 0xB7E0
TFT_PINK 0xFC9F
*/
/*
There are four different methods of plotting anti-aliased fonts to the screen.
This sketch uses method 2, using graphics calls plotting direct to the TFT:
tft.drawString(string, x, y);
tft.drawNumber(integer, x, y);
tft.drawFloat(float, dp, x, y); // dp = number of decimal places
setTextDatum() and setTextPadding() functions work with those draw functions.
This method is good for static text that does not change often because changing
values may flicker.
*/
// The fonts used are in the sketch data folder, press Ctrl+K to view.
// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the
// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE.
// To add this option follow instructions here for the ESP8266:
// https://github.com/esp8266/arduino-esp8266fs-plugin
// or for the ESP32:
// https://github.com/me-no-dev/arduino-esp32fs-plugin
// Close the IDE and open again to see the new menu option.
// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI
// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font
// This sketch uses font files created from the Noto family of fonts:
// https://www.google.com/get/noto/
#define AA_FONT_SMALL "NotoSansBold15"
#define AA_FONT_LARGE "NotoSansBold36"
// Font files are stored in SPIFFS, so load the linbrary
#include <FS.h>
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();
void setup(void) {
Serial.begin(250000);
tft.begin();
tft.setRotation(1);
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nSPIFFS available!");
}
void loop() {
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour and the background colour
tft.setTextDatum(TC_DATUM); // Top Centre datum
int xpos = tft.width() / 2; // Half the screen width
int ypos = 10;
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Small font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tft.loadFont(AA_FONT_SMALL); // Must load the font first
tft.drawString("Small 15pt font", xpos, ypos);
ypos += tft.fontHeight(); // Get the font height and move ypos down
tft.setTextColor(TFT_GREEN, TFT_BLACK);
// If the string does not fit the screen width, then the next character will wrap to a new line
tft.drawString("Ode To A Small Lump Of Green Putty I Found In My Armpit One Midsummer Morning", xpos, ypos);
tft.setTextColor(TFT_GREEN, TFT_BLUE); // Background colour does not match the screen background!
tft.drawString("Anti-aliasing causes odd looking shadow effects if the text and screen background colours are not the same!", xpos, ypos + 60);
tft.unloadFont(); // Remove the font to recover memory used
delay(5000);
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Large font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tft.loadFont(AA_FONT_LARGE); // Load another different font
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_GREEN, TFT_BLUE); // Change the font colour and the background colour
tft.drawString("36pt font", xpos, ypos);
ypos += tft.fontHeight(); // Get the font height and move ypos down
// Set text padding to 100 pixels wide area to over-write old values on screen
tft.setTextPadding(100);
// Draw changing numbers - likely to flicker using this plot method!
for (int i = 0; i <= 20; i++) {
tft.drawFloat(i / 10.0, 1, xpos, ypos);
delay (200);
}
tft.unloadFont(); // Remove the font to recover memory used
delay(5000);
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Setting the 12 datum positions works with free fonts
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Integer numbers, floats and strings can be drawn relative to a x,y datum, e.g.:
// tft.drawNumber( 123, x, y);
// tft.drawFloat( 1.23, dp, x, y); // Where dp is number of decimal places to show
// tft.drawString( "Abc", x, y);
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
// Use middle of screen as datum
xpos = tft.width() /2;
ypos = tft.height()/2;
tft.loadFont(AA_FONT_SMALL);
tft.setTextDatum(TL_DATUM);
tft.drawString("[Top left]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(TC_DATUM);
tft.drawString("[Top centre]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(TR_DATUM);
tft.drawString("[Top right]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(ML_DATUM);
tft.drawString("[Middle left]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(MC_DATUM);
tft.drawString("[Middle centre]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(MR_DATUM);
tft.drawString("[Middle right]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(BL_DATUM);
tft.drawString("[Bottom left]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(BC_DATUM);
tft.drawString("[Bottom centre]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(BR_DATUM);
tft.drawString("[Bottom right]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(L_BASELINE);
tft.drawString("[Left baseline]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(C_BASELINE);
tft.drawString("[Centre baseline]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(R_BASELINE);
tft.drawString("[Right baseline]", xpos, ypos);
drawDatumMarker(160,120);
delay(1000);
tft.unloadFont(); // Remove the font to recover memory used
delay(4000);
}
// Draw a + mark centred on x,y
void drawDatumMarker(int x, int y)
{
tft.drawLine(x - 5, y, x + 5, y, TFT_GREEN);
tft.drawLine(x, y - 5, x, y + 5, TFT_GREEN);
}
/*
Information notes only:
======================
//These are the text plotting alignment (reference datum point)
TL_DATUM = Top left (default)
TC_DATUM = Top centre
TR_DATUM = Top right
ML_DATUM = Middle left
MC_DATUM = Middle centre
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
// Basic colours already defined:
TFT_BLACK 0x0000
TFT_NAVY 0x000F
TFT_DARKGREEN 0x03E0
TFT_DARKCYAN 0x03EF
TFT_MAROON 0x7800
TFT_PURPLE 0x780F
TFT_OLIVE 0x7BE0
TFT_LIGHTGREY 0xC618
TFT_DARKGREY 0x7BEF
TFT_BLUE 0x001F
TFT_GREEN 0x07E0
TFT_CYAN 0x07FF
TFT_RED 0xF800
TFT_MAGENTA 0xF81F
TFT_YELLOW 0xFFE0
TFT_WHITE 0xFFFF
TFT_ORANGE 0xFDA0
TFT_GREENYELLOW 0xB7E0
TFT_PINK 0xFC9F
*/
/*
There are four different methods of plotting anti-aliased fonts to the screen.
This sketch uses method 3, the font characters are first plotted in a Sprite, then the
Sprite is pushed to the screen. This method is very flexible and the Sprite can be
created, deleted, resized as needed. To render anit-aliased fonts well the Sprite
needs to be 16 bit. The fonts will render in 1 bit per pixel sprites but there
will then be no anti-aliasing. Using 1 bit per pixel Sprites is however useful
to use the extended Unicode range in fonts on mono displays like ePaper.
A single Sprite can be re-used for plotting different values and graphics to
different positions on the screen. This makes this method a very powerful display tool,
for example round buttons can be created, making use of transparent colour plotting.
*/
// The fonts used are in the sketch data folder, press Ctrl+K to view.
// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the
// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE.
// To add this option follow instructions here for the ESP8266:
// https://github.com/esp8266/arduino-esp8266fs-plugin
// or for the ESP32:
// https://github.com/me-no-dev/arduino-esp32fs-plugin
// Close the IDE and open again to see the new menu option.
// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI
// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font
// This sketch uses font files created from the Noto family of fonts:
// https://www.google.com/get/noto/
#define AA_FONT_SMALL "NotoSansBold15"
#define AA_FONT_LARGE "NotoSansBold36"
#define AA_FONT_MONO "NotoSansMonoSCB20" // NotoSansMono-SemiCondensedBold 20pt
// Font files are stored in SPIFFS, so load the linbrary
#include <FS.h>
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite spr = TFT_eSprite(&tft); // Sprite class needs to be invoked
void setup(void) {
Serial.begin(250000);
tft.begin();
tft.setRotation(1);
spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nSPIFFS available!");
}
void loop() {
tft.fillScreen(TFT_DARKGREY);
int xpos = tft.width() / 2; // Half the screen width
int ypos = 50;
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Small font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
spr.loadFont(AA_FONT_SMALL); // Must load the font first into the sprite class
spr.createSprite(100, 50); // Create a sprite 100 pixels wide and 50 high
spr.fillSprite(TFT_BLUE);
spr.drawRect(0, 0, 100, 50, TFT_WHITE); // Draw sprite border outline (so we see extent)
spr.setTextColor(TFT_YELLOW, TFT_DARKGREY); // Set the sprite font colour and the background colour
spr.setTextDatum(MC_DATUM); // Middle Centre datum
spr.drawString("15pt font", 50, 25 ); // Coords of middle of 100 x 50 Sprite
spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10
spr.pushSprite(10, 70, TFT_BLUE); // Push to TFT screen, TFT_BLUE is transparent
spr.unloadFont(); // Remove the font from sprite class to recover memory used
delay(4000);
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Large font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tft.fillScreen(TFT_BLACK);
// Beware: Sprites are a differerent "class" to TFT, so different fonts can be loaded
// in the tft and sprite instances, so load the font in the class instance you use!
// In this example this means the spr. instance.
spr.loadFont(AA_FONT_LARGE); // Load another different font into the sprite instance
// 100 x 50 sprite was created above and still exists...
spr.fillSprite(TFT_GREEN);
spr.setTextColor(TFT_BLACK, TFT_GREEN); // Set the font colour and the background colour
spr.setTextDatum(MC_DATUM); // Middle Centre datum
spr.drawString("Fits", 50, 25); // Make sure text fits in the Sprite!
spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10
spr.fillSprite(TFT_RED);
spr.setTextColor(TFT_WHITE, TFT_RED); // Set the font colour and the background colour
spr.drawString("Too big", 50, 25); // Text is too big to all fit in the Sprite!
spr.pushSprite(10, 70); // Push to TFT screen coord 10, 70
// Draw changing numbers - no flicker using this plot method!
// >>>> Note: it is best to use drawNumber() and drawFloat() for numeric values <<<<
// >>>> this reduces digit position movement when the value changes <<<<
// >>>> drawNumber() and drawFloat() functions behave like drawString() and are <<<<
// >>>> supported by setTextDatum() and setTextPadding() <<<<
spr.setTextDatum(TC_DATUM); // Top Centre datum
spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour
for (int i = 0; i <= 200; i++) {
spr.fillSprite(TFT_BLUE);
spr.drawFloat(i / 100.0, 2, 50, 10); // draw with 2 decimal places at 50,10 in sprite
spr.pushSprite(10, 130); // Push to TFT screen coord 10, 130
delay (20);
}
spr.unloadFont(); // Remove the font to recover memory used
spr.deleteSprite(); // Recover memory
delay(1000);
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Mono spaced font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
spr.loadFont(AA_FONT_MONO); // Mono spaced fonts have fixed intercharacter gaps to
// aid formatting
int bnum = 1;
// Example of drawing buttons
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 4; k++)
{
int x = 120 + k * 45;
int y = 40 + j * 30;
button(x, y, bnum++);
}
}
for (int i = 0; i < 100; i++)
{
button(120, 160, i);
delay(50);
}
spr.unloadFont();
delay(8000);
}
// #########################################################################
// Draw a number in a rounded rectangle with some transparent pixels
// Load the font before calling
// #########################################################################
void button(int x, int y, int num )
{
// Size of sprite
#define IWIDTH 40
#define IHEIGHT 25
// Create a 16 bit sprite 40 pixels wide, 25 high (2000 bytes of RAM needed)
spr.setColorDepth(16);
spr.createSprite(IWIDTH, IHEIGHT);
// Fill it with black (this will be the transparent colour this time)
spr.fillSprite(TFT_BLACK);
// Draw a background for the numbers
spr.fillRoundRect( 0, 0, IWIDTH, IHEIGHT, 8, TFT_RED);
spr.drawRoundRect( 0, 0, IWIDTH, IHEIGHT, 8, TFT_WHITE);
// Set the font parameters
// Set text coordinate datum to middle centre
spr.setTextDatum(MC_DATUM);
// Set the font colour and the background colour
spr.setTextColor(TFT_WHITE, TFT_RED);
// Draw the number
spr.drawNumber(num, IWIDTH/2, 1 + IHEIGHT/2);
// Push sprite to TFT screen CGRAM at coordinate x,y (top left corner)
// All black pixels will not be drawn hence will show as "transparent"
spr.pushSprite(x, y, TFT_BLACK);
// Delete sprite to free up the RAM
spr.deleteSprite();
}
/*
Information notes only:
======================
Note: it is best to use drawNumber() and drawFloat() for numeric values
this reduces digit position movement when the value changes
drawNumber() and drawFloat() functions behave like drawString() and are
supported by setTextDatum() and setTextPadding()
//These are the text plotting alignment (reference datum point)
TL_DATUM = Top left (default)
TC_DATUM = Top centre
TR_DATUM = Top right
ML_DATUM = Middle left
MC_DATUM = Middle centre
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
// Basic colours already defined:
TFT_BLACK 0x0000
TFT_NAVY 0x000F
TFT_DARKGREEN 0x03E0
TFT_DARKCYAN 0x03EF
TFT_MAROON 0x7800
TFT_PURPLE 0x780F
TFT_OLIVE 0x7BE0
TFT_LIGHTGREY 0xC618
TFT_DARKGREY 0x7BEF
TFT_BLUE 0x001F
TFT_GREEN 0x07E0
TFT_CYAN 0x07FF
TFT_RED 0xF800
TFT_MAGENTA 0xF81F
TFT_YELLOW 0xFFE0
TFT_WHITE 0xFFFF
TFT_ORANGE 0xFDA0
TFT_GREENYELLOW 0xB7E0
TFT_PINK 0xFC9F
*/
/*
There are four different methods of plotting anti-aliased fonts to the screen.
This sketch uses method 4, printing "String" or character array types only to screen,
via a Sprite. The Sprite must NOT have been created already. The printToSprite()
function automatically creates a sprite of a minimal size to contain the String,
then plots to screen at the "tft" cursor position. Printing via a sprite draws the
text faster on the screen. This method minimises flicker but uses RAM for the Sprite,
the Sprite is automatically deleted after plotting to the TFT.
Number and float types must be converted to strings to use printToSprite() e.g.:
spr.printToSprite( (String) number );
spr.printToSprite( (String) (number * 55 / 1.23) ); // Put calculations within brackets
The key advantage of this method is that you do not need to calculate the size of sprite
needed to contain the text, the library does that for you. The library also fills the
the sprite with text background colour for you.
printToSprite() has a second purpose, if the sprite has been created already the String
will be printed into the Sprite at the "sprite" cursor position, which is
different to the "tft" cursor position. In this case the Sprite is not deleted and
you must use pushSprite() to plot on the screen. This method is not used in this sketch.
because in general it is better to use drawString() in an already created sprite.
printToSprite() will NOT move the tft cursor.
*/
// The fonts used are in the sketch data folder, press Ctrl+K to view.
// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the
// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE.
// To add this option follow instructions here for the ESP8266:
// https://github.com/esp8266/arduino-esp8266fs-plugin
// or for the ESP32:
// https://github.com/me-no-dev/arduino-esp32fs-plugin
// Close the IDE and open again to see the new menu option.
// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI
// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font
// This sketch uses font files created from the Noto family of fonts:
// https://www.google.com/get/noto/
#define AA_FONT_SMALL "NotoSansBold15"
#define AA_FONT_LARGE "NotoSansBold36"
// Font files are stored in SPIFFS, so load the linbrary
#include <FS.h>
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite spr = TFT_eSprite(&tft); // Sprite class needs to be invoked
void setup(void) {
Serial.begin(250000);
tft.begin();
tft.setRotation(1);
spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nSPIFFS available!");
}
void loop() {
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour and the background colour
tft.setTextDatum(TC_DATUM); // Top Centre datum
int xpos = tft.width() / 2; // Half the screen width
int ypos = 50;
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Small font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
spr.loadFont(AA_FONT_SMALL); // Must load the font first into the sprite class
spr.setTextColor(TFT_YELLOW, TFT_BLACK); // Set the sprite font colour and the background colour
tft.setCursor(xpos - 50, ypos); // Set the tft cursor position, yes tft position!
spr.printToSprite("Small 15pt font"); // Prints to tft cursor position, tft cursor NOT moved
ypos += spr.fontHeight(); // Get the font height and move ypos down
spr.unloadFont(); // Remove the font from sprite class to recover memory used
delay(4000);
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Large font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tft.fillScreen(TFT_BLACK);
spr.loadFont(AA_FONT_LARGE); // Load another different font
spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour
tft.setCursor(xpos - 90, ypos); // Set the tft cursor position
spr.printToSprite("36pt font"); // Text is rendered via a minimally sized sprite
ypos += spr.fontHeight(); // Get the font height and move ypos down
// Draw changing numbers - no flicker using this plot method!
for (int i = 0; i <= 200; i++) {
tft.setCursor(10, 10);
// Number is converted to String type by (String) (number)
spr.printToSprite(" " + (String) (i / 100.0) + " "); // Space padding helps over-write old numbers
delay (20);
}
spr.unloadFont(); // Remove the font to recover memory used
delay(8000);
}
/*
Information notes only:
======================
//These are the text plotting alignment (reference datum point)
TL_DATUM = Top left (default)
TC_DATUM = Top centre
TR_DATUM = Top right
ML_DATUM = Middle left
MC_DATUM = Middle centre
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
// Basic colours already defined:
TFT_BLACK 0x0000
TFT_NAVY 0x000F
TFT_DARKGREEN 0x03E0
TFT_DARKCYAN 0x03EF
TFT_MAROON 0x7800
TFT_PURPLE 0x780F
TFT_OLIVE 0x7BE0
TFT_LIGHTGREY 0xC618
TFT_DARKGREY 0x7BEF
TFT_BLUE 0x001F
TFT_GREEN 0x07E0
TFT_CYAN 0x07FF
TFT_RED 0xF800
TFT_MAGENTA 0xF81F
TFT_YELLOW 0xFFE0
TFT_WHITE 0xFFFF
TFT_ORANGE 0xFDA0
TFT_GREENYELLOW 0xB7E0
TFT_PINK 0xFC9F
*/
......@@ -36,6 +36,7 @@ getCursorY KEYWORD2
setTextColor KEYWORD2
setTextSize KEYWORD2
setTextFont KEYWORD2
setFreeFont KEYWORD2
setTextWrap KEYWORD2
setTextDatum KEYWORD2
setTextPadding KEYWORD2
......
{
"name": "TFT_eSPI",
"version": "1.0.2",
"version": "1.1.0",
"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.0.2
version=1.1.0
author=Bodmer
maintainer=Bodmer
sentence=A fast TFT library for ESP8266 and ESP32 processors for the Arduino IDE
paragraph=Supports TFT displays using drivers (ILI9341 etc) that operate with hardware SPI.
sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE
paragraph=Supports TFT displays using drivers (ILI9341 etc) that operate with hardware SPI or 8 bit parallel.
category=Display
url=https://github.com/Bodmer/TFT_eSPI
architectures=esp8266,esp32
......
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