Address #1001 - flicker reduction for smooth fonts
Replace block erase of string area with glyph by glyph scan-line clearing to minimise flicker
This commit is contained in:
parent
04747bcaaa
commit
34c00b12e7
|
|
@ -316,7 +316,7 @@ uint32_t TFT_eSPI::readInt32(void)
|
|||
|
||||
#ifdef FONT_FS_AVAILABLE
|
||||
if (fs_font) {
|
||||
val |= fontFile.read() << 24;
|
||||
val = fontFile.read() << 24;
|
||||
val |= fontFile.read() << 16;
|
||||
val |= fontFile.read() << 8;
|
||||
val |= fontFile.read();
|
||||
|
|
@ -324,7 +324,7 @@ uint32_t TFT_eSPI::readInt32(void)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
val |= pgm_read_byte(fontPtr++) << 24;
|
||||
val = pgm_read_byte(fontPtr++) << 24;
|
||||
val |= pgm_read_byte(fontPtr++) << 16;
|
||||
val |= pgm_read_byte(fontPtr++) << 8;
|
||||
val |= pgm_read_byte(fontPtr++);
|
||||
|
|
@ -364,8 +364,12 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
|||
|
||||
if (code < 0x21)
|
||||
{
|
||||
if (code == 0x20) {
|
||||
//if (fg!=bg) fillRect(cursor_x, cursor_y, gFont.spaceWidth, gFont.yAdvance, bg);
|
||||
if (code == 0x20) { // May need to expand to other thin space glyphs, see https://en.wikipedia.org/wiki/Thin_space
|
||||
if (fg!=bg && _sfbg_enable) {
|
||||
fillRect(glyph_xbg, cursor_y, gFont.spaceWidth, gFont.yAdvance, bg);
|
||||
glyph_xbg += gFont.spaceWidth;
|
||||
// glyph_1st = false;
|
||||
}
|
||||
cursor_x += gFont.spaceWidth;
|
||||
return;
|
||||
}
|
||||
|
|
@ -374,6 +378,8 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
|||
cursor_x = 0;
|
||||
cursor_y += gFont.yAdvance;
|
||||
if (textwrapY && (cursor_y >= height())) cursor_y = 0;
|
||||
glyph_xbg = 0;
|
||||
// glyph_1st = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -390,7 +396,12 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
|||
cursor_x = 0;
|
||||
}
|
||||
if (textwrapY && ((cursor_y + gFont.yAdvance) >= height())) cursor_y = 0;
|
||||
if (cursor_x == 0) cursor_x -= gdX[gNum];
|
||||
if (cursor_x == 0)
|
||||
{
|
||||
cursor_x -= gdX[gNum];
|
||||
glyph_xbg = 0;
|
||||
// glyph_1st = true;
|
||||
}
|
||||
|
||||
uint8_t* pbuffer = nullptr;
|
||||
const uint8_t* gPtr = (const uint8_t*) gFont.gArray;
|
||||
|
|
@ -405,6 +416,7 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
|||
|
||||
int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum];
|
||||
int16_t cx = cursor_x + gdX[gNum];
|
||||
int32_t bw = 0;
|
||||
|
||||
int16_t xs = cx;
|
||||
uint32_t dl = 0;
|
||||
|
|
@ -412,7 +424,15 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
|||
|
||||
startWrite(); // Avoid slow ESP32 transaction overhead for every pixel
|
||||
|
||||
//if (fg!=bg) fillRect(cursor_x, cursor_y, gxAdvance[gNum], gFont.yAdvance, bg);
|
||||
if (fg!=bg && _sfbg_enable)
|
||||
{
|
||||
bw = (cursor_x + gxAdvance[gNum]) - glyph_xbg;
|
||||
if (bw > 0)
|
||||
{
|
||||
fillRect(glyph_xbg, cursor_y, bw, gFont.maxAscent - gdY[gNum], bg);
|
||||
fillRect(glyph_xbg, cursor_y + (gFont.maxAscent - gdY[gNum]) + gHeight[gNum], bw, gFont.descent - (gHeight[gNum] - gdY[gNum]), bg);
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = 0; y < gHeight[gNum]; y++)
|
||||
{
|
||||
|
|
@ -432,6 +452,7 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
drawFastHLine(glyph_xbg, y + cy, bw, bg);
|
||||
for (int x = 0; x < gWidth[gNum]; x++)
|
||||
{
|
||||
#ifdef FONT_FS_AVAILABLE
|
||||
|
|
@ -468,6 +489,8 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
|||
|
||||
if (pbuffer) free(pbuffer);
|
||||
cursor_x += gxAdvance[gNum];
|
||||
glyph_xbg += bw;
|
||||
// glyph_1st = false;
|
||||
endWrite();
|
||||
}
|
||||
else
|
||||
|
|
|
|||
36
TFT_eSPI.cpp
36
TFT_eSPI.cpp
|
|
@ -506,6 +506,8 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
|
|||
textwrapY = false; // Wrap text at bottom of screen when using print stream
|
||||
textdatum = TL_DATUM; // Top Left text alignment is default
|
||||
fontsloaded = 0;
|
||||
glyph_xbg = 0; // Smooth font scan blanking line start coordinate
|
||||
// glyph_1st = true; // Not used at the moment, flags blanking adjustment needed
|
||||
|
||||
_swapBytes = false; // Do not swap colour bytes by default
|
||||
|
||||
|
|
@ -515,6 +517,7 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
|
|||
_booted = true; // Default attributes
|
||||
_cp437 = true;
|
||||
_utf8 = true;
|
||||
_sfbg_enable = false;
|
||||
|
||||
#ifdef FONT_FS_AVAILABLE
|
||||
fs_font = true; // Smooth font filing system or array (fs_font = false) flag
|
||||
|
|
@ -1414,9 +1417,12 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_
|
|||
|
||||
// The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse
|
||||
// so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left
|
||||
*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
//*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
//*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
//*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
*data++ = tft_Read_8();
|
||||
*data++ = tft_Read_8();
|
||||
*data++ = tft_Read_8();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1565,9 +1571,12 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
|
|||
|
||||
// The 6 colour bits are in MS 6 bits of each byte but we do not include the extra clock pulse
|
||||
// so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left
|
||||
uint8_t r = (tft_Read_8()&0x7E)<<1;
|
||||
uint8_t g = (tft_Read_8()&0x7E)<<1;
|
||||
uint8_t b = (tft_Read_8()&0x7E)<<1;
|
||||
//uint8_t r = (tft_Read_8()&0x7E)<<1;
|
||||
//uint8_t g = (tft_Read_8()&0x7E)<<1;
|
||||
//uint8_t b = (tft_Read_8()&0x7E)<<1;
|
||||
uint8_t r = tft_Read_8();
|
||||
uint8_t g = tft_Read_8();
|
||||
uint8_t b = tft_Read_8();
|
||||
color = color565(r, g, b);
|
||||
#endif
|
||||
|
||||
|
|
@ -3824,7 +3833,10 @@ void TFT_eSPI::setAttribute(uint8_t attr_id, uint8_t param) {
|
|||
#endif
|
||||
_psram_enable = false;
|
||||
break;
|
||||
//case 4: // TBD future feature control
|
||||
case SFBG_ENABLE: // Enable glyph by glyph background clearing
|
||||
_sfbg_enable = param;
|
||||
break;
|
||||
//case 5: // TBD future feature control
|
||||
// _tbd = param;
|
||||
// break;
|
||||
}
|
||||
|
|
@ -3843,7 +3855,9 @@ uint8_t TFT_eSPI::getAttribute(uint8_t attr_id) {
|
|||
return _utf8;
|
||||
case PSRAM_ENABLE:
|
||||
return _psram_enable;
|
||||
//case 3: // TBD future feature control
|
||||
case SFBG_ENABLE:
|
||||
return _sfbg_enable;
|
||||
//case 5: // TBD future feature control
|
||||
// return _tbd;
|
||||
// break;
|
||||
}
|
||||
|
|
@ -4495,7 +4509,8 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
|
|||
|
||||
#ifdef SMOOTH_FONT
|
||||
if(fontLoaded) {
|
||||
if (textcolor!=textbgcolor) fillRect(poX, poY, cwidth, cheight, textbgcolor);
|
||||
// This line causes flicker - to be replaced by new experimental scanline blanking
|
||||
if (textcolor!=textbgcolor && !_sfbg_enable) fillRect(poX, poY, cwidth, cheight, textbgcolor);
|
||||
/*
|
||||
// The above only works for a single text line, not if the text is going to wrap...
|
||||
// So need to use code like this in a while loop to fix it:
|
||||
|
|
@ -4507,12 +4522,15 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
|
|||
cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont);
|
||||
*/
|
||||
setCursor(poX, poY);
|
||||
glyph_xbg = poX; // Keeps track of next area to clear
|
||||
// glyph_1st = true; // Flag for first glyph, true means glyph_xbg adjustment required
|
||||
|
||||
while (n < len) {
|
||||
uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n);
|
||||
drawGlyph(uniCode);
|
||||
}
|
||||
sumX += cwidth;
|
||||
// glyph_1st = false;
|
||||
//fontFile.close();
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -676,9 +676,11 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
// id = 1: Turn on (a=true) or off (a=false) GLCD cp437 font character error correction
|
||||
// id = 2: Turn on (a=true) or off (a=false) UTF8 decoding
|
||||
// id = 3: Enable or disable use of ESP32 PSRAM (if available)
|
||||
// id = 4: Enable or disable glyph by glyph background clearing to reduce flicker (experimental)
|
||||
#define CP437_SWITCH 1
|
||||
#define UTF8_SWITCH 2
|
||||
#define PSRAM_ENABLE 3
|
||||
#define SFBG_ENABLE 4
|
||||
void setAttribute(uint8_t id = 0, uint8_t a = 0); // Set attribute value
|
||||
uint8_t getAttribute(uint8_t id = 0); // Get attribute value
|
||||
|
||||
|
|
@ -788,6 +790,8 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
|
||||
uint8_t glyph_ab, // Smooth font glyph delta Y (height) above baseline
|
||||
glyph_bb; // Smooth font glyph delta Y (height) below baseline
|
||||
int32_t glyph_xbg; // x coordinate for glyph by glyph background clearing (experimental)
|
||||
//bool glyph_1st; // flags first glyph in a string, since glyph_xbg might need adjusting for italic scripts
|
||||
|
||||
bool isDigits; // adjust bounding box for numbers to reduce visual jiggling
|
||||
bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display
|
||||
|
|
@ -800,6 +804,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
bool _cp437; // If set, use correct CP437 charset (default is ON)
|
||||
bool _utf8; // If set, use UTF-8 decoder in print stream 'write()' function (default ON)
|
||||
bool _psram_enable; // Enable PSRAM use for library functions (TBD) and Sprites
|
||||
bool _sfbg_enable; // Enable glyph by glyph background clearing (experimental)
|
||||
|
||||
uint32_t _lastColor; // Buffered value of last colour used
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue