Home | History | Annotate | Download | only in parser
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "xfa/src/foxitlib.h"
      8 #include "xfa/src/fxfa/src/common/xfa_utils.h"
      9 #include "xfa/src/fxfa/src/common/xfa_object.h"
     10 #include "xfa/src/fxfa/src/common/xfa_document.h"
     11 #include "xfa/src/fxfa/src/common/xfa_parser.h"
     12 #include "xfa/src/fxfa/src/common/xfa_script.h"
     13 #include "xfa/src/fxfa/src/common/xfa_docdata.h"
     14 #include "xfa/src/fxfa/src/common/xfa_doclayout.h"
     15 #include "xfa/src/fxfa/src/common/xfa_localemgr.h"
     16 #include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h"
     17 #include "xfa_document_datamerger_imp.h"
     18 #include "xfa_document_layout_imp.h"
     19 #include "xfa_layout_itemlayout.h"
     20 #include "xfa_layout_pagemgr_new.h"
     21 #include "xfa_layout_appadapter.h"
     22 CXFA_LayoutPageMgr::CXFA_LayoutPageMgr(CXFA_LayoutProcessor* pLayoutProcessor)
     23     : m_pLayoutProcessor(pLayoutProcessor),
     24       m_pTemplatePageSetRoot(nullptr),
     25       m_pPageSetLayoutItemRoot(nullptr),
     26       m_pPageSetCurRoot(nullptr),
     27       m_pCurrentContainerRecord(nullptr),
     28       m_pCurPageArea(nullptr),
     29       m_nAvailPages(0),
     30       m_nCurPageCount(0),
     31       m_ePageSetMode(XFA_ATTRIBUTEENUM_OrderedOccurrence),
     32       m_bCreateOverFlowPage(FALSE) {
     33 }
     34 CXFA_LayoutPageMgr::~CXFA_LayoutPageMgr() {
     35   ClearData();
     36   CXFA_LayoutItem* pLayoutItem = GetRootLayoutItem();
     37   CXFA_LayoutItem* pNextLayout = NULL;
     38   for (; pLayoutItem; pLayoutItem = pNextLayout) {
     39     pNextLayout = pLayoutItem->m_pNextSibling;
     40     XFA_ReleaseLayoutItem(pLayoutItem);
     41   }
     42 }
     43 FX_BOOL CXFA_LayoutPageMgr::InitLayoutPage(CXFA_Node* pFormNode) {
     44   PrepareLayout();
     45   CXFA_Node* pTemplateNode = pFormNode->GetTemplateNode();
     46   if (!pTemplateNode) {
     47     return FALSE;
     48   }
     49   m_pTemplatePageSetRoot = pTemplateNode->GetProperty(0, XFA_ELEMENT_PageSet);
     50   ASSERT(m_pTemplatePageSetRoot);
     51   if (m_pPageSetLayoutItemRoot) {
     52     m_pPageSetLayoutItemRoot->m_pParent = NULL;
     53     m_pPageSetLayoutItemRoot->m_pFirstChild = NULL;
     54     m_pPageSetLayoutItemRoot->m_pNextSibling = NULL;
     55     m_pPageSetLayoutItemRoot->m_pFormNode = m_pTemplatePageSetRoot;
     56   } else {
     57     m_pPageSetLayoutItemRoot =
     58         new CXFA_ContainerLayoutItem(m_pTemplatePageSetRoot);
     59   }
     60   m_pPageSetCurRoot = m_pPageSetLayoutItemRoot;
     61   m_pTemplatePageSetRoot->SetUserData(XFA_LAYOUTITEMKEY,
     62                                       (void*)m_pPageSetLayoutItemRoot);
     63   XFA_ATTRIBUTEENUM eRelation =
     64       m_pTemplatePageSetRoot->GetEnum(XFA_ATTRIBUTE_Relation);
     65   if (eRelation != XFA_ATTRIBUTEENUM_Unknown) {
     66     m_ePageSetMode = eRelation;
     67   }
     68   InitPageSetMap();
     69   CXFA_Node* pPageArea = NULL;
     70   int32_t iCount = 0;
     71   for (pPageArea = m_pTemplatePageSetRoot->GetNodeItem(XFA_NODEITEM_FirstChild);
     72        pPageArea;
     73        pPageArea = pPageArea->GetNodeItem(XFA_NODEITEM_NextSibling)) {
     74     if (pPageArea->GetClassID() == XFA_ELEMENT_PageArea) {
     75       iCount++;
     76       if (pPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea)) {
     77         return TRUE;
     78       }
     79     }
     80   }
     81   if (iCount > 0) {
     82     return FALSE;
     83   }
     84   CXFA_Document* pDocument = pTemplateNode->GetDocument();
     85   IXFA_ObjFactory* pObjFactory = pDocument->GetParser()->GetFactory();
     86   pPageArea = m_pTemplatePageSetRoot->GetChild(0, XFA_ELEMENT_PageArea);
     87   if (!pPageArea) {
     88     pPageArea = pObjFactory->CreateNode(m_pTemplatePageSetRoot->GetPacketID(),
     89                                         XFA_ELEMENT_PageArea);
     90     if (!pPageArea) {
     91       return FALSE;
     92     }
     93     m_pTemplatePageSetRoot->InsertChild(pPageArea, NULL);
     94     pPageArea->SetFlag(XFA_NODEFLAG_Initialized);
     95   }
     96   CXFA_Node* pContentArea = pPageArea->GetChild(0, XFA_ELEMENT_ContentArea);
     97   if (!pContentArea) {
     98     pContentArea = pObjFactory->CreateNode(pPageArea->GetPacketID(),
     99                                            XFA_ELEMENT_ContentArea);
    100     if (!pContentArea) {
    101       return FALSE;
    102     }
    103     pPageArea->InsertChild(pContentArea, NULL);
    104     pContentArea->SetFlag(XFA_NODEFLAG_Initialized);
    105     pContentArea->SetMeasure(XFA_ATTRIBUTE_X,
    106                              CXFA_Measurement(0.25f, XFA_UNIT_In));
    107     pContentArea->SetMeasure(XFA_ATTRIBUTE_Y,
    108                              CXFA_Measurement(0.25f, XFA_UNIT_In));
    109     pContentArea->SetMeasure(XFA_ATTRIBUTE_W,
    110                              CXFA_Measurement(8.0f, XFA_UNIT_In));
    111     pContentArea->SetMeasure(XFA_ATTRIBUTE_H,
    112                              CXFA_Measurement(10.5f, XFA_UNIT_In));
    113   }
    114   CXFA_Node* pMedium = pPageArea->GetChild(0, XFA_ELEMENT_Medium);
    115   if (!pMedium) {
    116     pMedium =
    117         pObjFactory->CreateNode(pPageArea->GetPacketID(), XFA_ELEMENT_Medium);
    118     if (!pContentArea) {
    119       return FALSE;
    120     }
    121     pPageArea->InsertChild(pMedium, NULL);
    122     pMedium->SetFlag(XFA_NODEFLAG_Initialized);
    123     pMedium->SetMeasure(XFA_ATTRIBUTE_Short,
    124                         CXFA_Measurement(8.5f, XFA_UNIT_In));
    125     pMedium->SetMeasure(XFA_ATTRIBUTE_Long,
    126                         CXFA_Measurement(11.0f, XFA_UNIT_In));
    127   }
    128   return TRUE;
    129 }
    130 FX_BOOL CXFA_LayoutPageMgr::PrepareFirstPage(CXFA_Node* pRootSubform) {
    131   FX_BOOL bProBreakBefore = FALSE;
    132   CXFA_Node* pBreakBeforeNode = NULL;
    133   while (pRootSubform) {
    134     for (CXFA_Node* pBreakNode =
    135              pRootSubform->GetNodeItem(XFA_NODEITEM_FirstChild);
    136          pBreakNode;
    137          pBreakNode = pBreakNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
    138       XFA_ELEMENT eType = pBreakNode->GetClassID();
    139       if (eType == XFA_ELEMENT_BreakBefore ||
    140           (eType == XFA_ELEMENT_Break &&
    141            pBreakNode->GetEnum(XFA_ATTRIBUTE_Before) !=
    142                XFA_ATTRIBUTEENUM_Auto)) {
    143         bProBreakBefore = TRUE;
    144         pBreakBeforeNode = pBreakNode;
    145         break;
    146       }
    147     }
    148     if (bProBreakBefore) {
    149       break;
    150     }
    151     bProBreakBefore = TRUE;
    152     pRootSubform = pRootSubform->GetFirstChildByClass(XFA_ELEMENT_Subform);
    153     while (pRootSubform &&
    154            !XFA_ItemLayoutProcessor_IsTakingSpace(pRootSubform)) {
    155       pRootSubform = pRootSubform->GetNextSameClassSibling(XFA_ELEMENT_Subform);
    156     }
    157   }
    158   CXFA_Node *pLeader, *pTrailer;
    159   if (pBreakBeforeNode &&
    160       ExecuteBreakBeforeOrAfter(pBreakBeforeNode, TRUE, pLeader, pTrailer)) {
    161     m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetHeadPosition();
    162     return TRUE;
    163   }
    164   return AppendNewPage(TRUE);
    165 }
    166 FX_BOOL CXFA_LayoutPageMgr::AppendNewPage(FX_BOOL bFirstTemPage) {
    167   if (m_pCurrentContainerRecord !=
    168       m_rgProposedContainerRecord.GetTailPosition()) {
    169     return TRUE;
    170   }
    171   CXFA_Node* pPageNode = GetNextAvailPageArea(NULL);
    172   if (!pPageNode) {
    173     return FALSE;
    174   }
    175   if (bFirstTemPage && m_pCurrentContainerRecord == NULL) {
    176     m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetHeadPosition();
    177   }
    178   return !bFirstTemPage || m_pCurrentContainerRecord != NULL;
    179 }
    180 static void XFA_LayoutItemMgr_ReorderLayoutItemToTail(
    181     CXFA_ContainerLayoutItem* pLayoutItem) {
    182   CXFA_ContainerLayoutItem* pParentLayoutItem =
    183       (CXFA_ContainerLayoutItem*)pLayoutItem->m_pParent;
    184   if (!pParentLayoutItem) {
    185     return;
    186   }
    187   pParentLayoutItem->RemoveChild(pLayoutItem);
    188   pParentLayoutItem->AddChild(pLayoutItem);
    189 }
    190 static void XFA_LayoutItemMgr_RemoveLayoutItem(
    191     CXFA_ContainerLayoutItem* pLayoutItem) {
    192   CXFA_ContainerLayoutItem* pParentLayoutItem =
    193       (CXFA_ContainerLayoutItem*)pLayoutItem->m_pParent;
    194   if (!pParentLayoutItem) {
    195     return;
    196   }
    197   pParentLayoutItem->RemoveChild(pLayoutItem);
    198 }
    199 void CXFA_LayoutPageMgr::RemoveLayoutRecord(CXFA_ContainerRecord* pNewRecord,
    200                                             CXFA_ContainerRecord* pPrevRecord) {
    201   if (!pNewRecord || !pPrevRecord) {
    202     return;
    203   }
    204   if (pNewRecord->pCurPageSet != pPrevRecord->pCurPageSet) {
    205     XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurPageSet);
    206     return;
    207   }
    208   if (pNewRecord->pCurPageArea != pPrevRecord->pCurPageArea) {
    209     XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurPageArea);
    210     return;
    211   }
    212   if (pNewRecord->pCurContentArea != pPrevRecord->pCurContentArea) {
    213     XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurContentArea);
    214     return;
    215   }
    216 }
    217 void CXFA_LayoutPageMgr::ReorderPendingLayoutRecordToTail(
    218     CXFA_ContainerRecord* pNewRecord,
    219     CXFA_ContainerRecord* pPrevRecord) {
    220   if (!pNewRecord || !pPrevRecord) {
    221     return;
    222   }
    223   if (pNewRecord->pCurPageSet != pPrevRecord->pCurPageSet) {
    224     XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurPageSet);
    225     return;
    226   }
    227   if (pNewRecord->pCurPageArea != pPrevRecord->pCurPageArea) {
    228     XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurPageArea);
    229     return;
    230   }
    231   if (pNewRecord->pCurContentArea != pPrevRecord->pCurContentArea) {
    232     XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurContentArea);
    233     return;
    234   }
    235 }
    236 void CXFA_LayoutPageMgr::SubmitContentItem(
    237     CXFA_ContentLayoutItem* pContentLayoutItem,
    238     XFA_ItemLayoutProcessorResult eStatus) {
    239   if (pContentLayoutItem) {
    240     GetCurrentContainerRecord()->pCurContentArea->AddChild(pContentLayoutItem);
    241     m_bCreateOverFlowPage = FALSE;
    242   }
    243   if (eStatus != XFA_ItemLayoutProcessorResult_Done) {
    244     if (eStatus == XFA_ItemLayoutProcessorResult_PageFullBreak &&
    245         m_pCurrentContainerRecord ==
    246             m_rgProposedContainerRecord.GetTailPosition()) {
    247       AppendNewPage();
    248     }
    249     m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetTailPosition();
    250     m_pCurPageArea = GetCurrentContainerRecord()->pCurPageArea->m_pFormNode;
    251   }
    252 }
    253 FX_FLOAT CXFA_LayoutPageMgr::GetAvailHeight() {
    254   FX_FLOAT fAvailHeight =
    255       GetCurrentContainerRecord()
    256           ->pCurContentArea->m_pFormNode->GetMeasure(XFA_ATTRIBUTE_H)
    257           .ToUnit(XFA_UNIT_Pt);
    258   if (fAvailHeight < XFA_LAYOUT_FLOAT_PERCISION) {
    259     if (m_pCurrentContainerRecord ==
    260         m_rgProposedContainerRecord.GetHeadPosition()) {
    261       fAvailHeight = 0;
    262     } else {
    263       fAvailHeight = XFA_LAYOUT_FLOAT_MAX;
    264     }
    265   }
    266   return fAvailHeight;
    267 }
    268 static CXFA_Node* XFA_ResolveBreakTarget(CXFA_Node* pPageSetRoot,
    269                                          FX_BOOL bNewExprStyle,
    270                                          CFX_WideStringC& wsTargetExpr) {
    271   CXFA_Document* pDocument = pPageSetRoot->GetDocument();
    272   if (wsTargetExpr.IsEmpty()) {
    273     return NULL;
    274   }
    275   CFX_WideString wsTargetAll = wsTargetExpr;
    276   wsTargetAll.TrimLeft();
    277   wsTargetAll.TrimRight();
    278   int32_t iSpliteIndex = 0;
    279   FX_BOOL bTargetAllFind = TRUE;
    280   while (iSpliteIndex != -1) {
    281     CFX_WideString wsTargetExpr;
    282     int32_t iSpliteNextIndex = 0;
    283     if (!bTargetAllFind) {
    284       iSpliteNextIndex = wsTargetAll.Find(' ', iSpliteIndex);
    285       wsTargetExpr =
    286           wsTargetAll.Mid(iSpliteIndex, iSpliteNextIndex - iSpliteIndex);
    287     } else {
    288       wsTargetExpr = wsTargetAll;
    289     }
    290     if (wsTargetExpr.IsEmpty()) {
    291       return NULL;
    292     }
    293     bTargetAllFind = FALSE;
    294     if (wsTargetExpr.GetAt(0) == '#') {
    295       CXFA_Node* pNode = pDocument->GetNodeByID(
    296           (CXFA_Node*)pDocument->GetXFANode(XFA_HASHCODE_Template),
    297           wsTargetExpr.Mid(1));
    298       if (pNode) {
    299         return pNode;
    300       }
    301     } else if (bNewExprStyle) {
    302       CFX_WideString wsProcessedTarget = wsTargetExpr;
    303       if (wsTargetExpr.Left(4) == FX_WSTRC(L"som(") &&
    304           wsTargetExpr.Right(1) == FX_WSTRC(L")")) {
    305         wsProcessedTarget = wsTargetExpr.Mid(4, wsTargetExpr.GetLength() - 5);
    306       }
    307       XFA_RESOLVENODE_RS rs;
    308       int32_t iCount = pDocument->GetScriptContext()->ResolveObjects(
    309           pPageSetRoot, wsProcessedTarget, rs,
    310           XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
    311               XFA_RESOLVENODE_Attributes | XFA_RESOLVENODE_Siblings |
    312               XFA_RESOLVENODE_Parent);
    313       if (iCount > 0 && rs.nodes[0]->IsNode()) {
    314         return (CXFA_Node*)rs.nodes[0];
    315       }
    316     }
    317     iSpliteIndex = iSpliteNextIndex;
    318   }
    319   return NULL;
    320 }
    321 
    322 FX_BOOL XFA_LayoutPageMgr_RunBreakTestScript(CXFA_Node* pTestScript) {
    323   CFX_WideString wsExpression;
    324   pTestScript->TryContent(wsExpression);
    325   if (wsExpression.IsEmpty()) {
    326     return TRUE;
    327   }
    328   return pTestScript->GetDocument()->GetParser()->GetNotify()->RunScript(
    329       pTestScript, pTestScript->GetNodeItem(XFA_NODEITEM_Parent,
    330                                             XFA_OBJECTTYPE_ContainerNode));
    331 }
    332 CXFA_ContainerRecord* CXFA_LayoutPageMgr::CreateContainerRecord(
    333     CXFA_Node* pPageNode,
    334     FX_BOOL bCreateNew) {
    335   CXFA_ContainerRecord* pNewRecord = new CXFA_ContainerRecord();
    336   if (m_pCurrentContainerRecord) {
    337     if (!IsPageSetRootOrderedOccurrence() || pPageNode == NULL) {
    338       *pNewRecord = *GetCurrentContainerRecord();
    339       m_rgProposedContainerRecord.AddTail(pNewRecord);
    340       return pNewRecord;
    341     }
    342     CXFA_Node* pPageSet = pPageNode->GetNodeItem(XFA_NODEITEM_Parent);
    343     if (!bCreateNew) {
    344       if (pPageSet == m_pTemplatePageSetRoot) {
    345         pNewRecord->pCurPageSet = m_pPageSetCurRoot;
    346       } else {
    347         CXFA_ContainerLayoutItem* pParentLayoutItem =
    348             (CXFA_ContainerLayoutItem*)pPageSet->GetUserData(XFA_LAYOUTITEMKEY);
    349         if (pParentLayoutItem == NULL) {
    350           pParentLayoutItem = m_pPageSetCurRoot;
    351         }
    352         pNewRecord->pCurPageSet = pParentLayoutItem;
    353       }
    354     } else {
    355       CXFA_ContainerLayoutItem* pParentPageSetLayout = NULL;
    356       if (pPageSet == GetCurrentContainerRecord()->pCurPageSet->m_pFormNode) {
    357         pParentPageSetLayout =
    358             (CXFA_ContainerLayoutItem*)
    359                 GetCurrentContainerRecord()->pCurPageSet->m_pParent;
    360       } else {
    361         pParentPageSetLayout =
    362             (CXFA_ContainerLayoutItem*)pPageSet->GetNodeItem(
    363                                                      XFA_NODEITEM_Parent)
    364                 ->GetUserData(XFA_LAYOUTITEMKEY);
    365       }
    366       CXFA_ContainerLayoutItem* pPageSetLayoutItem =
    367           new CXFA_ContainerLayoutItem(pPageSet);
    368       pPageSet->SetUserData(XFA_LAYOUTITEMKEY, (void*)pPageSetLayoutItem);
    369       if (pParentPageSetLayout == NULL) {
    370         CXFA_ContainerLayoutItem* pPrePageSet = m_pPageSetLayoutItemRoot;
    371         while (pPrePageSet->m_pNextSibling) {
    372           pPrePageSet = (CXFA_ContainerLayoutItem*)pPrePageSet->m_pNextSibling;
    373         }
    374         pPrePageSet->m_pNextSibling = pPageSetLayoutItem;
    375         m_pPageSetCurRoot = pPageSetLayoutItem;
    376       } else {
    377         pParentPageSetLayout->AddChild(pPageSetLayoutItem);
    378       }
    379       pNewRecord->pCurPageSet = pPageSetLayoutItem;
    380     }
    381   } else {
    382     if (pPageNode) {
    383       CXFA_Node* pPageSet = pPageNode->GetNodeItem(XFA_NODEITEM_Parent);
    384       if (pPageSet == m_pTemplatePageSetRoot) {
    385         pNewRecord->pCurPageSet = m_pPageSetLayoutItemRoot;
    386       } else {
    387         CXFA_ContainerLayoutItem* pPageSetLayoutItem =
    388             new CXFA_ContainerLayoutItem(pPageSet);
    389         pPageSet->SetUserData(XFA_LAYOUTITEMKEY, (void*)pPageSetLayoutItem);
    390         m_pPageSetLayoutItemRoot->AddChild(pPageSetLayoutItem);
    391         pNewRecord->pCurPageSet = pPageSetLayoutItem;
    392       }
    393     } else {
    394       pNewRecord->pCurPageSet = m_pPageSetLayoutItemRoot;
    395     }
    396   }
    397   m_rgProposedContainerRecord.AddTail(pNewRecord);
    398   return pNewRecord;
    399 }
    400 void CXFA_LayoutPageMgr::AddPageAreaLayoutItem(CXFA_ContainerRecord* pNewRecord,
    401                                                CXFA_Node* pNewPageArea) {
    402   CXFA_ContainerLayoutItem* pNewPageAreaLayoutItem = NULL;
    403   if (m_PageArray.GetSize() > m_nAvailPages) {
    404     CXFA_ContainerLayoutItem* pContainerItem = m_PageArray[m_nAvailPages];
    405     pContainerItem->m_pFormNode = pNewPageArea;
    406     m_nAvailPages++;
    407     pNewPageAreaLayoutItem = pContainerItem;
    408   } else {
    409     IXFA_Notify* pNotify =
    410         pNewPageArea->GetDocument()->GetParser()->GetNotify();
    411     CXFA_ContainerLayoutItem* pContainerItem =
    412         (CXFA_ContainerLayoutItem*)pNotify->OnCreateLayoutItem(pNewPageArea);
    413     m_PageArray.Add(pContainerItem);
    414     m_nAvailPages++;
    415     pNotify->OnPageEvent(pContainerItem, XFA_PAGEEVENT_PageAdded,
    416                          (void*)(uintptr_t)m_nAvailPages);
    417     pNewPageAreaLayoutItem = pContainerItem;
    418   }
    419   pNewRecord->pCurPageSet->AddChild(pNewPageAreaLayoutItem);
    420   pNewRecord->pCurPageArea = pNewPageAreaLayoutItem;
    421   pNewRecord->pCurContentArea = NULL;
    422 }
    423 void CXFA_LayoutPageMgr::AddContentAreaLayoutItem(
    424     CXFA_ContainerRecord* pNewRecord,
    425     CXFA_Node* pContentArea) {
    426   if (pContentArea == NULL) {
    427     pNewRecord->pCurContentArea = NULL;
    428     return;
    429   }
    430   CXFA_ContainerLayoutItem* pNewContentAreaLayoutItem =
    431       new CXFA_ContainerLayoutItem(pContentArea);
    432   ASSERT(pNewRecord->pCurPageArea);
    433   pNewRecord->pCurPageArea->AddChild(pNewContentAreaLayoutItem);
    434   pNewRecord->pCurContentArea = pNewContentAreaLayoutItem;
    435 }
    436 class CXFA_TraverseStrategy_PageSetContainerLayoutItem {
    437  public:
    438   static inline CXFA_ContainerLayoutItem* GetFirstChild(
    439       CXFA_ContainerLayoutItem* pLayoutItem) {
    440     if (pLayoutItem->m_pFormNode->GetClassID() == XFA_ELEMENT_PageSet) {
    441       CXFA_ContainerLayoutItem* pChildItem =
    442           (CXFA_ContainerLayoutItem*)pLayoutItem->m_pFirstChild;
    443       while (pChildItem &&
    444              pChildItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageSet) {
    445         pChildItem = (CXFA_ContainerLayoutItem*)pChildItem->m_pNextSibling;
    446       }
    447       return pChildItem;
    448     }
    449     return NULL;
    450   }
    451   static inline CXFA_ContainerLayoutItem* GetNextSibling(
    452       CXFA_ContainerLayoutItem* pLayoutItem) {
    453     CXFA_ContainerLayoutItem* pChildItem =
    454         (CXFA_ContainerLayoutItem*)pLayoutItem->m_pNextSibling;
    455     while (pChildItem &&
    456            pChildItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageSet) {
    457       pChildItem = (CXFA_ContainerLayoutItem*)pChildItem->m_pNextSibling;
    458     }
    459     return pChildItem;
    460   }
    461   static inline CXFA_ContainerLayoutItem* GetParent(
    462       CXFA_ContainerLayoutItem* pLayoutItem) {
    463     return (CXFA_ContainerLayoutItem*)pLayoutItem->m_pParent;
    464   }
    465 };
    466 void CXFA_LayoutPageMgr::FinishPaginatedPageSets() {
    467   CXFA_ContainerLayoutItem* pRootPageSetLayoutItem = m_pPageSetLayoutItemRoot;
    468   for (; pRootPageSetLayoutItem;
    469        pRootPageSetLayoutItem =
    470            (CXFA_ContainerLayoutItem*)pRootPageSetLayoutItem->m_pNextSibling) {
    471     CXFA_NodeIteratorTemplate<CXFA_ContainerLayoutItem,
    472                               CXFA_TraverseStrategy_PageSetContainerLayoutItem>
    473         sIterator(pRootPageSetLayoutItem);
    474     for (CXFA_ContainerLayoutItem* pPageSetLayoutItem = sIterator.GetCurrent();
    475          pPageSetLayoutItem; pPageSetLayoutItem = sIterator.MoveToNext()) {
    476       XFA_ATTRIBUTEENUM ePageRelation =
    477           pPageSetLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Relation);
    478       switch (ePageRelation) {
    479         case XFA_ATTRIBUTEENUM_OrderedOccurrence:
    480         default: { ProcessLastPageSet(); } break;
    481         case XFA_ATTRIBUTEENUM_SimplexPaginated:
    482         case XFA_ATTRIBUTEENUM_DuplexPaginated: {
    483           CXFA_LayoutItem* pLastPageAreaLayoutItem = NULL;
    484           int32_t nPageAreaCount = 0;
    485           for (CXFA_LayoutItem* pPageAreaLayoutItem =
    486                    pPageSetLayoutItem->m_pFirstChild;
    487                pPageAreaLayoutItem;
    488                pPageAreaLayoutItem = pPageAreaLayoutItem->m_pNextSibling) {
    489             if (pPageAreaLayoutItem->m_pFormNode->GetClassID() !=
    490                 XFA_ELEMENT_PageArea) {
    491               continue;
    492             }
    493             nPageAreaCount++;
    494             pLastPageAreaLayoutItem = pPageAreaLayoutItem;
    495           }
    496           if (!pLastPageAreaLayoutItem) {
    497             break;
    498           }
    499           if (!FindPageAreaFromPageSet_SimplexDuplex(
    500                   pPageSetLayoutItem->m_pFormNode, NULL, NULL, NULL, TRUE, TRUE,
    501                   nPageAreaCount == 1 ? XFA_ATTRIBUTEENUM_Only
    502                                       : XFA_ATTRIBUTEENUM_Last) &&
    503               (nPageAreaCount == 1 &&
    504                !FindPageAreaFromPageSet_SimplexDuplex(
    505                    pPageSetLayoutItem->m_pFormNode, NULL, NULL, NULL, TRUE,
    506                    TRUE, XFA_ATTRIBUTEENUM_Last))) {
    507             break;
    508           }
    509           CXFA_Node* pNode = m_pCurPageArea;
    510           XFA_ATTRIBUTEENUM eCurChoice =
    511               pNode->GetEnum(XFA_ATTRIBUTE_PagePosition);
    512           if (eCurChoice == XFA_ATTRIBUTEENUM_Last) {
    513             XFA_ATTRIBUTEENUM eOddOrEven = XFA_ATTRIBUTEENUM_Any;
    514             pNode->TryEnum(XFA_ATTRIBUTE_OddOrEven, eOddOrEven);
    515             XFA_ATTRIBUTEENUM eLastChoice =
    516                 pLastPageAreaLayoutItem->m_pFormNode->GetEnum(
    517                     XFA_ATTRIBUTE_PagePosition);
    518             if (eLastChoice == XFA_ATTRIBUTEENUM_First &&
    519                 (ePageRelation == XFA_ATTRIBUTEENUM_SimplexPaginated ||
    520                  eOddOrEven != XFA_ATTRIBUTEENUM_Odd)) {
    521               CXFA_ContainerRecord* pRecord = CreateContainerRecord();
    522               AddPageAreaLayoutItem(pRecord, pNode);
    523               break;
    524               ;
    525             }
    526           }
    527           FX_BOOL bUsable = TRUE;
    528           CFX_ArrayTemplate<FX_FLOAT> rgUsedHeights;
    529           for (CXFA_LayoutItem* pChildLayoutItem =
    530                    pLastPageAreaLayoutItem->m_pFirstChild;
    531                pChildLayoutItem;
    532                pChildLayoutItem = pChildLayoutItem->m_pNextSibling) {
    533             if (pChildLayoutItem->m_pFormNode->GetClassID() !=
    534                 XFA_ELEMENT_ContentArea) {
    535               continue;
    536             }
    537             FX_FLOAT fUsedHeight = 0;
    538             for (CXFA_LayoutItem* pContentChildLayoutItem =
    539                      pChildLayoutItem->m_pFirstChild;
    540                  pContentChildLayoutItem;
    541                  pContentChildLayoutItem =
    542                      pContentChildLayoutItem->m_pNextSibling) {
    543               if (CXFA_ContentLayoutItem* pContent =
    544                       pContentChildLayoutItem->AsContentLayoutItem()) {
    545                 fUsedHeight += pContent->m_sSize.y;
    546               }
    547             }
    548             rgUsedHeights.Add(fUsedHeight);
    549           }
    550           int32_t iCurContentAreaIndex = -1;
    551           for (CXFA_Node* pContentAreaNode =
    552                    pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
    553                pContentAreaNode;
    554                pContentAreaNode =
    555                    pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
    556             if (pContentAreaNode->GetClassID() != XFA_ELEMENT_ContentArea) {
    557               continue;
    558             }
    559             iCurContentAreaIndex++;
    560             if (rgUsedHeights[iCurContentAreaIndex] >
    561                 pContentAreaNode->GetMeasure(XFA_ATTRIBUTE_H)
    562                         .ToUnit(XFA_UNIT_Pt) +
    563                     XFA_LAYOUT_FLOAT_PERCISION) {
    564               bUsable = FALSE;
    565               break;
    566             }
    567           }
    568           if (bUsable) {
    569             CXFA_LayoutItem* pChildLayoutItem =
    570                 pLastPageAreaLayoutItem->m_pFirstChild;
    571             CXFA_Node* pContentAreaNode =
    572                 pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
    573             pLastPageAreaLayoutItem->m_pFormNode = pNode;
    574             while (pChildLayoutItem && pContentAreaNode) {
    575               if (pChildLayoutItem->m_pFormNode->GetClassID() !=
    576                   XFA_ELEMENT_ContentArea) {
    577                 pChildLayoutItem = pChildLayoutItem->m_pNextSibling;
    578                 continue;
    579               }
    580               if (pContentAreaNode->GetClassID() != XFA_ELEMENT_ContentArea) {
    581                 pContentAreaNode =
    582                     pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling);
    583                 continue;
    584               }
    585               pChildLayoutItem->m_pFormNode = pContentAreaNode;
    586               pChildLayoutItem = pChildLayoutItem->m_pNextSibling;
    587               pContentAreaNode =
    588                   pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling);
    589             }
    590           } else if (pNode->GetEnum(XFA_ATTRIBUTE_PagePosition) ==
    591                      XFA_ATTRIBUTEENUM_Last) {
    592             CXFA_ContainerRecord* pRecord = CreateContainerRecord();
    593             AddPageAreaLayoutItem(pRecord, pNode);
    594           }
    595         } break;
    596       }
    597     }
    598   }
    599 }
    600 int32_t CXFA_LayoutPageMgr::GetPageCount() const {
    601   return m_PageArray.GetSize();
    602 }
    603 IXFA_LayoutPage* CXFA_LayoutPageMgr::GetPage(int32_t index) const {
    604   if (index < 0 || index >= m_PageArray.GetSize())
    605     return nullptr;
    606   return m_PageArray[index];
    607 }
    608 int32_t CXFA_LayoutPageMgr::GetPageIndex(const IXFA_LayoutPage* pPage) const {
    609   // FIXME: Find() method should take const.
    610   return m_PageArray.Find(static_cast<CXFA_ContainerLayoutItem*>(
    611       const_cast<IXFA_LayoutPage*>(pPage)));
    612 }
    613 FX_BOOL CXFA_LayoutPageMgr::RunBreak(XFA_ELEMENT eBreakType,
    614                                      XFA_ATTRIBUTEENUM eTargetType,
    615                                      CXFA_Node* pTarget,
    616                                      FX_BOOL bStartNew) {
    617   FX_BOOL bRet = FALSE;
    618   switch (eTargetType) {
    619     case XFA_ATTRIBUTEENUM_ContentArea:
    620       if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_ContentArea) {
    621         pTarget = NULL;
    622       }
    623       if (!pTarget || !m_pCurrentContainerRecord ||
    624           pTarget !=
    625               GetCurrentContainerRecord()->pCurContentArea->m_pFormNode ||
    626           bStartNew) {
    627         CXFA_Node* pPageArea = NULL;
    628         if (pTarget) {
    629           pPageArea = pTarget->GetNodeItem(XFA_NODEITEM_Parent);
    630         }
    631         pPageArea = GetNextAvailPageArea(pPageArea, pTarget);
    632         bRet = pPageArea != NULL;
    633       }
    634       break;
    635     case XFA_ATTRIBUTEENUM_PageArea:
    636       if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) {
    637         pTarget = NULL;
    638       }
    639       if (!pTarget || !m_pCurrentContainerRecord ||
    640           pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode ||
    641           bStartNew) {
    642         CXFA_Node* pPageArea = GetNextAvailPageArea(pTarget, NULL, TRUE);
    643         bRet = pPageArea != NULL;
    644       }
    645       break;
    646     case XFA_ATTRIBUTEENUM_PageOdd:
    647       if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) {
    648         pTarget = NULL;
    649       }
    650       if (m_nAvailPages % 2 != 1 || !m_pCurrentContainerRecord ||
    651           (pTarget &&
    652            pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode) ||
    653           bStartNew) {
    654         if (m_nAvailPages % 2 == 1) {
    655         }
    656       }
    657       break;
    658     case XFA_ATTRIBUTEENUM_PageEven:
    659       if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) {
    660         pTarget = NULL;
    661       }
    662       if (m_nAvailPages % 2 != 0 || !m_pCurrentContainerRecord ||
    663           (pTarget &&
    664            pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode) ||
    665           bStartNew) {
    666         if (m_nAvailPages % 2 == 0) {
    667         }
    668       }
    669       break;
    670     case XFA_ATTRIBUTEENUM_Auto:
    671     default:
    672       break;
    673       ;
    674   }
    675   return bRet;
    676 }
    677 FX_BOOL CXFA_LayoutPageMgr::ExecuteBreakBeforeOrAfter(
    678     CXFA_Node* pCurNode,
    679     FX_BOOL bBefore,
    680     CXFA_Node*& pBreakLeaderTemplate,
    681     CXFA_Node*& pBreakTrailerTemplate) {
    682   XFA_ELEMENT eType = pCurNode->GetClassID();
    683   switch (eType) {
    684     case XFA_ELEMENT_BreakBefore:
    685     case XFA_ELEMENT_BreakAfter: {
    686       CFX_WideStringC wsBreakLeader, wsBreakTrailer;
    687       CXFA_Node* pFormNode = pCurNode->GetNodeItem(
    688           XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);
    689       CXFA_Node* pContainer = pFormNode->GetTemplateNode();
    690       FX_BOOL bStartNew = pCurNode->GetInteger(XFA_ATTRIBUTE_StartNew) != 0;
    691       CXFA_Node* pScript = pCurNode->GetFirstChildByClass(XFA_ELEMENT_Script);
    692       if (pScript && !XFA_LayoutPageMgr_RunBreakTestScript(pScript)) {
    693         return FALSE;
    694       }
    695       CFX_WideStringC wsTarget = pCurNode->GetCData(XFA_ATTRIBUTE_Target);
    696       CXFA_Node* pTarget =
    697           XFA_ResolveBreakTarget(m_pTemplatePageSetRoot, TRUE, wsTarget);
    698       wsBreakTrailer = pCurNode->GetCData(XFA_ATTRIBUTE_Trailer);
    699       wsBreakLeader = pCurNode->GetCData(XFA_ATTRIBUTE_Leader);
    700       pBreakLeaderTemplate =
    701           XFA_ResolveBreakTarget(pContainer, TRUE, wsBreakLeader);
    702       pBreakTrailerTemplate =
    703           XFA_ResolveBreakTarget(pContainer, TRUE, wsBreakTrailer);
    704       if (RunBreak(eType, pCurNode->GetEnum(XFA_ATTRIBUTE_TargetType), pTarget,
    705                    bStartNew)) {
    706         return TRUE;
    707       } else {
    708         if (m_rgProposedContainerRecord.GetCount() > 0 &&
    709             m_pCurrentContainerRecord ==
    710                 m_rgProposedContainerRecord.GetHeadPosition() &&
    711             eType == XFA_ELEMENT_BreakBefore) {
    712           CXFA_Node* pParentNode = pFormNode->GetNodeItem(
    713               XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);
    714           if (!pParentNode ||
    715               pFormNode !=
    716                   pParentNode->GetNodeItem(XFA_NODEITEM_FirstChild,
    717                                            XFA_OBJECTTYPE_ContainerNode)) {
    718             break;
    719           }
    720           pParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
    721           if (!pParentNode || pParentNode->GetClassID() != XFA_ELEMENT_Form) {
    722             break;
    723           }
    724           return TRUE;
    725         }
    726       }
    727     } break;
    728     case XFA_ELEMENT_Break: {
    729       FX_BOOL bStartNew = pCurNode->GetInteger(XFA_ATTRIBUTE_StartNew) != 0;
    730       CFX_WideStringC wsTarget = pCurNode->GetCData(
    731           bBefore ? XFA_ATTRIBUTE_BeforeTarget : XFA_ATTRIBUTE_AfterTarget);
    732       CXFA_Node* pTarget =
    733           XFA_ResolveBreakTarget(m_pTemplatePageSetRoot, TRUE, wsTarget);
    734       if (RunBreak(bBefore ? XFA_ELEMENT_BreakBefore : XFA_ELEMENT_BreakAfter,
    735                    pCurNode->GetEnum(bBefore ? XFA_ATTRIBUTE_Before
    736                                              : XFA_ATTRIBUTE_After),
    737                    pTarget, bStartNew)) {
    738         return TRUE;
    739       }
    740     } break;
    741     default:
    742       break;
    743   }
    744   return FALSE;
    745 }
    746 static void XFA_SetLayoutGeneratedNodeFlag(CXFA_Node* pNode) {
    747   pNode->SetFlag(XFA_NODEFLAG_LayoutGeneratedNode, TRUE, FALSE);
    748   pNode->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE, FALSE);
    749 }
    750 FX_BOOL CXFA_LayoutPageMgr::ProcessBreakBeforeOrAfter(
    751     CXFA_Node* pBreakNode,
    752     FX_BOOL bBefore,
    753     CXFA_Node*& pBreakLeaderNode,
    754     CXFA_Node*& pBreakTrailerNode,
    755     FX_BOOL& bCreatePage) {
    756   CXFA_Node *pLeaderTemplate = NULL, *pTrailerTemplate = NULL;
    757   CXFA_Node* pFormNode = pBreakNode->GetNodeItem(XFA_NODEITEM_Parent,
    758                                                  XFA_OBJECTTYPE_ContainerNode);
    759   if (XFA_ItemLayoutProcessor_IsTakingSpace(pFormNode)) {
    760     bCreatePage = ExecuteBreakBeforeOrAfter(pBreakNode, bBefore,
    761                                             pLeaderTemplate, pTrailerTemplate);
    762     CXFA_Document* pDocument = pBreakNode->GetDocument();
    763     CXFA_Node* pDataScope = NULL;
    764     pFormNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent,
    765                                        XFA_OBJECTTYPE_ContainerNode);
    766     if (pLeaderTemplate) {
    767       if (!pDataScope) {
    768         pDataScope = XFA_DataMerge_FindDataScope(pFormNode);
    769       }
    770       pBreakLeaderNode = pDocument->DataMerge_CopyContainer(
    771           pLeaderTemplate, pFormNode, pDataScope, TRUE);
    772       pDocument->DataMerge_UpdateBindingRelations(pBreakLeaderNode);
    773       XFA_SetLayoutGeneratedNodeFlag(pBreakLeaderNode);
    774     }
    775     if (pTrailerTemplate) {
    776       if (!pDataScope) {
    777         pDataScope = XFA_DataMerge_FindDataScope(pFormNode);
    778       }
    779       pBreakTrailerNode = pDocument->DataMerge_CopyContainer(
    780           pTrailerTemplate, pFormNode, pDataScope, TRUE);
    781       pDocument->DataMerge_UpdateBindingRelations(pBreakTrailerNode);
    782       XFA_SetLayoutGeneratedNodeFlag(pBreakTrailerNode);
    783     }
    784     return TRUE;
    785   }
    786   return FALSE;
    787 }
    788 FX_BOOL CXFA_LayoutPageMgr::ProcessBookendLeaderOrTrailer(
    789     CXFA_Node* pBookendNode,
    790     FX_BOOL bLeader,
    791     CXFA_Node*& pBookendAppendNode) {
    792   CXFA_Node* pLeaderTemplate = NULL;
    793   CXFA_Node* pFormNode = pBookendNode->GetNodeItem(
    794       XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);
    795   if (ResolveBookendLeaderOrTrailer(pBookendNode, bLeader, pLeaderTemplate)) {
    796     CXFA_Document* pDocument = pBookendNode->GetDocument();
    797     CXFA_Node* pDataScope = NULL;
    798     if (pLeaderTemplate) {
    799       if (!pDataScope) {
    800         pDataScope = XFA_DataMerge_FindDataScope(pFormNode);
    801       }
    802       pBookendAppendNode = pDocument->DataMerge_CopyContainer(
    803           pLeaderTemplate, pFormNode, pDataScope, TRUE);
    804       pDocument->DataMerge_UpdateBindingRelations(pBookendAppendNode);
    805       XFA_SetLayoutGeneratedNodeFlag(pBookendAppendNode);
    806       return TRUE;
    807     }
    808   }
    809   return FALSE;
    810 }
    811 CXFA_Node* CXFA_LayoutPageMgr::BreakOverflow(CXFA_Node* pOverflowNode,
    812                                              CXFA_Node*& pLeaderTemplate,
    813                                              CXFA_Node*& pTrailerTemplate,
    814                                              FX_BOOL bCreatePage) {
    815   CFX_WideStringC wsOverflowLeader, wsOverflowTrailer;
    816   CXFA_Node* pContainer =
    817       pOverflowNode->GetNodeItem(XFA_NODEITEM_Parent,
    818                                  XFA_OBJECTTYPE_ContainerNode)
    819           ->GetTemplateNode();
    820   if (pOverflowNode->GetClassID() == XFA_ELEMENT_Break) {
    821     CFX_WideStringC wsOverflowLeader;
    822     CFX_WideStringC wsOverflowTarget;
    823     CFX_WideStringC wsOverflowTrailer;
    824     pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowLeader, wsOverflowLeader);
    825     pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowTrailer, wsOverflowTrailer);
    826     pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowTarget, wsOverflowTarget);
    827     if (!wsOverflowLeader.IsEmpty() || !wsOverflowTrailer.IsEmpty() ||
    828         !wsOverflowTarget.IsEmpty()) {
    829       if (!wsOverflowTarget.IsEmpty() && bCreatePage &&
    830           !m_bCreateOverFlowPage) {
    831         CXFA_Node* pTarget = XFA_ResolveBreakTarget(
    832             this->m_pTemplatePageSetRoot, TRUE, wsOverflowTarget);
    833         if (pTarget) {
    834           m_bCreateOverFlowPage = TRUE;
    835           switch (pTarget->GetClassID()) {
    836             case XFA_ELEMENT_PageArea:
    837               RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_PageArea,
    838                        pTarget, TRUE);
    839               break;
    840             case XFA_ELEMENT_ContentArea:
    841               RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_ContentArea,
    842                        pTarget, TRUE);
    843               break;
    844             default:
    845               break;
    846           }
    847         }
    848       }
    849       if (!bCreatePage) {
    850         pLeaderTemplate =
    851             XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowLeader);
    852         pTrailerTemplate =
    853             XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowTrailer);
    854       }
    855       return pOverflowNode;
    856     }
    857     return NULL;
    858   } else if (pOverflowNode->GetClassID() == XFA_ELEMENT_Overflow) {
    859     CFX_WideStringC wsOverflowTarget;
    860     pOverflowNode->TryCData(XFA_ATTRIBUTE_Leader, wsOverflowLeader);
    861     pOverflowNode->TryCData(XFA_ATTRIBUTE_Trailer, wsOverflowTrailer);
    862     pOverflowNode->TryCData(XFA_ATTRIBUTE_Target, wsOverflowTarget);
    863     if (!wsOverflowTarget.IsEmpty() && bCreatePage && !m_bCreateOverFlowPage) {
    864       CXFA_Node* pTarget = XFA_ResolveBreakTarget(this->m_pTemplatePageSetRoot,
    865                                                   TRUE, wsOverflowTarget);
    866       if (pTarget) {
    867         m_bCreateOverFlowPage = TRUE;
    868         switch (pTarget->GetClassID()) {
    869           case XFA_ELEMENT_PageArea:
    870             RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_PageArea, pTarget,
    871                      TRUE);
    872             break;
    873           case XFA_ELEMENT_ContentArea:
    874             RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_ContentArea,
    875                      pTarget, TRUE);
    876             break;
    877           default:
    878             break;
    879         }
    880       }
    881     }
    882     if (!bCreatePage) {
    883       pLeaderTemplate =
    884           XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowLeader);
    885       pTrailerTemplate =
    886           XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowTrailer);
    887     }
    888     return pOverflowNode;
    889   }
    890   return NULL;
    891 }
    892 FX_BOOL CXFA_LayoutPageMgr::ProcessOverflow(CXFA_Node* pFormNode,
    893                                             CXFA_Node*& pLeaderNode,
    894                                             CXFA_Node*& pTrailerNode,
    895                                             FX_BOOL bDataMerge,
    896                                             FX_BOOL bCreatePage) {
    897   if (pFormNode == NULL) {
    898     return FALSE;
    899   }
    900   CXFA_Node *pLeaderTemplate = NULL, *pTrailerTemplate = NULL;
    901   FX_BOOL bIsOverflowNode = FALSE;
    902   if (pFormNode->GetClassID() == XFA_ELEMENT_Overflow ||
    903       pFormNode->GetClassID() == XFA_ELEMENT_Break) {
    904     bIsOverflowNode = TRUE;
    905   }
    906   for (CXFA_Node* pCurNode =
    907            bIsOverflowNode ? pFormNode
    908                            : pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild);
    909        pCurNode; pCurNode = pCurNode->GetNodeItem((XFA_NODEITEM_NextSibling))) {
    910     if (BreakOverflow(pCurNode, pLeaderTemplate, pTrailerTemplate,
    911                       bCreatePage)) {
    912       if (bIsOverflowNode) {
    913         pFormNode = pCurNode->GetNodeItem(XFA_NODEITEM_Parent);
    914       }
    915       CXFA_Document* pDocument = pCurNode->GetDocument();
    916       CXFA_Node* pDataScope = NULL;
    917       if (pLeaderTemplate) {
    918         if (!pDataScope) {
    919           pDataScope = XFA_DataMerge_FindDataScope(pFormNode);
    920         }
    921         pLeaderNode = pDocument->DataMerge_CopyContainer(
    922             pLeaderTemplate, pFormNode, pDataScope, TRUE);
    923         pDocument->DataMerge_UpdateBindingRelations(pLeaderNode);
    924         XFA_SetLayoutGeneratedNodeFlag(pLeaderNode);
    925       }
    926       if (pTrailerTemplate) {
    927         if (!pDataScope) {
    928           pDataScope = XFA_DataMerge_FindDataScope(pFormNode);
    929         }
    930         pTrailerNode = pDocument->DataMerge_CopyContainer(
    931             pTrailerTemplate, pFormNode, pDataScope, TRUE);
    932         pDocument->DataMerge_UpdateBindingRelations(pTrailerNode);
    933         XFA_SetLayoutGeneratedNodeFlag(pTrailerNode);
    934       }
    935       return TRUE;
    936     }
    937     if (bIsOverflowNode) {
    938       break;
    939     }
    940   }
    941   return FALSE;
    942 }
    943 FX_BOOL CXFA_LayoutPageMgr::ResolveBookendLeaderOrTrailer(
    944     CXFA_Node* pBookendNode,
    945     FX_BOOL bLeader,
    946     CXFA_Node*& pBookendAppendTemplate) {
    947   CFX_WideStringC wsBookendLeader;
    948   CXFA_Node* pContainer =
    949       pBookendNode->GetNodeItem(XFA_NODEITEM_Parent,
    950                                 XFA_OBJECTTYPE_ContainerNode)
    951           ->GetTemplateNode();
    952   if (pBookendNode->GetClassID() == XFA_ELEMENT_Break) {
    953     pBookendNode->TryCData(
    954         bLeader ? XFA_ATTRIBUTE_BookendLeader : XFA_ATTRIBUTE_BookendTrailer,
    955         wsBookendLeader);
    956     if (!wsBookendLeader.IsEmpty()) {
    957       pBookendAppendTemplate =
    958           XFA_ResolveBreakTarget(pContainer, FALSE, wsBookendLeader);
    959       return TRUE;
    960     }
    961     return FALSE;
    962   } else if (pBookendNode->GetClassID() == XFA_ELEMENT_Bookend) {
    963     pBookendNode->TryCData(
    964         bLeader ? XFA_ATTRIBUTE_Leader : XFA_ATTRIBUTE_Trailer,
    965         wsBookendLeader);
    966     pBookendAppendTemplate =
    967         XFA_ResolveBreakTarget(pContainer, TRUE, wsBookendLeader);
    968     return TRUE;
    969   }
    970   return FALSE;
    971 }
    972 FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet(
    973     CXFA_Node* pPageSet,
    974     CXFA_Node* pStartChild,
    975     CXFA_Node* pTargetPageArea,
    976     CXFA_Node* pTargetContentArea,
    977     FX_BOOL bNewPage,
    978     FX_BOOL bQuery) {
    979   if (pPageSet == NULL && pStartChild == NULL) {
    980     return FALSE;
    981   }
    982   if (IsPageSetRootOrderedOccurrence()) {
    983     return FindPageAreaFromPageSet_Ordered(pPageSet, pStartChild,
    984                                            pTargetPageArea, pTargetContentArea,
    985                                            bNewPage, bQuery);
    986   }
    987   XFA_ATTRIBUTEENUM ePreferredPosition = m_pCurrentContainerRecord
    988                                              ? XFA_ATTRIBUTEENUM_Rest
    989                                              : XFA_ATTRIBUTEENUM_First;
    990   return FindPageAreaFromPageSet_SimplexDuplex(
    991       pPageSet, pStartChild, pTargetPageArea, pTargetContentArea, bNewPage,
    992       bQuery, ePreferredPosition);
    993 }
    994 FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet_Ordered(
    995     CXFA_Node* pPageSet,
    996     CXFA_Node* pStartChild,
    997     CXFA_Node* pTargetPageArea,
    998     CXFA_Node* pTargetContentArea,
    999     FX_BOOL bNewPage,
   1000     FX_BOOL bQuery) {
   1001   int32_t iPageSetCount = 0;
   1002   if (!pStartChild && !bQuery) {
   1003     m_pPageSetMap.Lookup(pPageSet, iPageSetCount);
   1004     int32_t iMax = -1;
   1005     CXFA_Node* pOccurNode = pPageSet->GetFirstChildByClass(XFA_ELEMENT_Occur);
   1006     if (pOccurNode) {
   1007       pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE);
   1008     }
   1009     if (iMax >= 0 && iMax <= iPageSetCount) {
   1010       return FALSE;
   1011     }
   1012   }
   1013   FX_BOOL bRes = FALSE;
   1014   CXFA_Node* pCurrentNode =
   1015       pStartChild ? pStartChild->GetNodeItem(XFA_NODEITEM_NextSibling)
   1016                   : pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild);
   1017   for (; pCurrentNode;
   1018        pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
   1019     if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) {
   1020       if ((pTargetPageArea == pCurrentNode || pTargetPageArea == NULL)) {
   1021         if (pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea) ==
   1022             NULL) {
   1023           if (pTargetPageArea == pCurrentNode) {
   1024             CreateMinPageRecord(pCurrentNode, TRUE);
   1025             pTargetPageArea = NULL;
   1026           }
   1027           continue;
   1028         }
   1029         if (!bQuery) {
   1030           CXFA_ContainerRecord* pNewRecord =
   1031               CreateContainerRecord(pCurrentNode, pStartChild == NULL);
   1032           AddPageAreaLayoutItem(pNewRecord, pCurrentNode);
   1033           if (pTargetContentArea == NULL) {
   1034             pTargetContentArea =
   1035                 pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea);
   1036           }
   1037           AddContentAreaLayoutItem(pNewRecord, pTargetContentArea);
   1038         }
   1039         m_pCurPageArea = pCurrentNode;
   1040         m_nCurPageCount = 1;
   1041         bRes = TRUE;
   1042         break;
   1043       }
   1044       if (!bQuery) {
   1045         CreateMinPageRecord(pCurrentNode, FALSE);
   1046       }
   1047     } else if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) {
   1048       if (FindPageAreaFromPageSet_Ordered(pCurrentNode, NULL, pTargetPageArea,
   1049                                           pTargetContentArea, bNewPage,
   1050                                           bQuery)) {
   1051         bRes = TRUE;
   1052         break;
   1053       }
   1054       if (!bQuery) {
   1055         CreateMinPageSetRecord(pCurrentNode, TRUE);
   1056       }
   1057     }
   1058   }
   1059   if (!pStartChild && bRes && !bQuery) {
   1060     m_pPageSetMap.SetAt(pPageSet, ++iPageSetCount);
   1061   }
   1062   return bRes;
   1063 }
   1064 FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet_SimplexDuplex(
   1065     CXFA_Node* pPageSet,
   1066     CXFA_Node* pStartChild,
   1067     CXFA_Node* pTargetPageArea,
   1068     CXFA_Node* pTargetContentArea,
   1069     FX_BOOL bNewPage,
   1070     FX_BOOL bQuery,
   1071     XFA_ATTRIBUTEENUM ePreferredPosition) {
   1072   const XFA_ATTRIBUTEENUM eFallbackPosition = XFA_ATTRIBUTEENUM_Any;
   1073   CXFA_Node *pPreferredPageArea = NULL, *pFallbackPageArea = NULL;
   1074   CXFA_Node* pCurrentNode = NULL;
   1075   if (!pStartChild || pStartChild->GetClassID() == XFA_ELEMENT_PageArea) {
   1076     pCurrentNode = pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild);
   1077   } else {
   1078     pCurrentNode = pStartChild->GetNodeItem(XFA_NODEITEM_NextSibling);
   1079   }
   1080   for (; pCurrentNode;
   1081        pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
   1082     if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) {
   1083       if (!MatchPageAreaOddOrEven(pCurrentNode, FALSE)) {
   1084         continue;
   1085       }
   1086       XFA_ATTRIBUTEENUM eCurPagePosition =
   1087           pCurrentNode->GetEnum(XFA_ATTRIBUTE_PagePosition);
   1088       if (ePreferredPosition == XFA_ATTRIBUTEENUM_Last) {
   1089         if (eCurPagePosition != ePreferredPosition) {
   1090           continue;
   1091         }
   1092         if (m_ePageSetMode == XFA_ATTRIBUTEENUM_SimplexPaginated ||
   1093             pCurrentNode->GetEnum(XFA_ATTRIBUTE_OddOrEven) ==
   1094                 XFA_ATTRIBUTEENUM_Any) {
   1095           pPreferredPageArea = pCurrentNode;
   1096           break;
   1097         }
   1098         CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();
   1099         AddPageAreaLayoutItem(pNewRecord, pCurrentNode);
   1100         AddContentAreaLayoutItem(pNewRecord, pCurrentNode->GetFirstChildByClass(
   1101                                                  XFA_ELEMENT_ContentArea));
   1102         pPreferredPageArea = pCurrentNode;
   1103         return FALSE;
   1104       } else if (ePreferredPosition == XFA_ATTRIBUTEENUM_Only) {
   1105         if (eCurPagePosition != ePreferredPosition) {
   1106           continue;
   1107         }
   1108         if (m_ePageSetMode != XFA_ATTRIBUTEENUM_DuplexPaginated ||
   1109             pCurrentNode->GetEnum(XFA_ATTRIBUTE_OddOrEven) ==
   1110                 XFA_ATTRIBUTEENUM_Any) {
   1111           pPreferredPageArea = pCurrentNode;
   1112           break;
   1113         }
   1114         return FALSE;
   1115       }
   1116       if ((pTargetPageArea == pCurrentNode || pTargetPageArea == NULL)) {
   1117         if (pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea) ==
   1118             NULL) {
   1119           if (pTargetPageArea == pCurrentNode) {
   1120             CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();
   1121             AddPageAreaLayoutItem(pNewRecord, pCurrentNode);
   1122             pTargetPageArea = NULL;
   1123           }
   1124           continue;
   1125         }
   1126         if ((ePreferredPosition == XFA_ATTRIBUTEENUM_Rest &&
   1127              eCurPagePosition == XFA_ATTRIBUTEENUM_Any) ||
   1128             eCurPagePosition == ePreferredPosition) {
   1129           pPreferredPageArea = pCurrentNode;
   1130           break;
   1131         } else if (eCurPagePosition == eFallbackPosition &&
   1132                    !pFallbackPageArea) {
   1133           pFallbackPageArea = pCurrentNode;
   1134         }
   1135       } else if (pTargetPageArea &&
   1136                  !MatchPageAreaOddOrEven(pTargetPageArea, FALSE)) {
   1137         CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();
   1138         AddPageAreaLayoutItem(pNewRecord, pCurrentNode);
   1139         AddContentAreaLayoutItem(pNewRecord, pCurrentNode->GetFirstChildByClass(
   1140                                                  XFA_ELEMENT_ContentArea));
   1141       }
   1142     } else if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) {
   1143       if (FindPageAreaFromPageSet_SimplexDuplex(
   1144               pCurrentNode, NULL, pTargetPageArea, pTargetContentArea, bNewPage,
   1145               bQuery, ePreferredPosition)) {
   1146         break;
   1147       }
   1148     }
   1149   }
   1150   CXFA_Node* pCurPageArea = NULL;
   1151   if (pPreferredPageArea) {
   1152     pCurPageArea = pPreferredPageArea;
   1153   } else if (pFallbackPageArea) {
   1154     pCurPageArea = pFallbackPageArea;
   1155   }
   1156   if (!pCurPageArea) {
   1157     return FALSE;
   1158   }
   1159   if (!bQuery) {
   1160     CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();
   1161     AddPageAreaLayoutItem(pNewRecord, pCurPageArea);
   1162     if (pTargetContentArea == NULL) {
   1163       pTargetContentArea =
   1164           pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea);
   1165     }
   1166     AddContentAreaLayoutItem(pNewRecord, pTargetContentArea);
   1167   }
   1168   m_pCurPageArea = pCurPageArea;
   1169   return TRUE;
   1170 }
   1171 FX_BOOL CXFA_LayoutPageMgr::MatchPageAreaOddOrEven(CXFA_Node* pPageArea,
   1172                                                    FX_BOOL bLastMatch) {
   1173   if (m_ePageSetMode != XFA_ATTRIBUTEENUM_DuplexPaginated) {
   1174     return TRUE;
   1175   }
   1176   XFA_ATTRIBUTEENUM eOddOrEven = XFA_ATTRIBUTEENUM_Any;
   1177   pPageArea->TryEnum(XFA_ATTRIBUTE_OddOrEven, eOddOrEven);
   1178   if (eOddOrEven != XFA_ATTRIBUTEENUM_Any) {
   1179     int32_t iPageCount = GetPageCount();
   1180     if (bLastMatch) {
   1181       return eOddOrEven == XFA_ATTRIBUTEENUM_Odd ? iPageCount % 2 == 1
   1182                                                  : iPageCount % 2 == 0;
   1183     }
   1184     return eOddOrEven == XFA_ATTRIBUTEENUM_Odd ? iPageCount % 2 == 0
   1185                                                : iPageCount % 2 == 1;
   1186   }
   1187   return TRUE;
   1188 }
   1189 CXFA_Node* CXFA_LayoutPageMgr::GetNextAvailPageArea(
   1190     CXFA_Node* pTargetPageArea,
   1191     CXFA_Node* pTargetContentArea,
   1192     FX_BOOL bNewPage,
   1193     FX_BOOL bQuery) {
   1194   if (m_pCurPageArea == NULL) {
   1195     FindPageAreaFromPageSet(m_pTemplatePageSetRoot, NULL, pTargetPageArea,
   1196                             pTargetContentArea, bNewPage, bQuery);
   1197     ASSERT(m_pCurPageArea);
   1198     return m_pCurPageArea;
   1199   }
   1200   if (pTargetPageArea == NULL || pTargetPageArea == m_pCurPageArea) {
   1201     if (!bNewPage && GetNextContentArea(pTargetContentArea)) {
   1202       return m_pCurPageArea;
   1203     }
   1204     if (IsPageSetRootOrderedOccurrence()) {
   1205       int32_t iMax = -1;
   1206       CXFA_Node* pOccurNode =
   1207           m_pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_Occur);
   1208       if (pOccurNode) {
   1209         pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE);
   1210       }
   1211       if ((iMax < 0 || m_nCurPageCount < iMax)) {
   1212         if (!bQuery) {
   1213           CXFA_ContainerRecord* pNewRecord =
   1214               CreateContainerRecord(m_pCurPageArea);
   1215           AddPageAreaLayoutItem(pNewRecord, m_pCurPageArea);
   1216           if (pTargetContentArea == NULL) {
   1217             pTargetContentArea =
   1218                 m_pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea);
   1219           }
   1220           AddContentAreaLayoutItem(pNewRecord, pTargetContentArea);
   1221         }
   1222         m_nCurPageCount++;
   1223         return m_pCurPageArea;
   1224       }
   1225     }
   1226   }
   1227   if (!bQuery && IsPageSetRootOrderedOccurrence()) {
   1228     CreateMinPageRecord(m_pCurPageArea, FALSE, TRUE);
   1229   }
   1230   if (FindPageAreaFromPageSet(m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent),
   1231                               m_pCurPageArea, pTargetPageArea,
   1232                               pTargetContentArea, bNewPage, bQuery)) {
   1233     return m_pCurPageArea;
   1234   }
   1235   CXFA_Node* pPageSet = m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent);
   1236   while (TRUE) {
   1237     if (FindPageAreaFromPageSet(pPageSet, NULL, pTargetPageArea,
   1238                                 pTargetContentArea, bNewPage, bQuery)) {
   1239       return m_pCurPageArea;
   1240     }
   1241     if (!bQuery && IsPageSetRootOrderedOccurrence()) {
   1242       CreateMinPageSetRecord(pPageSet);
   1243     }
   1244     if (FindPageAreaFromPageSet(NULL, pPageSet, pTargetPageArea,
   1245                                 pTargetContentArea, bNewPage, bQuery)) {
   1246       return m_pCurPageArea;
   1247     }
   1248     if (pPageSet == m_pTemplatePageSetRoot) {
   1249       break;
   1250     }
   1251     pPageSet = pPageSet->GetNodeItem(XFA_NODEITEM_Parent);
   1252   }
   1253   return NULL;
   1254 }
   1255 static FX_BOOL XFA_LayoutPageMgr_CheckContentAreaNotUsed(
   1256     CXFA_ContainerLayoutItem* pPageAreaLayoutItem,
   1257     CXFA_Node* pContentArea,
   1258     CXFA_ContainerLayoutItem*& pContentAreaLayoutItem) {
   1259   for (CXFA_ContainerLayoutItem* pLayoutItem =
   1260            (CXFA_ContainerLayoutItem*)pPageAreaLayoutItem->m_pFirstChild;
   1261        pLayoutItem;
   1262        pLayoutItem = (CXFA_ContainerLayoutItem*)pLayoutItem->m_pNextSibling) {
   1263     if (pLayoutItem->m_pFormNode == pContentArea) {
   1264       if (pLayoutItem->m_pFirstChild == NULL) {
   1265         pContentAreaLayoutItem = pLayoutItem;
   1266         return TRUE;
   1267       }
   1268       return FALSE;
   1269     }
   1270   }
   1271   return TRUE;
   1272 }
   1273 FX_BOOL CXFA_LayoutPageMgr::GetNextContentArea(CXFA_Node* pContentArea) {
   1274   CXFA_Node* pCurContentNode =
   1275       GetCurrentContainerRecord()->pCurContentArea->m_pFormNode;
   1276   if (pContentArea == NULL) {
   1277     pContentArea =
   1278         pCurContentNode->GetNextSameClassSibling(XFA_ELEMENT_ContentArea);
   1279     if (pContentArea == NULL) {
   1280       return FALSE;
   1281     }
   1282   } else {
   1283     if (pContentArea->GetNodeItem(XFA_NODEITEM_Parent) != m_pCurPageArea) {
   1284       return FALSE;
   1285     }
   1286     CXFA_ContainerLayoutItem* pContentAreaLayout = NULL;
   1287     if (!XFA_LayoutPageMgr_CheckContentAreaNotUsed(
   1288             GetCurrentContainerRecord()->pCurPageArea, pContentArea,
   1289             pContentAreaLayout)) {
   1290       return FALSE;
   1291     }
   1292     if (pContentAreaLayout) {
   1293       if (pContentAreaLayout->m_pFormNode != pCurContentNode) {
   1294         CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();
   1295         pNewRecord->pCurContentArea = pContentAreaLayout;
   1296         return TRUE;
   1297       } else {
   1298         return FALSE;
   1299       }
   1300     }
   1301   }
   1302   CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();
   1303   AddContentAreaLayoutItem(pNewRecord, pContentArea);
   1304   return TRUE;
   1305 }
   1306 void CXFA_LayoutPageMgr::InitPageSetMap() {
   1307   if (!IsPageSetRootOrderedOccurrence()) {
   1308     return;
   1309   }
   1310   CXFA_NodeIterator sIterator(m_pTemplatePageSetRoot);
   1311   for (CXFA_Node* pPageSetNode = sIterator.GetCurrent(); pPageSetNode;
   1312        pPageSetNode = sIterator.MoveToNext()) {
   1313     if (pPageSetNode->GetClassID() == XFA_ELEMENT_PageSet) {
   1314       XFA_ATTRIBUTEENUM eRelation =
   1315           pPageSetNode->GetEnum(XFA_ATTRIBUTE_Relation);
   1316       if (eRelation == XFA_ATTRIBUTEENUM_OrderedOccurrence) {
   1317         m_pPageSetMap.SetAt(pPageSetNode, 0);
   1318       }
   1319     }
   1320   }
   1321 }
   1322 int32_t CXFA_LayoutPageMgr::CreateMinPageRecord(CXFA_Node* pPageArea,
   1323                                                 FX_BOOL bTargetPageArea,
   1324                                                 FX_BOOL bCreateLast) {
   1325   if (pPageArea == NULL) {
   1326     return 0;
   1327   }
   1328   CXFA_Node* pOccurNode = pPageArea->GetFirstChildByClass(XFA_ELEMENT_Occur);
   1329   int32_t iMin = 0;
   1330   if ((pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, FALSE)) ||
   1331       bTargetPageArea) {
   1332     CXFA_Node* pContentArea =
   1333         pPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea);
   1334     if (iMin < 1 && bTargetPageArea && !pContentArea) {
   1335       iMin = 1;
   1336     }
   1337     int32_t i = 0;
   1338     if (bCreateLast) {
   1339       i = m_nCurPageCount;
   1340     }
   1341     for (; i < iMin; i++) {
   1342       CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();
   1343       AddPageAreaLayoutItem(pNewRecord, pPageArea);
   1344       AddContentAreaLayoutItem(pNewRecord, pContentArea);
   1345     }
   1346   }
   1347   return iMin;
   1348 }
   1349 void CXFA_LayoutPageMgr::CreateMinPageSetRecord(CXFA_Node* pPageSet,
   1350                                                 FX_BOOL bCreateAll) {
   1351   if (pPageSet == NULL) {
   1352     return;
   1353   }
   1354   int32_t iCurSetCount = 0;
   1355   if (!m_pPageSetMap.Lookup(pPageSet, iCurSetCount)) {
   1356     return;
   1357   }
   1358   if (bCreateAll) {
   1359     iCurSetCount = 0;
   1360   }
   1361   CXFA_Node* pOccurNode = pPageSet->GetFirstChildByClass(XFA_ELEMENT_Occur);
   1362   int32_t iMin = 0;
   1363   if (pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, FALSE)) {
   1364     if (iCurSetCount < iMin) {
   1365       for (int32_t i = 0; i < iMin - iCurSetCount; i++) {
   1366         for (CXFA_Node* pCurrentPageNode =
   1367                  pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild);
   1368              pCurrentPageNode; pCurrentPageNode = pCurrentPageNode->GetNodeItem(
   1369                                    XFA_NODEITEM_NextSibling)) {
   1370           if (pCurrentPageNode->GetClassID() == XFA_ELEMENT_PageArea) {
   1371             CreateMinPageRecord(pCurrentPageNode, FALSE);
   1372           } else if (pCurrentPageNode->GetClassID() == XFA_ELEMENT_PageSet) {
   1373             CreateMinPageSetRecord(pCurrentPageNode, TRUE);
   1374           }
   1375         }
   1376       }
   1377       m_pPageSetMap.SetAt(pPageSet, iMin);
   1378     }
   1379   }
   1380 }
   1381 void CXFA_LayoutPageMgr::CreateNextMinRecord(CXFA_Node* pRecordNode) {
   1382   if (pRecordNode == NULL) {
   1383     return;
   1384   }
   1385   for (CXFA_Node* pCurrentNode =
   1386            pRecordNode->GetNodeItem(XFA_NODEITEM_NextSibling);
   1387        pCurrentNode;
   1388        pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
   1389     if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) {
   1390       CreateMinPageRecord(pCurrentNode, FALSE);
   1391     } else if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) {
   1392       CreateMinPageSetRecord(pCurrentNode, TRUE);
   1393     }
   1394   }
   1395 }
   1396 void CXFA_LayoutPageMgr::ProcessLastPageSet() {
   1397   CreateMinPageRecord(m_pCurPageArea, FALSE, TRUE);
   1398   CreateNextMinRecord(m_pCurPageArea);
   1399   CXFA_Node* pPageSet = m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent);
   1400   while (TRUE) {
   1401     CreateMinPageSetRecord(pPageSet);
   1402     if (pPageSet == m_pTemplatePageSetRoot) {
   1403       break;
   1404     }
   1405     CreateNextMinRecord(pPageSet);
   1406     pPageSet = pPageSet->GetNodeItem(XFA_NODEITEM_Parent);
   1407   }
   1408 }
   1409 FX_BOOL CXFA_LayoutPageMgr::GetNextAvailContentHeight(FX_FLOAT fChildHeight) {
   1410   CXFA_Node* pCurContentNode =
   1411       GetCurrentContainerRecord()->pCurContentArea->m_pFormNode;
   1412   if (pCurContentNode == NULL) {
   1413     return FALSE;
   1414   }
   1415   pCurContentNode =
   1416       pCurContentNode->GetNextSameClassSibling(XFA_ELEMENT_ContentArea);
   1417   if (pCurContentNode) {
   1418     FX_FLOAT fNextContentHeight =
   1419         pCurContentNode->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt);
   1420     return fNextContentHeight > fChildHeight;
   1421   }
   1422   CXFA_Node* pPageNode = GetCurrentContainerRecord()->pCurPageArea->m_pFormNode;
   1423   CXFA_Node* pOccurNode = pPageNode->GetFirstChildByClass(XFA_ELEMENT_Occur);
   1424   int32_t iMax = 0;
   1425   if (pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE)) {
   1426     if (m_nCurPageCount == iMax) {
   1427       CXFA_Node* pSrcPage = m_pCurPageArea;
   1428       int32_t nSrcPageCount = m_nCurPageCount;
   1429       FX_POSITION psSrcRecord = m_rgProposedContainerRecord.GetTailPosition();
   1430       CXFA_Node* pNextPage = GetNextAvailPageArea(NULL, NULL, FALSE, TRUE);
   1431       m_pCurPageArea = pSrcPage;
   1432       m_nCurPageCount = nSrcPageCount;
   1433       CXFA_ContainerRecord* pPrevRecord =
   1434           (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext(
   1435               psSrcRecord);
   1436       while (psSrcRecord) {
   1437         FX_POSITION psSaveRecord = psSrcRecord;
   1438         CXFA_ContainerRecord* pInsertRecord =
   1439             (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext(
   1440                 psSrcRecord);
   1441         RemoveLayoutRecord(pInsertRecord, pPrevRecord);
   1442         delete pInsertRecord;
   1443         m_rgProposedContainerRecord.RemoveAt(psSaveRecord);
   1444       }
   1445       if (pNextPage) {
   1446         CXFA_Node* pContentArea =
   1447             pNextPage->GetFirstChildByClass(XFA_ELEMENT_ContentArea);
   1448         if (pContentArea) {
   1449           FX_FLOAT fNextContentHeight =
   1450               pContentArea->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt);
   1451           if (fNextContentHeight > fChildHeight) {
   1452             return TRUE;
   1453           }
   1454         }
   1455       }
   1456       return FALSE;
   1457     }
   1458   }
   1459   CXFA_Node* pContentArea =
   1460       pPageNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea);
   1461   FX_FLOAT fNextContentHeight =
   1462       pContentArea->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt);
   1463   if (fNextContentHeight < XFA_LAYOUT_FLOAT_PERCISION) {
   1464     return TRUE;
   1465   }
   1466   if (fNextContentHeight > fChildHeight) {
   1467     return TRUE;
   1468   }
   1469   return FALSE;
   1470 }
   1471 void CXFA_LayoutPageMgr::ClearData() {
   1472   ClearRecordList();
   1473 }
   1474 void CXFA_LayoutPageMgr::ClearRecordList() {
   1475   if (!m_pTemplatePageSetRoot) {
   1476     return;
   1477   }
   1478   if (m_rgProposedContainerRecord.GetCount() > 0) {
   1479     FX_POSITION sPos;
   1480     sPos = m_rgProposedContainerRecord.GetHeadPosition();
   1481     while (sPos) {
   1482       CXFA_ContainerRecord* pRecord =
   1483           (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext(sPos);
   1484       delete pRecord;
   1485     }
   1486     m_rgProposedContainerRecord.RemoveAll();
   1487   }
   1488   m_pCurrentContainerRecord = NULL;
   1489   m_pCurPageArea = NULL;
   1490   m_nCurPageCount = 0;
   1491   m_bCreateOverFlowPage = FALSE;
   1492   m_pPageSetMap.RemoveAll();
   1493 }
   1494 CXFA_LayoutItem* CXFA_LayoutPageMgr::FindOrCreateLayoutItem(
   1495     CXFA_Node* pFormNode) {
   1496 #if defined(_XFA_LAYOUTITEM_MAPCACHE_)
   1497   if (m_NodeToContent.GetCount() > 0) {
   1498     CXFA_ContentLayoutItem* pLayoutItem = NULL;
   1499     if (m_NodeToContent.Lookup(pFormNode, (void*&)pLayoutItem)) {
   1500       if (pLayoutItem->m_pNext) {
   1501         m_NodeToContent.SetAt(pFormNode, pLayoutItem->m_pNext);
   1502         pLayoutItem->m_pNext->m_pPrev = NULL;
   1503         pLayoutItem->m_pNext = NULL;
   1504       } else {
   1505         m_NodeToContent.RemoveKey(pFormNode);
   1506       }
   1507       pLayoutItem->m_pFormNode = pFormNode;
   1508       return pLayoutItem;
   1509     }
   1510   }
   1511 #endif
   1512   return (CXFA_LayoutItem*)pFormNode->GetDocument()
   1513       ->GetParser()
   1514       ->GetNotify()
   1515       ->OnCreateLayoutItem(pFormNode);
   1516 }
   1517 #if defined(_XFA_LAYOUTITEM_MAPCACHE_)
   1518 void CXFA_LayoutPageMgr::SaveLayoutItem(CXFA_LayoutItem* pParentLayoutItem) {
   1519   CXFA_LayoutItem* pNextLayoutItem,
   1520       * pCurLayoutItem = pParentLayoutItem->m_pFirstChild;
   1521   while (pCurLayoutItem) {
   1522     pNextLayoutItem = pCurLayoutItem->m_pNextSibling;
   1523     if (pCurLayoutItem->m_pFirstChild) {
   1524       SaveLayoutItem(pCurLayoutItem);
   1525     }
   1526     if (pCurLayoutItem->IsContentLayoutItem()) {
   1527       if (m_NodeToContent.GetValueAt(pCurLayoutItem->m_pFormNode) == NULL) {
   1528         pCurLayoutItem->m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, NULL);
   1529         m_NodeToContent.SetAt(pCurLayoutItem->m_pFormNode, pCurLayoutItem);
   1530       }
   1531     } else if (pCurLayoutItem->m_pFormNode->GetClassID() !=
   1532                XFA_ELEMENT_PageArea) {
   1533       delete pCurLayoutItem;
   1534       pCurLayoutItem = NULL;
   1535     }
   1536     if (pCurLayoutItem) {
   1537       pCurLayoutItem->m_pParent = NULL;
   1538       pCurLayoutItem->m_pNextSibling = NULL;
   1539       pCurLayoutItem->m_pFirstChild = NULL;
   1540     }
   1541     pCurLayoutItem = pNextLayoutItem;
   1542   }
   1543 }
   1544 #elif defined(_XFA_LAYOUTITEM_ProcessCACHE_)
   1545 static void XFA_SyncRemoveLayoutItem(CXFA_LayoutItem* pParentLayoutItem,
   1546                                      IXFA_Notify* pNotify,
   1547                                      IXFA_DocLayout* pDocLayout) {
   1548   CXFA_LayoutItem* pNextLayoutItem;
   1549   CXFA_LayoutItem* pCurLayoutItem = pParentLayoutItem->m_pFirstChild;
   1550   while (pCurLayoutItem) {
   1551     pNextLayoutItem = pCurLayoutItem->m_pNextSibling;
   1552     if (pCurLayoutItem->m_pFirstChild) {
   1553       XFA_SyncRemoveLayoutItem(pCurLayoutItem, pNotify, pDocLayout);
   1554     }
   1555     pNotify->OnLayoutEvent(pDocLayout, pCurLayoutItem,
   1556                            XFA_LAYOUTEVENT_ItemRemoving);
   1557     delete pCurLayoutItem;
   1558     pCurLayoutItem = pNextLayoutItem;
   1559   }
   1560 }
   1561 void CXFA_LayoutPageMgr::SaveLayoutItem(CXFA_LayoutItem* pParentLayoutItem) {
   1562   CXFA_LayoutItem* pNextLayoutItem;
   1563   CXFA_LayoutItem* pCurLayoutItem = pParentLayoutItem->m_pFirstChild;
   1564   while (pCurLayoutItem) {
   1565     pNextLayoutItem = pCurLayoutItem->m_pNextSibling;
   1566     if (pCurLayoutItem->IsContentLayoutItem()) {
   1567       FX_DWORD dwFlag = pCurLayoutItem->m_pFormNode->GetFlag();
   1568       if (dwFlag & (XFA_NODEFLAG_HasRemoved)) {
   1569         IXFA_Notify* pNotify =
   1570             m_pTemplatePageSetRoot->GetDocument()->GetParser()->GetNotify();
   1571         IXFA_DocLayout* pDocLayout =
   1572             m_pTemplatePageSetRoot->GetDocument()->GetDocLayout();
   1573         if (pCurLayoutItem->m_pFirstChild) {
   1574           XFA_SyncRemoveLayoutItem(pCurLayoutItem, pNotify, pDocLayout);
   1575         }
   1576         pNotify->OnLayoutEvent(pDocLayout, pCurLayoutItem,
   1577                                XFA_LAYOUTEVENT_ItemRemoving);
   1578         delete pCurLayoutItem;
   1579         pCurLayoutItem = pNextLayoutItem;
   1580         continue;
   1581       }
   1582       if (dwFlag & XFA_NODEFLAG_LayoutGeneratedNode) {
   1583         CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode>
   1584             sIterator(pCurLayoutItem->m_pFormNode);
   1585         for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
   1586              pNode = sIterator.MoveToNext()) {
   1587           pNode->SetFlag(XFA_NODEFLAG_UnusedNode, TRUE, FALSE);
   1588         }
   1589       }
   1590     }
   1591     if (pCurLayoutItem->m_pFirstChild) {
   1592       SaveLayoutItem(pCurLayoutItem);
   1593     }
   1594     pCurLayoutItem->m_pParent = NULL;
   1595     pCurLayoutItem->m_pNextSibling = NULL;
   1596     pCurLayoutItem->m_pFirstChild = NULL;
   1597     if (!pCurLayoutItem->IsContentLayoutItem() &&
   1598         pCurLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) {
   1599       delete pCurLayoutItem;
   1600     }
   1601     pCurLayoutItem = pNextLayoutItem;
   1602   }
   1603 }
   1604 #endif
   1605 CXFA_Node* CXFA_LayoutPageMgr::QueryOverflow(
   1606     CXFA_Node* pFormNode,
   1607     CXFA_LayoutContext* pLayoutContext) {
   1608   for (CXFA_Node* pCurNode = pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild);
   1609        pCurNode; pCurNode = pCurNode->GetNodeItem((XFA_NODEITEM_NextSibling))) {
   1610     if (pCurNode->GetClassID() == XFA_ELEMENT_Break) {
   1611       CFX_WideStringC wsOverflowLeader;
   1612       CFX_WideStringC wsOverflowTarget;
   1613       CFX_WideStringC wsOverflowTrailer;
   1614       pCurNode->TryCData(XFA_ATTRIBUTE_OverflowLeader, wsOverflowLeader);
   1615       pCurNode->TryCData(XFA_ATTRIBUTE_OverflowTrailer, wsOverflowTrailer);
   1616       pCurNode->TryCData(XFA_ATTRIBUTE_OverflowTarget, wsOverflowTarget);
   1617       if (!wsOverflowLeader.IsEmpty() || !wsOverflowTrailer.IsEmpty() ||
   1618           !wsOverflowTarget.IsEmpty()) {
   1619         return pCurNode;
   1620       }
   1621       return NULL;
   1622     } else if (pCurNode->GetClassID() == XFA_ELEMENT_Overflow) {
   1623       return pCurNode;
   1624     }
   1625   }
   1626   return NULL;
   1627 }
   1628 void CXFA_LayoutPageMgr::MergePageSetContents() {
   1629   CXFA_Document* pDocument = m_pTemplatePageSetRoot->GetDocument();
   1630   IXFA_Notify* pNotify = pDocument->GetParser()->GetNotify();
   1631   IXFA_DocLayout* pDocLayout = pDocument->GetDocLayout();
   1632   CXFA_ContainerLayoutItem* pRootLayout = this->GetRootLayoutItem();
   1633   {
   1634     for (int32_t iIndex = 0; iIndex < pDocument->m_pPendingPageSet.GetSize();
   1635          iIndex++) {
   1636       CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode>
   1637           sIterator(pDocument->m_pPendingPageSet.GetAt(iIndex));
   1638       for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
   1639            pNode = sIterator.MoveToNext()) {
   1640         if (pNode->IsContainerNode()) {
   1641           CXFA_Node* pBindNode = pNode->GetBindData();
   1642           if (pBindNode) {
   1643             pBindNode->RemoveBindItem(pNode);
   1644             pNode->SetObject(XFA_ATTRIBUTE_BindingNode, NULL);
   1645           }
   1646         }
   1647         pNode->SetFlag(XFA_NODEFLAG_UnusedNode);
   1648       }
   1649     }
   1650   }
   1651   int32_t iIndex = 0;
   1652   CXFA_Node* pPendingPageSet = NULL;
   1653   for (; pRootLayout;
   1654        pRootLayout = (CXFA_ContainerLayoutItem*)pRootLayout->m_pNextSibling) {
   1655     pPendingPageSet = NULL;
   1656     CXFA_NodeIteratorTemplate<
   1657         CXFA_ContainerLayoutItem,
   1658         CXFA_TraverseStrategy_ContentAreaContainerLayoutItem>
   1659         iterator(pRootLayout);
   1660     CXFA_ContainerLayoutItem* pRootPageSetContainerItem = iterator.GetCurrent();
   1661     ASSERT(pRootPageSetContainerItem->m_pFormNode->GetClassID() ==
   1662            XFA_ELEMENT_PageSet);
   1663     if (iIndex < pDocument->m_pPendingPageSet.GetSize()) {
   1664       pPendingPageSet = pDocument->m_pPendingPageSet.GetAt(iIndex);
   1665       iIndex++;
   1666     }
   1667     if (!pPendingPageSet) {
   1668       if (pRootPageSetContainerItem->m_pFormNode->GetPacketID() ==
   1669           XFA_XDPPACKET_Template) {
   1670         pPendingPageSet =
   1671             pRootPageSetContainerItem->m_pFormNode->CloneTemplateToForm(FALSE);
   1672       } else {
   1673         pPendingPageSet = pRootPageSetContainerItem->m_pFormNode;
   1674       }
   1675     }
   1676     if (pRootPageSetContainerItem->m_pFormNode->GetUserData(
   1677             XFA_LAYOUTITEMKEY) == pRootPageSetContainerItem) {
   1678       pRootPageSetContainerItem->m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY,
   1679                                                           NULL);
   1680     }
   1681     pRootPageSetContainerItem->m_pFormNode = pPendingPageSet;
   1682     pPendingPageSet->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE);
   1683     for (CXFA_ContainerLayoutItem* pContainerItem = iterator.MoveToNext();
   1684          pContainerItem; pContainerItem = iterator.MoveToNext()) {
   1685       CXFA_Node* pNode = pContainerItem->m_pFormNode;
   1686       if (pNode->GetPacketID() != XFA_XDPPACKET_Template) {
   1687         continue;
   1688       }
   1689       switch (pNode->GetClassID()) {
   1690         case XFA_ELEMENT_PageSet: {
   1691           CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode;
   1692           pContainerItem->m_pFormNode = XFA_NodeMerge_CloneOrMergeContainer(
   1693               pDocument, pParentNode, pContainerItem->m_pFormNode, TRUE);
   1694         } break;
   1695         case XFA_ELEMENT_PageArea: {
   1696           CXFA_ContainerLayoutItem* pFormLayout = pContainerItem;
   1697           CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode;
   1698           FX_BOOL bIsExistForm = TRUE;
   1699           for (int32_t iLevel = 0; iLevel < 3; iLevel++) {
   1700             pFormLayout = (CXFA_ContainerLayoutItem*)pFormLayout->m_pFirstChild;
   1701             if (iLevel == 2) {
   1702               while (pFormLayout &&
   1703                      !XFA_ItemLayoutProcessor_IsTakingSpace(
   1704                          pFormLayout->m_pFormNode)) {
   1705                 pFormLayout =
   1706                     (CXFA_ContainerLayoutItem*)pFormLayout->m_pNextSibling;
   1707               }
   1708             }
   1709             if (pFormLayout == NULL) {
   1710               bIsExistForm = FALSE;
   1711               break;
   1712             }
   1713           }
   1714           if (bIsExistForm) {
   1715             CXFA_Node* pNewSubform = pFormLayout->m_pFormNode;
   1716             if (pContainerItem->m_pOldSubform != NULL &&
   1717                 pContainerItem->m_pOldSubform != pNewSubform) {
   1718               CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance(
   1719                   pDocument, pContainerItem->m_pFormNode->GetClassID(),
   1720                   pContainerItem->m_pFormNode->GetNameHash(), pParentNode);
   1721               CXFA_ContainerIterator sIterator(pExistingNode);
   1722               for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
   1723                    pNode = sIterator.MoveToNext()) {
   1724                 if (pNode->GetClassID() != XFA_ELEMENT_ContentArea) {
   1725                   CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>(
   1726                       pNode->GetUserData(XFA_LAYOUTITEMKEY));
   1727                   if (pLayoutItem) {
   1728                     pNotify->OnLayoutEvent(pDocLayout, pLayoutItem,
   1729                                            XFA_LAYOUTEVENT_ItemRemoving);
   1730                     delete pLayoutItem;
   1731                   }
   1732                 }
   1733               }
   1734               if (pExistingNode) {
   1735                 pParentNode->RemoveChild(pExistingNode);
   1736               }
   1737             }
   1738             pContainerItem->m_pOldSubform = pNewSubform;
   1739           }
   1740           pContainerItem->m_pFormNode = pDocument->DataMerge_CopyContainer(
   1741               pContainerItem->m_pFormNode, pParentNode,
   1742               (CXFA_Node*)pDocument->GetXFANode(XFA_HASHCODE_Record), TRUE);
   1743         } break;
   1744         case XFA_ELEMENT_ContentArea: {
   1745           CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode;
   1746           for (CXFA_Node* pChildNode =
   1747                    pParentNode->GetNodeItem(XFA_NODEITEM_FirstChild);
   1748                pChildNode;
   1749                pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
   1750             if (pChildNode->GetTemplateNode() != pContainerItem->m_pFormNode) {
   1751               continue;
   1752             }
   1753             pContainerItem->m_pFormNode = pChildNode;
   1754             break;
   1755           }
   1756         } break;
   1757         default:
   1758           break;
   1759       }
   1760     }
   1761     if (!pPendingPageSet->GetNodeItem(XFA_NODEITEM_Parent)) {
   1762       CXFA_Node* pFormToplevelSubform =
   1763           ((CXFA_Node*)pDocument->GetXFANode(XFA_HASHCODE_Form))
   1764               ->GetFirstChildByClass(XFA_ELEMENT_Subform);
   1765       pFormToplevelSubform->InsertChild(pPendingPageSet);
   1766     }
   1767     pDocument->DataMerge_UpdateBindingRelations(pPendingPageSet);
   1768     pPendingPageSet->SetFlag(XFA_NODEFLAG_Initialized);
   1769   }
   1770   pPendingPageSet = GetRootLayoutItem()->m_pFormNode;
   1771   while (pPendingPageSet) {
   1772     CXFA_Node* pNextPendingPageSet =
   1773         pPendingPageSet->GetNextSameClassSibling(XFA_ELEMENT_PageSet);
   1774     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode>
   1775         sIterator(pPendingPageSet);
   1776     CXFA_Node* pNode = sIterator.GetCurrent();
   1777     while (pNode) {
   1778       if (pNode->HasFlag(XFA_NODEFLAG_UnusedNode)) {
   1779         if (pNode->GetObjectType() == XFA_OBJECTTYPE_ContainerNode) {
   1780           XFA_ELEMENT eCurId = pNode->GetClassID();
   1781           if (eCurId == XFA_ELEMENT_PageArea || eCurId == XFA_ELEMENT_PageSet) {
   1782             CXFA_ContainerIterator iteChild(pNode);
   1783             CXFA_Node* pChildNode = iteChild.MoveToNext();
   1784             for (; pChildNode; pChildNode = iteChild.MoveToNext()) {
   1785               CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>(
   1786                   pChildNode->GetUserData(XFA_LAYOUTITEMKEY));
   1787               if (pLayoutItem) {
   1788                 pNotify->OnLayoutEvent(pDocLayout, pLayoutItem,
   1789                                        XFA_LAYOUTEVENT_ItemRemoving);
   1790                 delete pLayoutItem;
   1791               }
   1792             }
   1793           } else if (eCurId != XFA_ELEMENT_ContentArea) {
   1794             CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>(
   1795                 pNode->GetUserData(XFA_LAYOUTITEMKEY));
   1796             if (pLayoutItem) {
   1797               pNotify->OnLayoutEvent(pDocLayout, pLayoutItem,
   1798                                      XFA_LAYOUTEVENT_ItemRemoving);
   1799               delete pLayoutItem;
   1800             }
   1801           }
   1802           CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext();
   1803           pNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pNode);
   1804           pNode = pNext;
   1805         } else {
   1806           pNode->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE);
   1807           pNode->SetFlag(XFA_NODEFLAG_Initialized);
   1808           pNode = sIterator.MoveToNext();
   1809         }
   1810       } else {
   1811         pNode->SetFlag(XFA_NODEFLAG_Initialized);
   1812         pNode = sIterator.MoveToNext();
   1813       }
   1814     }
   1815     pPendingPageSet = pNextPendingPageSet;
   1816   }
   1817 }
   1818 void CXFA_LayoutPageMgr::LayoutPageSetContents() {
   1819   CXFA_ContainerLayoutItem* pRootLayoutItem = this->GetRootLayoutItem();
   1820   for (; pRootLayoutItem;
   1821        pRootLayoutItem =
   1822            (CXFA_ContainerLayoutItem*)pRootLayoutItem->m_pNextSibling) {
   1823     CXFA_NodeIteratorTemplate<
   1824         CXFA_ContainerLayoutItem,
   1825         CXFA_TraverseStrategy_ContentAreaContainerLayoutItem>
   1826         iterator(pRootLayoutItem);
   1827     for (CXFA_ContainerLayoutItem* pContainerItem = iterator.GetCurrent();
   1828          pContainerItem; pContainerItem = iterator.MoveToNext()) {
   1829       CXFA_Node* pNode = pContainerItem->m_pFormNode;
   1830       switch (pNode->GetClassID()) {
   1831         case XFA_ELEMENT_PageArea:
   1832           m_pLayoutProcessor->GetRootRootItemLayoutProcessor()
   1833               ->DoLayoutPageArea(pContainerItem);
   1834           break;
   1835         default:
   1836           break;
   1837       }
   1838     }
   1839   }
   1840 }
   1841 void XFA_SyncContainer(IXFA_Notify* pNotify,
   1842                        IXFA_DocLayout* pDocLayout,
   1843                        CXFA_LayoutItem* pContainerItem,
   1844                        FX_DWORD dwRelevant,
   1845                        FX_BOOL bVisible,
   1846                        int32_t nPageIndex) {
   1847   FX_BOOL bVisibleItem = FALSE;
   1848   FX_DWORD dwStatus = 0;
   1849   FX_DWORD dwRelevantContainer = 0;
   1850   if (bVisible) {
   1851     XFA_ATTRIBUTEENUM eAttributeValue =
   1852         pContainerItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Presence);
   1853     if (eAttributeValue == XFA_ATTRIBUTEENUM_Visible ||
   1854         eAttributeValue == XFA_ATTRIBUTEENUM_Unknown) {
   1855       bVisibleItem = TRUE;
   1856     }
   1857     dwRelevantContainer =
   1858         XFA_GetRelevant(pContainerItem->m_pFormNode, dwRelevant);
   1859     dwStatus =
   1860         (bVisibleItem ? XFA_LAYOUTSTATUS_Visible : 0) | dwRelevantContainer;
   1861   }
   1862   pNotify->OnLayoutEvent(pDocLayout, pContainerItem, XFA_LAYOUTEVENT_ItemAdded,
   1863                          (void*)(uintptr_t)nPageIndex,
   1864                          (void*)(uintptr_t)dwStatus);
   1865   for (CXFA_LayoutItem* pChild = pContainerItem->m_pFirstChild; pChild;
   1866        pChild = pChild->m_pNextSibling) {
   1867     if (pChild->IsContentLayoutItem()) {
   1868       XFA_SyncContainer(pNotify, pDocLayout, pChild, dwRelevantContainer,
   1869                         bVisibleItem, nPageIndex);
   1870     }
   1871   }
   1872 }
   1873 void CXFA_LayoutPageMgr::SyncLayoutData() {
   1874   MergePageSetContents();
   1875   LayoutPageSetContents();
   1876   IXFA_Notify* pNotify =
   1877       m_pTemplatePageSetRoot->GetDocument()->GetParser()->GetNotify();
   1878   int32_t nPageIdx = -1;
   1879   CXFA_ContainerLayoutItem* pRootLayoutItem = this->GetRootLayoutItem();
   1880   for (; pRootLayoutItem;
   1881        pRootLayoutItem =
   1882            (CXFA_ContainerLayoutItem*)pRootLayoutItem->m_pNextSibling) {
   1883     CXFA_NodeIteratorTemplate<
   1884         CXFA_ContainerLayoutItem,
   1885         CXFA_TraverseStrategy_ContentAreaContainerLayoutItem>
   1886         iteratorParent(pRootLayoutItem);
   1887     for (CXFA_ContainerLayoutItem* pContainerItem = iteratorParent.GetCurrent();
   1888          pContainerItem; pContainerItem = iteratorParent.MoveToNext()) {
   1889       switch (pContainerItem->m_pFormNode->GetClassID()) {
   1890         case XFA_ELEMENT_PageArea: {
   1891           nPageIdx++;
   1892           FX_DWORD dwRelevant =
   1893               XFA_LAYOUTSTATUS_Viewable | XFA_LAYOUTSTATUS_Printable;
   1894           CXFA_NodeIteratorTemplate<CXFA_LayoutItem,
   1895                                     CXFA_TraverseStrategy_LayoutItem>
   1896               iterator(pContainerItem);
   1897           CXFA_LayoutItem* pChildLayoutItem = iterator.GetCurrent();
   1898           while (pChildLayoutItem) {
   1899             CXFA_ContentLayoutItem* pContentItem =
   1900                 pChildLayoutItem->AsContentLayoutItem();
   1901             if (!pContentItem) {
   1902               pChildLayoutItem = iterator.MoveToNext();
   1903               continue;
   1904             }
   1905             FX_BOOL bVisible =
   1906                 (pContentItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Presence) ==
   1907                  XFA_ATTRIBUTEENUM_Visible);
   1908             FX_DWORD dwRelevantChild =
   1909                 XFA_GetRelevant(pContentItem->m_pFormNode, dwRelevant);
   1910             XFA_SyncContainer(pNotify, m_pLayoutProcessor, pContentItem,
   1911                               dwRelevantChild, bVisible, nPageIdx);
   1912             pChildLayoutItem = iterator.SkipChildrenAndMoveToNext();
   1913           }
   1914         } break;
   1915         default:
   1916           break;
   1917       }
   1918     }
   1919   }
   1920   int32_t nPage = m_PageArray.GetSize();
   1921   for (int32_t i = nPage - 1; i >= m_nAvailPages; i--) {
   1922     CXFA_ContainerLayoutItem* pPage = m_PageArray[i];
   1923     m_PageArray.RemoveAt(i);
   1924     pNotify->OnPageEvent(pPage, XFA_PAGEEVENT_PageRemoved);
   1925     delete pPage;
   1926   }
   1927   ClearRecordList();
   1928 }
   1929 void XFA_ReleaseLayoutItem_NoPageArea(CXFA_LayoutItem* pLayoutItem) {
   1930   CXFA_LayoutItem* pNext, * pNode = pLayoutItem->m_pFirstChild;
   1931   while (pNode) {
   1932     pNext = pNode->m_pNextSibling;
   1933     pNode->m_pParent = NULL;
   1934     XFA_ReleaseLayoutItem_NoPageArea(pNode);
   1935     pNode = pNext;
   1936   }
   1937   if (pLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) {
   1938     delete pLayoutItem;
   1939   }
   1940 }
   1941 void CXFA_LayoutPageMgr::PrepareLayout() {
   1942   m_pPageSetCurRoot = NULL;
   1943   m_ePageSetMode = XFA_ATTRIBUTEENUM_OrderedOccurrence;
   1944   m_nAvailPages = 0;
   1945   ClearRecordList();
   1946   if (!m_pPageSetLayoutItemRoot) {
   1947     return;
   1948   }
   1949   CXFA_ContainerLayoutItem* pRootLayoutItem = m_pPageSetLayoutItemRoot;
   1950   if (pRootLayoutItem &&
   1951       pRootLayoutItem->m_pFormNode->GetPacketID() == XFA_XDPPACKET_Form) {
   1952     CXFA_Node* pPageSetFormNode = pRootLayoutItem->m_pFormNode;
   1953     pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.RemoveAll();
   1954     if (pPageSetFormNode->HasFlag(XFA_NODEFLAG_HasRemoved)) {
   1955       XFA_ReleaseLayoutItem(pRootLayoutItem);
   1956       m_pPageSetLayoutItemRoot = NULL;
   1957       pRootLayoutItem = NULL;
   1958       pPageSetFormNode = NULL;
   1959       m_PageArray.RemoveAll();
   1960     }
   1961     while (pPageSetFormNode) {
   1962       CXFA_Node* pNextPageSet =
   1963           pPageSetFormNode->GetNextSameClassSibling(XFA_ELEMENT_PageSet);
   1964       pPageSetFormNode->GetNodeItem(XFA_NODEITEM_Parent)
   1965           ->RemoveChild(pPageSetFormNode, FALSE);
   1966       pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.Add(
   1967           pPageSetFormNode);
   1968       pPageSetFormNode = pNextPageSet;
   1969     }
   1970   }
   1971 #if defined(_XFA_LAYOUTITEM_MAPCACHE_) || defined(_XFA_LAYOUTITEM_ProcessCACHE_)
   1972   pRootLayoutItem = m_pPageSetLayoutItemRoot;
   1973   CXFA_ContainerLayoutItem* pNextLayout = NULL;
   1974   for (; pRootLayoutItem; pRootLayoutItem = pNextLayout) {
   1975     pNextLayout = (CXFA_ContainerLayoutItem*)pRootLayoutItem->m_pNextSibling;
   1976     SaveLayoutItem(pRootLayoutItem);
   1977     delete pRootLayoutItem;
   1978   }
   1979   m_pPageSetLayoutItemRoot = NULL;
   1980 #else
   1981   IXFA_Notify* pNotify =
   1982       m_pLayoutProcessor->GetDocument()->GetParser()->GetNotify();
   1983   pRootLayoutItem = m_pPageSetLayoutItemRoot;
   1984   for (; pRootLayoutItem;
   1985        pRootLayoutItem =
   1986            (CXFA_ContainerLayoutItem*)pRootLayoutItem->m_pNextSibling) {
   1987     CXFA_NodeIteratorTemplate<CXFA_ContainerLayoutItem,
   1988                               CXFA_TraverseStrategy_PageAreaContainerLayoutItem>
   1989         iterator(pRootLayoutItem);
   1990     for (CXFA_ContainerLayoutItem* pContainerItem = iterator.GetCurrent();
   1991          pContainerItem; pContainerItem = iterator.MoveToNext()) {
   1992       if (pContainerItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) {
   1993         continue;
   1994       }
   1995       CXFA_NodeIteratorTemplate<CXFA_LayoutItem,
   1996                                 CXFA_TraverseStrategy_LayoutItem>
   1997           iterator(pContainerItem);
   1998       for (CXFA_LayoutItem* pLayoutItem = iterator.GetCurrent(); pLayoutItem;
   1999            pLayoutItem = iterator.MoveToNext()) {
   2000         if (!pLayoutItem->IsContentLayoutItem()) {
   2001           continue;
   2002         }
   2003         pNotify->OnLayoutEvent(m_pLayoutProcessor, pLayoutItem,
   2004                                XFA_LAYOUTEVENT_ItemRemoving);
   2005       }
   2006       pNotify->OnPageEvent(pContainerItem, XFA_PAGEEVENT_PageRemoved);
   2007     }
   2008   }
   2009   pRootLayoutItem = m_pPageSetLayoutItemRoot;
   2010   CXFA_ContainerLayoutItem* pNextLayout = NULL;
   2011   for (; pRootLayoutItem; pRootLayoutItem = pNextLayout) {
   2012     pNextLayout = (CXFA_ContainerLayoutItem*)pRootLayoutItem->m_pNextSibling;
   2013     XFA_ReleaseLayoutItem_NoPageArea(pRootLayoutItem);
   2014   }
   2015   m_pPageSetLayoutItemRoot = NULL;
   2016 #endif
   2017 }
   2018