From de8619027d46dd57d423eec25b269e9ff4046b76 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sat, 14 Nov 2020 01:38:09 +0000 Subject: [PATCH] Add ESP8266 LittleFS examples The ESP8266 has the LittleFS Flash filing system which is significantly faster than SPIFFS. New Smooth Font examples have been added that use LittleFS. --- User_Setup_Select.h | 2 +- .../LittleFS/Font_Demo_1/Font_Demo_1.ino | 181 ++++++++++++++ .../LittleFS/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 .../LittleFS/Font_Demo_2/Font_Demo_2.ino | 230 +++++++++++++++++ .../LittleFS/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 .../LittleFS/Font_Demo_3/Font_Demo_3.ino | 231 ++++++++++++++++++ .../LittleFS/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 .../LittleFS/Font_Demo_4/Font_Demo_4.ino | 140 +++++++++++ .../LittleFS/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 .../Print_Smooth_Font/Print_Smooth_Font.ino | 149 +++++++++++ .../data/Final-Frontier-28.vlw | Bin 0 -> 25287 bytes .../Smooth_font_gradient.ino | 120 +++++++++ .../data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Smooth_font_reading_TFT.ino | 165 +++++++++++++ .../data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Unicode_test/LittleFS_functions.ino | 39 +++ .../LittleFS/Unicode_test/Unicode_test.ino | 152 ++++++++++++ .../Unicode_test/data/Final-Frontier-28.vlw | Bin 0 -> 25287 bytes .../Unicode_test/data/Latin-Hiragana-24.vlw | Bin 0 -> 54478 bytes .../Unicode_test/data/Unicode-Test-72.vlw | Bin 0 -> 36469 bytes 31 files changed, 1637 insertions(+), 1 deletion(-) create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_1/Font_Demo_1.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_1/Notes.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_2/Font_Demo_2.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_2/Notes.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_2/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_2/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/Font_Demo_3.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/Notes.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansMonoSCB20.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_4/Font_Demo_4.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_4/Notes.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_4/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_4/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Print_Smooth_Font/Print_Smooth_Font.ino create mode 100644 examples/Smooth Fonts/LittleFS/Print_Smooth_Font/data/Final-Frontier-28.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_gradient/Smooth_font_gradient.ino create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/LittleFS_functions.ino create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/Unicode_test.ino create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/data/Final-Frontier-28.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/data/Latin-Hiragana-24.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/data/Unicode-Test-72.vlw diff --git a/User_Setup_Select.h b/User_Setup_Select.h index 8ee352e..5a6d1ca 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -72,7 +72,7 @@ //#include // Setup file for ESP32 and TTGO T-CameraPlus ST7789 SPI bus TFT 240x240 //#include // Setup file for ESP32 and TTGO T-Watch ST7789 SPI bus TFT 240x240 -//#include // Setup file configured for ST7735 128 x 160 +//#include // Setup file configured for ST7735 128 x 128 animated eyes //#include // Setup file for ESP32 and SSD1963 TFT display diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_1/Font_Demo_1.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_1/Font_Demo_1.ino new file mode 100644 index 0000000..7d41d8d --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_1/Font_Demo_1.ino @@ -0,0 +1,181 @@ +/* + 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 LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-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 Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(0); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\nFonts found OK."); +} + + +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, LittleFS); // 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, LittleFS); // 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/LittleFS/Font_Demo_1/Notes.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_1/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_1/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 zcmZQzV2Ed6VBlt8VBlwf03HSg1{MYe21N!21{fQ}2dROmU|>*UU|?WnU|?WlU|?W} z>Su&XDnt2P3=9k)jI2+Efq{XSfq{X8fq{V&YCcpOgDR8{lIMe(0h3dM%7NSiG7p4d za_UgGFhSi7l7qQLgMonoWERM+APka&>C?m`rv-H*$ekbzvKOXL8%Yl22M~tI=|J58 z3NH`_xd|qx%fP?@;)C1)!!S8LG=0o42?hoReP~#K!Wx8;{a^qM7myo4?m(6^MA8S7 zgN2I`R1PE#!pQoJ@tA3XN1rJkeP&QOkX;~*Y@azEGcBO{u=&ptkDL`W?SbL|gh6(~ zg47ynA4nX8k>zZl=@MoiDE-3p*+SD9Ob$fDM z2z4h&4CD?F4YSV)DhF~qOb!;e&QSZ1c7o(!`hubMfy@M9kQ_{32$DXKUSzpYs6Lo^AUT+sVNiV_IS>ZP!ORSY z%7My%5Jr}ZfXadNfH1OLB$6DuTcV(HAaM{z))x&87f{{<$1MW`1I(QS{RS#`L1}{R|NsC0VVW2i7!nv57(it$$Q>XIiYJ(KBD4$v z#R14n5QfPmLGvw04iqjReK0>HBk2RlBkN0n>H~?v^uf$bh3W&z!7xlN4H~y#KS0?q zxpXu$L3&|w8Bnz#cfjm}xib?g2lGF&AF>!27zCi@9XMQ&!Yv!B4`dGrBkRk7%3(7z z7g|Pw$~jOv1L=jiB@ZeGb0@M~KAvzXfchPqzCx%R$SjcGK{PB}ilFv^(ikXAL2@v+ z6hrL;iGwgm4yLaJDSd+EK<2{aN}>9&xupzhAIK~ihUqJZ%7MZKghBE!xeBNpNDPKy za+OH_Lzk<9>I1nEghBE!ebvx>1oArwBj=SGXuN~+3&wBkTfQ)C*~GBsIRg(52r)1)L@sCYSPrs+ zVbwc^#a}>{Gu&UtaB>?11IM~`|L?E+^KhLt$LJ*_435c% ze$e~Dz+HH{~JX92Q?rV7#PGs4FU!R zro59bYzzz;@BaV)|EJa9|Nq1H7v6{u{r|yZ3rNwY|F2JiLecob|Nq~5K;e`1;s5_N zObiSzTcZE}2sqc;d~V(UYmR?F7C$v*;PGlc=K>0T2HWKzyJJrt2Nlrv>l_&vwEjPS z{9l8C;nICJ28OKvvC;nv7!v=3%Hb*h0|Nd}VS9QGq$T-(boBp%`v2C+vm+T){ycp6 z-|@?a=KsI`S2F}1KOQ^nkIK_;9N(UUlxqE-!0`Vl!)|byxapHH!>?Nm7yd9XFgX4% zXJFX-r|8dN1_p*p57`(P^q&8J32Nejw1ILt$c?sZ9_|JeF$@e0dcXdE`12oBPBAbf z|6k5f@P9E_W$6FoJp2EH@*4vK)0O{U{%-V!Y4~9Sd zzX4Q-uc&VqggRKaGKb>Dw13 z28MP2Z5bG*fkHj)e=-9@!T&@ChPnU485j=!*I^L+^N@j|U|`txiGhJZ+Ma3oIR+iQ=>K0HK7ILrwpQZ8|NnO4=7?AqyP6Y zFfas&Gh~50$k6i%;=?Kb*%%m@*x081=V488iL)#b)_`Aw&EpONO3LpFRb3yng*U06l+!`XFmoF)%QM{$I+#z_8=L8v}#* zpQj8UA9a9|0VwSm{6ERSz%T(6s!Xqc2{JJF{a?qxz_95*sL95_P;~V1QZ)vK=KueH z{eLOW^6P&9)8YReUjM&=Li|GX|0@g(9{+zN|KGyE;PU@}?Ej+-3~vAb1pNO53ghQ| zfBvg6O#8o_VgCQeTmJvIXW(1+|Nkd&3S;8|`GrAp@j5LA`;8vp92poiUV_8Vi-BRwOnJ85pmYVYpy)rSxME;nIQJh^zA`ZM z{l5juv<&tCpUQ#~boKxHV7mPOB~cLH>;M06pFVy1#1;!S@Be=`2EXN(uC4K6(EIcM z&!7MQ0~pfWnAnbkgOq_`;r}iM2HVK4U+07w7`FWX{}9y5w~efQ`5%<>K#~7N66B7) z|1V>|ty_Nh|NlnYyZ`_He-0|O*?3^}jm|nypffNqU4k}eTK_;8rvH1u42~Q3Wxz<|KHER!1Mn#I@%C(^X&o z_b@Q7)G#nTgnB9Z{|&GJ z!@2*U)(-=N?f-WWm+bftO8ubX_m4bS$-@7jT*AO0{pUY8@ECaNw_I7{1}Xx+UHJb$ zi0l6!afa6aOId#X*I}6Ue*#0^|4;k>UlC{EIQswpFG~iN8|M?RX3QGQ7|6eA8 z5}ow_KRW;aFQ0bp|0agehyVZonGXs?F0dbX>bGp0Aj!aR803YQl3xEmXmD)%KeH0# z4xj(;vOwVx`v1TA|Nql!U;h6O%6|W=L3v8rOUdW|CXk~A&-{;Os9d<})BoMzg!i(M zje!A{p!6IW*na)@V|n@Cnt=tD#uzXvUqvHbs+ zRtAk#|6f+~F?js{UkQpO`Bi^@%?8&i@;zVvp93|z8Mun>g4BbIa5J6)20gIij)@Hd zESH19{2)-~`}FClB*-uZ28Qs*MPQc7;r~w|EYl7DpF>z0$N%4FU|>r-_y2LZbl<1{ z=VC#X%sOy=E)R)X2DOeIPq)M~?D+rZ$N&FX#<466<&XfZ1QihsCI3I^F)&pBzY7}a zdG`lg1Vn=pHUonOXyAlF=|8xAApPwRn9BoJ0jeMCmoA?I>V7jY@GSlRbi=9}|M!YA zFfbkd1g;!{z8q#?DEjXuI_>GZy;*txeHb3^XS(vKHva!&mOt~Q|CfaRPh(*FKbPUt za*zMv$^Ts#l>Sd+__5IPe|+fw9ER%ub4~w8v;11lbol?LAG`nmI?BW__m3r$PqYd{ zP$(M%gXrCFjV^rVL36=LT5!@gP)a%n<}ffY8F+!3Fre^eu-&o+RMddj3;+N60j_@- zSib#Q1*+meZLI&B!XW{|u;G6O&mT|~z`*zCzcj-RaP6P=|7CLW8c>2{*blPf|NsBe z46^_Kmn0`A-}+y~Q1bsF$n2i~=NK;hp9ErB|NpO6v~Jy+r4#HKVC}CihUNd43tO-G z|AS#UsLBonGma)V-u>SPRdYd!Vfp|40ihfIzhnce;rsvJ1I!5c|KEK1{~xd4{r`Uw ztoYB<381{h;J4=5$;DovdJ^Qa;|!7i{}-_FBziC$|34Sx5(cI}|3M=G;KBtGS8V@5 zwIE3H1GEvtFzx?iNd^Wc6$a^-|9@@U_H7{pgUaqd|Nnmib$%F_KxH)8JC&fc4{1;S zsR#LNxv*vH|NmJKA2D?Oe+p$;|NpN9b~va^bAhl7{{Pp4u*&~`VFI&)KK<`t0Qu|3 z|Npx=Kpy+^X&b0>TLdoQ(jZn%0R^0}Fb`M@$krQErcBX-$ayXQe=s~eToNv~5acnC zk*{BOK$J{@80G@uB`^QKP*_-)ZTbJ%5S4S;*w~mLaxTmNKislqive5?ssx#0U|=wq zx%cU|DaH&8^`J2S|38!==>PxaDh$$DObo|CO)`+dOn?4^Mnpi(%K!ge7(gZUayC%A zukZDb|H~O(gX`ki|CcjN`TtrARI@B+5P$mr&+bj1Kn*zARiMW6HE^lT!~-fYi`IcU zlpO2UaX`Gv^Z!3IK+svB(3uIAg*XqS4irZ5U@=hmpzFXCO9O?!b>ffz|6f{y$~87{ z+lGMvX?pno|5dV6K-Pj9_z)*UoJ%?hO1_u=*YfPY_W!>Q&;S3g;~5w@K-~_Au~XLN zfz53F|5y~n2>AcQ7?k)lKK+jerIA(FKv9i(ZN6(_2c#H*H0md>POMKb)Y28;J9vG^>T0z z0o3CDzh(LVZ~vtk7+8LN1F<)OnxEnSH-Xq$|F^D|M?JBkiq}|#$d5PvL7M7y_|6>^#u0aZ@4gU`^FoBws z3=9mh|9^nW3vjbL;QxOnw*UV@qo1H&69dD`|IMI$H38J#?)m>tgMmTk)Bjoq2EqIP z|Li~f=l?ZO+7Mm%>;L~>)4)X|1Ek<$U|;~3UDcwXH1Plb|Ch3$@+9E-{|Vsup8J0t zm_Gb}>GJ>gSKa#m-yR%sk3l`>9o8UI!SaX{081Aj=g`TYjR=3<01fnl{rUeWv?gZa z>HGf$+~5E?iDCEumyk{x0|SHLq$%Yf|F2qFAP!2xptyLg2C9nW{T~0H3-QYA{~N#z z=_~(xKsn~e|Nj?+LFMv0aC;Ht{iFX|LE0BGX#M#E&S#(;a}82Uaoqpk!@yFx`{}ku z6^1n+8~(=&{{Qd6q*cwN@&7-h6>|6g>mpFytabPQ|L33@iLKx%q+P+lbMpT}9Z=o0 z=KsQg|L-;&{{P=i@7(|Y{~v?e5#ZW~p&V2oty{OwdL7vO|Nq0aY;BMJ@36H6g~1k3 zw-w}fN*LwqKwW*kb?aEx{htCU>extUtpV37UjP3yHUGaa2rAfbF-X4q|82{y|DX=G z7O1^@3sgEXFt9*+`P0^crc)S-*5yt54;~+R{y)g}|2HNE2J8PnSQs9I@<0!0=%Ejk zV{U<}bIboP8Fc=C0`;mM{!YhqCQ|9J6# zV}^DAD?wTr7@q$>_l}fvgn@x!>3>jD-{Aj$P!}AO_dzByeE1I<#ED)9D*YK| zu8S0Y32LJx{(sKL5dQyzIL~u%t-9&|(k_ro85pEL{RefSK>nZfACyKJ7#L(f{r~@5 z7$mgg|Af8ZUTWcNFQsJFy+_y5wab)b4yYu!4@(Er~=85q`p z`Yz}GcQEMu|DypaAb&`%16L*tJO1zZ|4kBPvd;hi(C#h6!vC*9g#@_#+6|J!&+>q# zWUVY{N;Z}Tb>8km0*N8#|5LEj)xP})WeEnRbN?rR4Q>8^4U~Tv%>VxZO|3F;-32!x z7#KSK|9=evUJIcH2CQ1QF6+mi-94W!wv=p4zB<&76yjUU!ZEhl0kGw za=i?g@L8(9E|0nDJ|7TD5^#2pXr2qe4dY${kz`zFX zP`boIirL*@XD~1z=txOFOAvqdm;e7aFzo*St-j;`|K#1Em|XLJ6lc!tmjL0E6v^|NoC)`X9jX@c*r%!~g#W7=vtM`}RM;4-_m6+dzyT3?N?y zsQv$M&cOHUe*nXo|L>OG05N2*{r}TC0c}ScmI#Y ziWnGlLU|Y%o`TxU)tmGf81!t#L2(>Q6mjN%tVhtV{{cV#|9{9)IlD+0?k9NWKx0VT z+A@LMEC2j|5lBk(E~xa`{XhQ9e^3>$`~Us_e?SeM-T(hT1l1P|yZ_fqzXMejAYDQK zf9Qd9frhJZ@wmh)Vf7QTpq@E{w4VzDgQ%Yu3&ZX|d4K-@KNtSv|Nr~KyZ`@b?)v}# z|Ag8<|4Vj*D#YWUdSKoEx!~~K0BRE~{J#)nEd#h&Ks-m!oIxC7U(T=p{~v-Qu!M{V z1m_{}ObR#;J+@|GIR5`i&X)i0gf;$y2K#UQ&wvyLtNzc1FxLH_Dfs8VEd$T%|IrLH z|G!&xZ^?Mim(tK;;W8Ume{6E?=&pmoK2~1kYDH{)5UFQwFYY z;PU0=;!B|NMd{lA|2+@?gGw$gHnbv)0aliQ7?Wlj=$SL{`6=!GW%}}e{OzHG7H z{r?OPC_#hfwINQ$BpDdg{QT5Ft%3jl|4(xH|06VVv5VvX|COLRaLfPy-#R!L7<>-@ z|34d4M3?-39dKiA?aBWe%t6J_L1_jCE^x>)J)8-e_xQiV)-nxTyEq>Fe>6FsVKyj* zp^=~|ilYC&mTqGZJpTXx2hijz7lS#dg{x$%0dBZV`M(@1Jq;?p@c;7rpk~3f|I6q9 z|FQhc|NqM+&;0*?$p_TB-~gAFwzi=5g|V&d4$zDY*RTJ!;h-K{?Em`=Ebso?GHe2M zswVuO#Pti*ayR(@JQ^|xe&PRq$b@0u|NoyrUS<&d1|2O^5V_5v@{x49y@#)upbB4tK5GO4E|AUFa;Q#*;1_m8lJq89QTU*JX z|9`X?s{g+fW?1$Ap!_#b^HB8V|NG#wf+6<*|4$&_GEDmqntB1v0sfl%|2_|>@l?-r z<^L3hNub`a<^TWI)}V5Z!Q57M8z`tm|NOW00=2%={@-U{di*~KRPKNVe3tY50cAAV zKR?nSHR`tik3rLA3=CfX|Nj6t(3l=W+T#ptFF_MH46<&^|6cu}@C-A%{h-3-?Rn%MlpLAnjsC^A?zzY6?%Yv$VkfYxHua*S2 zAwgNmAV}IWX!$4H&@#w&X}ur=Lo~R@z+efUap3t6YWDJg!-M1h4@V{jhVV*-=pL+q|R0|O6eIFipVza(EFI5DqS!6`o{ Og@G5u2XS>lTt)yW$uvy> literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_2/Font_Demo_2.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_2/Font_Demo_2.ino new file mode 100644 index 0000000..03ec36f --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_2/Font_Demo_2.ino @@ -0,0 +1,230 @@ +/* + 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 LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-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 Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\nFonts found OK."); +} + +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, LittleFS); // 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, LittleFS); // 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, LittleFS); + tft.setTextDatum(TL_DATUM); + tft.drawString("[Top left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(TC_DATUM); + tft.drawString("[Top centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(TR_DATUM); + tft.drawString("[Top right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(ML_DATUM); + tft.drawString("[Middle left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(MC_DATUM); + tft.drawString("[Middle centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(MR_DATUM); + tft.drawString("[Middle right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BL_DATUM); + tft.drawString("[Bottom left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BC_DATUM); + tft.drawString("[Bottom centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BR_DATUM); + tft.drawString("[Bottom right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(L_BASELINE); + tft.drawString("[Left baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(C_BASELINE); + tft.drawString("[Centre baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(R_BASELINE); + tft.drawString("[Right baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + 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/LittleFS/Font_Demo_2/Notes.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_2/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_2/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_2/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_3/Font_Demo_3.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_3/Font_Demo_3.ino new file mode 100644 index 0000000..f1189a9 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_3/Font_Demo_3.ino @@ -0,0 +1,231 @@ +/* + 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 LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-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 Flash FS +#include +#include +#define FlashFS LittleFS + +#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 (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansMonoSCB20.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\nFonts found OK."); +} + +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, LittleFS); // 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, LittleFS); // 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, LittleFS); // 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/LittleFS/Font_Demo_3/Notes.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_3/Notes.ino new file mode 100644 index 0000000..bdab3d0 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_3/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_3/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_3/data/NotoSansMonoSCB20.vlw b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_4/Font_Demo_4.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_4/Font_Demo_4.ino new file mode 100644 index 0000000..c156320 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_4/Font_Demo_4.ino @@ -0,0 +1,140 @@ +/* + 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 LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-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 Flash FS +#include +#include +#define FlashFS LittleFS + +#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 (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\nFonts found OK."); +} + +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, LittleFS); // 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, LittleFS); // 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/LittleFS/Font_Demo_4/Notes.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_4/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_4/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/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/LittleFS/Font_Demo_4/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/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/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/Print_Smooth_Font.ino b/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/Print_Smooth_Font.ino new file mode 100644 index 0000000..cda3f32 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/Print_Smooth_Font.ino @@ -0,0 +1,149 @@ +/* + Sketch to demonstrate using the print class with smooth fonts + + Sketch is writtent for a 240 x 320 display + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-plugin + + New font files in the .vlw format can be created using the Processing + sketch in the library Tools folder. The Processing sketch can convert + TrueType fonts in *.ttf or *.otf files. + + The library supports 16 bit unicode characters: + https://en.wikipedia.org/wiki/Unicode_font + + The characters supported are in the in the Basic Multilingal Plane: + https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane + + Make sure all the display driver and pin connenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Font files are stored in Flash FS +#include +#include +#define FlashFS LittleFS + +// Graphics and font library +#include +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke library + +// ------------------------------------------------------------------------- +// Setup +// ------------------------------------------------------------------------- +void setup(void) { + Serial.begin(115200); // Used for messages + + tft.init(); + tft.setRotation(1); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + listFiles(); // Lists the files so you can see what is in the SPIFFS + +} + +// ------------------------------------------------------------------------- +// Main loop +// ------------------------------------------------------------------------- +void loop() { + // Wrap test at right and bottom of screen + tft.setTextWrap(true, true); + + // Name of font file (library adds leading / and .vlw) + String fileName = "Final-Frontier-28"; + + // Font and background colour, background colour is used for anti-alias blending + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // Load the font + tft.loadFont(fileName, LittleFS); + + // Display all characters of the font + tft.showFont(2000); + + // Set "cursor" at top left corner of display (0,0) + // (cursor will move to next line automatically during printing with 'tft.println' + // or stay on the line is there is room for the text with tft.print) + tft.setCursor(0, 0); + + // Set the font colour to be white with a black background, set text size multiplier to 1 + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // We can now plot text on screen using the "print" class + tft.println("Hello World!"); + + // Set the font colour to be yellow + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + tft.println(1234.56); + + // Set the font colour to be red + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println((uint32_t)3735928559, HEX); // Should print DEADBEEF + + // Set the font colour to be green with black background + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Anti-aliased font!"); + tft.println(""); + + // Test some print formatting functions + float fnumber = 123.45; + + // Set the font colour to be blue + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.print("Float = "); tft.println(fnumber); // Print floating point number + tft.print("Binary = "); tft.println((int)fnumber, BIN); // Print as integer value in binary + tft.print("Hexadecimal = "); tft.println((int)fnumber, HEX); // Print as integer number in Hexadecimal + + // Unload the font to recover used RAM + tft.unloadFont(); + + delay(10000); +} + + +// ------------------------------------------------------------------------- +// List files in ESP8266 or ESP32 SPIFFS memory +// ------------------------------------------------------------------------- +void listFiles(void) { + Serial.println(); + Serial.println("Flash FS files found:"); + + fs::Dir dir = LittleFS.openDir("/"); // Root directory + String line = "====================================="; + + Serial.println(line); + Serial.println(" File name Size"); + Serial.println(line); + + while (dir.next()) { + String fileName = dir.fileName(); + Serial.print(fileName); + int spaces = 25 - fileName.length(); // Tabulate nicely + if (spaces < 0) spaces = 1; + while (spaces--) Serial.print(" "); + fs::File f = dir.openFile("r"); + Serial.print(f.size()); Serial.println(" bytes"); + yield(); + } + + Serial.println(line); + + Serial.println(); + delay(1000); +} + +// ------------------------------------------------------------------------- diff --git a/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/data/Final-Frontier-28.vlw b/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/data/Final-Frontier-28.vlw new file mode 100644 index 0000000000000000000000000000000000000000..2872fd554bbf34f5e1268770dd8ea3cf55cecdfd GIT binary patch literal 25287 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/Smooth_font_gradient.ino b/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/Smooth_font_gradient.ino new file mode 100644 index 0000000..9e3ca8f --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/Smooth_font_gradient.ino @@ -0,0 +1,120 @@ +/* + This sketch is based on Font Demo 1. It introduces a method for rendering + anti-aliased fonts on a graded background. This is acheived by telling the + TFT_eSPI library the pixel color at each point on the screen. In this sketch + a graded background is drawn, the color of each pixel can therefore be + determined. The TFT does not need to support reading of the graphics memory. + The sketch could be adapted so only part of the screen is has a color gradient. + + The TFT_eSPI library must be given the name of the function in the sketch + that will return the pixel xolor at a position x,y on the TFT. In this + sketch that function is called gradientColor, so this line is included: + + tft.setCallback(gradientColor); + + TFT_eSPI will call this function during the rendering of the anti-aliased + font to blend the edges of each character with the returned color. + + If the TFT supports reading the screen RAM then the returned value can be + tft.readPixel(x,y) and anti-aliased text can the be drawn over any screen + image. See "Smooth_font_reading_TFT" example. +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-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 Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + +#define TOP_COLOR TFT_RED +#define BOTTOM_COLOR TFT_BLACK + +#define GRADIENT_HEIGHT (9 + tft.fontHeight() * 5) // Gradient over 5 lines +#define OUTSIDE_GRADIENT TFT_BLUE + +uint16_t gradientColor(uint16_t x, uint16_t y) +{ + if (y > GRADIENT_HEIGHT) return OUTSIDE_GRADIENT; // Outside gradient area + uint8_t alpha = (255 * y) / GRADIENT_HEIGHT; // alpha is a value in the range 0-255 + return tft.alphaBlend(alpha, BOTTOM_COLOR, TOP_COLOR); +} + +void fillGradient() { + uint16_t w = tft.width(); + for (uint16_t y = 0; y < tft.height(); ++y) { + uint16_t color = gradientColor(0, y); // x not used here + tft.drawFastHLine(0, y, w, color); + } +} + +void setup(void) { + Serial.begin(115200); + + tft.begin(); + + tft.setCallback(gradientColor); // Switch on color callback for anti-aliased fonts + //tft.setCallback(nullptr); // Switch off callback (off by default) + + tft.setRotation(1); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while (1) yield(); + } + else Serial.println("\nFonts found OK."); +} + + +void loop() { + + // Select a font size comensurate with screen size + if (tft.width()>= 320) + tft.loadFont(AA_FONT_LARGE, LittleFS); + else + tft.loadFont(AA_FONT_SMALL, LittleFS); + + fillGradient(); // Put here after selecting the font so fontHeight() is already set + + tft.setTextColor(TFT_WHITE); // Background color is ignored in gradient area + tft.setCursor(0, 10); // Set cursor at top left of screen + + uint32_t t = millis(); + tft.println(" Ode to a small\n lump of green\n putty I found\n in my armpit\n one midsummer\n morning "); + Serial.println(t = millis()-t); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(2000); +} diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/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/LittleFS/Smooth_font_gradient/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/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/LittleFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino b/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino new file mode 100644 index 0000000..52f2b91 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino @@ -0,0 +1,165 @@ +/* + This sketch is based on Font Demo 1. It introduces a method for rendering + anti-aliased fonts on an arbitrary background. This is acheived by reading + the pixel color at each point on the screen. The TFT must support reading + the graphics RAM of the screen memory. This sketch has been tested with + ILI9241 and ILI9481 serial and parallel screens. Other screens may or may + not work! + + The TFT_eSPI library must be given the name of the function in the sketch + that will return the pixel color at a position x,y on the TFT. In this + sketch that function is called pixelColor, so this line is included: + + tft.setCallback(pixelColor); + + TFT_eSPI will call this function during the rendering of the anti-aliased + font and use it to blend the edges of each character with the screen color. +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-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 Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + +// Callback function to provide the pixel color at x,y +uint16_t pixelColor(uint16_t x, uint16_t y) { return tft.readPixel(x, y); } + + +void setup(void) { + Serial.begin(115200); + + tft.begin(); + + tft.setCallback(pixelColor); // The callback is only used durung font rendering + //tft.setCallback(nullptr); // Switch off callback (off by default) + + tft.setRotation(1); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + // ESP32 will crash if any of the fonts are missing, so check + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while (1) yield(); + } + else Serial.println("\nFonts found OK."); +} + + +void loop() { + + rainbow_fill(); // Fill the screen with rainbow colours + + // Select a font size comensurate with screen size + if (tft.width()>= 320) + tft.loadFont(AA_FONT_LARGE, LittleFS); + else + tft.loadFont(AA_FONT_SMALL, LittleFS); + + tft.setTextColor(TFT_BLACK, TFT_WHITE); // Background color is ignored if callback is set + tft.setCursor(0, 10); // Set cursor at top left of screen + + uint32_t t = millis(); + tft.println(" Ode to a small\n lump of green\n putty I found\n in my armpit\n one midsummer\n morning "); + Serial.println(t = millis()-t); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(2000); +} + +// ######################################################################### +// Fill screen with a rainbow pattern +// ######################################################################### +byte red = 31; +byte green = 0; +byte blue = 0; +byte state = 0; +unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each + +void rainbow_fill() +{ + // The colours and state are not initialised so the start colour changes each time the funtion is called + + for (int i = 319; i >= 0; i--) { + // Draw a vertical line 1 pixel wide in the selected colour + tft.drawFastHLine(0, i, tft.width(), colour); // in this example tft.width() returns the pixel width of the display + // This is a "state machine" that ramps up/down the colour brightnesses in sequence + switch (state) { + case 0: + green ++; + if (green == 64) { + green = 63; + state = 1; + } + break; + case 1: + red--; + if (red == 255) { + red = 0; + state = 2; + } + break; + case 2: + blue ++; + if (blue == 32) { + blue = 31; + state = 3; + } + break; + case 3: + green --; + if (green == 255) { + green = 0; + state = 4; + } + break; + case 4: + red ++; + if (red == 32) { + red = 31; + state = 5; + } + break; + case 5: + blue --; + if (blue == 255) { + blue = 0; + state = 0; + } + break; + } + colour = red << 11 | green << 5 | blue; + } +} diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/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/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 zcmZQzV2ER2VBlt8U{GOz02u}b22KVB21N!225ANc26hGp1}+8$1}O#x1}2CS1|_H% zF9QREAex*qlrPS}zyQJ^eNb&+JLDM{7=#%Z7(^Ku7(jM0LM2t9e2}~X)NYuZ8dMHs z7RXH?43krbx`ho&gVey>slmX&05S{Yejcd1VEQ!i$Z0V!FbF}h2-I$vK5eKtNFL+| zF$M+(n4AvO4X`j{MUvBHU|<08VQvAr2c}OC8qP3%Aiu!;pbvF7KLY~;2!s3w4KfA; zsM}!Si5xD5P<@~{0=W~U4`!wjG<>n?Gsa`43Ditbn83`0xy2M}CM;Y)_QCvT29<-^ zhb(6fH4~eh1s;8tc;u|0=?fN~Aos%jZq2~JAj!bMzyXabkQ~gNHVh05AU@0wp!5rq zvxVjpm>h_P$=Tu2XAcceP(A@+P#nR+%z=S{L6(7mK@OT0k;BCi8ZIEWf-p!9rq2l~ z2XdN|gGz$_3nF-V93Y7z;F_2zlIX66V?oj(cW`gv9 z%!S$K0o4bR1Lbv)Jj^~%s2nIC@Il$I@bqF}0GBZ!IS`im|NsAAsQci%TV5of{GeLd;*#`@k5F~vdy&(Ib!NL#<%@3fk2I&FG!NNKWst*)iFn7ZAg+t{) zMOf$A_=oTJ+p&%nR{3I_pD`3Xu#|NsC05A|RIwA=;Nf1q*_lr~^tod_*M zK=A{sYz7(iFkT^^qOfD6w4&EC;Q|r^*$1LwVO9Y3 zJ4g%^o*)`#W+7A#WF|}wrmqNUA1EwAVT!D;7-}C#92EB;Ihei@Xx#xyn;>~mm_mbv zp%khQWFJTzqz~qnGN^r^FawE$Fic-LR1Op_AdDdDUP<vFL+^OC2;Hf$Rdg2V^f;ZvHwD(AojY zbN~6afGM^$V2WWWi2B7aA4Gj(mo)WyAFdMh{~G@QX$G93!-KgfJhbw4iHrm{r~^} zUknTkAakQZPW`~ZzyLBgz~le_|7RE&7_R;Q|KCIB|NsA+7#J8pfuIM{xs-u{Vb%Zt z|2aU8p3A@h4haT^X|rd8iq`1av!}pap16GZa$^PtjpfUigNhfJ_`3i9|BEt!LkXk> zCj9RI|4$4I43qx<{|{5_qg!RP<~|2+&04B!6$KL=F_ zqALIY{~yZ0ApigW|Ainv6ocHW!2pgBP}#!3z%XITlqpl5|NsAg%9JSw|NsBLZOW7> z)(i}wfCPmOGEOE{*xJ_C7L;@{Y;9{nk!EXaYYVDQ85kH2LVVHq|Nnnbr4Mx;(=UiG zKmh|PyP(1b|NsA=&%nU&>Hq)75FvvtTefUD^Z)<8HL)P!28!Qz|Nno1*a#*A{{R19!oUEEiY;IP2vPt4 z|9>w?RP;eaz$7T2@G&qzqXH}hBJThH{|=gTK>Zt#5Ca1^1AwCU?*IQkph6(Z@&Et- zT@cy*AU-no3IO#xkVP0?|3@S`s06x@eB`7b|8Fhs3I}zPKx!Nh!$Ru+|L2oHU7!gF z0T8Q;fdLeKASMi}Fo^yFvv2(Pe{0*f|NsB*XJ7~gi}*ntp_FkLl#f9|FBu?0Aj=pS z!a+iR)R2WhS?mA*cX`N8g*yu2Az4r|1?m2OI2M)zBtdBwEcX9#5lk=?lwl!)7eGxu zu*F_`AtL|(KLu4MU@-JZ;L4|9iusmc!f%as-SGrHK<_V*}L?P%R(|?o|*66$`fB{r~^Nd{7r2 zBEhnB-MV$47C4A2dLQJ{|Np;%x)>k1@Rdex}Z57%mXF5U&0J?|NsAgA1t8s=l}n2ptdoX2hz8VfdP~!|AQK9;KH~O zECnJ?LX1)a*#UB#IjER`1}He1LA3~^`T>twlJ+&I6o>+)y7>$Y zP{Wz-LJ9zo3>Yu}|Ns9MxYLRt*~5PBrY%boK_LyQetrov%>MuX|5FA*P>AR;fos$M z|F1|hFvx;xq6;81{`Wycq!r`~5Wd2~zyPkwK%8%~O27X9{~-;|i+?~>*8dy^1|E=C z{{R2~CzJtXMk7N8NUbT;(f^Rbm96^P|Nq~X8!&*1)#p55MaLoe@(*a>0@j`f8I#4p zup3f^fP(Kos1FVHAjEH=5CP?&nGBF{1a6L2g$z%wJ9M2 z=%l2Fk2xs1k;Kus5E-7l-QWKI|8cSvy~X1QFYtbWTILYdAkq?1Nc{f~>ga$3!5C5U z{r~^}HBv4IdF}uIYH49`3++EVupx~BaLa}PRAK!G^@+hoF);XnJh&Ld0VO0*6$fI2 zFu26N1ZpvZLiZ0i`+>w67#JRcG{rK=gBxh8pn_luln?%YY6hp%mxwYLl-|JYH;~5v zFJXlPSPKIKD20P1j>AiGh>Qv-gM(zIK?1cF)C2%k7PcQiq9FVdTwbz(1FMgLK?_{0 zgCzd{e+f!o;O6OnV+ICLOXC0krM6%N@64e|;{pQ%I0^kf$iQF@k+L)eYmaAONCq=N zgG1(^Ao%|Y?B82V43L)ae^57<0U`xf2^yl90%m~*z8DZvYe3!swL$;?-w%l|Q&9f@ z|NkMVC&Hit*7N^TypE(-B`8;c_@F*N1Ec{C;v!>E_nbi(rVv@?Kd2YVAPTPrK`ozF zTd?E*LsGTR7I0Ag|9`1klz~AHlK!FTo5{c@Aixb;K7gFe0Bc}_iz87`mj2HI^2aZ5 z^YQ}&r1cC+DVxA8?WN$>{aknpnSp^JcHO#lpeSQ709g!5lT4ss1hs=0%0WdKsMg^D zIT2hxgOe_3e3Jp>KTz^x0LKTY3&sFyO8y7c!=Se1|JNWVf|`^6!ATJ0ivOS<5Tv>Q zjkQ4fD4?1Fq7^h23yC{$B?0yonAHOcM36%m5iE@TTFus{sO0Vwj2Nd{|9G424heN zfsz{oL-_LL%X4F?Bqc@L8By)X4)rk17*ZO5`zcBwKZ80Q3``&v#DO69fzvX$ z?*uUhlxZLhWl;MX9Iap-;82nT>75DkF}Pz08XtnV6&%8#p2{z9egGMA5Twi=qyZe) zpsvw>P^hwjBzJ%$vp|xdti=KfUfjeFq%a<<)b)Z2yKv*k0JUkri zPY@4;LG83ZAO;+R8W`Z@1Q!9tImBBqAy9u160i&m#*N@!+b?kYf`Khy5<~R=|F4&Z z3qJh+KVGL~@2~&=*}xw7|L4d5|Da&||Np-&sHy{b0geMEYW zU{9oh)N3#>fD~N=r*;Ox<}aY275?%NQN;*@!jr)o95G;h3=9nR$;rv!LVVuYxr3V!>^%UtHkM_)-RNYuN>?;w}T&h!O^d#)S(P@-Z;ncnSs0plAdc z^?wRBRu8DR55l1gq>iRQozB2u4jNB^ls6zTP)YJ1l<`0u1{P3?x&dZ_2vBbNkH~PK zF#ZouD&PWOFGv{}gZjz;5$1v_f^YEp2HgAv4YGihGJtDRcx#jeRO3Us2q0-tV;xf1 zgLn+!J_tD3g1Dlf>;rClf_RVu2a&ulfht9K)&jSgKm!k8rI4~5ZYdL}l?o~3LDJy1 z5~M%|aY0$|KfK8*46+nb;)5hX*%4A3gLn*}#?LQsRRiLJt155-3F3j<|7dv$B+kNy zQfe_JZu$2A|DS7J@W539g&#N}e1V3kIH*bhi~NT*8bM=OFp>X1K+Xjx!~a*3gTNKn ze~>#s+2H>}&`=||0ry87JP`B$KWGq^feGA1%>ef${{IKpGLUx38c0VUI+g)0ou7kS z>i?gD+z;tM{Qu7c9zKK?rr?pm|MK9*<_3r=aH9Y30&bat>kkG7VX%w6zy&6%5LhEr z2t3gD-woM#a838$98|*n2R9xVz@umX|8sz=bEs3nN%jY{2$e`eVa0810 zlu$rpE#Sa84st8RbPomwYq0y~OEdX^8&Kd8E96Gk|Nr3HRt40o0W1Cg|Nm}~2@DLD zU>#t=y|4r!3eCtjkb0*KOy+(8J}6CS1_t4|>(;G<4)z&i;jnt)AE5z_=?9ZbH0f===YFn;<0by=Gw8+rhv9 z=YUfqxF`VI!@vOU-Gb}^`)p{+AQnu3J;5MfyZh7s|9@UChjny?=YldeB;byMTWl_f z7zEX}vanGxh#C-in1O)@+~4@Mrn&%}i2sB7)soNu|L+60_(AQB|NlXqPUCCfh8F_^ z1E@g>&WsR;fJm@bQ2qpQAQ;qR2aOg&cpy?7>^^Wq6~qN$aAJNAjxP|GfdSl5|NkG- z1%L=?feKV;6BQyN4K6%hLh=JxNEFlt|Njo$90v<92!k`l2XN~LA|ePX+Wvz&R1iJ` zgCMxq_7dFKhKNB#o>k`+X8bMXv80_ zl?85>zlP}nDdYnUzk>#aKpX=vub|k4;Hd2a@fjGvV?Q8w{=Wm{dZ-XF22oH|`Tqix2cf_P=YM$p z4iW^X%>ST@2E+qnaNYf%%@0&Hfdv>qZEw)9*~0&aOB_MkHOe6koj!1r=>Pv;Kfq!2 z|Ns9Fl29R#Bf8%ru$%$hzJ%!ob$DM2GeAbFA?jp7Aq86h z0InJ!VxZa$-1S34`!@5pFMp3nr-~Rtt)LI0lV5K)Ya2Pk`Eppms2n3+moM=NC~#K%K__|3ATi zB?AL^MgcVU2X-xp05^%QfLJgLZfJu0w=fa#FcwNp0E)N&b8SOoBfX%_2++Vf)bc;u zz@;y^Wds%a{~t6P4K0gcVrdKv86aPPdZ`exAJPmAqIm)03=B*Lt>9(?QZt(YI?c8X z<}45mnwta9c7Zrx49*iMUIZ7?&%u&V0$jGQ(@BKqM6eJ4SG)ZGu{^_ti%rl6;`l%E z(Ch?p9(bw@O=K?%)LAek(?Dg0{bF#l6;wmdhO}8hi^)LQ-2;tMfXh-yL%t8> zuwP7&j@tj_N(_?VmMLg#iwWG`0Lg>#A5cbw588u;AZ;2ggs1<&#?je|Am0165Tpwh zxZ+*`ey|~Xc>abnz~fI~bKwNIK!NkX3@k#C;F)D80V+TL|3YfYK;r>C5(aY!cnS#I zDu9VVI)aFfD+2=q57;Pp#SKykt_*I0STM{4Zra1V4HgBv@C&qH0E<9YQ-DYGAbe1C=!Y5&dTd z$h`UgU!Y_M)5Zc$tB4Lc0|R7k3p9ieQ^NpWt??f+s09@Sk1zfQRa#I1=m0;W_YM~4 z%UJXB&;K8n=0aO{3=BEo#u7MMFF?`>N+a_Vs33(H{{IiCb^|R)fR4ZYe;3ZgAPs3u zxj=i&kT3wJ+C=b*4OovE+!!i=&O<;V6x?tNWdP51{l5g7U;&M%gA)$8^8WwOo(g^os?o9M%*B``ZOvbig_!;OfB( ztO`60z`(!*cAqJz`S2ey7$gi<^o{{MK>q*#-BpXBvlP_~kRg1q+rY$LP=%2QPDx@kRgM+5$Qfm6`` zyW!$WS)f`3w5kb`TM*9w|KE`TX?F1-*kCRO1`k+3oDl`}>A+(pl3lm{{Qq;KkptX2 zISC0v1}1O?1Rf26OlLsFAp-*7`4*T6c%thmaxnlI00Gyv;1N4EAJByD|NpnZhW`Ka z;TD-U8JYXW|8L6(CpWq^%LgO%Nd_Fh0m19Wg2-E;;9XkLO#nD2$H=!FPb zg4!7nCYS{C;j4Zb7@++BFTt`543^NbtQ%RN5&*$J11)>3q4Ik{EprA21}Oi}Vn`x_ zc6$E*n1F~}$jm_xQaugH!vB9Q1$7xA7OPDGmwo^LU&@15r+nq$8u$PIA2UJK16Uzb zBzVN<|NsAIlEEn%Bx=42T!#Mt4_a>s5@29pkne&dJSZ1Tapi%ULtrL?@H>baVjvj< zh?}8_9ZV4;;;|bYfD9vqp|d8C2@^0$j9r*&9O0cf7()qV1OViYkYzcbsC--r zb28Yc|Ib7t%FX2e|NpE(q)G+`hU8B@h@=d127^4LCIqul34}QeOnx&@g60ukE(fpG z5pRZcTR`^zKQ76@0IANv-2dPO3gAV&Fg|#Z=C=R;A5IDP^2!0%IltH#jQ2y!Wl^xl zkvlx#njKNuGBAL14w6T}UPbEcfLpGJ`6Lc-592?43P}`_%eKHKaCpE?j{k`9DbUiP z|F6LT4G9BKHTVT-#R(V4FUSo{@bYA6+XSqIB{?}c8Oe!YK>~zubZZb&C^Kk)g7plN z2*e-Y)&#^TNI*lYeUK2i20~scD-TMcaG!&eaD*np8?GQe6blB_&tJZL>6A#s7#dWD zfhl%Bv zUoI`Lbz}k$u7cXtpa23*NCbdw1H1UY3wVC#Fav|&umAr)@WFZu5J^y{;qm|fe>fP@ z{)30x!6S=T(%f8pKxHrw0|Th(;RRj_VadP%%BK6l2@8}#*%%l=Q(DoW1*AWi7&Jg@ zRUqAAP$Fl5tm#e$Eo#32X^=r@xIpb{21uq(2F*}yfXtvk8cLw?AkfGND3wQp#xYhw zW>Fxa1sXC24Yz?7y?KGAL)SsNNVCD=2%4b*$!-Dp2$X2|Gk`r04mt2_)h7l9&}_hd z28Lh%|9@j(U;(B5HL?ui;LgW?FAmU@WdH*MXe`Z?0URjM)d`^Z1z}L<6V&AZ^%KDp zu%LiU1lj!m|NmQ{jv6Q&z)j9jP;mV}Y|g+?^x^;iU$Y@)7bw5)2Sp_Vo4GwWEE$-L z%|XQ=$PXHzpxXqmM?pf!7(AwRAH04NBFq=G6e&r97JK~v|7BHWWI#Z4^YUwdz)P|r zDnZNSk&*?-*{HG%e2t*cfJlJiavQAW2sMDot!vZkU;qFAdbwdz5Hw*!r9dM`kO~yq z?Lvsd`zJ^x3`7>3MgISXEqjFsf|k>P!WrZYw5}<51;>AIaRzO|z_fsR4u3$2+7J>V6m5|mra@h+R12BLr^Fj6sxQxHczyMxH_Y0|z0GFl{7@*YxXp9MJ zIk@Nt#SJJW|3?f6f@em*fD(Wp$e(}Ul`AOoLZ`PtEkEcoDFz1c96NX>gn22C$bvnG+g3;MK1Gr$P3jfHyWkCBS*_|2rn| zC=Q~B&cFa(4EO)P4|p07ISRlf&;S36tD%EbtCr7)FYE^oFv7g_|9&l~0e~v@|Nnhi z$c7fUG7#eeRP5=NEn9Yg%0iH!3wYxTXxNQ`fk6wD>OiR%Y#wys6R11`?KVLcgG^G* zN7l>02Quz|0g4!8JXZxGb_+B|un;n&J`L&?upS68jRjroF}RrzwiluVOr9}-sss6B zH#C2L(ty|jakD6-7~7332I<}W|IYz7526lIhX4QXhDFQ^MGRD1{r~TXEC!y8`TvIn zEC%-5Y;fuL|NjPvyv0tBdOhBtOL5pf(sR}~7 z&AtR$ZuW3h26&>Hfq}sbxrW~lE?2;V24FM61Sn5~YC$juLV%_hLDlsC|Np-%ug;na zYI1ckFi3+c=l}obLW*yd)|YAwko7X4MG_DPfF@JH%Y*(uhLrtKVeo{;e^~nfA_yKJ z{14635Ftq86I4G!`5+3MA)t#VKztAeHLk!rr9d1g2G!ZqfECz z=SUHoLBJ-03nR2;IiNZj+yn-zfD+&q?H^EdK?N8X7{H4@|33wnG9XbU7X}6%uxtMR znH}V4>lQxq3fQrbkb#6dhy;&_gIX&f4itmM7~DXuL8u61n;2+^eBNs9 z5CpP~fyLG@AizrlR17n~%Z;V8GaSJpASH;D1)2(&240_vkp}H*eEJ4cdfGB`uP2zWUP72u0r zdzY8deMoPk@X>LA?EEFIbNcxaxukfk@EmYiLId#D!we&xa6CsI$CypR{ z*4WtC*dPl-Z6S3te6|l#mfM25&;JoaMNm-&NGlVzunHy$G2$C^Kn5nt1{#O`|NsAv zSQlGIA4ntJmVv<>QvM>`1zyhwtI3dr!7VHu(DVtCAgsgSwGL*?pKD9wL7izx=rgGJ zfF>$bzzGCW=0e5;K++uGTo1`lh|&e(UetCebPL}9!7h3qR!A&_w4@>KMGh|zn{?4% zuvIpnz{zgVhXV~_6SO=SoL<(gTZq(Le2vVmhlCEO+1Jd#Qvx0|d0ql;)Psj4A=wp@ z`G*!;1Kd@(puxak4X#2!$!MD`vfpvBK^ct!CFg++fX2`$8xlUq;Q$_yfes;oD!%`q zK_b|S|4?IDCbn2eRV9fSuGxlItNB9<&i)kyT^;lP|6$N!a2q#RC57MNEbo*d};DMt5;0<(eiy)QABuEfKon#E|v>k*L_)wKwzy^Z0UO<$B z%>*Uk|Ik$uAYo*|cd)TFWI^Z<8`RAIf2twl5TKDdSOf2|DT5Z+{=4Ab9n?t-uvP$M zZ35U#P$+SMt55L4D}+kO2qI|F1JojrO6VXVcquYmI|BoFXWsu$k|-)6Lw%qgFp^5> z8u!$+kYQOQIYbj5GBOJ~ zR|lr=11#4ufVXUc91J!ST#$g~p1_F&Gz0@~t%2qCg7PM$gkyjV9)cH%f#qI;mM?;q zM1b`1fif0IFT|Z6z-we6%gVr8i*JD!`-1g-11~^O_B%u5*w{dQ4)Eq9(BO6lWR)mX4xFt(B^w7wktwPi zC=7pbKxVb>L#D4Fe)!J@S+f}m$=`iwa^Q{i%ONud=IC;uVX!Yupw-@>hCPUeo5=v) z1m^;3--GtSpvr;U?BG?npw&ERa^Ro`pQ{0#Wo^Pz*BU^Xl~LGwbO*!d4hHV`>zx&~EcAd5h2Wk9JK6vLolU8oprxhzx| zy5$Tc3GN-igr9=jWf;PURg@^I|NnxG+`xq&f)g>MV+K0-26Sr4|Ns9FLx!m!?gq_p z{s#|9yyOA5kgh?p2;7hl&{;0XT3fjAHwN&&#{ZCt2rm2!cBTS&P8}``TFe4&@Pq3T zgfJTegEV*q5wrmul+VB}0dE@tC7=JGMV;Wv8yqH}elHt%^65SsI6Wg&gEv9^|6dPT zVh2|ZU3vFK8nkT!Nj0=ySqgR&l4{7b*?;hk9%Nxja3cUzTp$|)o3{apBdca$f%YUJ z0SopHC>o(PCo~!m!tinm#SjK)O^viJih%)bUntmAp7`YtK`HUaxoOa<9xTjMiE#A) z|JUGBqM#XIkdt8;x>-mNJpBk01k<3*37OIdoi?(xD7kqP$fEz?c!A|N$T%^BJh)Z( z|1lE-19$-=_|!76LpUG?Cqs&o|Bpe@2$q0u_Sp+wSoR-fuK`%g9~Q{G5z-zs$a>lT zE}#Mq<(xF|p%nlBM}wmdbp95^1_lPmd368l!Gjc#p$n)KcnbCZ6!6>uDE&c&VawE~ zfg3;2Wjzo%ND0#gjwbLDNr*74=^G1a?jkS50MEw$_X5`nkbR+0E#OJR|9qes_5a9Q zry#@47ofQd>F^h@rJ&QvK;{1b|KFf%Y?;7wtN*`%+Jn%chl6PzE-Pl5JNcmxFa*(0JD zS|YAnw|sUEs62Vh2j&;qD5*aK4bq^$52b&1QRbX%>S^#5|M+af6anQ>nNHYbT2odGc ze?;R5EW^Mc?hz0VsRu!m-B3Xo1?lhqflh2SSj61-!Zy)L=&vgtUr46&|u6 zxZ(kw%Z4lnuKGbMZ;%ARo5H}&0kGgfFR!2?NQn(T%Lpt8aW|L*57wg!eu9klqX@2p z);uVJuw9a1!8JTQkg*nsZb%gZ@;i8s$4f{&fmMP8A!8ljZLSEF&=wnbPzSCO(ii#< z-u{Xt2pQ`Db+M2Hp<^BK(AWf71d4ocQu!c_WD$I<18uPibgTp1s{`qT-|+zEuqCc} z4mvdP_#`(-esBRVNC1c9|JQxc!)GB}5c!&kK?&R`0CB*$1F}N#|Nr|Fl6zKx285NM zXS^MUj1ZYl067}078;IVo5ANi{fEw=fJMN^*udHq5D`cd;wZEa3=)HEQThLWE@JHm zs22z_{?BY!ocD4eK?Oh*bZbK_IG#ZQ zprQpnhay}HD{gKz!wON5;~Cgo`~v)3U_}7KG*Ed18Sep0GpKkU6KF+fgxgzgn*fG(^B zdkNeXhxr4tLKoa<1Fs{5HXXrZtp6dqNx)m}Ve5~T14M$Lo2~H=_v#=N#APadx zYooyt4H;MgsfR47aARNsw-J#x&Vf!x{yzb7+7#mKGX}_kp;s8dK@VE53^oKrfQxfT zFBB;%pkq{_pt=lY<2d;2`2XO+HOQ&n5cZs?RF)JurnGT>}d3)-;p zAMQm+(*ruR1+Cm2!Nbmw!=xD)z^8})hpuLU?56ntiwQCw3T^3t*WLezw;VuQGeFDT z!6^YcBLEpoh3~fpH>%5_$HzifvxC~Ypx}or;D=ai2|Zl;57?jJqeVelAxl%i>*&9M z8g!uc*ne3_aK};9eCdGu#60Nr9Zs0}e9q#&B>09MmuckJm2+ zr(N(Y33%uW+{Xcrg@GFL;Ke0b;2o);R0kf80*S*;{xyakC~OQ_|1J;h|3TW#;F$~1 z>VDA3$`_~?6QRQ@&@&3aCFODk@OA{y;SnG&E@uF{33|R9WSsCN9Jo#zdUgn?7YWt~nMYp8zyMkQbp@1OK@#ARP0*=A zkOCPrWC;?6Y}bTrc?0(nL9@aP43P1BXqBl1o`(Z>;=twT4_Lz+GLLT0z#tFGNRUBI zkfD%+)2=Xqk3{`{0pzj(=xTYigX9^YL*Sq|eG2cyfI0!-aqJD?42m3e zpw#^TgCuCe4ta|cBrbBGqcjMUKt(yYpoN^|0S;LP2Iyfc;93IQM1jtyf=?QTOrJ48 zCWFAy2tKCt|8r?^GoU5aCy;V*LV=!v!vMOO0DSWdyt)t$uWeYgPpzitrS3Tfkw%|bwKECZgv=IOm1uqi%1nb;`1tB{Dpoh4E zMHrO8=@&L}3lRg)J3#UyL;$iq6uA@tjUj={J*2@81_tmU%-JAFhI`30%t(DAh=$5jkNNW0dl0w|1*$P z@?dfT2RP5b;|Ij}0dA9kSO`qCm)GZ>jfSc!tK@{+5W}gsNgF9~E9gAS?pewqdJxeej zlnoFI{UB|mA{JOGwFbA}K~WWsjRi6R+}j45Km1wP!T=%00^T3IeED+t*lFL>r{Go% zD4d{J@)y#!0H_#vXEP!#fkYt#X3*oBKmrV~;t6GI1n9Um(1<&7jSR|Nm7oD-aHK%= zUi<(5moVrMEyP*rpdQ>b$Qe73o&*B}`1B_Y2JmTH521}$P{IbMR8WrrItT-*HNbnh zK_)&2kJErUX3)+qNFg}!g4_V@Wq}le+9M#}e*kM>fLPrOxmE|X#~y zx8Qa>xF^cM-~w8a(FJw{gDj|agH6!c+S-C!i5ewq9)r#@IN1l;O6dqv1hM@8|Ain= zfinP11TysiR`crGuCHXj2|=hd7FXfrUrI9$b=u z)-N#yEClVag;~eI;00~z!$lxn9MFEuFW`>Me->~B`oGVV33|!VfACU1NV^kq?a_bm zxd+fwaUm@@PhFAwWq5yPdMmTto0VD~=kZ?wn`yfI3 ziGdsJAS=NbVlN+q{hCjIzMU)wB?HJgR{z<+^Ln7$#6UX0>i&QWV{o9nlx2Xb19Kt7 zUbxu1S|2~~(A@w3rciaiK*m7ZC=;M!&~5@~oZ$Z@s2FGz5VU?3WaJ;H7_?~)iBJx( zTR^9PgM0uUv-mHFMNAeV1|IK$uBQCY1rdW5E#Mx^A0~(xwDtqX`$MR`U%>4vP*L;$ z|5B*f|0^y`Op&162I|B@^n%<9#kZhg@C}k?!J>{(v1V(Cw*UXZsSl+0k1T^cID7v; z2+rRiFM+YB7wVDqf?1&B7Qa1Qo(NhCz`#(8F#neU0|R7NFW5HFdCv^ciB70MD+6SW z=>PwV!vkU$e*g_4LZSy;z%Vd@&KUytj=`Jgzz%?nXd-u^Ah{W-poerSk($DgoCRv~ zL5zS7!XTOk(9_dFOLd?sz~fN=;RC@843KTg-=KvGhaUsv!lC~!W7!zk99v&*VPFsi zH|U{$1Gfes7DGkAg;F?@8n6I^^aSvr@c;iWyWqq1pzUHl;NlVL90(-~%C*ph2oZs- z@C8lUL;0|wZF&d^*Pi?K=ff&{NP7}wqa)NS|0jWW>iu9~Fh!&XaK`KhXgv=0bcL-1KcwF5ACyo z2dRHRMhgC)(PLmx0`Iu`|ARpu?2G^Zzkn+!$Pq%2S_fp;fA9b=C@%3o$V0_yr)!b8zfSmhb-b=hugIc~D<4Fw{dW{r~?Rw1p0yCIOrO zAGDB`0eUv+|6ga$f$I#=Y`GekwMv+Q0W#5W3p$nvX%2CK=dSD-z_lJ|;FbZJ6>7m_ zum4>@yExg{z)628ByYm(1JUas(E(z@@H((s7!ORZgOs0nSqR_(ZjpnE2(V|t1o$)? z@OBh17fgWH0YFAOJ^=wfdhjY1w00r1c1mBo7c`xzL1#)pcRDgK zFsQ)`UC3oRkm43(3;5VuXhZDiy2F1!t0$o)6sXh20*+ot0D+kxUqVNK!AuY#2^qKq zwc7F+7(|gbDldmMQ$Th>E*OJUB?!J`csOXD;s1Y7fdgrGL+k??4Z*{m&mi1<>DQmv zpk7DTa>$|dZm<}e0$$SdgMq;qnhroWFM|s99}G;OE-Ex2!PF1Px%>bBObL&i0xR7h zaSf{7pc{{WKqid9OS+(EuKa+U$qgNO1!trmU=r5E03X2vE#0805WHRocj*SLUm&Vb zN;lAD$p3#pDm_pdV}P!9{sF1>pqmuHS?dR68ukBPSq26{aDN?Cx`B&~|Nq~;gED@= zPDlX<0(iCpRBl0Y-T(hPzaW6)`a&*y+m|DOeF8$DlD8yVme4#~%_c|by7H^GQ-Xe$WD|NjTnag*Hy zFFODKS_(Cn$uYKL_QHiTi~Jz9i6|(0pthnxjVH*~afs6xV5XzAtEsOF()xnh2{E3F z!FuV_KffL>23ZXeVuIH$YoGz~4Lkx4@%t8xu=)Sr9-{I8|Aj$b8IZ2fe5ep8m>6Wi zN%|5*2zp{TxGwty5rQTr@U-nWh!Av5J9uK@2Sf<6CK{4cph6%=gD#f@Ic+EjF))}1 zSTZoMfp%q{WP_BF0pMi(KN>PKt;gWEDUUdZ-Wr7HDae=2!zdOIm1ftZ{U>}u$~6g_8(veLWg-^DnSti!mtT+h(#a~(9Px00T-y?Q6F$+ z3F!txZJ*BsS@Z+Bm=7ulavx}Y$$!XX4n#Xh5HbS;ZtNlip}XWj6H7>fkX0N1^PrB0 zHX?YyYp(u4Z?1$2GJr-W|NpOpx&J0F~t+0noe>WcL@C*8`CTv#}7rgu#aY|No=I z&j;LL1u0q;F!#P}Z$l?Hb(Aq^?WH4u>Tq$v<-aAyFru41$g#!jg_$Ao2JA|Lh>IG;k*U4~=n1DI^X~ zL(q2DIdH`Z$>Gp;7j%sTcnQe}X?HO&F!1H9d-v=Ar~QqHS&jm5K!Jk(PZuQnKzD+J zgg{q#gV&@WwSqz7pt2J*_wxV$kG`M)=sEJ?(3_k<3sD#tM8U%#ml(i@^Fr%tA=d1?p1p6z2cMkR}3b{ubN| zoeSw5LR*oLv9S^+aFT@1`aqU7x*bT7lNBW90-02Eh88hy!L_%q5rq)!66FrI%tWLOF)1Zc(@w0 zJQh^V>o71_qL1p=Li?2e|KA4<$Ai=UQBp?reIUaXXrubzF2;YfQGM_r589|cc&ZR> zR38!%)Em_Y5B8yr>Vw;RsH6IjHCzi}MFMD4-wWKD`R@f2gM>VYyauby!BqlCx5vIU-j=RebshGxJ~0vZKnU?4Q`3>}&Q z=T7LrGjtXLdEl9(p&2X#&nlp3g$_JJd(+?s0(9URIy3{WPGAGi;Gr2vi{l4_3M5St42@*ta1Hc8XoChyP2KgN} z2wcF#z~l%TM1{11{{Q&$=RaupkO@+=fqVtxA_h3XvJ4FN;Qsml|7Rd`5DX0BJ^_B9 z3xf^7K?Y5Bi6G82$Q%YVfq=VHPltpMxSU3HDmW^kLeK;anhX376@ml?7r6X-3OTI= zlKj9;jQ>v|Q%Ap|nHV_0OL0Im@8BWw|KNZJg*HeC5;_pxZcqc_DFbxu0VH-t7}O62 zZEb?)wa2w=;N2h~A#jVq4^c5s0L1`o=N5w+h_~Dv+^G5njU&i;>A!d&OIn~qz~C(v zpeeJN1Q4bE(kbp{OJrsf*xsYaimX$ZWg?-vK;FdE3V9tP;KH<6G@ zU-)W4@ZOuH;1N*B<{nVu2QM(Z3zkA!9S%yFe?W`Fk(LKS23$asB!~>l0NFeP3Ji#E zK}Isb_h*4l@P~?kigZXF4{iCw#39Xe$bc6ELp&%}pkn}_X4CTJ(DG~wNCLdw`Tq|{ zp$5rykoW-ajQKAKnP~;rXwZ!$kj-=8R`LY~$TClGrxP-f4&BfKo(gD%x*ELy1GK#m zw6F#o^5Bx*9=dN1T#H=z|NjqYR2j4j3>==I-E<7#W{4L9_|}O_pbphz1_sE&d9WkF zYeqUCdzR*d*Qd%eKsJkjmWDyf^rMiKapB+!C>**k4BX}g?+O3I22PCf;G@?TGJpqY zq1|e5r^ySHsh&c1H(r5Ml8`(HSvr&f>TQ9>Uta$I|Az_eYe+7IT&p)5)Dr+bTh(LmIo#J$B%N2<2=INa+FDy#@}L|NsBP(>(0h zM(Alv;KjGFE624!NoqNCnFP~pFi#kAF9T$w8zcll-A>4X3U@(y4s!n1El`OE&ii0z zgToSfzB0HF{GkM$&xfXV@LlHrw?MY`fHi}BmIKN-|G`lQ)eI7amV*EPgKP!~fUpuM z%s|TFnn9wVr~nB;VQfJt5Hq8lDER3~(?ofcFRf|HT6?2w`iXSU@!e=nPVD zWIzf5Xsgf-I%y0lyg`TJf&34uEg-c#cr7*Lgg)@j8n9Jh{g8?XT$@0w0u3{OvIH!t zf~}gyz`z7r7#OB(S_dkD z{{R0EZvR6B!BhJn?|{p2h!}X414s;c85~sbK4?qOfpbx`ht0GcZVkC!*$q z&-&rv;bDOmt`OfM?MQ(Npm`s$V+AG;vI2AgOi=Uu<7YZ5cgLHONTkwjd>NWWWke(4Y+igXKa{KN)&)iS<%YBMHI*cPjov*6Ts0 zDR+dbfm{wY8d6t6u62ZOBO=GuDBcFQBEa6(i3C?g|3MZ)&dY)YA~ZxHO&&1k7j)M{ z+S2)rL6D6RpwLw+n!k7&V$F~(Ll3xk`~PPPxMpIi`~~hYKnj6R>*g+gj#+eoL@vZS zx+QLb=>7ly|H)+V<`4!3@k(%^^`Vgs9IPNK85r0cy(~e=fX^?#BwryoF|Sy`DL*HL NffvLFadkmlMgV{oX3+ou literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/LittleFS_functions.ino b/examples/Smooth Fonts/LittleFS/Unicode_test/LittleFS_functions.ino new file mode 100644 index 0000000..fbdc0aa --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Unicode_test/LittleFS_functions.ino @@ -0,0 +1,39 @@ +/*==================================================================================== + This sketch supports the ESP6266 with LittleFS Flash filing system + + Created by Bodmer 15th Jan 2017 + ==================================================================================*/ + +//==================================================================================== +// Print a Flash FS directory list (root directory) +//==================================================================================== + +void listFiles(void) { + Serial.println(); + Serial.println("Flash FS files found:"); + + fs::Dir dir = LittleFS.openDir("/"); // Root directory + String line = "====================================="; + + Serial.println(line); + Serial.println(" File name Size"); + Serial.println(line); + + while (dir.next()) { + String fileName = dir.fileName(); + Serial.print(fileName); + int spaces = 25 - fileName.length(); // Tabulate nicely + if (spaces < 0) spaces = 1; + while (spaces--) Serial.print(" "); + fs::File f = dir.openFile("r"); + Serial.print(f.size()); Serial.println(" bytes"); + yield(); + } + + Serial.println(line); + + Serial.println(); + delay(1000); +} +//==================================================================================== + diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/Unicode_test.ino b/examples/Smooth Fonts/LittleFS/Unicode_test/Unicode_test.ino new file mode 100644 index 0000000..46f2fa0 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Unicode_test/Unicode_test.ino @@ -0,0 +1,152 @@ +// Created by Bodmer 24th Jan 2017 - Tested in Arduino IDE 1.8.5 esp8266 Core 2.4.0 + +// The latest Arduino IDE versions support UTF-8 encoding of Unicode characters +// within sketches: +// https://playground.arduino.cc/Code/UTF-8 + +/* + The library expects strings to be in UTF-8 encoded format: + https://www.fileformat.info/info/unicode/utf8.htm + + Creating varaibles needs to be done with care when using character arrays: + char c = 'µ'; // Wrong + char bad[4] = "5µA"; // Wrong + char good[] = "5µA"; // Good + String okay = "5µA"; // Good + + This is because UTF-8 characters outside the basic Latin set occupy more than + 1 byte per character! A 16 bit unicode character occupies 3 bytes! + +*/ + + // Flash filing system + #include + #include + + +//==================================================================================== +// Libraries +//==================================================================================== +// Call up the FLASH filing system this is part of the ESP Core + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +uint16_t bg = TFT_BLACK; +uint16_t fg = TFT_WHITE; + + +//==================================================================================== +// Setup +//==================================================================================== +void setup() +{ + Serial.begin(115200); // Used for messages and the C array generator + + Serial.println("NodeMCU vlw font test!"); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\nInitialisation done."); + + listFiles(); // Lists the files so you can see what is in the Flash FS + + tft.begin(); + tft.setRotation(0); // portrait + + fg = TFT_WHITE; + bg = TFT_BLACK; +} + +//==================================================================================== +// Loop +//==================================================================================== +void loop() +{ + tft.setTextColor(fg, bg); + + //---------------------------------------------------------------------------- + // Anti-aliased font test + + String test1 = "Hello World"; + + // Load a smooth font from Flash FS + tft.loadFont("Final-Frontier-28", LittleFS); + + tft.setRotation(0); + + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! + + tft.fillScreen(bg); + tft.setCursor(0,0); + + tft.println(test1); + + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + + //---------------------------------------------------------------------------- + // We can have any random mix of characters in the font + + String test2 = "仝倀"; // Unicodes 0x4EDD, 0x5000 + + tft.loadFont("Unicode-Test-72", LittleFS); + + tft.setRotation(1); + + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! + + tft.fillScreen(bg); + tft.setCursor(0,0); +uint32_t dt = millis(); + tft.setTextColor(TFT_CYAN, bg); + tft.println(test2); + + tft.setTextColor(TFT_YELLOW, bg); + tft.println("12:00pm"); + + tft.setTextColor(TFT_MAGENTA, bg); + tft.println("1000Ω"); +Serial.println(millis()-dt); + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + + //---------------------------------------------------------------------------- + // Latin and Hiragana font mix + + String test3 = "こんにちは"; + + tft.loadFont("Latin-Hiragana-24",LittleFS); + + tft.setRotation(0); +dt = millis(); + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! +Serial.println(millis()-dt); + tft.fillScreen(bg); + tft.setTextColor(TFT_GREEN, bg); + tft.setCursor(0,0); +dt = millis(); + tft.println("Konnichiwa"); + tft.println(test3); + tft.println(); + tft.println("Sayonara"); + tft.println("さようなら"); // Sayonara +Serial.println(millis()-dt); + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + // + //---------------------------------------------------------------------------- +} +//==================================================================================== diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/data/Final-Frontier-28.vlw b/examples/Smooth Fonts/LittleFS/Unicode_test/data/Final-Frontier-28.vlw new file mode 100644 index 0000000000000000000000000000000000000000..2872fd554bbf34f5e1268770dd8ea3cf55cecdfd GIT binary patch literal 25287 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/data/Latin-Hiragana-24.vlw b/examples/Smooth Fonts/LittleFS/Unicode_test/data/Latin-Hiragana-24.vlw new file mode 100644 index 0000000000000000000000000000000000000000..b2f128b4ed054b8c3a488b361f6903e4b557722d GIT binary patch literal 54478 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/data/Unicode-Test-72.vlw b/examples/Smooth Fonts/LittleFS/Unicode_test/data/Unicode-Test-72.vlw new file mode 100644 index 0000000000000000000000000000000000000000..c4757564c98f7c46a98dc54f913b83808f2bcb79 GIT binary patch literal 36469 zcmZQzU=U+qVBlt8VDMmo022lV20jJ`1_cHN21Y0rVPIgG@c;k+9S|i9+6)W~N>HrD zz`y{)EKoUJ1_lOJ1_lO@9to)VOi(#J1_lOpCd953=9k)cQ8Zc z3>g?0j2Rdhgc%qZKyn~92UN}osutuPkQ_)K%s!AhTxNpQf#j8u%mn!tWGqMzNFHV; zNFB^AW_a9b4s|CseHM81S>lniVqjoUMG7+z8y04X3=9nFNMWYNz`y`=XD$N+1Bed_ z9~&qe6fYqE6+pub6vv=21F3__ZH3CoLBj<}j(H{2o%#$63?RRP!U-Dhes>ud80;7r z7#yK#31lZ!E&ybw0|Ntt6OtUvogg_F{tpH)9yS`R;6FAQnAoTaSV%zVfeR0a&BKF) zge8oG_zA|tMvtmM4VA$h9uT(;G7>5Hq|=sO`10$=mrJYiRFH(>OoL5-kQ{&54K4v? za7;sz1~WH^LZu*-_yw>i3h@+Fr$eL}7({QO$U!+TK~)Dt3DaSS*pF#GJPZuN0ds#r z`1b`N@(c_e5P{v2FahZu5RrvY0WF9pU|g{1Y={zTFo$6an71Fofswnxg2%yJEin6= zG?)V?B)@=#!G=r$Gh5+uP)0pi7-Tim2N3fQ+?7xT45DBU{a|5WZ~-a!zYQjVpx1yU z0w67=|NqkvGB8#+Sj99321s~giA-Uzic1VE;K29*(}+wz1S$E$VhN)DuS1rBu~&hm z>>;+zhKVB6U0@aAtzaq^Sq8?A1xs};1ykVq8zuvzeZW$SH-RaPGzU^;50=_=98AfB zM9?uGSn9$%Fa>MSp(x@2OTGIBreMuF6ctQhsZT$^6p9R-1D1j)z|nLdQUzGqf4pWu ztbtpN!T@XkLD(;Z!vm6lFj6VVHc7B8=OFRo0un*TZeSG~AaU!1E(_uZfK@E+0aJL= zM-L>KOakda$B?WR?g%ymYdT#Ama=C9Q_s=$gZR%uQh!(&E`jL(X!#nXKpHG@iGg7z zm;q`JgM^WAB3NP?0|UfQSn@3-r2H5dSipJwk1UdIFjEwq8NY#2-$JlyU0`7(q8Tha z6C`2_X8r*606<(QmW7l-pgs-*!%47`gCO&u(hLkt`@w>{Ap($`^M5IX2O%NR^&ixQ z0tqY!tN*_r?pkSx3IBUQvLGx7E-C*1|25l3kbyza2UaGZg!LX67&Kl&OhF~@i-WX7 zu^u=MP!(K4O?aY^5JXZllMAXFPI*8p2#BIBkbr>8LKrGJ%P)NS@#E8(rD>=ZK%^lg zID8>YD9LmMWGIvap&;=AVM9nrGDOa~8jxIuBqaM3WYB-4{H+2Lfva+S4OIhIRRm5Q z5K*vQu!;>Klmo6*{{Jt42{}UY@BeS13=kp9gAn@vEiDG95LDp*6i`^gI3W58sJDo$ z>M5+M0m*{!!vc5|gSh|yAB{vxY!D%^Q(?rY&}c{?r+ZLn&@@f(1WnuY`rEG`Uv8{x zc0)>=Ad5lRd=0oPhPdJX|JOZe1%mVjm=v7;Q47)t!#>a~2bTsj_QIQ^3~68iOyUAe zNhnnA&xU9XCI$v!zX`CczaQdY6-Y(?e-*q4X5grY76yp1l#xvxyXhpfmE7l43Ku<8mK5Tl?OIt zDZ^Yajjf*71It`tfV9;?!(hnzL2O9#>k9+K${I$}|hi!AA6fP56Hjn;clI9HQV0XygtofKFsU6#Pd|cW`wu z1s!k^GzPRL`@a}X9L{ZoT7fe{AZhOZ{|%7L1lI^-@Ig9u|Nk$?p+MyZ)CzF33#JW; z_J9=u^+^B|9=-pP)lEfnt)XBfJ}yCcmrbs zTnLq+11T;3|B6Qyhx4?c3f|emg-{vt&<5N~Sj!Prnt?$Ok|h7X)}I3}iuMHnb1^|1h#33LDa0`2QbU83R@b>48JT6DtKvwOA#=f{-pcn2Cdc z1{MxkkTAHs1u<}9uyer#Tfp4CpML!Mc6UuV*1#3-f%FR?MqP*mYeFW{AjK*~9z-5T zO=%pEzCK6>jz1xH>DVBp9$XU22t`-|9b@@_Axn#ifz7fO)@!hbDS>pH{(pm4V@#Eh zFnG)ZQNjYz@(I!|g^1Zg91bl&vLMz5LFAw$q+a?4F$7XsZGcL_C`hLPoIN2m0KEGH zQvs<5K{X{qHQ17KFc}yPDb;U)xR3!Ply(A07*hRw12OM|&45jXfkYq}Ec^@17WAoJ z^Bms31`9DTFhDx7U^8GsXf&j*zk();%!Le*f&GFkj9`mGx-8)c5p))$@_3H58V0Fl zfz)9CvDNh;c?NrE&jh(^azZYBL6OEj|``x!6-`?$>AC5JyA^w7rkP&n!2P?$`sZp@XK?R}Z1eAx3 z@`Ab>n;b+;5LVkmxY$VOFdKZd2U88KpNLzDD6Hd%TM1Ib1k(nv2sG`1{R9@kASA)* z6gt;~Aqy4&_a^W2fDM5UX@O;61f+nrhmJwPM3HG(aLqmiHUNbz1!IF#)m<(;N+8J> z)SkrU7D(?JJeY|~3AmWQ1@1}VP*MpNhqOz;ObkzJfO8|*8XV4L0@sMwphY`YQ^2Lr zA6Uy3n-V>6iwQC+z<|{vHgH$r3cTFFVhXr@@CT7UF_oBtg^;?qU_P>^Ilwb{7m(^0 z3?-n2KL7t9w^z}XK$2E)_f4EzhV5rArn2bfz8OH~jWEC%zDAb5QC z3`7P_q9_43cz&R^n$g?>Q9oozxIa-C5a*)^p>sx+poa*APpfc&G;koMqmdAc86Y!p zXmSuPR0X6wh6tgNP!)^Ogps&V70@;bk_4OyQNaW*o&H0MIEWZ3X%5zbXW)w=8mwYD zsx}lJIK%%hM-fBifa{I_$lX^|c?Je>Y5gBIM2jv9TIB|I#%nAxFd;~NjdNUz0oD$O z7uGP1NHnCIh1#7(l4f9FfV91^PI^NWih~`BufquGO@U?vg`*dq{PgSBmkW#IK`S63 z1~4!%fa{(A(-_=#Kq3%q`7Tj%lbcP5d&m|;2m1S z9E11<+*!aXur5G>8m0kOac;`OH9KB^14SWJ96>>H+EPec9_tzsNRdzgNu}5VjtSE7 z(SZ!rzD8=cz^sAH@84oD06XVDW5Yzt8M{x>tG6~Y&f%IDc|38W7;7LQf5g(xK5J-O&G{ljp#l*m%6tomN-Sr2a zdLe@W5ceRFzmUQ)88YgCB>VsWf7BeL0v)8GxQc}gL!ysoK-%vAL6r(5Yhfl- z$RYtyIR;6x;DJ%F&tU{)7VH880|U4Kz7G>e(30QoZ(B9Dl7Rudkm5f|BOaj&%!16} zK&t_;2s#0-u(4PISH}cS*Ena17#J8J!G&|;fPn!ze+eCS(5qed_}i}^FW1!~`aukk z(i=Qj=!e|cIS0=ykfNE1fk7PH1x89jyP-3u;8De23=BHpE(MZ;|Nmb?I*{Oz^iK?G z*izv)@C*^SpZ^-V?&eyFIU56$QaGfo@c;iOP|XESf3Lv_{Uu^lQVX&o=s&103u)ni z?7xJ(-iZb5zW<;!23K(dnk1p2%>s^%|9|8m<^TWx|1o9&CBgRppTGcXFQ9d<7#N_V z=%1LNwtPX)r3?%_5GfC6W}6SS9+`p^cO4%<-uV9?Tb&6R&R7SHEuO*Mo z!TZHuBE+LXUtfT!4+;PS+_yTs~FG$7wADbpBKV3}MR-ki6ChP0F9ZRCJIU@E02c1Ejh46yC;z z83d_kL2Y#C2qXH!J;=x$c%+*NI%bJFM=T1-9S6ZC!g?>rW4FQ(Xa0fKeXv=*32?Vq zLYf2ro54mfFfhR~G3w8fb(nU|?W@7Qv7hfRpEt8y%4FgUf*#hmjR9 zFjzzCf3Oso_|u3|iG%Em1rPRsW&i*GwGdiegJcj`t6=$+FF$^KI5;gEys6wS%^iL3$q88k|tIkXe++xSBc)3>uIU6k01mb)is@f(w+{ zP=pa2NCk{J-+)j7$xFDyiUHEXzJ}0&!Gh#stnD#~T1ZKNWmzmlnt_1{+~NfpgJ}pcLm6iu*5y*A~R2di#QW?P~(_z908q(+a0Up;zh$6H6z?NXEMqsKStpz-( zlMCE1`+`vb!VF+wfMj+&>6Zag@uF4`2>qZ|FQj=5ZDFBEK{=4V623`sNWqS|01j#Z z0|Nu30>M`8!qh+-ELaP3h!RMhimyKm$!TbNPavA1B*dYh#yL~~gMx$??zLeI&>b%D zRx5@H3=ELk6YF*hsA@=<<1QT;7{F2gA5YYSO){@tb04%q^TP5xY$3;z2QC-DDe?dR z|0gjTd6wWD3zG-YN5L(0u;Cyg4N`=HWZ?J%vd>_P%;2(M#xF#t5Rwo6|Nk@ryz3}v zG1SCw(AEb7Z02n#JUEmfO|bvBpe-!$WXJ#iD7`i4vM)&2hz}B4XbBKf4!j1p7a^kq z&ym^!Am2e(Jb}7%(2N2x4F7Z)kE?D)aM{A5DaPIf>S?aG!Qf|2a$r3klFL6AReR*iQyN>01bHHqzG)`V>D~n zASoAInMp(939YP#^l70*Jhb5mRt~Zjgdqn1?*p+J7@*y(|MTH-D-4ae8?dNQgS1xv zf0+c@0m0=n36eMd-$m3!;+O*@|NsBrgfd1F0IoQ|zJe0x5NQzX7$!GJf`Cf@|Gxt@ z%W%{}8b)w=5MwW-TM0J603|blWFdGV%q#X#r~f~gVamq9z~NC3%U(Ai%a2tcZJPgQ zkP=Z4B+UOm1bYWOUHbq3Oq4Xl18Js!*EB%-WS9e(;O^@G|M3hA5IZqfp0Yp&XKyiB zL!1rj>Vo}+ARxVy|F)1lXIO_oAqx#UATGjMtw4r1Hb4Rs>%atLIN>EErK9*1<`hV3 z{{~5dFhNur?1^7EavVr0)C|aKF<4;(l7M5#s=Cbbwa^LxTVR8WdBQpcxU| zqJgf2`F{&M+5vH?Ikd<00W#NN4+;7I|1Xr-voSERSrj zF@+{vB-#J}|35?y0-h-l&m$|DiQ3^~P@4wJHDFa=rlICaum_ktTG!qE^5e&s`|G;A zuqGJ6$oYpq{P^?j)~W)mNlt4yq>2FB@&7nRMaTu|OhBZ; zvgAMzGIsPIwOhpliGFbMfR1XTtT19=U{HZ136MTWv|fVPh(to#PJ0;`po5^uj({i= zhJ>*+10=s-8*_vdQ#lL}8Zqb#F#tqDYU)kU?YG#PS&(_oZ+NEfAQkR^J&1d-CKyN@ zhC|XP$X*N#QPBYj7z|lZ%Ne3#F{DsOOV(fwDi9T$AQcZH>wqP}L=Z&9708G+N(%=p z&%gl9+wUNaTP(A?OyE)E|Np;0TS3SpJrFY>9k>7ge?S{KkI~)A18GwH|Nn~tI)t_Z z+-ibo2a%BY`v3p`9|ou)|F^-aJ&-)ing2nyFo;5jUvDA$w2)P7SHS5LG%w}|iJSlb zk7gJ!F)+yntpZ2ICpB=r0bbS^08;`9BMAA;g#kQb3E5`i0ttJF6oh-$1w(eBgJz(yNP>kRbJXZL9xMeVAe|m_ z28Jn%*X(}%4croeNdy8g!u4A5P^m}v}BI)G+eAj9|=bNA4;HfYWUQmbNg@*(vw zxb}nee9>z{NM8dw$^pqS|MMUYgpkmwLFm?Bc}Uj%-vw{wNT1WefW?#GWG@3zejh4}$212dIq8mwzD6GZz2rV!y7>CkEGZhiUj=f}5q z2bWjcqnH0|8L)~LruB6zN{JW^tEpk~Ao?Y^SO8nXfi1#8YGB!d4N@nAgwXIGXu5$8 zvHri+>Lbd;z`&vuGznbr{r~?TvQiFGy8M5QJY>QK*)k2?e*-DA-a$(vu)`Q&E2Y8N z0@}{UXzM@9A3DARX{4X{|pSGkizdJQZE3kfPo8U3#2st zf?7_2)Ie5_{)cViz!*kgV1TsI{xdK@(kzx1J2ZzdKqoOl#-d^#Xyp!5fu2cWlbrwm zvp~14LURtn80eCr|Nl9lTVK(elhTmB-~a#rd7uII2X*O^2eh5?|NnnW251C*0*?kk zY|%h2{5=>LAXVG{|3}mGm_Yse5@<@e1@TNI1A{2EF$M`_IJrd-QX+t6GYl}>EdRgd zz;Z6Q(X4`&K>q(<4(hqFK@11`fvFO?koqzcS`0v{R%p|Q$*ph8>mNV9z1+})z1IZs zrE&A7cRzl8d$^_?dF)TRV9i6&B>skG=wJodGawy~@YD$!g@HxBENoy8r0zI4vOui= z3=C|r!Vb*;|No00$P|WTlz!j;|DZk&SOo(Qw3iF!K?qRc3mKG$@F8RtG)F+=A0h}P zUkXE~$)S7*^-BvDAFEz-vibl2|F@7fsz3)<{{R1f9I1f?vGPA;(B%LBZ-|BmeAN8^|Hts* zGmtHi@dDVAQq(>JG-sks=R-OGM?qfr|Njr_P(P$M^&gz>K&C@5qznMJwEzD{8&QWY zHiWjaAnF;QwSiQ%o2p3e3KxP%7^%H|RMw9k6#1e=GaY*F^;Xp~q%5Mk*)Xg(bh4_LQFUZmq#DNfR2sXLjCs# zy)s|`kB$6a2$cu5t>DoCW=s@O`%Fad0=^ne)OsiqyjRI3TXvkTV?|p--PtRFghBbE!SZ4AyXvC9a)gsAPnh( zKn^-Yo4f@{GeDZ(kaU37Kmp0KfLoA%Abn9RN5Vk1yBvh34~!8h=n!)TRQ^Buj4EWw z%xeyqJYq2Y972xDLc#$;j)n##93UjTn1BZhL>xk*4o|_y1tF6EQTnwY z{g4_5DvMmkfFz-POsFiz{3CP@9wLpgGyzf` zOprk^s4UWiFW6w{sX8!O)LKd&QuV_n|363S{!3#nH$jZ%`9K;^2%TWorT}3ECXEb8 z;|(^a2a{wvvw4sQbU-4tuqqG4VGx9v2V#S8EmDOBDwUY(AypYj?gprW z12Lc&6a;)3YaW05@#V}+q!t218YGJikIEv43MHWdt{Cu+up`^V<=3(9(uW_vetbB$ zs@Vr^1{hf(C>zJ_Mja&owE-0OXsTe`4CKTJ@zDSOHz4DHFg0*m3(}y3DMQdZP)DvH z8sZ_%SA;4A3u(#*qLzW77B0KL$cu-Gfr-Z}Zwt&Lf6&|TFx7whK*O&vGsK%=2_98F zbZOTAbI`F^n0f|jNDtuuALIf}2hx1}zZj#0WMF{K^Sng(7jk|s(pnL?;UEUoorn$; zWO(yG`cYjVwIB>V*AKS2Nfgp?ypOGk4^qwoiIAtzE(+9j$esbILSP+8fI`**>IhhPCnoBcm}5Q62Pge=5(&{`E}4*}tEs1g(kvQ`bW5*xZ<3Zrg7Q4X2> z0!>^&CeT2ebx;(bav%p%gI0b)jsbvYy@UF#2giZsAXV)EZl@`fn$Jd%Y^J6hbcj(!DT$s z0&_@d09p`(tO~}49JYWwAp%(=hCU4fQEv|(!a-V$#K0g5?yCR5mcfm|Df|Mow1$|# zpam90Svd%iu?0)KL{H$hkm?CCzyMJRB9pPMnnJUf8@WP9^vy z=KlYIva|}nYD`)17D3Po5=<$gL?8_we2dly7z1AD`VLo6%@qn8UkcK;aw+5OTyj<`y zm>*h@VjMJ2fLAr9B&3WiVBml(y+$vJFg2iw*n$H9lm@jRg&B_i2AVcFS03EQhRnS~ zs=9CJL&R{k*cgygZ+<{WSs{xc-eKK{fK4|80|&Tbh97&u0-3*mNp!}B?%GCFL6AD* zKd~k-K?d%@RXx;&kXqzF&SR>f${-XAq)OWhsm&o`4A6Sz9b{$-Du|upgDeAqAEyab z|Nozl;y17^1d#`EDAH-4 z2ssAW;^yP9<_MA;geeROezapsA#xzn4bp4-kENFjl4fuLtxW+P=LF_qBh0}G{Qv*| zjj&1>Nfi&I6^Z*$bC6nj*gVBaq=74t1Or0=)Oyf*Y={U}QV^0z{{R1iJbB2#paK)$ zk36Y@)dX__=9A_Hs1{U;ki7_bRDF1OU@ds$2}+F`0F79JA%#c5XdsRTA}D!`rUUw= z18`WALx3U*gvrqh)&tTE!e9 z|38i~9g1HInk;zd6rq7aG(D(X@K_IYa1R_(_z6_aU>>;51Uf|&zN7@N5nw$ige+J+ zbfFQLjh{f#4CX*aE1^9s{F=eCU`;3lc&Zq7v@KW-egZ`^m;;_KfpxmTn!&=v6X2m2 z@NRLC9&$_opKJLC*6=3B1n}H7eCUG=6CiUh@F6I$33v#QPth=VR_PbK^M^+>SPD%y z=ulm7gB&rS3|5ARz%&6e28_tvcr=5hFiik&1VP&L3s#1Qz%T)_zW{0M1gsfD86E-1 z>_1XBl~fZTQHeZ3L#heTm2F6lB+&%eAv9#0zy#~)qMHDA2zCNVDFXuoBb710+3zRU-+5`FIEHV!&GPm;hc3{sHRoaAU4V0%Q%#x>|6X_y2#;CDTYcVN84`zz(zqtNH)`8umFJuq@0tSi2g= zhsgP@=*MdU4+CVM z$Nz`Oi?m>tLuouFFy%dGfE}^)4!*$?st-ZoHX-&FXc;5}Y<2x?j76+41BeLNM7|>ML><@-42ZKRp4YR608Hl1d)*Cwy>dc z=#2)jLoq2KFkDg*A*mk9MiiD zE|6(Ako13~1$n4(0iCM5hNBa1x*ReU^#4Eda6Z^bm>U>C+czF#J%kLRL>zLfBg%|8 zc=!P#4I%{(m*dF9AXyMrD%uS`MOMJEC^IofAv7;DIX@*;!8e$J4=e%|@C{}J0HoGP AeE