pub struct TextDisplay { /* private fields */ }
Expand description
Text type-setting object (low-level, without text and configuration)
This struct caches type-setting data at multiple levels of preparation. Its end result is a sequence of type-set glyphs.
It is usually recommended to use Text
instead, which includes
the source text, type-setting configuration and status tracking.
§Status of preparation
Stages of preparation are as follows:
-
Ensure all required fonts are loaded.
-
Call
Self::prepare_runs
to break text into level runs, then shape these runs into glyph runs (unwrapped but with weak break points).This method must be called again if the
text
, textdirection
orfont_id
change. If only the text size (dpem
) changes, it is sufficient to instead callSelf::resize_runs
. -
Optionally,
Self::measure_width
andSelf::measure_height
may be used at this point to determine size requirements. -
Call
Self::prepare_lines
to wrap text and perform re-ordering (where lines are bi-directional) and horizontal alignment.This must be called again if any of
wrap_width
,width_bound
orh_align
change. -
Call
Self::vertically_align
to set or adjust vertical alignment. (Not technically required if alignment is always top.)
All methods are idempotent (that is, they may be called multiple times without affecting the result). Later stages of preparation do not affect earlier stages, but if an earlier stage is repeated to account for adjusted configuration then later stages must also be repeated.
This struct does not track the state of preparation. It is recommended to
use Text
or a custom wrapper for that purpose. Failure to observe the
correct sequence is memory-safe but may cause panic or an unexpected result.
§Text navigation
Despite lacking a copy of the underlying text, text-indices may be mapped to glyphs and lines, and vice-versa.
The text range is 0..self.text_len()
. Any index within this range
(inclusive of end point) is valid for usage in all methods taking a text index.
Multiple indices may map to the same glyph (e.g. within multi-byte chars,
with combining-diacritics, and with ligatures). In some cases a single index
corresponds to multiple glyph positions (due to line-wrapping or change of
direction in bi-directional text).
Navigating to the start or end of a line can be done with
TextDisplay::find_line
and TextDisplay::line_range
.
Navigating forwards or backwards should be done via a library such as
unicode-segmentation
which provides a
GraphemeCursor
to step back or forward one “grapheme”, in logical text order.
Optionally, the direction may
be reversed for right-to-left lines TextDisplay::line_is_rtl
, but note
that the result may be confusing since not all text on the line follows the
line’s base direction and adjacent lines may have different directions.
Navigating glyphs left or right in display-order is not currently supported.
To navigate “up” and “down” lines, use TextDisplay::text_glyph_pos
to
get the position of the cursor, TextDisplay::find_line
to get the line
number, then TextDisplay::line_index_nearest
to find the new index.
Implementations§
Source§impl TextDisplay
impl TextDisplay
Sourcepub fn text_glyph_pos(&self, index: usize) -> MarkerPosIter ⓘ
pub fn text_glyph_pos(&self, index: usize) -> MarkerPosIter ⓘ
Find the starting position (top-left) of the glyph at the given index
Requires status: text is fully prepared for display.
The index should be no greater than the text length. It is not required to be on a code-point boundary. Returns an iterator over matching positions. Length of results is guaranteed to be one of 0, 1 or 2:
- 0 if the index is not included in any run of text (probably only possible within a multi-byte line break or beyond the text length)
- 1 is the normal case
- 2 if the index is at the end of one run of text and at the start
of another; these positions may be the same or may not be (over
line breaks and with bidirectional text). If only a single position
is desired, usually the latter is preferred (via
next_back()
).
The result is not guaranteed to be within Self::bounding_box
.
Depending on the use-case, the caller may need to clamp the resulting
position.
Sourcepub fn glyphs<F>(&self, f: F)
pub fn glyphs<F>(&self, f: F)
Yield a sequence of positioned glyphs
Requires status: text is fully prepared for display.
Glyphs are yielded in undefined order by a call to f
. The number of
glyphs yielded will equal [TextDisplay::num_glyphs
]. The closure f
receives parameters face_id, dpem, glyph
.
This may be used as follows:
let mut text = Text::new("Some example text");
text.prepare();
let mut glyphs = Vec::with_capacity(text.num_glyphs().unwrap_or(0));
text.glyphs(|_, dpem, glyph| glyphs.push((dpem, glyph)));
draw(glyphs);
This method has fairly low cost: O(n)
in the number of glyphs with
low overhead.
Sourcepub fn glyphs_with_effects<X, F, G>(
&self,
effects: &[Effect<X>],
default_aux: X,
f: F,
g: G,
)
pub fn glyphs_with_effects<X, F, G>( &self, effects: &[Effect<X>], default_aux: X, f: F, g: G, )
Like TextDisplay::glyphs
but with added effects
Requires status: text is fully prepared for display.
If the list effects
is empty or has first entry with start > 0
, the
result of Effect::default(default_aux)
is used. The user payload of
type X
is simply passed through to f
and g
calls and may be useful
for color information.
The callback f
receives face_id, dpem, glyph, i, aux
where
dpu
and height
are both measures of the font size (pixels per font
unit and pixels per height, respectively), and i
is the index within
effects
(or usize::MAX
when a default-constructed effect token is
used).
The callback g
receives positioning for each underline/strike-through
segment: x1, x2, y_top, h
where h
is the thickness (height). Note
that it is possible to have h < 1.0
and y_top, y_top + h
to round to
the same number; the renderer is responsible for ensuring such lines
are actually visible. The last parameters are i, aux
as for f
.
Note: this is significantly more computationally expensive than
TextDisplay::glyphs
. Optionally one may choose to cache the result,
though this is not really necessary.
Sourcepub fn highlight_range(
&self,
range: Range<usize>,
f: &mut dyn FnMut(Vec2, Vec2),
)
pub fn highlight_range( &self, range: Range<usize>, f: &mut dyn FnMut(Vec2, Vec2), )
Yield a sequence of rectangles to highlight a given text range
Requires status: text is fully prepared for display.
Calls f(top_left, bottom_right)
for each highlighting rectangle.
Source§impl TextDisplay
impl TextDisplay
Sourcepub fn resize_runs<F>(&mut self, text: &F, dpem: f32)where
F: FormattableText + ?Sized,
pub fn resize_runs<F>(&mut self, text: &F, dpem: f32)where
F: FormattableText + ?Sized,
Update font size
Requires status: level runs have been
prepared and are valid in all ways except size (dpem
).
This updates the result of TextDisplay::prepare_runs
due to change
in font size.
Sourcepub fn prepare_runs<F>(
&mut self,
text: &F,
direction: Direction,
font_id: FontId,
dpem: f32,
) -> Result<(), InvalidFontId>where
F: FormattableText + ?Sized,
pub fn prepare_runs<F>(
&mut self,
text: &F,
direction: Direction,
font_id: FontId,
dpem: f32,
) -> Result<(), InvalidFontId>where
F: FormattableText + ?Sized,
Break text into level runs
Requires status: none.
Must be called again if any of text
, direction
or font_id
change.
If only dpem
changes, Self::resize_runs
may be called instead.
The text is broken into a set of contiguous “level runs”. These runs are
maximal slices of the text
which do not contain explicit line breaks
and have a single text direction according to the
Unicode Bidirectional Algorithm.
Source§impl TextDisplay
impl TextDisplay
Sourcepub fn measure_width(&self, max_width: f32) -> f32
pub fn measure_width(&self, max_width: f32) -> f32
Measure required width, up to some max_width
Requires status: level runs have been prepared.
This method allows calculation of the width requirement of a text object
without full wrapping and glyph placement. Whenever the requirement
exceeds max_width
, the algorithm stops early, returning max_width
.
The return value is unaffected by alignment and wrap configuration.
Sourcepub fn measure_height(&self, wrap_width: f32) -> f32
pub fn measure_height(&self, wrap_width: f32) -> f32
Measure required vertical height, wrapping as configured
Requires status: level runs have been prepared.
This method performs most required preparation steps of the
TextDisplay
. Remaining prepartion should be fast.
Sourcepub fn prepare_lines(
&mut self,
wrap_width: f32,
width_bound: f32,
h_align: Align,
) -> f32
pub fn prepare_lines( &mut self, wrap_width: f32, width_bound: f32, h_align: Align, ) -> f32
Prepare lines (“wrap”)
Requires status: level runs have been prepared.
This does text layout, including wrapping and horizontal alignment but excluding vertical alignment.
Returns the required height.
Sourcepub fn vertically_align(&mut self, bound: f32, v_align: Align)
pub fn vertically_align(&mut self, bound: f32, v_align: Align)
Vertically align lines
Requires status: lines have been wrapped.
Source§impl TextDisplay
impl TextDisplay
Sourcepub fn num_lines(&self) -> usize
pub fn num_lines(&self) -> usize
Get the number of lines (after wrapping)
Requires status: lines have been wrapped.
Sourcepub fn bounding_box(&self) -> (Vec2, Vec2)
pub fn bounding_box(&self) -> (Vec2, Vec2)
Get the size of the required bounding box
Requires status: lines have been wrapped.
Returns the position of the upper-left and lower-right corners of a bounding box on content. Alignment and input bounds do affect the result.
Sourcepub fn find_line(&self, index: usize) -> Option<(usize, Range<usize>)>
pub fn find_line(&self, index: usize) -> Option<(usize, Range<usize>)>
Find the line containing text index
Requires status: lines have been wrapped.
Returns the line number and the text-range of the line.
Returns None
in case index
does not line on or at the end of a line
(which means either that index
is beyond the end of the text or that
index
is within a mult-byte line break).
Sourcepub fn line_range(&self, line: usize) -> Option<Range<usize>>
pub fn line_range(&self, line: usize) -> Option<Range<usize>>
Get the range of a line, by line number
Requires status: lines have been wrapped.
Sourcepub fn text_is_rtl(&self, text: &str, direction: Direction) -> bool
pub fn text_is_rtl(&self, text: &str, direction: Direction) -> bool
Get the base directionality of the text
Requires status: none.
Sourcepub fn line_is_rtl(&self, line: usize) -> Option<bool>
pub fn line_is_rtl(&self, line: usize) -> Option<bool>
Get the directionality of the current line
Requires status: lines have been wrapped.
Returns:
None
if text is emptySome(line_is_right_to_left)
otherwise
Note: indeterminate lines (e.g. empty lines) have their direction determined from the passed environment, by default left-to-right.
Sourcepub fn text_index_nearest(&self, pos: Vec2) -> usize
pub fn text_index_nearest(&self, pos: Vec2) -> usize
Find the text index for the glyph nearest the given pos
Requires status: text is fully prepared for display.
This includes the index immediately after the last glyph, thus
result ≤ text.len()
.
Note: if the font’s rect
does not start at the origin, then its top-left
coordinate should first be subtracted from pos
.
Sourcepub fn line_index_nearest(&self, line: usize, x: f32) -> Option<usize>
pub fn line_index_nearest(&self, line: usize, x: f32) -> Option<usize>
Find the text index nearest horizontal-coordinate x
on line
Requires status: lines have been wrapped.
This is similar to TextDisplay::text_index_nearest
, but allows the
line to be specified explicitly. Returns None
only on invalid line
.
Trait Implementations§
Source§impl Clone for TextDisplay
impl Clone for TextDisplay
Source§fn clone(&self) -> TextDisplay
fn clone(&self) -> TextDisplay
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreSource§impl Debug for TextDisplay
impl Debug for TextDisplay
Source§impl Default for TextDisplay
impl Default for TextDisplay
Source§fn default() -> TextDisplay
fn default() -> TextDisplay
Auto Trait Implementations§
impl Freeze for TextDisplay
impl RefUnwindSafe for TextDisplay
impl Send for TextDisplay
impl Sync for TextDisplay
impl Unpin for TextDisplay
impl UnwindSafe for TextDisplay
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<S, T> CastApprox<T> for Swhere
T: ConvApprox<S>,
impl<S, T> CastApprox<T> for Swhere
T: ConvApprox<S>,
Source§fn try_cast_approx(self) -> Result<T, Error>
fn try_cast_approx(self) -> Result<T, Error>
Source§fn cast_approx(self) -> T
fn cast_approx(self) -> T
Source§impl<S, T> CastFloat<T> for Swhere
T: ConvFloat<S>,
impl<S, T> CastFloat<T> for Swhere
T: ConvFloat<S>,
Source§fn cast_trunc(self) -> T
fn cast_trunc(self) -> T
Source§fn cast_nearest(self) -> T
fn cast_nearest(self) -> T
Source§fn cast_floor(self) -> T
fn cast_floor(self) -> T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian()
.