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