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