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