Fix IME text doubling and baseline jitter with glyph-level vertical offsets#601
Open
Cupnfish wants to merge 2 commits intolinebender:mainfrom
Open
Fix IME text doubling and baseline jitter with glyph-level vertical offsets#601Cupnfish wants to merge 2 commits intolinebender:mainfrom
Cupnfish wants to merge 2 commits intolinebender:mainfrom
Conversation
… vertical offsets
- Add `commit_compose` to atomically replace preedit with committed text,
fixing text doubling on Windows where `Ime::Commit` arrives before
`Ime::Preedit("")` clears the buffer.
- Add glyph-level vertical offset stabilization: after layout rebuild,
compute per-line baseline deltas and apply them directly to glyph
y-coordinates in `layout.data.glyphs`, preventing visual jitter when
font fallback changes line metrics (e.g., mixing CJK and Latin scripts).
- Reuse a `baseline_snapshots` scratch Vec to avoid per-update allocation.
- Extract `STABILIZATION_THRESHOLD` constant for the significance threshold.
- Gate stabilization on num_old_lines > 0 to skip empty layouts entirely - Track any_stabilized flag to avoid unnecessary generation nudges - Add performance notes in code comments explaining the O(lines) overhead is negligible compared to the O(text) layout build cost
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.
Summary
Fixes two issues with IME input and text layout stability:
1. IME text doubling on Windows (
commit_compose)On Windows (and possibly other platforms),
Ime::Commitarrives while the preedit text is still in the buffer, beforeIme::Preedit("")clears it. The existinginsert_or_replace_selectioninserts the committed text in addition to the preedit, causing a doubled-text flash. The newcommit_composemethod atomically replaces the preedit with the committed text.2. Baseline jitter from font fallback (glyph-level vertical offsets)
When mixing scripts on the same line (e.g., typing English after Chinese), font fallback changes line metrics between layout rebuilds, causing visible vertical jitter. This PR introduces glyph-level vertical offset stabilization:
Vec<f32>layout.data.glyphs(for array glyphs) and toline.metrics.baseline(for inline glyphs and cursor/selection consistency)baseline_snapshotsscratchVec<f32>is reused across updates to avoid per-update heap allocationPerformance
The stabilization adds minimal overhead:
For context, the layout build itself is O(text length) and involves expensive font shaping, BiDi processing, and line breaking. The stabilization overhead (O(lines) float operations) is negligible in comparison, even for documents with tens of thousands of lines.
The stabilization is also gated: it skips entirely when there are no previous lines to compare against (e.g., first layout or after buffer clear).
Comparison with PR #599
PR #599 (branch
fix/ime-windows-commit) solves the same two problems with a different stabilization strategy. Here is a detailed comparison:Shared parts
Both PRs include the identical
commit_composemethod for the IME text doubling fix.Difference: baseline stabilization approach
LineVerticalSnapshot(baseline, min_coord, max_coord, line_height)baselineper line (Vec<f32>)LineMetricsstruct, overriding line_height, leading, etc.yvalues + line positionglyph.yin layout dataVec<LineVerticalSnapshot>(~16 bytes/line)Vec<f32>(~4 bytes/line)Advantages of this approach
line_heightandleadingremain as computed by the layout engine, so the line box size reflects the actual content. PR Fix IME text doubling on Windows and baseline jitter during composition #599 restores old values, which can cause line boxes to be too small (or too large) when font fallback genuinely changes metrics.f32per line vs four fields per line. Less memory, fewer writes.y=0and can only be repositioned via baseline) are handled the same way as in PR Fix IME text doubling on Windows and baseline jitter during composition #599, so cursor and selection geometry remain correct.Trade-offs
line → line_items → runs → clusters → glyphs, which is more code than PR Fix IME text doubling on Windows and baseline jitter during composition #599's direct metric restoration.STABILIZATION_THRESHOLD = 0.01) is used to filter out insignificant changes.Notes
STABILIZATION_THRESHOLDconstant replaces repeated0.01literals, and a scratchVecavoids per-update allocation.