Expand description
Paragraph layout for densa: shaping, line breaking, bidi and alignment.
TextSystem (fonts plus layout scratch space, one per application) turns text and a
ParagraphStyle, with optional Spans, into a Paragraph: shaped by parley,
broken into lines at a maximum width and aligned. A paragraph hands its glyphs out as
densa_text::GlyphRuns, which a renderer draws (densa-draw’s Canvas::draw_run), so
layout and rendering stay independent of each other.
TextSelection adds what editing needs on top: hit-testing a point to a text position,
caret and selection rectangles, and keyboard motions (by character, word and line, in
visual order for mixed-direction text).
TextEditor makes text editable: typing, deletion by character, word or line,
input-method (IME) composition, and undo and redo, keeping a selection and a laid-out
paragraph in step.
Laying out allocates and happens when text, style or width change; drawing a laid-out paragraph, hit-testing and moving a selection or a caret do not allocate.
§Fonts and scripts
TextSystem::new draws the default monospace family with the bundled JetBrains Mono
and every character it lacks (Korean, Japanese, Chinese, symbols, …) with the operating
system’s fonts; TextSystem::bundled uses the bundled font alone, the same on every
machine. Features:
system-fonts(default): find the operating system’s fonts. On Linux, fontconfig is loaded at run time; without it, text falls back to the bundled font.complex-scripts: dictionaries for word breaks in Chinese and Japanese and line breaks in Thai, Lao, Khmer and Burmese (several MB). Without it, a double-click in Japanese selects one character.
use densa_paragraph::{ParagraphStyle, TextSystem};
// `TextSystem::new()` also finds the system's fonts; `bundled()` is the same everywhere.
let mut text = TextSystem::bundled()?;
let style = ParagraphStyle::new(16.0).with_max_width(Some(120.0));
let mut paragraph = text.paragraph("A paragraph wrapped at a width.", &style, &[])?;
let wrapped = paragraph.lines().len();
assert!(wrapped > 1);
// A new width re-breaks the lines without shaping the text again.
paragraph.reflow(None)?;
assert_eq!(paragraph.lines().len(), 1);Structs§
- Color
- A color in linear RGB with straight (not premultiplied) alpha: the space densa blends in.
- LineBox
- One laid-out line, in pixels relative to the paragraph’s top-left corner.
- Paragraph
- Shaped, line-broken and aligned text, ready to draw as
GlyphRuns. - Paragraph
Style - How a whole paragraph is set;
Spans override parts of it. - Point
- A position in pixels, y down.
- Rect
- An axis-aligned rectangle in pixels, y down, stored as its four edges.
- Span
- A styled part of a paragraph’s text.
- Text
Editor - Editable text: a
Paragraphwith aTextSelection, typing, deletion and input-method composition. - Text
Selection - A caret (collapsed) or a selected range within a
Paragraph. - Text
System - Fonts plus layout scratch space: builds
Paragraphs.
Enums§
- Affinity
- Which character a caret at a position belongs to, where that matters: at a line wrap (end of one line or start of the next) and at a change of text direction.
- Motion
- A way to move a caret or extend a selection.
- Paragraph
Error - Why a paragraph could not be laid out.
- Text
Align - Horizontal alignment of each line within the paragraph’s width.
Constants§
- MAX_
FONT_ PX - Largest font size accepted, in pixels per em. Far beyond any UI text; it keeps every
line metric finite (sizes near
f32::MAXturn layout geometry into NaN). - MAX_
LINE_ HEIGHT - Largest line height accepted, as a multiple of the font size.