XFA: break pages at top-level subform

This commit is contained in:
Jakub Melka 2021-12-25 19:04:48 +01:00
parent f53b9f2988
commit 2209c04f48

View File

@ -10031,6 +10031,8 @@ private:
} }
else else
{ {
m_engine->layoutFlow(parameters, true);
// Store final layout // 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())); 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 /// Perform flow layout. Does nothing, if layout has positional
/// layout type. Final layout is stored also in the layout parameters. /// layout type. Final layout is stored also in the layout parameters.
/// \param layoutParameters Layout parameters /// \param layoutParameters Layout parameters
void layoutFlow(LayoutParameters& layoutParameters); void layoutFlow(LayoutParameters& layoutParameters, bool breakPages);
void addSubformToLayout(LayoutParameters& layoutParameters); void addSubformToLayout(LayoutParameters& layoutParameters);
@ -10068,6 +10070,11 @@ private:
bool layoutPositional(LayoutParameters& sourceLayoutParameters, bool layoutPositional(LayoutParameters& sourceLayoutParameters,
LayoutParameters& targetLayoutParameters); LayoutParameters& targetLayoutParameters);
void finalizeAndAddLayout(QMarginsF captionMargins,
Layout finalLayout,
LayoutParameters& layoutParameters,
QSizeF nominalContentSize);
LayoutParameters& getLayoutParameters() { return m_layoutParameters.top(); } LayoutParameters& getLayoutParameters() { return m_layoutParameters.top(); }
const LayoutParameters& getLayoutParameters() const { return m_layoutParameters.top(); } const LayoutParameters& getLayoutParameters() const { return m_layoutParameters.top(); }
@ -10163,7 +10170,7 @@ void PDFXFALayoutEngine::layout(LayoutParameters layoutParameters)
// Case 1) // Case 1)
LayoutParameters& currentLayoutParameters = getLayoutParameters(); LayoutParameters& currentLayoutParameters = getLayoutParameters();
layoutFlow(layoutParameters); layoutFlow(layoutParameters, false);
std::vector<Layout>& layouts = currentLayoutParameters.layout; std::vector<Layout>& layouts = currentLayoutParameters.layout;
if (layoutParameters.nodeArea) if (layoutParameters.nodeArea)
@ -10219,7 +10226,27 @@ void PDFXFALayoutEngine::layout(LayoutParameters layoutParameters)
std::make_move_iterator(layoutParameters.tableRows.end())); 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) if (layoutParameters.layoutType == xfa::XFA_BaseNode::LAYOUT::Position)
{ {
@ -10356,9 +10383,10 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters)
} }
layoutParameters.layout.clear(); layoutParameters.layout.clear();
PDFInteger pageOffset = 0;
for (auto& item : layoutsPerPage) for (auto& item : layoutsPerPage)
{ {
const size_t pageIndex = item.first; const size_t sourcePageIndex = item.first;
std::vector<Layout> layouts = std::move(item.second); std::vector<Layout> layouts = std::move(item.second);
for (Layout& layout : layouts) for (Layout& layout : layouts)
@ -10373,6 +10401,7 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters)
break; break;
case xfa::XFA_BaseNode::LAYOUT::Lr_tb: case xfa::XFA_BaseNode::LAYOUT::Lr_tb:
// TODO: Implement Lr_Tb
break; break;
case xfa::XFA_BaseNode::LAYOUT::Rl_row: case xfa::XFA_BaseNode::LAYOUT::Rl_row:
@ -10383,6 +10412,7 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters)
} }
case xfa::XFA_BaseNode::LAYOUT::Rl_tb: case xfa::XFA_BaseNode::LAYOUT::Rl_tb:
// TODO: Implement Rl_tb
break; break;
case xfa::XFA_BaseNode::LAYOUT::Row: case xfa::XFA_BaseNode::LAYOUT::Row:
@ -10401,14 +10431,52 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters)
{ {
// Top-to-bottom layout // Top-to-bottom layout
Layout finalLayout; Layout finalLayout;
finalLayout.pageIndex = pageIndex; PDFInteger targetPageIndex = sourcePageIndex + pageOffset;
finalLayout.pageIndex = targetPageIndex;
PDFReal x = 0.0; PDFReal x = 0.0;
PDFReal y = 0.0; PDFReal y = 0.0;
PDFReal h = 0.0;
PDFReal maxW = 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) 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); layout.translate(x, y);
finalLayout.items.insert(finalLayout.items.end(), layout.items.begin(), layout.items.end()); finalLayout.items.insert(finalLayout.items.end(), layout.items.begin(), layout.items.end());
y += layout.nominalExtent.height(); y += layout.nominalExtent.height();
@ -10416,26 +10484,15 @@ void PDFXFALayoutEngine::layoutFlow(LayoutParameters& layoutParameters)
} }
// Translate by margin // Translate by margin
finalLayout.translate(layoutParameters.margins.left(), layoutParameters.margins.top()); finalizeAndAddLayout(captionMargins, finalLayout, layoutParameters, QSizeF(maxW, y));
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));
}
break; break;
} }
default: default:
{
Q_ASSERT(false); Q_ASSERT(false);
break; break;
}
} }
} }