Earlier posts discussed my motivation for having a dot matrix font that faithfully reproduced the look and feel of a simple character mode LCD display module, and my plan for a utility to easily make fonts like that.
This post is one of several describing a utility that will read a variety of textual descriptions of characters and produce a usable TrueType font.
TrueType and its close relative OpenType are an immensely powerful language for describing font faces, including the detailed shapes that make up each character, an ability to inject code into the font rendering process to improve its appearance at small font sizes, the ability to describe multiple mappings between the characters known to the font and character codes (ASCII, Unicode, ANSI with code pages, etc.) used by applications. All this power comes at the price of a very complex file format.
Fortunately, it is possible to ignore most of the advanced features and still get nice looking results when creating fonts which are not intended for typesetting dense running text at small sizes.
A TrueType font is fundamentally a collection of shapes that can be drawn, along with details such as how far to advance the cursor after drawing each shape, and all the information needed to do advanced typographic tricks such as kerning, picking one of several variations of a character based on context, and more. These shapes are called glyphs and are not quite the same as characters. Although for our purposes, the difference is mostly academic, and we can consider a character in a font as being a map from a character code to a particular glyph to draw.
A TTF glyph is a collection of vectors that describe the shape to draw, using a technique called quadratic Bézier curves. A glyph can also be drawn as a bitmap or raster image, or if OpenType extensions are used, as vectors based on cubic Bézier curves or even SVG.
A glyph can also be made up by composing other glyphs. This is a handy feature for building complicated fonts with lots of accented characters that we won’t use.
Glyphs are Contours
Since we are restricting ourselves to simple classic TrueType vectors, each glyph will fundamentally be a named array of contours, and each contour is a closed curve made up of segments that are each a quadratic Bézier curve.
In the simplest case, the “inside” of each contour will be filled with ink. Things get more complex when one contour is nested inside another, of course. Luckily, for a dot matrix font we won’t need to worry about those cases because each dot in the matrix can be made from a single contour.
So we define a contour simply with a list of control points, with some “obvious” simpler cases supported. Each point is marked as on or off the curve, and that marking is used to decide which corners are sharp and which are not.
Character codes map to glyphs
Without character codes, a font would be hard to use. Not so many years ago, the choice of character code was difficult and messy if you needed characters outside of the 96 well known characters of 7-bit ASCII. Things got messy quickly just by attempting to support the small handful of accented letters needed by common European languages, got messier when Greek and Russian were considered, and you don’t even want to try to imagine what was done to provide support for Japanese, Chinese, Korean, and all the rest.
Luckily, the Unicode standard was created, and has finally achieved enough traction to be useful. Unicode provides a coding system that maps “code points” to characters used by as many living languages with writing systems as possible, with provision for some historically interesting dead languages along with symbols, punctuation, and even the emoji symbols made popular in text messages.
One of the key features of a TrueType font then is the mapping table that identifies which glyph from the font to retrieve for a specific character code. There are actually multiple maps, one for each character coding system.
We will be interesting in providing maps for generic Unicode, Macintosh, and Windows.
Fonts need Names
TrueType provides a table to collect strings that describe the font. Each string may be provided in multiple platform encodings, as well as in multiple languages. Specific strings are identified by Name ID, a 16-bit unsigned number, which is qualified by platform, encoding, and language codes.
At present, there are 25 Name ID codes with explicit definitions, ranging from 0 to 24, codes 25 to 255 are reserved for future use, and codes 256 to 65535 are free for use by the font vendor or the font itself.
Some of these are just free text fields intended to hold things like copyright message in Name ID 0, trademark notice in Name ID 7, license statement in Name ID 13, and even a description of the typeface in Name ID 10.
Others have well-defined formats. These include the version string in Name ID 5, which should begin like
Version 1.001, as well as several strings that are expected to hold [URL]s related to the font vendor and designer, and a string containing sample text to demonstrate the font.
There is some unfortunate complexity surrounding the collection of strings that are intended to provide a name for the font for use by both humans and programs. Some of the complexity is due to different expectations from Mac and Windows systems; some from providing for ease of use with PostScript; and some from supporting the strong convention that fonts are often designed in families made up of variations in weight, width, and slant.
Name IDs 1 and 2 are the font family and subfamily names. These will likely be shown to the user in a font selection menu, but the full font name with Name ID 4 could also be shown instead. Name IDs 16 and 17 provide for more complex font families with more than just the four variations “Regular”, “Bold”, “Italic”, and “Bold Italic”. Name IDs 21 and 22 provide for even richer naming conventions.
Every font used by Windows must provide usable strings in Name IDs 1 through 6. In particular, leaving out IDs 3 or 6 will almost certainly cause the dreaded error “The requested file … is not a valid font file” to pop up in Windows. These strings should relate to each other in the ways specified in the description of the
The detail that Name IDs 3 and 6 are important was discovered from this answer to a question at Stack Overflow. Since Name ID 6 is related to PostScript, it is surprising that Windows cares. Name ID 3 is defined as a “unique font identifier”, and is hardly described at all. Accidentally leaving Name ID 3 out of my first font produced by hand was the cause of much exasperation.
Playing Along at Home
I have created a public fossil repository for code related to this effort.
The first version of the code that correctly writes a TTF font is from checkin [dcc428b741b42cc4].
There are a lot of features missing from the script, starting with the fact that the font it generates along with the name of the file it writes are all encoded directly in the Lua code in
dotfonter.lua. The plan, of course, is to separate the source code of the font from the source code of the utility, and to implement options like the common
-o to name the output file.
All of the code is licensed under the MIT license. Please do let me know if
dotfonter is useful to you, or if you find any issues.
Here’s some tools I’m using to develop this utility:
- Lua is a remarkably powerful programming language originally created to extend large applications through scripting and data representation. Modern versions are stable, free, perform well, and are suitable for constructing complete programs, with supporting libraries written in C.
The usual Lua IDE with highlighting, debugging, and many other features is ZeroBrane Studio. Unlike most IDEs, it treats the file system as the only metadata it needs about a project, which makes it trivial to work with any version control system desired. This project will use fossil, as is my habit.
While Lua doesn’t require a build step in general, distributing our utility will mean building a release
.exefile along with a
.zipcontaining that along with some documentation. Since our needs are simple, the classic make will do all that we need.
fontTools is a library for manipulating fonts, written in Python. TTX is a font conversion tool based on the library that can convert a variety of fonts into an XML form, and convert the XML back into a font in a variety of formats.
FontUtils is a collection of font manipulation utilities written in Perl that includes fret, which draws nice reports showing detailed views of all glyphs in a font.
When working with TrueType at this level, having documentation to refer to that can unambiguously answer detailed questions will be handy. Resources that were helpful include:
- ISO/IEC 14496-22:2015(E) OpenType, standardized as Open Font Format. Since OTF shares many details with TTF, this covers many details of TrueType as well as OTF. The link is to the ISO/IEC directory of free standards, search that page for 14496-22 and collect everything that seems relevant.
TrueType according to Apple The TrueType Reference Manual from Apple. It covers most details of TTF, with strong recommendations for keeping Apple systems happy.
OpenType according to Microsoft All things OpenType, references, links, and recommendations from a Microsoft and Windows point of view..
Watch this space for more articles about work in progress on the utility.
The code I have running today has created a TTF font from scratch covering only the digits, and a few letters. The output is styled after a seven segment display and is a fixed pitch font.
The next demonstration will focus on separating font design source from the utility source code. This will convert a one-off stunt into the beginnings of a useful tool.
After making a dot matrix display font by hand using the impressive capabilities of FontStruct, I decided I wanted a tool to make the whole process easier. The result is the work in progress currently named
If you have a project involving embedded systems, micro-controllers, electronics design, audio, video, or more we can help. Check out our main site and call or email us with your needs. No project is too small!
+1 626 303-1602
Cheshire Engineering Corp.
710 S Myrtle Ave, #315
Monrovia, CA 91016
(Written with StackEdit.)