Repository navigation
Tab stops - #934
Tab stops#934WilliamDGH wants to merge 34 commits into
Conversation
parley_engine: check that marks and joiners after a tab leave it glyphless
|
Blitz WPT results are looking generally good (+69 -20). See DioxusLabs/blitz#1313. Benchmark results are not so great (roughly +20% on line-breaking, and content widths, and +10% glyph iteration). I suspect we can do better than this.
|
|
I haven't fully reviewed the changes yet, but DioxusLabs#96 has this down to closer to 2%. @WilliamDGH feel free to incorporate any of those changes into your branch as you see fit. And also as a general point, I didn't have to do much more than point my agent at the PR and tell it to fix the regressions to get these results. Would recommend! |
Thanks @nicoburns , I will take a look of that PR and try to fix the benchmark results. |
|
Added 3 commits that recover the regressions on text without tabs, based on DioxusLabs/parley#96 (thanks @nicoburns). Ran Tango benchmark on my Mac and this is the results:
Full Tango output, this branch vs merge-base (102 rows, -t 2)Full Tango output, this branch before the performance fix vs merge-base (102 rows, -t 2) |
Implement tab stops, which fixes issue 302.
LLM Contributions:
Font::TabWidth.What is it
Preserved tabs (U+0009) now advance to the next tab stop, following CSS
tab-size. A tab shapes to no glyphs and a zero advance like a newline. The line breaker computes its advance when it reaches it and stores it per line, andEffectiveSpacingadds it back on read, like justification.parley_engine
parley
StyleProperty::TabSize(TabSize).TabSize { size, skip_threshold }holds two lengths in layout units, scaled like other lengths and passed fromTextStylethrough the resolved styles tolayout::Style.sizedefaults to0.0, so tabs take no space until a size is set. A tab whose next stop is closer thanskip_thresholdskips to the one after it (one stop at most); when unset, the threshold is half the root style's font size, resolved once from the style table's root entry.layout::tab::tab_advanceto compute the distance to the next tab stop.LayoutData::tab_advances(eachLineDataowns a range, likealigned_subtree_offsets). Tabs with no advance get no entry. Backtracking to an earlier break,revert_toand a new layout all truncate the table.EffectiveSpacing, which adds a tab's recorded advance as itsaftergap on read, like justification (a binary search over the line's entries). Hanging whitespace, run and cluster advances, glyph positioning and hit testing all go through it.Spacing::gapsto give tabs no letter or word spacing of their own, as CSS puts that spacing into the tab size's unit rather than around the tab.GlyphRunIterto end a glyph run at a glyphless advance and shift the next run by it, and to count spacing gaps for glyphless atoms like the breaker does.ContentWidthsMeasurerto size tabs from each constraint's running width, tracking hanging whitespace per constraint, so it keeps matching the breaker.parley/src/tests/test_layout.rsintests/mod.rs.Changelog