• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SeparateStringW(const FX_WCHAR * pStr,int32_t iStrLen,FX_WCHAR delimiter)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 
UpdateWidgetSize(CXFA_ContentLayoutItem * pLayoutItem,FX_FLOAT * fWidth,FX_FLOAT * fHeight)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 
CalculateContainerSpecifiedSize(CXFA_Node * pFormNode,bool * bContainerWidthAutoSize,bool * bContainerHeightAutoSize)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 
CalculateContainerComponentSizeFromContentSize(CXFA_Node * pFormNode,bool bContainerWidthAutoSize,FX_FLOAT fContentCalculatedWidth,bool bContainerHeightAutoSize,FX_FLOAT fContentCalculatedHeight,const CFX_SizeF & currentContainerSize)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 
RelocateTableRowCells(CXFA_ContentLayoutItem * pLayoutRow,const CFX_ArrayTemplate<FX_FLOAT> & rgSpecifiedColumnWidths,XFA_ATTRIBUTEENUM eLayout)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 
UpdatePendingItemLayout(CXFA_ItemLayoutProcessor * pProcessor,CXFA_ContentLayoutItem * pLayoutItem)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 
AddTrailerBeforeSplit(CXFA_ItemLayoutProcessor * pProcessor,FX_FLOAT fSplitPos,CXFA_ContentLayoutItem * pTrailerLayoutItem,bool bUseInherited)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 
AddLeaderAfterSplit(CXFA_ItemLayoutProcessor * pProcessor,CXFA_ContentLayoutItem * pLeaderLayoutItem)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 
AddPendingNode(CXFA_ItemLayoutProcessor * pProcessor,CXFA_Node * pPendingNode,bool bBreakPending)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 
InsertPendingItems(CXFA_ItemLayoutProcessor * pProcessor,CXFA_Node * pCurChildNode)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 
GetLayout(CXFA_Node * pFormNode,bool * bRootForceTb)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 
ExistContainerKeep(CXFA_Node * pCurNode,bool bPreFind)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 
FindBreakNode(CXFA_Node * pContainerNode,CXFA_Node * & pCurActionNode,XFA_ItemLayoutProcessorStages * nCurStage,bool bBreakBefore)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 
DeleteLayoutGeneratedNode(CXFA_Node * pGenerateNode)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 
HAlignEnumToInt(XFA_ATTRIBUTEENUM eHAlign)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 
InsertFlowedItem(CXFA_ItemLayoutProcessor * pThis,CXFA_ItemLayoutProcessor * pProcessor,bool bContainerWidthAutoSize,bool bContainerHeightAutoSize,FX_FLOAT fContainerHeight,XFA_ATTRIBUTEENUM eFlowStrategy,uint8_t * uCurHAlignState,CFX_ArrayTemplate<CXFA_ContentLayoutItem * > (& rgCurLineLayoutItems)[3],bool bUseBreakControl,FX_FLOAT fAvailHeight,FX_FLOAT fRealHeight,FX_FLOAT fContentWidthLimit,FX_FLOAT * fContentCurRowY,FX_FLOAT * fContentCurRowAvailWidth,FX_FLOAT * fContentCurRowHeight,bool * bAddedItemInRow,bool * bForceEndPage,CXFA_LayoutContext * pLayoutContext,bool bNewRow)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 
FindLayoutItemSplitPos(CXFA_ContentLayoutItem * pLayoutItem,FX_FLOAT fCurVerticalOffset,FX_FLOAT * fProposedSplitPos,bool * bAppChange,bool bCalculateMargin)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 
CalculatePositionedContainerPos(CXFA_Node * pNode,const CFX_SizeF & size)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 
CXFA_ItemLayoutProcessor(CXFA_Node * pNode,CXFA_LayoutPageMgr * pPageMgr)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 
~CXFA_ItemLayoutProcessor()1122 CXFA_ItemLayoutProcessor::~CXFA_ItemLayoutProcessor() {}
1123 
CreateContentLayoutItem(CXFA_Node * pFormNode)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 
FindSplitPos(FX_FLOAT fProposedSplitPos)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 
SplitLayoutItem(CXFA_ContentLayoutItem * pLayoutItem,CXFA_ContentLayoutItem * pSecondParent,FX_FLOAT fSplitPos)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 
SplitLayoutItem(FX_FLOAT fSplitPos)1285 void CXFA_ItemLayoutProcessor::SplitLayoutItem(FX_FLOAT fSplitPos) {
1286   ASSERT(m_pLayoutItem);
1287   SplitLayoutItem(m_pLayoutItem, nullptr, fSplitPos);
1288 }
1289 
ExtractLayoutItem()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 
GotoNextContainerNode(CXFA_Node * & pCurActionNode,XFA_ItemLayoutProcessorStages & nCurStage,CXFA_Node * pParentContainer,bool bUsePageBreak)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 
ProcessKeepNodesForCheckNext(CXFA_Node * & pCurActionNode,XFA_ItemLayoutProcessorStages & nCurStage,CXFA_Node * & pNextContainer,bool & bLastKeepNode)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 
ProcessKeepNodesForBreakBefore(CXFA_Node * & pCurActionNode,XFA_ItemLayoutProcessorStages & nCurStage,CXFA_Node * pContainerNode)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 
XFA_ItemLayoutProcessor_IsTakingSpace(CXFA_Node * pNode)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 
IncrementRelayoutNode(CXFA_LayoutProcessor * pLayoutProcessor,CXFA_Node * pNode,CXFA_Node * pParentNode)1551 bool CXFA_ItemLayoutProcessor::IncrementRelayoutNode(
1552     CXFA_LayoutProcessor* pLayoutProcessor,
1553     CXFA_Node* pNode,
1554     CXFA_Node* pParentNode) {
1555   return false;
1556 }
1557 
DoLayoutPageArea(CXFA_ContainerLayoutItem * pPageAreaLayoutItem)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 
DoLayoutPositionedContainer(CXFA_LayoutContext * pContext)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 
DoLayoutTableContainer(CXFA_Node * pLayoutNode)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 
IsAddNewRowForTrailer(CXFA_ContentLayoutItem * pTrailerItem)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 
InsertKeepLayoutItems()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 
ProcessKeepForSplit(CXFA_ItemLayoutProcessor * pParentProcessor,CXFA_ItemLayoutProcessor * pChildProcessor,XFA_ItemLayoutProcessorResult eRetValue,CFX_ArrayTemplate<CXFA_ContentLayoutItem * > * rgCurLineLayoutItem,FX_FLOAT * fContentCurRowAvailWidth,FX_FLOAT * fContentCurRowHeight,FX_FLOAT * fContentCurRowY,bool * bAddedItemInRow,bool * bForceEndPage,XFA_ItemLayoutProcessorResult * result)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 
JudgePutNextPage(CXFA_ContentLayoutItem * pParentLayoutItem,FX_FLOAT fChildHeight,std::vector<CXFA_ContentLayoutItem * > * pKeepItems)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 
ProcessUnUseBinds(CXFA_Node * pFormNode)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 
ProcessUnUseOverFlow(CXFA_Node * pLeaderNode,CXFA_Node * pTrailerNode,CXFA_ContentLayoutItem * pTrailerItem,CXFA_Node * pFormNode)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 
DoLayoutFlowedContainer(bool bUseBreakControl,XFA_ATTRIBUTEENUM eFlowStrategy,FX_FLOAT fHeightLimit,FX_FLOAT fRealHeight,CXFA_LayoutContext * pContext,bool bRootForceTb)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 
CalculateRowChildPosition(CFX_ArrayTemplate<CXFA_ContentLayoutItem * > (& rgCurLineLayoutItems)[3],XFA_ATTRIBUTEENUM eFlowStrategy,bool bContainerHeightAutoSize,bool bContainerWidthAutoSize,FX_FLOAT * fContentCalculatedWidth,FX_FLOAT * fContentCalculatedHeight,FX_FLOAT * fContentCurRowY,FX_FLOAT fContentCurRowHeight,FX_FLOAT fContentWidthLimit,bool bRootForceTb)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 
GetSubformSetParent(CXFA_Node * pSubformSet)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 
DoLayoutField()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 
DoLayout(bool bUseBreakControl,FX_FLOAT fHeightLimit,FX_FLOAT fRealHeight,CXFA_LayoutContext * pContext)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 
GetCurrentComponentSize()2761 CFX_SizeF CXFA_ItemLayoutProcessor::GetCurrentComponentSize() {
2762   return CFX_SizeF(m_pLayoutItem->m_sSize.width, m_pLayoutItem->m_sSize.height);
2763 }
2764 
SetCurrentComponentPos(const CFX_PointF & pos)2765 void CXFA_ItemLayoutProcessor::SetCurrentComponentPos(const CFX_PointF& pos) {
2766   m_pLayoutItem->m_sPos = pos;
2767 }
2768 
SetCurrentComponentSize(const CFX_SizeF & size)2769 void CXFA_ItemLayoutProcessor::SetCurrentComponentSize(const CFX_SizeF& size) {
2770   m_pLayoutItem->m_sSize = size;
2771 }
2772 
JudgeLeaderOrTrailerForOccur(CXFA_Node * pFormNode)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