Files
CDashDisplay/lib/Arduino_GFX/src/Arduino_TFT.cpp
T
esilva f9d0bfa4d9 First commit
I shall move all this to another branch -> master_vendored or something
2025-03-12 21:42:39 +00:00

1104 lines
25 KiB
C++

/*
* start rewrite from:
* https://github.com/adafruit/Adafruit-GFX-Library.git
*/
#include "Arduino_DataBus.h"
#include "Arduino_GFX.h"
#include "Arduino_TFT.h"
#include "font/glcdfont.h"
Arduino_TFT::Arduino_TFT(
Arduino_DataBus *bus, int8_t rst, uint8_t r,
bool ips, int16_t w, int16_t h,
uint8_t col_offset1, uint8_t row_offset1, uint8_t col_offset2, uint8_t row_offset2)
: Arduino_GFX(w, h), _bus(bus), _rst(rst), _ips(ips),
COL_OFFSET1(col_offset1), ROW_OFFSET1(row_offset1),
COL_OFFSET2(col_offset2), ROW_OFFSET2(row_offset2)
{
_rotation = r;
}
bool Arduino_TFT::begin(int32_t speed)
{
if (_override_datamode != GFX_NOT_DEFINED)
{
if (!_bus->begin(speed, _override_datamode))
{
return false;
}
}
else
{
if (!_bus->begin(speed))
{
return false;
}
}
tftInit();
setRotation(_rotation); // apply the setting rotation to the display
setAddrWindow(0, 0, _width, _height);
return true;
}
void Arduino_TFT::startWrite()
{
_bus->beginWrite();
}
void Arduino_TFT::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
{
writeAddrWindow(x, y, 1, 1);
_bus->write16(color);
}
void Arduino_TFT::writeRepeat(uint16_t color, uint32_t len)
{
_bus->writeRepeat(color, len);
}
void Arduino_TFT::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
{
if (_ordered_in_range(x, 0, _max_x) && h)
{ // X on screen, nonzero height
if (h < 0)
{ // If negative height...
y += h + 1; // Move Y to top edge
h = -h; // Use positive height
}
if (y <= _max_y)
{ // Not off bottom
int16_t y2 = y + h - 1;
if (y2 >= 0)
{ // Not off top
// Line partly or fully overlaps screen
if (y < 0)
{
y = 0;
h = y2 + 1;
} // Clip top
if (y2 > _max_y)
{
h = _max_y - y + 1;
} // Clip bottom
writeFillRectPreclipped(x, y, 1, h, color);
}
}
}
}
void Arduino_TFT::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
{
if (_ordered_in_range(y, 0, _max_y) && w)
{ // Y on screen, nonzero width
if (w < 0)
{ // If negative width...
x += w + 1; // Move X to left edge
w = -w; // Use positive width
}
if (x <= _max_x)
{ // Not off right
int16_t x2 = x + w - 1;
if (x2 >= 0)
{ // Not off left
// Line partly or fully overlaps screen
if (x < 0)
{
x = 0;
w = x2 + 1;
} // Clip left
if (x2 > _max_x)
{
w = _max_x - x + 1;
} // Clip right
writeFillRectPreclipped(x, y, w, 1, color);
}
}
}
}
void Arduino_TFT::writeFillRectPreclipped(
int16_t x, int16_t y,
int16_t w, int16_t h, uint16_t color)
{
#ifdef ESP8266
yield();
#endif
writeAddrWindow(x, y, w, h);
writeRepeat(color, (uint32_t)w * h);
}
void Arduino_TFT::endWrite()
{
_bus->endWrite();
}
void Arduino_TFT::setAddrWindow(int16_t x0, int16_t y0, uint16_t w,
uint16_t h)
{
startWrite();
writeAddrWindow(x0, y0, w, h);
endWrite();
}
void Arduino_TFT::setRotation(uint8_t r)
{
Arduino_GFX::setRotation(r);
switch (_rotation)
{
case 5:
case 3:
_xStart = ROW_OFFSET2;
_yStart = COL_OFFSET1;
break;
case 6:
case 2:
_xStart = COL_OFFSET2;
_yStart = ROW_OFFSET2;
break;
case 7:
case 1:
_xStart = ROW_OFFSET1;
_yStart = COL_OFFSET2;
break;
case 4:
default: // case 0:
_xStart = COL_OFFSET1;
_yStart = ROW_OFFSET1;
break;
}
_currentX = 0xFFFF;
_currentY = 0xFFFF;
_currentW = 0xFFFF;
_currentH = 0xFFFF;
}
void Arduino_TFT::writeColor(uint16_t color)
{
_bus->write16(color);
}
// TFT optimization code, too big for ATMEL family
#if !defined(LITTLE_FOOT_PRINT)
void Arduino_TFT::writeBytes(uint8_t *data, uint32_t len)
{
_bus->writeBytes(data, len);
}
void Arduino_TFT::writePixels(uint16_t *data, uint32_t len)
{
_bus->writePixels(data, len);
}
void Arduino_TFT::pushColor(uint16_t color)
{
_bus->beginWrite();
writeColor(color);
_bus->endWrite();
}
void Arduino_TFT::writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
{
int16_t dx;
int16_t dy;
int16_t err;
int16_t xs;
int16_t step;
int16_t len;
bool steep = _diff(y1, y0) > _diff(x1, x0);
if (steep)
{
_swap_int16_t(x0, y0);
_swap_int16_t(x1, y1);
}
if (x0 > x1)
{
_swap_int16_t(x0, x1);
_swap_int16_t(y0, y1);
}
dx = x1 - x0;
dy = _diff(y1, y0);
err = dx >> 1;
xs = x0;
step = (y0 < y1) ? 1 : -1;
len = 0;
while (x0 <= x1)
{
x0++;
len++;
err -= dy;
if ((err < 0) || ((x0 > x1) && len))
{
if (steep)
{
writeFillRectPreclipped(y0, xs, 1, len, color);
}
else
{
writeFillRectPreclipped(xs, y0, len, 1, color);
}
err += dx;
y0 += step;
len = 0;
xs = x0;
}
}
}
// TFT tuned BITMAP / XBITMAP / GRAYSCALE / RGB BITMAP FUNCTIONS ---------------------
void Arduino_TFT::writeIndexedPixels(uint8_t *bitmap, uint16_t *color_index, uint32_t len)
{
_bus->writeIndexedPixels(bitmap, color_index, len);
}
void Arduino_TFT::writeIndexedPixelsDouble(uint8_t *bitmap, uint16_t *color_index, uint32_t len)
{
_bus->writeIndexedPixelsDouble(bitmap, color_index, len);
}
void Arduino_TFT::drawYCbCrBitmap(int16_t x, int16_t y, uint8_t *yData, uint8_t *cbData, uint8_t *crData, int16_t w, int16_t h)
{
startWrite();
writeAddrWindow(0, 0, w, h);
_bus->writeYCbCrPixels(yData, cbData, crData, w, h);
endWrite();
}
void Arduino_TFT::drawBitmap(
int16_t x, int16_t y,
const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::drawBitmap(x, y, bitmap, w, h, color, bg);
}
else
{
int32_t pixels = w * h;
uint8_t byte = 0;
uint16_t idx = 0;
startWrite();
writeAddrWindow(x, y, w, h);
for (int32_t i = 0; i < pixels; i++)
{
if (i & 7)
{
byte <<= 1;
}
else
{
byte = pgm_read_byte(&bitmap[idx++]);
}
_bus->write16((byte & 0x80) ? color : bg);
}
endWrite();
}
}
void Arduino_TFT::drawBitmap(
int16_t x, int16_t y,
uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::drawBitmap(x, y, bitmap, w, h, color, bg);
}
else
{
int32_t pixels = w * h;
uint8_t byte = 0;
startWrite();
writeAddrWindow(x, y, w, h);
for (int32_t i = 0; i < pixels; i++)
{
if (i & 7)
{
byte <<= 1;
}
else
{
byte = *(bitmap++);
}
_bus->write16((byte & 0x80) ? color : bg);
}
endWrite();
}
}
void Arduino_TFT::drawGrayscaleBitmap(
int16_t x, int16_t y,
const uint8_t bitmap[], int16_t w, int16_t h)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::drawGrayscaleBitmap(x, y, bitmap, w, h);
}
else
{
uint32_t len = (uint32_t)w * h;
uint8_t v;
startWrite();
writeAddrWindow(x, y, w, h);
for (uint32_t i = 0; i < len; i++)
{
v = pgm_read_byte(&bitmap[i]);
_bus->write16(color565(v, v, v));
}
endWrite();
}
}
void Arduino_TFT::drawGrayscaleBitmap(
int16_t x, int16_t y,
uint8_t *bitmap, int16_t w, int16_t h)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::drawGrayscaleBitmap(x, y, bitmap, w, h);
}
else
{
uint32_t len = (uint32_t)w * h;
uint8_t v;
startWrite();
writeAddrWindow(x, y, w, h);
while (len--)
{
v = *(bitmap++);
_bus->write16(color565(v, v, v));
}
endWrite();
}
}
void Arduino_TFT::drawIndexedBitmap(
int16_t x, int16_t y,
uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
}
else
{
startWrite();
writeAddrWindow(x, y, w, h);
if (x_skip == 0)
{
_bus->writeIndexedPixels(bitmap, color_index, h * w);
}
else
{
while (h--)
{
_bus->writeIndexedPixels(bitmap, color_index, w);
bitmap += w + x_skip;
}
}
endWrite();
}
}
void Arduino_TFT::draw16bitRGBBitmapWithMask(int16_t x, int16_t y,
uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::draw16bitRGBBitmapWithMask(x, y, bitmap, mask, w, h);
}
else
{
int32_t offset = 0, maskIdx = 0, len = 0;
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 = mask[maskIdx++];
}
if (byte & 0x80)
{
len++;
}
else
{
if (len)
{
writeAddrWindow(x + i - len, y, len, 1);
_bus->writePixels(&bitmap[offset - len], len);
len = 0;
}
}
offset++;
}
if (len)
{
writeAddrWindow(x + w - 1 - len, y, len, 1);
_bus->writePixels(&bitmap[offset - len], len);
len = 0;
}
}
endWrite();
}
}
void Arduino_TFT::draw16bitRGBBitmap(
int16_t x, int16_t y,
const uint16_t bitmap[], int16_t w, int16_t h)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::draw16bitRGBBitmap(x, y, bitmap, w, h);
}
else
{
uint32_t len = (uint32_t)w * h;
startWrite();
writeAddrWindow(x, y, w, h);
for (uint32_t i = 0; i < len; i++)
{
_bus->write16(pgm_read_word(&bitmap[i]));
}
endWrite();
}
}
void Arduino_TFT::draw16bitRGBBitmap(
int16_t x, int16_t y,
uint16_t *bitmap, int16_t w, int16_t h)
{
if (
((y + h - 1) < 0) || // Outside top
(y > _max_y) // Outside bottom
)
{
return;
}
else if (_isRoundMode)
{
if (
(x > _roundMaxX[y + h - 1]) && // top left
((x + w - 1) < _roundMinX[y]) && // top right
(x > _roundMaxX[y + h - 1]) && // bottom left
((x + w - 1) < _roundMinX[y + h - 1]) // bottom right
)
{
return;
}
}
else if (
((x + w - 1) < 0) || // Outside left
(x > _max_x) // Outside right
)
{
return;
}
else
{
int16_t out_width = w;
if ((y + h - 1) > _max_y)
{
h -= (y + h - 1) - _max_y;
}
if (y < 0)
{
bitmap -= y * w;
h += y;
y = 0;
}
if ((x + w - 1) > _max_x)
{
out_width -= (x + w - 1) - _max_x;
}
if (x < 0)
{
bitmap -= x;
out_width += x;
x = 0;
}
startWrite();
writeAddrWindow(x, y, out_width, h);
if (out_width < w)
{
for (int16_t j = 0; j < h; j++)
{
_bus->writePixels(bitmap, out_width);
bitmap += w;
}
}
else
{
_bus->writePixels(bitmap, (uint32_t)w * h);
}
endWrite();
}
}
void Arduino_TFT::draw16bitBeRGBBitmap(
int16_t x, int16_t y,
uint16_t *bitmap, int16_t w, int16_t h)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else
{
int16_t out_width = w;
if ((y + h - 1) > _max_y)
{
h -= (y + h - 1) - _max_y;
}
if (y < 0)
{
bitmap -= y * w;
h += y;
y = 0;
}
if ((x + w - 1) > _max_x)
{
out_width -= (x + w - 1) - _max_x;
}
if (x < 0)
{
bitmap -= x;
out_width += x;
x = 0;
}
startWrite();
writeAddrWindow(x, y, out_width, h);
if (out_width < w)
{
out_width <<= 1;
for (int16_t j = 0; j < h; j++)
{
_bus->writeBytes((uint8_t *)bitmap, out_width);
bitmap += w;
}
}
else
{
_bus->writeBytes((uint8_t *)bitmap, (uint32_t)w * h * 2);
}
endWrite();
}
}
void Arduino_TFT::draw16bitBeRGBBitmapR1(
int16_t x, int16_t y,
uint16_t *bitmap, int16_t w, int16_t h)
{
if (
((x + h - 1) < 0) || // Outside left
((y + w - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + h - 1) > _max_x) || // Clip right
((y + w - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::draw16bitBeRGBBitmapR1(x, y, bitmap, w, h);
}
else
{
startWrite();
writeAddrWindow(x, y, h, w);
_bus->write16bitBeRGBBitmapR1(bitmap, w, h);
endWrite();
}
}
void Arduino_TFT::draw24bitRGBBitmap(
int16_t x, int16_t y,
const uint8_t bitmap[], int16_t w, int16_t h)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::draw24bitRGBBitmap(x, y, bitmap, w, h);
}
else
{
uint32_t len = (uint32_t)w * h;
uint32_t offset = 0;
startWrite();
writeAddrWindow(x, y, w, h);
while (len--)
{
_bus->write16(color565(pgm_read_byte(&bitmap[offset]), pgm_read_byte(&bitmap[offset + 1]), pgm_read_byte(&bitmap[offset + 2])));
offset += 3;
}
endWrite();
}
}
void Arduino_TFT::draw24bitRGBBitmap(
int16_t x, int16_t y,
uint8_t *bitmap, int16_t w, int16_t h)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else if (
(x < 0) || // Clip left
(y < 0) || // Clip top
((x + w - 1) > _max_x) || // Clip right
((y + h - 1) > _max_y) // Clip bottom
)
{
Arduino_GFX::draw24bitRGBBitmap(x, y, bitmap, w, h);
}
else
{
uint32_t len = (uint32_t)w * h;
uint32_t offset = 0;
startWrite();
writeAddrWindow(x, y, w, h);
while (len--)
{
_bus->write16(color565(bitmap[offset], bitmap[offset + 1], bitmap[offset + 2]));
offset += 3;
}
endWrite();
}
}
void Arduino_TFT::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg)
{
uint16_t block_w;
uint16_t block_h;
#if !defined(ATTINY_CORE)
if (gfxFont) // custom font
{
// Character is assumed previously filtered by write() to eliminate
// newlines, returns, non-printable characters, etc. Calling
// drawChar() directly with 'bad' characters of font may cause mayhem!
uint8_t first = pgm_read_byte(&gfxFont->first);
GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first);
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),
xAdvance = pgm_read_byte(&glyph->xAdvance),
yAdvance = pgm_read_byte(&gfxFont->yAdvance),
baseline = yAdvance * 2 / 3; // TODO: baseline is an arbitrary currently, may be define in font file
int8_t xo = pgm_read_sbyte(&glyph->xOffset),
yo = pgm_read_sbyte(&glyph->yOffset);
// urgly workaround for the character not fit in the box
if ((bg != color) // have background color
&& ((xo + w) > xAdvance)) // if character draw outside the box
{
xo = xAdvance - w; // pad inside the box
}
uint8_t xx, yy, bits = 0, bit = 0;
int16_t xo16 = xo, yo16 = yo;
if (xAdvance < w)
{
xAdvance = w; // Don't know why it exists
}
block_w = xAdvance * textsize_x;
block_h = yAdvance * textsize_y;
int16_t x1 = (xo < 0) ? (x + xo) : x;
if (
(x1 < _min_text_x) || // Clip left
((y - baseline) < _min_text_y) || // Clip top
((x1 + block_w - 1) > _max_text_x) || // Clip right
((y - baseline + block_h - 1) > _max_text_y) // Clip bottom
)
{
// partial draw char by parent class
Arduino_GFX::drawChar(x, y, c, color, bg);
}
else
{
// NOTE: Different from Adafruit_GFX design, Adruino_GFX also cater background.
// Since it may introduce many ugly output, it should limited using on mono font only.
if (xo < 0) // padding X offset to >= 0
{
x += xo;
xo = 0;
}
startWrite();
if (bg != color) // have background color
{
writeAddrWindow(x, y - (baseline * textsize_y), block_w, block_h);
uint16_t line_buf[block_w];
int8_t i;
bool draw_dot;
for (yy = 0; yy < yAdvance; yy++)
{
if ((yy < (baseline + yo)) || (yy > (baseline + yo + h - 1)))
{
writeRepeat(bg, block_w * textsize_y);
}
else
{
i = 0;
for (xx = 0; xx < xAdvance; xx++)
{
if ((xx < xo) || (xx > (xo + w - 1)))
{
draw_dot = false;
}
else
{
if (!(bit++ & 7))
{
bits = pgm_read_byte(&bitmap[bo++]);
}
draw_dot = bits & 0x80;
bits <<= 1;
}
if (textsize_x == 1)
{
line_buf[i++] = draw_dot ? color : bg;
}
else
{
if (draw_dot)
{
for (int8_t k = 0; k < textsize_x; k++)
{
line_buf[i++] = (k < (textsize_x - text_pixel_margin)) ? color : bg;
}
}
else
{
for (int8_t k = 0; k < textsize_x; k++)
{
line_buf[i++] = bg;
}
}
}
}
if (textsize_y == 1)
{
writePixels(line_buf, block_w);
}
else
{
for (int8_t l = 0; l < textsize_y; l++)
{
if (l < (textsize_y - text_pixel_margin))
{
writePixels(line_buf, block_w);
}
else
{
writeRepeat(bg, block_w);
}
}
}
}
}
}
else // (bg == color), no background color
{
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 (textsize_x == 1 && textsize_y == 1)
{
writePixelPreclipped(x + xo + xx, y + yo + yy, color);
}
else
{
writeFillRectPreclipped(x + (xo16 + xx) * textsize_x, y + (yo16 + yy) * textsize_y,
textsize_x - text_pixel_margin, textsize_y - text_pixel_margin, color);
}
}
bits <<= 1;
}
}
}
endWrite();
}
}
else // not gfxFont
#endif // !defined(ATTINY_CORE)
#if defined(U8G2_FONT_SUPPORT)
if (u8g2Font)
{
Arduino_GFX::drawChar(x, y, c, color, bg);
}
else // not u8g2Font
#endif // defined(U8G2_FONT_SUPPORT)
{
block_w = 6 * textsize_x;
block_h = 8 * textsize_y;
if (
(x < _min_text_x) || // Clip left
(y < _min_text_y) || // Clip top
((x + block_w - 1) > _max_text_x) || // Clip right
((y + block_h - 1) > _max_text_y) // Clip bottom
)
{
// partial draw char by parent class
Arduino_GFX::drawChar(x, y, c, color, bg);
}
else
{
uint8_t col[5];
for (int8_t i = 0; i < 5; i++)
{
col[i] = pgm_read_byte(&font[c * 5 + i]);
}
startWrite();
if (bg != color) // have background color
{
writeAddrWindow(x, y, block_w, block_h);
uint16_t line_buf[block_w];
if (textsize_x == 1)
{
line_buf[5] = bg; // last column always bg
}
else
{
for (int8_t k = 0; k < textsize_x; k++)
{
line_buf[5 * textsize_x + k] = bg;
}
}
uint8_t bit = 1;
bool draw_dot;
while (bit)
{
for (int8_t i = 0; i < 5; i++)
{
draw_dot = col[i] & bit;
if (textsize_x == 1)
{
line_buf[i] = (draw_dot) ? color : bg;
}
else
{
if (draw_dot)
{
for (int8_t k = 0; k < textsize_x; k++)
{
line_buf[i * textsize_x + k] = (k < (textsize_x - text_pixel_margin)) ? color : bg;
}
}
else
{
for (int8_t k = 0; k < textsize_x; k++)
{
line_buf[i * textsize_x + k] = bg;
}
}
}
}
if (textsize_y == 1)
{
writePixels(line_buf, block_w);
}
else
{
for (int8_t l = 0; l < textsize_y; l++)
{
if (l < (textsize_y - text_pixel_margin))
{
writePixels(line_buf, block_w);
}
else
{
writeRepeat(bg, block_w);
}
}
}
bit <<= 1;
}
}
else // (bg == color), no background color
{
for (int8_t i = 0; i < 5; i++)
{ // Char bitmap = 5 columns
uint8_t line = col[i];
for (int8_t j = 0; j < 8; j++, line >>= 1)
{
if (line & 1)
{
if (textsize_x == 1 && textsize_y == 1)
{
writePixelPreclipped(x + i, y + j, color);
}
else
{
writeFillRectPreclipped(x + i * textsize_x, y + j * textsize_y, textsize_x - text_pixel_margin, textsize_y - text_pixel_margin, color);
}
}
}
}
}
endWrite();
}
}
}
#endif // !defined(LITTLE_FOOT_PRINT)