MatrixMiniR4 1.1.5
Matrix Mini R4 Arduino Library API Documentation
Loading...
Searching...
No Matches
MiniR4_GFX.cpp
Go to the documentation of this file.
1
6/*
7The MIT License (MIT)
8
9Copyright (c) 2017 Adafruit Industries
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
28*/
29
30/*
31This is the core graphics library for all our displays, providing a common
32set of graphics primitives (points, lines, circles, etc.). It needs to be
33paired with a hardware-specific library for each display device we carry
34(to handle the lower-level functions).
35
36Adafruit invests time and resources providing this open source code, please
37support Adafruit & open-source hardware by purchasing products from Adafruit!
38
39Copyright (c) 2013 Adafruit Industries. All rights reserved.
40
41Redistribution and use in source and binary forms, with or without
42modification, are permitted provided that the following conditions are met:
43
44- Redistributions of source code must retain the above copyright notice,
45 this list of conditions and the following disclaimer.
46- Redistributions in binary form must reproduce the above copyright notice,
47 this list of conditions and the following disclaimer in the documentation
48 and/or other materials provided with the distribution.
49
50THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
51AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
54LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60POSSIBILITY OF SUCH DAMAGE.
61 */
62
63#include "MiniR4_GFX.h"
64#include "MiniR4_glcdfont.c"
65#ifdef __AVR__
66# include <avr/pgmspace.h>
67#elif defined(ESP8266) || defined(ESP32)
68# include <pgmspace.h>
69#endif
70
71// Many (but maybe not all) non-AVR board installs define macros
72// for compatibility with existing PROGMEM-reading AVR code.
73// Do our own checks and defines here for good measure...
74
75#ifndef pgm_read_byte
76# define pgm_read_byte(addr) (*(const unsigned char*)(addr))
77#endif
78#ifndef pgm_read_word
79# define pgm_read_word(addr) (*(const unsigned short*)(addr))
80#endif
81#ifndef pgm_read_dword
82# define pgm_read_dword(addr) (*(const unsigned long*)(addr))
83#endif
84
85// Pointers are a peculiar case...typically 16-bit on AVR boards,
86// 32 bits elsewhere. Try to accommodate both...
87
88#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF)
89# define pgm_read_pointer(addr) ((void*)pgm_read_dword(addr))
90#else
91# define pgm_read_pointer(addr) ((void*)pgm_read_word(addr))
92#endif
93
94inline GFXglyph* pgm_read_glyph_ptr(const GFXfont* gfxFont, uint8_t c)
95{
96#ifdef __AVR__
97 return &(((GFXglyph*)pgm_read_pointer(&gfxFont->glyph))[c]);
98#else
99 // expression in __AVR__ section may generate "dereferencing type-punned
100 // pointer will break strict-aliasing rules" warning In fact, on other
101 // platforms (such as STM32) there is no need to do this pointer magic as
102 // program memory may be read in a usual way So expression may be simplified
103 return gfxFont->glyph + c;
104#endif //__AVR__
105}
106
107inline uint8_t* pgm_read_bitmap_ptr(const GFXfont* gfxFont)
108{
109#ifdef __AVR__
110 return (uint8_t*)pgm_read_pointer(&gfxFont->bitmap);
111#else
112 // expression in __AVR__ section generates "dereferencing type-punned pointer
113 // will break strict-aliasing rules" warning In fact, on other platforms (such
114 // as STM32) there is no need to do this pointer magic as program memory may
115 // be read in a usual way So expression may be simplified
116 return gfxFont->bitmap;
117#endif //__AVR__
118}
119
120#ifndef min
121# define min(a, b) (((a) < (b)) ? (a) : (b))
122#endif
123
124#ifndef _swap_int16_t
125# define _swap_int16_t(a, b) \
126 { \
127 int16_t t = a; \
128 a = b; \
129 b = t; \
130 }
131#endif
132
133/**************************************************************************/
140/**************************************************************************/
141Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h)
142 : WIDTH(w)
143 , HEIGHT(h)
144{
145 _width = WIDTH;
146 _height = HEIGHT;
147 rotation = 0;
148 cursor_y = cursor_x = 0;
150 textcolor = textbgcolor = 0xFFFF;
151 wrap = true;
152 _cp437 = false;
153 gfxFont = NULL;
154}
155
156/**************************************************************************/
165/**************************************************************************/
166void Adafruit_GFX::writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
167{
168#if defined(ESP8266)
169 yield();
170#endif
171 int16_t steep = abs(y1 - y0) > abs(x1 - x0);
172 if (steep) {
173 _swap_int16_t(x0, y0);
174 _swap_int16_t(x1, y1);
175 }
176
177 if (x0 > x1) {
178 _swap_int16_t(x0, x1);
179 _swap_int16_t(y0, y1);
180 }
181
182 int16_t dx, dy;
183 dx = x1 - x0;
184 dy = abs(y1 - y0);
185
186 int16_t err = dx / 2;
187 int16_t ystep;
188
189 if (y0 < y1) {
190 ystep = 1;
191 } else {
192 ystep = -1;
193 }
194
195 for (; x0 <= x1; x0++) {
196 if (steep) {
197 writePixel(y0, x0, color);
198 } else {
199 writePixel(x0, y0, color);
200 }
201 err -= dy;
202 if (err < 0) {
203 y0 += ystep;
204 err += dx;
205 }
206 }
207}
208
209/**************************************************************************/
213/**************************************************************************/
215
216/**************************************************************************/
223/**************************************************************************/
224void Adafruit_GFX::writePixel(int16_t x, int16_t y, uint16_t color)
225{
226 drawPixel(x, y, color);
227}
228
229/**************************************************************************/
238/**************************************************************************/
239void Adafruit_GFX::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
240{
241 // Overwrite in subclasses if startWrite is defined!
242 // Can be just writeLine(x, y, x, y+h-1, color);
243 // or writeFillRect(x, y, 1, h, color);
244 drawFastVLine(x, y, h, color);
245}
246
247/**************************************************************************/
256/**************************************************************************/
257void Adafruit_GFX::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
258{
259 // Overwrite in subclasses if startWrite is defined!
260 // Example: writeLine(x, y, x+w-1, y, color);
261 // or writeFillRect(x, y, w, 1, color);
262 drawFastHLine(x, y, w, color);
263}
264
265/**************************************************************************/
275/**************************************************************************/
276void Adafruit_GFX::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
277{
278 // Overwrite in subclasses if desired!
279 fillRect(x, y, w, h, color);
280}
281
282/**************************************************************************/
287/**************************************************************************/
289
290/**************************************************************************/
299/**************************************************************************/
300void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
301{
302 startWrite();
303 writeLine(x, y, x, y + h - 1, color);
304 endWrite();
305}
306
307/**************************************************************************/
316/**************************************************************************/
317void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
318{
319 startWrite();
320 writeLine(x, y, x + w - 1, y, color);
321 endWrite();
322}
323
324/**************************************************************************/
334/**************************************************************************/
335void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
336{
337 startWrite();
338 for (int16_t i = x; i < x + w; i++) {
339 writeFastVLine(i, y, h, color);
340 }
341 endWrite();
342}
343
344/**************************************************************************/
350/**************************************************************************/
351void Adafruit_GFX::fillScreen(uint16_t color)
352{
353 fillRect(0, 0, _width, _height, color);
354}
355
356/**************************************************************************/
365/**************************************************************************/
366void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
367{
368 // Update in subclasses if desired!
369 if (x0 == x1) {
370 if (y0 > y1) _swap_int16_t(y0, y1);
371 drawFastVLine(x0, y0, y1 - y0 + 1, color);
372 } else if (y0 == y1) {
373 if (x0 > x1) _swap_int16_t(x0, x1);
374 drawFastHLine(x0, y0, x1 - x0 + 1, color);
375 } else {
376 startWrite();
377 writeLine(x0, y0, x1, y1, color);
378 endWrite();
379 }
380}
381
382/**************************************************************************/
390/**************************************************************************/
391void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
392{
393#if defined(ESP8266)
394 yield();
395#endif
396 int16_t f = 1 - r;
397 int16_t ddF_x = 1;
398 int16_t ddF_y = -2 * r;
399 int16_t x = 0;
400 int16_t y = r;
401
402 startWrite();
403 writePixel(x0, y0 + r, color);
404 writePixel(x0, y0 - r, color);
405 writePixel(x0 + r, y0, color);
406 writePixel(x0 - r, y0, color);
407
408 while (x < y) {
409 if (f >= 0) {
410 y--;
411 ddF_y += 2;
412 f += ddF_y;
413 }
414 x++;
415 ddF_x += 2;
416 f += ddF_x;
417
418 writePixel(x0 + x, y0 + y, color);
419 writePixel(x0 - x, y0 + y, color);
420 writePixel(x0 + x, y0 - y, color);
421 writePixel(x0 - x, y0 - y, color);
422 writePixel(x0 + y, y0 + x, color);
423 writePixel(x0 - y, y0 + x, color);
424 writePixel(x0 + y, y0 - x, color);
425 writePixel(x0 - y, y0 - x, color);
426 }
427 endWrite();
428}
429
430/**************************************************************************/
440/**************************************************************************/
442 int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color)
443{
444 int16_t f = 1 - r;
445 int16_t ddF_x = 1;
446 int16_t ddF_y = -2 * r;
447 int16_t x = 0;
448 int16_t y = r;
449
450 while (x < y) {
451 if (f >= 0) {
452 y--;
453 ddF_y += 2;
454 f += ddF_y;
455 }
456 x++;
457 ddF_x += 2;
458 f += ddF_x;
459 if (cornername & 0x4) {
460 writePixel(x0 + x, y0 + y, color);
461 writePixel(x0 + y, y0 + x, color);
462 }
463 if (cornername & 0x2) {
464 writePixel(x0 + x, y0 - y, color);
465 writePixel(x0 + y, y0 - x, color);
466 }
467 if (cornername & 0x8) {
468 writePixel(x0 - y, y0 + x, color);
469 writePixel(x0 - x, y0 + y, color);
470 }
471 if (cornername & 0x1) {
472 writePixel(x0 - y, y0 - x, color);
473 writePixel(x0 - x, y0 - y, color);
474 }
475 }
476}
477
478/**************************************************************************/
486/**************************************************************************/
487void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
488{
489 startWrite();
490 writeFastVLine(x0, y0 - r, 2 * r + 1, color);
491 fillCircleHelper(x0, y0, r, 3, 0, color);
492 endWrite();
493}
494
495/**************************************************************************/
505/**************************************************************************/
507 int16_t x0, int16_t y0, int16_t r, uint8_t corners, int16_t delta, uint16_t color)
508{
509
510 int16_t f = 1 - r;
511 int16_t ddF_x = 1;
512 int16_t ddF_y = -2 * r;
513 int16_t x = 0;
514 int16_t y = r;
515 int16_t px = x;
516 int16_t py = y;
517
518 delta++; // Avoid some +1's in the loop
519
520 while (x < y) {
521 if (f >= 0) {
522 y--;
523 ddF_y += 2;
524 f += ddF_y;
525 }
526 x++;
527 ddF_x += 2;
528 f += ddF_x;
529 // These checks avoid double-drawing certain lines, important
530 // for the SSD1306 library which has an INVERT drawing mode.
531 if (x < (y + 1)) {
532 if (corners & 1) writeFastVLine(x0 + x, y0 - y, 2 * y + delta, color);
533 if (corners & 2) writeFastVLine(x0 - x, y0 - y, 2 * y + delta, color);
534 }
535 if (y != py) {
536 if (corners & 1) writeFastVLine(x0 + py, y0 - px, 2 * px + delta, color);
537 if (corners & 2) writeFastVLine(x0 - py, y0 - px, 2 * px + delta, color);
538 py = y;
539 }
540 px = x;
541 }
542}
543
544/**************************************************************************/
553/**************************************************************************/
554void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
555{
556 startWrite();
557 writeFastHLine(x, y, w, color);
558 writeFastHLine(x, y + h - 1, w, color);
559 writeFastVLine(x, y, h, color);
560 writeFastVLine(x + w - 1, y, h, color);
561 endWrite();
562}
563
564/**************************************************************************/
574/**************************************************************************/
576 int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
577{
578 int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis
579 if (r > max_radius) r = max_radius;
580 // smarter version
581 startWrite();
582 writeFastHLine(x + r, y, w - 2 * r, color); // Top
583 writeFastHLine(x + r, y + h - 1, w - 2 * r, color); // Bottom
584 writeFastVLine(x, y + r, h - 2 * r, color); // Left
585 writeFastVLine(x + w - 1, y + r, h - 2 * r, color); // Right
586 // draw four corners
587 drawCircleHelper(x + r, y + r, r, 1, color);
588 drawCircleHelper(x + w - r - 1, y + r, r, 2, color);
589 drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color);
590 drawCircleHelper(x + r, y + h - r - 1, r, 8, color);
591 endWrite();
592}
593
594/**************************************************************************/
604/**************************************************************************/
606 int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
607{
608 int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis
609 if (r > max_radius) r = max_radius;
610 // smarter version
611 startWrite();
612 writeFillRect(x + r, y, w - 2 * r, h, color);
613 // draw four corners
614 fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color);
615 fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1, color);
616 endWrite();
617}
618
619/**************************************************************************/
630/**************************************************************************/
632 int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
633{
634 drawLine(x0, y0, x1, y1, color);
635 drawLine(x1, y1, x2, y2, color);
636 drawLine(x2, y2, x0, y0, color);
637}
638
639/**************************************************************************/
650/**************************************************************************/
652 int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
653{
654
655 int16_t a, b, y, last;
656
657 // Sort coordinates by Y order (y2 >= y1 >= y0)
658 if (y0 > y1) {
659 _swap_int16_t(y0, y1);
660 _swap_int16_t(x0, x1);
661 }
662 if (y1 > y2) {
663 _swap_int16_t(y2, y1);
664 _swap_int16_t(x2, x1);
665 }
666 if (y0 > y1) {
667 _swap_int16_t(y0, y1);
668 _swap_int16_t(x0, x1);
669 }
670
671 startWrite();
672 if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
673 a = b = x0;
674 if (x1 < a)
675 a = x1;
676 else if (x1 > b)
677 b = x1;
678 if (x2 < a)
679 a = x2;
680 else if (x2 > b)
681 b = x2;
682 writeFastHLine(a, y0, b - a + 1, color);
683 endWrite();
684 return;
685 }
686
687 int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0, dx12 = x2 - x1,
688 dy12 = y2 - y1;
689 int32_t sa = 0, sb = 0;
690
691 // For upper part of triangle, find scanline crossings for segments
692 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
693 // is included here (and second loop will be skipped, avoiding a /0
694 // error there), otherwise scanline y1 is skipped here and handled
695 // in the second loop...which also avoids a /0 error here if y0=y1
696 // (flat-topped triangle).
697 if (y1 == y2)
698 last = y1; // Include y1 scanline
699 else
700 last = y1 - 1; // Skip it
701
702 for (y = y0; y <= last; y++) {
703 a = x0 + sa / dy01;
704 b = x0 + sb / dy02;
705 sa += dx01;
706 sb += dx02;
707 /* longhand:
708 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
709 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
710 */
711 if (a > b) _swap_int16_t(a, b);
712 writeFastHLine(a, y, b - a + 1, color);
713 }
714
715 // For lower part of triangle, find scanline crossings for segments
716 // 0-2 and 1-2. This loop is skipped if y1=y2.
717 sa = (int32_t)dx12 * (y - y1);
718 sb = (int32_t)dx02 * (y - y0);
719 for (; y <= y2; y++) {
720 a = x1 + sa / dy12;
721 b = x0 + sb / dy02;
722 sa += dx12;
723 sb += dx02;
724 /* longhand:
725 a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
726 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
727 */
728 if (a > b) _swap_int16_t(a, b);
729 writeFastHLine(a, y, b - a + 1, color);
730 }
731 endWrite();
732}
733
734// BITMAP / XBITMAP / GRAYSCALE / RGB BITMAP FUNCTIONS ---------------------
735
736/**************************************************************************/
747/**************************************************************************/
749 int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)
750{
751
752 int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
753 uint8_t b = 0;
754
755 startWrite();
756 for (int16_t j = 0; j < h; j++, y++) {
757 for (int16_t i = 0; i < w; i++) {
758 if (i & 7)
759 b <<= 1;
760 else
761 b = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
762 if (b & 0x80) writePixel(x + i, y, color);
763 }
764 }
765 endWrite();
766}
767
768/**************************************************************************/
781/**************************************************************************/
783 int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg)
784{
785
786 int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
787 uint8_t b = 0;
788
789 startWrite();
790 for (int16_t j = 0; j < h; j++, y++) {
791 for (int16_t i = 0; i < w; i++) {
792 if (i & 7)
793 b <<= 1;
794 else
795 b = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
796 writePixel(x + i, y, (b & 0x80) ? color : bg);
797 }
798 }
799 endWrite();
800}
801
802/**************************************************************************/
813/**************************************************************************/
815 int16_t x, int16_t y, uint8_t* bitmap, int16_t w, int16_t h, uint16_t color)
816{
817
818 int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
819 uint8_t b = 0;
820
821 startWrite();
822 for (int16_t j = 0; j < h; j++, y++) {
823 for (int16_t i = 0; i < w; i++) {
824 if (i & 7)
825 b <<= 1;
826 else
827 b = bitmap[j * byteWidth + i / 8];
828 if (b & 0x80) writePixel(x + i, y, color);
829 }
830 }
831 endWrite();
832}
833
834/**************************************************************************/
847/**************************************************************************/
849 int16_t x, int16_t y, uint8_t* bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg)
850{
851
852 int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
853 uint8_t b = 0;
854
855 startWrite();
856 for (int16_t j = 0; j < h; j++, y++) {
857 for (int16_t i = 0; i < w; i++) {
858 if (i & 7)
859 b <<= 1;
860 else
861 b = bitmap[j * byteWidth + i / 8];
862 writePixel(x + i, y, (b & 0x80) ? color : bg);
863 }
864 }
865 endWrite();
866}
867
868/**************************************************************************/
882/**************************************************************************/
884 int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)
885{
886
887 int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
888 uint8_t b = 0;
889
890 startWrite();
891 for (int16_t j = 0; j < h; j++, y++) {
892 for (int16_t i = 0; i < w; i++) {
893 if (i & 7)
894 b >>= 1;
895 else
896 b = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
897 // Nearly identical to drawBitmap(), only the bit order
898 // is reversed here (left-to-right = LSB to MSB):
899 if (b & 0x01) writePixel(x + i, y, color);
900 }
901 }
902 endWrite();
903}
904
905/**************************************************************************/
916/**************************************************************************/
918 int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h)
919{
920 startWrite();
921 for (int16_t j = 0; j < h; j++, y++) {
922 for (int16_t i = 0; i < w; i++) {
923 writePixel(x + i, y, (uint8_t)pgm_read_byte(&bitmap[j * w + i]));
924 }
925 }
926 endWrite();
927}
928
929/**************************************************************************/
940/**************************************************************************/
941void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t* bitmap, int16_t w, int16_t h)
942{
943 startWrite();
944 for (int16_t j = 0; j < h; j++, y++) {
945 for (int16_t i = 0; i < w; i++) {
946 writePixel(x + i, y, bitmap[j * w + i]);
947 }
948 }
949 endWrite();
950}
951
952/**************************************************************************/
966/**************************************************************************/
968 int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h)
969{
970 int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte
971 uint8_t b = 0;
972 startWrite();
973 for (int16_t j = 0; j < h; j++, y++) {
974 for (int16_t i = 0; i < w; i++) {
975 if (i & 7)
976 b <<= 1;
977 else
978 b = pgm_read_byte(&mask[j * bw + i / 8]);
979 if (b & 0x80) {
980 writePixel(x + i, y, (uint8_t)pgm_read_byte(&bitmap[j * w + i]));
981 }
982 }
983 }
984 endWrite();
985}
986
987/**************************************************************************/
1001/**************************************************************************/
1003 int16_t x, int16_t y, uint8_t* bitmap, uint8_t* mask, int16_t w, int16_t h)
1004{
1005 int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte
1006 uint8_t b = 0;
1007 startWrite();
1008 for (int16_t j = 0; j < h; j++, y++) {
1009 for (int16_t i = 0; i < w; i++) {
1010 if (i & 7)
1011 b <<= 1;
1012 else
1013 b = mask[j * bw + i / 8];
1014 if (b & 0x80) {
1015 writePixel(x + i, y, bitmap[j * w + i]);
1016 }
1017 }
1018 }
1019 endWrite();
1020}
1021
1022/**************************************************************************/
1032/**************************************************************************/
1034 int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h)
1035{
1036 startWrite();
1037 for (int16_t j = 0; j < h; j++, y++) {
1038 for (int16_t i = 0; i < w; i++) {
1039 writePixel(x + i, y, pgm_read_word(&bitmap[j * w + i]));
1040 }
1041 }
1042 endWrite();
1043}
1044
1045/**************************************************************************/
1055/**************************************************************************/
1056void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, uint16_t* bitmap, int16_t w, int16_t h)
1057{
1058 startWrite();
1059 for (int16_t j = 0; j < h; j++, y++) {
1060 for (int16_t i = 0; i < w; i++) {
1061 writePixel(x + i, y, bitmap[j * w + i]);
1062 }
1063 }
1064 endWrite();
1065}
1066
1067/**************************************************************************/
1080/**************************************************************************/
1082 int16_t x, int16_t y, const uint16_t bitmap[], const uint8_t mask[], int16_t w, int16_t h)
1083{
1084 int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte
1085 uint8_t b = 0;
1086 startWrite();
1087 for (int16_t j = 0; j < h; j++, y++) {
1088 for (int16_t i = 0; i < w; i++) {
1089 if (i & 7)
1090 b <<= 1;
1091 else
1092 b = pgm_read_byte(&mask[j * bw + i / 8]);
1093 if (b & 0x80) {
1094 writePixel(x + i, y, pgm_read_word(&bitmap[j * w + i]));
1095 }
1096 }
1097 }
1098 endWrite();
1099}
1100
1101/**************************************************************************/
1114/**************************************************************************/
1116 int16_t x, int16_t y, uint16_t* bitmap, uint8_t* mask, int16_t w, int16_t h)
1117{
1118 int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte
1119 uint8_t b = 0;
1120 startWrite();
1121 for (int16_t j = 0; j < h; j++, y++) {
1122 for (int16_t i = 0; i < w; i++) {
1123 if (i & 7)
1124 b <<= 1;
1125 else
1126 b = mask[j * bw + i / 8];
1127 if (b & 0x80) {
1128 writePixel(x + i, y, bitmap[j * w + i]);
1129 }
1130 }
1131 }
1132 endWrite();
1133}
1134
1135// TEXT- AND CHARACTER-HANDLING FUNCTIONS ----------------------------------
1136
1137// Draw a character
1138/**************************************************************************/
1149/**************************************************************************/
1151 int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size)
1152{
1153 drawChar(x, y, c, color, bg, size, size);
1154}
1155
1156// Draw a character
1157/**************************************************************************/
1169/**************************************************************************/
1171 int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x,
1172 uint8_t size_y)
1173{
1174
1175 if (!gfxFont) { // 'Classic' built-in font
1176
1177 if ((x >= _width) || // Clip right
1178 (y >= _height) || // Clip bottom
1179 ((x + 6 * size_x - 1) < 0) || // Clip left
1180 ((y + 8 * size_y - 1) < 0)) // Clip top
1181 return;
1182
1183 if (!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior
1184
1185 startWrite();
1186 for (int8_t i = 0; i < 5; i++) { // Char bitmap = 5 columns
1187 uint8_t line = pgm_read_byte(&font[c * 5 + i]);
1188 for (int8_t j = 0; j < 8; j++, line >>= 1) {
1189 if (line & 1) {
1190 if (size_x == 1 && size_y == 1)
1191 writePixel(x + i, y + j, color);
1192 else
1193 writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, color);
1194 } else if (bg != color) {
1195 if (size_x == 1 && size_y == 1)
1196 writePixel(x + i, y + j, bg);
1197 else
1198 writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg);
1199 }
1200 }
1201 }
1202 if (bg != color) { // If opaque, draw vertical line for last column
1203 if (size_x == 1 && size_y == 1)
1204 writeFastVLine(x + 5, y, 8, bg);
1205 else
1206 writeFillRect(x + 5 * size_x, y, size_x, 8 * size_y, bg);
1207 }
1208 endWrite();
1209
1210 } else { // Custom font
1211
1212 // Character is assumed previously filtered by write() to eliminate
1213 // newlines, returns, non-printable characters, etc. Calling
1214 // drawChar() directly with 'bad' characters of font may cause mayhem!
1215
1216 c -= (uint8_t)pgm_read_byte(&gfxFont->first);
1217 GFXglyph* glyph = pgm_read_glyph_ptr(gfxFont, c);
1218 uint8_t* bitmap = pgm_read_bitmap_ptr(gfxFont);
1219
1220 uint16_t bo = pgm_read_word(&glyph->bitmapOffset);
1221 uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height);
1222 int8_t xo = pgm_read_byte(&glyph->xOffset), yo = pgm_read_byte(&glyph->yOffset);
1223 uint8_t xx, yy, bits = 0, bit = 0;
1224 int16_t xo16 = 0, yo16 = 0;
1225
1226 if (size_x > 1 || size_y > 1) {
1227 xo16 = xo;
1228 yo16 = yo;
1229 }
1230
1231 // Todo: Add character clipping here
1232
1233 // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.
1234 // THIS IS ON PURPOSE AND BY DESIGN. The background color feature
1235 // has typically been used with the 'classic' font to overwrite old
1236 // screen contents with new data. This ONLY works because the
1237 // characters are a uniform size; it's not a sensible thing to do with
1238 // proportionally-spaced fonts with glyphs of varying sizes (and that
1239 // may overlap). To replace previously-drawn text when using a custom
1240 // font, use the getTextBounds() function to determine the smallest
1241 // rectangle encompassing a string, erase the area with fillRect(),
1242 // then draw new text. This WILL infortunately 'blink' the text, but
1243 // is unavoidable. Drawing 'background' pixels will NOT fix this,
1244 // only creates a new set of problems. Have an idea to work around
1245 // this (a canvas object type for MCUs that can afford the RAM and
1246 // displays supporting setAddrWindow() and pushColors()), but haven't
1247 // implemented this yet.
1248
1249 startWrite();
1250 for (yy = 0; yy < h; yy++) {
1251 for (xx = 0; xx < w; xx++) {
1252 if (!(bit++ & 7)) {
1253 bits = pgm_read_byte(&bitmap[bo++]);
1254 }
1255 if (bits & 0x80) {
1256 if (size_x == 1 && size_y == 1) {
1257 writePixel(x + xo + xx, y + yo + yy, color);
1258 } else {
1260 x + (xo16 + xx) * size_x,
1261 y + (yo16 + yy) * size_y,
1262 size_x,
1263 size_y,
1264 color);
1265 }
1266 }
1267 bits <<= 1;
1268 }
1269 }
1270 endWrite();
1271
1272 } // End classic vs custom font
1273}
1274/**************************************************************************/
1279/**************************************************************************/
1280size_t Adafruit_GFX::write(uint8_t c)
1281{
1282 if (!gfxFont) { // 'Classic' built-in font
1283
1284 if (c == '\n') { // Newline?
1285 cursor_x = 0; // Reset x to zero,
1286 cursor_y += textsize_y * 8; // advance y one line
1287 } else if (c != '\r') { // Ignore carriage returns
1288 if (wrap && ((cursor_x + textsize_x * 6) > _width)) { // Off right?
1289 cursor_x = 0; // Reset x to zero,
1290 cursor_y += textsize_y * 8; // advance y one line
1291 }
1293 cursor_x += textsize_x * 6; // Advance x one char
1294 }
1295
1296 } else { // Custom font
1297
1298 if (c == '\n') {
1299 cursor_x = 0;
1300 cursor_y += (int16_t)textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
1301 } else if (c != '\r') {
1302 uint8_t first = pgm_read_byte(&gfxFont->first);
1303 if ((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) {
1304 GFXglyph* glyph = pgm_read_glyph_ptr(gfxFont, c - first);
1305 uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height);
1306 if ((w > 0) && (h > 0)) { // Is there an associated bitmap?
1307 int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic
1308 if (wrap && ((cursor_x + textsize_x * (xo + w)) > _width)) {
1309 cursor_x = 0;
1310 cursor_y +=
1311 (int16_t)textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
1312 }
1314 }
1315 cursor_x += (uint8_t)pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize_x;
1316 }
1317 }
1318 }
1319 return 1;
1320}
1321
1322/**************************************************************************/
1328/**************************************************************************/
1330{
1331 setTextSize(s, s);
1332}
1333
1334/**************************************************************************/
1341/**************************************************************************/
1342void Adafruit_GFX::setTextSize(uint8_t s_x, uint8_t s_y)
1343{
1344 textsize_x = (s_x > 0) ? s_x : 1;
1345 textsize_y = (s_y > 0) ? s_y : 1;
1346}
1347
1348/**************************************************************************/
1353/**************************************************************************/
1355{
1356 rotation = (x & 3);
1357 switch (rotation) {
1358 case 0:
1359 case 2:
1360 _width = WIDTH;
1361 _height = HEIGHT;
1362 break;
1363 case 1:
1364 case 3:
1365 _width = HEIGHT;
1366 _height = WIDTH;
1367 break;
1368 }
1369}
1370
1371/**************************************************************************/
1376/**************************************************************************/
1378{
1379 if (f) { // Font struct pointer passed in?
1380 if (!gfxFont) { // And no current font struct?
1381 // Switching from classic to new font behavior.
1382 // Move cursor pos down 6 pixels so it's on baseline.
1383 cursor_y += 6;
1384 }
1385 } else if (gfxFont) { // NULL passed. Current font struct defined?
1386 // Switching from new to classic font behavior.
1387 // Move cursor pos up 6 pixels so it's at top-left of char.
1388 cursor_y -= 6;
1389 }
1390 gfxFont = (GFXfont*)f;
1391}
1392
1393/**************************************************************************/
1410/**************************************************************************/
1412 unsigned char c, int16_t* x, int16_t* y, int16_t* minx, int16_t* miny, int16_t* maxx,
1413 int16_t* maxy)
1414{
1415
1416 if (gfxFont) {
1417
1418 if (c == '\n') { // Newline?
1419 *x = 0; // Reset x to zero, advance y by one line
1420 *y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
1421 } else if (c != '\r') { // Not a carriage return; is normal char
1422 uint8_t first = pgm_read_byte(&gfxFont->first), last = pgm_read_byte(&gfxFont->last);
1423 if ((c >= first) && (c <= last)) { // Char present in this font?
1424 GFXglyph* glyph = pgm_read_glyph_ptr(gfxFont, c - first);
1425 uint8_t gw = pgm_read_byte(&glyph->width), gh = pgm_read_byte(&glyph->height),
1426 xa = pgm_read_byte(&glyph->xAdvance);
1427 int8_t xo = pgm_read_byte(&glyph->xOffset), yo = pgm_read_byte(&glyph->yOffset);
1428 if (wrap && ((*x + (((int16_t)xo + gw) * textsize_x)) > _width)) {
1429 *x = 0; // Reset x to zero, advance y by one line
1430 *y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
1431 }
1432 int16_t tsx = (int16_t)textsize_x, tsy = (int16_t)textsize_y, x1 = *x + xo * tsx,
1433 y1 = *y + yo * tsy, x2 = x1 + gw * tsx - 1, y2 = y1 + gh * tsy - 1;
1434 if (x1 < *minx) *minx = x1;
1435 if (y1 < *miny) *miny = y1;
1436 if (x2 > *maxx) *maxx = x2;
1437 if (y2 > *maxy) *maxy = y2;
1438 *x += xa * tsx;
1439 }
1440 }
1441
1442 } else { // Default font
1443
1444 if (c == '\n') { // Newline?
1445 *x = 0; // Reset x to zero,
1446 *y += textsize_y * 8; // advance y one line
1447 // min/max x/y unchaged -- that waits for next 'normal' character
1448 } else if (c != '\r') { // Normal char; ignore carriage returns
1449 if (wrap && ((*x + textsize_x * 6) > _width)) { // Off right?
1450 *x = 0; // Reset x to zero,
1451 *y += textsize_y * 8; // advance y one line
1452 }
1453 int x2 = *x + textsize_x * 6 - 1, // Lower-right pixel of char
1454 y2 = *y + textsize_y * 8 - 1;
1455 if (x2 > *maxx) *maxx = x2; // Track max x, y
1456 if (y2 > *maxy) *maxy = y2;
1457 if (*x < *minx) *minx = *x; // Track min x, y
1458 if (*y < *miny) *miny = *y;
1459 *x += textsize_x * 6; // Advance x one char
1460 }
1461 }
1462}
1463
1464/**************************************************************************/
1476/**************************************************************************/
1478 const char* str, int16_t x, int16_t y, int16_t* x1, int16_t* y1, uint16_t* w, uint16_t* h)
1479{
1480
1481 uint8_t c; // Current character
1482 int16_t minx = 0x7FFF, miny = 0x7FFF, maxx = -1, maxy = -1; // Bound rect
1483 // Bound rect is intentionally initialized inverted, so 1st char sets it
1484
1485 *x1 = x; // Initial position is value passed in
1486 *y1 = y;
1487 *w = *h = 0; // Initial size is zero
1488
1489 while ((c = *str++)) {
1490 // charBounds() modifies x/y to advance for each character,
1491 // and min/max x/y are updated to incrementally build bounding rect.
1492 charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy);
1493 }
1494
1495 if (maxx >= minx) { // If legit string bounds were found...
1496 *x1 = minx; // Update x1 to least X coord,
1497 *w = maxx - minx + 1; // And w to bound rect width
1498 }
1499 if (maxy >= miny) { // Same for height
1500 *y1 = miny;
1501 *h = maxy - miny + 1;
1502 }
1503}
1504
1505/**************************************************************************/
1517/**************************************************************************/
1519 const String& str, int16_t x, int16_t y, int16_t* x1, int16_t* y1, uint16_t* w, uint16_t* h)
1520{
1521 if (str.length() != 0) {
1522 getTextBounds(const_cast<char*>(str.c_str()), x, y, x1, y1, w, h);
1523 }
1524}
1525
1526/**************************************************************************/
1538/**************************************************************************/
1540 const __FlashStringHelper* str, int16_t x, int16_t y, int16_t* x1, int16_t* y1, uint16_t* w,
1541 uint16_t* h)
1542{
1543 uint8_t *s = (uint8_t*)str, c;
1544
1545 *x1 = x;
1546 *y1 = y;
1547 *w = *h = 0;
1548
1549 int16_t minx = _width, miny = _height, maxx = -1, maxy = -1;
1550
1551 while ((c = pgm_read_byte(s++))) charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy);
1552
1553 if (maxx >= minx) {
1554 *x1 = minx;
1555 *w = maxx - minx + 1;
1556 }
1557 if (maxy >= miny) {
1558 *y1 = miny;
1559 *h = maxy - miny + 1;
1560 }
1561}
1562
1563/**************************************************************************/
1568/**************************************************************************/
1570{
1571 // Do nothing, must be subclassed if supported by hardware
1572 (void)i; // disable -Wunused-parameter warning
1573}
1574
1575/***************************************************************************/
1576
1577/**************************************************************************/
1581/**************************************************************************/
1583{
1584 _gfx = 0;
1585}
1586
1587/**************************************************************************/
1601/**************************************************************************/
1602// Classic initButton() function: pass center & size
1604 Adafruit_GFX* gfx, int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t outline,
1605 uint16_t fill, uint16_t textcolor, char* label, uint8_t textsize)
1606{
1607 // Tweak arguments and pass to the newer initButtonUL() function...
1608 initButtonUL(gfx, x - (w / 2), y - (h / 2), w, h, outline, fill, textcolor, label, textsize);
1609}
1610
1611/**************************************************************************/
1626/**************************************************************************/
1627// Classic initButton() function: pass center & size
1629 Adafruit_GFX* gfx, int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t outline,
1630 uint16_t fill, uint16_t textcolor, char* label, uint8_t textsize_x, uint8_t textsize_y)
1631{
1632 // Tweak arguments and pass to the newer initButtonUL() function...
1634 gfx,
1635 x - (w / 2),
1636 y - (h / 2),
1637 w,
1638 h,
1639 outline,
1640 fill,
1641 textcolor,
1642 label,
1643 textsize_x,
1644 textsize_y);
1645}
1646
1647/**************************************************************************/
1662/**************************************************************************/
1664 Adafruit_GFX* gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h, uint16_t outline,
1665 uint16_t fill, uint16_t textcolor, char* label, uint8_t textsize)
1666{
1667 initButtonUL(gfx, x1, y1, w, h, outline, fill, textcolor, label, textsize, textsize);
1668}
1669
1670/**************************************************************************/
1686/**************************************************************************/
1688 Adafruit_GFX* gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h, uint16_t outline,
1689 uint16_t fill, uint16_t textcolor, char* label, uint8_t textsize_x, uint8_t textsize_y)
1690{
1691 _x1 = x1;
1692 _y1 = y1;
1693 _w = w;
1694 _h = h;
1695 _outlinecolor = outline;
1696 _fillcolor = fill;
1697 _textcolor = textcolor;
1698 _textsize_x = textsize_x;
1699 _textsize_y = textsize_y;
1700 _gfx = gfx;
1701 strncpy(_label, label, 9);
1702 _label[9] = 0; // strncpy does not place a null at the end.
1703 // When 'label' is >9 characters, _label is not terminated.
1704}
1705
1706/**************************************************************************/
1712/**************************************************************************/
1714{
1715 uint16_t fill, outline, text;
1716
1717 if (!inverted) {
1718 fill = _fillcolor;
1719 outline = _outlinecolor;
1720 text = _textcolor;
1721 } else {
1722 fill = _textcolor;
1723 outline = _outlinecolor;
1724 text = _fillcolor;
1725 }
1726
1727 uint8_t r = min(_w, _h) / 4; // Corner radius
1728 _gfx->fillRoundRect(_x1, _y1, _w, _h, r, fill);
1729 _gfx->drawRoundRect(_x1, _y1, _w, _h, r, outline);
1730
1731 _gfx->setCursor(
1732 _x1 + (_w / 2) - (strlen(_label) * 3 * _textsize_x), _y1 + (_h / 2) - (4 * _textsize_y));
1733 _gfx->setTextColor(text);
1734 _gfx->setTextSize(_textsize_x, _textsize_y);
1735 _gfx->print(_label);
1736}
1737
1738/**************************************************************************/
1746/**************************************************************************/
1747bool Adafruit_GFX_Button::contains(int16_t x, int16_t y)
1748{
1749 return ((x >= _x1) && (x < (int16_t)(_x1 + _w)) && (y >= _y1) && (y < (int16_t)(_y1 + _h)));
1750}
1751
1752/**************************************************************************/
1757/**************************************************************************/
1759{
1760 return (currstate && !laststate);
1761}
1762
1763/**************************************************************************/
1768/**************************************************************************/
1770{
1771 return (!currstate && laststate);
1772}
1773
1774// -------------------------------------------------------------------------
1775
1776// GFXcanvas1, GFXcanvas8 and GFXcanvas16 (currently a WIP, don't get too
1777// comfy with the implementation) provide 1-, 8- and 16-bit offscreen
1778// canvases, the address of which can be passed to drawBitmap() or
1779// pushColors() (the latter appears only in a couple of GFX-subclassed TFT
1780// libraries at this time). This is here mostly to help with the recently-
1781// added proportionally-spaced fonts; adds a way to refresh a section of the
1782// screen without a massive flickering clear-and-redraw...but maybe you'll
1783// find other uses too. VERY RAM-intensive, since the buffer is in MCU
1784// memory and not the display driver...GXFcanvas1 might be minimally useful
1785// on an Uno-class board, but this and the others are much more likely to
1786// require at least a Mega or various recent ARM-type boards (recommended,
1787// as the text+bitmap draw can be pokey). GFXcanvas1 requires 1 bit per
1788// pixel (rounded up to nearest byte per scanline), GFXcanvas8 is 1 byte
1789// per pixel (no scanline pad), and GFXcanvas16 uses 2 bytes per pixel (no
1790// scanline pad).
1791// NOT EXTENSIVELY TESTED YET. MAY CONTAIN WORST BUGS KNOWN TO HUMANKIND.
1792
1793#ifdef __AVR__
1794// Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR
1795const uint8_t PROGMEM GFXcanvas1::GFXsetBit[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1796const uint8_t PROGMEM GFXcanvas1::GFXclrBit[] = {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE};
1797#endif
1798
1799/**************************************************************************/
1805/**************************************************************************/
1806GFXcanvas1::GFXcanvas1(uint16_t w, uint16_t h)
1807 : Adafruit_GFX(w, h)
1808{
1809 uint32_t bytes = ((w + 7) / 8) * h;
1810 if ((buffer = (uint8_t*)malloc(bytes))) {
1811 memset(buffer, 0, bytes);
1812 }
1813}
1814
1815/**************************************************************************/
1819/**************************************************************************/
1821{
1822 if (buffer) free(buffer);
1823}
1824
1825/**************************************************************************/
1832/**************************************************************************/
1833void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color)
1834{
1835 if (buffer) {
1836 if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;
1837
1838 int16_t t;
1839 switch (rotation) {
1840 case 1:
1841 t = x;
1842 x = WIDTH - 1 - y;
1843 y = t;
1844 break;
1845 case 2:
1846 x = WIDTH - 1 - x;
1847 y = HEIGHT - 1 - y;
1848 break;
1849 case 3:
1850 t = x;
1851 x = y;
1852 y = HEIGHT - 1 - t;
1853 break;
1854 }
1855
1856 uint8_t* ptr = &buffer[(x / 8) + y * ((WIDTH + 7) / 8)];
1857#ifdef __AVR__
1858 if (color)
1859 *ptr |= pgm_read_byte(&GFXsetBit[x & 7]);
1860 else
1861 *ptr &= pgm_read_byte(&GFXclrBit[x & 7]);
1862#else
1863 if (color)
1864 *ptr |= 0x80 >> (x & 7);
1865 else
1866 *ptr &= ~(0x80 >> (x & 7));
1867#endif
1868 }
1869}
1870
1871/**********************************************************************/
1879/**********************************************************************/
1880bool GFXcanvas1::getPixel(int16_t x, int16_t y) const
1881{
1882 int16_t t;
1883 switch (rotation) {
1884 case 1:
1885 t = x;
1886 x = WIDTH - 1 - y;
1887 y = t;
1888 break;
1889 case 2:
1890 x = WIDTH - 1 - x;
1891 y = HEIGHT - 1 - y;
1892 break;
1893 case 3:
1894 t = x;
1895 x = y;
1896 y = HEIGHT - 1 - t;
1897 break;
1898 }
1899 return getRawPixel(x, y);
1900}
1901
1902/**********************************************************************/
1912/**********************************************************************/
1913bool GFXcanvas1::getRawPixel(int16_t x, int16_t y) const
1914{
1915 if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT)) return 0;
1916 if (buffer) {
1917 uint8_t* ptr = &buffer[(x / 8) + y * ((WIDTH + 7) / 8)];
1918
1919#ifdef __AVR__
1920 return ((*ptr) & pgm_read_byte(&GFXsetBit[x & 7])) != 0;
1921#else
1922 return ((*ptr) & (0x80 >> (x & 7))) != 0;
1923#endif
1924 }
1925 return 0;
1926}
1927
1928/**************************************************************************/
1933/**************************************************************************/
1934void GFXcanvas1::fillScreen(uint16_t color)
1935{
1936 if (buffer) {
1937 uint32_t bytes = ((WIDTH + 7) / 8) * HEIGHT;
1938 memset(buffer, color ? 0xFF : 0x00, bytes);
1939 }
1940}
1941
1942/**************************************************************************/
1950/**************************************************************************/
1951void GFXcanvas1::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
1952{
1953
1954 if (h < 0) { // Convert negative heights to positive equivalent
1955 h *= -1;
1956 y -= h - 1;
1957 if (y < 0) {
1958 h += y;
1959 y = 0;
1960 }
1961 }
1962
1963 // Edge rejection (no-draw if totally off canvas)
1964 if ((x < 0) || (x >= width()) || (y >= height()) || ((y + h - 1) < 0)) {
1965 return;
1966 }
1967
1968 if (y < 0) { // Clip top
1969 h += y;
1970 y = 0;
1971 }
1972 if (y + h > height()) { // Clip bottom
1973 h = height() - y;
1974 }
1975
1976 if (getRotation() == 0) {
1977 drawFastRawVLine(x, y, h, color);
1978 } else if (getRotation() == 1) {
1979 int16_t t = x;
1980 x = WIDTH - 1 - y;
1981 y = t;
1982 x -= h - 1;
1983 drawFastRawHLine(x, y, h, color);
1984 } else if (getRotation() == 2) {
1985 x = WIDTH - 1 - x;
1986 y = HEIGHT - 1 - y;
1987
1988 y -= h - 1;
1989 drawFastRawVLine(x, y, h, color);
1990 } else if (getRotation() == 3) {
1991 int16_t t = x;
1992 x = y;
1993 y = HEIGHT - 1 - t;
1994 drawFastRawHLine(x, y, h, color);
1995 }
1996}
1997
1998/**************************************************************************/
2006/**************************************************************************/
2007void GFXcanvas1::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
2008{
2009 if (w < 0) { // Convert negative widths to positive equivalent
2010 w *= -1;
2011 x -= w - 1;
2012 if (x < 0) {
2013 w += x;
2014 x = 0;
2015 }
2016 }
2017
2018 // Edge rejection (no-draw if totally off canvas)
2019 if ((y < 0) || (y >= height()) || (x >= width()) || ((x + w - 1) < 0)) {
2020 return;
2021 }
2022
2023 if (x < 0) { // Clip left
2024 w += x;
2025 x = 0;
2026 }
2027 if (x + w >= width()) { // Clip right
2028 w = width() - x;
2029 }
2030
2031 if (getRotation() == 0) {
2032 drawFastRawHLine(x, y, w, color);
2033 } else if (getRotation() == 1) {
2034 int16_t t = x;
2035 x = WIDTH - 1 - y;
2036 y = t;
2037 drawFastRawVLine(x, y, w, color);
2038 } else if (getRotation() == 2) {
2039 x = WIDTH - 1 - x;
2040 y = HEIGHT - 1 - y;
2041
2042 x -= w - 1;
2043 drawFastRawHLine(x, y, w, color);
2044 } else if (getRotation() == 3) {
2045 int16_t t = x;
2046 x = y;
2047 y = HEIGHT - 1 - t;
2048 y -= w - 1;
2049 drawFastRawVLine(x, y, w, color);
2050 }
2051}
2052
2053/**************************************************************************/
2061/**************************************************************************/
2062void GFXcanvas1::drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
2063{
2064 // x & y already in raw (rotation 0) coordinates, no need to transform.
2065 int16_t row_bytes = ((WIDTH + 7) / 8);
2066 uint8_t* ptr = &buffer[(x / 8) + y * row_bytes];
2067
2068 if (color > 0) {
2069#ifdef __AVR__
2070 uint8_t bit_mask = pgm_read_byte(&GFXsetBit[x & 7]);
2071#else
2072 uint8_t bit_mask = (0x80 >> (x & 7));
2073#endif
2074 for (int16_t i = 0; i < h; i++) {
2075 *ptr |= bit_mask;
2076 ptr += row_bytes;
2077 }
2078 } else {
2079#ifdef __AVR__
2080 uint8_t bit_mask = pgm_read_byte(&GFXclrBit[x & 7]);
2081#else
2082 uint8_t bit_mask = ~(0x80 >> (x & 7));
2083#endif
2084 for (int16_t i = 0; i < h; i++) {
2085 *ptr &= bit_mask;
2086 ptr += row_bytes;
2087 }
2088 }
2089}
2090
2091/**************************************************************************/
2099/**************************************************************************/
2100void GFXcanvas1::drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
2101{
2102 // x & y already in raw (rotation 0) coordinates, no need to transform.
2103 int16_t rowBytes = ((WIDTH + 7) / 8);
2104 uint8_t* ptr = &buffer[(x / 8) + y * rowBytes];
2105 size_t remainingWidthBits = w;
2106
2107 // check to see if first byte needs to be partially filled
2108 if ((x & 7) > 0) {
2109 // create bit mask for first byte
2110 uint8_t startByteBitMask = 0x00;
2111 for (int8_t i = (x & 7); ((i < 8) && (remainingWidthBits > 0)); i++) {
2112#ifdef __AVR__
2113 startByteBitMask |= pgm_read_byte(&GFXsetBit[i]);
2114#else
2115 startByteBitMask |= (0x80 >> i);
2116#endif
2117 remainingWidthBits--;
2118 }
2119 if (color > 0) {
2120 *ptr |= startByteBitMask;
2121 } else {
2122 *ptr &= ~startByteBitMask;
2123 }
2124
2125 ptr++;
2126 }
2127
2128 // do the next remainingWidthBits bits
2129 if (remainingWidthBits > 0) {
2130 size_t remainingWholeBytes = remainingWidthBits / 8;
2131 size_t lastByteBits = remainingWidthBits % 8;
2132 uint8_t wholeByteColor = color > 0 ? 0xFF : 0x00;
2133
2134 memset(ptr, wholeByteColor, remainingWholeBytes);
2135
2136 if (lastByteBits > 0) {
2137 uint8_t lastByteBitMask = 0x00;
2138 for (size_t i = 0; i < lastByteBits; i++) {
2139#ifdef __AVR__
2140 lastByteBitMask |= pgm_read_byte(&GFXsetBit[i]);
2141#else
2142 lastByteBitMask |= (0x80 >> i);
2143#endif
2144 }
2145 ptr += remainingWholeBytes;
2146
2147 if (color > 0) {
2148 *ptr |= lastByteBitMask;
2149 } else {
2150 *ptr &= ~lastByteBitMask;
2151 }
2152 }
2153 }
2154}
2155
2156/**************************************************************************/
2162/**************************************************************************/
2163GFXcanvas8::GFXcanvas8(uint16_t w, uint16_t h)
2164 : Adafruit_GFX(w, h)
2165{
2166 uint32_t bytes = w * h;
2167 if ((buffer = (uint8_t*)malloc(bytes))) {
2168 memset(buffer, 0, bytes);
2169 }
2170}
2171
2172/**************************************************************************/
2176/**************************************************************************/
2178{
2179 if (buffer) free(buffer);
2180}
2181
2182/**************************************************************************/
2189/**************************************************************************/
2190void GFXcanvas8::drawPixel(int16_t x, int16_t y, uint16_t color)
2191{
2192 if (buffer) {
2193 if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;
2194
2195 int16_t t;
2196 switch (rotation) {
2197 case 1:
2198 t = x;
2199 x = WIDTH - 1 - y;
2200 y = t;
2201 break;
2202 case 2:
2203 x = WIDTH - 1 - x;
2204 y = HEIGHT - 1 - y;
2205 break;
2206 case 3:
2207 t = x;
2208 x = y;
2209 y = HEIGHT - 1 - t;
2210 break;
2211 }
2212
2213 buffer[x + y * WIDTH] = color;
2214 }
2215}
2216
2217/**********************************************************************/
2224/**********************************************************************/
2225uint8_t GFXcanvas8::getPixel(int16_t x, int16_t y) const
2226{
2227 int16_t t;
2228 switch (rotation) {
2229 case 1:
2230 t = x;
2231 x = WIDTH - 1 - y;
2232 y = t;
2233 break;
2234 case 2:
2235 x = WIDTH - 1 - x;
2236 y = HEIGHT - 1 - y;
2237 break;
2238 case 3:
2239 t = x;
2240 x = y;
2241 y = HEIGHT - 1 - t;
2242 break;
2243 }
2244 return getRawPixel(x, y);
2245}
2246
2247/**********************************************************************/
2256/**********************************************************************/
2257uint8_t GFXcanvas8::getRawPixel(int16_t x, int16_t y) const
2258{
2259 if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT)) return 0;
2260 if (buffer) {
2261 return buffer[x + y * WIDTH];
2262 }
2263 return 0;
2264}
2265
2266/**************************************************************************/
2271/**************************************************************************/
2272void GFXcanvas8::fillScreen(uint16_t color)
2273{
2274 if (buffer) {
2275 memset(buffer, color, WIDTH * HEIGHT);
2276 }
2277}
2278
2279/**************************************************************************/
2288/**************************************************************************/
2289void GFXcanvas8::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
2290{
2291 if (h < 0) { // Convert negative heights to positive equivalent
2292 h *= -1;
2293 y -= h - 1;
2294 if (y < 0) {
2295 h += y;
2296 y = 0;
2297 }
2298 }
2299
2300 // Edge rejection (no-draw if totally off canvas)
2301 if ((x < 0) || (x >= width()) || (y >= height()) || ((y + h - 1) < 0)) {
2302 return;
2303 }
2304
2305 if (y < 0) { // Clip top
2306 h += y;
2307 y = 0;
2308 }
2309 if (y + h > height()) { // Clip bottom
2310 h = height() - y;
2311 }
2312
2313 if (getRotation() == 0) {
2314 drawFastRawVLine(x, y, h, color);
2315 } else if (getRotation() == 1) {
2316 int16_t t = x;
2317 x = WIDTH - 1 - y;
2318 y = t;
2319 x -= h - 1;
2320 drawFastRawHLine(x, y, h, color);
2321 } else if (getRotation() == 2) {
2322 x = WIDTH - 1 - x;
2323 y = HEIGHT - 1 - y;
2324
2325 y -= h - 1;
2326 drawFastRawVLine(x, y, h, color);
2327 } else if (getRotation() == 3) {
2328 int16_t t = x;
2329 x = y;
2330 y = HEIGHT - 1 - t;
2331 drawFastRawHLine(x, y, h, color);
2332 }
2333}
2334
2335/**************************************************************************/
2344/**************************************************************************/
2345void GFXcanvas8::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
2346{
2347
2348 if (w < 0) { // Convert negative widths to positive equivalent
2349 w *= -1;
2350 x -= w - 1;
2351 if (x < 0) {
2352 w += x;
2353 x = 0;
2354 }
2355 }
2356
2357 // Edge rejection (no-draw if totally off canvas)
2358 if ((y < 0) || (y >= height()) || (x >= width()) || ((x + w - 1) < 0)) {
2359 return;
2360 }
2361
2362 if (x < 0) { // Clip left
2363 w += x;
2364 x = 0;
2365 }
2366 if (x + w >= width()) { // Clip right
2367 w = width() - x;
2368 }
2369
2370 if (getRotation() == 0) {
2371 drawFastRawHLine(x, y, w, color);
2372 } else if (getRotation() == 1) {
2373 int16_t t = x;
2374 x = WIDTH - 1 - y;
2375 y = t;
2376 drawFastRawVLine(x, y, w, color);
2377 } else if (getRotation() == 2) {
2378 x = WIDTH - 1 - x;
2379 y = HEIGHT - 1 - y;
2380
2381 x -= w - 1;
2382 drawFastRawHLine(x, y, w, color);
2383 } else if (getRotation() == 3) {
2384 int16_t t = x;
2385 x = y;
2386 y = HEIGHT - 1 - t;
2387 y -= w - 1;
2388 drawFastRawVLine(x, y, w, color);
2389 }
2390}
2391
2392/**************************************************************************/
2401/**************************************************************************/
2402void GFXcanvas8::drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
2403{
2404 // x & y already in raw (rotation 0) coordinates, no need to transform.
2405 uint8_t* buffer_ptr = buffer + y * WIDTH + x;
2406 for (int16_t i = 0; i < h; i++) {
2407 (*buffer_ptr) = color;
2408 buffer_ptr += WIDTH;
2409 }
2410}
2411
2412/**************************************************************************/
2421/**************************************************************************/
2422void GFXcanvas8::drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
2423{
2424 // x & y already in raw (rotation 0) coordinates, no need to transform.
2425 memset(buffer + y * WIDTH + x, color, w);
2426}
2427
2428/**************************************************************************/
2434/**************************************************************************/
2435GFXcanvas16::GFXcanvas16(uint16_t w, uint16_t h)
2436 : Adafruit_GFX(w, h)
2437{
2438 uint32_t bytes = w * h * 2;
2439 if ((buffer = (uint16_t*)malloc(bytes))) {
2440 memset(buffer, 0, bytes);
2441 }
2442}
2443
2444/**************************************************************************/
2448/**************************************************************************/
2450{
2451 if (buffer) free(buffer);
2452}
2453
2454/**************************************************************************/
2461/**************************************************************************/
2462void GFXcanvas16::drawPixel(int16_t x, int16_t y, uint16_t color)
2463{
2464 if (buffer) {
2465 if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;
2466
2467 int16_t t;
2468 switch (rotation) {
2469 case 1:
2470 t = x;
2471 x = WIDTH - 1 - y;
2472 y = t;
2473 break;
2474 case 2:
2475 x = WIDTH - 1 - x;
2476 y = HEIGHT - 1 - y;
2477 break;
2478 case 3:
2479 t = x;
2480 x = y;
2481 y = HEIGHT - 1 - t;
2482 break;
2483 }
2484
2485 buffer[x + y * WIDTH] = color;
2486 }
2487}
2488
2489/**********************************************************************/
2496/**********************************************************************/
2497uint16_t GFXcanvas16::getPixel(int16_t x, int16_t y) const
2498{
2499 int16_t t;
2500 switch (rotation) {
2501 case 1:
2502 t = x;
2503 x = WIDTH - 1 - y;
2504 y = t;
2505 break;
2506 case 2:
2507 x = WIDTH - 1 - x;
2508 y = HEIGHT - 1 - y;
2509 break;
2510 case 3:
2511 t = x;
2512 x = y;
2513 y = HEIGHT - 1 - t;
2514 break;
2515 }
2516 return getRawPixel(x, y);
2517}
2518
2519/**********************************************************************/
2528/**********************************************************************/
2529uint16_t GFXcanvas16::getRawPixel(int16_t x, int16_t y) const
2530{
2531 if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT)) return 0;
2532 if (buffer) {
2533 return buffer[x + y * WIDTH];
2534 }
2535 return 0;
2536}
2537
2538/**************************************************************************/
2543/**************************************************************************/
2544void GFXcanvas16::fillScreen(uint16_t color)
2545{
2546 if (buffer) {
2547 uint8_t hi = color >> 8, lo = color & 0xFF;
2548 if (hi == lo) {
2549 memset(buffer, lo, WIDTH * HEIGHT * 2);
2550 } else {
2551 uint32_t i, pixels = WIDTH * HEIGHT;
2552 for (i = 0; i < pixels; i++) buffer[i] = color;
2553 }
2554 }
2555}
2556
2557/**************************************************************************/
2569/**************************************************************************/
2571{
2572 if (buffer) {
2573 uint32_t i, pixels = WIDTH * HEIGHT;
2574 for (i = 0; i < pixels; i++) buffer[i] = __builtin_bswap16(buffer[i]);
2575 }
2576}
2577
2578/**************************************************************************/
2586/**************************************************************************/
2587void GFXcanvas16::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
2588{
2589 if (h < 0) { // Convert negative heights to positive equivalent
2590 h *= -1;
2591 y -= h - 1;
2592 if (y < 0) {
2593 h += y;
2594 y = 0;
2595 }
2596 }
2597
2598 // Edge rejection (no-draw if totally off canvas)
2599 if ((x < 0) || (x >= width()) || (y >= height()) || ((y + h - 1) < 0)) {
2600 return;
2601 }
2602
2603 if (y < 0) { // Clip top
2604 h += y;
2605 y = 0;
2606 }
2607 if (y + h > height()) { // Clip bottom
2608 h = height() - y;
2609 }
2610
2611 if (getRotation() == 0) {
2612 drawFastRawVLine(x, y, h, color);
2613 } else if (getRotation() == 1) {
2614 int16_t t = x;
2615 x = WIDTH - 1 - y;
2616 y = t;
2617 x -= h - 1;
2618 drawFastRawHLine(x, y, h, color);
2619 } else if (getRotation() == 2) {
2620 x = WIDTH - 1 - x;
2621 y = HEIGHT - 1 - y;
2622
2623 y -= h - 1;
2624 drawFastRawVLine(x, y, h, color);
2625 } else if (getRotation() == 3) {
2626 int16_t t = x;
2627 x = y;
2628 y = HEIGHT - 1 - t;
2629 drawFastRawHLine(x, y, h, color);
2630 }
2631}
2632
2633/**************************************************************************/
2641/**************************************************************************/
2642void GFXcanvas16::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
2643{
2644 if (w < 0) { // Convert negative widths to positive equivalent
2645 w *= -1;
2646 x -= w - 1;
2647 if (x < 0) {
2648 w += x;
2649 x = 0;
2650 }
2651 }
2652
2653 // Edge rejection (no-draw if totally off canvas)
2654 if ((y < 0) || (y >= height()) || (x >= width()) || ((x + w - 1) < 0)) {
2655 return;
2656 }
2657
2658 if (x < 0) { // Clip left
2659 w += x;
2660 x = 0;
2661 }
2662 if (x + w >= width()) { // Clip right
2663 w = width() - x;
2664 }
2665
2666 if (getRotation() == 0) {
2667 drawFastRawHLine(x, y, w, color);
2668 } else if (getRotation() == 1) {
2669 int16_t t = x;
2670 x = WIDTH - 1 - y;
2671 y = t;
2672 drawFastRawVLine(x, y, w, color);
2673 } else if (getRotation() == 2) {
2674 x = WIDTH - 1 - x;
2675 y = HEIGHT - 1 - y;
2676
2677 x -= w - 1;
2678 drawFastRawHLine(x, y, w, color);
2679 } else if (getRotation() == 3) {
2680 int16_t t = x;
2681 x = y;
2682 y = HEIGHT - 1 - t;
2683 y -= w - 1;
2684 drawFastRawVLine(x, y, w, color);
2685 }
2686}
2687
2688/**************************************************************************/
2696/**************************************************************************/
2697void GFXcanvas16::drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
2698{
2699 // x & y already in raw (rotation 0) coordinates, no need to transform.
2700 uint16_t* buffer_ptr = buffer + y * WIDTH + x;
2701 for (int16_t i = 0; i < h; i++) {
2702 (*buffer_ptr) = color;
2703 buffer_ptr += WIDTH;
2704 }
2705}
2706
2707/**************************************************************************/
2715/**************************************************************************/
2716void GFXcanvas16::drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
2717{
2718 // x & y already in raw (rotation 0) coordinates, no need to transform.
2719 uint32_t buffer_index = y * WIDTH + x;
2720 for (uint32_t i = buffer_index; i < buffer_index + w; i++) {
2721 buffer[i] = color;
2722 }
2723}
#define pgm_read_pointer(addr)
#define pgm_read_byte(addr)
#define _swap_int16_t(a, b)
#define pgm_read_word(addr)
uint8_t * pgm_read_bitmap_ptr(const GFXfont *gfxFont)
GFXglyph * pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c)
#define min(a, b)
Adafruit SSD1306 dependency code.
Adafruit SSD1306 dependency code.
#define PROGMEM
void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t outline, uint16_t fill, uint16_t textcolor, char *label, uint8_t textsize)
Initialize button with our desired color/size/settings.
Adafruit_GFX_Button(void)
Create a simple drawn button UI element.
void initButtonUL(Adafruit_GFX *gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h, uint16_t outline, uint16_t fill, uint16_t textcolor, char *label, uint8_t textsize)
Initialize button with our desired color/size/settings, with upper-left coordinates.
void drawButton(bool inverted=false)
Draw the button on the screen.
bool justReleased()
Query whether the button was released since we last checked state.
bool justPressed()
Query whether the button was pressed since we last checked state.
bool contains(int16_t x, int16_t y)
Helper to let us know if a coordinate is within the bounds of the button.
A generic graphics superclass that can handle all sorts of drawing. At a.
Definition MiniR4_GFX.h:51
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Draw a perfectly vertical line (this is often optimized in a subclass!)
void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color)
Quarter-circle drawer with fill, used for circles and roundrects.
uint16_t textbgcolor
16-bit text color for print()
Definition MiniR4_GFX.h:270
virtual void fillScreen(uint16_t color)
Fill the screen completely with one color. Update in subclasses if desired!
int16_t HEIGHT
This is the 'raw' display height - never changes.
Definition MiniR4_GFX.h:264
int16_t width(void) const
Get width of the display, accounting for current rotation.
Definition MiniR4_GFX.h:223
uint8_t rotation
Display rotation (0 thru 3)
Definition MiniR4_GFX.h:273
void setTextSize(uint8_t s)
Set text 'magnification' size. Each increase in s makes 1 pixel that much bigger.
void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color)
Quarter-circle drawer, used to do circles and roundrects.
virtual void invertDisplay(bool i)
Invert the display (ideally using built-in hardware command)
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
Draw a triangle with no fill color.
int16_t height(void) const
Get height of the display, accounting for current rotation.
Definition MiniR4_GFX.h:231
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
Draw a triangle with color-fill.
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Draw a perfectly horizontal line (this is often optimized in a subclass!)
void setTextColor(uint16_t c)
Set text font color with transparant background.
Definition MiniR4_GFX.h:170
virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
Write a rectangle completely with one color, overwrite in subclasses if startWrite is defined!
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
Draw a circle with filled color.
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
Draw a circle outline.
void charBounds(unsigned char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy)
Helper to determine size of a character with current font/size. Broke this out as it's used by both t...
virtual void setRotation(uint8_t r)
Set rotation setting for display.
Adafruit_GFX(int16_t w, int16_t h)
Instatiate a GFX context for graphics! Can only be done by a superclass.
bool _cp437
If set, use correct CP437 charset (default is off)
Definition MiniR4_GFX.h:275
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color)
Draw a rounded rectangle with fill color.
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)
Draw a PROGMEM-resident 1-bit image at the specified (x,y) position, using the specified foreground c...
virtual void write(uint8_t)
Print one byte/character of data, used to support print()
bool wrap
If set, 'wrap' text at right edge of display.
Definition MiniR4_GFX.h:274
uint16_t textcolor
16-bit background color for print()
Definition MiniR4_GFX.h:269
int16_t cursor_x
x location to start print()ing text
Definition MiniR4_GFX.h:267
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
Helper to determine size of a string with current font/size. Pass string and a cursor position,...
uint8_t textsize_x
Desired magnification in X-axis of text to print()
Definition MiniR4_GFX.h:271
virtual void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
Draw a rectangle with no fill color.
virtual void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
Draw a line.
virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
Fill a rectangle completely with one color. Update in subclasses if desired!
void drawXBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)
Draw PROGMEM-resident XBitMap Files (*.xbm), exported from GIMP. Usage: Export from GIMP to *....
uint8_t textsize_y
Desired magnification in Y-axis of text to print()
Definition MiniR4_GFX.h:272
virtual void startWrite(void)
Start a display-writing routine, overwrite in subclasses.
void setCursor(int16_t x, int16_t y)
Set text cursor location.
Definition MiniR4_GFX.h:156
void setFont(const GFXfont *f=NULL)
Set the font to display when print()ing, either custom or default.
int16_t _width
Display width as modified by current rotation.
Definition MiniR4_GFX.h:265
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color)
Draw a rounded rectangle with no fill color.
virtual void writePixel(int16_t x, int16_t y, uint16_t color)
Write a pixel, overwrite in subclasses if startWrite is defined!
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size)
Draw a single character.
virtual void drawPixel(int16_t x, int16_t y, uint16_t color)=0
Draw to the screen/framebuffer/etc. Must be overridden in subclass.
uint8_t getRotation(void) const
Get rotation setting for display.
Definition MiniR4_GFX.h:239
int16_t _height
Display height as modified by current rotation.
Definition MiniR4_GFX.h:266
virtual void endWrite(void)
End a display-writing routine, overwrite in subclasses if startWrite is defined!
virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Write a perfectly horizontal line, overwrite in subclasses if startWrite is defined!
int16_t WIDTH
This is the 'raw' display width - never changes.
Definition MiniR4_GFX.h:263
virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Write a perfectly vertical line, overwrite in subclasses if startWrite is defined!
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
Write a line. Bresenham's algorithm - thx wikpedia.
int16_t cursor_y
y location to start print()ing text
Definition MiniR4_GFX.h:268
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h)
Draw a PROGMEM-resident 8-bit image (grayscale) at the specified (x,y) pos. Specifically for 8-bit di...
void drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h)
Draw a PROGMEM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) position. For 16-bit display ...
GFXfont * gfxFont
Pointer to special font.
Definition MiniR4_GFX.h:276
GFXcanvas16(uint16_t w, uint16_t h)
Instatiate a GFX 16-bit canvas context for graphics.
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Speed optimized horizontal line drawing into the raw canvas buffer.
uint16_t * buffer
Raster data: no longer private, allow subclass access.
Definition MiniR4_GFX.h:419
~GFXcanvas16(void)
Delete the canvas, free memory.
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Speed optimized vertical line drawing.
void byteSwap(void)
Reverses the "endian-ness" of each 16-bit pixel within the canvas; little-endian to big-endian,...
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Speed optimized vertical line drawing into the raw canvas buffer.
uint16_t getPixel(int16_t x, int16_t y) const
Get the pixel color value at a given coordinate.
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Speed optimized horizontal line drawing.
void drawPixel(int16_t x, int16_t y, uint16_t color)
Draw a pixel to the canvas framebuffer.
void fillScreen(uint16_t color)
Fill the framebuffer completely with one color.
uint16_t getRawPixel(int16_t x, int16_t y) const
Get the pixel color value at a given, unrotated coordinate. This method is intended for hardware driv...
void drawPixel(int16_t x, int16_t y, uint16_t color)
Draw a pixel to the canvas framebuffer.
GFXcanvas1(uint16_t w, uint16_t h)
Instatiate a GFX 1-bit canvas context for graphics.
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Speed optimized vertical line drawing.
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Speed optimized vertical line drawing into the raw canvas buffer.
bool getRawPixel(int16_t x, int16_t y) const
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Speed optimized horizontal line drawing into the raw canvas buffer.
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Speed optimized horizontal line drawing.
~GFXcanvas1(void)
Delete the canvas, free memory.
bool getPixel(int16_t x, int16_t y) const
void fillScreen(uint16_t color)
Fill the framebuffer completely with one color.
uint8_t * buffer
Raster data: no longer private, allow subclass access.
Definition MiniR4_GFX.h:360
~GFXcanvas8(void)
Delete the canvas, free memory.
uint8_t getRawPixel(int16_t x, int16_t y) const
Get the pixel color value at a given, unrotated coordinate. This method is intended for hardware driv...
GFXcanvas8(uint16_t w, uint16_t h)
Instatiate a GFX 8-bit canvas context for graphics.
void drawPixel(int16_t x, int16_t y, uint16_t color)
Draw a pixel to the canvas framebuffer.
uint8_t getPixel(int16_t x, int16_t y) const
Get the pixel color value at a given coordinate.
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Speed optimized horizontal line drawing into the raw canvas buffer.
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Speed optimized vertical line drawing.
void fillScreen(uint16_t color)
Fill the framebuffer completely with one color.
uint8_t * buffer
Raster data: no longer private, allow subclass access.
Definition MiniR4_GFX.h:392
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Speed optimized vertical line drawing into the raw canvas buffer.
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Speed optimized horizontal line drawing.
Data stored for FONT AS A WHOLE.
uint16_t first
ASCII extents (first char)
uint8_t * bitmap
Glyph bitmaps, concatenated.
uint16_t last
ASCII extents (last char)
uint8_t yAdvance
Newline distance (y axis)
GFXglyph * glyph
Glyph array.
Font data stored PER GLYPH.
uint8_t width
Bitmap dimensions in pixels.
uint8_t height
Bitmap dimensions in pixels.
uint16_t bitmapOffset
Pointer into GFXfont->bitmap.
int8_t yOffset
Y dist from cursor pos to UL corner.
uint8_t xAdvance
Distance to advance cursor (x axis)
int8_t xOffset
X dist from cursor pos to UL corner.