From 0f77ad45b3bca28b6d9430672d1d21300d3fd207 Mon Sep 17 00:00:00 2001 From: sleepy-monax Date: Tue, 21 Oct 2025 14:08:59 +0200 Subject: [PATCH] (wip) vaev-driver: Pagination rework. --- src/vaev-engine/dom/window.cpp | 12 +- src/vaev-engine/driver/print.cpp | 445 ++++++++++-------- src/vaev-engine/driver/render.cpp | 10 +- src/vaev-engine/layout/base/breaks.cpp | 23 +- src/vaev-engine/layout/base/input.cpp | 4 +- .../layout/base/running-position.cpp | 6 +- src/vaev-engine/layout/block.cpp | 2 +- src/vaev-engine/layout/builder/mod.cpp | 2 +- src/vaev-engine/layout/flex.cpp | 2 +- src/vaev-engine/layout/inline.cpp | 2 +- src/vaev-engine/layout/positioned.cpp | 2 +- src/vaev-engine/style/computer.cpp | 12 +- 12 files changed, 288 insertions(+), 234 deletions(-) diff --git a/src/vaev-engine/dom/window.cpp b/src/vaev-engine/dom/window.cpp index 47697317..8e3336c8 100644 --- a/src/vaev-engine/dom/window.cpp +++ b/src/vaev-engine/dom/window.cpp @@ -82,7 +82,11 @@ export struct Window { Font::Database db; if (not db.loadSystemFonts()) logWarn("not all fonts were properly loaded into database"); - Style::Computer computer{_media, *_document->styleSheets, db}; + Style::Computer computer{ + _media, + *_document->styleSheets, + std::move(db), + }; computer.build(); computer.styleDocument(*_document); } @@ -96,8 +100,10 @@ export struct Window { } [[clang::coro_wrapper]] - Generator print(Print::Settings const& settings) const { - return Driver::print(_document.upgrade(), settings); + Generator print(Print::Settings const& settings) { + auto context = Driver::PaginationContext::create(*_document, settings); + for (auto p : context.iterPages()) + co_yield p; } }; diff --git a/src/vaev-engine/driver/print.cpp b/src/vaev-engine/driver/print.cpp index f82e848b..7779453e 100644 --- a/src/vaev-engine/driver/print.cpp +++ b/src/vaev-engine/driver/print.cpp @@ -20,243 +20,274 @@ using namespace Karm; namespace Vaev::Driver { -void _paintCornerMargin(Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack, RectAu const& rect, Style::PageArea area, usize currentPage, Layout::RunningPositionMap& runningPosition) { - Layout::Tree tree{ - .root = Layout::buildForPseudoElement(pageStyle.area(area), currentPage, runningPosition), - .viewport = Layout::Viewport{.small = rect.size()} - }; - auto [_, frag] = Layout::layoutCreateFragment( - tree, - { - .knownSize = rect.size().cast>(), - .position = rect.topStart(), - .availableSpace = rect.size(), - .containingBlock = rect.size(), - } - ); - Layout::paint(frag, stack); -} - -void _paintMainMargin(Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack, RectAu const& rect, Style::PageArea mainArea, Array subAreas, usize currentPage, Layout::RunningPositionMap& runningPosition) { - auto box = Layout::buildForPseudoElement(pageStyle.area(mainArea), currentPage, runningPosition); - for (auto subArea : subAreas) { - box.add(Layout::buildForPseudoElement(pageStyle.area(subArea), currentPage, runningPosition)); - } - Layout::Tree tree{ - .root = std::move(box), - .viewport = Layout::Viewport{.small = rect.size()} - }; - auto [_, frag] = Layout::layoutCreateFragment( - tree, - { - .knownSize = rect.size().cast>(), - .position = rect.topStart(), - .availableSpace = rect.size(), - .containingBlock = rect.size(), - } - ); - Layout::paint(frag, stack); -} - -void _paintMargins(Style::PageSpecifiedValues& pageStyle, RectAu pageRect, RectAu pageContent, Scene::Stack& stack, usize currentPage, Layout::RunningPositionMap& runningPosition) { - // Compute all corner rects - auto topLeftMarginCornerRect = RectAu::fromTwoPoint(pageRect.topStart(), pageContent.topStart()); - auto topRightMarginCornerRect = RectAu::fromTwoPoint(pageRect.topEnd(), pageContent.topEnd()); - auto bottomLeftMarginCornerRect = RectAu::fromTwoPoint(pageRect.bottomStart(), pageContent.bottomStart()); - auto bottomRightMarginCornerRect = RectAu::fromTwoPoint(pageRect.bottomEnd(), pageContent.bottomEnd()); - - // Paint corners - _paintCornerMargin(pageStyle, stack, topLeftMarginCornerRect, Style::PageArea::TOP_LEFT_CORNER, currentPage, runningPosition); - _paintCornerMargin(pageStyle, stack, topRightMarginCornerRect, Style::PageArea::TOP_RIGHT_CORNER, currentPage, runningPosition); - _paintCornerMargin(pageStyle, stack, bottomLeftMarginCornerRect, Style::PageArea::BOTTOM_LEFT_CORNER, currentPage, runningPosition); - _paintCornerMargin(pageStyle, stack, bottomRightMarginCornerRect, Style::PageArea::BOTTOM_RIGHT_CORNER, currentPage, runningPosition); - - // Compute main area rects - auto topRect = RectAu::fromTwoPoint(topLeftMarginCornerRect.topEnd(), topRightMarginCornerRect.bottomStart()); - auto bottomRect = RectAu::fromTwoPoint(bottomLeftMarginCornerRect.topEnd(), bottomRightMarginCornerRect.bottomStart()); - auto leftRect = RectAu::fromTwoPoint(topLeftMarginCornerRect.bottomEnd(), bottomLeftMarginCornerRect.topStart()); - auto rightRect = RectAu::fromTwoPoint(topRightMarginCornerRect.bottomEnd(), bottomRightMarginCornerRect.topStart()); - - // Paint main areas - _paintMainMargin(pageStyle, stack, topRect, Style::PageArea::TOP, {Style::PageArea::TOP_LEFT, Style::PageArea::TOP_CENTER, Style::PageArea::TOP_RIGHT}, currentPage, runningPosition); - _paintMainMargin(pageStyle, stack, bottomRect, Style::PageArea::BOTTOM, {Style::PageArea::BOTTOM_LEFT, Style::PageArea::BOTTOM_CENTER, Style::PageArea::BOTTOM_RIGHT}, currentPage, runningPosition); - _paintMainMargin(pageStyle, stack, leftRect, Style::PageArea::LEFT, {Style::PageArea::LEFT_TOP, Style::PageArea::LEFT_MIDDLE, Style::PageArea::LEFT_BOTTOM}, currentPage, runningPosition); - _paintMainMargin(pageStyle, stack, rightRect, Style::PageArea::RIGHT, {Style::PageArea::RIGHT_TOP, Style::PageArea::RIGHT_MIDDLE, Style::PageArea::RIGHT_BOTTOM}, currentPage, runningPosition); -} - -struct PaginationContext { - Layout::Tree& contentTree; - Style::Media& media; - Print::Settings const& settings; - Style::Computer& computer; - Style::SpecifiedValues& initialStyle; -}; - -struct PageLayoutInfos { - RectAu pageRect; - RectAu pageContent; - Rc pageStyle; +struct Page { + Rc style; + usize index = 0; + RectAu borderBox = {}; + RectAu contentBox = {}; + Layout::Frag fragment = {}; + Opt> canvas = {}; + Layout::Breakpoint breakpoint = {}; }; -Pair, Vec> collectBreakPointsAndRunningPositions(Layout::RunningPositionMap& runningPosition, PaginationContext& context) { - usize pageNumber = 0; - Layout::Breakpoint prevBreakpoint{ - .endIdx = 0, - .advance = Layout::Breakpoint::Advance::WITHOUT_CHILDREN - }; - - Vec breakpoints = {prevBreakpoint}; - Vec pageInfos = {}; - - while (true) { - Style::Page page{ - .name = ""s, - .number = pageNumber++, - .blank = false, +export struct PaginationContext { + Layout::Tree _tree; + Style::Media _media; + Print::Settings _settings; + Style::Computer _computer; + Style::SpecifiedValues _style; + Layout::Runnings _runnings = {}; + Vec _pages = {}; + + static PaginationContext create(Gc::Ref dom, Print::Settings const& settings) { + auto media = Style::Media::forPrint(settings); + Font::Database database; + if (not database.loadSystemFonts()) + logWarn("not all fonts were properly loaded into database"); + Style::Computer computer{ + media, *dom->styleSheets, std::move(database) }; - - Rc pageStyle = context.computer.computeFor(context.initialStyle, page); - RectAu pageRect{ - context.media.width / Au{context.media.resolution.toDppx()}, - context.media.height / Au{context.media.resolution.toDppx()} + computer.build(); + computer.styleDocument(*dom); + + Style::SpecifiedValues initialStyle = Style::SpecifiedValues::initial(); + initialStyle.color = Gfx::BLACK; + initialStyle.setCustomProp("-vaev-url", {Css::Token::string(Io::format("\"{}\"", dom->url()))}); + initialStyle.setCustomProp("-vaev-title", {Css::Token::string(Io::format("\"{}\"", dom->title()))}); + initialStyle.setCustomProp("-vaev-datetime", {Css::Token::string(Io::format("\"{}\"", Sys::now()))}); + + return { + ._tree = {Layout::build(dom)}, + ._media = media, + ._settings = settings, + ._computer = std::move(computer), + ._style = initialStyle, }; + } - auto pageSize = pageRect.size().cast(); - - auto pageStack = makeRc(); + // MARK: Page Creation --------------------------------------------------------- - InsetsAu pageMargin; + InsetsAu _resolvePageMargins(Page& page) { + InsetsAu margins; - if (context.settings.margins == Print::Margins::DEFAULT) { + if (_settings.margins == Print::Margins::DEFAULT) { Layout::Resolver resolver{}; - pageMargin = { - resolver.resolve(pageStyle->style->margin->top, pageRect.height), - resolver.resolve(pageStyle->style->margin->end, pageRect.width), - resolver.resolve(pageStyle->style->margin->bottom, pageRect.height), - resolver.resolve(pageStyle->style->margin->start, pageRect.width), + margins = { + resolver.resolve(page.style->style->margin->top, page.borderBox.height), + resolver.resolve(page.style->style->margin->end, page.borderBox.width), + resolver.resolve(page.style->style->margin->bottom, page.borderBox.height), + resolver.resolve(page.style->style->margin->start, page.borderBox.width), }; - } else if (context.settings.margins == Print::Margins::CUSTOM) { - pageMargin = context.settings.margins.custom.template cast(); - } else if (context.settings.margins == Print::Margins::MINIMUM) { - pageMargin = {}; + } else if (_settings.margins == Print::Margins::CUSTOM) { + margins = _settings.margins.custom.cast(); + } else if (_settings.margins == Print::Margins::MINIMUM) { + margins = {}; } - RectAu pageContent = pageRect.shrink(pageMargin); - - pageInfos.pushBack({pageRect, pageContent, pageStyle}); + return margins; + } - Layout::Viewport vp{ - .small = pageContent.size(), + Page _createPage(usize index) { + Page page = { + _computer.computeFor( + _style, + { + .name = ""s, + .number = index, + .blank = false, + } + ) }; - context.contentTree.viewport = vp; - context.contentTree.fc = {pageContent.size()}; - - Layout::Input pageLayoutInput{ - .knownSize = {pageContent.width, NONE}, - .position = pageContent.topStart(), - .availableSpace = pageContent.size(), - .containingBlock = pageContent.size(), - .pageNumber = pageNumber, + page.borderBox = { + _media.width / Au{_media.resolution.toDppx()}, + _media.height / Au{_media.resolution.toDppx()} }; - pageLayoutInput.runningPosition = {&runningPosition}; - context.contentTree.fc.enterDiscovery(); - auto outDiscovery = Layout::layout( - context.contentTree, - pageLayoutInput.withBreakpointTraverser(Layout::BreakpointTraverser(&prevBreakpoint)) + auto size = page.borderBox.size().cast(); + auto margins = _resolvePageMargins(page); + page.contentBox = page.borderBox.shrink(margins); + return page; + } + + // MARK: Page Breaking --------------------------------------------------------- + + Pair _pageBreak(Page& page, Cursor previousBreakpoint) { + Layout::Viewport vp{.small = page.contentBox.size()}; + + _tree.viewport = vp; + _tree.fc = {page.contentBox.size()}; + + _tree.fc.enterDiscovery(); + + auto output = Layout::layout( + _tree, + { + .knownSize = {page.contentBox.width, NONE}, + .position = page.contentBox.topStart(), + .availableSpace = page.contentBox.size(), + .containingBlock = page.contentBox.size(), + .runningPosition = &_runnings, + .pageIndex = page.index, + .breakpointTraverser = { + previousBreakpoint + }, + } ); - Layout::Breakpoint currBreakpoint = - outDiscovery.completelyLaidOut - ? Layout::Breakpoint::classB(1, false) - : outDiscovery.breakpoint.unwrap(); + _tree.fc.leaveDiscovery(); - context.contentTree.fc.leaveDiscovery(); + return {output.completelyLaidOut, output.breakpoint.unwrap()}; + } - breakpoints.pushBack(currBreakpoint); - if (outDiscovery.completelyLaidOut) - break; + void _splitPages() { + usize pageNumber = 0; - prevBreakpoint = std::move(currBreakpoint); + while (true) { + auto page = _createPage(pageNumber++); + Cursor previousBreakpoint = + _pages ? &last(_pages).breakpoint + : &Layout::Breakpoint::START_OF_DOCUMENT; + + auto [done, breakpoint] = _pageBreak(page, previousBreakpoint); + page.breakpoint = std::move(breakpoint); + _pages.pushBack(page); + if (done) + break; + } } - return {breakpoints, pageInfos}; -} - -export Generator print(Gc::Ref dom, Print::Settings const& settings) { - auto media = Style::Media::forPrint(settings); - - Font::Database db; - if (not db.loadSystemFonts()) - logWarn("not all fonts were properly loaded into database"); - - Style::Computer computer{ - media, *dom->styleSheets, db - }; - computer.build(); - computer.styleDocument(*dom); - - // MARK: Page and Margins -------------------------------------------------- - - Style::SpecifiedValues initialStyle = Style::SpecifiedValues::initial(); - initialStyle.color = Gfx::BLACK; - initialStyle.setCustomProp("-vaev-url", {Css::Token::string(Io::format("\"{}\"", dom->url()))}); - initialStyle.setCustomProp("-vaev-title", {Css::Token::string(Io::format("\"{}\"", dom->title()))}); - initialStyle.setCustomProp("-vaev-datetime", {Css::Token::string(Io::format("\"{}\"", Sys::now()))}); - - // MARK: Page Content ------------------------------------------------------ - - Layout::Tree contentTree = { - Layout::build(dom), - }; - - Layout::RunningPositionMap runningPosition = {}; // Mapping the different Running positions to their respective names and their page. - PaginationContext paginationContext{ - .contentTree = contentTree, - .media = media, - .settings = settings, - .computer = computer, - .initialStyle = initialStyle, - }; - auto [breakpoints, pageInfos] = collectBreakPointsAndRunningPositions(runningPosition, paginationContext); - - for (usize pageNumber = 0; pageNumber < breakpoints.len() - 1; pageNumber++) { - Style::Page page{ - .name = ""s, - .number = pageNumber, - .blank = false, + // MARK: Page Painting --------------------------------------------------------- + + void _paintCornerMargin(Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack, RectAu const& rect, Style::PageArea area, usize currentPage, Layout::Runnings& runningPosition) { + Layout::Tree tree{ + .root = Layout::buildForPseudoElement(pageStyle.area(area), currentPage, runningPosition), + .viewport = Layout::Viewport{.small = rect.size()} }; - auto pageStack = makeRc(); - - auto infos = pageInfos[pageNumber]; - Layout::Input pageLayoutInput{ - .knownSize = {infos.pageContent.width, NONE}, - .position = infos.pageContent.topStart(), - .availableSpace = infos.pageContent.size(), - .containingBlock = infos.pageContent.size(), - .pageNumber = pageNumber, + auto [_, frag] = Layout::layoutCreateFragment( + tree, + { + .knownSize = rect.size().cast>(), + .position = rect.topStart(), + .availableSpace = rect.size(), + .containingBlock = rect.size(), + } + ); + Layout::paint(frag, stack); + } + + void _paintMainMargin(Style::PageSpecifiedValues& pageStyle, Scene::Stack& stack, RectAu const& rect, Style::PageArea mainArea, Array subAreas, usize currentPage, Layout::Runnings& runningPosition) { + auto box = Layout::buildForPseudoElement(pageStyle.area(mainArea), currentPage, runningPosition); + for (auto subArea : subAreas) { + box.add(Layout::buildForPseudoElement(pageStyle.area(subArea), currentPage, runningPosition)); + } + Layout::Tree tree{ + .root = std::move(box), + .viewport = Layout::Viewport{.small = rect.size()} }; - auto [outFragmentation, fragment] = Layout::layoutCreateFragment( - contentTree, - pageLayoutInput - .withBreakpointTraverser(Layout::BreakpointTraverser(&breakpoints[pageNumber], &breakpoints[pageNumber + 1])) + auto [_, frag] = Layout::layoutCreateFragment( + tree, + { + .knownSize = rect.size().cast>(), + .position = rect.topStart(), + .availableSpace = rect.size(), + .containingBlock = rect.size(), + } ); + Layout::paint(frag, stack); + } - if (settings.headerFooter and settings.margins != Print::Margins::NONE) - _paintMargins(*pageInfos[pageNumber].pageStyle, pageInfos[pageNumber].pageRect, pageInfos[pageNumber].pageContent, *pageStack, page.number, runningPosition); + void _paintMargins(Page& page, Scene::Stack& stack, Layout::Runnings& runningPosition) { + // Compute all corner rects + auto topLeftMarginCornerRect = RectAu::fromTwoPoint(page.borderBox.topStart(), page.contentBox.topStart()); + auto topRightMarginCornerRect = RectAu::fromTwoPoint(page.borderBox.topEnd(), page.contentBox.topEnd()); + auto bottomLeftMarginCornerRect = RectAu::fromTwoPoint(page.borderBox.bottomStart(), page.contentBox.bottomStart()); + auto bottomRightMarginCornerRect = RectAu::fromTwoPoint(page.borderBox.bottomEnd(), page.contentBox.bottomEnd()); + + // Paint corners + _paintCornerMargin(*page.style, stack, topLeftMarginCornerRect, Style::PageArea::TOP_LEFT_CORNER, page.index, runningPosition); + _paintCornerMargin(*page.style, stack, topRightMarginCornerRect, Style::PageArea::TOP_RIGHT_CORNER, page.index, runningPosition); + _paintCornerMargin(*page.style, stack, bottomLeftMarginCornerRect, Style::PageArea::BOTTOM_LEFT_CORNER, page.index, runningPosition); + _paintCornerMargin(*page.style, stack, bottomRightMarginCornerRect, Style::PageArea::BOTTOM_RIGHT_CORNER, page.index, runningPosition); + + // Compute main area rects + auto topRect = RectAu::fromTwoPoint(topLeftMarginCornerRect.topEnd(), topRightMarginCornerRect.bottomStart()); + auto bottomRect = RectAu::fromTwoPoint(bottomLeftMarginCornerRect.topEnd(), bottomRightMarginCornerRect.bottomStart()); + auto leftRect = RectAu::fromTwoPoint(topLeftMarginCornerRect.bottomEnd(), bottomLeftMarginCornerRect.topStart()); + auto rightRect = RectAu::fromTwoPoint(topRightMarginCornerRect.bottomEnd(), bottomRightMarginCornerRect.topStart()); + + // Paint main areas + _paintMainMargin(*page.style, stack, topRect, Style::PageArea::TOP, {Style::PageArea::TOP_LEFT, Style::PageArea::TOP_CENTER, Style::PageArea::TOP_RIGHT}, page.index, runningPosition); + _paintMainMargin(*page.style, stack, bottomRect, Style::PageArea::BOTTOM, {Style::PageArea::BOTTOM_LEFT, Style::PageArea::BOTTOM_CENTER, Style::PageArea::BOTTOM_RIGHT}, page.index, runningPosition); + _paintMainMargin(*page.style, stack, leftRect, Style::PageArea::LEFT, {Style::PageArea::LEFT_TOP, Style::PageArea::LEFT_MIDDLE, Style::PageArea::LEFT_BOTTOM}, page.index, runningPosition); + _paintMainMargin(*page.style, stack, rightRect, Style::PageArea::RIGHT, {Style::PageArea::RIGHT_TOP, Style::PageArea::RIGHT_MIDDLE, Style::PageArea::RIGHT_BOTTOM}, page.index, runningPosition); + } - Layout::paint(fragment, *pageStack); - pageStack->prepare(); + // https://drafts.csswg.org/css-page/#painting + Rc _paintPage(Page& page, Layout::Frag& fragment) { + auto pageCanvas = makeRc(); - co_yield Print::Page( - settings.paper, - makeRc( - pageStack, - Math::Trans2f::scale(media.resolution.toDppx()) - ) + // When drawing a page of content, the page layers are painted in + // the following painting order (bottommost first): + + // 1. Page background + // TODO + + // 2. document canvas + // TODO + + // 3. page borders + // TODO + + // 4. document contents + Layout::paint(fragment, *pageCanvas); + + // 5. page-margin boxes + if (_settings.headerFooter and _settings.margins != Print::Margins::NONE) + _paintMargins(page, *pageCanvas, _runnings); + + pageCanvas->prepare(); + return makeRc( + pageCanvas, + Math::Trans2f::scale(_media.resolution.toDppx()) ); } -} + + // MARK: Page Rendering ---------------------------------------------------- + + Generator _renderPages() { + for (auto& page : _pages) { + auto [_, fragment] = Layout::layoutCreateFragment( + _tree, + { + .knownSize = {page.contentBox.width, NONE}, + .position = page.contentBox.topStart(), + .availableSpace = page.contentBox.size(), + .containingBlock = page.contentBox.size(), + .pageIndex = page.index, + .breakpointTraverser = { + page.index + ? &_pages[page.index - 1].breakpoint + : &Layout::Breakpoint::START_OF_DOCUMENT, + &page.breakpoint, + }, + } + ); + + page.fragment = std::move(fragment); + + co_yield Print::Page( + _settings.paper, + _paintPage(page, fragment) + ); + } + } + + [[clang::coro_wrapper]] + Generator iterPages() { + _splitPages(); + return _renderPages(); + } +}; } // namespace Vaev::Driver diff --git a/src/vaev-engine/driver/render.cpp b/src/vaev-engine/driver/render.cpp index 85be179a..fadf7ac7 100644 --- a/src/vaev-engine/driver/render.cpp +++ b/src/vaev-engine/driver/render.cpp @@ -21,11 +21,15 @@ export struct RenderResult { }; export RenderResult render(Gc::Ref dom, Style::Media const& media, Layout::Viewport viewport) { - Font::Database db; - if (not db.loadSystemFonts()) + Font::Database database; + if (not database.loadSystemFonts()) logWarn("not all fonts were properly loaded into database"); - Style::Computer computer{media, *dom->styleSheets, db}; + Style::Computer computer{ + media, + *dom->styleSheets, + std::move(database), + }; computer.build(); computer.styleDocument(*dom); diff --git a/src/vaev-engine/layout/base/breaks.cpp b/src/vaev-engine/layout/base/breaks.cpp index 417b6067..57b5af72 100644 --- a/src/vaev-engine/layout/base/breaks.cpp +++ b/src/vaev-engine/layout/base/breaks.cpp @@ -82,6 +82,9 @@ export struct Breakpoint { Vec> children = {}; Advance advance; + static Breakpoint const START_OF_DOCUMENT; + static Breakpoint const END_OF_DOCUMENT; + static Breakpoint forced(usize endIdx) { return { .endIdx = endIdx, @@ -171,19 +174,29 @@ export struct Breakpoint { } }; +Breakpoint const Breakpoint::START_OF_DOCUMENT = { + .endIdx = 0, + .advance = Advance::WITHOUT_CHILDREN +}; + +Breakpoint const Breakpoint::END_OF_DOCUMENT = { + .endIdx = 1, + .advance = Advance::WITHOUT_CHILDREN +}; + export struct BreakpointTraverser { - MutCursor prevIteration, currIteration; + Cursor prevIteration, currIteration; BreakpointTraverser( - MutCursor prev = nullptr, - MutCursor curr = nullptr + Cursor prev = nullptr, + Cursor curr = nullptr ) : prevIteration(prev), currIteration(curr) {} bool isDeactivated() { return prevIteration == nullptr and currIteration == nullptr; } - MutCursor traversePrev(usize i, usize j) { + Cursor traversePrev(usize i, usize j) { if (prevIteration and prevIteration->children.len() > 0 and (i + 1 == prevIteration->endIdx or (prevIteration->advance == Breakpoint::Advance::WITH_CHILDREN and i == prevIteration->endIdx))) { @@ -193,7 +206,7 @@ export struct BreakpointTraverser { return nullptr; } - MutCursor traverseCurr(usize i, usize j) { + Cursor traverseCurr(usize i, usize j) { if (currIteration and currIteration->children.len() > 0 and i + 1 == currIteration->endIdx) { if (currIteration->children[j]) return &currIteration->children[j].unwrap(); diff --git a/src/vaev-engine/layout/base/input.cpp b/src/vaev-engine/layout/base/input.cpp index bf6c441d..a68445f7 100644 --- a/src/vaev-engine/layout/base/input.cpp +++ b/src/vaev-engine/layout/base/input.cpp @@ -26,8 +26,8 @@ export struct Input { Vec2Au position = {}; Vec2Au availableSpace = {}; Vec2Au containingBlock = {}; - MutCursor runningPosition = nullptr; - usize pageNumber = 0; + MutCursor runningPosition = nullptr; + usize pageIndex = 0; BreakpointTraverser breakpointTraverser = {}; diff --git a/src/vaev-engine/layout/base/running-position.cpp b/src/vaev-engine/layout/base/running-position.cpp index 051e8020..5a74239c 100644 --- a/src/vaev-engine/layout/base/running-position.cpp +++ b/src/vaev-engine/layout/base/running-position.cpp @@ -27,10 +27,11 @@ export struct RunningPositionInfo { } }; -struct RunningPositionMap { +// Mapping the different Running positions to their respective names and their page. +struct Runnings { Map> content; - void add(usize pageNumber, Layout::Box& box) { + void add(usize pageNumber, Box& box) { auto& style = box.style; if (auto position = style->position.is()) { @@ -79,7 +80,6 @@ struct RunningPositionMap { } Slice _searchPage(Slice list, usize page) { - page++; // pages are 1-indexed // binary search of all running positions that match the page auto res = search(list, [&](RunningPositionInfo const& info) { diff --git a/src/vaev-engine/layout/block.cpp b/src/vaev-engine/layout/block.cpp index 9ed05901..8d4ddd45 100644 --- a/src/vaev-engine/layout/block.cpp +++ b/src/vaev-engine/layout/block.cpp @@ -197,7 +197,7 @@ struct BlockFormatingContext : FormatingContext { .availableSpace = {input.availableSpace.x, 0_au}, .containingBlock = {inlineSize, input.knownSize.y.unwrapOr(0_au)}, .runningPosition = input.runningPosition, - .pageNumber = input.pageNumber, + .pageIndex = input.pageIndex, .breakpointTraverser = input.breakpointTraverser.traverseInsideUsingIthChild(i), .pendingVerticalSizes = input.pendingVerticalSizes, }; diff --git a/src/vaev-engine/layout/builder/mod.cpp b/src/vaev-engine/layout/builder/mod.cpp index 89772929..a1fd155a 100644 --- a/src/vaev-engine/layout/builder/mod.cpp +++ b/src/vaev-engine/layout/builder/mod.cpp @@ -828,7 +828,7 @@ export Box buildElement(Gc::Ref elt) { return box; } -export Box buildForPseudoElement(Dom::PseudoElement& el, usize currentPage, RunningPositionMap& runningPos) { +export Box buildForPseudoElement(Dom::PseudoElement& el, usize currentPage, Runnings& runningPos) { auto proseStyle = _proseStyleFromStyle(*el.specifiedValues(), el.specifiedValues()->fontFace); if (el.specifiedValues()->content.is()) { diff --git a/src/vaev-engine/layout/flex.cpp b/src/vaev-engine/layout/flex.cpp index 1fe3961b..f52a911e 100644 --- a/src/vaev-engine/layout/flex.cpp +++ b/src/vaev-engine/layout/flex.cpp @@ -1454,7 +1454,7 @@ struct FlexFormatingContext : FormatingContext { .position = flexItem.position, .availableSpace = availableSpace, .runningPosition = input.runningPosition, - .pageNumber = input.pageNumber, + .pageIndex = input.pageIndex, } ); flexItem.commit(input.fragment); diff --git a/src/vaev-engine/layout/inline.cpp b/src/vaev-engine/layout/inline.cpp index f36f0157..49941c03 100644 --- a/src/vaev-engine/layout/inline.cpp +++ b/src/vaev-engine/layout/inline.cpp @@ -119,7 +119,7 @@ struct InlineFormatingContext : FormatingContext { input.knownSize.y.unwrapOr(0_au) }, .runningPosition = input.runningPosition, - .pageNumber = input.pageNumber, + .pageIndex = input.pageIndex, } ); } diff --git a/src/vaev-engine/layout/positioned.cpp b/src/vaev-engine/layout/positioned.cpp index 5fc099fc..1f6ff34a 100644 --- a/src/vaev-engine/layout/positioned.cpp +++ b/src/vaev-engine/layout/positioned.cpp @@ -65,7 +65,7 @@ export void lookForRunningPosition(Input& input, Box& box) { if (box.style->position.is()) { auto& runningMap = input.runningPosition.peek(); - runningMap.add(input.pageNumber, box); + runningMap.add(input.pageIndex, box); } } diff --git a/src/vaev-engine/style/computer.cpp b/src/vaev-engine/style/computer.cpp index 32da8bcf..fb121eac 100644 --- a/src/vaev-engine/style/computer.cpp +++ b/src/vaev-engine/style/computer.cpp @@ -17,7 +17,7 @@ namespace Vaev::Style { export struct Computer { Media _media; StyleSheetList const& _styleBook; - Font::Database& fontBook; + Font::Database _database; StyleRuleLookup _styleRuleLookup{}; // MARK: Cascading --------------------------------------------------------- @@ -304,7 +304,7 @@ export struct Computer { _evalRule(rule, page, *computed); for (auto& area : computed->_areas) { - auto font = _lookupFontface(fontBook, *area.specifiedValues()); + auto font = _lookupFontface(_database, *area.specifiedValues()); area.specifiedValues()->fontFace = font; } @@ -323,7 +323,7 @@ export struct Computer { if (not parentSpecifiedValues.font.sameInstance(specifiedValues->font) and (parentSpecifiedValues.font->families != specifiedValues->font->families or parentSpecifiedValues.font->weight != specifiedValues->font->weight)) { - auto font = _lookupFontface(fontBook, *specifiedValues); + auto font = _lookupFontface(_database, *specifiedValues); specifiedValues->fontFace = font; } else { specifiedValues->fontFace = parentSpecifiedValues.fontFace; @@ -338,7 +338,7 @@ export struct Computer { void styleDocument(Dom::Document& doc) { if (auto el = doc.documentElement()) { auto rootSpecifiedValues = makeRc(SpecifiedValues::initial()); - rootSpecifiedValues->fontFace = _lookupFontface(fontBook, *rootSpecifiedValues); + rootSpecifiedValues->fontFace = _lookupFontface(_database, *rootSpecifiedValues); styleElement(*rootSpecifiedValues, *el); } _propagateBodyBackgroundToHtml(doc); @@ -390,13 +390,13 @@ export struct Computer { } // FIXME: use attrs from style::FontFace - if (fontBook.load(resolvedUrl.unwrap())) + if (_database.load(resolvedUrl.unwrap())) break; logWarn("Failed to load font {}", ff.family); } else { if ( - fontBook.queryExact(src.identifier.unwrap().name) + _database.queryExact(src.identifier.unwrap().name) ) break;