Skip to content

Commit 7ce1024

Browse files
committed
Replace fns Text{,Display}::text_is_rtl
Note: the removed fn line_is_rtl was incorrect for BiDi text
1 parent 800cff9 commit 7ce1024

File tree

3 files changed

+26
-71
lines changed

3 files changed

+26
-71
lines changed

src/display/mod.rs

Lines changed: 14 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
//! Text prepared for display
77
8-
#[allow(unused)]
9-
use crate::{Status, Text};
108
use crate::conv::to_usize;
11-
use crate::{Direction, Vec2, shaper};
9+
#[allow(unused)]
10+
use crate::{Direction, Status, Text};
11+
use crate::{Vec2, shaper};
1212
use smallvec::SmallVec;
1313
use tinyvec::TinyVec;
1414

@@ -76,12 +76,8 @@ pub struct NotReady;
7676
/// which provides a
7777
/// [`GraphemeCursor`](https://unicode-rs.github.io/unicode-segmentation/unicode_segmentation/struct.GraphemeCursor.html)
7878
/// to step back or forward one "grapheme", in logical text order.
79-
/// Optionally, the direction may
80-
/// be reversed for right-to-left lines [`TextDisplay::line_is_rtl`], but note
81-
/// that the result may be confusing since not all text on the line follows the
82-
/// line's base direction and adjacent lines may have different directions.
83-
///
84-
/// Navigating glyphs left or right in display-order is not currently supported.
79+
/// The direction of navigation may be reversed for [right-to-left text](Self::text_is_rtl)
80+
/// (i.e. reversed logical-order navigation).
8581
///
8682
/// To navigate "up" and "down" lines, use [`TextDisplay::text_glyph_pos`] to
8783
/// get the position of the cursor, [`TextDisplay::find_line`] to get the line
@@ -105,6 +101,7 @@ pub struct TextDisplay {
105101
wrapped_runs: TinyVec<[RunPart; 1]>,
106102
/// Visual (wrapped) lines, in visual and logical order
107103
lines: TinyVec<[Line; 1]>,
104+
is_rtl: bool,
108105
l_bound: f32,
109106
r_bound: f32,
110107
}
@@ -117,7 +114,7 @@ fn size_of_elts() {
117114
assert_eq!(size_of::<shaper::GlyphRun>(), 112);
118115
assert_eq!(size_of::<RunPart>(), 24);
119116
assert_eq!(size_of::<Line>(), 24);
120-
assert_eq!(size_of::<TextDisplay>(), 200);
117+
assert_eq!(size_of::<TextDisplay>(), 208);
121118
}
122119

123120
impl Default for TextDisplay {
@@ -126,6 +123,7 @@ impl Default for TextDisplay {
126123
runs: Default::default(),
127124
wrapped_runs: Default::default(),
128125
lines: Default::default(),
126+
is_rtl: false,
129127
l_bound: 0.0,
130128
r_bound: 0.0,
131129
}
@@ -201,45 +199,13 @@ impl TextDisplay {
201199

202200
/// Get the base directionality of the text
203201
///
204-
/// [Requires status][Self#status-of-preparation]: none.
205-
pub fn text_is_rtl(&self, text: &str, direction: Direction) -> bool {
206-
let (is_auto, mut is_rtl) = match direction {
207-
Direction::Ltr => (false, false),
208-
Direction::Rtl => (false, true),
209-
Direction::Auto => (true, false),
210-
Direction::AutoRtl => (true, true),
211-
};
212-
213-
if is_auto {
214-
match unicode_bidi::get_base_direction(text) {
215-
unicode_bidi::Direction::Ltr => is_rtl = false,
216-
unicode_bidi::Direction::Rtl => is_rtl = true,
217-
unicode_bidi::Direction::Mixed => (),
218-
}
219-
}
220-
221-
is_rtl
222-
}
223-
224-
/// Get the directionality of the current line
225-
///
226-
/// [Requires status][Self#status-of-preparation]: lines have been wrapped.
227-
///
228-
/// Returns:
229-
///
230-
/// - `None` if text is empty
231-
/// - `Some(line_is_right_to_left)` otherwise
202+
/// [Requires status][Self#status-of-preparation]: run-breaking is complete.
232203
///
233-
/// Note: indeterminate lines (e.g. empty lines) have their direction
234-
/// determined from the passed environment, by default left-to-right.
235-
pub fn line_is_rtl(&self, line: usize) -> Option<bool> {
236-
if let Some(line) = self.lines.get(line) {
237-
let first_run = line.run_range.start();
238-
let glyph_run = to_usize(self.wrapped_runs[first_run].glyph_run);
239-
Some(self.runs[glyph_run].level.is_rtl())
240-
} else {
241-
None
242-
}
204+
/// This returns the direction inferred from the `text` and [`Direction`]
205+
/// used during run-breaking. See also [`Direction::text_is_rtl`].
206+
#[inline]
207+
pub fn text_is_rtl(&self) -> bool {
208+
self.is_rtl
243209
}
244210

245211
/// Find the text index for the glyph nearest the given `pos`

src/display/text_runs.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ impl TextDisplay {
213213
Direction::Rtl => Some(RTL_LEVEL),
214214
};
215215
let info = BidiInfo::new(text, default_para_level);
216+
self.is_rtl = info
217+
.paragraphs
218+
.first()
219+
.map(|p| p.level.is_rtl())
220+
.unwrap_or_default();
216221
let levels = info.levels;
217222
assert_eq!(text.len(), levels.len());
218223

src/text.rs

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -310,23 +310,15 @@ impl<T: FormattableText + ?Sized> Text<T> {
310310

311311
/// Get the base directionality of the text
312312
///
313-
/// This does not require that the text is prepared.
313+
/// This returns the direction inferred during run-breaking if available,
314+
/// falling back to [`Direction::text_is_rtl`].
315+
#[inline]
314316
pub fn text_is_rtl(&self) -> bool {
315-
let cached_is_rtl = match self.line_is_rtl(0) {
316-
Ok(None) => Some(self.direction == Direction::Rtl),
317-
Ok(Some(is_rtl)) => Some(is_rtl),
318-
Err(NotReady) => None,
319-
};
320-
#[cfg(not(debug_assertions))]
321-
if let Some(cached) = cached_is_rtl {
322-
return cached;
323-
}
324-
325-
let is_rtl = self.display.text_is_rtl(self.as_str(), self.direction);
326-
if let Some(cached) = cached_is_rtl {
327-
debug_assert_eq!(cached, is_rtl);
317+
if self.status >= Status::ResizeLevelRuns {
318+
self.display.text_is_rtl()
319+
} else {
320+
self.direction.text_is_rtl(&self.text.as_str())
328321
}
329-
is_rtl
330322
}
331323

332324
/// Return the sequence of effect tokens
@@ -509,14 +501,6 @@ impl<T: FormattableText + ?Sized> Text<T> {
509501
Ok(self.wrapped_display()?.find_line(index))
510502
}
511503

512-
/// Get the directionality of the current line
513-
///
514-
/// See [`TextDisplay::line_is_rtl`].
515-
#[inline]
516-
pub fn line_is_rtl(&self, line: usize) -> Result<Option<bool>, NotReady> {
517-
Ok(self.wrapped_display()?.line_is_rtl(line))
518-
}
519-
520504
/// Find the text index for the glyph nearest the given `pos`
521505
///
522506
/// See [`TextDisplay::text_index_nearest`].

0 commit comments

Comments
 (0)