Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Restore simple text runs, correct for crashes (#6695)
Restores the simple text run analysis and skipping of most of the shaping/layout steps. Corrects one of the fast-path steps to ensure that offsets and clusters are assigned. ## References - Bug #6488 - Bug #6664 - Simple run PR #6206 - Simple run revert PR #6665 - Recycle glyph runs PR #6483 The "correction" functions, by which box drawing analysis is one of them, is dependent on the steps coming before it properly assigning the four main vectors of the text layout glyphs: indices, advances, offsets, and clusters. When the fast path is identified by the code from #6206, only two of those are fully updated: indices and advances. The offsets doesn't tend to cause a problem because offsets are rarely used so they're pretty much always 0 already (but this PR enforces that they're zero for the simple/fast path.) The clusters, however, were not mapped for the fast path. This showed itself in one of two ways: 1. Before the recycled runs PR #6483, the cluster map had a 0 in every field for the stock initialized vector. 2. After the recycled runs PR #6483, the cluster map had the previous run's mapping in it. This meant that when we reached the steps where glyph runs were potentially split during the correction phase for box drawing characters, unexpected values were present to map the glyph indices to clusters and were corrected, adjusted, or split in an unexpected fashion. For instance, the index out of range bug could appear when the default 0 values appended to the end of the clusters vector were decremented down to a negative value during the run splitter as the true DWrite cluster mapper doesn't generate that sort of pattern in the slow path case without also breaking the run itself. The resolution here is therefore to ensure that all of the fields related to glyph layout are populated even in the fast path. This doesn't affect the slow path because that one always populated all fields by asking DWrite to do it. The fast path just skips a bunch of DWrite steps because it can implicitly identify patterns and save a bunch of time. I've also identified a few vectors that weren't cleared on reset/reuse of the layout. I'm clearing those now so the `.resize()` operations performed on them to get to the correct lengths will fill them with fresh and empty values instead of hanging on to ones that may have been from the previous. This should be OK memory perf wise because the act of `.clear()` on a vector shouldn't free anything, just mark it invalid. And doing `.resize()` from an empty one should just default construct them into already allocated space (which ought to be super quick). ## Validation * [x] Far.exe doesn't crash and looks fine * [x] "\e[30;47m\u{2500} What \u{2500}\e[m" from #6488 appears appropriately antialiased * [x] Validate the "\e[30;47m\u{2500} What \u{2500}\e[m" still works when `FillGeometry` is nerfed as a quick test that the runs are split correctly. * [x] Put `u{fffd} into Powershell Core to make a replacement char in the output. Then press enter a few times and see that shrunken initial characters on random rows. Verify this is gone. Closes #6668 Closes #6669 Co-Authored-By: Chester Liu <[email protected]>
- Loading branch information