Skip to main content

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}