G2: font menus list the installed fonts

A Windows user reported that the Properties panel's font menu offered only the bundled Inter,
JetBrains Mono and Noto Serif. The system font folders were scanned only when a project asked for
a family the bundled fonts lack, so until then every font menu (Properties, Character, Essential
Graphics) and `file.findMissing {what: fonts}` saw the bundled families alone, on every
platform. Listing the families now scans the system fonts first, and the desktop app starts that
scan on a background thread at launch so the menus are complete when first opened.

The style menus in the Properties and Character panels list the chosen family's own styles
instead of a fixed Regular / Medium / SemiBold / Bold / Italic. Both menus build their lists only
while open.

New query for agents: `text.fonts {query?, rescan?}` (MCP tool `list_fonts`) lists every family
with its styles, origin (bundled / system / user) and own-language name; `rescan` picks up fonts
installed since launch.

Tests: a fresh-process test that the family list includes every family in the platform's font
folders without a prior scan (failed before), and `text.fonts` filtering, rescan and per-family
styles, and the `list_fonts` MCP tool.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EjTYdt76hTG4Kh2CJFnCr
This commit is contained in:
Claude
2026-10-06 15:14:55 +00:00
parent e6c817bb3f
commit dda9961889
11 changed files with 189 additions and 16 deletions
+7
View File
@@ -58,6 +58,7 @@ The server speaks JSON-RPC 2.0 over stdio, one message per line, and supports MC
| `set_property {layer, path, value?, time?, expression?, comp?}` | Sets a static value. With `time` it sets a keyframe; with `expression` it sets an expression. |
| `add_keyframe {layer, path, time+value \| keys:[...], interpolation?}` | Adds keys, then optionally applies linear/bezier/hold/easyEase. |
| `list_effects {filter?}` | Effect ids, names, categories, GPU / 32-bpc support and parameters. |
| `list_fonts {query?, rescan?}` | Font families text layers can use, bundled and installed, with their styles, origin and own-language name; `rescan` picks up fonts installed since launch. |
| `add_effect {layer, effect, values?, comp?}` | Apply an effect and set its parameters in one call; returns the instance path (`effects/#n`) and its parameter paths. |
| `render_frame {comp?, time?, max_side?, path?, inline?, transparent?}` | Returns a PNG image of a frame; `transparent: true` keeps the alpha (as an RGB + Alpha render writes it) instead of compositing over the comp background. |
| `open_project {path \| demo \| new}` / `save_project {path?}` | Open and save files. |
@@ -350,6 +351,12 @@ whole layer, or only characters `range: [start, end]` (character indices): chara
4. `edit.copy`, `edit.paste`, `edit.pasteTextMatchFormatting` and `edit.pasteTextFormattingOnly`
work on the selected text; `text.endEdit` commits (an empty Type-tool layer is removed).
Fonts: `text.fonts` (MCP `list_fonts`) lists every family a text layer can use, bundled and installed, with its
styles, origin (`bundled`, `system`, `user`) and own-language name (`{"query":"gothic"}` filters
by name; `{"rescan":true}` first picks up fonts installed since launch). Pass a listed `family` and
one of its `styles` to `layer.setText {"font", "style"}`; `text.fontFeatures` says which OpenType
options a font draws with its own glyphs.
In expressions, `text.sourceText.style` / `getStyleAt(i, t)` read styles and the setters
(`setFontSize(v, start?, count?)`, `setFillColor`, `setText`, `setJustification`…) return a
styled document.