add partial window support

This commit is contained in:
Shuanglei Tao
2025-06-24 21:40:37 +08:00
parent 988043e73e
commit f9b6f2753d
2 changed files with 79 additions and 20 deletions

View File

@@ -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

View File

@@ -25,11 +25,11 @@ 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
@@ -38,9 +38,10 @@ typedef struct {
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;
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);