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
124
125
126
127
128
129
//! Page-based timing model.
//!
//! The default scene timing — [`SceneDuration::Finite`] /
//! [`SceneDuration::Indefinite`] — is **timeline-based**: every event
//! lives on a continuous millisecond (or `time_base`-tick) axis, and
//! the renderer samples that axis at the scene's framerate.
//!
//! That model is the right shape for the streaming compositor and
//! the NLE timeline, but it's the wrong shape for paged content
//! (PDF, multi-page TIFF, EPUB-style flowed documents). A PDF is not
//! "the page-1 layout from t=0 to t=33ms, the page-2 layout from
//! t=33ms to t=66ms"; a PDF is a sequence of independently-sized
//! page surfaces with no temporal relationship between them.
//!
//! [`Page`] models that. A [`Scene`] carries a `pages: Option<Vec<Page>>`
//! field — `Some(...)` for paged content, `None` for time-based.
//! The two are mutually exclusive at render dispatch:
//!
//! - PDF / multi-page TIFF writers accept only `Some(pages)`.
//! - PNG / MP4 / video writers accept only `None` (timeline mode).
//! - SVG is single-page; it accepts either (single page → render
//! that page, timeline → render the frame at `t=0`).
//!
//! [`Scene::pages_to_timeline`] / [`Scene::timeline_to_pages`] adapt
//! between the two when the consumer needs to bridge.
//!
//! [`SceneDuration::Finite`]: crate::duration::SceneDuration::Finite
//! [`SceneDuration::Indefinite`]: crate::duration::SceneDuration::Indefinite
//! [`Scene`]: crate::scene::Scene
//! [`Scene::pages_to_timeline`]: crate::scene::Scene::pages_to_timeline
//! [`Scene::timeline_to_pages`]: crate::scene::Scene::timeline_to_pages
use ;
/// One page of paged content.
///
/// The content is an [`oxideav_core::VectorFrame`] — every page is
/// a self-contained vector composition. This is the natural shape
/// for PDF (a PDF page IS a vector composition), and rasterisable
/// via `oxideav_raster::Renderer` for raster-target writers (page
/// preview thumbnails, `pages_to_timeline()` adaptation).
///
/// Width / height are per-page because PDF, multi-page TIFF, and
/// EPUB all support varying page sizes within a single document
/// (cover spread + body pages, mixed portrait / landscape, etc).
/// Units match the scene's [`Canvas::Vector`] unit if the canvas
/// is vector; for raster canvases the values are in canvas pixels.
///
/// [`Canvas::Vector`]: crate::object::Canvas::Vector
/// Build an empty [`VectorFrame`] sized to `(width, height)` in the
/// page's own coordinate system. Used by both [`Page::default`] and
/// [`Page::new`].