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