Skip to main content

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}