Metadata-Version: 2.5
Name: localtools-font-subsetter
Version: 1.0.1
Summary: Subset fonts to the characters you use, instance variable fonts, and convert to WOFF2 (localtools, offline, fontTools)
Project-URL: Source, https://github.com/chayprabs/localtools
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: brotli>=1.1
Requires-Dist: fonttools>=4.60
Requires-Dist: multipart>=1.2
Description-Content-Type: text/markdown

# localtools-font-subsetter

Make web fonts small, on your machine: subset TTF/OTF/WOFF/WOFF2 fonts to the characters you actually use (Unicode
presets, your own text, or Unicode ranges), keep or drop OpenType features, drop hinting, pin or limit variable-font axes
(e.g. `wght` 400 to 700), and write WOFF2, WOFF or TTF/OTF. Each result shows before/after size and glyph count, a coverage
report (which requested characters the font does not have), font metadata (family, style, axes, license, fsType embedding
bits, with a warning when they forbid embedding or subsetting), a live preview rendered with the subset font, and a
ready-to-paste `@font-face` rule with the exact `unicode-range`. Nothing leaves your computer.

## Install

| OS | command |
|---|---|
| Windows (PowerShell) | `irm https://raw.githubusercontent.com/chayprabs/localtools/main/font-subsetter/install.ps1 \| iex` |
| macOS / Linux | `curl -fsSL https://raw.githubusercontent.com/chayprabs/localtools/main/font-subsetter/install.sh \| bash` |
| PyPI (Python 3.10+) | `pipx install localtools-font-subsetter` |

The installer unpacks a portable build with its own Python 3.13 (17 MB zip on Windows, 24 to 39 MB on macOS/Linux).

## Use

**UI:** run `localtools-font-subsetter` (or the Start menu / Applications launcher). It opens `http://127.0.0.1:47129`.
Drop one or more fonts, tick presets (Latin, Latin Ext, Cyrillic, Cyrillic Ext, Greek, Greek Ext, Vietnamese, or Keep all)
and/or type sample text, optionally Unicode ranges, layout features and axes, pick a format, press Subset. The preview line
is editable. Copy CSS and Download sit on each result.

- Presets use the same ranges Google Fonts serves, so `unicode-range` splitting works the way the web expects.
- Layout features: `default` (fontTools' set: kern, liga, calt, mark, mkmk, locl, ...), `all`, `none`, an exact list
  (`kern,liga`) or edits to the default (`+ss01,+tnum,-liga`).
- Axes use fontTools instancer syntax: `wght=400` pins, `wght=400:700` limits, `wght=300:400:700` limits and moves the
  default, `opsz=drop` pins to the default. Pin every axis to get a static font.
- Hinting is dropped by default (smaller files; browsers on modern systems barely use it). Tick Keep hinting to keep it.

**CLI:**

```sh
localtools-font-subsetter subset Inter.ttf --preset latin --text "Ωμέγα" --format woff2 -o out/
localtools-font-subsetter subset RobotoFlex.ttf --preset latin,latin-ext --axes "wght=400:700 opsz=drop" -o out/ --css > fonts.css
localtools-font-subsetter subset *.otf --text-file page.html --features +tnum --format woff -o out/ --json
```

Output files are `<name>-subset.<ext>`. Missing characters and license warnings go to stderr; `--css` prints the
`@font-face` rules, `--json` the full report.

**API:** `POST /api/subset`, multipart: `file` (repeat for several fonts), `preset` (comma list), `text`, `unicodes`,
`features`, `hinting` (`1`), `axes`, `format` (`woff2 woff ttf otf`). One font returns the font file, several return a zip
with `fonts.css`. `POST /api/report` takes the same fields and returns JSON (sizes, glyphs, axes, metadata, coverage,
warnings, CSS, base64 font). Errors: `400 {"error": "..."}`.

```sh
curl -F file=@Inter.ttf -F preset=latin -F text=Hello -F format=woff2 -o Inter-subset.woff2 http://127.0.0.1:47129/api/subset
```

## Engine

[fontTools](https://github.com/fonttools/fonttools) (MIT): `fontTools.subset` is pyftsubset, and `fontTools.varLib.instancer`
is the reference variable-font instancer; Google Fonts and most font foundries build with them. WOFF2 uses Google's
[brotli](https://github.com/google/brotli) (MIT). The font is subset first and instanced second: that is faster, and it
avoids a fontTools failure when subsetting an already partially-instanced font in memory. The full name table (copyright,
license, instance names) is kept.

## Not included

- Font collections (`.ttc`/`.otc`): refused with a clear error; extract a single font first.
- EOT and SVG fonts: obsolete web formats.
- Instancing large variable fonts is slow (a 2 MB, 4,500-glyph font takes about 20 s). Subsetting first helps a lot.

## Update / uninstall

`localtools-font-subsetter update` / `localtools-font-subsetter uninstall` (installer builds). For PyPI installs:
`pipx upgrade localtools-font-subsetter` / `pipx uninstall localtools-font-subsetter`.

## License

MIT. Test fonts in `samples/` are subsets of Inter, Roboto Flex and Noto Sans (SIL OFL 1.1, see `samples/licenses/`).
