@@ -19,9 +19,9 @@ import :css;
19
19
20
20
namespace Vaev ::Driver {
21
21
22
- void _paintCornerMargin (Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack, RectAu const & rect, Style::PageArea area) {
22
+ void _paintCornerMargin (Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack, RectAu const & rect, Style::PageArea area, usize& currentPage, Map<String, Vec<Layout::RunningPositionInfo>>& runningPosition ) {
23
23
Layout::Tree tree{
24
- .root = Layout::buildForPseudoElement (pageStyle.area (area)),
24
+ .root = Layout::buildForPseudoElement (pageStyle.area (area), currentPage, runningPosition ),
25
25
.viewport = Layout::Viewport{.small = rect.size ()}
26
26
};
27
27
auto [_, frag] = Layout::layoutCreateFragment (
@@ -36,10 +36,10 @@ void _paintCornerMargin(Style::PageSpecifiedValues& pageStyle, Scene::Stack& sta
36
36
Layout::paint (frag, stack);
37
37
}
38
38
39
- void _paintMainMargin (Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack, RectAu const & rect, Style::PageArea mainArea, Array<Style::PageArea, 3 > subAreas) {
40
- auto box = Layout::buildForPseudoElement (pageStyle.area (mainArea));
39
+ void _paintMainMargin (Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack, RectAu const & rect, Style::PageArea mainArea, Array<Style::PageArea, 3 > subAreas, usize& currentPage, Map<String, Vec<Layout::RunningPositionInfo>>& runningPosition ) {
40
+ auto box = Layout::buildForPseudoElement (pageStyle.area (mainArea), currentPage, runningPosition );
41
41
for (auto subArea : subAreas) {
42
- box.add (Layout::buildForPseudoElement (pageStyle.area (subArea)));
42
+ box.add (Layout::buildForPseudoElement (pageStyle.area (subArea), currentPage, runningPosition ));
43
43
}
44
44
Layout::Tree tree{
45
45
.root = std::move (box),
@@ -57,18 +57,18 @@ void _paintMainMargin(Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack
57
57
Layout::paint (frag, stack);
58
58
}
59
59
60
- void _paintMargins (Style::PageSpecifiedValues& pageStyle, RectAu pageRect, RectAu pageContent, Scene::Stack& stack) {
60
+ void _paintMargins (Style::PageSpecifiedValues& pageStyle, RectAu pageRect, RectAu pageContent, Scene::Stack& stack, usize& currentPage, Map<String, Vec<Layout::RunningPositionInfo>>& runningPosition ) {
61
61
// Compute all corner rects
62
62
auto topLeftMarginCornerRect = RectAu::fromTwoPoint (pageRect.topStart (), pageContent.topStart ());
63
63
auto topRightMarginCornerRect = RectAu::fromTwoPoint (pageRect.topEnd (), pageContent.topEnd ());
64
64
auto bottomLeftMarginCornerRect = RectAu::fromTwoPoint (pageRect.bottomStart (), pageContent.bottomStart ());
65
65
auto bottomRightMarginCornerRect = RectAu::fromTwoPoint (pageRect.bottomEnd (), pageContent.bottomEnd ());
66
66
67
67
// Paint corners
68
- _paintCornerMargin (pageStyle, stack, topLeftMarginCornerRect, Style::PageArea::TOP_LEFT_CORNER);
69
- _paintCornerMargin (pageStyle, stack, topRightMarginCornerRect, Style::PageArea::TOP_RIGHT_CORNER);
70
- _paintCornerMargin (pageStyle, stack, bottomLeftMarginCornerRect, Style::PageArea::BOTTOM_LEFT_CORNER);
71
- _paintCornerMargin (pageStyle, stack, bottomRightMarginCornerRect, Style::PageArea::BOTTOM_RIGHT_CORNER);
68
+ _paintCornerMargin (pageStyle, stack, topLeftMarginCornerRect, Style::PageArea::TOP_LEFT_CORNER, currentPage, runningPosition );
69
+ _paintCornerMargin (pageStyle, stack, topRightMarginCornerRect, Style::PageArea::TOP_RIGHT_CORNER, currentPage, runningPosition );
70
+ _paintCornerMargin (pageStyle, stack, bottomLeftMarginCornerRect, Style::PageArea::BOTTOM_LEFT_CORNER, currentPage, runningPosition );
71
+ _paintCornerMargin (pageStyle, stack, bottomRightMarginCornerRect, Style::PageArea::BOTTOM_RIGHT_CORNER, currentPage, runningPosition );
72
72
73
73
// Compute main area rects
74
74
auto topRect = RectAu::fromTwoPoint (topLeftMarginCornerRect.topEnd (), topRightMarginCornerRect.bottomStart ());
@@ -77,10 +77,10 @@ void _paintMargins(Style::PageSpecifiedValues& pageStyle, RectAu pageRect, RectA
77
77
auto rightRect = RectAu::fromTwoPoint (topRightMarginCornerRect.bottomEnd (), bottomRightMarginCornerRect.topStart ());
78
78
79
79
// Paint main areas
80
- _paintMainMargin (pageStyle, stack, topRect, Style::PageArea::TOP, {Style::PageArea::TOP_LEFT, Style::PageArea::TOP_CENTER, Style::PageArea::TOP_RIGHT});
81
- _paintMainMargin (pageStyle, stack, bottomRect, Style::PageArea::BOTTOM, {Style::PageArea::BOTTOM_LEFT, Style::PageArea::BOTTOM_CENTER, Style::PageArea::BOTTOM_RIGHT});
82
- _paintMainMargin (pageStyle, stack, leftRect, Style::PageArea::LEFT, {Style::PageArea::LEFT_TOP, Style::PageArea::LEFT_MIDDLE, Style::PageArea::LEFT_BOTTOM});
83
- _paintMainMargin (pageStyle, stack, rightRect, Style::PageArea::RIGHT, {Style::PageArea::RIGHT_TOP, Style::PageArea::RIGHT_MIDDLE, Style::PageArea::RIGHT_BOTTOM});
80
+ _paintMainMargin (pageStyle, stack, topRect, Style::PageArea::TOP, {Style::PageArea::TOP_LEFT, Style::PageArea::TOP_CENTER, Style::PageArea::TOP_RIGHT}, currentPage, runningPosition );
81
+ _paintMainMargin (pageStyle, stack, bottomRect, Style::PageArea::BOTTOM, {Style::PageArea::BOTTOM_LEFT, Style::PageArea::BOTTOM_CENTER, Style::PageArea::BOTTOM_RIGHT}, currentPage, runningPosition );
82
+ _paintMainMargin (pageStyle, stack, leftRect, Style::PageArea::LEFT, {Style::PageArea::LEFT_TOP, Style::PageArea::LEFT_MIDDLE, Style::PageArea::LEFT_BOTTOM}, currentPage, runningPosition );
83
+ _paintMainMargin (pageStyle, stack, rightRect, Style::PageArea::RIGHT, {Style::PageArea::RIGHT_TOP, Style::PageArea::RIGHT_MIDDLE, Style::PageArea::RIGHT_BOTTOM}, currentPage, runningPosition );
84
84
}
85
85
86
86
static Style::Media _constructMedia (Print::Settings const & settings) {
@@ -122,48 +122,32 @@ static Style::Media _constructMedia(Print::Settings const& settings) {
122
122
};
123
123
}
124
124
125
- export Generator<Print::Page> print (Gc::Ref<Dom::Document> dom, Print::Settings const & settings) {
126
- auto media = _constructMedia (settings);
127
-
128
- Text::FontBook fontBook;
129
- if (not fontBook.loadAll ())
130
- logWarn (" not all fonts were properly loaded into fontbook" );
131
-
132
- Style::Computer computer{
133
- media, *dom->styleSheets , fontBook
134
- };
135
- computer.build ();
136
- computer.styleDocument (*dom);
137
-
138
- // MARK: Page and Margins --------------------------------------------------
139
-
140
- Style::SpecifiedValues initialStyle = Style::SpecifiedValues::initial ();
141
- initialStyle.color = Gfx::BLACK;
142
- initialStyle.setCustomProp (" -vaev-url" , {Css::Token::string (Io::format (" \" {}\" " , dom->url ()))});
143
- initialStyle.setCustomProp (" -vaev-title" , {Css::Token::string (Io::format (" \" {}\" " , dom->title ()))});
144
- initialStyle.setCustomProp (" -vaev-datetime" , {Css::Token::string (Io::format (" \" {}\" " , Sys::now ()))});
145
-
146
- // MARK: Page Content ------------------------------------------------------
125
+ struct PageLayoutInfos {
126
+ RectAu pageRect;
127
+ Rc<Style::PageSpecifiedValues> pageStyle;
128
+ RectAu pageContent;
147
129
148
- Layout::Tree contentTree = {
149
- Layout::build (dom),
150
- };
151
- auto canvasColor = fixupBackgrounds (computer, dom, contentTree);
130
+ PageLayoutInfos (RectAu pageRect, Rc<Style::PageSpecifiedValues> pageStyle, RectAu pageContent) : pageRect{pageRect}, pageStyle{pageStyle}, pageContent{pageContent} {}
131
+ };
152
132
133
+ Pair<Vec<Layout::Breakpoint>, Vec<PageLayoutInfos>> collectBreakPointsAndRunningPositions (auto & runningPosition, Layout::Tree& contentTree, auto & media, auto & settings, auto & computer, auto & initialStyle) {
134
+ usize pageNumber = 0 ;
153
135
Layout::Breakpoint prevBreakpoint{
154
136
.endIdx = 0 ,
155
137
.advance = Layout::Breakpoint::Advance::WITHOUT_CHILDREN
156
138
};
157
139
158
- usize pageNumber = 0 ;
140
+ Vec<Layout::Breakpoint> breakpoints = {prevBreakpoint};
141
+ Vec<PageLayoutInfos> pageInfos = {};
142
+
159
143
while (true ) {
160
144
Style::Page page{
161
145
.name = " " s,
162
146
.number = pageNumber++,
163
147
.blank = false ,
164
148
};
165
149
166
- auto pageStyle = computer.computeFor (initialStyle, page);
150
+ Rc<Style::PageSpecifiedValues> pageStyle = computer.computeFor (initialStyle, page);
167
151
RectAu pageRect{
168
152
media.width / Au{media.resolution .toDppx ()},
169
153
media.height / Au{media.resolution .toDppx ()}
@@ -184,31 +168,32 @@ export Generator<Print::Page> print(Gc::Ref<Dom::Document> dom, Print::Settings
184
168
resolver.resolve (pageStyle->style ->margin ->start , pageRect.width ),
185
169
};
186
170
} else if (settings.margins == Print::Margins::CUSTOM) {
187
- pageMargin = settings.margins .custom .cast <Au>();
171
+ pageMargin = settings.margins .custom .template cast <Au>();
188
172
} else if (settings.margins == Print::Margins::MINIMUM) {
189
173
pageMargin = {};
190
174
}
191
175
192
176
RectAu pageContent = pageRect.shrink (pageMargin);
193
177
178
+ pageInfos.pushBack ({pageRect, pageStyle, pageContent});
179
+
194
180
Layout::Viewport vp{
195
181
.small = pageContent.size (),
196
182
};
197
183
198
184
contentTree.viewport = vp;
199
185
contentTree.fc = {pageContent.size ()};
200
186
201
- if (settings.headerFooter and settings.margins != Print::Margins::NONE)
202
- _paintMargins (*pageStyle, pageRect, pageContent, *pageStack);
203
-
204
187
Layout::Input pageLayoutInput{
205
188
.knownSize = {pageContent.width , NONE},
206
189
.position = pageContent.topStart (),
207
190
.availableSpace = pageContent.size (),
208
191
.containingBlock = pageContent.size (),
192
+ .page = page,
209
193
};
210
-
194
+ pageLayoutInput. runningPosition = {&runningPosition};
211
195
contentTree.fc .enterDiscovery ();
196
+
212
197
auto outDiscovery = Layout::layout (
213
198
contentTree,
214
199
pageLayoutInput.withBreakpointTraverser (Layout::BreakpointTraverser (&prevBreakpoint))
@@ -220,21 +205,79 @@ export Generator<Print::Page> print(Gc::Ref<Dom::Document> dom, Print::Settings
220
205
: outDiscovery.breakpoint .unwrap ();
221
206
222
207
contentTree.fc .leaveDiscovery ();
208
+
209
+ breakpoints.pushBack (currBreakpoint);
210
+ if (outDiscovery.completelyLaidOut )
211
+ break ;
212
+
213
+ prevBreakpoint = std::move (currBreakpoint);
214
+ }
215
+
216
+ return {breakpoints, pageInfos};
217
+ }
218
+
219
+ export Generator<Print::Page> print (Gc::Ref<Dom::Document> dom, Print::Settings const & settings) {
220
+ auto media = _constructMedia (settings);
221
+
222
+ Text::FontBook fontBook;
223
+ if (not fontBook.loadAll ())
224
+ logWarn (" not all fonts were properly loaded into fontbook" );
225
+
226
+ Style::Computer computer{
227
+ media, *dom->styleSheets , fontBook
228
+ };
229
+ computer.build ();
230
+ computer.styleDocument (*dom);
231
+
232
+ // MARK: Page and Margins --------------------------------------------------
233
+
234
+ Style::SpecifiedValues initialStyle = Style::SpecifiedValues::initial ();
235
+ initialStyle.color = Gfx::BLACK;
236
+ initialStyle.setCustomProp (" -vaev-url" , {Css::Token::string (Io::format (" \" {}\" " , dom->url ()))});
237
+ initialStyle.setCustomProp (" -vaev-title" , {Css::Token::string (Io::format (" \" {}\" " , dom->title ()))});
238
+ initialStyle.setCustomProp (" -vaev-datetime" , {Css::Token::string (Io::format (" \" {}\" " , Sys::now ()))});
239
+
240
+ // MARK: Page Content ------------------------------------------------------
241
+
242
+ Layout::Tree contentTree = {
243
+ Layout::build (dom),
244
+ };
245
+ auto canvasColor = fixupBackgrounds (computer, dom, contentTree);
246
+
247
+ Map<String, Vec<Layout::RunningPositionInfo>> runningPosition = {}; // Mapping the different Running positions to their respective names and their page.
248
+
249
+ auto [breakpoints, pageInfos] = collectBreakPointsAndRunningPositions (runningPosition, contentTree, media, settings, computer, initialStyle);
250
+
251
+ for (usize pageNumber = 0 ; pageNumber < breakpoints.len () - 1 ; pageNumber++) {
252
+ Style::Page page{
253
+ .name = " " s,
254
+ .number = pageNumber,
255
+ .blank = false ,
256
+ };
257
+
258
+ auto pageStack = makeRc<Scene::Stack>();
259
+
260
+ Layout::Input pageLayoutInput{
261
+ .knownSize = {pageInfos[pageNumber].pageContent .width , NONE},
262
+ .position = pageInfos[pageNumber].pageContent .topStart (),
263
+ .availableSpace = pageInfos[pageNumber].pageContent .size (),
264
+ .containingBlock = pageInfos[pageNumber].pageContent .size (),
265
+ .page = page,
266
+ };
267
+
223
268
auto [outFragmentation, fragment] = Layout::layoutCreateFragment (
224
269
contentTree,
225
270
pageLayoutInput
226
- .withBreakpointTraverser (Layout::BreakpointTraverser (&prevBreakpoint , &currBreakpoint ))
271
+ .withBreakpointTraverser (Layout::BreakpointTraverser (&breakpoints[pageNumber] , &breakpoints[pageNumber + 1 ] ))
227
272
);
228
273
274
+ if (settings.headerFooter and settings.margins != Print::Margins::NONE)
275
+ _paintMargins (*pageInfos[pageNumber].pageStyle , pageInfos[pageNumber].pageRect , pageInfos[pageNumber].pageContent , *pageStack, page.number , runningPosition);
276
+
229
277
Layout::paint (fragment, *pageStack);
230
278
pageStack->prepare ();
231
279
232
280
co_yield Print::Page (settings.paper , makeRc<Scene::Clear>(makeRc<Scene::Transform>(pageStack, Math::Trans2f::scale (media.resolution .toDppx ())), canvasColor));
233
-
234
- if (outFragmentation.completelyLaidOut )
235
- break ;
236
-
237
- prevBreakpoint = std::move (currBreakpoint);
238
281
}
239
282
}
240
283
0 commit comments