Awesome
fontwriter
Generates and optimizes Structured JSON fonts for TextraTypist.
Also stores pre-made Structured JSON fonts here in the repo.
Wait, what?
TextraTypist has the class Font
, a... fairly complete replacement
of the BitmapFont code in libGDX. It supports various extra features, including
rendering signed distance field (SDF) and multi-channel signed distance field (MSDF) fonts out-of-the-box.
These are ways of rendering fonts using a different shader internally, and allow one font image to scale
smoothly to much larger sizes without losing much quality. However, generating these fonts can be a
challenge; MSDF fonts in particular only had a few options (such as
msdf-gdx-gen, an inspiration for this project), and most of the
existing options had to clumsily wrap the one utility for generating MSDF fonts... one character at a time.
Having to stitch together sometimes hundreds of individual textures, one per char, tended to cause issues
where letters would "wobble" up and down over a sentence, especially for smaller chars or fonts with many
chars. The author of MSDF and most utilities surrounding it relatively-recently wrote
msdf-atlas-gen, which can output to several font file formats,
but not the AngelCode BMFont format that libGDX and TextraTypist can natively read. It can produce JSON,
though!
The Structured JSON msdf-atlas-gen produces can be read in by TextraTypist to produce working fonts.
Support for loading Structured JSON is present in TextraTypist snapshot builds and is expected in 1.0.0
(the next release). That release also includes (or will include) BitmapFontSupport
, which can
load a libGDX BitmapFont from a Structured JSON font file, and FWSkin
to load fonts produced by "FW"
(FontWriter, this project) as BitmapFont
or Font
. Another micro-library exists, FreeTypist
, to load
FreeType font configuration in a way that both Font
and BitmapFont
can read, as well as loading those
from .fnt
or .json
files.
Do I need to run this at all?
Possibly not! There are quite a few pre-made Structured JSON fonts in a variety of styles in
the docs/knownFonts folder. You can copy the JSON or DAT font file, the PNG file with the same
filename but different extension, and any license file(s) related to that font, copy them into your assets folder in a
libGDX project, and load the JSON/DAT using code from TextraTypist (maybe just copied without a dependency).
Using BitmapFontSupport
, you can load Structured JSON into BitmapFont objects (this class can probably be
copied). Otherwise, you can use the Font
constructor that takes as its last parameter
boolean ignoredStructuredJsonFlag
(its value doesn't matter, just that you pass a boolean there). You can
also use FWSkin
, FreeTypistSkin
, FWSkinLoader
, or FreeTypistSkinLoader
if you use these with scene2d.ui.
From then on, the font acts like a normal Font
or BitmapFont
. You probably shouldn't try loading distance field
fonts with BitmapFont
; it may be possible to load DistanceFieldFont
objects later. For now, "standard" is the
best option.
Note that the .json files are generated by msdf-atlas-gen, and the .dat files are simply compressed (binary) versions of the corresponding .json files. You only need one or the other. The .json files are larger, but human-readable and human-editable, somewhat. It isn't often that you'll need to edit one of the .json files, so .dat is usually better and a substantially smaller file. The file size will matter less in a JAR, but it matters a lot for a Git repo like this one or like TextraTypist that hosts a lot of fonts.
This can generate SDF and MSDF fonts about as easily as it can "standard" (non-distance field) fonts, and so there are SDF and MSDF versions of every "standard" font here. Crispness is handled automatically by information in the .json or .dat file, and by TextraTypist. This is an improvement over the .fnt approach, which couldn't store crispness info in the file.
OK, how do I use this?
For now, this is Windows-only. I would need to build some tools for other platforms to get this to work on Linux or macOS.
If you have the JAR from the releases, unzip it so the other files it came with are all in the same folder
structure. Then, you can enter the directory with that holds fontwriter-1.0.4.jar
and run
java -jar fontwriter-1.0.4.jar "MyFont.ttf" msdf 60
, where "MyFont.ttf" can be any path to a .ttf file
or probably also an .otf file. "MyFont.ttf" doesn't have to be in the same folder if you give it an absolute
path (on Windows, you can drag and drop a file after typing java -jar fontwriter-1.0.4.jar
to enter its
absolute path). The second parameter, msdf
, can also be sdf
or standard
. You might just want standard
for many reasons; even though it won't scale up nicely, it will scale down fairly well, and you can
interchange standard
fonts using FontFamily or using colorful emoji. On the other hand is msdf
, which
scales up very well, but cannot be used with colorful emoji or other fonts to the same extent. Then sdf
is somewhere in the middle; it works somewhat well with emoji, though it doesn't handle their partially
transparent edge very well, scales up nicely, and unfortunately doesn't work well with other fonts. The
"60" parameter is a size, I think measured in pt or px. It isn't necessarily going to be used as-is. You
can optionally specify a size of image to write (the default is 2048x2048, and fonts that only use ASCII
probably don't need that much space) as the next parameter. After that you can optionally specify a color
by name (such as "black" or "red") or RGB hex code (such as "BB3311"; RGBA also works but alpha is
ignored), which will write an extra preview of all chars using that color. The last argument is there so
that you can quickly see all chars, even on a white background.
Running that command will try the size you give it first, and if it can't fit all chars in the font into
a 2048x2048 (or other size, if specified) image, it will reduce the size and try again, repeatedly. Once
it can fit everything, it saves the file into fonts/
, then starts doing some TextraTypist-related
processing. It paints a small "block" of solid white pixels into the lower right corner, then (if using
sdf
or standard
) optimizes the image so that it only uses the alpha channel with white pixels. That
last step helps texture filtering; without it, fully transparent pixels are fully-transparent black rather
than fully-transparent white, and mixing with black will darken sometimes even if the mixed color is
transparent (with white usually doesn't do this). It then optimizes the image in fonts/
with oxipng
,
and generates a preview image that it places in previews/
. If you specified a color name or hex code,
it also writes a preview of all chars in that color. It then optimizes the preview image(s), and then
you're done!
Windows Binaries? Gross!
They're both downloaded from the official project pages, and you can replace them if you want!
The msdf-atlas-gen binary uses this starting in fontwriter 1.0.4: version v1.3, and older versions of fontwriter depended on a self-built, slightly modified fork of msdf-atlas-gen. That self-built mess isn't needed now.
The oxipng binary used this in earlier releases: version v9.0.0 (which is a little old by now), or this: version v9.1.1 starting in fontwriter 1.0.3.
Oxipng works on many desktop platforms, but I can't compile msdf-atlas-gen for Linux, macOS, or ARM Windows currently.
License
This uses the Apache License v2.0.
The included msdf-atlas-gen uses the MIT License. The version used here is an identical binary to the one distributed at that repo (v1.3).
The included oxipng also uses the MIT License.