// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "xfa/fxfa/parser/xfa_layout_itemlayout.h" #include <algorithm> #include <memory> #include <vector> #include "third_party/base/stl_util.h" #include "xfa/fxfa/app/xfa_ffnotify.h" #include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" #include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" #include "xfa/fxfa/parser/cxfa_document.h" #include "xfa/fxfa/parser/cxfa_layoutpagemgr.h" #include "xfa/fxfa/parser/cxfa_measurement.h" #include "xfa/fxfa/parser/cxfa_occur.h" #include "xfa/fxfa/parser/xfa_localemgr.h" #include "xfa/fxfa/parser/xfa_object.h" #include "xfa/fxfa/parser/xfa_utils.h" namespace { int32_t SeparateStringW(const FX_WCHAR* pStr, int32_t iStrLen, FX_WCHAR delimiter, std::vector<CFX_WideString>& pieces) { if (!pStr) return 0; if (iStrLen < 0) iStrLen = FXSYS_wcslen(pStr); const FX_WCHAR* pToken = pStr; const FX_WCHAR* pEnd = pStr + iStrLen; while (true) { if (pStr >= pEnd || delimiter == *pStr) { pieces.push_back(CFX_WideString(pToken, pStr - pToken)); pToken = pStr + 1; if (pStr >= pEnd) break; } pStr++; } return pdfium::CollectionSize<int32_t>(pieces); } } // namespace CXFA_ItemLayoutProcessor::CXFA_ItemLayoutProcessor(CXFA_Node* pNode, CXFA_LayoutPageMgr* pPageMgr) : m_bKeepBreakFinish(false), m_bIsProcessKeep(false), m_pKeepHeadNode(nullptr), m_pKeepTailNode(nullptr), m_pFormNode(pNode), m_pLayoutItem(nullptr), m_pOldLayoutItem(nullptr), m_pCurChildNode(XFA_LAYOUT_INVALIDNODE), m_pCurChildPreprocessor(nullptr), m_nCurChildNodeStage(XFA_ItemLayoutProcessorStages_None), m_fUsedSize(0), m_pPageMgr(pPageMgr), m_bBreakPending(true), m_fLastRowWidth(0), m_fLastRowY(0), m_fWidthLimite(0), m_bUseInheriated(false), m_ePreProcessRs(XFA_ItemLayoutProcessorResult_Done), m_bHasAvailHeight(true) { ASSERT(m_pFormNode && (m_pFormNode->IsContainerNode() || m_pFormNode->GetElementType() == XFA_Element::Form)); m_pOldLayoutItem = (CXFA_ContentLayoutItem*)m_pFormNode->GetUserData(XFA_LAYOUTITEMKEY); } CXFA_ItemLayoutProcessor::~CXFA_ItemLayoutProcessor() {} CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::CreateContentLayoutItem( CXFA_Node* pFormNode) { if (!pFormNode) { return nullptr; } CXFA_ContentLayoutItem* pLayoutItem = nullptr; if (m_pOldLayoutItem) { pLayoutItem = m_pOldLayoutItem; m_pOldLayoutItem = m_pOldLayoutItem->m_pNext; return pLayoutItem; } pLayoutItem = (CXFA_ContentLayoutItem*)pFormNode->GetDocument() ->GetNotify() ->OnCreateLayoutItem(pFormNode); CXFA_ContentLayoutItem* pPrevLayoutItem = (CXFA_ContentLayoutItem*)pFormNode->GetUserData(XFA_LAYOUTITEMKEY); if (pPrevLayoutItem) { while (pPrevLayoutItem->m_pNext) { pPrevLayoutItem = pPrevLayoutItem->m_pNext; } pPrevLayoutItem->m_pNext = pLayoutItem; pLayoutItem->m_pPrev = pPrevLayoutItem; } else { pFormNode->SetUserData(XFA_LAYOUTITEMKEY, pLayoutItem); } return pLayoutItem; } bool CXFA_ItemLayoutProcessor::FindLayoutItemSplitPos( CXFA_ContentLayoutItem* pLayoutItem, FX_FLOAT fCurVerticalOffset, FX_FLOAT& fProposedSplitPos, bool& bAppChange, bool bCalculateMargin) { CXFA_Node* pFormNode = pLayoutItem->m_pFormNode; if (fProposedSplitPos > fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION && fProposedSplitPos <= fCurVerticalOffset + pLayoutItem->m_sSize.y - XFA_LAYOUT_FLOAT_PERCISION) { switch (pFormNode->GetIntact()) { case XFA_ATTRIBUTEENUM_None: { bool bAnyChanged = false; CXFA_Document* pDocument = pFormNode->GetDocument(); CXFA_FFNotify* pNotify = pDocument->GetNotify(); FX_FLOAT fCurTopMargin = 0, fCurBottomMargin = 0; CXFA_Node* pMarginNode = pFormNode->GetFirstChildByClass(XFA_Element::Margin); if (pMarginNode && bCalculateMargin) { fCurTopMargin = pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset) .ToUnit(XFA_UNIT_Pt); fCurBottomMargin = pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset) .ToUnit(XFA_UNIT_Pt); } bool bChanged = true; while (bChanged) { bChanged = false; { FX_FLOAT fRelSplitPos = fProposedSplitPos - fCurVerticalOffset; if (pNotify->FindSplitPos(pFormNode, pLayoutItem->GetIndex(), fRelSplitPos)) { bAnyChanged = true; bChanged = true; fProposedSplitPos = fCurVerticalOffset + fRelSplitPos; bAppChange = true; if (fProposedSplitPos <= fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { return true; } } } FX_FLOAT fRelSplitPos = fProposedSplitPos - fCurBottomMargin; for (CXFA_ContentLayoutItem* pChildItem = (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; pChildItem; pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { FX_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; } break; case XFA_ATTRIBUTEENUM_ContentArea: case XFA_ATTRIBUTEENUM_PageArea: { fProposedSplitPos = fCurVerticalOffset; return true; } default: return false; } } return false; } static XFA_ATTRIBUTEENUM XFA_ItemLayoutProcessor_GetLayout(CXFA_Node* pFormNode, bool& bRootForceTb) { bRootForceTb = false; XFA_ATTRIBUTEENUM eLayoutMode; if (pFormNode->TryEnum(XFA_ATTRIBUTE_Layout, eLayoutMode, false)) { return eLayoutMode; } CXFA_Node* pParentNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent); if (pParentNode && pParentNode->GetElementType() == XFA_Element::Form) { bRootForceTb = true; return XFA_ATTRIBUTEENUM_Tb; } return XFA_ATTRIBUTEENUM_Position; } static bool XFA_ExistContainerKeep(CXFA_Node* pCurNode, bool bPreFind) { if (!pCurNode || !XFA_ItemLayoutProcessor_IsTakingSpace(pCurNode)) { return false; } XFA_NODEITEM eItemType = XFA_NODEITEM_PrevSibling; if (!bPreFind) { eItemType = XFA_NODEITEM_NextSibling; } CXFA_Node* pPreContainer = pCurNode->GetNodeItem(eItemType, XFA_ObjectType::ContainerNode); if (!pPreContainer) { return false; } CXFA_Node* pKeep = pCurNode->GetFirstChildByClass(XFA_Element::Keep); if (pKeep) { XFA_ATTRIBUTEENUM ePrevious; XFA_ATTRIBUTE eKeepType = XFA_ATTRIBUTE_Previous; if (!bPreFind) { eKeepType = XFA_ATTRIBUTE_Next; } if (pKeep->TryEnum(eKeepType, ePrevious, false)) { if (ePrevious == XFA_ATTRIBUTEENUM_ContentArea || ePrevious == XFA_ATTRIBUTEENUM_PageArea) { return true; } } } pKeep = pPreContainer->GetFirstChildByClass(XFA_Element::Keep); if (!pKeep) { return false; } XFA_ATTRIBUTEENUM eNext; XFA_ATTRIBUTE eKeepType = XFA_ATTRIBUTE_Next; if (!bPreFind) { eKeepType = XFA_ATTRIBUTE_Previous; } if (!pKeep->TryEnum(eKeepType, eNext, false)) { return false; } if (eNext == XFA_ATTRIBUTEENUM_ContentArea || eNext == XFA_ATTRIBUTEENUM_PageArea) { return true; } return false; } FX_FLOAT CXFA_ItemLayoutProcessor::FindSplitPos(FX_FLOAT fProposedSplitPos) { ASSERT(m_pLayoutItem); XFA_ATTRIBUTEENUM eLayout = m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); bool bCalculateMargin = true; if (eLayout == XFA_ATTRIBUTEENUM_Position) { bCalculateMargin = false; } while (fProposedSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { bool bAppChange = false; if (!FindLayoutItemSplitPos(m_pLayoutItem, 0, fProposedSplitPos, bAppChange, bCalculateMargin)) { break; } } return fProposedSplitPos; } void CXFA_ItemLayoutProcessor::SplitLayoutItem( CXFA_ContentLayoutItem* pLayoutItem, CXFA_ContentLayoutItem* pSecondParent, FX_FLOAT fSplitPos) { FX_FLOAT fCurTopMargin = 0, fCurBottomMargin = 0; XFA_ATTRIBUTEENUM eLayout = m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); bool bCalculateMargin = true; if (eLayout == XFA_ATTRIBUTEENUM_Position) { bCalculateMargin = false; } CXFA_Node* pMarginNode = pLayoutItem->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); if (pMarginNode && bCalculateMargin) { fCurTopMargin = pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); fCurBottomMargin = pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset).ToUnit(XFA_UNIT_Pt); } 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.x = pLayoutItem->m_sSize.x; pSecondLayoutItem->m_sPos.y = 0; pSecondLayoutItem->m_sSize.y = pLayoutItem->m_sSize.y - fSplitPos; pLayoutItem->m_sSize.y -= pSecondLayoutItem->m_sSize.y; if (pLayoutItem->m_pFirstChild) { pSecondLayoutItem->m_sSize.y += fCurTopMargin; } if (pSecondParent) { pSecondParent->AddChild(pSecondLayoutItem); if (fCurTopMargin > 0 && pLayoutItem->m_pFirstChild) { pSecondParent->m_sSize.y += fCurTopMargin; CXFA_ContentLayoutItem* pParentItem = (CXFA_ContentLayoutItem*)pSecondParent->m_pParent; while (pParentItem) { pParentItem->m_sSize.y += fCurTopMargin; pParentItem = (CXFA_ContentLayoutItem*)pParentItem->m_pParent; } } } else { pSecondLayoutItem->m_pParent = pLayoutItem->m_pParent; pSecondLayoutItem->m_pNextSibling = pLayoutItem->m_pNextSibling; pLayoutItem->m_pNextSibling = pSecondLayoutItem; } CXFA_ContentLayoutItem* pChildren = (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; pLayoutItem->m_pFirstChild = nullptr; FX_FLOAT lHeightForKeep = 0; CFX_ArrayTemplate<CXFA_ContentLayoutItem*> keepLayoutItems; FX_FLOAT fAddMarginHeight = 0; 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 (!XFA_ExistContainerKeep(pChildItem->m_pFormNode, true)) { pChildItem->m_sPos.y -= fSplitPos - fCurBottomMargin; pChildItem->m_sPos.y += lHeightForKeep; pChildItem->m_sPos.y += fAddMarginHeight; pSecondLayoutItem->AddChild(pChildItem); } else { if (lHeightForKeep < XFA_LAYOUT_FLOAT_PERCISION) { for (int32_t iIndex = 0; iIndex < keepLayoutItems.GetSize(); iIndex++) { CXFA_ContentLayoutItem* pPreItem = keepLayoutItems[iIndex]; 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.y > lHeightForKeep) { pPreItem->m_sPos.y = lHeightForKeep; lHeightForKeep += pPreItem->m_sSize.y; pSecondLayoutItem->m_sSize.y += pPreItem->m_sSize.y; if (pSecondParent) { pSecondParent->m_sSize.y += pPreItem->m_sSize.y; } } pSecondLayoutItem->AddChild(pPreItem); } } pChildItem->m_sPos.y -= fSplitPos; pChildItem->m_sPos.y += lHeightForKeep; pChildItem->m_sPos.y += fAddMarginHeight; pSecondLayoutItem->AddChild(pChildItem); } } else if (fSplitPos + XFA_LAYOUT_FLOAT_PERCISION >= fCurTopMargin + fCurBottomMargin + pChildItem->m_sPos.y + pChildItem->m_sSize.y) { pLayoutItem->AddChild(pChildItem); if (XFA_ExistContainerKeep(pChildItem->m_pFormNode, false)) { keepLayoutItems.Add(pChildItem); } else { keepLayoutItems.RemoveAll(); } } else { FX_FLOAT fOldHeight = pSecondLayoutItem->m_sSize.y; SplitLayoutItem( pChildItem, pSecondLayoutItem, fSplitPos - fCurTopMargin - fCurBottomMargin - pChildItem->m_sPos.y); fAddMarginHeight = pSecondLayoutItem->m_sSize.y - fOldHeight; pLayoutItem->AddChild(pChildItem); } } } void CXFA_ItemLayoutProcessor::SplitLayoutItem(FX_FLOAT fSplitPos) { ASSERT(m_pLayoutItem); SplitLayoutItem(m_pLayoutItem, nullptr, fSplitPos); } CXFA_ContainerLayoutItem* CXFA_LayoutItem::GetPage() const { for (CXFA_LayoutItem* pCurNode = const_cast<CXFA_LayoutItem*>(this); pCurNode; pCurNode = pCurNode->m_pParent) { if (pCurNode->m_pFormNode->GetElementType() == XFA_Element::PageArea) return static_cast<CXFA_ContainerLayoutItem*>(pCurNode); } return nullptr; } CXFA_Node* CXFA_LayoutItem::GetFormNode() const { return m_pFormNode; } void CXFA_LayoutItem::GetRect(CFX_RectF& rtLayout, bool bRelative) const { ASSERT(m_bIsContentLayoutItem); const CXFA_ContentLayoutItem* pThis = static_cast<const CXFA_ContentLayoutItem*>(this); CFX_PointF sPos = pThis->m_sPos; CFX_SizeF sSize = pThis->m_sSize; if (!bRelative) { for (CXFA_LayoutItem* pLayoutItem = pThis->m_pParent; pLayoutItem; pLayoutItem = pLayoutItem->m_pParent) { if (CXFA_ContentLayoutItem* pContent = pLayoutItem->AsContentLayoutItem()) { sPos += pContent->m_sPos; if (CXFA_Node* pMarginNode = pLayoutItem->m_pFormNode->GetFirstChildByClass( XFA_Element::Margin)) { sPos += CFX_PointF(pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset) .ToUnit(XFA_UNIT_Pt), pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset) .ToUnit(XFA_UNIT_Pt)); } } else { if (pLayoutItem->m_pFormNode->GetElementType() == XFA_Element::ContentArea) { sPos += CFX_PointF(pLayoutItem->m_pFormNode->GetMeasure(XFA_ATTRIBUTE_X) .ToUnit(XFA_UNIT_Pt), pLayoutItem->m_pFormNode->GetMeasure(XFA_ATTRIBUTE_Y) .ToUnit(XFA_UNIT_Pt)); break; } else if (pLayoutItem->m_pFormNode->GetElementType() == XFA_Element::PageArea) { break; } } } } rtLayout.Set(sPos.x, sPos.y, sSize.x, sSize.y); } CXFA_LayoutItem* CXFA_LayoutItem::GetParent() const { return m_pParent; } const CXFA_LayoutItem* CXFA_LayoutItem::GetFirst() const { ASSERT(m_bIsContentLayoutItem); const CXFA_ContentLayoutItem* pCurNode = static_cast<const CXFA_ContentLayoutItem*>(this); while (pCurNode->m_pPrev) { pCurNode = pCurNode->m_pPrev; } return pCurNode; } CXFA_LayoutItem* CXFA_LayoutItem::GetFirst() { ASSERT(m_bIsContentLayoutItem); CXFA_ContentLayoutItem* pCurNode = static_cast<CXFA_ContentLayoutItem*>(this); while (pCurNode->m_pPrev) { pCurNode = pCurNode->m_pPrev; } return pCurNode; } CXFA_LayoutItem* CXFA_LayoutItem::GetLast() { ASSERT(m_bIsContentLayoutItem); CXFA_ContentLayoutItem* pCurNode = static_cast<CXFA_ContentLayoutItem*>(this); while (pCurNode->m_pNext) { pCurNode = pCurNode->m_pNext; } return pCurNode; } const CXFA_LayoutItem* CXFA_LayoutItem::GetLast() const { ASSERT(m_bIsContentLayoutItem); const CXFA_ContentLayoutItem* pCurNode = static_cast<const CXFA_ContentLayoutItem*>(this); while (pCurNode->m_pNext) { pCurNode = pCurNode->m_pNext; } return pCurNode; } CXFA_LayoutItem* CXFA_LayoutItem::GetPrev() const { ASSERT(m_bIsContentLayoutItem); return static_cast<const CXFA_ContentLayoutItem*>(this)->m_pPrev; } CXFA_LayoutItem* CXFA_LayoutItem::GetNext() const { ASSERT(m_bIsContentLayoutItem); return static_cast<const CXFA_ContentLayoutItem*>(this)->m_pNext; } int32_t CXFA_LayoutItem::GetIndex() const { ASSERT(m_bIsContentLayoutItem); int32_t iIndex = 0; const CXFA_ContentLayoutItem* pCurNode = static_cast<const CXFA_ContentLayoutItem*>(this); while (pCurNode->m_pPrev) { pCurNode = pCurNode->m_pPrev; ++iIndex; } return iIndex; } int32_t CXFA_LayoutItem::GetCount() const { ASSERT(m_bIsContentLayoutItem); int32_t iCount = GetIndex() + 1; const CXFA_ContentLayoutItem* pCurNode = static_cast<const CXFA_ContentLayoutItem*>(this); while (pCurNode->m_pNext) { pCurNode = pCurNode->m_pNext; iCount++; } return iCount; } void CXFA_LayoutItem::AddChild(CXFA_LayoutItem* pChildItem) { if (pChildItem->m_pParent) { pChildItem->m_pParent->RemoveChild(pChildItem); } pChildItem->m_pParent = this; if (!m_pFirstChild) { m_pFirstChild = pChildItem; } else { CXFA_LayoutItem* pExistingChildItem = m_pFirstChild; while (pExistingChildItem->m_pNextSibling) { pExistingChildItem = pExistingChildItem->m_pNextSibling; } pExistingChildItem->m_pNextSibling = pChildItem; } } void CXFA_LayoutItem::AddHeadChild(CXFA_LayoutItem* pChildItem) { if (pChildItem->m_pParent) { pChildItem->m_pParent->RemoveChild(pChildItem); } pChildItem->m_pParent = this; if (!m_pFirstChild) { m_pFirstChild = pChildItem; } else { CXFA_LayoutItem* pExistingChildItem = m_pFirstChild; m_pFirstChild = pChildItem; m_pFirstChild->m_pNextSibling = pExistingChildItem; } } void CXFA_LayoutItem::InsertChild(CXFA_LayoutItem* pBeforeItem, CXFA_LayoutItem* pChildItem) { if (pBeforeItem->m_pParent != this) { return; } if (pChildItem->m_pParent) { pChildItem->m_pParent = nullptr; } pChildItem->m_pParent = this; CXFA_LayoutItem* pExistingChildItem = pBeforeItem->m_pNextSibling; pBeforeItem->m_pNextSibling = pChildItem; pChildItem->m_pNextSibling = pExistingChildItem; } void CXFA_LayoutItem::RemoveChild(CXFA_LayoutItem* pChildItem) { if (pChildItem->m_pParent != this) { return; } if (m_pFirstChild == pChildItem) { m_pFirstChild = pChildItem->m_pNextSibling; } else { CXFA_LayoutItem* pExistingChildItem = m_pFirstChild; while (pExistingChildItem && pExistingChildItem->m_pNextSibling != pChildItem) { pExistingChildItem = pExistingChildItem->m_pNextSibling; } if (pExistingChildItem) { pExistingChildItem->m_pNextSibling = pChildItem->m_pNextSibling; } } pChildItem->m_pNextSibling = nullptr; pChildItem->m_pParent = nullptr; } CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::ExtractLayoutItem() { CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem; if (pLayoutItem) { m_pLayoutItem = static_cast<CXFA_ContentLayoutItem*>(pLayoutItem->m_pNextSibling); pLayoutItem->m_pNextSibling = nullptr; } if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages_Done || !ToContentLayoutItem(m_pOldLayoutItem)) return pLayoutItem; 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; } m_pOldLayoutItem = nullptr; return pLayoutItem; } static bool XFA_ItemLayoutProcessor_FindBreakNode( CXFA_Node* pContainerNode, CXFA_Node*& pCurActionNode, XFA_ItemLayoutProcessorStages& nCurStage, bool bBreakBefore) { bool bFindRs = false; for (CXFA_Node* pBreakNode = pContainerNode; pBreakNode; pBreakNode = pBreakNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { XFA_ATTRIBUTE eAttributeType = XFA_ATTRIBUTE_Before; if (!bBreakBefore) { eAttributeType = XFA_ATTRIBUTE_After; } switch (pBreakNode->GetElementType()) { case XFA_Element::BreakBefore: { if (bBreakBefore) { pCurActionNode = pBreakNode; nCurStage = XFA_ItemLayoutProcessorStages_BreakBefore; bFindRs = true; } } break; case XFA_Element::BreakAfter: { if (!bBreakBefore) { pCurActionNode = pBreakNode; nCurStage = XFA_ItemLayoutProcessorStages_BreakAfter; bFindRs = true; } } break; case XFA_Element::Break: if (pBreakNode->GetEnum(eAttributeType) != XFA_ATTRIBUTEENUM_Auto) { pCurActionNode = pBreakNode; nCurStage = XFA_ItemLayoutProcessorStages_BreakBefore; if (!bBreakBefore) { nCurStage = XFA_ItemLayoutProcessorStages_BreakAfter; } bFindRs = true; break; } default: break; } if (bFindRs) { break; } } return bFindRs; } static void XFA_DeleteLayoutGeneratedNode(CXFA_Node* pGenerateNode) { CXFA_FFNotify* pNotify = pGenerateNode->GetDocument()->GetNotify(); CXFA_LayoutProcessor* pDocLayout = pGenerateNode->GetDocument()->GetDocLayout(); CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator( pGenerateNode); for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) { CXFA_ContentLayoutItem* pCurLayoutItem = (CXFA_ContentLayoutItem*)pNode->GetUserData(XFA_LAYOUTITEMKEY); CXFA_ContentLayoutItem* pNextLayoutItem = nullptr; while (pCurLayoutItem) { pNextLayoutItem = pCurLayoutItem->m_pNext; pNotify->OnLayoutItemRemoving(pDocLayout, pCurLayoutItem); delete pCurLayoutItem; pCurLayoutItem = pNextLayoutItem; } } pGenerateNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pGenerateNode); } void CXFA_ItemLayoutProcessor::XFA_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->GetNodeItem(XFA_NODEITEM_Parent); } break; case XFA_ItemLayoutProcessorStages_Keep: case XFA_ItemLayoutProcessorStages_Container: pChildContainer = pCurActionNode; break; default: pChildContainer = XFA_LAYOUT_INVALIDNODE; break; } switch (nCurStage) { case XFA_ItemLayoutProcessorStages_Keep: { CXFA_Node* pBreakAfterNode = pChildContainer->GetNodeItem(XFA_NODEITEM_FirstChild); if (!m_bKeepBreakFinish && XFA_ItemLayoutProcessor_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->GetNodeItem(XFA_NODEITEM_FirstChild) : pCurActionNode->GetNodeItem(XFA_NODEITEM_NextSibling); pBookendNode; pBookendNode = pBookendNode->GetNodeItem( XFA_NODEITEM_NextSibling)) { 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->GetNodeItem(XFA_NODEITEM_NextSibling); if (!m_bKeepBreakFinish && XFA_ItemLayoutProcessor_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; } case XFA_ItemLayoutProcessorStages_Container: { pCurActionNode = XFA_LAYOUT_INVALIDNODE; case XFA_ItemLayoutProcessorStages_BreakAfter: { if (pCurActionNode == XFA_LAYOUT_INVALIDNODE) { CXFA_Node* pBreakAfterNode = pChildContainer->GetNodeItem(XFA_NODEITEM_FirstChild); if (!m_bKeepBreakFinish && XFA_ItemLayoutProcessor_FindBreakNode( pBreakAfterNode, pCurActionNode, nCurStage, false)) { return; } } else { CXFA_Node* pBreakAfterNode = pCurActionNode->GetNodeItem(XFA_NODEITEM_NextSibling); if (XFA_ItemLayoutProcessor_FindBreakNode( pBreakAfterNode, pCurActionNode, nCurStage, false)) { return; } } goto CheckNextChildContainer; } } CheckNextChildContainer : { CXFA_Node* pNextChildContainer = pChildContainer == XFA_LAYOUT_INVALIDNODE ? pEntireContainer->GetNodeItem(XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode) : pChildContainer->GetNodeItem(XFA_NODEITEM_NextSibling, XFA_ObjectType::ContainerNode); while (pNextChildContainer && pNextChildContainer->IsLayoutGeneratedNode()) { CXFA_Node* pSaveNode = pNextChildContainer; pNextChildContainer = pNextChildContainer->GetNodeItem( XFA_NODEITEM_NextSibling, XFA_ObjectType::ContainerNode); if (pSaveNode->IsUnusedNode()) XFA_DeleteLayoutGeneratedNode(pSaveNode); } if (!pNextChildContainer) { goto NoMoreChildContainer; } bool bLastKeep = false; if (ProcessKeepNodesForCheckNext(pCurActionNode, nCurStage, pNextChildContainer, bLastKeep)) { return; } if (!m_bKeepBreakFinish && !bLastKeep && XFA_ItemLayoutProcessor_FindBreakNode( pNextChildContainer->GetNodeItem(XFA_NODEITEM_FirstChild), 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->GetNodeItem(XFA_NODEITEM_FirstChild) : pCurActionNode->GetNodeItem(XFA_NODEITEM_NextSibling); pBookendNode; pBookendNode = pBookendNode->GetNodeItem( XFA_NODEITEM_NextSibling)) { switch (pBookendNode->GetElementType()) { case XFA_Element::Bookend: case XFA_Element::Break: pCurActionNode = pBookendNode; nCurStage = XFA_ItemLayoutProcessorStages_BookendTrailer; return; default: break; } } } 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 (XFA_ExistContainerKeep(pNextContainer, false)) { bNextKeep = true; } if (bNextKeep && !bCanSplit) { if (!m_bIsProcessKeep && !m_bKeepBreakFinish) { m_pKeepHeadNode = pNextContainer; m_bIsProcessKeep = true; } } else { if (m_bIsProcessKeep && m_pKeepHeadNode) { m_pKeepTailNode = pNextContainer; if (!m_bKeepBreakFinish && XFA_ItemLayoutProcessor_FindBreakNode( pNextContainer->GetNodeItem(XFA_NODEITEM_FirstChild), pCurActionNode, nCurStage, true)) { return true; } else { 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 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; } CXFA_Node* pBreakAfterNode = pContainerNode->GetNodeItem(XFA_NODEITEM_FirstChild); if (XFA_ItemLayoutProcessor_FindBreakNode(pBreakAfterNode, pCurActionNode, nCurStage, false)) { return true; } return false; } bool XFA_ItemLayoutProcessor_IsTakingSpace(CXFA_Node* pNode) { XFA_ATTRIBUTEENUM ePresence = pNode->GetEnum(XFA_ATTRIBUTE_Presence); return ePresence == XFA_ATTRIBUTEENUM_Visible || ePresence == XFA_ATTRIBUTEENUM_Invisible; } static inline void XFA_ItemLayoutProcessor_CalculateContainerSpecfiedSize( CXFA_Node* pFormNode, FX_FLOAT& fContainerWidth, FX_FLOAT& fContainerHeight, bool& bContainerWidthAutoSize, bool& bContainerHeightAutoSize) { fContainerWidth = 0; fContainerHeight = 0; bContainerWidthAutoSize = true; bContainerHeightAutoSize = true; XFA_Element eType = pFormNode->GetElementType(); CXFA_Measurement mTmpValue; if (bContainerWidthAutoSize && (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup) && pFormNode->TryMeasure(XFA_ATTRIBUTE_W, mTmpValue, false) && mTmpValue.GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { fContainerWidth = mTmpValue.ToUnit(XFA_UNIT_Pt); bContainerWidthAutoSize = false; } if (bContainerHeightAutoSize && (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup) && pFormNode->TryMeasure(XFA_ATTRIBUTE_H, mTmpValue, false) && mTmpValue.GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { fContainerHeight = mTmpValue.ToUnit(XFA_UNIT_Pt); bContainerHeightAutoSize = false; } if (bContainerWidthAutoSize && eType == XFA_Element::Subform && pFormNode->TryMeasure(XFA_ATTRIBUTE_MaxW, mTmpValue, false) && mTmpValue.GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { fContainerWidth = mTmpValue.ToUnit(XFA_UNIT_Pt); bContainerWidthAutoSize = false; } if (bContainerHeightAutoSize && eType == XFA_Element::Subform && pFormNode->TryMeasure(XFA_ATTRIBUTE_MaxH, mTmpValue, false) && mTmpValue.GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { fContainerHeight = mTmpValue.ToUnit(XFA_UNIT_Pt); bContainerHeightAutoSize = false; } } static inline void XFA_ItemLayoutProcessor_CalculateContainerComponentSizeFromContentSize( CXFA_Node* pFormNode, bool bContainerWidthAutoSize, FX_FLOAT fContentCalculatedWidth, FX_FLOAT& fContainerWidth, bool bContainerHeightAutoSize, FX_FLOAT fContentCalculatedHeight, FX_FLOAT& fContainerHeight) { CXFA_Node* pMarginNode = pFormNode->GetFirstChildByClass(XFA_Element::Margin); CXFA_Measurement mTmpValue; if (bContainerWidthAutoSize) { fContainerWidth = fContentCalculatedWidth; if (pMarginNode) { if (pMarginNode->TryMeasure(XFA_ATTRIBUTE_LeftInset, mTmpValue, false)) { fContainerWidth += mTmpValue.ToUnit(XFA_UNIT_Pt); } if (pMarginNode->TryMeasure(XFA_ATTRIBUTE_RightInset, mTmpValue, false)) { fContainerWidth += mTmpValue.ToUnit(XFA_UNIT_Pt); } } } if (bContainerHeightAutoSize) { fContainerHeight = fContentCalculatedHeight; if (pMarginNode) { if (pMarginNode->TryMeasure(XFA_ATTRIBUTE_TopInset, mTmpValue, false)) { fContainerHeight += mTmpValue.ToUnit(XFA_UNIT_Pt); } if (pMarginNode->TryMeasure(XFA_ATTRIBUTE_BottomInset, mTmpValue, false)) { fContainerHeight += mTmpValue.ToUnit(XFA_UNIT_Pt); } } } } void CXFA_ItemLayoutProcessor::CalculatePositionedContainerPos( CXFA_Node* pNode, FX_FLOAT fWidth, FX_FLOAT fHeight, FX_FLOAT& fAbsoluteX, FX_FLOAT& fAbsoluteY) { XFA_ATTRIBUTEENUM eAnchorType = pNode->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}}; FX_FLOAT fAnchorX = pNode->GetMeasure(XFA_ATTRIBUTE_X).ToUnit(XFA_UNIT_Pt); FX_FLOAT fAnchorY = pNode->GetMeasure(XFA_ATTRIBUTE_Y).ToUnit(XFA_UNIT_Pt); int32_t nRotate = FXSYS_round(pNode->GetMeasure(XFA_ATTRIBUTE_Rotate).GetValue()); nRotate = XFA_MapRotation(nRotate) / 90; int32_t nAbsoluteAnchorType = nNextPos[nRotate][nAnchorType]; fAbsoluteX = fAnchorX; fAbsoluteY = fAnchorY; switch (nAbsoluteAnchorType / 3) { case 1: fAbsoluteY -= fHeight / 2; break; case 2: fAbsoluteY -= fHeight; break; default: break; } switch (nAbsoluteAnchorType % 3) { case 1: fAbsoluteX -= fWidth / 2; break; case 2: fAbsoluteX -= fWidth; break; default: break; } } bool CXFA_ItemLayoutProcessor::IncrementRelayoutNode( CXFA_LayoutProcessor* pLayoutProcessor, CXFA_Node* pNode, CXFA_Node* pParentNode) { 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 (XFA_ItemLayoutProcessor_GotoNextContainerNode( pCurChildNode, nCurChildNodeStage, pFormNode, false); pCurChildNode; XFA_ItemLayoutProcessor_GotoNextContainerNode( pCurChildNode, nCurChildNodeStage, pFormNode, false)) { if (nCurChildNodeStage != XFA_ItemLayoutProcessorStages_Container) { continue; } if (pCurChildNode->GetElementType() == XFA_Element::Variables) { continue; } CXFA_ItemLayoutProcessor* pProcessor = new CXFA_ItemLayoutProcessor(pCurChildNode, nullptr); pProcessor->DoLayout(false, XFA_LAYOUT_FLOAT_MAX); if (!pProcessor->HasLayoutItem()) { delete pProcessor; continue; } FX_FLOAT fWidth, fHeight; pProcessor->GetCurrentComponentSize(fWidth, fHeight); FX_FLOAT fAbsoluteX = 0, fAbsoluteY = 0; CalculatePositionedContainerPos(pCurChildNode, fWidth, fHeight, fAbsoluteX, fAbsoluteY); pProcessor->SetCurrentComponentPos(fAbsoluteX, fAbsoluteY); CXFA_LayoutItem* pProcessItem = pProcessor->ExtractLayoutItem(); if (!pBeforeItem) { pPageAreaLayoutItem->AddHeadChild(pProcessItem); } else { pPageAreaLayoutItem->InsertChild(pBeforeItem, pProcessItem); } pBeforeItem = pProcessItem; delete pProcessor; } 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) { 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->GetEnum(XFA_ATTRIBUTE_Layout) != XFA_ATTRIBUTEENUM_Position); FX_FLOAT fContainerWidth = 0, fContainerHeight = 0; bool bContainerWidthAutoSize = true, bContainerHeightAutoSize = true; XFA_ItemLayoutProcessor_CalculateContainerSpecfiedSize( m_pFormNode, fContainerWidth, fContainerHeight, bContainerWidthAutoSize, bContainerHeightAutoSize); FX_FLOAT fContentCalculatedWidth = 0, fContentCalculatedHeight = 0; FX_FLOAT fHiddenContentCalculatedWidth = 0, fHiddenContentCalculatedHeight = 0; if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { XFA_ItemLayoutProcessor_GotoNextContainerNode( m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false); } int32_t iColIndex = 0; for (; m_pCurChildNode; XFA_ItemLayoutProcessor_GotoNextContainerNode( m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages_Container) { continue; } if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) { continue; } CXFA_ItemLayoutProcessor* pProcessor = new CXFA_ItemLayoutProcessor(m_pCurChildNode, m_pPageMgr); if (pContext && pContext->m_prgSpecifiedColumnWidths) { int32_t iColSpan = m_pCurChildNode->GetInteger(XFA_ATTRIBUTE_ColSpan); if (iColSpan <= pContext->m_prgSpecifiedColumnWidths->GetSize() - iColIndex) { pContext->m_fCurColumnWidth = 0; pContext->m_bCurColumnWidthAvaiable = true; if (iColSpan == -1) iColSpan = pContext->m_prgSpecifiedColumnWidths->GetSize(); for (int32_t i = 0; iColIndex + i < iColSpan; ++i) { pContext->m_fCurColumnWidth += pContext->m_prgSpecifiedColumnWidths->GetAt(iColIndex + i); } if (pContext->m_fCurColumnWidth == 0) pContext->m_bCurColumnWidthAvaiable = false; iColIndex += iColSpan >= 0 ? iColSpan : 0; } } pProcessor->DoLayout(false, XFA_LAYOUT_FLOAT_MAX, XFA_LAYOUT_FLOAT_MAX, pContext); if (!pProcessor->HasLayoutItem()) { delete pProcessor; continue; } FX_FLOAT fWidth, fHeight; pProcessor->GetCurrentComponentSize(fWidth, fHeight); bool bChangeParentSize = false; if (XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) { bChangeParentSize = true; } FX_FLOAT fAbsoluteX = 0, fAbsoluteY = 0; if (!bIgnoreXY) { CalculatePositionedContainerPos(m_pCurChildNode, fWidth, fHeight, fAbsoluteX, fAbsoluteY); } pProcessor->SetCurrentComponentPos(fAbsoluteX, fAbsoluteY); if (bContainerWidthAutoSize) { FX_FLOAT fChildSuppliedWidth = fAbsoluteX + fWidth; if (bChangeParentSize) { if (fContentCalculatedWidth < fChildSuppliedWidth) { fContentCalculatedWidth = fChildSuppliedWidth; } } else { if (fHiddenContentCalculatedWidth < fChildSuppliedWidth && m_pCurChildNode->GetElementType() != XFA_Element::Subform) { fHiddenContentCalculatedWidth = fChildSuppliedWidth; } } } if (bContainerHeightAutoSize) { FX_FLOAT fChildSuppliedHeight = fAbsoluteY + fHeight; if (bChangeParentSize) { if (fContentCalculatedHeight < fChildSuppliedHeight) { fContentCalculatedHeight = fChildSuppliedHeight; } } else { if (fHiddenContentCalculatedHeight < fChildSuppliedHeight && m_pCurChildNode->GetElementType() != XFA_Element::Subform) { fHiddenContentCalculatedHeight = fChildSuppliedHeight; } } } m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); delete pProcessor; } 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; } XFA_ItemLayoutProcessor_CalculateContainerComponentSizeFromContentSize( m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, fContainerWidth, bContainerHeightAutoSize, fContentCalculatedHeight, fContainerHeight); SetCurrentComponentSize(fContainerWidth, fContainerHeight); } static inline void XFA_ItemLayoutProcessor_UpdateWidgetSize( CXFA_ContentLayoutItem* pLayoutItem, FX_FLOAT& fWidth, FX_FLOAT& fHeight) { CXFA_Node* pNode = pLayoutItem->m_pFormNode; ASSERT(pNode); switch (pNode->GetElementType()) { case XFA_Element::Subform: case XFA_Element::Area: case XFA_Element::ExclGroup: case XFA_Element::SubformSet: { if (fWidth < -XFA_LAYOUT_FLOAT_PERCISION) { fWidth = pLayoutItem->m_sSize.x; } if (fHeight < -XFA_LAYOUT_FLOAT_PERCISION) { fHeight = pLayoutItem->m_sSize.y; } break; } case XFA_Element::Draw: case XFA_Element::Field: { pNode->GetDocument()->GetNotify()->StartFieldDrawLayout(pNode, fWidth, fHeight); break; } default: ASSERT(false); } } static inline void XFA_ItemLayoutProcessor_RelocateTableRowCells( CXFA_ContentLayoutItem* pLayoutRow, const CFX_ArrayTemplate<FX_FLOAT>& rgSpecifiedColumnWidths, XFA_ATTRIBUTEENUM eLayout) { FX_FLOAT fContainerWidth = 0, fContainerHeight = 0; bool bContainerWidthAutoSize = true, bContainerHeightAutoSize = true; XFA_ItemLayoutProcessor_CalculateContainerSpecfiedSize( pLayoutRow->m_pFormNode, fContainerWidth, fContainerHeight, bContainerWidthAutoSize, bContainerHeightAutoSize); CXFA_Node* pMarginNode = pLayoutRow->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); FX_FLOAT fLeftInset = 0, fTopInset = 0, fRightInset = 0, fBottomInset = 0; if (pMarginNode) { fLeftInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); fTopInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); fRightInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); fBottomInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset).ToUnit(XFA_UNIT_Pt); } FX_FLOAT fContentWidthLimit = bContainerWidthAutoSize ? XFA_LAYOUT_FLOAT_MAX : fContainerWidth - fLeftInset - fRightInset; FX_FLOAT fContentCurrentHeight = pLayoutRow->m_sSize.y - fTopInset - fBottomInset; FX_FLOAT fContentCalculatedWidth = 0, fContentCalculatedHeight = 0; FX_FLOAT fCurrentColX = 0; int32_t nCurrentColIdx = 0; bool bMetWholeRowCell = false; for (CXFA_ContentLayoutItem* pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; pLayoutChild; pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { int32_t nOriginalColSpan = pLayoutChild->m_pFormNode->GetInteger(XFA_ATTRIBUTE_ColSpan); int32_t nColSpan = nOriginalColSpan; FX_FLOAT fColSpanWidth = 0; if (nColSpan == -1 || nCurrentColIdx + nColSpan > rgSpecifiedColumnWidths.GetSize()) { nColSpan = rgSpecifiedColumnWidths.GetSize() - nCurrentColIdx; } for (int32_t i = 0; i < nColSpan; i++) { fColSpanWidth += rgSpecifiedColumnWidths[nCurrentColIdx + i]; } if (nColSpan != nOriginalColSpan) { fColSpanWidth = bMetWholeRowCell ? 0 : std::max(fColSpanWidth, pLayoutChild->m_sSize.y); } if (nOriginalColSpan == -1) { bMetWholeRowCell = true; } pLayoutChild->m_sPos = CFX_PointF(fCurrentColX, 0); pLayoutChild->m_sSize.x = fColSpanWidth; if (XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) { fCurrentColX += fColSpanWidth; nCurrentColIdx += nColSpan; FX_FLOAT fNewHeight = bContainerHeightAutoSize ? -1 : fContentCurrentHeight; XFA_ItemLayoutProcessor_UpdateWidgetSize(pLayoutChild, fColSpanWidth, fNewHeight); pLayoutChild->m_sSize.y = fNewHeight; if (bContainerHeightAutoSize) { FX_FLOAT fChildSuppliedHeight = pLayoutChild->m_sSize.y; if (fContentCalculatedHeight < fChildSuppliedHeight) { fContentCalculatedHeight = fChildSuppliedHeight; } } } } if (bContainerHeightAutoSize) { for (CXFA_ContentLayoutItem* pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; pLayoutChild; pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { XFA_ItemLayoutProcessor_UpdateWidgetSize( pLayoutChild, pLayoutChild->m_sSize.x, fContentCalculatedHeight); FX_FLOAT fOldChildHeight = pLayoutChild->m_sSize.y; pLayoutChild->m_sSize.y = fContentCalculatedHeight; CXFA_Node* pParaNode = pLayoutChild->m_pFormNode->GetFirstChildByClass(XFA_Element::Para); if (pParaNode && pLayoutChild->m_pFirstChild) { FX_FLOAT fOffHeight = fContentCalculatedHeight - fOldChildHeight; XFA_ATTRIBUTEENUM eVType = pParaNode->GetEnum(XFA_ATTRIBUTE_VAlign); switch (eVType) { case XFA_ATTRIBUTEENUM_Middle: fOffHeight = fOffHeight / 2; break; case XFA_ATTRIBUTEENUM_Bottom: break; case XFA_ATTRIBUTEENUM_Top: default: fOffHeight = 0; break; } if (fOffHeight > 0) { for (CXFA_ContentLayoutItem* pInnerLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild; pInnerLayoutChild; pInnerLayoutChild = (CXFA_ContentLayoutItem*)pInnerLayoutChild->m_pNextSibling) { pInnerLayoutChild->m_sPos.y += fOffHeight; } } } } } if (bContainerWidthAutoSize) { FX_FLOAT fChildSuppliedWidth = fCurrentColX; if (fContentWidthLimit < XFA_LAYOUT_FLOAT_MAX && fContentWidthLimit > fChildSuppliedWidth) { fChildSuppliedWidth = fContentWidthLimit; } if (fContentCalculatedWidth < fChildSuppliedWidth) { fContentCalculatedWidth = fChildSuppliedWidth; } } else { fContentCalculatedWidth = fContainerWidth - fLeftInset - fRightInset; } if (pLayoutRow->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout) == XFA_ATTRIBUTEENUM_Rl_row) { for (CXFA_ContentLayoutItem* pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; pLayoutChild; pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { pLayoutChild->m_sPos.x = fContentCalculatedWidth - pLayoutChild->m_sPos.x - pLayoutChild->m_sSize.x; } } XFA_ItemLayoutProcessor_CalculateContainerComponentSizeFromContentSize( pLayoutRow->m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, fContainerWidth, bContainerHeightAutoSize, fContentCalculatedHeight, fContainerHeight); pLayoutRow->m_sSize = CFX_SizeF(fContainerWidth, fContainerHeight); } void CXFA_ItemLayoutProcessor::DoLayoutTableContainer(CXFA_Node* pLayoutNode) { if (m_pLayoutItem) return; if (!pLayoutNode) { pLayoutNode = m_pFormNode; } ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); FX_FLOAT fContainerWidth = 0, fContainerHeight = 0; bool bContainerWidthAutoSize = true, bContainerHeightAutoSize = true; XFA_ItemLayoutProcessor_CalculateContainerSpecfiedSize( m_pFormNode, fContainerWidth, fContainerHeight, bContainerWidthAutoSize, bContainerHeightAutoSize); FX_FLOAT fContentCalculatedWidth = 0, fContentCalculatedHeight = 0; CXFA_Node* pMarginNode = m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); FX_FLOAT fLeftInset = 0; FX_FLOAT fRightInset = 0; if (pMarginNode) { fLeftInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); fRightInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); } FX_FLOAT fContentWidthLimit = bContainerWidthAutoSize ? XFA_LAYOUT_FLOAT_MAX : fContainerWidth - fLeftInset - fRightInset; CFX_WideStringC wsColumnWidths; if (pLayoutNode->TryCData(XFA_ATTRIBUTE_ColumnWidths, wsColumnWidths)) { std::vector<CFX_WideString> widths; if (SeparateStringW(wsColumnWidths.c_str(), wsColumnWidths.GetLength(), L' ', widths) > 0) { int32_t iCols = pdfium::CollectionSize<int32_t>(widths); CFX_WideString wsWidth; for (int32_t i = 0; i < iCols; i++) { wsWidth = widths[i]; wsWidth.TrimLeft(L' '); if (!wsWidth.IsEmpty()) { CXFA_Measurement measure(wsWidth.AsStringC()); m_rgSpecifiedColumnWidths.Add(measure.ToUnit(XFA_UNIT_Pt)); } } } } int32_t iSpecifiedColumnCount = m_rgSpecifiedColumnWidths.GetSize(); CXFA_LayoutContext layoutContext; layoutContext.m_prgSpecifiedColumnWidths = &m_rgSpecifiedColumnWidths; CXFA_LayoutContext* pLayoutContext = iSpecifiedColumnCount > 0 ? &layoutContext : nullptr; if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { XFA_ItemLayoutProcessor_GotoNextContainerNode( m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false); } for (; m_pCurChildNode; XFA_ItemLayoutProcessor_GotoNextContainerNode( m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { layoutContext.m_bCurColumnWidthAvaiable = false; layoutContext.m_fCurColumnWidth = 0; if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages_Container) { continue; } CXFA_ItemLayoutProcessor* pProcessor = new CXFA_ItemLayoutProcessor(m_pCurChildNode, m_pPageMgr); pProcessor->DoLayout(false, XFA_LAYOUT_FLOAT_MAX, XFA_LAYOUT_FLOAT_MAX, pLayoutContext); if (!pProcessor->HasLayoutItem()) { delete pProcessor; continue; } m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); delete pProcessor; } int32_t iRowCount = 0, iColCount = 0; { CFX_ArrayTemplate<CXFA_ContentLayoutItem*> rgRowItems; CFX_ArrayTemplate<int32_t> rgRowItemsSpan; CFX_ArrayTemplate<FX_FLOAT> rgRowItemsWidth; for (CXFA_ContentLayoutItem* pLayoutChild = (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; pLayoutChild; pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { if (pLayoutChild->m_pFormNode->GetElementType() != XFA_Element::Subform) { continue; } if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) { continue; } XFA_ATTRIBUTEENUM eLayout = pLayoutChild->m_pFormNode->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.Add(pRowLayoutCell); int32_t iColSpan = pRowLayoutCell->m_pFormNode->GetInteger(XFA_ATTRIBUTE_ColSpan); rgRowItemsSpan.Add(iColSpan); rgRowItemsWidth.Add(pRowLayoutCell->m_sSize.x); } } iRowCount = rgRowItems.GetSize(); 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 || !XFA_ItemLayoutProcessor_IsTakingSpace( rgRowItems[i]->m_pFormNode))) { CXFA_ContentLayoutItem* pNewCell = (CXFA_ContentLayoutItem*)rgRowItems[i]->m_pNextSibling; if (rgRowItemsSpan[i] < 0 && XFA_ItemLayoutProcessor_IsTakingSpace( rgRowItems[i]->m_pFormNode)) { pNewCell = nullptr; } rgRowItems[i] = pNewCell; rgRowItemsSpan[i] = pNewCell ? pNewCell->m_pFormNode->GetInteger(XFA_ATTRIBUTE_ColSpan) : 0; rgRowItemsWidth[i] = pNewCell ? pNewCell->m_sSize.x : 0; } CXFA_ContentLayoutItem* pCell = rgRowItems[i]; if (!pCell) { continue; } bMoreColumns = true; if (rgRowItemsSpan[i] == 1) { if (iColCount >= iSpecifiedColumnCount) { for (int32_t j = 0, c = iColCount + 1 - m_rgSpecifiedColumnWidths.GetSize(); j < c; j++) { m_rgSpecifiedColumnWidths.Add(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) { FX_FLOAT fFinalColumnWidth = 0.0f; if (iColCount < m_rgSpecifiedColumnWidths.GetSize()) fFinalColumnWidth = m_rgSpecifiedColumnWidths[iColCount]; for (int32_t i = 0; i < iRowCount; ++i) { if (!rgRowItems[i]) continue; --rgRowItemsSpan[i]; rgRowItemsWidth[i] -= fFinalColumnWidth; } ++iColCount; } } } FX_FLOAT fCurrentRowY = 0; for (CXFA_ContentLayoutItem* pLayoutChild = (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; pLayoutChild; pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) { continue; } if (pLayoutChild->m_pFormNode->GetElementType() == XFA_Element::Subform) { XFA_ATTRIBUTEENUM eSubformLayout = pLayoutChild->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); if (eSubformLayout == XFA_ATTRIBUTEENUM_Row || eSubformLayout == XFA_ATTRIBUTEENUM_Rl_row) { XFA_ItemLayoutProcessor_RelocateTableRowCells( pLayoutChild, m_rgSpecifiedColumnWidths, eSubformLayout); } } pLayoutChild->m_sPos.y = fCurrentRowY; if (bContainerWidthAutoSize) { pLayoutChild->m_sPos.x = 0; } else { switch (pLayoutChild->m_pFormNode->GetEnum(XFA_ATTRIBUTE_HAlign)) { case XFA_ATTRIBUTEENUM_Left: default: pLayoutChild->m_sPos.x = 0; break; case XFA_ATTRIBUTEENUM_Center: pLayoutChild->m_sPos.x = (fContentWidthLimit - pLayoutChild->m_sSize.x) / 2; break; case XFA_ATTRIBUTEENUM_Right: pLayoutChild->m_sPos.x = fContentWidthLimit - pLayoutChild->m_sSize.x; break; } } if (bContainerWidthAutoSize) { FX_FLOAT fChildSuppliedWidth = pLayoutChild->m_sPos.x + pLayoutChild->m_sSize.x; if (fContentWidthLimit < XFA_LAYOUT_FLOAT_MAX && fContentWidthLimit > fChildSuppliedWidth) { fChildSuppliedWidth = fContentWidthLimit; } if (fContentCalculatedWidth < fChildSuppliedWidth) { fContentCalculatedWidth = fChildSuppliedWidth; } } fCurrentRowY += pLayoutChild->m_sSize.y; } if (bContainerHeightAutoSize) { FX_FLOAT fChildSuppliedHeight = fCurrentRowY; if (fContentCalculatedHeight < fChildSuppliedHeight) { fContentCalculatedHeight = fChildSuppliedHeight; } } XFA_ItemLayoutProcessor_CalculateContainerComponentSizeFromContentSize( m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, fContainerWidth, bContainerHeightAutoSize, fContentCalculatedHeight, fContainerHeight); SetCurrentComponentSize(fContainerWidth, fContainerHeight); } static uint8_t XFA_ItemLayoutProcessor_HAlignEnumToInt( XFA_ATTRIBUTEENUM eHAlign) { switch (eHAlign) { case XFA_ATTRIBUTEENUM_Center: return 1; case XFA_ATTRIBUTEENUM_Right: return 2; case XFA_ATTRIBUTEENUM_Left: default: return 0; } } static void XFA_ItemLayoutProcessor_UpdatePendedItemLayout( CXFA_ItemLayoutProcessor* pProcessor, CXFA_ContentLayoutItem* pLayoutItem) { XFA_ATTRIBUTEENUM eLayout = pLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); switch (eLayout) { case XFA_ATTRIBUTEENUM_Row: case XFA_ATTRIBUTEENUM_Rl_row: XFA_ItemLayoutProcessor_RelocateTableRowCells( pLayoutItem, pProcessor->m_rgSpecifiedColumnWidths, eLayout); break; default: break; } } bool CXFA_ItemLayoutProcessor::IsAddNewRowForTrailer( CXFA_ContentLayoutItem* pTrailerItem) { if (!pTrailerItem) { return false; } FX_FLOAT fWidth = pTrailerItem->m_sSize.x; XFA_ATTRIBUTEENUM eLayout = m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); if (eLayout != XFA_ATTRIBUTEENUM_Tb && m_fWidthLimite > fWidth) { return false; } return true; } static void XFA_ItemLayoutProcessor_AddTrailerBeforeSplit( CXFA_ItemLayoutProcessor* pProcessor, FX_FLOAT fSplitPos, CXFA_ContentLayoutItem* pTrailerLayoutItem, bool bUseInherited = false) { if (!pTrailerLayoutItem) { return; } FX_FLOAT fHeight = pTrailerLayoutItem->m_sSize.y; if (bUseInherited) { FX_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; } XFA_ItemLayoutProcessor_UpdatePendedItemLayout(pProcessor, pTrailerLayoutItem); CXFA_Node* pMarginNode = pProcessor->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); FX_FLOAT fLeftInset = 0, fTopInset = 0, fRightInset = 0, fBottomInset = 0; if (pMarginNode) { fLeftInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); fTopInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); fRightInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); fBottomInset = pMarginNode->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.x += pTrailerLayoutItem->m_sSize.x; pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); return; } FX_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->GetEnum(XFA_ATTRIBUTE_HAlign)) { case XFA_ATTRIBUTEENUM_Left: default: pTrailerLayoutItem->m_sPos.x = fLeftInset; break; case XFA_ATTRIBUTEENUM_Right: pTrailerLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.x - fRightInset - pTrailerLayoutItem->m_sSize.x; break; case XFA_ATTRIBUTEENUM_Center: pTrailerLayoutItem->m_sPos.x = (pProcessor->m_pLayoutItem->m_sSize.x - fLeftInset - fRightInset - pTrailerLayoutItem->m_sSize.x) / 2; break; } pProcessor->m_pLayoutItem->m_sSize.y += fHeight; pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); } static void XFA_ItemLayoutProcessor_AddLeaderAfterSplit( CXFA_ItemLayoutProcessor* pProcessor, CXFA_ContentLayoutItem* pLeaderLayoutItem) { XFA_ItemLayoutProcessor_UpdatePendedItemLayout(pProcessor, pLeaderLayoutItem); CXFA_Node* pMarginNode = pProcessor->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); FX_FLOAT fLeftInset = 0; FX_FLOAT fRightInset = 0; if (pMarginNode) { fLeftInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); fRightInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); } FX_FLOAT fHeight = pLeaderLayoutItem->m_sSize.y; 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->GetEnum(XFA_ATTRIBUTE_HAlign)) { case XFA_ATTRIBUTEENUM_Left: default: pLeaderLayoutItem->m_sPos.x = fLeftInset; break; case XFA_ATTRIBUTEENUM_Right: pLeaderLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.x - fRightInset - pLeaderLayoutItem->m_sSize.x; break; case XFA_ATTRIBUTEENUM_Center: pLeaderLayoutItem->m_sPos.x = (pProcessor->m_pLayoutItem->m_sSize.x - fLeftInset - fRightInset - pLeaderLayoutItem->m_sSize.x) / 2; break; } pProcessor->m_pLayoutItem->m_sSize.y += fHeight; pProcessor->m_pLayoutItem->AddChild(pLeaderLayoutItem); } static void XFA_ItemLayoutProcessor_AddPendingNode( CXFA_ItemLayoutProcessor* pProcessor, CXFA_Node* pPendingNode, bool bBreakPending) { pProcessor->m_PendingNodes.push_back(pPendingNode); pProcessor->m_bBreakPending = bBreakPending; } static FX_FLOAT XFA_ItemLayoutProcessor_InsertPendingItems( CXFA_ItemLayoutProcessor* pProcessor, CXFA_Node* pCurChildNode) { FX_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()) { std::unique_ptr<CXFA_ItemLayoutProcessor> pPendingProcessor( new CXFA_ItemLayoutProcessor(pProcessor->m_PendingNodes.front(), nullptr)); pProcessor->m_PendingNodes.pop_front(); pPendingProcessor->DoLayout(false, XFA_LAYOUT_FLOAT_MAX); CXFA_ContentLayoutItem* pPendingLayoutItem = pPendingProcessor->HasLayoutItem() ? pPendingProcessor->ExtractLayoutItem() : nullptr; if (pPendingLayoutItem) { XFA_ItemLayoutProcessor_AddLeaderAfterSplit(pProcessor, pPendingLayoutItem); if (pProcessor->m_bBreakPending) { fTotalHeight += pPendingLayoutItem->m_sSize.y; } } } return fTotalHeight; } FX_FLOAT CXFA_ItemLayoutProcessor::InsertKeepLayoutItems() { FX_FLOAT fTotalHeight = 0; if (m_arrayKeepItems.GetSize()) { if (!m_pLayoutItem) { m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); m_pLayoutItem->m_sSize.clear(); } for (int32_t iIndex = m_arrayKeepItems.GetSize() - 1; iIndex >= 0; iIndex--) { XFA_ItemLayoutProcessor_AddLeaderAfterSplit(this, m_arrayKeepItems[iIndex]); fTotalHeight += m_arrayKeepItems[iIndex]->m_sSize.y; } m_arrayKeepItems.RemoveAll(); } return fTotalHeight; } bool CXFA_ItemLayoutProcessor::ProcessKeepForSplite( CXFA_ItemLayoutProcessor* pParentProcessor, CXFA_ItemLayoutProcessor* pChildProcessor, XFA_ItemLayoutProcessorResult eRetValue, CFX_ArrayTemplate<CXFA_ContentLayoutItem*>& rgCurLineLayoutItem, FX_FLOAT& fContentCurRowAvailWidth, FX_FLOAT& fContentCurRowHeight, FX_FLOAT& fContentCurRowY, bool& bAddedItemInRow, bool& bForceEndPage, XFA_ItemLayoutProcessorResult& result) { if (!pParentProcessor || !pChildProcessor) { return false; } if (pParentProcessor->m_pCurChildNode->GetIntact() != XFA_ATTRIBUTEENUM_None || !pChildProcessor->m_bHasAvailHeight) { if (XFA_ExistContainerKeep(pParentProcessor->m_pCurChildNode, true)) { FX_FLOAT fChildWidth, fChildHeight; pChildProcessor->GetCurrentComponentSize(fChildWidth, fChildHeight); CFX_ArrayTemplate<CXFA_ContentLayoutItem*> keepLayoutItems; if (pParentProcessor->JudgePutNextPage(pParentProcessor->m_pLayoutItem, fChildHeight, keepLayoutItems)) { m_arrayKeepItems.RemoveAll(); for (int32_t iIndex = 0; iIndex < keepLayoutItems.GetSize(); iIndex++) { CXFA_ContentLayoutItem* pItem = keepLayoutItems.GetAt(iIndex); pParentProcessor->m_pLayoutItem->RemoveChild(pItem); fContentCurRowY -= pItem->m_sSize.y; m_arrayKeepItems.Add(pItem); } bAddedItemInRow = true; bForceEndPage = true; result = XFA_ItemLayoutProcessorResult_PageFullBreak; return true; } rgCurLineLayoutItem.Add(pChildProcessor->ExtractLayoutItem()); bAddedItemInRow = true; fContentCurRowAvailWidth -= fChildWidth; if (fContentCurRowHeight < fChildHeight) { fContentCurRowHeight = fChildHeight; } result = eRetValue; return true; } } return false; } bool CXFA_ItemLayoutProcessor::JudgePutNextPage( CXFA_ContentLayoutItem* pParentLayoutItem, FX_FLOAT fChildHeight, CFX_ArrayTemplate<CXFA_ContentLayoutItem*>& pKeepItems) { if (!pParentLayoutItem) { return false; } FX_FLOAT fItemsHeight = 0; for (CXFA_ContentLayoutItem* pChildLayoutItem = (CXFA_ContentLayoutItem*)pParentLayoutItem->m_pFirstChild; pChildLayoutItem; pChildLayoutItem = (CXFA_ContentLayoutItem*)pChildLayoutItem->m_pNextSibling) { if (XFA_ExistContainerKeep(pChildLayoutItem->m_pFormNode, false)) { pKeepItems.Add(pChildLayoutItem); fItemsHeight += pChildLayoutItem->m_sSize.y; } else { pKeepItems.RemoveAll(); fItemsHeight = 0; } } fItemsHeight += fChildHeight; if (m_pPageMgr->GetNextAvailContentHeight(fItemsHeight)) { return true; } return false; } void CXFA_ItemLayoutProcessor::ProcessUnUseBinds(CXFA_Node* pFormNode) { if (!pFormNode) { return; } CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> 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->SetObject(XFA_ATTRIBUTE_BindingNode, nullptr); } } pNode->SetFlag(XFA_NodeFlag_UnusedNode, true); } } void CXFA_ItemLayoutProcessor::ProcessUnUseOverFlow( CXFA_Node* pLeaderNode, CXFA_Node* pTrailerNode, CXFA_ContentLayoutItem* pTrailerItem, CXFA_Node* pFormNode) { ProcessUnUseBinds(pLeaderNode); ProcessUnUseBinds(pTrailerNode); if (!pFormNode) { return; } if (pFormNode->GetElementType() == XFA_Element::Overflow || pFormNode->GetElementType() == XFA_Element::Break) { pFormNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent); } if (pLeaderNode && pFormNode) { pFormNode->RemoveChild(pLeaderNode); } if (pTrailerNode && pFormNode) { pFormNode->RemoveChild(pTrailerNode); } if (pTrailerItem) { XFA_ReleaseLayoutItem(pTrailerItem); } } static XFA_ItemLayoutProcessorResult XFA_ItemLayoutProcessor_InsertFlowedItem( CXFA_ItemLayoutProcessor* pThis, CXFA_ItemLayoutProcessor* pProcessor, bool bContainerWidthAutoSize, bool bContainerHeightAutoSize, FX_FLOAT fContainerHeight, XFA_ATTRIBUTEENUM eFlowStrategy, uint8_t& uCurHAlignState, CFX_ArrayTemplate<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], bool bUseBreakControl, FX_FLOAT fAvailHeight, FX_FLOAT fRealHeight, FX_FLOAT& fContentCurRowY, FX_FLOAT& fContentWidthLimit, FX_FLOAT& fContentCurRowAvailWidth, FX_FLOAT& fContentCurRowHeight, bool& bAddedItemInRow, bool& bForceEndPage, CXFA_LayoutContext* pLayoutContext = nullptr, bool bNewRow = false) { bool bTakeSpace = XFA_ItemLayoutProcessor_IsTakingSpace(pProcessor->m_pFormNode); uint8_t uHAlign = XFA_ItemLayoutProcessor_HAlignEnumToInt( pThis->m_pCurChildNode->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 bIsOwnSplite = pProcessor->m_pFormNode->GetIntact() == XFA_ATTRIBUTEENUM_None; bool bUseRealHeight = bTakeSpace && bContainerHeightAutoSize && bIsOwnSplite && pProcessor->m_pFormNode->GetNodeItem(XFA_NODEITEM_Parent)->GetIntact() == XFA_ATTRIBUTEENUM_None; bool bIsTransHeight = bTakeSpace; if (bIsTransHeight && !bIsOwnSplite) { bool bRootForceTb = false; XFA_ATTRIBUTEENUM eLayoutStrategy = XFA_ItemLayoutProcessor_GetLayout( pProcessor->m_pFormNode, bRootForceTb); if (eLayoutStrategy == XFA_ATTRIBUTEENUM_Lr_tb || eLayoutStrategy == XFA_ATTRIBUTEENUM_Rl_tb) { bIsTransHeight = 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 : XFA_LAYOUT_FLOAT_MAX, bIsTransHeight ? fRealHeight - fContentCurRowY : XFA_LAYOUT_FLOAT_MAX, pLayoutContext); pProcessor->m_ePreProcessRs = eRetValue; } else { eRetValue = pProcessor->m_ePreProcessRs; pProcessor->m_ePreProcessRs = XFA_ItemLayoutProcessorResult_Done; } if (pProcessor->HasLayoutItem() == false) { return eRetValue; } FX_FLOAT fChildWidth, fChildHeight; pProcessor->GetCurrentComponentSize(fChildWidth, fChildHeight); if (bUseRealHeight && fRealHeight < XFA_LAYOUT_FLOAT_PERCISION) { fRealHeight = XFA_LAYOUT_FLOAT_MAX; fAvailHeight = XFA_LAYOUT_FLOAT_MAX; } if (!bTakeSpace || (fChildWidth <= fContentCurRowAvailWidth + XFA_LAYOUT_FLOAT_PERCISION) || (fContentWidthLimit - fContentCurRowAvailWidth <= XFA_LAYOUT_FLOAT_PERCISION)) { 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) { CXFA_ItemLayoutProcessor* pOverflowLeaderProcessor = new CXFA_ItemLayoutProcessor(pOverflowTrailerNode, nullptr); pOverflowLeaderProcessor->DoLayout(false, XFA_LAYOUT_FLOAT_MAX); pTrailerLayoutItem = pOverflowLeaderProcessor->HasLayoutItem() ? pOverflowLeaderProcessor->ExtractLayoutItem() : nullptr; delete pOverflowLeaderProcessor; } if (bUseInherited) { bIsAddTrailerHeight = pThis->IsAddNewRowForTrailer(pTrailerLayoutItem); } else { bIsAddTrailerHeight = pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem); } if (bIsAddTrailerHeight) { FX_FLOAT fTrailerHeight = pTrailerLayoutItem->m_sSize.y; fChildHeight += fTrailerHeight; bIsAddTrailerHeight = true; } } } } if (!bTakeSpace || fContentCurRowY + fChildHeight <= 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) { XFA_ItemLayoutProcessor_AddTrailerBeforeSplit( pProcessor, fChildHeight, pTrailerLayoutItem); } if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) { XFA_ItemLayoutProcessor_AddPendingNode(pProcessor, pOverflowLeaderNode, false); } pProcessor->m_bUseInheriated = false; } else { if (bIsAddTrailerHeight) { fChildHeight -= pTrailerLayoutItem->m_sSize.y; } pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, pTrailerLayoutItem, pFormNode); } CXFA_ContentLayoutItem* pChildLayoutItem = pProcessor->ExtractLayoutItem(); if (XFA_ExistContainerKeep(pProcessor->m_pFormNode, false) && pProcessor->m_pFormNode->GetIntact() == XFA_ATTRIBUTEENUM_None) { pThis->m_arrayKeepItems.Add(pChildLayoutItem); } else { pThis->m_arrayKeepItems.RemoveAll(); } rgCurLineLayoutItems[uHAlign].Add(pChildLayoutItem); bAddedItemInRow = true; if (bTakeSpace) { fContentCurRowAvailWidth -= fChildWidth; if (fContentCurRowHeight < fChildHeight) { fContentCurRowHeight = fChildHeight; } } return XFA_ItemLayoutProcessorResult_Done; } else { if (eRetValue == XFA_ItemLayoutProcessorResult_PageFullBreak) { if (pProcessor->m_bUseInheriated) { if (pTrailerLayoutItem) { XFA_ItemLayoutProcessor_AddTrailerBeforeSplit( pProcessor, fChildHeight, pTrailerLayoutItem); } if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) { XFA_ItemLayoutProcessor_AddPendingNode( pProcessor, pOverflowLeaderNode, false); } pProcessor->m_bUseInheriated = false; } else { if (bIsAddTrailerHeight) { fChildHeight -= pTrailerLayoutItem->m_sSize.y; } pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, pTrailerLayoutItem, pFormNode); } } rgCurLineLayoutItems[uHAlign].Add(pProcessor->ExtractLayoutItem()); bAddedItemInRow = true; fContentCurRowAvailWidth -= fChildWidth; if (fContentCurRowHeight < fChildHeight) { fContentCurRowHeight = fChildHeight; } return eRetValue; } } else { XFA_ItemLayoutProcessorResult eResult; if (pThis->ProcessKeepForSplite( pThis, pProcessor, eRetValue, rgCurLineLayoutItems[uHAlign], fContentCurRowAvailWidth, fContentCurRowHeight, fContentCurRowY, bAddedItemInRow, bForceEndPage, eResult)) { return eResult; } bForceEndPage = true; FX_FLOAT fSplitPos = pProcessor->FindSplitPos(fAvailHeight - fContentCurRowY); if (fSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { XFA_ATTRIBUTEENUM eLayout = pProcessor->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); if (eLayout == XFA_ATTRIBUTEENUM_Tb && eRetValue == XFA_ItemLayoutProcessorResult_Done) { pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, pTrailerLayoutItem, pFormNode); rgCurLineLayoutItems[uHAlign].Add(pProcessor->ExtractLayoutItem()); bAddedItemInRow = true; if (bTakeSpace) { fContentCurRowAvailWidth -= fChildWidth; if (fContentCurRowHeight < fChildHeight) { fContentCurRowHeight = fChildHeight; } } 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) { XFA_ItemLayoutProcessor_AddTrailerBeforeSplit( pProcessor, fSplitPos, pTrailerLayoutItem, bUseInherited); } else { pProcessor->SplitLayoutItem(fSplitPos); } 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)) { XFA_ItemLayoutProcessor_AddPendingNode( pProcessor, pOverflowLeaderNode, false); } } } if (pProcessor->m_pLayoutItem->m_pNextSibling) { pProcessor->GetCurrentComponentSize(fChildWidth, fChildHeight); rgCurLineLayoutItems[uHAlign].Add(pProcessor->ExtractLayoutItem()); bAddedItemInRow = true; if (bTakeSpace) { fContentCurRowAvailWidth -= fChildWidth; if (fContentCurRowHeight < fChildHeight) { fContentCurRowHeight = fChildHeight; } } } return XFA_ItemLayoutProcessorResult_PageFullBreak; } else if (fContentCurRowY <= XFA_LAYOUT_FLOAT_PERCISION) { pProcessor->GetCurrentComponentSize(fChildWidth, fChildHeight); if (pProcessor->m_pPageMgr->GetNextAvailContentHeight(fChildHeight)) { CXFA_Node* pTempLeaderNode = nullptr; CXFA_Node* pTempTrailerNode = nullptr; if (pThis->m_pPageMgr) { if (!pFormNode && pLayoutContext) { pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; } pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, pTempTrailerNode, false, true); } if (bUseInherited) { pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, pTrailerLayoutItem, pFormNode); pThis->m_bUseInheriated = true; } return XFA_ItemLayoutProcessorResult_PageFullBreak; } rgCurLineLayoutItems[uHAlign].Add(pProcessor->ExtractLayoutItem()); bAddedItemInRow = true; if (bTakeSpace) { fContentCurRowAvailWidth -= fChildWidth; if (fContentCurRowHeight < fChildHeight) { fContentCurRowHeight = fChildHeight; } } if (eRetValue == XFA_ItemLayoutProcessorResult_Done) { bForceEndPage = false; } return eRetValue; } else { XFA_ATTRIBUTEENUM eLayout = pProcessor->m_pFormNode->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) { XFA_ItemLayoutProcessor_AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem); } if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) { XFA_ItemLayoutProcessor_AddPendingNode(pProcessor, pOverflowLeaderNode, false); } } else { if (eRetValue == XFA_ItemLayoutProcessorResult_Done) { if (!pFormNode && pLayoutContext) { pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; } if (pThis->m_pPageMgr) { pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, pOverflowTrailerNode, false, true); } if (bUseInherited) { pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, pTrailerLayoutItem, pFormNode); pThis->m_bUseInheriated = true; } } } return XFA_ItemLayoutProcessorResult_PageFullBreak; } } } else { return XFA_ItemLayoutProcessorResult_RowFullBreak; } return XFA_ItemLayoutProcessorResult_Done; } XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayoutFlowedContainer( bool bUseBreakControl, XFA_ATTRIBUTEENUM eFlowStrategy, FX_FLOAT fHeightLimit, FX_FLOAT fRealHeight, CXFA_LayoutContext* pContext, bool bRootForceTb) { m_bHasAvailHeight = true; FX_FLOAT fContainerWidth = 0, fContainerHeight = 0; bool bBreakDone = false; bool bContainerWidthAutoSize = true, bContainerHeightAutoSize = true; bool bForceEndPage = false; bool bIsManualBreak = false; if (m_pCurChildPreprocessor) { m_pCurChildPreprocessor->m_ePreProcessRs = XFA_ItemLayoutProcessorResult_Done; } XFA_ItemLayoutProcessor_CalculateContainerSpecfiedSize( m_pFormNode, fContainerWidth, fContainerHeight, bContainerWidthAutoSize, bContainerHeightAutoSize); if (pContext && pContext->m_bCurColumnWidthAvaiable) { bContainerWidthAutoSize = false; fContainerWidth = pContext->m_fCurColumnWidth; } if (!bContainerHeightAutoSize) { fContainerHeight -= m_fUsedSize; } if (!bContainerHeightAutoSize) { CXFA_Node* pParentNode = m_pFormNode->GetNodeItem(XFA_NODEITEM_Parent); bool bFocrTb = false; if (pParentNode && XFA_ItemLayoutProcessor_GetLayout(pParentNode, bFocrTb) == XFA_ATTRIBUTEENUM_Row) { CXFA_Node* pChildContainer = m_pFormNode->GetNodeItem( XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode); if (pChildContainer && pChildContainer->GetNodeItem(XFA_NODEITEM_NextSibling, XFA_ObjectType::ContainerNode)) { fContainerHeight = 0; bContainerHeightAutoSize = true; } } } CXFA_Node* pMarginNode = m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); FX_FLOAT fLeftInset = 0, fTopInset = 0, fRightInset = 0, fBottomInset = 0; if (pMarginNode) { fLeftInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); fTopInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); fRightInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); fBottomInset = pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset).ToUnit(XFA_UNIT_Pt); } FX_FLOAT fContentWidthLimit = bContainerWidthAutoSize ? XFA_LAYOUT_FLOAT_MAX : fContainerWidth - fLeftInset - fRightInset; FX_FLOAT fContentCalculatedWidth = 0, fContentCalculatedHeight = 0; FX_FLOAT fAvailHeight = fHeightLimit - fTopInset - fBottomInset; if (fAvailHeight < 0) { m_bHasAvailHeight = false; } fRealHeight = fRealHeight - fTopInset - fBottomInset; FX_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; } } } for (CXFA_ContentLayoutItem* pLayoutTempChild = (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; pLayoutTempChild != pLayoutChild; pLayoutTempChild = (CXFA_ContentLayoutItem*)pLayoutTempChild->m_pNextSibling) { if (XFA_ItemLayoutProcessor_IsTakingSpace( pLayoutTempChild->m_pFormNode)) { FX_FLOAT fChildContentWidth = pLayoutTempChild->m_sPos.x + pLayoutTempChild->m_sSize.x; FX_FLOAT fChildContentHeight = pLayoutTempChild->m_sPos.y + pLayoutTempChild->m_sSize.y; if (fContentCalculatedWidth < fChildContentWidth) { fContentCalculatedWidth = fChildContentWidth; } if (fContentCalculatedHeight < fChildContentHeight) { fContentCalculatedHeight = fChildContentHeight; } } } if (pLayoutChild) { fContentCurRowY = pLayoutChild->m_sPos.y; } else { fContentCurRowY = fContentCalculatedHeight; } } fContentCurRowY += InsertKeepLayoutItems(); if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages_None) { XFA_ItemLayoutProcessor_GotoNextContainerNode( m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, true); } fContentCurRowY += XFA_ItemLayoutProcessor_InsertPendingItems(this, m_pFormNode); if (m_pCurChildPreprocessor && m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages_Container) { if (XFA_ExistContainerKeep(m_pCurChildPreprocessor->GetFormNode(), false)) { m_pKeepHeadNode = m_pCurChildNode; m_bIsProcessKeep = true; m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages_Keep; } } while (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages_Done) { FX_FLOAT fContentCurRowHeight = 0; FX_FLOAT fContentCurRowAvailWidth = fContentWidthLimit; m_fWidthLimite = fContentCurRowAvailWidth; CFX_ArrayTemplate<CXFA_ContentLayoutItem*> 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 = XFA_ItemLayoutProcessor_HAlignEnumToInt( pLayoutNext->m_pFormNode->GetEnum(XFA_ATTRIBUTE_HAlign)); rgCurLineLayoutItems[uHAlign].Add(pLayoutNext); if (eFlowStrategy == XFA_ATTRIBUTEENUM_Lr_tb) { if (uHAlign > uCurHAlignState) { uCurHAlignState = uHAlign; } } else if (uHAlign < uCurHAlignState) { uCurHAlignState = uHAlign; } if (XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutNext->m_pFormNode)) { if (pLayoutNext->m_sSize.y > fContentCurRowHeight) { fContentCurRowHeight = pLayoutNext->m_sSize.y; } fContentCurRowAvailWidth -= pLayoutNext->m_sSize.x; } } 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; } } } 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; } while (m_pCurChildNode) { CXFA_ItemLayoutProcessor* pProcessor = nullptr; bool bAddedItemInRow = false; fContentCurRowY += XFA_ItemLayoutProcessor_InsertPendingItems(this, m_pFormNode); switch (m_nCurChildNodeStage) { case XFA_ItemLayoutProcessorStages_Keep: case XFA_ItemLayoutProcessorStages_None: break; case XFA_ItemLayoutProcessorStages_BreakBefore: { for (int32_t iIndex = 0; iIndex < m_arrayKeepItems.GetSize(); iIndex++) { CXFA_ContentLayoutItem* pItem = m_arrayKeepItems.GetAt(iIndex); m_pLayoutItem->RemoveChild(pItem); fContentCalculatedHeight -= pItem->m_sSize.y; } 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) { if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { XFA_ItemLayoutProcessor_AddPendingNode(this, pLeaderNode, true); } if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { if (m_pFormNode->GetNodeItem(XFA_NODEITEM_Parent) ->GetElementType() == XFA_Element::Form && !m_pLayoutItem) { XFA_ItemLayoutProcessor_AddPendingNode(this, pTrailerNode, true); } else { std::unique_ptr<CXFA_ItemLayoutProcessor> pTempProcessor( new CXFA_ItemLayoutProcessor(pTrailerNode, nullptr)); XFA_ItemLayoutProcessor_InsertFlowedItem( this, pTempProcessor.get(), bContainerWidthAutoSize, bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, uCurHAlignState, rgCurLineLayoutItems, false, XFA_LAYOUT_FLOAT_MAX, XFA_LAYOUT_FLOAT_MAX, fContentCurRowY, fContentWidthLimit, fContentCurRowAvailWidth, fContentCurRowHeight, bAddedItemInRow, bForceEndPage, pContext); } } XFA_ItemLayoutProcessor_GotoNextContainerNode( m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, true); bForceEndPage = true; bIsManualBreak = true; goto SuspendAndCreateNewRow; } } break; 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) { if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { std::unique_ptr<CXFA_ItemLayoutProcessor> pTempProcessor( new CXFA_ItemLayoutProcessor(pTrailerNode, nullptr)); XFA_ItemLayoutProcessor_InsertFlowedItem( this, pTempProcessor.get(), bContainerWidthAutoSize, bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, uCurHAlignState, rgCurLineLayoutItems, false, XFA_LAYOUT_FLOAT_MAX, XFA_LAYOUT_FLOAT_MAX, fContentCurRowY, fContentWidthLimit, fContentCurRowAvailWidth, fContentCurRowHeight, bAddedItemInRow, bForceEndPage, pContext); } if (!bCreatePage) { if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { CalculateRowChildPosition( rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, bContainerWidthAutoSize, fContentCalculatedWidth, fContentCalculatedHeight, fContentCurRowY, fContentCurRowHeight, fContentWidthLimit); rgCurLineLayoutItems->RemoveAll(); std::unique_ptr<CXFA_ItemLayoutProcessor> pTempProcessor( new CXFA_ItemLayoutProcessor(pLeaderNode, nullptr)); XFA_ItemLayoutProcessor_InsertFlowedItem( this, pTempProcessor.get(), bContainerWidthAutoSize, bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, uCurHAlignState, rgCurLineLayoutItems, false, XFA_LAYOUT_FLOAT_MAX, XFA_LAYOUT_FLOAT_MAX, fContentCurRowY, fContentWidthLimit, fContentCurRowAvailWidth, fContentCurRowHeight, bAddedItemInRow, bForceEndPage, pContext); } } else { if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { XFA_ItemLayoutProcessor_AddPendingNode(this, pLeaderNode, true); } } XFA_ItemLayoutProcessor_GotoNextContainerNode( m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, true); if (bCreatePage) { bForceEndPage = true; bIsManualBreak = true; if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages_Done) { bBreakDone = true; } } goto SuspendAndCreateNewRow; } } break; case XFA_ItemLayoutProcessorStages_BookendLeader: { CXFA_Node* pLeaderNode = nullptr; if (m_pCurChildPreprocessor) { pProcessor = m_pCurChildPreprocessor; m_pCurChildPreprocessor = nullptr; } else if (m_pPageMgr && m_pPageMgr->ProcessBookendLeaderOrTrailer( m_pCurChildNode, true, pLeaderNode)) { pProcessor = new CXFA_ItemLayoutProcessor(pLeaderNode, m_pPageMgr); } if (pProcessor) { if (XFA_ItemLayoutProcessor_InsertFlowedItem( this, pProcessor, bContainerWidthAutoSize, bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl, fAvailHeight, fRealHeight, fContentCurRowY, fContentWidthLimit, fContentCurRowAvailWidth, fContentCurRowHeight, bAddedItemInRow, bForceEndPage, pContext) != XFA_ItemLayoutProcessorResult_Done) { goto SuspendAndCreateNewRow; } else { delete pProcessor; pProcessor = nullptr; } } } break; case XFA_ItemLayoutProcessorStages_BookendTrailer: { CXFA_Node* pTrailerNode = nullptr; if (m_pCurChildPreprocessor) { pProcessor = m_pCurChildPreprocessor; m_pCurChildPreprocessor = nullptr; } else if (m_pPageMgr && m_pPageMgr->ProcessBookendLeaderOrTrailer( m_pCurChildNode, false, pTrailerNode)) { pProcessor = new CXFA_ItemLayoutProcessor(pTrailerNode, m_pPageMgr); } if (pProcessor) { if (XFA_ItemLayoutProcessor_InsertFlowedItem( this, pProcessor, bContainerWidthAutoSize, bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl, fAvailHeight, fRealHeight, fContentCurRowY, fContentWidthLimit, fContentCurRowAvailWidth, fContentCurRowHeight, bAddedItemInRow, bForceEndPage, pContext) != XFA_ItemLayoutProcessorResult_Done) { goto SuspendAndCreateNewRow; } else { delete pProcessor; pProcessor = nullptr; } } } break; case XFA_ItemLayoutProcessorStages_Container: ASSERT(m_pCurChildNode->IsContainerNode()); if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) { break; } if (fContentCurRowY >= fHeightLimit + XFA_LAYOUT_FLOAT_PERCISION && XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) { bForceEndPage = true; goto SuspendAndCreateNewRow; } if (m_pCurChildNode->IsContainerNode()) { bool bNewRow = false; if (m_pCurChildPreprocessor) { pProcessor = m_pCurChildPreprocessor; m_pCurChildPreprocessor = nullptr; bNewRow = true; } else { pProcessor = new CXFA_ItemLayoutProcessor(m_pCurChildNode, m_pPageMgr); } XFA_ItemLayoutProcessor_InsertPendingItems(pProcessor, m_pCurChildNode); XFA_ItemLayoutProcessorResult rs = XFA_ItemLayoutProcessor_InsertFlowedItem( this, pProcessor, bContainerWidthAutoSize, bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl, fAvailHeight, fRealHeight, fContentCurRowY, fContentWidthLimit, 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 += XFA_ItemLayoutProcessor_InsertPendingItems( pProcessor, m_pCurChildNode); delete pProcessor; pProcessor = nullptr; } } break; case XFA_ItemLayoutProcessorStages_Done: break; default: break; } XFA_ItemLayoutProcessor_GotoNextContainerNode( m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, true); if (bAddedItemInRow && eFlowStrategy == XFA_ATTRIBUTEENUM_Tb) { break; } else { continue; } SuspendAndCreateNewRow: if (pProcessor) { m_pCurChildPreprocessor = pProcessor; } break; } CalculateRowChildPosition(rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, bContainerWidthAutoSize, fContentCalculatedWidth, fContentCalculatedHeight, fContentCurRowY, fContentCurRowHeight, fContentWidthLimit, bRootForceTb); m_fWidthLimite = fContentCurRowAvailWidth; if (bForceEndPage) { break; } } bool bRetValue = m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages_Done && m_PendingNodes.empty(); if (bBreakDone) { bRetValue = false; } XFA_ItemLayoutProcessor_CalculateContainerComponentSizeFromContentSize( m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, fContainerWidth, bContainerHeightAutoSize, fContentCalculatedHeight, fContainerHeight); if (fContainerHeight >= XFA_LAYOUT_FLOAT_PERCISION || m_pLayoutItem || bRetValue) { if (!m_pLayoutItem) { m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); } if (fContainerHeight < 0) { fContainerHeight = 0; } SetCurrentComponentSize(fContainerWidth, fContainerHeight); if (bForceEndPage) { m_fUsedSize = 0; } else { m_fUsedSize += m_pLayoutItem->m_sSize.y; } } return bRetValue ? XFA_ItemLayoutProcessorResult_Done : (bIsManualBreak ? XFA_ItemLayoutProcessorResult_ManualBreak : XFA_ItemLayoutProcessorResult_PageFullBreak); } bool CXFA_ItemLayoutProcessor::CalculateRowChildPosition( CFX_ArrayTemplate<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], XFA_ATTRIBUTEENUM eFlowStrategy, bool bContainerHeightAutoSize, bool bContainerWidthAutoSize, FX_FLOAT& fContentCalculatedWidth, FX_FLOAT& fContentCalculatedHeight, FX_FLOAT& fContentCurRowY, FX_FLOAT fContentCurRowHeight, FX_FLOAT fContentWidthLimit, bool bRootForceTb) { int32_t nGroupLengths[3] = {0, 0, 0}; FX_FLOAT fGroupWidths[3] = {0, 0, 0}; int32_t nTotalLength = 0; for (int32_t i = 0; i < 3; i++) { nGroupLengths[i] = rgCurLineLayoutItems[i].GetSize(); for (int32_t c = nGroupLengths[i], j = 0; j < c; j++) { nTotalLength++; if (XFA_ItemLayoutProcessor_IsTakingSpace( rgCurLineLayoutItems[i][j]->m_pFormNode)) { fGroupWidths[i] += rgCurLineLayoutItems[i][j]->m_sSize.x; } } } if (!nTotalLength) { if (bContainerHeightAutoSize) { FX_FLOAT fNewHeight = fContentCurRowY; if (fContentCalculatedHeight > fNewHeight) { fContentCalculatedHeight = fNewHeight; } } return false; } if (!m_pLayoutItem) { m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); } if (eFlowStrategy != XFA_ATTRIBUTEENUM_Rl_tb) { FX_FLOAT fCurPos; fCurPos = 0; for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { if (bRootForceTb) { FX_FLOAT fAbsoluteX, fAbsoluteY; CalculatePositionedContainerPos(rgCurLineLayoutItems[0][j]->m_pFormNode, rgCurLineLayoutItems[0][j]->m_sSize.x, rgCurLineLayoutItems[0][j]->m_sSize.y, fAbsoluteX, fAbsoluteY); rgCurLineLayoutItems[0][j]->m_sPos = CFX_PointF(fAbsoluteX, fAbsoluteY); } else { rgCurLineLayoutItems[0][j]->m_sPos = CFX_PointF(fCurPos, fContentCurRowY); if (XFA_ItemLayoutProcessor_IsTakingSpace( rgCurLineLayoutItems[0][j]->m_pFormNode)) { fCurPos += rgCurLineLayoutItems[0][j]->m_sSize.x; } } 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) { FX_FLOAT fAbsoluteX, fAbsoluteY; CalculatePositionedContainerPos(rgCurLineLayoutItems[1][j]->m_pFormNode, rgCurLineLayoutItems[1][j]->m_sSize.x, rgCurLineLayoutItems[1][j]->m_sSize.y, fAbsoluteX, fAbsoluteY); rgCurLineLayoutItems[1][j]->m_sPos = CFX_PointF(fAbsoluteX, fAbsoluteY); } else { rgCurLineLayoutItems[1][j]->m_sPos = CFX_PointF(fCurPos, fContentCurRowY); if (XFA_ItemLayoutProcessor_IsTakingSpace( rgCurLineLayoutItems[1][j]->m_pFormNode)) { fCurPos += rgCurLineLayoutItems[1][j]->m_sSize.x; } } 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) { FX_FLOAT fAbsoluteX, fAbsoluteY; CalculatePositionedContainerPos(rgCurLineLayoutItems[2][j]->m_pFormNode, rgCurLineLayoutItems[2][j]->m_sSize.x, rgCurLineLayoutItems[2][j]->m_sSize.y, fAbsoluteX, fAbsoluteY); rgCurLineLayoutItems[2][j]->m_sPos = CFX_PointF(fAbsoluteX, fAbsoluteY); } else { rgCurLineLayoutItems[2][j]->m_sPos = CFX_PointF(fCurPos, fContentCurRowY); if (XFA_ItemLayoutProcessor_IsTakingSpace( rgCurLineLayoutItems[2][j]->m_pFormNode)) { fCurPos += rgCurLineLayoutItems[2][j]->m_sSize.x; } } m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); m_fLastRowWidth = fCurPos; } } else { FX_FLOAT fCurPos; fCurPos = fGroupWidths[0]; for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { if (XFA_ItemLayoutProcessor_IsTakingSpace( rgCurLineLayoutItems[0][j]->m_pFormNode)) { fCurPos -= rgCurLineLayoutItems[0][j]->m_sSize.x; } 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 (XFA_ItemLayoutProcessor_IsTakingSpace( rgCurLineLayoutItems[1][j]->m_pFormNode)) { fCurPos -= rgCurLineLayoutItems[1][j]->m_sSize.x; } 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 (XFA_ItemLayoutProcessor_IsTakingSpace( rgCurLineLayoutItems[2][j]->m_pFormNode)) { fCurPos -= rgCurLineLayoutItems[2][j]->m_sSize.x; } 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) { FX_FLOAT fChildSuppliedWidth = fGroupWidths[0]; if (fContentWidthLimit < XFA_LAYOUT_FLOAT_MAX && fContentWidthLimit > fChildSuppliedWidth) { fChildSuppliedWidth = fContentWidthLimit; } if (fContentCalculatedWidth < fChildSuppliedWidth) { fContentCalculatedWidth = fChildSuppliedWidth; } } if (bContainerHeightAutoSize) { FX_FLOAT fChildSuppliedHeight = fContentCurRowY; if (fContentCalculatedHeight < fChildSuppliedHeight) { fContentCalculatedHeight = fChildSuppliedHeight; } } return true; } CXFA_Node* CXFA_ItemLayoutProcessor::GetSubformSetParent( CXFA_Node* pSubformSet) { if (pSubformSet && pSubformSet->GetElementType() == XFA_Element::SubformSet) { CXFA_Node* pParent = pSubformSet->GetNodeItem(XFA_NODEITEM_Parent); while (pParent) { if (pParent->GetElementType() != XFA_Element::SubformSet) { return pParent; } pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent); } } 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; } CXFA_Document* pDocument = m_pFormNode->GetDocument(); CXFA_FFNotify* pNotify = pDocument->GetNotify(); FX_FLOAT fHeight = -1; FX_FLOAT fWidth = -1; pNotify->StartFieldDrawLayout(m_pFormNode, fWidth, fHeight); int32_t nRotate = FXSYS_round(m_pFormNode->GetMeasure(XFA_ATTRIBUTE_Rotate).GetValue()); nRotate = XFA_MapRotation(nRotate); if (nRotate == 90 || nRotate == 270) { FX_FLOAT fTmp = fWidth; fWidth = fHeight; fHeight = fTmp; } SetCurrentComponentSize(fWidth, fHeight); } XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayout( bool bUseBreakControl, FX_FLOAT fHeightLimit, FX_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 = XFA_ItemLayoutProcessor_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; } } void CXFA_ItemLayoutProcessor::GetCurrentComponentPos(FX_FLOAT& fAbsoluteX, FX_FLOAT& fAbsoluteY) { ASSERT(m_pLayoutItem); fAbsoluteX = m_pLayoutItem->m_sPos.x; fAbsoluteY = m_pLayoutItem->m_sPos.y; } void CXFA_ItemLayoutProcessor::GetCurrentComponentSize(FX_FLOAT& fWidth, FX_FLOAT& fHeight) { ASSERT(m_pLayoutItem); fWidth = m_pLayoutItem->m_sSize.x; fHeight = m_pLayoutItem->m_sSize.y; } void CXFA_ItemLayoutProcessor::SetCurrentComponentPos(FX_FLOAT fAbsoluteX, FX_FLOAT fAbsoluteY) { m_pLayoutItem->m_sPos = CFX_PointF(fAbsoluteX, fAbsoluteY); } void CXFA_ItemLayoutProcessor::SetCurrentComponentSize(FX_FLOAT fWidth, FX_FLOAT fHeight) { m_pLayoutItem->m_sSize = CFX_SizeF(fWidth, fHeight); } bool CXFA_ItemLayoutProcessor::JudgeLeaderOrTrailerForOccur( CXFA_Node* pFormNode) { if (!pFormNode) return false; CXFA_Node* pTemplate = pFormNode->GetTemplateNode(); if (!pTemplate) pTemplate = pFormNode; CXFA_Occur NodeOccur(pTemplate->GetFirstChildByClass(XFA_Element::Occur)); int32_t iMax = NodeOccur.GetMax(); if (iMax < 0) return true; int32_t iCount = m_PendingNodesCount[pTemplate]; if (iCount >= iMax) return false; m_PendingNodesCount[pTemplate] = iCount + 1; return true; }