-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathdumbdisplay.h
More file actions
1936 lines (1822 loc) · 92.6 KB
/
dumbdisplay.h
File metadata and controls
1936 lines (1822 loc) · 92.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
============================
if want to disable int parameter encoding, define DD_DISABLE_PARAM_ENCODING before including dumbdisplay.h, like
#define DD_DISABLE_PARAM_ENCODING
=============================
*/
#ifdef DD_DISABLE_PARAM_ENCODING
#pragma "message ***** DD_DISABLE_PARAM_ENCODING *****"
#endif
#ifndef dumbdisplay_h
#define dumbdisplay_h
// not used???
// #ifdef DD_4_ESP32
// #include <esp_spp_api.h>
// #include "HardwareSerial.h"
// #endif
#define DUMBDISPLAY_BAUD 115200
#define DD_SERIAL_BAUD DUMBDISPLAY_BAUD
#define DD_WIFI_PORT 10201
#define DD_DEF_SEND_BUFFER_SIZE 128
#define DD_DEF_IDLE_TIMEOUT 5000
#define DD_DEF_TUNNEL_TIMEOUT 150000
#include "_dd_util.h"
#define DD_CONDENSE_COMMAND
#define DD_HEX_COLOR(color) ("#" + String(color, 16))
#ifdef DD_CONDENSE_COMMAND
#define DD_INT_COLOR(color) ("+" + DDIntEncoder(color).encoded())
#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) || defined(DD_DISABLE_PARAM_ENCODING)
#define DD_RGB_COLOR(r, g, b) (String(r) + "-" + String(g) + "-" + String(b))
#else
#define DD_RGB_COLOR(r, g, b) ("+" + DDIntEncoder(0xffffff & ((((((int32_t) (r)) << 8) + ((int32_t) (g))) << 8) + ((int32_t) (b)))).encoded())
#endif
// #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO)
// #define DD_RGB_COLOR(r, g, b) (String(r) + "-" + String(g) + "-" + String(b))
// //#define DD_RGB_COLOR(r, g, b) (String(r<0?0:(r>255?255:r)) + "-" + String(g<0?0:(g>255?255:g)) + "-" + String(b<0?0:(b>255?255:b)))
// #else
// #if defined(DD_DISABLE_PARAM_ENCODING)
// #define DD_RGB_COLOR(r, g, b) ("#" + String(0xffffff & ((((((int32_t) (r)) << 8) + ((int32_t) (g))) << 8) + ((int32_t) (b))), 16))
// #else
// #define DD_RGB_COLOR(r, g, b) ("+" + DDIntEncoder(0xffffff & ((((((int32_t) (r)) << 8) + ((int32_t) (g))) << 8) + ((int32_t) (b)))).encoded())
// #endif
// #endif
#else
#define DD_RGB_COLOR(r, g, b) (String(r<0?0:(r>255?255:r)) + "-" + String(g<0?0:(g>255?255:g)) + "-" + String(b<0?0:(b>255?255:b)))
#define DD_INT_COLOR(color) ("+" + String(color))
#endif
#define DD_AP_HORI "H(*)"
#define DD_AP_VERT "V(*)"
#define DD_AP_STACK "S(*)"
#define DD_AP_HORI_2(id1, id2) ("H(" + id1 + "+" + id2 + ")")
#define DD_AP_VERT_2(id1, id2) ("V(" + id1 + "+" + id2 + ")")
#define DD_AP_STACK_2(id1, id2) ("S(" + id1 + "+" + id2 + ")")
#define DD_AP_HORI_3(id1, id2, id3) ("H(" + id1 + "+" + id2 + "+" + id3 + ")")
#define DD_AP_VERT_3(id1, id2, id3) ("V(" + id1 + "+" + id2 + "+" + id3 + ")")
#define DD_AP_STACK_3(id1, id2, id3) ("S(" + id1 + "+" + id2 + "+" + id3 + ")")
#define DD_AP_HORI_4(id1, id2, id3, id4) ("H(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + ")")
#define DD_AP_VERT_4(id1, id2, id3, id4) ("V(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + ")")
#define DD_AP_STACK_4(id1, id2, id3, id4) ("S(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + ")")
#define DD_AP_HORI_5(id1, id2, id3, id4, id5) ("H(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + "+" + id5 + ")")
#define DD_AP_VERT_5(id1, id2, id3, id4, id5) ("V(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + "+" + id5 + ")")
#define DD_AP_STACK_5(id1, id2, id3, id4, id5) ("S(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + "+" + id5 + ")")
#define DD_AP_HORI_6(id1, id2, id3, id4, id5, id6) ("H(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + "+" + id5 + ")" + "+" + id6 + ")")
#define DD_AP_VERT_6(id1, id2, id3, id4, id5, id6) ("V(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + "+" + id5 + ")" + "+" + id6 + ")")
#define DD_AP_STACK_6(id1, id2, id3, id4, id5, id6) ("S(" + id1 + "+" + id2 + "+" + id3 + "+" + id4 + "+" + id5 + ")" + "+" + id6 + ")")
#define DD_AP_PADDING(lp, tp, rp, bp, id) ("S/" + String(lp) + "-" + String(tp) + "-" + String(rp) + "-" + String(bp) + "(" + id + ")")
#define DD_AP_SPACER(w, h) (String("<") + String(w) + "x" + String(h) + String(">"))
#define DD_PROGRAM_SPACE_COMPRESS_BA_0 '!'
#define DD_COMPRESS_BA_0 '0'
#ifndef DD_TUNNEL_DEF_BUFFER_SIZE
#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO)
#define DD_TUNNEL_DEF_BUFFER_SIZE 2
#else
#define DD_TUNNEL_DEF_BUFFER_SIZE 4
#endif
#endif
#if DD_TUNNEL_DEF_BUFFER_SIZE < 2
#error "DD_TUNNEL_DEF_BUFFER_SIZE must be at least 2"
#endif
#define DDIO_USE_DD_SERIAL
#include "_dd_serial.h"
#ifdef DDIO_USE_DD_SERIAL
extern DDSerial* _The_DD_Serial;
#endif
#include "_dd_io.h"
#include "_dd_feedback.h"
#include "_dd_colors.h"
class DDLayer;
/// @struct DDFeedbackHandler
/// @brief
/// Type signature for "feedback" handler. See DDLayer::setFeedbackHandler()
/// @param pLayer pointer to the DDLayer from which "feedback" is for
/// @param type type of the "feedback"
/// @param feedback data concerning the "feedback"
typedef void (*DDFeedbackHandler)(DDLayer* pLayer, DDFeedbackType type, const DDFeedback& feedback);
const int8_t DD_OBJECT_TYPE_LAYER = 0;
const int8_t DD_OBJECT_TYPE_TUNNEL = 1;
/// Base class for DD objects.
struct DDObject {
/// object type -- DD_OBJECT_TYPE_LAYER or DD_OBJECT_TYPE_TUNNEL
int8_t objectType;
#ifdef DD_NO_CUSTOM_DATA
#warning ??? DD_NO_CUSTOM_DATA set ???
#else
/// custom data
String customData;
#endif
public:
// since 20230601
virtual ~DDObject() {}
};
/// experimental: _h is for internal use only
struct DDLayerHandle {
int _h;
};
/// Base class for the different layers support by DumbDisplay; created with various layer creation methods of DumbDisplay, DumbDisplay::createLedGridLayer()
class DDLayer: public DDObject {
public:
/// set border for each size
/// @param size size unit is pixel:
/// - LcdLayer -- each character is composed of pixels
/// - 7SegmentRowLayer -- each 7-segment is composed of fixed 220 x 320 pixels
/// - LedGridLayer -- a LED is considered as a pixel
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
/// @param shape can be "flat", "hair", "round", "raised" or "sunken"
/// @param extraSize simply add to size; however if shape is "round", it affects the "roundness"
/// @note layer property
void border(float size, const String& color, const String& shape = "flat", float extraSize = 0);
/// set no border
/// @note layer property
void noBorder();
/// set padding for all sides
/// @param size for size unit, see border()
/// @note layer property
void padding(float size);
/// set padding for each side;
/// for unit, see border()
/// @note layer property
void padding(float left, float top, float right, float bottom);
/// set no padding
/// @note layer property
void noPadding();
/// set margin for all sides
/// @param size for size unit, see border()
/// @note layer property
void margin(float size);
/// set margin for each side;
/// for unit, see DDLayer::border()
/// @note layer property
void margin(float left, float top, float right, float bottom);
/// set no margin
/// @note layer property
void noMargin();
/// set layer background color
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
/// @param opacity background opacity (0 - 100); it combines with layer opacity and alpha
/// @note layer property
void backgroundColor(const String& color, int opacity = 100);
/// set no layer background color
/// @note layer property
void noBackgroundColor();
/// set layer background image (on top of background color; follow opacity of background color)
/// @param backgroundImageName name of the image
/// can be a series of images like dumbdisplay_##0-7##.png (for dumbdisplay_0.png to dumbdisplay_7.png)
/// which can be used for animation with animateBackgroundImage()
/// @param drawBackgroundOptions options for drawing the background; same means as the option param of GraphicalDDLayer::drawImageFiler()
/// @param refImageWidth the reference width of the image to scale the image (while keeping the aspect ration); 0 means no scaling
void backgroundImage(const String& backgroundImageName, const String& drawBackgroundOptions = "", int refImageWidth = 0);
/// set no layer background image
void noBackgroundImage();
/// export the layer as background image
/// @param replace replace any existing background image; for add as an item of background image series that can be used for animation with animateBackgroundImage()
/// @param noDrawBackground during export, do not draw background
/// @param exportAsWidth the width of the image; 0 means the default (should be good enough)
void exportAsBackgroundImage(bool replace = true, bool noDrawBackground = true, int exportAsWidth = 0);
/// start animate background image series
/// @param fps frames per second which is used to calculate the interval between the series of images
/// @param reset reset to the first image in the series (before start animation)
/// @param options can be "r" to reverse the order of the series of images
void animateBackgroundImage(float fps, bool reset = true, const String& options = "");
/// stop animate background image
/// @param reset reset to the first image in the series
void stopAnimateBackgroundImage(bool reset = true);
/// set whether layer visible (not visible means hidden)
/// @note layer property
void visible(bool visible);
/// set whether layer is transparent
/// @note layer property
void transparent(bool transparent);
/// set layer disabled or not; if disabled, layer will not have "feedback", and its appearance will be like disabled
/// @note layer property
void disabled(bool disabled = true);
/// set layer opacity percentage
/// @param opacity 0 - 100
/// @note layer property
void opacity(int opacity);
/// set layer's alpha channel; it combines with opacity
/// @param alpha 0 - 255
/// @note layer property
void alpha(int alpha);
/// blending with "film" of color over the layer
/// @param color
/// @param alpha
/// @param mode xfermode "darken" / "lighten" / "screen" / "overlay" / "" (no xfermode)
/// @note layer property
void blend(const String& color, int alpha = 255, const String& mode = "darken");
/// no blending
/// @note layer property
void noblend();
/// clear the layer
void clear();
/// normally used for "feedback" -- flash the default way (layer + border)
void flash();
/// normally used for "feedback" -- flash the area (x, y) where the layer is clicked
void flashArea(int x, int y);
/// trigger explicit "feedback" to the layer (similar to implicit "feedback" when layer is clicked)
/// @param type other than CLICK etc, can be CUSTOM (which is only possible with explicit "feedback");
/// @param option can be "" / "keys" / "numkeys" / "confirm";
/// - in case of "keys" / "numkeys", input box will be popped up for user to enter the "text" of the "feedback";
/// and the "text" in the parameter will be the "hint"
/// - in case of "confirm", a confirmation dialog will be popped up with "text" as the message,
/// and the "feedback" "text" will be "Yes" or "No";
/// @note feedback must be enabled for this to work
void explicitFeedback(int16_t x = 0, int16_t y = 0, const String& text = "", DDFeedbackType type = DDFeedbackType::CLICK, const String& option = "");
inline const String& getLayerId() const { return layerId; }
/// set explicit (and more responsive) "feedback" handler (and enable feedback)
/// @param handler "feedback" handler; see DDFeedbackHandler
/// @param autoFeedbackMethod see DDLayer::enableFeedback()
/// @param allowedFeedbackTypes can be comma-delimited list of "CLICK", "LONGPRESS" and "DOUBLECLICK"
/// @note if you will not be making use of "feedback", you can disable it by defining DD_NO_FEEDBACK in order to reduce footprint
void setFeedbackHandler(DDFeedbackHandler handler, const String& autoFeedbackMethod = "", const String& allowFeedbackTypes = "");
/// rely on getFeedback() being called
/// @param autoFeedbackMethod
/// - "" -- no auto feedback flash (the default); need explicit call to DDLayer::flash() or DDLayer::FlashArea() once detected feedback
/// - "f" -- flash the standard way (layer + border)
/// - "fl" -- flash the layer
/// - "fa" -- flash the area where the layer is clicked
/// - "fas" -- flash the area (as a spot) where the layer is clicked
/// - "fs" -- flash the spot where the layer is clicked (regardless of any area boundary)
/// @param allowedFeedbackType can be comma-delimited list of "CLICK", "LONGPRESS" and "DOUBLECLICK"
/// @note if you will not be making use of "feedback", you can disable it by defining DD_NO_FEEDBACK in order to reduce footprint
void enableFeedback(const String& autoFeedbackMethod = "", const String& allowFeedbackTypes = "");
/// disable "feedback"
void disableFeedback();
/// get "feedback" DDFeedback
/// @return NULL if no pending "feedback"
const DDFeedback* getFeedback();
/// for debug use
void debugOnly(int i);
public:
#ifndef DD_NO_FEEDBACK
/// @attention used internally
inline DDFeedbackManager* getFeedbackManager() const { return pFeedbackManager; }
/// @attention used internally
inline DDFeedbackHandler getFeedbackHandler() const { return feedbackHandler; }
#endif
protected:
DDLayer(int8_t layerId);
public:
// made virtual since 20230601
virtual ~DDLayer();
protected:
void _enableFeedback();
protected:
String layerId;
#ifndef DD_NO_FEEDBACK
// either feedbackManager or feedbackHandler is used
DDFeedbackManager *pFeedbackManager;
DDFeedbackHandler feedbackHandler;
#endif
};
#define DD_DEF_LAYER_LEVEL_ID "_"
/// Base class for a multi-level layer.
/// A layer (single-level or multi-level) will have at least one level (DD_DEF_LAYER_LEVEL_ID).
/// A multi-level layer can have other named levels, which act like separate sub-layers with separate sets of non-layer-specific properties.
class MultiLevelDDLayer: public DDLayer {
public:
/// add a level, optionally change its "opening" size
/// @param levelId level ID; cannot be DD_DEF_LAYER_LEVEL_ID
/// @param width width of the level "opening"; 0 means the maximum width (the width of the layer)
/// @param height height of the level "opening"; 0 means the maximum height (the height of the layer)
void addLevel(const String& levelId, float width, float height, bool switchToIt = false);
/// another version of addLevel()
inline void addLevel(const String& levelId, bool switchToIt = false) {
addLevel(levelId, 0, 0, switchToIt);
}
/// like addLevel() but add to the top (i.e. will be drawn last)
void addTopLevel(const String& levelId, float width = 0, float height = 0, bool switchToIt = false);
/// another version of addTopLevel()
inline void addTopLevel(const String& levelId, bool switchToIt) {
addTopLevel(levelId, 0, 0, switchToIt);
}
/// switch to a different level (which is like a sub-layer), making it the current level
/// @param levelId level ID; use DD_DEF_LAYER_LEVEL_ID for the default level
/// @param addIfMissing if true, add the level if it is missing
void switchLevel(const String& levelId, bool addIfMissing = true);
/// push the current level onto the level stack, to be pop with popLevel()
void pushLevel();
/// push the current level onto the level stack, to be pop with popLevel()
/// @param switchTolevelId switch to level ID (after pushing current level)
void pushLevelAndSwitchTo(const String& switchTolevelId, bool addIfMissing = true);
/// pop a level from the level stack and make it the current level
void popLevel();
/// set the opacity of the current level
/// @param opacity background opacity (0 - 100)
void levelOpacity(int opacity);
/// set whether level is transparent
void levelTransparent(bool transparent);
/// set the anchor of the level; note that level anchor is the top-left corner of the level "opening"
void setLevelAnchor(float x, float y, long reachInMillis = 0);
/// move the level anchor
void moveLevelAnchorBy(float byX, float byY, long reachInMillis = 0);
/// set the rotation of the level
/// @param angle rotation angle in degree; positive is clockwise
/// @param pivotX x coordinate of the pivot point (relative to the level anchor)
/// @param pivotY y coordinate of the pivot point (relative to the level anchor)
void setLevelRotation(float angle, float pivotX = 0, float pivotY = 0, long reachInMillis = 0);
/// register an image for setting as level's background
/// @param backgroundId id to identify the background -- see setLevelBackground()
/// @param backgroundImageName name of the image
/// can be a series of images like dumbdisplay_##0-7##.png (for dumbdisplay_0.png to dumbdisplay_7.png)
/// which can be used for animation with animateLevelBackground()
/// @param drawBackgroundOptions options for drawing the background; same means as the option param of GraphicalDDLayer::drawImageFiler()
void registerLevelBackground(const String& backgroundId, const String& backgroundImageName, const String& drawBackgroundOptions = "");
/// experimental:
/// export the current level as a registered background image -- see exportLevelsAsImage() and registerLevelBackground()
/// @param backgroundId id to identify the background -- see setLevelBackground()
/// @param replace if true (default), replace the existing registered background image with the same id;
/// if false, will add as an item of background image series that can be used for animation with animateLevelBackground()
void exportLevelAsRegisteredBackground(const String& backgroundId, bool replace = true);
/// set a registered background image as the current level's background
/// @param backgroundId can be the empty String ""
/// @param backgroundImageName if not registered, the name of the image to register;
/// can be a series of images like dumbdisplay_##0-7##.png (for dumbdisplay_0.png to dumbdisplay_7.png)
/// which can be used for animation with animateLevelBackground()
/// @param drawBackgroundOptions if not registered, the options for drawing the background
void setLevelBackground(const String& backgroundId, const String& backgroundImageName = "", const String& drawBackgroundOptions = "");
/// set that the current level uses no background image
void setLevelNoBackground();
/// start animate level background (if level background has a series of images)
/// @param fps frames per second which is used to calculate the interval between the series of images
/// @param reset reset to the first image in the series (before start animation)
/// @param options can be "r" to reverse the order of the series of images
void animateLevelBackground(float fps, bool reset = true, const String& options = "");
/// stop animate level background
/// @param reset reset to the first image in the series
void stopAnimateLevelBackground(bool reset = true);
/// reorder the specified level (by moving it in the z-order plane)
/// @param how can be "T" for top; or "B" for bottom; "U" for up; or "D" for down
void reorderLevel(const String& levelId, const String& how);
/// export (and save) the levels as an image (without the decorations of the layer like border)
void exportLevelsAsImage(const String& imageFileName, bool cacheItNotSave = false);
/// delete the specified level
void deleteLevel(const String& levelId);
protected:
MultiLevelDDLayer(int8_t layerId): DDLayer(layerId) {}
};
enum MbArrow { North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest };
enum MbIcon { Heart, SmallHeart, Yes, No, Happy, Sad, Confused, Angry, Asleep, Surprised,
Silly, Fabulous, Meh, TShirt, Rollerskate, Duck, House, Tortoise, Butterfly, StickFigure,
Ghost, Sword, Giraffe, Skull, Umbrella, Snake, Rabbit, Cow, QuarterNote, EigthNote,
Pitchfork, Target, Triangle, LeftTriangle, Chessboard, Diamond, SmallDiamond, Square, SmallSquare, Scissors };
class MbImage {
public:
MbImage(int8_t imageId) {
this->imageId = String(imageId);
}
inline const String& getImageId() const { return this->imageId; }
private:
String imageId;
};
/// Class for Microbit-like DD layer; created with DumbDisplay::createMicrobitLayer()
class MbDDLayer: public DDLayer {
public:
/// for internal use only
MbDDLayer(int8_t layerId): DDLayer(layerId) {
}
/// show Microbit icon
void showIcon(MbIcon icon);
/// show Microbit arrow
void showArrow(MbArrow arrow);
/// show number; scroll if more than a single digit; but you get to control timing by using delay()
void showNumber(int num);
/// show string; scroll if more than a single character; but you get to control timing by using delay()
void showString(const String& str);
/// turn on LED @ (x, y)
void plot(int x, int y);
/// turn off LED @ (x, y)
void unplot(int x, int y);
/// toggle LED @ (x, y) on / off
void toggle(int x, int y);
/// turn LEDs on by "pattern"
/// - '.': off
/// - '#': on
/// - '|': delimit a row
/// - e.g. "#|.#|..#" -- 3 rows
void showLeds(const String& ledPattern);
/// set LED color
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
void ledColor(const String& color);
MbImage* createImage(const String& ledPattern);
void releaseImage(MbImage *pImage);
void showImage(MbImage *pImage, int xOff);
void scrollImage(MbImage *pImage, int xOff, long interval);
};
/// Class for Turtle-like DD layer; created with DumbDisplay::createTurtleLayer()
class TurtleDDLayer: public MultiLevelDDLayer {
public:
/// for internal use only
TurtleDDLayer(int8_t layerId): MultiLevelDDLayer(layerId) {
}
/// forward; with pen or not
void forward(int distance, bool withPen = true);
/// backward; with pen or not
void backward(int distance, bool withPen = true);
/// left turn
void leftTurn(int angle);
/// right turn
void rightTurn(int angle);
/// go home (0, 0); with pen or not
void home(bool withPen = true);
/// go to (x, y); with pen or not
void goTo(int x, int y, bool withPen = true);
/// go by (byX, byY); with pen or not
void goBy(int byX, int byY, bool withPen = true);
/// set heading angle (degree)
void setHeading(int angle);
/// set pen size
void penSize(int size);
/// set pen color
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
void penColor(const String& color);
/// set fill color
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
void fillColor(const String& color);
/// set no fill color
void noFillColor();
/// set pen filled or not; if filled, shape drawn will be filled
void penFilled(bool filled = true);
/// set text size
void setTextSize(int size);
/// set font
/// @param fontName: empty means default
/// @param textSize: 0 means default
void setTextFont(const String& fontName = "", int textSize = 0);
/// pen up
void penUp();
/// pen down
void penDown();
void beginFill();
void endFill();
/// draw a dot
void dot(int size, const String& color);
/// draw circle; centered or not
void circle(int radius, bool centered = false);
/// draw oval; centered or not
void oval(int width, int height, bool centered = false);
/// draw arc; centered or not
void arc(int width, int height, int startAngle, int sweepAngle, bool centered = false);
/// draw triangle (SAS)
void triangle(int side1, int angle, int side2);
/// draw isosceles triangle; given size and angle
void isoscelesTriangle(int side, int angle);
/// draw rectangle; centered or not
void rectangle(int width, int height, bool centered = false);
/// draw polygon given side and vertex count
void polygon(int side, int vertexCount);
/// draw polygon enclosed in an imaginary centered circle
/// - given circle radius and vertex count
/// - whether inside the imaginary circle or outside of it
void centeredPolygon(int radius, int vertexCount, bool inside = false);
/// write text
void write(const String& text); // TODO: add align param
/// draw text (honor heading)
void drawText(const String& text);
/// @deprecated
inline void write(const String& text, bool draw) {
if (draw) {
drawText(text);
} else {
write(text);
}
}
};
struct LedGridDDLayerHandle: DDLayerHandle {};
/// Class for LED grid layer; created with DumbDisplay::createLedGridLayer()
class LedGridDDLayer: public DDLayer {
public:
/// experimental: construct a "transient" LedGridDDLayer from LedGridDDLayerHandle
/// created using DUmbDisplay::createLcdLayerHandle()
LedGridDDLayer(LedGridDDLayerHandle layerHandle): DDLayer(layerHandle._h) {
}
public:
/// for internal use only
LedGridDDLayer(int8_t layerId): DDLayer(layerId) {
}
/// turn on LED @ (x, y)
void turnOn(int x = 0, int y = 0);
/// turn off LED @ (x, y)
void turnOff(int x = 0, int y = 0);
/// toggle LED @ (x, y)
void toggle(int x = 0, int y = 0);
/// turn on LED @ (x, y)
/// @param onColor LED on color (common color name); empty string means what already set
void turnOnEx(int x = 0, int y = 0, const String& onColor = "");
/// turn on/off LEDs based on bits
/// @param bits most significant bit (bit 0) maps to left-most LED
/// @param y row
/// @param reverse true means reversed ... i.e. least significant bit (bit 31) maps to left-most LED
void bitwise(unsigned int bits, int y = 0, bool reverse = false);
/// turn on/off two rows of LEDs by bits
/// @see bitwise()
void bitwise2(unsigned int bits_0, unsigned int bits_1, int y = 0, bool reverse = false);
/// turn on/off three rows of LEDs by bits
/// @see bitwise()
void bitwise3(unsigned int bits_0, unsigned int bits_1, unsigned int bits_2, int y = 0, bool reverse = false);
/// turn on/off four rows of LEDs by bits
/// @see bitwise()
void bitwise4(unsigned int bits_0, unsigned int bits_1, unsigned int bits_2, unsigned int bits_3, int y = 0, bool reverse = false);
/// turn on LEDs to form a horizontal "bar"
/// @see bitwise()
void horizontalBar(int count, bool rightToLeft = false);
/// turn on LEDs to form a vertical "bar"
/// @param bottomToTop true means bottom to top
void verticalBar(int count, bool bottomToTop = true);
/// turn on LEDs to form a horizontal "bar"
/// @param count can be negative (if it makes sense)
/// @param startX normally 0
/// @param color LED on color; DD_RGB_COLOR(...) or common color name; empty string means what already set
void horizontalBarEx(int count, int startX = 0, const String& color = "");
/// turn on LEDs to form a vertical "bar"
/// @param count can be negative (if it makes sense)
/// @param startY normally 0
/// @param color LED on color; DD_RGB_COLOR(...) or common color name; empty string means what already set
void verticalBarEx(int count, int startY = 0, const String& color = "");
/// set LED on color
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
void onColor(const String& color);
/// set LED off color
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
void offColor(const String& color);
/// set no LED off color
void noOffColor();
};
struct LcdDDLayerHandle: DDLayerHandle {};
/// @brief
/// Class for LCD layer; created with DumbDisplay::createLcdLayer()
/// @note with "feedback" enabled, can be used as a button
/// @note with "feedback" enabled, can be used as checkbox; consider using these emojis for checkbox --
/// ☒☐✅❎🟩✔️ ☑️⬛✔✖
class LcdDDLayer: public DDLayer {
public:
/// experimental: construct a "transient" LcdDDLayer from LcdDDLayerHandle
/// created using DUmbDisplay::createLcdLayerHandle()
LcdDDLayer(LcdDDLayerHandle layerHandle): DDLayer(layerHandle._h) {
}
public:
/// for internal use only
LcdDDLayer(int8_t layerId): DDLayer(layerId) {
}
/// print text, moving cursor
void print(const String& text);
/// move cursor to home
void home();
/// set cursor position
/// @param x horizontal position
/// @param y vertical position
void setCursor(int x, int y);
/// show cursor
void cursor();
/// hide cursor
void noCursor();
/// enable auto-scroll
void autoscroll();
/// disable auto-scroll
void noAutoscroll();
void display();
void noDisplay();
void scrollDisplayLeft();
void scrollDisplayRight();
/// write text as a line (of y-th row)
/// @param align 'L', 'C', or 'R'
void writeLine(const String& text, int y = 0, const String& align = "L");
/// write text as a right-aligned line
void writeRightAlignedLine(const String& text, int y = 0);
/// write text as a line, with align "centered"
void writeCenteredLine(const String& text, int y = 0);
/// set pixel color
/// @param color DD_RGB_COLOR(...) or common color name
void pixelColor(const String &color);
/// set "background" (off) pixel color
/// @param color DD_RGB_COLOR(...) or common color name
void bgPixelColor(const String &color, bool sameForBackgroundColor = false, int backgroundOpacity = 100);
/// set no "background" (off) pixel color
void noBgPixelColor();
};
class SelectionBaseDDLayer: public DDLayer {
public:
/// for internal use only
SelectionBaseDDLayer(int8_t layerId): DDLayer(layerId) {
_enableFeedback();
}
/// set pixel color (of bot selected and unselected "selection" units)
/// @param color DD_RGB_COLOR(...) or common color name
/// please use the other version of pixelColor() to select different colors for selected and unselected
void pixelColor(const String &color);
/// set pixel color (when whether selected or not have different colors)
/// @param color DD_RGB_COLOR(...) or common color name
/// please use the other version of pixelColor() to select a single color for both selected and unselected
void pixelColor(const String &color, bool selected);
// /// set background pixel color
// /// @param color DD_RGB_COLOR(...) or common color name
// void bgPixelColor(const String &color, bool sameForBackgroundColor = false, int backgroundOpacity = 100);
/// select all "selection" units
void selectAll();
/// deselect all "selection" units
void deselectAll();
/// set selected / unselected "selection" unit border characteristics
/// @param borderColor DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"; "" means default
/// @param borderShape can be "flat", "hair", "round", "raised" or "sunken"; "" means default
void highlightBorder(bool forSelected, const String& borderColor = "", const String& borderShape = "");
};
/// @brief
/// Class for "selection" layer of multiple LCD-like "selection" units; created with DumbDisplay::createSelectionLayer()
/// @note by default, it has "feedback" enabled to indicate which "selection" unit is clicked
/// @since v0.9.9-r10
class SelectionDDLayer: public SelectionBaseDDLayer {
public:
/// for internal use only
SelectionDDLayer(int8_t layerId): SelectionBaseDDLayer(layerId) {}
/// set a "selection" unit text (of y-th row)
/// @param align 'L', 'C', or 'R'
void text(const String& text, int y = 0, int horiSelectionIdx = 0, int vertSelectionIdx = 0, const String& align = "L");
/// set a "selection" unit centered text (of y-th row)
void textCentered(const String& text, int y = 0, int horiSelectionIdx = 0, int vertSelectionIdx = 0);
/// set a "selection" unit right-aligned text (of y-th row)
void textRightAligned(const String& text, int y = 0, int horiSelectionIdx = 0, int vertSelectionIdx = 0);
/// set a "selection" unit text (of y-th row) when unselected (it defaults to the same text as selected)
/// @param align 'L', 'C', or 'R'
void unselectedText(const String& text, int y = 0, int horiSelectionIdx = 0, int vertSelectionIdx = 0, const String& align = "L");
/// set a "selection" unit centered text (of y-th row) when unselected (it defaults to the same text as selected)
void unselectedTextCentered(const String& text, int y = 0, int horiSelectionIdx = 0, int vertSelectionIdx = 0);
/// set a "selection" unit right-aligned text (of y-th row) when unselected (it defaults to the same text as selected)
void unselectedTextRightAligned(const String& text, int y = 0, int horiSelectionIdx = 0, int vertSelectionIdx = 0);
/// select a "selection" unit
void select(int horiSelectionIdx = 0, int vertSelectionIdx = 0, bool deselectTheOthers = true);
/// deselect a "selection" unit
void deselect(int horiSelectionIdx = 0, int vertSelectionIdx = 0, bool selectTheOthers = false);
/// @deprecated
void setSelected(bool selected, int horiSelectionIdx = 0, int vertSelectionIdx = 0) {
if (selected) {
select(horiSelectionIdx, vertSelectionIdx, false);
} else {
deselect(horiSelectionIdx, vertSelectionIdx, false);
}
}
/// set a "selection" unit selected or not (combination of select() and deselect())
void selected(bool selected, int horiSelectionIdx = 0, int vertSelectionIdx = 0, bool reverseTheOthers = false);
};
/// @brief
/// Class for "selection list" layer, like SelectionDDLayer but "selections" can be added and removed dynamically; it can be created with DumbDisplay::createListSelectionLayer()
/// Consider using SelectionListLayerHelper / SelectionListLayerWrapper for richer tracking of the "list"
/// @note by default, it has "feedback" enabled to indicate which "selection" unit is clicked
/// @since v0.9.9-r41
class SelectionListDDLayer: public SelectionBaseDDLayer {
public:
/// for internal use only
SelectionListDDLayer(int8_t layerId): SelectionBaseDDLayer(layerId) {}
/// add (insert) a "selection" unit
/// @param selectionIdx add (insert) the selection to index
void add(int selectionIdx);
/// remove a "selection" unit
/// @param selectionIdx remove the selection at index
void remove(int selectionIdx);
/// set the offset to the "selection" unit start showing
void offset(int offset);
/// set a "selection" unit text (of y-th row)
/// @param align 'L', 'C', or 'R'
void text(int selectionIdx, const String& text, int y = 0, const String& align = "L");
/// set a "selection" unit centered text (of y-th row)
void textCentered(int selectionIdx, const String& text, int y = 0);
/// set a "selection" unit right-aligned text (of y-th row)
void textRightAligned(int selectionIdx, const String& text, int y = 0);
/// set a "selection" unit text (of y-th row) when unselected (it defaults to the same text as selected)
/// @param align 'L', 'C', or 'R'
void unselectedText(int selectionIdx, const String& text, int y = 0, const String& align = "L");
/// set a "selection" unit centered text (of y-th row) when unselected (it defaults to the same text as selected)
void unselectedTextCentered(int selectionIdx, const String& text, int y = 0);
/// set a "selection" unit right-aligned text (of y-th row) when unselected (it defaults to the same text as selected)
void unselectedTextRightAligned(int selectionIdx, const String& text, int y = 0);
/// select a "selection" unit
void select(int selectionIdx, bool deselectTheOthers = true);
/// deselect a "selection" unit
void deselect(int selectionIdx, bool selectTheOthers = false);
/// set a "selection" unit selected or not (combination of select() and deselect())
void selected(int selectionIdx, bool selected, bool reverseTheOthers = false);
};
struct GraphicalDDLayerHandle: DDLayerHandle {};
/// Class for graphical LCD layer; created with DumbDisplay::createGraphicalLayer()
class GraphicalDDLayer: public MultiLevelDDLayer {
public:
/// experimental: construct a "transient" LcdDDLayer from LcdDDLayerHandle
/// created using DUmbDisplay::createGraphicalLayerHandle()
GraphicalDDLayer(GraphicalDDLayerHandle layerHandle): MultiLevelDDLayer(layerHandle._h) {
}
public:
/// for internal use only
GraphicalDDLayer(int8_t layerId): MultiLevelDDLayer(layerId) {
}
/// rotate the screen
void setRotation(int8_t rotationType);
/// set cursor to position
void setCursor(int x, int y);
/// move cursor by some amount
void moveCursorBy(int byX, int byY);
/// set text color and text background color
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
/// @param bgColor empty background color means no background color
void setTextColor(const String& color, const String& bgColor = "");
/// set text size
void setTextSize(int size);
/// set font
/// @param fontName empty means default
/// @param textSize 0 means default
void setTextFont(const String& fontName);
/// reset text font and size
void setTextFont();
/// @deprecated
inline void setTextFont(const String& fontName, int textSize) {
setTextFont(fontName);
if (textSize > 0) {
setTextSize(textSize);
}
}
/// set whether "print" will auto wrap or not
void setTextWrap(bool wrapOn);
/// fill screen with color
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
void fillScreen(const String& color);
/// print text
void print(const String& text);
/// print text with line feed
void println(const String& text = "");
/// draw char
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
/// @param backgroundColor DD_RGB_COLOR(...) or common color name; empty background color means no background color
/// @param size 0 means default
void drawChar(int x, int y, char c, const String& color = "", const String& bgColor = "", int size = 0);
/// draw string
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
/// @param backgroundColor DD_RGB_COLOR(...) or common color name; empty background color means no background color
/// @param size 0 means default
void drawStr(int x, int y, const String& string, const String& color = "", const String& bgColor = "", int size = 0);
/// similar to drawStr(), but draw string as a text line at (0, y) with alignment option
/// @param align 'L', 'C', or 'R'
void drawTextLine(const String& text, int y, const String& align = "L", const String& color = "", const String& bgColor = "", int size = 0);
/// draw a pixel
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
void drawPixel(int x, int y, const String& color = "");
/// draw a line
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
void drawLine(int x1, int y1, int x2, int y2, const String& color = "");
/// draw a circle
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
void drawCircle(int x, int y, int r, const String& color = "", bool filled = false);
// draw filled circle
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
inline void fillCircle(int x, int y, int r, const String& color = "") {
drawCircle(x, y, r, color, true);
}
/// draw a triangle
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
void drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, const String& color = "", bool filled = false);
/// draw filled triangle
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
inline void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, const String& color = "") {
drawTriangle(x1, y1, x2, y2, x3, y3, color, true);
}
/// draw a rectangle
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
void drawRect(int x, int y, int w, int h, const String& color = "", bool filled = false);
/// draw filled rectangle
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
inline void fillRect(int x, int y, int w, int h, const String& color = "") {
drawRect(x, y, w, h, color, true);
}
/// draw a rounded rectangle
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
void drawRoundRect(int x, int y, int w, int h, int r, const String& color = "", bool filled = false);
/// draw filled rounded rectangle
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
inline void fillRoundRect(int x, int y, int w, int h, int r, const String& color = "") {
drawRoundRect(x, y, w, h, r, color, true);
}
/// draw an ellipse (oval)
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
void drawOval(int x, int y, int w, int h, const String& color = "", bool filled = false);
/// draw filled ellipse (oval)
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
inline void fillOval(int x, int y, int w, int h, const String& color = "") {
drawOval(x, y, w, h, color, true);
}
/// draw an arc
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
void drawArc(int x, int y, int w, int h, int startAngle, int sweepAngle, bool useCenter, const String& color = "", bool filled = false);
/// draw filled arc
/// @param color DD_RGB_COLOR(...) or common color name; empty color means text color
inline void fillArc(int x, int y, int w, int h, int startAngle, int sweepAngle, bool useCenter, const String& color = "") {
drawArc(x, y, w, h, startAngle, sweepAngle, useCenter, color, true);
}
/// move forward (relative to cursor)
void forward(int distance, bool withPen = true);
/// move backward (relative to cursor)
void backward(int distance, bool withPen = true);
/// turn left
void leftTurn(int angle);
/// turn right
void rightTurn(int angle);
/// set heading angle (degree)
void setHeading(int angle);
/// set pen size
void penSize(int size);
/// set pen color (i.e. text color)
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
void penColor(const String& color);
/// set fill color (for shape)
/// @param color DD_COLOR_XXX; DD_RGB_COLOR(...); can also be common "color name"
void fillColor(const String& color);
/// set no fill color (for shape)
void noFillColor();
/// draw a circle; centered or not
void circle(int radius, bool centered = false);
/// draw an oval; centered or not
void oval(int width, int height, bool centered = false);
/// draw arc; centered or not
void arc(int width, int height, int startAngle, int sweepAngle, bool centered = false);
/// draw triangle (SAS)
void triangle(int side1, int angle, int side2);
/// draw isosceles triangle; given size and angle
void isoscelesTriangle(int side, int angle);
/// draw rectangle; centered or not
void rectangle(int width, int height, bool centered = false);
/// draw polygon given side and vertex count
void polygon(int side, int vertexCount);
/// draw polygon "enclosed" in an imaginary centered circle
/// @param radius circle radius
/// @param vertexCount number of vertices
/// @param inside whether inside the imaginary circle or outside of it
void centeredPolygon(int radius, int vertexCount, bool inside = false);
/// write text (will not auto wrap)
void write(const String& text);
/// draw text (honor heading)
void drawText(const String& text);
/// @deprecated
inline void write(const String& text, bool draw) {
if (draw) {
drawText(text);
} else {
write(text);
}
}
/// load image file to cache
/// @param w,h: image size to scale to; if both 0, will not scale, if any 0, will scale keeping aspect ratio
/// @param asImageFileName: better provide a different name for the scaled cached
void loadImageFile(const String& imageFileName, int w = 0, int h = 0, const String& asImageFileName = "");
/// load image file to cache cropped
/// @param x,y,w,h: rect to crop the image
/// @param asImageFileName: since image cropped, should provide a different name for the scaled cached
/// @param
/// @see loadImageFile()
inline void loadImageFileScaled(const String& imageFileName, int w, int h, const String& asImageFileName) {
loadImageFile(imageFileName, w, h, asImageFileName);
}
void loadImageFileCropped(const String& imageFileName, int x, int y, int w, int h, const String& asImageFileName, int scaleW = 0, int scaleH = 0);
/// unload image file from cache
void unloadImageFile(const String& imageFileName);
/// unload all image files from cache
void unloadAllImageFiles();
/// draw image file in cache (if not already loaded to cache, load it)
/// @param x,y: position of the left-top corner
/// @param w,h: image size to scale to; if both 0, will not scale, if any 0, will scale keeping aspect ratio
void drawImageFile(const String& imageFileName, int x = 0, int y = 0, int w = 0, int h = 0, const String& options = "");
/// another version of drawImageFile() with options
inline void drawImageFile(const String& imageFileName, const String& options) {
drawImageFile(imageFileName, 0, 0, 0, 0, options);
}
/// draw image file in cache scaled, like calling drawImageFile(imageFileName, 0, 0, w, h, options) with w and h
/// @see drawImageFile()
inline void drawImageFileScaled(const String& imageFileName, int w, int h, const String& options = "") {
drawImageFile(imageFileName, 0, 0, w, h, options);
}
/// draw image file in cache (if not already loaded to cache, load it)
/// @param x,y,w,h: rect to draw the image; 0 means the default value
/// @param options (e.g. "LB"): left align "L"; right align "R"; top align "T"; bottom align "B"; default to fit centered
void drawImageFileFit(const String& imageFileName, int x = 0, int y = 0, int w = 0, int h = 0, const String& options = "");
/// another version of drawImageFileFit() with options
inline void drawImageFileFit(const String& imageFileName, const String& options) {
drawImageFileFit(imageFileName, 0, 0, 0, 0, options);
}
/// cache image; not saved
/// @param imageName cached image name
void cacheImage(const String& imageName, const uint8_t *bytes, int byteCount, char compressionMethod = 0);
/// cache image with specified timestamp; not saved
/// @param imageName cached image name
void cacheImageWithTS(const String& imageName, const uint8_t *bytes, int byteCount, long imageTimestamp, char compressionMethod = 0);
/// cache single-bit "pixel" image (i.e. B&W image); not saved
/// @param imageName cached image name
void cachePixelImage(const String& imageName, const uint8_t *bytes, int width, int height, const String& color = "", char compressionMethod = 0);
/// cache 16-bit "pixel" image (i.e. 565 RGB image); not saved
/// @param imageName cached image name
void cachePixelImage16(const String& imageName, const uint16_t *data, int width, int height, const String& options = "", char compressMethod = 0);
/// cache grayscale "pixel" image; not saved
/// @param imageName cached image name
void cachePixelImageGS(const String& imageName, const uint8_t *data, int width, int height, const String& options = "", char compressMethod = 0);
/// saved cached image (to file)
/// @param imageName cached image name
void saveCachedImageFile(const String& imageName, const String& asImageName = "");
#ifdef ESP32
/// saved cached image with timestamp
/// @param imageName cachedImageName
void saveCachedImageFileWithTS(const String& imageName, const String& asImageName, int64_t imageTimestamp);
#endif
/// saved cached image (async / non-blocking)
/// @param imageName cachedImageName
void saveCachedImageFileAsync(const String& imageName, const String& asImageName = "");
#ifdef ESP32
/// saved cached image (async / non-blocking)
/// @param imageName cachedImageName
void saveCachedImageFileWithTSAsync(const String& imageName, const String& asImageName, int64_t imageTimestamp);
#endif
/// saved cached image
/// @param stitchAsImageName if not empty, will stitch all cached images to one image file of the given name
void saveCachedImageFiles(const String& stitchAsImageName = "");