Move CFX_ClipRgn and CFX_PathData into their own files.

This is the second CL in an attempt to split up the classes in fxge/include/fx_ge.h into their own files. CFX_ClipRgn is moved to core/fxge/ge because it is only used in core/fxge. The header for CFX_PathData is left in core/fxge/include since it is used elsewhere.

Review-Url: https://codereview.chromium.org/2216853004
diff --git a/BUILD.gn b/BUILD.gn
index ddbf41f..4b8f222 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -728,11 +728,14 @@
     "core/fxge/fontdata/chromefontdata/FoxitSymbol.cpp",
     "core/fxge/fontdata/chromefontdata/chromefontdata.h",
     "core/fxge/freetype/fx_freetype.cpp",
+    "core/fxge/ge/cfx_cliprgn.cpp",
+    "core/fxge/ge/cfx_cliprgn.h",
     "core/fxge/ge/cfx_folderfontinfo.cpp",
     "core/fxge/ge/cfx_folderfontinfo.h",
     "core/fxge/ge/cfx_fontmapper.cpp",
     "core/fxge/ge/cfx_fontmgr.cpp",
     "core/fxge/ge/cfx_gemodule.cpp",
+    "core/fxge/ge/cfx_pathdata.cpp",
     "core/fxge/ge/fx_ge_device.cpp",
     "core/fxge/ge/fx_ge_font.cpp",
     "core/fxge/ge/fx_ge_fontmap.cpp",
@@ -745,6 +748,7 @@
     "core/fxge/ge/include/ifx_systemfontinfo.h",
     "core/fxge/ifx_renderdevicedriver.cpp",
     "core/fxge/include/cfx_gemodule.h",
+    "core/fxge/include/cfx_pathdata.h",
     "core/fxge/include/cfx_windowsdevice.h",
     "core/fxge/include/fx_dib.h",
     "core/fxge/include/fx_font.h",
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
index e20fe44..483a6b1 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
@@ -34,6 +34,7 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
 #include "core/fxcrt/include/fx_safe_types.h"
+#include "core/fxge/include/cfx_pathdata.h"
 
 namespace {
 
diff --git a/core/fpdfapi/fpdf_page/include/cpdf_path.h b/core/fpdfapi/fpdf_page/include/cpdf_path.h
index d9f3ead..bed4058 100644
--- a/core/fpdfapi/fpdf_page/include/cpdf_path.h
+++ b/core/fpdfapi/fpdf_page/include/cpdf_path.h
@@ -8,6 +8,7 @@
 #define CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_PATH_H_
 
 #include "core/fxcrt/include/fx_system.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 
 class CPDF_Path : public CFX_CountRef<CFX_PathData> {
diff --git a/core/fpdfapi/fpdf_page/pageint.h b/core/fpdfapi/fpdf_page/pageint.h
index 30c5874..655e02d 100644
--- a/core/fpdfapi/fpdf_page/pageint.h
+++ b/core/fpdfapi/fpdf_page/pageint.h
@@ -16,6 +16,7 @@
 #include "core/fpdfapi/fpdf_page/cpdf_contentmark.h"
 #include "core/fpdfapi/fpdf_page/cpdf_countedobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobjectholder.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 
 class CPDF_AllStates;
diff --git a/core/fpdfapi/fpdf_render/fpdf_render.cpp b/core/fpdfapi/fpdf_render/fpdf_render.cpp
index f4e1414..86bc3aa 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render.cpp
@@ -30,6 +30,7 @@
 #include "core/fpdfapi/fpdf_render/include/cpdf_textrenderer.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
 #include "core/fpdfdoc/include/cpdf_occontext.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 
 CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc)
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
index f4f82a1..ce58dd9 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
@@ -26,6 +26,7 @@
 #include "core/fpdfdoc/include/cpdf_occontext.h"
 #include "core/fxcodec/include/fx_codec.h"
 #include "core/fxcrt/include/fx_safe_types.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 
 #ifdef _SKIA_SUPPORT_
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
index dcf4407..d9a93dc 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
@@ -21,6 +21,7 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_render/include/cpdf_rendercontext.h"
 #include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/ifx_renderdevicedriver.h"
 
 namespace {
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
index f1c204d..a64bc89 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
@@ -23,6 +23,7 @@
 #include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
 #include "core/fpdfapi/fpdf_render/include/cpdf_textrenderer.h"
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 
 namespace {
diff --git a/core/fpdfapi/fpdf_render/render_int.h b/core/fpdfapi/fpdf_render/render_int.h
index e3e1a8a..f487b46 100644
--- a/core/fpdfapi/fpdf_render/render_int.h
+++ b/core/fpdfapi/fpdf_render/render_int.h
@@ -22,6 +22,7 @@
 class CFX_FontCache;
 class CFX_GlyphBitmap;
 class CFX_ImageTransformer;
+class CFX_PathData;
 class CPDF_Color;
 class CPDF_Dictionary;
 class CPDF_Document;
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp
index 7396aa2..726636e 100644
--- a/core/fpdfdoc/cpdf_annot.cpp
+++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -14,6 +14,7 @@
 #include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
 #include "core/fpdfdoc/cpvt_generateap.h"
 #include "core/fxcrt/include/fx_memory.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 
 CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict, CPDF_Document* pDocument)
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index f5bf76a..ea12896 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -11,8 +11,10 @@
 #include "core/fxcodec/include/fx_codec.h"
 #include "core/fxcrt/include/fx_memory.h"
 #include "core/fxge/dib/dib_int.h"
+#include "core/fxge/ge/cfx_cliprgn.h"
 #include "core/fxge/ge/fx_text_int.h"
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "core/fxge/include/ifx_renderdevicedriver.h"
 #include "third_party/agg23/agg_conv_dash.h"
diff --git a/core/fxge/apple/apple_int.h b/core/fxge/apple/apple_int.h
index 07484a4..56e458b 100644
--- a/core/fxge/apple/apple_int.h
+++ b/core/fxge/apple/apple_int.h
@@ -11,6 +11,7 @@
 
 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_dib.h"
 #include "core/fxge/include/ifx_renderdevicedriver.h"
 
diff --git a/core/fxge/apple/fx_apple_platform.cpp b/core/fxge/apple/fx_apple_platform.cpp
index f8aba28..744bc52 100644
--- a/core/fxge/apple/fx_apple_platform.cpp
+++ b/core/fxge/apple/fx_apple_platform.cpp
@@ -16,6 +16,7 @@
 #include "core/fxge/apple/apple_int.h"
 #include "core/fxge/apple/cfx_quartzdevice.h"
 #include "core/fxge/dib/dib_int.h"
+#include "core/fxge/ge/cfx_cliprgn.h"
 #include "core/fxge/ge/fx_text_int.h"
 #include "core/fxge/include/cfx_gemodule.h"
 #include "core/fxge/include/fx_freetype.h"
diff --git a/core/fxge/apple/fx_quartz_device.cpp b/core/fxge/apple/fx_quartz_device.cpp
index e3cca4c..46d98e0 100644
--- a/core/fxge/apple/fx_quartz_device.cpp
+++ b/core/fxge/apple/fx_quartz_device.cpp
@@ -14,6 +14,7 @@
 #include "core/fxge/dib/dib_int.h"
 #include "core/fxge/ge/fx_text_int.h"
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_freetype.h"
 #include "core/fxge/include/fx_ge.h"
 
diff --git a/core/fxge/dib/fx_dib_composite.cpp b/core/fxge/dib/fx_dib_composite.cpp
index e255053..32de185 100644
--- a/core/fxge/dib/fx_dib_composite.cpp
+++ b/core/fxge/dib/fx_dib_composite.cpp
@@ -6,6 +6,7 @@
 
 #include "core/fxcodec/include/fx_codec.h"
 #include "core/fxge/dib/dib_int.h"
+#include "core/fxge/ge/cfx_cliprgn.h"
 #include "core/fxge/include/cfx_gemodule.h"
 #include "core/fxge/include/fx_ge.h"
 
diff --git a/core/fxge/dib/fx_dib_main.cpp b/core/fxge/dib/fx_dib_main.cpp
index a9a1056..8656d54 100644
--- a/core/fxge/dib/fx_dib_main.cpp
+++ b/core/fxge/dib/fx_dib_main.cpp
@@ -11,6 +11,7 @@
 
 #include "core/fxcodec/include/fx_codec.h"
 #include "core/fxge/dib/dib_int.h"
+#include "core/fxge/ge/cfx_cliprgn.h"
 #include "core/fxge/include/cfx_gemodule.h"
 #include "core/fxge/include/fx_ge.h"
 
diff --git a/core/fxge/ge/cfx_cliprgn.cpp b/core/fxge/ge/cfx_cliprgn.cpp
new file mode 100644
index 0000000..41975e4
--- /dev/null
+++ b/core/fxge/ge/cfx_cliprgn.cpp
@@ -0,0 +1,107 @@
+// Copyright 2016 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxge/ge/cfx_cliprgn.h"
+
+CFX_ClipRgn::CFX_ClipRgn(int width, int height)
+    : m_Type(RectI), m_Box(0, 0, width, height) {}
+
+CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) {
+  m_Type = src.m_Type;
+  m_Box = src.m_Box;
+  m_Mask = src.m_Mask;
+}
+
+CFX_ClipRgn::~CFX_ClipRgn() {}
+
+void CFX_ClipRgn::Reset(const FX_RECT& rect) {
+  m_Type = RectI;
+  m_Box = rect;
+  m_Mask.SetNull();
+}
+
+void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) {
+  if (m_Type == RectI) {
+    m_Box.Intersect(rect);
+    return;
+  }
+  if (m_Type == MaskF) {
+    IntersectMaskRect(rect, m_Box, m_Mask);
+    return;
+  }
+}
+
+void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect,
+                                    FX_RECT mask_rect,
+                                    CFX_DIBitmapRef Mask) {
+  const CFX_DIBitmap* mask_dib = Mask.GetObject();
+  m_Type = MaskF;
+  m_Box = rect;
+  m_Box.Intersect(mask_rect);
+  if (m_Box.IsEmpty()) {
+    m_Type = RectI;
+    return;
+  }
+  if (m_Box == mask_rect) {
+    m_Mask = Mask;
+    return;
+  }
+  CFX_DIBitmap* new_dib = m_Mask.New();
+  if (!new_dib)
+    return;
+  new_dib->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask);
+  for (int row = m_Box.top; row < m_Box.bottom; row++) {
+    uint8_t* dest_scan =
+        new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top);
+    uint8_t* src_scan =
+        mask_dib->GetBuffer() + mask_dib->GetPitch() * (row - mask_rect.top);
+    for (int col = m_Box.left; col < m_Box.right; col++)
+      dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left];
+  }
+}
+
+void CFX_ClipRgn::IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask) {
+  const CFX_DIBitmap* mask_dib = Mask.GetObject();
+  ASSERT(mask_dib->GetFormat() == FXDIB_8bppMask);
+  FX_RECT mask_box(left, top, left + mask_dib->GetWidth(),
+                   top + mask_dib->GetHeight());
+  if (m_Type == RectI) {
+    IntersectMaskRect(m_Box, mask_box, Mask);
+    return;
+  }
+  if (m_Type == MaskF) {
+    FX_RECT new_box = m_Box;
+    new_box.Intersect(mask_box);
+    if (new_box.IsEmpty()) {
+      m_Type = RectI;
+      m_Mask.SetNull();
+      m_Box = new_box;
+      return;
+    }
+    CFX_DIBitmapRef new_mask;
+    CFX_DIBitmap* new_dib = new_mask.New();
+    if (!new_dib)
+      return;
+    new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask);
+    const CFX_DIBitmap* old_dib = m_Mask.GetObject();
+    for (int row = new_box.top; row < new_box.bottom; row++) {
+      uint8_t* old_scan =
+          old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch();
+      uint8_t* mask_scan =
+          mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch();
+      uint8_t* new_scan =
+          new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch();
+      for (int col = new_box.left; col < new_box.right; col++) {
+        new_scan[col - new_box.left] =
+            old_scan[col - m_Box.left] * mask_scan[col - left] / 255;
+      }
+    }
+    m_Box = new_box;
+    m_Mask = new_mask;
+    return;
+  }
+  ASSERT(FALSE);
+}
diff --git a/core/fxge/ge/cfx_cliprgn.h b/core/fxge/ge/cfx_cliprgn.h
new file mode 100644
index 0000000..5d61760
--- /dev/null
+++ b/core/fxge/ge/cfx_cliprgn.h
@@ -0,0 +1,36 @@
+// Copyright 2016 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXGE_GE_CFX_CLIPRGN_H_
+#define CORE_FXGE_GE_CFX_CLIPRGN_H_
+
+#include "core/fxge/include/fx_dib.h"
+
+class CFX_ClipRgn {
+ public:
+  enum ClipType { RectI, MaskF };
+
+  CFX_ClipRgn(int device_width, int device_height);
+  CFX_ClipRgn(const CFX_ClipRgn& src);
+  ~CFX_ClipRgn();
+
+  ClipType GetType() const { return m_Type; }
+  const FX_RECT& GetBox() const { return m_Box; }
+  CFX_DIBitmapRef GetMask() const { return m_Mask; }
+
+  void Reset(const FX_RECT& rect);
+  void IntersectRect(const FX_RECT& rect);
+  void IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask);
+
+ private:
+  void IntersectMaskRect(FX_RECT rect, FX_RECT mask_box, CFX_DIBitmapRef Mask);
+
+  ClipType m_Type;
+  FX_RECT m_Box;
+  CFX_DIBitmapRef m_Mask;
+};
+
+#endif  // CORE_FXGE_GE_CFX_CLIPRGN_H_
diff --git a/core/fxge/ge/cfx_gemodule.cpp b/core/fxge/ge/cfx_gemodule.cpp
index 98649a1..73189b7 100644
--- a/core/fxge/ge/cfx_gemodule.cpp
+++ b/core/fxge/ge/cfx_gemodule.cpp
@@ -1,4 +1,4 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
+// Copyright 2016 PDFium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/core/fxge/ge/cfx_pathdata.cpp b/core/fxge/ge/cfx_pathdata.cpp
new file mode 100644
index 0000000..6679264
--- /dev/null
+++ b/core/fxge/ge/cfx_pathdata.cpp
@@ -0,0 +1,533 @@
+// Copyright 2016 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxge/include/cfx_pathdata.h"
+
+#include "core/fxcrt/include/fx_system.h"
+#include "core/fxge/include/fx_ge.h"
+#include "third_party/base/numerics/safe_math.h"
+
+CFX_PathData::CFX_PathData()
+    : m_PointCount(0), m_pPoints(nullptr), m_AllocCount(0) {}
+
+CFX_PathData::~CFX_PathData() {
+  FX_Free(m_pPoints);
+}
+
+void CFX_PathData::SetPointCount(int nPoints) {
+  m_PointCount = nPoints;
+  if (m_AllocCount < nPoints) {
+    FX_Free(m_pPoints);
+    m_pPoints = FX_Alloc(FX_PATHPOINT, nPoints);
+    m_AllocCount = nPoints;
+  }
+}
+
+void CFX_PathData::AllocPointCount(int nPoints) {
+  if (m_AllocCount < nPoints) {
+    FX_PATHPOINT* pNewBuf = FX_Alloc(FX_PATHPOINT, nPoints);
+    if (m_PointCount) {
+      FXSYS_memcpy(pNewBuf, m_pPoints, m_PointCount * sizeof(FX_PATHPOINT));
+    }
+    FX_Free(m_pPoints);
+    m_pPoints = pNewBuf;
+    m_AllocCount = nPoints;
+  }
+}
+
+CFX_PathData::CFX_PathData(const CFX_PathData& src) {
+  m_PointCount = m_AllocCount = src.m_PointCount;
+  m_pPoints = FX_Alloc(FX_PATHPOINT, src.m_PointCount);
+  FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount);
+}
+
+void CFX_PathData::TrimPoints(int nPoints) {
+  if (m_PointCount <= nPoints) {
+    return;
+  }
+  SetPointCount(nPoints);
+}
+
+void CFX_PathData::AddPointCount(int addPoints) {
+  pdfium::base::CheckedNumeric<int> safe_new_count = m_PointCount;
+  safe_new_count += addPoints;
+  int new_count = safe_new_count.ValueOrDie();
+  AllocPointCount(new_count);
+  m_PointCount = new_count;
+}
+
+void CFX_PathData::Append(const CFX_PathData* pSrc, const CFX_Matrix* pMatrix) {
+  int old_count = m_PointCount;
+  AddPointCount(pSrc->m_PointCount);
+  FXSYS_memcpy(m_pPoints + old_count, pSrc->m_pPoints,
+               pSrc->m_PointCount * sizeof(FX_PATHPOINT));
+  if (pMatrix) {
+    for (int i = 0; i < pSrc->m_PointCount; i++) {
+      pMatrix->Transform(m_pPoints[old_count + i].m_PointX,
+                         m_pPoints[old_count + i].m_PointY);
+    }
+  }
+}
+
+void CFX_PathData::SetPoint(int index, FX_FLOAT x, FX_FLOAT y, int flag) {
+  ASSERT(index < m_PointCount);
+  m_pPoints[index].m_PointX = x;
+  m_pPoints[index].m_PointY = y;
+  m_pPoints[index].m_Flag = flag;
+}
+
+void CFX_PathData::AppendRect(FX_FLOAT left,
+                              FX_FLOAT bottom,
+                              FX_FLOAT right,
+                              FX_FLOAT top) {
+  int old_count = m_PointCount;
+  AddPointCount(5);
+  FX_PATHPOINT* pPoints = m_pPoints + old_count;
+  pPoints[0].m_PointX = pPoints[1].m_PointX = pPoints[4].m_PointX = left;
+  pPoints[2].m_PointX = pPoints[3].m_PointX = right;
+  pPoints[0].m_PointY = pPoints[3].m_PointY = pPoints[4].m_PointY = bottom;
+  pPoints[1].m_PointY = pPoints[2].m_PointY = top;
+  pPoints[0].m_Flag = FXPT_MOVETO;
+  pPoints[1].m_Flag = pPoints[2].m_Flag = pPoints[3].m_Flag = FXPT_LINETO;
+  pPoints[4].m_Flag = FXPT_LINETO | FXPT_CLOSEFIGURE;
+}
+
+CFX_FloatRect CFX_PathData::GetBoundingBox() const {
+  CFX_FloatRect rect;
+  if (m_PointCount) {
+    rect.InitRect(m_pPoints[0].m_PointX, m_pPoints[0].m_PointY);
+    for (int i = 1; i < m_PointCount; i++) {
+      rect.UpdateRect(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY);
+    }
+  }
+  return rect;
+}
+
+static void _UpdateLineEndPoints(CFX_FloatRect& rect,
+                                 FX_FLOAT start_x,
+                                 FX_FLOAT start_y,
+                                 FX_FLOAT end_x,
+                                 FX_FLOAT end_y,
+                                 FX_FLOAT hw) {
+  if (start_x == end_x) {
+    if (start_y == end_y) {
+      rect.UpdateRect(end_x + hw, end_y + hw);
+      rect.UpdateRect(end_x - hw, end_y - hw);
+      return;
+    }
+    FX_FLOAT point_y;
+    if (end_y < start_y) {
+      point_y = end_y - hw;
+    } else {
+      point_y = end_y + hw;
+    }
+    rect.UpdateRect(end_x + hw, point_y);
+    rect.UpdateRect(end_x - hw, point_y);
+    return;
+  }
+  if (start_y == end_y) {
+    FX_FLOAT point_x;
+    if (end_x < start_x) {
+      point_x = end_x - hw;
+    } else {
+      point_x = end_x + hw;
+    }
+    rect.UpdateRect(point_x, end_y + hw);
+    rect.UpdateRect(point_x, end_y - hw);
+    return;
+  }
+  FX_FLOAT dx = end_x - start_x;
+  FX_FLOAT dy = end_y - start_y;
+  FX_FLOAT ll = FXSYS_sqrt2(dx, dy);
+  FX_FLOAT mx = end_x + hw * dx / ll;
+  FX_FLOAT my = end_y + hw * dy / ll;
+  FX_FLOAT dx1 = hw * dy / ll;
+  FX_FLOAT dy1 = hw * dx / ll;
+  rect.UpdateRect(mx - dx1, my + dy1);
+  rect.UpdateRect(mx + dx1, my - dy1);
+}
+
+static void _UpdateLineJoinPoints(CFX_FloatRect& rect,
+                                  FX_FLOAT start_x,
+                                  FX_FLOAT start_y,
+                                  FX_FLOAT middle_x,
+                                  FX_FLOAT middle_y,
+                                  FX_FLOAT end_x,
+                                  FX_FLOAT end_y,
+                                  FX_FLOAT half_width,
+                                  FX_FLOAT miter_limit) {
+  FX_FLOAT start_k = 0, start_c = 0, end_k = 0, end_c = 0, start_len = 0,
+           start_dc = 0, end_len = 0, end_dc = 0;
+  FX_BOOL bStartVert = FXSYS_fabs(start_x - middle_x) < 1.0f / 20;
+  FX_BOOL bEndVert = FXSYS_fabs(middle_x - end_x) < 1.0f / 20;
+  if (bStartVert && bEndVert) {
+    int start_dir = middle_y > start_y ? 1 : -1;
+    FX_FLOAT point_y = middle_y + half_width * start_dir;
+    rect.UpdateRect(middle_x + half_width, point_y);
+    rect.UpdateRect(middle_x - half_width, point_y);
+    return;
+  }
+  if (!bStartVert) {
+    start_k = (middle_y - start_y) / (middle_x - start_x);
+    start_c = middle_y - (start_k * middle_x);
+    start_len = FXSYS_sqrt2(start_x - middle_x, start_y - middle_y);
+    start_dc =
+        (FX_FLOAT)FXSYS_fabs(half_width * start_len / (start_x - middle_x));
+  }
+  if (!bEndVert) {
+    end_k = (end_y - middle_y) / (end_x - middle_x);
+    end_c = middle_y - (end_k * middle_x);
+    end_len = FXSYS_sqrt2(end_x - middle_x, end_y - middle_y);
+    end_dc = (FX_FLOAT)FXSYS_fabs(half_width * end_len / (end_x - middle_x));
+  }
+  if (bStartVert) {
+    FX_FLOAT outside_x = start_x;
+    if (end_x < start_x) {
+      outside_x += half_width;
+    } else {
+      outside_x -= half_width;
+    }
+    FX_FLOAT outside_y;
+    if (start_y < (end_k * start_x) + end_c) {
+      outside_y = (end_k * outside_x) + end_c + end_dc;
+    } else {
+      outside_y = (end_k * outside_x) + end_c - end_dc;
+    }
+    rect.UpdateRect(outside_x, outside_y);
+    return;
+  }
+  if (bEndVert) {
+    FX_FLOAT outside_x = end_x;
+    if (start_x < end_x) {
+      outside_x += half_width;
+    } else {
+      outside_x -= half_width;
+    }
+    FX_FLOAT outside_y;
+    if (end_y < (start_k * end_x) + start_c) {
+      outside_y = (start_k * outside_x) + start_c + start_dc;
+    } else {
+      outside_y = (start_k * outside_x) + start_c - start_dc;
+    }
+    rect.UpdateRect(outside_x, outside_y);
+    return;
+  }
+  if (FXSYS_fabs(start_k - end_k) < 1.0f / 20) {
+    int start_dir = middle_x > start_x ? 1 : -1;
+    int end_dir = end_x > middle_x ? 1 : -1;
+    if (start_dir == end_dir) {
+      _UpdateLineEndPoints(rect, middle_x, middle_y, end_x, end_y, half_width);
+    } else {
+      _UpdateLineEndPoints(rect, start_x, start_y, middle_x, middle_y,
+                           half_width);
+    }
+    return;
+  }
+  FX_FLOAT start_outside_c = start_c;
+  if (end_y < (start_k * end_x) + start_c) {
+    start_outside_c += start_dc;
+  } else {
+    start_outside_c -= start_dc;
+  }
+  FX_FLOAT end_outside_c = end_c;
+  if (start_y < (end_k * start_x) + end_c) {
+    end_outside_c += end_dc;
+  } else {
+    end_outside_c -= end_dc;
+  }
+  FX_FLOAT join_x = (end_outside_c - start_outside_c) / (start_k - end_k);
+  FX_FLOAT join_y = (start_k * join_x) + start_outside_c;
+  rect.UpdateRect(join_x, join_y);
+}
+
+CFX_FloatRect CFX_PathData::GetBoundingBox(FX_FLOAT line_width,
+                                           FX_FLOAT miter_limit) const {
+  CFX_FloatRect rect(100000 * 1.0f, 100000 * 1.0f, -100000 * 1.0f,
+                     -100000 * 1.0f);
+  int iPoint = 0;
+  FX_FLOAT half_width = line_width;
+  int iStartPoint = 0;
+  int iEndPoint = 0;
+  int iMiddlePoint = 0;
+  FX_BOOL bJoin;
+  while (iPoint < m_PointCount) {
+    if (m_pPoints[iPoint].m_Flag == FXPT_MOVETO) {
+      iStartPoint = iPoint + 1;
+      iEndPoint = iPoint;
+      bJoin = FALSE;
+    } else {
+      if (m_pPoints[iPoint].m_Flag == FXPT_BEZIERTO) {
+        rect.UpdateRect(m_pPoints[iPoint].m_PointX, m_pPoints[iPoint].m_PointY);
+        rect.UpdateRect(m_pPoints[iPoint + 1].m_PointX,
+                        m_pPoints[iPoint + 1].m_PointY);
+        iPoint += 2;
+      }
+      if (iPoint == m_PointCount - 1 ||
+          m_pPoints[iPoint + 1].m_Flag == FXPT_MOVETO) {
+        iStartPoint = iPoint - 1;
+        iEndPoint = iPoint;
+        bJoin = FALSE;
+      } else {
+        iStartPoint = iPoint - 1;
+        iMiddlePoint = iPoint;
+        iEndPoint = iPoint + 1;
+        bJoin = TRUE;
+      }
+    }
+    FX_FLOAT start_x = m_pPoints[iStartPoint].m_PointX;
+    FX_FLOAT start_y = m_pPoints[iStartPoint].m_PointY;
+    FX_FLOAT end_x = m_pPoints[iEndPoint].m_PointX;
+    FX_FLOAT end_y = m_pPoints[iEndPoint].m_PointY;
+    if (bJoin) {
+      FX_FLOAT middle_x = m_pPoints[iMiddlePoint].m_PointX;
+      FX_FLOAT middle_y = m_pPoints[iMiddlePoint].m_PointY;
+      _UpdateLineJoinPoints(rect, start_x, start_y, middle_x, middle_y, end_x,
+                            end_y, half_width, miter_limit);
+    } else {
+      _UpdateLineEndPoints(rect, start_x, start_y, end_x, end_y, half_width);
+    }
+    iPoint++;
+  }
+  return rect;
+}
+
+void CFX_PathData::Transform(const CFX_Matrix* pMatrix) {
+  if (!pMatrix) {
+    return;
+  }
+  for (int i = 0; i < m_PointCount; i++) {
+    pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY);
+  }
+}
+
+FX_BOOL CFX_PathData::GetZeroAreaPath(CFX_PathData& NewPath,
+                                      CFX_Matrix* pMatrix,
+                                      FX_BOOL& bThin,
+                                      FX_BOOL bAdjust) const {
+  if (m_PointCount < 3) {
+    return FALSE;
+  }
+  if (m_PointCount == 3 && (m_pPoints[0].m_Flag & FXPT_TYPE) == FXPT_MOVETO &&
+      (m_pPoints[1].m_Flag & FXPT_TYPE) == FXPT_LINETO &&
+      (m_pPoints[2].m_Flag & FXPT_TYPE) == FXPT_LINETO &&
+      m_pPoints[0].m_PointX == m_pPoints[2].m_PointX &&
+      m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) {
+    NewPath.AddPointCount(2);
+    if (bAdjust) {
+      if (pMatrix) {
+        FX_FLOAT x = m_pPoints[0].m_PointX, y = m_pPoints[0].m_PointY;
+        pMatrix->TransformPoint(x, y);
+        x = (int)x + 0.5f;
+        y = (int)y + 0.5f;
+        NewPath.SetPoint(0, x, y, FXPT_MOVETO);
+        x = m_pPoints[1].m_PointX, y = m_pPoints[1].m_PointY;
+        pMatrix->TransformPoint(x, y);
+        x = (int)x + 0.5f;
+        y = (int)y + 0.5f;
+        NewPath.SetPoint(1, x, y, FXPT_LINETO);
+        pMatrix->SetIdentity();
+      } else {
+        FX_FLOAT x = (int)m_pPoints[0].m_PointX + 0.5f,
+                 y = (int)m_pPoints[0].m_PointY + 0.5f;
+        NewPath.SetPoint(0, x, y, FXPT_MOVETO);
+        x = (int)m_pPoints[1].m_PointX + 0.5f,
+        y = (int)m_pPoints[1].m_PointY + 0.5f;
+        NewPath.SetPoint(1, x, y, FXPT_LINETO);
+      }
+    } else {
+      NewPath.SetPoint(0, m_pPoints[0].m_PointX, m_pPoints[0].m_PointY,
+                       FXPT_MOVETO);
+      NewPath.SetPoint(1, m_pPoints[1].m_PointX, m_pPoints[1].m_PointY,
+                       FXPT_LINETO);
+    }
+    if (m_pPoints[0].m_PointX != m_pPoints[1].m_PointX &&
+        m_pPoints[0].m_PointY != m_pPoints[1].m_PointY) {
+      bThin = TRUE;
+    }
+    return TRUE;
+  }
+  if (((m_PointCount > 3) && (m_PointCount % 2))) {
+    int mid = m_PointCount / 2;
+    FX_BOOL bZeroArea = FALSE;
+    CFX_PathData t_path;
+    for (int i = 0; i < mid; i++) {
+      if (!(m_pPoints[mid - i - 1].m_PointX ==
+                m_pPoints[mid + i + 1].m_PointX &&
+            m_pPoints[mid - i - 1].m_PointY ==
+                m_pPoints[mid + i + 1].m_PointY &&
+            ((m_pPoints[mid - i - 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO &&
+             (m_pPoints[mid + i + 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO))) {
+        bZeroArea = TRUE;
+        break;
+      }
+      int new_count = t_path.GetPointCount();
+      t_path.AddPointCount(2);
+      t_path.SetPoint(new_count, m_pPoints[mid - i].m_PointX,
+                      m_pPoints[mid - i].m_PointY, FXPT_MOVETO);
+      t_path.SetPoint(new_count + 1, m_pPoints[mid - i - 1].m_PointX,
+                      m_pPoints[mid - i - 1].m_PointY, FXPT_LINETO);
+    }
+    if (!bZeroArea) {
+      NewPath.Append(&t_path, nullptr);
+      bThin = TRUE;
+      return TRUE;
+    }
+  }
+  int stratPoint = 0;
+  int next = 0, i;
+  for (i = 0; i < m_PointCount; i++) {
+    int point_type = m_pPoints[i].m_Flag & FXPT_TYPE;
+    if (point_type == FXPT_MOVETO) {
+      stratPoint = i;
+    } else if (point_type == FXPT_LINETO) {
+      next = (i + 1 - stratPoint) % (m_PointCount - stratPoint) + stratPoint;
+      if ((m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO &&
+          (m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_MOVETO) {
+        if ((m_pPoints[i - 1].m_PointX == m_pPoints[i].m_PointX &&
+             m_pPoints[i].m_PointX == m_pPoints[next].m_PointX) &&
+            ((m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) *
+                 (m_pPoints[i].m_PointY - m_pPoints[next].m_PointY) >
+             0)) {
+          int pre = i;
+          if (FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) <
+              FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[next].m_PointY)) {
+            pre--;
+            next--;
+          }
+          int new_count = NewPath.GetPointCount();
+          NewPath.AddPointCount(2);
+          NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX,
+                           m_pPoints[pre].m_PointY, FXPT_MOVETO);
+          NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX,
+                           m_pPoints[next].m_PointY, FXPT_LINETO);
+        } else if ((m_pPoints[i - 1].m_PointY == m_pPoints[i].m_PointY &&
+                    m_pPoints[i].m_PointY == m_pPoints[next].m_PointY) &&
+                   ((m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) *
+                        (m_pPoints[i].m_PointX - m_pPoints[next].m_PointX) >
+                    0)) {
+          int pre = i;
+          if (FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) <
+              FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[next].m_PointX)) {
+            pre--;
+            next--;
+          }
+          int new_count = NewPath.GetPointCount();
+          NewPath.AddPointCount(2);
+          NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX,
+                           m_pPoints[pre].m_PointY, FXPT_MOVETO);
+          NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX,
+                           m_pPoints[next].m_PointY, FXPT_LINETO);
+        } else if ((m_pPoints[i - 1].m_Flag & FXPT_TYPE) == FXPT_MOVETO &&
+                   (m_pPoints[next].m_Flag & FXPT_TYPE) == FXPT_LINETO &&
+                   m_pPoints[i - 1].m_PointX == m_pPoints[next].m_PointX &&
+                   m_pPoints[i - 1].m_PointY == m_pPoints[next].m_PointY &&
+                   m_pPoints[next].m_Flag & FXPT_CLOSEFIGURE) {
+          int new_count = NewPath.GetPointCount();
+          NewPath.AddPointCount(2);
+          NewPath.SetPoint(new_count, m_pPoints[i - 1].m_PointX,
+                           m_pPoints[i - 1].m_PointY, FXPT_MOVETO);
+          NewPath.SetPoint(new_count + 1, m_pPoints[i].m_PointX,
+                           m_pPoints[i].m_PointY, FXPT_LINETO);
+          bThin = TRUE;
+        }
+      }
+    } else if (point_type == FXPT_BEZIERTO) {
+      i += 2;
+      continue;
+    }
+  }
+  if (m_PointCount > 3 && NewPath.GetPointCount()) {
+    bThin = TRUE;
+  }
+  if (NewPath.GetPointCount() == 0) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+FX_BOOL CFX_PathData::IsRect() const {
+  if (m_PointCount != 5 && m_PointCount != 4) {
+    return FALSE;
+  }
+  if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX ||
+                             m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) ||
+      (m_pPoints[0].m_PointX == m_pPoints[2].m_PointX &&
+       m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) ||
+      (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX &&
+       m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) {
+    return FALSE;
+  }
+  if (m_pPoints[0].m_PointX != m_pPoints[3].m_PointX &&
+      m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) {
+    return FALSE;
+  }
+  for (int i = 1; i < 4; i++) {
+    if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) {
+      return FALSE;
+    }
+    if (m_pPoints[i].m_PointX != m_pPoints[i - 1].m_PointX &&
+        m_pPoints[i].m_PointY != m_pPoints[i - 1].m_PointY) {
+      return FALSE;
+    }
+  }
+  return m_PointCount == 5 || (m_pPoints[3].m_Flag & FXPT_CLOSEFIGURE);
+}
+
+FX_BOOL CFX_PathData::IsRect(const CFX_Matrix* pMatrix,
+                             CFX_FloatRect* pRect) const {
+  if (!pMatrix) {
+    if (!IsRect()) {
+      return FALSE;
+    }
+    if (pRect) {
+      pRect->left = m_pPoints[0].m_PointX;
+      pRect->right = m_pPoints[2].m_PointX;
+      pRect->bottom = m_pPoints[0].m_PointY;
+      pRect->top = m_pPoints[2].m_PointY;
+      pRect->Normalize();
+    }
+    return TRUE;
+  }
+  if (m_PointCount != 5 && m_PointCount != 4) {
+    return FALSE;
+  }
+  if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX ||
+                             m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) ||
+      (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX &&
+       m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) {
+    return FALSE;
+  }
+  if (m_PointCount == 4 && m_pPoints[0].m_PointX != m_pPoints[3].m_PointX &&
+      m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) {
+    return FALSE;
+  }
+  FX_FLOAT x[5], y[5];
+  for (int i = 0; i < m_PointCount; i++) {
+    pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY, x[i],
+                       y[i]);
+    if (i) {
+      if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) {
+        return FALSE;
+      }
+      if (x[i] != x[i - 1] && y[i] != y[i - 1]) {
+        return FALSE;
+      }
+    }
+  }
+  if (pRect) {
+    pRect->left = x[0];
+    pRect->right = x[2];
+    pRect->bottom = y[0];
+    pRect->top = y[2];
+    pRect->Normalize();
+  }
+  return TRUE;
+}
+
+void CFX_PathData::Copy(const CFX_PathData& src) {
+  SetPointCount(src.m_PointCount);
+  FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount);
+}
diff --git a/core/fxge/ge/fx_ge_device.cpp b/core/fxge/ge/fx_ge_device.cpp
index 2f4e0a0..36d2920 100644
--- a/core/fxge/ge/fx_ge_device.cpp
+++ b/core/fxge/ge/fx_ge_device.cpp
@@ -4,6 +4,7 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "core/fxge/include/ifx_renderdevicedriver.h"
 
diff --git a/core/fxge/ge/fx_ge_path.cpp b/core/fxge/ge/fx_ge_path.cpp
index 468d80e..e0e30b8 100644
--- a/core/fxge/ge/fx_ge_path.cpp
+++ b/core/fxge/ge/fx_ge_path.cpp
@@ -6,634 +6,6 @@
 
 #include "core/fxcrt/include/fx_system.h"
 #include "core/fxge/include/fx_ge.h"
-#include "third_party/base/numerics/safe_math.h"
-
-CFX_ClipRgn::CFX_ClipRgn(int width, int height)
-    : m_Type(RectI), m_Box(0, 0, width, height) {}
-
-CFX_ClipRgn::CFX_ClipRgn(const FX_RECT& rect) : m_Type(RectI), m_Box(rect) {}
-
-CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) {
-  m_Type = src.m_Type;
-  m_Box = src.m_Box;
-  m_Mask = src.m_Mask;
-}
-
-CFX_ClipRgn::~CFX_ClipRgn() {}
-
-void CFX_ClipRgn::Reset(const FX_RECT& rect) {
-  m_Type = RectI;
-  m_Box = rect;
-  m_Mask.SetNull();
-}
-
-void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) {
-  if (m_Type == RectI) {
-    m_Box.Intersect(rect);
-    return;
-  }
-  if (m_Type == MaskF) {
-    IntersectMaskRect(rect, m_Box, m_Mask);
-    return;
-  }
-}
-
-void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect,
-                                    FX_RECT mask_rect,
-                                    CFX_DIBitmapRef Mask) {
-  const CFX_DIBitmap* mask_dib = Mask.GetObject();
-  m_Type = MaskF;
-  m_Box = rect;
-  m_Box.Intersect(mask_rect);
-  if (m_Box.IsEmpty()) {
-    m_Type = RectI;
-    return;
-  }
-  if (m_Box == mask_rect) {
-    m_Mask = Mask;
-    return;
-  }
-  CFX_DIBitmap* new_dib = m_Mask.New();
-  if (!new_dib) {
-    return;
-  }
-  new_dib->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask);
-  for (int row = m_Box.top; row < m_Box.bottom; row++) {
-    uint8_t* dest_scan =
-        new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top);
-    uint8_t* src_scan =
-        mask_dib->GetBuffer() + mask_dib->GetPitch() * (row - mask_rect.top);
-    for (int col = m_Box.left; col < m_Box.right; col++) {
-      dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left];
-    }
-  }
-}
-
-void CFX_ClipRgn::IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask) {
-  const CFX_DIBitmap* mask_dib = Mask.GetObject();
-  ASSERT(mask_dib->GetFormat() == FXDIB_8bppMask);
-  FX_RECT mask_box(left, top, left + mask_dib->GetWidth(),
-                   top + mask_dib->GetHeight());
-  if (m_Type == RectI) {
-    IntersectMaskRect(m_Box, mask_box, Mask);
-    return;
-  }
-  if (m_Type == MaskF) {
-    FX_RECT new_box = m_Box;
-    new_box.Intersect(mask_box);
-    if (new_box.IsEmpty()) {
-      m_Type = RectI;
-      m_Mask.SetNull();
-      m_Box = new_box;
-      return;
-    }
-    CFX_DIBitmapRef new_mask;
-    CFX_DIBitmap* new_dib = new_mask.New();
-    if (!new_dib) {
-      return;
-    }
-    new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask);
-    const CFX_DIBitmap* old_dib = m_Mask.GetObject();
-    for (int row = new_box.top; row < new_box.bottom; row++) {
-      uint8_t* old_scan =
-          old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch();
-      uint8_t* mask_scan =
-          mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch();
-      uint8_t* new_scan =
-          new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch();
-      for (int col = new_box.left; col < new_box.right; col++) {
-        new_scan[col - new_box.left] =
-            old_scan[col - m_Box.left] * mask_scan[col - left] / 255;
-      }
-    }
-    m_Box = new_box;
-    m_Mask = new_mask;
-    return;
-  }
-  ASSERT(FALSE);
-}
-
-CFX_PathData::CFX_PathData()
-    : m_PointCount(0), m_pPoints(nullptr), m_AllocCount(0) {}
-
-CFX_PathData::~CFX_PathData() {
-  FX_Free(m_pPoints);
-}
-
-void CFX_PathData::SetPointCount(int nPoints) {
-  m_PointCount = nPoints;
-  if (m_AllocCount < nPoints) {
-    FX_Free(m_pPoints);
-    m_pPoints = FX_Alloc(FX_PATHPOINT, nPoints);
-    m_AllocCount = nPoints;
-  }
-}
-
-void CFX_PathData::AllocPointCount(int nPoints) {
-  if (m_AllocCount < nPoints) {
-    FX_PATHPOINT* pNewBuf = FX_Alloc(FX_PATHPOINT, nPoints);
-    if (m_PointCount) {
-      FXSYS_memcpy(pNewBuf, m_pPoints, m_PointCount * sizeof(FX_PATHPOINT));
-    }
-    FX_Free(m_pPoints);
-    m_pPoints = pNewBuf;
-    m_AllocCount = nPoints;
-  }
-}
-
-CFX_PathData::CFX_PathData(const CFX_PathData& src) {
-  m_PointCount = m_AllocCount = src.m_PointCount;
-  m_pPoints = FX_Alloc(FX_PATHPOINT, src.m_PointCount);
-  FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount);
-}
-
-void CFX_PathData::TrimPoints(int nPoints) {
-  if (m_PointCount <= nPoints) {
-    return;
-  }
-  SetPointCount(nPoints);
-}
-
-void CFX_PathData::AddPointCount(int addPoints) {
-  pdfium::base::CheckedNumeric<int> safe_new_count = m_PointCount;
-  safe_new_count += addPoints;
-  int new_count = safe_new_count.ValueOrDie();
-  AllocPointCount(new_count);
-  m_PointCount = new_count;
-}
-
-void CFX_PathData::Append(const CFX_PathData* pSrc, const CFX_Matrix* pMatrix) {
-  int old_count = m_PointCount;
-  AddPointCount(pSrc->m_PointCount);
-  FXSYS_memcpy(m_pPoints + old_count, pSrc->m_pPoints,
-               pSrc->m_PointCount * sizeof(FX_PATHPOINT));
-  if (pMatrix) {
-    for (int i = 0; i < pSrc->m_PointCount; i++) {
-      pMatrix->Transform(m_pPoints[old_count + i].m_PointX,
-                         m_pPoints[old_count + i].m_PointY);
-    }
-  }
-}
-
-void CFX_PathData::SetPoint(int index, FX_FLOAT x, FX_FLOAT y, int flag) {
-  ASSERT(index < m_PointCount);
-  m_pPoints[index].m_PointX = x;
-  m_pPoints[index].m_PointY = y;
-  m_pPoints[index].m_Flag = flag;
-}
-
-void CFX_PathData::AppendRect(FX_FLOAT left,
-                              FX_FLOAT bottom,
-                              FX_FLOAT right,
-                              FX_FLOAT top) {
-  int old_count = m_PointCount;
-  AddPointCount(5);
-  FX_PATHPOINT* pPoints = m_pPoints + old_count;
-  pPoints[0].m_PointX = pPoints[1].m_PointX = pPoints[4].m_PointX = left;
-  pPoints[2].m_PointX = pPoints[3].m_PointX = right;
-  pPoints[0].m_PointY = pPoints[3].m_PointY = pPoints[4].m_PointY = bottom;
-  pPoints[1].m_PointY = pPoints[2].m_PointY = top;
-  pPoints[0].m_Flag = FXPT_MOVETO;
-  pPoints[1].m_Flag = pPoints[2].m_Flag = pPoints[3].m_Flag = FXPT_LINETO;
-  pPoints[4].m_Flag = FXPT_LINETO | FXPT_CLOSEFIGURE;
-}
-
-CFX_FloatRect CFX_PathData::GetBoundingBox() const {
-  CFX_FloatRect rect;
-  if (m_PointCount) {
-    rect.InitRect(m_pPoints[0].m_PointX, m_pPoints[0].m_PointY);
-    for (int i = 1; i < m_PointCount; i++) {
-      rect.UpdateRect(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY);
-    }
-  }
-  return rect;
-}
-
-static void _UpdateLineEndPoints(CFX_FloatRect& rect,
-                                 FX_FLOAT start_x,
-                                 FX_FLOAT start_y,
-                                 FX_FLOAT end_x,
-                                 FX_FLOAT end_y,
-                                 FX_FLOAT hw) {
-  if (start_x == end_x) {
-    if (start_y == end_y) {
-      rect.UpdateRect(end_x + hw, end_y + hw);
-      rect.UpdateRect(end_x - hw, end_y - hw);
-      return;
-    }
-    FX_FLOAT point_y;
-    if (end_y < start_y) {
-      point_y = end_y - hw;
-    } else {
-      point_y = end_y + hw;
-    }
-    rect.UpdateRect(end_x + hw, point_y);
-    rect.UpdateRect(end_x - hw, point_y);
-    return;
-  }
-  if (start_y == end_y) {
-    FX_FLOAT point_x;
-    if (end_x < start_x) {
-      point_x = end_x - hw;
-    } else {
-      point_x = end_x + hw;
-    }
-    rect.UpdateRect(point_x, end_y + hw);
-    rect.UpdateRect(point_x, end_y - hw);
-    return;
-  }
-  FX_FLOAT dx = end_x - start_x;
-  FX_FLOAT dy = end_y - start_y;
-  FX_FLOAT ll = FXSYS_sqrt2(dx, dy);
-  FX_FLOAT mx = end_x + hw * dx / ll;
-  FX_FLOAT my = end_y + hw * dy / ll;
-  FX_FLOAT dx1 = hw * dy / ll;
-  FX_FLOAT dy1 = hw * dx / ll;
-  rect.UpdateRect(mx - dx1, my + dy1);
-  rect.UpdateRect(mx + dx1, my - dy1);
-}
-
-static void _UpdateLineJoinPoints(CFX_FloatRect& rect,
-                                  FX_FLOAT start_x,
-                                  FX_FLOAT start_y,
-                                  FX_FLOAT middle_x,
-                                  FX_FLOAT middle_y,
-                                  FX_FLOAT end_x,
-                                  FX_FLOAT end_y,
-                                  FX_FLOAT half_width,
-                                  FX_FLOAT miter_limit) {
-  FX_FLOAT start_k = 0, start_c = 0, end_k = 0, end_c = 0, start_len = 0,
-           start_dc = 0, end_len = 0, end_dc = 0;
-  FX_BOOL bStartVert = FXSYS_fabs(start_x - middle_x) < 1.0f / 20;
-  FX_BOOL bEndVert = FXSYS_fabs(middle_x - end_x) < 1.0f / 20;
-  if (bStartVert && bEndVert) {
-    int start_dir = middle_y > start_y ? 1 : -1;
-    FX_FLOAT point_y = middle_y + half_width * start_dir;
-    rect.UpdateRect(middle_x + half_width, point_y);
-    rect.UpdateRect(middle_x - half_width, point_y);
-    return;
-  }
-  if (!bStartVert) {
-    start_k = (middle_y - start_y) / (middle_x - start_x);
-    start_c = middle_y - (start_k * middle_x);
-    start_len = FXSYS_sqrt2(start_x - middle_x, start_y - middle_y);
-    start_dc =
-        (FX_FLOAT)FXSYS_fabs(half_width * start_len / (start_x - middle_x));
-  }
-  if (!bEndVert) {
-    end_k = (end_y - middle_y) / (end_x - middle_x);
-    end_c = middle_y - (end_k * middle_x);
-    end_len = FXSYS_sqrt2(end_x - middle_x, end_y - middle_y);
-    end_dc = (FX_FLOAT)FXSYS_fabs(half_width * end_len / (end_x - middle_x));
-  }
-  if (bStartVert) {
-    FX_FLOAT outside_x = start_x;
-    if (end_x < start_x) {
-      outside_x += half_width;
-    } else {
-      outside_x -= half_width;
-    }
-    FX_FLOAT outside_y;
-    if (start_y < (end_k * start_x) + end_c) {
-      outside_y = (end_k * outside_x) + end_c + end_dc;
-    } else {
-      outside_y = (end_k * outside_x) + end_c - end_dc;
-    }
-    rect.UpdateRect(outside_x, outside_y);
-    return;
-  }
-  if (bEndVert) {
-    FX_FLOAT outside_x = end_x;
-    if (start_x < end_x) {
-      outside_x += half_width;
-    } else {
-      outside_x -= half_width;
-    }
-    FX_FLOAT outside_y;
-    if (end_y < (start_k * end_x) + start_c) {
-      outside_y = (start_k * outside_x) + start_c + start_dc;
-    } else {
-      outside_y = (start_k * outside_x) + start_c - start_dc;
-    }
-    rect.UpdateRect(outside_x, outside_y);
-    return;
-  }
-  if (FXSYS_fabs(start_k - end_k) < 1.0f / 20) {
-    int start_dir = middle_x > start_x ? 1 : -1;
-    int end_dir = end_x > middle_x ? 1 : -1;
-    if (start_dir == end_dir) {
-      _UpdateLineEndPoints(rect, middle_x, middle_y, end_x, end_y, half_width);
-    } else {
-      _UpdateLineEndPoints(rect, start_x, start_y, middle_x, middle_y,
-                           half_width);
-    }
-    return;
-  }
-  FX_FLOAT start_outside_c = start_c;
-  if (end_y < (start_k * end_x) + start_c) {
-    start_outside_c += start_dc;
-  } else {
-    start_outside_c -= start_dc;
-  }
-  FX_FLOAT end_outside_c = end_c;
-  if (start_y < (end_k * start_x) + end_c) {
-    end_outside_c += end_dc;
-  } else {
-    end_outside_c -= end_dc;
-  }
-  FX_FLOAT join_x = (end_outside_c - start_outside_c) / (start_k - end_k);
-  FX_FLOAT join_y = (start_k * join_x) + start_outside_c;
-  rect.UpdateRect(join_x, join_y);
-}
-
-CFX_FloatRect CFX_PathData::GetBoundingBox(FX_FLOAT line_width,
-                                           FX_FLOAT miter_limit) const {
-  CFX_FloatRect rect(100000 * 1.0f, 100000 * 1.0f, -100000 * 1.0f,
-                     -100000 * 1.0f);
-  int iPoint = 0;
-  FX_FLOAT half_width = line_width;
-  int iStartPoint = 0;
-  int iEndPoint = 0;
-  int iMiddlePoint = 0;
-  FX_BOOL bJoin;
-  while (iPoint < m_PointCount) {
-    if (m_pPoints[iPoint].m_Flag == FXPT_MOVETO) {
-      iStartPoint = iPoint + 1;
-      iEndPoint = iPoint;
-      bJoin = FALSE;
-    } else {
-      if (m_pPoints[iPoint].m_Flag == FXPT_BEZIERTO) {
-        rect.UpdateRect(m_pPoints[iPoint].m_PointX, m_pPoints[iPoint].m_PointY);
-        rect.UpdateRect(m_pPoints[iPoint + 1].m_PointX,
-                        m_pPoints[iPoint + 1].m_PointY);
-        iPoint += 2;
-      }
-      if (iPoint == m_PointCount - 1 ||
-          m_pPoints[iPoint + 1].m_Flag == FXPT_MOVETO) {
-        iStartPoint = iPoint - 1;
-        iEndPoint = iPoint;
-        bJoin = FALSE;
-      } else {
-        iStartPoint = iPoint - 1;
-        iMiddlePoint = iPoint;
-        iEndPoint = iPoint + 1;
-        bJoin = TRUE;
-      }
-    }
-    FX_FLOAT start_x = m_pPoints[iStartPoint].m_PointX;
-    FX_FLOAT start_y = m_pPoints[iStartPoint].m_PointY;
-    FX_FLOAT end_x = m_pPoints[iEndPoint].m_PointX;
-    FX_FLOAT end_y = m_pPoints[iEndPoint].m_PointY;
-    if (bJoin) {
-      FX_FLOAT middle_x = m_pPoints[iMiddlePoint].m_PointX;
-      FX_FLOAT middle_y = m_pPoints[iMiddlePoint].m_PointY;
-      _UpdateLineJoinPoints(rect, start_x, start_y, middle_x, middle_y, end_x,
-                            end_y, half_width, miter_limit);
-    } else {
-      _UpdateLineEndPoints(rect, start_x, start_y, end_x, end_y, half_width);
-    }
-    iPoint++;
-  }
-  return rect;
-}
-
-void CFX_PathData::Transform(const CFX_Matrix* pMatrix) {
-  if (!pMatrix) {
-    return;
-  }
-  for (int i = 0; i < m_PointCount; i++) {
-    pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY);
-  }
-}
-
-FX_BOOL CFX_PathData::GetZeroAreaPath(CFX_PathData& NewPath,
-                                      CFX_Matrix* pMatrix,
-                                      FX_BOOL& bThin,
-                                      FX_BOOL bAdjust) const {
-  if (m_PointCount < 3) {
-    return FALSE;
-  }
-  if (m_PointCount == 3 && (m_pPoints[0].m_Flag & FXPT_TYPE) == FXPT_MOVETO &&
-      (m_pPoints[1].m_Flag & FXPT_TYPE) == FXPT_LINETO &&
-      (m_pPoints[2].m_Flag & FXPT_TYPE) == FXPT_LINETO &&
-      m_pPoints[0].m_PointX == m_pPoints[2].m_PointX &&
-      m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) {
-    NewPath.AddPointCount(2);
-    if (bAdjust) {
-      if (pMatrix) {
-        FX_FLOAT x = m_pPoints[0].m_PointX, y = m_pPoints[0].m_PointY;
-        pMatrix->TransformPoint(x, y);
-        x = (int)x + 0.5f;
-        y = (int)y + 0.5f;
-        NewPath.SetPoint(0, x, y, FXPT_MOVETO);
-        x = m_pPoints[1].m_PointX, y = m_pPoints[1].m_PointY;
-        pMatrix->TransformPoint(x, y);
-        x = (int)x + 0.5f;
-        y = (int)y + 0.5f;
-        NewPath.SetPoint(1, x, y, FXPT_LINETO);
-        pMatrix->SetIdentity();
-      } else {
-        FX_FLOAT x = (int)m_pPoints[0].m_PointX + 0.5f,
-                 y = (int)m_pPoints[0].m_PointY + 0.5f;
-        NewPath.SetPoint(0, x, y, FXPT_MOVETO);
-        x = (int)m_pPoints[1].m_PointX + 0.5f,
-        y = (int)m_pPoints[1].m_PointY + 0.5f;
-        NewPath.SetPoint(1, x, y, FXPT_LINETO);
-      }
-    } else {
-      NewPath.SetPoint(0, m_pPoints[0].m_PointX, m_pPoints[0].m_PointY,
-                       FXPT_MOVETO);
-      NewPath.SetPoint(1, m_pPoints[1].m_PointX, m_pPoints[1].m_PointY,
-                       FXPT_LINETO);
-    }
-    if (m_pPoints[0].m_PointX != m_pPoints[1].m_PointX &&
-        m_pPoints[0].m_PointY != m_pPoints[1].m_PointY) {
-      bThin = TRUE;
-    }
-    return TRUE;
-  }
-  if (((m_PointCount > 3) && (m_PointCount % 2))) {
-    int mid = m_PointCount / 2;
-    FX_BOOL bZeroArea = FALSE;
-    CFX_PathData t_path;
-    for (int i = 0; i < mid; i++) {
-      if (!(m_pPoints[mid - i - 1].m_PointX ==
-                m_pPoints[mid + i + 1].m_PointX &&
-            m_pPoints[mid - i - 1].m_PointY ==
-                m_pPoints[mid + i + 1].m_PointY &&
-            ((m_pPoints[mid - i - 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO &&
-             (m_pPoints[mid + i + 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO))) {
-        bZeroArea = TRUE;
-        break;
-      }
-      int new_count = t_path.GetPointCount();
-      t_path.AddPointCount(2);
-      t_path.SetPoint(new_count, m_pPoints[mid - i].m_PointX,
-                      m_pPoints[mid - i].m_PointY, FXPT_MOVETO);
-      t_path.SetPoint(new_count + 1, m_pPoints[mid - i - 1].m_PointX,
-                      m_pPoints[mid - i - 1].m_PointY, FXPT_LINETO);
-    }
-    if (!bZeroArea) {
-      NewPath.Append(&t_path, nullptr);
-      bThin = TRUE;
-      return TRUE;
-    }
-  }
-  int stratPoint = 0;
-  int next = 0, i;
-  for (i = 0; i < m_PointCount; i++) {
-    int point_type = m_pPoints[i].m_Flag & FXPT_TYPE;
-    if (point_type == FXPT_MOVETO) {
-      stratPoint = i;
-    } else if (point_type == FXPT_LINETO) {
-      next = (i + 1 - stratPoint) % (m_PointCount - stratPoint) + stratPoint;
-      if ((m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO &&
-          (m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_MOVETO) {
-        if ((m_pPoints[i - 1].m_PointX == m_pPoints[i].m_PointX &&
-             m_pPoints[i].m_PointX == m_pPoints[next].m_PointX) &&
-            ((m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) *
-                 (m_pPoints[i].m_PointY - m_pPoints[next].m_PointY) >
-             0)) {
-          int pre = i;
-          if (FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) <
-              FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[next].m_PointY)) {
-            pre--;
-            next--;
-          }
-          int new_count = NewPath.GetPointCount();
-          NewPath.AddPointCount(2);
-          NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX,
-                           m_pPoints[pre].m_PointY, FXPT_MOVETO);
-          NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX,
-                           m_pPoints[next].m_PointY, FXPT_LINETO);
-        } else if ((m_pPoints[i - 1].m_PointY == m_pPoints[i].m_PointY &&
-                    m_pPoints[i].m_PointY == m_pPoints[next].m_PointY) &&
-                   ((m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) *
-                        (m_pPoints[i].m_PointX - m_pPoints[next].m_PointX) >
-                    0)) {
-          int pre = i;
-          if (FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) <
-              FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[next].m_PointX)) {
-            pre--;
-            next--;
-          }
-          int new_count = NewPath.GetPointCount();
-          NewPath.AddPointCount(2);
-          NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX,
-                           m_pPoints[pre].m_PointY, FXPT_MOVETO);
-          NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX,
-                           m_pPoints[next].m_PointY, FXPT_LINETO);
-        } else if ((m_pPoints[i - 1].m_Flag & FXPT_TYPE) == FXPT_MOVETO &&
-                   (m_pPoints[next].m_Flag & FXPT_TYPE) == FXPT_LINETO &&
-                   m_pPoints[i - 1].m_PointX == m_pPoints[next].m_PointX &&
-                   m_pPoints[i - 1].m_PointY == m_pPoints[next].m_PointY &&
-                   m_pPoints[next].m_Flag & FXPT_CLOSEFIGURE) {
-          int new_count = NewPath.GetPointCount();
-          NewPath.AddPointCount(2);
-          NewPath.SetPoint(new_count, m_pPoints[i - 1].m_PointX,
-                           m_pPoints[i - 1].m_PointY, FXPT_MOVETO);
-          NewPath.SetPoint(new_count + 1, m_pPoints[i].m_PointX,
-                           m_pPoints[i].m_PointY, FXPT_LINETO);
-          bThin = TRUE;
-        }
-      }
-    } else if (point_type == FXPT_BEZIERTO) {
-      i += 2;
-      continue;
-    }
-  }
-  if (m_PointCount > 3 && NewPath.GetPointCount()) {
-    bThin = TRUE;
-  }
-  if (NewPath.GetPointCount() == 0) {
-    return FALSE;
-  }
-  return TRUE;
-}
-
-FX_BOOL CFX_PathData::IsRect() const {
-  if (m_PointCount != 5 && m_PointCount != 4) {
-    return FALSE;
-  }
-  if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX ||
-                             m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) ||
-      (m_pPoints[0].m_PointX == m_pPoints[2].m_PointX &&
-       m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) ||
-      (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX &&
-       m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) {
-    return FALSE;
-  }
-  if (m_pPoints[0].m_PointX != m_pPoints[3].m_PointX &&
-      m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) {
-    return FALSE;
-  }
-  for (int i = 1; i < 4; i++) {
-    if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) {
-      return FALSE;
-    }
-    if (m_pPoints[i].m_PointX != m_pPoints[i - 1].m_PointX &&
-        m_pPoints[i].m_PointY != m_pPoints[i - 1].m_PointY) {
-      return FALSE;
-    }
-  }
-  return m_PointCount == 5 || (m_pPoints[3].m_Flag & FXPT_CLOSEFIGURE);
-}
-
-FX_BOOL CFX_PathData::IsRect(const CFX_Matrix* pMatrix,
-                             CFX_FloatRect* pRect) const {
-  if (!pMatrix) {
-    if (!IsRect()) {
-      return FALSE;
-    }
-    if (pRect) {
-      pRect->left = m_pPoints[0].m_PointX;
-      pRect->right = m_pPoints[2].m_PointX;
-      pRect->bottom = m_pPoints[0].m_PointY;
-      pRect->top = m_pPoints[2].m_PointY;
-      pRect->Normalize();
-    }
-    return TRUE;
-  }
-  if (m_PointCount != 5 && m_PointCount != 4) {
-    return FALSE;
-  }
-  if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX ||
-                             m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) ||
-      (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX &&
-       m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) {
-    return FALSE;
-  }
-  if (m_PointCount == 4 && m_pPoints[0].m_PointX != m_pPoints[3].m_PointX &&
-      m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) {
-    return FALSE;
-  }
-  FX_FLOAT x[5], y[5];
-  for (int i = 0; i < m_PointCount; i++) {
-    pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY, x[i],
-                       y[i]);
-    if (i) {
-      if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) {
-        return FALSE;
-      }
-      if (x[i] != x[i - 1] && y[i] != y[i - 1]) {
-        return FALSE;
-      }
-    }
-  }
-  if (pRect) {
-    pRect->left = x[0];
-    pRect->right = x[2];
-    pRect->bottom = y[0];
-    pRect->top = y[2];
-    pRect->Normalize();
-  }
-  return TRUE;
-}
-
-void CFX_PathData::Copy(const CFX_PathData& src) {
-  SetPointCount(src.m_PointCount);
-  FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount);
-}
 
 CFX_GraphStateData::CFX_GraphStateData()
     : m_LineCap(LineCapButt),
diff --git a/core/fxge/ge/fx_ge_text.cpp b/core/fxge/ge/fx_ge_text.cpp
index b3c234f..8365549 100644
--- a/core/fxge/ge/fx_ge_text.cpp
+++ b/core/fxge/ge/fx_ge_text.cpp
@@ -11,6 +11,7 @@
 #include "core/fxge/ge/fx_text_int.h"
 #include "core/fxge/include/cfx_fontmgr.h"
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_freetype.h"
 #include "core/fxge/include/fx_ge.h"
 #include "core/fxge/include/ifx_renderdevicedriver.h"
diff --git a/core/fxge/ifx_renderdevicedriver.cpp b/core/fxge/ifx_renderdevicedriver.cpp
index 2265a3d..4fd685f 100644
--- a/core/fxge/ifx_renderdevicedriver.cpp
+++ b/core/fxge/ifx_renderdevicedriver.cpp
@@ -7,6 +7,7 @@
 #include "core/fxge/include/ifx_renderdevicedriver.h"
 
 #include "core/fxcrt/include/fx_coordinates.h"
+#include "core/fxge/include/cfx_pathdata.h"
 
 IFX_RenderDeviceDriver::~IFX_RenderDeviceDriver() {}
 
diff --git a/core/fxge/include/cfx_gemodule.h b/core/fxge/include/cfx_gemodule.h
index e6b46de..351c036 100644
--- a/core/fxge/include/cfx_gemodule.h
+++ b/core/fxge/include/cfx_gemodule.h
@@ -1,4 +1,4 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
+// Copyright 2016 PDFium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/core/fxge/include/cfx_pathdata.h b/core/fxge/include/cfx_pathdata.h
new file mode 100644
index 0000000..fe95631
--- /dev/null
+++ b/core/fxge/include/cfx_pathdata.h
@@ -0,0 +1,57 @@
+// Copyright 2016 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXGE_INCLUDE_CFX_PATHDATA_H_
+#define CORE_FXGE_INCLUDE_CFX_PATHDATA_H_
+
+#include "core/fxcrt/include/fx_coordinates.h"
+#include "core/fxcrt/include/fx_system.h"
+
+struct FX_PATHPOINT {
+  FX_FLOAT m_PointX;
+  FX_FLOAT m_PointY;
+  int m_Flag;
+};
+
+class CFX_PathData {
+ public:
+  CFX_PathData();
+  CFX_PathData(const CFX_PathData& src);
+  ~CFX_PathData();
+
+  int GetPointCount() const { return m_PointCount; }
+  int GetFlag(int index) const { return m_pPoints[index].m_Flag; }
+  FX_FLOAT GetPointX(int index) const { return m_pPoints[index].m_PointX; }
+  FX_FLOAT GetPointY(int index) const { return m_pPoints[index].m_PointY; }
+  FX_PATHPOINT* GetPoints() const { return m_pPoints; }
+
+  void SetPointCount(int nPoints);
+  void AllocPointCount(int nPoints);
+  void AddPointCount(int addPoints);
+  CFX_FloatRect GetBoundingBox() const;
+  CFX_FloatRect GetBoundingBox(FX_FLOAT line_width, FX_FLOAT miter_limit) const;
+  void Transform(const CFX_Matrix* pMatrix);
+  FX_BOOL IsRect() const;
+  FX_BOOL GetZeroAreaPath(CFX_PathData& NewPath,
+                          CFX_Matrix* pMatrix,
+                          FX_BOOL& bThin,
+                          FX_BOOL bAdjust) const;
+  FX_BOOL IsRect(const CFX_Matrix* pMatrix, CFX_FloatRect* rect) const;
+  void Append(const CFX_PathData* pSrc, const CFX_Matrix* pMatrix);
+  void AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top);
+  void SetPoint(int index, FX_FLOAT x, FX_FLOAT y, int flag);
+  void TrimPoints(int nPoints);
+  void Copy(const CFX_PathData& src);
+
+ private:
+  friend class CPDF_Path;
+
+  int m_PointCount;
+  FX_PATHPOINT* m_pPoints;
+  int m_AllocCount;
+};
+
+#endif  // CORE_FXGE_INCLUDE_CFX_PATHDATA_H_
diff --git a/core/fxge/include/fx_ge.h b/core/fxge/include/fx_ge.h
index 53c6ccb..fabcee4 100644
--- a/core/fxge/include/fx_ge.h
+++ b/core/fxge/include/fx_ge.h
@@ -22,75 +22,6 @@
 class IFX_RenderDeviceDriver;
 class SkPictureRecorder;
 
-struct FX_PATHPOINT {
-  FX_FLOAT m_PointX;
-  FX_FLOAT m_PointY;
-  int m_Flag;
-};
-
-class CFX_ClipRgn {
- public:
-  enum ClipType { RectI, MaskF };
-
-  CFX_ClipRgn(int device_width, int device_height);
-  explicit CFX_ClipRgn(const FX_RECT& rect);
-  CFX_ClipRgn(const CFX_ClipRgn& src);
-  ~CFX_ClipRgn();
-
-  ClipType GetType() const { return m_Type; }
-  const FX_RECT& GetBox() const { return m_Box; }
-  CFX_DIBitmapRef GetMask() const { return m_Mask; }
-
-  void Reset(const FX_RECT& rect);
-  void IntersectRect(const FX_RECT& rect);
-  void IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask);
-
- protected:
-  void IntersectMaskRect(FX_RECT rect, FX_RECT mask_box, CFX_DIBitmapRef Mask);
-
-  ClipType m_Type;
-  FX_RECT m_Box;
-  CFX_DIBitmapRef m_Mask;
-};
-
-class CFX_PathData {
- public:
-  CFX_PathData();
-  CFX_PathData(const CFX_PathData& src);
-  ~CFX_PathData();
-
-  int GetPointCount() const { return m_PointCount; }
-  int GetFlag(int index) const { return m_pPoints[index].m_Flag; }
-  FX_FLOAT GetPointX(int index) const { return m_pPoints[index].m_PointX; }
-  FX_FLOAT GetPointY(int index) const { return m_pPoints[index].m_PointY; }
-  FX_PATHPOINT* GetPoints() const { return m_pPoints; }
-
-  void SetPointCount(int nPoints);
-  void AllocPointCount(int nPoints);
-  void AddPointCount(int addPoints);
-  CFX_FloatRect GetBoundingBox() const;
-  CFX_FloatRect GetBoundingBox(FX_FLOAT line_width, FX_FLOAT miter_limit) const;
-  void Transform(const CFX_Matrix* pMatrix);
-  FX_BOOL IsRect() const;
-  FX_BOOL GetZeroAreaPath(CFX_PathData& NewPath,
-                          CFX_Matrix* pMatrix,
-                          FX_BOOL& bThin,
-                          FX_BOOL bAdjust) const;
-  FX_BOOL IsRect(const CFX_Matrix* pMatrix, CFX_FloatRect* rect) const;
-  void Append(const CFX_PathData* pSrc, const CFX_Matrix* pMatrix);
-  void AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top);
-  void SetPoint(int index, FX_FLOAT x, FX_FLOAT y, int flag);
-  void TrimPoints(int nPoints);
-  void Copy(const CFX_PathData& src);
-
- protected:
-  friend class CPDF_Path;
-
-  int m_PointCount;
-  FX_PATHPOINT* m_pPoints;
-  int m_AllocCount;
-};
-
 class CFX_GraphStateData {
  public:
   enum LineCap { LineCapButt = 0, LineCapRound = 1, LineCapSquare = 2 };
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 3ccfd14..b6cf7c0 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -15,6 +15,7 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/skia/fx_skia_device.h"
 
 #include "third_party/skia/include/core/SkCanvas.h"
diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h
index a7a5f85..2169f54 100644
--- a/core/fxge/skia/fx_skia_device.h
+++ b/core/fxge/skia/fx_skia_device.h
@@ -7,6 +7,7 @@
 
 #if defined(_SKIA_SUPPORT_)
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/ifx_renderdevicedriver.h"
 
 class SkCanvas;
diff --git a/core/fxge/skia/fx_skia_device_unittest.cpp b/core/fxge/skia/fx_skia_device_unittest.cpp
index b2f7f6d..fa46ea3 100644
--- a/core/fxge/skia/fx_skia_device_unittest.cpp
+++ b/core/fxge/skia/fx_skia_device_unittest.cpp
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "core/fxge/skia/fx_skia_device.h"
 #include "fpdfsdk/include/fsdk_define.h"
diff --git a/core/fxge/win32/fx_win32_device.cpp b/core/fxge/win32/fx_win32_device.cpp
index cb1243f..a0309b0 100644
--- a/core/fxge/win32/fx_win32_device.cpp
+++ b/core/fxge/win32/fx_win32_device.cpp
@@ -25,6 +25,7 @@
 #include "core/fxge/ge/fx_text_int.h"
 #include "core/fxge/include/cfx_fontmapper.h"
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/cfx_windowsdevice.h"
 #include "core/fxge/include/ifx_systemfontinfo.h"
 #include "core/fxge/include/fx_font.h"
diff --git a/core/fxge/win32/fx_win32_dwrite.cpp b/core/fxge/win32/fx_win32_dwrite.cpp
index 305a8a8..9c1d6c3 100644
--- a/core/fxge/win32/fx_win32_dwrite.cpp
+++ b/core/fxge/win32/fx_win32_dwrite.cpp
@@ -4,6 +4,7 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
+#include "core/fxge/ge/cfx_cliprgn.h"
 #include "core/fxge/include/fx_ge.h"
 
 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
diff --git a/core/fxge/win32/fx_win32_gdipext.cpp b/core/fxge/win32/fx_win32_gdipext.cpp
index d21043c..b9fc97a 100644
--- a/core/fxge/win32/fx_win32_gdipext.cpp
+++ b/core/fxge/win32/fx_win32_gdipext.cpp
@@ -18,6 +18,7 @@
 #include <gdiplus.h>
 
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/win32/cfx_windowsdib.h"
 #include "core/fxge/win32/win32_int.h"
 
diff --git a/core/fxge/win32/win32_int.h b/core/fxge/win32/win32_int.h
index c7a7606..3bfb295 100644
--- a/core/fxge/win32/win32_int.h
+++ b/core/fxge/win32/win32_int.h
@@ -7,6 +7,7 @@
 #ifndef CORE_FXGE_WIN32_WIN32_INT_H_
 #define CORE_FXGE_WIN32_WIN32_INT_H_
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/ifx_renderdevicedriver.h"
 #include "core/fxge/win32/dwrite_int.h"
 
diff --git a/fpdfsdk/formfiller/cffl_iformfiller.cpp b/fpdfsdk/formfiller/cffl_iformfiller.cpp
index 2fd4af1..55907aa 100644
--- a/fpdfsdk/formfiller/cffl_iformfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_iformfiller.cpp
@@ -8,6 +8,7 @@
 
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "fpdfsdk/formfiller/cffl_checkbox.h"
 #include "fpdfsdk/formfiller/cffl_combobox.h"
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index a5c2741..c782150 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -15,6 +15,7 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "fpdfsdk/include/fsdk_define.h"
 
 namespace {
diff --git a/fpdfsdk/fsdk_baseform.cpp b/fpdfsdk/fsdk_baseform.cpp
index 1b1d40b..50d0eac 100644
--- a/fpdfsdk/fsdk_baseform.cpp
+++ b/fpdfsdk/fsdk_baseform.cpp
@@ -18,6 +18,7 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
 #include "core/fpdfdoc/include/cpdf_actionfields.h"
 #include "core/fpdfdoc/include/cpdf_interform.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "fpdfsdk/formfiller/cffl_formfiller.h"
 #include "fpdfsdk/fxedit/include/fxet_edit.h"
diff --git a/fpdfsdk/fxedit/fxet_edit.cpp b/fpdfsdk/fxedit/fxet_edit.cpp
index f31c60a..43646bd 100644
--- a/fpdfsdk/fxedit/fxet_edit.cpp
+++ b/fpdfsdk/fxedit/fxet_edit.cpp
@@ -19,6 +19,7 @@
 #include "core/fpdfdoc/include/cpvt_section.h"
 #include "core/fpdfdoc/include/cpvt_word.h"
 #include "core/fpdfdoc/include/ipvt_fontmap.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "fpdfsdk/cfx_systemhandler.h"
 #include "fpdfsdk/fxedit/include/fx_edit.h"
diff --git a/fpdfsdk/pdfwindow/PWL_Caret.cpp b/fpdfsdk/pdfwindow/PWL_Caret.cpp
index a5728ce..8bc87a4 100644
--- a/fpdfsdk/pdfwindow/PWL_Caret.cpp
+++ b/fpdfsdk/pdfwindow/PWL_Caret.cpp
@@ -6,6 +6,7 @@
 
 #include "fpdfsdk/pdfwindow/PWL_Caret.h"
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "fpdfsdk/pdfwindow/PWL_Utils.h"
 #include "fpdfsdk/pdfwindow/PWL_Wnd.h"
diff --git a/fpdfsdk/pdfwindow/PWL_ComboBox.cpp b/fpdfsdk/pdfwindow/PWL_ComboBox.cpp
index 7349ed0..46c2e68 100644
--- a/fpdfsdk/pdfwindow/PWL_ComboBox.cpp
+++ b/fpdfsdk/pdfwindow/PWL_ComboBox.cpp
@@ -6,6 +6,7 @@
 
 #include "fpdfsdk/pdfwindow/PWL_ComboBox.h"
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "fpdfsdk/fxedit/include/fxet_list.h"
 #include "fpdfsdk/pdfwindow/PWL_Edit.h"
diff --git a/fpdfsdk/pdfwindow/PWL_Edit.cpp b/fpdfsdk/pdfwindow/PWL_Edit.cpp
index 5d20dd4..cd58688 100644
--- a/fpdfsdk/pdfwindow/PWL_Edit.cpp
+++ b/fpdfsdk/pdfwindow/PWL_Edit.cpp
@@ -12,6 +12,7 @@
 #include "core/fpdfdoc/include/cpvt_word.h"
 #include "core/fxcrt/include/fx_safe_types.h"
 #include "core/fxcrt/include/fx_xml.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "fpdfsdk/fxedit/include/fxet_edit.h"
 #include "fpdfsdk/pdfwindow/PWL_Caret.h"
diff --git a/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp b/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp
index 410be18..ff5021e 100644
--- a/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp
+++ b/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp
@@ -6,6 +6,7 @@
 
 #include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "fpdfsdk/pdfwindow/PWL_Utils.h"
 #include "fpdfsdk/pdfwindow/PWL_Wnd.h"
diff --git a/fpdfsdk/pdfwindow/PWL_Utils.cpp b/fpdfsdk/pdfwindow/PWL_Utils.cpp
index 7e961a4..c67b75a 100644
--- a/fpdfsdk/pdfwindow/PWL_Utils.cpp
+++ b/fpdfsdk/pdfwindow/PWL_Utils.cpp
@@ -9,6 +9,7 @@
 #include <algorithm>
 
 #include "core/fpdfdoc/include/cpvt_word.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "fpdfsdk/fxedit/include/fxet_edit.h"
 #include "fpdfsdk/pdfwindow/PWL_Icon.h"
diff --git a/pdfium.gyp b/pdfium.gyp
index 50409da..584de12 100644
--- a/pdfium.gyp
+++ b/pdfium.gyp
@@ -713,14 +713,17 @@
         'core/fxge/fontdata/chromefontdata/FoxitSerifMM.cpp',
         'core/fxge/fontdata/chromefontdata/FoxitSymbol.cpp',
         'core/fxge/freetype/fx_freetype.cpp',
-        "core/fxge/ge/cfx_folderfontinfo.cpp",
-        "core/fxge/ge/cfx_folderfontinfo.h",
-        "core/fxge/ge/cfx_fontmapper.cpp",
-        "core/fxge/ge/cfx_fontmgr.cpp",
-        "core/fxge/ge/include/cfx_fontmapper.h",
-        "core/fxge/ge/include/cfx_fontmgr.h",
-        "core/fxge/ge/include/ifx_systemfontinfo.h",
+        'core/fxge/ge/cfx_cliprgn.cpp',
+        'core/fxge/ge/cfx_cliprgn.h',
+        'core/fxge/ge/cfx_folderfontinfo.cpp',
+        'core/fxge/ge/cfx_folderfontinfo.h',
+        'core/fxge/ge/cfx_fontmapper.cpp',
+        'core/fxge/ge/cfx_fontmgr.cpp',
         'core/fxge/ge/cfx_gemodule.cpp',
+        'core/fxge/ge/cfx_pathdata.cpp',
+        'core/fxge/ge/include/cfx_fontmapper.h',
+        'core/fxge/ge/include/cfx_fontmgr.h',
+        'core/fxge/ge/include/ifx_systemfontinfo.h',
         'core/fxge/ge/fx_ge_device.cpp',
         'core/fxge/ge/fx_ge_font.cpp',
         'core/fxge/ge/fx_ge_fontmap.cpp',
@@ -730,7 +733,8 @@
         'core/fxge/ge/fx_text_int.h',
         'core/fxge/ifx_renderdevicedriver.cpp',
         'core/fxge/include/cfx_gemodule.h',
-        "core/fxge/include/cfx_windowsdevice.h",
+        'core/fxge/include/cfx_pathdata.h',
+        'core/fxge/include/cfx_windowsdevice.h',
         'core/fxge/include/fx_dib.h',
         'core/fxge/include/fx_font.h',
         'core/fxge/include/fx_freetype.h',
diff --git a/xfa/fde/cfde_path.h b/xfa/fde/cfde_path.h
index c9f213d..fcf35cd 100644
--- a/xfa/fde/cfde_path.h
+++ b/xfa/fde/cfde_path.h
@@ -7,6 +7,7 @@
 #ifndef XFA_FDE_CFDE_PATH_H_
 #define XFA_FDE_CFDE_PATH_H_
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "xfa/fgas/crt/fgas_memory.h"
 
diff --git a/xfa/fwl/theme/cfwl_checkboxtp.cpp b/xfa/fwl/theme/cfwl_checkboxtp.cpp
index 23cc21f..d00a097 100644
--- a/xfa/fwl/theme/cfwl_checkboxtp.cpp
+++ b/xfa/fwl/theme/cfwl_checkboxtp.cpp
@@ -6,6 +6,7 @@
 
 #include "xfa/fwl/theme/cfwl_checkboxtp.h"
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "xfa/fde/tto/fde_textout.h"
 #include "xfa/fwl/basewidget/ifwl_checkbox.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
diff --git a/xfa/fxbarcode/BC_TwoDimWriter.cpp b/xfa/fxbarcode/BC_TwoDimWriter.cpp
index 40b5519..91ea570 100644
--- a/xfa/fxbarcode/BC_TwoDimWriter.cpp
+++ b/xfa/fxbarcode/BC_TwoDimWriter.cpp
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 #include "third_party/base/numerics/safe_math.h"
 #include "xfa/fxbarcode/BC_TwoDimWriter.h"
diff --git a/xfa/fxbarcode/oned/BC_OneDimWriter.cpp b/xfa/fxbarcode/oned/BC_OneDimWriter.cpp
index 4cdb7e7..8ba7d8e 100644
--- a/xfa/fxbarcode/oned/BC_OneDimWriter.cpp
+++ b/xfa/fxbarcode/oned/BC_OneDimWriter.cpp
@@ -26,6 +26,7 @@
 #include <memory>
 
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "xfa/fxbarcode/BC_Writer.h"
 #include "xfa/fxbarcode/common/BC_CommonBitMatrix.h"
 
diff --git a/xfa/fxfa/app/xfa_ffwidget.cpp b/xfa/fxfa/app/xfa_ffwidget.cpp
index 4fac623..6cea803 100644
--- a/xfa/fxfa/app/xfa_ffwidget.cpp
+++ b/xfa/fxfa/app/xfa_ffwidget.cpp
@@ -13,6 +13,7 @@
 #include "core/fxcodec/codec/include/ccodec_progressivedecoder.h"
 #include "core/fxcodec/include/fx_codec.h"
 #include "core/fxge/include/cfx_gemodule.h"
+#include "core/fxge/include/cfx_pathdata.h"
 #include "xfa/fxfa/app/xfa_textlayout.h"
 #include "xfa/fxfa/include/fxfa_widget.h"
 #include "xfa/fxfa/include/cxfa_eventparam.h"
diff --git a/xfa/fxgraphics/cfx_path.cpp b/xfa/fxgraphics/cfx_path.cpp
index fe956d3..892a339 100644
--- a/xfa/fxgraphics/cfx_path.cpp
+++ b/xfa/fxgraphics/cfx_path.cpp
@@ -6,6 +6,7 @@
 
 #include "xfa/fxgraphics/cfx_path.h"
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "xfa/fxgraphics/cfx_path_generator.h"
 
 CFX_Path::CFX_Path() {
diff --git a/xfa/fxgraphics/cfx_path_generator.cpp b/xfa/fxgraphics/cfx_path_generator.cpp
index 984e2e9..f2dc182 100644
--- a/xfa/fxgraphics/cfx_path_generator.cpp
+++ b/xfa/fxgraphics/cfx_path_generator.cpp
@@ -6,6 +6,8 @@
 
 #include "xfa/fxgraphics/cfx_path_generator.h"
 
+#include "core/fxge/include/cfx_pathdata.h"
+
 CFX_PathGenerator::CFX_PathGenerator() : m_pPathData(nullptr) {}
 
 void CFX_PathGenerator::Create() {
diff --git a/xfa/fxgraphics/cfx_path_generator.h b/xfa/fxgraphics/cfx_path_generator.h
index 02aa423..186178e 100644
--- a/xfa/fxgraphics/cfx_path_generator.h
+++ b/xfa/fxgraphics/cfx_path_generator.h
@@ -7,6 +7,7 @@
 #ifndef XFA_FXGRAPHICS_CFX_PATH_GENERATOR_H_
 #define XFA_FXGRAPHICS_CFX_PATH_GENERATOR_H_
 
+#include "core/fxge/include/cfx_pathdata.h"
 #include "core/fxge/include/fx_ge.h"
 
 class CFX_PathGenerator {