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