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