Typography: Notes of a Beginner Engineer
Hi everyone!
My name is Marian, and I’ve decided to dive into typography from an engineering perspective. I got interested in this field quite recently when I realized how much is hidden behind fonts and how they are rendered. Before, I never thought about how it all works, but now I want to explore the path that others in this area have already taken. Luckily, many problems have already been solved, which makes it easier for me compared to those who started decades ago.
I prefer learning by doing, and typography will be no different. My plan is to create my own font rendering engine. Along the way, I might also develop some small tools that will add to my experience. I’ll document this journey by taking notes and sharing the important steps. This will help me stay organized and could even be useful for others who face similar challenges. But most importantly, it’s for me—to better understand the process and get advice from those who know more.
I know this won’t be easy, and there will be lots of questions and challenges ahead. But that only motivates me to keep going. It’s going to be a long but exciting journey.
I’ll take it step by step, setting small goals and tasks. As I make progress, I’ll share my updates and the issues I encounter.
The first step will be to create a simple parser for TTF fonts that can render a given glyph. At first, it will draw to a file, and all calculations will run on the CPU. Since I actively use C++, it will be my main programming language, and I’ll try not to rely on external libraries for the implementation.
Let’s get started!
Comments
-
The first thing I needed was the TrueType specification, which I found on Apple’s website: TrueType Reference Manual.
Before starting to draw anything, I prepared some basic tools:
Image format: I decided to save images in the simplest educational graphics format, .ppm (Portable PixMap).
Basic rendering: To draw contours, I’ll connect points with straight lines using the simple Bresenham’s line algorithm. It’s perfect for a start.
Endian conversion: Since bits can be stored in different orders (endianness), I wrote some helper functions for byte swapping. As far as I understand, TTF files mostly use Big-Endian.
Configuration: For easier testing, I added a JSON config file to input various settings—such as the font file, output image size and name, glyph and background colors, and more.
Logging: To make debugging easier, I added a logger that can write messages to either a file or the console.
With these basic preparations done, I set up the project using CMake as a simple console application. Now the task is to extract the necessary information from the font file to render individual glyphs. For now, I’m not worried about optimizations or full details—this first step is just to get things working.
The Process So Far
Reading the file header: This helps determine the font type and number of tables.
Reading the table directory: This provides access to specific tables in the font file. The records here also contain checksums for table integrity and their sizes.
Exploring tables: The test font I used had 12 tables with the following tags: FFTM, OS/2, cmap, gasp, glyf, head, hhea, hmtx, loca, maxp, name, post.
Next, I started reading specific tables, focusing on these:
head: This table contains global font data (TrueType head table).
maxp: This gives details about the maximum values for various font elements (TrueType maxp table).
cmap: This maps character codes to glyph indices (TrueType cmap table).
loca: This table provides offsets to glyph data in the glyf table (TrueType loca table).
Finally, I moved on to the glyf table, which contains the actual glyph data. Since it’s quite complex, I started simple—drawing contours as straight lines connecting control points.
Results
The result of this first step took me about 6–7 hours. It’s not perfect, but it’s a start. Next, I’ll focus on adding Bézier curves and calculating glyph spacing. I’ll also refine the details needed for rendering contours.
Here’s the image of what I’ve got so far. It’s just the beginning, but I’m excited for what’s next!
1 -
Hey, Marian! That is very cool.
I will just note that, while the background here is complicated, the OpenType / Open Font Format specification essentially also the TrueType specification… as used by the vast majority of folks other than Apple.0 -
Thomas thank you very much! Yes, after TrueType, I plan to extend the functionality to include OpenType and WOFF.0
-
I think perhaps you miss my point? I mean, the OpenType spec IS the TrueType spec for most of the world, for the past 28 years. It is not crazy to refer to both for TrueType purposes and to understand what is “core” to the format vs not. But if you want cross-platform fonts, using only the Apple spec is not the way to go. You *can* use only the OpenType / OFF spec, though.
If you are only using one spec for TrueType, you are probably using the wrong one, IMO.
0 -
Thank you for the detailed explanation! I really appreciate it. My initial thought was that starting with OpenType might be more complex, so I decided to begin with what seemed like the simpler TrueType specification. But now I see.0
-
Unfortunately "OpenType" means many things and people use it in different ways:
- OpenType came about as the merger of TrueType with CFF, so some people refer to "OpenType" as opposed to "TrueType" - in other words, "fonts with a CFF table".
- OpenType added OpenType Layout, so some people refer to "OpenType" as opposed to morx/kern/etc - in other words, "fonts with GSUB and GPOS tables".
- These two meanings are orthogonal: you can have TrueType ("not OpenType" under meaning 1) outlines with OpenType Layout tables, and you can have CFF outlines ("OpenType") without OpenType Layout tables.
So if you're looking at which specification to implement, the answer is: "Use the OpenType spec, even if you are not planning to touch the CFF table, or even if you're not thinking about GSUB/GPOS-based layout rules for now, because it's the modern specification which covers all of them". Apple's TrueType spec is a historical artefact at this point.
Oh, and:maxp: This gives details about the maximum values for various font elementsIn my experience, maxp contains two things: the number of glyphs in the font, and lies.
Also: very cool! Keep going! You may find this chapter useful.
4 -
Thank you all for your feedback and advice — it really means a lot to me. Today I continued working on font parsing and made two small but important improvements.
The first change is related to adding the calculation of the spacing between characters so that the text looks more natural when displayed. For this, I used the hhea and hmtx tables. The hmtx (Horizontal Metrics Table) holds specific data such as the character width (advance width) and the left side bearing for each glyph. Currently, my implementation only supports horizontal text, so many details, like vertical writing or special font metrics, are not yet handled. However, I plan to revisit this in the future to make the character spacing calculation more accurate and universal.
The second change is about rendering glyphs. I added support for Bezier curves and reworked the rendering logic. Previously, I displayed glyphs using only straight lines between points, which worked fine for simple shapes. Now the algorithm checks the flags of the points (on-curve or off-curve), and if necessary, it draws quadratic Bezier curves to smoothly connect the control points. Now the glyphs look much closer to the original, but this is just the beginning. In the future, I plan to optimize the code and consider more aspects of rendering, like supporting more complex contours and additional font parameters.
Your feedback and advice on this would be very helpful, especially if you have experience working on similar tasks!
0 -
This is looking good! Next thing to do is to read The Raster Tragedy.3
-
Thank you Simon! I'm already reading it (it is a brilliant), but I think I'll spend a few more days experimenting with this code, extending the functionality for testing, and checking as many fonts and characters as possible to fix the most obvious issues. Then we can move on to the anti-aliasing part!0
-
Thank you for letting us participate in your development process
The Raster tragedy, and by extension, a TrueType scaler engine, are very interesting indeed. But before you go down that rabbit hole, perhaps ask yourself which area interests you most.
TrueType rasterization using TT instructions are mainly useful for small text sizes, and you could spend a really long time diving into this.
But maybe implementing OpenType layout (the link goes to another chapter of @Simon Cozens’ book) would be more relevant? It's another deep rabbit hole...2
Categories
- All Categories
- 43 Introductions
- 3.7K Typeface Design
- 803 Font Technology
- 1K Technique and Theory
- 622 Type Business
- 444 Type Design Critiques
- 542 Type Design Software
- 30 Punchcutting
- 136 Lettering and Calligraphy
- 83 Technique and Theory
- 53 Lettering Critiques
- 485 Typography
- 303 History of Typography
- 114 Education
- 68 Resources
- 499 Announcements
- 80 Events
- 105 Job Postings
- 148 Type Releases
- 165 Miscellaneous News
- 270 About TypeDrawers
- 53 TypeDrawers Announcements
- 116 Suggestions and Bug Reports