@@ -46,6 +46,11 @@ POSSIBILITY OF SUCH DAMAGE.
4646#define min (a,b ) (((a) < (b)) ? (a) : (b))
4747#endif
4848
49+ // Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR
50+ static const uint8_t PROGMEM
51+ GFXsetBit[] = { 0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 },
52+ GFXclrBit[] = { 0x7F , 0xBF , 0xDF , 0xEF , 0xF7 , 0xFB , 0xFD , 0xFE };
53+
4954Adafruit_GFX::Adafruit_GFX (int16_t w, int16_t h):
5055 WIDTH(w), HEIGHT(h)
5156{
@@ -354,64 +359,82 @@ void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0,
354359 }
355360}
356361
362+ // Draw a 1-bit image (bitmap) at the specified (x,y) position from the
363+ // provided bitmap buffer (must be PROGMEM memory) using the specified
364+ // foreground color (unset bits are transparent).
357365void Adafruit_GFX::drawBitmap (int16_t x, int16_t y,
358366 const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) {
359367
360368 int16_t i, j, byteWidth = (w + 7 ) / 8 ;
369+ uint8_t bitnum, byte;
361370
362371 for (j=0 ; j<h; j++) {
363- for (i=0 ; i<w; i++ ) {
364- if (pgm_read_byte (bitmap + j * byteWidth + i / 8 ) & (128 >> (i & 7 ))) {
372+ for (i=0 ; i<w; i++) {
373+ bitnum = i & 7 ;
374+ if (!bitnum) byte = pgm_read_byte (bitmap + j * byteWidth + i / 8 );
375+ if (byte & pgm_read_byte (&GFXsetBit[bitnum])) {
365376 drawPixel (x+i, y+j, color);
366377 }
367378 }
368379 }
369380}
370381
371- // Draw a 1-bit color bitmap at the specified x, y position from the
372- // provided bitmap buffer (must be PROGMEM memory) using color as the
373- // foreground color and bg as the background color .
382+ // Draw a 1-bit image ( bitmap) at the specified (x,y) position from the
383+ // provided bitmap buffer (must be PROGMEM memory) using the specified
384+ // foreground (for set bits) and background (for clear bits) colors .
374385void Adafruit_GFX::drawBitmap (int16_t x, int16_t y,
375386 const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) {
376387
377388 int16_t i, j, byteWidth = (w + 7 ) / 8 ;
389+ uint8_t bitnum, byte;
378390
379391 for (j=0 ; j<h; j++) {
380392 for (i=0 ; i<w; i++ ) {
381- if (pgm_read_byte (bitmap + j * byteWidth + i / 8 ) & (128 >> (i & 7 ))) {
393+ bitnum = i & 7 ;
394+ if (!bitnum) byte = pgm_read_byte (bitmap + j * byteWidth + i / 8 );
395+ if (byte & pgm_read_byte (&GFXsetBit[bitnum])) {
382396 drawPixel (x+i, y+j, color);
383- }
384- else {
397+ } else {
385398 drawPixel (x+i, y+j, bg);
386399 }
387400 }
388401 }
389402}
390403
404+ // drawBitmap() variant for RAM-resident (not PROGMEM) bitmaps.
391405void Adafruit_GFX::drawBitmap (int16_t x, int16_t y,
392406 uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) {
393407
394408 int16_t i, j, byteWidth = (w + 7 ) / 8 ;
409+ uint8_t bitnum, byte;
395410
396411 for (j=0 ; j<h; j++) {
397412 for (i=0 ; i<w; i++ ) {
398- if (bitRead (bitmap[j], 7 -i)) drawPixel (x+i, y+j, color);
413+ bitnum = i & 7 ;
414+ if (!bitnum) byte = bitmap[j * byteWidth + i / 8 ];
415+ if (byte & pgm_read_byte (&GFXsetBit[bitnum])) {
416+ drawPixel (x+i, y+j, color);
417+ }
399418 }
400419 }
401420}
402421
403- // Draw a 1-bit color bitmap at the specified x, y position from the
404- // provided bitmap buffer (NOT PROGMEM memory nor a const) using color
405- // as the foreground color and bg as the background color.
422+ // drawBitmap() variant w/background for RAM-resident (not PROGMEM) bitmaps.
406423void Adafruit_GFX::drawBitmap (int16_t x, int16_t y,
407424 uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) {
408425
409426 int16_t i, j, byteWidth = (w + 7 ) / 8 ;
427+ uint8_t bitnum, byte;
410428
411429 for (j=0 ; j<h; j++) {
412430 for (i=0 ; i<w; i++ ) {
413- if (bitRead (bitmap[j], 7 -i)) drawPixel (x+i, y+j, color);
414- else drawPixel (x+i, y+j, bg);
431+ bitnum = i & 7 ;
432+ if (!bitnum) byte = bitmap[j * byteWidth + i / 8 ];
433+ if (byte & pgm_read_byte (&GFXsetBit[bitnum])) {
434+ drawPixel (x+i, y+j, color);
435+ } else {
436+ drawPixel (x+i, y+j, bg);
437+ }
415438 }
416439 }
417440}
@@ -423,10 +446,13 @@ void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y,
423446 const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) {
424447
425448 int16_t i, j, byteWidth = (w + 7 ) / 8 ;
449+ uint8_t bitnum, byte;
426450
427451 for (j=0 ; j<h; j++) {
428452 for (i=0 ; i<w; i++ ) {
429- if (pgm_read_byte (bitmap + j * byteWidth + i / 8 ) & (1 << (i % 8 ))) {
453+ bitnum = i & 7 ;
454+ if (!bitnum) byte = pgm_read_byte (bitmap + j * byteWidth + i / 8 );
455+ if (byte & pgm_read_byte (&GFXsetBit[7 -bitnum])) {
430456 drawPixel (x+i, y+j, color);
431457 }
432458 }
@@ -909,3 +935,124 @@ void Adafruit_GFX_Button::press(boolean p) {
909935boolean Adafruit_GFX_Button::isPressed () { return currstate; }
910936boolean Adafruit_GFX_Button::justPressed () { return (currstate && !laststate); }
911937boolean Adafruit_GFX_Button::justReleased () { return (!currstate && laststate); }
938+
939+ // -------------------------------------------------------------------------
940+
941+ // GFXcanvas1 and GFXcanvas16 (currently a WIP, don't get too comfy with the
942+ // implementation) provide 1- and 16-bit offscreen canvases, the address of
943+ // which can be passed to drawBitmap() or pushColors() (the latter appears
944+ // to only be in Adafruit_TFTLCD at this time). This is here mostly to
945+ // help with the recently-added proportionally-spaced fonts; adds a way to
946+ // refresh a section of the screen without a massive flickering clear-and-
947+ // redraw...but maybe you'll find other uses too. VERY RAM-intensive, since
948+ // the buffer is in MCU memory and not the display driver...GXFcanvas1 might
949+ // be minimally useful on an Uno-class board, but this and GFXcanvas16 are
950+ // much more likely to require at least a Mega or various recent ARM-type
951+ // boards (recomment, as the text+bitmap draw can be pokey). GFXcanvas1
952+ // requires 1 bit per pixel (rounded up to nearest byte per scanline),
953+ // GFXcanvas16 requires 2 bytes per pixel (no scanline pad).
954+ // NOT EXTENSIVELY TESTED YET. MAY CONTAIN WORST BUGS KNOWN TO HUMANKIND.
955+
956+ GFXcanvas1::GFXcanvas1 (uint16_t w, uint16_t h) : Adafruit_GFX (w, h) {
957+ uint16_t bytes = ((w + 7 ) / 8 ) * h;
958+ if ((buffer = (uint8_t *)malloc (bytes))) {
959+ memset (buffer, 0 , bytes);
960+ }
961+ }
962+
963+ GFXcanvas1::~GFXcanvas1 (void ) {
964+ if (buffer) free (buffer);
965+ }
966+
967+ uint8_t * GFXcanvas1::getBuffer (void ) {
968+ return buffer;
969+ }
970+
971+ void GFXcanvas1::drawPixel (int16_t x, int16_t y, uint16_t color) {
972+ if (buffer) {
973+ if ((x < 0 ) || (y < 0 ) || (x >= _width) || (y >= _height)) return ;
974+
975+ int16_t t;
976+ switch (rotation) {
977+ case 1 :
978+ t = x;
979+ x = WIDTH - 1 - y;
980+ y = t;
981+ break ;
982+ case 2 :
983+ x = WIDTH - 1 - x;
984+ y = HEIGHT - 1 - y;
985+ break ;
986+ case 3 :
987+ t = x;
988+ x = y;
989+ y = HEIGHT - 1 - t;
990+ break ;
991+ }
992+
993+ uint8_t *ptr = &buffer[(x / 8 ) + y * ((WIDTH + 7 ) / 8 )];
994+ if (color) *ptr |= pgm_read_byte (&GFXsetBit[x & 7 ]);
995+ else *ptr &= pgm_read_byte (&GFXclrBit[x & 7 ]);
996+ }
997+ }
998+
999+ void GFXcanvas1::fillScreen (uint16_t color) {
1000+ if (buffer) {
1001+ uint16_t bytes = ((WIDTH + 7 ) / 8 ) * HEIGHT;
1002+ memset (buffer, color ? 0xFF : 0x00 , bytes);
1003+ }
1004+ }
1005+
1006+ GFXcanvas16::GFXcanvas16 (uint16_t w, uint16_t h) : Adafruit_GFX (w, h) {
1007+ uint16_t bytes = w * h * 2 ;
1008+ if ((buffer = (uint16_t *)malloc (bytes))) {
1009+ memset (buffer, 0 , bytes);
1010+ }
1011+ }
1012+
1013+ GFXcanvas16::~GFXcanvas16 (void ) {
1014+ if (buffer) free (buffer);
1015+ }
1016+
1017+ uint16_t * GFXcanvas16::getBuffer (void ) {
1018+ return buffer;
1019+ }
1020+
1021+ void GFXcanvas16::drawPixel (int16_t x, int16_t y, uint16_t color) {
1022+ if (buffer) {
1023+ if ((x < 0 ) || (y < 0 ) || (x >= _width) || (y >= _height)) return ;
1024+
1025+ int16_t t;
1026+ switch (rotation) {
1027+ case 1 :
1028+ t = x;
1029+ x = WIDTH - 1 - y;
1030+ y = t;
1031+ break ;
1032+ case 2 :
1033+ x = WIDTH - 1 - x;
1034+ y = HEIGHT - 1 - y;
1035+ break ;
1036+ case 3 :
1037+ t = x;
1038+ x = y;
1039+ y = HEIGHT - 1 - t;
1040+ break ;
1041+ }
1042+
1043+ buffer[x + y * WIDTH] = color;
1044+ }
1045+ }
1046+
1047+ void GFXcanvas16::fillScreen (uint16_t color) {
1048+ if (buffer) {
1049+ uint8_t hi = color >> 8 , lo = color & 0xFF ;
1050+ if (hi == lo) {
1051+ memset (buffer, lo, WIDTH * HEIGHT * 2 );
1052+ } else {
1053+ uint16_t i, pixels = WIDTH * HEIGHT;
1054+ for (i=0 ; i<pixels; i++) buffer[i] = color;
1055+ }
1056+ }
1057+ }
1058+
0 commit comments