Reintegrated Adafruit-GFX-Library.

This commit is contained in:
nitko12 2020-09-11 09:35:36 +02:00
parent 4df80297ea
commit 4687d67162
15 changed files with 3165 additions and 901 deletions

View File

@ -8,8 +8,9 @@
This example will show you how you can draw some simple graphics using
Adafruit GFX functions. Yes, Inkplate library is 100% compatible with GFX lib!
Learn more about Adafruit GFX: https://learn.adafruit.com/adafruit-gfx-graphics-library
Inkplate will be used in grayscale mode which is 3 bit, so you can have up to 8 different colors (black, 6 gray colors and white)
Color is represented by number, where number 0 means black and number 7 means white, while everything in between are shades of gray.
Inkplate will be used in grayscale mode which is 3 bit, so you can have up to 8 different colors (black, 6 gray
colors and white) Color is represented by number, where number 0 means black and number 7 means white, while
everything in between are shades of gray.
Want to learn more about Inkplate? Visit www.inkplate.io
Looking to get support? Write on our forums: http://forum.e-radionica.com/en/
@ -18,58 +19,67 @@
#include "Inkplate.h" //Include Inkplate library to the sketch
#include "image.h" //Include image file that holds grayscale image data. You can see it in next tab inside Arduino IDE.
Inkplate display(INKPLATE_3BIT); //Create object on Inkplate library and set library to work in grayscale mode (3-bit)
//Other option is monochrome mode, which is demonstrated in next example "2-Inkplate_basic_monochrome"
Inkplate display(INKPLATE_3BIT); // Create object on Inkplate library and set library to work in grayscale mode (3-bit)
// Other option is monochrome mode, which is demonstrated in next example
// "2-Inkplate_basic_monochrome"
#define DELAY_MS 5000 //Delay in milliseconds between screen refresh. Refreshing e-paper screens more often than 5s is not recommended \
#define DELAY_MS \
5000 //Delay in milliseconds between screen refresh. Refreshing e-paper screens more often than 5s is not recommended \
//Want to refresh faster? Use partial update! Find example in "3-Inkplate-basic_partial_update"
void setup()
{
display.begin(); //Init library (you should call this function ONLY ONCE)
display.clearDisplay(); //Clear any data that may have been in (software) frame buffer.
//(NOTE! This does not clean image on screen, it only clears it in the frame buffer inside ESP32).
display.clean(); //Clear everything that has previously been on a screen
display.begin(); // Init library (you should call this function ONLY ONCE)
display.clearDisplay(); // Clear any data that may have been in (software) frame buffer.
//(NOTE! This does not clean image on screen, it only clears it in the frame buffer inside
// ESP32).
display.clean(); // Clear everything that has previously been on a screen
display.setTextColor(0, 7);
display.setCursor(150, 320);
display.setTextSize(4);
display.print("Welcome to Inkplate 6!");
display.display(); //Write hello message
delay(5000); //Wait a little bit
display.display(); // Write hello message
delay(5000); // Wait a little bit
}
void loop()
{
//Example will demostrate funcionality one by one. You always first set everything in the frame buffer and afterwards you show
//it on the screen using display.display().
// Example will demostrate funcionality one by one. You always first set everything in the frame buffer and
// afterwards you show it on the screen using display.display().
//Let'sstart by drawing pixel at x = 100 and y = 50 location
display.clearDisplay(); //Clear everytning that is inside frame buffer in ESP32
display.drawPixel(100, 50, 0); //Draw one black pixel at X = 100, Y = 50 position in 0 (BLACK) color
displayCurrentAction("Drawing a pixel"); //Function which writes small text at bottom left indicating what's currently done
//NOTE: you do not need displayCurrentAction function to use Inkplate!
display.display(); //Send image to display. You need to call this one each time you want to transfer frame buffer to the screen.
delay(DELAY_MS); //Wait a little bit
// Let'sstart by drawing pixel at x = 100 and y = 50 location
display.clearDisplay(); // Clear everytning that is inside frame buffer in ESP32
display.drawPixel(100, 50, 0); // Draw one black pixel at X = 100, Y = 50 position in 0 (BLACK) color
displayCurrentAction(
"Drawing a pixel"); // Function which writes small text at bottom left indicating what's currently done
// NOTE: you do not need displayCurrentAction function to use Inkplate!
display.display(); // Send image to display. You need to call this one each time you want to transfer frame buffer
// to the screen.
delay(DELAY_MS); // Wait a little bit
//Now, let's draw some random pixels!
display.clearDisplay(); //Clear everything that is inside frame buffer in ESP32
// Now, let's draw some random pixels!
display.clearDisplay(); // Clear everything that is inside frame buffer in ESP32
for (int i = 0; i < 1000; i++)
{ //Write 1000 random colored pixels at random locations
display.drawPixel(random(0, 799), random(0, 599), random(0, 7)); //We are setting color of the pixels using numbers from 0 to 7,
} //where 0 mens black, 7 white and gray is in between
{ // Write 1000 random colored pixels at random locations
display.drawPixel(random(0, 799), random(0, 599),
random(0, 7)); // We are setting color of the pixels using numbers from 0 to 7,
} // where 0 mens black, 7 white and gray is in between
displayCurrentAction("Drawing 600 random pixels in random colors");
display.display(); //Write everything from frame buffer to screen
delay(DELAY_MS); //Wait
display.display(); // Write everything from frame buffer to screen
delay(DELAY_MS); // Wait
//Draw two diagonal lines accros screen
// Draw two diagonal lines accros screen
display.clearDisplay();
display.drawLine(0, 0, 799, 599, 0); //All of those drawing fuctions originate from Adafruit GFX library, so maybe you are already familiar
display.drawLine(799, 0, 0, 599, 0); //with those. Arguments are: start X, start Y, ending X, ending Y, color.
display.drawLine(
0, 0, 799, 599,
0); // All of those drawing fuctions originate from Adafruit GFX library, so maybe you are already familiar
display.drawLine(799, 0, 0, 599, 0); // with those. Arguments are: start X, start Y, ending X, ending Y, color.
displayCurrentAction("Drawing two diagonal lines");
display.display();
delay(DELAY_MS);
//And again, let's draw some random lines on screen!
// And again, let's draw some random lines on screen!
display.clearDisplay();
for (int i = 0; i < 100; i++)
{
@ -79,43 +89,45 @@ void loop()
display.display();
delay(DELAY_MS);
//Let's draw some random thick lines on screen!
// Let's draw some random thick lines on screen!
display.clearDisplay();
for (int i = 0; i < 100; i++)
{
display.drawThickLine(random(0, 799), random(0, 599), random(0, 799), random(0, 599), random(0, 7), (float)random(1, 20));
display.drawThickLine(random(0, 799), random(0, 599), random(0, 799), random(0, 599), random(0, 7),
(float)random(1, 20));
}
displayCurrentAction("Drawing 50 random lines in random colors and thickness");
display.display();
delay(DELAY_MS);
//Let's draw some random gradient thick lines on screen!
// Let's draw some random gradient thick lines on screen!
display.clearDisplay();
for (int i = 0; i < 100; i++)
{
int startColor = random(0, 7);
int endColor = random(startColor, 7);
display.drawGradientLine(random(0, 799), random(0, 599), random(0, 799), random(0, 599), startColor, endColor, (float)random(1, 20));
display.drawGradientLine(random(0, 799), random(0, 599), random(0, 799), random(0, 599), startColor, endColor,
(float)random(1, 20));
}
displayCurrentAction("Drawing 50 random gradient lines in random colors and thickness");
display.display();
delay(DELAY_MS);
//Now draw one horizontal...
// Now draw one horizontal...
display.clearDisplay();
display.drawFastHLine(100, 100, 600, 0); //Arguments are: starting X, starting Y, length, color
display.drawFastHLine(100, 100, 600, 0); // Arguments are: starting X, starting Y, length, color
displayCurrentAction("Drawing one horizontal line");
display.display();
delay(DELAY_MS);
//... and one vertical line
display.clearDisplay();
display.drawFastVLine(100, 100, 400, 0); //Arguments are: starting X, starting Y, length, color
display.drawFastVLine(100, 100, 400, 0); // Arguments are: starting X, starting Y, length, color
displayCurrentAction("Drawing one vertical line");
display.display();
delay(DELAY_MS);
//Now, let' make a grid using only horizontal and vertical lines in random colors!
// Now, let' make a grid using only horizontal and vertical lines in random colors!
display.clearDisplay();
for (int i = 0; i < 800; i += 8)
{
@ -129,14 +141,14 @@ void loop()
display.display();
delay(DELAY_MS);
//Draw rectangle at X = 200, Y = 200 and size of 400x300 pixels
// Draw rectangle at X = 200, Y = 200 and size of 400x300 pixels
display.clearDisplay();
display.drawRect(200, 200, 400, 300, 0); //Arguments are: start X, start Y, size X, size Y, color
display.drawRect(200, 200, 400, 300, 0); // Arguments are: start X, start Y, size X, size Y, color
displayCurrentAction("Drawing rectangle");
display.display();
delay(DELAY_MS);
//Draw rectangles on random location, size 100x150 pixels in random color
// Draw rectangles on random location, size 100x150 pixels in random color
display.clearDisplay();
for (int i = 0; i < 50; i++)
{
@ -146,14 +158,14 @@ void loop()
display.display();
delay(DELAY_MS);
//Draw filled black rectangle at X = 200, Y = 200, size of 400x300 pixels in gray color
// Draw filled black rectangle at X = 200, Y = 200, size of 400x300 pixels in gray color
display.clearDisplay();
display.fillRect(200, 200, 400, 300, 4); //Arguments are: start X, start Y, size X, size Y, color
display.fillRect(200, 200, 400, 300, 4); // Arguments are: start X, start Y, size X, size Y, color
displayCurrentAction("Drawing gray rectangle");
display.display();
delay(DELAY_MS);
//Draw filled random colored rectangles on random location, size of 30x30 pixels in radnom color
// Draw filled random colored rectangles on random location, size of 30x30 pixels in radnom color
display.clearDisplay();
for (int i = 0; i < 50; i++)
{
@ -163,14 +175,14 @@ void loop()
display.display();
delay(DELAY_MS);
//Draw circle at center of a screen with radius of 75 pixels
// Draw circle at center of a screen with radius of 75 pixels
display.clearDisplay();
display.drawCircle(400, 300, 75, 0); //Arguments are: start X, start Y, radius, color
display.drawCircle(400, 300, 75, 0); // Arguments are: start X, start Y, radius, color
displayCurrentAction("Drawing a circle");
display.display();
delay(DELAY_MS);
//Draw some random colored circles at random location with radius of 25 pixels in random color
// Draw some random colored circles at random location with radius of 25 pixels in random color
display.clearDisplay();
for (int i = 0; i < 40; i++)
{
@ -180,31 +192,31 @@ void loop()
display.display();
delay(DELAY_MS);
//Draw black filled circle at center of a screen with radius of 75 pixels
// Draw black filled circle at center of a screen with radius of 75 pixels
display.clearDisplay();
display.fillCircle(400, 300, 75, 0); //Arguments are: start X, start Y, radius, color
display.fillCircle(400, 300, 75, 0); // Arguments are: start X, start Y, radius, color
displayCurrentAction("Drawing black-filled circle");
display.display();
delay(DELAY_MS);
//Draw some random colored filled circles at random location with radius of 15 pixels
// Draw some random colored filled circles at random location with radius of 15 pixels
display.clearDisplay();
for (int i = 0; i < 40; i++)
{
display.fillCircle(random(0, 799), random(0, 599), 15, random(0, 7));
}
displayCurrentAction("Drawing many filled circles randomly in random colors");
display.display(); //To show stuff on screen, you always need to call display.display();
display.display(); // To show stuff on screen, you always need to call display.display();
delay(DELAY_MS);
//Draw rounded rectangle at X = 200, Y = 200 and size of 400x300 pixels and radius of 10 pixels
// Draw rounded rectangle at X = 200, Y = 200 and size of 400x300 pixels and radius of 10 pixels
display.clearDisplay();
display.drawRoundRect(200, 200, 400, 300, 10, 0); //Arguments are: start X, start Y, size X, size Y, radius, color
display.drawRoundRect(200, 200, 400, 300, 10, 0); // Arguments are: start X, start Y, size X, size Y, radius, color
displayCurrentAction("Drawing rectangle with rounded edges");
display.display();
delay(DELAY_MS);
//Draw rounded rectangles on random location, size 100x150 pixels, radius of 5 pixels in radnom color
// Draw rounded rectangles on random location, size 100x150 pixels, radius of 5 pixels in radnom color
display.clearDisplay();
for (int i = 0; i < 50; i++)
{
@ -214,14 +226,14 @@ void loop()
display.display();
delay(DELAY_MS);
//Draw filled random colored rectangle at X = 200, Y = 200, size of 400x300 pixels and radius of 10 pixels
// Draw filled random colored rectangle at X = 200, Y = 200, size of 400x300 pixels and radius of 10 pixels
display.clearDisplay();
display.fillRoundRect(200, 200, 400, 300, 10, 0); //Arguments are: start X, start Y, size X, size Y, radius, color
display.fillRoundRect(200, 200, 400, 300, 10, 0); // Arguments are: start X, start Y, size X, size Y, radius, color
displayCurrentAction("Drawing filled rectangle with rounded edges");
display.display();
delay(DELAY_MS);
//Draw filled random colored rectangle on random location, size of 30x30 pixels, radius of 3 pixels in radnom color
// Draw filled random colored rectangle on random location, size of 30x30 pixels, radius of 3 pixels in radnom color
display.clearDisplay();
for (int i = 0; i < 50; i++)
{
@ -231,43 +243,47 @@ void loop()
display.display();
delay(DELAY_MS);
//Draw simple triangle
// Draw simple triangle
display.clearDisplay();
display.drawTriangle(250, 400, 550, 400, 400, 100, 0); //Arguments are: X1, Y1, X2, Y2, X3, Y3, color
display.drawTriangle(250, 400, 550, 400, 400, 100, 0); // Arguments are: X1, Y1, X2, Y2, X3, Y3, color
display.display();
delay(DELAY_MS);
//Draw filled triangle inside simple triangle (so no display.clearDisplay() this time)
display.fillTriangle(300, 350, 500, 350, 400, 150, 0); //Arguments are: X1, Y1, X2, Y2, X3, Y3, color
// Draw filled triangle inside simple triangle (so no display.clearDisplay() this time)
display.fillTriangle(300, 350, 500, 350, 400, 150, 0); // Arguments are: X1, Y1, X2, Y2, X3, Y3, color
displayCurrentAction("Drawing filled triangle inside exsisting one");
display.display();
delay(DELAY_MS);
//Display some grayscale image on screen. We are going to display e-radionica logo on display at location X = 100, Y = 100
//Image size is 500x332 pixels.
// Display some grayscale image on screen. We are going to display e-radionica logo on display at location X = 100,
// Y = 100 Image size is 500x332 pixels.
display.clearDisplay();
display.drawBitmap3Bit(100, 100, picture1, 500, 332); //Arguments are: start X, start Y, array variable name, size X, size Y
display.drawBitmap3Bit(100, 100, picture1, 500,
332); // Arguments are: start X, start Y, array variable name, size X, size Y
displayCurrentAction("Drawing a bitmap image");
display.display();
delay(DELAY_MS);
//Write some text on screen with different sizes and color
// Write some text on screen with different sizes and color
display.clearDisplay();
for (int i = 0; i < 6; i++)
{
display.setTextColor(i);
display.setTextSize(i + 1); //textSize parameter starts at 0 and goes up to 10 (larger won't fit Inkplate 6 screen)
display.setCursor(200, (i * i * 8)); //setCursor works as same as on LCD displays - sets "the cursor" at the place you want to write someting next
display.print("INKPLATE6!"); //The actual text you want to show on e-paper as String
display.setTextSize(i +
1); // textSize parameter starts at 0 and goes up to 10 (larger won't fit Inkplate 6 screen)
display.setCursor(200, (i * i * 8)); // setCursor works as same as on LCD displays - sets "the cursor" at the
// place you want to write someting next
display.print("INKPLATE6!"); // The actual text you want to show on e-paper as String
}
displayCurrentAction("Text in different sizes and shadings");
display.display(); //To show stuff on screen, you always need to call display.display();
display.display(); // To show stuff on screen, you always need to call display.display();
delay(DELAY_MS);
//Write same text on different location, but now invert colors (text is white, text background is black)
display.setTextColor(7, 0); //First argument is text color, while second argument is background color. In greyscale,
// Write same text on different location, but now invert colors (text is white, text background is black)
display.setTextColor(7, 0); // First argument is text color, while second argument is background color. In
// greyscale,
for (int i = 0; i < 6; i++)
{ //you are able to choose from 8 different colors (0-7)
{ // you are able to choose from 8 different colors (0-7)
display.setTextSize(i + 1);
display.setCursor(200, 300 + (i * i * 8));
display.print("INKPLATE6!");
@ -328,7 +344,7 @@ void loop()
delay(DELAY_MS);
//Write text and rotate it by 90 deg. forever
// Write text and rotate it by 90 deg. forever
int r = 0;
display.setTextSize(8);
display.setTextColor(7, 0);
@ -336,18 +352,19 @@ void loop()
{
display.setCursor(100, 100);
display.clearDisplay();
display.setRotation(r); //Set rotation will sent rotation for the entire display, so you can use it sideways or upside-down
display.setRotation(
r); // Set rotation will sent rotation for the entire display, so you can use it sideways or upside-down
display.print("INKPLATE6");
display.display();
r++;
delay(DELAY_MS);
}
//Did you know that you can change between monochrome and greyscale mode anytime?
//Just call Inkplate display(INKPLATE_1BIT) or Inkplate display(INKPLATE_3BIT)
// Did you know that you can change between monochrome and greyscale mode anytime?
// Just call Inkplate display(INKPLATE_1BIT) or Inkplate display(INKPLATE_3BIT)
}
//Small function that will write on the screen what function is currently in demonstration.
// Small function that will write on the screen what function is currently in demonstration.
void displayCurrentAction(String text)
{
display.setTextSize(2);

View File

@ -95,7 +95,7 @@
#define DATA 0x0E8C0030
Inkplate::Inkplate(uint8_t _mode) : Graphics(E_INK_WIDTH, E_INK_HEIGHT)
Inkplate::Inkplate(uint8_t _mode) : Adafruit_GFX(E_INK_WIDTH, E_INK_HEIGHT), Graphics(E_INK_WIDTH, E_INK_HEIGHT)
{
setDisplayMode(_mode);
for (uint32_t i = 0; i < 256; ++i)
@ -194,7 +194,7 @@ void Inkplate::display1b()
{
memcpy(DMemoryNew, _partial, 60000);
uint16_t _pos;
uint32_t _send;
uint8_t data;
uint8_t dram;
@ -209,23 +209,23 @@ void Inkplate::display1b()
cleanFast(0, 11);
for (int k = 0; k < 3; ++k)
{
_pos = 59999;
uint8_t *DMemoryNewPtr = DMemoryNew + 59999;
vscan_start();
for (int i = 0; i < 600; ++i)
{
dram = *(DMemoryNew + _pos);
data = LUTB[(dram >> 4) & 0x0F];
dram = *(DMemoryNewPtr--);
data = LUTB[dram >> 4];
_send = pinLUT[data];
hscan_start(_send);
data = LUTB[dram & 0x0F];
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
_pos--;
for (int j = 0; j < 99; ++j)
{
dram = *(DMemoryNew + _pos);
data = LUTB[(dram >> 4) & 0x0F];
dram = *(DMemoryNewPtr--);
data = LUTB[dram >> 4];
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
@ -233,7 +233,6 @@ void Inkplate::display1b()
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
_pos--;
}
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
@ -242,12 +241,12 @@ void Inkplate::display1b()
delayMicroseconds(230);
}
_pos = 59999;
uint16_t _pos = 59999;
vscan_start();
for (int i = 0; i < 600; ++i)
{
dram = *(DMemoryNew + _pos);
data = LUT2[(dram >> 4) & 0x0F];
data = LUT2[dram >> 4];
_send = pinLUT[data];
hscan_start(_send);
data = LUT2[dram & 0x0F];
@ -258,7 +257,7 @@ void Inkplate::display1b()
for (int j = 0; j < 99; ++j)
{
dram = *(DMemoryNew + _pos);
data = LUT2[(dram >> 4) & 0x0F];
data = LUT2[dram >> 4];
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
@ -278,10 +277,10 @@ void Inkplate::display1b()
for (int i = 0; i < 600; ++i)
{
dram = *(DMemoryNew + _pos);
data = 0b00000000;
data = 0;
_send = pinLUT[data];
hscan_start(_send);
data = 0b00000000;
data = 0;
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
for (int j = 0; j < 99; ++j)
@ -387,10 +386,9 @@ void Inkplate::partialUpdate()
uint16_t _pos = 59999;
uint32_t _send;
uint8_t data;
uint8_t data = 0;
uint8_t diffw, diffb;
uint32_t n = 119999;
uint8_t dram;
for (int i = 0; i < 600; ++i)
{
@ -459,7 +457,7 @@ void Inkplate::clean()
void Inkplate::cleanFast(uint8_t c, uint8_t rep)
{
einkOn();
uint8_t data;
uint8_t data = 0;
if (c == 0)
data = B10101010;
else if (c == 1)

View File

@ -1,346 +0,0 @@
#include "Font.h"
inline GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c)
{
return gfxFont->glyph + c;
}
inline uint8_t *pgm_read_bitmap_ptr(const GFXfont *gfxFont)
{
return gfxFont->bitmap;
}
void Font::setCursor(int16_t x, int16_t y)
{
cursor_x = x;
cursor_y = y;
}
void Font::setTextColor(uint16_t c)
{
textcolor = textbgcolor = c;
}
void Font::setTextColor(uint16_t c, uint16_t bg)
{
textcolor = c;
textbgcolor = bg;
}
void Font::setTextWrap(bool w)
{
wrap = w;
}
void Font::cp437(bool x = true)
{
_cp437 = x;
}
int16_t Font::getCursorX()
{
return cursor_x;
}
int16_t Font::getCursorY()
{
return cursor_y;
}
void Font::setTextSize(uint8_t s)
{
setTextSize(s, s);
}
void Font::setTextSize(uint8_t s_x, uint8_t s_y)
{
textsize_x = (s_x > 0) ? s_x : 1;
textsize_y = (s_y > 0) ? s_y : 1;
}
void Font::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size)
{
drawChar(x, y, c, color, bg, size, size);
}
void Font::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y)
{
if (!gfxFont)
{
if ((x >= width()) || // Clip right
(y >= height()) || // Clip bottom
((x + 6 * size_x - 1) < 0) || // Clip left
((y + 8 * size_y - 1) < 0)) // Clip top
return;
if (!_cp437 && (c >= 176))
c++;
startWrite();
for (int8_t i = 0; i < 5; i++)
{
uint8_t line = pgm_read_byte(&font[c * 5 + i]);
for (int8_t j = 0; j < 8; j++, line >>= 1)
{
if (line & 1)
{
if (size_x == 1 && size_y == 1)
writePixel(x + i, y + j, color);
else
writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, color);
}
else if (bg != color)
{
if (size_x == 1 && size_y == 1)
writePixel(x + i, y + j, bg);
else
writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg);
}
}
}
if (bg != color)
{
if (size_x == 1 && size_y == 1)
writeFastVLine(x + 5, y, 8, bg);
else
writeFillRect(x + 5 * size_x, y, size_x, 8 * size_y, bg);
}
endWrite();
}
else
{
c -= (uint8_t)pgm_read_byte(&gfxFont->first);
GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c);
uint8_t *bitmap = pgm_read_bitmap_ptr(gfxFont);
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_x > 1 || size_y > 1)
{
xo16 = xo;
yo16 = yo;
}
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_x == 1 && size_y == 1)
{
writePixel(x + xo + xx, y + yo + yy, color);
}
else
{
writeFillRect(x + (xo16 + xx) * size_x, y + (yo16 + yy) * size_y, size_x, size_y, color);
}
}
bits <<= 1;
}
}
endWrite();
}
}
size_t Font::write(uint8_t c)
{
if (!gfxFont)
{ // 'Classic' built-in font
if (c == '\n')
{ // Newline?
cursor_x = 0; // Reset x to zero,
cursor_y += textsize_y * 8; // advance y one line
}
else if (c != '\r')
{ // Ignore carriage returns
if (wrap && ((cursor_x + textsize_x * 6) > width()))
{ // Off right?
cursor_x = 0; // Reset x to zero,
cursor_y += textsize_y * 8; // advance y one line
}
drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize_x, textsize_y);
cursor_x += textsize_x * 6; // Advance x one char
}
}
else
{ // Custom font
if (c == '\n')
{
cursor_x = 0;
cursor_y += (int16_t)textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
}
else if (c != '\r')
{
uint8_t first = pgm_read_byte(&gfxFont->first);
if ((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last)))
{
GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first);
uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height);
if ((w > 0) && (h > 0))
{ // Is there an associated bitmap?
int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic
if (wrap && ((cursor_x + textsize_x * (xo + w)) > width()))
{
cursor_x = 0;
cursor_y += (int16_t)textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
}
drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize_x, textsize_y);
}
cursor_x += (uint8_t)pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize_x;
}
}
}
return 1;
}
void Font::setFont(const GFXfont *f)
{
if (f)
{
if (!gfxFont)
{
cursor_y += 6;
}
}
else if (gfxFont)
{
cursor_y -= 6;
}
gfxFont = (GFXfont *)f;
}
void Font::charBounds(char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy)
{
if (gfxFont)
{
if (c == '\n')
{
*x = 0;
*y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
}
else if (c != '\r')
{
uint8_t first = pgm_read_byte(&gfxFont->first), last = pgm_read_byte(&gfxFont->last);
if ((c >= first) && (c <= last))
{
GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first);
uint8_t gw = pgm_read_byte(&glyph->width), gh = 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);
if (wrap && ((*x + (((int16_t)xo + gw) * textsize_x)) > width()))
{
*x = 0;
*y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
}
int16_t tsx = (int16_t)textsize_x, tsy = (int16_t)textsize_y, x1 = *x + xo * tsx, y1 = *y + yo * tsy,
x2 = x1 + gw * tsx - 1, y2 = y1 + gh * tsy - 1;
if (x1 < *minx)
*minx = x1;
if (y1 < *miny)
*miny = y1;
if (x2 > *maxx)
*maxx = x2;
if (y2 > *maxy)
*maxy = y2;
*x += xa * tsx;
}
}
}
else
{
if (c == '\n')
{
*x = 0;
*y += textsize_y * 8;
}
else if (c != '\r')
{
if (wrap && ((*x + textsize_x * 6) > width()))
{
*x = 0;
*y += textsize_y * 8;
}
int x2 = *x + textsize_x * 6 - 1, y2 = *y + textsize_y * 8 - 1;
if (x2 > *maxx)
*maxx = x2; // Track max x, y
if (y2 > *maxy)
*maxy = y2;
if (*x < *minx)
*minx = *x; // Track min x, y
if (*y < *miny)
*miny = *y;
*x += textsize_x * 6; // Advance x one char
}
}
}
void Font::getTextBounds(const char *str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
{
uint8_t c;
*x1 = x;
*y1 = y;
*w = *h = 0;
int16_t minx = width(), miny = height(), maxx = -1, maxy = -1;
while ((c = *str++))
charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy);
if (maxx >= minx)
{
*x1 = minx;
*w = maxx - minx + 1;
}
if (maxy >= miny)
{
*y1 = miny;
*h = maxy - miny + 1;
}
}
void Font::getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
{
if (str.length() != 0)
{
getTextBounds(const_cast<char *>(str.c_str()), x, y, x1, y1, w, h);
}
}
void Font::getTextBounds(const __FlashStringHelper *str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w,
uint16_t *h)
{
uint8_t *s = (uint8_t *)str, c;
*x1 = x;
*y1 = y;
*w = *h = 0;
int16_t minx = width(), miny = height(), maxx = -1, maxy = -1;
while ((c = pgm_read_byte(s++)))
charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy);
if (maxx >= minx)
{
*x1 = minx;
*w = maxx - minx + 1;
}
if (maxy >= miny)
{
*y1 = miny;
*h = maxy - miny + 1;
}
}

View File

@ -1,64 +0,0 @@
#ifndef __FONT_H__
#define __FONT_H__
#include "Arduino.h"
#include "Print.h"
#include "../libs/GFXFont/gfxfont.h"
#include "../libs/GFXFont/glcdfont.c"
class Font : public Print
{
public:
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
virtual int16_t width() = 0;
virtual int16_t height() = 0;
virtual size_t write(uint8_t);
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size);
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y);
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w,
uint16_t *h);
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void setTextSize(uint8_t s);
void setTextSize(uint8_t sx, uint8_t sy);
void setFont(const GFXfont *f = NULL);
int16_t getCursorX();
int16_t getCursorY();
void setCursor(int16_t x, int16_t y);
void setTextColor(uint16_t c);
void setTextColor(uint16_t c, uint16_t bg);
void setTextWrap(bool w);
void cp437(bool x);
private:
int16_t cursor_x = 0;
int16_t cursor_y = 0;
uint16_t textcolor, textbgcolor;
uint8_t textsize_x, textsize_y;
bool wrap, _cp437;
virtual void startWrite(void) = 0;
virtual void writePixel(int16_t x, int16_t y, uint16_t color) = 0;
virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) = 0;
virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) = 0;
virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) = 0;
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) = 0;
virtual void endWrite(void) = 0;
protected:
GFXfont *gfxFont;
void charBounds(char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy);
};
#endif

View File

@ -13,19 +13,6 @@
}
#endif
Graphics::Graphics(int16_t w, int16_t h)
{
_width = WIDTH = w;
_height = HEIGHT = h;
setRotation(0);
setCursor(0, 0);
setTextSize(1);
setTextColor(0xFFFF, 0xFFFF);
setTextWrap(true);
cp437(false);
gfxFont = NULL;
}
void Graphics::setRotation(uint8_t x)
{
rotation = (x & 3);
@ -84,7 +71,7 @@ void Graphics::writePixel(int16_t x0, int16_t y0, uint16_t color)
int x = x0 >> 3;
int x_sub = x0 & 7;
uint8_t temp = *(_partial + 100 * y0 + x);
*(_partial + 100 * y0 + x) = ~pixelMaskLUT[x_sub] & temp | (color ? pixelMaskLUT[x_sub] : 0);
*(_partial + 100 * y0 + x) = (~pixelMaskLUT[x_sub] & temp) | (color ? pixelMaskLUT[x_sub] : 0);
}
else
{
@ -93,7 +80,7 @@ void Graphics::writePixel(int16_t x0, int16_t y0, uint16_t color)
int x_sub = x0 & 1;
uint8_t temp;
temp = *(D_memory4Bit + 400 * y0 + x);
*(D_memory4Bit + 400 * y0 + x) = pixelMaskGLUT[x_sub] & temp | (x_sub ? color : color << 4);
*(D_memory4Bit + 400 * y0 + x) = (pixelMaskGLUT[x_sub] & temp) | (x_sub ? color : color << 4);
}
}

View File

@ -1,9 +1,8 @@
#ifndef __Graphics_H__
#define __Graphics_H__
#ifndef __GRAPHICS_H__
#define __GRAPHICS_H__
#include "Arduino.h"
#include "Font.h"
#include "Image.h"
#include "Shapes.h"
@ -26,15 +25,15 @@
#endif
class Graphics : public Shapes, public Image, public Font
class Graphics : public Shapes, public Image
{
public:
Graphics(int16_t w, int16_t h);
Graphics(int16_t w, int16_t h) : Adafruit_GFX(w, h), Shapes(w, h), Image(w, h){};
void setRotation(uint8_t r);
uint8_t getRotation();
inline void drawPixel(int16_t x, int16_t y, uint16_t color) override;
void drawPixel(int16_t x, int16_t y, uint16_t color) override;
void selectDisplayMode(uint8_t _mode);
@ -65,7 +64,7 @@ class Graphics : public Shapes, public Image, public Font
private:
void startWrite(void) override;
inline void writePixel(int16_t x, int16_t y, uint16_t color) override;
void writePixel(int16_t x, int16_t y, uint16_t color) override;
void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
@ -75,9 +74,6 @@ class Graphics : public Shapes, public Image, public Font
uint8_t _displayMode = 0;
protected:
int16_t WIDTH, HEIGHT;
int16_t _width, _height;
uint8_t rotation = 0;
};
#endif

View File

@ -9,7 +9,7 @@
Image *_imagePtrJpeg = nullptr;
Image::Image()
Image::Image(int16_t w, int16_t h) : Adafruit_GFX(w, h)
{
_imagePtrJpeg = this;
}
@ -35,6 +35,7 @@ bool Image::drawImage(const char *path, int x, int y, bool dither, bool invert)
if (strstr(path, ".jpg") != NULL || strstr(path, ".jpeg") != NULL)
return drawJpegFromSd(path, x, y, dither, invert);
}
return 0;
};
bool Image::drawImage(const uint8_t *buf, int x, int y, int16_t w, int16_t h, uint8_t c, uint8_t bg)
@ -45,30 +46,7 @@ bool Image::drawImage(const uint8_t *buf, int x, int y, int16_t w, int16_t h, ui
drawBitmap(x, y, buf, w, h, c, bg);
else if (getDisplayMode() == INKPLATE_3BIT)
drawBitmap3Bit(x, y, buf, w, h);
}
void Image::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 byteWidth = (w + 7) >> 3; // Bitmap scanline pad = whole byte
uint8_t byte = 0;
startWrite();
for (int16_t j = 0; j < h; j++, y++)
{
for (int16_t i = 0; i < w; i++)
{
if (i & 7)
byte <<= 1;
else
byte = bitmap[j * byteWidth + (i >> 3)];
if (byte & 0x80)
writePixel(x + i, y, color);
else if (bg != 0xFFFF)
writePixel(x + i, y, bg);
}
}
endWrite();
return 1;
}
void Image::drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char *_p, int16_t _w, int16_t _h)

View File

@ -1,16 +1,17 @@
#ifndef __IMAGE_H__
#define __IMAGE_H__
#include "../libs/Adafruit-GFX-Library/Adafruit_GFX.h"
#include "../libs/SdFat/SdFat.h"
#include "Arduino.h"
#include "Network.h"
#include "WiFiClient.h"
#include "defines.h"
class Image : virtual public Network
class Image : virtual public Network, virtual public Adafruit_GFX
{
public:
Image();
Image(int16_t w, int16_t h);
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
@ -23,8 +24,11 @@ class Image : virtual public Network
bool drawImage(const String path, int x, int y, bool dither = 1, bool invert = 0);
bool drawImage(const uint8_t *buf, int x, int y, int16_t w, int16_t h, uint8_t c = BLACK, uint8_t bg = 0xFF);
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color,
uint16_t bg = 0xFFFF);
// Defined in Adafruit-GFX-Library, but should fit here
// void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
// void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color,
// uint16_t bg);
void drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char *_p, int16_t _w, int16_t _h);
bool drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool invert);

View File

@ -116,7 +116,7 @@ bool Image::drawBitmapFromWeb(const char *url, int x, int y, bool dither, bool i
ret = drawBitmapFromBuffer(buf, x, y, dither, invert);
free(buf);
return 1;
return ret;
}
bool Image::drawBitmapFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither, bool invert)
@ -127,7 +127,7 @@ bool Image::drawBitmapFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dit
ret = drawBitmapFromBuffer(buf, x, y, dither, invert);
free(buf);
return 1;
return ret;
}
bool Image::drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool invert)
@ -155,7 +155,7 @@ bool Image::drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool i
void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool dither, bool invert)
{
int16_t w = bmpHeader->width, h = bmpHeader->height;
int16_t w = bmpHeader->width;
int8_t c = bmpHeader->color;
startWrite();
@ -164,7 +164,7 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
switch (c)
{
case 1:
writePixel(x + j, y, (invert ^ (palette[0] < palette[1])) ^ !!(pixelBuffer[j >> 3] & (1 << (7 - j & 7))));
writePixel(x + j, y, (invert ^ (palette[0] < palette[1])) ^ !!(pixelBuffer[j >> 3] & (1 << (7 - (j & 7)))));
break;
// as for 2 bit, literally cannot find an example online or in PS, so skipped
case 4: {

View File

@ -13,322 +13,6 @@
}
#endif
void Shapes::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
{
startWrite();
writeFastVLine(x, y, h, color);
endWrite();
}
void Shapes::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
{
startWrite();
writeFastHLine(x, y, w, color);
endWrite();
}
void Shapes::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
startWrite();
writeFillRect(x, y, w, h, color);
endWrite();
}
void Shapes::fillScreen(uint16_t color)
{
startWrite();
fillRect(0, 0, width(), height(), color);
endWrite();
}
void Shapes::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
{
if (x0 == x1)
{
if (y0 > y1)
{
_swap_int16_t(y0, y1);
}
drawFastVLine(x0, y0, y1 - y0 + 1, color);
}
else if (y0 == y1)
{
if (x0 > x1)
{
_swap_int16_t(x0, x1);
}
drawFastHLine(x0, y0, x1 - x0 + 1, color);
}
else
{
startWrite();
writeLine(x0, y0, x1, y1, color);
endWrite();
}
}
void Shapes::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 Shapes::drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color)
{
startWrite();
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);
}
}
endWrite();
}
void Shapes::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();
}
void Shapes::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t corners, int16_t delta, uint16_t color)
{
startWrite();
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;
int16_t px = x;
int16_t py = y;
++delta;
while (x < y)
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (x < (y + 1))
{
if (corners & 1)
writeFastVLine(x0 + x, y0 - y, 2 * y + delta, color);
if (corners & 2)
writeFastVLine(x0 - x, y0 - y, 2 * y + delta, color);
}
if (y != py)
{
if (corners & 1)
writeFastVLine(x0 + py, y0 - px, 2 * px + delta, color);
if (corners & 2)
writeFastVLine(x0 - py, y0 - px, 2 * px + delta, color);
py = y;
}
px = x;
}
endWrite();
}
void Shapes::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();
}
void Shapes::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
{
int16_t max_radius = ((w < h) ? w : h) / 2;
if (r > max_radius)
r = max_radius;
startWrite();
writeFastHLine(x + r, y, w - 2 * r, color);
writeFastHLine(x + r, y + h - 1, w - 2 * r, color);
writeFastVLine(x, y + r, h - 2 * r, color);
writeFastVLine(x + w - 1, y + r, h - 2 * r, color);
endWrite();
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);
}
void Shapes::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
{
int16_t max_radius = ((w < h) ? w : h) / 2;
if (r > max_radius)
r = max_radius;
startWrite();
writeFillRect(x + r, y, w - 2 * r, h, color);
endWrite();
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);
}
void Shapes::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
{
startWrite();
writeLine(x0, y0, x1, y1, color);
writeLine(x1, y1, x2, y2, color);
writeLine(x2, y2, x0, y0, color);
endWrite();
}
void Shapes::fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
{
int16_t a, b, y, last;
if (y0 > y1)
{
_swap_int16_t(y0, y1);
_swap_int16_t(x0, x1);
}
if (y1 > y2)
{
_swap_int16_t(y2, y1);
_swap_int16_t(x2, x1);
}
if (y0 > y1)
{
_swap_int16_t(y0, y1);
_swap_int16_t(x0, x1);
}
startWrite();
if (y0 == y2)
{
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;
writeFastHLine(a, y0, b - a + 1, color);
endWrite();
return;
}
int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0, dx12 = x2 - x1, dy12 = y2 - y1;
int32_t sa = 0, sb = 0;
if (y1 == y2)
last = y1;
else
last = y1 - 1;
for (y = y0; y <= last; y++)
{
a = x0 + sa / dy01;
b = x0 + sb / dy02;
sa += dx01;
sb += dx02;
if (a > b)
_swap_int16_t(a, b);
writeFastHLine(a, y, b - a + 1, color);
}
sa = (int32_t)dx12 * (y - y1);
sb = (int32_t)dx02 * (y - y0);
for (; y <= y2; y++)
{
a = x1 + sa / dy12;
b = x0 + sb / dy02;
sa += dx12;
sb += dx02;
if (a > b)
_swap_int16_t(a, b);
writeFastHLine(a, y, b - a + 1, color);
}
endWrite();
}
void Shapes::drawElipse(int rx, int ry, int xc, int yc, int c)
{
float dx, dy, d1, d2, x, y;
@ -437,7 +121,6 @@ void Shapes::drawThickLine(int x1, int y1, int x2, int y2, int color, float thic
float deg = atan2f((float)(y2 - y1), (float)(x2 - x1));
float l1 = tan(deg);
float k1 = (float)y1 - l1 * (float)x1;
float degShift = (l1 < 0 ? M_PI_2 : -M_PI_2);

View File

@ -1,34 +1,19 @@
#ifndef __SHAPES_H__
#define __SHAPES_H__
#include "../libs/Adafruit-GFX-Library/Adafruit_GFX.h"
#include "Arduino.h"
#include "Triangulate.h"
class Shapes
class Shapes : virtual public Adafruit_GFX
{
public:
Shapes(int16_t w, int16_t h) : Adafruit_GFX(w, h){};
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
virtual void selectDisplayMode(uint8_t _mode) = 0;
virtual uint8_t getDisplayMode() = 0;
virtual int16_t width() = 0;
virtual int16_t height() = 0;
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void fillScreen(uint16_t color);
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color);
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color);
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
void drawElipse(int rx, int ry, int xc, int yc, int c);
void fillElipse(int rx, int ry, int xc, int yc, int c);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,403 @@
#ifndef _ADAFRUIT_GFX_H
#define _ADAFRUIT_GFX_H
#if ARDUINO >= 100
#include "Arduino.h"
#include "Print.h"
#else
#include "WProgram.h"
#endif
#include "gfxfont.h"
/// A generic graphics superclass that can handle all sorts of drawing. At a
/// minimum you can subclass and provide drawPixel(). At a maximum you can do a
/// ton of overriding to optimize. Used for any/all Adafruit displays!
class Adafruit_GFX : public Print
{
public:
Adafruit_GFX(int16_t w, int16_t h); // Constructor
/**********************************************************************/
/*!
@brief Draw to the screen/framebuffer/etc.
Must be overridden in subclass.
@param x X coordinate in pixels
@param y Y coordinate in pixels
@param color 16-bit pixel color.
*/
/**********************************************************************/
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(bool i);
// BASIC DRAW API
// These MAY be overridden by the subclass to provide device-specific
// optimized code. Otherwise 'generic' versions are used.
// It's good to implement those, even if using transaction API
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
virtual void fillScreen(uint16_t color);
// Optional and probably not necessary to change
virtual void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
virtual void 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 drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color);
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color);
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
void drawXBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
void drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
void drawRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
void drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
void drawRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size);
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y);
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w,
uint16_t *h);
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void setTextSize(uint8_t s);
void setTextSize(uint8_t sx, uint8_t sy);
void setFont(const GFXfont *f = NULL);
/**********************************************************************/
/*!
@brief Set text cursor location
@param x X coordinate in pixels
@param y Y coordinate in pixels
*/
/**********************************************************************/
void setCursor(int16_t x, int16_t y)
{
cursor_x = x;
cursor_y = y;
}
/**********************************************************************/
/*!
@brief Set text font color with transparant background
@param c 16-bit 5-6-5 Color to draw text with
@note For 'transparent' background, background and foreground
are set to same color rather than using a separate flag.
*/
/**********************************************************************/
void setTextColor(uint16_t c)
{
textcolor = textbgcolor = c;
}
/**********************************************************************/
/*!
@brief Set text font color with custom background color
@param c 16-bit 5-6-5 Color to draw text with
@param bg 16-bit 5-6-5 Color to draw background/fill with
*/
/**********************************************************************/
void setTextColor(uint16_t c, uint16_t bg)
{
textcolor = c;
textbgcolor = bg;
}
/**********************************************************************/
/*!
@brief Set whether text that is too long for the screen width should
automatically wrap around to the next line (else clip right).
@param w true for wrapping, false for clipping
*/
/**********************************************************************/
void setTextWrap(bool w)
{
wrap = w;
}
/**********************************************************************/
/*!
@brief Enable (or disable) Code Page 437-compatible charset.
There was an error in glcdfont.c for the longest time -- one
character (#176, the 'light shade' block) was missing -- this
threw off the index of every character that followed it.
But a TON of code has been written with the erroneous
character indices. By default, the library uses the original
'wrong' behavior and old sketches will still work. Pass
'true' to this function to use correct CP437 character values
in your code.
@param x true = enable (new behavior), false = disable (old behavior)
*/
/**********************************************************************/
void cp437(bool x = true)
{
_cp437 = x;
}
using Print::write;
#if ARDUINO >= 100
virtual size_t write(uint8_t);
#else
virtual void write(uint8_t);
#endif
/************************************************************************/
/*!
@brief Get width of the display, accounting for current rotation
@returns Width in pixels
*/
/************************************************************************/
int16_t width(void) const
{
return _width;
};
/************************************************************************/
/*!
@brief Get height of the display, accounting for current rotation
@returns Height in pixels
*/
/************************************************************************/
int16_t height(void) const
{
return _height;
}
/************************************************************************/
/*!
@brief Get rotation setting for display
@returns 0 thru 3 corresponding to 4 cardinal rotations
*/
/************************************************************************/
uint8_t getRotation(void) const
{
return rotation;
}
// get current cursor position (get rotation safe maximum values,
// using: width() for x, height() for y)
/************************************************************************/
/*!
@brief Get text cursor X location
@returns X coordinate in pixels
*/
/************************************************************************/
int16_t getCursorX(void) const
{
return cursor_x;
}
/************************************************************************/
/*!
@brief Get text cursor Y location
@returns Y coordinate in pixels
*/
/************************************************************************/
int16_t getCursorY(void) const
{
return cursor_y;
};
protected:
void charBounds(unsigned char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx,
int16_t *maxy);
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
int16_t cursor_x; ///< x location to start print()ing text
int16_t cursor_y; ///< y location to start print()ing text
uint16_t textcolor; ///< 16-bit background color for print()
uint16_t textbgcolor; ///< 16-bit text color for print()
uint8_t textsize_x; ///< Desired magnification in X-axis of text to print()
uint8_t textsize_y; ///< Desired magnification in Y-axis of text to print()
uint8_t rotation; ///< Display rotation (0 thru 3)
bool wrap; ///< If set, 'wrap' text at right edge of display
bool _cp437; ///< If set, use correct CP437 charset (default is off)
GFXfont *gfxFont; ///< Pointer to special font
};
/// A simple drawn button UI element
class Adafruit_GFX_Button
{
public:
Adafruit_GFX_Button(void);
// "Classic" initButton() uses center & size
void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
uint16_t textcolor, char *label, uint8_t textsize);
void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
uint16_t textcolor, char *label, uint8_t textsize_x, uint8_t textsize_y);
// New/alt initButton() uses upper-left corner & size
void initButtonUL(Adafruit_GFX *gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h, uint16_t outline,
uint16_t fill, uint16_t textcolor, char *label, uint8_t textsize);
void initButtonUL(Adafruit_GFX *gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h, uint16_t outline,
uint16_t fill, uint16_t textcolor, char *label, uint8_t textsize_x, uint8_t textsize_y);
void drawButton(bool inverted = false);
bool contains(int16_t x, int16_t y);
/**********************************************************************/
/*!
@brief Sets button state, should be done by some touch function
@param p True for pressed, false for not.
*/
/**********************************************************************/
void press(bool p)
{
laststate = currstate;
currstate = p;
}
bool justPressed();
bool justReleased();
/**********************************************************************/
/*!
@brief Query whether the button is currently pressed
@returns True if pressed
*/
/**********************************************************************/
bool isPressed(void)
{
return currstate;
};
private:
Adafruit_GFX *_gfx;
int16_t _x1, _y1; // Coordinates of top-left corner
uint16_t _w, _h;
uint8_t _textsize_x;
uint8_t _textsize_y;
uint16_t _outlinecolor, _fillcolor, _textcolor;
char _label[10];
bool currstate, laststate;
};
/// A GFX 1-bit canvas context for graphics
class GFXcanvas1 : public Adafruit_GFX
{
public:
GFXcanvas1(uint16_t w, uint16_t h);
~GFXcanvas1(void);
void drawPixel(int16_t x, int16_t y, uint16_t color);
void fillScreen(uint16_t color);
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
bool getPixel(int16_t x, int16_t y) const;
/**********************************************************************/
/*!
@brief Get a pointer to the internal buffer memory
@returns A pointer to the allocated buffer
*/
/**********************************************************************/
uint8_t *getBuffer(void) const
{
return buffer;
}
protected:
bool getRawPixel(int16_t x, int16_t y) const;
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
private:
uint8_t *buffer;
#ifdef __AVR__
// Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR
static const uint8_t PROGMEM GFXsetBit[], GFXclrBit[];
#endif
};
/// A GFX 8-bit canvas context for graphics
class GFXcanvas8 : public Adafruit_GFX
{
public:
GFXcanvas8(uint16_t w, uint16_t h);
~GFXcanvas8(void);
void drawPixel(int16_t x, int16_t y, uint16_t color);
void fillScreen(uint16_t color);
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
uint8_t getPixel(int16_t x, int16_t y) const;
/**********************************************************************/
/*!
@brief Get a pointer to the internal buffer memory
@returns A pointer to the allocated buffer
*/
/**********************************************************************/
uint8_t *getBuffer(void) const
{
return buffer;
}
protected:
uint8_t getRawPixel(int16_t x, int16_t y) const;
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
private:
uint8_t *buffer;
};
/// A GFX 16-bit canvas context for graphics
class GFXcanvas16 : public Adafruit_GFX
{
public:
GFXcanvas16(uint16_t w, uint16_t h);
~GFXcanvas16(void);
void drawPixel(int16_t x, int16_t y, uint16_t color);
void fillScreen(uint16_t color);
void byteSwap(void);
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
uint16_t getPixel(int16_t x, int16_t y) const;
/**********************************************************************/
/*!
@brief Get a pointer to the internal buffer memory
@returns A pointer to the allocated buffer
*/
/**********************************************************************/
uint16_t *getBuffer(void) const
{
return buffer;
}
protected:
uint16_t getRawPixel(int16_t x, int16_t y) const;
void drawFastRawVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastRawHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
private:
uint16_t *buffer;
};
#endif // _ADAFRUIT_GFX_H