Skip to content

Commit 31be45d

Browse files
committed
GFXcanvas: Allow subclass to take charge of buffer allocations
In Adafruit_dvhstx, the low level driver takes charge of the framebuffer allocations. Consequently, any allocation by the GFXcanvas class would be an unused waste of memory. Introduce a new constructor parameter `bool allocate_buffer=true`. The default preserves the old behavior of allocating the buffer in the constructor and freeing it in the destructor, while passing in `false` skips buffer allocation & freeing. In this case, the subclass must allocate the buffer before the first drawing operation (such as in its constructor or begin method), and free it in its own destructor or end method. The subclass can also freely change the buffer pointer at runtime, for instance in a swap method if the underlying framebuffer is double-buffered.
1 parent d472098 commit 31be45d

File tree

2 files changed

+60
-28
lines changed

2 files changed

+60
-28
lines changed

Adafruit_GFX.cpp

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,12 +1758,21 @@ const uint8_t PROGMEM GFXcanvas1::GFXclrBit[] = {0x7F, 0xBF, 0xDF, 0xEF,
17581758
@brief Instatiate a GFX 1-bit canvas context for graphics
17591759
@param w Display width, in pixels
17601760
@param h Display height, in pixels
1761-
*/
1762-
/**************************************************************************/
1763-
GFXcanvas1::GFXcanvas1(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) {
1764-
uint32_t bytes = ((w + 7) / 8) * h;
1765-
if ((buffer = (uint8_t *)malloc(bytes))) {
1766-
memset(buffer, 0, bytes);
1761+
@param allocate_buffer If true, a buffer is allocated with malloc. If
1762+
false, the subclass must initialize the buffer before any drawing operation,
1763+
and free it in the destructor. If false (the default), the buffer is
1764+
allocated and freed by the library.
1765+
*/
1766+
/**************************************************************************/
1767+
GFXcanvas1::GFXcanvas1(uint16_t w, uint16_t h, bool allocate_buffer)
1768+
: Adafruit_GFX(w, h), buffer_owned(allocate_buffer) {
1769+
if (allocate_buffer) {
1770+
uint32_t bytes = ((w + 7) / 8) * h;
1771+
if ((buffer = (uint8_t *)malloc(bytes))) {
1772+
memset(buffer, 0, bytes);
1773+
}
1774+
} else {
1775+
buffer = nullptr;
17671776
}
17681777
}
17691778

@@ -1773,7 +1782,7 @@ GFXcanvas1::GFXcanvas1(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) {
17731782
*/
17741783
/**************************************************************************/
17751784
GFXcanvas1::~GFXcanvas1(void) {
1776-
if (buffer)
1785+
if (buffer && buffer_owned)
17771786
free(buffer);
17781787
}
17791788

@@ -2111,13 +2120,21 @@ void GFXcanvas1::drawFastRawHLine(int16_t x, int16_t y, int16_t w,
21112120
@brief Instatiate a GFX 8-bit canvas context for graphics
21122121
@param w Display width, in pixels
21132122
@param h Display height, in pixels
2114-
*/
2115-
/**************************************************************************/
2116-
GFXcanvas8::GFXcanvas8(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) {
2117-
uint32_t bytes = w * h;
2118-
if ((buffer = (uint8_t *)malloc(bytes))) {
2119-
memset(buffer, 0, bytes);
2120-
}
2123+
@param allocate_buffer If true, a buffer is allocated with malloc. If
2124+
false, the subclass must initialize the buffer before any drawing operation,
2125+
and free it in the destructor. If false (the default), the buffer is
2126+
allocated and freed by the library.
2127+
*/
2128+
/**************************************************************************/
2129+
GFXcanvas8::GFXcanvas8(uint16_t w, uint16_t h, bool allocate_buffer)
2130+
: Adafruit_GFX(w, h), buffer_owned(allocate_buffer) {
2131+
if (allocate_buffer) {
2132+
uint32_t bytes = w * h;
2133+
if ((buffer = (uint8_t *)malloc(bytes))) {
2134+
memset(buffer, 0, bytes);
2135+
}
2136+
} else
2137+
buffer = nullptr;
21212138
}
21222139

21232140
/**************************************************************************/
@@ -2126,7 +2143,7 @@ GFXcanvas8::GFXcanvas8(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) {
21262143
*/
21272144
/**************************************************************************/
21282145
GFXcanvas8::~GFXcanvas8(void) {
2129-
if (buffer)
2146+
if (buffer && buffer_owned)
21302147
free(buffer);
21312148
}
21322149

@@ -2379,12 +2396,21 @@ void GFXcanvas8::drawFastRawHLine(int16_t x, int16_t y, int16_t w,
23792396
@brief Instatiate a GFX 16-bit canvas context for graphics
23802397
@param w Display width, in pixels
23812398
@param h Display height, in pixels
2382-
*/
2383-
/**************************************************************************/
2384-
GFXcanvas16::GFXcanvas16(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) {
2385-
uint32_t bytes = w * h * 2;
2386-
if ((buffer = (uint16_t *)malloc(bytes))) {
2387-
memset(buffer, 0, bytes);
2399+
@param allocate_buffer If true, a buffer is allocated with malloc. If
2400+
false, the subclass must initialize the buffer before any drawing operation,
2401+
and free it in the destructor. If false (the default), the buffer is
2402+
allocated and freed by the library.
2403+
*/
2404+
/**************************************************************************/
2405+
GFXcanvas16::GFXcanvas16(uint16_t w, uint16_t h, bool allocate_buffer)
2406+
: Adafruit_GFX(w, h), buffer_owned(allocate_buffer) {
2407+
if (allocate_buffer) {
2408+
uint32_t bytes = w * h * 2;
2409+
if ((buffer = (uint16_t *)malloc(bytes))) {
2410+
memset(buffer, 0, bytes);
2411+
}
2412+
} else {
2413+
buffer = nullptr;
23882414
}
23892415
}
23902416

@@ -2394,7 +2420,7 @@ GFXcanvas16::GFXcanvas16(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) {
23942420
*/
23952421
/**************************************************************************/
23962422
GFXcanvas16::~GFXcanvas16(void) {
2397-
if (buffer)
2423+
if (buffer && buffer_owned)
23982424
free(buffer);
23992425
}
24002426

Adafruit_GFX.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ class Adafruit_GFX_Button {
309309
/// A GFX 1-bit canvas context for graphics
310310
class GFXcanvas1 : public Adafruit_GFX {
311311
public:
312-
GFXcanvas1(uint16_t w, uint16_t h);
312+
GFXcanvas1(uint16_t w, uint16_t h, bool allocate_buffer = true);
313313
~GFXcanvas1(void);
314314
void drawPixel(int16_t x, int16_t y, uint16_t color);
315315
void fillScreen(uint16_t color);
@@ -328,7 +328,9 @@ class GFXcanvas1 : public Adafruit_GFX {
328328
bool getRawPixel(int16_t x, int16_t y) const;
329329
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
330330
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
331-
uint8_t *buffer; ///< Raster data: no longer private, allow subclass access
331+
uint8_t *buffer; ///< Raster data: no longer private, allow subclass access
332+
bool buffer_owned; ///< If true, destructor will free buffer, else it will do
333+
///< nothing
332334

333335
private:
334336
#ifdef __AVR__
@@ -340,7 +342,7 @@ class GFXcanvas1 : public Adafruit_GFX {
340342
/// A GFX 8-bit canvas context for graphics
341343
class GFXcanvas8 : public Adafruit_GFX {
342344
public:
343-
GFXcanvas8(uint16_t w, uint16_t h);
345+
GFXcanvas8(uint16_t w, uint16_t h, bool allocate_buffer = true);
344346
~GFXcanvas8(void);
345347
void drawPixel(int16_t x, int16_t y, uint16_t color);
346348
void fillScreen(uint16_t color);
@@ -359,13 +361,15 @@ class GFXcanvas8 : public Adafruit_GFX {
359361
uint8_t getRawPixel(int16_t x, int16_t y) const;
360362
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
361363
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
362-
uint8_t *buffer; ///< Raster data: no longer private, allow subclass access
364+
uint8_t *buffer; ///< Raster data: no longer private, allow subclass access
365+
bool buffer_owned; ///< If true, destructor will free buffer, else it will do
366+
///< nothing
363367
};
364368

365369
/// A GFX 16-bit canvas context for graphics
366370
class GFXcanvas16 : public Adafruit_GFX {
367371
public:
368-
GFXcanvas16(uint16_t w, uint16_t h);
372+
GFXcanvas16(uint16_t w, uint16_t h, bool allocate_buffer = true);
369373
~GFXcanvas16(void);
370374
void drawPixel(int16_t x, int16_t y, uint16_t color);
371375
void fillScreen(uint16_t color);
@@ -385,7 +389,9 @@ class GFXcanvas16 : public Adafruit_GFX {
385389
uint16_t getRawPixel(int16_t x, int16_t y) const;
386390
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
387391
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
388-
uint16_t *buffer; ///< Raster data: no longer private, allow subclass access
392+
uint16_t *buffer; ///< Raster data: no longer private, allow subclass access
393+
bool buffer_owned; ///< If true, destructor will free buffer, else it will do
394+
///< nothing
389395
};
390396

391397
#endif // _ADAFRUIT_GFX_H

0 commit comments

Comments
 (0)