// 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 <algorithm> | |
#include "xfa/src/foxitlib.h" | |
#include "xfa/src/fxfa/src/common/xfa_utils.h" | |
#include "xfa/src/fxfa/src/common/xfa_object.h" | |
#include "xfa/src/fxfa/src/common/xfa_document.h" | |
#include "xfa/src/fxfa/src/common/xfa_parser.h" | |
#include "xfa/src/fxfa/src/common/xfa_script.h" | |
#include "xfa/src/fxfa/src/common/xfa_docdata.h" | |
#include "xfa/src/fxfa/src/common/xfa_doclayout.h" | |
#include "xfa/src/fxfa/src/common/xfa_localemgr.h" | |
#include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h" | |
#include "xfa_document_layout_imp.h" | |
#include "xfa_layout_itemlayout.h" | |
#include "xfa_layout_pagemgr_new.h" | |
#include "xfa_layout_appadapter.h" | |
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), | |
#ifdef _XFA_LAYOUTITEM_ProcessCACHE_ | |
m_pOldLayoutItem(nullptr), | |
#else | |
m_pPageMgrCreateItem(nullptr), | |
#endif | |
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) { | |
FXSYS_assert(m_pFormNode && (m_pFormNode->IsContainerNode() || | |
m_pFormNode->GetClassID() == XFA_ELEMENT_Form)); | |
#ifdef _XFA_LAYOUTITEM_ProcessCACHE_ | |
m_pOldLayoutItem = | |
(CXFA_ContentLayoutItem*)m_pFormNode->GetUserData(XFA_LAYOUTITEMKEY); | |
#endif | |
} | |
CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::CreateContentLayoutItem( | |
CXFA_Node* pFormNode) { | |
if (!pFormNode) { | |
return NULL; | |
} | |
CXFA_ContentLayoutItem* pLayoutItem = NULL; | |
#ifdef _XFA_LAYOUTITEM_ProcessCACHE_ | |
if (m_pOldLayoutItem) { | |
pLayoutItem = m_pOldLayoutItem; | |
m_pOldLayoutItem = m_pOldLayoutItem->m_pNext; | |
return pLayoutItem; | |
} | |
pLayoutItem = (CXFA_ContentLayoutItem*)pFormNode->GetDocument() | |
->GetParser() | |
->GetNotify() | |
->OnCreateLayoutItem(pFormNode); | |
#else | |
pLayoutItem = | |
(CXFA_ContentLayoutItem*)m_pPageMgrCreateItem->FindOrCreateLayoutItem( | |
pFormNode); | |
#endif | |
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; | |
} | |
FX_BOOL CXFA_ItemLayoutProcessor::FindLayoutItemSplitPos( | |
CXFA_ContentLayoutItem* pLayoutItem, | |
FX_FLOAT fCurVerticalOffset, | |
FX_FLOAT& fProposedSplitPos, | |
FX_BOOL& bAppChange, | |
FX_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: { | |
FX_BOOL bAnyChanged = FALSE; | |
CXFA_Document* pDocument = pFormNode->GetDocument(); | |
IXFA_Notify* pNotify = pDocument->GetParser()->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); | |
} | |
FX_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; | |
FX_BOOL bAppChange = FALSE; | |
if (FindLayoutItemSplitPos(pChildItem, fChildOffset, fRelSplitPos, | |
bAppChange, bCalculateMargin)) { | |
if (fRelSplitPos - fChildOffset < XFA_LAYOUT_FLOAT_PERCISION && | |
bAppChange) { | |
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, | |
FX_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->GetClassID() == XFA_ELEMENT_Form) { | |
bRootForceTb = TRUE; | |
return XFA_ATTRIBUTEENUM_Tb; | |
} | |
return XFA_ATTRIBUTEENUM_Position; | |
} | |
static FX_BOOL XFA_ExistContainerKeep(CXFA_Node* pCurNode, FX_BOOL bPreFind) { | |
if (pCurNode == NULL || !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 == NULL) { | |
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); | |
FX_BOOL bCalculateMargin = TRUE; | |
if (eLayout == XFA_ATTRIBUTEENUM_Position) { | |
bCalculateMargin = FALSE; | |
} | |
while (fProposedSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { | |
FX_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); | |
FX_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 = NULL; | |
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 = NULL; | |
FX_FLOAT lHeightForKeep = 0; | |
CFX_ArrayTemplate<CXFA_ContentLayoutItem*> keepLayoutItems; | |
FX_FLOAT fAddMarginHeight = 0; | |
for (CXFA_ContentLayoutItem* pChildItem = pChildren, * pChildNext = NULL; | |
pChildItem; pChildItem = pChildNext) { | |
pChildNext = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling; | |
pChildItem->m_pNextSibling = NULL; | |
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, NULL, fSplitPos); | |
} | |
IXFA_LayoutPage* CXFA_LayoutItem::GetPage() const { | |
for (CXFA_LayoutItem* pCurNode = const_cast<CXFA_LayoutItem*>(this); pCurNode; | |
pCurNode = pCurNode->m_pParent) { | |
if (pCurNode->m_pFormNode->GetClassID() == 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, FX_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.Add(pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset) | |
.ToUnit(XFA_UNIT_Pt), | |
pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset) | |
.ToUnit(XFA_UNIT_Pt)); | |
} | |
} else { | |
if (pLayoutItem->m_pFormNode->GetClassID() == XFA_ELEMENT_ContentArea) { | |
sPos.Add(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->GetClassID() == | |
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 == NULL) { | |
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 == NULL) { | |
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 = NULL; | |
} | |
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 = NULL; | |
pChildItem->m_pParent = NULL; | |
} | |
CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::ExtractLayoutItem() { | |
CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem; | |
if (pLayoutItem) { | |
m_pLayoutItem = (CXFA_ContentLayoutItem*)pLayoutItem->m_pNextSibling; | |
pLayoutItem->m_pNextSibling = NULL; | |
} | |
#ifdef _XFA_LAYOUTITEM_ProcessCACHE_ | |
if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages_Done && | |
ToContentLayoutItem(m_pOldLayoutItem)) { | |
if (m_pOldLayoutItem->m_pPrev) { | |
m_pOldLayoutItem->m_pPrev->m_pNext = NULL; | |
} | |
IXFA_Notify* pNotify = | |
m_pOldLayoutItem->m_pFormNode->GetDocument()->GetParser()->GetNotify(); | |
IXFA_DocLayout* pDocLayout = | |
m_pOldLayoutItem->m_pFormNode->GetDocument()->GetDocLayout(); | |
CXFA_ContentLayoutItem* pOldLayoutItem = m_pOldLayoutItem; | |
while (pOldLayoutItem) { | |
CXFA_ContentLayoutItem* pNextOldLayoutItem = pOldLayoutItem->m_pNext; | |
pNotify->OnLayoutEvent(pDocLayout, pOldLayoutItem, | |
XFA_LAYOUTEVENT_ItemRemoving); | |
delete pOldLayoutItem; | |
pOldLayoutItem = pNextOldLayoutItem; | |
} | |
m_pOldLayoutItem = NULL; | |
} | |
#endif | |
return pLayoutItem; | |
} | |
static FX_BOOL XFA_ItemLayoutProcessor_FindBreakNode( | |
CXFA_Node* pContainerNode, | |
CXFA_Node*& pCurActionNode, | |
XFA_ItemLayoutProcessorStages& nCurStage, | |
FX_BOOL bBreakBefore) { | |
FX_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->GetClassID()) { | |
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; | |
} | |
#ifdef _XFA_LAYOUTITEM_ProcessCACHE_ | |
static void XFA_DeleteLayoutGeneratedNode(CXFA_Node* pGenerateNode) { | |
IXFA_Notify* pNotify = pGenerateNode->GetDocument()->GetParser()->GetNotify(); | |
IXFA_DocLayout* 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 = NULL; | |
while (pCurLayoutItem) { | |
pNextLayoutItem = pCurLayoutItem->m_pNext; | |
pNotify->OnLayoutEvent(pDocLayout, pCurLayoutItem, | |
XFA_LAYOUTEVENT_ItemRemoving); | |
delete pCurLayoutItem; | |
pCurLayoutItem = pNextLayoutItem; | |
} | |
} | |
pGenerateNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pGenerateNode); | |
} | |
#endif | |
void CXFA_ItemLayoutProcessor::XFA_ItemLayoutProcessor_GotoNextContainerNode( | |
CXFA_Node*& pCurActionNode, | |
XFA_ItemLayoutProcessorStages& nCurStage, | |
CXFA_Node* pParentContainer, | |
FX_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->GetClassID()) { | |
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->HasFlag(XFA_NODEFLAG_LayoutGeneratedNode)) { | |
CXFA_Node* pSaveNode = pNextChildContainer; | |
pNextChildContainer = pNextChildContainer->GetNodeItem( | |
XFA_NODEITEM_NextSibling, XFA_OBJECTTYPE_ContainerNode); | |
#ifdef _XFA_LAYOUTITEM_ProcessCACHE_ | |
if (pSaveNode->HasFlag(XFA_NODEFLAG_UnusedNode)) { | |
XFA_DeleteLayoutGeneratedNode(pSaveNode); | |
} | |
#endif | |
} | |
if (!pNextChildContainer) { | |
goto NoMoreChildContainer; | |
} | |
FX_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->GetClassID()) { | |
case XFA_ELEMENT_Bookend: | |
case XFA_ELEMENT_Break: | |
pCurActionNode = pBookendNode; | |
nCurStage = XFA_ItemLayoutProcessorStages_BookendTrailer; | |
return; | |
default: | |
break; | |
} | |
} | |
} | |
default: | |
pCurActionNode = NULL; | |
nCurStage = XFA_ItemLayoutProcessorStages_Done; | |
} | |
} | |
FX_BOOL CXFA_ItemLayoutProcessor::ProcessKeepNodesForCheckNext( | |
CXFA_Node*& pCurActionNode, | |
XFA_ItemLayoutProcessorStages& nCurStage, | |
CXFA_Node*& pNextContainer, | |
FX_BOOL& bLastKeepNode) { | |
FX_BOOL bCanSplite = pNextContainer->GetIntact() == XFA_ATTRIBUTEENUM_None; | |
FX_BOOL bNextKeep = FALSE; | |
if (XFA_ExistContainerKeep(pNextContainer, FALSE)) { | |
bNextKeep = TRUE; | |
} | |
if (bNextKeep && !bCanSplite) { | |
if (!m_bIsProcessKeep && !m_bKeepBreakFinish) { | |
m_pKeepHeadNode = pNextContainer; | |
m_bIsProcessKeep = TRUE; | |
} | |
} else { | |
if (m_bIsProcessKeep && m_pKeepHeadNode != NULL) { | |
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 = NULL; | |
m_pKeepTailNode = NULL; | |
m_bIsProcessKeep = FALSE; | |
} | |
} else { | |
if (m_bKeepBreakFinish) { | |
bLastKeepNode = TRUE; | |
} | |
m_bKeepBreakFinish = FALSE; | |
} | |
} | |
return FALSE; | |
} | |
FX_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 = NULL; | |
m_pKeepTailNode = NULL; | |
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; | |
} | |
FX_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, | |
FX_BOOL& bContainerWidthAutoSize, | |
FX_BOOL& bContainerHeightAutoSize) { | |
fContainerWidth = 0; | |
fContainerHeight = 0; | |
bContainerWidthAutoSize = TRUE; | |
bContainerHeightAutoSize = TRUE; | |
XFA_ELEMENT eClassID = pFormNode->GetClassID(); | |
CXFA_Measurement mTmpValue; | |
if (bContainerWidthAutoSize && | |
(eClassID == XFA_ELEMENT_Subform || eClassID == 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 && | |
(eClassID == XFA_ELEMENT_Subform || eClassID == 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 && eClassID == 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 && eClassID == 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, | |
FX_BOOL bContainerWidthAutoSize, | |
FX_FLOAT fContentCalculatedWidth, | |
FX_FLOAT& fContainerWidth, | |
FX_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; | |
} | |
} | |
FX_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 = NULL; | |
for (XFA_ItemLayoutProcessor_GotoNextContainerNode( | |
pCurChildNode, nCurChildNodeStage, pFormNode, FALSE); | |
pCurChildNode; XFA_ItemLayoutProcessor_GotoNextContainerNode( | |
pCurChildNode, nCurChildNodeStage, pFormNode, FALSE)) { | |
if (nCurChildNodeStage != XFA_ItemLayoutProcessorStages_Container) { | |
continue; | |
} | |
if (pCurChildNode->GetClassID() == XFA_ELEMENT_Variables) { | |
continue; | |
} | |
CXFA_ItemLayoutProcessor* pProcessor = | |
new CXFA_ItemLayoutProcessor(pCurChildNode, NULL); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
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 == NULL) { | |
pPageAreaLayoutItem->AddHeadChild(pProcessItem); | |
} else { | |
pPageAreaLayoutItem->InsertChild(pBeforeItem, pProcessItem); | |
} | |
pBeforeItem = pProcessItem; | |
delete pProcessor; | |
} | |
pBeforeItem = NULL; | |
CXFA_LayoutItem* pLayoutItem = pPageAreaLayoutItem->m_pFirstChild; | |
while (pLayoutItem) { | |
if (!pLayoutItem->IsContentLayoutItem() || | |
pLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_Draw) { | |
pLayoutItem = pLayoutItem->m_pNextSibling; | |
continue; | |
} | |
if (pLayoutItem->m_pFormNode->GetClassID() == XFA_ELEMENT_Draw) { | |
CXFA_LayoutItem* pNextLayoutItem = pLayoutItem->m_pNextSibling; | |
pPageAreaLayoutItem->RemoveChild(pLayoutItem); | |
if (pBeforeItem == NULL) { | |
pPageAreaLayoutItem->AddHeadChild(pLayoutItem); | |
} else { | |
pPageAreaLayoutItem->InsertChild(pBeforeItem, pLayoutItem); | |
} | |
pBeforeItem = pLayoutItem; | |
pLayoutItem = pNextLayoutItem; | |
} | |
} | |
} | |
void CXFA_ItemLayoutProcessor::DoLayoutPositionedContainer( | |
CXFA_LayoutContext* pContext) { | |
if (m_pLayoutItem != NULL) { | |
return; | |
} | |
m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); | |
FX_BOOL bIgnoreXY = (m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout) != | |
XFA_ATTRIBUTEENUM_Position); | |
FX_FLOAT fContainerWidth = 0, fContainerHeight = 0; | |
FX_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->GetClassID() == XFA_ELEMENT_Variables) { | |
continue; | |
} | |
CXFA_ItemLayoutProcessor* pProcessor = | |
new CXFA_ItemLayoutProcessor(m_pCurChildNode, m_pPageMgr); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
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; i < iColSpan; i++) { | |
pContext->m_fCurColumnWidth += | |
pContext->m_prgSpecifiedColumnWidths->GetAt(iColIndex + i); | |
} | |
if (pContext->m_fCurColumnWidth == 0) { | |
pContext->m_bCurColumnWidthAvaiable = FALSE; | |
} | |
iColIndex += iColSpan; | |
} | |
} | |
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); | |
FX_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->GetClassID() != 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->GetClassID() != 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); | |
XFA_ELEMENT eClassID = pNode->GetClassID(); | |
switch (eClassID) { | |
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()->GetParser()->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; | |
FX_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; | |
FX_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.Set(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.Set(fContainerWidth, fContainerHeight); | |
} | |
void CXFA_ItemLayoutProcessor::DoLayoutTableContainer(CXFA_Node* pLayoutNode) { | |
if (m_pLayoutItem != NULL) { | |
return; | |
} | |
if (pLayoutNode == NULL) { | |
pLayoutNode = m_pFormNode; | |
} | |
ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); | |
m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); | |
FX_FLOAT fContainerWidth = 0, fContainerHeight = 0; | |
FX_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, 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; | |
CFX_WideStringC wsColumnWidths; | |
if (pLayoutNode->TryCData(XFA_ATTRIBUTE_ColumnWidths, wsColumnWidths)) { | |
CFX_WideStringArray widths; | |
if (FX_SeparateStringW(wsColumnWidths.GetPtr(), wsColumnWidths.GetLength(), | |
L' ', widths) > 0) { | |
int32_t iCols = widths.GetSize(); | |
CFX_WideString wsWidth; | |
for (int32_t i = 0; i < iCols; i++) { | |
wsWidth = widths[i]; | |
wsWidth.TrimLeft(L' '); | |
if (!wsWidth.IsEmpty()) { | |
CXFA_Measurement measure(wsWidth); | |
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 : NULL; | |
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); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
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->GetClassID() != 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; | |
FX_BOOL bMoreColumns = TRUE; | |
while (bMoreColumns) { | |
bMoreColumns = FALSE; | |
FX_BOOL bAutoCol = FALSE; | |
for (int32_t i = 0; i < iRowCount; i++) { | |
while (rgRowItems[i] != NULL && (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 = NULL; | |
} | |
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 = 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->GetClassID() == 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; | |
} | |
} | |
FX_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, | |
FX_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, 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 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, | |
FX_BOOL bBreakPending) { | |
pProcessor->m_rgPendingNodes.AddTail(pPendingNode); | |
pProcessor->m_bBreakPending = bBreakPending; | |
} | |
static FX_FLOAT XFA_ItemLayoutProcessor_InsertPendingItems( | |
CXFA_ItemLayoutProcessor* pProcessor, | |
CXFA_Node* pCurChildNode) { | |
FX_FLOAT fTotalHeight = 0; | |
if (pProcessor->m_rgPendingNodes.GetCount() < 1) { | |
return fTotalHeight; | |
} | |
if (pProcessor->m_pLayoutItem == NULL) { | |
pProcessor->m_pLayoutItem = | |
pProcessor->CreateContentLayoutItem(pCurChildNode); | |
pProcessor->m_pLayoutItem->m_sSize.Set(0, 0); | |
} | |
while (pProcessor->m_rgPendingNodes.GetCount() > 0) { | |
FX_POSITION pos = pProcessor->m_rgPendingNodes.GetHeadPosition(); | |
CXFA_Node* pPendingNode = | |
(CXFA_Node*)pProcessor->m_rgPendingNodes.GetAt(pos); | |
pProcessor->m_rgPendingNodes.RemoveAt(pos); | |
CXFA_ContentLayoutItem* pPendingLayoutItem = NULL; | |
CXFA_ItemLayoutProcessor* pPendingProcessor = | |
new CXFA_ItemLayoutProcessor(pPendingNode, NULL); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pPendingProcessor->m_pPageMgrCreateItem = pProcessor->m_pPageMgrCreateItem; | |
#endif | |
pPendingProcessor->DoLayout(FALSE, XFA_LAYOUT_FLOAT_MAX); | |
pPendingLayoutItem = pPendingProcessor->HasLayoutItem() | |
? pPendingProcessor->ExtractLayoutItem() | |
: NULL; | |
delete pPendingProcessor; | |
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 == NULL) { | |
m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); | |
m_pLayoutItem->m_sSize.Set(0, 0); | |
} | |
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; | |
} | |
FX_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, | |
FX_BOOL& bAddedItemInRow, | |
FX_BOOL& bForceEndPage, | |
XFA_ItemLayoutProcessorResult& result) { | |
if (pParentProcessor == NULL || pChildProcessor == NULL) { | |
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; | |
} | |
FX_BOOL CXFA_ItemLayoutProcessor::JudgePutNextPage( | |
CXFA_ContentLayoutItem* pParentLayoutItem, | |
FX_FLOAT fChildHeight, | |
CFX_ArrayTemplate<CXFA_ContentLayoutItem*>& pKeepItems) { | |
if (pParentLayoutItem == NULL) { | |
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, NULL); | |
} | |
} | |
pNode->SetFlag(XFA_NODEFLAG_UnusedNode); | |
} | |
} | |
void CXFA_ItemLayoutProcessor::ProcessUnUseOverFlow( | |
CXFA_Node* pLeaderNode, | |
CXFA_Node* pTrailerNode, | |
CXFA_ContentLayoutItem* pTrailerItem, | |
CXFA_Node* pFormNode) { | |
ProcessUnUseBinds(pLeaderNode); | |
ProcessUnUseBinds(pTrailerNode); | |
if (pFormNode == NULL) { | |
return; | |
} | |
if (pFormNode->GetClassID() == XFA_ELEMENT_Overflow || | |
pFormNode->GetClassID() == 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, | |
FX_BOOL bContainerWidthAutoSize, | |
FX_BOOL bContainerHeightAutoSize, | |
FX_FLOAT fContainerHeight, | |
XFA_ATTRIBUTEENUM eFlowStrategy, | |
uint8_t& uCurHAlignState, | |
CFX_ArrayTemplate<CXFA_ContentLayoutItem*>(&rgCurLineLayoutItems)[3], | |
FX_BOOL bUseBreakControl, | |
FX_FLOAT fAvailHeight, | |
FX_FLOAT fRealHeight, | |
FX_FLOAT& fContentCurRowY, | |
FX_FLOAT& fContentWidthLimit, | |
FX_FLOAT& fContentCurRowAvailWidth, | |
FX_FLOAT& fContentCurRowHeight, | |
FX_BOOL& bAddedItemInRow, | |
FX_BOOL& bForceEndPage, | |
CXFA_LayoutContext* pLayoutContext = NULL, | |
FX_BOOL bNewRow = FALSE) { | |
FX_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; | |
FX_BOOL bIsOwnSplite = | |
pProcessor->m_pFormNode->GetIntact() == XFA_ATTRIBUTEENUM_None; | |
FX_BOOL bUseRealHeight = | |
bTakeSpace && bContainerHeightAutoSize && bIsOwnSplite && | |
pProcessor->m_pFormNode->GetNodeItem(XFA_NODEITEM_Parent)->GetIntact() == | |
XFA_ATTRIBUTEENUM_None; | |
FX_BOOL bIsTransHeight = bTakeSpace; | |
if (bIsTransHeight && !bIsOwnSplite) { | |
FX_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; | |
} | |
} | |
FX_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 = NULL, *pOverflowTrailerNode = NULL, | |
*pFormNode = NULL; | |
CXFA_ContentLayoutItem* pTrailerLayoutItem = NULL; | |
FX_BOOL bIsAddTrailerHeight = FALSE; | |
if (pThis->m_pPageMgr && | |
pProcessor->m_pFormNode->GetIntact() == XFA_ATTRIBUTEENUM_None) { | |
pFormNode = pThis->m_pPageMgr->QueryOverflow(pProcessor->m_pFormNode); | |
if (pFormNode == NULL && 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, NULL); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pOverflowLeaderProcessor->m_pPageMgrCreateItem = | |
pProcessor->m_pPageMgrCreateItem; | |
#endif | |
pOverflowLeaderProcessor->DoLayout(FALSE, XFA_LAYOUT_FLOAT_MAX); | |
pTrailerLayoutItem = | |
pOverflowLeaderProcessor->HasLayoutItem() | |
? pOverflowLeaderProcessor->ExtractLayoutItem() | |
: NULL; | |
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 = NULL, *pTempTrailerNode = NULL; | |
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 { | |
if (pProcessor->m_pLayoutItem->m_pFirstChild && | |
pProcessor->m_pLayoutItem->m_pFirstChild->m_pNextSibling == | |
NULL && | |
pProcessor->m_pLayoutItem->m_pFirstChild->m_pFormNode->HasFlag( | |
XFA_NODEFLAG_LayoutGeneratedNode)) { | |
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 = NULL, *pTempTrailerNode = NULL; | |
if (pThis->m_pPageMgr) { | |
if (pFormNode == NULL && pLayoutContext != NULL) { | |
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 == NULL && pLayoutContext != NULL) { | |
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( | |
FX_BOOL bUseBreakControl, | |
XFA_ATTRIBUTEENUM eFlowStrategy, | |
FX_FLOAT fHeightLimit, | |
FX_FLOAT fRealHeight, | |
CXFA_LayoutContext* pContext, | |
FX_BOOL bRootForceTb) { | |
m_bHasAvailHeight = TRUE; | |
FX_FLOAT fContainerWidth = 0, fContainerHeight = 0; | |
FX_BOOL bBreakDone = FALSE; | |
FX_BOOL bContainerWidthAutoSize = TRUE, bContainerHeightAutoSize = TRUE; | |
FX_BOOL bForceEndPage = FALSE; | |
FX_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); | |
FX_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 = NULL; | |
if (m_pLayoutItem != NULL) { | |
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 == NULL && 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 = NULL; | |
} 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 = NULL; | |
break; | |
} | |
} | |
} | |
CXFA_ContentLayoutItem* pLayoutNextTemp = | |
(CXFA_ContentLayoutItem*)pLayoutChild; | |
while (pLayoutNextTemp) { | |
pLayoutNextTemp->m_pParent = NULL; | |
CXFA_ContentLayoutItem* pSaveLayoutNext = | |
(CXFA_ContentLayoutItem*)pLayoutNextTemp->m_pNextSibling; | |
pLayoutNextTemp->m_pNextSibling = NULL; | |
pLayoutNextTemp = pSaveLayoutNext; | |
} | |
pLayoutChild = NULL; | |
} | |
while (m_pCurChildNode) { | |
CXFA_ItemLayoutProcessor* pProcessor = NULL; | |
FX_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 = NULL, *pTrailerNode = NULL; | |
FX_BOOL bCreatePage = FALSE; | |
if (bUseBreakControl && m_pPageMgr && | |
m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, TRUE, | |
pLeaderNode, pTrailerNode, | |
bCreatePage) && | |
m_pFormNode->GetClassID() != XFA_ELEMENT_Form && bCreatePage) { | |
if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { | |
XFA_ItemLayoutProcessor_AddPendingNode(this, pLeaderNode, TRUE); | |
} | |
if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { | |
if (m_pFormNode->GetNodeItem(XFA_NODEITEM_Parent)->GetClassID() == | |
XFA_ELEMENT_Form && | |
m_pLayoutItem == NULL) { | |
XFA_ItemLayoutProcessor_AddPendingNode(this, pTrailerNode, | |
TRUE); | |
} else { | |
CXFA_ItemLayoutProcessor* pProcessor = | |
new CXFA_ItemLayoutProcessor(pTrailerNode, NULL); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
XFA_ItemLayoutProcessor_InsertFlowedItem( | |
this, pProcessor, bContainerWidthAutoSize, | |
bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, | |
uCurHAlignState, rgCurLineLayoutItems, FALSE, | |
XFA_LAYOUT_FLOAT_MAX, XFA_LAYOUT_FLOAT_MAX, fContentCurRowY, | |
fContentWidthLimit, fContentCurRowAvailWidth, | |
fContentCurRowHeight, bAddedItemInRow, bForceEndPage, | |
pContext); | |
delete pProcessor; | |
pProcessor = NULL; | |
} | |
} | |
XFA_ItemLayoutProcessor_GotoNextContainerNode( | |
m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, TRUE); | |
bForceEndPage = TRUE; | |
bIsManualBreak = TRUE; | |
goto SuspendAndCreateNewRow; | |
} | |
} break; | |
case XFA_ItemLayoutProcessorStages_BreakAfter: { | |
XFA_ItemLayoutProcessorResult eResult; | |
CXFA_Node *pLeaderNode = NULL, *pTrailerNode = NULL; | |
FX_BOOL bCreatePage = FALSE; | |
if (bUseBreakControl && m_pPageMgr && | |
m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, FALSE, | |
pLeaderNode, pTrailerNode, | |
bCreatePage) && | |
m_pFormNode->GetClassID() != XFA_ELEMENT_Form) { | |
if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { | |
CXFA_ItemLayoutProcessor* pProcessor = | |
new CXFA_ItemLayoutProcessor(pTrailerNode, NULL); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
eResult = XFA_ItemLayoutProcessor_InsertFlowedItem( | |
this, pProcessor, bContainerWidthAutoSize, | |
bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, | |
uCurHAlignState, rgCurLineLayoutItems, FALSE, | |
XFA_LAYOUT_FLOAT_MAX, XFA_LAYOUT_FLOAT_MAX, fContentCurRowY, | |
fContentWidthLimit, fContentCurRowAvailWidth, | |
fContentCurRowHeight, bAddedItemInRow, bForceEndPage, | |
pContext); | |
delete pProcessor; | |
pProcessor = NULL; | |
} | |
if (!bCreatePage) { | |
if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { | |
CalculateRowChildPosition( | |
rgCurLineLayoutItems, eFlowStrategy, | |
bContainerHeightAutoSize, bContainerWidthAutoSize, | |
fContentCalculatedWidth, fContentCalculatedHeight, | |
fContentCurRowY, fContentCurRowHeight, fContentWidthLimit); | |
rgCurLineLayoutItems->RemoveAll(); | |
CXFA_ItemLayoutProcessor* pProcessor = | |
new CXFA_ItemLayoutProcessor(pLeaderNode, NULL); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
XFA_ItemLayoutProcessor_InsertFlowedItem( | |
this, pProcessor, bContainerWidthAutoSize, | |
bContainerHeightAutoSize, fContainerHeight, eFlowStrategy, | |
uCurHAlignState, rgCurLineLayoutItems, FALSE, | |
XFA_LAYOUT_FLOAT_MAX, XFA_LAYOUT_FLOAT_MAX, fContentCurRowY, | |
fContentWidthLimit, fContentCurRowAvailWidth, | |
fContentCurRowHeight, bAddedItemInRow, bForceEndPage, | |
pContext); | |
delete pProcessor; | |
pProcessor = NULL; | |
} | |
} 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 = NULL; | |
if (m_pCurChildPreprocessor) { | |
pProcessor = m_pCurChildPreprocessor; | |
m_pCurChildPreprocessor = NULL; | |
} else if (m_pPageMgr && | |
m_pPageMgr->ProcessBookendLeaderOrTrailer( | |
m_pCurChildNode, TRUE, pLeaderNode)) { | |
pProcessor = new CXFA_ItemLayoutProcessor(pLeaderNode, m_pPageMgr); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
} | |
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 = NULL; | |
} | |
} | |
} break; | |
case XFA_ItemLayoutProcessorStages_BookendTrailer: { | |
CXFA_Node* pTrailerNode = NULL; | |
if (m_pCurChildPreprocessor) { | |
pProcessor = m_pCurChildPreprocessor; | |
m_pCurChildPreprocessor = NULL; | |
} else if (m_pPageMgr && | |
m_pPageMgr->ProcessBookendLeaderOrTrailer( | |
m_pCurChildNode, FALSE, pTrailerNode)) { | |
pProcessor = new CXFA_ItemLayoutProcessor(pTrailerNode, m_pPageMgr); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
} | |
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 = NULL; | |
} | |
} | |
} break; | |
case XFA_ItemLayoutProcessorStages_Container: | |
ASSERT(m_pCurChildNode->IsContainerNode()); | |
if (m_pCurChildNode->GetClassID() == XFA_ELEMENT_Variables) { | |
break; | |
} | |
if (fContentCurRowY >= fHeightLimit + XFA_LAYOUT_FLOAT_PERCISION && | |
XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) { | |
bForceEndPage = TRUE; | |
goto SuspendAndCreateNewRow; | |
} | |
if (m_pCurChildNode->IsContainerNode()) { | |
FX_BOOL bNewRow = FALSE; | |
if (m_pCurChildPreprocessor) { | |
pProcessor = m_pCurChildPreprocessor; | |
m_pCurChildPreprocessor = NULL; | |
bNewRow = TRUE; | |
} else { | |
pProcessor = | |
new CXFA_ItemLayoutProcessor(m_pCurChildNode, m_pPageMgr); | |
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_ | |
pProcessor->m_pPageMgrCreateItem = m_pPageMgrCreateItem; | |
#endif | |
} | |
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 = NULL; | |
} | |
} | |
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; | |
} | |
} | |
FX_BOOL bRetValue = | |
(m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages_Done && | |
m_rgPendingNodes.GetCount() == 0); | |
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 == NULL) { | |
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); | |
} | |
FX_BOOL CXFA_ItemLayoutProcessor::CalculateRowChildPosition( | |
CFX_ArrayTemplate<CXFA_ContentLayoutItem*>(&rgCurLineLayoutItems)[3], | |
XFA_ATTRIBUTEENUM eFlowStrategy, | |
FX_BOOL bContainerHeightAutoSize, | |
FX_BOOL bContainerWidthAutoSize, | |
FX_FLOAT& fContentCalculatedWidth, | |
FX_FLOAT& fContentCalculatedHeight, | |
FX_FLOAT& fContentCurRowY, | |
FX_FLOAT fContentCurRowHeight, | |
FX_FLOAT fContentWidthLimit, | |
FX_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 == NULL) { | |
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.Set(fAbsoluteX, fAbsoluteY); | |
} else { | |
rgCurLineLayoutItems[0][j]->m_sPos.Set(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.Set(fAbsoluteX, fAbsoluteY); | |
} else { | |
rgCurLineLayoutItems[1][j]->m_sPos.Set(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.Set(fAbsoluteX, fAbsoluteY); | |
} else { | |
rgCurLineLayoutItems[2][j]->m_sPos.Set(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.Set(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.Set(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.Set(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->GetClassID() == XFA_ELEMENT_SubformSet) { | |
CXFA_Node* pParent = pSubformSet->GetNodeItem(XFA_NODEITEM_Parent); | |
while (pParent) { | |
if (pParent->GetClassID() != XFA_ELEMENT_SubformSet) { | |
return pParent; | |
} | |
pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent); | |
} | |
} | |
return pSubformSet; | |
} | |
void CXFA_ItemLayoutProcessor::DoLayoutField() { | |
if (m_pLayoutItem != NULL) { | |
return; | |
} | |
ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); | |
m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); | |
if (!m_pLayoutItem) { | |
return; | |
} | |
CXFA_Document* pDocument = m_pFormNode->GetDocument(); | |
IXFA_Notify* pNotify = pDocument->GetParser()->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( | |
FX_BOOL bUseBreakControl, | |
FX_FLOAT fHeightLimit, | |
FX_FLOAT fRealHeight, | |
CXFA_LayoutContext* pContext) { | |
XFA_ELEMENT eClassID = m_pFormNode->GetClassID(); | |
switch (eClassID) { | |
case XFA_ELEMENT_Subform: | |
case XFA_ELEMENT_Area: | |
case XFA_ELEMENT_ExclGroup: | |
case XFA_ELEMENT_SubformSet: { | |
FX_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) { | |
ASSERT(m_pLayoutItem); | |
m_pLayoutItem->m_sPos.Set(fAbsoluteX, fAbsoluteY); | |
} | |
void CXFA_ItemLayoutProcessor::SetCurrentComponentSize(FX_FLOAT fWidth, | |
FX_FLOAT fHeight) { | |
ASSERT(m_pLayoutItem); | |
m_pLayoutItem->m_sSize.Set(fWidth, fHeight); | |
} | |
FX_BOOL CXFA_ItemLayoutProcessor::JudgeLeaderOrTrailerForOccur( | |
CXFA_Node* pFormNode) { | |
if (pFormNode == NULL) { | |
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 > -1) { | |
int32_t iCount = | |
(int32_t)(uintptr_t)m_PendingNodesCount.GetValueAt(pTemplate); | |
if (iCount >= iMax) { | |
return FALSE; | |
} | |
iCount++; | |
m_PendingNodesCount.SetAt(pTemplate, (void*)(uintptr_t)(iCount)); | |
return TRUE; | |
} | |
return TRUE; | |
} |