What happens
DocumentTextStyle.builder().fontName(FontName.HELVETICA_BOLD).size(13).build()
renders regular Helvetica. Not approximately — the glyph program is the regular one, and the text is measured with regular metrics. The same holds for all nine standard-14 style variants (TIMES_BOLD, COURIER_OBLIQUE, HELVETICA_BOLD_OBLIQUE, …). No warning is logged; the style silently does nothing for weight or slant.
Why
Two pieces that are each individually reasonable:
So the design is name selects the family, decoration selects the face, and .fontName(HELVETICA_BOLD) expresses the family twice and the face never. The working form is:
DocumentTextStyle.builder()
.fontName(FontName.HELVETICA)
.decoration(DocumentTextDecoration.BOLD)
.size(13)
.build()
Measured difference on a real deck heading — GraphCompose Engine at 13pt is 135.84 pt as rendered today and 144.47 pt as the author intended, 6.4% narrower than the bold it asks for.
Where it bites today
ChartDefaults:101, HeadingBarStyle:21, TimelineBuilder:69, TimelineMarker:74 and ModernProfessional:134 all use the non-working form, plus 111 call sites across examples/. Every chart axis label, heading bar, timeline marker and those preset headings are currently regular weight in shipped output.
This is also what #450 traced: the PPTX backend used to read the weight off the name string, so it asked the viewer for a bold face the layout had never measured and the text overran its frame. That is fixed by matching the engine's rule, which means PPTX now renders regular too — correct parity, and the same missing bold.
Options
- Make the alias a real fallback. Look the requested variant up first and only fall back to the base family when nothing is registered. The standard-14 families already declare all four faces (
DefaultFonts passes "HELVETICA_BOLD" etc. to FontFamilyDefinition.standard14), so the bold program is available — it is only unreachable.
- Reject the form. Log once per style, or fail fast, when a style names a variant that resolves to a different face than it asks for, so the silent no-op becomes visible.
- Leave the behaviour, document it. Cheapest, and the weakest — the API reads as if it works.
Option 1 is the one that matches what callers already write, but it changes rendered output wherever the form is used: text gets wider, lines re-wrap, and every layout snapshot and pixel baseline covering those sites moves. That is why it was kept out of the 2.1.0 release week rather than folded into #450.
Also update
docs/architecture/backend-capability-matrix.md if the resolution rule changes, and the font documentation, which does not currently state that the face comes from the decoration.
What happens
renders regular Helvetica. Not approximately — the glyph program is the regular one, and the text is measured with regular metrics. The same holds for all nine standard-14 style variants (
TIMES_BOLD,COURIER_OBLIQUE,HELVETICA_BOLD_OBLIQUE, …). No warning is logged; the style silently does nothing for weight or slant.Why
Two pieces that are each individually reasonable:
FontLibrary.resolveBaseFontmaps every standard-14 style variant onto its regular base throughFONT_ALIASES— before any lookup, so it is a rewrite rather than a fallback.Font.fontType(TextDecoration)then picks the real face from the span's decoration.So the design is name selects the family, decoration selects the face, and
.fontName(HELVETICA_BOLD)expresses the family twice and the face never. The working form is:Measured difference on a real deck heading —
GraphCompose Engineat 13pt is 135.84 pt as rendered today and 144.47 pt as the author intended, 6.4% narrower than the bold it asks for.Where it bites today
ChartDefaults:101,HeadingBarStyle:21,TimelineBuilder:69,TimelineMarker:74andModernProfessional:134all use the non-working form, plus 111 call sites acrossexamples/. Every chart axis label, heading bar, timeline marker and those preset headings are currently regular weight in shipped output.This is also what #450 traced: the PPTX backend used to read the weight off the name string, so it asked the viewer for a bold face the layout had never measured and the text overran its frame. That is fixed by matching the engine's rule, which means PPTX now renders regular too — correct parity, and the same missing bold.
Options
DefaultFontspasses"HELVETICA_BOLD"etc. toFontFamilyDefinition.standard14), so the bold program is available — it is only unreachable.Option 1 is the one that matches what callers already write, but it changes rendered output wherever the form is used: text gets wider, lines re-wrap, and every layout snapshot and pixel baseline covering those sites moves. That is why it was kept out of the 2.1.0 release week rather than folded into #450.
Also update
docs/architecture/backend-capability-matrix.mdif the resolution rule changes, and the font documentation, which does not currently state that the face comes from the decoration.