Break circular dependence between xfa/fde and xfa/fgas/layout.

Introduce CFX_TxtBreak::Engine interface to abstract the calls
back into the higher layer. Move FX_TXTRUN inside CFX_TxtBreak
while we're at it.

Change-Id: Iaf4cb9fe4a4aec2883b42505511e3afb3a3ab3cb
Reviewed-on: https://pdfium-review.googlesource.com/c/48250
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/xfa/fde/BUILD.gn b/xfa/fde/BUILD.gn
index 0b126d9..7154691 100644
--- a/xfa/fde/BUILD.gn
+++ b/xfa/fde/BUILD.gn
@@ -22,6 +22,7 @@
     "../../core/fxcrt",
     "../../core/fxge",
     "../fgas",
+    "../fgas/layout",
   ]
   configs += [
     "../../:pdfium_core_config",
diff --git a/xfa/fde/cfde_texteditengine.cpp b/xfa/fde/cfde_texteditengine.cpp
index fd59cbc..7610457 100644
--- a/xfa/fde/cfde_texteditengine.cpp
+++ b/xfa/fde/cfde_texteditengine.cpp
@@ -1042,7 +1042,7 @@
   if (piece.nCount < 1)
     return std::vector<CFX_RectF>();
 
-  FX_TXTRUN tr;
+  CFX_TxtBreak::Run tr;
   tr.pEdtEngine = this;
   tr.iStart = piece.nStart;
   tr.iLength = piece.nCount;
@@ -1059,7 +1059,7 @@
   if (piece.nCount < 1)
     return std::vector<FXTEXT_CHARPOS>();
 
-  FX_TXTRUN tr;
+  CFX_TxtBreak::Run tr;
   tr.pEdtEngine = this;
   tr.iStart = piece.nStart;
   tr.iLength = piece.nCount;
diff --git a/xfa/fde/cfde_texteditengine.h b/xfa/fde/cfde_texteditengine.h
index 5971611..01adc3d 100644
--- a/xfa/fde/cfde_texteditengine.h
+++ b/xfa/fde/cfde_texteditengine.h
@@ -36,7 +36,7 @@
     default;
 inline FDE_TEXTEDITPIECE::~FDE_TEXTEDITPIECE() = default;
 
-class CFDE_TextEditEngine {
+class CFDE_TextEditEngine : public CFX_TxtBreak::Engine {
  public:
   class Iterator {
    public:
@@ -84,7 +84,11 @@
   enum class RecordOperation { kInsertRecord, kSkipRecord, kSkipNotify };
 
   CFDE_TextEditEngine();
-  ~CFDE_TextEditEngine();
+  ~CFDE_TextEditEngine() override;
+
+  // CFX_TxtBreak::Engine:
+  wchar_t GetChar(size_t idx) const override;
+  size_t GetWidthOfChar(size_t idx) override;
 
   void SetDelegate(Delegate* delegate) { delegate_ = delegate; }
   void Clear();
@@ -158,9 +162,6 @@
 
   void Layout();
 
-  wchar_t GetChar(size_t idx) const;
-  // Non-const so we can force a Layout() if needed.
-  size_t GetWidthOfChar(size_t idx);
   // Non-const so we can force a Layout() if needed.
   size_t GetIndexForPoint(const CFX_PointF& point);
   // <start_idx, count>
diff --git a/xfa/fde/cfde_textout.cpp b/xfa/fde/cfde_textout.cpp
index f7ccafd..836fd3e 100644
--- a/xfa/fde/cfde_textout.cpp
+++ b/xfa/fde/cfde_textout.cpp
@@ -506,7 +506,7 @@
   if (pdfium::CollectionSize<int32_t>(m_CharPos) < pPiece->iChars)
     m_CharPos.resize(pPiece->iChars, FXTEXT_CHARPOS());
 
-  FX_TXTRUN tr;
+  CFX_TxtBreak::Run tr;
   tr.wsStr = m_wsText + pPiece->iStartChar;
   tr.pWidths = &m_CharWidths[pPiece->iStartChar];
   tr.iLength = pPiece->iChars;
diff --git a/xfa/fgas/layout/BUILD.gn b/xfa/fgas/layout/BUILD.gn
index 4411101..2749067 100644
--- a/xfa/fgas/layout/BUILD.gn
+++ b/xfa/fgas/layout/BUILD.gn
@@ -25,9 +25,7 @@
     "../:fgas",
     "../../../core/fxcrt",
     "../../../core/fxge",
-    "../../fde",
   ]
-  allow_circular_includes_from = [ "../../fde" ]
   configs += [
     "../../../:pdfium_core_config",
     "../../:xfa_warnings",
diff --git a/xfa/fgas/layout/cfx_txtbreak.cpp b/xfa/fgas/layout/cfx_txtbreak.cpp
index f2a3f67..acaf644 100644
--- a/xfa/fgas/layout/cfx_txtbreak.cpp
+++ b/xfa/fgas/layout/cfx_txtbreak.cpp
@@ -11,8 +11,8 @@
 #include "core/fxcrt/cfx_char.h"
 #include "core/fxcrt/fx_arabic.h"
 #include "core/fxcrt/fx_linebreak.h"
+#include "core/fxge/cfx_renderdevice.h"
 #include "third_party/base/stl_util.h"
-#include "xfa/fde/cfde_texteditengine.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
 
 namespace {
@@ -656,12 +656,12 @@
   int32_t iWidth;
 };
 
-size_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun,
+size_t CFX_TxtBreak::GetDisplayPos(const Run* pTxtRun,
                                    FXTEXT_CHARPOS* pCharPos) const {
   if (!pTxtRun || pTxtRun->iLength < 1)
     return 0;
 
-  CFDE_TextEditEngine* pEngine = pTxtRun->pEdtEngine;
+  Engine* pEngine = pTxtRun->pEdtEngine;
   const wchar_t* pStr = pTxtRun->wsStr.c_str();
   int32_t* pWidths = pTxtRun->pWidths;
   int32_t iLength = pTxtRun->iLength - 1;
@@ -909,12 +909,12 @@
   return szCount;
 }
 
-std::vector<CFX_RectF> CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun,
+std::vector<CFX_RectF> CFX_TxtBreak::GetCharRects(const Run* pTxtRun,
                                                   bool bCharBBox) const {
   if (!pTxtRun || pTxtRun->iLength < 1)
     return std::vector<CFX_RectF>();
 
-  CFDE_TextEditEngine* pEngine = pTxtRun->pEdtEngine;
+  Engine* pEngine = pTxtRun->pEdtEngine;
   const wchar_t* pStr = pTxtRun->wsStr.c_str();
   int32_t* pWidths = pTxtRun->pWidths;
   int32_t iLength = pTxtRun->iLength;
@@ -990,19 +990,10 @@
   return rtArray;
 }
 
-FX_TXTRUN::FX_TXTRUN()
-    : pEdtEngine(nullptr),
-      pWidths(nullptr),
-      iLength(0),
-      pFont(nullptr),
-      fFontSize(12),
-      dwStyles(0),
-      iHorizontalScale(100),
-      iVerticalScale(100),
-      dwCharStyles(0),
-      pRect(nullptr),
-      bSkipSpace(true) {}
+CFX_TxtBreak::Engine::~Engine() = default;
 
-FX_TXTRUN::~FX_TXTRUN() {}
+CFX_TxtBreak::Run::Run() = default;
 
-FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default;
+CFX_TxtBreak::Run::~Run() = default;
+
+CFX_TxtBreak::Run::Run(const CFX_TxtBreak::Run& other) = default;
diff --git a/xfa/fgas/layout/cfx_txtbreak.h b/xfa/fgas/layout/cfx_txtbreak.h
index 9b095cc..3cfd3a1 100644
--- a/xfa/fgas/layout/cfx_txtbreak.h
+++ b/xfa/fgas/layout/cfx_txtbreak.h
@@ -14,10 +14,8 @@
 #include "core/fxcrt/fx_coordinates.h"
 #include "xfa/fgas/layout/cfx_break.h"
 
-class CFDE_TextEditEngine;
 class CFGAS_GEFont;
 class FXTEXT_CHARPOS;
-struct FDE_TEXTEDITPIECE;
 
 #define FX_TXTCHARSTYLE_ArabicShadda 0x0020
 #define FX_TXTCHARSTYLE_OddBidiLevel 0x0040
@@ -33,28 +31,36 @@
   return type == CFX_BreakType::None || type == CFX_BreakType::Piece;
 }
 
-struct FX_TXTRUN {
-  FX_TXTRUN();
-  FX_TXTRUN(const FX_TXTRUN& other);
-  ~FX_TXTRUN();
-
-  CFDE_TextEditEngine* pEdtEngine;
-  WideString wsStr;
-  int32_t* pWidths;
-  int32_t iStart;
-  int32_t iLength;
-  RetainPtr<CFGAS_GEFont> pFont;
-  float fFontSize;
-  uint32_t dwStyles;
-  int32_t iHorizontalScale;
-  int32_t iVerticalScale;
-  uint32_t dwCharStyles;
-  const CFX_RectF* pRect;
-  bool bSkipSpace;
-};
-
 class CFX_TxtBreak final : public CFX_Break {
  public:
+  class Engine {
+   public:
+    virtual ~Engine();
+    virtual wchar_t GetChar(size_t idx) const = 0;
+    // Non-const so we can force a layout if needed.
+    virtual size_t GetWidthOfChar(size_t idx) = 0;
+  };
+
+  struct Run {
+    Run();
+    Run(const Run& other);
+    ~Run();
+
+    CFX_TxtBreak::Engine* pEdtEngine = nullptr;
+    WideString wsStr;
+    int32_t* pWidths = nullptr;
+    int32_t iStart = 0;
+    int32_t iLength = 0;
+    RetainPtr<CFGAS_GEFont> pFont;
+    float fFontSize = 12.0f;
+    uint32_t dwStyles = 0;
+    int32_t iHorizontalScale = 100;
+    int32_t iVerticalScale = 100;
+    uint32_t dwCharStyles = 0;
+    const CFX_RectF* pRect = nullptr;
+    bool bSkipSpace = true;
+  };
+
   CFX_TxtBreak();
   ~CFX_TxtBreak() override;
 
@@ -63,10 +69,8 @@
   void SetCombWidth(float fCombWidth);
   CFX_BreakType EndBreak(CFX_BreakType dwStatus);
 
-  size_t GetDisplayPos(const FX_TXTRUN* pTxtRun,
-                       FXTEXT_CHARPOS* pCharPos) const;
-  std::vector<CFX_RectF> GetCharRects(const FX_TXTRUN* pTxtRun,
-                                      bool bCharBBox) const;
+  size_t GetDisplayPos(const Run* pTxtRun, FXTEXT_CHARPOS* pCharPos) const;
+  std::vector<CFX_RectF> GetCharRects(const Run* pTxtRun, bool bCharBBox) const;
   CFX_BreakType AppendChar(wchar_t wch);
 
  private: