TFT_eSPI/Extensions/Smooth_font.cpp

213 lines
6.4 KiB
C++

// Coded by Bodmer 10/2/18, see license in root directory.
// This is part of the TFT_eSPI class and is associated with anti-aliased font functions
////////////////////////////////////////////////////////////////////////////////////////
// New anti-aliased (smoothed) font functions added below
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
** Function name: loadFont
** Description: loads parameters from a font vlw array in memory
*************************************************************************************x*/
void TFT_eSPI::loadFont(const uint8_t array[])
{
loadFont("", false);
}
#ifdef FONT_FS_AVAILABLE
/***************************************************************************************
** Function name: loadFont
** Description: loads parameters from a font vlw file
*************************************************************************************x*/
void TFT_eSPI::loadFont(String fontName, fs::FS &ffs)
{
loadFont(fontName, false);
}
#endif
/***************************************************************************************
** Function name: loadFont
** Description: loads parameters from a font vlw file
*************************************************************************************x*/
void TFT_eSPI::loadFont(String fontName, bool flash)
{
sf->loadFont(fontName, flash);
fontLoaded = true;
}
/***************************************************************************************
** Function name: deleteMetrics
** Description: Delete the old glyph metrics and free up the memory
*************************************************************************************x*/
void TFT_eSPI::unloadFont( void )
{
fontLoaded = false;
}
/***************************************************************************************
** Function name: drawGlyph
** Description: Write a character to the TFT cursor position
*************************************************************************************x*/
// Expects file to be open
void TFT_eSPI::drawGlyph(uint16_t code)
{
if (code < 0x21)
{
if (code == 0x20) {
cursor_x += sf->gFont.spaceWidth;
return;
}
if (code == '\n') {
cursor_x = 0;
cursor_y += sf->gFont.yAdvance;
if (cursor_y >= _height) cursor_y = 0;
return;
}
}
uint16_t gNum = 0;
bool found = sf->getUnicodeIndex(code, &gNum);
uint16_t fg = textcolor;
uint16_t bg = textbgcolor;
if (found)
{
if (textwrapX && (cursor_x + sf->gWidth[gNum] + sf->gdX[gNum] > _width))
{
cursor_y += sf->gFont.yAdvance;
cursor_x = 0;
}
if (textwrapY && ((cursor_y + sf->gFont.yAdvance) >= _height)) cursor_y = 0;
if (cursor_x == 0) cursor_x -= sf->gdX[gNum];
uint8_t* pbuffer = nullptr;
const uint8_t* gPtr = (const uint8_t*) sf->gFont.gArray;
#ifdef FONT_FS_AVAILABLE
if (sf->fs_font)
{
sf->fontFile.seek(sf->gBitmap[gNum], fs::SeekSet); // This is taking >30ms for a significant position shift
pbuffer = (uint8_t*)malloc(sf->gWidth[gNum]);
}
#endif
int16_t xs = 0;
uint32_t dl = 0;
uint8_t pixel;
int16_t cy = cursor_y + sf->gFont.maxAscent - sf->gdY[gNum];
int16_t cx = cursor_x + sf->gdX[gNum];
startWrite(); // Avoid slow ESP32 transaction overhead for every pixel
for (int y = 0; y < sf->gHeight[gNum]; y++)
{
#ifdef FONT_FS_AVAILABLE
if (sf->fs_font) {
if (sf->spiffs)
{
sf->fontFile.read(pbuffer, sf->gWidth[gNum]);
//Serial.println("SPIFFS");
}
else
{
endWrite(); // Release SPI for SD card transaction
sf->fontFile.read(pbuffer,sf-> gWidth[gNum]);
startWrite(); // Re-start SPI for TFT transaction
//Serial.println("Not SPIFFS");
}
}
#endif
for (int x = 0; x < sf->gWidth[gNum]; x++)
{
#ifdef FONT_FS_AVAILABLE
if (sf->fs_font) pixel = pbuffer[x];
else
#endif
pixel = pgm_read_byte(gPtr + sf->gBitmap[gNum] + x + sf->gWidth[gNum] * y);
if (pixel)
{
if (pixel != 0xFF)
{
if (dl) {
if (dl==1) drawPixel(xs, y + cy, fg);
else drawFastHLine( xs, y + cy, dl, fg);
dl = 0;
}
if (getColor) bg = getColor(x + cx, y + cy);
drawPixel(x + cx, y + cy, alphaBlend(pixel, fg, bg));
}
else
{
if (dl==0) xs = x + cx;
dl++;
}
}
else
{
if (dl) { drawFastHLine( xs, y + cy, dl, fg); dl = 0; }
}
}
if (dl) { drawFastHLine( xs, y + cy, dl, fg); dl = 0; }
}
if (pbuffer) free(pbuffer);
cursor_x += sf->gxAdvance[gNum];
endWrite();
}
else
{
// Not a Unicode in font so draw a rectangle and move on cursor
drawRect(cursor_x, cursor_y + sf->gFont.maxAscent - sf->gFont.ascent, sf->gFont.spaceWidth, sf->gFont.ascent, fg);
cursor_x += sf->gFont.spaceWidth + 1;
}
}
/***************************************************************************************
** Function name: showFont
** Description: Page through all characters in font, td ms between screens
*************************************************************************************x*/
void TFT_eSPI::showFont(uint32_t td)
{
if( !fontLoaded || sf == nullptr) return;
int16_t cursorX = width(); // Force start of new page to initialise cursor
int16_t cursorY = height();// for the first character
uint32_t timeDelay = 0; // No delay before first page
fillScreen(textbgcolor);
for (uint16_t i = 0; i < sf->gFont.gCount; i++)
{
// Check if this will need a new screen
if (cursorX + sf->gdX[i] + sf->gWidth[i] >= width()) {
cursorX = -sf->gdX[i];
cursorY += sf->gFont.yAdvance;
if (cursorY + sf->gFont.maxAscent + sf->gFont.descent >= height()) {
cursorX = -sf->gdX[i];
cursorY = 0;
delay(timeDelay);
timeDelay = td;
fillScreen(textbgcolor);
}
}
setCursor(cursorX, cursorY);
drawGlyph(sf->gUnicode[i]);
cursorX += sf->gxAdvance[i];
//cursorX += printToSprite( cursorX, cursorY, i );
yield();
}
delay(timeDelay);
fillScreen(textbgcolor);
//fontFile.close();
}