Refactor code in CXFA_ItemLayoutProcessor::DoLayoutFlowedContainer().

DoLayoutFlowedContainer() is over 400 lines long. Move some of the code
at the beginning into their own functions.

- Create functions like GetMarginInset() and use them in more places in
  the same file.
- Use structs from fx_coordinates.h as appropriate.
- Move some variables closer to where declared.

Change-Id: I53a38ca0175a22ce92d3f8ec71a66bed6a578bba
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52179
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
index dd5bf40..d0bfa10 100644
--- a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
+++ b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
@@ -171,6 +171,22 @@
   return componentSize;
 }
 
+CFX_FloatRect GetMarginInset(const CXFA_Margin* pMargin) {
+  CFX_FloatRect inset;
+  if (!pMargin)
+    return inset;
+
+  inset.left = pMargin->JSObject()->GetMeasureInUnit(XFA_Attribute::LeftInset,
+                                                     XFA_Unit::Pt);
+  inset.top = pMargin->JSObject()->GetMeasureInUnit(XFA_Attribute::TopInset,
+                                                    XFA_Unit::Pt);
+  inset.right = pMargin->JSObject()->GetMeasureInUnit(XFA_Attribute::RightInset,
+                                                      XFA_Unit::Pt);
+  inset.bottom = pMargin->JSObject()->GetMeasureInUnit(
+      XFA_Attribute::BottomInset, XFA_Unit::Pt);
+  return inset;
+}
+
 void RelocateTableRowCells(CXFA_ContentLayoutItem* pLayoutRow,
                            const std::vector<float>& rgSpecifiedColumnWidths,
                            XFA_AttributeValue eLayout) {
@@ -179,29 +195,15 @@
   CFX_SizeF containerSize = CalculateContainerSpecifiedSize(
       pLayoutRow->GetFormNode(), &bContainerWidthAutoSize,
       &bContainerHeightAutoSize);
-  CXFA_Margin* pMarginNode =
+  CXFA_Margin* pMargin =
       pLayoutRow->GetFormNode()->GetFirstChildByClass<CXFA_Margin>(
           XFA_Element::Margin);
-  float fLeftInset = 0;
-  float fTopInset = 0;
-  float fRightInset = 0;
-  float fBottomInset = 0;
-  if (pMarginNode) {
-    fLeftInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::LeftInset, XFA_Unit::Pt);
-    fTopInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::TopInset, XFA_Unit::Pt);
-    fRightInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::RightInset, XFA_Unit::Pt);
-    fBottomInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::BottomInset, XFA_Unit::Pt);
-  }
-
+  CFX_FloatRect inset = GetMarginInset(pMargin);
   float fContentWidthLimit =
       bContainerWidthAutoSize ? FLT_MAX
-                              : containerSize.width - fLeftInset - fRightInset;
+                              : containerSize.width - inset.left - inset.right;
   float fContentCurrentHeight =
-      pLayoutRow->m_sSize.height - fTopInset - fBottomInset;
+      pLayoutRow->m_sSize.height - inset.top - inset.bottom;
   float fContentCalculatedWidth = 0;
   float fContentCalculatedHeight = 0;
   float fCurrentColX = 0;
@@ -308,7 +310,7 @@
     fContentCalculatedWidth =
         std::max(fContentCalculatedWidth, fChildSuppliedWidth);
   } else {
-    fContentCalculatedWidth = containerSize.width - fLeftInset - fRightInset;
+    fContentCalculatedWidth = containerSize.width - inset.left - inset.right;
   }
 
   if (pLayoutRow->GetFormNode()->JSObject()->GetEnum(XFA_Attribute::Layout) ==
@@ -1504,102 +1506,36 @@
     CXFA_LayoutContext* pContext,
     bool bRootForceTb) {
   m_bHasAvailHeight = true;
-  bool bBreakDone = false;
-  bool bContainerWidthAutoSize = true;
-  bool bContainerHeightAutoSize = true;
-  bool bForceEndPage = false;
-  bool bIsManualBreak = false;
   if (m_pCurChildPreprocessor)
     m_pCurChildPreprocessor->m_ePreProcessRs = Result::kDone;
 
-  CFX_SizeF containerSize = CalculateContainerSpecifiedSize(
+  bool bContainerWidthAutoSize = true;
+  bool bContainerHeightAutoSize = true;
+  CFX_SizeF container_size = CalculateContainerSpecifiedSize(
       GetFormNode(), &bContainerWidthAutoSize, &bContainerHeightAutoSize);
-  if (pContext && pContext->m_fCurColumnWidth.has_value()) {
-    containerSize.width = pContext->m_fCurColumnWidth.value();
-    bContainerWidthAutoSize = false;
-  }
-  if (!bContainerHeightAutoSize)
-    containerSize.height -= m_fUsedSize;
+  AdjustContainerSpecifiedSize(pContext, &container_size,
+                               &bContainerWidthAutoSize,
+                               &bContainerHeightAutoSize);
 
-  if (!bContainerHeightAutoSize) {
-    CXFA_Node* pParentNode = GetFormNode()->GetParent();
-    bool bFocrTb = false;
-    if (pParentNode &&
-        GetLayout(pParentNode, &bFocrTb) == XFA_AttributeValue::Row) {
-      CXFA_Node* pChildContainer = GetFormNode()->GetFirstContainerChild();
-      if (pChildContainer && pChildContainer->GetNextContainerSibling()) {
-        containerSize.height = 0;
-        bContainerHeightAutoSize = true;
-      }
-    }
-  }
-
-  CXFA_Margin* pMarginNode =
+  CXFA_Margin* pMargin =
       GetFormNode()->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin);
-  float fLeftInset = 0;
-  float fTopInset = 0;
-  float fRightInset = 0;
-  float fBottomInset = 0;
-  if (pMarginNode) {
-    fLeftInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::LeftInset, XFA_Unit::Pt);
-    fTopInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::TopInset, XFA_Unit::Pt);
-    fRightInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::RightInset, XFA_Unit::Pt);
-    fBottomInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::BottomInset, XFA_Unit::Pt);
-  }
+  CFX_FloatRect inset = GetMarginInset(pMargin);
   float fContentWidthLimit =
       bContainerWidthAutoSize ? FLT_MAX
-                              : containerSize.width - fLeftInset - fRightInset;
-  float fContentCalculatedWidth = 0;
-  float fContentCalculatedHeight = 0;
-  float fAvailHeight = fHeightLimit - fTopInset - fBottomInset;
+                              : container_size.width - inset.left - inset.right;
+  float fAvailHeight = fHeightLimit - inset.top - inset.bottom;
   if (fAvailHeight < 0)
     m_bHasAvailHeight = false;
 
-  fRealHeight = fRealHeight - fTopInset - fBottomInset;
+  fRealHeight = fRealHeight - inset.top - inset.bottom;
+  CFX_SizeF calculated_size;
   float fContentCurRowY = 0;
-  CXFA_ContentLayoutItem* pLayoutChild = nullptr;
+  CXFA_ContentLayoutItem* pLastChild = nullptr;
   if (m_pLayoutItem) {
-    if (m_nCurChildNodeStage != Stage::kDone &&
-        eFlowStrategy != XFA_AttributeValue::Tb) {
-      pLayoutChild = ToContentLayoutItem(m_pLayoutItem->GetFirstChild());
-      for (CXFA_LayoutItem* pLayoutNext = pLayoutChild; pLayoutNext;
-           pLayoutNext = pLayoutNext->GetNextSibling()) {
-        CXFA_ContentLayoutItem* pContentNext =
-            pLayoutNext->AsContentLayoutItem();
-        if (!pContentNext)
-          continue;
-
-        if (pContentNext->m_sPos.y != pLayoutChild->m_sPos.y)
-          pLayoutChild = pContentNext;
-      }
-    }
-
-    for (CXFA_LayoutItem* pTempChild = m_pLayoutItem->GetFirstChild();
-         pTempChild != pLayoutChild;
-         pTempChild = pTempChild->GetNextSibling()) {
-      CXFA_ContentLayoutItem* pLayoutTempChild =
-          pTempChild->AsContentLayoutItem();
-      if (!pLayoutTempChild)
-        continue;
-      if (!pLayoutTempChild->GetFormNode()->PresenceRequiresSpace())
-        continue;
-
-      fContentCalculatedWidth = std::max(
-          fContentCalculatedWidth,
-          pLayoutTempChild->m_sPos.x + pLayoutTempChild->m_sSize.width);
-      fContentCalculatedHeight = std::max(
-          fContentCalculatedHeight,
-          pLayoutTempChild->m_sPos.y + pLayoutTempChild->m_sSize.height);
-    }
-
-    if (pLayoutChild)
-      fContentCurRowY = pLayoutChild->m_sPos.y;
-    else
-      fContentCurRowY = fContentCalculatedHeight;
+    pLastChild = FindLastContentLayoutItem(eFlowStrategy);
+    calculated_size = CalculateLayoutItemSize(pLastChild);
+    fContentCurRowY =
+        pLastChild ? pLastChild->m_sPos.y : calculated_size.height;
   }
 
   fContentCurRowY += InsertKeepLayoutItems();
@@ -1615,6 +1551,9 @@
     }
   }
 
+  bool bForceEndPage = false;
+  bool bBreakDone = false;
+  bool bIsManualBreak = false;
   while (m_nCurChildNodeStage != Stage::kDone) {
     float fContentCurRowHeight = 0;
     float fContentCurRowAvailWidth = fContentWidthLimit;
@@ -1622,8 +1561,8 @@
     std::vector<CXFA_ContentLayoutItem*> rgCurLineLayoutItems[3];
     uint8_t uCurHAlignState =
         (eFlowStrategy != XFA_AttributeValue::Rl_tb ? 0 : 2);
-    if (pLayoutChild) {
-      for (CXFA_LayoutItem* pNext = pLayoutChild; pNext;
+    if (pLastChild) {
+      for (CXFA_LayoutItem* pNext = pLastChild; pNext;
            pNext = pNext->GetNextSibling()) {
         CXFA_ContentLayoutItem* pLayoutNext = pNext->AsContentLayoutItem();
         if (!pLayoutNext)
@@ -1653,21 +1592,20 @@
         }
       }
 
-      if (ToContentLayoutItem(m_pLayoutItem->GetFirstChild()) == pLayoutChild) {
+      if (ToContentLayoutItem(m_pLayoutItem->GetFirstChild()) == pLastChild) {
         m_pLayoutItem->SetFirstChild(nullptr);
       } else {
         for (CXFA_LayoutItem* pLayoutNext = m_pLayoutItem->GetFirstChild();
              pLayoutNext; pLayoutNext = pLayoutNext->GetNextSibling()) {
           if (ToContentLayoutItem(pLayoutNext->GetNextSibling()) ==
-              pLayoutChild) {
+              pLastChild) {
             pLayoutNext->SetNextSibling(nullptr);
             break;
           }
         }
       }
 
-      CXFA_ContentLayoutItem* pLayoutNextTemp =
-          ToContentLayoutItem(pLayoutChild);
+      CXFA_ContentLayoutItem* pLayoutNextTemp = ToContentLayoutItem(pLastChild);
       while (pLayoutNextTemp) {
         pLayoutNextTemp->SetParent(nullptr);
         CXFA_ContentLayoutItem* pSaveLayoutNext =
@@ -1675,7 +1613,7 @@
         pLayoutNextTemp->SetNextSibling(nullptr);
         pLayoutNextTemp = pSaveLayoutNext;
       }
-      pLayoutChild = nullptr;
+      pLastChild = nullptr;
     }
 
     while (m_pCurChildNode) {
@@ -1689,7 +1627,7 @@
         case Stage::kBreakBefore: {
           for (auto* item : m_arrayKeepItems) {
             m_pLayoutItem->RemoveChild(item);
-            fContentCalculatedHeight -= item->m_sSize.height;
+            calculated_size.height -= item->m_sSize.height;
           }
 
           if (!bUseBreakControl || !m_pPageMgr)
@@ -1718,9 +1656,9 @@
                                                                nullptr);
               InsertFlowedItem(
                   pTempProcessor.get(), bContainerWidthAutoSize,
-                  bContainerHeightAutoSize, containerSize.height, eFlowStrategy,
-                  &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX,
-                  FLT_MAX, fContentWidthLimit, &fContentCurRowY,
+                  bContainerHeightAutoSize, container_size.height,
+                  eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, false,
+                  FLT_MAX, FLT_MAX, fContentWidthLimit, &fContentCurRowY,
                   &fContentCurRowAvailWidth, &fContentCurRowHeight,
                   &bAddedItemInRow, &bForceEndPage, pContext, false);
             }
@@ -1748,7 +1686,7 @@
             auto pTempProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(
                 pTrailerNode, nullptr);
             InsertFlowedItem(pTempProcessor.get(), bContainerWidthAutoSize,
-                             bContainerHeightAutoSize, containerSize.height,
+                             bContainerHeightAutoSize, container_size.height,
                              eFlowStrategy, &uCurHAlignState,
                              rgCurLineLayoutItems, false, FLT_MAX, FLT_MAX,
                              fContentWidthLimit, &fContentCurRowY,
@@ -1759,8 +1697,8 @@
             if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) {
               CalculateRowChildPosition(
                   rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize,
-                  bContainerWidthAutoSize, &fContentCalculatedWidth,
-                  &fContentCalculatedHeight, &fContentCurRowY,
+                  bContainerWidthAutoSize, &calculated_size.width,
+                  &calculated_size.height, &fContentCurRowY,
                   fContentCurRowHeight, fContentWidthLimit, false);
               rgCurLineLayoutItems->clear();
               auto pTempProcessor =
@@ -1768,9 +1706,9 @@
                                                                nullptr);
               InsertFlowedItem(
                   pTempProcessor.get(), bContainerWidthAutoSize,
-                  bContainerHeightAutoSize, containerSize.height, eFlowStrategy,
-                  &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX,
-                  FLT_MAX, fContentWidthLimit, &fContentCurRowY,
+                  bContainerHeightAutoSize, container_size.height,
+                  eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, false,
+                  FLT_MAX, FLT_MAX, fContentWidthLimit, &fContentCurRowY,
                   &fContentCurRowAvailWidth, &fContentCurRowHeight,
                   &bAddedItemInRow, &bForceEndPage, pContext, false);
             }
@@ -1801,15 +1739,15 @@
           }
 
           if (pProcessor) {
-            if (InsertFlowedItem(pProcessor.get(), bContainerWidthAutoSize,
-                                 bContainerHeightAutoSize, containerSize.height,
-                                 eFlowStrategy, &uCurHAlignState,
-                                 rgCurLineLayoutItems, bUseBreakControl,
-                                 fAvailHeight, fRealHeight, fContentWidthLimit,
-                                 &fContentCurRowY, &fContentCurRowAvailWidth,
-                                 &fContentCurRowHeight, &bAddedItemInRow,
-                                 &bForceEndPage, pContext,
-                                 false) != Result::kDone) {
+            if (InsertFlowedItem(
+                    pProcessor.get(), bContainerWidthAutoSize,
+                    bContainerHeightAutoSize, container_size.height,
+                    eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
+                    bUseBreakControl, fAvailHeight, fRealHeight,
+                    fContentWidthLimit, &fContentCurRowY,
+                    &fContentCurRowAvailWidth, &fContentCurRowHeight,
+                    &bAddedItemInRow, &bForceEndPage, pContext,
+                    false) != Result::kDone) {
               goto SuspendAndCreateNewRow;
             }
             pProcessor.reset();
@@ -1828,15 +1766,15 @@
             }
           }
           if (pProcessor) {
-            if (InsertFlowedItem(pProcessor.get(), bContainerWidthAutoSize,
-                                 bContainerHeightAutoSize, containerSize.height,
-                                 eFlowStrategy, &uCurHAlignState,
-                                 rgCurLineLayoutItems, bUseBreakControl,
-                                 fAvailHeight, fRealHeight, fContentWidthLimit,
-                                 &fContentCurRowY, &fContentCurRowAvailWidth,
-                                 &fContentCurRowHeight, &bAddedItemInRow,
-                                 &bForceEndPage, pContext,
-                                 false) != Result::kDone) {
+            if (InsertFlowedItem(
+                    pProcessor.get(), bContainerWidthAutoSize,
+                    bContainerHeightAutoSize, container_size.height,
+                    eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
+                    bUseBreakControl, fAvailHeight, fRealHeight,
+                    fContentWidthLimit, &fContentCurRowY,
+                    &fContentCurRowAvailWidth, &fContentCurRowHeight,
+                    &bAddedItemInRow, &bForceEndPage, pContext,
+                    false) != Result::kDone) {
               goto SuspendAndCreateNewRow;
             }
             pProcessor.reset();
@@ -1867,7 +1805,7 @@
           pProcessor->InsertPendingItems(m_pCurChildNode);
           Result rs = InsertFlowedItem(
               pProcessor.get(), bContainerWidthAutoSize,
-              bContainerHeightAutoSize, containerSize.height, eFlowStrategy,
+              bContainerHeightAutoSize, container_size.height, eFlowStrategy,
               &uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl,
               fAvailHeight, fRealHeight, fContentWidthLimit, &fContentCurRowY,
               &fContentCurRowAvailWidth, &fContentCurRowHeight,
@@ -1905,11 +1843,11 @@
       break;
     }
 
-    CalculateRowChildPosition(
-        rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize,
-        bContainerWidthAutoSize, &fContentCalculatedWidth,
-        &fContentCalculatedHeight, &fContentCurRowY, fContentCurRowHeight,
-        fContentWidthLimit, bRootForceTb);
+    CalculateRowChildPosition(rgCurLineLayoutItems, eFlowStrategy,
+                              bContainerHeightAutoSize, bContainerWidthAutoSize,
+                              &calculated_size.width, &calculated_size.height,
+                              &fContentCurRowY, fContentCurRowHeight,
+                              fContentWidthLimit, bRootForceTb);
     m_fWidthLimit = fContentCurRowAvailWidth;
     if (bForceEndPage)
       break;
@@ -1920,26 +1858,26 @@
   if (bBreakDone)
     bRetValue = false;
 
-  containerSize = CalculateContainerComponentSizeFromContentSize(
-      GetFormNode(), bContainerWidthAutoSize, fContentCalculatedWidth,
-      bContainerHeightAutoSize, fContentCalculatedHeight, containerSize);
+  container_size = CalculateContainerComponentSizeFromContentSize(
+      GetFormNode(), bContainerWidthAutoSize, calculated_size.width,
+      bContainerHeightAutoSize, calculated_size.height, container_size);
 
-  if (containerSize.height >= kXFALayoutPrecision || m_pLayoutItem ||
+  if (container_size.height >= kXFALayoutPrecision || m_pLayoutItem ||
       bRetValue) {
     if (!m_pLayoutItem)
       m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
-    containerSize.height = std::max(containerSize.height, 0.f);
+    container_size.height = std::max(container_size.height, 0.f);
 
-    SetCurrentComponentSize(containerSize);
+    SetCurrentComponentSize(container_size);
     if (bForceEndPage)
       m_fUsedSize = 0;
     else
       m_fUsedSize += m_pLayoutItem->m_sSize.height;
   }
 
-  return bRetValue
-             ? Result::kDone
-             : (bIsManualBreak ? Result::kManualBreak : Result::kPageFullBreak);
+  if (bRetValue)
+    return Result::kDone;
+  return bIsManualBreak ? Result::kManualBreak : Result::kPageFullBreak;
 }
 
 bool CXFA_ItemLayoutProcessor::CalculateRowChildPosition(
@@ -2226,23 +2164,9 @@
   }
 
   UpdatePendingItemLayout(pTrailerLayoutItem);
-  CXFA_Margin* pMarginNode =
+  CXFA_Margin* pMargin =
       GetFormNode()->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin);
-  float fLeftInset = 0;
-  float fTopInset = 0;
-  float fRightInset = 0;
-  float fBottomInset = 0;
-  if (pMarginNode) {
-    fLeftInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::LeftInset, XFA_Unit::Pt);
-    fTopInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::TopInset, XFA_Unit::Pt);
-    fRightInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::RightInset, XFA_Unit::Pt);
-    fBottomInset = pMarginNode->JSObject()->GetMeasureInUnit(
-        XFA_Attribute::BottomInset, XFA_Unit::Pt);
-  }
-
+  CFX_FloatRect inset = GetMarginInset(pMargin);
   if (!IsAddNewRowForTrailer(pTrailerLayoutItem)) {
     pTrailerLayoutItem->m_sPos.y = m_fLastRowY;
     pTrailerLayoutItem->m_sPos.x = m_fLastRowWidth;
@@ -2257,27 +2181,27 @@
 
   if (fNewSplitPos > kXFALayoutPrecision) {
     SplitLayoutItem(fNewSplitPos);
-    pTrailerLayoutItem->m_sPos.y = fNewSplitPos - fTopInset - fBottomInset;
+    pTrailerLayoutItem->m_sPos.y = fNewSplitPos - inset.top - inset.bottom;
   } else {
-    pTrailerLayoutItem->m_sPos.y = fSplitPos - fTopInset - fBottomInset;
+    pTrailerLayoutItem->m_sPos.y = fSplitPos - inset.top - inset.bottom;
   }
 
   switch (pTrailerLayoutItem->GetFormNode()->JSObject()->GetEnum(
       XFA_Attribute::HAlign)) {
     case XFA_AttributeValue::Right:
       pTrailerLayoutItem->m_sPos.x = m_pLayoutItem->m_sSize.width -
-                                     fRightInset -
+                                     inset.right -
                                      pTrailerLayoutItem->m_sSize.width;
       break;
     case XFA_AttributeValue::Center:
       pTrailerLayoutItem->m_sPos.x =
-          (m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset -
+          (m_pLayoutItem->m_sSize.width - inset.left - inset.right -
            pTrailerLayoutItem->m_sSize.width) /
           2;
       break;
     case XFA_AttributeValue::Left:
     default:
-      pTrailerLayoutItem->m_sPos.x = fLeftInset;
+      pTrailerLayoutItem->m_sPos.x = inset.left;
       break;
   }
   m_pLayoutItem->m_sSize.height += fHeight;
@@ -2815,3 +2739,66 @@
   m_pKeepTailNode = nullptr;
   m_bIsProcessKeep = false;
 }
+
+void CXFA_ItemLayoutProcessor::AdjustContainerSpecifiedSize(
+    CXFA_LayoutContext* pContext,
+    CFX_SizeF* pSize,
+    bool* pContainerWidthAutoSize,
+    bool* pContainerHeightAutoSize) {
+  if (pContext && pContext->m_fCurColumnWidth.has_value()) {
+    pSize->width = pContext->m_fCurColumnWidth.value();
+    *pContainerWidthAutoSize = false;
+  }
+  if (*pContainerHeightAutoSize)
+    return;
+
+  pSize->height -= m_fUsedSize;
+  CXFA_Node* pParentNode = GetFormNode()->GetParent();
+  bool bFocrTb = false;
+  if (!pParentNode ||
+      GetLayout(pParentNode, &bFocrTb) != XFA_AttributeValue::Row) {
+    return;
+  }
+
+  CXFA_Node* pChildContainer = GetFormNode()->GetFirstContainerChild();
+  if (!pChildContainer || !pChildContainer->GetNextContainerSibling())
+    return;
+
+  pSize->height = 0;
+  *pContainerHeightAutoSize = true;
+}
+
+CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::FindLastContentLayoutItem(
+    XFA_AttributeValue eFlowStrategy) {
+  if (m_nCurChildNodeStage == Stage::kDone ||
+      eFlowStrategy == XFA_AttributeValue::Tb) {
+    return nullptr;
+  }
+
+  CXFA_ContentLayoutItem* pLastChild =
+      ToContentLayoutItem(m_pLayoutItem->GetFirstChild());
+  for (CXFA_LayoutItem* pNext = pLastChild; pNext;
+       pNext = pNext->GetNextSibling()) {
+    CXFA_ContentLayoutItem* pContentNext = pNext->AsContentLayoutItem();
+    if (pContentNext && pContentNext->m_sPos.y != pLastChild->m_sPos.y)
+      pLastChild = pContentNext;
+  }
+  return pLastChild;
+}
+
+CFX_SizeF CXFA_ItemLayoutProcessor::CalculateLayoutItemSize(
+    const CXFA_ContentLayoutItem* pLastChild) {
+  CFX_SizeF size;
+  for (CXFA_LayoutItem* pChild = m_pLayoutItem->GetFirstChild();
+       pChild != pLastChild; pChild = pChild->GetNextSibling()) {
+    CXFA_ContentLayoutItem* pLayout = pChild->AsContentLayoutItem();
+    if (!pLayout || !pLayout->GetFormNode()->PresenceRequiresSpace())
+      continue;
+
+    float fWidth = pLayout->m_sPos.x + pLayout->m_sSize.width;
+    float fHeight = pLayout->m_sPos.y + pLayout->m_sSize.height;
+    size.width = std::max(size.width, fWidth);
+    size.height = std::max(size.height, fHeight);
+  }
+  return size;
+}
diff --git a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.h b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.h
index 5cfd8a2..6fdf25b 100644
--- a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.h
+++ b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.h
@@ -176,6 +176,13 @@
   Optional<Stage> HandleBookendTrailer(CXFA_Node* pParentContainer,
                                        CXFA_Node** pCurActionNode);
   void ProcessKeepNodesEnd();
+  void AdjustContainerSpecifiedSize(CXFA_LayoutContext* pContext,
+                                    CFX_SizeF* pSize,
+                                    bool* pContainerWidthAutoSize,
+                                    bool* pContainerHeightAutoSize);
+  CXFA_ContentLayoutItem* FindLastContentLayoutItem(
+      XFA_AttributeValue eFlowStrategy);
+  CFX_SizeF CalculateLayoutItemSize(const CXFA_ContentLayoutItem* pLayoutChild);
 
   Stage m_nCurChildNodeStage = Stage::kNone;
   Result m_ePreProcessRs = Result::kDone;