diff --git a/GUI/Adafruit_GFX.c b/GUI/Adafruit_GFX.c index f4a7157..468c334 100644 --- a/GUI/Adafruit_GFX.c +++ b/GUI/Adafruit_GFX.c @@ -88,6 +88,7 @@ void GFX_begin(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height) { gfx->buffer = malloc(((gfx->WIDTH + 7) / 8) * buffer_height); gfx->page_height = buffer_height; gfx->total_pages = (gfx->HEIGHT / gfx->page_height) + (gfx->HEIGHT % gfx->page_height > 0); + GFX_setWindow(gfx, 0, 0, gfx->WIDTH, gfx->HEIGHT); } /**************************************************************************/ @@ -130,10 +131,19 @@ void GFX_firstPage(Adafruit_GFX *gfx) { } bool GFX_nextPage(Adafruit_GFX *gfx, buffer_callback callback) { - int16_t page_y = gfx->current_page * gfx->page_height; - int16_t height = MIN(gfx->page_height, gfx->HEIGHT - page_y); - if (callback) - callback(gfx->buffer, gfx->color, 0, page_y, gfx->WIDTH, height); + if (callback) { + int16_t page_ys = gfx->current_page * gfx->page_height; + if (gfx->px != 0 || gfx->py != 0 || gfx->pw != gfx->_width || gfx->ph != gfx->_height) { + int16_t page_ye = gfx->current_page < gfx->total_pages - 1 ? page_ys + gfx->page_height : gfx->HEIGHT; + uint16_t dest_ys = gfx->py + page_ys; // transposed + uint16_t dest_ye = MIN(gfx->py + gfx->ph, gfx->py + page_ye); + if (dest_ye > dest_ys) + callback(gfx->buffer, gfx->color, gfx->px, dest_ys, gfx->pw, dest_ye - dest_ys); + } else { + int16_t height = MIN(gfx->page_height, gfx->HEIGHT - page_ys); + callback(gfx->buffer, gfx->color, 0, page_ys, gfx->WIDTH, height); + } + } gfx->current_page++; GFX_fillScreen(gfx, GFX_WHITE); @@ -163,6 +173,46 @@ void GFX_setRotation(Adafruit_GFX *gfx, GFX_Rotate r) { } } +/**************************************************************************/ +/*! + setWindow, use parameters according to actual rotation. + x and w should be multiple of 8, for rotation 0 or 2, + y and h should be multiple of 8, for rotation 1 or 3, + else window is increased as needed, + this is an addressing limitation of the e-paper controllers +*/ +/**************************************************************************/ +void GFX_setWindow(Adafruit_GFX *gfx, uint16_t x, uint16_t y, uint16_t w, uint16_t h) +{ + gfx->px = MIN(x, gfx->_width); + gfx->py = MIN(y, gfx->_height); + gfx->pw = MIN(w, gfx->_width - gfx->px); + gfx->ph = MIN(h, gfx->_height - gfx->py); + + switch(gfx->rotation) { + case GFX_ROTATE_0: + break; + case GFX_ROTATE_90: + SWAP(gfx->px, gfx->py, uint16_t); + SWAP(gfx->pw, gfx->ph, uint16_t); + gfx->px = gfx->WIDTH - gfx->px - gfx->pw; + break; + case GFX_ROTATE_180: + gfx->px = gfx->WIDTH - gfx->px - gfx->pw; + gfx->py = gfx->HEIGHT - gfx->py - gfx->ph; + break; + case GFX_ROTATE_270: + SWAP(gfx->px, gfx->py, uint16_t); + SWAP(gfx->pw, gfx->ph, uint16_t); + gfx->py = gfx->HEIGHT - gfx->py - gfx->ph; + break; + } + + gfx->pw += gfx->px % 8; + if (gfx->pw % 8 > 0) gfx->pw += 8 - (gfx->pw % 8); + gfx->px -= gfx->px % 8; +} + static uint8_t color4(uint16_t color) { static uint16_t _prev_color = GFX_BLACK; static uint8_t _prev_color4 = 0x00; // black @@ -224,11 +274,18 @@ void GFX_drawPixel(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t color) { break; } + // transpose partial window to 0,0 + x -= gfx->px; + y -= gfx->py; + // clip to (partial) window + if (x < 0 || x >= gfx->pw || y < 0 || y >= gfx->ph) return; + // adjust for current page y -= gfx->current_page * gfx->page_height; + // check if in current page if (y < 0 || y >= gfx->page_height) return; if (gfx->color == gfx->buffer) { // 4c - uint32_t i = x / 4 + ((uint32_t)y) * (gfx->WIDTH / 4); + uint32_t i = x / 4 + ((uint32_t)y) * (gfx->pw / 4); uint8_t pv = color4(color); switch(x % 4) { case 0: gfx->buffer[i] = (gfx->buffer[i] & 0x3F) | (pv << 6); break; @@ -237,7 +294,7 @@ void GFX_drawPixel(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t color) { case 3: gfx->buffer[i] = (gfx->buffer[i] & 0xFC) | pv; break; } } else if (gfx->color != NULL) { // 3c - uint16_t i = x / 8 + y * (gfx->WIDTH / 8); + uint16_t i = x / 8 + y * (gfx->pw / 8); gfx->buffer[i] |= 0x80 >> (x & 7); // white gfx->color[i] |= 0x80 >> (x & 7); if (color == GFX_BLACK) @@ -245,7 +302,7 @@ void GFX_drawPixel(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t color) { else if (color != GFX_WHITE) gfx->color[i] &= ~(0x80 >> (x & 7)); } else { - uint16_t i = x / 8 + y * (gfx->WIDTH / 8); + uint16_t i = x / 8 + y * (gfx->pw / 8); if (color == GFX_WHITE) gfx->buffer[i] |= 0x80 >> (x & 7); else diff --git a/GUI/Adafruit_GFX.h b/GUI/Adafruit_GFX.h index 848c03c..c09e5b1 100644 --- a/GUI/Adafruit_GFX.h +++ b/GUI/Adafruit_GFX.h @@ -25,22 +25,23 @@ typedef enum { // GRAPHICS CONTEXT typedef struct { - int16_t WIDTH; ///< This is the 'raw' display width - never changes - int16_t HEIGHT; ///< This is the 'raw' display height - never changes - int16_t _width; ///< Display width as modified by current rotation - int16_t _height; ///< Display height as modified by current rotation - GFX_Rotate rotation; ///< Display rotation (0 thru 3) + int16_t WIDTH; // This is the 'raw' display width - never changes + int16_t HEIGHT; // This is the 'raw' display height - never changes + int16_t _width; // Display width as modified by current rotation + int16_t _height; // Display height as modified by current rotation + GFX_Rotate rotation; // Display rotation (0 thru 3) u8g2_font_t u8g2; - int16_t tx, ty; // current position for the print command - uint16_t encoding; // the unicode, detected by the utf-8 decoder - uint8_t utf8_state; // current state of the utf-8 decoder, contains the remaining bytes for a detected unicode glyph + int16_t tx, ty; // current position for the print command + uint16_t encoding; // the unicode, detected by the utf-8 decoder + uint8_t utf8_state; // current state of the utf-8 decoder, contains the remaining bytes for a detected unicode glyph - uint8_t *buffer; // black pixel buffer - uint8_t *color; // color pixel buffer (3c only) - int16_t page_height; - int16_t current_page; - int16_t total_pages; + uint8_t *buffer; // black pixel buffer + uint8_t *color; // color pixel buffer (3c only) + uint16_t px, py, pw, ph; // partial window offset and size + int16_t page_height; // height to be drawn in one page + int16_t current_page; // index of the current drawing page + int16_t total_pages; // total number of pages to be drawn } Adafruit_GFX; // CONTROL API @@ -48,6 +49,7 @@ void GFX_begin(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height); void GFX_begin_3c(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height); void GFX_begin_4c(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height); void GFX_setRotation(Adafruit_GFX *gfx, GFX_Rotate r); +void GFX_setWindow(Adafruit_GFX *gfx, uint16_t x, uint16_t y, uint16_t w, uint16_t h); void GFX_firstPage(Adafruit_GFX *gfx); bool GFX_nextPage(Adafruit_GFX *gfx, buffer_callback callback); void GFX_end(Adafruit_GFX *gfx);