Expose BaseDirection through paragraph analysis - #708
Conversation
|
Assisted by GPT 5.6 Sol high. I reviewed it. |
|
This came about during development of Overstory and is needed there. |
nicoburns
left a comment
There was a problem hiding this comment.
This makes sense to me. I believe I will eventually need a span-level override for web compat (at which point it probably makes sense to make it a style). But I imagine that's a lot more involved to implement.
|
There's plenty of future work to do on bidi for sure. But this is fixing something really basic / simple / trivial. |
| /// Whether the paragraph's resolved base direction is right-to-left. | ||
| #[inline(always)] | ||
| pub fn is_rtl(&self) -> bool { | ||
| !self.paragraph_level.is_multiple_of(2) | ||
| } |
There was a problem hiding this comment.
I'd normally suggest dropping this method, as it's derivable from Analysis::paragraph_level (and having both methods introduces some mental overhead of whether the two methods are the same).
But, users having to is_multiple_of(2) really isn't so nice, so I'll open a follow-up proposal instead.
There was a problem hiding this comment.
There's more issues there than that ... paragraph level has at least 2 names in the code. :)
Parley previously always inferred the paragraph embedding level from the text, even when a caller knew the surrounding reading direction. This is especially wrong for numeric or neutral text and for mixed-direction text whose first strong character does not represent the paragraph direction. Unicode UAX linebender#9 rule HL1 explicitly permits a higher-level protocol to set the paragraph embedding level instead of applying the P2/P3 first-strong heuristic. This is also the model exposed by HTML `dir="ltr"`, `dir="rtl"`, and `dir="auto"`, and by CSS `direction`. Supplying a base direction is not a bidi override: Latin and numeric runs remain LTR inside an RTL paragraph, while neutral resolution, visual ordering, alignment, and editing use the requested paragraph level. Add `BaseDirection` to `AnalysisOptions`, default it to `Auto`, and use it in `BidiResolver`. Explicit RTL analysis now bypasses the all-LTR content fast path so neutral and numeric text receives complete bidi levels, and empty text retains its requested base direction. Re-export the shared `parlance::BaseDirection`, add `Analysis::is_rtl`, and expose `set_base_direction` on all three Parley builders. A private shared builder-options value keeps the new paragraph option and the existing build settings on one path. This updates the unreleased low-level API: replace `None`, `Some(0)`, and `Some(1)` passed to `BidiResolver::resolve` with `BaseDirection::Auto`, `BaseDirection::Ltr`, and `BaseDirection::Rtl`. Existing `AnalysisOptions` literals can add `base_direction` or use `..AnalysisOptions::default()`. Paired Tango benchmarks against `main` found no consistent layout regression. The first 8-second full comparison put all 18 layout cases between -1.33% and +0.79%; a repeat ranged from -0.39% to +1.79% without a consistent pattern. A focused 20-second comparison measured the shortest default Latin case at +0.00% and the styled Latin case at -1.05%. Spec references: - https://www.unicode.org/reports/tr9/#HL1 - https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute - https://www.w3.org/TR/css-writing-modes-3/#text-direction
d280506 to
2663edf
Compare
Parley previously always inferred the paragraph embedding level from the text, even when a caller knew the surrounding reading direction. This is especially wrong for numeric or neutral text and for mixed-direction text whose first strong character does not represent the paragraph direction.
Unicode UAX #9 rule HL1 explicitly permits a higher-level protocol to set the paragraph embedding level instead of applying the P2/P3 first-strong heuristic. This is also the model exposed by HTML
dir="ltr",dir="rtl", anddir="auto", and by CSSdirection. Supplying a base direction is not a bidi override: Latin and numeric runs remain LTR inside an RTL paragraph, while neutral resolution, visual ordering, alignment, and editing use the requested paragraph level.Add
BaseDirectiontoAnalysisOptions, default it toAuto, and use it inBidiResolver. Explicit RTL analysis now bypasses the all-LTR content fast path so neutral and numeric text receives complete bidi levels, and empty text retains its requested base direction. Re-export the sharedparlance::BaseDirection, addAnalysis::is_rtl, and exposeset_base_directionon all three Parley builders. A private shared builder-options value keeps the new paragraph option and the existing build settings on one path.This updates the unreleased low-level API: replace
None,Some(0), andSome(1)passed toBidiResolver::resolvewithBaseDirection::Auto,BaseDirection::Ltr, andBaseDirection::Rtl. ExistingAnalysisOptionsliterals can addbase_directionor use..AnalysisOptions::default().Paired Tango benchmarks against
mainfound no consistent layout regression. The first 8-second full comparison put all 18 layout cases between -1.33% and +0.79%; a repeat ranged from -0.39% to +1.79% without a consistent pattern. A focused 20-second comparison measured the shortest default Latin case at +0.00% and the styled Latin case at -1.05%.Spec references: