1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Paged media layout primitives.
//!
//! Provides the [`FragmentationContext`] that the layout solver threads through to
//! distinguish continuous (screen) from paged (print) media.
//!
//! For continuous media (screens), content flows into a single infinitely tall
//! container. For paged media (print), content is laid out on a continuous canvas
//! and afterwards sliced into fixed-size pages by the display-list slicer
//! (`paginate_display_list_with_slicer_and_breaks` in `azul_layout::solver3::display_list`).
//! This lets the layout engine make break decisions while respecting CSS properties
//! like `break-before`, `break-after`, and `break-inside`.
//!
//! Page *decoration* (headers, footers, margin boxes, counters) lives in
//! `azul_layout::solver3::pagination`.
use crate::geom::LogicalSize;
/// Selects how content is fragmented during layout.
///
/// This is the core abstraction for fragmentation support:
/// - Screen rendering: [`Continuous`](Self::Continuous) — a single infinite container.
/// - Print rendering: [`Paged`](Self::Paged) — a series of fixed-size page containers.
#[derive(Debug, Clone, Copy)]
pub enum FragmentationContext {
/// Continuous media (screen): a single, infinitely tall container.
///
/// Used for normal screen rendering where content can scroll indefinitely;
/// breaks are never forced.
Continuous {
/// Width of the viewport.
width: f32,
},
/// Paged media (print): fixed-size pages.
///
/// Used for PDF generation and print preview. Content flows from one page to
/// the next when a page is full.
Paged {
/// Size of each page.
page_size: LogicalSize,
},
}
impl FragmentationContext {
/// Create a continuous fragmentation context for screen rendering.
#[must_use]
pub const fn new_continuous(width: f32) -> Self {
Self::Continuous { width }
}
/// Create a paged fragmentation context for print rendering.
#[must_use]
pub const fn new_paged(page_size: LogicalSize) -> Self {
Self::Paged { page_size }
}
/// Get the page content height (page height for paged media).
///
/// For continuous media, returns `f32::MAX`.
#[must_use]
pub const fn page_content_height(&self) -> f32 {
match self {
Self::Continuous { .. } => f32::MAX,
Self::Paged { page_size, .. } => page_size.height,
}
}
/// Check if this is paged media.
#[must_use]
pub const fn is_paged(&self) -> bool {
matches!(self, Self::Paged { .. })
}
}
/// Page margins in points.
///
/// Canonical paged-media margin type (formerly defined in the now-removed
/// `crate::fragmentation` module). Re-exported from the crate root as
/// `azul_layout::PageMargins`.
#[derive(Debug, Clone, Copy, Default, PartialEq)]
#[repr(C)] // crosses the C API in `PageSetup` (9g-ii-f-i)
pub struct PageMargins {
pub top: f32,
pub right: f32,
pub bottom: f32,
pub left: f32,
}
impl PageMargins {
#[must_use]
pub const fn new(top: f32, right: f32, bottom: f32, left: f32) -> Self {
Self {
top,
right,
bottom,
left,
}
}
#[must_use]
pub const fn uniform(margin: f32) -> Self {
Self {
top: margin,
right: margin,
bottom: margin,
left: margin,
}
}
#[must_use]
pub fn horizontal(&self) -> f32 {
self.left + self.right
}
#[must_use]
pub fn vertical(&self) -> f32 {
self.top + self.bottom
}
}
#[cfg(test)]
#[path = "paged_test.rs"]
mod paged_test;