Skip to content

Commit

Permalink
Add option to use UTF-8 glyphs
Browse files Browse the repository at this point in the history
  • Loading branch information
DoomHammer committed Feb 3, 2023
1 parent 5ea4be3 commit 3941d5a
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 22 deletions.
98 changes: 80 additions & 18 deletions Adafruit_GFX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h) : WIDTH(w), HEIGHT(h) {
textcolor = textbgcolor = 0xFFFF;
wrap = true;
_cp437 = false;
_utf8 = false;
gfxFont = NULL;
}

Expand Down Expand Up @@ -1105,15 +1106,15 @@ void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap,
@brief Draw a single character
@param x Bottom left corner x coordinate
@param y Bottom left corner y coordinate
@param c The 8-bit font-indexed character (likely ascii)
@param c The 16-bit font-indexed character (likely ascii)
@param color 16-bit 5-6-5 Color to draw chraracter with
@param bg 16-bit 5-6-5 Color to fill background with (if same as color,
no background)
@param size Font magnification level, 1 is 'original' size
*/
/**************************************************************************/
void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
uint16_t color, uint16_t bg, uint8_t size) {
void Adafruit_GFX::drawChar(int16_t x, int16_t y, uint16_t c, uint16_t color,
uint16_t bg, uint8_t size) {
drawChar(x, y, c, color, bg, size, size);
}

Expand All @@ -1123,17 +1124,16 @@ void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
@brief Draw a single character
@param x Bottom left corner x coordinate
@param y Bottom left corner y coordinate
@param c The 8-bit font-indexed character (likely ascii)
@param c The 16-bit font-indexed character (likely ascii)
@param color 16-bit 5-6-5 Color to draw chraracter with
@param bg 16-bit 5-6-5 Color to fill background with (if same as color,
no background)
@param size_x Font magnification level in X-axis, 1 is 'original' size
@param size_y Font magnification level in Y-axis, 1 is 'original' size
*/
/**************************************************************************/
void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
uint16_t color, uint16_t bg, uint8_t size_x,
uint8_t size_y) {
void Adafruit_GFX::drawChar(int16_t x, int16_t y, uint16_t c, uint16_t color,
uint16_t bg, uint8_t size_x, uint8_t size_y) {

if (!gfxFont) { // 'Classic' built-in font

Expand Down Expand Up @@ -1178,9 +1178,9 @@ void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
// newlines, returns, non-printable characters, etc. Calling
// drawChar() directly with 'bad' characters of font may cause mayhem!

c -= (uint8_t)pgm_read_byte(&gfxFont->first);
GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c);
uint8_t *bitmap = pgm_read_bitmap_ptr(gfxFont);
c -= pgm_read_word(&gfxFont->first);
GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);

uint16_t bo = pgm_read_word(&glyph->bitmapOffset);
uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height);
Expand Down Expand Up @@ -1233,15 +1233,76 @@ void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,

} // End classic vs custom font
}

/**************************************************************************/
/*!
@brief Serial UTF-8 decoder
@param c 8 bit value from encoded stream
@returns 0 if decoding is not complete yet, 16 bit code point
otherwise. Can cast to 8 bits for ASCII range (0-255)
*/
/**************************************************************************/

uint16_t Adafruit_GFX::decodeUTF8(uint8_t c) {
// 7 bit Unicode Code Point
if ((c & 0x80) == 0x00) {
decoderState = 0;
return (uint16_t)c;
}

if (decoderState == 0) {
// 11 bit Unicode Code Point
if ((c & 0xE0) == 0xC0) {
decoderBuffer = ((c & 0x1F) << 6); // Save first 5 bits
decoderState = 1;
return 0;
}

// 16 bit Unicode Code Point
if ((c & 0xF0) == 0xE0) {
decoderBuffer = ((c & 0x0F) << 12); // Save first 4 bits
decoderState = 2;
return 0;
}

// 21 bit Unicode Code Point not supported so fall-back to extended ASCII
if ((c & 0xF8) == 0xF0)
return (uint16_t)c;
} else {
if (decoderState == 2) {
decoderBuffer |=
((c & 0x3F) << 6); // Add next 6 bits of 16 bit code point
decoderState--;
return 0;
} else // decoderState must be == 1
{
decoderBuffer |= (c & 0x3F); // Add last 6 bits of code point
decoderState = 0;
return decoderBuffer;
}
}

decoderState = 0;

return (uint16_t)c; // fall-back to extended ASCII
}

/**************************************************************************/
/*!
@brief Print one byte/character of data, used to support print()
@param c The 8-bit ascii character to write
@param data The 8-bit UTF-8 or ascii character to write
*/
/**************************************************************************/
size_t Adafruit_GFX::write(uint8_t c) {
if (!gfxFont) { // 'Classic' built-in font
size_t Adafruit_GFX::write(uint8_t data) {
uint16_t c = (uint16_t)data;
if (_utf8)
c = decodeUTF8(data);
if (c == 0)
return 1;

if (!gfxFont) { // 'Classic' built-in font
if (c > 255)
return 1; // Stop 16 bit characters
if (c == '\n') { // Newline?
cursor_x = 0; // Reset x to zero,
cursor_y += textsize_y * 8; // advance y one line
Expand All @@ -1262,9 +1323,10 @@ size_t Adafruit_GFX::write(uint8_t c) {
cursor_y +=
(int16_t)textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
} else if (c != '\r') {
uint8_t first = pgm_read_byte(&gfxFont->first);
if ((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) {
GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first);
uint16_t first = pgm_read_word(&gfxFont->first);
if ((c >= first) && (c <= pgm_read_word(&gfxFont->last))) {
GFXglyph *glyph =
&(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c - first]);
uint8_t w = pgm_read_byte(&glyph->width),
h = pgm_read_byte(&glyph->height);
if ((w > 0) && (h > 0)) { // Is there an associated bitmap?
Expand Down Expand Up @@ -1378,8 +1440,8 @@ void Adafruit_GFX::charBounds(unsigned char c, int16_t *x, int16_t *y,
*x = 0; // Reset x to zero, advance y by one line
*y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
} else if (c != '\r') { // Not a carriage return; is normal char
uint8_t first = pgm_read_byte(&gfxFont->first),
last = pgm_read_byte(&gfxFont->last);
uint16_t first = pgm_read_word(&gfxFont->first),
last = pgm_read_word(&gfxFont->last);
if ((c >= first) && (c <= last)) { // Char present in this font?
GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first);
uint8_t gw = pgm_read_byte(&glyph->width),
Expand Down
27 changes: 23 additions & 4 deletions Adafruit_GFX.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ class Adafruit_GFX : public Print {
const uint8_t mask[], int16_t w, int16_t h);
void drawRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask,
int16_t w, int16_t h);
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color,
uint16_t bg, uint8_t size);
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color,
uint16_t bg, uint8_t size_x, uint8_t size_y);
void drawChar(int16_t x, int16_t y, uint16_t c, uint16_t color, uint16_t bg,
uint8_t size);
void drawChar(int16_t x, int16_t y, uint16_t c, uint16_t color, uint16_t bg,
uint8_t size_x, uint8_t size_y);
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1,
int16_t *y1, uint16_t *w, uint16_t *h);
void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y,
Expand All @@ -121,6 +121,9 @@ class Adafruit_GFX : public Print {
void setTextSize(uint8_t sx, uint8_t sy);
void setFont(const GFXfont *f = NULL);

// Serial UTF-8 decoder
uint16_t decodeUTF8(uint8_t c);

/**********************************************************************/
/*!
@brief Set text cursor location
Expand Down Expand Up @@ -180,6 +183,18 @@ class Adafruit_GFX : public Print {
/**********************************************************************/
void cp437(bool x = true) { _cp437 = x; }

/**********************************************************************/
/*!
@brief Enable (or disable) UTF-8-compatible charset in custom made fonts
By default, the font.h files boundled to the library use ASCII
charset as UTF-8 fonts need more memory as many AVR chips can offer. Pass
'true' to this function if you are willing to use UTF-8 fonts that you
generated whith fontconvert and also your board has enough free memory.
@param x true = enable (new behavior), false = disable (old behavior)
*/
/**********************************************************************/
void utf8(boolean x = true) { _utf8 = x; }

using Print::write;
#if ARDUINO >= 100
virtual size_t write(uint8_t);
Expand Down Expand Up @@ -245,7 +260,11 @@ class Adafruit_GFX : public Print {
uint8_t rotation; ///< Display rotation (0 thru 3)
bool wrap; ///< If set, 'wrap' text at right edge of display
bool _cp437; ///< If set, use correct CP437 charset (default is off)
bool _utf8; ///< If set, use correct UTF-8 charset (default is off)
GFXfont *gfxFont; ///< Pointer to special font

uint8_t decoderState = 0; ///< UTF-8 decoder state
uint16_t decoderBuffer; ///< Unicode code-point buffer
};

/// A simple drawn button UI element
Expand Down

0 comments on commit 3941d5a

Please sign in to comment.