# 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:

- Page weight. Inlining every script as base64 into `pfodWeb.html` would permanently add hundreds of KB to the pfodWeb.html file that's loaded on every page load, for scripts most devices never display.
- On-demand local load. Each `@font-face` rule in `pfodweb-extra-fonts.css` declares a `unicode-range`. The browser only loads the locally hosted woff2 file the first time a character inside that range actually needs to be painted. A sketch that never sends Cyrillic text never triggers a load of the Cyrillic woff2 files at all.

## 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

Subset | Files | unicode-range covers
--- | --- | ---
Cyrillic | `Roboto-Normal-Cyrillic.woff2`, `Roboto-Italic-Cyrillic.woff2` | Russian and related Cyrillic-script languages
Cyrillic Extended | `Roboto-Normal-CyrillicExt.woff2`, `Roboto-Italic-CyrillicExt.woff2` | Additional Cyrillic letters used by some minority languages
Greek | `Roboto-Normal-Greek.woff2`, `Roboto-Italic-Greek.woff2` | Modern Greek
Greek Extended | `Roboto-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 `.woff2` → `font/woff2`, `.css` → `text/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.