Creating GLCD fonts

Hello all,

I have some questions about GLCD fonts. Both glcdv3 and openglcd releases contain, among others, these fonts: fixednums7x15, fixednums8x16 and fixednums15x31.

I have a project with KS0108 compatible controller and a 128x64 LCD. Now, I can use these fonts directly and they render perfectly. The problem is that if I create a font of the same size with one of the font creators, they do not render properly. Here's what I've found out:

FontCreator2 (java based):

  • for fixednums7x15: to be able to use the generated font, I had to shift the lower 8 bytes 2 bits to the right (if not, this results in a gap of 2 pixels in the middle of the character).
  • for a 8x8 font I have already, this creator seemed to create the correct bit patterns

Mikroelektronika Font Creator v1.2 for GLCD:

  • for fixednums7x15: the created bit pattern is incorrect. I needed to take every second byte of the created character to make the correct one. So if the created byte order is 0, 1, 2, 3, 4 ... 13 to make it right, the byte order would have to be 0, 2, 4 etc. and after that 1, 3, 5 etc. To confirm this I created the same character with the creator and compared it with the one in fixednums7x15.
  • I tried to do the same for fixednums15x31 but couldn't convert it using the same logic.

So the questions are:

  • what creator was used to create the fixednums7x15, 8x16 and 15x31 fonts? And how do I create these fonts more easily?
  • where can I find OpenGLCD font creator? (or: how do I create new fonts into OpenGLCD?) The documentation mentions it and there is a link to the zip but the link is dead. I think this creator may create the correct characters.

I don't use either GLCDv3 or the OpenGLCD libraries directly, I have my own libraries for KS0108.

Example: bit pattern of the character '1':

// Correct bit pattern for the character 1, size 15x31 (no padding). From fixednums15x31.h.
0x30, 0x30, 0x30, 0x30, 0x3c, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,

// From Mikroelektronika font creator, visually created the same character (renders incorrectly):
0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
0x30, 0x3C, 0x00, 0x00, 0x30, 0x3C, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF,
0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x30, 0x00,
0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30,


// From GLCD fontcreator 2 (java based)
0x30, 0x30, 0x30, 0x30, 0x3C, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFC, 0xFC, 0xFC, 0xFC, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,

Any help is greatly appreciated!

Apparently, at some point I accidentally removed openGLCDfontCreator from the download area.
I have put it back into the openGLCD download area.
The links in the openGLCD html documentation to the openGLCDFontCreator should work again.

I'll also consider including it within the release just like the bitmap tools.

Keep in mind that there are different types of fonts.

  • Fixed width
  • Fixed Width (with no pixel padding)
  • Variable width with pixel padding.

openGLCDFontCreator creates fonts using the variable width format.

There are other tools out there that work that I have used to create compatible pixel data.
(It has been several years since I have done this)
It can be tricky to get the tool to create the pixel data in the needed format and some tools are incapable of creating
data in the needed format.

The issue you are probably running into is they way bits are stuffed into fractional bytes.
Fractional bytes are bytes that contain less than 8 bits of pixel data.
I absolutely detest the way it was done, and I think it was a bug in Thiele's original Font creator and/or library.
This goes back to his early ks0108 library and has been propagated around and including up to openGLCD.
I had originally thought about fixing it (the fix is easy) but it would break glcdv3 compatibility
which I had as a high level goal for openGLCD.

The issue is for fractional bytes when the rendered glyph (not including pixel padding) is not an exact multiple of 8 pixels.
The valid bits are pushed to what I consider to be the wrong end of the byte.
This is a real pain to support, makes the code a bit larger and slower,
and it is not the way the bits are stuffed into bytes for bitmaps. This is why I believe it was an error vs an intentional design.

Changing fonts to map the bits the same way as bitmaps has many advantages,
This would keep all the rendering code the same and bitmaps and font glyphs could then be interchangeable.
The only disadvantage is it is not compatible with any of the existing fonts that users may have created for use with the earlier libraries.

There are many many issues with the current font format as well as bugs in the font tool that require several work arounds in the library code . Someday I hope transition away from the format, even though re-writing the rendering code to correctly render any sized character on any pixel boundary without a frame buffer is a big task.

--- bill

Hi Bill and thanks for putting the fontcreator back. I'm hoping you could give me some tips as to why the fontcreator does this. For testing I created an all-black, size 15x30 "character", ie. all bits set. When I export it from fontcreator I get this:

0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,

So, even though I set all bits and it should be an all-black char sized 15x30, it's not. Although this is not that simple as after every 15 bytes the rendering code inserts a pad byte (0x00). I have attached a picture of the LCD showing the character. The LCD is set to print the above char, then period (.), then the number 2 and then again the above char.

From the picture you can see that a) there is a shift of 2 horizontal pixel rows and b) 2 extra horizontal pixel rows at the bottom. The other chars are from the fixednums15x31 font file, unmodified.

Could it be that the fontcreator can't handle characters this big? Any tips on how to get proper fonts out of the creator or how to convert these without bit manipulation by hand? Thanks in advance.

Edit: corrected typos, the font is indeed 15x30, not 7x15 (the attachment is incorrectly named).

I am seeing some conflicting information.
You said you created a 7x30 character, but from the data it looks like it is 15x30

That image appears to be rendering a character 15x32 pixels but it looks like the font data is only 30 pixels tall.
It appears the rendering is incorrectly interpreting Thiele's font data format.

I'm assuming that this is not being rendered with openGLCD?
If so, why not use openGLCD?
Rendering arbitrary font sizes on arbitrary vertical pixel boundaries is quite difficult; why try to re-create the wheel?

The lower byte of the font is only 6 pixel bits and those 6 pixel bits are in bits 2-7 not bits 0-5 since the valid bits
are shifted up.

Thiele's font format shifts the fractional pixels in a byte to the other end of the byte.
A 30 pixel tall font is not a multiple of eight so the lower set of pixels resides in a byte that is no 8 pixels of data.
When this occurs, valid pixel bits are shifted up in the byte value and the unused bits in the bytes are set to 0.

i.e. if there is only 1 valid pixel it will be bit 7, if 2 it will be bits 6 and 7, if 6 pixels it will be bits 2 to 7.
That is why the 15 lower bytes of the glyph are 0xFC vs 0x3F

I have never liked this way of doing things as it makes the decoding a pain since you have to know when you are decoding the lower byte and then how many pixel bits are valid to know where the the pixel bits start in the byte, rather than always starting at bit zero and grabbing the bits until you have all of them.

I only stuck with this format for compatibility with the older glcdv3 library.

--- bill

This font generator produces nice font files in C code compatible format that can easily be adapted for the Arduino. This is the font generator I use for all my projects that use graphics LCD displays, example here.

The generated font file formats are convenient as all the character pointer, width etc. information is nicely presented in const variables and arrays making proportional font rendering easier.

The bad news is that the generator can crash occasionally so regular saves of work in progress are advised but once the quirks are known it is a very productive tool.

TTFN

Hi Bill, thanks for your input.

bperrybap:
I am seeing some conflicting information.
You said you created a 7x30 character, but from the data it looks like it is 15x30

Yes, sorry, it is of course 15x30.

That image appears to be rendering a character 15x32 pixels but it looks like the font data is only 30 pixels tall.
It appears the rendering is incorrectly interpreting Thiele's font data format.

So the fontcreator is correct and I need to figure out how to convert the fonts to my format.

I'm assuming that this is not being rendered with openGLCD?
If so, why not use openGLCD?
Rendering arbitrary font sizes on arbitrary vertical pixel boundaries is quite difficult; why try to re-create the wheel?

I understand your point and I would definitely use the openGLCD if I could. But, I don't use arduino and so using the openGLCD could prove quite difficult (I could convert it but it's in C++ and I'm not familiar with it). Second, I already have working fonts (the fixednums7x15, 8x16 and 15x31).

So if these fonts are incorrectly formatted, will they work with GLCD library at all? Because as I said these work with my rendering code and so I already have the numbers 0-9 and a couple of special chars. Just need to find out how to create more without too much trouble. And I think it's easier to convert the fonts than develop a new rendering code (or implement the one openGLCD uses) in C.

The lower byte of the font is only 6 pixel bits and those 6 pixel bits are in bits 2-7 not bits 0-5 since the valid bits
are shifted up.

Thiele's font format shifts the fractional pixels in a byte to the other end of the byte.
A 30 pixel tall font is not a multiple of eight so the lower set of pixels resides in a byte that is no 8 pixels of data.
When this occurs, valid pixel bits are shifted up in the byte value and the unused bits in the bytes are set to 0.

i.e. if there is only 1 valid pixel it will be bit 7, if 2 it will be bits 6 and 7, if 6 pixels it will be bits 2 to 7.
That is why the 15 lower bytes of the glyph are 0xFC vs 0x3F

I have never liked this way of doing things as it makes the decoding a pain since you have to know when you are decoding the lower byte and then how many pixel bits are valid to know where the the pixel bits start in the byte, rather than always starting at bit zero and grabbing the bits until you have all of them.

I only stuck with this format for compatibility with the older glcdv3 library.

I don't really get the Thiele format and why it needs to do that. But thank you for the explanation.

Not sure what you mean by:

So if these fonts are incorrectly formatted, will they work with GLCD library at all?

What "GLCD" library? Anything can work with anything. It is all a matter of programming.

The Thiele format shifts the used pixel bits to the upper end of the byte when there are less then 8 pixel bits in the byte. My guess is that this is/was an unintended bug.
If you look at the byte to pixel layout, this shift would make sense to do if you are laying out your pixel data horizontally
vs vertically and the bits are mapped to the display MSB to LSB going left to right. In that case, a shift of the valid pixels twards the MSB end (to the left on the display) would make sense.
But for this format where pixels are mapped LSB to MSB vertically top to bottom, the shift of the valid pixel bits twards the MSB end of the byte (down on the display) doesn't make sense since the byte no longer matches the physical pixel mapping of the GLCD.

Font data generation tools often have options as to how to create the output data.
Things like horizontal vs vertical pixel data, MSB vs LSB first, then 8 bit vs 16 or even 32bit data, and when the data is wider than 8 bits it can be big or little endian. And then how to handle the fractional bytes.

There are many combinations of how the data can be stored and several of the tools have options you can set to control how the data is stored so it can match what the rendering code expects.

Just remember that openGLCD is licensed GPL v3 so it cannot be used in closed source projects/products, and if you use it or portions of it, all your code must become GPL v3 open source.

--- bill