diff --git a/Pdf4QtLib/sources/pdfxfaengine.cpp b/Pdf4QtLib/sources/pdfxfaengine.cpp index 13fe374..9076ccb 100644 --- a/Pdf4QtLib/sources/pdfxfaengine.cpp +++ b/Pdf4QtLib/sources/pdfxfaengine.cpp @@ -10031,6 +10031,8 @@ private: } else { + m_engine->layoutFlow(parameters, true); + // Store final layout m_engine->m_layout.insert(m_engine->m_layout.end(), std::make_move_iterator(parameters.layout.begin()), std::make_move_iterator(parameters.layout.end())); } @@ -10057,7 +10059,7 @@ private: /// Perform flow layout. Does nothing, if layout has positional /// layout type. Final layout is stored also in the layout parameters. /// \param layoutParameters Layout parameters - void layoutFlow(LayoutParameters& layoutParameters); + void layoutFlow(LayoutParameters& layoutParameters, bool breakPages); void addSubformToLayout(LayoutParameters& layoutParameters); @@ -10068,6 +10070,11 @@ private: bool layoutPositional(LayoutParameters& sourceLayoutParameters, LayoutParameters& targetLayoutParameters); + void finalizeAndAddLayout(QMarginsF captionMargins, + Layout finalLayout, + LayoutParameters& layoutParameters, + QSizeF nominalContentSize); + LayoutParameters& getLayoutParameters() { return m_layoutParameters.top(); } const LayoutParameters& getLayoutParameters() const { return m_layoutParameters.top(); } @@ -10163,7 +10170,7 @@ void PDFXFALayoutEngine::layout(LayoutParameters layoutParameters) // Case 1) LayoutParameters& currentLayoutParameters = getLayoutParameters(); - layoutFlow(layoutParameters); + layoutFlow(layoutParameters, false); std::vector& layouts = currentLayoutParameters.layout; if (layoutParameters.nodeArea) @@ -10219,7 +10226,27 @@ void PDFXFALayoutEngine::layout(LayoutParameters layoutParameters) std::make_move_iterator(layoutParameters.tableRows.end())); } -void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters) +void PDFXFALayoutEngine::finalizeAndAddLayout(QMarginsF captionMargins, + Layout finalLayout, + LayoutParameters& layoutParameters, + QSizeF nominalContentSize) +{ + finalLayout.translate(layoutParameters.margins.left(), layoutParameters.margins.top()); + + QSizeF nominalExtentSizeWithoutCaption = nominalContentSize.grownBy(layoutParameters.margins); + QSizeF nominalExtentSize = nominalExtentSizeWithoutCaption.grownBy(captionMargins); + nominalExtentSize = layoutParameters.sizeInfo.adjustNominalExtentSize(nominalExtentSize); + QRectF nominalExtentRegion(QPointF(0, 0), nominalExtentSize); + finalLayout.nominalExtent = nominalExtentRegion; + finalLayout.colSpan = layoutParameters.columnSpan; + + if (!finalLayout.items.empty()) + { + layoutParameters.layout.emplace_back(std::move(finalLayout)); + } +} + +void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters, bool breakPages) { if (layoutParameters.layoutType == xfa::XFA_BaseNode::LAYOUT::Position) { @@ -10356,9 +10383,10 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters) } layoutParameters.layout.clear(); + PDFInteger pageOffset = 0; for (auto& item : layoutsPerPage) { - const size_t pageIndex = item.first; + const size_t sourcePageIndex = item.first; std::vector layouts = std::move(item.second); for (Layout& layout : layouts) @@ -10373,6 +10401,7 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters) break; case xfa::XFA_BaseNode::LAYOUT::Lr_tb: + // TODO: Implement Lr_Tb break; case xfa::XFA_BaseNode::LAYOUT::Rl_row: @@ -10383,6 +10412,7 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters) } case xfa::XFA_BaseNode::LAYOUT::Rl_tb: + // TODO: Implement Rl_tb break; case xfa::XFA_BaseNode::LAYOUT::Row: @@ -10401,14 +10431,52 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters) { // Top-to-bottom layout Layout finalLayout; - finalLayout.pageIndex = pageIndex; + PDFInteger targetPageIndex = sourcePageIndex + pageOffset; + finalLayout.pageIndex = targetPageIndex; PDFReal x = 0.0; PDFReal y = 0.0; + PDFReal h = 0.0; PDFReal maxW = 0.0; + PDFReal maxH = 0.0; + + if (breakPages && targetPageIndex < PDFInteger(m_pages.size())) + { + maxH = m_pages[targetPageIndex].contentBox.height() - layoutParameters.margins.top() - layoutParameters.margins.bottom(); + } for (Layout& layout : layouts) { + if (breakPages && !qFuzzyIsNull(maxH)) + { + PDFReal currentH = h + layout.nominalExtent.height(); + + if (currentH > maxH) + { + finalizeAndAddLayout(captionMargins, finalLayout, layoutParameters, QSizeF(maxW, y)); + + // Update page offets and maximal height + ++pageOffset; + ++targetPageIndex; + if (targetPageIndex < PDFInteger(m_pages.size())) + { + maxH = m_pages[targetPageIndex].contentBox.height() - layoutParameters.margins.top() - layoutParameters.margins.bottom(); + } + + // Reinitialize final layout + finalLayout = Layout(); + finalLayout.pageIndex = targetPageIndex; + + // Current item is layouted onto the next page + h = layout.nominalExtent.height(); + y = 0.0; + } + else + { + h = currentH; + } + } + layout.translate(x, y); finalLayout.items.insert(finalLayout.items.end(), layout.items.begin(), layout.items.end()); y += layout.nominalExtent.height(); @@ -10416,26 +10484,15 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters) } // Translate by margin - finalLayout.translate(layoutParameters.margins.left(), layoutParameters.margins.top()); - - QSizeF nominalContentSize(maxW, y); - QSizeF nominalExtentSizeWithoutCaption = nominalContentSize.grownBy(layoutParameters.margins); - QSizeF nominalExtentSize = nominalExtentSizeWithoutCaption.grownBy(captionMargins); - nominalExtentSize = layoutParameters.sizeInfo.adjustNominalExtentSize(nominalExtentSize); - QRectF nominalExtentRegion(QPointF(0, 0), nominalExtentSize); - finalLayout.nominalExtent = nominalExtentRegion; - finalLayout.colSpan = layoutParameters.columnSpan; - - if (!finalLayout.items.empty()) - { - layoutParameters.layout.emplace_back(std::move(finalLayout)); - } + finalizeAndAddLayout(captionMargins, finalLayout, layoutParameters, QSizeF(maxW, y)); break; } default: + { Q_ASSERT(false); break; + } } }