mirror of
https://github.com/adafruit/Adafruit-GFX-Library.git
synced 2024-10-03 18:18:46 -04:00
Implement transaction based drawing
With using transactions to draw, we save huge amount of time in pin changing and SPI setup. This new model, together with the updated ILI9341 lib give a much better performance.
This commit is contained in:
parent
dc40877a22
commit
4290f0b161
570
Adafruit_GFX.cpp
570
Adafruit_GFX.cpp
@ -29,15 +29,15 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <pgmspace.h>
|
||||
#endif
|
||||
#include "Adafruit_GFX.h"
|
||||
#include "glcdfont.c"
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
#include <pgmspace.h>
|
||||
#endif
|
||||
|
||||
// Many (but maybe not all) non-AVR board installs define macros
|
||||
// for compatibility with existing PROGMEM-reading AVR code.
|
||||
@ -71,7 +71,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#endif
|
||||
|
||||
Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h):
|
||||
WIDTH(w), HEIGHT(h)
|
||||
WIDTH(w), HEIGHT(h)
|
||||
{
|
||||
_width = WIDTH;
|
||||
_height = HEIGHT;
|
||||
@ -84,116 +84,8 @@ Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h):
|
||||
gfxFont = NULL;
|
||||
}
|
||||
|
||||
// Draw a circle outline
|
||||
void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
|
||||
uint16_t color) {
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
drawPixel(x0 , y0+r, color);
|
||||
drawPixel(x0 , y0-r, color);
|
||||
drawPixel(x0+r, y0 , color);
|
||||
drawPixel(x0-r, y0 , color);
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
drawPixel(x0 + x, y0 + y, color);
|
||||
drawPixel(x0 - x, y0 + y, color);
|
||||
drawPixel(x0 + x, y0 - y, color);
|
||||
drawPixel(x0 - x, y0 - y, color);
|
||||
drawPixel(x0 + y, y0 + x, color);
|
||||
drawPixel(x0 - y, y0 + x, color);
|
||||
drawPixel(x0 + y, y0 - x, color);
|
||||
drawPixel(x0 - y, y0 - x, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0,
|
||||
int16_t r, uint8_t cornername, uint16_t color) {
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
if (cornername & 0x4) {
|
||||
drawPixel(x0 + x, y0 + y, color);
|
||||
drawPixel(x0 + y, y0 + x, color);
|
||||
}
|
||||
if (cornername & 0x2) {
|
||||
drawPixel(x0 + x, y0 - y, color);
|
||||
drawPixel(x0 + y, y0 - x, color);
|
||||
}
|
||||
if (cornername & 0x8) {
|
||||
drawPixel(x0 - y, y0 + x, color);
|
||||
drawPixel(x0 - x, y0 + y, color);
|
||||
}
|
||||
if (cornername & 0x1) {
|
||||
drawPixel(x0 - y, y0 - x, color);
|
||||
drawPixel(x0 - x, y0 - y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
|
||||
uint16_t color) {
|
||||
drawFastVLine(x0, y0-r, 2*r+1, color);
|
||||
fillCircleHelper(x0, y0, r, 3, 0, color);
|
||||
}
|
||||
|
||||
// Used to do circles and roundrects
|
||||
void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
|
||||
uint8_t cornername, int16_t delta, uint16_t color) {
|
||||
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
if (cornername & 0x1) {
|
||||
drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
|
||||
drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
|
||||
}
|
||||
if (cornername & 0x2) {
|
||||
drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
|
||||
drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bresenham's algorithm - thx wikpedia
|
||||
void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
void Adafruit_GFX::writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
uint16_t color) {
|
||||
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
|
||||
if (steep) {
|
||||
@ -221,9 +113,9 @@ void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
|
||||
for (; x0<=x1; x0++) {
|
||||
if (steep) {
|
||||
drawPixel(y0, x0, color);
|
||||
writePixel(y0, x0, color);
|
||||
} else {
|
||||
drawPixel(x0, y0, color);
|
||||
writePixel(x0, y0, color);
|
||||
}
|
||||
err -= dy;
|
||||
if (err < 0) {
|
||||
@ -233,63 +125,240 @@ void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a rectangle
|
||||
void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
drawFastHLine(x, y, w, color);
|
||||
drawFastHLine(x, y+h-1, w, color);
|
||||
void Adafruit_GFX::startWrite(){
|
||||
// Overwrite in subclasses if desired!
|
||||
}
|
||||
|
||||
void Adafruit_GFX::writePixel(int16_t x, int16_t y, uint16_t color){
|
||||
// Overwrite in subclasses if startWrite is defined!
|
||||
drawPixel(x, y, color);
|
||||
}
|
||||
|
||||
void Adafruit_GFX::writeFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color) {
|
||||
// Overwrite in subclasses if startWrite is defined!
|
||||
// Can be just writeLine(x, y, x, y+h-1, color);
|
||||
// or writeFillRect(x, y, 1, h, color);
|
||||
drawFastVLine(x, y, h, color);
|
||||
drawFastVLine(x+w-1, y, h, color);
|
||||
}
|
||||
|
||||
void Adafruit_GFX::writeFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color) {
|
||||
// Overwrite in subclasses if startWrite is defined!
|
||||
// Example: writeLine(x, y, x+w-1, y, color);
|
||||
// or writeFillRect(x, y, w, 1, color);
|
||||
drawFastHLine(x, y, w, color);
|
||||
}
|
||||
|
||||
void Adafruit_GFX::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
// Overwrite in subclasses if desired!
|
||||
fillRect(x,y,w,h,color);
|
||||
}
|
||||
|
||||
void Adafruit_GFX::endWrite(){
|
||||
// Overwrite in subclasses if startWrite is defined!
|
||||
}
|
||||
|
||||
void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color) {
|
||||
// Update in subclasses if desired!
|
||||
drawLine(x, y, x, y+h-1, color);
|
||||
startWrite();
|
||||
writeLine(x, y, x, y+h-1, color);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color) {
|
||||
// Update in subclasses if desired!
|
||||
drawLine(x, y, x+w-1, y, color);
|
||||
startWrite();
|
||||
writeLine(x, y, x+w-1, y, color);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
// Update in subclasses if desired!
|
||||
startWrite();
|
||||
for (int16_t i=x; i<x+w; i++) {
|
||||
drawFastVLine(i, y, h, color);
|
||||
writeFastVLine(i, y, h, color);
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Adafruit_GFX::fillScreen(uint16_t color) {
|
||||
// Update in subclasses if desired!
|
||||
fillRect(0, 0, _width, _height, color);
|
||||
}
|
||||
|
||||
#define distDiff(a,b) ((max(a,b) - min(a,b))+1)
|
||||
|
||||
void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
uint16_t color) {
|
||||
// Update in subclasses if desired!
|
||||
if(x0 == x1){
|
||||
drawFastVLine(x0, y0, distDiff(y0,y1), color);
|
||||
} else if(y0 == y1){
|
||||
drawFastHLine(x0, y0, distDiff(x0,x1), color);
|
||||
} else {
|
||||
startWrite();
|
||||
writeLine(x0, y0, x1, y1, color);
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Draw a circle outline
|
||||
void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
|
||||
uint16_t color) {
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
startWrite();
|
||||
writePixel(x0 , y0+r, color);
|
||||
writePixel(x0 , y0-r, color);
|
||||
writePixel(x0+r, y0 , color);
|
||||
writePixel(x0-r, y0 , color);
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
writePixel(x0 + x, y0 + y, color);
|
||||
writePixel(x0 - x, y0 + y, color);
|
||||
writePixel(x0 + x, y0 - y, color);
|
||||
writePixel(x0 - x, y0 - y, color);
|
||||
writePixel(x0 + y, y0 + x, color);
|
||||
writePixel(x0 - y, y0 + x, color);
|
||||
writePixel(x0 + y, y0 - x, color);
|
||||
writePixel(x0 - y, y0 - x, color);
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0,
|
||||
int16_t r, uint8_t cornername, uint16_t color) {
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
if (cornername & 0x4) {
|
||||
writePixel(x0 + x, y0 + y, color);
|
||||
writePixel(x0 + y, y0 + x, color);
|
||||
}
|
||||
if (cornername & 0x2) {
|
||||
writePixel(x0 + x, y0 - y, color);
|
||||
writePixel(x0 + y, y0 - x, color);
|
||||
}
|
||||
if (cornername & 0x8) {
|
||||
writePixel(x0 - y, y0 + x, color);
|
||||
writePixel(x0 - x, y0 + y, color);
|
||||
}
|
||||
if (cornername & 0x1) {
|
||||
writePixel(x0 - y, y0 - x, color);
|
||||
writePixel(x0 - x, y0 - y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
|
||||
uint16_t color) {
|
||||
startWrite();
|
||||
writeFastVLine(x0, y0-r, 2*r+1, color);
|
||||
fillCircleHelper(x0, y0, r, 3, 0, color);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// Used to do circles and roundrects
|
||||
void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
|
||||
uint8_t cornername, int16_t delta, uint16_t color) {
|
||||
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
if (cornername & 0x1) {
|
||||
writeFastVLine(x0+x, y0-y, 2*y+1+delta, color);
|
||||
writeFastVLine(x0+y, y0-x, 2*x+1+delta, color);
|
||||
}
|
||||
if (cornername & 0x2) {
|
||||
writeFastVLine(x0-x, y0-y, 2*y+1+delta, color);
|
||||
writeFastVLine(x0-y, y0-x, 2*x+1+delta, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a rectangle
|
||||
void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
startWrite();
|
||||
writeFastHLine(x, y, w, color);
|
||||
writeFastHLine(x, y+h-1, w, color);
|
||||
writeFastVLine(x, y, h, color);
|
||||
writeFastVLine(x+w-1, y, h, color);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// Draw a rounded rectangle
|
||||
void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
|
||||
int16_t h, int16_t r, uint16_t color) {
|
||||
// smarter version
|
||||
drawFastHLine(x+r , y , w-2*r, color); // Top
|
||||
drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
|
||||
drawFastVLine(x , y+r , h-2*r, color); // Left
|
||||
drawFastVLine(x+w-1, y+r , h-2*r, color); // Right
|
||||
startWrite();
|
||||
writeFastHLine(x+r , y , w-2*r, color); // Top
|
||||
writeFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
|
||||
writeFastVLine(x , y+r , h-2*r, color); // Left
|
||||
writeFastVLine(x+w-1, y+r , h-2*r, color); // Right
|
||||
// draw four corners
|
||||
drawCircleHelper(x+r , y+r , r, 1, color);
|
||||
drawCircleHelper(x+w-r-1, y+r , r, 2, color);
|
||||
drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
|
||||
drawCircleHelper(x+r , y+h-r-1, r, 8, color);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// Fill a rounded rectangle
|
||||
void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
|
||||
int16_t h, int16_t r, uint16_t color) {
|
||||
// smarter version
|
||||
fillRect(x+r, y, w-2*r, h, color);
|
||||
startWrite();
|
||||
writeFillRect(x+r, y, w-2*r, h, color);
|
||||
|
||||
// draw four corners
|
||||
fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
|
||||
fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// Draw a triangle
|
||||
@ -317,13 +386,15 @@ void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0,
|
||||
_swap_int16_t(y0, y1); _swap_int16_t(x0, x1);
|
||||
}
|
||||
|
||||
startWrite();
|
||||
if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
|
||||
a = b = x0;
|
||||
if(x1 < a) a = x1;
|
||||
else if(x1 > b) b = x1;
|
||||
if(x2 < a) a = x2;
|
||||
else if(x2 > b) b = x2;
|
||||
drawFastHLine(a, y0, b-a+1, color);
|
||||
writeFastHLine(a, y0, b-a+1, color);
|
||||
endWrite();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -357,7 +428,7 @@ void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0,
|
||||
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
|
||||
*/
|
||||
if(a > b) _swap_int16_t(a,b);
|
||||
drawFastHLine(a, y, b-a+1, color);
|
||||
writeFastHLine(a, y, b-a+1, color);
|
||||
}
|
||||
|
||||
// For lower part of triangle, find scanline crossings for segments
|
||||
@ -374,8 +445,9 @@ void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0,
|
||||
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
|
||||
*/
|
||||
if(a > b) _swap_int16_t(a,b);
|
||||
drawFastHLine(a, y, b-a+1, color);
|
||||
writeFastHLine(a, y, b-a+1, color);
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// Draw a 1-bit image (bitmap) at the specified (x,y) position from the
|
||||
@ -385,15 +457,17 @@ 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 byte;
|
||||
uint8_t byte = 0;
|
||||
|
||||
startWrite();
|
||||
for(j=0; j<h; j++) {
|
||||
for(i=0; i<w; i++) {
|
||||
if(i & 7) byte <<= 1;
|
||||
else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8);
|
||||
if(byte & 0x80) drawPixel(x+i, y+j, color);
|
||||
if(byte & 0x80) writePixel(x+i, y+j, color);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// Draw a 1-bit image (bitmap) at the specified (x,y) position from the
|
||||
@ -403,16 +477,18 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
|
||||
const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) {
|
||||
|
||||
int16_t i, j, byteWidth = (w + 7) / 8;
|
||||
uint8_t byte;
|
||||
uint8_t byte = 0;
|
||||
|
||||
startWrite();
|
||||
for(j=0; j<h; j++) {
|
||||
for(i=0; i<w; i++ ) {
|
||||
if(i & 7) byte <<= 1;
|
||||
else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8);
|
||||
if(byte & 0x80) drawPixel(x+i, y+j, color);
|
||||
else drawPixel(x+i, y+j, bg);
|
||||
if(byte & 0x80) writePixel(x+i, y+j, color);
|
||||
else writePixel(x+i, y+j, bg);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// drawBitmap() variant for RAM-resident (not PROGMEM) bitmaps.
|
||||
@ -420,15 +496,17 @@ 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 byte;
|
||||
uint8_t byte = 0;
|
||||
|
||||
startWrite();
|
||||
for(j=0; j<h; j++) {
|
||||
for(i=0; i<w; i++ ) {
|
||||
if(i & 7) byte <<= 1;
|
||||
else byte = bitmap[j * byteWidth + i / 8];
|
||||
if(byte & 0x80) drawPixel(x+i, y+j, color);
|
||||
if(byte & 0x80) writePixel(x+i, y+j, color);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// drawBitmap() variant w/background for RAM-resident (not PROGMEM) bitmaps.
|
||||
@ -436,16 +514,18 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
|
||||
uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) {
|
||||
|
||||
int16_t i, j, byteWidth = (w + 7) / 8;
|
||||
uint8_t byte;
|
||||
uint8_t byte = 0;
|
||||
|
||||
startWrite();
|
||||
for(j=0; j<h; j++) {
|
||||
for(i=0; i<w; i++ ) {
|
||||
if(i & 7) byte <<= 1;
|
||||
else byte = bitmap[j * byteWidth + i / 8];
|
||||
if(byte & 0x80) drawPixel(x+i, y+j, color);
|
||||
else drawPixel(x+i, y+j, bg);
|
||||
if(byte & 0x80) writePixel(x+i, y+j, color);
|
||||
else writePixel(x+i, y+j, bg);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
//Draw XBitMap Files (*.xbm), exported from GIMP,
|
||||
@ -455,15 +535,110 @@ void Adafruit_GFX::drawXBitmap(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 byte;
|
||||
uint8_t byte = 0;
|
||||
|
||||
startWrite();
|
||||
for(j=0; j<h; j++) {
|
||||
for(i=0; i<w; i++ ) {
|
||||
if(i & 7) byte >>= 1;
|
||||
else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8);
|
||||
if(byte & 0x01) drawPixel(x+i, y+j, color);
|
||||
if(byte & 0x01) writePixel(x+i, y+j, color);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// Draw a character
|
||||
void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
|
||||
uint16_t color, uint16_t bg, uint8_t size) {
|
||||
|
||||
if(!gfxFont) { // 'Classic' built-in font
|
||||
|
||||
if((x >= _width) || // Clip right
|
||||
(y >= _height) || // Clip bottom
|
||||
((x + 6 * size - 1) < 0) || // Clip left
|
||||
((y + 8 * size - 1) < 0)) // Clip top
|
||||
return;
|
||||
|
||||
if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior
|
||||
|
||||
startWrite();
|
||||
for(int8_t i=0; i<6; i++ ) {
|
||||
uint8_t line;
|
||||
if(i < 5) line = pgm_read_byte(font+(c*5)+i);
|
||||
else line = 0x0;
|
||||
for(int8_t j=0; j<8; j++, line >>= 1) {
|
||||
if(line & 0x1) {
|
||||
if(size == 1) writePixel(x+i, y+j, color);
|
||||
else writeFillRect(x+(i*size), y+(j*size), size, size, color);
|
||||
} else if(bg != color) {
|
||||
if(size == 1) writePixel(x+i, y+j, bg);
|
||||
else writeFillRect(x+i*size, y+j*size, size, size, bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
|
||||
} else { // Custom font
|
||||
|
||||
// Character is assumed previously filtered by write() to eliminate
|
||||
// newlines, returns, non-printable characters, etc. Calling drawChar()
|
||||
// directly with 'bad' characters of font may cause mayhem!
|
||||
|
||||
c -= pgm_read_byte(&gfxFont->first);
|
||||
GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
|
||||
uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
|
||||
|
||||
uint16_t bo = pgm_read_word(&glyph->bitmapOffset);
|
||||
uint8_t w = pgm_read_byte(&glyph->width),
|
||||
h = pgm_read_byte(&glyph->height);
|
||||
int8_t xo = pgm_read_byte(&glyph->xOffset),
|
||||
yo = pgm_read_byte(&glyph->yOffset);
|
||||
uint8_t xx, yy, bits = 0, bit = 0;
|
||||
int16_t xo16 = 0, yo16 = 0;
|
||||
|
||||
if(size > 1) {
|
||||
xo16 = xo;
|
||||
yo16 = yo;
|
||||
}
|
||||
|
||||
// Todo: Add character clipping here
|
||||
|
||||
// NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.
|
||||
// THIS IS ON PURPOSE AND BY DESIGN. The background color feature
|
||||
// has typically been used with the 'classic' font to overwrite old
|
||||
// screen contents with new data. This ONLY works because the
|
||||
// characters are a uniform size; it's not a sensible thing to do with
|
||||
// proportionally-spaced fonts with glyphs of varying sizes (and that
|
||||
// may overlap). To replace previously-drawn text when using a custom
|
||||
// font, use the getTextBounds() function to determine the smallest
|
||||
// rectangle encompassing a string, erase the area with fillRect(),
|
||||
// then draw new text. This WILL infortunately 'blink' the text, but
|
||||
// is unavoidable. Drawing 'background' pixels will NOT fix this,
|
||||
// only creates a new set of problems. Have an idea to work around
|
||||
// this (a canvas object type for MCUs that can afford the RAM and
|
||||
// displays supporting setAddrWindow() and pushColors()), but haven't
|
||||
// implemented this yet.
|
||||
|
||||
startWrite();
|
||||
for(yy=0; yy<h; yy++) {
|
||||
for(xx=0; xx<w; xx++) {
|
||||
if(!(bit++ & 7)) {
|
||||
bits = pgm_read_byte(&bitmap[bo++]);
|
||||
}
|
||||
if(bits & 0x80) {
|
||||
if(size == 1) {
|
||||
writePixel(x+xo+xx, y+yo+yy, color);
|
||||
} else {
|
||||
writeFillRect(x+(xo16+xx)*size, y+(yo16+yy)*size, size, size, color);
|
||||
}
|
||||
}
|
||||
bits <<= 1;
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
|
||||
} // End classic vs custom font
|
||||
}
|
||||
|
||||
#if ARDUINO >= 100
|
||||
@ -471,7 +646,6 @@ size_t Adafruit_GFX::write(uint8_t c) {
|
||||
#else
|
||||
void Adafruit_GFX::write(uint8_t c) {
|
||||
#endif
|
||||
|
||||
if(!gfxFont) { // 'Classic' built-in font
|
||||
|
||||
if(c == '\n') {
|
||||
@ -521,96 +695,6 @@ void Adafruit_GFX::write(uint8_t c) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Draw a character
|
||||
void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
|
||||
uint16_t color, uint16_t bg, uint8_t size) {
|
||||
|
||||
if(!gfxFont) { // 'Classic' built-in font
|
||||
|
||||
if((x >= _width) || // Clip right
|
||||
(y >= _height) || // Clip bottom
|
||||
((x + 6 * size - 1) < 0) || // Clip left
|
||||
((y + 8 * size - 1) < 0)) // Clip top
|
||||
return;
|
||||
|
||||
if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior
|
||||
|
||||
for(int8_t i=0; i<6; i++ ) {
|
||||
uint8_t line;
|
||||
if(i < 5) line = pgm_read_byte(font+(c*5)+i);
|
||||
else line = 0x0;
|
||||
for(int8_t j=0; j<8; j++, line >>= 1) {
|
||||
if(line & 0x1) {
|
||||
if(size == 1) drawPixel(x+i, y+j, color);
|
||||
else fillRect(x+(i*size), y+(j*size), size, size, color);
|
||||
} else if(bg != color) {
|
||||
if(size == 1) drawPixel(x+i, y+j, bg);
|
||||
else fillRect(x+i*size, y+j*size, size, size, bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else { // Custom font
|
||||
|
||||
// Character is assumed previously filtered by write() to eliminate
|
||||
// newlines, returns, non-printable characters, etc. Calling drawChar()
|
||||
// directly with 'bad' characters of font may cause mayhem!
|
||||
|
||||
c -= pgm_read_byte(&gfxFont->first);
|
||||
GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
|
||||
uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
|
||||
|
||||
uint16_t bo = pgm_read_word(&glyph->bitmapOffset);
|
||||
uint8_t w = pgm_read_byte(&glyph->width),
|
||||
h = pgm_read_byte(&glyph->height),
|
||||
xa = pgm_read_byte(&glyph->xAdvance);
|
||||
int8_t xo = pgm_read_byte(&glyph->xOffset),
|
||||
yo = pgm_read_byte(&glyph->yOffset);
|
||||
uint8_t xx, yy, bits, bit = 0;
|
||||
int16_t xo16, yo16;
|
||||
|
||||
if(size > 1) {
|
||||
xo16 = xo;
|
||||
yo16 = yo;
|
||||
}
|
||||
|
||||
// Todo: Add character clipping here
|
||||
|
||||
// NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.
|
||||
// THIS IS ON PURPOSE AND BY DESIGN. The background color feature
|
||||
// has typically been used with the 'classic' font to overwrite old
|
||||
// screen contents with new data. This ONLY works because the
|
||||
// characters are a uniform size; it's not a sensible thing to do with
|
||||
// proportionally-spaced fonts with glyphs of varying sizes (and that
|
||||
// may overlap). To replace previously-drawn text when using a custom
|
||||
// font, use the getTextBounds() function to determine the smallest
|
||||
// rectangle encompassing a string, erase the area with fillRect(),
|
||||
// then draw new text. This WILL infortunately 'blink' the text, but
|
||||
// is unavoidable. Drawing 'background' pixels will NOT fix this,
|
||||
// only creates a new set of problems. Have an idea to work around
|
||||
// this (a canvas object type for MCUs that can afford the RAM and
|
||||
// displays supporting setAddrWindow() and pushColors()), but haven't
|
||||
// implemented this yet.
|
||||
|
||||
for(yy=0; yy<h; yy++) {
|
||||
for(xx=0; xx<w; xx++) {
|
||||
if(!(bit++ & 7)) {
|
||||
bits = pgm_read_byte(&bitmap[bo++]);
|
||||
}
|
||||
if(bits & 0x80) {
|
||||
if(size == 1) {
|
||||
drawPixel(x+xo+xx, y+yo+yy, color);
|
||||
} else {
|
||||
fillRect(x+(xo16+xx)*size, y+(yo16+yy)*size, size, size, color);
|
||||
}
|
||||
}
|
||||
bits <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
} // End classic vs custom font
|
||||
}
|
||||
|
||||
void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
@ -887,6 +971,16 @@ void Adafruit_GFX::invertDisplay(boolean i) {
|
||||
|
||||
Adafruit_GFX_Button::Adafruit_GFX_Button(void) {
|
||||
_gfx = 0;
|
||||
laststate = 0;
|
||||
_fillcolor = 0;
|
||||
_textsize = 1;
|
||||
_w = 0;
|
||||
_x = 0;
|
||||
currstate = 0;
|
||||
_textcolor = 0;
|
||||
_outlinecolor = 0;
|
||||
_h = 0;
|
||||
_y = 0;
|
||||
}
|
||||
|
||||
void Adafruit_GFX_Button::initButton(
|
||||
|
27
Adafruit_GFX.h
Normal file → Executable file
27
Adafruit_GFX.h
Normal file → Executable file
@ -7,7 +7,6 @@
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include "gfxfont.h"
|
||||
|
||||
class Adafruit_GFX : public Print {
|
||||
@ -19,16 +18,35 @@ class Adafruit_GFX : public Print {
|
||||
// This MUST be defined by the subclass:
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
|
||||
// TRANSACTION API / CORE DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void startWrite(void);
|
||||
virtual void writePixel(int16_t x, int16_t y, uint16_t color);
|
||||
virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
virtual void endWrite(void);
|
||||
|
||||
// CONTROL API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void setRotation(uint8_t r);
|
||||
virtual void invertDisplay(boolean i);
|
||||
|
||||
// BASIC DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void
|
||||
drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color),
|
||||
// It's good to implement those, even if using transaction API
|
||||
drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
|
||||
drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
|
||||
drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
fillScreen(uint16_t color),
|
||||
invertDisplay(boolean i);
|
||||
// Optional and probably not necessary to change
|
||||
drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color),
|
||||
drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
|
||||
// These exist only with Adafruit_GFX (no subclass overrides)
|
||||
void
|
||||
@ -63,7 +81,6 @@ class Adafruit_GFX : public Print {
|
||||
setTextColor(uint16_t c, uint16_t bg),
|
||||
setTextSize(uint8_t s),
|
||||
setTextWrap(boolean w),
|
||||
setRotation(uint8_t r),
|
||||
cp437(boolean x=true),
|
||||
setFont(const GFXfont *f = NULL),
|
||||
getTextBounds(char *string, int16_t x, int16_t y,
|
||||
|
Loading…
x
Reference in New Issue
Block a user