Add smooth arc drawing function
Update ESP8266 architecture reference Add pushMaskedImage() to render 16bpp images with a 1bpp mask (used for transparent PNG images plus with sprites) New functions added using drawArc: drawSmoothArc drawSmoothCircle drawSmoothRoundRect New sqrt_fraction() added to improve smooth graphics performance on processors without a FPU (e.g. RP2040) Faster alphaBlend() function added which retains 6bpp for green Rename swap_coord() to transpose()
This commit is contained in:
parent
ea82a7c15a
commit
82d232adfc
|
|
@ -1257,8 +1257,8 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const u
|
||||||
// Intentionally not constrained to viewport area, does not manage 1bpp rotations
|
// Intentionally not constrained to viewport area, does not manage 1bpp rotations
|
||||||
void TFT_eSprite::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
void TFT_eSprite::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||||
{
|
{
|
||||||
if (x0 > x1) swap_coord(x0, x1);
|
if (x0 > x1) transpose(x0, x1);
|
||||||
if (y0 > y1) swap_coord(y0, y1);
|
if (y0 > y1) transpose(y0, y1);
|
||||||
|
|
||||||
int32_t w = width();
|
int32_t w = width();
|
||||||
int32_t h = height();
|
int32_t h = height();
|
||||||
|
|
@ -1700,13 +1700,13 @@ void TFT_eSprite::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint3
|
||||||
|
|
||||||
bool steep = abs(y1 - y0) > abs(x1 - x0);
|
bool steep = abs(y1 - y0) > abs(x1 - x0);
|
||||||
if (steep) {
|
if (steep) {
|
||||||
swap_coord(x0, y0);
|
transpose(x0, y0);
|
||||||
swap_coord(x1, y1);
|
transpose(x1, y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x0 > x1) {
|
if (x0 > x1) {
|
||||||
swap_coord(x0, x1);
|
transpose(x0, x1);
|
||||||
swap_coord(y0, y1);
|
transpose(y0, y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t dx = x1 - x0, dy = abs(y1 - y0);;
|
int32_t dx = x1 - x0, dy = abs(y1 - y0);;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
#define DMA_BUSY_CHECK // DMA not available, leave blank
|
#define DMA_BUSY_CHECK // DMA not available, leave blank
|
||||||
|
|
||||||
// Initialise processor specific SPI functions, used by init()
|
// Initialise processor specific SPI functions, used by init()
|
||||||
#if (!defined (SUPPORT_TRANSACTIONS) && defined (ESP8266))
|
#if (!defined (SUPPORT_TRANSACTIONS) && defined (ARDUINO_ARCH_ESP8266))
|
||||||
#define INIT_TFT_DATA_BUS \
|
#define INIT_TFT_DATA_BUS \
|
||||||
spi.setBitOrder(MSBFIRST); \
|
spi.setBitOrder(MSBFIRST); \
|
||||||
spi.setDataMode(TFT_SPI_MODE); \
|
spi.setDataMode(TFT_SPI_MODE); \
|
||||||
|
|
|
||||||
|
|
@ -577,7 +577,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#ifdef RP2040_DMA // DMA functions for 16 bit SPI and 8 bit parallel displays
|
#ifdef RP2040_DMA // DMA functions for 16 bit SPI and 8/16 bit parallel displays
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/*
|
/*
|
||||||
These are created in header file:
|
These are created in header file:
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,20 @@
|
||||||
#define DMA_BUSY_CHECK
|
#define DMA_BUSY_CHECK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Handle high performance MHS RPi display type
|
||||||
|
#if defined (MHS_DISPLAY_TYPE) && !defined (RPI_DISPLAY_TYPE)
|
||||||
|
#define RPI_DISPLAY_TYPE
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined (RP2040_PIO_INTERFACE) // SPI
|
#if !defined (RP2040_PIO_INTERFACE) // SPI
|
||||||
|
|
||||||
|
#if defined (MHS_DISPLAY_TYPE) // High speed RPi TFT type always needs 16 bit transfers
|
||||||
|
// This swaps to 16 bit mode, used for commands so wait avoids clash with DC timing
|
||||||
|
#define INIT_TFT_DATA_BUS hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS)
|
||||||
|
#else
|
||||||
// Initialise processor specific SPI functions, used by init()
|
// Initialise processor specific SPI functions, used by init()
|
||||||
#define INIT_TFT_DATA_BUS // Not used
|
#define INIT_TFT_DATA_BUS // Not used
|
||||||
|
#endif
|
||||||
|
|
||||||
// Wait for tx to end, flush rx FIFO, clear rx overrun
|
// Wait for tx to end, flush rx FIFO, clear rx overrun
|
||||||
#define SPI_BUSY_CHECK while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
#define SPI_BUSY_CHECK while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||||
|
|
@ -141,7 +152,7 @@
|
||||||
#if !defined (RP2040_PIO_INTERFACE)// SPI
|
#if !defined (RP2040_PIO_INTERFACE)// SPI
|
||||||
//#define DC_C sio_hw->gpio_clr = (1ul << TFT_DC)
|
//#define DC_C sio_hw->gpio_clr = (1ul << TFT_DC)
|
||||||
//#define DC_D sio_hw->gpio_set = (1ul << TFT_DC)
|
//#define DC_D sio_hw->gpio_set = (1ul << TFT_DC)
|
||||||
#if defined (RPI_DISPLAY_TYPE)
|
#if defined (RPI_DISPLAY_TYPE) && !defined (MHS_DISPLAY_TYPE)
|
||||||
#define DC_C digitalWrite(TFT_DC, LOW);
|
#define DC_C digitalWrite(TFT_DC, LOW);
|
||||||
#define DC_D digitalWrite(TFT_DC, HIGH);
|
#define DC_D digitalWrite(TFT_DC, HIGH);
|
||||||
#else
|
#else
|
||||||
|
|
@ -167,7 +178,7 @@
|
||||||
#define CS_H // No macro allocated so it generates no code
|
#define CS_H // No macro allocated so it generates no code
|
||||||
#else
|
#else
|
||||||
#if !defined (RP2040_PIO_INTERFACE) // SPI
|
#if !defined (RP2040_PIO_INTERFACE) // SPI
|
||||||
#if defined (RPI_DISPLAY_TYPE)
|
#if defined (RPI_DISPLAY_TYPE) && !defined (MHS_DISPLAY_TYPE)
|
||||||
#define CS_L digitalWrite(TFT_CS, LOW);
|
#define CS_L digitalWrite(TFT_CS, LOW);
|
||||||
#define CS_H digitalWrite(TFT_CS, HIGH);
|
#define CS_H digitalWrite(TFT_CS, HIGH);
|
||||||
#else
|
#else
|
||||||
|
|
@ -287,7 +298,28 @@
|
||||||
// Macros to write commands/pixel colour data to other displays
|
// Macros to write commands/pixel colour data to other displays
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#else
|
#else
|
||||||
#if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers
|
#if defined (MHS_DISPLAY_TYPE) // High speed RPi TFT type always needs 16 bit transfers
|
||||||
|
// This swaps to 16 bit mode, used for commands so wait avoids clash with DC timing
|
||||||
|
#define tft_Write_8(C) while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||||
|
hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); \
|
||||||
|
spi_get_hw(SPI_X)->dr = (uint32_t)((C) | ((C)<<8)); \
|
||||||
|
while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||||
|
|
||||||
|
// Note: the following macros do not wait for the end of transmission
|
||||||
|
|
||||||
|
#define tft_Write_16(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||||
|
|
||||||
|
#define tft_Write_16N(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||||
|
|
||||||
|
#define tft_Write_16S(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)<<8 | (C)>>8
|
||||||
|
|
||||||
|
#define tft_Write_32(C) spi_get_hw(SPI_X)->dr = (uint32_t)((C)>>16); spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||||
|
|
||||||
|
#define tft_Write_32C(C,D) spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(D)
|
||||||
|
|
||||||
|
#define tft_Write_32D(C) spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||||
|
|
||||||
|
#elif defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers
|
||||||
#define tft_Write_8(C) spi.transfer(C); spi.transfer(C)
|
#define tft_Write_8(C) spi.transfer(C); spi.transfer(C)
|
||||||
#define tft_Write_16(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0))
|
#define tft_Write_16(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0))
|
||||||
#define tft_Write_16N(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0))
|
#define tft_Write_16N(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0))
|
||||||
|
|
|
||||||
648
TFT_eSPI.cpp
648
TFT_eSPI.cpp
|
|
@ -149,7 +149,6 @@ inline void TFT_eSPI::begin_tft_read(void){
|
||||||
SET_BUS_READ_MODE;
|
SET_BUS_READ_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: end_tft_read (was called spi_end_read)
|
** Function name: end_tft_read (was called spi_end_read)
|
||||||
** Description: End transaction for reads and deselect TFT
|
** Description: End transaction for reads and deselect TFT
|
||||||
|
|
@ -233,7 +232,6 @@ void TFT_eSPI::setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDa
|
||||||
|
|
||||||
//Serial.print(" _vpX=");Serial.print( _vpX);Serial.print(", _vpY=");Serial.print( _vpY);
|
//Serial.print(" _vpX=");Serial.print( _vpX);Serial.print(", _vpY=");Serial.print( _vpY);
|
||||||
//Serial.print(", _vpW=");Serial.print(_vpW);Serial.print(", _vpH=");Serial.println(_vpH);
|
//Serial.print(", _vpW=");Serial.print(_vpW);Serial.print(", _vpH=");Serial.println(_vpH);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
|
|
@ -866,6 +864,48 @@ void TFT_eSPI::setRotation(uint8_t m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: getRotation
|
||||||
|
** Description: Return the rotation value (as used by setRotation())
|
||||||
|
***************************************************************************************/
|
||||||
|
uint8_t TFT_eSPI::getRotation(void)
|
||||||
|
{
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: setOrigin
|
||||||
|
** Description: Set graphics origin to position x,y wrt to top left corner
|
||||||
|
***************************************************************************************/
|
||||||
|
//Note: setRotation, setViewport and resetViewport will revert origin to top left
|
||||||
|
void TFT_eSPI::setOrigin(int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
_xDatum = x;
|
||||||
|
_yDatum = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: getOriginX
|
||||||
|
** Description: Set graphics origin to position x
|
||||||
|
***************************************************************************************/
|
||||||
|
int32_t TFT_eSPI::getOriginX(void)
|
||||||
|
{
|
||||||
|
return _xDatum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: getOriginY
|
||||||
|
** Description: Set graphics origin to position y
|
||||||
|
***************************************************************************************/
|
||||||
|
int32_t TFT_eSPI::getOriginY(void)
|
||||||
|
{
|
||||||
|
return _yDatum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: commandList, used for FLASH based lists only (e.g. ST7735)
|
** Function name: commandList, used for FLASH based lists only (e.g. ST7735)
|
||||||
** Description: Get initialisation commands from FLASH and send to TFT
|
** Description: Get initialisation commands from FLASH and send to TFT
|
||||||
|
|
@ -1998,6 +2038,91 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da
|
||||||
end_tft_write();
|
end_tft_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: pushMaskedImage
|
||||||
|
** Description: Render a 16 bit colour image with a 1bpp mask
|
||||||
|
***************************************************************************************/
|
||||||
|
// Can be used with a 16bpp sprite and a 1bpp sprite for the mask
|
||||||
|
void TFT_eSPI::pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask)
|
||||||
|
{
|
||||||
|
if (_vpOoB || w < 1 || h < 1) return;
|
||||||
|
|
||||||
|
// To simplify mask handling the window clipping is done by the pushImage function
|
||||||
|
// Each mask image line assumed to be padded to and integer number of bytes & padding bits are 0
|
||||||
|
|
||||||
|
begin_tft_write();
|
||||||
|
inTransaction = true;
|
||||||
|
|
||||||
|
uint8_t *mptr = mask;
|
||||||
|
uint8_t *eptr = mask + ((w + 7) >> 3);
|
||||||
|
uint16_t *iptr = img;
|
||||||
|
uint32_t setCount = 0;
|
||||||
|
|
||||||
|
// For each line in the image
|
||||||
|
while (h--) {
|
||||||
|
uint32_t xp = 0;
|
||||||
|
uint32_t clearCount = 0;
|
||||||
|
uint8_t mbyte= *mptr++;
|
||||||
|
uint32_t bits = 8;
|
||||||
|
// Scan through each byte of the bitmap and determine run lengths
|
||||||
|
do {
|
||||||
|
setCount = 0;
|
||||||
|
|
||||||
|
//Get run length for clear bits to determine x offset
|
||||||
|
while ((mbyte & 0x80) == 0x00) {
|
||||||
|
// Check if remaining bits in byte are clear (reduce shifts)
|
||||||
|
if (mbyte == 0) {
|
||||||
|
clearCount += bits; // bits not always 8 here
|
||||||
|
if (mptr >= eptr) break; // end of line
|
||||||
|
mbyte = *mptr++;
|
||||||
|
bits = 8;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mbyte = mbyte << 1; // 0's shifted in
|
||||||
|
clearCount ++;
|
||||||
|
if (--bits) continue;;
|
||||||
|
if (mptr >= eptr) break;
|
||||||
|
mbyte = *mptr++;
|
||||||
|
bits = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get run length for set bits to determine render width
|
||||||
|
while ((mbyte & 0x80) == 0x80) {
|
||||||
|
// Check if all bits are set (reduces shifts)
|
||||||
|
if (mbyte == 0xFF) {
|
||||||
|
setCount += bits;
|
||||||
|
if (mptr >= eptr) break;
|
||||||
|
mbyte = *mptr++;
|
||||||
|
//bits = 8; // NR, bits always 8 here unless 1's shifted in
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mbyte = mbyte << 1; //or mbyte += mbyte + 1 to shift in 1's
|
||||||
|
setCount ++;
|
||||||
|
if (--bits) continue;
|
||||||
|
if (mptr >= eptr) break;
|
||||||
|
mbyte = *mptr++;
|
||||||
|
bits = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A mask boundary or mask end has been found, so render the pixel line
|
||||||
|
if (setCount) {
|
||||||
|
xp += clearCount;
|
||||||
|
clearCount = 0;
|
||||||
|
pushImage(x + xp, y, setCount, 1, iptr + xp); // pushImage handles clipping
|
||||||
|
//pushImageDMA(x + xp, y, setCount, 1, iptr + xp);
|
||||||
|
xp += setCount;
|
||||||
|
}
|
||||||
|
} while (setCount || mptr < eptr);
|
||||||
|
|
||||||
|
y++;
|
||||||
|
iptr += w;
|
||||||
|
eptr += ((w + 7) >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
inTransaction = lockTransaction;
|
||||||
|
end_tft_write();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: setSwapBytes
|
** Function name: setSwapBytes
|
||||||
|
|
@ -2510,13 +2635,13 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in
|
||||||
|
|
||||||
// Sort coordinates by Y order (y2 >= y1 >= y0)
|
// Sort coordinates by Y order (y2 >= y1 >= y0)
|
||||||
if (y0 > y1) {
|
if (y0 > y1) {
|
||||||
swap_coord(y0, y1); swap_coord(x0, x1);
|
transpose(y0, y1); transpose(x0, x1);
|
||||||
}
|
}
|
||||||
if (y1 > y2) {
|
if (y1 > y2) {
|
||||||
swap_coord(y2, y1); swap_coord(x2, x1);
|
transpose(y2, y1); transpose(x2, x1);
|
||||||
}
|
}
|
||||||
if (y0 > y1) {
|
if (y0 > y1) {
|
||||||
swap_coord(y0, y1); swap_coord(x0, x1);
|
transpose(y0, y1); transpose(x0, x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
|
if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
|
||||||
|
|
@ -2557,7 +2682,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in
|
||||||
sa += dx01;
|
sa += dx01;
|
||||||
sb += dx02;
|
sb += dx02;
|
||||||
|
|
||||||
if (a > b) swap_coord(a, b);
|
if (a > b) transpose(a, b);
|
||||||
drawFastHLine(a, y, b - a + 1, color);
|
drawFastHLine(a, y, b - a + 1, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2571,7 +2696,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in
|
||||||
sa += dx12;
|
sa += dx12;
|
||||||
sb += dx02;
|
sb += dx02;
|
||||||
|
|
||||||
if (a > b) swap_coord(a, b);
|
if (a > b) transpose(a, b);
|
||||||
drawFastHLine(a, y, b - a + 1, color);
|
drawFastHLine(a, y, b - a + 1, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2837,15 +2962,6 @@ uint16_t TFT_eSPI::getTextPadding(void)
|
||||||
return padX;
|
return padX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************************
|
|
||||||
** Function name: getRotation
|
|
||||||
** Description: Return the rotation value (as used by setRotation())
|
|
||||||
***************************************************************************************/
|
|
||||||
uint8_t TFT_eSPI::getRotation(void)
|
|
||||||
{
|
|
||||||
return rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: getTextDatum
|
** Function name: getTextDatum
|
||||||
** Description: Return the text datum value (as used by setTextDatum())
|
** Description: Return the text datum value (as used by setTextDatum())
|
||||||
|
|
@ -3194,7 +3310,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||||
addr_col = 0xFFFF;
|
addr_col = 0xFFFF;
|
||||||
|
|
||||||
#if defined (ILI9225_DRIVER)
|
#if defined (ILI9225_DRIVER)
|
||||||
if (rotation & 0x01) { swap_coord(x0, y0); swap_coord(x1, y1); }
|
if (rotation & 0x01) { transpose(x0, y0); transpose(x1, y1); }
|
||||||
SPI_BUSY_CHECK;
|
SPI_BUSY_CHECK;
|
||||||
DC_C; tft_Write_8(TFT_CASET1);
|
DC_C; tft_Write_8(TFT_CASET1);
|
||||||
DC_D; tft_Write_16(x0);
|
DC_D; tft_Write_16(x0);
|
||||||
|
|
@ -3222,8 +3338,8 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||||
#endif
|
#endif
|
||||||
#elif defined (SSD1351_DRIVER)
|
#elif defined (SSD1351_DRIVER)
|
||||||
if (rotation & 1) {
|
if (rotation & 1) {
|
||||||
swap_coord(x0, y0);
|
transpose(x0, y0);
|
||||||
swap_coord(x1, y1);
|
transpose(x1, y1);
|
||||||
}
|
}
|
||||||
SPI_BUSY_CHECK;
|
SPI_BUSY_CHECK;
|
||||||
DC_C; tft_Write_8(TFT_CASET);
|
DC_C; tft_Write_8(TFT_CASET);
|
||||||
|
|
@ -3234,7 +3350,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||||
DC_D;
|
DC_D;
|
||||||
#else
|
#else
|
||||||
#if defined (SSD1963_DRIVER)
|
#if defined (SSD1963_DRIVER)
|
||||||
if ((rotation & 0x1) == 0) { swap_coord(x0, y0); swap_coord(x1, y1); }
|
if ((rotation & 0x1) == 0) { transpose(x0, y0); transpose(x1, y1); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CGRAM_OFFSET
|
#ifdef CGRAM_OFFSET
|
||||||
|
|
@ -3326,7 +3442,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
|
||||||
addr_row = 0xFFFF;
|
addr_row = 0xFFFF;
|
||||||
|
|
||||||
#if defined (SSD1963_DRIVER)
|
#if defined (SSD1963_DRIVER)
|
||||||
if ((rotation & 0x1) == 0) { swap_coord(xs, ys); swap_coord(xe, ye); }
|
if ((rotation & 0x1) == 0) { transpose(xs, ys); transpose(xe, ye); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CGRAM_OFFSET
|
#ifdef CGRAM_OFFSET
|
||||||
|
|
@ -3420,7 +3536,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
|
||||||
begin_tft_write();
|
begin_tft_write();
|
||||||
|
|
||||||
#if defined (ILI9225_DRIVER)
|
#if defined (ILI9225_DRIVER)
|
||||||
if (rotation & 0x01) { swap_coord(x, y); }
|
if (rotation & 0x01) { transpose(x, y); }
|
||||||
SPI_BUSY_CHECK;
|
SPI_BUSY_CHECK;
|
||||||
|
|
||||||
// Set window to full screen to optimise sequential pixel rendering
|
// Set window to full screen to optimise sequential pixel rendering
|
||||||
|
|
@ -3455,7 +3571,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
|
||||||
#elif (defined (ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) && !defined (SSD1351_DRIVER)
|
#elif (defined (ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) && !defined (SSD1351_DRIVER)
|
||||||
|
|
||||||
#if defined (SSD1963_DRIVER)
|
#if defined (SSD1963_DRIVER)
|
||||||
if ((rotation & 0x1) == 0) { swap_coord(x, y); }
|
if ((rotation & 0x1) == 0) { transpose(x, y); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(RP2040_PIO_INTERFACE)
|
#if !defined(RP2040_PIO_INTERFACE)
|
||||||
|
|
@ -3535,13 +3651,13 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined (SSD1963_DRIVER)
|
#if defined (SSD1963_DRIVER)
|
||||||
if ((rotation & 0x1) == 0) { swap_coord(x, y); }
|
if ((rotation & 0x1) == 0) { transpose(x, y); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SPI_BUSY_CHECK;
|
SPI_BUSY_CHECK;
|
||||||
|
|
||||||
#if defined (SSD1351_DRIVER)
|
#if defined (SSD1351_DRIVER)
|
||||||
if (rotation & 0x1) { swap_coord(x, y); }
|
if (rotation & 0x1) { transpose(x, y); }
|
||||||
// No need to send x if it has not changed (speeds things up)
|
// No need to send x if it has not changed (speeds things up)
|
||||||
if (addr_col != x) {
|
if (addr_col != x) {
|
||||||
DC_C; tft_Write_8(TFT_CASET);
|
DC_C; tft_Write_8(TFT_CASET);
|
||||||
|
|
@ -3693,13 +3809,13 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
|
||||||
|
|
||||||
bool steep = abs(y1 - y0) > abs(x1 - x0);
|
bool steep = abs(y1 - y0) > abs(x1 - x0);
|
||||||
if (steep) {
|
if (steep) {
|
||||||
swap_coord(x0, y0);
|
transpose(x0, y0);
|
||||||
swap_coord(x1, y1);
|
transpose(x1, y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x0 > x1) {
|
if (x0 > x1) {
|
||||||
swap_coord(x0, x1);
|
transpose(x0, x1);
|
||||||
swap_coord(y0, y1);
|
transpose(y0, y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t dx = x1 - x0, dy = abs(y1 - y0);;
|
int32_t dx = x1 - x0, dy = abs(y1 - y0);;
|
||||||
|
|
@ -3750,6 +3866,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
|
||||||
constexpr float PixelAlphaGain = 255.0;
|
constexpr float PixelAlphaGain = 255.0;
|
||||||
constexpr float LoAlphaTheshold = 1.0/32.0;
|
constexpr float LoAlphaTheshold = 1.0/32.0;
|
||||||
constexpr float HiAlphaTheshold = 1.0 - LoAlphaTheshold;
|
constexpr float HiAlphaTheshold = 1.0 - LoAlphaTheshold;
|
||||||
|
constexpr float deg2rad = 3.14159265359/180.0;
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: drawPixel (alpha blended)
|
** Function name: drawPixel (alpha blended)
|
||||||
|
|
@ -3763,6 +3880,291 @@ uint16_t TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: drawSmoothArc
|
||||||
|
** Description: Draw a smooth arc clockwise from 6 o'clock
|
||||||
|
***************************************************************************************/
|
||||||
|
void TFT_eSPI::drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t startAngle, int32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds)
|
||||||
|
// Centre at x,y
|
||||||
|
// r = arc outer radius, ir = arc inner radius. Inclusive so arc thickness = r - ir + 1
|
||||||
|
// Angles in range 0-360
|
||||||
|
// Arc foreground colour anti-aliased with background colour at edges
|
||||||
|
// anti-aliased roundEnd is optional, default is anti-aliased straight end
|
||||||
|
// Note: rounded ends extend the arc angle so can overlap, user sketch to manage this.
|
||||||
|
{
|
||||||
|
inTransaction = true;
|
||||||
|
|
||||||
|
if (endAngle != startAngle)
|
||||||
|
{
|
||||||
|
float sx = -sinf(startAngle * deg2rad);
|
||||||
|
float sy = +cosf(startAngle * deg2rad);
|
||||||
|
float ex = -sinf( endAngle * deg2rad);
|
||||||
|
float ey = +cosf( endAngle * deg2rad);
|
||||||
|
|
||||||
|
if (roundEnds)
|
||||||
|
{ // Round ends
|
||||||
|
sx = sx * (r + ir)/2.0 + x;
|
||||||
|
sy = sy * (r + ir)/2.0 + y;
|
||||||
|
drawSpot(sx, sy, (r - ir)/2.0, fg_color, bg_color);
|
||||||
|
|
||||||
|
ex = ex * (r + ir)/2.0 + x;
|
||||||
|
ey = ey * (r + ir)/2.0 + y;
|
||||||
|
drawSpot(ex, ey, (r - ir)/2.0, fg_color, bg_color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Square ends
|
||||||
|
float asx = sx * ir + x;
|
||||||
|
float asy = sy * ir + y;
|
||||||
|
float aex = sx * r + x;
|
||||||
|
float aey = sy * r + y;
|
||||||
|
drawWedgeLine(asx, asy, aex, aey, 0.3, 0.3, fg_color, bg_color);
|
||||||
|
|
||||||
|
asx = ex * ir + x;
|
||||||
|
asy = ey * ir + y;
|
||||||
|
aex = ex * r + x;
|
||||||
|
aey = ey * r + y;
|
||||||
|
drawWedgeLine(asx, asy, aex, aey, 0.3, 0.3, fg_color, bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endAngle > startAngle)
|
||||||
|
{
|
||||||
|
// Draw arc in single sweep
|
||||||
|
drawArc(x, y, r, ir, startAngle, endAngle, fg_color, bg_color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Arc sweeps through 6 o'clock so draw in two parts
|
||||||
|
drawArc(x, y, r, ir, startAngle, 360, fg_color, bg_color);
|
||||||
|
drawArc(x, y, r, ir, 0, endAngle, fg_color, bg_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Draw full 360
|
||||||
|
{
|
||||||
|
drawArc(x, y, r, ir, 0, 360, fg_color, bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
inTransaction = lockTransaction;
|
||||||
|
end_tft_write();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: sqrt_fraction
|
||||||
|
** Description: Smooth graphics support function for alpha derivation
|
||||||
|
***************************************************************************************/
|
||||||
|
// Compute the fixed point square root of an integer and
|
||||||
|
// return the 8 MS bits of fractional part.
|
||||||
|
// Quicker than sqrt() for processors that do not have and FPU (e.g. RP2040)
|
||||||
|
inline uint8_t TFT_eSPI::sqrt_fraction(uint32_t num) {
|
||||||
|
if (num > (0x40000000)) return 0;
|
||||||
|
uint32_t bsh = 0x00004000;
|
||||||
|
uint32_t fpr = 0;
|
||||||
|
uint32_t osh = 0;
|
||||||
|
|
||||||
|
// Auto adjust from U8:8 up to U15:16
|
||||||
|
while (num>bsh) {bsh <<= 2; osh++;}
|
||||||
|
|
||||||
|
do {
|
||||||
|
uint32_t bod = bsh + fpr;
|
||||||
|
if(num >= bod)
|
||||||
|
{
|
||||||
|
num -= bod;
|
||||||
|
fpr = bsh + bod;
|
||||||
|
}
|
||||||
|
num <<= 1;
|
||||||
|
} while(bsh >>= 1);
|
||||||
|
|
||||||
|
return fpr>>osh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: drawArc
|
||||||
|
** Description: Draw an arc clockwise from 6 o'clock position
|
||||||
|
***************************************************************************************/
|
||||||
|
// Centre at x,y
|
||||||
|
// r = arc outer radius, ir = arc inner radius. Inclusive, so arc thickness = r-ir+1
|
||||||
|
// Angles MUST be in range 0-360, end angle MUST be greater than start angle
|
||||||
|
// Arc foreground fg_color anti-aliased with background colour along sides
|
||||||
|
// smooth is optional, default is true, smooth=false means no antialiasing
|
||||||
|
// Note: Arc ends are not anti-aliased (use drawSmoothArc instead for that)
|
||||||
|
void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir,
|
||||||
|
int32_t startAngle, int32_t endAngle,
|
||||||
|
uint32_t fg_color, uint32_t bg_color,
|
||||||
|
bool smooth)
|
||||||
|
{
|
||||||
|
if (_vpOoB) return;
|
||||||
|
if (r < ir) transpose(r, ir); // Required that r > ir
|
||||||
|
if (r <= 0 || ir < 0) return; // Invalid r, ir can be zero (circle sector)
|
||||||
|
if (endAngle < startAngle) transpose(startAngle, endAngle);
|
||||||
|
if (startAngle < 0) startAngle = 0;
|
||||||
|
if (endAngle > 360) endAngle = 360;
|
||||||
|
|
||||||
|
inTransaction = true;
|
||||||
|
|
||||||
|
int32_t xs = 0; // x start position for quadrant scan
|
||||||
|
uint8_t alpha = 0; // alpha value for blending pixels
|
||||||
|
|
||||||
|
int32_t r2 = r * r; // Outer arc radius^2
|
||||||
|
if (smooth) r++; // Outer AA zone radius
|
||||||
|
int32_t r1 = r * r; // Outer AA radius^2
|
||||||
|
int16_t w = r - ir; // Width of arc (r - ir + 1)
|
||||||
|
int32_t r3 = ir * ir; // Inner arc radius^2
|
||||||
|
if (smooth) ir--; // Inner AA zone radius
|
||||||
|
int32_t r4 = ir * ir; // Inner AA radius^2
|
||||||
|
|
||||||
|
// Float variants of adjusted inner and outer arc radii
|
||||||
|
//float irf = ir;
|
||||||
|
//float rf = r;
|
||||||
|
|
||||||
|
// 1 | 2
|
||||||
|
// ---¦--- Arc quadrant index
|
||||||
|
// 0 | 3
|
||||||
|
// Fixed point U16.16 slope table for arc start/end in each quadrant
|
||||||
|
uint32_t startSlope[4] = {0, 0, 0xFFFFFFFF, 0};
|
||||||
|
uint32_t endSlope[4] = {0, 0xFFFFFFFF, 0, 0};
|
||||||
|
|
||||||
|
// Ensure maximum U16.16 slope of arc ends is ~ 0x8000 0000
|
||||||
|
constexpr float minDivisor = 1.0f/0x8000;
|
||||||
|
|
||||||
|
// Fill in start slope table and empty quadrants
|
||||||
|
float fabscos = fabsf(cosf(startAngle * deg2rad));
|
||||||
|
float fabssin = fabsf(sinf(startAngle * deg2rad));
|
||||||
|
|
||||||
|
// U16.16 slope of arc start
|
||||||
|
uint32_t slope = (fabscos/(fabssin + minDivisor)) * (float)(1<<16);
|
||||||
|
|
||||||
|
// Update slope table, add slope for arc start
|
||||||
|
if (startAngle < 90) {
|
||||||
|
startSlope[0] = slope;
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
< 180) {
|
||||||
|
startSlope[1] = slope;
|
||||||
|
}
|
||||||
|
else if (startAngle < 270) {
|
||||||
|
startSlope[1] = 0xFFFFFFFF;
|
||||||
|
startSlope[2] = slope;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
startSlope[1] = 0xFFFFFFFF;
|
||||||
|
startSlope[2] = 0;
|
||||||
|
startSlope[3] = slope;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in end slope table and empty quadrants
|
||||||
|
fabscos = fabsf(cosf(endAngle * deg2rad));
|
||||||
|
fabssin = fabsf(sinf(endAngle * deg2rad));
|
||||||
|
|
||||||
|
// U16.16 slope of arc end
|
||||||
|
slope = (uint32_t)((fabscos/(fabssin + minDivisor)) * (float)(1<<16));
|
||||||
|
|
||||||
|
// Work out which quadrants will need to be drawn and add slope for arc end
|
||||||
|
if (endAngle < 90) {
|
||||||
|
endSlope[0] = slope;
|
||||||
|
endSlope[1] = 0;
|
||||||
|
endSlope[2] = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
else if (endAngle < 180) {
|
||||||
|
endSlope[1] = slope;
|
||||||
|
endSlope[2] = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
else if (endAngle < 270) {
|
||||||
|
endSlope[2] = slope;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
endSlope[3] = slope;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan quadrant
|
||||||
|
for (int32_t cy = r - 1; cy > 0; cy--)
|
||||||
|
{
|
||||||
|
uint32_t len[4] = { 0, 0, 0, 0}; // Pixel run length
|
||||||
|
int32_t xst[4] = {-1, -1, -1, -1}; // Pixel run x start
|
||||||
|
uint32_t dy2 = (r - cy) * (r - cy);
|
||||||
|
|
||||||
|
// Find and track arc zone start point
|
||||||
|
while ((r - xs) * (r - xs) + dy2 >= r1) xs++;
|
||||||
|
|
||||||
|
for (int32_t cx = xs; cx < r; cx++)
|
||||||
|
{
|
||||||
|
// Calculate radius^2
|
||||||
|
uint32_t hyp = (r - cx) * (r - cx) + dy2;
|
||||||
|
|
||||||
|
// If in outer zone calculate alpha
|
||||||
|
if (hyp > r2) {
|
||||||
|
//alpha = (uint8_t)((rf - sqrtf(hyp)) * 255);
|
||||||
|
alpha = ~sqrt_fraction(hyp); // Outer AA zone
|
||||||
|
}
|
||||||
|
// If within arc fill zone, get line start and lengths for each quadrant
|
||||||
|
else if (hyp >= r3) {
|
||||||
|
// Calculate U16.16 slope
|
||||||
|
slope = ((r - cy) << 16)/(r - cx);
|
||||||
|
if (slope <= startSlope[0] && slope >= endSlope[0]) { // slope hi -> lo
|
||||||
|
xst[0] = cx; // Bottom left line end
|
||||||
|
len[0]++;
|
||||||
|
}
|
||||||
|
if (slope >= startSlope[1] && slope <= endSlope[1]) { // slope lo -> hi
|
||||||
|
xst[1] = cx; // Top left line end
|
||||||
|
len[1]++;
|
||||||
|
}
|
||||||
|
if (slope <= startSlope[2] && slope >= endSlope[2]) { // slope hi -> lo
|
||||||
|
xst[2] = cx; // Bottom right line start
|
||||||
|
len[2]++;
|
||||||
|
}
|
||||||
|
if (slope >= startSlope[3] && slope <= endSlope[3]) { // slope lo -> hi
|
||||||
|
xst[3] = cx; // Top right line start
|
||||||
|
len[3]++;
|
||||||
|
}
|
||||||
|
continue; // Next x
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (hyp <= r4) break; // Skip inner pixels
|
||||||
|
//alpha = (uint8_t)((sqrtf(hyp) - irf) * 255.0);
|
||||||
|
alpha = sqrt_fraction(hyp); // Inner AA zone
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alpha < 16) continue; // Skip low alpha pixels
|
||||||
|
|
||||||
|
// If background is read it must be done in each quadrant
|
||||||
|
uint16_t pcol = alphaBlend(alpha, fg_color, bg_color);
|
||||||
|
// Check if an AA pixels need to be drawn
|
||||||
|
slope = ((r - cy)<<16)/(r - cx);
|
||||||
|
if (slope <= startSlope[0] && slope >= endSlope[0]) // BL
|
||||||
|
drawPixel(x + cx - r, y - cy + r, pcol);
|
||||||
|
if (slope >= startSlope[1] && slope <= endSlope[1]) // TL
|
||||||
|
drawPixel(x + cx - r, y + cy - r, pcol);
|
||||||
|
if (slope <= startSlope[2] && slope >= endSlope[2]) // TR
|
||||||
|
drawPixel(x - cx + r, y + cy - r, pcol);
|
||||||
|
if (slope >= startSlope[3] && slope <= endSlope[3]) // BR
|
||||||
|
drawPixel(x - cx + r, y - cy + r, pcol);
|
||||||
|
}
|
||||||
|
// Add line in inner zone
|
||||||
|
if (len[0]) drawFastHLine(x + xst[0] - len[0] + 1 - r, y - cy + r, len[0], fg_color); // BL
|
||||||
|
if (len[1]) drawFastHLine(x + xst[1] - len[1] + 1 - r, y + cy - r, len[1], fg_color); // TL
|
||||||
|
if (len[2]) drawFastHLine(x - xst[2] + r, y + cy - r, len[2], fg_color); // TR
|
||||||
|
if (len[3]) drawFastHLine(x - xst[3] + r, y - cy + r, len[3], fg_color); // BR
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in centre lines
|
||||||
|
if (startAngle == 0 || endAngle == 360) drawFastVLine(x, y + r - w, w, fg_color); // Bottom
|
||||||
|
if (startAngle <= 90 && endAngle >= 90) drawFastHLine(x - r + 1, y, w, fg_color); // Left
|
||||||
|
if (startAngle <= 180 && endAngle >= 180) drawFastVLine(x, y - r + 1, w, fg_color); // Top
|
||||||
|
if (startAngle <= 270 && endAngle >= 270) drawFastHLine(x + r - w, y, w, fg_color); // Right
|
||||||
|
|
||||||
|
inTransaction = lockTransaction;
|
||||||
|
end_tft_write();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: drawSmoothCircle
|
||||||
|
** Description: Draw a smooth circle
|
||||||
|
***************************************************************************************/
|
||||||
|
// To have effective anti-aliasing the circle will be 3 pixels thick
|
||||||
|
void TFT_eSPI::drawSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t fg_color, uint32_t bg_color)
|
||||||
|
{
|
||||||
|
drawSmoothRoundRect(x-r, y-r, r, r-1, 0, 0, fg_color, bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: fillSmoothCircle
|
** Function name: fillSmoothCircle
|
||||||
** Description: Draw a filled anti-aliased circle
|
** Description: Draw a filled anti-aliased circle
|
||||||
|
|
@ -3789,12 +4191,19 @@ void TFT_eSPI::fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color,
|
||||||
int32_t hyp2 = (r - cx) * (r - cx) + dy2;
|
int32_t hyp2 = (r - cx) * (r - cx) + dy2;
|
||||||
if (hyp2 <= r1) break;
|
if (hyp2 <= r1) break;
|
||||||
if (hyp2 >= r2) continue;
|
if (hyp2 >= r2) continue;
|
||||||
|
//*
|
||||||
|
uint8_t alpha = ~sqrt_fraction(hyp2);
|
||||||
|
if (alpha > 246) break;
|
||||||
|
xs = cx;
|
||||||
|
if (alpha < 9) continue;
|
||||||
|
//*/
|
||||||
|
/*
|
||||||
float alphaf = (float)r - sqrtf(hyp2);
|
float alphaf = (float)r - sqrtf(hyp2);
|
||||||
if (alphaf > HiAlphaTheshold) break;
|
if (alphaf > HiAlphaTheshold) break;
|
||||||
xs = cx;
|
xs = cx;
|
||||||
if (alphaf < LoAlphaTheshold) continue;
|
if (alphaf < LoAlphaTheshold) continue;
|
||||||
uint8_t alpha = alphaf * 255;
|
uint8_t alpha = alphaf * 255;
|
||||||
|
//*/
|
||||||
if (bg_color == 0x00FFFFFF) {
|
if (bg_color == 0x00FFFFFF) {
|
||||||
drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color);
|
drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color);
|
||||||
drawPixel(x - cx + r, y + cy - r, color, alpha, bg_color);
|
drawPixel(x - cx + r, y + cy - r, color, alpha, bg_color);
|
||||||
|
|
@ -3816,6 +4225,119 @@ void TFT_eSPI::fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: drawSmoothRoundRect
|
||||||
|
** Description: Draw a rounded rectangle
|
||||||
|
***************************************************************************************/
|
||||||
|
// x,y is top left corner of bounding box for a complete rounded rectangle
|
||||||
|
// r = arc outer corner radius, ir = arc inner radius. Arc thickness = r-ir+1
|
||||||
|
// w and h are width and height of the bounding rectangle
|
||||||
|
// If w and h are < radius (e.g. 0,0) a circle will be drawn with centre at x+r,y+r
|
||||||
|
// Arc foreground fg_color anti-aliased with background colour at edges
|
||||||
|
// A subset of corners can be drawn by specifying a quadrants mask. A bit set in the
|
||||||
|
// mask means draw that quadrant (all are drawn if parameter missing):
|
||||||
|
// 0x1 | 0x2
|
||||||
|
// ---¦--- Arc quadrant mask select bits (as in drawCircleHelper fn)
|
||||||
|
// 0x8 | 0x4
|
||||||
|
void TFT_eSPI::drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t w, int32_t h, uint32_t fg_color, uint32_t bg_color, uint8_t quadrants)
|
||||||
|
{
|
||||||
|
if (_vpOoB) return;
|
||||||
|
if (r < ir) transpose(r, ir); // Required that r > ir
|
||||||
|
if (r <= 0 || ir < 0) return; // Invalid
|
||||||
|
|
||||||
|
w -= 2*r;
|
||||||
|
h -= 2*r;
|
||||||
|
|
||||||
|
if (w < 0) w = 0;
|
||||||
|
if (h < 0) h = 0;
|
||||||
|
|
||||||
|
inTransaction = true;
|
||||||
|
|
||||||
|
x += r;
|
||||||
|
y += r;
|
||||||
|
/*
|
||||||
|
float alphaGain = 1.0;
|
||||||
|
if (w != 0 || h != 0) {
|
||||||
|
if (r - ir < 2) alphaGain = 1.5; // Boost brightness for thin lines
|
||||||
|
if (r - ir < 1) alphaGain = 1.7;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
uint16_t t = r - ir + 1;
|
||||||
|
int32_t xs = 0;
|
||||||
|
int32_t cx = 0;
|
||||||
|
|
||||||
|
int32_t r2 = r * r; // Outer arc radius^2
|
||||||
|
r++;
|
||||||
|
int32_t r1 = r * r; // Outer AA zone radius^2
|
||||||
|
|
||||||
|
int32_t r3 = ir * ir; // Inner arc radius^2
|
||||||
|
ir--;
|
||||||
|
int32_t r4 = ir * ir; // Inner AA zone radius^2
|
||||||
|
|
||||||
|
//float irf = ir;
|
||||||
|
//float rf = r;
|
||||||
|
uint8_t alpha = 0;
|
||||||
|
|
||||||
|
// Scan top left quadrant x y r ir fg_color bg_color
|
||||||
|
for (int32_t cy = r - 1; cy > 0; cy--)
|
||||||
|
{
|
||||||
|
int32_t len = 0; // Pixel run length
|
||||||
|
int32_t lxst = 0; // Left side run x start
|
||||||
|
int32_t rxst = 0; // Right side run x start
|
||||||
|
int32_t dy2 = (r - cy) * (r - cy);
|
||||||
|
|
||||||
|
// Find and track arc zone start point
|
||||||
|
while ((r - xs) * (r - xs) + dy2 >= r1) xs++;
|
||||||
|
|
||||||
|
for (cx = xs; cx < r; cx++)
|
||||||
|
{
|
||||||
|
// Calculate radius^2
|
||||||
|
int32_t hyp = (r - cx) * (r - cx) + dy2;
|
||||||
|
|
||||||
|
// If in outer zone calculate alpha
|
||||||
|
if (hyp > r2) {
|
||||||
|
alpha = ~sqrt_fraction(hyp);
|
||||||
|
//alpha = (uint8_t)((rf - sqrtf(hyp)) * 255); // Outer AA zone
|
||||||
|
}
|
||||||
|
// If within arc fill zone, get line lengths for each quadrant
|
||||||
|
else if (hyp >= r3) {
|
||||||
|
rxst = cx; // Right side start
|
||||||
|
len++; // Line segment length
|
||||||
|
continue; // Next x
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (hyp <= r4) break; // Skip inner pixels
|
||||||
|
//alpha = (uint8_t)((sqrtf(hyp) - irf) * 255); // Inner AA zone
|
||||||
|
alpha = sqrt_fraction(hyp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alpha < 16) continue; // Skip low alpha pixels
|
||||||
|
|
||||||
|
// If background is read it must be done in each quadrant - TODO
|
||||||
|
uint16_t pcol = alphaBlend(alpha, fg_color, bg_color);
|
||||||
|
if (quadrants & 0x8) drawPixel(x + cx - r, y - cy + r + h, pcol); // BL
|
||||||
|
if (quadrants & 0x1) drawPixel(x + cx - r, y + cy - r, pcol); // TL
|
||||||
|
if (quadrants & 0x2) drawPixel(x - cx + r + w, y + cy - r, pcol); // TR
|
||||||
|
if (quadrants & 0x4) drawPixel(x - cx + r + w, y - cy + r + h, pcol); // BR
|
||||||
|
}
|
||||||
|
// Fill arc inner zone in each quadrant
|
||||||
|
lxst = rxst - len + 1; // Calculate line segment start for left side
|
||||||
|
if (quadrants & 0x8) drawFastHLine(x + lxst - r, y - cy + r + h, len, fg_color); // BL
|
||||||
|
if (quadrants & 0x1) drawFastHLine(x + lxst - r, y + cy - r, len, fg_color); // TL
|
||||||
|
if (quadrants & 0x2) drawFastHLine(x - rxst + r + w, y + cy - r, len, fg_color); // TR
|
||||||
|
if (quadrants & 0x4) drawFastHLine(x - rxst + r + w, y - cy + r + h, len, fg_color); // BR
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw sides
|
||||||
|
if ((quadrants & 0xC) == 0xC) fillRect(x, y + r - t + h, w + 1, t, fg_color); // Bottom
|
||||||
|
if ((quadrants & 0x9) == 0x9) fillRect(x - r + 1, y, t, h + 1, fg_color); // Left
|
||||||
|
if ((quadrants & 0x3) == 0x3) fillRect(x, y - r + 1, w + 1, t, fg_color); // Top
|
||||||
|
if ((quadrants & 0x6) == 0x6) fillRect(x + r - t + w, y, t, h + 1, fg_color); // Right
|
||||||
|
|
||||||
|
inTransaction = lockTransaction;
|
||||||
|
end_tft_write();
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: fillSmoothRoundRect
|
** Function name: fillSmoothRoundRect
|
||||||
** Description: Draw a filled anti-aliased rounded corner rectangle
|
** Description: Draw a filled anti-aliased rounded corner rectangle
|
||||||
|
|
@ -3823,6 +4345,7 @@ void TFT_eSPI::fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color,
|
||||||
void TFT_eSPI::fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color, uint32_t bg_color)
|
void TFT_eSPI::fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color, uint32_t bg_color)
|
||||||
{
|
{
|
||||||
inTransaction = true;
|
inTransaction = true;
|
||||||
|
|
||||||
int32_t xs = 0;
|
int32_t xs = 0;
|
||||||
int32_t cx = 0;
|
int32_t cx = 0;
|
||||||
|
|
||||||
|
|
@ -3834,9 +4357,11 @@ void TFT_eSPI::fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, i
|
||||||
y += r;
|
y += r;
|
||||||
h -= 2*r;
|
h -= 2*r;
|
||||||
fillRect(x, y, w, h, color);
|
fillRect(x, y, w, h, color);
|
||||||
|
|
||||||
h--;
|
h--;
|
||||||
x += r;
|
x += r;
|
||||||
w -= 2*r+1;
|
w -= 2*r+1;
|
||||||
|
|
||||||
int32_t r1 = r * r;
|
int32_t r1 = r * r;
|
||||||
r++;
|
r++;
|
||||||
int32_t r2 = r * r;
|
int32_t r2 = r * r;
|
||||||
|
|
@ -3849,12 +4374,18 @@ void TFT_eSPI::fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, i
|
||||||
int32_t hyp2 = (r - cx) * (r - cx) + dy2;
|
int32_t hyp2 = (r - cx) * (r - cx) + dy2;
|
||||||
if (hyp2 <= r1) break;
|
if (hyp2 <= r1) break;
|
||||||
if (hyp2 >= r2) continue;
|
if (hyp2 >= r2) continue;
|
||||||
|
|
||||||
|
uint8_t alpha = ~sqrt_fraction(hyp2);
|
||||||
|
if (alpha > 246) break;
|
||||||
|
xs = cx;
|
||||||
|
if (alpha < 9) continue;
|
||||||
|
/*
|
||||||
float alphaf = (float)r - sqrtf(hyp2);
|
float alphaf = (float)r - sqrtf(hyp2);
|
||||||
if (alphaf > HiAlphaTheshold) break;
|
if (alphaf > HiAlphaTheshold) break;
|
||||||
xs = cx;
|
xs = cx;
|
||||||
if (alphaf < LoAlphaTheshold) continue;
|
if (alphaf < LoAlphaTheshold) continue;
|
||||||
uint8_t alpha = alphaf * 255;
|
uint8_t alpha = alphaf * 255;
|
||||||
|
*/
|
||||||
drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color);
|
drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color);
|
||||||
drawPixel(x - cx + r + w, y + cy - r, color, alpha, bg_color);
|
drawPixel(x - cx + r + w, y + cy - r, color, alpha, bg_color);
|
||||||
drawPixel(x - cx + r + w, y - cy + r + h, color, alpha, bg_color);
|
drawPixel(x - cx + r + w, y - cy + r + h, color, alpha, bg_color);
|
||||||
|
|
@ -3871,6 +4402,7 @@ void TFT_eSPI::fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, i
|
||||||
** Function name: drawSpot - maths intensive, so for small filled circles
|
** Function name: drawSpot - maths intensive, so for small filled circles
|
||||||
** Description: Draw an anti-aliased filled circle at ax,ay with radius r
|
** Description: Draw an anti-aliased filled circle at ax,ay with radius r
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
// Coordinates are floating point to achieve sub-pixel positioning
|
||||||
void TFT_eSPI::drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color)
|
void TFT_eSPI::drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color)
|
||||||
{
|
{
|
||||||
// Filled circle can be created by the wide line function with zero line length
|
// Filled circle can be created by the wide line function with zero line length
|
||||||
|
|
@ -3893,7 +4425,7 @@ void TFT_eSPI::drawWideLine(float ax, float ay, float bx, float by, float wd, ui
|
||||||
void TFT_eSPI::drawWedgeLine(float ax, float ay, float bx, float by, float ar, float br, uint32_t fg_color, uint32_t bg_color)
|
void TFT_eSPI::drawWedgeLine(float ax, float ay, float bx, float by, float ar, float br, uint32_t fg_color, uint32_t bg_color)
|
||||||
{
|
{
|
||||||
if ( (ar < 0.0) || (br < 0.0) )return;
|
if ( (ar < 0.0) || (br < 0.0) )return;
|
||||||
if ( (abs(ax - bx) < 0.01f) && (abs(ay - by) < 0.01f) ) bx += 0.01f; // Avoid divide by zero
|
if ( (fabsf(ax - bx) < 0.01f) && (fabsf(ay - by) < 0.01f) ) bx += 0.01f; // Avoid divide by zero
|
||||||
|
|
||||||
// Find line bounding box
|
// Find line bounding box
|
||||||
int32_t x0 = (int32_t)floorf(fminf(ax-ar, bx-br));
|
int32_t x0 = (int32_t)floorf(fminf(ax-ar, bx-br));
|
||||||
|
|
@ -3963,7 +4495,7 @@ void TFT_eSPI::drawWedgeLine(float ax, float ay, float bx, float by, float ar, f
|
||||||
pushColor(fg_color);
|
pushColor(fg_color);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//Blend color with background and plot
|
//Blend colour with background and plot
|
||||||
if (bg_color == 0x00FFFFFF) {
|
if (bg_color == 0x00FFFFFF) {
|
||||||
bg = readPixel(xp, yp); swin = true;
|
bg = readPixel(xp, yp); swin = true;
|
||||||
}
|
}
|
||||||
|
|
@ -3976,7 +4508,7 @@ void TFT_eSPI::drawWedgeLine(float ax, float ay, float bx, float by, float ar, f
|
||||||
end_nin_write();
|
end_nin_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate distance of px,py to closest part of line
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: lineDistance - private helper function for drawWedgeLine
|
** Function name: lineDistance - private helper function for drawWedgeLine
|
||||||
** Description: returns distance of px,py to closest part of a to b wedge
|
** Description: returns distance of px,py to closest part of a to b wedge
|
||||||
|
|
@ -4375,26 +4907,13 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
|
||||||
** Function name: alphaBlend
|
** Function name: alphaBlend
|
||||||
** Description: Blend 16bit foreground and background
|
** Description: Blend 16bit foreground and background
|
||||||
*************************************************************************************x*/
|
*************************************************************************************x*/
|
||||||
uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc)
|
inline uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc)
|
||||||
{
|
{
|
||||||
// For speed use fixed point maths and rounding to permit a power of 2 division
|
uint32_t rxb = bgc & 0xF81F;
|
||||||
uint16_t fgR = ((fgc >> 10) & 0x3E) + 1;
|
rxb += ((fgc & 0xF81F) - rxb) * (alpha >> 2) >> 6;
|
||||||
uint16_t fgG = ((fgc >> 4) & 0x7E) + 1;
|
uint32_t xgx = bgc & 0x07E0;
|
||||||
uint16_t fgB = ((fgc << 1) & 0x3E) + 1;
|
xgx += ((fgc & 0x07E0) - xgx) * alpha >> 8;
|
||||||
|
return (rxb & 0xF81F) | (xgx & 0x07E0);
|
||||||
uint16_t bgR = ((bgc >> 10) & 0x3E) + 1;
|
|
||||||
uint16_t bgG = ((bgc >> 4) & 0x7E) + 1;
|
|
||||||
uint16_t bgB = ((bgc << 1) & 0x3E) + 1;
|
|
||||||
|
|
||||||
// Shift right 1 to drop rounding bit and shift right 8 to divide by 256
|
|
||||||
uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9);
|
|
||||||
uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9);
|
|
||||||
uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9);
|
|
||||||
|
|
||||||
// Combine RGB565 colours into 16 bits
|
|
||||||
//return ((r&0x18) << 11) | ((g&0x30) << 5) | ((b&0x18) << 0); // 2 bit greyscale
|
|
||||||
//return ((r&0x1E) << 11) | ((g&0x3C) << 5) | ((b&0x1E) << 0); // 4 bit greyscale
|
|
||||||
return (r << 11) | (g << 5) | (b << 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
|
|
@ -4427,22 +4946,13 @@ uint32_t TFT_eSPI::alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8
|
||||||
if (alphaDither >255) alpha = 255;
|
if (alphaDither >255) alpha = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For speed use fixed point maths and rounding to permit a power of 2 division
|
uint32_t rxx = bgc & 0xFF0000;
|
||||||
uint16_t fgR = ((fgc >> 15) & 0x1FE) + 1;
|
rxx += ((fgc & 0xFF0000) - rxx) * alpha >> 8;
|
||||||
uint16_t fgG = ((fgc >> 7) & 0x1FE) + 1;
|
uint32_t xgx = bgc & 0x00FF00;
|
||||||
uint16_t fgB = ((fgc << 1) & 0x1FE) + 1;
|
xgx += ((fgc & 0xFF0000) - xgx) * alpha >> 8;
|
||||||
|
uint32_t xxb = bgc & 0x0000FF;
|
||||||
uint16_t bgR = ((bgc >> 15) & 0x1FE) + 1;
|
xxb += ((fgc & 0xFF0000) - xxb) * alpha >> 8;
|
||||||
uint16_t bgG = ((bgc >> 7) & 0x1FE) + 1;
|
return (rxx & 0xFF0000) | (xgx & 0x00FF00) | (xxb & 0x0000FF);
|
||||||
uint16_t bgB = ((bgc << 1) & 0x1FE) + 1;
|
|
||||||
|
|
||||||
// Shift right 1 to drop rounding bit and shift right 8 to divide by 256
|
|
||||||
uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9);
|
|
||||||
uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9);
|
|
||||||
uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9);
|
|
||||||
|
|
||||||
// Combine RGB colours into 24 bits
|
|
||||||
return (r << 16) | (g << 8) | (b << 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
|
|
|
||||||
112
TFT_eSPI.h
112
TFT_eSPI.h
|
|
@ -16,7 +16,7 @@
|
||||||
#ifndef _TFT_eSPIH_
|
#ifndef _TFT_eSPIH_
|
||||||
#define _TFT_eSPIH_
|
#define _TFT_eSPIH_
|
||||||
|
|
||||||
#define TFT_ESPI_VERSION "2.4.79"
|
#define TFT_ESPI_VERSION "2.5.81b"
|
||||||
|
|
||||||
// Bit level feature flags
|
// Bit level feature flags
|
||||||
// Bit 0 set: viewport capability
|
// Bit 0 set: viewport capability
|
||||||
|
|
@ -402,9 +402,6 @@ int16_t tch_spi_freq;// Touch controller read/write SPI frequency
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Section 8: Class member and support functions
|
** Section 8: Class member and support functions
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
// Swap any type
|
|
||||||
template <typename T> static inline void
|
|
||||||
swap_coord(T& a, T& b) { T t = a; a = b; b = t; }
|
|
||||||
|
|
||||||
// Callback prototype for smooth font pixel colour read
|
// Callback prototype for smooth font pixel colour read
|
||||||
typedef uint16_t (*getColorCallback)(uint16_t x, uint16_t y);
|
typedef uint16_t (*getColorCallback)(uint16_t x, uint16_t y);
|
||||||
|
|
@ -449,6 +446,12 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3
|
void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3
|
||||||
uint8_t getRotation(void); // Read the current rotation
|
uint8_t getRotation(void); // Read the current rotation
|
||||||
|
|
||||||
|
// Change the origin position from the default top left
|
||||||
|
// Note: setRotation, setViewport and resetViewport will revert origin to top left corner of screen/sprite
|
||||||
|
void setOrigin(int32_t x, int32_t y);
|
||||||
|
int32_t getOriginX(void);
|
||||||
|
int32_t getOriginY(void);
|
||||||
|
|
||||||
void invertDisplay(bool i); // Tell TFT to invert all displayed colours
|
void invertDisplay(bool i); // Tell TFT to invert all displayed colours
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -491,6 +494,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
void end_SDA_Read(void); // Restore MOSI to output
|
void end_SDA_Read(void); // Restore MOSI to output
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Graphics drawing
|
// Graphics drawing
|
||||||
void fillScreen(uint32_t color),
|
void fillScreen(uint32_t color),
|
||||||
drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color),
|
drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color),
|
||||||
|
|
@ -500,28 +504,6 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2);
|
void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2);
|
||||||
void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2);
|
void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2);
|
||||||
|
|
||||||
// Draw a pixel blended with the pixel colour on the TFT or sprite, return blended colour
|
|
||||||
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
|
||||||
uint16_t drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color = 0x00FFFFFF);
|
|
||||||
|
|
||||||
// Draw a small anti-aliased filled circle at ax,ay with radius r (uses drawWideLine)
|
|
||||||
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
|
||||||
void drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
|
|
||||||
|
|
||||||
// Draw an anti-aliased filled circle at x, y with radius r
|
|
||||||
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
|
||||||
void fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF);
|
|
||||||
|
|
||||||
void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, uint32_t bg_color = 0x00FFFFFF);
|
|
||||||
|
|
||||||
// Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2)
|
|
||||||
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
|
||||||
void drawWideLine(float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
|
|
||||||
|
|
||||||
// Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with radiused ends
|
|
||||||
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
|
||||||
void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
|
|
||||||
|
|
||||||
void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color),
|
void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color),
|
||||||
drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color),
|
drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color),
|
||||||
fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color),
|
fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color),
|
||||||
|
|
@ -534,6 +516,53 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color),
|
drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color),
|
||||||
fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color);
|
fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color);
|
||||||
|
|
||||||
|
|
||||||
|
// Smooth (anti-aliased) graphics drawing
|
||||||
|
// Draw a pixel blended with the background pixel colour (bg_color) specified, return blended colour
|
||||||
|
// If the bg_color is not specified, the background pixel colour will be read from TFT or sprite
|
||||||
|
uint16_t drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color = 0x00FFFFFF);
|
||||||
|
|
||||||
|
// Draw an anti-aliased (smooth) arc between start and end angles. Arc ends are anti-aliased.
|
||||||
|
// By default the arc is drawn with square ends unless the "roundEnds" parameter is included and set true
|
||||||
|
// Angle = 0 is at 6 o'clock position, 90 at 9 o'clock etc. The angles must be in range 0-360 or they will be clipped to these limits
|
||||||
|
// The start angle may be larger than the end angle. Arcs are always drawn clockwise from the start angle.
|
||||||
|
void drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t startAngle, int32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds = false);
|
||||||
|
|
||||||
|
// As per "drawSmoothArc" except endAngle should be greater than startAngle (angles will be swapped otherwise)
|
||||||
|
// The sides of the arc are anti-aliased by default. If smoothArc is false sides will NOT be anti-aliased
|
||||||
|
// The ends of the arc are NOT anti-aliased, this facilitates dynamic arc length changes with arc segments and ensures clean segment joints
|
||||||
|
void drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t startAngle, int32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool smoothArc = true);
|
||||||
|
|
||||||
|
// Draw an anti-aliased filled circle at x, y with radius r
|
||||||
|
// Note: The thickness of line is 3 pixels to reduce the visible "braiding" effect of anti-aliasing narrow lines
|
||||||
|
// this means the inner anti-alias zone is always at r-1 and the outer zone at r+1
|
||||||
|
void drawSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t fg_color, uint32_t bg_color);
|
||||||
|
|
||||||
|
// Draw an anti-aliased filled circle at x, y with radius r
|
||||||
|
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
||||||
|
void fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF);
|
||||||
|
|
||||||
|
// Draw a rounded rectangle that has a line thickness of r-ir+1 and bounding box defined by x,y and w,h
|
||||||
|
// The outer corner radius is r, inner corner radius is ir
|
||||||
|
// The inside and outside of the border are anti-aliased
|
||||||
|
void drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t w, int32_t h, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF, uint8_t quadrants = 0xF);
|
||||||
|
|
||||||
|
// Draw a filled rounded rectangle , corner radius r and bounding box defined by x,y and w,h
|
||||||
|
void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, uint32_t bg_color = 0x00FFFFFF);
|
||||||
|
|
||||||
|
// Draw a small anti-aliased filled circle at ax,ay with radius r (uses drawWideLine)
|
||||||
|
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
||||||
|
void drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
|
||||||
|
|
||||||
|
// Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2)
|
||||||
|
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
||||||
|
void drawWideLine(float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
|
||||||
|
|
||||||
|
// Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with radiused ends
|
||||||
|
// If bg_color is not included the background pixel colour will be read from TFT or sprite
|
||||||
|
void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
|
||||||
|
|
||||||
|
|
||||||
// Image rendering
|
// Image rendering
|
||||||
// Swap the byte order for pushImage() and pushPixels() - corrects endianness
|
// Swap the byte order for pushImage() and pushPixels() - corrects endianness
|
||||||
void setSwapBytes(bool swap);
|
void setSwapBytes(bool swap);
|
||||||
|
|
@ -572,11 +601,16 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true, uint16_t *cmap = nullptr);
|
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true, uint16_t *cmap = nullptr);
|
||||||
// FLASH version
|
// FLASH version
|
||||||
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap = nullptr);
|
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap = nullptr);
|
||||||
|
|
||||||
|
// Render a 16 bit colour image with a 1bpp mask
|
||||||
|
void pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask);
|
||||||
|
|
||||||
// This next function has been used successfully to dump the TFT screen to a PC for documentation purposes
|
// This next function has been used successfully to dump the TFT screen to a PC for documentation purposes
|
||||||
// It reads a screen area and returns the 3 RGB 8 bit colour values of each pixel in the buffer
|
// It reads a screen area and returns the 3 RGB 8 bit colour values of each pixel in the buffer
|
||||||
// Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes
|
// Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes
|
||||||
void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data);
|
void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data);
|
||||||
|
|
||||||
|
|
||||||
// Text rendering - value returned is the pixel width of the rendered text
|
// Text rendering - value returned is the pixel width of the rendered text
|
||||||
int16_t drawNumber(long intNumber, int32_t x, int32_t y, uint8_t font), // Draw integer using specified font number
|
int16_t drawNumber(long intNumber, int32_t x, int32_t y, uint8_t font), // Draw integer using specified font number
|
||||||
drawNumber(long intNumber, int32_t x, int32_t y), // Draw integer using current font
|
drawNumber(long intNumber, int32_t x, int32_t y), // Draw integer using current font
|
||||||
|
|
@ -598,6 +632,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
drawCentreString(const String& string, int32_t x, int32_t y, uint8_t font),// Deprecated, use setTextDatum() and drawString()
|
drawCentreString(const String& string, int32_t x, int32_t y, uint8_t font),// Deprecated, use setTextDatum() and drawString()
|
||||||
drawRightString(const String& string, int32_t x, int32_t y, uint8_t font); // Deprecated, use setTextDatum() and drawString()
|
drawRightString(const String& string, int32_t x, int32_t y, uint8_t font); // Deprecated, use setTextDatum() and drawString()
|
||||||
|
|
||||||
|
|
||||||
// Text rendering and font handling support funtions
|
// Text rendering and font handling support funtions
|
||||||
void setCursor(int16_t x, int16_t y), // Set cursor for tft.print()
|
void setCursor(int16_t x, int16_t y), // Set cursor for tft.print()
|
||||||
setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print()
|
setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print()
|
||||||
|
|
@ -645,6 +680,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
|
|
||||||
uint16_t fontsLoaded(void); // Each bit in returned value represents a font type that is loaded - used for debug/error handling only
|
uint16_t fontsLoaded(void); // Each bit in returned value represents a font type that is loaded - used for debug/error handling only
|
||||||
|
|
||||||
|
|
||||||
// Low level read/write
|
// Low level read/write
|
||||||
void spiwrite(uint8_t); // legacy support only
|
void spiwrite(uint8_t); // legacy support only
|
||||||
#ifndef RM68120_DRIVER
|
#ifndef RM68120_DRIVER
|
||||||
|
|
@ -678,15 +714,15 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
// Alpha blend 2 colours, see generic "alphaBlend_Test" example
|
// Alpha blend 2 colours, see generic "alphaBlend_Test" example
|
||||||
// alpha = 0 = 100% background colour
|
// alpha = 0 = 100% background colour
|
||||||
// alpha = 255 = 100% foreground colour
|
// alpha = 255 = 100% foreground colour
|
||||||
uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc);
|
inline uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc);
|
||||||
// 16 bit colour alphaBlend with alpha dither (dither reduces colour banding)
|
// 16 bit colour alphaBlend with alpha dither (dither reduces colour banding)
|
||||||
uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither);
|
uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither);
|
||||||
// 24 bit colour alphaBlend with optional alpha dither
|
// 24 bit colour alphaBlend with optional alpha dither
|
||||||
uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0);
|
uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0);
|
||||||
|
|
||||||
|
// Direct Memory Access (DMA) support functions
|
||||||
// DMA support functions - these are currently just for SPI writes when using the ESP32 or STM32 processors
|
// These can be used for SPI writes when using the ESP32 (original) or STM32 processors.
|
||||||
// DMA works also on RP2040 and PIO SPI, 8 bit parallel and 16 bit parallel
|
// DMA also works on a RP2040 processor with PIO based SPI and parallel (8 and 16 bit) interfaces
|
||||||
// Bear in mind DMA will only be of benefit in particular circumstances and can be tricky
|
// Bear in mind DMA will only be of benefit in particular circumstances and can be tricky
|
||||||
// to manage by noobs. The functions have however been designed to be noob friendly and
|
// to manage by noobs. The functions have however been designed to be noob friendly and
|
||||||
// avoid a few DMA behaviour "gotchas".
|
// avoid a few DMA behaviour "gotchas".
|
||||||
|
|
@ -718,8 +754,13 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
|
|
||||||
// Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image
|
// Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image
|
||||||
// Use the buffer if the image data will get over-written or destroyed while DMA is in progress
|
// Use the buffer if the image data will get over-written or destroyed while DMA is in progress
|
||||||
// If swapping colour bytes is defined, and the double buffer option is NOT used, then the bytes
|
//
|
||||||
// in the original data image will be swapped by the function before DMA is initiated.
|
// Note 1: If swapping colour bytes is defined, and the double buffer option is NOT used, then the bytes
|
||||||
|
// in the original image buffer content will be byte swapped by the function before DMA is initiated.
|
||||||
|
//
|
||||||
|
// Note 2: If part of the image will be off screen or outside of a set viewport, then the the original
|
||||||
|
// image buffer content will be altered to a correctly clipped image before DMA is initiated.
|
||||||
|
//
|
||||||
// The function will wait for the last DMA to complete if it is called while a previous DMA is still
|
// The function will wait for the last DMA to complete if it is called while a previous DMA is still
|
||||||
// in progress, this simplifies the sketch and helps avoid "gotchas".
|
// in progress, this simplifies the sketch and helps avoid "gotchas".
|
||||||
void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr);
|
void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr);
|
||||||
|
|
@ -812,6 +853,9 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
// Single GPIO input/output direction control
|
// Single GPIO input/output direction control
|
||||||
void gpioMode(uint8_t gpio, uint8_t mode);
|
void gpioMode(uint8_t gpio, uint8_t mode);
|
||||||
|
|
||||||
|
// Smooth graphics helper
|
||||||
|
uint8_t sqrt_fraction(uint32_t num);
|
||||||
|
|
||||||
// Helper function: calculate distance of a point from a finite length line between two points
|
// Helper function: calculate distance of a point from a finite length line between two points
|
||||||
float wedgeLineDistance(float pax, float pay, float bax, float bay, float dr);
|
float wedgeLineDistance(float pax, float pay, float bax, float bay, float dr);
|
||||||
|
|
||||||
|
|
@ -917,6 +961,10 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||||
|
|
||||||
}; // End of class TFT_eSPI
|
}; // End of class TFT_eSPI
|
||||||
|
|
||||||
|
// Swap any type
|
||||||
|
template <typename T> static inline void
|
||||||
|
transpose(T& a, T& b) { T t = a; a = b; b = t; }
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Section 10: Additional extension classes
|
** Section 10: Additional extension classes
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
#include <Timezone.h>
|
#include <Timezone.h>
|
||||||
|
|
||||||
// Choose library to load
|
// Choose library to load
|
||||||
#ifdef ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
// ESP8266
|
// ESP8266
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#elif (defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_RP2040)) && !defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
#elif (defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_RP2040)) && !defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
TFT_eSPI tft = TFT_eSPI(); // Invoke library
|
TFT_eSPI tft = TFT_eSPI(); // Invoke library
|
||||||
|
|
||||||
#ifdef ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
ADC_MODE(ADC_VCC); // Read the supply voltage
|
ADC_MODE(ADC_VCC); // Read the supply voltage
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -45,15 +45,15 @@ Serial.print("\n[code]\n");
|
||||||
|
|
||||||
Serial.print ("TFT_eSPI ver = "); Serial.println(user.version);
|
Serial.print ("TFT_eSPI ver = "); Serial.println(user.version);
|
||||||
printProcessorName();
|
printProcessorName();
|
||||||
#if defined (ESP32) || defined (ESP8266)
|
#if defined (ESP32) || defined (ARDUINO_ARCH_ESP8266)
|
||||||
if (user.esp < 0x32F000 || user.esp > 0x32FFFF) { Serial.print("Frequency = "); Serial.print(ESP.getCpuFreqMHz());Serial.println("MHz"); }
|
if (user.esp < 0x32F000 || user.esp > 0x32FFFF) { Serial.print("Frequency = "); Serial.print(ESP.getCpuFreqMHz());Serial.println("MHz"); }
|
||||||
#endif
|
#endif
|
||||||
#ifdef ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
Serial.print("Voltage = "); Serial.print(ESP.getVcc() / 918.0); Serial.println("V"); // 918 empirically determined
|
Serial.print("Voltage = "); Serial.print(ESP.getVcc() / 918.0); Serial.println("V"); // 918 empirically determined
|
||||||
#endif
|
#endif
|
||||||
Serial.print("Transactions = "); Serial.println((user.trans == 1) ? "Yes" : "No");
|
Serial.print("Transactions = "); Serial.println((user.trans == 1) ? "Yes" : "No");
|
||||||
Serial.print("Interface = "); Serial.println((user.serial == 1) ? "SPI" : "Parallel");
|
Serial.print("Interface = "); Serial.println((user.serial == 1) ? "SPI" : "Parallel");
|
||||||
#ifdef ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
if (user.serial == 1){ Serial.print("SPI overlap = "); Serial.println((user.overlap == 1) ? "Yes\n" : "No\n"); }
|
if (user.serial == 1){ Serial.print("SPI overlap = "); Serial.println((user.overlap == 1) ? "Yes\n" : "No\n"); }
|
||||||
#endif
|
#endif
|
||||||
if (user.tft_driver != 0xE9D) // For ePaper displays the size is defined in the sketch
|
if (user.tft_driver != 0xE9D) // For ePaper displays the size is defined in the sketch
|
||||||
|
|
@ -78,7 +78,7 @@ if (user.pin_tft_mosi != -1) { Serial.print("MOSI = "); Serial.print("GPIO ")
|
||||||
if (user.pin_tft_miso != -1) { Serial.print("MISO = "); Serial.print("GPIO "); Serial.println(getPinName(user.pin_tft_miso)); }
|
if (user.pin_tft_miso != -1) { Serial.print("MISO = "); Serial.print("GPIO "); Serial.println(getPinName(user.pin_tft_miso)); }
|
||||||
if (user.pin_tft_clk != -1) { Serial.print("SCK = "); Serial.print("GPIO "); Serial.println(getPinName(user.pin_tft_clk)); }
|
if (user.pin_tft_clk != -1) { Serial.print("SCK = "); Serial.print("GPIO "); Serial.println(getPinName(user.pin_tft_clk)); }
|
||||||
|
|
||||||
#ifdef ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
if (user.overlap == true)
|
if (user.overlap == true)
|
||||||
{
|
{
|
||||||
Serial.println("Overlap selected, following pins MUST be used:");
|
Serial.println("Overlap selected, following pins MUST be used:");
|
||||||
|
|
@ -92,7 +92,7 @@ if (user.overlap == true)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
String pinNameRef = "GPIO ";
|
String pinNameRef = "GPIO ";
|
||||||
#ifdef ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
pinNameRef = "PIN_D";
|
pinNameRef = "PIN_D";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
12
keywords.txt
12
keywords.txt
|
|
@ -18,6 +18,9 @@ pushColor KEYWORD2
|
||||||
|
|
||||||
setRotation KEYWORD2
|
setRotation KEYWORD2
|
||||||
getRotation KEYWORD2
|
getRotation KEYWORD2
|
||||||
|
setOrigin KEYWORD2
|
||||||
|
getOriginX KEYWORD2
|
||||||
|
getOriginY KEYWORD2
|
||||||
invertDisplay KEYWORD2
|
invertDisplay KEYWORD2
|
||||||
setAddrWindow KEYWORD2
|
setAddrWindow KEYWORD2
|
||||||
|
|
||||||
|
|
@ -44,6 +47,8 @@ end_SDA_Read KEYWORD2
|
||||||
fillScreen KEYWORD2
|
fillScreen KEYWORD2
|
||||||
|
|
||||||
drawRect KEYWORD2
|
drawRect KEYWORD2
|
||||||
|
fillRectHGradient KEYWORD2
|
||||||
|
fillRectVGradient KEYWORD2
|
||||||
drawRoundRect KEYWORD2
|
drawRoundRect KEYWORD2
|
||||||
fillRoundRect KEYWORD2
|
fillRoundRect KEYWORD2
|
||||||
|
|
||||||
|
|
@ -69,6 +74,7 @@ getPivotY KEYWORD2
|
||||||
readRect KEYWORD2
|
readRect KEYWORD2
|
||||||
pushRect KEYWORD2
|
pushRect KEYWORD2
|
||||||
pushImage KEYWORD2
|
pushImage KEYWORD2
|
||||||
|
pushMaskedImage KEYWORD2
|
||||||
readRectRGB KEYWORD2
|
readRectRGB KEYWORD2
|
||||||
|
|
||||||
drawNumber KEYWORD2
|
drawNumber KEYWORD2
|
||||||
|
|
@ -140,10 +146,12 @@ calibrateTouch KEYWORD2
|
||||||
setTouch KEYWORD2
|
setTouch KEYWORD2
|
||||||
|
|
||||||
# Smooth (anti-aliased) graphics functions
|
# Smooth (anti-aliased) graphics functions
|
||||||
fillRectHGradient KEYWORD2
|
drawSmoothCircle KEYWORD2
|
||||||
fillRectVGradient KEYWORD2
|
|
||||||
fillSmoothCircle KEYWORD2
|
fillSmoothCircle KEYWORD2
|
||||||
|
drawSmoothRoundRect KEYWORD2
|
||||||
fillSmoothRoundRect KEYWORD2
|
fillSmoothRoundRect KEYWORD2
|
||||||
|
drawSmoothArc KEYWORD2
|
||||||
|
drawArc KEYWORD2
|
||||||
drawSpot KEYWORD2
|
drawSpot KEYWORD2
|
||||||
drawWideLine KEYWORD2
|
drawWideLine KEYWORD2
|
||||||
drawWedgeLine KEYWORD2
|
drawWedgeLine KEYWORD2
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue