Repository navigation
feat: font_thicken ("auto", true or false) and font_thicken_strength draw terminal text alike for every text color - #547
Conversation
…ike for every text color
…text Issue herdrdev#414 asked for a way to turn smoothing fully off, as Ghostty's `font-thicken = false` (its default) does. Strength 30 only reaches CoreGraphics' lightest smoothing level, which still dilates glyphs; with smoothing off they draw as plain antialiased coverage, lighter still and the same for every text color. `font_thicken` takes `"auto"` (absent, the default: GPUI's color-based smoothing), `true` (thicken at `font_thicken_strength`) or `false` (smoothing off). The default stays out of settings.json and `true`/`false` round-trip as JSON booleans, so existing files keep their meaning. Any other string is kept and named in `problems()`, and draws as `"auto"`. GPUI carries the three states as `GlyphThicken` (`Auto`, `Strength(u8)`, `Off`) in `RenderGlyphParams::thicken`, so it stays in the glyph atlas key and differently smoothed glyphs never share a tile. The macOS rasteriser draws `Off` with `setShouldSmoothFonts(false)`, as Ghostty's coretext.zig does, without the extra pixel of raster room thickening needs. Other backends take the field and ignore it. tests/thicken_ink.rs gains the off rows: JetBrains Mono 12 device px inks 0.0511 in both polarities, against 0.0588 for the lightest smoothing and 0.0711 for light text on dark under `"auto"`.
…at false means smoothing off
|
TL;DR: fixed the Linux CI failure and merged
|
|
+1 for Measured from a side-by-side with the same font (JetBrains Mono Nerd Font Mono) and colors on a 2x display: the "T" stroke is 0.155 of the cap height in Herdr and 0.122 in Ghostty. That matches CoreText rendering with smoothing on (0.143–0.150) and off (0.122). Workaround until this lands: |
|
Thanks @Tom-Caz, those measurements line up with mine: On panel text: this PR covers terminal text only. My fork has a second pair of settings for everything else in the window (panels, tabs, overlays, toasts, mods and the Settings window):
@ogulcancelik would you take Until then, the |
…-setting # Conflicts: # src/settings.rs # src/terminal.rs
…-setting # Conflicts: # THIRD-PARTY-NOTICES
|
@ogulcancelik any chance this could be merged? would be great to have thickness configurable. |
TL;DR:
font_thicken("auto",trueorfalse) andfont_thicken_strength(settings.json) control how macOS font smoothing draws terminal text.truethickens it the same for every text color, as Ghostty'sfont-thickendoes;falseturns smoothing off, as Ghostty'sfont-thicken = false;"auto", the default, keeps today's behaviour. Closes #414: dark-on-light text can be drawn as heavy as light-on-dark, and, for the dark-theme case in the #414 comments, light-on-dark can be drawn as light as dark-on-light, or lighter still with smoothing off.Why
glyph_dilation_for_color): dark text on a light background gets the lightest level, light text on dark the heaviest. The same terminal text inks ~21% heavier on a dark theme than on a light one.font-thicken-strength / 255in linear gray, then tints it, so both polarities ink alike. Withfont-thicken = false(its default) it doesn't smooth at all.What changes
GlyphThicken(Auto,Strength(u8),Off) inRenderGlyphParams::thicken, which is in the glyph atlas key, so differently smoothed glyphs never share a tile; andWindow::with_glyph_thicken(thicken, f). On macOS the rasteriser drawsStrengthas Ghostty does, with one more pixel of raster room, as Ghostty pads thickened glyphs, andOffwithsetShouldSmoothFonts(false), as Ghostty's coretext.zig does. Other platforms take the field and ignore it. Everything outsidewith_glyph_thickenkeeps GPUI's color-based smoothing.with_glyph_thicken; the row cache key carries the setting, so a change redraws kept rows.font_thicken: absent or"auto"(the default) leaves smoothing to GPUI,truethickens atfont_thicken_strength,falseturns smoothing off. The default stays out of settings.json andtrue/falseround-trip as JSON booleans. Any other string is reported byproblems()and draws as"auto".font_thicken_strength(0..255, default 255, Ghostty's default), validated inproblems(). Both keys are documented indefaults/AGENTS.md. Panels keep the system's smoothing.THIRD-PARTY-NOTICESregenerated withjust notices(the Cargo.toml hash, plus the 0.1.13 version it was behind on).Numbers
tests/thicken_ink.rson this branch (upstream/mastere77f112 plus this change): real CoreText and GPU readback, headless Metal, JetBrains Mono 400 at 12 device px. Ink is the mean of (pixel − background) / (text − background) over the text's box, so polarities compare directly."auto"(today, the default)true, strength 30true, strength 255false(smoothing off)trueat either strength andfalse, both polarities within 1%; 255 thicker than 30;falselighter than auto's dark on light.Not in this pull request
font_ligatureseither) and the same choice for panel text (ui_font_thicken), which my fork carries.Tests
settings::tests::font_thicken_defaults_auto_at_ghosttys_strength_and_validates_it,settings::tests::font_thicken_is_auto_true_or_false_and_names_anything_else,tests/thicken_ink.rs(new[[test]], macOS only), andthe_guide_explains_every_settingcovering both keys.just checkpasses.