pfodWeb — extraFonts Guide

Providing font files maintains uniformity of the menus across varying browsers and operating systems. The standard pfodWeb build embeds Roboto's Latin and Latin Extended fonts. Extra off-line locally loaded fonts can be added to the extraFonts directory without needing to recompile pfodWeb.

This document describes how to add other fonts without having to rebuild pfodWeb.html.

1. Why extraFonts/ exists

Having a consistent set of fonts give consistent displays of menus and drawings on different platforms, Android, iPhone, Windows, MacOS, linux. pfodWeb.html embeds (Android's) Roboto's Latin and Latin Extended subsets directly as base64 data:, because almost every pfodWeb screen needs them and they're always wanted as soon as the page loads. References to every other font needed (Cyrillic, Greek, etc.) are moved out into a separate, plain CSS file — extraFonts/pfodweb-extra-fonts.css — referenced via an ordinary <link rel="stylesheet href="extraFonts/pfodweb-extra-fonts.css"> tag rather than inlined.

This split matters for two reasons:

2. Adding a new script/font to pfodWeb

extraFonts/ sits next to pfodWeb.html and pfodProxy.exe in every build output (Windows, Linux, and the Contents/MacOS folder of the macOS .app) — not embedded inside pfodWeb.html

  1. Get a woff2 file covering the script. If Roboto itself has glyphs for it, download it from Google Fonts for that subset. If Roboto has no glyphs for the script (e.g. Thai), use a different actual font family (e.g. Noto Sans Thai) — that's fine, since step 3 still labels it font-family: 'Roboto' so pfodWeb's existing font stacks pick it up automatically.
  2. Drop the woff2 file(s) into pfodWeb's directory extraFonts/.
  3. Add an @font-face rule to pfodweb-extra-fonts.css following the existing pattern — same font-family: 'Roboto', correct unicode-range, and a normal + italic pair if both are available. The filename itself is just a local reference you choose; it doesn't need to follow the Roboto-<Style>-<Subset> convention used by the real Roboto subsets — name it after whatever font you actually sourced the woff2 from, since it's the font-family: 'Roboto' label (not the filename) that makes pfodWeb's font stacks pick it up:
    @font-face {
        font-family: 'Roboto';
        font-style: normal;
        font-weight: 100 900;
        font-display: swap;
        src: url('NotoSansThai-Normal.woff2') format('woff2');
        unicode-range: U+0E01-0E5B;
    }
  4. Clear the browser cache and restart pfodWeb / pfodProxy

3. Current subset coverage

Four extra scripts are currently included in the /extraFonts directory, each as a separate woff2 per style (normal/italic).
If you don't need these fonts you can just delete the /extraFonts directory

SubsetFilesunicode-range covers
CyrillicRoboto-Normal-Cyrillic.woff2, Roboto-Italic-Cyrillic.woff2 Russian and related Cyrillic-script languages
Cyrillic ExtendedRoboto-Normal-CyrillicExt.woff2, Roboto-Italic-CyrillicExt.woff2 Additional Cyrillic letters used by some minority languages
GreekRoboto-Normal-Greek.woff2, Roboto-Italic-Greek.woff2 Modern Greek
Greek ExtendedRoboto-Normal-GreekExt.woff2, Roboto-Italic-GreekExt.woff2 Polytonic Greek (accented historical text)

4. How it's wired up

pfodWeb.html attempts to load the locally hosted extraFonts/pfodweb-extra-fonts.css stylesheet.
The extraFonts/pfodweb-extra-fonts.css and fonts are entirely optional. If the .css or one of its woff2 files is missing, the local load attempt returns 404 not found, and the pfodWeb continues to work just fine — text in that script falls back to Arial / the OS system font instead of Roboto. Nothing in pfodWeb depends on this local directory being present.

Every rule inside that file uses font-family: 'Roboto' — the same family name used everywhere else in pfodWeb. Because each rule's unicode-range only covers its own script, the browser layers all of them (the two inlined Latin/LatinExt faces plus whichever extraFonts faces are present) into one logical "Roboto" that automatically picks the right face per character. No JS or font-stack changes are needed elsewhere in pfodWeb to support a new script — once a matching @font-face rule exists in extraFonts/pfodweb-extra-fonts.css, any text containing those characters just renders correctly.

Both font-weight: 100 900 (a variable-font weight range covering normal and bold in one file) and normal/italic styles are declared per subset, mirroring the four faces already inlined in pfodCommon.css.

5. Serving at runtime: micro self-hosted vs. file://

How extraFonts/pfodweb-extra-fonts.css and its .woff2 files actually get loaded depends on how pfodWeb.html itself was opened:

Micro self-hosted (pfodDevice's own HTTP server)

When a pfodDevice serves pfodWeb.html itself (e.g. ESP_PicoW_pfodWebServer), the browser's requests for extraFonts/pfodweb-extra-fonts.css and the individual .woff2 files it references go straight to that same device over ordinary http:// — ESP_PicoW_pfodWebServer serves them like any other static file it hosts, mapping .woff2font/woff2, .csstext/css, etc., or returning 404 if a file is missing. Nothing about this path changed.

Opened directly via file:// (the common case)

Browser security rules don't allow font files to be loaded directly from local disk this way, so when pfodWeb.html is opened as a file:// page, it instead asks pfodProxy (if running) to serve pfodweb-extra-fonts.css and its font files on its behalf. This is automatic — nothing to configure — and if pfodProxy isn't running, extra-script text just falls back to the system font, the same as if extraFonts/ were missing entirely.

pfodProxy validates every such request before serving anything (see pfodProxy's Security section for the full list) and only grants access to pfodWeb's extraFonts/pfodweb-extra-fonts.css and its valid font files. If pfodProxy has a password configured (see Setting a password), these requests are also password protect.

6. Refreshing an existing subset from Google Fonts

pfodWeb_src/fonts/fetch-roboto.js only fetches the two subsets inlined in pfodWeb.html (Latin, Latin Extended) by default — Cyrillic, Cyrillic Extended, Greek, and Greek Extended are commented out of its KEEP_SUBSETS list, since they no longer need to be embedded. To pull a fresh copy of one of the extraFonts subsets:

  1. Uncomment the relevant line(s) in KEEP_SUBSETS near the top of fetch-roboto.js.
  2. Run node pfodWeb_src/fonts/fetch-roboto.js. It writes the new woff2 file(s) into pfodWeb_src/fonts/ (not extraFonts/).
  3. Move the resulting file(s) into /extraFonts/ by hand, then re-comment the line(s) you uncommented in step 1.