From 9cb1ec440168d508ec520e8c028876e444244f3c Mon Sep 17 00:00:00 2001 From: Phillip Burgess Date: Mon, 28 Dec 2015 10:58:40 -0800 Subject: [PATCH] Bitmap fixes, initial canvas support --- Adafruit_GFX.cpp | 177 +++++++++++++++++++++++++++++++++++++++++---- Adafruit_GFX.h | 22 ++++++ library.properties | 2 +- 3 files changed, 185 insertions(+), 16 deletions(-) diff --git a/Adafruit_GFX.cpp b/Adafruit_GFX.cpp index 3a45ab4..e851513 100644 --- a/Adafruit_GFX.cpp +++ b/Adafruit_GFX.cpp @@ -46,6 +46,11 @@ POSSIBILITY OF SUCH DAMAGE. #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif +// Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR +static const uint8_t PROGMEM + GFXsetBit[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, + GFXclrBit[] = { 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE }; + Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h): WIDTH(w), HEIGHT(h) { @@ -354,64 +359,82 @@ void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0, } } +// Draw a 1-bit image (bitmap) at the specified (x,y) position from the +// provided bitmap buffer (must be PROGMEM memory) using the specified +// foreground color (unset bits are transparent). void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { int16_t i, j, byteWidth = (w + 7) / 8; + uint8_t bitnum, byte; for(j=0; j> (i & 7))) { + for(i=0; i> (i & 7))) { + bitnum = i & 7; + if(!bitnum) byte = pgm_read_byte(bitmap + j * byteWidth + i / 8); + if(byte & pgm_read_byte(&GFXsetBit[bitnum])) { drawPixel(x+i, y+j, color); - } - else { + } else { drawPixel(x+i, y+j, bg); } } } } +// drawBitmap() variant for RAM-resident (not PROGMEM) bitmaps. void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { int16_t i, j, byteWidth = (w + 7) / 8; + uint8_t bitnum, byte; for(j=0; j= _width) || (y >= _height)) return; + + int16_t t; + switch(rotation) { + case 1: + t = x; + x = WIDTH - 1 - y; + y = t; + break; + case 2: + x = WIDTH - 1 - x; + y = HEIGHT - 1 - y; + break; + case 3: + t = x; + x = y; + y = HEIGHT - 1 - t; + break; + } + + uint8_t *ptr = &buffer[(x / 8) + y * ((WIDTH + 7) / 8)]; + if(color) *ptr |= pgm_read_byte(&GFXsetBit[x & 7]); + else *ptr &= pgm_read_byte(&GFXclrBit[x & 7]); + } +} + +void GFXcanvas1::fillScreen(uint16_t color) { + if(buffer) { + uint16_t bytes = ((WIDTH + 7) / 8) * HEIGHT; + memset(buffer, color ? 0xFF : 0x00, bytes); + } +} + +GFXcanvas16::GFXcanvas16(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { + uint16_t bytes = w * h * 2; + if((buffer = (uint16_t *)malloc(bytes))) { + memset(buffer, 0, bytes); + } +} + +GFXcanvas16::~GFXcanvas16(void) { + if(buffer) free(buffer); +} + +uint16_t* GFXcanvas16::getBuffer(void) { + return buffer; +} + +void GFXcanvas16::drawPixel(int16_t x, int16_t y, uint16_t color) { + if(buffer) { + if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return; + + int16_t t; + switch(rotation) { + case 1: + t = x; + x = WIDTH - 1 - y; + y = t; + break; + case 2: + x = WIDTH - 1 - x; + y = HEIGHT - 1 - y; + break; + case 3: + t = x; + x = y; + y = HEIGHT - 1 - t; + break; + } + + buffer[x + y * WIDTH] = color; + } +} + +void GFXcanvas16::fillScreen(uint16_t color) { + if(buffer) { + uint8_t hi = color >> 8, lo = color & 0xFF; + if(hi == lo) { + memset(buffer, lo, WIDTH * HEIGHT * 2); + } else { + uint16_t i, pixels = WIDTH * HEIGHT; + for(i=0; i sentence=Adafruit GFX graphics core library, this is the 'core' class that all our other graphics libraries derive from.