1use std::cell::OnceCell;
2use std::ops::Deref;
3
4#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
5pub enum WhiteSpaceMode {
6 #[default]
7 Normal,
8 PreWrap,
9}
10
11#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
12pub enum WordBreakMode {
13 #[default]
14 Normal,
15 KeepAll,
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
19pub enum SegmentBreakKind {
20 Text,
21 Space,
22 PreservedSpace,
23 Tab,
24 Glue,
25 ZeroWidthBreak,
26 SoftHyphen,
27 HardBreak,
28}
29
30#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
31pub struct PrepareOptions {
32 pub white_space: WhiteSpaceMode,
33 pub word_break: WordBreakMode,
34}
35
36#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
38pub struct LayoutCursor {
39 pub segment_index: usize,
40 pub grapheme_index: usize,
41}
42
43impl LayoutCursor {
44 pub const fn new(segment_index: usize, grapheme_index: usize) -> Self {
45 Self {
46 segment_index,
47 grapheme_index,
48 }
49 }
50}
51
52#[derive(Clone, Copy, Debug, Default, PartialEq)]
53pub struct LayoutResult {
54 pub line_count: usize,
55 pub height: f64,
56}
57
58#[derive(Clone, Copy, Debug, Default, PartialEq)]
59pub struct LineStats {
60 pub line_count: usize,
61 pub max_line_width: f64,
62}
63
64#[derive(Clone, Copy, Debug, Default, PartialEq)]
65pub struct PrepareProfile {
66 pub analysis_ms: f64,
67 pub measure_ms: f64,
68 pub total_ms: f64,
69 pub analysis_segments: usize,
70 pub prepared_segments: usize,
71 pub breakable_segments: usize,
72}
73
74#[derive(Clone, Copy, Debug, PartialEq, Eq)]
75pub struct PreparedLineChunk {
76 pub start_segment_index: usize,
77 pub end_segment_index: usize,
78 pub consumed_end_segment_index: usize,
79}
80
81#[derive(Clone, Debug, PartialEq)]
82pub struct LayoutLine {
83 pub text: String,
84 pub width: f64,
85 pub start: LayoutCursor,
86 pub end: LayoutCursor,
87}
88
89#[derive(Clone, Copy, Debug, PartialEq)]
90pub struct LayoutLineRange {
91 pub width: f64,
92 pub start: LayoutCursor,
93 pub end: LayoutCursor,
94}
95
96#[derive(Clone, Debug, PartialEq)]
97pub struct LayoutLinesResult {
98 pub line_count: usize,
99 pub height: f64,
100 pub lines: Vec<LayoutLine>,
101}
102
103#[derive(Clone, Debug)]
105pub struct PreparedText {
106 pub(crate) font: String,
107 pub(crate) white_space: WhiteSpaceMode,
108 pub(crate) widths: Vec<f64>,
109 pub(crate) line_end_fit_advances: Vec<f64>,
110 pub(crate) line_end_paint_advances: Vec<f64>,
111 pub(crate) kinds: Vec<SegmentBreakKind>,
112 pub(crate) breakable_widths: Vec<Option<Vec<f64>>>,
113 pub(crate) breakable_prefix_widths: Vec<Option<Vec<f64>>>,
114 pub(crate) discretionary_hyphen_width: f64,
115 pub(crate) tab_stop_advance: f64,
116 pub(crate) chunks: Vec<PreparedLineChunk>,
117 pub(crate) simple_line_walk_fast_path: bool,
118}
119
120impl PreparedText {
121 pub fn font(&self) -> &str {
122 &self.font
123 }
124 pub fn white_space(&self) -> WhiteSpaceMode {
125 self.white_space
126 }
127 pub fn discretionary_hyphen_width(&self) -> f64 {
128 self.discretionary_hyphen_width
129 }
130 pub fn tab_stop_advance(&self) -> f64 {
131 self.tab_stop_advance
132 }
133 pub fn widths(&self) -> &[f64] {
134 &self.widths
135 }
136 pub fn line_end_fit_advances(&self) -> &[f64] {
137 &self.line_end_fit_advances
138 }
139 pub fn line_end_paint_advances(&self) -> &[f64] {
140 &self.line_end_paint_advances
141 }
142 pub fn kinds(&self) -> &[SegmentBreakKind] {
143 &self.kinds
144 }
145 pub fn breakable_widths(&self) -> &[Option<Vec<f64>>] {
146 &self.breakable_widths
147 }
148 pub fn breakable_prefix_widths(&self) -> &[Option<Vec<f64>>] {
149 &self.breakable_prefix_widths
150 }
151 pub fn chunks(&self) -> &[PreparedLineChunk] {
152 &self.chunks
153 }
154 pub fn simple_line_walk_fast_path(&self) -> bool {
155 self.simple_line_walk_fast_path
156 }
157}
158
159#[derive(Debug)]
161pub struct PreparedTextWithSegments {
162 pub(crate) base: PreparedText,
163 pub(crate) segments: Vec<String>,
164 pub(crate) segment_levels: Option<Vec<i8>>,
165 pub(crate) grapheme_offsets: Vec<OnceCell<Vec<usize>>>,
166}
167
168impl PreparedTextWithSegments {
169 pub fn segments(&self) -> &[String] {
170 &self.segments
171 }
172 pub fn segment_levels(&self) -> Option<&[i8]> {
173 self.segment_levels.as_deref()
174 }
175}
176
177impl Deref for PreparedTextWithSegments {
178 type Target = PreparedText;
179
180 fn deref(&self) -> &Self::Target {
181 &self.base
182 }
183}