Files
photocraft/docs/font-resolution.md
ce6fccc3f5 fix(type): missing-font checks follow layout's PostScript resolution; split hyphenless style suffixes (#608)
* fix(text): split hyphenless PostScript style suffixes

A PostScript name without a hyphen kept its style in the guessed family:
`GmarketSansBold` became the family "Gmarket Sans Bold" at weight 400.
The guess now drops a trailing capitalised style word (Gmarket Sans, 700).
A lowercase ending ("Daylight") is not a style, and a style word after the
vendor tag MT stays in the legacy family ("Arial Rounded MT Bold").
Hyphenated names keep the last-hyphen parsing from #3878.

PSD import stores this guess when the exact face is absent. A legacy family
that ends in a style word without MT before it ("CooperBlack") is stored as
the shorter family (Cooper, 900) until the face is installed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(type): missing-font checks follow layout's PostScript resolution

When a run's stored family is not installed, layout draws it with its exact
PostScript face, or with the family guessed from that name if installed.
Missing-font detection compared only the stored family label, so such a run
was reported missing, and Replace Missing Fonts rewrote it whenever an
unresolved run shared the label. missing_fonts, missing_fonts_in_layer and
the replacement now use layout's decision.

#1406 already corrects the label when a PSD or Affinity file is opened with
the face installed, and #1844 finds exact faces outside the family prefix.
The label still stays on a run reopened from .pcraft after its font was
installed, on fonts that arrive after opening, and on a run created with
both "font" and "postscriptName". The tests take the .pcraft and command
paths.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: kijoong <gijoong.gim@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:48:09 -04:00

43 lines
2.1 KiB
Markdown

# PostScript font resolution
PSD text may identify a face by its PostScript name as well as a family/style.
The PostScript prefix need not match the family name, and the family stored with
a run can be a guess made from that name.
## Resolution
`FontDb::resolve_postscript` first looks for an installed face with that exact
PostScript name (families that share the guessed prefix are read first), then
falls back to a heuristic split of the name. The heuristic splits at the last
hyphen. A name without a hyphen loses a trailing capitalised style word
(`GmarketSansBold` → Gmarket Sans, 700; `ExampleSansSemiBoldItalic` → Example
Sans, 600, italic). A lowercase ending is not a style (`Daylight`), and a style
word after the vendor tag `MT` stays in the family (`ArialRoundedMTBold` →
Arial Rounded MT Bold).
The heuristic also gives the family, weight and slant stored on PSD import when
the exact face is absent. A legacy family whose name ends in a style word and
has no `MT` tag before it (`CooperBlack`) is then stored as the shorter family
(Cooper, 900) until the face is installed.
## Missing fonts
Opening a PSD or Affinity file already replaces a run's guessed family with the
installed family its PostScript name resolves to. A guess still stays on a run
when the face was absent at import and the document is reopened from `.pcraft`
after the font is installed, when fonts are registered after opening, or when a
command sets `font` and `postscriptName` together.
Missing-font detection (`missing_fonts` and `missing_fonts_in_layer`) and Replace
Missing Fonts therefore use the same decision as layout: a run is missing only
when neither its stored family, its exact PostScript face nor the heuristic
family is installed. A run that resolves is not replaced because an unresolved
run shares its family label.
## Cost
Detection resolves the PostScript name only for runs whose stored family is not
installed. The first such lookup reads the name tables of installed faces; the
result is cached until fonts are registered or system fonts are loaded, and
layout performs the same lookup for those runs.