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