Repository navigation
fix(macos): match GNU font weight by extracting masks with dark-on-light smoothing - #637
Conversation
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Polarity rasterization and coverage validation crates/neomacs-renderer-wgpu/src/glyph_atlas/macos.rs, crates/neomacs-renderer-wgpu/src/glyph_atlas/tests/macos_test.rs |
The rasterizer defaults to dark-on-light polarity. Bitmap initialization, glyph color, and luminance-to-coverage conversion depend on polarity. A test compares summed coverage at 16 and 32 pixels. |
Priority:
Estimated code review effort: 2 (Simple) | ~12 minutes
Change: Bug fix
Possibly related PRs
- eval-exec/neomacs#622: Adds the macOS Core Graphics native rasterizer that this change updates.
Suggested reviewers: eval-exec
Merge Risk: 
Minimal · up to e7b94
-
The mask polarity change has no identified merge-blocking issue.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Title check
-
Explanation
The title names the macOS glyph-mask change: extracting masks with dark-on-light smoothing to match GNU font weight. The raw summary and objectives confirm the change rasterizes dark glyphs on white, inverts luminance, and keeps font smoothing enabled. The title is specific and matches the main change. It uses the conventional fix(macos) prefix, and it is 82 characters, which is slightly long but readable.
Full details: Description check
-
Explanation
The description states the problem (
#622extracted white-on-black glyph coverage, which inflated weight through Core Graphics contrast-dependent gamma), the fix (dark-on-white rasterization with luminance inversion and smoothing kept enabled), measurements, test results, and caveats. It directly relates to the changeset, so it passes this lenient check.
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 3 functions across 2 files.
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
There was a problem hiding this comment.
Please don't add verification image into git track.
…rity PR eval-exec#622 enabled Core Graphics font smoothing for native outline masks but extracted coverage from white glyphs on black. Font smoothing's gamma is contrast-dependent, so that inflated coverage and made 1x text about 21% heavier than GNU Emacs, as reported after the merge. Draw dark glyphs on white and invert the coverage, matching GNU's ordinary on-screen contrast, and keep smoothing enabled. Measured on a 1x display with Monaco 16, ink over the same four ASCII lines is +21% before and -1.5% after, relative to GNU Emacs 31.1.50. Keep the inverse polarity as a test control and add a regression test that requires the production path to stay lighter.
a45bc5d to
e7b944e
Compare
eval-exec
left a comment
There was a problem hiding this comment.
Approved as a stopgap (e7b944e3bd).
The light-theme fix is verified end-to-end. I rebuilt GNU Emacs 31.1 from the pinned a360712c9d27 with --with-ns and captured the frame content view through a small Emacs module at the display's 2x scale (Monaco 16 pt, the same four lines, no chrome):
| GNU GUI at 2x | ink | PR mask at 32 px |
|---|---|---|
| light (black on white) | 4,420,610 | production dark-on-light: 4,420,610 |
| dark (white on black) | 4,806,838 | old light-on-dark: 4,806,838 |
The production polarity is therefore GNU-exact for the default light face, and the old mask is exactly GNU's dark rendering. The 1x −1.5% residual is a 1x/crop/context effect, not a mask-polarity error.
Approving as the interim fix: default light theme correct; dark-theme/light-foreground text is 8.7% lighter than GNU at 2x and ~20% at 1x (16 px masks), accepted as the known stopgap. The long-term direction is a polarity-independent coverage mask with renderer-owned stem darkening/gamma and gamma-correct compositing, which makes this whole polarity dimension obsolete; reproducing Core Graphics' per-color smoothing gamma is not the target architecture.
Follow-ups, not blockers:
- Correct the caveat: the dark-theme swing is 8.7% at 32 px and 22.6% at 16 px, not "a few percent"; GNU's dark rendering is exactly the old control mask.
- The new test is not run by CI — the macOS jobs run neovm-core/Doom, the display-stack job is Ubuntu. Adding
cargo nextest run -p neomacs-renderer-wgpu --lib macos_to the macOS job keeps the guard alive (~0.1 s after build). - The test only asserts strict ordering; a margin (e.g. ≥1.05 at 16 px, ≥1.02 at 32 px) or logged inks would be stronger.
MaskPolarity's "polarity-independent mask" wording is inverted: the mask is polarity-dependent, the atlas stores one shared mask.
Verification: macos_ 9/9; full neomacs-renderer-wgpu 897/900 with only environment/network failures (4 CJK tests reproduce with pre-PR files — missing Noto CJK, installed by the Linux display job; 3 color-font tests timed out downloading pinned fixtures from raw.githubusercontent.com; 3 aborted by the download); cargo fmt --all --check and git diff --check clean. The Neomacs wgpu surface could not be captured in this locked console session; the GNU-vs-mask equality and the PR's own 1x screen measurement cover that gap.
Follow-up to #622.
Problem
#622 moved macOS outline rasterization to Core Graphics and enabled font smoothing, but extracted glyph coverage from white glyphs on black. Core Graphics font smoothing applies a contrast-dependent gamma, so that inflates coverage on the way into the atlas. After the merge, @yibie measured Neomacs roughly 30% heavier than GNU Emacs on a 1x (non-Retina) display at Monaco 16.
Fix
Rasterize the mask the way GNU draws ordinary text: dark glyphs on white, then invert the luminance. Font smoothing stays enabled, matching GNU's window context default.
Measurements
Same four ASCII lines, Monaco 16, 1x 1920x1080, GNU Emacs 31.1.50. Ink is
Σ(255 - luminance)over the identical crop:An earlier attempt that simply disabled smoothing measured −14.9%: right idea, wrong weight.
Tests
cargo test -p neomacs-renderer-wgpu --lib macos_: 9 passed, 1 ignored (the manual visual probe), macOS 26 aarch64.macos_native_masks_use_dark_on_light_smoothingrenders the inverse polarity as a control and requires the production path to stay lighter.cargo fmt --checkandgit diff --checkpass; no new clippy warnings in the changed files.Caveats