Skip to main content

text_typeset/layout/
line.rs

1use std::ops::Range;
2
3use crate::shaping::run::ShapedRun;
4
5#[derive(Clone)]
6pub struct LayoutLine {
7    pub runs: Vec<PositionedRun>,
8    /// Baseline y relative to block top (set by block layout).
9    pub y: f32,
10    pub ascent: f32,
11    pub descent: f32,
12    pub leading: f32,
13    /// Total line height: ascent + descent + leading.
14    pub line_height: f32,
15    /// Actual content width (sum of run advances).
16    pub width: f32,
17    /// Character range in the block's text.
18    pub char_range: Range<usize>,
19}
20
21impl LayoutLine {
22    /// Find the x coordinate for a char offset within this line.
23    ///
24    /// Walks runs and glyphs, returning the x position of the first glyph
25    /// whose cluster >= `offset`. Falls back to the end of the line.
26    pub fn x_for_offset(&self, offset: usize) -> f32 {
27        for (i, run) in self.runs.iter().enumerate() {
28            let mut glyph_x = run.x;
29            for glyph in &run.shaped_run.glyphs {
30                if glyph.cluster as usize >= offset {
31                    return glyph_x;
32                }
33                glyph_x += glyph.x_advance;
34            }
35            // Only return from this run if the offset doesn't belong to a later run
36            let next_run_start = self
37                .runs
38                .get(i + 1)
39                .and_then(|r| r.shaped_run.glyphs.first())
40                .map(|g| g.cluster as usize);
41            match next_run_start {
42                Some(next_start) if offset >= next_start => continue,
43                _ => return glyph_x,
44            }
45        }
46        self.runs
47            .last()
48            .map(|r| r.x + r.shaped_run.advance_width)
49            .unwrap_or(0.0)
50    }
51}
52
53#[derive(Clone)]
54pub struct PositionedRun {
55    pub shaped_run: ShapedRun,
56    /// X offset from the left edge of the content area.
57    pub x: f32,
58    /// Decoration flags for this run.
59    pub decorations: RunDecorations,
60}
61
62/// Text decoration flags and metadata carried from the source TextFormat.
63#[derive(Clone, Debug, Default)]
64pub struct RunDecorations {
65    pub underline_style: crate::types::UnderlineStyle,
66    pub overline: bool,
67    pub strikeout: bool,
68    pub is_link: bool,
69    /// Text foreground color (RGBA). None means default (black).
70    pub foreground_color: Option<[f32; 4]>,
71    /// Underline color (RGBA). None means use foreground_color.
72    pub underline_color: Option<[f32; 4]>,
73    /// Text-level background highlight color (RGBA). None means transparent.
74    pub background_color: Option<[f32; 4]>,
75    /// Hyperlink destination URL.
76    pub anchor_href: Option<String>,
77    /// Tooltip text.
78    pub tooltip: Option<String>,
79    /// Vertical alignment (normal, superscript, subscript).
80    pub vertical_alignment: crate::types::VerticalAlignment,
81}