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