Skip to main content

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}