Skip to main content

TextEngine

Struct TextEngine 

Source
pub struct TextEngine { /* private fields */ }
Expand description

Fonts, a bounded glyph cache, and everything that needs both.

One of these per application. It is &mut for measurement as well as drawing, because measuring is what populates the cache: a label measured during layout and drawn a moment later rasterises its glyphs once, and a label measured on every layout pass and never redrawn pays a cache lookup rather than an outline computation each time.

Implementations§

Source§

impl TextEngine

Source

pub fn new() -> TextEngine

An engine with the built-in bitmap font registered as FontId(0), and a 64 KB glyph cache.

FontId(0) is always the built-in font, in every configuration, so a widget that names no font gets something that certainly exists.

Source

pub fn with_atlas(atlas: GlyphAtlas) -> TextEngine

As TextEngine::new, with a cache of a chosen size.

Source

pub fn add_font(&mut self, source: Box<dyn GlyphSource>) -> FontId

Registers a font and returns its id.

Source

pub fn set_default_font(&mut self, font: FontId)

Draws every style that names no font in this face.

Without this, FontId(0) is the built-in 5x7 bitmap and there is no way to ask for anything else: every widget in this workspace carries TextStyle::built_in or TextStyle::default, both of which name FontId::DEFAULT, so registering a face with add_font alone registers something nothing refers to. That was #130.

One indirection, resolved when a style becomes glyphs — so no widget, no TextStyle and no form file changes, and an application that wants a real face says two lines instead of threading a style through everything it builds.

An id that was never registered is ignored, because the alternative is a panel that draws nothing.

let mut engine = TextEngine::new();
// Nothing registered but the built-in, so the default is the built-in.
assert_eq!(engine.default_font(), FontId::DEFAULT);

// An id nobody registered changes nothing.
engine.set_default_font(FontId(9));
assert_eq!(engine.default_font(), FontId::DEFAULT);
Source

pub const fn default_font(&self) -> FontId

Which face FontId::DEFAULT currently stands for.

Source

pub fn font_count(&self) -> usize

Number of registered fonts.

Source

pub fn font_name(&self, font: FontId) -> Option<&str>

Name of a registered font.

Source

pub fn font_contains(&self, font: FontId, ch: char) -> bool

Whether a registered font has a glyph of its own for ch.

The question an application asks before choosing what to draw: a keyboard that would like on its Backspace key, a status line that would like °. Drawing a character the font lacks is not an error — it comes out as the missing-character box — so this is what turns a silent row of tofu into a legible fallback the author picked.

false for an unregistered id, and for a font that can only render ch through shaping — see GlyphSource::glyph_id.

Source

pub const fn atlas(&self) -> &GlyphAtlas

The glyph cache.

Source

pub const fn stats(&self) -> AtlasStats

Cache statistics.

Source

pub fn clear_cache(&mut self)

Empties the glyph cache. Needed after nothing; useful in benches.

Source

pub fn metrics(&self, style: TextStyle) -> FontMetrics

Vertical metrics for a style.

Source

pub fn snap_size(&self, style: TextStyle) -> u16

The size this style will actually be drawn at.

Source

pub fn line_height(&self, style: TextStyle) -> i32

Baseline-to-baseline distance for a style.

Source

pub fn layout_line( &mut self, style: TextStyle, text: &str, f: impl FnMut(PositionedGlyph), ) -> i32

Lays out one line, calling f for each glyph that has ink.

Returns the total advance. Positions are relative to the line’s start, with bounds.y measured from the baseline — so a caller places the line by translating, and never has to know how the font was measured.

Source

pub fn measure_line(&mut self, style: TextStyle, text: &str) -> i32

Width of one line, ignoring \n.

Source

pub fn measure(&mut self, style: TextStyle, text: &str) -> Size

Extent of text, honouring \n.

The height is lines * line_height, not the ink’s bounding box: a label that changes from Ok to Ogg must not change height, or a form would reflow every time a reading gained a descender.

Source

pub fn wrap<'a>( &mut self, style: TextStyle, text: &'a str, max_width: i32, ) -> Vec<&'a str>

The lines text becomes when broken to fit max_width.

Greedy: words are added to a line until the next one would not fit. That is what every text editor does, it is one measuring pass, and the alternative — balancing lines by minimising raggedness — is a dynamic-programming problem this toolkit has no reason to solve.

Explicit \n always breaks, so a caller who has already decided where the lines go keeps that decision.

Slices borrow from text; nothing is copied. Words are separated by ASCII spaces, which is the boundary the built-in font can render and the one the languages this toolkit ships keyboard layouts for use.

§A word wider than the line

Goes on a line of its own and overflows, rather than being broken between characters. Breaking mid-word needs to know where a grapheme ends, and getting that wrong turns æ into two bytes of nothing — so an honest overflow the caller can see beats a corruption they cannot. A max_width of zero or less disables wrapping entirely for the same reason: there is no width that any word fits in.

Source

pub fn wrapped_height( &mut self, style: TextStyle, text: &str, max_width: i32, ) -> i32

Height of text once wrapped to max_width.

Source

pub fn draw_line( &mut self, canvas: &mut Pen<'_>, style: TextStyle, origin: Point, text: &str, color: Color, ) -> i32

Draws one line with its baseline at origin.

Returns the total advance, of the whole line and not of the part drawn: a caller measuring a line to know how far it scrolls needs all of it.

Only the glyphs the canvas would keep are rasterised and handed over. The painter clips the rest away to nothing, so the pixels are the same either way, but handing them over is not free: a line a megabyte long is a million glyphs, and a painter that builds geometry per glyph turns that into hundreds of megabytes for the few hundred that are on screen — more, on some, than a GPU will take in one buffer. Laying the line out is still the whole of it, which is where width comes from; it is cheap beside rasterising, being an advance apiece from the cache.

Source

pub fn draw( &mut self, canvas: &mut Pen<'_>, style: TextStyle, origin: Point, text: &str, color: Color, ) -> Size

Draws text with the top-left corner of its first line at origin, honouring \n. Returns the extent laid out.

Top-left rather than baseline, because a widget positions text in a box and should not have to know where the baseline of a font it did not choose happens to fall.

Trait Implementations§

Source§

impl Debug for TextEngine

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for TextEngine

Source§

fn default() -> TextEngine

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsAny for T
where T: Any,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Borrows as dyn Any.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Mutably borrows as dyn Any.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.