• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
GetFirstChild(CXFA_ContainerLayoutItem * pLayoutItem)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 
GetNextSibling(CXFA_ContainerLayoutItem * pLayoutItem)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 
GetParent(CXFA_ContainerLayoutItem * pLayoutItem)56   static CXFA_ContainerLayoutItem* GetParent(
57       CXFA_ContainerLayoutItem* pLayoutItem) {
58     return static_cast<CXFA_ContainerLayoutItem*>(pLayoutItem->m_pParent);
59   }
60 };
61 
GetRelevant(CXFA_Node * pFormItem,uint32_t dwParentRelvant)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 
SyncContainer(CXFA_FFNotify * pNotify,CXFA_LayoutProcessor * pDocLayout,CXFA_LayoutItem * pContainerItem,uint32_t dwRelevant,bool bVisible,int32_t nPageIndex)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 
ReorderLayoutItemToTail(CXFA_ContainerLayoutItem * pLayoutItem)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 
RemoveLayoutItem(CXFA_ContainerLayoutItem * pLayoutItem)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 
ResolveBreakTarget(CXFA_Node * pPageSetRoot,bool bNewExprStyle,CFX_WideStringC & wsTargetExpr)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 
SetLayoutGeneratedNodeFlag(CXFA_Node * pNode)183 void SetLayoutGeneratedNodeFlag(CXFA_Node* pNode) {
184   pNode->SetFlag(XFA_NodeFlag_LayoutGeneratedNode, false);
185   pNode->ClearFlag(XFA_NodeFlag_UnusedNode);
186 }
187 
CheckContentAreaNotUsed(CXFA_ContainerLayoutItem * pPageAreaLayoutItem,CXFA_Node * pContentArea,CXFA_ContainerLayoutItem * & pContentAreaLayoutItem)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 
SyncRemoveLayoutItem(CXFA_LayoutItem * pParentLayoutItem,CXFA_FFNotify * pNotify,CXFA_LayoutProcessor * pDocLayout)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:
CXFA_ContainerRecord(CXFA_ContainerLayoutItem * pPageSet=nullptr,CXFA_ContainerLayoutItem * pPageArea=nullptr,CXFA_ContainerLayoutItem * pContentArea=nullptr)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 
CXFA_LayoutPageMgr(CXFA_LayoutProcessor * pLayoutProcessor)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 
~CXFA_LayoutPageMgr()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 
InitLayoutPage(CXFA_Node * pFormNode)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 
PrepareFirstPage(CXFA_Node * pRootSubform)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 
AppendNewPage(bool bFirstTemPage)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 
RemoveLayoutRecord(CXFA_ContainerRecord * pNewRecord,CXFA_ContainerRecord * pPrevRecord)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 
ReorderPendingLayoutRecordToTail(CXFA_ContainerRecord * pNewRecord,CXFA_ContainerRecord * pPrevRecord)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 
SubmitContentItem(CXFA_ContentLayoutItem * pContentLayoutItem,XFA_ItemLayoutProcessorResult eStatus)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 
GetAvailHeight()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 
XFA_LayoutPageMgr_RunBreakTestScript(CXFA_Node * pTestScript)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 
CreateContainerRecord(CXFA_Node * pPageNode,bool bCreateNew)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 
AddPageAreaLayoutItem(CXFA_ContainerRecord * pNewRecord,CXFA_Node * pNewPageArea)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 
AddContentAreaLayoutItem(CXFA_ContainerRecord * pNewRecord,CXFA_Node * pContentArea)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 
FinishPaginatedPageSets()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 
GetPageCount() const725 int32_t CXFA_LayoutPageMgr::GetPageCount() const {
726   return m_PageArray.GetSize();
727 }
728 
GetPage(int32_t index) const729 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 
GetPageIndex(const CXFA_ContainerLayoutItem * pPage) const735 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 
RunBreak(XFA_Element eBreakType,XFA_ATTRIBUTEENUM eTargetType,CXFA_Node * pTarget,bool bStartNew)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 
ExecuteBreakBeforeOrAfter(CXFA_Node * pCurNode,bool bBefore,CXFA_Node * & pBreakLeaderTemplate,CXFA_Node * & pBreakTrailerTemplate)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 
ProcessBreakBeforeOrAfter(CXFA_Node * pBreakNode,bool bBefore,CXFA_Node * & pBreakLeaderNode,CXFA_Node * & pBreakTrailerNode,bool & bCreatePage)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 
ProcessBookendLeaderOrTrailer(CXFA_Node * pBookendNode,bool bLeader,CXFA_Node * & pBookendAppendNode)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 
BreakOverflow(CXFA_Node * pOverflowNode,CXFA_Node * & pLeaderTemplate,CXFA_Node * & pTrailerTemplate,bool bCreatePage)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 
ProcessOverflow(CXFA_Node * pFormNode,CXFA_Node * & pLeaderNode,CXFA_Node * & pTrailerNode,bool bDataMerge,bool bCreatePage)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 
ResolveBookendLeaderOrTrailer(CXFA_Node * pBookendNode,bool bLeader,CXFA_Node * & pBookendAppendTemplate)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 
FindPageAreaFromPageSet(CXFA_Node * pPageSet,CXFA_Node * pStartChild,CXFA_Node * pTargetPageArea,CXFA_Node * pTargetContentArea,bool bNewPage,bool bQuery)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 
FindPageAreaFromPageSet_Ordered(CXFA_Node * pPageSet,CXFA_Node * pStartChild,CXFA_Node * pTargetPageArea,CXFA_Node * pTargetContentArea,bool bNewPage,bool bQuery)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 
FindPageAreaFromPageSet_SimplexDuplex(CXFA_Node * pPageSet,CXFA_Node * pStartChild,CXFA_Node * pTargetPageArea,CXFA_Node * pTargetContentArea,bool bNewPage,bool bQuery,XFA_ATTRIBUTEENUM ePreferredPosition)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 
MatchPageAreaOddOrEven(CXFA_Node * pPageArea,bool bLastMatch)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 
GetNextAvailPageArea(CXFA_Node * pTargetPageArea,CXFA_Node * pTargetContentArea,bool bNewPage,bool bQuery)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 
GetNextContentArea(CXFA_Node * pContentArea)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 
InitPageSetMap()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 
CreateMinPageRecord(CXFA_Node * pPageArea,bool bTargetPageArea,bool bCreateLast)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 
CreateMinPageSetRecord(CXFA_Node * pPageSet,bool bCreateAll)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 
CreateNextMinRecord(CXFA_Node * pRecordNode)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 
ProcessLastPageSet()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 
GetNextAvailContentHeight(FX_FLOAT fChildHeight)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 
ClearData()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 
SaveLayoutItem(CXFA_LayoutItem * pParentLayoutItem)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 
QueryOverflow(CXFA_Node * pFormNode,CXFA_LayoutContext * pLayoutContext)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 
MergePageSetContents()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 
LayoutPageSetContents()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 
SyncLayoutData()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 
XFA_ReleaseLayoutItem_NoPageArea(CXFA_LayoutItem * pLayoutItem)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 
PrepareLayout()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