From 405f17ae3f297d28917370d013d95adc31e7c4a1 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Wed, 31 Jan 2018 20:13:44 +0000 Subject: Cleanup visibility in CXFA_ItemLayoutProcessor This CL moves anonymous namespace methods in CXFA_ItemLayoutProcessor to be private methods and then fixes the visibility on most of the methods/data to be private. Change-Id: Idfccbc53b94628b18bc3576e4466391b0f704b44 Reviewed-on: https://pdfium-review.googlesource.com/24851 Reviewed-by: Henrique Nakashima Commit-Queue: dsinclair --- xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp | 4136 +++++++++++++------------- xfa/fxfa/parser/cxfa_itemlayoutprocessor.h | 72 +- xfa/fxfa/parser/cxfa_layoutprocessor.cpp | 12 +- 3 files changed, 2105 insertions(+), 2115 deletions(-) diff --git a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp index f5392a584c..b4bea75fb2 100644 --- a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp +++ b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp @@ -321,189 +321,6 @@ void RelocateTableRowCells(CXFA_ContentLayoutItem* pLayoutRow, bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); } -void UpdatePendingItemLayout(CXFA_ItemLayoutProcessor* pProcessor, - CXFA_ContentLayoutItem* pLayoutItem) { - XFA_AttributeEnum eLayout = - pLayoutItem->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); - switch (eLayout) { - case XFA_AttributeEnum::Row: - case XFA_AttributeEnum::Rl_row: - RelocateTableRowCells(pLayoutItem, pProcessor->m_rgSpecifiedColumnWidths, - eLayout); - break; - default: - break; - } -} - -void AddTrailerBeforeSplit(CXFA_ItemLayoutProcessor* pProcessor, - float fSplitPos, - CXFA_ContentLayoutItem* pTrailerLayoutItem, - bool bUseInherited) { - if (!pTrailerLayoutItem) - return; - - float fHeight = pTrailerLayoutItem->m_sSize.height; - if (bUseInherited) { - float fNewSplitPos = 0; - if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) - fNewSplitPos = pProcessor->FindSplitPos(fSplitPos - fHeight); - if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) - pProcessor->SplitLayoutItem(fNewSplitPos); - return; - } - - UpdatePendingItemLayout(pProcessor, pTrailerLayoutItem); - CXFA_Margin* pMarginNode = - pProcessor->m_pFormNode->GetFirstChildByClass( - XFA_Element::Margin); - float fLeftInset = 0; - float fTopInset = 0; - float fRightInset = 0; - float fBottomInset = 0; - if (pMarginNode) { - fLeftInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::LeftInset) - .ToUnit(XFA_Unit::Pt); - fTopInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::TopInset) - .ToUnit(XFA_Unit::Pt); - fRightInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::RightInset) - .ToUnit(XFA_Unit::Pt); - fBottomInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::BottomInset) - .ToUnit(XFA_Unit::Pt); - } - - if (!pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem)) { - pTrailerLayoutItem->m_sPos.y = pProcessor->m_fLastRowY; - pTrailerLayoutItem->m_sPos.x = pProcessor->m_fLastRowWidth; - pProcessor->m_pLayoutItem->m_sSize.width += - pTrailerLayoutItem->m_sSize.width; - pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); - return; - } - - float fNewSplitPos = 0; - if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) - fNewSplitPos = pProcessor->FindSplitPos(fSplitPos - fHeight); - - if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { - pProcessor->SplitLayoutItem(fNewSplitPos); - pTrailerLayoutItem->m_sPos.y = fNewSplitPos - fTopInset - fBottomInset; - } else { - pTrailerLayoutItem->m_sPos.y = fSplitPos - fTopInset - fBottomInset; - } - - switch (pTrailerLayoutItem->m_pFormNode->JSObject()->GetEnum( - XFA_Attribute::HAlign)) { - case XFA_AttributeEnum::Right: - pTrailerLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.width - - fRightInset - - pTrailerLayoutItem->m_sSize.width; - break; - case XFA_AttributeEnum::Center: - pTrailerLayoutItem->m_sPos.x = - (pProcessor->m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - - pTrailerLayoutItem->m_sSize.width) / - 2; - break; - case XFA_AttributeEnum::Left: - default: - pTrailerLayoutItem->m_sPos.x = fLeftInset; - break; - } - pProcessor->m_pLayoutItem->m_sSize.height += fHeight; - pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); -} - -void AddLeaderAfterSplit(CXFA_ItemLayoutProcessor* pProcessor, - CXFA_ContentLayoutItem* pLeaderLayoutItem) { - UpdatePendingItemLayout(pProcessor, pLeaderLayoutItem); - - CXFA_Margin* pMarginNode = - pProcessor->m_pFormNode->GetFirstChildByClass( - XFA_Element::Margin); - float fLeftInset = 0; - float fRightInset = 0; - if (pMarginNode) { - fLeftInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::LeftInset) - .ToUnit(XFA_Unit::Pt); - fRightInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::RightInset) - .ToUnit(XFA_Unit::Pt); - } - - float fHeight = pLeaderLayoutItem->m_sSize.height; - for (CXFA_ContentLayoutItem* pChildItem = - (CXFA_ContentLayoutItem*)pProcessor->m_pLayoutItem->m_pFirstChild; - pChildItem; - pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { - pChildItem->m_sPos.y += fHeight; - } - pLeaderLayoutItem->m_sPos.y = 0; - - switch (pLeaderLayoutItem->m_pFormNode->JSObject()->GetEnum( - XFA_Attribute::HAlign)) { - case XFA_AttributeEnum::Right: - pLeaderLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.width - - fRightInset - - pLeaderLayoutItem->m_sSize.width; - break; - case XFA_AttributeEnum::Center: - pLeaderLayoutItem->m_sPos.x = - (pProcessor->m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - - pLeaderLayoutItem->m_sSize.width) / - 2; - break; - case XFA_AttributeEnum::Left: - default: - pLeaderLayoutItem->m_sPos.x = fLeftInset; - break; - } - pProcessor->m_pLayoutItem->m_sSize.height += fHeight; - pProcessor->m_pLayoutItem->AddChild(pLeaderLayoutItem); -} - -void AddPendingNode(CXFA_ItemLayoutProcessor* pProcessor, - CXFA_Node* pPendingNode, - bool bBreakPending) { - pProcessor->m_PendingNodes.push_back(pPendingNode); - pProcessor->m_bBreakPending = bBreakPending; -} - -float InsertPendingItems(CXFA_ItemLayoutProcessor* pProcessor, - CXFA_Node* pCurChildNode) { - float fTotalHeight = 0; - if (pProcessor->m_PendingNodes.empty()) - return fTotalHeight; - - if (!pProcessor->m_pLayoutItem) { - pProcessor->m_pLayoutItem = - pProcessor->CreateContentLayoutItem(pCurChildNode); - pProcessor->m_pLayoutItem->m_sSize.clear(); - } - - while (!pProcessor->m_PendingNodes.empty()) { - auto pPendingProcessor = pdfium::MakeUnique( - pProcessor->m_PendingNodes.front(), nullptr); - pProcessor->m_PendingNodes.pop_front(); - pPendingProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); - CXFA_ContentLayoutItem* pPendingLayoutItem = - pPendingProcessor->HasLayoutItem() - ? pPendingProcessor->ExtractLayoutItem() - : nullptr; - if (pPendingLayoutItem) { - AddLeaderAfterSplit(pProcessor, pPendingLayoutItem); - if (pProcessor->m_bBreakPending) - fTotalHeight += pPendingLayoutItem->m_sSize.height; - } - } - return fTotalHeight; -} - XFA_AttributeEnum GetLayout(CXFA_Node* pFormNode, bool* bRootForceTb) { *bRootForceTb = false; Optional layoutMode = @@ -646,2179 +463,2340 @@ uint8_t HAlignEnumToInt(XFA_AttributeEnum eHAlign) { } } -XFA_ItemLayoutProcessorResult InsertFlowedItem( - CXFA_ItemLayoutProcessor* pThis, - CXFA_ItemLayoutProcessor* pProcessor, - bool bContainerWidthAutoSize, - bool bContainerHeightAutoSize, - float fContainerHeight, - XFA_AttributeEnum eFlowStrategy, - uint8_t* uCurHAlignState, - std::vector (&rgCurLineLayoutItems)[3], - bool bUseBreakControl, - float fAvailHeight, - float fRealHeight, - float fContentWidthLimit, - float* fContentCurRowY, - float* fContentCurRowAvailWidth, - float* fContentCurRowHeight, - bool* bAddedItemInRow, - bool* bForceEndPage, - CXFA_LayoutContext* pLayoutContext, - bool bNewRow) { - bool bTakeSpace = pProcessor->m_pFormNode->PresenceRequiresSpace(); - uint8_t uHAlign = HAlignEnumToInt( - pThis->m_pCurChildNode->JSObject()->GetEnum(XFA_Attribute::HAlign)); - if (bContainerWidthAutoSize) - uHAlign = 0; - - if ((eFlowStrategy != XFA_AttributeEnum::Rl_tb && - uHAlign < *uCurHAlignState) || - (eFlowStrategy == XFA_AttributeEnum::Rl_tb && - uHAlign > *uCurHAlignState)) { - return XFA_ItemLayoutProcessorResult::RowFullBreak; +bool FindLayoutItemSplitPos(CXFA_ContentLayoutItem* pLayoutItem, + float fCurVerticalOffset, + float* fProposedSplitPos, + bool* bAppChange, + bool bCalculateMargin) { + CXFA_Node* pFormNode = pLayoutItem->m_pFormNode; + if (*fProposedSplitPos <= fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION || + *fProposedSplitPos > fCurVerticalOffset + pLayoutItem->m_sSize.height - + XFA_LAYOUT_FLOAT_PERCISION) { + return false; } - *uCurHAlignState = uHAlign; - bool bIsOwnSplit = - pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None; - bool bUseRealHeight = bTakeSpace && bContainerHeightAutoSize && bIsOwnSplit && - pProcessor->m_pFormNode->GetParent()->GetIntact() == - XFA_AttributeEnum::None; - bool bIsTransHeight = bTakeSpace; - if (bIsTransHeight && !bIsOwnSplit) { - bool bRootForceTb = false; - XFA_AttributeEnum eLayoutStrategy = - GetLayout(pProcessor->m_pFormNode, &bRootForceTb); - if (eLayoutStrategy == XFA_AttributeEnum::Lr_tb || - eLayoutStrategy == XFA_AttributeEnum::Rl_tb) { - bIsTransHeight = false; + switch (pFormNode->GetIntact()) { + case XFA_AttributeEnum::None: { + bool bAnyChanged = false; + CXFA_Document* pDocument = pFormNode->GetDocument(); + CXFA_FFNotify* pNotify = pDocument->GetNotify(); + float fCurTopMargin = 0, fCurBottomMargin = 0; + CXFA_Margin* pMarginNode = + pFormNode->GetFirstChildByClass(XFA_Element::Margin); + if (pMarginNode && bCalculateMargin) { + fCurTopMargin = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); + fCurBottomMargin = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); + } + bool bChanged = true; + while (bChanged) { + bChanged = false; + { + float fRelSplitPos = *fProposedSplitPos - fCurVerticalOffset; + if (pFormNode->FindSplitPos(pNotify->GetHDOC()->GetDocView(), + pLayoutItem->GetIndex(), fRelSplitPos)) { + bAnyChanged = true; + bChanged = true; + *fProposedSplitPos = fCurVerticalOffset + fRelSplitPos; + *bAppChange = true; + if (*fProposedSplitPos <= + fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { + return true; + } + } + } + float fRelSplitPos = *fProposedSplitPos - fCurBottomMargin; + for (CXFA_ContentLayoutItem* pChildItem = + (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; + pChildItem; + pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { + float fChildOffset = + fCurVerticalOffset + fCurTopMargin + pChildItem->m_sPos.y; + bool bChange = false; + if (FindLayoutItemSplitPos(pChildItem, fChildOffset, &fRelSplitPos, + &bChange, bCalculateMargin)) { + if (fRelSplitPos - fChildOffset < XFA_LAYOUT_FLOAT_PERCISION && + bChange) { + *fProposedSplitPos = fRelSplitPos - fCurTopMargin; + } else { + *fProposedSplitPos = fRelSplitPos + fCurBottomMargin; + } + bAnyChanged = true; + bChanged = true; + if (*fProposedSplitPos <= + fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { + return true; + } + if (bAnyChanged) + break; + } + } + } + return bAnyChanged; + } + case XFA_AttributeEnum::ContentArea: + case XFA_AttributeEnum::PageArea: { + *fProposedSplitPos = fCurVerticalOffset; + return true; } + default: + return false; } +} - bool bUseInherited = false; - CXFA_LayoutContext layoutContext; - if (pThis->m_pPageMgr) { - CXFA_Node* pOverflowNode = - pThis->m_pPageMgr->QueryOverflow(pThis->m_pFormNode); - if (pOverflowNode) { - layoutContext.m_pOverflowNode = pOverflowNode; - layoutContext.m_pOverflowProcessor = pThis; - pLayoutContext = &layoutContext; - } - } - - XFA_ItemLayoutProcessorResult eRetValue = XFA_ItemLayoutProcessorResult::Done; - if (!bNewRow || - pProcessor->m_ePreProcessRs == XFA_ItemLayoutProcessorResult::Done) { - eRetValue = pProcessor->DoLayout( - bTakeSpace ? bUseBreakControl : false, - bUseRealHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, - bIsTransHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, - pLayoutContext); - pProcessor->m_ePreProcessRs = eRetValue; - } else { - eRetValue = pProcessor->m_ePreProcessRs; - pProcessor->m_ePreProcessRs = XFA_ItemLayoutProcessorResult::Done; +CFX_PointF CalculatePositionedContainerPos(CXFA_Node* pNode, + const CFX_SizeF& size) { + XFA_AttributeEnum eAnchorType = + pNode->JSObject()->GetEnum(XFA_Attribute::AnchorType); + int32_t nAnchorType = 0; + switch (eAnchorType) { + case XFA_AttributeEnum::TopLeft: + nAnchorType = 0; + break; + case XFA_AttributeEnum::TopCenter: + nAnchorType = 1; + break; + case XFA_AttributeEnum::TopRight: + nAnchorType = 2; + break; + case XFA_AttributeEnum::MiddleLeft: + nAnchorType = 3; + break; + case XFA_AttributeEnum::MiddleCenter: + nAnchorType = 4; + break; + case XFA_AttributeEnum::MiddleRight: + nAnchorType = 5; + break; + case XFA_AttributeEnum::BottomLeft: + nAnchorType = 6; + break; + case XFA_AttributeEnum::BottomCenter: + nAnchorType = 7; + break; + case XFA_AttributeEnum::BottomRight: + nAnchorType = 8; + break; + default: + break; } - if (pProcessor->HasLayoutItem() == false) - return eRetValue; + static const uint8_t nNextPos[4][9] = {{0, 1, 2, 3, 4, 5, 6, 7, 8}, + {6, 3, 0, 7, 4, 1, 8, 5, 2}, + {8, 7, 6, 5, 4, 3, 2, 1, 0}, + {2, 5, 8, 1, 4, 7, 0, 3, 6}}; - CFX_SizeF childSize = pProcessor->GetCurrentComponentSize(); - if (bUseRealHeight && fRealHeight < XFA_LAYOUT_FLOAT_PERCISION) { - fRealHeight = FLT_MAX; - fAvailHeight = FLT_MAX; - } - if (bTakeSpace && (childSize.width > - *fContentCurRowAvailWidth + XFA_LAYOUT_FLOAT_PERCISION) && - (fContentWidthLimit - *fContentCurRowAvailWidth > - XFA_LAYOUT_FLOAT_PERCISION)) { - return XFA_ItemLayoutProcessorResult::RowFullBreak; + CFX_PointF pos( + pNode->JSObject()->GetMeasure(XFA_Attribute::X).ToUnit(XFA_Unit::Pt), + pNode->JSObject()->GetMeasure(XFA_Attribute::Y).ToUnit(XFA_Unit::Pt)); + int32_t nRotate = + XFA_MapRotation(pNode->JSObject()->GetInteger(XFA_Attribute::Rotate)) / + 90; + int32_t nAbsoluteAnchorType = nNextPos[nRotate][nAnchorType]; + switch (nAbsoluteAnchorType / 3) { + case 1: + pos.y -= size.height / 2; + break; + case 2: + pos.y -= size.height; + break; + default: + break; } - - CXFA_Node* pOverflowLeaderNode = nullptr; - CXFA_Node* pOverflowTrailerNode = nullptr; - CXFA_Node* pFormNode = nullptr; - CXFA_ContentLayoutItem* pTrailerLayoutItem = nullptr; - bool bIsAddTrailerHeight = false; - if (pThis->m_pPageMgr && - pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None) { - pFormNode = pThis->m_pPageMgr->QueryOverflow(pProcessor->m_pFormNode); - if (!pFormNode && pLayoutContext && pLayoutContext->m_pOverflowProcessor) { - pFormNode = pLayoutContext->m_pOverflowNode; - bUseInherited = true; - } - if (pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, - pOverflowTrailerNode, false, - false)) { - if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowTrailerNode)) { - if (pOverflowTrailerNode) { - auto pOverflowLeaderProcessor = - pdfium::MakeUnique(pOverflowTrailerNode, - nullptr); - pOverflowLeaderProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); - pTrailerLayoutItem = - pOverflowLeaderProcessor->HasLayoutItem() - ? pOverflowLeaderProcessor->ExtractLayoutItem() - : nullptr; - } - - bIsAddTrailerHeight = - bUseInherited - ? pThis->IsAddNewRowForTrailer(pTrailerLayoutItem) - : pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem); - if (bIsAddTrailerHeight) { - childSize.height += pTrailerLayoutItem->m_sSize.height; - bIsAddTrailerHeight = true; - } - } - } + switch (nAbsoluteAnchorType % 3) { + case 1: + pos.x -= size.width / 2; + break; + case 2: + pos.x -= size.width; + break; + default: + break; } + return pos; +} - if (!bTakeSpace || - *fContentCurRowY + childSize.height <= - fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION || - (!bContainerHeightAutoSize && - pThis->m_fUsedSize + fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION >= - fContainerHeight)) { - if (!bTakeSpace || eRetValue == XFA_ItemLayoutProcessorResult::Done) { - if (pProcessor->m_bUseInheriated) { - if (pTrailerLayoutItem) - AddTrailerBeforeSplit(pProcessor, childSize.height, - pTrailerLayoutItem, false); - if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) - AddPendingNode(pProcessor, pOverflowLeaderNode, false); +} // namespace - pProcessor->m_bUseInheriated = false; - } else { - if (bIsAddTrailerHeight) - childSize.height -= pTrailerLayoutItem->m_sSize.height; +CXFA_ItemLayoutProcessor::CXFA_ItemLayoutProcessor(CXFA_Node* pNode, + CXFA_LayoutPageMgr* pPageMgr) + : m_pFormNode(pNode), + m_pLayoutItem(nullptr), + m_pCurChildNode(XFA_LAYOUT_INVALIDNODE), + m_fUsedSize(0), + m_pPageMgr(pPageMgr), + m_bBreakPending(true), + m_fLastRowWidth(0), + m_fLastRowY(0), + m_bUseInheriated(false), + m_ePreProcessRs(XFA_ItemLayoutProcessorResult::Done), + m_bKeepBreakFinish(false), + m_bIsProcessKeep(false), + m_pKeepHeadNode(nullptr), + m_pKeepTailNode(nullptr), + m_pOldLayoutItem(nullptr), + m_pCurChildPreprocessor(nullptr), + m_nCurChildNodeStage(XFA_ItemLayoutProcessorStages::None), + m_fWidthLimite(0), + m_bHasAvailHeight(true) { + ASSERT(m_pFormNode && (m_pFormNode->IsContainerNode() || + m_pFormNode->GetElementType() == XFA_Element::Form)); + m_pOldLayoutItem = static_cast( + m_pFormNode->JSObject()->GetLayoutItem()); +} - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - } +CXFA_ItemLayoutProcessor::~CXFA_ItemLayoutProcessor() {} - CXFA_ContentLayoutItem* pChildLayoutItem = - pProcessor->ExtractLayoutItem(); - if (ExistContainerKeep(pProcessor->m_pFormNode, false) && - pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None) { - pThis->m_arrayKeepItems.push_back(pChildLayoutItem); - } else { - pThis->m_arrayKeepItems.clear(); - } - rgCurLineLayoutItems[uHAlign].push_back(pChildLayoutItem); - *bAddedItemInRow = true; - if (bTakeSpace) { - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = - std::max(*fContentCurRowHeight, childSize.height); - } - return XFA_ItemLayoutProcessorResult::Done; - } +CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::CreateContentLayoutItem( + CXFA_Node* pFormNode) { + if (!pFormNode) + return nullptr; - if (eRetValue == XFA_ItemLayoutProcessorResult::PageFullBreak) { - if (pProcessor->m_bUseInheriated) { - if (pTrailerLayoutItem) { - AddTrailerBeforeSplit(pProcessor, childSize.height, - pTrailerLayoutItem, false); - } - if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) - AddPendingNode(pProcessor, pOverflowLeaderNode, false); + CXFA_ContentLayoutItem* pLayoutItem = nullptr; + if (m_pOldLayoutItem) { + pLayoutItem = m_pOldLayoutItem; + m_pOldLayoutItem = m_pOldLayoutItem->m_pNext; + return pLayoutItem; + } + pLayoutItem = + pFormNode->GetDocument()->GetNotify()->OnCreateContentLayoutItem( + pFormNode); + CXFA_ContentLayoutItem* pPrevLayoutItem = + static_cast( + pFormNode->JSObject()->GetLayoutItem()); + if (pPrevLayoutItem) { + while (pPrevLayoutItem->m_pNext) + pPrevLayoutItem = pPrevLayoutItem->m_pNext; - pProcessor->m_bUseInheriated = false; - } else { - if (bIsAddTrailerHeight) - childSize.height -= pTrailerLayoutItem->m_sSize.height; + pPrevLayoutItem->m_pNext = pLayoutItem; + pLayoutItem->m_pPrev = pPrevLayoutItem; + } else { + pFormNode->JSObject()->SetLayoutItem(pLayoutItem); + } + return pLayoutItem; +} - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - } +float CXFA_ItemLayoutProcessor::FindSplitPos(float fProposedSplitPos) { + ASSERT(m_pLayoutItem); + XFA_AttributeEnum eLayout = m_pFormNode->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position); + bool bCalculateMargin = eLayout != XFA_AttributeEnum::Position; + while (fProposedSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { + bool bAppChange = false; + if (!FindLayoutItemSplitPos(m_pLayoutItem, 0, &fProposedSplitPos, + &bAppChange, bCalculateMargin)) { + break; } - rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); - return eRetValue; } + return fProposedSplitPos; +} - XFA_ItemLayoutProcessorResult eResult; - if (pThis->ProcessKeepForSplit( - pThis, pProcessor, eRetValue, &rgCurLineLayoutItems[uHAlign], - fContentCurRowAvailWidth, fContentCurRowHeight, fContentCurRowY, - bAddedItemInRow, bForceEndPage, &eResult)) { - return eResult; - } +void CXFA_ItemLayoutProcessor::SplitLayoutItem( + CXFA_ContentLayoutItem* pLayoutItem, + CXFA_ContentLayoutItem* pSecondParent, + float fSplitPos) { + float fCurTopMargin = 0, fCurBottomMargin = 0; + XFA_AttributeEnum eLayout = m_pFormNode->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position); + bool bCalculateMargin = true; + if (eLayout == XFA_AttributeEnum::Position) + bCalculateMargin = false; - *bForceEndPage = true; - float fSplitPos = pProcessor->FindSplitPos(fAvailHeight - *fContentCurRowY); - if (fSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { - XFA_AttributeEnum eLayout = - pProcessor->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); - if (eLayout == XFA_AttributeEnum::Tb && - eRetValue == XFA_ItemLayoutProcessorResult::Done) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, pTrailerLayoutItem, - pFormNode); - rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - if (bTakeSpace) { - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = - std::max(*fContentCurRowHeight, childSize.height); - } - return XFA_ItemLayoutProcessorResult::PageFullBreak; - } - - CXFA_Node* pTempLeaderNode = nullptr; - CXFA_Node* pTempTrailerNode = nullptr; - if (pThis->m_pPageMgr && !pProcessor->m_bUseInheriated && - eRetValue != XFA_ItemLayoutProcessorResult::PageFullBreak) { - pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, - pTempTrailerNode, false, true); - } - if (pTrailerLayoutItem && bIsAddTrailerHeight) { - AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem, - bUseInherited); - } else { - pProcessor->SplitLayoutItem(fSplitPos); - } + CXFA_Margin* pMarginNode = + pLayoutItem->m_pFormNode->GetFirstChildByClass( + XFA_Element::Margin); + if (pMarginNode && bCalculateMargin) { + fCurTopMargin = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); + fCurBottomMargin = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); + } - if (bUseInherited) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, pTrailerLayoutItem, - pFormNode); - pThis->m_bUseInheriated = true; - } else { - CXFA_LayoutItem* firstChild = pProcessor->m_pLayoutItem->m_pFirstChild; - if (firstChild && !firstChild->m_pNextSibling && - firstChild->m_pFormNode->IsLayoutGeneratedNode()) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - } else if (pProcessor->JudgeLeaderOrTrailerForOccur( - pOverflowLeaderNode)) { - AddPendingNode(pProcessor, pOverflowLeaderNode, false); - } - } + CXFA_ContentLayoutItem* pSecondLayoutItem = nullptr; + if (m_pCurChildPreprocessor && + m_pCurChildPreprocessor->m_pFormNode == pLayoutItem->m_pFormNode) { + pSecondLayoutItem = m_pCurChildPreprocessor->CreateContentLayoutItem( + pLayoutItem->m_pFormNode); + } else { + pSecondLayoutItem = CreateContentLayoutItem(pLayoutItem->m_pFormNode); + } + pSecondLayoutItem->m_sPos.x = pLayoutItem->m_sPos.x; + pSecondLayoutItem->m_sSize.width = pLayoutItem->m_sSize.width; + pSecondLayoutItem->m_sPos.y = 0; + pSecondLayoutItem->m_sSize.height = pLayoutItem->m_sSize.height - fSplitPos; + pLayoutItem->m_sSize.height -= pSecondLayoutItem->m_sSize.height; + if (pLayoutItem->m_pFirstChild) + pSecondLayoutItem->m_sSize.height += fCurTopMargin; - if (pProcessor->m_pLayoutItem->m_pNextSibling) { - childSize = pProcessor->GetCurrentComponentSize(); - rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - if (bTakeSpace) { - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = - std::max(*fContentCurRowHeight, childSize.height); + if (pSecondParent) { + pSecondParent->AddChild(pSecondLayoutItem); + if (fCurTopMargin > 0 && pLayoutItem->m_pFirstChild) { + pSecondParent->m_sSize.height += fCurTopMargin; + CXFA_ContentLayoutItem* pParentItem = + (CXFA_ContentLayoutItem*)pSecondParent->m_pParent; + while (pParentItem) { + pParentItem->m_sSize.height += fCurTopMargin; + pParentItem = (CXFA_ContentLayoutItem*)pParentItem->m_pParent; } } - return XFA_ItemLayoutProcessorResult::PageFullBreak; + } else { + pSecondLayoutItem->m_pParent = pLayoutItem->m_pParent; + pSecondLayoutItem->m_pNextSibling = pLayoutItem->m_pNextSibling; + pLayoutItem->m_pNextSibling = pSecondLayoutItem; } - if (*fContentCurRowY <= XFA_LAYOUT_FLOAT_PERCISION) { - childSize = pProcessor->GetCurrentComponentSize(); - if (pProcessor->m_pPageMgr->GetNextAvailContentHeight(childSize.height)) { - CXFA_Node* pTempLeaderNode = nullptr; - CXFA_Node* pTempTrailerNode = nullptr; - if (pThis->m_pPageMgr) { - if (!pFormNode && pLayoutContext) - pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; + CXFA_ContentLayoutItem* pChildren = + (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; + pLayoutItem->m_pFirstChild = nullptr; - pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, - pTempTrailerNode, false, true); + float lHeightForKeep = 0; + float fAddMarginHeight = 0; + std::vector keepLayoutItems; + for (CXFA_ContentLayoutItem *pChildItem = pChildren, *pChildNext = nullptr; + pChildItem; pChildItem = pChildNext) { + pChildNext = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling; + pChildItem->m_pNextSibling = nullptr; + if (fSplitPos <= fCurTopMargin + pChildItem->m_sPos.y + fCurBottomMargin + + XFA_LAYOUT_FLOAT_PERCISION) { + if (!ExistContainerKeep(pChildItem->m_pFormNode, true)) { + pChildItem->m_sPos.y -= fSplitPos - fCurBottomMargin; + pChildItem->m_sPos.y += lHeightForKeep; + pChildItem->m_sPos.y += fAddMarginHeight; + pSecondLayoutItem->AddChild(pChildItem); + continue; } - if (bUseInherited) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - pThis->m_bUseInheriated = true; + if (lHeightForKeep < XFA_LAYOUT_FLOAT_PERCISION) { + for (auto* pPreItem : keepLayoutItems) { + pLayoutItem->RemoveChild(pPreItem); + pPreItem->m_sPos.y -= fSplitPos; + if (pPreItem->m_sPos.y < 0) + pPreItem->m_sPos.y = 0; + if (pPreItem->m_sPos.y + pPreItem->m_sSize.height > lHeightForKeep) { + pPreItem->m_sPos.y = lHeightForKeep; + lHeightForKeep += pPreItem->m_sSize.height; + pSecondLayoutItem->m_sSize.height += pPreItem->m_sSize.height; + if (pSecondParent) + pSecondParent->m_sSize.height += pPreItem->m_sSize.height; + } + pSecondLayoutItem->AddChild(pPreItem); + } } - return XFA_ItemLayoutProcessorResult::PageFullBreak; + pChildItem->m_sPos.y -= fSplitPos; + pChildItem->m_sPos.y += lHeightForKeep; + pChildItem->m_sPos.y += fAddMarginHeight; + pSecondLayoutItem->AddChild(pChildItem); + continue; } - - rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - if (bTakeSpace) { - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); + if (fSplitPos + XFA_LAYOUT_FLOAT_PERCISION >= + fCurTopMargin + fCurBottomMargin + pChildItem->m_sPos.y + + pChildItem->m_sSize.height) { + pLayoutItem->AddChild(pChildItem); + if (ExistContainerKeep(pChildItem->m_pFormNode, false)) + keepLayoutItems.push_back(pChildItem); + else + keepLayoutItems.clear(); + continue; } - if (eRetValue == XFA_ItemLayoutProcessorResult::Done) - *bForceEndPage = false; - return eRetValue; + float fOldHeight = pSecondLayoutItem->m_sSize.height; + SplitLayoutItem( + pChildItem, pSecondLayoutItem, + fSplitPos - fCurTopMargin - fCurBottomMargin - pChildItem->m_sPos.y); + fAddMarginHeight = pSecondLayoutItem->m_sSize.height - fOldHeight; + pLayoutItem->AddChild(pChildItem); } +} - XFA_AttributeEnum eLayout = - pProcessor->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); - if (pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None && - eLayout == XFA_AttributeEnum::Tb) { - if (pThis->m_pPageMgr) { - pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, - pOverflowTrailerNode, false, true); - } - if (pTrailerLayoutItem) - AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem, false); - if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) - AddPendingNode(pProcessor, pOverflowLeaderNode, false); +void CXFA_ItemLayoutProcessor::SplitLayoutItem(float fSplitPos) { + ASSERT(m_pLayoutItem); + SplitLayoutItem(m_pLayoutItem, nullptr, fSplitPos); +} - return XFA_ItemLayoutProcessorResult::PageFullBreak; +CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::ExtractLayoutItem() { + CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem; + if (pLayoutItem) { + m_pLayoutItem = + static_cast(pLayoutItem->m_pNextSibling); + pLayoutItem->m_pNextSibling = nullptr; } - if (eRetValue != XFA_ItemLayoutProcessorResult::Done) - return XFA_ItemLayoutProcessorResult::PageFullBreak; - - if (!pFormNode && pLayoutContext) - pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; - if (pThis->m_pPageMgr) { - pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, - pOverflowTrailerNode, false, true); + if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done || + !ToContentLayoutItem(m_pOldLayoutItem)) { + return pLayoutItem; } - if (bUseInherited) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - pThis->m_bUseInheriated = true; + + if (m_pOldLayoutItem->m_pPrev) + m_pOldLayoutItem->m_pPrev->m_pNext = nullptr; + + CXFA_FFNotify* pNotify = + m_pOldLayoutItem->m_pFormNode->GetDocument()->GetNotify(); + CXFA_LayoutProcessor* pDocLayout = + m_pOldLayoutItem->m_pFormNode->GetDocument()->GetDocLayout(); + CXFA_ContentLayoutItem* pOldLayoutItem = m_pOldLayoutItem; + while (pOldLayoutItem) { + CXFA_ContentLayoutItem* pNextOldLayoutItem = pOldLayoutItem->m_pNext; + pNotify->OnLayoutItemRemoving(pDocLayout, pOldLayoutItem); + if (pOldLayoutItem->m_pParent) + pOldLayoutItem->m_pParent->RemoveChild(pOldLayoutItem); + + delete pOldLayoutItem; + pOldLayoutItem = pNextOldLayoutItem; } - return XFA_ItemLayoutProcessorResult::PageFullBreak; + m_pOldLayoutItem = nullptr; + return pLayoutItem; } -bool FindLayoutItemSplitPos(CXFA_ContentLayoutItem* pLayoutItem, - float fCurVerticalOffset, - float* fProposedSplitPos, - bool* bAppChange, - bool bCalculateMargin) { - CXFA_Node* pFormNode = pLayoutItem->m_pFormNode; - if (*fProposedSplitPos <= fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION || - *fProposedSplitPos > fCurVerticalOffset + pLayoutItem->m_sSize.height - - XFA_LAYOUT_FLOAT_PERCISION) { - return false; +void CXFA_ItemLayoutProcessor::GotoNextContainerNode( + CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages* nCurStage, + CXFA_Node* pParentContainer, + bool bUsePageBreak) { + CXFA_Node* pEntireContainer = pParentContainer; + CXFA_Node* pChildContainer = XFA_LAYOUT_INVALIDNODE; + switch (*nCurStage) { + case XFA_ItemLayoutProcessorStages::BreakBefore: + case XFA_ItemLayoutProcessorStages::BreakAfter: { + pChildContainer = pCurActionNode->GetParent(); + break; + } + case XFA_ItemLayoutProcessorStages::Keep: + case XFA_ItemLayoutProcessorStages::Container: + pChildContainer = pCurActionNode; + break; + default: + pChildContainer = XFA_LAYOUT_INVALIDNODE; + break; } - switch (pFormNode->GetIntact()) { - case XFA_AttributeEnum::None: { - bool bAnyChanged = false; - CXFA_Document* pDocument = pFormNode->GetDocument(); - CXFA_FFNotify* pNotify = pDocument->GetNotify(); - float fCurTopMargin = 0, fCurBottomMargin = 0; - CXFA_Margin* pMarginNode = - pFormNode->GetFirstChildByClass(XFA_Element::Margin); - if (pMarginNode && bCalculateMargin) { - fCurTopMargin = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::TopInset) - .ToUnit(XFA_Unit::Pt); - fCurBottomMargin = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::BottomInset) - .ToUnit(XFA_Unit::Pt); + switch (*nCurStage) { + case XFA_ItemLayoutProcessorStages::Keep: { + CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild(); + if (!m_bKeepBreakFinish && + FindBreakNode(pBreakAfterNode, pCurActionNode, nCurStage, false)) { + return; } - bool bChanged = true; - while (bChanged) { - bChanged = false; - { - float fRelSplitPos = *fProposedSplitPos - fCurVerticalOffset; - if (pFormNode->FindSplitPos(pNotify->GetHDOC()->GetDocView(), - pLayoutItem->GetIndex(), fRelSplitPos)) { - bAnyChanged = true; - bChanged = true; - *fProposedSplitPos = fCurVerticalOffset + fRelSplitPos; - *bAppChange = true; - if (*fProposedSplitPos <= - fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { - return true; - } + goto CheckNextChildContainer; + } + case XFA_ItemLayoutProcessorStages::None: { + pCurActionNode = XFA_LAYOUT_INVALIDNODE; + case XFA_ItemLayoutProcessorStages::BookendLeader: + for (CXFA_Node* pBookendNode = pCurActionNode == XFA_LAYOUT_INVALIDNODE + ? pEntireContainer->GetFirstChild() + : pCurActionNode->GetNextSibling(); + pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) { + switch (pBookendNode->GetElementType()) { + case XFA_Element::Bookend: + case XFA_Element::Break: + pCurActionNode = pBookendNode; + *nCurStage = XFA_ItemLayoutProcessorStages::BookendLeader; + return; + default: + break; } } - float fRelSplitPos = *fProposedSplitPos - fCurBottomMargin; - for (CXFA_ContentLayoutItem* pChildItem = - (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; - pChildItem; - pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { - float fChildOffset = - fCurVerticalOffset + fCurTopMargin + pChildItem->m_sPos.y; - bool bChange = false; - if (FindLayoutItemSplitPos(pChildItem, fChildOffset, &fRelSplitPos, - &bChange, bCalculateMargin)) { - if (fRelSplitPos - fChildOffset < XFA_LAYOUT_FLOAT_PERCISION && - bChange) { - *fProposedSplitPos = fRelSplitPos - fCurTopMargin; - } else { - *fProposedSplitPos = fRelSplitPos + fCurBottomMargin; + } + { + pCurActionNode = XFA_LAYOUT_INVALIDNODE; + case XFA_ItemLayoutProcessorStages::BreakBefore: + if (pCurActionNode != XFA_LAYOUT_INVALIDNODE) { + CXFA_Node* pBreakBeforeNode = pCurActionNode->GetNextSibling(); + if (!m_bKeepBreakFinish && + FindBreakNode(pBreakBeforeNode, pCurActionNode, nCurStage, + true)) { + return; } - bAnyChanged = true; - bChanged = true; - if (*fProposedSplitPos <= - fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { - return true; + if (m_bIsProcessKeep) { + if (ProcessKeepNodesForBreakBefore(pCurActionNode, nCurStage, + pChildContainer)) { + return; + } + goto CheckNextChildContainer; } - if (bAnyChanged) - break; + pCurActionNode = pChildContainer; + *nCurStage = XFA_ItemLayoutProcessorStages::Container; + return; + } + goto CheckNextChildContainer; + } + case XFA_ItemLayoutProcessorStages::Container: { + pCurActionNode = XFA_LAYOUT_INVALIDNODE; + case XFA_ItemLayoutProcessorStages::BreakAfter: { + if (pCurActionNode == XFA_LAYOUT_INVALIDNODE) { + CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild(); + if (!m_bKeepBreakFinish && + FindBreakNode(pBreakAfterNode, pCurActionNode, nCurStage, + false)) { + return; + } + } else { + CXFA_Node* pBreakAfterNode = pCurActionNode->GetNextSibling(); + if (FindBreakNode(pBreakAfterNode, pCurActionNode, nCurStage, + false)) { + return; } } + goto CheckNextChildContainer; } - return bAnyChanged; } - case XFA_AttributeEnum::ContentArea: - case XFA_AttributeEnum::PageArea: { - *fProposedSplitPos = fCurVerticalOffset; - return true; + + CheckNextChildContainer : { + CXFA_Node* pNextChildContainer = + pChildContainer == XFA_LAYOUT_INVALIDNODE + ? pEntireContainer->GetFirstContainerChild() + : pChildContainer->GetNextContainerSibling(); + while (pNextChildContainer && + pNextChildContainer->IsLayoutGeneratedNode()) { + CXFA_Node* pSaveNode = pNextChildContainer; + pNextChildContainer = pNextChildContainer->GetNextContainerSibling(); + if (pSaveNode->IsUnusedNode()) + DeleteLayoutGeneratedNode(pSaveNode); + } + if (!pNextChildContainer) + goto NoMoreChildContainer; + + bool bLastKeep = false; + if (ProcessKeepNodesForCheckNext(pCurActionNode, nCurStage, + pNextChildContainer, bLastKeep)) { + return; + } + if (!m_bKeepBreakFinish && !bLastKeep && + FindBreakNode(pNextChildContainer->GetFirstChild(), pCurActionNode, + nCurStage, true)) { + return; + } + pCurActionNode = pNextChildContainer; + if (m_bIsProcessKeep) + *nCurStage = XFA_ItemLayoutProcessorStages::Keep; + else + *nCurStage = XFA_ItemLayoutProcessorStages::Container; + return; + } + + NoMoreChildContainer : { + pCurActionNode = XFA_LAYOUT_INVALIDNODE; + case XFA_ItemLayoutProcessorStages::BookendTrailer: + for (CXFA_Node* pBookendNode = pCurActionNode == XFA_LAYOUT_INVALIDNODE + ? pEntireContainer->GetFirstChild() + : pCurActionNode->GetNextSibling(); + pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) { + switch (pBookendNode->GetElementType()) { + case XFA_Element::Bookend: + case XFA_Element::Break: + pCurActionNode = pBookendNode; + *nCurStage = XFA_ItemLayoutProcessorStages::BookendTrailer; + return; + default: + break; + } + } } default: - return false; + pCurActionNode = nullptr; + *nCurStage = XFA_ItemLayoutProcessorStages::Done; } } -CFX_PointF CalculatePositionedContainerPos(CXFA_Node* pNode, - const CFX_SizeF& size) { - XFA_AttributeEnum eAnchorType = - pNode->JSObject()->GetEnum(XFA_Attribute::AnchorType); - int32_t nAnchorType = 0; - switch (eAnchorType) { - case XFA_AttributeEnum::TopLeft: - nAnchorType = 0; - break; - case XFA_AttributeEnum::TopCenter: - nAnchorType = 1; - break; - case XFA_AttributeEnum::TopRight: - nAnchorType = 2; - break; - case XFA_AttributeEnum::MiddleLeft: - nAnchorType = 3; - break; - case XFA_AttributeEnum::MiddleCenter: - nAnchorType = 4; - break; - case XFA_AttributeEnum::MiddleRight: - nAnchorType = 5; - break; - case XFA_AttributeEnum::BottomLeft: - nAnchorType = 6; - break; - case XFA_AttributeEnum::BottomCenter: - nAnchorType = 7; - break; - case XFA_AttributeEnum::BottomRight: - nAnchorType = 8; - break; - default: - break; - } - static const uint8_t nNextPos[4][9] = {{0, 1, 2, 3, 4, 5, 6, 7, 8}, - {6, 3, 0, 7, 4, 1, 8, 5, 2}, - {8, 7, 6, 5, 4, 3, 2, 1, 0}, - {2, 5, 8, 1, 4, 7, 0, 3, 6}}; +bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForCheckNext( + CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages* nCurStage, + CXFA_Node*& pNextContainer, + bool& bLastKeepNode) { + const bool bCanSplit = pNextContainer->GetIntact() == XFA_AttributeEnum::None; + bool bNextKeep = false; + if (ExistContainerKeep(pNextContainer, false)) + bNextKeep = true; - CFX_PointF pos( - pNode->JSObject()->GetMeasure(XFA_Attribute::X).ToUnit(XFA_Unit::Pt), - pNode->JSObject()->GetMeasure(XFA_Attribute::Y).ToUnit(XFA_Unit::Pt)); - int32_t nRotate = - XFA_MapRotation(pNode->JSObject()->GetInteger(XFA_Attribute::Rotate)) / - 90; - int32_t nAbsoluteAnchorType = nNextPos[nRotate][nAnchorType]; - switch (nAbsoluteAnchorType / 3) { - case 1: - pos.y -= size.height / 2; - break; - case 2: - pos.y -= size.height; - break; - default: - break; + if (bNextKeep && !bCanSplit) { + if (!m_bIsProcessKeep && !m_bKeepBreakFinish) { + m_pKeepHeadNode = pNextContainer; + m_bIsProcessKeep = true; + } + return false; } - switch (nAbsoluteAnchorType % 3) { - case 1: - pos.x -= size.width / 2; - break; - case 2: - pos.x -= size.width; - break; - default: - break; + + if (m_bIsProcessKeep && m_pKeepHeadNode) { + m_pKeepTailNode = pNextContainer; + if (!m_bKeepBreakFinish && FindBreakNode(pNextContainer->GetFirstChild(), + pCurActionNode, nCurStage, true)) { + return true; + } + + pNextContainer = m_pKeepHeadNode; + m_bKeepBreakFinish = true; + m_pKeepHeadNode = nullptr; + m_pKeepTailNode = nullptr; + m_bIsProcessKeep = false; + } else { + if (m_bKeepBreakFinish) + bLastKeepNode = true; + m_bKeepBreakFinish = false; } - return pos; + + return false; } -} // namespace +bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForBreakBefore( + CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages* nCurStage, + CXFA_Node* pContainerNode) { + if (m_pKeepTailNode == pContainerNode) { + pCurActionNode = m_pKeepHeadNode; + m_bKeepBreakFinish = true; + m_pKeepHeadNode = nullptr; + m_pKeepTailNode = nullptr; + m_bIsProcessKeep = false; + *nCurStage = XFA_ItemLayoutProcessorStages::Container; + return true; + } -CXFA_ItemLayoutProcessor::CXFA_ItemLayoutProcessor(CXFA_Node* pNode, - CXFA_LayoutPageMgr* pPageMgr) - : m_pFormNode(pNode), - m_pLayoutItem(nullptr), - m_pCurChildNode(XFA_LAYOUT_INVALIDNODE), - m_fUsedSize(0), - m_pPageMgr(pPageMgr), - m_bBreakPending(true), - m_fLastRowWidth(0), - m_fLastRowY(0), - m_bUseInheriated(false), - m_ePreProcessRs(XFA_ItemLayoutProcessorResult::Done), - m_bKeepBreakFinish(false), - m_bIsProcessKeep(false), - m_pKeepHeadNode(nullptr), - m_pKeepTailNode(nullptr), - m_pOldLayoutItem(nullptr), - m_pCurChildPreprocessor(nullptr), - m_nCurChildNodeStage(XFA_ItemLayoutProcessorStages::None), - m_fWidthLimite(0), - m_bHasAvailHeight(true) { - ASSERT(m_pFormNode && (m_pFormNode->IsContainerNode() || - m_pFormNode->GetElementType() == XFA_Element::Form)); - m_pOldLayoutItem = static_cast( - m_pFormNode->JSObject()->GetLayoutItem()); + CXFA_Node* pBreakAfterNode = pContainerNode->GetFirstChild(); + return FindBreakNode(pBreakAfterNode, pCurActionNode, nCurStage, false); } -CXFA_ItemLayoutProcessor::~CXFA_ItemLayoutProcessor() {} +void CXFA_ItemLayoutProcessor::DoLayoutPageArea( + CXFA_ContainerLayoutItem* pPageAreaLayoutItem) { + CXFA_Node* pFormNode = pPageAreaLayoutItem->m_pFormNode; + CXFA_Node* pCurChildNode = XFA_LAYOUT_INVALIDNODE; + XFA_ItemLayoutProcessorStages nCurChildNodeStage = + XFA_ItemLayoutProcessorStages::None; + CXFA_LayoutItem* pBeforeItem = nullptr; + for (GotoNextContainerNode(pCurChildNode, &nCurChildNodeStage, pFormNode, + false); + pCurChildNode; GotoNextContainerNode(pCurChildNode, &nCurChildNodeStage, + pFormNode, false)) { + if (nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) + continue; + if (pCurChildNode->GetElementType() == XFA_Element::Variables) + continue; -CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::CreateContentLayoutItem( - CXFA_Node* pFormNode) { - if (!pFormNode) - return nullptr; + auto pProcessor = + pdfium::MakeUnique(pCurChildNode, nullptr); + pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); + if (!pProcessor->HasLayoutItem()) + continue; - CXFA_ContentLayoutItem* pLayoutItem = nullptr; - if (m_pOldLayoutItem) { - pLayoutItem = m_pOldLayoutItem; - m_pOldLayoutItem = m_pOldLayoutItem->m_pNext; - return pLayoutItem; - } - pLayoutItem = - pFormNode->GetDocument()->GetNotify()->OnCreateContentLayoutItem( - pFormNode); - CXFA_ContentLayoutItem* pPrevLayoutItem = - static_cast( - pFormNode->JSObject()->GetLayoutItem()); - if (pPrevLayoutItem) { - while (pPrevLayoutItem->m_pNext) - pPrevLayoutItem = pPrevLayoutItem->m_pNext; + pProcessor->SetCurrentComponentPos(CalculatePositionedContainerPos( + pCurChildNode, pProcessor->GetCurrentComponentSize())); + CXFA_LayoutItem* pProcessItem = pProcessor->ExtractLayoutItem(); + if (!pBeforeItem) + pPageAreaLayoutItem->AddHeadChild(pProcessItem); + else + pPageAreaLayoutItem->InsertChild(pBeforeItem, pProcessItem); - pPrevLayoutItem->m_pNext = pLayoutItem; - pLayoutItem->m_pPrev = pPrevLayoutItem; - } else { - pFormNode->JSObject()->SetLayoutItem(pLayoutItem); + pBeforeItem = pProcessItem; } - return pLayoutItem; -} -float CXFA_ItemLayoutProcessor::FindSplitPos(float fProposedSplitPos) { - ASSERT(m_pLayoutItem); - XFA_AttributeEnum eLayout = m_pFormNode->JSObject() - ->TryEnum(XFA_Attribute::Layout, true) - .value_or(XFA_AttributeEnum::Position); - bool bCalculateMargin = eLayout != XFA_AttributeEnum::Position; - while (fProposedSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { - bool bAppChange = false; - if (!FindLayoutItemSplitPos(m_pLayoutItem, 0, &fProposedSplitPos, - &bAppChange, bCalculateMargin)) { - break; + pBeforeItem = nullptr; + CXFA_LayoutItem* pLayoutItem = pPageAreaLayoutItem->m_pFirstChild; + while (pLayoutItem) { + if (!pLayoutItem->IsContentLayoutItem() || + pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) { + pLayoutItem = pLayoutItem->m_pNextSibling; + continue; } - } - return fProposedSplitPos; -} + if (pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) + continue; -void CXFA_ItemLayoutProcessor::SplitLayoutItem( - CXFA_ContentLayoutItem* pLayoutItem, - CXFA_ContentLayoutItem* pSecondParent, - float fSplitPos) { - float fCurTopMargin = 0, fCurBottomMargin = 0; - XFA_AttributeEnum eLayout = m_pFormNode->JSObject() - ->TryEnum(XFA_Attribute::Layout, true) - .value_or(XFA_AttributeEnum::Position); - bool bCalculateMargin = true; - if (eLayout == XFA_AttributeEnum::Position) - bCalculateMargin = false; + CXFA_LayoutItem* pNextLayoutItem = pLayoutItem->m_pNextSibling; + pPageAreaLayoutItem->RemoveChild(pLayoutItem); + if (!pBeforeItem) + pPageAreaLayoutItem->AddHeadChild(pLayoutItem); + else + pPageAreaLayoutItem->InsertChild(pBeforeItem, pLayoutItem); - CXFA_Margin* pMarginNode = - pLayoutItem->m_pFormNode->GetFirstChildByClass( - XFA_Element::Margin); - if (pMarginNode && bCalculateMargin) { - fCurTopMargin = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::TopInset) - .ToUnit(XFA_Unit::Pt); - fCurBottomMargin = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::BottomInset) - .ToUnit(XFA_Unit::Pt); + pBeforeItem = pLayoutItem; + pLayoutItem = pNextLayoutItem; } +} - CXFA_ContentLayoutItem* pSecondLayoutItem = nullptr; - if (m_pCurChildPreprocessor && - m_pCurChildPreprocessor->m_pFormNode == pLayoutItem->m_pFormNode) { - pSecondLayoutItem = m_pCurChildPreprocessor->CreateContentLayoutItem( - pLayoutItem->m_pFormNode); - } else { - pSecondLayoutItem = CreateContentLayoutItem(pLayoutItem->m_pFormNode); - } - pSecondLayoutItem->m_sPos.x = pLayoutItem->m_sPos.x; - pSecondLayoutItem->m_sSize.width = pLayoutItem->m_sSize.width; - pSecondLayoutItem->m_sPos.y = 0; - pSecondLayoutItem->m_sSize.height = pLayoutItem->m_sSize.height - fSplitPos; - pLayoutItem->m_sSize.height -= pSecondLayoutItem->m_sSize.height; - if (pLayoutItem->m_pFirstChild) - pSecondLayoutItem->m_sSize.height += fCurTopMargin; +void CXFA_ItemLayoutProcessor::DoLayoutPositionedContainer( + CXFA_LayoutContext* pContext) { + if (m_pLayoutItem) + return; - if (pSecondParent) { - pSecondParent->AddChild(pSecondLayoutItem); - if (fCurTopMargin > 0 && pLayoutItem->m_pFirstChild) { - pSecondParent->m_sSize.height += fCurTopMargin; - CXFA_ContentLayoutItem* pParentItem = - (CXFA_ContentLayoutItem*)pSecondParent->m_pParent; - while (pParentItem) { - pParentItem->m_sSize.height += fCurTopMargin; - pParentItem = (CXFA_ContentLayoutItem*)pParentItem->m_pParent; - } - } - } else { - pSecondLayoutItem->m_pParent = pLayoutItem->m_pParent; - pSecondLayoutItem->m_pNextSibling = pLayoutItem->m_pNextSibling; - pLayoutItem->m_pNextSibling = pSecondLayoutItem; + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + bool bIgnoreXY = (m_pFormNode->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position) != + XFA_AttributeEnum::Position); + bool bContainerWidthAutoSize = true; + bool bContainerHeightAutoSize = true; + CFX_SizeF containerSize = CalculateContainerSpecifiedSize( + m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); + + float fContentCalculatedWidth = 0; + float fContentCalculatedHeight = 0; + float fHiddenContentCalculatedWidth = 0; + float fHiddenContentCalculatedHeight = 0; + if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { + GotoNextContainerNode(m_pCurChildNode, &m_nCurChildNodeStage, m_pFormNode, + false); } - CXFA_ContentLayoutItem* pChildren = - (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; - pLayoutItem->m_pFirstChild = nullptr; + int32_t iColIndex = 0; + for (; m_pCurChildNode; GotoNextContainerNode( + m_pCurChildNode, &m_nCurChildNodeStage, m_pFormNode, false)) { + if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) + continue; + if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) + continue; - float lHeightForKeep = 0; - float fAddMarginHeight = 0; - std::vector keepLayoutItems; - for (CXFA_ContentLayoutItem *pChildItem = pChildren, *pChildNext = nullptr; - pChildItem; pChildItem = pChildNext) { - pChildNext = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling; - pChildItem->m_pNextSibling = nullptr; - if (fSplitPos <= fCurTopMargin + pChildItem->m_sPos.y + fCurBottomMargin + - XFA_LAYOUT_FLOAT_PERCISION) { - if (!ExistContainerKeep(pChildItem->m_pFormNode, true)) { - pChildItem->m_sPos.y -= fSplitPos - fCurBottomMargin; - pChildItem->m_sPos.y += lHeightForKeep; - pChildItem->m_sPos.y += fAddMarginHeight; - pSecondLayoutItem->AddChild(pChildItem); - continue; - } - if (lHeightForKeep < XFA_LAYOUT_FLOAT_PERCISION) { - for (auto* pPreItem : keepLayoutItems) { - pLayoutItem->RemoveChild(pPreItem); - pPreItem->m_sPos.y -= fSplitPos; - if (pPreItem->m_sPos.y < 0) - pPreItem->m_sPos.y = 0; - if (pPreItem->m_sPos.y + pPreItem->m_sSize.height > lHeightForKeep) { - pPreItem->m_sPos.y = lHeightForKeep; - lHeightForKeep += pPreItem->m_sSize.height; - pSecondLayoutItem->m_sSize.height += pPreItem->m_sSize.height; - if (pSecondParent) - pSecondParent->m_sSize.height += pPreItem->m_sSize.height; - } - pSecondLayoutItem->AddChild(pPreItem); + auto pProcessor = pdfium::MakeUnique( + m_pCurChildNode, m_pPageMgr); + if (pContext && pContext->m_prgSpecifiedColumnWidths) { + int32_t iColSpan = + m_pCurChildNode->JSObject()->GetInteger(XFA_Attribute::ColSpan); + if (iColSpan <= pdfium::CollectionSize( + *pContext->m_prgSpecifiedColumnWidths) - + iColIndex) { + pContext->m_fCurColumnWidth = 0; + pContext->m_bCurColumnWidthAvaiable = true; + if (iColSpan == -1) { + iColSpan = pdfium::CollectionSize( + *pContext->m_prgSpecifiedColumnWidths); + } + for (int32_t i = 0; iColIndex + i < iColSpan; ++i) { + pContext->m_fCurColumnWidth += + (*pContext->m_prgSpecifiedColumnWidths)[iColIndex + i]; } + if (pContext->m_fCurColumnWidth == 0) + pContext->m_bCurColumnWidthAvaiable = false; + + iColIndex += iColSpan >= 0 ? iColSpan : 0; } - pChildItem->m_sPos.y -= fSplitPos; - pChildItem->m_sPos.y += lHeightForKeep; - pChildItem->m_sPos.y += fAddMarginHeight; - pSecondLayoutItem->AddChild(pChildItem); - continue; - } - if (fSplitPos + XFA_LAYOUT_FLOAT_PERCISION >= - fCurTopMargin + fCurBottomMargin + pChildItem->m_sPos.y + - pChildItem->m_sSize.height) { - pLayoutItem->AddChild(pChildItem); - if (ExistContainerKeep(pChildItem->m_pFormNode, false)) - keepLayoutItems.push_back(pChildItem); - else - keepLayoutItems.clear(); - continue; } - float fOldHeight = pSecondLayoutItem->m_sSize.height; - SplitLayoutItem( - pChildItem, pSecondLayoutItem, - fSplitPos - fCurTopMargin - fCurBottomMargin - pChildItem->m_sPos.y); - fAddMarginHeight = pSecondLayoutItem->m_sSize.height - fOldHeight; - pLayoutItem->AddChild(pChildItem); + pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pContext); + if (!pProcessor->HasLayoutItem()) + continue; + + CFX_SizeF size = pProcessor->GetCurrentComponentSize(); + bool bChangeParentSize = false; + if (m_pCurChildNode->PresenceRequiresSpace()) + bChangeParentSize = true; + + CFX_PointF absolutePos; + if (!bIgnoreXY) + absolutePos = CalculatePositionedContainerPos(m_pCurChildNode, size); + + pProcessor->SetCurrentComponentPos(absolutePos); + if (bContainerWidthAutoSize) { + float fChildSuppliedWidth = absolutePos.x + size.width; + if (bChangeParentSize) { + fContentCalculatedWidth = + std::max(fContentCalculatedWidth, fChildSuppliedWidth); + } else { + if (fHiddenContentCalculatedWidth < fChildSuppliedWidth && + m_pCurChildNode->GetElementType() != XFA_Element::Subform) { + fHiddenContentCalculatedWidth = fChildSuppliedWidth; + } + } + } + + if (bContainerHeightAutoSize) { + float fChildSuppliedHeight = absolutePos.y + size.height; + if (bChangeParentSize) { + fContentCalculatedHeight = + std::max(fContentCalculatedHeight, fChildSuppliedHeight); + } else { + if (fHiddenContentCalculatedHeight < fChildSuppliedHeight && + m_pCurChildNode->GetElementType() != XFA_Element::Subform) { + fHiddenContentCalculatedHeight = fChildSuppliedHeight; + } + } + } + m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); } -} -void CXFA_ItemLayoutProcessor::SplitLayoutItem(float fSplitPos) { - ASSERT(m_pLayoutItem); - SplitLayoutItem(m_pLayoutItem, nullptr, fSplitPos); + XFA_VERSION eVersion = m_pFormNode->GetDocument()->GetCurVersionMode(); + if (fContentCalculatedWidth == 0 && eVersion < XFA_VERSION_207) + fContentCalculatedWidth = fHiddenContentCalculatedWidth; + if (fContentCalculatedHeight == 0 && eVersion < XFA_VERSION_207) + fContentCalculatedHeight = fHiddenContentCalculatedHeight; + + containerSize = CalculateContainerComponentSizeFromContentSize( + m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, + bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); + SetCurrentComponentSize(containerSize); } -CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::ExtractLayoutItem() { - CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem; - if (pLayoutItem) { - m_pLayoutItem = - static_cast(pLayoutItem->m_pNextSibling); - pLayoutItem->m_pNextSibling = nullptr; - } +void CXFA_ItemLayoutProcessor::DoLayoutTableContainer(CXFA_Node* pLayoutNode) { + if (m_pLayoutItem) + return; + if (!pLayoutNode) + pLayoutNode = m_pFormNode; - if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done || - !ToContentLayoutItem(m_pOldLayoutItem)) { - return pLayoutItem; + ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); + + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + bool bContainerWidthAutoSize = true; + bool bContainerHeightAutoSize = true; + CFX_SizeF containerSize = CalculateContainerSpecifiedSize( + m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); + float fContentCalculatedWidth = 0; + float fContentCalculatedHeight = 0; + CXFA_Margin* pMarginNode = + m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); + float fLeftInset = 0; + float fRightInset = 0; + if (pMarginNode) { + fLeftInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt); + fRightInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::RightInset) + .ToUnit(XFA_Unit::Pt); } - if (m_pOldLayoutItem->m_pPrev) - m_pOldLayoutItem->m_pPrev->m_pNext = nullptr; + float fContentWidthLimit = + bContainerWidthAutoSize ? FLT_MAX + : containerSize.width - fLeftInset - fRightInset; + WideString wsColumnWidths = + pLayoutNode->JSObject()->GetCData(XFA_Attribute::ColumnWidths); + if (!wsColumnWidths.IsEmpty()) { + auto widths = SeparateStringW(wsColumnWidths.c_str(), + wsColumnWidths.GetLength(), L' '); + for (auto& width : widths) { + width.TrimLeft(L' '); + if (width.IsEmpty()) + continue; - CXFA_FFNotify* pNotify = - m_pOldLayoutItem->m_pFormNode->GetDocument()->GetNotify(); - CXFA_LayoutProcessor* pDocLayout = - m_pOldLayoutItem->m_pFormNode->GetDocument()->GetDocLayout(); - CXFA_ContentLayoutItem* pOldLayoutItem = m_pOldLayoutItem; - while (pOldLayoutItem) { - CXFA_ContentLayoutItem* pNextOldLayoutItem = pOldLayoutItem->m_pNext; - pNotify->OnLayoutItemRemoving(pDocLayout, pOldLayoutItem); - if (pOldLayoutItem->m_pParent) - pOldLayoutItem->m_pParent->RemoveChild(pOldLayoutItem); + m_rgSpecifiedColumnWidths.push_back( + CXFA_Measurement(width.AsStringView()).ToUnit(XFA_Unit::Pt)); + } + } - delete pOldLayoutItem; - pOldLayoutItem = pNextOldLayoutItem; + int32_t iSpecifiedColumnCount = + pdfium::CollectionSize(m_rgSpecifiedColumnWidths); + CXFA_LayoutContext layoutContext; + layoutContext.m_prgSpecifiedColumnWidths = &m_rgSpecifiedColumnWidths; + CXFA_LayoutContext* pLayoutContext = + iSpecifiedColumnCount > 0 ? &layoutContext : nullptr; + if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { + GotoNextContainerNode(m_pCurChildNode, &m_nCurChildNodeStage, m_pFormNode, + false); } - m_pOldLayoutItem = nullptr; - return pLayoutItem; -} -void CXFA_ItemLayoutProcessor::GotoNextContainerNode( - CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node* pParentContainer, - bool bUsePageBreak) { - CXFA_Node* pEntireContainer = pParentContainer; - CXFA_Node* pChildContainer = XFA_LAYOUT_INVALIDNODE; - switch (nCurStage) { - case XFA_ItemLayoutProcessorStages::BreakBefore: - case XFA_ItemLayoutProcessorStages::BreakAfter: { - pChildContainer = pCurActionNode->GetParent(); - break; - } - case XFA_ItemLayoutProcessorStages::Keep: - case XFA_ItemLayoutProcessorStages::Container: - pChildContainer = pCurActionNode; - break; - default: - pChildContainer = XFA_LAYOUT_INVALIDNODE; - break; + for (; m_pCurChildNode; GotoNextContainerNode( + m_pCurChildNode, &m_nCurChildNodeStage, m_pFormNode, false)) { + layoutContext.m_bCurColumnWidthAvaiable = false; + layoutContext.m_fCurColumnWidth = 0; + if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) + continue; + + auto pProcessor = pdfium::MakeUnique( + m_pCurChildNode, m_pPageMgr); + pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pLayoutContext); + if (!pProcessor->HasLayoutItem()) + continue; + + m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); } - switch (nCurStage) { - case XFA_ItemLayoutProcessorStages::Keep: { - CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild(); - if (!m_bKeepBreakFinish && - FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, false)) { - return; - } - goto CheckNextChildContainer; - } - case XFA_ItemLayoutProcessorStages::None: { - pCurActionNode = XFA_LAYOUT_INVALIDNODE; - case XFA_ItemLayoutProcessorStages::BookendLeader: - for (CXFA_Node* pBookendNode = pCurActionNode == XFA_LAYOUT_INVALIDNODE - ? pEntireContainer->GetFirstChild() - : pCurActionNode->GetNextSibling(); - pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) { - switch (pBookendNode->GetElementType()) { - case XFA_Element::Bookend: - case XFA_Element::Break: - pCurActionNode = pBookendNode; - nCurStage = XFA_ItemLayoutProcessorStages::BookendLeader; - return; - default: - break; - } - } - } - { - pCurActionNode = XFA_LAYOUT_INVALIDNODE; - case XFA_ItemLayoutProcessorStages::BreakBefore: - if (pCurActionNode != XFA_LAYOUT_INVALIDNODE) { - CXFA_Node* pBreakBeforeNode = pCurActionNode->GetNextSibling(); - if (!m_bKeepBreakFinish && - FindBreakNode(pBreakBeforeNode, pCurActionNode, &nCurStage, - true)) { - return; - } - if (m_bIsProcessKeep) { - if (ProcessKeepNodesForBreakBefore(pCurActionNode, nCurStage, - pChildContainer)) { - return; - } - goto CheckNextChildContainer; - } - pCurActionNode = pChildContainer; - nCurStage = XFA_ItemLayoutProcessorStages::Container; - return; - } - goto CheckNextChildContainer; + int32_t iRowCount = 0; + int32_t iColCount = 0; + { + std::vector rgRowItems; + std::vector rgRowItemsSpan; + std::vector rgRowItemsWidth; + for (auto* pLayoutChild = + static_cast(m_pLayoutItem->m_pFirstChild); + pLayoutChild; pLayoutChild = static_cast( + pLayoutChild->m_pNextSibling)) { + if (pLayoutChild->m_pFormNode->GetElementType() != XFA_Element::Subform) + continue; + if (!pLayoutChild->m_pFormNode->PresenceRequiresSpace()) + continue; + + XFA_AttributeEnum eLayout = + pLayoutChild->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + if (eLayout != XFA_AttributeEnum::Row && + eLayout != XFA_AttributeEnum::Rl_row) { + continue; } - case XFA_ItemLayoutProcessorStages::Container: { - pCurActionNode = XFA_LAYOUT_INVALIDNODE; - case XFA_ItemLayoutProcessorStages::BreakAfter: { - if (pCurActionNode == XFA_LAYOUT_INVALIDNODE) { - CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild(); - if (!m_bKeepBreakFinish && - FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, - false)) { - return; - } - } else { - CXFA_Node* pBreakAfterNode = pCurActionNode->GetNextSibling(); - if (FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, - false)) { - return; - } - } - goto CheckNextChildContainer; + if (CXFA_ContentLayoutItem* pRowLayoutCell = + (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild) { + rgRowItems.push_back(pRowLayoutCell); + int32_t iColSpan = pRowLayoutCell->m_pFormNode->JSObject()->GetInteger( + XFA_Attribute::ColSpan); + rgRowItemsSpan.push_back(iColSpan); + rgRowItemsWidth.push_back(pRowLayoutCell->m_sSize.width); } } - CheckNextChildContainer : { - CXFA_Node* pNextChildContainer = - pChildContainer == XFA_LAYOUT_INVALIDNODE - ? pEntireContainer->GetFirstContainerChild() - : pChildContainer->GetNextContainerSibling(); - while (pNextChildContainer && - pNextChildContainer->IsLayoutGeneratedNode()) { - CXFA_Node* pSaveNode = pNextChildContainer; - pNextChildContainer = pNextChildContainer->GetNextContainerSibling(); - if (pSaveNode->IsUnusedNode()) - DeleteLayoutGeneratedNode(pSaveNode); - } - if (!pNextChildContainer) - goto NoMoreChildContainer; + iRowCount = pdfium::CollectionSize(rgRowItems); + iColCount = 0; + bool bMoreColumns = true; + while (bMoreColumns) { + bMoreColumns = false; + bool bAutoCol = false; + for (int32_t i = 0; i < iRowCount; i++) { + while (rgRowItems[i] && + (rgRowItemsSpan[i] <= 0 || + !rgRowItems[i]->m_pFormNode->PresenceRequiresSpace())) { + CXFA_ContentLayoutItem* pNewCell = + (CXFA_ContentLayoutItem*)rgRowItems[i]->m_pNextSibling; + if (rgRowItemsSpan[i] < 0 && + rgRowItems[i]->m_pFormNode->PresenceRequiresSpace()) { + pNewCell = nullptr; + } + rgRowItems[i] = pNewCell; + rgRowItemsSpan[i] = + pNewCell ? pNewCell->m_pFormNode->JSObject()->GetInteger( + XFA_Attribute::ColSpan) + : 0; + rgRowItemsWidth[i] = pNewCell ? pNewCell->m_sSize.width : 0; + } + CXFA_ContentLayoutItem* pCell = rgRowItems[i]; + if (!pCell) + continue; - bool bLastKeep = false; - if (ProcessKeepNodesForCheckNext(pCurActionNode, nCurStage, - pNextChildContainer, bLastKeep)) { - return; - } - if (!m_bKeepBreakFinish && !bLastKeep && - FindBreakNode(pNextChildContainer->GetFirstChild(), pCurActionNode, - &nCurStage, true)) { - return; - } - pCurActionNode = pNextChildContainer; - if (m_bIsProcessKeep) - nCurStage = XFA_ItemLayoutProcessorStages::Keep; - else - nCurStage = XFA_ItemLayoutProcessorStages::Container; - return; - } + bMoreColumns = true; + if (rgRowItemsSpan[i] != 1) + continue; - NoMoreChildContainer : { - pCurActionNode = XFA_LAYOUT_INVALIDNODE; - case XFA_ItemLayoutProcessorStages::BookendTrailer: - for (CXFA_Node* pBookendNode = pCurActionNode == XFA_LAYOUT_INVALIDNODE - ? pEntireContainer->GetFirstChild() - : pCurActionNode->GetNextSibling(); - pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) { - switch (pBookendNode->GetElementType()) { - case XFA_Element::Bookend: - case XFA_Element::Break: - pCurActionNode = pBookendNode; - nCurStage = XFA_ItemLayoutProcessorStages::BookendTrailer; - return; - default: - break; - } + if (iColCount >= iSpecifiedColumnCount) { + int32_t c = + iColCount + 1 - + pdfium::CollectionSize(m_rgSpecifiedColumnWidths); + for (int32_t j = 0; j < c; j++) + m_rgSpecifiedColumnWidths.push_back(0); + } + if (m_rgSpecifiedColumnWidths[iColCount] < XFA_LAYOUT_FLOAT_PERCISION) + bAutoCol = true; + if (bAutoCol && + m_rgSpecifiedColumnWidths[iColCount] < rgRowItemsWidth[i]) { + m_rgSpecifiedColumnWidths[iColCount] = rgRowItemsWidth[i]; } + } + + if (!bMoreColumns) + continue; + + float fFinalColumnWidth = 0.0f; + if (pdfium::IndexInBounds(m_rgSpecifiedColumnWidths, iColCount)) + fFinalColumnWidth = m_rgSpecifiedColumnWidths[iColCount]; + + for (int32_t i = 0; i < iRowCount; ++i) { + if (!rgRowItems[i]) + continue; + --rgRowItemsSpan[i]; + rgRowItemsWidth[i] -= fFinalColumnWidth; + } + ++iColCount; } - default: - pCurActionNode = nullptr; - nCurStage = XFA_ItemLayoutProcessorStages::Done; } -} -bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForCheckNext( - CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node*& pNextContainer, - bool& bLastKeepNode) { - const bool bCanSplit = pNextContainer->GetIntact() == XFA_AttributeEnum::None; - bool bNextKeep = false; - if (ExistContainerKeep(pNextContainer, false)) - bNextKeep = true; + float fCurrentRowY = 0; + for (CXFA_ContentLayoutItem* pLayoutChild = + (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + pLayoutChild; + pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { + if (!pLayoutChild->m_pFormNode->PresenceRequiresSpace()) + continue; - if (bNextKeep && !bCanSplit) { - if (!m_bIsProcessKeep && !m_bKeepBreakFinish) { - m_pKeepHeadNode = pNextContainer; - m_bIsProcessKeep = true; + if (pLayoutChild->m_pFormNode->GetElementType() == XFA_Element::Subform) { + XFA_AttributeEnum eSubformLayout = + pLayoutChild->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + if (eSubformLayout == XFA_AttributeEnum::Row || + eSubformLayout == XFA_AttributeEnum::Rl_row) { + RelocateTableRowCells(pLayoutChild, m_rgSpecifiedColumnWidths, + eSubformLayout); + } } - return false; - } - if (m_bIsProcessKeep && m_pKeepHeadNode) { - m_pKeepTailNode = pNextContainer; - if (!m_bKeepBreakFinish && - FindBreakNode(pNextContainer->GetFirstChild(), pCurActionNode, - &nCurStage, true)) { - return true; + pLayoutChild->m_sPos.y = fCurrentRowY; + if (bContainerWidthAutoSize) { + pLayoutChild->m_sPos.x = 0; + } else { + switch (pLayoutChild->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::HAlign)) { + case XFA_AttributeEnum::Center: + pLayoutChild->m_sPos.x = + (fContentWidthLimit - pLayoutChild->m_sSize.width) / 2; + break; + case XFA_AttributeEnum::Right: + pLayoutChild->m_sPos.x = + fContentWidthLimit - pLayoutChild->m_sSize.width; + break; + case XFA_AttributeEnum::Left: + default: + pLayoutChild->m_sPos.x = 0; + break; + } } - pNextContainer = m_pKeepHeadNode; - m_bKeepBreakFinish = true; - m_pKeepHeadNode = nullptr; - m_pKeepTailNode = nullptr; - m_bIsProcessKeep = false; - } else { - if (m_bKeepBreakFinish) - bLastKeepNode = true; - m_bKeepBreakFinish = false; + if (bContainerWidthAutoSize) { + float fChildSuppliedWidth = + pLayoutChild->m_sPos.x + pLayoutChild->m_sSize.width; + if (fContentWidthLimit < FLT_MAX && + fContentWidthLimit > fChildSuppliedWidth) { + fChildSuppliedWidth = fContentWidthLimit; + } + fContentCalculatedWidth = + std::max(fContentCalculatedWidth, fChildSuppliedWidth); + } + fCurrentRowY += pLayoutChild->m_sSize.height; } - return false; -} - -bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForBreakBefore( - CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node* pContainerNode) { - if (m_pKeepTailNode == pContainerNode) { - pCurActionNode = m_pKeepHeadNode; - m_bKeepBreakFinish = true; - m_pKeepHeadNode = nullptr; - m_pKeepTailNode = nullptr; - m_bIsProcessKeep = false; - nCurStage = XFA_ItemLayoutProcessorStages::Container; - return true; - } + if (bContainerHeightAutoSize) + fContentCalculatedHeight = std::max(fContentCalculatedHeight, fCurrentRowY); - CXFA_Node* pBreakAfterNode = pContainerNode->GetFirstChild(); - return FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, false); + containerSize = CalculateContainerComponentSizeFromContentSize( + m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, + bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); + SetCurrentComponentSize(containerSize); } -bool CXFA_ItemLayoutProcessor::IncrementRelayoutNode( - CXFA_LayoutProcessor* pLayoutProcessor, - CXFA_Node* pNode, - CXFA_Node* pParentNode) { - return false; -} +bool CXFA_ItemLayoutProcessor::IsAddNewRowForTrailer( + CXFA_ContentLayoutItem* pTrailerItem) { + if (!pTrailerItem) + return false; -void CXFA_ItemLayoutProcessor::DoLayoutPageArea( - CXFA_ContainerLayoutItem* pPageAreaLayoutItem) { - CXFA_Node* pFormNode = pPageAreaLayoutItem->m_pFormNode; - CXFA_Node* pCurChildNode = XFA_LAYOUT_INVALIDNODE; - XFA_ItemLayoutProcessorStages nCurChildNodeStage = - XFA_ItemLayoutProcessorStages::None; - CXFA_LayoutItem* pBeforeItem = nullptr; - for (GotoNextContainerNode(pCurChildNode, nCurChildNodeStage, pFormNode, - false); - pCurChildNode; GotoNextContainerNode(pCurChildNode, nCurChildNodeStage, - pFormNode, false)) { - if (nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) - continue; - if (pCurChildNode->GetElementType() == XFA_Element::Variables) - continue; + float fWidth = pTrailerItem->m_sSize.width; + XFA_AttributeEnum eLayout = + m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + return eLayout == XFA_AttributeEnum::Tb || m_fWidthLimite <= fWidth; +} - auto pProcessor = - pdfium::MakeUnique(pCurChildNode, nullptr); - pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); - if (!pProcessor->HasLayoutItem()) - continue; +float CXFA_ItemLayoutProcessor::InsertKeepLayoutItems() { + if (m_arrayKeepItems.empty()) + return 0; - pProcessor->SetCurrentComponentPos(CalculatePositionedContainerPos( - pCurChildNode, pProcessor->GetCurrentComponentSize())); - CXFA_LayoutItem* pProcessItem = pProcessor->ExtractLayoutItem(); - if (!pBeforeItem) - pPageAreaLayoutItem->AddHeadChild(pProcessItem); - else - pPageAreaLayoutItem->InsertChild(pBeforeItem, pProcessItem); + if (!m_pLayoutItem) { + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + m_pLayoutItem->m_sSize.clear(); + } - pBeforeItem = pProcessItem; + float fTotalHeight = 0; + for (auto iter = m_arrayKeepItems.rbegin(); iter != m_arrayKeepItems.rend(); + iter++) { + AddLeaderAfterSplit(*iter); + fTotalHeight += (*iter)->m_sSize.height; } + m_arrayKeepItems.clear(); - pBeforeItem = nullptr; - CXFA_LayoutItem* pLayoutItem = pPageAreaLayoutItem->m_pFirstChild; - while (pLayoutItem) { - if (!pLayoutItem->IsContentLayoutItem() || - pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) { - pLayoutItem = pLayoutItem->m_pNextSibling; - continue; - } - if (pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) - continue; + return fTotalHeight; +} - CXFA_LayoutItem* pNextLayoutItem = pLayoutItem->m_pNextSibling; - pPageAreaLayoutItem->RemoveChild(pLayoutItem); - if (!pBeforeItem) - pPageAreaLayoutItem->AddHeadChild(pLayoutItem); - else - pPageAreaLayoutItem->InsertChild(pBeforeItem, pLayoutItem); - - pBeforeItem = pLayoutItem; - pLayoutItem = pNextLayoutItem; - } -} - -void CXFA_ItemLayoutProcessor::DoLayoutPositionedContainer( - CXFA_LayoutContext* pContext) { - if (m_pLayoutItem) - return; - - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - bool bIgnoreXY = (m_pFormNode->JSObject() - ->TryEnum(XFA_Attribute::Layout, true) - .value_or(XFA_AttributeEnum::Position) != - XFA_AttributeEnum::Position); - bool bContainerWidthAutoSize = true; - bool bContainerHeightAutoSize = true; - CFX_SizeF containerSize = CalculateContainerSpecifiedSize( - m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); +bool CXFA_ItemLayoutProcessor::ProcessKeepForSplit( + CXFA_ItemLayoutProcessor* pChildProcessor, + XFA_ItemLayoutProcessorResult eRetValue, + std::vector* rgCurLineLayoutItem, + float* fContentCurRowAvailWidth, + float* fContentCurRowHeight, + float* fContentCurRowY, + bool* bAddedItemInRow, + bool* bForceEndPage, + XFA_ItemLayoutProcessorResult* result) { + if (!pChildProcessor) + return false; - float fContentCalculatedWidth = 0; - float fContentCalculatedHeight = 0; - float fHiddenContentCalculatedWidth = 0; - float fHiddenContentCalculatedHeight = 0; - if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, - false); - } + if (m_pCurChildNode->GetIntact() == XFA_AttributeEnum::None && + pChildProcessor->m_bHasAvailHeight) + return false; - int32_t iColIndex = 0; - for (; m_pCurChildNode; GotoNextContainerNode( - m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { - if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) - continue; - if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) - continue; + if (!ExistContainerKeep(m_pCurChildNode, true)) + return false; - auto pProcessor = pdfium::MakeUnique( - m_pCurChildNode, m_pPageMgr); - if (pContext && pContext->m_prgSpecifiedColumnWidths) { - int32_t iColSpan = - m_pCurChildNode->JSObject()->GetInteger(XFA_Attribute::ColSpan); - if (iColSpan <= pdfium::CollectionSize( - *pContext->m_prgSpecifiedColumnWidths) - - iColIndex) { - pContext->m_fCurColumnWidth = 0; - pContext->m_bCurColumnWidthAvaiable = true; - if (iColSpan == -1) { - iColSpan = pdfium::CollectionSize( - *pContext->m_prgSpecifiedColumnWidths); - } - for (int32_t i = 0; iColIndex + i < iColSpan; ++i) { - pContext->m_fCurColumnWidth += - (*pContext->m_prgSpecifiedColumnWidths)[iColIndex + i]; - } - if (pContext->m_fCurColumnWidth == 0) - pContext->m_bCurColumnWidthAvaiable = false; + CFX_SizeF childSize = pChildProcessor->GetCurrentComponentSize(); + std::vector keepLayoutItems; + if (JudgePutNextPage(m_pLayoutItem, childSize.height, &keepLayoutItems)) { + m_arrayKeepItems.clear(); - iColIndex += iColSpan >= 0 ? iColSpan : 0; - } + for (auto* item : keepLayoutItems) { + m_pLayoutItem->RemoveChild(item); + *fContentCurRowY -= item->m_sSize.height; + m_arrayKeepItems.push_back(item); } + *bAddedItemInRow = true; + *bForceEndPage = true; + *result = XFA_ItemLayoutProcessorResult::PageFullBreak; + return true; + } - pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pContext); - if (!pProcessor->HasLayoutItem()) - continue; + rgCurLineLayoutItem->push_back(pChildProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); + *result = eRetValue; - CFX_SizeF size = pProcessor->GetCurrentComponentSize(); - bool bChangeParentSize = false; - if (m_pCurChildNode->PresenceRequiresSpace()) - bChangeParentSize = true; + return true; +} - CFX_PointF absolutePos; - if (!bIgnoreXY) - absolutePos = CalculatePositionedContainerPos(m_pCurChildNode, size); +bool CXFA_ItemLayoutProcessor::JudgePutNextPage( + CXFA_ContentLayoutItem* pParentLayoutItem, + float fChildHeight, + std::vector* pKeepItems) { + if (!pParentLayoutItem) + return false; - pProcessor->SetCurrentComponentPos(absolutePos); - if (bContainerWidthAutoSize) { - float fChildSuppliedWidth = absolutePos.x + size.width; - if (bChangeParentSize) { - fContentCalculatedWidth = - std::max(fContentCalculatedWidth, fChildSuppliedWidth); - } else { - if (fHiddenContentCalculatedWidth < fChildSuppliedWidth && - m_pCurChildNode->GetElementType() != XFA_Element::Subform) { - fHiddenContentCalculatedWidth = fChildSuppliedWidth; - } - } + float fItemsHeight = 0; + for (CXFA_ContentLayoutItem* pChildLayoutItem = + (CXFA_ContentLayoutItem*)pParentLayoutItem->m_pFirstChild; + pChildLayoutItem; + pChildLayoutItem = + (CXFA_ContentLayoutItem*)pChildLayoutItem->m_pNextSibling) { + if (ExistContainerKeep(pChildLayoutItem->m_pFormNode, false)) { + pKeepItems->push_back(pChildLayoutItem); + fItemsHeight += pChildLayoutItem->m_sSize.height; + } else { + pKeepItems->clear(); + fItemsHeight = 0; } + } + fItemsHeight += fChildHeight; + return m_pPageMgr->GetNextAvailContentHeight(fItemsHeight); +} - if (bContainerHeightAutoSize) { - float fChildSuppliedHeight = absolutePos.y + size.height; - if (bChangeParentSize) { - fContentCalculatedHeight = - std::max(fContentCalculatedHeight, fChildSuppliedHeight); - } else { - if (fHiddenContentCalculatedHeight < fChildSuppliedHeight && - m_pCurChildNode->GetElementType() != XFA_Element::Subform) { - fHiddenContentCalculatedHeight = fChildSuppliedHeight; - } +void CXFA_ItemLayoutProcessor::ProcessUnUseBinds(CXFA_Node* pFormNode) { + if (!pFormNode) + return; + + CXFA_NodeIteratorTemplate sIterator( + pFormNode); + for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode; + pNode = sIterator.MoveToNext()) { + if (pNode->IsContainerNode()) { + CXFA_Node* pBindNode = pNode->GetBindData(); + if (pBindNode) { + pBindNode->RemoveBindItem(pNode); + pNode->SetBindingNode(nullptr); } } - m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); + pNode->SetFlag(XFA_NodeFlag_UnusedNode, true); } - - XFA_VERSION eVersion = m_pFormNode->GetDocument()->GetCurVersionMode(); - if (fContentCalculatedWidth == 0 && eVersion < XFA_VERSION_207) - fContentCalculatedWidth = fHiddenContentCalculatedWidth; - if (fContentCalculatedHeight == 0 && eVersion < XFA_VERSION_207) - fContentCalculatedHeight = fHiddenContentCalculatedHeight; - - containerSize = CalculateContainerComponentSizeFromContentSize( - m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, - bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); - SetCurrentComponentSize(containerSize); } -void CXFA_ItemLayoutProcessor::DoLayoutTableContainer(CXFA_Node* pLayoutNode) { - if (m_pLayoutItem) +void CXFA_ItemLayoutProcessor::ProcessUnUseOverFlow( + CXFA_Node* pLeaderNode, + CXFA_Node* pTrailerNode, + CXFA_ContentLayoutItem* pTrailerItem, + CXFA_Node* pFormNode) { + ProcessUnUseBinds(pLeaderNode); + ProcessUnUseBinds(pTrailerNode); + if (!pFormNode) return; - if (!pLayoutNode) - pLayoutNode = m_pFormNode; - ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); + if (pFormNode->GetElementType() == XFA_Element::Overflow || + pFormNode->GetElementType() == XFA_Element::Break) { + pFormNode = pFormNode->GetParent(); + } + if (pLeaderNode && pFormNode) + pFormNode->RemoveChild(pLeaderNode, true); + if (pTrailerNode && pFormNode) + pFormNode->RemoveChild(pTrailerNode, true); + if (pTrailerItem) + XFA_ReleaseLayoutItem(pTrailerItem); +} - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); +XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayoutFlowedContainer( + bool bUseBreakControl, + XFA_AttributeEnum eFlowStrategy, + float fHeightLimit, + float fRealHeight, + CXFA_LayoutContext* pContext, + bool bRootForceTb) { + m_bHasAvailHeight = true; + bool bBreakDone = false; bool bContainerWidthAutoSize = true; bool bContainerHeightAutoSize = true; + bool bForceEndPage = false; + bool bIsManualBreak = false; + if (m_pCurChildPreprocessor) { + m_pCurChildPreprocessor->m_ePreProcessRs = + XFA_ItemLayoutProcessorResult::Done; + } + CFX_SizeF containerSize = CalculateContainerSpecifiedSize( m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); - float fContentCalculatedWidth = 0; - float fContentCalculatedHeight = 0; + if (pContext && pContext->m_bCurColumnWidthAvaiable) { + bContainerWidthAutoSize = false; + containerSize.width = pContext->m_fCurColumnWidth; + } + if (!bContainerHeightAutoSize) + containerSize.height -= m_fUsedSize; + + if (!bContainerHeightAutoSize) { + CXFA_Node* pParentNode = m_pFormNode->GetParent(); + bool bFocrTb = false; + if (pParentNode && + GetLayout(pParentNode, &bFocrTb) == XFA_AttributeEnum::Row) { + CXFA_Node* pChildContainer = m_pFormNode->GetFirstContainerChild(); + if (pChildContainer && pChildContainer->GetNextContainerSibling()) { + containerSize.height = 0; + bContainerHeightAutoSize = true; + } + } + } + CXFA_Margin* pMarginNode = m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); float fLeftInset = 0; + float fTopInset = 0; float fRightInset = 0; + float fBottomInset = 0; if (pMarginNode) { fLeftInset = pMarginNode->JSObject() ->GetMeasure(XFA_Attribute::LeftInset) .ToUnit(XFA_Unit::Pt); + fTopInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); fRightInset = pMarginNode->JSObject() ->GetMeasure(XFA_Attribute::RightInset) .ToUnit(XFA_Unit::Pt); + fBottomInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); } - float fContentWidthLimit = bContainerWidthAutoSize ? FLT_MAX : containerSize.width - fLeftInset - fRightInset; - WideString wsColumnWidths = - pLayoutNode->JSObject()->GetCData(XFA_Attribute::ColumnWidths); - if (!wsColumnWidths.IsEmpty()) { - auto widths = SeparateStringW(wsColumnWidths.c_str(), - wsColumnWidths.GetLength(), L' '); - for (auto& width : widths) { - width.TrimLeft(L' '); - if (width.IsEmpty()) - continue; + float fContentCalculatedWidth = 0; + float fContentCalculatedHeight = 0; + float fAvailHeight = fHeightLimit - fTopInset - fBottomInset; + if (fAvailHeight < 0) + m_bHasAvailHeight = false; - m_rgSpecifiedColumnWidths.push_back( - CXFA_Measurement(width.AsStringView()).ToUnit(XFA_Unit::Pt)); + fRealHeight = fRealHeight - fTopInset - fBottomInset; + float fContentCurRowY = 0; + CXFA_ContentLayoutItem* pLayoutChild = nullptr; + if (m_pLayoutItem) { + if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done && + eFlowStrategy != XFA_AttributeEnum::Tb) { + pLayoutChild = (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; + pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { + if (pLayoutNext->m_sPos.y != pLayoutChild->m_sPos.y) + pLayoutChild = pLayoutNext; + } } - } - - int32_t iSpecifiedColumnCount = - pdfium::CollectionSize(m_rgSpecifiedColumnWidths); - CXFA_LayoutContext layoutContext; - layoutContext.m_prgSpecifiedColumnWidths = &m_rgSpecifiedColumnWidths; - CXFA_LayoutContext* pLayoutContext = - iSpecifiedColumnCount > 0 ? &layoutContext : nullptr; - if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, - false); - } - for (; m_pCurChildNode; GotoNextContainerNode( - m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { - layoutContext.m_bCurColumnWidthAvaiable = false; - layoutContext.m_fCurColumnWidth = 0; - if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) - continue; + for (CXFA_ContentLayoutItem* pLayoutTempChild = + (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + pLayoutTempChild != pLayoutChild; + pLayoutTempChild = + (CXFA_ContentLayoutItem*)pLayoutTempChild->m_pNextSibling) { + if (!pLayoutTempChild->m_pFormNode->PresenceRequiresSpace()) + continue; - auto pProcessor = pdfium::MakeUnique( - m_pCurChildNode, m_pPageMgr); - pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pLayoutContext); - if (!pProcessor->HasLayoutItem()) - continue; + fContentCalculatedWidth = std::max( + fContentCalculatedWidth, + pLayoutTempChild->m_sPos.x + pLayoutTempChild->m_sSize.width); + fContentCalculatedHeight = std::max( + fContentCalculatedHeight, + pLayoutTempChild->m_sPos.y + pLayoutTempChild->m_sSize.height); + } - m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); + if (pLayoutChild) + fContentCurRowY = pLayoutChild->m_sPos.y; + else + fContentCurRowY = fContentCalculatedHeight; } - int32_t iRowCount = 0; - int32_t iColCount = 0; - { - std::vector rgRowItems; - std::vector rgRowItemsSpan; - std::vector rgRowItemsWidth; - for (auto* pLayoutChild = - static_cast(m_pLayoutItem->m_pFirstChild); - pLayoutChild; pLayoutChild = static_cast( - pLayoutChild->m_pNextSibling)) { - if (pLayoutChild->m_pFormNode->GetElementType() != XFA_Element::Subform) - continue; - if (!pLayoutChild->m_pFormNode->PresenceRequiresSpace()) - continue; + fContentCurRowY += InsertKeepLayoutItems(); + if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::None) { + GotoNextContainerNode(m_pCurChildNode, &m_nCurChildNodeStage, m_pFormNode, + true); + } - XFA_AttributeEnum eLayout = - pLayoutChild->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); - if (eLayout != XFA_AttributeEnum::Row && - eLayout != XFA_AttributeEnum::Rl_row) { - continue; - } - if (CXFA_ContentLayoutItem* pRowLayoutCell = - (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild) { - rgRowItems.push_back(pRowLayoutCell); - int32_t iColSpan = pRowLayoutCell->m_pFormNode->JSObject()->GetInteger( - XFA_Attribute::ColSpan); - rgRowItemsSpan.push_back(iColSpan); - rgRowItemsWidth.push_back(pRowLayoutCell->m_sSize.width); - } + fContentCurRowY += InsertPendingItems(m_pFormNode); + if (m_pCurChildPreprocessor && + m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Container) { + if (ExistContainerKeep(m_pCurChildPreprocessor->GetFormNode(), false)) { + m_pKeepHeadNode = m_pCurChildNode; + m_bIsProcessKeep = true; + m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Keep; } + } - iRowCount = pdfium::CollectionSize(rgRowItems); - iColCount = 0; - bool bMoreColumns = true; - while (bMoreColumns) { - bMoreColumns = false; - bool bAutoCol = false; - for (int32_t i = 0; i < iRowCount; i++) { - while (rgRowItems[i] && - (rgRowItemsSpan[i] <= 0 || - !rgRowItems[i]->m_pFormNode->PresenceRequiresSpace())) { - CXFA_ContentLayoutItem* pNewCell = - (CXFA_ContentLayoutItem*)rgRowItems[i]->m_pNextSibling; - if (rgRowItemsSpan[i] < 0 && - rgRowItems[i]->m_pFormNode->PresenceRequiresSpace()) { - pNewCell = nullptr; - } - rgRowItems[i] = pNewCell; - rgRowItemsSpan[i] = - pNewCell ? pNewCell->m_pFormNode->JSObject()->GetInteger( - XFA_Attribute::ColSpan) - : 0; - rgRowItemsWidth[i] = pNewCell ? pNewCell->m_sSize.width : 0; + while (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done) { + float fContentCurRowHeight = 0; + float fContentCurRowAvailWidth = fContentWidthLimit; + m_fWidthLimite = fContentCurRowAvailWidth; + std::vector rgCurLineLayoutItems[3]; + uint8_t uCurHAlignState = + (eFlowStrategy != XFA_AttributeEnum::Rl_tb ? 0 : 2); + if (pLayoutChild) { + for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; + pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { + if (!pLayoutNext->m_pNextSibling && m_pCurChildPreprocessor && + m_pCurChildPreprocessor->m_pFormNode == pLayoutNext->m_pFormNode) { + pLayoutNext->m_pNext = m_pCurChildPreprocessor->m_pLayoutItem; + m_pCurChildPreprocessor->m_pLayoutItem = pLayoutNext; + break; } - CXFA_ContentLayoutItem* pCell = rgRowItems[i]; - if (!pCell) - continue; - - bMoreColumns = true; - if (rgRowItemsSpan[i] != 1) - continue; - - if (iColCount >= iSpecifiedColumnCount) { - int32_t c = iColCount + 1 - pdfium::CollectionSize( - m_rgSpecifiedColumnWidths); - for (int32_t j = 0; j < c; j++) - m_rgSpecifiedColumnWidths.push_back(0); + uint8_t uHAlign = + HAlignEnumToInt(pLayoutNext->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::HAlign)); + rgCurLineLayoutItems[uHAlign].push_back(pLayoutNext); + if (eFlowStrategy == XFA_AttributeEnum::Lr_tb) { + if (uHAlign > uCurHAlignState) + uCurHAlignState = uHAlign; + } else if (uHAlign < uCurHAlignState) { + uCurHAlignState = uHAlign; } - if (m_rgSpecifiedColumnWidths[iColCount] < XFA_LAYOUT_FLOAT_PERCISION) - bAutoCol = true; - if (bAutoCol && - m_rgSpecifiedColumnWidths[iColCount] < rgRowItemsWidth[i]) { - m_rgSpecifiedColumnWidths[iColCount] = rgRowItemsWidth[i]; + if (pLayoutNext->m_pFormNode->PresenceRequiresSpace()) { + if (pLayoutNext->m_sSize.height > fContentCurRowHeight) + fContentCurRowHeight = pLayoutNext->m_sSize.height; + fContentCurRowAvailWidth -= pLayoutNext->m_sSize.width; } } - if (!bMoreColumns) - continue; - - float fFinalColumnWidth = 0.0f; - if (pdfium::IndexInBounds(m_rgSpecifiedColumnWidths, iColCount)) - fFinalColumnWidth = m_rgSpecifiedColumnWidths[iColCount]; - - for (int32_t i = 0; i < iRowCount; ++i) { - if (!rgRowItems[i]) - continue; - --rgRowItemsSpan[i]; - rgRowItemsWidth[i] -= fFinalColumnWidth; + if ((CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild == + pLayoutChild) { + m_pLayoutItem->m_pFirstChild = nullptr; + } else { + CXFA_ContentLayoutItem* pLayoutNext = + (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + for (; pLayoutNext; + pLayoutNext = + (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { + if ((CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling == + pLayoutChild) { + pLayoutNext->m_pNextSibling = nullptr; + break; + } + } } - ++iColCount; - } - } - - float fCurrentRowY = 0; - for (CXFA_ContentLayoutItem* pLayoutChild = - (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - pLayoutChild; - pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { - if (!pLayoutChild->m_pFormNode->PresenceRequiresSpace()) - continue; - if (pLayoutChild->m_pFormNode->GetElementType() == XFA_Element::Subform) { - XFA_AttributeEnum eSubformLayout = - pLayoutChild->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); - if (eSubformLayout == XFA_AttributeEnum::Row || - eSubformLayout == XFA_AttributeEnum::Rl_row) { - RelocateTableRowCells(pLayoutChild, m_rgSpecifiedColumnWidths, - eSubformLayout); + CXFA_ContentLayoutItem* pLayoutNextTemp = + (CXFA_ContentLayoutItem*)pLayoutChild; + while (pLayoutNextTemp) { + pLayoutNextTemp->m_pParent = nullptr; + CXFA_ContentLayoutItem* pSaveLayoutNext = + (CXFA_ContentLayoutItem*)pLayoutNextTemp->m_pNextSibling; + pLayoutNextTemp->m_pNextSibling = nullptr; + pLayoutNextTemp = pSaveLayoutNext; } + pLayoutChild = nullptr; } - pLayoutChild->m_sPos.y = fCurrentRowY; - if (bContainerWidthAutoSize) { - pLayoutChild->m_sPos.x = 0; - } else { - switch (pLayoutChild->m_pFormNode->JSObject()->GetEnum( - XFA_Attribute::HAlign)) { - case XFA_AttributeEnum::Center: - pLayoutChild->m_sPos.x = - (fContentWidthLimit - pLayoutChild->m_sSize.width) / 2; - break; - case XFA_AttributeEnum::Right: - pLayoutChild->m_sPos.x = - fContentWidthLimit - pLayoutChild->m_sSize.width; - break; - case XFA_AttributeEnum::Left: - default: - pLayoutChild->m_sPos.x = 0; + while (m_pCurChildNode) { + std::unique_ptr pProcessor; + bool bAddedItemInRow = false; + fContentCurRowY += InsertPendingItems(m_pFormNode); + switch (m_nCurChildNodeStage) { + case XFA_ItemLayoutProcessorStages::Keep: + case XFA_ItemLayoutProcessorStages::None: break; - } - } - - if (bContainerWidthAutoSize) { - float fChildSuppliedWidth = - pLayoutChild->m_sPos.x + pLayoutChild->m_sSize.width; - if (fContentWidthLimit < FLT_MAX && - fContentWidthLimit > fChildSuppliedWidth) { - fChildSuppliedWidth = fContentWidthLimit; - } - fContentCalculatedWidth = - std::max(fContentCalculatedWidth, fChildSuppliedWidth); - } - fCurrentRowY += pLayoutChild->m_sSize.height; - } + case XFA_ItemLayoutProcessorStages::BreakBefore: { + for (auto* item : m_arrayKeepItems) { + m_pLayoutItem->RemoveChild(item); + fContentCalculatedHeight -= item->m_sSize.height; + } - if (bContainerHeightAutoSize) - fContentCalculatedHeight = std::max(fContentCalculatedHeight, fCurrentRowY); + CXFA_Node* pLeaderNode = nullptr; + CXFA_Node* pTrailerNode = nullptr; + bool bCreatePage = false; + if (!bUseBreakControl || !m_pPageMgr || + !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, true, + pLeaderNode, pTrailerNode, + bCreatePage) || + m_pFormNode->GetElementType() == XFA_Element::Form || + !bCreatePage) { + break; + } - containerSize = CalculateContainerComponentSizeFromContentSize( - m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, - bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); - SetCurrentComponentSize(containerSize); -} + if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) + AddPendingNode(pLeaderNode, true); -bool CXFA_ItemLayoutProcessor::IsAddNewRowForTrailer( - CXFA_ContentLayoutItem* pTrailerItem) { - if (!pTrailerItem) - return false; + if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { + if (m_pFormNode->GetParent()->GetElementType() == + XFA_Element::Form && + !m_pLayoutItem) { + AddPendingNode(pTrailerNode, true); + } else { + auto pTempProcessor = + pdfium::MakeUnique(pTrailerNode, + nullptr); + InsertFlowedItem( + pTempProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, eFlowStrategy, + &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, + FLT_MAX, fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, false); + } + } + GotoNextContainerNode(m_pCurChildNode, &m_nCurChildNodeStage, + m_pFormNode, true); + bForceEndPage = true; + bIsManualBreak = true; + goto SuspendAndCreateNewRow; + } + case XFA_ItemLayoutProcessorStages::BreakAfter: { + CXFA_Node* pLeaderNode = nullptr; + CXFA_Node* pTrailerNode = nullptr; + bool bCreatePage = false; + if (!bUseBreakControl || !m_pPageMgr || + !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, false, + pLeaderNode, pTrailerNode, + bCreatePage) || + m_pFormNode->GetElementType() == XFA_Element::Form) { + break; + } - float fWidth = pTrailerItem->m_sSize.width; - XFA_AttributeEnum eLayout = - m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); - return eLayout == XFA_AttributeEnum::Tb || m_fWidthLimite <= fWidth; -} + if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { + auto pTempProcessor = pdfium::MakeUnique( + pTrailerNode, nullptr); + InsertFlowedItem(pTempProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, + eFlowStrategy, &uCurHAlignState, + rgCurLineLayoutItems, false, FLT_MAX, FLT_MAX, + fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, false); + } + if (!bCreatePage) { + if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { + CalculateRowChildPosition( + rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, + bContainerWidthAutoSize, &fContentCalculatedWidth, + &fContentCalculatedHeight, &fContentCurRowY, + fContentCurRowHeight, fContentWidthLimit, false); + rgCurLineLayoutItems->clear(); + auto pTempProcessor = + pdfium::MakeUnique(pLeaderNode, + nullptr); + InsertFlowedItem( + pTempProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, eFlowStrategy, + &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, + FLT_MAX, fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, false); + } + } else { + if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) + AddPendingNode(pLeaderNode, true); + } -float CXFA_ItemLayoutProcessor::InsertKeepLayoutItems() { - if (m_arrayKeepItems.empty()) - return 0; + GotoNextContainerNode(m_pCurChildNode, &m_nCurChildNodeStage, + m_pFormNode, true); + if (bCreatePage) { + bForceEndPage = true; + bIsManualBreak = true; + if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done) + bBreakDone = true; + } + goto SuspendAndCreateNewRow; + } + case XFA_ItemLayoutProcessorStages::BookendLeader: { + CXFA_Node* pLeaderNode = nullptr; + if (m_pCurChildPreprocessor) { + pProcessor.reset(m_pCurChildPreprocessor); + m_pCurChildPreprocessor = nullptr; + } else if (m_pPageMgr && m_pPageMgr->ProcessBookendLeaderOrTrailer( + m_pCurChildNode, true, pLeaderNode)) { + pProcessor = pdfium::MakeUnique( + pLeaderNode, m_pPageMgr); + } - if (!m_pLayoutItem) { - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - m_pLayoutItem->m_sSize.clear(); - } + if (pProcessor) { + if (InsertFlowedItem(pProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, + eFlowStrategy, &uCurHAlignState, + rgCurLineLayoutItems, bUseBreakControl, + fAvailHeight, fRealHeight, fContentWidthLimit, + &fContentCurRowY, &fContentCurRowAvailWidth, + &fContentCurRowHeight, &bAddedItemInRow, + &bForceEndPage, pContext, false) != + XFA_ItemLayoutProcessorResult::Done) { + goto SuspendAndCreateNewRow; + } else { + pProcessor.reset(); + } + } + break; + } + case XFA_ItemLayoutProcessorStages::BookendTrailer: { + CXFA_Node* pTrailerNode = nullptr; + if (m_pCurChildPreprocessor) { + pProcessor.reset(m_pCurChildPreprocessor); + m_pCurChildPreprocessor = nullptr; + } else if (m_pPageMgr && m_pPageMgr->ProcessBookendLeaderOrTrailer( + m_pCurChildNode, false, pTrailerNode)) { + pProcessor = pdfium::MakeUnique( + pTrailerNode, m_pPageMgr); + } + if (pProcessor) { + if (InsertFlowedItem(pProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, + eFlowStrategy, &uCurHAlignState, + rgCurLineLayoutItems, bUseBreakControl, + fAvailHeight, fRealHeight, fContentWidthLimit, + &fContentCurRowY, &fContentCurRowAvailWidth, + &fContentCurRowHeight, &bAddedItemInRow, + &bForceEndPage, pContext, false) != + XFA_ItemLayoutProcessorResult::Done) { + goto SuspendAndCreateNewRow; + } else { + pProcessor.reset(); + } + } + break; + } + case XFA_ItemLayoutProcessorStages::Container: { + ASSERT(m_pCurChildNode->IsContainerNode()); + if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) + break; + if (fContentCurRowY >= fHeightLimit + XFA_LAYOUT_FLOAT_PERCISION && + m_pCurChildNode->PresenceRequiresSpace()) { + bForceEndPage = true; + goto SuspendAndCreateNewRow; + } + if (!m_pCurChildNode->IsContainerNode()) + break; - float fTotalHeight = 0; - for (auto iter = m_arrayKeepItems.rbegin(); iter != m_arrayKeepItems.rend(); - iter++) { - AddLeaderAfterSplit(this, *iter); - fTotalHeight += (*iter)->m_sSize.height; - } - m_arrayKeepItems.clear(); + bool bNewRow = false; + if (m_pCurChildPreprocessor) { + pProcessor.reset(m_pCurChildPreprocessor); + m_pCurChildPreprocessor = nullptr; + bNewRow = true; + } else { + pProcessor = pdfium::MakeUnique( + m_pCurChildNode, m_pPageMgr); + } - return fTotalHeight; -} + pProcessor->InsertPendingItems(m_pCurChildNode); + XFA_ItemLayoutProcessorResult rs = InsertFlowedItem( + pProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, eFlowStrategy, + &uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl, + fAvailHeight, fRealHeight, fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, bNewRow); + switch (rs) { + case XFA_ItemLayoutProcessorResult::ManualBreak: + bIsManualBreak = true; + case XFA_ItemLayoutProcessorResult::PageFullBreak: + bForceEndPage = true; + case XFA_ItemLayoutProcessorResult::RowFullBreak: + goto SuspendAndCreateNewRow; + case XFA_ItemLayoutProcessorResult::Done: + default: + fContentCurRowY += + pProcessor->InsertPendingItems(m_pCurChildNode); + pProcessor.reset(); + } + break; + } + case XFA_ItemLayoutProcessorStages::Done: + break; + default: + break; + } + GotoNextContainerNode(m_pCurChildNode, &m_nCurChildNodeStage, m_pFormNode, + true); + if (bAddedItemInRow && eFlowStrategy == XFA_AttributeEnum::Tb) + break; + continue; + SuspendAndCreateNewRow: + if (pProcessor) + m_pCurChildPreprocessor = pProcessor.release(); + break; + } -bool CXFA_ItemLayoutProcessor::ProcessKeepForSplit( - CXFA_ItemLayoutProcessor* pParentProcessor, - CXFA_ItemLayoutProcessor* pChildProcessor, - XFA_ItemLayoutProcessorResult eRetValue, - std::vector* rgCurLineLayoutItem, - float* fContentCurRowAvailWidth, - float* fContentCurRowHeight, - float* fContentCurRowY, - bool* bAddedItemInRow, - bool* bForceEndPage, - XFA_ItemLayoutProcessorResult* result) { - if (!pParentProcessor || !pChildProcessor) - return false; + CalculateRowChildPosition( + rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, + bContainerWidthAutoSize, &fContentCalculatedWidth, + &fContentCalculatedHeight, &fContentCurRowY, fContentCurRowHeight, + fContentWidthLimit, bRootForceTb); + m_fWidthLimite = fContentCurRowAvailWidth; + if (bForceEndPage) + break; + } - if (pParentProcessor->m_pCurChildNode->GetIntact() == - XFA_AttributeEnum::None && - pChildProcessor->m_bHasAvailHeight) - return false; + bool bRetValue = + m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done && + m_PendingNodes.empty(); + if (bBreakDone) + bRetValue = false; - if (!ExistContainerKeep(pParentProcessor->m_pCurChildNode, true)) - return false; + containerSize = CalculateContainerComponentSizeFromContentSize( + m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, + bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); - CFX_SizeF childSize = pChildProcessor->GetCurrentComponentSize(); - std::vector keepLayoutItems; - if (pParentProcessor->JudgePutNextPage(pParentProcessor->m_pLayoutItem, - childSize.height, &keepLayoutItems)) { - m_arrayKeepItems.clear(); + if (containerSize.height >= XFA_LAYOUT_FLOAT_PERCISION || m_pLayoutItem || + bRetValue) { + if (!m_pLayoutItem) + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + containerSize.height = std::max(containerSize.height, 0.f); - for (auto* item : keepLayoutItems) { - pParentProcessor->m_pLayoutItem->RemoveChild(item); - *fContentCurRowY -= item->m_sSize.height; - m_arrayKeepItems.push_back(item); - } - *bAddedItemInRow = true; - *bForceEndPage = true; - *result = XFA_ItemLayoutProcessorResult::PageFullBreak; - return true; + SetCurrentComponentSize(containerSize); + if (bForceEndPage) + m_fUsedSize = 0; + else + m_fUsedSize += m_pLayoutItem->m_sSize.height; } - rgCurLineLayoutItem->push_back(pChildProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); - *result = eRetValue; - - return true; + return bRetValue + ? XFA_ItemLayoutProcessorResult::Done + : (bIsManualBreak ? XFA_ItemLayoutProcessorResult::ManualBreak + : XFA_ItemLayoutProcessorResult::PageFullBreak); } -bool CXFA_ItemLayoutProcessor::JudgePutNextPage( - CXFA_ContentLayoutItem* pParentLayoutItem, - float fChildHeight, - std::vector* pKeepItems) { - if (!pParentLayoutItem) +bool CXFA_ItemLayoutProcessor::CalculateRowChildPosition( + std::vector (&rgCurLineLayoutItems)[3], + XFA_AttributeEnum eFlowStrategy, + bool bContainerHeightAutoSize, + bool bContainerWidthAutoSize, + float* fContentCalculatedWidth, + float* fContentCalculatedHeight, + float* fContentCurRowY, + float fContentCurRowHeight, + float fContentWidthLimit, + bool bRootForceTb) { + int32_t nGroupLengths[3] = {0, 0, 0}; + float fGroupWidths[3] = {0, 0, 0}; + int32_t nTotalLength = 0; + for (int32_t i = 0; i < 3; i++) { + nGroupLengths[i] = pdfium::CollectionSize(rgCurLineLayoutItems[i]); + for (int32_t c = nGroupLengths[i], j = 0; j < c; j++) { + nTotalLength++; + if (rgCurLineLayoutItems[i][j]->m_pFormNode->PresenceRequiresSpace()) + fGroupWidths[i] += rgCurLineLayoutItems[i][j]->m_sSize.width; + } + } + if (!nTotalLength) { + if (bContainerHeightAutoSize) { + *fContentCalculatedHeight = + std::min(*fContentCalculatedHeight, *fContentCurRowY); + } return false; + } + if (!m_pLayoutItem) + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - float fItemsHeight = 0; - for (CXFA_ContentLayoutItem* pChildLayoutItem = - (CXFA_ContentLayoutItem*)pParentLayoutItem->m_pFirstChild; - pChildLayoutItem; - pChildLayoutItem = - (CXFA_ContentLayoutItem*)pChildLayoutItem->m_pNextSibling) { - if (ExistContainerKeep(pChildLayoutItem->m_pFormNode, false)) { - pKeepItems->push_back(pChildLayoutItem); - fItemsHeight += pChildLayoutItem->m_sSize.height; - } else { - pKeepItems->clear(); - fItemsHeight = 0; + if (eFlowStrategy != XFA_AttributeEnum::Rl_tb) { + float fCurPos; + fCurPos = 0; + for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { + if (bRootForceTb) { + rgCurLineLayoutItems[0][j]->m_sPos = CalculatePositionedContainerPos( + rgCurLineLayoutItems[0][j]->m_pFormNode, + rgCurLineLayoutItems[0][j]->m_sSize); + } else { + rgCurLineLayoutItems[0][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + if (rgCurLineLayoutItems[0][j]->m_pFormNode->PresenceRequiresSpace()) + fCurPos += rgCurLineLayoutItems[0][j]->m_sSize.width; + } + m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); + m_fLastRowWidth = fCurPos; + } + fCurPos = (fContentWidthLimit + fGroupWidths[0] - fGroupWidths[1] - + fGroupWidths[2]) / + 2; + for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { + if (bRootForceTb) { + rgCurLineLayoutItems[1][j]->m_sPos = CalculatePositionedContainerPos( + rgCurLineLayoutItems[1][j]->m_pFormNode, + rgCurLineLayoutItems[1][j]->m_sSize); + } else { + rgCurLineLayoutItems[1][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + if (rgCurLineLayoutItems[1][j]->m_pFormNode->PresenceRequiresSpace()) + fCurPos += rgCurLineLayoutItems[1][j]->m_sSize.width; + } + m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); + m_fLastRowWidth = fCurPos; + } + fCurPos = fContentWidthLimit - fGroupWidths[2]; + for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { + if (bRootForceTb) { + rgCurLineLayoutItems[2][j]->m_sPos = CalculatePositionedContainerPos( + rgCurLineLayoutItems[2][j]->m_pFormNode, + rgCurLineLayoutItems[2][j]->m_sSize); + } else { + rgCurLineLayoutItems[2][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + if (rgCurLineLayoutItems[2][j]->m_pFormNode->PresenceRequiresSpace()) + fCurPos += rgCurLineLayoutItems[2][j]->m_sSize.width; + } + m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); + m_fLastRowWidth = fCurPos; + } + } else { + float fCurPos; + fCurPos = fGroupWidths[0]; + for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { + if (rgCurLineLayoutItems[0][j]->m_pFormNode->PresenceRequiresSpace()) + fCurPos -= rgCurLineLayoutItems[0][j]->m_sSize.width; + + rgCurLineLayoutItems[0][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); + m_fLastRowWidth = fCurPos; + } + fCurPos = (fContentWidthLimit + fGroupWidths[0] + fGroupWidths[1] - + fGroupWidths[2]) / + 2; + for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { + if (rgCurLineLayoutItems[1][j]->m_pFormNode->PresenceRequiresSpace()) + fCurPos -= rgCurLineLayoutItems[1][j]->m_sSize.width; + + rgCurLineLayoutItems[1][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); + m_fLastRowWidth = fCurPos; + } + fCurPos = fContentWidthLimit; + for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { + if (rgCurLineLayoutItems[2][j]->m_pFormNode->PresenceRequiresSpace()) + fCurPos -= rgCurLineLayoutItems[2][j]->m_sSize.width; + + rgCurLineLayoutItems[2][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); + m_fLastRowWidth = fCurPos; } } - fItemsHeight += fChildHeight; - return m_pPageMgr->GetNextAvailContentHeight(fItemsHeight); + m_fLastRowY = *fContentCurRowY; + *fContentCurRowY += fContentCurRowHeight; + if (bContainerWidthAutoSize) { + float fChildSuppliedWidth = fGroupWidths[0]; + if (fContentWidthLimit < FLT_MAX && + fContentWidthLimit > fChildSuppliedWidth) { + fChildSuppliedWidth = fContentWidthLimit; + } + *fContentCalculatedWidth = + std::max(*fContentCalculatedWidth, fChildSuppliedWidth); + } + if (bContainerHeightAutoSize) { + *fContentCalculatedHeight = + std::max(*fContentCalculatedHeight, *fContentCurRowY); + } + return true; } -void CXFA_ItemLayoutProcessor::ProcessUnUseBinds(CXFA_Node* pFormNode) { - if (!pFormNode) - return; - - CXFA_NodeIteratorTemplate sIterator( - pFormNode); - for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode; - pNode = sIterator.MoveToNext()) { - if (pNode->IsContainerNode()) { - CXFA_Node* pBindNode = pNode->GetBindData(); - if (pBindNode) { - pBindNode->RemoveBindItem(pNode); - pNode->SetBindingNode(nullptr); - } +CXFA_Node* CXFA_ItemLayoutProcessor::GetSubformSetParent( + CXFA_Node* pSubformSet) { + if (pSubformSet && pSubformSet->GetElementType() == XFA_Element::SubformSet) { + CXFA_Node* pParent = pSubformSet->GetParent(); + while (pParent) { + if (pParent->GetElementType() != XFA_Element::SubformSet) + return pParent; + pParent = pParent->GetParent(); } - pNode->SetFlag(XFA_NodeFlag_UnusedNode, true); } + return pSubformSet; } -void CXFA_ItemLayoutProcessor::ProcessUnUseOverFlow( - CXFA_Node* pLeaderNode, - CXFA_Node* pTrailerNode, - CXFA_ContentLayoutItem* pTrailerItem, - CXFA_Node* pFormNode) { - ProcessUnUseBinds(pLeaderNode); - ProcessUnUseBinds(pTrailerNode); - if (!pFormNode) +void CXFA_ItemLayoutProcessor::DoLayoutField() { + if (m_pLayoutItem) return; - if (pFormNode->GetElementType() == XFA_Element::Overflow || - pFormNode->GetElementType() == XFA_Element::Break) { - pFormNode = pFormNode->GetParent(); - } - if (pLeaderNode && pFormNode) - pFormNode->RemoveChild(pLeaderNode, true); - if (pTrailerNode && pFormNode) - pFormNode->RemoveChild(pTrailerNode, true); - if (pTrailerItem) - XFA_ReleaseLayoutItem(pTrailerItem); + ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + if (!m_pLayoutItem) + return; + + CXFA_Document* pDocument = m_pFormNode->GetDocument(); + CXFA_FFNotify* pNotify = pDocument->GetNotify(); + CFX_SizeF size(-1, -1); + pNotify->StartFieldDrawLayout(m_pFormNode, size.width, size.height); + + int32_t nRotate = XFA_MapRotation( + m_pFormNode->JSObject()->GetInteger(XFA_Attribute::Rotate)); + if (nRotate == 90 || nRotate == 270) + std::swap(size.width, size.height); + + SetCurrentComponentSize(size); } -XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayoutFlowedContainer( +XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayout( bool bUseBreakControl, - XFA_AttributeEnum eFlowStrategy, float fHeightLimit, float fRealHeight, - CXFA_LayoutContext* pContext, - bool bRootForceTb) { - m_bHasAvailHeight = true; - bool bBreakDone = false; - bool bContainerWidthAutoSize = true; - bool bContainerHeightAutoSize = true; - bool bForceEndPage = false; - bool bIsManualBreak = false; - if (m_pCurChildPreprocessor) { - m_pCurChildPreprocessor->m_ePreProcessRs = - XFA_ItemLayoutProcessorResult::Done; - } - - CFX_SizeF containerSize = CalculateContainerSpecifiedSize( - m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); - if (pContext && pContext->m_bCurColumnWidthAvaiable) { - bContainerWidthAutoSize = false; - containerSize.width = pContext->m_fCurColumnWidth; - } - if (!bContainerHeightAutoSize) - containerSize.height -= m_fUsedSize; - - if (!bContainerHeightAutoSize) { - CXFA_Node* pParentNode = m_pFormNode->GetParent(); - bool bFocrTb = false; - if (pParentNode && - GetLayout(pParentNode, &bFocrTb) == XFA_AttributeEnum::Row) { - CXFA_Node* pChildContainer = m_pFormNode->GetFirstContainerChild(); - if (pChildContainer && pChildContainer->GetNextContainerSibling()) { - containerSize.height = 0; - bContainerHeightAutoSize = true; - } - } - } - - CXFA_Margin* pMarginNode = - m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); - float fLeftInset = 0; - float fTopInset = 0; - float fRightInset = 0; - float fBottomInset = 0; - if (pMarginNode) { - fLeftInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::LeftInset) - .ToUnit(XFA_Unit::Pt); - fTopInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::TopInset) - .ToUnit(XFA_Unit::Pt); - fRightInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::RightInset) - .ToUnit(XFA_Unit::Pt); - fBottomInset = pMarginNode->JSObject() - ->GetMeasure(XFA_Attribute::BottomInset) - .ToUnit(XFA_Unit::Pt); - } - float fContentWidthLimit = - bContainerWidthAutoSize ? FLT_MAX - : containerSize.width - fLeftInset - fRightInset; - float fContentCalculatedWidth = 0; - float fContentCalculatedHeight = 0; - float fAvailHeight = fHeightLimit - fTopInset - fBottomInset; - if (fAvailHeight < 0) - m_bHasAvailHeight = false; - - fRealHeight = fRealHeight - fTopInset - fBottomInset; - float fContentCurRowY = 0; - CXFA_ContentLayoutItem* pLayoutChild = nullptr; - if (m_pLayoutItem) { - if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done && - eFlowStrategy != XFA_AttributeEnum::Tb) { - pLayoutChild = (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; - pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { - if (pLayoutNext->m_sPos.y != pLayoutChild->m_sPos.y) - pLayoutChild = pLayoutNext; + CXFA_LayoutContext* pContext) { + switch (m_pFormNode->GetElementType()) { + case XFA_Element::Subform: + case XFA_Element::Area: + case XFA_Element::ExclGroup: + case XFA_Element::SubformSet: { + bool bRootForceTb = false; + CXFA_Node* pLayoutNode = GetSubformSetParent(m_pFormNode); + XFA_AttributeEnum eLayoutStrategy = GetLayout(pLayoutNode, &bRootForceTb); + switch (eLayoutStrategy) { + case XFA_AttributeEnum::Tb: + case XFA_AttributeEnum::Lr_tb: + case XFA_AttributeEnum::Rl_tb: + return DoLayoutFlowedContainer(bUseBreakControl, eLayoutStrategy, + fHeightLimit, fRealHeight, pContext, + bRootForceTb); + case XFA_AttributeEnum::Position: + case XFA_AttributeEnum::Row: + case XFA_AttributeEnum::Rl_row: + default: + DoLayoutPositionedContainer(pContext); + m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; + return XFA_ItemLayoutProcessorResult::Done; + case XFA_AttributeEnum::Table: + DoLayoutTableContainer(pLayoutNode); + m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; + return XFA_ItemLayoutProcessorResult::Done; } } + case XFA_Element::Draw: + case XFA_Element::Field: + DoLayoutField(); + m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; + return XFA_ItemLayoutProcessorResult::Done; + case XFA_Element::ContentArea: + return XFA_ItemLayoutProcessorResult::Done; + default: + return XFA_ItemLayoutProcessorResult::Done; + } +} - for (CXFA_ContentLayoutItem* pLayoutTempChild = - (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - pLayoutTempChild != pLayoutChild; - pLayoutTempChild = - (CXFA_ContentLayoutItem*)pLayoutTempChild->m_pNextSibling) { - if (!pLayoutTempChild->m_pFormNode->PresenceRequiresSpace()) - continue; - - fContentCalculatedWidth = std::max( - fContentCalculatedWidth, - pLayoutTempChild->m_sPos.x + pLayoutTempChild->m_sSize.width); - fContentCalculatedHeight = std::max( - fContentCalculatedHeight, - pLayoutTempChild->m_sPos.y + pLayoutTempChild->m_sSize.height); - } +CFX_SizeF CXFA_ItemLayoutProcessor::GetCurrentComponentSize() { + return CFX_SizeF(m_pLayoutItem->m_sSize.width, m_pLayoutItem->m_sSize.height); +} - if (pLayoutChild) - fContentCurRowY = pLayoutChild->m_sPos.y; - else - fContentCurRowY = fContentCalculatedHeight; - } +void CXFA_ItemLayoutProcessor::SetCurrentComponentPos(const CFX_PointF& pos) { + m_pLayoutItem->m_sPos = pos; +} - fContentCurRowY += InsertKeepLayoutItems(); - if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::None) { - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, - true); - } +void CXFA_ItemLayoutProcessor::SetCurrentComponentSize(const CFX_SizeF& size) { + m_pLayoutItem->m_sSize = size; +} - fContentCurRowY += InsertPendingItems(this, m_pFormNode); - if (m_pCurChildPreprocessor && - m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Container) { - if (ExistContainerKeep(m_pCurChildPreprocessor->GetFormNode(), false)) { - m_pKeepHeadNode = m_pCurChildNode; - m_bIsProcessKeep = true; - m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Keep; - } - } +bool CXFA_ItemLayoutProcessor::JudgeLeaderOrTrailerForOccur( + CXFA_Node* pFormNode) { + if (!pFormNode) + return false; - while (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done) { - float fContentCurRowHeight = 0; - float fContentCurRowAvailWidth = fContentWidthLimit; - m_fWidthLimite = fContentCurRowAvailWidth; - std::vector rgCurLineLayoutItems[3]; - uint8_t uCurHAlignState = - (eFlowStrategy != XFA_AttributeEnum::Rl_tb ? 0 : 2); - if (pLayoutChild) { - for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; - pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { - if (!pLayoutNext->m_pNextSibling && m_pCurChildPreprocessor && - m_pCurChildPreprocessor->m_pFormNode == pLayoutNext->m_pFormNode) { - pLayoutNext->m_pNext = m_pCurChildPreprocessor->m_pLayoutItem; - m_pCurChildPreprocessor->m_pLayoutItem = pLayoutNext; - break; - } - uint8_t uHAlign = - HAlignEnumToInt(pLayoutNext->m_pFormNode->JSObject()->GetEnum( - XFA_Attribute::HAlign)); - rgCurLineLayoutItems[uHAlign].push_back(pLayoutNext); - if (eFlowStrategy == XFA_AttributeEnum::Lr_tb) { - if (uHAlign > uCurHAlignState) - uCurHAlignState = uHAlign; - } else if (uHAlign < uCurHAlignState) { - uCurHAlignState = uHAlign; - } - if (pLayoutNext->m_pFormNode->PresenceRequiresSpace()) { - if (pLayoutNext->m_sSize.height > fContentCurRowHeight) - fContentCurRowHeight = pLayoutNext->m_sSize.height; - fContentCurRowAvailWidth -= pLayoutNext->m_sSize.width; - } - } + CXFA_Node* pTemplate = pFormNode->GetTemplateNodeIfExists(); + if (!pTemplate) + pTemplate = pFormNode; - if ((CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild == - pLayoutChild) { - m_pLayoutItem->m_pFirstChild = nullptr; - } else { - CXFA_ContentLayoutItem* pLayoutNext = - (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - for (; pLayoutNext; - pLayoutNext = - (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { - if ((CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling == - pLayoutChild) { - pLayoutNext->m_pNextSibling = nullptr; - break; - } - } - } + int32_t iMax = + pTemplate->GetFirstChildByClass(XFA_Element::Occur)->GetMax(); + if (iMax < 0) + return true; - CXFA_ContentLayoutItem* pLayoutNextTemp = - (CXFA_ContentLayoutItem*)pLayoutChild; - while (pLayoutNextTemp) { - pLayoutNextTemp->m_pParent = nullptr; - CXFA_ContentLayoutItem* pSaveLayoutNext = - (CXFA_ContentLayoutItem*)pLayoutNextTemp->m_pNextSibling; - pLayoutNextTemp->m_pNextSibling = nullptr; - pLayoutNextTemp = pSaveLayoutNext; - } - pLayoutChild = nullptr; - } + int32_t iCount = m_PendingNodesCount[pTemplate]; + if (iCount >= iMax) + return false; - while (m_pCurChildNode) { - std::unique_ptr pProcessor; - bool bAddedItemInRow = false; - fContentCurRowY += InsertPendingItems(this, m_pFormNode); - switch (m_nCurChildNodeStage) { - case XFA_ItemLayoutProcessorStages::Keep: - case XFA_ItemLayoutProcessorStages::None: - break; - case XFA_ItemLayoutProcessorStages::BreakBefore: { - for (auto* item : m_arrayKeepItems) { - m_pLayoutItem->RemoveChild(item); - fContentCalculatedHeight -= item->m_sSize.height; - } + m_PendingNodesCount[pTemplate] = iCount + 1; + return true; +} - CXFA_Node* pLeaderNode = nullptr; - CXFA_Node* pTrailerNode = nullptr; - bool bCreatePage = false; - if (!bUseBreakControl || !m_pPageMgr || - !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, true, - pLeaderNode, pTrailerNode, - bCreatePage) || - m_pFormNode->GetElementType() == XFA_Element::Form || - !bCreatePage) { - break; - } +void CXFA_ItemLayoutProcessor::UpdatePendingItemLayout( + CXFA_ContentLayoutItem* pLayoutItem) { + XFA_AttributeEnum eLayout = + pLayoutItem->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + switch (eLayout) { + case XFA_AttributeEnum::Row: + case XFA_AttributeEnum::Rl_row: + RelocateTableRowCells(pLayoutItem, m_rgSpecifiedColumnWidths, eLayout); + break; + default: + break; + } +} - if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) - AddPendingNode(this, pLeaderNode, true); +void CXFA_ItemLayoutProcessor::AddTrailerBeforeSplit( + float fSplitPos, + CXFA_ContentLayoutItem* pTrailerLayoutItem, + bool bUseInherited) { + if (!pTrailerLayoutItem) + return; - if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { - if (m_pFormNode->GetParent()->GetElementType() == - XFA_Element::Form && - !m_pLayoutItem) { - AddPendingNode(this, pTrailerNode, true); - } else { - auto pTempProcessor = - pdfium::MakeUnique(pTrailerNode, - nullptr); - InsertFlowedItem( - this, pTempProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, eFlowStrategy, - &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, - FLT_MAX, fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, false); - } - } - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, - m_pFormNode, true); - bForceEndPage = true; - bIsManualBreak = true; - goto SuspendAndCreateNewRow; - } - case XFA_ItemLayoutProcessorStages::BreakAfter: { - CXFA_Node* pLeaderNode = nullptr; - CXFA_Node* pTrailerNode = nullptr; - bool bCreatePage = false; - if (!bUseBreakControl || !m_pPageMgr || - !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, false, - pLeaderNode, pTrailerNode, - bCreatePage) || - m_pFormNode->GetElementType() == XFA_Element::Form) { - break; - } + float fHeight = pTrailerLayoutItem->m_sSize.height; + if (bUseInherited) { + float fNewSplitPos = 0; + if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) + fNewSplitPos = FindSplitPos(fSplitPos - fHeight); + if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) + SplitLayoutItem(fNewSplitPos); + return; + } - if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { - auto pTempProcessor = pdfium::MakeUnique( - pTrailerNode, nullptr); - InsertFlowedItem( - this, pTempProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, eFlowStrategy, - &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, FLT_MAX, - fContentWidthLimit, &fContentCurRowY, &fContentCurRowAvailWidth, - &fContentCurRowHeight, &bAddedItemInRow, &bForceEndPage, - pContext, false); - } - if (!bCreatePage) { - if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { - CalculateRowChildPosition( - rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, - bContainerWidthAutoSize, &fContentCalculatedWidth, - &fContentCalculatedHeight, &fContentCurRowY, - fContentCurRowHeight, fContentWidthLimit, false); - rgCurLineLayoutItems->clear(); - auto pTempProcessor = - pdfium::MakeUnique(pLeaderNode, - nullptr); - InsertFlowedItem( - this, pTempProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, eFlowStrategy, - &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, - FLT_MAX, fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, false); - } - } else { - if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) - AddPendingNode(this, pLeaderNode, true); - } + UpdatePendingItemLayout(pTrailerLayoutItem); + CXFA_Margin* pMarginNode = + m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); + float fLeftInset = 0; + float fTopInset = 0; + float fRightInset = 0; + float fBottomInset = 0; + if (pMarginNode) { + fLeftInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt); + fTopInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); + fRightInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::RightInset) + .ToUnit(XFA_Unit::Pt); + fBottomInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); + } - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, - m_pFormNode, true); - if (bCreatePage) { - bForceEndPage = true; - bIsManualBreak = true; - if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done) - bBreakDone = true; - } - goto SuspendAndCreateNewRow; - } - case XFA_ItemLayoutProcessorStages::BookendLeader: { - CXFA_Node* pLeaderNode = nullptr; - if (m_pCurChildPreprocessor) { - pProcessor.reset(m_pCurChildPreprocessor); - m_pCurChildPreprocessor = nullptr; - } else if (m_pPageMgr && - m_pPageMgr->ProcessBookendLeaderOrTrailer( - m_pCurChildNode, true, pLeaderNode)) { - pProcessor = pdfium::MakeUnique( - pLeaderNode, m_pPageMgr); - } + if (!IsAddNewRowForTrailer(pTrailerLayoutItem)) { + pTrailerLayoutItem->m_sPos.y = m_fLastRowY; + pTrailerLayoutItem->m_sPos.x = m_fLastRowWidth; + m_pLayoutItem->m_sSize.width += pTrailerLayoutItem->m_sSize.width; + m_pLayoutItem->AddChild(pTrailerLayoutItem); + return; + } - if (pProcessor) { - if (InsertFlowedItem( - this, pProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, - eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, - bUseBreakControl, fAvailHeight, fRealHeight, - fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, - false) != XFA_ItemLayoutProcessorResult::Done) { - goto SuspendAndCreateNewRow; - } else { - pProcessor.reset(); - } - } - break; - } - case XFA_ItemLayoutProcessorStages::BookendTrailer: { - CXFA_Node* pTrailerNode = nullptr; - if (m_pCurChildPreprocessor) { - pProcessor.reset(m_pCurChildPreprocessor); - m_pCurChildPreprocessor = nullptr; - } else if (m_pPageMgr && - m_pPageMgr->ProcessBookendLeaderOrTrailer( - m_pCurChildNode, false, pTrailerNode)) { - pProcessor = pdfium::MakeUnique( - pTrailerNode, m_pPageMgr); - } - if (pProcessor) { - if (InsertFlowedItem( - this, pProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, - eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, - bUseBreakControl, fAvailHeight, fRealHeight, - fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, - false) != XFA_ItemLayoutProcessorResult::Done) { - goto SuspendAndCreateNewRow; - } else { - pProcessor.reset(); - } - } - break; - } - case XFA_ItemLayoutProcessorStages::Container: { - ASSERT(m_pCurChildNode->IsContainerNode()); - if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) - break; - if (fContentCurRowY >= fHeightLimit + XFA_LAYOUT_FLOAT_PERCISION && - m_pCurChildNode->PresenceRequiresSpace()) { - bForceEndPage = true; - goto SuspendAndCreateNewRow; - } - if (!m_pCurChildNode->IsContainerNode()) - break; + float fNewSplitPos = 0; + if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) + fNewSplitPos = FindSplitPos(fSplitPos - fHeight); - bool bNewRow = false; - if (m_pCurChildPreprocessor) { - pProcessor.reset(m_pCurChildPreprocessor); - m_pCurChildPreprocessor = nullptr; - bNewRow = true; - } else { - pProcessor = pdfium::MakeUnique( - m_pCurChildNode, m_pPageMgr); - } + if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { + SplitLayoutItem(fNewSplitPos); + pTrailerLayoutItem->m_sPos.y = fNewSplitPos - fTopInset - fBottomInset; + } else { + pTrailerLayoutItem->m_sPos.y = fSplitPos - fTopInset - fBottomInset; + } - InsertPendingItems(pProcessor.get(), m_pCurChildNode); - XFA_ItemLayoutProcessorResult rs = InsertFlowedItem( - this, pProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, eFlowStrategy, - &uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl, - fAvailHeight, fRealHeight, fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, bNewRow); - switch (rs) { - case XFA_ItemLayoutProcessorResult::ManualBreak: - bIsManualBreak = true; - case XFA_ItemLayoutProcessorResult::PageFullBreak: - bForceEndPage = true; - case XFA_ItemLayoutProcessorResult::RowFullBreak: - goto SuspendAndCreateNewRow; - case XFA_ItemLayoutProcessorResult::Done: - default: - fContentCurRowY += - InsertPendingItems(pProcessor.get(), m_pCurChildNode); - pProcessor.reset(); - } - break; - } - case XFA_ItemLayoutProcessorStages::Done: - break; - default: - break; - } - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, - true); - if (bAddedItemInRow && eFlowStrategy == XFA_AttributeEnum::Tb) - break; - continue; - SuspendAndCreateNewRow: - if (pProcessor) - m_pCurChildPreprocessor = pProcessor.release(); + switch (pTrailerLayoutItem->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::HAlign)) { + case XFA_AttributeEnum::Right: + pTrailerLayoutItem->m_sPos.x = m_pLayoutItem->m_sSize.width - + fRightInset - + pTrailerLayoutItem->m_sSize.width; break; - } + case XFA_AttributeEnum::Center: + pTrailerLayoutItem->m_sPos.x = + (m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - + pTrailerLayoutItem->m_sSize.width) / + 2; + break; + case XFA_AttributeEnum::Left: + default: + pTrailerLayoutItem->m_sPos.x = fLeftInset; + break; + } + m_pLayoutItem->m_sSize.height += fHeight; + m_pLayoutItem->AddChild(pTrailerLayoutItem); +} - CalculateRowChildPosition( - rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, - bContainerWidthAutoSize, &fContentCalculatedWidth, - &fContentCalculatedHeight, &fContentCurRowY, fContentCurRowHeight, - fContentWidthLimit, bRootForceTb); - m_fWidthLimite = fContentCurRowAvailWidth; - if (bForceEndPage) +void CXFA_ItemLayoutProcessor::AddLeaderAfterSplit( + CXFA_ContentLayoutItem* pLeaderLayoutItem) { + UpdatePendingItemLayout(pLeaderLayoutItem); + + CXFA_Margin* pMarginNode = + m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); + float fLeftInset = 0; + float fRightInset = 0; + if (pMarginNode) { + fLeftInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt); + fRightInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::RightInset) + .ToUnit(XFA_Unit::Pt); + } + + float fHeight = pLeaderLayoutItem->m_sSize.height; + for (CXFA_ContentLayoutItem* pChildItem = + (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + pChildItem; + pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { + pChildItem->m_sPos.y += fHeight; + } + pLeaderLayoutItem->m_sPos.y = 0; + + switch (pLeaderLayoutItem->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::HAlign)) { + case XFA_AttributeEnum::Right: + pLeaderLayoutItem->m_sPos.x = m_pLayoutItem->m_sSize.width - fRightInset - + pLeaderLayoutItem->m_sSize.width; + break; + case XFA_AttributeEnum::Center: + pLeaderLayoutItem->m_sPos.x = + (m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - + pLeaderLayoutItem->m_sSize.width) / + 2; + break; + case XFA_AttributeEnum::Left: + default: + pLeaderLayoutItem->m_sPos.x = fLeftInset; break; } + m_pLayoutItem->m_sSize.height += fHeight; + m_pLayoutItem->AddChild(pLeaderLayoutItem); +} - bool bRetValue = - m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done && - m_PendingNodes.empty(); - if (bBreakDone) - bRetValue = false; - - containerSize = CalculateContainerComponentSizeFromContentSize( - m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, - bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); +void CXFA_ItemLayoutProcessor::AddPendingNode(CXFA_Node* pPendingNode, + bool bBreakPending) { + m_PendingNodes.push_back(pPendingNode); + m_bBreakPending = bBreakPending; +} - if (containerSize.height >= XFA_LAYOUT_FLOAT_PERCISION || m_pLayoutItem || - bRetValue) { - if (!m_pLayoutItem) - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - containerSize.height = std::max(containerSize.height, 0.f); +float CXFA_ItemLayoutProcessor::InsertPendingItems(CXFA_Node* pCurChildNode) { + float fTotalHeight = 0; + if (m_PendingNodes.empty()) + return fTotalHeight; - SetCurrentComponentSize(containerSize); - if (bForceEndPage) - m_fUsedSize = 0; - else - m_fUsedSize += m_pLayoutItem->m_sSize.height; + if (!m_pLayoutItem) { + m_pLayoutItem = CreateContentLayoutItem(pCurChildNode); + m_pLayoutItem->m_sSize.clear(); } - return bRetValue - ? XFA_ItemLayoutProcessorResult::Done - : (bIsManualBreak ? XFA_ItemLayoutProcessorResult::ManualBreak - : XFA_ItemLayoutProcessorResult::PageFullBreak); + while (!m_PendingNodes.empty()) { + auto pPendingProcessor = pdfium::MakeUnique( + m_PendingNodes.front(), nullptr); + m_PendingNodes.pop_front(); + pPendingProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); + CXFA_ContentLayoutItem* pPendingLayoutItem = + pPendingProcessor->HasLayoutItem() + ? pPendingProcessor->ExtractLayoutItem() + : nullptr; + if (pPendingLayoutItem) { + AddLeaderAfterSplit(pPendingLayoutItem); + if (m_bBreakPending) + fTotalHeight += pPendingLayoutItem->m_sSize.height; + } + } + return fTotalHeight; } -bool CXFA_ItemLayoutProcessor::CalculateRowChildPosition( - std::vector (&rgCurLineLayoutItems)[3], - XFA_AttributeEnum eFlowStrategy, - bool bContainerHeightAutoSize, +XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::InsertFlowedItem( + CXFA_ItemLayoutProcessor* pProcessor, bool bContainerWidthAutoSize, - float* fContentCalculatedWidth, - float* fContentCalculatedHeight, - float* fContentCurRowY, - float fContentCurRowHeight, + bool bContainerHeightAutoSize, + float fContainerHeight, + XFA_AttributeEnum eFlowStrategy, + uint8_t* uCurHAlignState, + std::vector (&rgCurLineLayoutItems)[3], + bool bUseBreakControl, + float fAvailHeight, + float fRealHeight, float fContentWidthLimit, - bool bRootForceTb) { - int32_t nGroupLengths[3] = {0, 0, 0}; - float fGroupWidths[3] = {0, 0, 0}; - int32_t nTotalLength = 0; - for (int32_t i = 0; i < 3; i++) { - nGroupLengths[i] = pdfium::CollectionSize(rgCurLineLayoutItems[i]); - for (int32_t c = nGroupLengths[i], j = 0; j < c; j++) { - nTotalLength++; - if (rgCurLineLayoutItems[i][j]->m_pFormNode->PresenceRequiresSpace()) - fGroupWidths[i] += rgCurLineLayoutItems[i][j]->m_sSize.width; + float* fContentCurRowY, + float* fContentCurRowAvailWidth, + float* fContentCurRowHeight, + bool* bAddedItemInRow, + bool* bForceEndPage, + CXFA_LayoutContext* pLayoutContext, + bool bNewRow) { + bool bTakeSpace = pProcessor->m_pFormNode->PresenceRequiresSpace(); + uint8_t uHAlign = HAlignEnumToInt( + m_pCurChildNode->JSObject()->GetEnum(XFA_Attribute::HAlign)); + if (bContainerWidthAutoSize) + uHAlign = 0; + + if ((eFlowStrategy != XFA_AttributeEnum::Rl_tb && + uHAlign < *uCurHAlignState) || + (eFlowStrategy == XFA_AttributeEnum::Rl_tb && + uHAlign > *uCurHAlignState)) { + return XFA_ItemLayoutProcessorResult::RowFullBreak; + } + + *uCurHAlignState = uHAlign; + bool bIsOwnSplit = + pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None; + bool bUseRealHeight = bTakeSpace && bContainerHeightAutoSize && bIsOwnSplit && + pProcessor->m_pFormNode->GetParent()->GetIntact() == + XFA_AttributeEnum::None; + bool bIsTransHeight = bTakeSpace; + if (bIsTransHeight && !bIsOwnSplit) { + bool bRootForceTb = false; + XFA_AttributeEnum eLayoutStrategy = + GetLayout(pProcessor->m_pFormNode, &bRootForceTb); + if (eLayoutStrategy == XFA_AttributeEnum::Lr_tb || + eLayoutStrategy == XFA_AttributeEnum::Rl_tb) { + bIsTransHeight = false; } } - if (!nTotalLength) { - if (bContainerHeightAutoSize) { - *fContentCalculatedHeight = - std::min(*fContentCalculatedHeight, *fContentCurRowY); + + bool bUseInherited = false; + CXFA_LayoutContext layoutContext; + if (m_pPageMgr) { + CXFA_Node* pOverflowNode = m_pPageMgr->QueryOverflow(m_pFormNode); + if (pOverflowNode) { + layoutContext.m_pOverflowNode = pOverflowNode; + layoutContext.m_pOverflowProcessor = this; + pLayoutContext = &layoutContext; } - return false; } - if (!m_pLayoutItem) - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - if (eFlowStrategy != XFA_AttributeEnum::Rl_tb) { - float fCurPos; - fCurPos = 0; - for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { - if (bRootForceTb) { - rgCurLineLayoutItems[0][j]->m_sPos = CalculatePositionedContainerPos( - rgCurLineLayoutItems[0][j]->m_pFormNode, - rgCurLineLayoutItems[0][j]->m_sSize); - } else { - rgCurLineLayoutItems[0][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - if (rgCurLineLayoutItems[0][j]->m_pFormNode->PresenceRequiresSpace()) - fCurPos += rgCurLineLayoutItems[0][j]->m_sSize.width; - } - m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); - m_fLastRowWidth = fCurPos; + XFA_ItemLayoutProcessorResult eRetValue = XFA_ItemLayoutProcessorResult::Done; + if (!bNewRow || + pProcessor->m_ePreProcessRs == XFA_ItemLayoutProcessorResult::Done) { + eRetValue = pProcessor->DoLayout( + bTakeSpace ? bUseBreakControl : false, + bUseRealHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, + bIsTransHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, + pLayoutContext); + pProcessor->m_ePreProcessRs = eRetValue; + } else { + eRetValue = pProcessor->m_ePreProcessRs; + pProcessor->m_ePreProcessRs = XFA_ItemLayoutProcessorResult::Done; + } + if (pProcessor->HasLayoutItem() == false) + return eRetValue; + + CFX_SizeF childSize = pProcessor->GetCurrentComponentSize(); + if (bUseRealHeight && fRealHeight < XFA_LAYOUT_FLOAT_PERCISION) { + fRealHeight = FLT_MAX; + fAvailHeight = FLT_MAX; + } + if (bTakeSpace && + (childSize.width > + *fContentCurRowAvailWidth + XFA_LAYOUT_FLOAT_PERCISION) && + (fContentWidthLimit - *fContentCurRowAvailWidth > + XFA_LAYOUT_FLOAT_PERCISION)) { + return XFA_ItemLayoutProcessorResult::RowFullBreak; + } + + CXFA_Node* pOverflowLeaderNode = nullptr; + CXFA_Node* pOverflowTrailerNode = nullptr; + CXFA_Node* pFormNode = nullptr; + CXFA_ContentLayoutItem* pTrailerLayoutItem = nullptr; + bool bIsAddTrailerHeight = false; + if (m_pPageMgr && + pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None) { + pFormNode = m_pPageMgr->QueryOverflow(pProcessor->m_pFormNode); + if (!pFormNode && pLayoutContext && pLayoutContext->m_pOverflowProcessor) { + pFormNode = pLayoutContext->m_pOverflowNode; + bUseInherited = true; } - fCurPos = (fContentWidthLimit + fGroupWidths[0] - fGroupWidths[1] - - fGroupWidths[2]) / - 2; - for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { - if (bRootForceTb) { - rgCurLineLayoutItems[1][j]->m_sPos = CalculatePositionedContainerPos( - rgCurLineLayoutItems[1][j]->m_pFormNode, - rgCurLineLayoutItems[1][j]->m_sSize); - } else { - rgCurLineLayoutItems[1][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - if (rgCurLineLayoutItems[1][j]->m_pFormNode->PresenceRequiresSpace()) - fCurPos += rgCurLineLayoutItems[1][j]->m_sSize.width; + if (m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, + pOverflowTrailerNode, false, false)) { + if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowTrailerNode)) { + if (pOverflowTrailerNode) { + auto pOverflowLeaderProcessor = + pdfium::MakeUnique(pOverflowTrailerNode, + nullptr); + pOverflowLeaderProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); + pTrailerLayoutItem = + pOverflowLeaderProcessor->HasLayoutItem() + ? pOverflowLeaderProcessor->ExtractLayoutItem() + : nullptr; + } + + bIsAddTrailerHeight = + bUseInherited + ? IsAddNewRowForTrailer(pTrailerLayoutItem) + : pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem); + if (bIsAddTrailerHeight) { + childSize.height += pTrailerLayoutItem->m_sSize.height; + bIsAddTrailerHeight = true; + } } - m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); - m_fLastRowWidth = fCurPos; } - fCurPos = fContentWidthLimit - fGroupWidths[2]; - for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { - if (bRootForceTb) { - rgCurLineLayoutItems[2][j]->m_sPos = CalculatePositionedContainerPos( - rgCurLineLayoutItems[2][j]->m_pFormNode, - rgCurLineLayoutItems[2][j]->m_sSize); + } + + if (!bTakeSpace || + *fContentCurRowY + childSize.height <= + fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION || + (!bContainerHeightAutoSize && + m_fUsedSize + fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION >= + fContainerHeight)) { + if (!bTakeSpace || eRetValue == XFA_ItemLayoutProcessorResult::Done) { + if (pProcessor->m_bUseInheriated) { + if (pTrailerLayoutItem) + pProcessor->AddTrailerBeforeSplit(childSize.height, + pTrailerLayoutItem, false); + if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) + pProcessor->AddPendingNode(pOverflowLeaderNode, false); + + pProcessor->m_bUseInheriated = false; } else { - rgCurLineLayoutItems[2][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - if (rgCurLineLayoutItems[2][j]->m_pFormNode->PresenceRequiresSpace()) - fCurPos += rgCurLineLayoutItems[2][j]->m_sSize.width; - } - m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); - m_fLastRowWidth = fCurPos; - } - } else { - float fCurPos; - fCurPos = fGroupWidths[0]; - for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { - if (rgCurLineLayoutItems[0][j]->m_pFormNode->PresenceRequiresSpace()) - fCurPos -= rgCurLineLayoutItems[0][j]->m_sSize.width; + if (bIsAddTrailerHeight) + childSize.height -= pTrailerLayoutItem->m_sSize.height; - rgCurLineLayoutItems[0][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); - m_fLastRowWidth = fCurPos; - } - fCurPos = (fContentWidthLimit + fGroupWidths[0] + fGroupWidths[1] - - fGroupWidths[2]) / - 2; - for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { - if (rgCurLineLayoutItems[1][j]->m_pFormNode->PresenceRequiresSpace()) - fCurPos -= rgCurLineLayoutItems[1][j]->m_sSize.width; + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + } - rgCurLineLayoutItems[1][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); - m_fLastRowWidth = fCurPos; + CXFA_ContentLayoutItem* pChildLayoutItem = + pProcessor->ExtractLayoutItem(); + if (ExistContainerKeep(pProcessor->m_pFormNode, false) && + pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None) { + m_arrayKeepItems.push_back(pChildLayoutItem); + } else { + m_arrayKeepItems.clear(); + } + rgCurLineLayoutItems[uHAlign].push_back(pChildLayoutItem); + *bAddedItemInRow = true; + if (bTakeSpace) { + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = + std::max(*fContentCurRowHeight, childSize.height); + } + return XFA_ItemLayoutProcessorResult::Done; } - fCurPos = fContentWidthLimit; - for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { - if (rgCurLineLayoutItems[2][j]->m_pFormNode->PresenceRequiresSpace()) - fCurPos -= rgCurLineLayoutItems[2][j]->m_sSize.width; - rgCurLineLayoutItems[2][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); - m_fLastRowWidth = fCurPos; - } - } - m_fLastRowY = *fContentCurRowY; - *fContentCurRowY += fContentCurRowHeight; - if (bContainerWidthAutoSize) { - float fChildSuppliedWidth = fGroupWidths[0]; - if (fContentWidthLimit < FLT_MAX && - fContentWidthLimit > fChildSuppliedWidth) { - fChildSuppliedWidth = fContentWidthLimit; - } - *fContentCalculatedWidth = - std::max(*fContentCalculatedWidth, fChildSuppliedWidth); - } - if (bContainerHeightAutoSize) { - *fContentCalculatedHeight = - std::max(*fContentCalculatedHeight, *fContentCurRowY); - } - return true; -} + if (eRetValue == XFA_ItemLayoutProcessorResult::PageFullBreak) { + if (pProcessor->m_bUseInheriated) { + if (pTrailerLayoutItem) { + pProcessor->AddTrailerBeforeSplit(childSize.height, + pTrailerLayoutItem, false); + } + if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) + pProcessor->AddPendingNode(pOverflowLeaderNode, false); -CXFA_Node* CXFA_ItemLayoutProcessor::GetSubformSetParent( - CXFA_Node* pSubformSet) { - if (pSubformSet && pSubformSet->GetElementType() == XFA_Element::SubformSet) { - CXFA_Node* pParent = pSubformSet->GetParent(); - while (pParent) { - if (pParent->GetElementType() != XFA_Element::SubformSet) - return pParent; - pParent = pParent->GetParent(); + pProcessor->m_bUseInheriated = false; + } else { + if (bIsAddTrailerHeight) + childSize.height -= pTrailerLayoutItem->m_sSize.height; + + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + } } + rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); + return eRetValue; } - return pSubformSet; -} - -void CXFA_ItemLayoutProcessor::DoLayoutField() { - if (m_pLayoutItem) - return; - ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - if (!m_pLayoutItem) - return; + XFA_ItemLayoutProcessorResult eResult; + if (ProcessKeepForSplit(pProcessor, eRetValue, &rgCurLineLayoutItems[uHAlign], + fContentCurRowAvailWidth, fContentCurRowHeight, + fContentCurRowY, bAddedItemInRow, bForceEndPage, + &eResult)) { + return eResult; + } - CXFA_Document* pDocument = m_pFormNode->GetDocument(); - CXFA_FFNotify* pNotify = pDocument->GetNotify(); - CFX_SizeF size(-1, -1); - pNotify->StartFieldDrawLayout(m_pFormNode, size.width, size.height); + *bForceEndPage = true; + float fSplitPos = pProcessor->FindSplitPos(fAvailHeight - *fContentCurRowY); + if (fSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { + XFA_AttributeEnum eLayout = + pProcessor->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + if (eLayout == XFA_AttributeEnum::Tb && + eRetValue == XFA_ItemLayoutProcessorResult::Done) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, pTrailerLayoutItem, + pFormNode); + rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + if (bTakeSpace) { + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = + std::max(*fContentCurRowHeight, childSize.height); + } + return XFA_ItemLayoutProcessorResult::PageFullBreak; + } - int32_t nRotate = XFA_MapRotation( - m_pFormNode->JSObject()->GetInteger(XFA_Attribute::Rotate)); - if (nRotate == 90 || nRotate == 270) - std::swap(size.width, size.height); + CXFA_Node* pTempLeaderNode = nullptr; + CXFA_Node* pTempTrailerNode = nullptr; + if (m_pPageMgr && !pProcessor->m_bUseInheriated && + eRetValue != XFA_ItemLayoutProcessorResult::PageFullBreak) { + m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, pTempTrailerNode, + false, true); + } + if (pTrailerLayoutItem && bIsAddTrailerHeight) { + pProcessor->AddTrailerBeforeSplit(fSplitPos, pTrailerLayoutItem, + bUseInherited); + } else { + pProcessor->SplitLayoutItem(fSplitPos); + } - SetCurrentComponentSize(size); -} + if (bUseInherited) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, pTrailerLayoutItem, + pFormNode); + m_bUseInheriated = true; + } else { + CXFA_LayoutItem* firstChild = pProcessor->m_pLayoutItem->m_pFirstChild; + if (firstChild && !firstChild->m_pNextSibling && + firstChild->m_pFormNode->IsLayoutGeneratedNode()) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + } else if (pProcessor->JudgeLeaderOrTrailerForOccur( + pOverflowLeaderNode)) { + pProcessor->AddPendingNode(pOverflowLeaderNode, false); + } + } -XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayout( - bool bUseBreakControl, - float fHeightLimit, - float fRealHeight, - CXFA_LayoutContext* pContext) { - switch (m_pFormNode->GetElementType()) { - case XFA_Element::Subform: - case XFA_Element::Area: - case XFA_Element::ExclGroup: - case XFA_Element::SubformSet: { - bool bRootForceTb = false; - CXFA_Node* pLayoutNode = GetSubformSetParent(m_pFormNode); - XFA_AttributeEnum eLayoutStrategy = GetLayout(pLayoutNode, &bRootForceTb); - switch (eLayoutStrategy) { - case XFA_AttributeEnum::Tb: - case XFA_AttributeEnum::Lr_tb: - case XFA_AttributeEnum::Rl_tb: - return DoLayoutFlowedContainer(bUseBreakControl, eLayoutStrategy, - fHeightLimit, fRealHeight, pContext, - bRootForceTb); - case XFA_AttributeEnum::Position: - case XFA_AttributeEnum::Row: - case XFA_AttributeEnum::Rl_row: - default: - DoLayoutPositionedContainer(pContext); - m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; - return XFA_ItemLayoutProcessorResult::Done; - case XFA_AttributeEnum::Table: - DoLayoutTableContainer(pLayoutNode); - m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; - return XFA_ItemLayoutProcessorResult::Done; + if (pProcessor->m_pLayoutItem->m_pNextSibling) { + childSize = pProcessor->GetCurrentComponentSize(); + rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + if (bTakeSpace) { + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = + std::max(*fContentCurRowHeight, childSize.height); } } - case XFA_Element::Draw: - case XFA_Element::Field: - DoLayoutField(); - m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; - return XFA_ItemLayoutProcessorResult::Done; - case XFA_Element::ContentArea: - return XFA_ItemLayoutProcessorResult::Done; - default: - return XFA_ItemLayoutProcessorResult::Done; + return XFA_ItemLayoutProcessorResult::PageFullBreak; } -} -CFX_SizeF CXFA_ItemLayoutProcessor::GetCurrentComponentSize() { - return CFX_SizeF(m_pLayoutItem->m_sSize.width, m_pLayoutItem->m_sSize.height); -} + if (*fContentCurRowY <= XFA_LAYOUT_FLOAT_PERCISION) { + childSize = pProcessor->GetCurrentComponentSize(); + if (pProcessor->m_pPageMgr->GetNextAvailContentHeight(childSize.height)) { + CXFA_Node* pTempLeaderNode = nullptr; + CXFA_Node* pTempTrailerNode = nullptr; + if (m_pPageMgr) { + if (!pFormNode && pLayoutContext) + pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; -void CXFA_ItemLayoutProcessor::SetCurrentComponentPos(const CFX_PointF& pos) { - m_pLayoutItem->m_sPos = pos; -} + m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, + pTempTrailerNode, false, true); + } + if (bUseInherited) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + m_bUseInheriated = true; + } + return XFA_ItemLayoutProcessorResult::PageFullBreak; + } -void CXFA_ItemLayoutProcessor::SetCurrentComponentSize(const CFX_SizeF& size) { - m_pLayoutItem->m_sSize = size; -} + rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + if (bTakeSpace) { + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); + } + if (eRetValue == XFA_ItemLayoutProcessorResult::Done) + *bForceEndPage = false; -bool CXFA_ItemLayoutProcessor::JudgeLeaderOrTrailerForOccur( - CXFA_Node* pFormNode) { - if (!pFormNode) - return false; + return eRetValue; + } - CXFA_Node* pTemplate = pFormNode->GetTemplateNodeIfExists(); - if (!pTemplate) - pTemplate = pFormNode; + XFA_AttributeEnum eLayout = + pProcessor->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + if (pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None && + eLayout == XFA_AttributeEnum::Tb) { + if (m_pPageMgr) { + m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, + pOverflowTrailerNode, false, true); + } + if (pTrailerLayoutItem) + pProcessor->AddTrailerBeforeSplit(fSplitPos, pTrailerLayoutItem, false); + if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) + pProcessor->AddPendingNode(pOverflowLeaderNode, false); - int32_t iMax = - pTemplate->GetFirstChildByClass(XFA_Element::Occur)->GetMax(); - if (iMax < 0) - return true; + return XFA_ItemLayoutProcessorResult::PageFullBreak; + } - int32_t iCount = m_PendingNodesCount[pTemplate]; - if (iCount >= iMax) - return false; + if (eRetValue != XFA_ItemLayoutProcessorResult::Done) + return XFA_ItemLayoutProcessorResult::PageFullBreak; - m_PendingNodesCount[pTemplate] = iCount + 1; - return true; + if (!pFormNode && pLayoutContext) + pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; + if (m_pPageMgr) { + m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, + pOverflowTrailerNode, false, true); + } + if (bUseInherited) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + m_bUseInheriated = true; + } + return XFA_ItemLayoutProcessorResult::PageFullBreak; } diff --git a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.h b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.h index 7dbc754ec6..fdca14285f 100644 --- a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.h +++ b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.h @@ -48,10 +48,6 @@ enum class XFA_ItemLayoutProcessorStages { class CXFA_ItemLayoutProcessor { public: - static bool IncrementRelayoutNode(CXFA_LayoutProcessor* pLayoutProcessor, - CXFA_Node* pNode, - CXFA_Node* pParentNode); - CXFA_ItemLayoutProcessor(CXFA_Node* pNode, CXFA_LayoutPageMgr* pPageMgr); ~CXFA_ItemLayoutProcessor(); @@ -61,16 +57,17 @@ class CXFA_ItemLayoutProcessor { CXFA_LayoutContext* pContext); void DoLayoutPageArea(CXFA_ContainerLayoutItem* pPageAreaLayoutItem); - CFX_SizeF GetCurrentComponentSize(); CXFA_Node* GetFormNode() { return m_pFormNode; } - bool HasLayoutItem() const { return !!m_pLayoutItem; } CXFA_ContentLayoutItem* ExtractLayoutItem(); + + private: + CFX_SizeF GetCurrentComponentSize(); + bool HasLayoutItem() const { return !!m_pLayoutItem; } void SplitLayoutItem(float fSplitPos); float FindSplitPos(float fProposedSplitPos); bool ProcessKeepForSplit( - CXFA_ItemLayoutProcessor* pParentProcessor, CXFA_ItemLayoutProcessor* pChildProcessor, XFA_ItemLayoutProcessorResult eRetValue, std::vector* rgCurLineLayoutItem, @@ -89,21 +86,6 @@ class CXFA_ItemLayoutProcessor { CXFA_ContentLayoutItem* CreateContentLayoutItem(CXFA_Node* pFormNode); - CXFA_Node* m_pFormNode; - CXFA_ContentLayoutItem* m_pLayoutItem; - CXFA_Node* m_pCurChildNode; - float m_fUsedSize; - CXFA_LayoutPageMgr* m_pPageMgr; - std::list m_PendingNodes; - bool m_bBreakPending; - std::vector m_rgSpecifiedColumnWidths; - std::vector m_arrayKeepItems; - float m_fLastRowWidth; - float m_fLastRowY; - bool m_bUseInheriated; - XFA_ItemLayoutProcessorResult m_ePreProcessRs; - - private: void SetCurrentComponentPos(const CFX_PointF& pos); void SetCurrentComponentSize(const CFX_SizeF& size); @@ -139,21 +121,61 @@ class CXFA_ItemLayoutProcessor { void DoLayoutField(); void GotoNextContainerNode(CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, + XFA_ItemLayoutProcessorStages* nCurStage, CXFA_Node* pParentContainer, bool bUsePageBreak); bool ProcessKeepNodesForCheckNext(CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, + XFA_ItemLayoutProcessorStages* nCurStage, CXFA_Node*& pNextContainer, bool& bLastKeepNode); bool ProcessKeepNodesForBreakBefore(CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, + XFA_ItemLayoutProcessorStages* nCurStage, CXFA_Node* pContainerNode); CXFA_Node* GetSubformSetParent(CXFA_Node* pSubformSet); + void UpdatePendingItemLayout(CXFA_ContentLayoutItem* pLayoutItem); + void AddTrailerBeforeSplit(float fSplitPos, + CXFA_ContentLayoutItem* pTrailerLayoutItem, + bool bUseInherited); + void AddLeaderAfterSplit(CXFA_ContentLayoutItem* pLeaderLayoutItem); + void AddPendingNode(CXFA_Node* pPendingNode, bool bBreakPending); + float InsertPendingItems(CXFA_Node* pCurChildNode); + XFA_ItemLayoutProcessorResult InsertFlowedItem( + CXFA_ItemLayoutProcessor* pProcessor, + bool bContainerWidthAutoSize, + bool bContainerHeightAutoSize, + float fContainerHeight, + XFA_AttributeEnum eFlowStrategy, + uint8_t* uCurHAlignState, + std::vector (&rgCurLineLayoutItems)[3], + bool bUseBreakControl, + float fAvailHeight, + float fRealHeight, + float fContentWidthLimit, + float* fContentCurRowY, + float* fContentCurRowAvailWidth, + float* fContentCurRowHeight, + bool* bAddedItemInRow, + bool* bForceEndPage, + CXFA_LayoutContext* pLayoutContext, + bool bNewRow); + + CXFA_Node* m_pFormNode; + CXFA_ContentLayoutItem* m_pLayoutItem; + CXFA_Node* m_pCurChildNode; + float m_fUsedSize; + CXFA_LayoutPageMgr* m_pPageMgr; + std::list m_PendingNodes; + bool m_bBreakPending; + std::vector m_rgSpecifiedColumnWidths; + std::vector m_arrayKeepItems; + float m_fLastRowWidth; + float m_fLastRowY; + bool m_bUseInheriated; + XFA_ItemLayoutProcessorResult m_ePreProcessRs; bool m_bKeepBreakFinish; bool m_bIsProcessKeep; CXFA_Node* m_pKeepHeadNode; diff --git a/xfa/fxfa/parser/cxfa_layoutprocessor.cpp b/xfa/fxfa/parser/cxfa_layoutprocessor.cpp index 540e1c9156..c31766f6f6 100644 --- a/xfa/fxfa/parser/cxfa_layoutprocessor.cpp +++ b/xfa/fxfa/parser/cxfa_layoutprocessor.cpp @@ -101,17 +101,7 @@ bool CXFA_LayoutProcessor::IncrementLayout() { StartLayout(true); return DoLayout() == 100; } - for (CXFA_Node* pNode : m_rgChangedContainers) { - CXFA_Node* pParentNode = pNode->GetContainerParent(); - if (!pParentNode) - return false; - if (!CXFA_ItemLayoutProcessor::IncrementRelayoutNode(this, pNode, - pParentNode)) { - return false; - } - } - m_rgChangedContainers.clear(); - return true; + return m_rgChangedContainers.empty(); } int32_t CXFA_LayoutProcessor::CountPages() const { -- cgit v1.2.3