Adding glyphs to adafruit GFX builtin font

I would like to add ° (degrees) to the adafruit GFX built in font (glcd font).
Is it possible, and if so, how should I do it.

may be this will help ?

Thanks for the advice, unfortunately this doesnt help, Im not looking to create a new font, but rather just add a single glyph to the existing font. Apart from that, I am not running Linux.
There are other online font converters available, and my plan was to use one of them to create the glyph and simply add it to the exising font.
Here is the font I would like to modify;

And here is how a created font looks:

I know nothing of the subject, but would it be easier to replace one of the existing characters with the new one rather than adding a new one ?

That would also work i guess. I would replace ' with °
Unfortunately I have no idea how this works, is each hex number a single character, and the ASCII value is used to pull the character from the array?

If you read the tutorial you’ll know about the font structure and how to design a glyph... then it’s just a matter of editing an existung one

When Adafruit draws text on a screen, it uses a print() call. You can override where your calling print to check your character stream for a char that YOU selected as the degree symbol. At that point, draw your symbol at the cursor location then tell the Adafruit code to print a space. (32) to hop over your symbol.

Oh, and to know where you are when you are sitting there wondering where to draw your little circle..

Adafruit has...

int16_t getCursorX(void);
int16_t getCursorY(void);

Just waiting to tell you where you are currently drawing charaters. It'll be an offset from that.

And lastly, how to draw your little circle?

There is always..

void drawPixel(int16_t x, int16_t y, uint16_t color);

And that's a packed 16 bit color. There's ways to get that from a 24 bit to a 16 bit in their stuff as well.

Good luck!

-jim lee

@J-M-L, I read the tutorial and followed the instructions, but was unable to modify the built in text in that manner.
In the file for the built in font there were a couple of code tags marking where some characters are (umlauts for example). I targeted these but was unable to make any sense of the data (i converted the hex from the marked characters to binary to see if I could map out a character, then change it, but no luck). custom fonts are no problem, they can be easily modified. Its just the 5x7 built in font thats proving difficult.

@jimLee, unfortuately it wont be so simple. I am using GUI slice which kind of piggy backs the fonts from adafruit. I am working with a pretty hefty sketch here, doing alot of stuff with characters, atoi, snprintf and so on. I would like some kind of solution that allows me to get the degree symbol using either ASCII or UTF8 to call the character. If I could just replace one character in the font with the symbol I would be right as rain. Its beginning to look like I should just make my own font that resembles the built in font with the glyph that I need.

I cracked the code regarding the built in font in the adafruit lib, upon doing so I found the degree symbol is actually present. It appears to be a bug in the GUI slice lib, I have since opened an issue there.

For anyone wanting to do something similar, In this font each character is 5 bytes. After converting the bytes to bits the characters are rotated 90° clockwise. For example the letter E is shown as so:

00000000
11111110
10010010
10010010
00000000

Glad you could move on

Just to summarize:

Basically a font GFXfont is a collection of glyphs

/// Data stored for FONT AS A WHOLE
typedef struct {
  uint8_t *bitmap;  ///< Glyph bitmaps, concatenated
  GFXglyph *glyph;  ///< Glyph array
  uint16_t first;   ///< ASCII extents (first char)
  uint16_t last;    ///< ASCII extents (last char)
  uint8_t yAdvance; ///< Newline distance (y axis)
} GFXfont;

The first entry is a pointer to a huge array that holds the drawing information for each glyph and then you have a pointer that gives you the description of how to make sense of hat is in this huge array through a GFXglyph description and some overall bounding box and other info.

The GFXglyph structure that looks like this:

/// Font data stored PER GLYPH
typedef struct {
  uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap
  uint8_t width;         ///< Bitmap dimensions in pixels
  uint8_t height;        ///< Bitmap dimensions in pixels
  uint8_t xAdvance;      ///< Distance to advance cursor (x axis)
  int8_t xOffset;        ///< X dist from cursor pos to UL corner
  int8_t yOffset;        ///< Y dist from cursor pos to UL corner
} GFXglyph;

So each glyph is described by the start position in the big bitmap array and then its dimensions (w,h) and some cursor information, where the next character will draw and (X,Y) upper left corner of this glyph.

So a font is described by 3 structures:

  • a GFXfont that is the entry point with high level information global to the font
  • a GFXglyp structure that describes high level information for each character
  • a "BLOB" (binary large object) where all the glyphs bitmap are dumped/packed next to each other

Now, if you look in your FreeMono12pt7 font description

At the bottom you’ll see

const GFXfont FreeMono12pt7b PROGMEM = {(uint8_t *)FreeMono12pt7bBitmaps,
                                        (GFXglyph *)FreeMono12pt7bGlyphs, 0x20,
                                        0x7E, 24};

this says that the BLOB is in the FreeMono12pt7bBitmaps binary array and the high level glyphs description in the FreeMono12pt7bGlyphs structure. It also states that the first ASCII char represented starts at 0x20 (the space) and ends at 0x7E (the ~) and that going to the next line requires to move the cursor 24 pixels down for vertical spacing.

And if you look at the first line of the Glyph description you see

const GFXglyph FreeMono12pt7bGlyphs[] PROGMEM = {
    {0, 0, 0, 14, 0, 1},        // 0x20 ' '

We know from the font description that this entry is for ASCII code 0x20 (space) and This tells us that the offset for the bitmap is 0 ( so this glyph is described directly at the start of the BLOB) and is 0 pixel wide on 0 pixel high... That means we should expect NO byte to be used to describe this glyph! This is somewhat weird as you would expect a bitmap but since a space has no black pixel, you can just represent 'space' by the fact that you don’t paint anything and just move the cursor right which is the 14 you see.

The next entry is more interesting:

   {0, 3, 15, 14, 6, -14},     // 0x21 '!'

it tells you that the offset is 0, so bitmap starts again at the beginning if the BLOB (makes sense since we used no bytes to describe the space) is 3 pixel wide and 15 pixel high and the 3 cursor information (14, 6, -14 ) to position the bitmap in its space.

So if we go look now at the start of the BLOB

const uint8_t FreeMono12pt7bBitmaps[] PROGMEM = {
    0x49, 0x24, 0x92, 0x48, 0x01, 0xF8, 0xE7, 0xE7, 0x67, 0x42, 0x42, 0x42,
    0x42, 0x09, 0x02, 0x41, 0x10, 0x44, 0x11, 0x1F, 0xF1, 0x10, 0x4C, 0x12,
    0x3F, 0xE1, 0x20, 0x48, 0x12, 0x04, 0x81, 0x20, 0x48, 0x04, 0x07, 0xA2,
    0x19, 0x02, 0x40, 0x10, 0x03, 0x00, 0x3C, 0x00, 0x80, 0x10, 0x06, 0x01,
...

3 x 15 = 45 bits, and as we store as bytes, we will need a multiple of 8 bits so the closest is 6x8=48 with 3 wasted bits.

So We need 6 bytes to represent the bitmap and thus only the first 6 bytes are of interest for this glyph0x49, 0x24, 0x92, 0x48, 0x01, 0xF8,. This is confirmed by reading the next line in the glyph structure where we can see the next starting position is 6, leaving bytes 0 to 5 for the '!' bitmap :

{[color=red]6[/color], 8, 7, 14, 3, -14},      // 0x22 '"'

if you try to depict the bits in the bitmap they look like this:

rawBitmap.png

it's hard to see an exclamation mark '!' drawing in this... You need to take into account the glyph definition: we know it's 3 bits wide, so you need to grab the data 3 bits by 3 bits (and ignoring the 3 last bits)

3x3.png

and when you line them up, ignoring the 3 last bits displayed in red here, then the '!' is revealed

In smaller/ real size, it looks "better" of course:
. . . .

So now that we know this, if you want to modify an existing character and not have to mess around with the whole indexing of each start of glyph, you need to pick a glyph you won't use and make a drawing that will use up the exact same number of bytes. You can re-arrrange width and height and cursor information as you see fit since this is independent of then other glyphs but the bitmap has to require the same number of byes to make it easy. Then you draw your glyph, reverse the process to go to the bytes, find where the bitmap needs to go in the bitmap array and replace the bytes of the former glyph by the new glyph.

One option is also to get rid of '~' if you don't need it and as this is the last glyph in the bitmap array, then you can draw your symbol the way you want, without having to worry about the number of bytes

Hope this helps someone at some point!

1 Like

@J-M-L — thank you very much for taking the time to post this fantastic summary of the Adafruit font structures. I am certain that it will help out a lot of people!