tool for finding visual differences between two font versions
fontdiff
is a utility for testing fonts. When you modify a TrueType
or OpenType font, fontdiff
generates a PDF showing the typeset text both before and after the
change. You can use this PDF to easily review the changes and spot any
errors caused by a font switch.
For every line in the text sample, the tool renders two raster images
in high resolution. One image is typeset using the original font, and
the second uses the new font. If there is any difference between
these two high-resolution images (even if it’s just whitespace caused
by kerning changes), the output PDF highlights the difference in
color.
Since fontdiff is using
HarfBuzz for
OpenType shaping, text gets rendered in a similar way across Firefox,
Chrome, Android, LibreOffice, XeTeX, GNOME, KDE, ChromeOS, and other
products.
To provide sample text, use HTML with embedded CSS styling:
<html lang="la">
<p>Lorem <span style="font-weight:700">ipsum</span> dolor sit amet.</p>
</html>
The lang
tag can make a difference for rendering. For example, when
diffing a font with Polish letter
forms,
you can write <span lang="pl">ćńóśź</span>
to see the Polish
variants of accented letters, or <span lang="und">ćńóśź</span>
to see the default design. As with HTML, you can combine spans in
multiple languages into the same document. fontdiff recognizes the
same language tags
as modern web browsers; “und” is the “undefined” or default language.
This is not an official Google product. We needed a lightweight tool
to test our font production pipeline, so we built fontdiff, and we hope
you’ll find it useful, too. However, please understand that there are
some limitations:
Not a full renderer: HTML and CSS are much richer than what this
little testing tool supports. If you miss something, please do not
hesitate to make the change yourself and send a pull request.
Lousy codebase: The current state of the codebase isn’t something
we’d be proud to call production-ready: no tests, too many dependencies,
and so on. fontdiff isn’t a “real” product, and definitely not a showcase
for writing production code.
Not secure: Do not run this tool on untrusted input. It parses
complicated input formats (TrueType, OpenType, HTML) but it isn’t
hardened in any way. Use it at your own risk.
Not a sample generator: This tool compares how an existing
sample text gets rendered in two versions of the same font. However,
it won’t find text for you to render. Some font designers may want
to manually craft samples. Others may want to see how an entire
volume of text is rendered, or check the output of a font-affecting
tool or script. Because the use cases for fontdiff are wildly
different, we felt it would be best to limit its scope to the actual
diffing operation.
$ git clone --recursive https://github.com/googlefonts/fontdiff.git
$ cd fontdiff
$ ./src/third_party/gyp/gyp -f make --depth . --generator-output build src/fontdiff/fontdiff.gyp
$ make --directory build
$ build/out/Default/fontdiff \
--before path/to/old/FooFont*.ttf \
--after path/to/new/FooFont*.ttf \
--specimen src/fontdiff/specimen.html \
--out out.pdf
This incantation works on reasonably recent versions of Linux and MacOS X.
If you want to support other platforms, feel free to make the change.
Pull requests are very welcome!
Here are a few features and concepts we’d love your help implementing,
if you’re bored and/or want to get your hands dirty (or are just a
magnanimous person who loves fontdiff):
Port to other platforms. This should be a very easy starter task
for people familiar with the respective platforms. It shouldn’t
take more than a few hours, since the project already uses
cross-platform libraries and a cross-platform build system.
Testing. Currently, the codebase is entirely untested, which makes
it hard to maintain the code.
More constructs from CSS and HTML.
MathML. With (even limited) support for MathML rendering,
font designers could use fontdiff to test their mathematical fonts.
Sandboxing. To protect users against attacks that use malicious
font or text sample files, set up a
sandbox
early in the tool’s execution and then do all the rendering inside
the sandbox.
CSS box model. It might be nice to properly support the layout of
CSS and HTML, where boxes can be inside boxes. Not sure if this is
terribly important for testing/diffing fonts, but if this tickles
your interest, go ahead.
Paragraph layout. The current paragraph layout is rather
ad-hoc. On the positive side, fontdiff uses
ICU for finding potential line
breaks, so it can be used in testing fonts for Thai and
other languages that don’t mark word boundaries. However, there is
currently no hyphenation or justification, and the current support
for bidirectional text is rather iffy. One option for doing this
properly could be Raqm,
another might be
Minikin. If
you want to look into this, make sure to think about the special
needs for diffing fonts. In particular, a changed glyph width should
not require a re-flow in the entire paragraph — the
resulting diffs would become meaningless. When fontdiff breaks
paragraphs into lines, it currently measures the width of text runs
using both the old and the new font version. The decision about
line breaking is then made based on the maximum of both these
values, which means fontdiff doesn’t run into this reflowing
problem. It will probably be difficult to replicate this
logic when using an existing paragraph layout library. However,
being able to precisely locate the difference between two fonts is
important for font designers, which is why we wrote
the tool in the first place.
Reduce binary size. To avoid dependency hell and to maintain
reproducible versioning, fontdiff is statically linked to all its
dependencies. This is a very intentional choice, but ICU’s data
files are huge. By building a static ICU data library with only
the needed data files (the break iterators), the size of the
compiled fontdiff binary would shrink by about 20MB. If you are
interested in this task, check out how
NodeJS
does it. This task shouldn’t be very difficult, but it’s probably also
not the biggest problem fontdiff needs to solve.
Have fun!