Building on the base documented in my previous post, it is time to shift from a seven segment display to a true dot matrix display. This takes advantage of the refactored model, demonstrating that dotfonter.lua
itself need not change to support a radically different kind of font to draw.
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.
A dot matrix font
See the previous post for a discussion of the division of labor between the dotfonter.lua
utility (and its associated Lua modules) and the font description in a .dotfont
file. To follow along, refer to the tree view of files in the project, or clone and open your own working copy of the project.
The existing sevensegment.dotfont
and the new fivebyseven.dotfont
files are in the src
folder, along with all the source code of the dotfonter
utility, primarily written in Lua.
No changes were needed to any other source file as part of making a font based on a dot matrix instead of seven segments. That hints that the refactoring done for the previous post achieved its goal. I did tweak the Makefile
to better reflect my current preferences for the font summary document written by fret
.
So let’s compare sevensegment.dotfont
to fivebyseven.dotfont
.
Both are intended to be loaded by dotfonter.lua
, and as such must be a Lua program that returns a table describing the font to build. Both use a locally defined function to transform a textual description of a character into a set of TrueType glyph contours.
For the seven segment font, we made a table of the seven (actually ten, including a decimal point, a second dot for a colon, and a triangle to make a comma) segments giving each a letter name. The individual characters then list which segments to light up by name: abcdef
for a zero, bc
for a one, etc.
For the dot matrix, my sample is based on the character generator ROM for a popular LCD controller (the HD44780). Since the characters are low resolution, ASCII art seems like a reasonable representation for them, so we will use an array of strings, one for each row of dots, to draw each character.
For example, the at sign (@
) will look like this:
Glyph{unicode=0x40, name='at', pat={ '.###.', '#...#', '....#', '.##.#', '#.#.#', '#.#.#', '.###.', } },
This snippet is taken from the array of glyphs in the font, and calls the function Glyph
defined in the .dotfont
file to convert the pattern into contours, and assign a code point (U+0040) and a name (“at”) to the character. It will infer the left side bearing from the leftmost column containing a dot, and will by default set the rest of the character metrics for a fixed pitch font.
The Glyph
function could easily be extended to discover the size of the matrix from the count and lengths of the strings, and even to support variable pitch fonts by allowing the strings to vary in length and computing the necessary metrics from the strings. The present version uses the first five characters of the first seven strings. Excess characters and strings are silently ignored.
It makes copies of a single dot definition at each of the up to 35 locations for dots in the character cell. The current sample takes advantage of the cubic splines in TrueType to draw a dot that is very nearly circular, centered in a 128 by 128 unit square with a radius of 55 units. That makes adjacent dots have about an 18 unit gap between them, which is more than enough for them to appear quite distinct even at relatively small sizes.
As with the seven segment font, every glyph is drawn in a 1024 unit em square.
local dot = { { 9, 64, 1}, { 13, 13, 0}, { 64, 9, 1}, {115, 13, 0}, {119, 64, 1}, {115, 115, 0}, { 64, 119, 1}, { 13, 115, 0}, }
Drawing a circle in TrueType
A little googling around will reveal that TrueType fonts are based on a class of curves call “quadratic spline curves”.
These curves are assembled piece-wise from segments of quadratic polynomials. This turns out to be a compact way to describe a wiggly path. The path is defined by a list of points, some of which are on the curve and others off the curve. It is guaranteed to pass through every point that is on the curve. But it has the “problem” that it is impossible to draw a circle with quadratic splines.
But it turns out that “impossible” really means that the curve cannot be exactly a circlular arc, but does not mean that it can’t be a decent approximation of a circular arc. And it turns out that the eight points listed above are a usable approximation of a circle from four quadratic segments. A better approximation would use eight segments, but that seems like gilding a lily.
The eight points are the centers of the sides of the bounding box marked “on” the curve, and points along the radii not quite all the way to the corners of the box.
Wikipedia or any decent textbook on computer graphics will lead you along a very dreary garden path to calculating just where to put the off-curve points for a good approximation. I used a much more pragmatic approach: I started with the corners of the bounding box then walked the points inward along the radius until I liked how they look. This seemed like the right approach for a simple decorative font design.
Playing Along at Home
Clone the public fossil repository.
The version of the code described in this post is from checkin [5d5253b6].
There are still a lot of features missing from the script, but the bones are there to build upon. dotfonter.lua
defers to an external file for both the shapes of the segments and the ROM image itself. This post shows that the external file alone had enough power to define a five by seven dot matrix font.
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.
Supporting Cast
Here are some tools I’m using to develop this utility:
Documentation and references:
Foreshadowing
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 five by seven dot matrix display and is a fixed pitch font.
The next step is to build a complete font for a dot matrix display.
Summary
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 dotfonter
.
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.)