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_itemlayoutprocessor.h" 8 9 #include <algorithm> 10 #include <memory> 11 #include <utility> 12 #include <vector> 13 14 #include "fxjs/xfa/cjx_object.h" 15 #include "third_party/base/logging.h" 16 #include "third_party/base/ptr_util.h" 17 #include "third_party/base/stl_util.h" 18 #include "xfa/fxfa/cxfa_ffnotify.h" 19 #include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" 20 #include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" 21 #include "xfa/fxfa/parser/cxfa_document.h" 22 #include "xfa/fxfa/parser/cxfa_keep.h" 23 #include "xfa/fxfa/parser/cxfa_layoutcontext.h" 24 #include "xfa/fxfa/parser/cxfa_layoutpagemgr.h" 25 #include "xfa/fxfa/parser/cxfa_localemgr.h" 26 #include "xfa/fxfa/parser/cxfa_margin.h" 27 #include "xfa/fxfa/parser/cxfa_measurement.h" 28 #include "xfa/fxfa/parser/cxfa_node.h" 29 #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" 30 #include "xfa/fxfa/parser/cxfa_occur.h" 31 #include "xfa/fxfa/parser/cxfa_para.h" 32 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h" 33 #include "xfa/fxfa/parser/xfa_utils.h" 34 35 namespace { 36 37 std::vector<WideString> SeparateStringW(const wchar_t* pStr, 38 int32_t iStrLen, 39 wchar_t delimiter) { 40 std::vector<WideString> ret; 41 if (!pStr) 42 return ret; 43 if (iStrLen < 0) 44 iStrLen = wcslen(pStr); 45 46 const wchar_t* pToken = pStr; 47 const wchar_t* pEnd = pStr + iStrLen; 48 while (true) { 49 if (pStr >= pEnd || delimiter == *pStr) { 50 ret.push_back(WideString(pToken, pStr - pToken)); 51 pToken = pStr + 1; 52 if (pStr >= pEnd) 53 break; 54 } 55 pStr++; 56 } 57 return ret; 58 } 59 60 void UpdateWidgetSize(CXFA_ContentLayoutItem* pLayoutItem, 61 float* fWidth, 62 float* fHeight) { 63 CXFA_Node* pNode = pLayoutItem->m_pFormNode; 64 switch (pNode->GetElementType()) { 65 case XFA_Element::Subform: 66 case XFA_Element::Area: 67 case XFA_Element::ExclGroup: 68 case XFA_Element::SubformSet: { 69 if (*fWidth < -XFA_LAYOUT_FLOAT_PERCISION) 70 *fWidth = pLayoutItem->m_sSize.width; 71 if (*fHeight < -XFA_LAYOUT_FLOAT_PERCISION) 72 *fHeight = pLayoutItem->m_sSize.height; 73 break; 74 } 75 case XFA_Element::Draw: 76 case XFA_Element::Field: { 77 pNode->GetDocument()->GetNotify()->StartFieldDrawLayout(pNode, *fWidth, 78 *fHeight); 79 break; 80 } 81 default: 82 NOTREACHED(); 83 } 84 } 85 86 CFX_SizeF CalculateContainerSpecifiedSize(CXFA_Node* pFormNode, 87 bool* bContainerWidthAutoSize, 88 bool* bContainerHeightAutoSize) { 89 *bContainerWidthAutoSize = true; 90 *bContainerHeightAutoSize = true; 91 92 XFA_Element eType = pFormNode->GetElementType(); 93 94 CFX_SizeF containerSize; 95 if (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup) { 96 Optional<CXFA_Measurement> wValue = 97 pFormNode->JSObject()->TryMeasure(XFA_Attribute::W, false); 98 if (wValue && wValue->GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { 99 containerSize.width = wValue->ToUnit(XFA_Unit::Pt); 100 *bContainerWidthAutoSize = false; 101 } 102 103 Optional<CXFA_Measurement> hValue = 104 pFormNode->JSObject()->TryMeasure(XFA_Attribute::H, false); 105 if (hValue && hValue->GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { 106 containerSize.height = hValue->ToUnit(XFA_Unit::Pt); 107 *bContainerHeightAutoSize = false; 108 } 109 } 110 111 if (*bContainerWidthAutoSize && eType == XFA_Element::Subform) { 112 Optional<CXFA_Measurement> maxW = 113 pFormNode->JSObject()->TryMeasure(XFA_Attribute::MaxW, false); 114 if (maxW && maxW->GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { 115 containerSize.width = maxW->ToUnit(XFA_Unit::Pt); 116 *bContainerWidthAutoSize = false; 117 } 118 119 Optional<CXFA_Measurement> maxH = 120 pFormNode->JSObject()->TryMeasure(XFA_Attribute::MaxH, false); 121 if (maxH && maxH->GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { 122 containerSize.height = maxH->ToUnit(XFA_Unit::Pt); 123 *bContainerHeightAutoSize = false; 124 } 125 } 126 return containerSize; 127 } 128 129 CFX_SizeF CalculateContainerComponentSizeFromContentSize( 130 CXFA_Node* pFormNode, 131 bool bContainerWidthAutoSize, 132 float fContentCalculatedWidth, 133 bool bContainerHeightAutoSize, 134 float fContentCalculatedHeight, 135 const CFX_SizeF& currentContainerSize) { 136 CFX_SizeF componentSize = currentContainerSize; 137 CXFA_Margin* pMarginNode = 138 pFormNode->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin); 139 if (bContainerWidthAutoSize) { 140 componentSize.width = fContentCalculatedWidth; 141 if (pMarginNode) { 142 Optional<CXFA_Measurement> leftInset = 143 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::LeftInset, false); 144 if (leftInset) 145 componentSize.width += leftInset->ToUnit(XFA_Unit::Pt); 146 147 Optional<CXFA_Measurement> rightInset = 148 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::RightInset, false); 149 if (rightInset) 150 componentSize.width += rightInset->ToUnit(XFA_Unit::Pt); 151 } 152 } 153 154 if (bContainerHeightAutoSize) { 155 componentSize.height = fContentCalculatedHeight; 156 if (pMarginNode) { 157 Optional<CXFA_Measurement> topInset = 158 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::TopInset, false); 159 if (topInset) 160 componentSize.height += topInset->ToUnit(XFA_Unit::Pt); 161 162 Optional<CXFA_Measurement> bottomInset = 163 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::BottomInset, 164 false); 165 if (bottomInset) 166 componentSize.height += bottomInset->ToUnit(XFA_Unit::Pt); 167 } 168 } 169 return componentSize; 170 } 171 172 void RelocateTableRowCells(CXFA_ContentLayoutItem* pLayoutRow, 173 const std::vector<float>& rgSpecifiedColumnWidths, 174 XFA_AttributeEnum eLayout) { 175 bool bContainerWidthAutoSize = true; 176 bool bContainerHeightAutoSize = true; 177 CFX_SizeF containerSize = CalculateContainerSpecifiedSize( 178 pLayoutRow->m_pFormNode, &bContainerWidthAutoSize, 179 &bContainerHeightAutoSize); 180 CXFA_Margin* pMarginNode = 181 pLayoutRow->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( 182 XFA_Element::Margin); 183 float fLeftInset = 0; 184 float fTopInset = 0; 185 float fRightInset = 0; 186 float fBottomInset = 0; 187 if (pMarginNode) { 188 fLeftInset = pMarginNode->JSObject() 189 ->GetMeasure(XFA_Attribute::LeftInset) 190 .ToUnit(XFA_Unit::Pt); 191 fTopInset = pMarginNode->JSObject() 192 ->GetMeasure(XFA_Attribute::TopInset) 193 .ToUnit(XFA_Unit::Pt); 194 fRightInset = pMarginNode->JSObject() 195 ->GetMeasure(XFA_Attribute::RightInset) 196 .ToUnit(XFA_Unit::Pt); 197 fBottomInset = pMarginNode->JSObject() 198 ->GetMeasure(XFA_Attribute::BottomInset) 199 .ToUnit(XFA_Unit::Pt); 200 } 201 202 float fContentWidthLimit = 203 bContainerWidthAutoSize ? FLT_MAX 204 : containerSize.width - fLeftInset - fRightInset; 205 float fContentCurrentHeight = 206 pLayoutRow->m_sSize.height - fTopInset - fBottomInset; 207 float fContentCalculatedWidth = 0; 208 float fContentCalculatedHeight = 0; 209 float fCurrentColX = 0; 210 int32_t nCurrentColIdx = 0; 211 bool bMetWholeRowCell = false; 212 213 for (auto* pLayoutChild = 214 static_cast<CXFA_ContentLayoutItem*>(pLayoutRow->m_pFirstChild); 215 pLayoutChild; pLayoutChild = static_cast<CXFA_ContentLayoutItem*>( 216 pLayoutChild->m_pNextSibling)) { 217 int32_t nOriginalColSpan = 218 pLayoutChild->m_pFormNode->JSObject()->GetInteger( 219 XFA_Attribute::ColSpan); 220 int32_t nColSpan = nOriginalColSpan; 221 float fColSpanWidth = 0; 222 if (nColSpan == -1 || 223 nCurrentColIdx + nColSpan > 224 pdfium::CollectionSize<int32_t>(rgSpecifiedColumnWidths)) { 225 nColSpan = pdfium::CollectionSize<int32_t>(rgSpecifiedColumnWidths) - 226 nCurrentColIdx; 227 } 228 for (int32_t i = 0; i < nColSpan; i++) 229 fColSpanWidth += rgSpecifiedColumnWidths[nCurrentColIdx + i]; 230 231 if (nColSpan != nOriginalColSpan) { 232 fColSpanWidth = 233 bMetWholeRowCell ? 0 : std::max(fColSpanWidth, 234 pLayoutChild->m_sSize.height); 235 } 236 if (nOriginalColSpan == -1) 237 bMetWholeRowCell = true; 238 239 pLayoutChild->m_sPos = CFX_PointF(fCurrentColX, 0); 240 pLayoutChild->m_sSize.width = fColSpanWidth; 241 if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) 242 continue; 243 244 fCurrentColX += fColSpanWidth; 245 nCurrentColIdx += nColSpan; 246 float fNewHeight = bContainerHeightAutoSize ? -1 : fContentCurrentHeight; 247 UpdateWidgetSize(pLayoutChild, &fColSpanWidth, &fNewHeight); 248 pLayoutChild->m_sSize.height = fNewHeight; 249 if (bContainerHeightAutoSize) { 250 fContentCalculatedHeight = 251 std::max(fContentCalculatedHeight, pLayoutChild->m_sSize.height); 252 } 253 } 254 255 if (bContainerHeightAutoSize) { 256 for (CXFA_ContentLayoutItem* pLayoutChild = 257 (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; 258 pLayoutChild; 259 pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { 260 UpdateWidgetSize(pLayoutChild, &pLayoutChild->m_sSize.width, 261 &fContentCalculatedHeight); 262 float fOldChildHeight = pLayoutChild->m_sSize.height; 263 pLayoutChild->m_sSize.height = fContentCalculatedHeight; 264 CXFA_Para* pParaNode = 265 pLayoutChild->m_pFormNode->GetFirstChildByClass<CXFA_Para>( 266 XFA_Element::Para); 267 if (pParaNode && pLayoutChild->m_pFirstChild) { 268 float fOffHeight = fContentCalculatedHeight - fOldChildHeight; 269 XFA_AttributeEnum eVType = 270 pParaNode->JSObject()->GetEnum(XFA_Attribute::VAlign); 271 switch (eVType) { 272 case XFA_AttributeEnum::Middle: 273 fOffHeight = fOffHeight / 2; 274 break; 275 case XFA_AttributeEnum::Bottom: 276 break; 277 case XFA_AttributeEnum::Top: 278 default: 279 fOffHeight = 0; 280 break; 281 } 282 if (fOffHeight > 0) { 283 for (CXFA_ContentLayoutItem* pInnerLayoutChild = 284 (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild; 285 pInnerLayoutChild; 286 pInnerLayoutChild = 287 (CXFA_ContentLayoutItem*)pInnerLayoutChild->m_pNextSibling) { 288 pInnerLayoutChild->m_sPos.y += fOffHeight; 289 } 290 } 291 } 292 } 293 } 294 295 if (bContainerWidthAutoSize) { 296 float fChildSuppliedWidth = fCurrentColX; 297 if (fContentWidthLimit < FLT_MAX && 298 fContentWidthLimit > fChildSuppliedWidth) { 299 fChildSuppliedWidth = fContentWidthLimit; 300 } 301 fContentCalculatedWidth = 302 std::max(fContentCalculatedWidth, fChildSuppliedWidth); 303 } else { 304 fContentCalculatedWidth = containerSize.width - fLeftInset - fRightInset; 305 } 306 307 if (pLayoutRow->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout) == 308 XFA_AttributeEnum::Rl_row) { 309 for (CXFA_ContentLayoutItem* pLayoutChild = 310 (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; 311 pLayoutChild; 312 pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { 313 pLayoutChild->m_sPos.x = fContentCalculatedWidth - 314 pLayoutChild->m_sPos.x - 315 pLayoutChild->m_sSize.width; 316 } 317 } 318 pLayoutRow->m_sSize = CalculateContainerComponentSizeFromContentSize( 319 pLayoutRow->m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, 320 bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); 321 } 322 323 void UpdatePendingItemLayout(CXFA_ItemLayoutProcessor* pProcessor, 324 CXFA_ContentLayoutItem* pLayoutItem) { 325 XFA_AttributeEnum eLayout = 326 pLayoutItem->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); 327 switch (eLayout) { 328 case XFA_AttributeEnum::Row: 329 case XFA_AttributeEnum::Rl_row: 330 RelocateTableRowCells(pLayoutItem, pProcessor->m_rgSpecifiedColumnWidths, 331 eLayout); 332 break; 333 default: 334 break; 335 } 336 } 337 338 void AddTrailerBeforeSplit(CXFA_ItemLayoutProcessor* pProcessor, 339 float fSplitPos, 340 CXFA_ContentLayoutItem* pTrailerLayoutItem, 341 bool bUseInherited) { 342 if (!pTrailerLayoutItem) 343 return; 344 345 float fHeight = pTrailerLayoutItem->m_sSize.height; 346 if (bUseInherited) { 347 float fNewSplitPos = 0; 348 if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) 349 fNewSplitPos = pProcessor->FindSplitPos(fSplitPos - fHeight); 350 if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) 351 pProcessor->SplitLayoutItem(fNewSplitPos); 352 return; 353 } 354 355 UpdatePendingItemLayout(pProcessor, pTrailerLayoutItem); 356 CXFA_Margin* pMarginNode = 357 pProcessor->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( 358 XFA_Element::Margin); 359 float fLeftInset = 0; 360 float fTopInset = 0; 361 float fRightInset = 0; 362 float fBottomInset = 0; 363 if (pMarginNode) { 364 fLeftInset = pMarginNode->JSObject() 365 ->GetMeasure(XFA_Attribute::LeftInset) 366 .ToUnit(XFA_Unit::Pt); 367 fTopInset = pMarginNode->JSObject() 368 ->GetMeasure(XFA_Attribute::TopInset) 369 .ToUnit(XFA_Unit::Pt); 370 fRightInset = pMarginNode->JSObject() 371 ->GetMeasure(XFA_Attribute::RightInset) 372 .ToUnit(XFA_Unit::Pt); 373 fBottomInset = pMarginNode->JSObject() 374 ->GetMeasure(XFA_Attribute::BottomInset) 375 .ToUnit(XFA_Unit::Pt); 376 } 377 378 if (!pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem)) { 379 pTrailerLayoutItem->m_sPos.y = pProcessor->m_fLastRowY; 380 pTrailerLayoutItem->m_sPos.x = pProcessor->m_fLastRowWidth; 381 pProcessor->m_pLayoutItem->m_sSize.width += 382 pTrailerLayoutItem->m_sSize.width; 383 pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); 384 return; 385 } 386 387 float fNewSplitPos = 0; 388 if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) 389 fNewSplitPos = pProcessor->FindSplitPos(fSplitPos - fHeight); 390 391 if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { 392 pProcessor->SplitLayoutItem(fNewSplitPos); 393 pTrailerLayoutItem->m_sPos.y = fNewSplitPos - fTopInset - fBottomInset; 394 } else { 395 pTrailerLayoutItem->m_sPos.y = fSplitPos - fTopInset - fBottomInset; 396 } 397 398 switch (pTrailerLayoutItem->m_pFormNode->JSObject()->GetEnum( 399 XFA_Attribute::HAlign)) { 400 case XFA_AttributeEnum::Right: 401 pTrailerLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.width - 402 fRightInset - 403 pTrailerLayoutItem->m_sSize.width; 404 break; 405 case XFA_AttributeEnum::Center: 406 pTrailerLayoutItem->m_sPos.x = 407 (pProcessor->m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - 408 pTrailerLayoutItem->m_sSize.width) / 409 2; 410 break; 411 case XFA_AttributeEnum::Left: 412 default: 413 pTrailerLayoutItem->m_sPos.x = fLeftInset; 414 break; 415 } 416 pProcessor->m_pLayoutItem->m_sSize.height += fHeight; 417 pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); 418 } 419 420 void AddLeaderAfterSplit(CXFA_ItemLayoutProcessor* pProcessor, 421 CXFA_ContentLayoutItem* pLeaderLayoutItem) { 422 UpdatePendingItemLayout(pProcessor, pLeaderLayoutItem); 423 424 CXFA_Margin* pMarginNode = 425 pProcessor->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( 426 XFA_Element::Margin); 427 float fLeftInset = 0; 428 float fRightInset = 0; 429 if (pMarginNode) { 430 fLeftInset = pMarginNode->JSObject() 431 ->GetMeasure(XFA_Attribute::LeftInset) 432 .ToUnit(XFA_Unit::Pt); 433 fRightInset = pMarginNode->JSObject() 434 ->GetMeasure(XFA_Attribute::RightInset) 435 .ToUnit(XFA_Unit::Pt); 436 } 437 438 float fHeight = pLeaderLayoutItem->m_sSize.height; 439 for (CXFA_ContentLayoutItem* pChildItem = 440 (CXFA_ContentLayoutItem*)pProcessor->m_pLayoutItem->m_pFirstChild; 441 pChildItem; 442 pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { 443 pChildItem->m_sPos.y += fHeight; 444 } 445 pLeaderLayoutItem->m_sPos.y = 0; 446 447 switch (pLeaderLayoutItem->m_pFormNode->JSObject()->GetEnum( 448 XFA_Attribute::HAlign)) { 449 case XFA_AttributeEnum::Right: 450 pLeaderLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.width - 451 fRightInset - 452 pLeaderLayoutItem->m_sSize.width; 453 break; 454 case XFA_AttributeEnum::Center: 455 pLeaderLayoutItem->m_sPos.x = 456 (pProcessor->m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - 457 pLeaderLayoutItem->m_sSize.width) / 458 2; 459 break; 460 case XFA_AttributeEnum::Left: 461 default: 462 pLeaderLayoutItem->m_sPos.x = fLeftInset; 463 break; 464 } 465 pProcessor->m_pLayoutItem->m_sSize.height += fHeight; 466 pProcessor->m_pLayoutItem->AddChild(pLeaderLayoutItem); 467 } 468 469 void AddPendingNode(CXFA_ItemLayoutProcessor* pProcessor, 470 CXFA_Node* pPendingNode, 471 bool bBreakPending) { 472 pProcessor->m_PendingNodes.push_back(pPendingNode); 473 pProcessor->m_bBreakPending = bBreakPending; 474 } 475 476 float InsertPendingItems(CXFA_ItemLayoutProcessor* pProcessor, 477 CXFA_Node* pCurChildNode) { 478 float fTotalHeight = 0; 479 if (pProcessor->m_PendingNodes.empty()) 480 return fTotalHeight; 481 482 if (!pProcessor->m_pLayoutItem) { 483 pProcessor->m_pLayoutItem = 484 pProcessor->CreateContentLayoutItem(pCurChildNode); 485 pProcessor->m_pLayoutItem->m_sSize.clear(); 486 } 487 488 while (!pProcessor->m_PendingNodes.empty()) { 489 auto pPendingProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( 490 pProcessor->m_PendingNodes.front(), nullptr); 491 pProcessor->m_PendingNodes.pop_front(); 492 pPendingProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); 493 CXFA_ContentLayoutItem* pPendingLayoutItem = 494 pPendingProcessor->HasLayoutItem() 495 ? pPendingProcessor->ExtractLayoutItem() 496 : nullptr; 497 if (pPendingLayoutItem) { 498 AddLeaderAfterSplit(pProcessor, pPendingLayoutItem); 499 if (pProcessor->m_bBreakPending) 500 fTotalHeight += pPendingLayoutItem->m_sSize.height; 501 } 502 } 503 return fTotalHeight; 504 } 505 506 XFA_AttributeEnum GetLayout(CXFA_Node* pFormNode, bool* bRootForceTb) { 507 *bRootForceTb = false; 508 Optional<XFA_AttributeEnum> layoutMode = 509 pFormNode->JSObject()->TryEnum(XFA_Attribute::Layout, false); 510 if (layoutMode) 511 return *layoutMode; 512 513 CXFA_Node* pParentNode = pFormNode->GetParent(); 514 if (pParentNode && pParentNode->GetElementType() == XFA_Element::Form) { 515 *bRootForceTb = true; 516 return XFA_AttributeEnum::Tb; 517 } 518 return XFA_AttributeEnum::Position; 519 } 520 521 bool ExistContainerKeep(CXFA_Node* pCurNode, bool bPreFind) { 522 if (!pCurNode || !XFA_ItemLayoutProcessor_IsTakingSpace(pCurNode)) 523 return false; 524 525 CXFA_Node* pPreContainer = bPreFind ? pCurNode->GetPrevContainerSibling() 526 : pCurNode->GetNextContainerSibling(); 527 if (!pPreContainer) 528 return false; 529 530 CXFA_Keep* pKeep = 531 pCurNode->GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep); 532 if (pKeep) { 533 XFA_Attribute eKeepType = XFA_Attribute::Previous; 534 if (!bPreFind) 535 eKeepType = XFA_Attribute::Next; 536 537 Optional<XFA_AttributeEnum> previous = 538 pKeep->JSObject()->TryEnum(eKeepType, false); 539 if (previous) { 540 if (*previous == XFA_AttributeEnum::ContentArea || 541 *previous == XFA_AttributeEnum::PageArea) { 542 return true; 543 } 544 } 545 } 546 547 pKeep = pPreContainer->GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep); 548 if (!pKeep) 549 return false; 550 551 XFA_Attribute eKeepType = XFA_Attribute::Next; 552 if (!bPreFind) 553 eKeepType = XFA_Attribute::Previous; 554 555 Optional<XFA_AttributeEnum> next = 556 pKeep->JSObject()->TryEnum(eKeepType, false); 557 if (!next) 558 return false; 559 if (*next == XFA_AttributeEnum::ContentArea || 560 *next == XFA_AttributeEnum::PageArea) { 561 return true; 562 } 563 return false; 564 } 565 566 bool FindBreakNode(CXFA_Node* pContainerNode, 567 CXFA_Node*& pCurActionNode, 568 XFA_ItemLayoutProcessorStages* nCurStage, 569 bool bBreakBefore) { 570 bool bFindRs = false; 571 for (CXFA_Node* pBreakNode = pContainerNode; pBreakNode; 572 pBreakNode = pBreakNode->GetNextSibling()) { 573 XFA_Attribute eAttributeType = XFA_Attribute::Before; 574 if (!bBreakBefore) 575 eAttributeType = XFA_Attribute::After; 576 577 switch (pBreakNode->GetElementType()) { 578 case XFA_Element::BreakBefore: { 579 if (bBreakBefore) { 580 pCurActionNode = pBreakNode; 581 *nCurStage = XFA_ItemLayoutProcessorStages::BreakBefore; 582 bFindRs = true; 583 } 584 break; 585 } 586 case XFA_Element::BreakAfter: { 587 if (!bBreakBefore) { 588 pCurActionNode = pBreakNode; 589 *nCurStage = XFA_ItemLayoutProcessorStages::BreakAfter; 590 bFindRs = true; 591 } 592 break; 593 } 594 case XFA_Element::Break: 595 if (pBreakNode->JSObject()->GetEnum(eAttributeType) != 596 XFA_AttributeEnum::Auto) { 597 pCurActionNode = pBreakNode; 598 *nCurStage = XFA_ItemLayoutProcessorStages::BreakBefore; 599 if (!bBreakBefore) 600 *nCurStage = XFA_ItemLayoutProcessorStages::BreakAfter; 601 602 bFindRs = true; 603 } 604 break; 605 default: 606 break; 607 } 608 if (bFindRs) 609 break; 610 } 611 return bFindRs; 612 } 613 614 void DeleteLayoutGeneratedNode(CXFA_Node* pGenerateNode) { 615 CXFA_FFNotify* pNotify = pGenerateNode->GetDocument()->GetNotify(); 616 CXFA_LayoutProcessor* pDocLayout = 617 pGenerateNode->GetDocument()->GetDocLayout(); 618 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator( 619 pGenerateNode); 620 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; 621 pNode = sIterator.MoveToNext()) { 622 CXFA_ContentLayoutItem* pCurLayoutItem = 623 static_cast<CXFA_ContentLayoutItem*>( 624 pNode->JSObject()->GetLayoutItem()); 625 CXFA_ContentLayoutItem* pNextLayoutItem = nullptr; 626 while (pCurLayoutItem) { 627 pNextLayoutItem = pCurLayoutItem->m_pNext; 628 pNotify->OnLayoutItemRemoving(pDocLayout, pCurLayoutItem); 629 delete pCurLayoutItem; 630 pCurLayoutItem = pNextLayoutItem; 631 } 632 } 633 pGenerateNode->GetParent()->RemoveChild(pGenerateNode, true); 634 } 635 636 uint8_t HAlignEnumToInt(XFA_AttributeEnum eHAlign) { 637 switch (eHAlign) { 638 case XFA_AttributeEnum::Center: 639 return 1; 640 case XFA_AttributeEnum::Right: 641 return 2; 642 case XFA_AttributeEnum::Left: 643 default: 644 return 0; 645 } 646 } 647 648 XFA_ItemLayoutProcessorResult InsertFlowedItem( 649 CXFA_ItemLayoutProcessor* pThis, 650 CXFA_ItemLayoutProcessor* pProcessor, 651 bool bContainerWidthAutoSize, 652 bool bContainerHeightAutoSize, 653 float fContainerHeight, 654 XFA_AttributeEnum eFlowStrategy, 655 uint8_t* uCurHAlignState, 656 std::vector<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], 657 bool bUseBreakControl, 658 float fAvailHeight, 659 float fRealHeight, 660 float fContentWidthLimit, 661 float* fContentCurRowY, 662 float* fContentCurRowAvailWidth, 663 float* fContentCurRowHeight, 664 bool* bAddedItemInRow, 665 bool* bForceEndPage, 666 CXFA_LayoutContext* pLayoutContext, 667 bool bNewRow) { 668 bool bTakeSpace = 669 XFA_ItemLayoutProcessor_IsTakingSpace(pProcessor->m_pFormNode); 670 uint8_t uHAlign = HAlignEnumToInt( 671 pThis->m_pCurChildNode->JSObject()->GetEnum(XFA_Attribute::HAlign)); 672 if (bContainerWidthAutoSize) 673 uHAlign = 0; 674 675 if ((eFlowStrategy != XFA_AttributeEnum::Rl_tb && 676 uHAlign < *uCurHAlignState) || 677 (eFlowStrategy == XFA_AttributeEnum::Rl_tb && 678 uHAlign > *uCurHAlignState)) { 679 return XFA_ItemLayoutProcessorResult::RowFullBreak; 680 } 681 682 *uCurHAlignState = uHAlign; 683 bool bIsOwnSplit = 684 pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None; 685 bool bUseRealHeight = bTakeSpace && bContainerHeightAutoSize && bIsOwnSplit && 686 pProcessor->m_pFormNode->GetParent()->GetIntact() == 687 XFA_AttributeEnum::None; 688 bool bIsTransHeight = bTakeSpace; 689 if (bIsTransHeight && !bIsOwnSplit) { 690 bool bRootForceTb = false; 691 XFA_AttributeEnum eLayoutStrategy = 692 GetLayout(pProcessor->m_pFormNode, &bRootForceTb); 693 if (eLayoutStrategy == XFA_AttributeEnum::Lr_tb || 694 eLayoutStrategy == XFA_AttributeEnum::Rl_tb) { 695 bIsTransHeight = false; 696 } 697 } 698 699 bool bUseInherited = false; 700 CXFA_LayoutContext layoutContext; 701 if (pThis->m_pPageMgr) { 702 CXFA_Node* pOverflowNode = 703 pThis->m_pPageMgr->QueryOverflow(pThis->m_pFormNode); 704 if (pOverflowNode) { 705 layoutContext.m_pOverflowNode = pOverflowNode; 706 layoutContext.m_pOverflowProcessor = pThis; 707 pLayoutContext = &layoutContext; 708 } 709 } 710 711 XFA_ItemLayoutProcessorResult eRetValue = XFA_ItemLayoutProcessorResult::Done; 712 if (!bNewRow || 713 pProcessor->m_ePreProcessRs == XFA_ItemLayoutProcessorResult::Done) { 714 eRetValue = pProcessor->DoLayout( 715 bTakeSpace ? bUseBreakControl : false, 716 bUseRealHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, 717 bIsTransHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, 718 pLayoutContext); 719 pProcessor->m_ePreProcessRs = eRetValue; 720 } else { 721 eRetValue = pProcessor->m_ePreProcessRs; 722 pProcessor->m_ePreProcessRs = XFA_ItemLayoutProcessorResult::Done; 723 } 724 if (pProcessor->HasLayoutItem() == false) 725 return eRetValue; 726 727 CFX_SizeF childSize = pProcessor->GetCurrentComponentSize(); 728 if (bUseRealHeight && fRealHeight < XFA_LAYOUT_FLOAT_PERCISION) { 729 fRealHeight = FLT_MAX; 730 fAvailHeight = FLT_MAX; 731 } 732 if (bTakeSpace && (childSize.width > 733 *fContentCurRowAvailWidth + XFA_LAYOUT_FLOAT_PERCISION) && 734 (fContentWidthLimit - *fContentCurRowAvailWidth > 735 XFA_LAYOUT_FLOAT_PERCISION)) { 736 return XFA_ItemLayoutProcessorResult::RowFullBreak; 737 } 738 739 CXFA_Node* pOverflowLeaderNode = nullptr; 740 CXFA_Node* pOverflowTrailerNode = nullptr; 741 CXFA_Node* pFormNode = nullptr; 742 CXFA_ContentLayoutItem* pTrailerLayoutItem = nullptr; 743 bool bIsAddTrailerHeight = false; 744 if (pThis->m_pPageMgr && 745 pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None) { 746 pFormNode = pThis->m_pPageMgr->QueryOverflow(pProcessor->m_pFormNode); 747 if (!pFormNode && pLayoutContext && pLayoutContext->m_pOverflowProcessor) { 748 pFormNode = pLayoutContext->m_pOverflowNode; 749 bUseInherited = true; 750 } 751 if (pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, 752 pOverflowTrailerNode, false, 753 false)) { 754 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowTrailerNode)) { 755 if (pOverflowTrailerNode) { 756 auto pOverflowLeaderProcessor = 757 pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pOverflowTrailerNode, 758 nullptr); 759 pOverflowLeaderProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); 760 pTrailerLayoutItem = 761 pOverflowLeaderProcessor->HasLayoutItem() 762 ? pOverflowLeaderProcessor->ExtractLayoutItem() 763 : nullptr; 764 } 765 766 bIsAddTrailerHeight = 767 bUseInherited 768 ? pThis->IsAddNewRowForTrailer(pTrailerLayoutItem) 769 : pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem); 770 if (bIsAddTrailerHeight) { 771 childSize.height += pTrailerLayoutItem->m_sSize.height; 772 bIsAddTrailerHeight = true; 773 } 774 } 775 } 776 } 777 778 if (!bTakeSpace || 779 *fContentCurRowY + childSize.height <= 780 fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION || 781 (!bContainerHeightAutoSize && 782 pThis->m_fUsedSize + fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION >= 783 fContainerHeight)) { 784 if (!bTakeSpace || eRetValue == XFA_ItemLayoutProcessorResult::Done) { 785 if (pProcessor->m_bUseInheriated) { 786 if (pTrailerLayoutItem) 787 AddTrailerBeforeSplit(pProcessor, childSize.height, 788 pTrailerLayoutItem, false); 789 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) 790 AddPendingNode(pProcessor, pOverflowLeaderNode, false); 791 792 pProcessor->m_bUseInheriated = false; 793 } else { 794 if (bIsAddTrailerHeight) 795 childSize.height -= pTrailerLayoutItem->m_sSize.height; 796 797 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, 798 pOverflowTrailerNode, 799 pTrailerLayoutItem, pFormNode); 800 } 801 802 CXFA_ContentLayoutItem* pChildLayoutItem = 803 pProcessor->ExtractLayoutItem(); 804 if (ExistContainerKeep(pProcessor->m_pFormNode, false) && 805 pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None) { 806 pThis->m_arrayKeepItems.push_back(pChildLayoutItem); 807 } else { 808 pThis->m_arrayKeepItems.clear(); 809 } 810 rgCurLineLayoutItems[uHAlign].push_back(pChildLayoutItem); 811 *bAddedItemInRow = true; 812 if (bTakeSpace) { 813 *fContentCurRowAvailWidth -= childSize.width; 814 *fContentCurRowHeight = 815 std::max(*fContentCurRowHeight, childSize.height); 816 } 817 return XFA_ItemLayoutProcessorResult::Done; 818 } 819 820 if (eRetValue == XFA_ItemLayoutProcessorResult::PageFullBreak) { 821 if (pProcessor->m_bUseInheriated) { 822 if (pTrailerLayoutItem) { 823 AddTrailerBeforeSplit(pProcessor, childSize.height, 824 pTrailerLayoutItem, false); 825 } 826 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) 827 AddPendingNode(pProcessor, pOverflowLeaderNode, false); 828 829 pProcessor->m_bUseInheriated = false; 830 } else { 831 if (bIsAddTrailerHeight) 832 childSize.height -= pTrailerLayoutItem->m_sSize.height; 833 834 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, 835 pOverflowTrailerNode, 836 pTrailerLayoutItem, pFormNode); 837 } 838 } 839 rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); 840 *bAddedItemInRow = true; 841 *fContentCurRowAvailWidth -= childSize.width; 842 *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); 843 return eRetValue; 844 } 845 846 XFA_ItemLayoutProcessorResult eResult; 847 if (pThis->ProcessKeepForSplit( 848 pThis, pProcessor, eRetValue, &rgCurLineLayoutItems[uHAlign], 849 fContentCurRowAvailWidth, fContentCurRowHeight, fContentCurRowY, 850 bAddedItemInRow, bForceEndPage, &eResult)) { 851 return eResult; 852 } 853 854 *bForceEndPage = true; 855 float fSplitPos = pProcessor->FindSplitPos(fAvailHeight - *fContentCurRowY); 856 if (fSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { 857 XFA_AttributeEnum eLayout = 858 pProcessor->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); 859 if (eLayout == XFA_AttributeEnum::Tb && 860 eRetValue == XFA_ItemLayoutProcessorResult::Done) { 861 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, 862 pOverflowTrailerNode, pTrailerLayoutItem, 863 pFormNode); 864 rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); 865 *bAddedItemInRow = true; 866 if (bTakeSpace) { 867 *fContentCurRowAvailWidth -= childSize.width; 868 *fContentCurRowHeight = 869 std::max(*fContentCurRowHeight, childSize.height); 870 } 871 return XFA_ItemLayoutProcessorResult::PageFullBreak; 872 } 873 874 CXFA_Node* pTempLeaderNode = nullptr; 875 CXFA_Node* pTempTrailerNode = nullptr; 876 if (pThis->m_pPageMgr && !pProcessor->m_bUseInheriated && 877 eRetValue != XFA_ItemLayoutProcessorResult::PageFullBreak) { 878 pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, 879 pTempTrailerNode, false, true); 880 } 881 if (pTrailerLayoutItem && bIsAddTrailerHeight) { 882 AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem, 883 bUseInherited); 884 } else { 885 pProcessor->SplitLayoutItem(fSplitPos); 886 } 887 888 if (bUseInherited) { 889 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, 890 pOverflowTrailerNode, pTrailerLayoutItem, 891 pFormNode); 892 pThis->m_bUseInheriated = true; 893 } else { 894 CXFA_LayoutItem* firstChild = pProcessor->m_pLayoutItem->m_pFirstChild; 895 if (firstChild && !firstChild->m_pNextSibling && 896 firstChild->m_pFormNode->IsLayoutGeneratedNode()) { 897 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, 898 pOverflowTrailerNode, 899 pTrailerLayoutItem, pFormNode); 900 } else if (pProcessor->JudgeLeaderOrTrailerForOccur( 901 pOverflowLeaderNode)) { 902 AddPendingNode(pProcessor, pOverflowLeaderNode, false); 903 } 904 } 905 906 if (pProcessor->m_pLayoutItem->m_pNextSibling) { 907 childSize = pProcessor->GetCurrentComponentSize(); 908 rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); 909 *bAddedItemInRow = true; 910 if (bTakeSpace) { 911 *fContentCurRowAvailWidth -= childSize.width; 912 *fContentCurRowHeight = 913 std::max(*fContentCurRowHeight, childSize.height); 914 } 915 } 916 return XFA_ItemLayoutProcessorResult::PageFullBreak; 917 } 918 919 if (*fContentCurRowY <= XFA_LAYOUT_FLOAT_PERCISION) { 920 childSize = pProcessor->GetCurrentComponentSize(); 921 if (pProcessor->m_pPageMgr->GetNextAvailContentHeight(childSize.height)) { 922 CXFA_Node* pTempLeaderNode = nullptr; 923 CXFA_Node* pTempTrailerNode = nullptr; 924 if (pThis->m_pPageMgr) { 925 if (!pFormNode && pLayoutContext) 926 pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; 927 928 pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, 929 pTempTrailerNode, false, true); 930 } 931 if (bUseInherited) { 932 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, 933 pOverflowTrailerNode, 934 pTrailerLayoutItem, pFormNode); 935 pThis->m_bUseInheriated = true; 936 } 937 return XFA_ItemLayoutProcessorResult::PageFullBreak; 938 } 939 940 rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); 941 *bAddedItemInRow = true; 942 if (bTakeSpace) { 943 *fContentCurRowAvailWidth -= childSize.width; 944 *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); 945 } 946 if (eRetValue == XFA_ItemLayoutProcessorResult::Done) 947 *bForceEndPage = false; 948 949 return eRetValue; 950 } 951 952 XFA_AttributeEnum eLayout = 953 pProcessor->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); 954 if (pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None && 955 eLayout == XFA_AttributeEnum::Tb) { 956 if (pThis->m_pPageMgr) { 957 pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, 958 pOverflowTrailerNode, false, true); 959 } 960 if (pTrailerLayoutItem) 961 AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem, false); 962 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) 963 AddPendingNode(pProcessor, pOverflowLeaderNode, false); 964 965 return XFA_ItemLayoutProcessorResult::PageFullBreak; 966 } 967 968 if (eRetValue != XFA_ItemLayoutProcessorResult::Done) 969 return XFA_ItemLayoutProcessorResult::PageFullBreak; 970 971 if (!pFormNode && pLayoutContext) 972 pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; 973 if (pThis->m_pPageMgr) { 974 pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, 975 pOverflowTrailerNode, false, true); 976 } 977 if (bUseInherited) { 978 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, 979 pTrailerLayoutItem, pFormNode); 980 pThis->m_bUseInheriated = true; 981 } 982 return XFA_ItemLayoutProcessorResult::PageFullBreak; 983 } 984 985 bool FindLayoutItemSplitPos(CXFA_ContentLayoutItem* pLayoutItem, 986 float fCurVerticalOffset, 987 float* fProposedSplitPos, 988 bool* bAppChange, 989 bool bCalculateMargin) { 990 CXFA_Node* pFormNode = pLayoutItem->m_pFormNode; 991 if (*fProposedSplitPos <= fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION || 992 *fProposedSplitPos > fCurVerticalOffset + pLayoutItem->m_sSize.height - 993 XFA_LAYOUT_FLOAT_PERCISION) { 994 return false; 995 } 996 997 switch (pFormNode->GetIntact()) { 998 case XFA_AttributeEnum::None: { 999 bool bAnyChanged = false; 1000 CXFA_Document* pDocument = pFormNode->GetDocument(); 1001 CXFA_FFNotify* pNotify = pDocument->GetNotify(); 1002 float fCurTopMargin = 0, fCurBottomMargin = 0; 1003 CXFA_Margin* pMarginNode = 1004 pFormNode->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin); 1005 if (pMarginNode && bCalculateMargin) { 1006 fCurTopMargin = pMarginNode->JSObject() 1007 ->GetMeasure(XFA_Attribute::TopInset) 1008 .ToUnit(XFA_Unit::Pt); 1009 fCurBottomMargin = pMarginNode->JSObject() 1010 ->GetMeasure(XFA_Attribute::BottomInset) 1011 .ToUnit(XFA_Unit::Pt); 1012 } 1013 bool bChanged = true; 1014 while (bChanged) { 1015 bChanged = false; 1016 { 1017 float fRelSplitPos = *fProposedSplitPos - fCurVerticalOffset; 1018 if (pNotify->FindSplitPos(pFormNode, pLayoutItem->GetIndex(), 1019 fRelSplitPos)) { 1020 bAnyChanged = true; 1021 bChanged = true; 1022 *fProposedSplitPos = fCurVerticalOffset + fRelSplitPos; 1023 *bAppChange = true; 1024 if (*fProposedSplitPos <= 1025 fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { 1026 return true; 1027 } 1028 } 1029 } 1030 float fRelSplitPos = *fProposedSplitPos - fCurBottomMargin; 1031 for (CXFA_ContentLayoutItem* pChildItem = 1032 (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; 1033 pChildItem; 1034 pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { 1035 float fChildOffset = 1036 fCurVerticalOffset + fCurTopMargin + pChildItem->m_sPos.y; 1037 bool bChange = false; 1038 if (FindLayoutItemSplitPos(pChildItem, fChildOffset, &fRelSplitPos, 1039 &bChange, bCalculateMargin)) { 1040 if (fRelSplitPos - fChildOffset < XFA_LAYOUT_FLOAT_PERCISION && 1041 bChange) { 1042 *fProposedSplitPos = fRelSplitPos - fCurTopMargin; 1043 } else { 1044 *fProposedSplitPos = fRelSplitPos + fCurBottomMargin; 1045 } 1046 bAnyChanged = true; 1047 bChanged = true; 1048 if (*fProposedSplitPos <= 1049 fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { 1050 return true; 1051 } 1052 if (bAnyChanged) 1053 break; 1054 } 1055 } 1056 } 1057 return bAnyChanged; 1058 } 1059 case XFA_AttributeEnum::ContentArea: 1060 case XFA_AttributeEnum::PageArea: { 1061 *fProposedSplitPos = fCurVerticalOffset; 1062 return true; 1063 } 1064 default: 1065 return false; 1066 } 1067 } 1068 1069 CFX_PointF CalculatePositionedContainerPos(CXFA_Node* pNode, 1070 const CFX_SizeF& size) { 1071 XFA_AttributeEnum eAnchorType = 1072 pNode->JSObject()->GetEnum(XFA_Attribute::AnchorType); 1073 int32_t nAnchorType = 0; 1074 switch (eAnchorType) { 1075 case XFA_AttributeEnum::TopLeft: 1076 nAnchorType = 0; 1077 break; 1078 case XFA_AttributeEnum::TopCenter: 1079 nAnchorType = 1; 1080 break; 1081 case XFA_AttributeEnum::TopRight: 1082 nAnchorType = 2; 1083 break; 1084 case XFA_AttributeEnum::MiddleLeft: 1085 nAnchorType = 3; 1086 break; 1087 case XFA_AttributeEnum::MiddleCenter: 1088 nAnchorType = 4; 1089 break; 1090 case XFA_AttributeEnum::MiddleRight: 1091 nAnchorType = 5; 1092 break; 1093 case XFA_AttributeEnum::BottomLeft: 1094 nAnchorType = 6; 1095 break; 1096 case XFA_AttributeEnum::BottomCenter: 1097 nAnchorType = 7; 1098 break; 1099 case XFA_AttributeEnum::BottomRight: 1100 nAnchorType = 8; 1101 break; 1102 default: 1103 break; 1104 } 1105 static const uint8_t nNextPos[4][9] = {{0, 1, 2, 3, 4, 5, 6, 7, 8}, 1106 {6, 3, 0, 7, 4, 1, 8, 5, 2}, 1107 {8, 7, 6, 5, 4, 3, 2, 1, 0}, 1108 {2, 5, 8, 1, 4, 7, 0, 3, 6}}; 1109 1110 CFX_PointF pos( 1111 pNode->JSObject()->GetMeasure(XFA_Attribute::X).ToUnit(XFA_Unit::Pt), 1112 pNode->JSObject()->GetMeasure(XFA_Attribute::Y).ToUnit(XFA_Unit::Pt)); 1113 int32_t nRotate = 1114 XFA_MapRotation(pNode->JSObject()->GetInteger(XFA_Attribute::Rotate)) / 1115 90; 1116 int32_t nAbsoluteAnchorType = nNextPos[nRotate][nAnchorType]; 1117 switch (nAbsoluteAnchorType / 3) { 1118 case 1: 1119 pos.y -= size.height / 2; 1120 break; 1121 case 2: 1122 pos.y -= size.height; 1123 break; 1124 default: 1125 break; 1126 } 1127 switch (nAbsoluteAnchorType % 3) { 1128 case 1: 1129 pos.x -= size.width / 2; 1130 break; 1131 case 2: 1132 pos.x -= size.width; 1133 break; 1134 default: 1135 break; 1136 } 1137 return pos; 1138 } 1139 1140 } // namespace 1141 1142 CXFA_ItemLayoutProcessor::CXFA_ItemLayoutProcessor(CXFA_Node* pNode, 1143 CXFA_LayoutPageMgr* pPageMgr) 1144 : m_pFormNode(pNode), 1145 m_pLayoutItem(nullptr), 1146 m_pCurChildNode(XFA_LAYOUT_INVALIDNODE), 1147 m_fUsedSize(0), 1148 m_pPageMgr(pPageMgr), 1149 m_bBreakPending(true), 1150 m_fLastRowWidth(0), 1151 m_fLastRowY(0), 1152 m_bUseInheriated(false), 1153 m_ePreProcessRs(XFA_ItemLayoutProcessorResult::Done), 1154 m_bKeepBreakFinish(false), 1155 m_bIsProcessKeep(false), 1156 m_pKeepHeadNode(nullptr), 1157 m_pKeepTailNode(nullptr), 1158 m_pOldLayoutItem(nullptr), 1159 m_pCurChildPreprocessor(nullptr), 1160 m_nCurChildNodeStage(XFA_ItemLayoutProcessorStages::None), 1161 m_fWidthLimite(0), 1162 m_bHasAvailHeight(true) { 1163 ASSERT(m_pFormNode && (m_pFormNode->IsContainerNode() || 1164 m_pFormNode->GetElementType() == XFA_Element::Form)); 1165 m_pOldLayoutItem = static_cast<CXFA_ContentLayoutItem*>( 1166 m_pFormNode->JSObject()->GetLayoutItem()); 1167 } 1168 1169 CXFA_ItemLayoutProcessor::~CXFA_ItemLayoutProcessor() {} 1170 1171 CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::CreateContentLayoutItem( 1172 CXFA_Node* pFormNode) { 1173 if (!pFormNode) 1174 return nullptr; 1175 1176 CXFA_ContentLayoutItem* pLayoutItem = nullptr; 1177 if (m_pOldLayoutItem) { 1178 pLayoutItem = m_pOldLayoutItem; 1179 m_pOldLayoutItem = m_pOldLayoutItem->m_pNext; 1180 return pLayoutItem; 1181 } 1182 pLayoutItem = 1183 pFormNode->GetDocument()->GetNotify()->OnCreateContentLayoutItem( 1184 pFormNode); 1185 CXFA_ContentLayoutItem* pPrevLayoutItem = 1186 static_cast<CXFA_ContentLayoutItem*>( 1187 pFormNode->JSObject()->GetLayoutItem()); 1188 if (pPrevLayoutItem) { 1189 while (pPrevLayoutItem->m_pNext) 1190 pPrevLayoutItem = pPrevLayoutItem->m_pNext; 1191 1192 pPrevLayoutItem->m_pNext = pLayoutItem; 1193 pLayoutItem->m_pPrev = pPrevLayoutItem; 1194 } else { 1195 pFormNode->JSObject()->SetLayoutItem(pLayoutItem); 1196 } 1197 return pLayoutItem; 1198 } 1199 1200 float CXFA_ItemLayoutProcessor::FindSplitPos(float fProposedSplitPos) { 1201 ASSERT(m_pLayoutItem); 1202 XFA_AttributeEnum eLayout = m_pFormNode->JSObject() 1203 ->TryEnum(XFA_Attribute::Layout, true) 1204 .value_or(XFA_AttributeEnum::Position); 1205 bool bCalculateMargin = eLayout != XFA_AttributeEnum::Position; 1206 while (fProposedSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { 1207 bool bAppChange = false; 1208 if (!FindLayoutItemSplitPos(m_pLayoutItem, 0, &fProposedSplitPos, 1209 &bAppChange, bCalculateMargin)) { 1210 break; 1211 } 1212 } 1213 return fProposedSplitPos; 1214 } 1215 1216 void CXFA_ItemLayoutProcessor::SplitLayoutItem( 1217 CXFA_ContentLayoutItem* pLayoutItem, 1218 CXFA_ContentLayoutItem* pSecondParent, 1219 float fSplitPos) { 1220 float fCurTopMargin = 0, fCurBottomMargin = 0; 1221 XFA_AttributeEnum eLayout = m_pFormNode->JSObject() 1222 ->TryEnum(XFA_Attribute::Layout, true) 1223 .value_or(XFA_AttributeEnum::Position); 1224 bool bCalculateMargin = true; 1225 if (eLayout == XFA_AttributeEnum::Position) 1226 bCalculateMargin = false; 1227 1228 CXFA_Margin* pMarginNode = 1229 pLayoutItem->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( 1230 XFA_Element::Margin); 1231 if (pMarginNode && bCalculateMargin) { 1232 fCurTopMargin = pMarginNode->JSObject() 1233 ->GetMeasure(XFA_Attribute::TopInset) 1234 .ToUnit(XFA_Unit::Pt); 1235 fCurBottomMargin = pMarginNode->JSObject() 1236 ->GetMeasure(XFA_Attribute::BottomInset) 1237 .ToUnit(XFA_Unit::Pt); 1238 } 1239 1240 CXFA_ContentLayoutItem* pSecondLayoutItem = nullptr; 1241 if (m_pCurChildPreprocessor && 1242 m_pCurChildPreprocessor->m_pFormNode == pLayoutItem->m_pFormNode) { 1243 pSecondLayoutItem = m_pCurChildPreprocessor->CreateContentLayoutItem( 1244 pLayoutItem->m_pFormNode); 1245 } else { 1246 pSecondLayoutItem = CreateContentLayoutItem(pLayoutItem->m_pFormNode); 1247 } 1248 pSecondLayoutItem->m_sPos.x = pLayoutItem->m_sPos.x; 1249 pSecondLayoutItem->m_sSize.width = pLayoutItem->m_sSize.width; 1250 pSecondLayoutItem->m_sPos.y = 0; 1251 pSecondLayoutItem->m_sSize.height = pLayoutItem->m_sSize.height - fSplitPos; 1252 pLayoutItem->m_sSize.height -= pSecondLayoutItem->m_sSize.height; 1253 if (pLayoutItem->m_pFirstChild) 1254 pSecondLayoutItem->m_sSize.height += fCurTopMargin; 1255 1256 if (pSecondParent) { 1257 pSecondParent->AddChild(pSecondLayoutItem); 1258 if (fCurTopMargin > 0 && pLayoutItem->m_pFirstChild) { 1259 pSecondParent->m_sSize.height += fCurTopMargin; 1260 CXFA_ContentLayoutItem* pParentItem = 1261 (CXFA_ContentLayoutItem*)pSecondParent->m_pParent; 1262 while (pParentItem) { 1263 pParentItem->m_sSize.height += fCurTopMargin; 1264 pParentItem = (CXFA_ContentLayoutItem*)pParentItem->m_pParent; 1265 } 1266 } 1267 } else { 1268 pSecondLayoutItem->m_pParent = pLayoutItem->m_pParent; 1269 pSecondLayoutItem->m_pNextSibling = pLayoutItem->m_pNextSibling; 1270 pLayoutItem->m_pNextSibling = pSecondLayoutItem; 1271 } 1272 1273 CXFA_ContentLayoutItem* pChildren = 1274 (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; 1275 pLayoutItem->m_pFirstChild = nullptr; 1276 1277 float lHeightForKeep = 0; 1278 float fAddMarginHeight = 0; 1279 std::vector<CXFA_ContentLayoutItem*> keepLayoutItems; 1280 for (CXFA_ContentLayoutItem *pChildItem = pChildren, *pChildNext = nullptr; 1281 pChildItem; pChildItem = pChildNext) { 1282 pChildNext = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling; 1283 pChildItem->m_pNextSibling = nullptr; 1284 if (fSplitPos <= fCurTopMargin + pChildItem->m_sPos.y + fCurBottomMargin + 1285 XFA_LAYOUT_FLOAT_PERCISION) { 1286 if (!ExistContainerKeep(pChildItem->m_pFormNode, true)) { 1287 pChildItem->m_sPos.y -= fSplitPos - fCurBottomMargin; 1288 pChildItem->m_sPos.y += lHeightForKeep; 1289 pChildItem->m_sPos.y += fAddMarginHeight; 1290 pSecondLayoutItem->AddChild(pChildItem); 1291 continue; 1292 } 1293 if (lHeightForKeep < XFA_LAYOUT_FLOAT_PERCISION) { 1294 for (auto* pPreItem : keepLayoutItems) { 1295 pLayoutItem->RemoveChild(pPreItem); 1296 pPreItem->m_sPos.y -= fSplitPos; 1297 if (pPreItem->m_sPos.y < 0) 1298 pPreItem->m_sPos.y = 0; 1299 if (pPreItem->m_sPos.y + pPreItem->m_sSize.height > lHeightForKeep) { 1300 pPreItem->m_sPos.y = lHeightForKeep; 1301 lHeightForKeep += pPreItem->m_sSize.height; 1302 pSecondLayoutItem->m_sSize.height += pPreItem->m_sSize.height; 1303 if (pSecondParent) 1304 pSecondParent->m_sSize.height += pPreItem->m_sSize.height; 1305 } 1306 pSecondLayoutItem->AddChild(pPreItem); 1307 } 1308 } 1309 pChildItem->m_sPos.y -= fSplitPos; 1310 pChildItem->m_sPos.y += lHeightForKeep; 1311 pChildItem->m_sPos.y += fAddMarginHeight; 1312 pSecondLayoutItem->AddChild(pChildItem); 1313 continue; 1314 } 1315 if (fSplitPos + XFA_LAYOUT_FLOAT_PERCISION >= 1316 fCurTopMargin + fCurBottomMargin + pChildItem->m_sPos.y + 1317 pChildItem->m_sSize.height) { 1318 pLayoutItem->AddChild(pChildItem); 1319 if (ExistContainerKeep(pChildItem->m_pFormNode, false)) 1320 keepLayoutItems.push_back(pChildItem); 1321 else 1322 keepLayoutItems.clear(); 1323 continue; 1324 } 1325 1326 float fOldHeight = pSecondLayoutItem->m_sSize.height; 1327 SplitLayoutItem( 1328 pChildItem, pSecondLayoutItem, 1329 fSplitPos - fCurTopMargin - fCurBottomMargin - pChildItem->m_sPos.y); 1330 fAddMarginHeight = pSecondLayoutItem->m_sSize.height - fOldHeight; 1331 pLayoutItem->AddChild(pChildItem); 1332 } 1333 } 1334 1335 void CXFA_ItemLayoutProcessor::SplitLayoutItem(float fSplitPos) { 1336 ASSERT(m_pLayoutItem); 1337 SplitLayoutItem(m_pLayoutItem, nullptr, fSplitPos); 1338 } 1339 1340 CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::ExtractLayoutItem() { 1341 CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem; 1342 if (pLayoutItem) { 1343 m_pLayoutItem = 1344 static_cast<CXFA_ContentLayoutItem*>(pLayoutItem->m_pNextSibling); 1345 pLayoutItem->m_pNextSibling = nullptr; 1346 } 1347 1348 if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done || 1349 !ToContentLayoutItem(m_pOldLayoutItem)) { 1350 return pLayoutItem; 1351 } 1352 1353 if (m_pOldLayoutItem->m_pPrev) 1354 m_pOldLayoutItem->m_pPrev->m_pNext = nullptr; 1355 1356 CXFA_FFNotify* pNotify = 1357 m_pOldLayoutItem->m_pFormNode->GetDocument()->GetNotify(); 1358 CXFA_LayoutProcessor* pDocLayout = 1359 m_pOldLayoutItem->m_pFormNode->GetDocument()->GetDocLayout(); 1360 CXFA_ContentLayoutItem* pOldLayoutItem = m_pOldLayoutItem; 1361 while (pOldLayoutItem) { 1362 CXFA_ContentLayoutItem* pNextOldLayoutItem = pOldLayoutItem->m_pNext; 1363 pNotify->OnLayoutItemRemoving(pDocLayout, pOldLayoutItem); 1364 if (pOldLayoutItem->m_pParent) 1365 pOldLayoutItem->m_pParent->RemoveChild(pOldLayoutItem); 1366 1367 delete pOldLayoutItem; 1368 pOldLayoutItem = pNextOldLayoutItem; 1369 } 1370 m_pOldLayoutItem = nullptr; 1371 return pLayoutItem; 1372 } 1373 1374 void CXFA_ItemLayoutProcessor::GotoNextContainerNode( 1375 CXFA_Node*& pCurActionNode, 1376 XFA_ItemLayoutProcessorStages& nCurStage, 1377 CXFA_Node* pParentContainer, 1378 bool bUsePageBreak) { 1379 CXFA_Node* pEntireContainer = pParentContainer; 1380 CXFA_Node* pChildContainer = XFA_LAYOUT_INVALIDNODE; 1381 switch (nCurStage) { 1382 case XFA_ItemLayoutProcessorStages::BreakBefore: 1383 case XFA_ItemLayoutProcessorStages::BreakAfter: { 1384 pChildContainer = pCurActionNode->GetParent(); 1385 break; 1386 } 1387 case XFA_ItemLayoutProcessorStages::Keep: 1388 case XFA_ItemLayoutProcessorStages::Container: 1389 pChildContainer = pCurActionNode; 1390 break; 1391 default: 1392 pChildContainer = XFA_LAYOUT_INVALIDNODE; 1393 break; 1394 } 1395 1396 switch (nCurStage) { 1397 case XFA_ItemLayoutProcessorStages::Keep: { 1398 CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild(); 1399 if (!m_bKeepBreakFinish && 1400 FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, false)) { 1401 return; 1402 } 1403 goto CheckNextChildContainer; 1404 } 1405 case XFA_ItemLayoutProcessorStages::None: { 1406 pCurActionNode = XFA_LAYOUT_INVALIDNODE; 1407 case XFA_ItemLayoutProcessorStages::BookendLeader: 1408 for (CXFA_Node* pBookendNode = pCurActionNode == XFA_LAYOUT_INVALIDNODE 1409 ? pEntireContainer->GetFirstChild() 1410 : pCurActionNode->GetNextSibling(); 1411 pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) { 1412 switch (pBookendNode->GetElementType()) { 1413 case XFA_Element::Bookend: 1414 case XFA_Element::Break: 1415 pCurActionNode = pBookendNode; 1416 nCurStage = XFA_ItemLayoutProcessorStages::BookendLeader; 1417 return; 1418 default: 1419 break; 1420 } 1421 } 1422 } 1423 { 1424 pCurActionNode = XFA_LAYOUT_INVALIDNODE; 1425 case XFA_ItemLayoutProcessorStages::BreakBefore: 1426 if (pCurActionNode != XFA_LAYOUT_INVALIDNODE) { 1427 CXFA_Node* pBreakBeforeNode = pCurActionNode->GetNextSibling(); 1428 if (!m_bKeepBreakFinish && 1429 FindBreakNode(pBreakBeforeNode, pCurActionNode, &nCurStage, 1430 true)) { 1431 return; 1432 } 1433 if (m_bIsProcessKeep) { 1434 if (ProcessKeepNodesForBreakBefore(pCurActionNode, nCurStage, 1435 pChildContainer)) { 1436 return; 1437 } 1438 goto CheckNextChildContainer; 1439 } 1440 pCurActionNode = pChildContainer; 1441 nCurStage = XFA_ItemLayoutProcessorStages::Container; 1442 return; 1443 } 1444 goto CheckNextChildContainer; 1445 } 1446 case XFA_ItemLayoutProcessorStages::Container: { 1447 pCurActionNode = XFA_LAYOUT_INVALIDNODE; 1448 case XFA_ItemLayoutProcessorStages::BreakAfter: { 1449 if (pCurActionNode == XFA_LAYOUT_INVALIDNODE) { 1450 CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild(); 1451 if (!m_bKeepBreakFinish && 1452 FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, 1453 false)) { 1454 return; 1455 } 1456 } else { 1457 CXFA_Node* pBreakAfterNode = pCurActionNode->GetNextSibling(); 1458 if (FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, 1459 false)) { 1460 return; 1461 } 1462 } 1463 goto CheckNextChildContainer; 1464 } 1465 } 1466 1467 CheckNextChildContainer : { 1468 CXFA_Node* pNextChildContainer = 1469 pChildContainer == XFA_LAYOUT_INVALIDNODE 1470 ? pEntireContainer->GetFirstContainerChild() 1471 : pChildContainer->GetNextContainerSibling(); 1472 while (pNextChildContainer && 1473 pNextChildContainer->IsLayoutGeneratedNode()) { 1474 CXFA_Node* pSaveNode = pNextChildContainer; 1475 pNextChildContainer = pNextChildContainer->GetNextContainerSibling(); 1476 if (pSaveNode->IsUnusedNode()) 1477 DeleteLayoutGeneratedNode(pSaveNode); 1478 } 1479 if (!pNextChildContainer) 1480 goto NoMoreChildContainer; 1481 1482 bool bLastKeep = false; 1483 if (ProcessKeepNodesForCheckNext(pCurActionNode, nCurStage, 1484 pNextChildContainer, bLastKeep)) { 1485 return; 1486 } 1487 if (!m_bKeepBreakFinish && !bLastKeep && 1488 FindBreakNode(pNextChildContainer->GetFirstChild(), pCurActionNode, 1489 &nCurStage, true)) { 1490 return; 1491 } 1492 pCurActionNode = pNextChildContainer; 1493 if (m_bIsProcessKeep) 1494 nCurStage = XFA_ItemLayoutProcessorStages::Keep; 1495 else 1496 nCurStage = XFA_ItemLayoutProcessorStages::Container; 1497 return; 1498 } 1499 1500 NoMoreChildContainer : { 1501 pCurActionNode = XFA_LAYOUT_INVALIDNODE; 1502 case XFA_ItemLayoutProcessorStages::BookendTrailer: 1503 for (CXFA_Node* pBookendNode = pCurActionNode == XFA_LAYOUT_INVALIDNODE 1504 ? pEntireContainer->GetFirstChild() 1505 : pCurActionNode->GetNextSibling(); 1506 pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) { 1507 switch (pBookendNode->GetElementType()) { 1508 case XFA_Element::Bookend: 1509 case XFA_Element::Break: 1510 pCurActionNode = pBookendNode; 1511 nCurStage = XFA_ItemLayoutProcessorStages::BookendTrailer; 1512 return; 1513 default: 1514 break; 1515 } 1516 } 1517 } 1518 default: 1519 pCurActionNode = nullptr; 1520 nCurStage = XFA_ItemLayoutProcessorStages::Done; 1521 } 1522 } 1523 1524 bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForCheckNext( 1525 CXFA_Node*& pCurActionNode, 1526 XFA_ItemLayoutProcessorStages& nCurStage, 1527 CXFA_Node*& pNextContainer, 1528 bool& bLastKeepNode) { 1529 const bool bCanSplit = pNextContainer->GetIntact() == XFA_AttributeEnum::None; 1530 bool bNextKeep = false; 1531 if (ExistContainerKeep(pNextContainer, false)) 1532 bNextKeep = true; 1533 1534 if (bNextKeep && !bCanSplit) { 1535 if (!m_bIsProcessKeep && !m_bKeepBreakFinish) { 1536 m_pKeepHeadNode = pNextContainer; 1537 m_bIsProcessKeep = true; 1538 } 1539 return false; 1540 } 1541 1542 if (m_bIsProcessKeep && m_pKeepHeadNode) { 1543 m_pKeepTailNode = pNextContainer; 1544 if (!m_bKeepBreakFinish && 1545 FindBreakNode(pNextContainer->GetFirstChild(), pCurActionNode, 1546 &nCurStage, true)) { 1547 return true; 1548 } 1549 1550 pNextContainer = m_pKeepHeadNode; 1551 m_bKeepBreakFinish = true; 1552 m_pKeepHeadNode = nullptr; 1553 m_pKeepTailNode = nullptr; 1554 m_bIsProcessKeep = false; 1555 } else { 1556 if (m_bKeepBreakFinish) 1557 bLastKeepNode = true; 1558 m_bKeepBreakFinish = false; 1559 } 1560 1561 return false; 1562 } 1563 1564 bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForBreakBefore( 1565 CXFA_Node*& pCurActionNode, 1566 XFA_ItemLayoutProcessorStages& nCurStage, 1567 CXFA_Node* pContainerNode) { 1568 if (m_pKeepTailNode == pContainerNode) { 1569 pCurActionNode = m_pKeepHeadNode; 1570 m_bKeepBreakFinish = true; 1571 m_pKeepHeadNode = nullptr; 1572 m_pKeepTailNode = nullptr; 1573 m_bIsProcessKeep = false; 1574 nCurStage = XFA_ItemLayoutProcessorStages::Container; 1575 return true; 1576 } 1577 1578 CXFA_Node* pBreakAfterNode = pContainerNode->GetFirstChild(); 1579 return FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, false); 1580 } 1581 1582 bool XFA_ItemLayoutProcessor_IsTakingSpace(CXFA_Node* pNode) { 1583 XFA_AttributeEnum ePresence = pNode->JSObject() 1584 ->TryEnum(XFA_Attribute::Presence, true) 1585 .value_or(XFA_AttributeEnum::Visible); 1586 return ePresence == XFA_AttributeEnum::Visible || 1587 ePresence == XFA_AttributeEnum::Invisible; 1588 } 1589 1590 bool CXFA_ItemLayoutProcessor::IncrementRelayoutNode( 1591 CXFA_LayoutProcessor* pLayoutProcessor, 1592 CXFA_Node* pNode, 1593 CXFA_Node* pParentNode) { 1594 return false; 1595 } 1596 1597 void CXFA_ItemLayoutProcessor::DoLayoutPageArea( 1598 CXFA_ContainerLayoutItem* pPageAreaLayoutItem) { 1599 CXFA_Node* pFormNode = pPageAreaLayoutItem->m_pFormNode; 1600 CXFA_Node* pCurChildNode = XFA_LAYOUT_INVALIDNODE; 1601 XFA_ItemLayoutProcessorStages nCurChildNodeStage = 1602 XFA_ItemLayoutProcessorStages::None; 1603 CXFA_LayoutItem* pBeforeItem = nullptr; 1604 for (GotoNextContainerNode(pCurChildNode, nCurChildNodeStage, pFormNode, 1605 false); 1606 pCurChildNode; GotoNextContainerNode(pCurChildNode, nCurChildNodeStage, 1607 pFormNode, false)) { 1608 if (nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) 1609 continue; 1610 if (pCurChildNode->GetElementType() == XFA_Element::Variables) 1611 continue; 1612 1613 auto pProcessor = 1614 pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pCurChildNode, nullptr); 1615 pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); 1616 if (!pProcessor->HasLayoutItem()) 1617 continue; 1618 1619 pProcessor->SetCurrentComponentPos(CalculatePositionedContainerPos( 1620 pCurChildNode, pProcessor->GetCurrentComponentSize())); 1621 CXFA_LayoutItem* pProcessItem = pProcessor->ExtractLayoutItem(); 1622 if (!pBeforeItem) 1623 pPageAreaLayoutItem->AddHeadChild(pProcessItem); 1624 else 1625 pPageAreaLayoutItem->InsertChild(pBeforeItem, pProcessItem); 1626 1627 pBeforeItem = pProcessItem; 1628 } 1629 1630 pBeforeItem = nullptr; 1631 CXFA_LayoutItem* pLayoutItem = pPageAreaLayoutItem->m_pFirstChild; 1632 while (pLayoutItem) { 1633 if (!pLayoutItem->IsContentLayoutItem() || 1634 pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) { 1635 pLayoutItem = pLayoutItem->m_pNextSibling; 1636 continue; 1637 } 1638 if (pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) 1639 continue; 1640 1641 CXFA_LayoutItem* pNextLayoutItem = pLayoutItem->m_pNextSibling; 1642 pPageAreaLayoutItem->RemoveChild(pLayoutItem); 1643 if (!pBeforeItem) 1644 pPageAreaLayoutItem->AddHeadChild(pLayoutItem); 1645 else 1646 pPageAreaLayoutItem->InsertChild(pBeforeItem, pLayoutItem); 1647 1648 pBeforeItem = pLayoutItem; 1649 pLayoutItem = pNextLayoutItem; 1650 } 1651 } 1652 1653 void CXFA_ItemLayoutProcessor::DoLayoutPositionedContainer( 1654 CXFA_LayoutContext* pContext) { 1655 if (m_pLayoutItem) 1656 return; 1657 1658 m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); 1659 bool bIgnoreXY = (m_pFormNode->JSObject() 1660 ->TryEnum(XFA_Attribute::Layout, true) 1661 .value_or(XFA_AttributeEnum::Position) != 1662 XFA_AttributeEnum::Position); 1663 bool bContainerWidthAutoSize = true; 1664 bool bContainerHeightAutoSize = true; 1665 CFX_SizeF containerSize = CalculateContainerSpecifiedSize( 1666 m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); 1667 1668 float fContentCalculatedWidth = 0; 1669 float fContentCalculatedHeight = 0; 1670 float fHiddenContentCalculatedWidth = 0; 1671 float fHiddenContentCalculatedHeight = 0; 1672 if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { 1673 GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, 1674 false); 1675 } 1676 1677 int32_t iColIndex = 0; 1678 for (; m_pCurChildNode; GotoNextContainerNode( 1679 m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { 1680 if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) 1681 continue; 1682 if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) 1683 continue; 1684 1685 auto pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( 1686 m_pCurChildNode, m_pPageMgr); 1687 if (pContext && pContext->m_prgSpecifiedColumnWidths) { 1688 int32_t iColSpan = 1689 m_pCurChildNode->JSObject()->GetInteger(XFA_Attribute::ColSpan); 1690 if (iColSpan <= pdfium::CollectionSize<int32_t>( 1691 *pContext->m_prgSpecifiedColumnWidths) - 1692 iColIndex) { 1693 pContext->m_fCurColumnWidth = 0; 1694 pContext->m_bCurColumnWidthAvaiable = true; 1695 if (iColSpan == -1) { 1696 iColSpan = pdfium::CollectionSize<int32_t>( 1697 *pContext->m_prgSpecifiedColumnWidths); 1698 } 1699 for (int32_t i = 0; iColIndex + i < iColSpan; ++i) { 1700 pContext->m_fCurColumnWidth += 1701 (*pContext->m_prgSpecifiedColumnWidths)[iColIndex + i]; 1702 } 1703 if (pContext->m_fCurColumnWidth == 0) 1704 pContext->m_bCurColumnWidthAvaiable = false; 1705 1706 iColIndex += iColSpan >= 0 ? iColSpan : 0; 1707 } 1708 } 1709 1710 pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pContext); 1711 if (!pProcessor->HasLayoutItem()) 1712 continue; 1713 1714 CFX_SizeF size = pProcessor->GetCurrentComponentSize(); 1715 bool bChangeParentSize = false; 1716 if (XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) 1717 bChangeParentSize = true; 1718 1719 CFX_PointF absolutePos; 1720 if (!bIgnoreXY) 1721 absolutePos = CalculatePositionedContainerPos(m_pCurChildNode, size); 1722 1723 pProcessor->SetCurrentComponentPos(absolutePos); 1724 if (bContainerWidthAutoSize) { 1725 float fChildSuppliedWidth = absolutePos.x + size.width; 1726 if (bChangeParentSize) { 1727 fContentCalculatedWidth = 1728 std::max(fContentCalculatedWidth, fChildSuppliedWidth); 1729 } else { 1730 if (fHiddenContentCalculatedWidth < fChildSuppliedWidth && 1731 m_pCurChildNode->GetElementType() != XFA_Element::Subform) { 1732 fHiddenContentCalculatedWidth = fChildSuppliedWidth; 1733 } 1734 } 1735 } 1736 1737 if (bContainerHeightAutoSize) { 1738 float fChildSuppliedHeight = absolutePos.y + size.height; 1739 if (bChangeParentSize) { 1740 fContentCalculatedHeight = 1741 std::max(fContentCalculatedHeight, fChildSuppliedHeight); 1742 } else { 1743 if (fHiddenContentCalculatedHeight < fChildSuppliedHeight && 1744 m_pCurChildNode->GetElementType() != XFA_Element::Subform) { 1745 fHiddenContentCalculatedHeight = fChildSuppliedHeight; 1746 } 1747 } 1748 } 1749 m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); 1750 } 1751 1752 XFA_VERSION eVersion = m_pFormNode->GetDocument()->GetCurVersionMode(); 1753 if (fContentCalculatedWidth == 0 && eVersion < XFA_VERSION_207) 1754 fContentCalculatedWidth = fHiddenContentCalculatedWidth; 1755 if (fContentCalculatedHeight == 0 && eVersion < XFA_VERSION_207) 1756 fContentCalculatedHeight = fHiddenContentCalculatedHeight; 1757 1758 containerSize = CalculateContainerComponentSizeFromContentSize( 1759 m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, 1760 bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); 1761 SetCurrentComponentSize(containerSize); 1762 } 1763 1764 void CXFA_ItemLayoutProcessor::DoLayoutTableContainer(CXFA_Node* pLayoutNode) { 1765 if (m_pLayoutItem) 1766 return; 1767 if (!pLayoutNode) 1768 pLayoutNode = m_pFormNode; 1769 1770 ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); 1771 1772 m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); 1773 bool bContainerWidthAutoSize = true; 1774 bool bContainerHeightAutoSize = true; 1775 CFX_SizeF containerSize = CalculateContainerSpecifiedSize( 1776 m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); 1777 float fContentCalculatedWidth = 0; 1778 float fContentCalculatedHeight = 0; 1779 CXFA_Margin* pMarginNode = 1780 m_pFormNode->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin); 1781 float fLeftInset = 0; 1782 float fRightInset = 0; 1783 if (pMarginNode) { 1784 fLeftInset = pMarginNode->JSObject() 1785 ->GetMeasure(XFA_Attribute::LeftInset) 1786 .ToUnit(XFA_Unit::Pt); 1787 fRightInset = pMarginNode->JSObject() 1788 ->GetMeasure(XFA_Attribute::RightInset) 1789 .ToUnit(XFA_Unit::Pt); 1790 } 1791 1792 float fContentWidthLimit = 1793 bContainerWidthAutoSize ? FLT_MAX 1794 : containerSize.width - fLeftInset - fRightInset; 1795 WideString wsColumnWidths = 1796 pLayoutNode->JSObject()->GetCData(XFA_Attribute::ColumnWidths); 1797 if (!wsColumnWidths.IsEmpty()) { 1798 auto widths = SeparateStringW(wsColumnWidths.c_str(), 1799 wsColumnWidths.GetLength(), L' '); 1800 for (auto& width : widths) { 1801 width.TrimLeft(L' '); 1802 if (width.IsEmpty()) 1803 continue; 1804 1805 m_rgSpecifiedColumnWidths.push_back( 1806 CXFA_Measurement(width.AsStringView()).ToUnit(XFA_Unit::Pt)); 1807 } 1808 } 1809 1810 int32_t iSpecifiedColumnCount = 1811 pdfium::CollectionSize<int32_t>(m_rgSpecifiedColumnWidths); 1812 CXFA_LayoutContext layoutContext; 1813 layoutContext.m_prgSpecifiedColumnWidths = &m_rgSpecifiedColumnWidths; 1814 CXFA_LayoutContext* pLayoutContext = 1815 iSpecifiedColumnCount > 0 ? &layoutContext : nullptr; 1816 if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { 1817 GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, 1818 false); 1819 } 1820 1821 for (; m_pCurChildNode; GotoNextContainerNode( 1822 m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { 1823 layoutContext.m_bCurColumnWidthAvaiable = false; 1824 layoutContext.m_fCurColumnWidth = 0; 1825 if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) 1826 continue; 1827 1828 auto pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( 1829 m_pCurChildNode, m_pPageMgr); 1830 pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pLayoutContext); 1831 if (!pProcessor->HasLayoutItem()) 1832 continue; 1833 1834 m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); 1835 } 1836 1837 int32_t iRowCount = 0; 1838 int32_t iColCount = 0; 1839 { 1840 std::vector<CXFA_ContentLayoutItem*> rgRowItems; 1841 std::vector<int32_t> rgRowItemsSpan; 1842 std::vector<float> rgRowItemsWidth; 1843 for (auto* pLayoutChild = 1844 static_cast<CXFA_ContentLayoutItem*>(m_pLayoutItem->m_pFirstChild); 1845 pLayoutChild; pLayoutChild = static_cast<CXFA_ContentLayoutItem*>( 1846 pLayoutChild->m_pNextSibling)) { 1847 if (pLayoutChild->m_pFormNode->GetElementType() != XFA_Element::Subform) 1848 continue; 1849 if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) 1850 continue; 1851 1852 XFA_AttributeEnum eLayout = 1853 pLayoutChild->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); 1854 if (eLayout != XFA_AttributeEnum::Row && 1855 eLayout != XFA_AttributeEnum::Rl_row) { 1856 continue; 1857 } 1858 if (CXFA_ContentLayoutItem* pRowLayoutCell = 1859 (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild) { 1860 rgRowItems.push_back(pRowLayoutCell); 1861 int32_t iColSpan = pRowLayoutCell->m_pFormNode->JSObject()->GetInteger( 1862 XFA_Attribute::ColSpan); 1863 rgRowItemsSpan.push_back(iColSpan); 1864 rgRowItemsWidth.push_back(pRowLayoutCell->m_sSize.width); 1865 } 1866 } 1867 1868 iRowCount = pdfium::CollectionSize<int32_t>(rgRowItems); 1869 iColCount = 0; 1870 bool bMoreColumns = true; 1871 while (bMoreColumns) { 1872 bMoreColumns = false; 1873 bool bAutoCol = false; 1874 for (int32_t i = 0; i < iRowCount; i++) { 1875 while (rgRowItems[i] && (rgRowItemsSpan[i] <= 0 || 1876 !XFA_ItemLayoutProcessor_IsTakingSpace( 1877 rgRowItems[i]->m_pFormNode))) { 1878 CXFA_ContentLayoutItem* pNewCell = 1879 (CXFA_ContentLayoutItem*)rgRowItems[i]->m_pNextSibling; 1880 if (rgRowItemsSpan[i] < 0 && XFA_ItemLayoutProcessor_IsTakingSpace( 1881 rgRowItems[i]->m_pFormNode)) { 1882 pNewCell = nullptr; 1883 } 1884 rgRowItems[i] = pNewCell; 1885 rgRowItemsSpan[i] = 1886 pNewCell ? pNewCell->m_pFormNode->JSObject()->GetInteger( 1887 XFA_Attribute::ColSpan) 1888 : 0; 1889 rgRowItemsWidth[i] = pNewCell ? pNewCell->m_sSize.width : 0; 1890 } 1891 CXFA_ContentLayoutItem* pCell = rgRowItems[i]; 1892 if (!pCell) 1893 continue; 1894 1895 bMoreColumns = true; 1896 if (rgRowItemsSpan[i] != 1) 1897 continue; 1898 1899 if (iColCount >= iSpecifiedColumnCount) { 1900 int32_t c = iColCount + 1 - pdfium::CollectionSize<int32_t>( 1901 m_rgSpecifiedColumnWidths); 1902 for (int32_t j = 0; j < c; j++) 1903 m_rgSpecifiedColumnWidths.push_back(0); 1904 } 1905 if (m_rgSpecifiedColumnWidths[iColCount] < XFA_LAYOUT_FLOAT_PERCISION) 1906 bAutoCol = true; 1907 if (bAutoCol && 1908 m_rgSpecifiedColumnWidths[iColCount] < rgRowItemsWidth[i]) { 1909 m_rgSpecifiedColumnWidths[iColCount] = rgRowItemsWidth[i]; 1910 } 1911 } 1912 1913 if (!bMoreColumns) 1914 continue; 1915 1916 float fFinalColumnWidth = 0.0f; 1917 if (pdfium::IndexInBounds(m_rgSpecifiedColumnWidths, iColCount)) 1918 fFinalColumnWidth = m_rgSpecifiedColumnWidths[iColCount]; 1919 1920 for (int32_t i = 0; i < iRowCount; ++i) { 1921 if (!rgRowItems[i]) 1922 continue; 1923 --rgRowItemsSpan[i]; 1924 rgRowItemsWidth[i] -= fFinalColumnWidth; 1925 } 1926 ++iColCount; 1927 } 1928 } 1929 1930 float fCurrentRowY = 0; 1931 for (CXFA_ContentLayoutItem* pLayoutChild = 1932 (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; 1933 pLayoutChild; 1934 pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { 1935 if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) 1936 continue; 1937 1938 if (pLayoutChild->m_pFormNode->GetElementType() == XFA_Element::Subform) { 1939 XFA_AttributeEnum eSubformLayout = 1940 pLayoutChild->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); 1941 if (eSubformLayout == XFA_AttributeEnum::Row || 1942 eSubformLayout == XFA_AttributeEnum::Rl_row) { 1943 RelocateTableRowCells(pLayoutChild, m_rgSpecifiedColumnWidths, 1944 eSubformLayout); 1945 } 1946 } 1947 1948 pLayoutChild->m_sPos.y = fCurrentRowY; 1949 if (bContainerWidthAutoSize) { 1950 pLayoutChild->m_sPos.x = 0; 1951 } else { 1952 switch (pLayoutChild->m_pFormNode->JSObject()->GetEnum( 1953 XFA_Attribute::HAlign)) { 1954 case XFA_AttributeEnum::Center: 1955 pLayoutChild->m_sPos.x = 1956 (fContentWidthLimit - pLayoutChild->m_sSize.width) / 2; 1957 break; 1958 case XFA_AttributeEnum::Right: 1959 pLayoutChild->m_sPos.x = 1960 fContentWidthLimit - pLayoutChild->m_sSize.width; 1961 break; 1962 case XFA_AttributeEnum::Left: 1963 default: 1964 pLayoutChild->m_sPos.x = 0; 1965 break; 1966 } 1967 } 1968 1969 if (bContainerWidthAutoSize) { 1970 float fChildSuppliedWidth = 1971 pLayoutChild->m_sPos.x + pLayoutChild->m_sSize.width; 1972 if (fContentWidthLimit < FLT_MAX && 1973 fContentWidthLimit > fChildSuppliedWidth) { 1974 fChildSuppliedWidth = fContentWidthLimit; 1975 } 1976 fContentCalculatedWidth = 1977 std::max(fContentCalculatedWidth, fChildSuppliedWidth); 1978 } 1979 fCurrentRowY += pLayoutChild->m_sSize.height; 1980 } 1981 1982 if (bContainerHeightAutoSize) 1983 fContentCalculatedHeight = std::max(fContentCalculatedHeight, fCurrentRowY); 1984 1985 containerSize = CalculateContainerComponentSizeFromContentSize( 1986 m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, 1987 bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); 1988 SetCurrentComponentSize(containerSize); 1989 } 1990 1991 bool CXFA_ItemLayoutProcessor::IsAddNewRowForTrailer( 1992 CXFA_ContentLayoutItem* pTrailerItem) { 1993 if (!pTrailerItem) 1994 return false; 1995 1996 float fWidth = pTrailerItem->m_sSize.width; 1997 XFA_AttributeEnum eLayout = 1998 m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); 1999 return eLayout == XFA_AttributeEnum::Tb || m_fWidthLimite <= fWidth; 2000 } 2001 2002 float CXFA_ItemLayoutProcessor::InsertKeepLayoutItems() { 2003 if (m_arrayKeepItems.empty()) 2004 return 0; 2005 2006 if (!m_pLayoutItem) { 2007 m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); 2008 m_pLayoutItem->m_sSize.clear(); 2009 } 2010 2011 float fTotalHeight = 0; 2012 for (auto iter = m_arrayKeepItems.rbegin(); iter != m_arrayKeepItems.rend(); 2013 iter++) { 2014 AddLeaderAfterSplit(this, *iter); 2015 fTotalHeight += (*iter)->m_sSize.height; 2016 } 2017 m_arrayKeepItems.clear(); 2018 2019 return fTotalHeight; 2020 } 2021 2022 bool CXFA_ItemLayoutProcessor::ProcessKeepForSplit( 2023 CXFA_ItemLayoutProcessor* pParentProcessor, 2024 CXFA_ItemLayoutProcessor* pChildProcessor, 2025 XFA_ItemLayoutProcessorResult eRetValue, 2026 std::vector<CXFA_ContentLayoutItem*>* rgCurLineLayoutItem, 2027 float* fContentCurRowAvailWidth, 2028 float* fContentCurRowHeight, 2029 float* fContentCurRowY, 2030 bool* bAddedItemInRow, 2031 bool* bForceEndPage, 2032 XFA_ItemLayoutProcessorResult* result) { 2033 if (!pParentProcessor || !pChildProcessor) 2034 return false; 2035 2036 if (pParentProcessor->m_pCurChildNode->GetIntact() == 2037 XFA_AttributeEnum::None && 2038 pChildProcessor->m_bHasAvailHeight) 2039 return false; 2040 2041 if (!ExistContainerKeep(pParentProcessor->m_pCurChildNode, true)) 2042 return false; 2043 2044 CFX_SizeF childSize = pChildProcessor->GetCurrentComponentSize(); 2045 std::vector<CXFA_ContentLayoutItem*> keepLayoutItems; 2046 if (pParentProcessor->JudgePutNextPage(pParentProcessor->m_pLayoutItem, 2047 childSize.height, &keepLayoutItems)) { 2048 m_arrayKeepItems.clear(); 2049 2050 for (auto* item : keepLayoutItems) { 2051 pParentProcessor->m_pLayoutItem->RemoveChild(item); 2052 *fContentCurRowY -= item->m_sSize.height; 2053 m_arrayKeepItems.push_back(item); 2054 } 2055 *bAddedItemInRow = true; 2056 *bForceEndPage = true; 2057 *result = XFA_ItemLayoutProcessorResult::PageFullBreak; 2058 return true; 2059 } 2060 2061 rgCurLineLayoutItem->push_back(pChildProcessor->ExtractLayoutItem()); 2062 *bAddedItemInRow = true; 2063 *fContentCurRowAvailWidth -= childSize.width; 2064 *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); 2065 *result = eRetValue; 2066 2067 return true; 2068 } 2069 2070 bool CXFA_ItemLayoutProcessor::JudgePutNextPage( 2071 CXFA_ContentLayoutItem* pParentLayoutItem, 2072 float fChildHeight, 2073 std::vector<CXFA_ContentLayoutItem*>* pKeepItems) { 2074 if (!pParentLayoutItem) 2075 return false; 2076 2077 float fItemsHeight = 0; 2078 for (CXFA_ContentLayoutItem* pChildLayoutItem = 2079 (CXFA_ContentLayoutItem*)pParentLayoutItem->m_pFirstChild; 2080 pChildLayoutItem; 2081 pChildLayoutItem = 2082 (CXFA_ContentLayoutItem*)pChildLayoutItem->m_pNextSibling) { 2083 if (ExistContainerKeep(pChildLayoutItem->m_pFormNode, false)) { 2084 pKeepItems->push_back(pChildLayoutItem); 2085 fItemsHeight += pChildLayoutItem->m_sSize.height; 2086 } else { 2087 pKeepItems->clear(); 2088 fItemsHeight = 0; 2089 } 2090 } 2091 fItemsHeight += fChildHeight; 2092 return m_pPageMgr->GetNextAvailContentHeight(fItemsHeight); 2093 } 2094 2095 void CXFA_ItemLayoutProcessor::ProcessUnUseBinds(CXFA_Node* pFormNode) { 2096 if (!pFormNode) 2097 return; 2098 2099 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator( 2100 pFormNode); 2101 for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode; 2102 pNode = sIterator.MoveToNext()) { 2103 if (pNode->IsContainerNode()) { 2104 CXFA_Node* pBindNode = pNode->GetBindData(); 2105 if (pBindNode) { 2106 pBindNode->RemoveBindItem(pNode); 2107 pNode->SetBindingNode(nullptr); 2108 } 2109 } 2110 pNode->SetFlag(XFA_NodeFlag_UnusedNode, true); 2111 } 2112 } 2113 2114 void CXFA_ItemLayoutProcessor::ProcessUnUseOverFlow( 2115 CXFA_Node* pLeaderNode, 2116 CXFA_Node* pTrailerNode, 2117 CXFA_ContentLayoutItem* pTrailerItem, 2118 CXFA_Node* pFormNode) { 2119 ProcessUnUseBinds(pLeaderNode); 2120 ProcessUnUseBinds(pTrailerNode); 2121 if (!pFormNode) 2122 return; 2123 2124 if (pFormNode->GetElementType() == XFA_Element::Overflow || 2125 pFormNode->GetElementType() == XFA_Element::Break) { 2126 pFormNode = pFormNode->GetParent(); 2127 } 2128 if (pLeaderNode && pFormNode) 2129 pFormNode->RemoveChild(pLeaderNode, true); 2130 if (pTrailerNode && pFormNode) 2131 pFormNode->RemoveChild(pTrailerNode, true); 2132 if (pTrailerItem) 2133 XFA_ReleaseLayoutItem(pTrailerItem); 2134 } 2135 2136 XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayoutFlowedContainer( 2137 bool bUseBreakControl, 2138 XFA_AttributeEnum eFlowStrategy, 2139 float fHeightLimit, 2140 float fRealHeight, 2141 CXFA_LayoutContext* pContext, 2142 bool bRootForceTb) { 2143 m_bHasAvailHeight = true; 2144 bool bBreakDone = false; 2145 bool bContainerWidthAutoSize = true; 2146 bool bContainerHeightAutoSize = true; 2147 bool bForceEndPage = false; 2148 bool bIsManualBreak = false; 2149 if (m_pCurChildPreprocessor) { 2150 m_pCurChildPreprocessor->m_ePreProcessRs = 2151 XFA_ItemLayoutProcessorResult::Done; 2152 } 2153 2154 CFX_SizeF containerSize = CalculateContainerSpecifiedSize( 2155 m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); 2156 if (pContext && pContext->m_bCurColumnWidthAvaiable) { 2157 bContainerWidthAutoSize = false; 2158 containerSize.width = pContext->m_fCurColumnWidth; 2159 } 2160 if (!bContainerHeightAutoSize) 2161 containerSize.height -= m_fUsedSize; 2162 2163 if (!bContainerHeightAutoSize) { 2164 CXFA_Node* pParentNode = m_pFormNode->GetParent(); 2165 bool bFocrTb = false; 2166 if (pParentNode && 2167 GetLayout(pParentNode, &bFocrTb) == XFA_AttributeEnum::Row) { 2168 CXFA_Node* pChildContainer = m_pFormNode->GetFirstContainerChild(); 2169 if (pChildContainer && pChildContainer->GetNextContainerSibling()) { 2170 containerSize.height = 0; 2171 bContainerHeightAutoSize = true; 2172 } 2173 } 2174 } 2175 2176 CXFA_Margin* pMarginNode = 2177 m_pFormNode->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin); 2178 float fLeftInset = 0; 2179 float fTopInset = 0; 2180 float fRightInset = 0; 2181 float fBottomInset = 0; 2182 if (pMarginNode) { 2183 fLeftInset = pMarginNode->JSObject() 2184 ->GetMeasure(XFA_Attribute::LeftInset) 2185 .ToUnit(XFA_Unit::Pt); 2186 fTopInset = pMarginNode->JSObject() 2187 ->GetMeasure(XFA_Attribute::TopInset) 2188 .ToUnit(XFA_Unit::Pt); 2189 fRightInset = pMarginNode->JSObject() 2190 ->GetMeasure(XFA_Attribute::RightInset) 2191 .ToUnit(XFA_Unit::Pt); 2192 fBottomInset = pMarginNode->JSObject() 2193 ->GetMeasure(XFA_Attribute::BottomInset) 2194 .ToUnit(XFA_Unit::Pt); 2195 } 2196 float fContentWidthLimit = 2197 bContainerWidthAutoSize ? FLT_MAX 2198 : containerSize.width - fLeftInset - fRightInset; 2199 float fContentCalculatedWidth = 0; 2200 float fContentCalculatedHeight = 0; 2201 float fAvailHeight = fHeightLimit - fTopInset - fBottomInset; 2202 if (fAvailHeight < 0) 2203 m_bHasAvailHeight = false; 2204 2205 fRealHeight = fRealHeight - fTopInset - fBottomInset; 2206 float fContentCurRowY = 0; 2207 CXFA_ContentLayoutItem* pLayoutChild = nullptr; 2208 if (m_pLayoutItem) { 2209 if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done && 2210 eFlowStrategy != XFA_AttributeEnum::Tb) { 2211 pLayoutChild = (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; 2212 for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; 2213 pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { 2214 if (pLayoutNext->m_sPos.y != pLayoutChild->m_sPos.y) 2215 pLayoutChild = pLayoutNext; 2216 } 2217 } 2218 2219 for (CXFA_ContentLayoutItem* pLayoutTempChild = 2220 (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; 2221 pLayoutTempChild != pLayoutChild; 2222 pLayoutTempChild = 2223 (CXFA_ContentLayoutItem*)pLayoutTempChild->m_pNextSibling) { 2224 if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutTempChild->m_pFormNode)) 2225 continue; 2226 2227 fContentCalculatedWidth = std::max( 2228 fContentCalculatedWidth, 2229 pLayoutTempChild->m_sPos.x + pLayoutTempChild->m_sSize.width); 2230 fContentCalculatedHeight = std::max( 2231 fContentCalculatedHeight, 2232 pLayoutTempChild->m_sPos.y + pLayoutTempChild->m_sSize.height); 2233 } 2234 2235 if (pLayoutChild) 2236 fContentCurRowY = pLayoutChild->m_sPos.y; 2237 else 2238 fContentCurRowY = fContentCalculatedHeight; 2239 } 2240 2241 fContentCurRowY += InsertKeepLayoutItems(); 2242 if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::None) { 2243 GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, 2244 true); 2245 } 2246 2247 fContentCurRowY += InsertPendingItems(this, m_pFormNode); 2248 if (m_pCurChildPreprocessor && 2249 m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Container) { 2250 if (ExistContainerKeep(m_pCurChildPreprocessor->GetFormNode(), false)) { 2251 m_pKeepHeadNode = m_pCurChildNode; 2252 m_bIsProcessKeep = true; 2253 m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Keep; 2254 } 2255 } 2256 2257 while (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done) { 2258 float fContentCurRowHeight = 0; 2259 float fContentCurRowAvailWidth = fContentWidthLimit; 2260 m_fWidthLimite = fContentCurRowAvailWidth; 2261 std::vector<CXFA_ContentLayoutItem*> rgCurLineLayoutItems[3]; 2262 uint8_t uCurHAlignState = 2263 (eFlowStrategy != XFA_AttributeEnum::Rl_tb ? 0 : 2); 2264 if (pLayoutChild) { 2265 for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; 2266 pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { 2267 if (!pLayoutNext->m_pNextSibling && m_pCurChildPreprocessor && 2268 m_pCurChildPreprocessor->m_pFormNode == pLayoutNext->m_pFormNode) { 2269 pLayoutNext->m_pNext = m_pCurChildPreprocessor->m_pLayoutItem; 2270 m_pCurChildPreprocessor->m_pLayoutItem = pLayoutNext; 2271 break; 2272 } 2273 uint8_t uHAlign = 2274 HAlignEnumToInt(pLayoutNext->m_pFormNode->JSObject()->GetEnum( 2275 XFA_Attribute::HAlign)); 2276 rgCurLineLayoutItems[uHAlign].push_back(pLayoutNext); 2277 if (eFlowStrategy == XFA_AttributeEnum::Lr_tb) { 2278 if (uHAlign > uCurHAlignState) 2279 uCurHAlignState = uHAlign; 2280 } else if (uHAlign < uCurHAlignState) { 2281 uCurHAlignState = uHAlign; 2282 } 2283 if (XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutNext->m_pFormNode)) { 2284 if (pLayoutNext->m_sSize.height > fContentCurRowHeight) 2285 fContentCurRowHeight = pLayoutNext->m_sSize.height; 2286 fContentCurRowAvailWidth -= pLayoutNext->m_sSize.width; 2287 } 2288 } 2289 2290 if ((CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild == 2291 pLayoutChild) { 2292 m_pLayoutItem->m_pFirstChild = nullptr; 2293 } else { 2294 CXFA_ContentLayoutItem* pLayoutNext = 2295 (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; 2296 for (; pLayoutNext; 2297 pLayoutNext = 2298 (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { 2299 if ((CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling == 2300 pLayoutChild) { 2301 pLayoutNext->m_pNextSibling = nullptr; 2302 break; 2303 } 2304 } 2305 } 2306 2307 CXFA_ContentLayoutItem* pLayoutNextTemp = 2308 (CXFA_ContentLayoutItem*)pLayoutChild; 2309 while (pLayoutNextTemp) { 2310 pLayoutNextTemp->m_pParent = nullptr; 2311 CXFA_ContentLayoutItem* pSaveLayoutNext = 2312 (CXFA_ContentLayoutItem*)pLayoutNextTemp->m_pNextSibling; 2313 pLayoutNextTemp->m_pNextSibling = nullptr; 2314 pLayoutNextTemp = pSaveLayoutNext; 2315 } 2316 pLayoutChild = nullptr; 2317 } 2318 2319 while (m_pCurChildNode) { 2320 std::unique_ptr<CXFA_ItemLayoutProcessor> pProcessor; 2321 bool bAddedItemInRow = false; 2322 fContentCurRowY += InsertPendingItems(this, m_pFormNode); 2323 switch (m_nCurChildNodeStage) { 2324 case XFA_ItemLayoutProcessorStages::Keep: 2325 case XFA_ItemLayoutProcessorStages::None: 2326 break; 2327 case XFA_ItemLayoutProcessorStages::BreakBefore: { 2328 for (auto* item : m_arrayKeepItems) { 2329 m_pLayoutItem->RemoveChild(item); 2330 fContentCalculatedHeight -= item->m_sSize.height; 2331 } 2332 2333 CXFA_Node* pLeaderNode = nullptr; 2334 CXFA_Node* pTrailerNode = nullptr; 2335 bool bCreatePage = false; 2336 if (!bUseBreakControl || !m_pPageMgr || 2337 !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, true, 2338 pLeaderNode, pTrailerNode, 2339 bCreatePage) || 2340 m_pFormNode->GetElementType() == XFA_Element::Form || 2341 !bCreatePage) { 2342 break; 2343 } 2344 2345 if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) 2346 AddPendingNode(this, pLeaderNode, true); 2347 2348 if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { 2349 if (m_pFormNode->GetParent()->GetElementType() == 2350 XFA_Element::Form && 2351 !m_pLayoutItem) { 2352 AddPendingNode(this, pTrailerNode, true); 2353 } else { 2354 auto pTempProcessor = 2355 pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pTrailerNode, 2356 nullptr); 2357 InsertFlowedItem( 2358 this, pTempProcessor.get(), bContainerWidthAutoSize, 2359 bContainerHeightAutoSize, containerSize.height, eFlowStrategy, 2360 &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, 2361 FLT_MAX, fContentWidthLimit, &fContentCurRowY, 2362 &fContentCurRowAvailWidth, &fContentCurRowHeight, 2363 &bAddedItemInRow, &bForceEndPage, pContext, false); 2364 } 2365 } 2366 GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, 2367 m_pFormNode, true); 2368 bForceEndPage = true; 2369 bIsManualBreak = true; 2370 goto SuspendAndCreateNewRow; 2371 } 2372 case XFA_ItemLayoutProcessorStages::BreakAfter: { 2373 CXFA_Node* pLeaderNode = nullptr; 2374 CXFA_Node* pTrailerNode = nullptr; 2375 bool bCreatePage = false; 2376 if (!bUseBreakControl || !m_pPageMgr || 2377 !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, false, 2378 pLeaderNode, pTrailerNode, 2379 bCreatePage) || 2380 m_pFormNode->GetElementType() == XFA_Element::Form) { 2381 break; 2382 } 2383 2384 if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { 2385 auto pTempProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( 2386 pTrailerNode, nullptr); 2387 InsertFlowedItem( 2388 this, pTempProcessor.get(), bContainerWidthAutoSize, 2389 bContainerHeightAutoSize, containerSize.height, eFlowStrategy, 2390 &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, FLT_MAX, 2391 fContentWidthLimit, &fContentCurRowY, &fContentCurRowAvailWidth, 2392 &fContentCurRowHeight, &bAddedItemInRow, &bForceEndPage, 2393 pContext, false); 2394 } 2395 if (!bCreatePage) { 2396 if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { 2397 CalculateRowChildPosition( 2398 rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, 2399 bContainerWidthAutoSize, &fContentCalculatedWidth, 2400 &fContentCalculatedHeight, &fContentCurRowY, 2401 fContentCurRowHeight, fContentWidthLimit, false); 2402 rgCurLineLayoutItems->clear(); 2403 auto pTempProcessor = 2404 pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pLeaderNode, 2405 nullptr); 2406 InsertFlowedItem( 2407 this, pTempProcessor.get(), bContainerWidthAutoSize, 2408 bContainerHeightAutoSize, containerSize.height, eFlowStrategy, 2409 &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, 2410 FLT_MAX, fContentWidthLimit, &fContentCurRowY, 2411 &fContentCurRowAvailWidth, &fContentCurRowHeight, 2412 &bAddedItemInRow, &bForceEndPage, pContext, false); 2413 } 2414 } else { 2415 if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) 2416 AddPendingNode(this, pLeaderNode, true); 2417 } 2418 2419 GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, 2420 m_pFormNode, true); 2421 if (bCreatePage) { 2422 bForceEndPage = true; 2423 bIsManualBreak = true; 2424 if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done) 2425 bBreakDone = true; 2426 } 2427 goto SuspendAndCreateNewRow; 2428 } 2429 case XFA_ItemLayoutProcessorStages::BookendLeader: { 2430 CXFA_Node* pLeaderNode = nullptr; 2431 if (m_pCurChildPreprocessor) { 2432 pProcessor.reset(m_pCurChildPreprocessor); 2433 m_pCurChildPreprocessor = nullptr; 2434 } else if (m_pPageMgr && 2435 m_pPageMgr->ProcessBookendLeaderOrTrailer( 2436 m_pCurChildNode, true, pLeaderNode)) { 2437 pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( 2438 pLeaderNode, m_pPageMgr); 2439 } 2440 2441 if (pProcessor) { 2442 if (InsertFlowedItem( 2443 this, pProcessor.get(), bContainerWidthAutoSize, 2444 bContainerHeightAutoSize, containerSize.height, 2445 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, 2446 bUseBreakControl, fAvailHeight, fRealHeight, 2447 fContentWidthLimit, &fContentCurRowY, 2448 &fContentCurRowAvailWidth, &fContentCurRowHeight, 2449 &bAddedItemInRow, &bForceEndPage, pContext, 2450 false) != XFA_ItemLayoutProcessorResult::Done) { 2451 goto SuspendAndCreateNewRow; 2452 } else { 2453 pProcessor.reset(); 2454 } 2455 } 2456 break; 2457 } 2458 case XFA_ItemLayoutProcessorStages::BookendTrailer: { 2459 CXFA_Node* pTrailerNode = nullptr; 2460 if (m_pCurChildPreprocessor) { 2461 pProcessor.reset(m_pCurChildPreprocessor); 2462 m_pCurChildPreprocessor = nullptr; 2463 } else if (m_pPageMgr && 2464 m_pPageMgr->ProcessBookendLeaderOrTrailer( 2465 m_pCurChildNode, false, pTrailerNode)) { 2466 pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( 2467 pTrailerNode, m_pPageMgr); 2468 } 2469 if (pProcessor) { 2470 if (InsertFlowedItem( 2471 this, pProcessor.get(), bContainerWidthAutoSize, 2472 bContainerHeightAutoSize, containerSize.height, 2473 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, 2474 bUseBreakControl, fAvailHeight, fRealHeight, 2475 fContentWidthLimit, &fContentCurRowY, 2476 &fContentCurRowAvailWidth, &fContentCurRowHeight, 2477 &bAddedItemInRow, &bForceEndPage, pContext, 2478 false) != XFA_ItemLayoutProcessorResult::Done) { 2479 goto SuspendAndCreateNewRow; 2480 } else { 2481 pProcessor.reset(); 2482 } 2483 } 2484 break; 2485 } 2486 case XFA_ItemLayoutProcessorStages::Container: { 2487 ASSERT(m_pCurChildNode->IsContainerNode()); 2488 if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) 2489 break; 2490 if (fContentCurRowY >= fHeightLimit + XFA_LAYOUT_FLOAT_PERCISION && 2491 XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) { 2492 bForceEndPage = true; 2493 goto SuspendAndCreateNewRow; 2494 } 2495 if (!m_pCurChildNode->IsContainerNode()) 2496 break; 2497 2498 bool bNewRow = false; 2499 if (m_pCurChildPreprocessor) { 2500 pProcessor.reset(m_pCurChildPreprocessor); 2501 m_pCurChildPreprocessor = nullptr; 2502 bNewRow = true; 2503 } else { 2504 pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( 2505 m_pCurChildNode, m_pPageMgr); 2506 } 2507 2508 InsertPendingItems(pProcessor.get(), m_pCurChildNode); 2509 XFA_ItemLayoutProcessorResult rs = InsertFlowedItem( 2510 this, pProcessor.get(), bContainerWidthAutoSize, 2511 bContainerHeightAutoSize, containerSize.height, eFlowStrategy, 2512 &uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl, 2513 fAvailHeight, fRealHeight, fContentWidthLimit, &fContentCurRowY, 2514 &fContentCurRowAvailWidth, &fContentCurRowHeight, 2515 &bAddedItemInRow, &bForceEndPage, pContext, bNewRow); 2516 switch (rs) { 2517 case XFA_ItemLayoutProcessorResult::ManualBreak: 2518 bIsManualBreak = true; 2519 case XFA_ItemLayoutProcessorResult::PageFullBreak: 2520 bForceEndPage = true; 2521 case XFA_ItemLayoutProcessorResult::RowFullBreak: 2522 goto SuspendAndCreateNewRow; 2523 case XFA_ItemLayoutProcessorResult::Done: 2524 default: 2525 fContentCurRowY += 2526 InsertPendingItems(pProcessor.get(), m_pCurChildNode); 2527 pProcessor.reset(); 2528 } 2529 break; 2530 } 2531 case XFA_ItemLayoutProcessorStages::Done: 2532 break; 2533 default: 2534 break; 2535 } 2536 GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, 2537 true); 2538 if (bAddedItemInRow && eFlowStrategy == XFA_AttributeEnum::Tb) 2539 break; 2540 continue; 2541 SuspendAndCreateNewRow: 2542 if (pProcessor) 2543 m_pCurChildPreprocessor = pProcessor.release(); 2544 break; 2545 } 2546 2547 CalculateRowChildPosition( 2548 rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, 2549 bContainerWidthAutoSize, &fContentCalculatedWidth, 2550 &fContentCalculatedHeight, &fContentCurRowY, fContentCurRowHeight, 2551 fContentWidthLimit, bRootForceTb); 2552 m_fWidthLimite = fContentCurRowAvailWidth; 2553 if (bForceEndPage) 2554 break; 2555 } 2556 2557 bool bRetValue = 2558 m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done && 2559 m_PendingNodes.empty(); 2560 if (bBreakDone) 2561 bRetValue = false; 2562 2563 containerSize = CalculateContainerComponentSizeFromContentSize( 2564 m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, 2565 bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); 2566 2567 if (containerSize.height >= XFA_LAYOUT_FLOAT_PERCISION || m_pLayoutItem || 2568 bRetValue) { 2569 if (!m_pLayoutItem) 2570 m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); 2571 containerSize.height = std::max(containerSize.height, 0.f); 2572 2573 SetCurrentComponentSize(containerSize); 2574 if (bForceEndPage) 2575 m_fUsedSize = 0; 2576 else 2577 m_fUsedSize += m_pLayoutItem->m_sSize.height; 2578 } 2579 2580 return bRetValue 2581 ? XFA_ItemLayoutProcessorResult::Done 2582 : (bIsManualBreak ? XFA_ItemLayoutProcessorResult::ManualBreak 2583 : XFA_ItemLayoutProcessorResult::PageFullBreak); 2584 } 2585 2586 bool CXFA_ItemLayoutProcessor::CalculateRowChildPosition( 2587 std::vector<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], 2588 XFA_AttributeEnum eFlowStrategy, 2589 bool bContainerHeightAutoSize, 2590 bool bContainerWidthAutoSize, 2591 float* fContentCalculatedWidth, 2592 float* fContentCalculatedHeight, 2593 float* fContentCurRowY, 2594 float fContentCurRowHeight, 2595 float fContentWidthLimit, 2596 bool bRootForceTb) { 2597 int32_t nGroupLengths[3] = {0, 0, 0}; 2598 float fGroupWidths[3] = {0, 0, 0}; 2599 int32_t nTotalLength = 0; 2600 for (int32_t i = 0; i < 3; i++) { 2601 nGroupLengths[i] = pdfium::CollectionSize<int32_t>(rgCurLineLayoutItems[i]); 2602 for (int32_t c = nGroupLengths[i], j = 0; j < c; j++) { 2603 nTotalLength++; 2604 if (XFA_ItemLayoutProcessor_IsTakingSpace( 2605 rgCurLineLayoutItems[i][j]->m_pFormNode)) { 2606 fGroupWidths[i] += rgCurLineLayoutItems[i][j]->m_sSize.width; 2607 } 2608 } 2609 } 2610 if (!nTotalLength) { 2611 if (bContainerHeightAutoSize) { 2612 *fContentCalculatedHeight = 2613 std::min(*fContentCalculatedHeight, *fContentCurRowY); 2614 } 2615 return false; 2616 } 2617 if (!m_pLayoutItem) 2618 m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); 2619 2620 if (eFlowStrategy != XFA_AttributeEnum::Rl_tb) { 2621 float fCurPos; 2622 fCurPos = 0; 2623 for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { 2624 if (bRootForceTb) { 2625 rgCurLineLayoutItems[0][j]->m_sPos = CalculatePositionedContainerPos( 2626 rgCurLineLayoutItems[0][j]->m_pFormNode, 2627 rgCurLineLayoutItems[0][j]->m_sSize); 2628 } else { 2629 rgCurLineLayoutItems[0][j]->m_sPos = 2630 CFX_PointF(fCurPos, *fContentCurRowY); 2631 if (XFA_ItemLayoutProcessor_IsTakingSpace( 2632 rgCurLineLayoutItems[0][j]->m_pFormNode)) { 2633 fCurPos += rgCurLineLayoutItems[0][j]->m_sSize.width; 2634 } 2635 } 2636 m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); 2637 m_fLastRowWidth = fCurPos; 2638 } 2639 fCurPos = (fContentWidthLimit + fGroupWidths[0] - fGroupWidths[1] - 2640 fGroupWidths[2]) / 2641 2; 2642 for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { 2643 if (bRootForceTb) { 2644 rgCurLineLayoutItems[1][j]->m_sPos = CalculatePositionedContainerPos( 2645 rgCurLineLayoutItems[1][j]->m_pFormNode, 2646 rgCurLineLayoutItems[1][j]->m_sSize); 2647 } else { 2648 rgCurLineLayoutItems[1][j]->m_sPos = 2649 CFX_PointF(fCurPos, *fContentCurRowY); 2650 if (XFA_ItemLayoutProcessor_IsTakingSpace( 2651 rgCurLineLayoutItems[1][j]->m_pFormNode)) { 2652 fCurPos += rgCurLineLayoutItems[1][j]->m_sSize.width; 2653 } 2654 } 2655 m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); 2656 m_fLastRowWidth = fCurPos; 2657 } 2658 fCurPos = fContentWidthLimit - fGroupWidths[2]; 2659 for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { 2660 if (bRootForceTb) { 2661 rgCurLineLayoutItems[2][j]->m_sPos = CalculatePositionedContainerPos( 2662 rgCurLineLayoutItems[2][j]->m_pFormNode, 2663 rgCurLineLayoutItems[2][j]->m_sSize); 2664 } else { 2665 rgCurLineLayoutItems[2][j]->m_sPos = 2666 CFX_PointF(fCurPos, *fContentCurRowY); 2667 if (XFA_ItemLayoutProcessor_IsTakingSpace( 2668 rgCurLineLayoutItems[2][j]->m_pFormNode)) { 2669 fCurPos += rgCurLineLayoutItems[2][j]->m_sSize.width; 2670 } 2671 } 2672 m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); 2673 m_fLastRowWidth = fCurPos; 2674 } 2675 } else { 2676 float fCurPos; 2677 fCurPos = fGroupWidths[0]; 2678 for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { 2679 if (XFA_ItemLayoutProcessor_IsTakingSpace( 2680 rgCurLineLayoutItems[0][j]->m_pFormNode)) { 2681 fCurPos -= rgCurLineLayoutItems[0][j]->m_sSize.width; 2682 } 2683 rgCurLineLayoutItems[0][j]->m_sPos = 2684 CFX_PointF(fCurPos, *fContentCurRowY); 2685 m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); 2686 m_fLastRowWidth = fCurPos; 2687 } 2688 fCurPos = (fContentWidthLimit + fGroupWidths[0] + fGroupWidths[1] - 2689 fGroupWidths[2]) / 2690 2; 2691 for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { 2692 if (XFA_ItemLayoutProcessor_IsTakingSpace( 2693 rgCurLineLayoutItems[1][j]->m_pFormNode)) { 2694 fCurPos -= rgCurLineLayoutItems[1][j]->m_sSize.width; 2695 } 2696 rgCurLineLayoutItems[1][j]->m_sPos = 2697 CFX_PointF(fCurPos, *fContentCurRowY); 2698 m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); 2699 m_fLastRowWidth = fCurPos; 2700 } 2701 fCurPos = fContentWidthLimit; 2702 for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { 2703 if (XFA_ItemLayoutProcessor_IsTakingSpace( 2704 rgCurLineLayoutItems[2][j]->m_pFormNode)) { 2705 fCurPos -= rgCurLineLayoutItems[2][j]->m_sSize.width; 2706 } 2707 rgCurLineLayoutItems[2][j]->m_sPos = 2708 CFX_PointF(fCurPos, *fContentCurRowY); 2709 m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); 2710 m_fLastRowWidth = fCurPos; 2711 } 2712 } 2713 m_fLastRowY = *fContentCurRowY; 2714 *fContentCurRowY += fContentCurRowHeight; 2715 if (bContainerWidthAutoSize) { 2716 float fChildSuppliedWidth = fGroupWidths[0]; 2717 if (fContentWidthLimit < FLT_MAX && 2718 fContentWidthLimit > fChildSuppliedWidth) { 2719 fChildSuppliedWidth = fContentWidthLimit; 2720 } 2721 *fContentCalculatedWidth = 2722 std::max(*fContentCalculatedWidth, fChildSuppliedWidth); 2723 } 2724 if (bContainerHeightAutoSize) { 2725 *fContentCalculatedHeight = 2726 std::max(*fContentCalculatedHeight, *fContentCurRowY); 2727 } 2728 return true; 2729 } 2730 2731 CXFA_Node* CXFA_ItemLayoutProcessor::GetSubformSetParent( 2732 CXFA_Node* pSubformSet) { 2733 if (pSubformSet && pSubformSet->GetElementType() == XFA_Element::SubformSet) { 2734 CXFA_Node* pParent = pSubformSet->GetParent(); 2735 while (pParent) { 2736 if (pParent->GetElementType() != XFA_Element::SubformSet) 2737 return pParent; 2738 pParent = pParent->GetParent(); 2739 } 2740 } 2741 return pSubformSet; 2742 } 2743 2744 void CXFA_ItemLayoutProcessor::DoLayoutField() { 2745 if (m_pLayoutItem) 2746 return; 2747 2748 ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); 2749 m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); 2750 if (!m_pLayoutItem) 2751 return; 2752 2753 CXFA_Document* pDocument = m_pFormNode->GetDocument(); 2754 CXFA_FFNotify* pNotify = pDocument->GetNotify(); 2755 CFX_SizeF size(-1, -1); 2756 pNotify->StartFieldDrawLayout(m_pFormNode, size.width, size.height); 2757 2758 int32_t nRotate = XFA_MapRotation( 2759 m_pFormNode->JSObject()->GetInteger(XFA_Attribute::Rotate)); 2760 if (nRotate == 90 || nRotate == 270) 2761 std::swap(size.width, size.height); 2762 2763 SetCurrentComponentSize(size); 2764 } 2765 2766 XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayout( 2767 bool bUseBreakControl, 2768 float fHeightLimit, 2769 float fRealHeight, 2770 CXFA_LayoutContext* pContext) { 2771 switch (m_pFormNode->GetElementType()) { 2772 case XFA_Element::Subform: 2773 case XFA_Element::Area: 2774 case XFA_Element::ExclGroup: 2775 case XFA_Element::SubformSet: { 2776 bool bRootForceTb = false; 2777 CXFA_Node* pLayoutNode = GetSubformSetParent(m_pFormNode); 2778 XFA_AttributeEnum eLayoutStrategy = GetLayout(pLayoutNode, &bRootForceTb); 2779 switch (eLayoutStrategy) { 2780 case XFA_AttributeEnum::Tb: 2781 case XFA_AttributeEnum::Lr_tb: 2782 case XFA_AttributeEnum::Rl_tb: 2783 return DoLayoutFlowedContainer(bUseBreakControl, eLayoutStrategy, 2784 fHeightLimit, fRealHeight, pContext, 2785 bRootForceTb); 2786 case XFA_AttributeEnum::Position: 2787 case XFA_AttributeEnum::Row: 2788 case XFA_AttributeEnum::Rl_row: 2789 default: 2790 DoLayoutPositionedContainer(pContext); 2791 m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; 2792 return XFA_ItemLayoutProcessorResult::Done; 2793 case XFA_AttributeEnum::Table: 2794 DoLayoutTableContainer(pLayoutNode); 2795 m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; 2796 return XFA_ItemLayoutProcessorResult::Done; 2797 } 2798 } 2799 case XFA_Element::Draw: 2800 case XFA_Element::Field: 2801 DoLayoutField(); 2802 m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; 2803 return XFA_ItemLayoutProcessorResult::Done; 2804 case XFA_Element::ContentArea: 2805 return XFA_ItemLayoutProcessorResult::Done; 2806 default: 2807 return XFA_ItemLayoutProcessorResult::Done; 2808 } 2809 } 2810 2811 CFX_SizeF CXFA_ItemLayoutProcessor::GetCurrentComponentSize() { 2812 return CFX_SizeF(m_pLayoutItem->m_sSize.width, m_pLayoutItem->m_sSize.height); 2813 } 2814 2815 void CXFA_ItemLayoutProcessor::SetCurrentComponentPos(const CFX_PointF& pos) { 2816 m_pLayoutItem->m_sPos = pos; 2817 } 2818 2819 void CXFA_ItemLayoutProcessor::SetCurrentComponentSize(const CFX_SizeF& size) { 2820 m_pLayoutItem->m_sSize = size; 2821 } 2822 2823 bool CXFA_ItemLayoutProcessor::JudgeLeaderOrTrailerForOccur( 2824 CXFA_Node* pFormNode) { 2825 if (!pFormNode) 2826 return false; 2827 2828 CXFA_Node* pTemplate = pFormNode->GetTemplateNodeIfExists(); 2829 if (!pTemplate) 2830 pTemplate = pFormNode; 2831 2832 int32_t iMax = 2833 pTemplate->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur)->GetMax(); 2834 if (iMax < 0) 2835 return true; 2836 2837 int32_t iCount = m_PendingNodesCount[pTemplate]; 2838 if (iCount >= iMax) 2839 return false; 2840 2841 m_PendingNodesCount[pTemplate] = iCount + 1; 2842 return true; 2843 } 2844