Separate CXFA_FFWidget from CXFA_ContentLayoutItem.

Layering. Precursor to ref-counting layout items so that dozens
of FF classes need not become refcounted.

Change-Id: I806c0905111cb4c3cd2ce5d7f5afa7d8e6b72235
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52970
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_xfawidget.cpp b/fpdfsdk/cpdfsdk_xfawidget.cpp
index fc88f9c..ef6e127 100644
--- a/fpdfsdk/cpdfsdk_xfawidget.cpp
+++ b/fpdfsdk/cpdfsdk_xfawidget.cpp
@@ -31,7 +31,7 @@
 }
 
 CFX_FloatRect CPDFSDK_XFAWidget::GetRect() const {
-  CFX_RectF rcBBox = GetXFAWidget()->GetRect(false);
+  CFX_RectF rcBBox = GetXFAWidget()->GetLayoutItem()->GetRect(false);
   return CFX_FloatRect(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width,
                        rcBBox.top + rcBBox.height);
 }
diff --git a/xfa/fxfa/cxfa_ffdatetimeedit.cpp b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
index eae163b..32ab1ab 100644
--- a/xfa/fxfa/cxfa_ffdatetimeedit.cpp
+++ b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
@@ -172,7 +172,7 @@
 }
 
 bool CXFA_FFDateTimeEdit::IsDataChanged() {
-  if (m_dwStatus & XFA_WidgetStatus_TextEditValueChanged)
+  if (GetLayoutItem()->m_dwStatus & XFA_WidgetStatus_TextEditValueChanged)
     return true;
 
   WideString wsText = GetPickerWidget()->GetEditText();
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp
index ca36cbd..587bcfa 100644
--- a/xfa/fxfa/cxfa_ffdocview.cpp
+++ b/xfa/fxfa/cxfa_ffdocview.cpp
@@ -249,7 +249,7 @@
 }
 
 CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) {
-  return ToFFWidget(ToContentLayoutItem(GetXFALayout()->GetLayoutItem(node)));
+  return GetFFWidget(ToContentLayoutItem(GetXFALayout()->GetLayoutItem(node)));
 }
 
 CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() {
diff --git a/xfa/fxfa/cxfa_fffield.cpp b/xfa/fxfa/cxfa_fffield.cpp
index dfd8a69..7675de2 100644
--- a/xfa/fxfa/cxfa_fffield.cpp
+++ b/xfa/fxfa/cxfa_fffield.cpp
@@ -35,8 +35,8 @@
 
 namespace {
 
-CXFA_FFField* ToField(CXFA_LayoutItem* widget) {
-  return static_cast<CXFA_FFField*>(widget);
+CXFA_FFField* ToField(CXFA_ContentLayoutItem* pItem) {
+  return pItem ? static_cast<CXFA_FFField*>(pItem->GetFFWidget()) : nullptr;
 }
 
 }  // namespace
@@ -103,7 +103,7 @@
 }
 
 void CXFA_FFField::DrawFocus(CXFA_Graphics* pGS, CFX_Matrix* pMatrix) {
-  if (!(m_dwStatus & XFA_WidgetStatus_Focused))
+  if (!(GetLayoutItem()->m_dwStatus & XFA_WidgetStatus_Focused))
     return;
 
   pGS->SetStrokeColor(CXFA_GEColor(0xFF000000));
@@ -142,13 +142,13 @@
   }
 
   float fScrollOffset = 0;
-  CXFA_FFField* pPrev = ToField(GetPrev());
+  CXFA_FFField* pPrev = ToField(GetLayoutItem()->GetPrev());
   if (pPrev)
     fScrollOffset = -(m_pNode->GetUIMargin().top);
 
   while (pPrev) {
     fScrollOffset += pPrev->m_rtUI.height;
-    pPrev = ToField(pPrev->GetPrev());
+    pPrev = ToField(pPrev->GetLayoutItem()->GetPrev());
   }
   static_cast<CFWL_Edit*>(m_pNormalWidget.get())
       ->SetScrollOffset(fScrollOffset);
@@ -169,7 +169,7 @@
   CFX_RectF rtWidget = GetRectWithoutRotate();
   CXFA_Margin* margin = m_pNode->GetMarginIfExists();
   if (margin) {
-    CXFA_ContentLayoutItem* pItem = this;
+    CXFA_ContentLayoutItem* pItem = GetLayoutItem();
     float fLeftInset = margin->GetLeftInset();
     float fRightInset = margin->GetRightInset();
     float fTopInset = margin->GetTopInset();
@@ -191,8 +191,10 @@
   CXFA_Caption* caption = m_pNode->GetCaptionIfExists();
   if (caption && !caption->IsHidden()) {
     iCapPlacement = caption->GetPlacementType();
-    if ((iCapPlacement == XFA_AttributeValue::Top && GetPrev()) ||
-        (iCapPlacement == XFA_AttributeValue::Bottom && GetNext())) {
+    if ((iCapPlacement == XFA_AttributeValue::Top &&
+         GetLayoutItem()->GetPrev()) ||
+        (iCapPlacement == XFA_AttributeValue::Bottom &&
+         GetLayoutItem()->GetNext())) {
       m_rtCaption = CFX_RectF();
     } else {
       fCapReserve = caption->GetReserve();
@@ -202,7 +204,7 @@
       } else {
         fCapReserve = std::min(fCapReserve, rtWidget.width);
       }
-      CXFA_ContentLayoutItem* pItem = this;
+      CXFA_ContentLayoutItem* pItem = GetLayoutItem();
       if (!pItem->GetPrev() && !pItem->GetNext()) {
         m_rtCaption = rtWidget;
       } else {
@@ -499,7 +501,7 @@
 
   CFWL_MessageSetFocus ms(nullptr, m_pNormalWidget.get());
   TranslateFWLMessage(&ms);
-  m_dwStatus |= XFA_WidgetStatus_Focused;
+  GetLayoutItem()->m_dwStatus |= XFA_WidgetStatus_Focused;
   InvalidateRect();
   return true;
 }
@@ -510,7 +512,7 @@
 
   CFWL_MessageKillFocus ms(nullptr, m_pNormalWidget.get());
   TranslateFWLMessage(&ms);
-  m_dwStatus &= ~XFA_WidgetStatus_Focused;
+  GetLayoutItem()->m_dwStatus &= ~XFA_WidgetStatus_Focused;
   InvalidateRect();
   CXFA_FFWidget::OnKillFocus(pNewWidget);
   return true;
diff --git a/xfa/fxfa/cxfa_ffnotify.cpp b/xfa/fxfa/cxfa_ffnotify.cpp
index be551d2..6c5f444 100644
--- a/xfa/fxfa/cxfa_ffnotify.cpp
+++ b/xfa/fxfa/cxfa_ffnotify.cpp
@@ -107,14 +107,14 @@
   return nullptr;
 }
 
-std::unique_ptr<CXFA_ContentLayoutItem>
-CXFA_FFNotify::OnCreateContentLayoutItem(CXFA_Node* pNode) {
+std::unique_ptr<CXFA_FFWidget> CXFA_FFNotify::OnCreateContentLayoutItem(
+    CXFA_Node* pNode) {
   ASSERT(pNode->GetElementType() != XFA_Element::ContentArea);
   ASSERT(pNode->GetElementType() != XFA_Element::PageArea);
 
   // We only need to create the widget for certain types of objects.
   if (!pNode->HasCreatedUIWidget())
-    return pdfium::MakeUnique<CXFA_ContentLayoutItem>(pNode);
+    return nullptr;
 
   std::unique_ptr<CXFA_FFWidget> pWidget;
   switch (pNode->GetFFWidgetType()) {
diff --git a/xfa/fxfa/cxfa_ffnotify.h b/xfa/fxfa/cxfa_ffnotify.h
index 34b850b..23a50dc 100644
--- a/xfa/fxfa/cxfa_ffnotify.h
+++ b/xfa/fxfa/cxfa_ffnotify.h
@@ -43,8 +43,7 @@
   void OnChildRemoved();
 
   std::unique_ptr<CXFA_ViewLayoutItem> OnCreateViewLayoutItem(CXFA_Node* pNode);
-  std::unique_ptr<CXFA_ContentLayoutItem> OnCreateContentLayoutItem(
-      CXFA_Node* pNode);
+  std::unique_ptr<CXFA_FFWidget> OnCreateContentLayoutItem(CXFA_Node* pNode);
 
   void OnLayoutItemAdded(CXFA_LayoutProcessor* pLayout,
                          CXFA_LayoutItem* pSender,
diff --git a/xfa/fxfa/cxfa_ffpageview.cpp b/xfa/fxfa/cxfa_ffpageview.cpp
index 29b4f5c..5ad5036 100644
--- a/xfa/fxfa/cxfa_ffpageview.cpp
+++ b/xfa/fxfa/cxfa_ffpageview.cpp
@@ -197,8 +197,8 @@
   return pLayoutItem ? XFA_GetWidgetFromLayoutItem(pLayoutItem) : nullptr;
 }
 
-bool CXFA_FFPageWidgetIterator::SetCurrentWidget(CXFA_FFWidget* hWidget) {
-  return hWidget && m_sIterator.SetCurrent(hWidget);
+bool CXFA_FFPageWidgetIterator::SetCurrentWidget(CXFA_FFWidget* pWidget) {
+  return pWidget && m_sIterator.SetCurrent(pWidget->GetLayoutItem());
 }
 
 CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetWidget(
diff --git a/xfa/fxfa/cxfa_fftext.cpp b/xfa/fxfa/cxfa_fftext.cpp
index 0db0aff..8e6cddb 100644
--- a/xfa/fxfa/cxfa_fftext.cpp
+++ b/xfa/fxfa/cxfa_fftext.cpp
@@ -42,7 +42,7 @@
   CFX_RectF rtText = GetRectWithoutRotate();
   CXFA_Margin* margin = m_pNode->GetMarginIfExists();
   if (margin) {
-    CXFA_ContentLayoutItem* pItem = this;
+    CXFA_ContentLayoutItem* pItem = GetLayoutItem();
     if (!pItem->GetPrev() && !pItem->GetNext()) {
       XFA_RectWithoutMargin(&rtText, margin);
     } else {
@@ -61,7 +61,8 @@
   CFX_Matrix mt(1, 0, 0, 1, rtText.left, rtText.top);
   CFX_RectF rtClip = mtRotate.TransformRect(rtText);
   mt.Concat(mtRotate);
-  pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex());
+  pTextLayout->DrawString(pRenderDevice, mt, rtClip,
+                          GetLayoutItem()->GetIndex());
 }
 
 bool CXFA_FFText::IsLoaded() {
@@ -78,7 +79,7 @@
     return true;
 
   pTextLayout->ClearBlocks();
-  CXFA_ContentLayoutItem* pItem = this;
+  CXFA_ContentLayoutItem* pItem = GetLayoutItem();
   if (!pItem->GetPrev() && !pItem->GetNext())
     return true;
 
diff --git a/xfa/fxfa/cxfa_fftextedit.cpp b/xfa/fxfa/cxfa_fftextedit.cpp
index 9d125db..528d55e 100644
--- a/xfa/fxfa/cxfa_fftextedit.cpp
+++ b/xfa/fxfa/cxfa_fftextedit.cpp
@@ -121,7 +121,7 @@
 
 void CXFA_FFTextEdit::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
   if (!IsFocused()) {
-    m_dwStatus |= XFA_WidgetStatus_Focused;
+    GetLayoutItem()->m_dwStatus |= XFA_WidgetStatus_Focused;
     UpdateFWLData();
     InvalidateRect();
   }
@@ -136,7 +136,7 @@
 
 void CXFA_FFTextEdit::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
   if (!IsFocused()) {
-    m_dwStatus |= XFA_WidgetStatus_Focused;
+    GetLayoutItem()->m_dwStatus |= XFA_WidgetStatus_Focused;
     UpdateFWLData();
     InvalidateRect();
   }
@@ -158,9 +158,9 @@
 }
 
 bool CXFA_FFTextEdit::OnSetFocus(CXFA_FFWidget* pOldWidget) {
-  m_dwStatus &= ~XFA_WidgetStatus_TextEditValueChanged;
+  GetLayoutItem()->m_dwStatus &= ~XFA_WidgetStatus_TextEditValueChanged;
   if (!IsFocused()) {
-    m_dwStatus |= XFA_WidgetStatus_Focused;
+    GetLayoutItem()->m_dwStatus |= XFA_WidgetStatus_Focused;
     UpdateFWLData();
     InvalidateRect();
   }
@@ -173,7 +173,7 @@
 bool CXFA_FFTextEdit::OnKillFocus(CXFA_FFWidget* pNewWidget) {
   CFWL_MessageKillFocus ms(nullptr, m_pNormalWidget.get());
   TranslateFWLMessage(&ms);
-  m_dwStatus &= ~XFA_WidgetStatus_Focused;
+  GetLayoutItem()->m_dwStatus &= ~XFA_WidgetStatus_Focused;
 
   SetEditScrollOffset();
   ProcessCommittedData();
@@ -181,7 +181,7 @@
   InvalidateRect();
   CXFA_FFWidget::OnKillFocus(pNewWidget);
 
-  m_dwStatus &= ~XFA_WidgetStatus_TextEditValueChanged;
+  GetLayoutItem()->m_dwStatus &= ~XFA_WidgetStatus_TextEditValueChanged;
   return true;
 }
 
@@ -211,7 +211,8 @@
 }
 
 bool CXFA_FFTextEdit::IsDataChanged() {
-  return (m_dwStatus & XFA_WidgetStatus_TextEditValueChanged) != 0;
+  auto* pItem = GetLayoutItem();
+  return !!(pItem->m_dwStatus & XFA_WidgetStatus_TextEditValueChanged);
 }
 
 uint32_t CXFA_FFTextEdit::GetAlignment() {
@@ -299,7 +300,7 @@
 
 void CXFA_FFTextEdit::OnTextWillChange(CFWL_Widget* pWidget,
                                        CFWL_EventTextWillChange* event) {
-  m_dwStatus |= XFA_WidgetStatus_TextEditValueChanged;
+  GetLayoutItem()->m_dwStatus |= XFA_WidgetStatus_TextEditValueChanged;
 
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_Change;
diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp
index 1c25af5..1db5c05 100644
--- a/xfa/fxfa/cxfa_ffwidget.cpp
+++ b/xfa/fxfa/cxfa_ffwidget.cpp
@@ -226,35 +226,30 @@
   if (!pLayoutItem->GetFormNode()->HasCreatedUIWidget())
     return nullptr;
 
-  return ToFFWidget(ToContentLayoutItem(pLayoutItem));
+  return GetFFWidget(ToContentLayoutItem(pLayoutItem));
 }
 
 CXFA_CalcData::CXFA_CalcData() : m_iRefCount(0) {}
 
 CXFA_CalcData::~CXFA_CalcData() {}
 
-CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node)
-    : CXFA_ContentLayoutItem(node), m_pNode(node) {}
+CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node) : m_pNode(node) {}
 
 CXFA_FFWidget::~CXFA_FFWidget() = default;
 
-CXFA_FFWidget* CXFA_FFWidget::AsFFWidget() {
-  return this;
-}
-
 const CFWL_App* CXFA_FFWidget::GetFWLApp() {
   return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp();
 }
 
 const CFX_RectF& CXFA_FFWidget::GetWidgetRect() const {
-  if ((m_dwStatus & XFA_WidgetStatus_RectCached) == 0)
+  if ((GetLayoutItem()->m_dwStatus & XFA_WidgetStatus_RectCached) == 0)
     RecacheWidgetRect();
   return m_rtWidget;
 }
 
 const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const {
-  m_dwStatus |= XFA_WidgetStatus_RectCached;
-  m_rtWidget = GetRect(false);
+  GetLayoutItem()->m_dwStatus |= XFA_WidgetStatus_RectCached;
+  m_rtWidget = GetLayoutItem()->GetRect(false);
   return m_rtWidget;
 }
 
@@ -283,11 +278,12 @@
 }
 
 uint32_t CXFA_FFWidget::GetStatus() {
-  return m_dwStatus;
+  return GetLayoutItem()->m_dwStatus;
 }
 
 void CXFA_FFWidget::ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved) {
-  m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded;
+  GetLayoutItem()->m_dwStatus =
+      (GetLayoutItem()->m_dwStatus & ~dwRemoved) | dwAdded;
 }
 
 CFX_RectF CXFA_FFWidget::GetBBox(uint32_t dwStatus, FocusOption focus) {
@@ -402,11 +398,11 @@
 }
 
 bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
-  CXFA_FFWidget* pParent = ToFFWidget(ToContentLayoutItem(GetParent()));
+  CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
   if (pParent && !pParent->IsAncestorOf(pOldWidget))
     pParent->OnSetFocus(pOldWidget);
 
-  m_dwStatus |= XFA_WidgetStatus_Focused;
+  GetLayoutItem()->m_dwStatus |= XFA_WidgetStatus_Focused;
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_Enter;
   eParam.m_pTarget = m_pNode.Get();
@@ -415,12 +411,12 @@
 }
 
 bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) {
-  m_dwStatus &= ~XFA_WidgetStatus_Focused;
+  GetLayoutItem()->m_dwStatus &= ~XFA_WidgetStatus_Focused;
   EventKillFocus();
   if (!pNewWidget)
     return true;
 
-  CXFA_FFWidget* pParent = ToFFWidget(ToContentLayoutItem(GetParent()));
+  CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
   if (pParent && !pParent->IsAncestorOf(pNewWidget))
     pParent->OnKillFocus(pNewWidget);
 
@@ -602,12 +598,12 @@
 }
 
 bool CXFA_FFWidget::IsMatchVisibleStatus(uint32_t dwStatus) {
-  return !!(m_dwStatus & XFA_WidgetStatus_Visible);
+  return !!(GetLayoutItem()->m_dwStatus & XFA_WidgetStatus_Visible);
 }
 
 void CXFA_FFWidget::EventKillFocus() {
-  if (m_dwStatus & XFA_WidgetStatus_Access) {
-    m_dwStatus &= ~XFA_WidgetStatus_Access;
+  if (GetLayoutItem()->m_dwStatus & XFA_WidgetStatus_Access) {
+    GetLayoutItem()->m_dwStatus &= ~XFA_WidgetStatus_Access;
     return;
   }
   CXFA_EventParam eParam;
@@ -617,10 +613,10 @@
 }
 
 bool CXFA_FFWidget::IsButtonDown() {
-  return (m_dwStatus & XFA_WidgetStatus_ButtonDown) != 0;
+  return (GetLayoutItem()->m_dwStatus & XFA_WidgetStatus_ButtonDown) != 0;
 }
 
 void CXFA_FFWidget::SetButtonDown(bool bSet) {
-  bSet ? m_dwStatus |= XFA_WidgetStatus_ButtonDown
-       : m_dwStatus &= ~XFA_WidgetStatus_ButtonDown;
+  bSet ? GetLayoutItem()->m_dwStatus |= XFA_WidgetStatus_ButtonDown
+       : GetLayoutItem()->m_dwStatus &= ~XFA_WidgetStatus_ButtonDown;
 }
diff --git a/xfa/fxfa/cxfa_ffwidget.h b/xfa/fxfa/cxfa_ffwidget.h
index fbd9266..02a9baa 100644
--- a/xfa/fxfa/cxfa_ffwidget.h
+++ b/xfa/fxfa/cxfa_ffwidget.h
@@ -61,15 +61,12 @@
   int32_t m_iRefCount;
 };
 
-class CXFA_FFWidget : public CXFA_ContentLayoutItem {
+class CXFA_FFWidget {
  public:
   enum FocusOption { kDoNotDrawFocus = 0, kDrawFocus };
 
   explicit CXFA_FFWidget(CXFA_Node* pNode);
-  ~CXFA_FFWidget() override;
-
-  // CXFA_ContentLayoutItem:
-  CXFA_FFWidget* AsFFWidget() override;
+  virtual ~CXFA_FFWidget();
 
   virtual CFX_RectF GetBBox(uint32_t dwStatus, FocusOption focus);
   virtual void RenderWidget(CXFA_Graphics* pGS,
@@ -121,9 +118,11 @@
   virtual void Delete();
   virtual void DeSelect();
   virtual WideString GetText();
-
   virtual FormFieldType GetFormFieldType();
 
+  CXFA_Node* GetNode() const { return m_pNode.Get(); }
+  CXFA_ContentLayoutItem* GetLayoutItem() const { return m_pLayoutItem.Get(); }
+  void SetLayoutItem(CXFA_ContentLayoutItem* pItem) { m_pLayoutItem = pItem; }
   CXFA_FFPageView* GetPageView() const { return m_pPageView.Get(); }
   void SetPageView(CXFA_FFPageView* pPageView) { m_pPageView = pPageView; }
   CXFA_FFDocView* GetDocView() const { return m_pDocView.Get(); }
@@ -134,13 +133,13 @@
   uint32_t GetStatus();
   void ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved);
 
-  CXFA_Node* GetNode() const { return m_pNode.Get(); }
-
   CXFA_FFDoc* GetDoc();
   CXFA_FFApp* GetApp();
   IXFA_AppProvider* GetAppProvider();
   void InvalidateRect();
-  bool IsFocused() const { return !!(m_dwStatus & XFA_WidgetStatus_Focused); }
+  bool IsFocused() const {
+    return !!(GetLayoutItem()->m_dwStatus & XFA_WidgetStatus_Focused);
+  }
   CFX_PointF Rotate2Normal(const CFX_PointF& point);
   CFX_Matrix GetRotateMatrix();
   bool IsLayoutRectEmpty();
@@ -167,6 +166,7 @@
   bool IsButtonDown();
   void SetButtonDown(bool bSet);
 
+  UnownedPtr<CXFA_ContentLayoutItem> m_pLayoutItem;
   UnownedPtr<CXFA_FFDocView> m_pDocView;
   UnownedPtr<CXFA_FFPageView> m_pPageView;
   UnownedPtr<CXFA_Node> const m_pNode;
diff --git a/xfa/fxfa/cxfa_ffwidgethandler.cpp b/xfa/fxfa/cxfa_ffwidgethandler.cpp
index 9b43c87..842dc1f 100644
--- a/xfa/fxfa/cxfa_ffwidgethandler.cpp
+++ b/xfa/fxfa/cxfa_ffwidgethandler.cpp
@@ -276,7 +276,7 @@
   m_pDocView->RunLayout();
   CXFA_LayoutItem* pLayout =
       m_pDocView->GetXFALayout()->GetLayoutItem(pNewFormItem);
-  return ToFFWidget(ToContentLayoutItem(pLayout));
+  return GetFFWidget(ToContentLayoutItem(pLayout));
 }
 
 CXFA_Node* CXFA_FFWidgetHandler::CreateWidgetFormItem(
diff --git a/xfa/fxfa/cxfa_fwltheme.cpp b/xfa/fxfa/cxfa_fwltheme.cpp
index 5cb5564..4aab239 100644
--- a/xfa/fxfa/cxfa_fwltheme.cpp
+++ b/xfa/fxfa/cxfa_fwltheme.cpp
@@ -150,7 +150,7 @@
   if (!pWidget)
     return CFX_RectF();
 
-  CXFA_ContentLayoutItem* pItem = pWidget;
+  CXFA_ContentLayoutItem* pItem = pWidget->GetLayoutItem();
   CXFA_Node* pNode = pWidget->GetNode();
   CFX_RectF rect = pNode->GetUIMargin();
   CXFA_Para* para = pNode->GetParaIfExists();
diff --git a/xfa/fxfa/layout/cxfa_contentlayoutitem.cpp b/xfa/fxfa/layout/cxfa_contentlayoutitem.cpp
index b88e1ae..157c7a3 100644
--- a/xfa/fxfa/layout/cxfa_contentlayoutitem.cpp
+++ b/xfa/fxfa/layout/cxfa_contentlayoutitem.cpp
@@ -6,12 +6,20 @@
 
 #include "xfa/fxfa/layout/cxfa_contentlayoutitem.h"
 
+#include <utility>
+
 #include "fxjs/xfa/cjx_object.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
 #include "xfa/fxfa/parser/cxfa_margin.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
 
-CXFA_ContentLayoutItem::CXFA_ContentLayoutItem(CXFA_Node* pNode)
-    : CXFA_LayoutItem(pNode, kContentItem) {}
+CXFA_ContentLayoutItem::CXFA_ContentLayoutItem(
+    CXFA_Node* pNode,
+    std::unique_ptr<CXFA_FFWidget> pWidget)
+    : CXFA_LayoutItem(pNode, kContentItem), m_pFFWidget(std::move(pWidget)) {
+  if (m_pFFWidget)
+    m_pFFWidget->SetLayoutItem(this);
+}
 
 CXFA_ContentLayoutItem::~CXFA_ContentLayoutItem() {
   RemoveSelf();
@@ -20,10 +28,6 @@
     pJsObject->SetLayoutItem(nullptr);
 }
 
-CXFA_FFWidget* CXFA_ContentLayoutItem::AsFFWidget() {
-  return nullptr;
-}
-
 CXFA_ContentLayoutItem* CXFA_ContentLayoutItem::GetFirst() {
   CXFA_ContentLayoutItem* pCurNode = this;
   while (auto* pPrev = pCurNode->GetPrev())
diff --git a/xfa/fxfa/layout/cxfa_contentlayoutitem.h b/xfa/fxfa/layout/cxfa_contentlayoutitem.h
index 2f8316e..fa1591e 100644
--- a/xfa/fxfa/layout/cxfa_contentlayoutitem.h
+++ b/xfa/fxfa/layout/cxfa_contentlayoutitem.h
@@ -7,6 +7,8 @@
 #ifndef XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTITEM_H_
 #define XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTITEM_H_
 
+#include <memory>
+
 #include "core/fxcrt/unowned_ptr.h"
 #include "xfa/fxfa/layout/cxfa_layoutitem.h"
 
@@ -14,10 +16,11 @@
 
 class CXFA_ContentLayoutItem : public CXFA_LayoutItem {
  public:
-  explicit CXFA_ContentLayoutItem(CXFA_Node* pNode);
+  CXFA_ContentLayoutItem(CXFA_Node* pNode,
+                         std::unique_ptr<CXFA_FFWidget> pFFWidget);
   ~CXFA_ContentLayoutItem() override;
 
-  virtual CXFA_FFWidget* AsFFWidget();
+  CXFA_FFWidget* GetFFWidget() { return m_pFFWidget.get(); }
 
   CXFA_ContentLayoutItem* GetFirst();
   CXFA_ContentLayoutItem* GetLast();
@@ -37,10 +40,11 @@
 
   UnownedPtr<CXFA_ContentLayoutItem> m_pPrev;
   UnownedPtr<CXFA_ContentLayoutItem> m_pNext;
+  std::unique_ptr<CXFA_FFWidget> const m_pFFWidget;
 };
 
-inline CXFA_FFWidget* ToFFWidget(CXFA_ContentLayoutItem* item) {
-  return item ? item->AsFFWidget() : nullptr;
+inline CXFA_FFWidget* GetFFWidget(CXFA_ContentLayoutItem* item) {
+  return item ? item->GetFFWidget() : nullptr;
 }
 
 #endif  // XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTITEM_H_
diff --git a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
index 9db5dca..a6ddfc8 100644
--- a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
+++ b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
@@ -18,6 +18,7 @@
 #include "third_party/base/stl_util.h"
 #include "xfa/fxfa/cxfa_ffdoc.h"
 #include "xfa/fxfa/cxfa_ffnotify.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
 #include "xfa/fxfa/layout/cxfa_contentlayoutitem.h"
 #include "xfa/fxfa/layout/cxfa_layoutcontext.h"
 #include "xfa/fxfa/layout/cxfa_layoutpagemgr.h"
@@ -639,9 +640,9 @@
     m_pOldLayoutItem = m_pOldLayoutItem->GetNext();
     return pLayoutItem;
   }
-  pLayoutItem = pFormNode->GetDocument()
-                    ->GetNotify()
-                    ->OnCreateContentLayoutItem(pFormNode)
+  CXFA_FFNotify* pNotify = pFormNode->GetDocument()->GetNotify();
+  pLayoutItem = pdfium::MakeUnique<CXFA_ContentLayoutItem>(
+                    pFormNode, pNotify->OnCreateContentLayoutItem(pFormNode))
                     .release();
   CXFA_ContentLayoutItem* pPrevLayoutItem =
       ToContentLayoutItem(pFormNode->JSObject()->GetLayoutItem());
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index 95fedd8..737e05d 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -3164,7 +3164,7 @@
 }
 
 CXFA_FFWidget* CXFA_Node::GetNextWidget(CXFA_FFWidget* pWidget) {
-  return ToFFWidget(pWidget->GetNext());
+  return GetFFWidget(pWidget->GetLayoutItem()->GetNext());
 }
 
 void CXFA_Node::UpdateUIDisplay(CXFA_FFDocView* pDocView,