400 LoC is impressive - my Ruby translation of libschrift is about 680 lines now, and of that 345 lines is parsing the damn TTF files. I might have to revisit it ;)
It's ~240 LoC of C to take a glyph from the file and paint it using GDI, including lots of debugging prints. Of course, error checking is minimal, but I think getting to the outline data itself isn't that difficult, since all you need to get to is a list of points and contours and whether they're on-curve or not.
I have a small TTF implementation in C++ that's only a little bigger than that and is open source. It's part of my canvas_ity single-header library [0] that's around 2300 LOC / 36 KB object size and implements a C++ version of most of the 2D HTML5 canvas spec [1].
The core implementation of the TTF parsing and drawing is in L1526-L1846 with another small bit at L3205-L3274 of src/canvas_ity.hpp.
It's something of a toy implementation that only supports western left-to-right text, and doesn't do any hinting at all, nor kerning, nor shaping. But it's enough to draw a basic "Hello world!" using any typical TTF file.
The test suite in test/test.cpp L84-304 embeds a few custom Base64-encoded TTF files. They're small and only have a few glyphs but they do exercise a number of interesting edge cases in the OpenType TTF spec [2]. Have a look at the HTML5 port of the test suite at test/test.html in different browsers to see how their canvas implementations render those fonts.
Having read through this, I love it. Very readable for C++...
In terms of the actual TTF bit, if you pull out everything needed it's probably somewhat bigger than what I already have, but that's because libschrift and my Ruby translation does tesselation and rasterisation that's doing the very barest minimum needed for the basic TTF rendering and yours is far more generic (and let's face it: fancier/more featureful in a good way) rendering of the polylines.
I've already half-wanted to pull that out of my Ruby port anyway and doing a basic canvas, so I might just look to yours for inspiration on doing that in a way that can be reused if I get the urge to extend it further later.
That's great. Thanks. For my use the lack of kerning doesn't matter much as I mostly use it for my terminal, and so monospaced, and I haven't added hinting either.
Comments
400 LoC is impressive - my Ruby translation of libschrift is about 680 lines now, and of that 345 lines is parsing the damn TTF files. I might have to revisit it ;)
It's ~240 LoC of C to take a glyph from the file and paint it using GDI, including lots of debugging prints. Of course, error checking is minimal, but I think getting to the outline data itself isn't that difficult, since all you need to get to is a list of points and contours and whether they're on-curve or not.
Is it open source? Would love to see. Doesn't matter if it's lacking error checks - still impressively small, and doubly so for C.
I have a small TTF implementation in C++ that's only a little bigger than that and is open source. It's part of my canvas_ity single-header library [0] that's around 2300 LOC / 36 KB object size and implements a C++ version of most of the 2D HTML5 canvas spec [1].
The core implementation of the TTF parsing and drawing is in L1526-L1846 with another small bit at L3205-L3274 of src/canvas_ity.hpp.
It's something of a toy implementation that only supports western left-to-right text, and doesn't do any hinting at all, nor kerning, nor shaping. But it's enough to draw a basic "Hello world!" using any typical TTF file.
The test suite in test/test.cpp L84-304 embeds a few custom Base64-encoded TTF files. They're small and only have a few glyphs but they do exercise a number of interesting edge cases in the OpenType TTF spec [2]. Have a look at the HTML5 port of the test suite at test/test.html in different browsers to see how their canvas implementations render those fonts.
[0] https://github.com/a-e-k/canvas_ity
[1] https://www.w3.org/TR/2015/REC-2dcontext-20151119/
[2] https://standards.iso.org/ittf/PubliclyAvailableStandards/c0...
Having read through this, I love it. Very readable for C++...
In terms of the actual TTF bit, if you pull out everything needed it's probably somewhat bigger than what I already have, but that's because libschrift and my Ruby translation does tesselation and rasterisation that's doing the very barest minimum needed for the basic TTF rendering and yours is far more generic (and let's face it: fancier/more featureful in a good way) rendering of the polylines.
I've already half-wanted to pull that out of my Ruby port anyway and doing a basic canvas, so I might just look to yours for inspiration on doing that in a way that can be reused if I get the urge to extend it further later.
That's great. Thanks. For my use the lack of kerning doesn't matter much as I mostly use it for my terminal, and so monospaced, and I haven't added hinting either.
Sorry, no. I used part of the code in a commercial product.