Skip to main content

text_document/
flow.rs

1//! Flow types for document traversal and layout engine support.
2//!
3//! The layout engine processes [`FlowElement`]s in order to build its layout
4//! tree. Snapshot types capture consistent views for thread-safe reads.
5
6use crate::text_block::TextBlock;
7use crate::text_frame::TextFrame;
8use crate::text_table::TextTable;
9use crate::{Alignment, BlockFormat, FrameFormat, ListStyle, TextFormat};
10
11// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
12// FlowElement
13// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
14
15/// An element in the document's visual flow.
16///
17/// The layout engine processes these in order to build its layout tree.
18/// Obtained from [`TextDocument::flow()`](crate::TextDocument::flow) or
19/// [`TextFrame::flow()`].
20#[derive(Clone)]
21pub enum FlowElement {
22    /// A paragraph or heading. Layout as a text block.
23    Block(TextBlock),
24
25    /// A table at this position in the flow. Layout as a grid.
26    /// The anchor frame's `table` field identifies the table entity.
27    Table(TextTable),
28
29    /// A non-table sub-frame (float, sidebar, blockquote).
30    /// Contains its own nested flow, accessible via
31    /// [`TextFrame::flow()`].
32    Frame(TextFrame),
33}
34
35// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
36// FragmentContent
37// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
38
39/// A contiguous run of content with uniform formatting within a block.
40///
41/// Offsets are **block-relative**: `offset` is the character position
42/// within the block where this fragment starts (0 = block start).
43#[derive(Debug, Clone, PartialEq, Eq)]
44pub enum FragmentContent {
45    /// A text run. The layout engine shapes these into glyphs.
46    Text {
47        text: String,
48        format: TextFormat,
49        /// Character offset within the block (block-relative).
50        offset: usize,
51        /// Character count.
52        length: usize,
53    },
54    /// An inline image. The layout engine reserves space for it.
55    ///
56    /// To retrieve the image pixel data, use the existing
57    /// [`TextDocument::resource(name)`](crate::TextDocument::resource) method.
58    Image {
59        name: String,
60        width: u32,
61        height: u32,
62        quality: u32,
63        format: TextFormat,
64        /// Character offset within the block (block-relative).
65        offset: usize,
66    },
67}
68
69// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
70// BlockSnapshot
71// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
72
73/// All layout-relevant data for one block, captured atomically.
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct BlockSnapshot {
76    pub block_id: usize,
77    pub position: usize,
78    pub length: usize,
79    pub text: String,
80    pub fragments: Vec<FragmentContent>,
81    pub block_format: BlockFormat,
82    pub list_info: Option<ListInfo>,
83}
84
85// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
86// ListInfo
87// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
88
89/// List membership and marker information for a block.
90#[derive(Debug, Clone, PartialEq, Eq)]
91pub struct ListInfo {
92    pub list_id: usize,
93    /// The list style (Disc, Decimal, LowerAlpha, etc.).
94    pub style: ListStyle,
95    /// Indentation level.
96    pub indent: u8,
97    /// Pre-formatted marker text: "•", "3.", "(c)", "IV.", etc.
98    pub marker: String,
99    /// 0-based index of this item within its list.
100    pub item_index: usize,
101}
102
103// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
104// TableCellRef
105// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
106
107/// Reference to a table cell that contains a block.
108#[derive(Clone)]
109pub struct TableCellRef {
110    pub table: TextTable,
111    pub row: usize,
112    pub column: usize,
113}
114
115// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
116// Table format types
117// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
118
119/// Table-level formatting.
120#[derive(Debug, Clone, Default, PartialEq, Eq)]
121pub struct TableFormat {
122    pub border: Option<i32>,
123    pub cell_spacing: Option<i32>,
124    pub cell_padding: Option<i32>,
125    pub width: Option<i32>,
126    pub alignment: Option<Alignment>,
127}
128
129/// Cell-level formatting.
130#[derive(Debug, Clone, Default, PartialEq, Eq)]
131pub struct CellFormat {
132    pub padding: Option<i32>,
133    pub border: Option<i32>,
134    pub vertical_alignment: Option<CellVerticalAlignment>,
135    pub background_color: Option<String>,
136}
137
138/// Vertical alignment within a table cell.
139#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
140pub enum CellVerticalAlignment {
141    #[default]
142    Top,
143    Middle,
144    Bottom,
145}
146
147// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
148// Table and Cell Snapshots
149// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
150
151/// Consistent snapshot of a table's structure and all cell content.
152#[derive(Debug, Clone, PartialEq, Eq)]
153pub struct TableSnapshot {
154    pub table_id: usize,
155    pub rows: usize,
156    pub columns: usize,
157    pub column_widths: Vec<i32>,
158    pub format: TableFormat,
159    pub cells: Vec<CellSnapshot>,
160}
161
162/// Snapshot of one table cell including its block content.
163#[derive(Debug, Clone, PartialEq, Eq)]
164pub struct CellSnapshot {
165    pub row: usize,
166    pub column: usize,
167    pub row_span: usize,
168    pub column_span: usize,
169    pub format: CellFormat,
170    pub blocks: Vec<BlockSnapshot>,
171}
172
173// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
174// Flow Snapshots
175// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
176
177/// Consistent snapshot of the entire document flow, captured in a
178/// single lock acquisition.
179#[derive(Debug, Clone, PartialEq, Eq)]
180pub struct FlowSnapshot {
181    pub elements: Vec<FlowElementSnapshot>,
182}
183
184/// Snapshot of one flow element.
185#[derive(Debug, Clone, PartialEq, Eq)]
186pub enum FlowElementSnapshot {
187    Block(BlockSnapshot),
188    Table(TableSnapshot),
189    Frame(FrameSnapshot),
190}
191
192/// Snapshot of a sub-frame and its contents.
193#[derive(Debug, Clone, PartialEq, Eq)]
194pub struct FrameSnapshot {
195    pub frame_id: usize,
196    pub format: FrameFormat,
197    pub elements: Vec<FlowElementSnapshot>,
198}
199
200// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
201// FormatChangeKind
202// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
203
204/// What kind of formatting changed.
205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
206pub enum FormatChangeKind {
207    /// Block-level: alignment, margins, indent, heading level.
208    /// Requires paragraph relayout.
209    Block,
210    /// Character-level: font, bold, italic, underline, color.
211    /// Requires reshaping but not necessarily reflow.
212    Character,
213}