floem/text/mod.rs
1//! Floem's high-level text API.
2//!
3//! This module exposes the text types used by Floem views and editor code:
4//! - styling attributes and font vocabulary re-exported from `floem_renderer::text`
5//! - Parley alignment, cursor, selection, and wrapping vocabulary used directly by Floem
6//! - [`TextLayout`], Floem's layout wrapper around Parley
7//! - [`TextLayoutState`], shared view state for overflow-aware text layout
8//!
9//! `TextLayout` deliberately hides Parley's concrete layout type from most
10//! callers while still using Parley's lower-level vocabulary types.
11
12use std::ops::Range;
13
14mod layout;
15mod layout_state;
16
17pub use floem_renderer::text::{
18 Attrs, AttrsList, AttrsOwned, FamilyOwned, FontStyle, FontWeight, FontWidth, Glyph,
19 GlyphRunProps, LineHeightValue, NormalizedCoord,
20};
21pub use layout::{FONT_CONTEXT, TextLayout, TextSelection};
22pub use layout_state::{TextLayoutState, TextOverflowChanged};
23pub use parley::Alignment;
24pub use parley::layout::{Affinity, Cursor, Selection};
25pub use parley::style::{OverflowWrap, TextWrapMode, WordBreakStrength};
26
27/// Returns the byte ranges of the source text's logical paragraphs.
28///
29/// This splits the original string on line-ending boundaries (`\n`, `\r\n`, or `\r`)
30/// and yields the content ranges between those separators. The returned ranges do not
31/// include the line-ending bytes themselves.
32///
33/// This is a source-text helper, not a layout helper:
34/// - use this when you need width-independent paragraph/logical-line ranges from the
35/// raw text buffer
36/// - do not use this when you need wrapped or shaped visual lines from Parley layout
37///
38/// In other words, this answers "how is the input text structurally split?" rather than
39/// "how did the text lay out on screen?".
40///
41/// Typical uses:
42/// - editor/document logic that works in terms of source paragraphs
43/// - fallback handling for single-paragraph text
44/// - debug or inspection code that wants the original paragraph segmentation
45///
46/// Prefer `TextLayout`/Parley queries when you care about:
47/// - wrapping
48/// - alignment
49/// - hit testing
50/// - visual line geometry
51pub fn paragraph_ranges(text: &str) -> impl Iterator<Item = Range<usize>> + '_ {
52 let bytes = text.as_bytes();
53 let mut start = 0;
54 let mut i = 0;
55
56 std::iter::from_fn(move || {
57 if start > bytes.len() {
58 return None;
59 }
60
61 while i < bytes.len() {
62 match bytes[i] {
63 b'\r' => {
64 let end = i;
65 i += if i + 1 < bytes.len() && bytes[i + 1] == b'\n' {
66 2
67 } else {
68 1
69 };
70 let range = start..end;
71 start = i;
72 return Some(range);
73 }
74 b'\n' => {
75 let end = i;
76 i += 1;
77 let range = start..end;
78 start = i;
79 return Some(range);
80 }
81 _ => i += 1,
82 }
83 }
84
85 let end = bytes.len();
86 let range = start..end;
87 start = bytes.len() + 1;
88 Some(range)
89 })
90}