Skip to main content

Crate densa_paragraph

Crate densa_paragraph 

Source
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.
ParagraphStyle
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.
TextEditor
Editable text: a Paragraph with a TextSelection, typing, deletion and input-method composition.
TextSelection
A caret (collapsed) or a selected range within a Paragraph.
TextSystem
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.
ParagraphError
Why a paragraph could not be laid out.
TextAlign
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::MAX turn layout geometry into NaN).
MAX_LINE_HEIGHT
Largest line height accepted, as a multiple of the font size.