text_typeset/layout/
frame.rs1use crate::font::registry::FontRegistry;
2use crate::layout::block::layout_block;
3use crate::layout::block::{BlockLayout, BlockLayoutParams};
4use crate::layout::table::{TableLayout, TableLayoutParams, layout_table};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
15pub enum FramePosition {
16 #[default]
18 Inline,
19 FloatLeft,
22 FloatRight,
25 Absolute,
28}
29
30pub struct FrameLayoutParams {
32 pub frame_id: usize,
33 pub position: FramePosition,
34 pub width: Option<f32>,
36 pub height: Option<f32>,
38 pub margin_top: f32,
39 pub margin_bottom: f32,
40 pub margin_left: f32,
41 pub margin_right: f32,
42 pub padding: f32,
43 pub border_width: f32,
44 pub blocks: Vec<BlockLayoutParams>,
46 pub tables: Vec<(usize, TableLayoutParams)>, }
48
49pub struct FrameLayout {
51 pub frame_id: usize,
52 pub y: f32,
53 pub x: f32,
54 pub total_width: f32,
55 pub total_height: f32,
56 pub content_x: f32,
57 pub content_y: f32,
58 pub content_width: f32,
59 pub content_height: f32,
60 pub blocks: Vec<BlockLayout>,
61 pub tables: Vec<TableLayout>,
62 pub border_width: f32,
63}
64
65pub fn layout_frame(
67 registry: &FontRegistry,
68 params: &FrameLayoutParams,
69 available_width: f32,
70) -> FrameLayout {
71 let border = params.border_width;
72 let pad = params.padding;
73 let frame_width = params.width.unwrap_or(available_width);
74 let content_width =
75 (frame_width - border * 2.0 - pad * 2.0 - params.margin_left - params.margin_right)
76 .max(0.0);
77
78 let mut blocks = Vec::new();
80 let mut content_y = 0.0f32;
81
82 for block_params in ¶ms.blocks {
83 let mut block = layout_block(registry, block_params, content_width);
84 block.y = content_y + block.top_margin;
85 let block_content = block.height - block.top_margin - block.bottom_margin;
86 content_y = block.y + block_content + block.bottom_margin;
87 blocks.push(block);
88 }
89
90 let mut tables = Vec::new();
92 for (_flow_idx, table_params) in ¶ms.tables {
93 let mut table = layout_table(registry, table_params, content_width);
94 table.y = content_y;
95 content_y += table.total_height;
96 tables.push(table);
97 }
98
99 let auto_content_height = content_y;
100 let content_height = params
101 .height
102 .map(|h| (h - border * 2.0 - pad * 2.0).max(0.0))
103 .unwrap_or(auto_content_height);
104
105 let total_height =
106 params.margin_top + border + pad + content_height + pad + border + params.margin_bottom;
107 let total_width =
108 params.margin_left + border + pad + content_width + pad + border + params.margin_right;
109
110 let content_x = params.margin_left + border + pad;
111 let content_y_offset = params.margin_top + border + pad;
112
113 FrameLayout {
114 frame_id: params.frame_id,
115 y: 0.0, x: 0.0,
117 total_width,
118 total_height,
119 content_x,
120 content_y: content_y_offset,
121 content_width,
122 content_height,
123 blocks,
124 tables,
125 border_width: border,
126 }
127}