text_typeset/types.rs
1/// Opaque handle to a registered font face.
2///
3/// Obtained from [`Typesetter::register_font`] or [`Typesetter::register_font_as`].
4/// Pass to [`Typesetter::set_default_font`] to make it the default.
5#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
6pub struct FontFaceId(pub u32);
7
8// ── Render output ───────────────────────────────────────────────
9
10/// Everything needed to draw one frame.
11///
12/// Produced by [`Typesetter::render`]. Contains glyph quads (textured rectangles
13/// from the atlas), inline image placeholders, and decoration rectangles
14/// (selections, cursor, underlines, table borders, etc.).
15///
16/// The adapter draws the frame in three passes:
17/// 1. Upload `atlas_pixels` as a GPU texture (only when `atlas_dirty` is true).
18/// 2. Draw each [`GlyphQuad`] as a textured rectangle from the atlas.
19/// 3. Draw each [`DecorationRect`] as a colored rectangle.
20pub struct RenderFrame {
21 /// True if the atlas texture changed since the last frame (needs re-upload).
22 pub atlas_dirty: bool,
23 /// Atlas texture width in pixels.
24 pub atlas_width: u32,
25 /// Atlas texture height in pixels.
26 pub atlas_height: u32,
27 /// RGBA pixel data, row-major. Length = `atlas_width * atlas_height * 4`.
28 pub atlas_pixels: Vec<u8>,
29 /// One textured rectangle per visible glyph.
30 pub glyphs: Vec<GlyphQuad>,
31 /// Inline image placeholders. The adapter loads the actual image data
32 /// (e.g., via `TextDocument::resource(name)`) and draws it at the given
33 /// screen position.
34 pub images: Vec<ImageQuad>,
35 /// Decoration rectangles: selections, cursor, underlines, strikeouts,
36 /// overlines, backgrounds, table borders, and cell backgrounds.
37 pub decorations: Vec<DecorationRect>,
38}
39
40/// A positioned glyph to draw as a textured quad from the atlas.
41///
42/// The adapter draws the rectangle at `screen` position, sampling from
43/// the `atlas` rectangle in the atlas texture, tinted with `color`.
44pub struct GlyphQuad {
45 /// Screen position and size: `[x, y, width, height]` in pixels.
46 pub screen: [f32; 4],
47 /// Atlas source rectangle: `[x, y, width, height]` in atlas pixel coordinates.
48 pub atlas: [f32; 4],
49 /// Glyph color: `[r, g, b, a]`, 0.0-1.0.
50 /// For normal text glyphs, this is the text color (default black).
51 /// For color emoji, this is `[1, 1, 1, 1]` (color is baked into the atlas).
52 pub color: [f32; 4],
53}
54
55/// An inline image placeholder.
56///
57/// text-typeset computes the position and size but does NOT load or rasterize
58/// the image. The adapter retrieves the image data (e.g., from
59/// `TextDocument::resource(name)`) and draws it as a separate texture.
60pub struct ImageQuad {
61 /// Screen position and size: `[x, y, width, height]` in pixels.
62 pub screen: [f32; 4],
63 /// Image resource name (matches `FragmentContent::Image::name` from text-document).
64 pub name: String,
65}
66
67/// A colored rectangle for decorations (underlines, selections, borders, etc.).
68pub struct DecorationRect {
69 /// Screen position and size: `[x, y, width, height]` in pixels.
70 pub rect: [f32; 4],
71 /// Color: `[r, g, b, a]`, 0.0-1.0.
72 pub color: [f32; 4],
73 /// What kind of decoration this rectangle represents.
74 pub kind: DecorationKind,
75}
76
77/// The type of a [`DecorationRect`].
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79pub enum DecorationKind {
80 /// Selection highlight (translucent background behind selected text).
81 Selection,
82 /// Cursor caret (thin vertical line at the insertion point).
83 Cursor,
84 /// Underline (below baseline, from font metrics).
85 Underline,
86 /// Strikethrough (at x-height, from font metrics).
87 Strikeout,
88 /// Overline (at ascent line).
89 Overline,
90 /// Generic background (e.g., frame borders).
91 Background,
92 /// Block-level background color.
93 BlockBackground,
94 /// Table border line.
95 TableBorder,
96 /// Table cell background color.
97 TableCellBackground,
98}
99
100// ── Hit testing ─────────────────────────────────────────────────
101
102/// Result of [`Typesetter::hit_test`] -maps a screen-space point to a
103/// document position.
104pub struct HitTestResult {
105 /// Absolute character position in the document.
106 pub position: usize,
107 /// Which block (paragraph) was hit, identified by stable block ID.
108 pub block_id: usize,
109 /// Character offset within the block (0 = start of block).
110 pub offset_in_block: usize,
111 /// What region of the layout was hit.
112 pub region: HitRegion,
113}
114
115/// What region of the layout a hit test landed in.
116pub enum HitRegion {
117 /// Inside a text run (normal text content).
118 Text,
119 /// In the block's left margin area (before any text content).
120 LeftMargin,
121 /// In the block's indent area.
122 Indent,
123 /// On a table border line.
124 TableBorder,
125 /// Below all content in the document.
126 BelowContent,
127 /// Past the end of a line (to the right of the last character).
128 PastLineEnd,
129 /// On an inline image.
130 Image { name: String },
131 /// On a hyperlink.
132 Link { href: String },
133}
134
135// ── Cursor display ──────────────────────────────────────────────
136
137/// Cursor display state for rendering.
138///
139/// The adapter reads cursor position from text-document's `TextCursor`
140/// and creates this struct to feed to [`Typesetter::set_cursor`].
141/// text-typeset uses it to generate caret and selection decorations
142/// in the next [`Typesetter::render`] call.
143pub struct CursorDisplay {
144 /// Cursor position (character offset in the document).
145 pub position: usize,
146 /// Selection anchor. Equals `position` when there is no selection.
147 /// When different from `position`, the range `[min(anchor, position), max(anchor, position))`
148 /// is highlighted as a selection.
149 pub anchor: usize,
150 /// Whether the caret is visible (false during the blink-off phase).
151 /// The adapter manages the blink timer; text-typeset just respects this flag.
152 pub visible: bool,
153}
154
155// ── Scrolling ───────────────────────────────────────────────────
156
157/// Visual position and size of a laid-out block.
158///
159/// Returned by [`Typesetter::block_visual_info`].
160pub struct BlockVisualInfo {
161 /// Block ID (matches `BlockSnapshot::block_id`).
162 pub block_id: usize,
163 /// Y position of the block's top edge relative to the document start, in pixels.
164 pub y: f32,
165 /// Total height of the block including margins, in pixels.
166 pub height: f32,
167}
168
169impl RenderFrame {
170 pub(crate) fn new() -> Self {
171 Self {
172 atlas_dirty: false,
173 atlas_width: 0,
174 atlas_height: 0,
175 atlas_pixels: Vec::new(),
176 glyphs: Vec::new(),
177 images: Vec::new(),
178 decorations: Vec::new(),
179 }
180 }
181}