feat(font): NewSyntheticBoldFont — faux bold for families with no bold instance - #169
Merged
Conversation
…d instance Some faces ship no bold weight the rasteriser can reach. The motivating case is a host UI typeface: macOS's SFNS is a variable font, and the pure-Go engine renders its default (Regular) master only, so an application matching the native look ends up with a Regular face and no bold at all — headings then draw at body weight, silently. NewSyntheticBoldFont over-strikes the run one pixel right, the same trick X11 and early PostScript printers used. It composes over ANY Font, including a fallback chain, so a script the primary lacks is emboldened too instead of staying light next to bold Latin. Measure includes the over-strike column, so the reported width covers every pixel Draw paints: without it two adjacent runs would overlap by a column, and a right-aligned or clipped string would lose its final stem. Advance and Height are the base face's — over-striking thickens glyphs, it does not re-space them. Ascent, FontData and SizePx forward when the base exposes them, so positioning and vector export keep working through the wrapper, and fall back to zero/nil when it does not. The doc is explicit that a designed bold is always better; this is for when the family offers none. 100% coverage; race-clean. Proved on pixels: the same string paints more coverage than the base face and reaches exactly one column further right. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Some faces ship no bold weight the rasteriser can reach. The motivating case is a host UI typeface: macOS's SFNS is a variable font and the pure-Go engine renders its default (Regular) master only, so an application matching the native look ends up with a Regular face and no bold at all — headings then draw at body weight, silently.
What
NewSyntheticBoldFontover-strikes the run one pixel right, the same trick X11 and early PostScript printers used. It composes over anyFont, including a fallback chain, so a script the primary lacks is emboldened too instead of staying light next to bold Latin.Measureincludes the over-strike column, so the reported width covers every pixelDrawpaints. Without it two adjacent runs would overlap by a column, and a right-aligned or clipped string would lose its final stem.AdvanceandHeightare the base face's — over-striking thickens glyphs, it does not re-space them.Ascent,FontDataandSizePxforward when the base exposes them, so positioning and vector export keep working through the wrapper, and fall back to zero/nil when it does not.The doc comment is explicit that a designed bold is always better; this is for when the family offers none.
Verification
go test -race→ 100.0% of statements, race-clean.🤖 Generated with Claude Code