From 1a0b37097a58d29f09955e0d7a5a0eb472152f2b Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 21 Oct 2018 17:53:27 +0100 Subject: [PATCH] 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. --- Extensions/Smooth_font.cpp | 2 +- Extensions/Smooth_font.h | 3 +- Extensions/Sprite.cpp | 13 +- TFT_eSPI.cpp | 61 +++-- TFT_eSPI.h | 10 +- User_Setup.h | 3 +- User_Setup_Select.h | 2 + User_Setups/Setup1_ILI9341.h | 6 +- User_Setups/Setup21_ILI9488.h | 3 + .../Smooth Fonts/Font_Demo_1/Font_Demo_1.ino | 170 ++++++++++++++ examples/Smooth Fonts/Font_Demo_1/Notes.ino | 56 +++++ .../Font_Demo_1/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_1/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Smooth Fonts/Font_Demo_2/Font_Demo_2.ino | 219 ++++++++++++++++++ examples/Smooth Fonts/Font_Demo_2/Notes.ino | 56 +++++ .../Font_Demo_2/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_2/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Smooth Fonts/Font_Demo_3/Font_Demo_3.ino | 218 +++++++++++++++++ examples/Smooth Fonts/Font_Demo_3/Notes.ino | 61 +++++ .../Font_Demo_3/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_3/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Font_Demo_3/data/NotoSansMonoSCB20.vlw | Bin 0 -> 15382 bytes .../Smooth Fonts/Font_Demo_4/Font_Demo_4.ino | 128 ++++++++++ examples/Smooth Fonts/Font_Demo_4/Notes.ino | 56 +++++ .../Font_Demo_4/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_4/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes keywords.txt | 1 + library.json | 2 +- library.properties | 6 +- 29 files changed, 1034 insertions(+), 42 deletions(-) create mode 100644 examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino create mode 100644 examples/Smooth Fonts/Font_Demo_1/Notes.ino create mode 100644 examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino create mode 100644 examples/Smooth Fonts/Font_Demo_2/Notes.ino create mode 100644 examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino create mode 100644 examples/Smooth Fonts/Font_Demo_3/Notes.ino create mode 100644 examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino create mode 100644 examples/Smooth Fonts/Font_Demo_4/Notes.ino create mode 100644 examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 7ec2340..7d573be 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -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]; diff --git a/Extensions/Smooth_font.h b/Extensions/Smooth_font.h index 6ab09fc..2c7faa2 100644 --- a/Extensions/Smooth_font.h +++ b/Extensions/Smooth_font.h @@ -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; diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index fb94747..acfc315 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -1473,10 +1473,10 @@ void TFT_eSprite::drawGlyph(uint16_t code) if (code == '\n') { if (_created) { - this->cursor_x = 0; - this->cursor_y += this->gFont.yAdvance; - if (this->cursor_y >= _height) this->cursor_y = 0; - return; + this->cursor_x = 0; + this->cursor_y += this->gFont.yAdvance; + if (this->cursor_y >= _height) this->cursor_y = 0; + return; } else { @@ -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 { diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index b50d4ee..aeb0766 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -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,23 +4175,23 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) } #endif + + // 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(); + } + else +#endif + if (font!=1) { + baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize; + cheight = fontHeight(font); + } + 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); - } - - else -#endif - if (font!=1) { - baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize; - cheight = fontHeight(font); - } - 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 diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 5729a37..2c93392 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -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 diff --git a/User_Setup.h b/User_Setup.h index 139f0e9..24e2873 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -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 diff --git a/User_Setup_Select.h b/User_Setup_Select.h index 00b6013..dee02cf 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -43,6 +43,8 @@ //#include // Setup file for ESP8266 and ILI9488 SPI bus TFT //#include // Setup file for ESP32 and ILI9488 SPI bus TFT +//#include // Setup file configured for my ST7735S 80x160 + //#include diff --git a/User_Setups/Setup1_ILI9341.h b/User_Setups/Setup1_ILI9341.h index 7eb6fba..1f02b38 100644 --- a/User_Setups/Setup1_ILI9341.h +++ b/User_Setups/Setup1_ILI9341.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 diff --git a/User_Setups/Setup21_ILI9488.h b/User_Setups/Setup21_ILI9488.h index 07e1f8f..b00d02a 100644 --- a/User_Setups/Setup21_ILI9488.h +++ b/User_Setups/Setup21_ILI9488.h @@ -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 diff --git a/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino b/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino new file mode 100644 index 0000000..0d24af9 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino @@ -0,0 +1,170 @@ +/* + 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 + +#include +#include // 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); +} diff --git a/examples/Smooth Fonts/Font_Demo_1/Notes.ino b/examples/Smooth Fonts/Font_Demo_1/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_1/Notes.ino @@ -0,0 +1,56 @@ +/* + +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 + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 Og@G5u2XS>lTt)yW$uvy> literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 NffvLFadkmlMgV{oX3+ou literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino new file mode 100644 index 0000000..7eca0be --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino @@ -0,0 +1,219 @@ +/* + 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 + +#include +#include // 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); +} diff --git a/examples/Smooth Fonts/Font_Demo_2/Notes.ino b/examples/Smooth Fonts/Font_Demo_2/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_2/Notes.ino @@ -0,0 +1,56 @@ +/* + +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 + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 Og@G5u2XS>lTt)yW$uvy> literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 NffvLFadkmlMgV{oX3+ou literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino b/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino new file mode 100644 index 0000000..5214264 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino @@ -0,0 +1,218 @@ +/* + 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 + +#include +#include // 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(); +} diff --git a/examples/Smooth Fonts/Font_Demo_3/Notes.ino b/examples/Smooth Fonts/Font_Demo_3/Notes.ino new file mode 100644 index 0000000..bdab3d0 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_3/Notes.ino @@ -0,0 +1,61 @@ +/* + +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 + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 Og@G5u2XS>lTt)yW$uvy> literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 NffvLFadkmlMgV{oX3+ou literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw new file mode 100644 index 0000000000000000000000000000000000000000..4045c621230f1d184991a5a74bf14d0785e2b913 GIT binary patch literal 15382 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 F5dev6?HvFB literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino b/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino new file mode 100644 index 0000000..f8ce4c1 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino @@ -0,0 +1,128 @@ +/* + 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 + +#include +#include // 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); +} diff --git a/examples/Smooth Fonts/Font_Demo_4/Notes.ino b/examples/Smooth Fonts/Font_Demo_4/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_4/Notes.ino @@ -0,0 +1,56 @@ +/* + +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 + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 Og@G5u2XS>lTt)yW$uvy> literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 NffvLFadkmlMgV{oX3+ou literal 0 HcmV?d00001 diff --git a/keywords.txt b/keywords.txt index 53b0825..b197c5a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -36,6 +36,7 @@ getCursorY KEYWORD2 setTextColor KEYWORD2 setTextSize KEYWORD2 setTextFont KEYWORD2 +setFreeFont KEYWORD2 setTextWrap KEYWORD2 setTextDatum KEYWORD2 setTextPadding KEYWORD2 diff --git a/library.json b/library.json index 15bfb8b..ceaa20f 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "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": diff --git a/library.properties b/library.properties index dd9055a..8e9b396 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ 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