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)]
8pub enum FramePosition {
9 #[default]
11 Inline,
12 FloatLeft,
14 FloatRight,
16 Absolute,
18}
19
20pub struct FrameLayoutParams {
22 pub frame_id: usize,
23 pub position: FramePosition,
24 pub width: Option<f32>,
26 pub height: Option<f32>,
28 pub margin_top: f32,
29 pub margin_bottom: f32,
30 pub margin_left: f32,
31 pub margin_right: f32,
32 pub padding: f32,
33 pub border_width: f32,
34 pub blocks: Vec<BlockLayoutParams>,
36 pub tables: Vec<(usize, TableLayoutParams)>, }
38
39pub struct FrameLayout {
41 pub frame_id: usize,
42 pub y: f32,
43 pub x: f32,
44 pub total_width: f32,
45 pub total_height: f32,
46 pub content_x: f32,
47 pub content_y: f32,
48 pub content_width: f32,
49 pub content_height: f32,
50 pub blocks: Vec<BlockLayout>,
51 pub tables: Vec<TableLayout>,
52 pub border_width: f32,
53}
54
55pub fn layout_frame(
57 registry: &FontRegistry,
58 params: &FrameLayoutParams,
59 available_width: f32,
60) -> FrameLayout {
61 let border = params.border_width;
62 let pad = params.padding;
63 let frame_width = params.width.unwrap_or(available_width);
64 let content_width =
65 (frame_width - border * 2.0 - pad * 2.0 - params.margin_left - params.margin_right)
66 .max(0.0);
67
68 let mut blocks = Vec::new();
70 let mut content_y = 0.0f32;
71
72 for block_params in ¶ms.blocks {
73 let mut block = layout_block(registry, block_params, content_width);
74 block.y = content_y + block.top_margin;
75 let block_content = block.height - block.top_margin - block.bottom_margin;
76 content_y = block.y + block_content + block.bottom_margin;
77 blocks.push(block);
78 }
79
80 let mut tables = Vec::new();
82 for (_flow_idx, table_params) in ¶ms.tables {
83 let mut table = layout_table(registry, table_params, content_width);
84 table.y = content_y;
85 content_y += table.total_height;
86 tables.push(table);
87 }
88
89 let auto_content_height = content_y;
90 let content_height = params
91 .height
92 .map(|h| (h - border * 2.0 - pad * 2.0).max(0.0))
93 .unwrap_or(auto_content_height);
94
95 let total_height =
96 params.margin_top + border + pad + content_height + pad + border + params.margin_bottom;
97 let total_width =
98 params.margin_left + border + pad + content_width + pad + border + params.margin_right;
99
100 let content_x = params.margin_left + border + pad;
101 let content_y_offset = params.margin_top + border + pad;
102
103 FrameLayout {
104 frame_id: params.frame_id,
105 y: 0.0, x: 0.0,
107 total_width,
108 total_height,
109 content_x,
110 content_y: content_y_offset,
111 content_width,
112 content_height,
113 blocks,
114 tables,
115 border_width: border,
116 }
117}