ksTFL renders DOCX documents using a C++ engine that requires TrueType/OpenType font files for text measurement and pagination. Starting with version 0.7.0, the package automatically discovers fonts installed on the operating system at load time. If a required font is not available on the system, a metrically compatible open-source fallback is used.
This guide explains how font discovery works, which fallback fonts are bundled, and how to configure custom font directories.
When ksTFL is loaded, it performs four steps:
Scan system directories. The C++ font scanner
inspects platform-specific directories and reads family names and style
flags from .ttf, .otf, and .ttc
files.
Scan user directories. If the R option
ksTFL.font_dirs is set, those directories are scanned as
well.
Scan bundled fallbacks. The package’s own
inst/fonts/ directory is scanned last.
Resolve target fonts. For each target family (Arial, Times New Roman, Courier New, Georgia, Verdana, Trebuchet MS), ksTFL keeps the discovered font when available or assigns a designated fallback.
Key rule: system-installed fonts always take priority. The bundled fallbacks are only used when a target font is not found anywhere on the system.
The scanner inspects the following directories by default:
| Platform | Directories |
|---|---|
| Linux | /usr/share/fonts, /usr/local/share/fonts,
~/.local/share/fonts, ~/.fonts, plus any XDG
data dirs |
| macOS | /System/Library/Fonts, /Library/Fonts,
~/Library/Fonts |
| Windows | System fonts directory (from registry), plus user fonts in
%LOCALAPPDATA%\Microsoft\Windows\Fonts |
The rendering engine targets six font families commonly used in clinical documents. Each has a metrically compatible open-source fallback bundled with the package:
| Target Font | Fallback Font | Notes |
|---|---|---|
| Arial | Liberation Sans | Metrically identical to Arial |
| Times New Roman | Liberation Serif | Metrically identical to Times New Roman |
| Courier New | Liberation Mono | Metrically identical to Courier New |
| Georgia | Liberation Serif | Serif fallback for Georgia |
| Verdana | Liberation Sans | Sans-serif fallback for Verdana |
| Trebuchet MS | Liberation Sans | Sans-serif fallback for Trebuchet MS |
All bundled fonts are licensed under the SIL Open Font License 1.1.
If a font family requested in a spec (via
s_font(font_name = "...")) is not a target font and is not
found on the system, the engine falls back to Liberation Sans as the
last resort.
For convenience, ksTFL also ships built-in style atoms for the target
font families: font_arial, font_courier_new,
font_times_new_roman, font_georgia,
font_verdana, and font_trebuchet_ms. These
atoms set only font_name, so they can be safely combined
with size, colour, alignment, and other style atoms via
f_combine().
After loading the package, call tfl_font_status() to see
the current font resolution:
library(ksTFL)
tfl_font_status()
#> ksTFL font scan: 3 target(s) resolved, 3 using fallback
#> [ok] Arial -> Arial
#> [ok] Times New Roman -> Times New Roman
#> [ok] Courier New -> Courier New
#> [fallback] Georgia -> Liberation Serif
#> [fallback] Verdana -> Liberation Sans
#> [fallback] Trebuchet MS -> Liberation Sans
#> Scanned 5 directoriesReading the output:
[ok] — The target font was found on
the system and will be used directly.[fallback] — The target font was not
found; the bundled fallback is used instead.If proprietary fonts are installed in a non-standard location (e.g.,
a network share or a project-local folder), point the
ksTFL.font_dirs option to those directories
before loading the package, or rescan afterwards:
Call tfl_rescan_fonts() after:
ksTFL.font_dirs option# Install Georgia to /usr/local/share/fonts/georgia/ ... then:
tfl_rescan_fonts()
#> ksTFL font scan: 6 target(s) resolved, 0 using fallback
#> [ok] Arial -> Arial
#> [ok] Times New Roman -> Times New Roman
#> [ok] Courier New -> Courier New
#> [ok] Georgia -> Georgia
#> [ok] Verdana -> Verdana
#> [ok] Trebuchet MS -> Trebuchet MS
#> Scanned 5 directoriesWhen the package is attached, it prints a concise summary if any target fonts are using fallbacks:
ksTFL v0.7.0 - Clinical TFL Framework
For help, type: ??ksTFL
Note: 3 font(s) using fallback: Georgia, Verdana, Trebuchet MS
Run tfl_font_status() for details.
If all target fonts are found on the system, no font-related message is shown.
write_doc()The write_doc() function (and
replay_report()) automatically uses the font directories
from the scanner cache. You can still pass additional per-call
directories via the font_dirs argument:
write_doc(report, name = "output",
outDir = "results",
metaPath = tempdir(),
font_dirs = "/path/to/extra-fonts")Per-call directories are appended to the scanner’s cached list for that render only — they do not modify the global font registry.
[fallback] for a font I know is installed.
What’s wrong?The font may be installed in a directory not scanned by default. Add
its directory to ksTFL.font_dirs and rescan:
Yes. Any font found during scanning is available to the renderer. Use
the family name as it appears in the font’s metadata (e.g.,
s_font(font_name = "Fira Sans")). If the font is in a
non-standard directory, add that directory to
ksTFL.font_dirs.
The fallback fonts (Liberation family) are designed to be metrically compatible with their proprietary counterparts. Line breaks, page breaks, and column widths should be identical or very close. Minor glyph-level differences may exist, but document layout is preserved.