Change parameter type for more SetClip_PathFill() methods.

To avoid bitwise operations, use a struct CFX_FillRenderOptions
|fill_options| as the input of fill rendering options instead of
the integer parameter |fill_mode| for
RenderDeviceDriverIface::SetClip_PathFill() and
CFX_RenderDevice::SetClip_PathFill().

Bug: pdfium:1531
Change-Id: If30e18b3a0c0bae3459d424d89989a6e33a3ef6c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/71270
Commit-Queue: Hui Yingst <nigi@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index 09474b4..70ff9e8 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -12,6 +12,7 @@
 #include "build/build_config.h"
 #include "core/fxge/cfx_cliprgn.h"
 #include "core/fxge/cfx_defaultrenderdevice.h"
+#include "core/fxge/cfx_fillrenderoptions.h"
 #include "core/fxge/cfx_graphstatedata.h"
 #include "core/fxge/cfx_pathdata.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
@@ -1245,9 +1246,11 @@
   m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, pThisLayer);
 }
 
-bool CFX_AggDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData,
-                                           const CFX_Matrix* pObject2Device,
-                                           int fill_mode) {
+bool CFX_AggDeviceDriver::SetClip_PathFill(
+    const CFX_PathData* pPathData,
+    const CFX_Matrix* pObject2Device,
+    const CFX_FillRenderOptions& fill_options) {
+  int fill_mode = GetIntegerFlagsFromFillOptions(fill_options);
   ASSERT(IsAlternateOrWindingFillMode(fill_mode));
   ASSERT(GetAlternateOrWindingFillMode(fill_mode) !=
          kAlternateOrWindingFillModeMask);
diff --git a/core/fxge/agg/fx_agg_driver.h b/core/fxge/agg/fx_agg_driver.h
index 0578421..c29342b 100644
--- a/core/fxge/agg/fx_agg_driver.h
+++ b/core/fxge/agg/fx_agg_driver.h
@@ -20,6 +20,7 @@
 class CFX_GraphStateData;
 class CFX_Matrix;
 class CFX_PathData;
+struct CFX_FillRenderOptions;
 
 class CAgg_PathData {
  public:
@@ -49,7 +50,7 @@
   void RestoreState(bool bKeepSaved) override;
   bool SetClip_PathFill(const CFX_PathData* pPathData,
                         const CFX_Matrix* pObject2Device,
-                        int fill_mode) override;
+                        const CFX_FillRenderOptions& fill_options) override;
   bool SetClip_PathStroke(const CFX_PathData* pPathData,
                           const CFX_Matrix* pObject2Device,
                           const CFX_GraphStateData* pGraphState) override;
diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp
index 80f70bb..724fb8f 100644
--- a/core/fxge/cfx_renderdevice.cpp
+++ b/core/fxge/cfx_renderdevice.cpp
@@ -472,9 +472,8 @@
     const CFX_PathData* pPathData,
     const CFX_Matrix* pObject2Device,
     const CFX_FillRenderOptions& fill_options) {
-  if (!m_pDeviceDriver->SetClip_PathFill(
-          pPathData, pObject2Device,
-          GetIntegerFlagsFromFillOptions(fill_options))) {
+  if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device,
+                                         fill_options)) {
     return false;
   }
   UpdateClipBox();
diff --git a/core/fxge/renderdevicedriver_iface.h b/core/fxge/renderdevicedriver_iface.h
index fcca520..c6357b0 100644
--- a/core/fxge/renderdevicedriver_iface.h
+++ b/core/fxge/renderdevicedriver_iface.h
@@ -24,6 +24,7 @@
 class CPDF_ShadingPattern;
 class PauseIndicatorIface;
 class TextCharPos;
+struct CFX_FillRenderOptions;
 struct FX_RECT;
 
 enum class DeviceType : bool {
@@ -46,7 +47,7 @@
   virtual void SetBaseClip(const FX_RECT& rect);
   virtual bool SetClip_PathFill(const CFX_PathData* pPathData,
                                 const CFX_Matrix* pObject2Device,
-                                int fill_mode) = 0;
+                                const CFX_FillRenderOptions& fill_options) = 0;
   virtual bool SetClip_PathStroke(const CFX_PathData* pPathData,
                                   const CFX_Matrix* pObject2Device,
                                   const CFX_GraphStateData* pGraphState);
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 3dbb494..9008917 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -23,6 +23,7 @@
 #include "core/fxcrt/fx_memory_wrappers.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxge/cfx_defaultrenderdevice.h"
+#include "core/fxge/cfx_fillrenderoptions.h"
 #include "core/fxge/cfx_font.h"
 #include "core/fxge/cfx_graphstatedata.h"
 #include "core/fxge/cfx_pathdata.h"
@@ -1958,10 +1959,10 @@
 bool CFX_SkiaDeviceDriver::SetClip_PathFill(
     const CFX_PathData* pPathData,     // path info
     const CFX_Matrix* pObject2Device,  // flips object's y-axis
-    int fill_mode                      // fill mode, WINDING or ALTERNATE
-    ) {
+    const CFX_FillRenderOptions& fill_options) {
   CFX_Matrix identity;
   const CFX_Matrix* deviceMatrix = pObject2Device ? pObject2Device : &identity;
+  const int fill_mode = GetIntegerFlagsFromFillOptions(fill_options);
   bool cached = m_pCache->SetClipFill(pPathData, deviceMatrix, fill_mode);
 
 #ifdef _SKIA_SUPPORT_PATHS_
diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h
index d423f6f..634cb7a 100644
--- a/core/fxge/skia/fx_skia_device.h
+++ b/core/fxge/skia/fx_skia_device.h
@@ -21,6 +21,7 @@
 class SkPictureRecorder;
 class SkiaState;
 class TextCharPos;
+struct CFX_FillRenderOptions;
 struct SkIRect;
 
 class CFX_SkiaDeviceDriver final : public RenderDeviceDriverIface {
@@ -45,9 +46,10 @@
 
   /** Set clipping path using filled region */
   bool SetClip_PathFill(
-      const CFX_PathData* pPathData,     // path info
-      const CFX_Matrix* pObject2Device,  // optional transformation
-      int fill_mode) override;           // fill mode, WINDING or ALTERNATE
+      const CFX_PathData* pPathData,              // path info
+      const CFX_Matrix* pObject2Device,           // optional transformation
+      const CFX_FillRenderOptions& fill_options)  // fill options
+      override;
 
   /** Set clipping path using stroked region */
   bool SetClip_PathStroke(
diff --git a/core/fxge/skia/fx_skia_device_embeddertest.cpp b/core/fxge/skia/fx_skia_device_embeddertest.cpp
index 6631e4d..128ca69 100644
--- a/core/fxge/skia/fx_skia_device_embeddertest.cpp
+++ b/core/fxge/skia/fx_skia_device_embeddertest.cpp
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "core/fxge/cfx_defaultrenderdevice.h"
+#include "core/fxge/cfx_fillrenderoptions.h"
 #include "core/fxge/cfx_font.h"
 #include "core/fxge/cfx_graphstatedata.h"
 #include "core/fxge/cfx_pathdata.h"
@@ -60,7 +61,7 @@
   if (state.m_save == State::Save::kYes)
     driver->SaveState();
   if (state.m_clip != State::Clip::kNo)
-    driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
+    driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
   if (state.m_graphic == State::Graphic::kPath) {
     driver->DrawPath(&path1, &matrix, &graphState, 0xFF112233, 0,
                      FXFILL_WINDING, BlendMode::kNormal);
@@ -79,11 +80,11 @@
       fontSize = 2;
   }
   if (state.m_clip == State::Clip::kSame)
-    driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
+    driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
   else if (state.m_clip == State::Clip::kDifferentPath)
-    driver->SetClip_PathFill(&clipPath2, &clipMatrix, 0);
+    driver->SetClip_PathFill(&clipPath2, &clipMatrix, CFX_FillRenderOptions());
   else if (state.m_clip == State::Clip::kDifferentMatrix)
-    driver->SetClip_PathFill(&clipPath, &clipMatrix2, 0);
+    driver->SetClip_PathFill(&clipPath, &clipMatrix2, CFX_FillRenderOptions());
   if (state.m_graphic == State::Graphic::kPath) {
     driver->DrawPath(&path2, &matrix2, &graphState, 0xFF112233, 0,
                      FXFILL_WINDING, BlendMode::kNormal);
@@ -101,18 +102,18 @@
   clipPath.AppendRect(1, 0, 3, 1);
   CFX_Matrix clipMatrix;
   driver->SaveState();
-  driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
+  driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
   driver->RestoreState(true);
   driver->SaveState();
-  driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
+  driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
   driver->RestoreState(false);
   driver->RestoreState(false);
 
   driver->SaveState();
   driver->SaveState();
-  driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
+  driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
   driver->RestoreState(true);
-  driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
+  driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
   driver->RestoreState(false);
   driver->RestoreState(false);
 }
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index a445174..bc67e62 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -13,6 +13,7 @@
 #include <utility>
 
 #include "core/fxcrt/maybe_owned.h"
+#include "core/fxge/cfx_fillrenderoptions.h"
 #include "core/fxge/cfx_fontcache.h"
 #include "core/fxge/cfx_gemodule.h"
 #include "core/fxge/cfx_glyphcache.h"
@@ -151,9 +152,10 @@
   WriteToStream(&buf);
 }
 
-void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData,
-                                      const CFX_Matrix* pObject2Device,
-                                      int fill_mode) {
+void CFX_PSRenderer::SetClip_PathFill(
+    const CFX_PathData* pPathData,
+    const CFX_Matrix* pObject2Device,
+    const CFX_FillRenderOptions& fill_options) {
   StartRendering();
   OutputPath(pPathData, pObject2Device);
   CFX_FloatRect rect = pPathData->GetBoundingBox();
@@ -166,7 +168,7 @@
   m_ClipBox.bottom = static_cast<int>(rect.bottom);
 
   m_pStream->WriteString("W");
-  if ((fill_mode & 3) != FXFILL_WINDING)
+  if (fill_options.fill_type != CFX_FillRenderOptions::FillType::kWinding)
     m_pStream->WriteString("*");
   m_pStream->WriteString(" n\n");
 }
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h
index 50e98a4..2b179c0 100644
--- a/core/fxge/win32/cfx_psrenderer.h
+++ b/core/fxge/win32/cfx_psrenderer.h
@@ -23,6 +23,7 @@
 class CFX_PathData;
 class CPSFont;
 class TextCharPos;
+struct CFX_FillRenderOptions;
 struct FXDIB_ResampleOptions;
 
 struct EncoderIface {
@@ -64,7 +65,7 @@
   void RestoreState(bool bKeepSaved);
   void SetClip_PathFill(const CFX_PathData* pPathData,
                         const CFX_Matrix* pObject2Device,
-                        int fill_mode);
+                        const CFX_FillRenderOptions& fill_options);
   void SetClip_PathStroke(const CFX_PathData* pPathData,
                           const CFX_Matrix* pObject2Device,
                           const CFX_GraphStateData* pGraphState);
diff --git a/core/fxge/win32/fx_win32_device.cpp b/core/fxge/win32/fx_win32_device.cpp
index 4aca5c4..109d8b6 100644
--- a/core/fxge/win32/fx_win32_device.cpp
+++ b/core/fxge/win32/fx_win32_device.cpp
@@ -13,6 +13,7 @@
 #include "core/fxcrt/fx_codepage.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/maybe_owned.h"
+#include "core/fxge/cfx_fillrenderoptions.h"
 #include "core/fxge/cfx_folderfontinfo.h"
 #include "core/fxge/cfx_fontmgr.h"
 #include "core/fxge/cfx_gemodule.h"
@@ -82,6 +83,18 @@
   return false;
 }
 
+constexpr int FillTypeToGdiFillType(CFX_FillRenderOptions::FillType fill_type) {
+  return static_cast<int>(fill_type);
+}
+
+static_assert(FillTypeToGdiFillType(
+                  CFX_FillRenderOptions::FillType::kEvenOdd) == ALTERNATE,
+              "CFX_FillRenderOptions::FillType::kEvenOdd value mismatch");
+
+static_assert(
+    FillTypeToGdiFillType(CFX_FillRenderOptions::FillType::kWinding) == WINDING,
+    "CFX_FillRenderOptions::FillType::kWinding value mismatch");
+
 HPEN CreateExtPen(const CFX_GraphStateData* pGraphState,
                   const CFX_Matrix* pMatrix,
                   uint32_t argb) {
@@ -1083,9 +1096,10 @@
   m_BaseClipBox = rect;
 }
 
-bool CGdiDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData,
-                                        const CFX_Matrix* pMatrix,
-                                        int fill_mode) {
+bool CGdiDeviceDriver::SetClip_PathFill(
+    const CFX_PathData* pPathData,
+    const CFX_Matrix* pMatrix,
+    const CFX_FillRenderOptions& fill_options) {
   if (pPathData->GetPoints().size() == 5) {
     Optional<CFX_FloatRect> maybe_rectf = pPathData->GetRect(pMatrix);
     if (maybe_rectf.has_value()) {
@@ -1099,7 +1113,7 @@
     }
   }
   SetPathToDC(m_hDC, pPathData, pMatrix);
-  SetPolyFillMode(m_hDC, fill_mode & 3);
+  SetPolyFillMode(m_hDC, FillTypeToGdiFillType(fill_options.fill_type));
   SelectClipPath(m_hDC, RGN_AND);
   return true;
 }
diff --git a/core/fxge/win32/fx_win32_print.cpp b/core/fxge/win32/fx_win32_print.cpp
index dfa75a9..408d258 100644
--- a/core/fxge/win32/fx_win32_print.cpp
+++ b/core/fxge/win32/fx_win32_print.cpp
@@ -12,6 +12,7 @@
 
 #include "core/fxcrt/fx_memory_wrappers.h"
 #include "core/fxcrt/fx_system.h"
+#include "core/fxge/cfx_fillrenderoptions.h"
 #include "core/fxge/cfx_font.h"
 #include "core/fxge/cfx_windowsrenderdevice.h"
 #include "core/fxge/dib/cfx_dibextractor.h"
@@ -377,7 +378,8 @@
                           static_cast<float>(pRect->right),
                           static_cast<float>(pRect->top));
         }
-        m_PSRenderer.SetClip_PathFill(&path, nullptr, FXFILL_WINDING);
+        m_PSRenderer.SetClip_PathFill(&path, nullptr,
+                                      CFX_FillRenderOptions::WindingOptions());
       }
     }
   }
@@ -428,10 +430,11 @@
   m_PSRenderer.RestoreState(bKeepSaved);
 }
 
-bool CPSPrinterDriver::SetClip_PathFill(const CFX_PathData* pPathData,
-                                        const CFX_Matrix* pObject2Device,
-                                        int fill_mode) {
-  m_PSRenderer.SetClip_PathFill(pPathData, pObject2Device, fill_mode);
+bool CPSPrinterDriver::SetClip_PathFill(
+    const CFX_PathData* pPathData,
+    const CFX_Matrix* pObject2Device,
+    const CFX_FillRenderOptions& fill_options) {
+  m_PSRenderer.SetClip_PathFill(pPathData, pObject2Device, fill_options);
   return true;
 }
 
@@ -553,9 +556,10 @@
   }
 }
 
-bool CTextOnlyPrinterDriver::SetClip_PathFill(const CFX_PathData* pPathData,
-                                              const CFX_Matrix* pObject2Device,
-                                              int fill_mode) {
+bool CTextOnlyPrinterDriver::SetClip_PathFill(
+    const CFX_PathData* pPathData,
+    const CFX_Matrix* pObject2Device,
+    const CFX_FillRenderOptions& fill_options) {
   return true;
 }
 
diff --git a/core/fxge/win32/win32_int.h b/core/fxge/win32/win32_int.h
index 7f299ef..f81457b 100644
--- a/core/fxge/win32/win32_int.h
+++ b/core/fxge/win32/win32_int.h
@@ -23,6 +23,7 @@
 
 class CFX_ImageRenderer;
 class TextCharPos;
+struct CFX_FillRenderOptions;
 struct WINDIB_Open_Args_;
 
 RetainPtr<CFX_DIBitmap> FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi,
@@ -85,7 +86,7 @@
   void SetBaseClip(const FX_RECT& rect) override;
   bool SetClip_PathFill(const CFX_PathData* pPathData,
                         const CFX_Matrix* pObject2Device,
-                        int fill_mode) override;
+                        const CFX_FillRenderOptions& fill_options) override;
   bool SetClip_PathStroke(const CFX_PathData* pPathData,
                           const CFX_Matrix* pObject2Device,
                           const CFX_GraphStateData* pGraphState) override;
@@ -236,7 +237,7 @@
   void RestoreState(bool bKeepSaved) override;
   bool SetClip_PathFill(const CFX_PathData* pPathData,
                         const CFX_Matrix* pObject2Device,
-                        int fill_mode) override;
+                        const CFX_FillRenderOptions& fill_options) override;
   bool SetClip_PathStroke(const CFX_PathData* pPathData,
                           const CFX_Matrix* pObject2Device,
                           const CFX_GraphStateData* pGraphState) override;
@@ -300,7 +301,7 @@
   void RestoreState(bool bKeepSaved) override {}
   bool SetClip_PathFill(const CFX_PathData* pPathData,
                         const CFX_Matrix* pObject2Device,
-                        int fill_mode) override;
+                        const CFX_FillRenderOptions& fill_options) override;
   bool SetClip_PathStroke(const CFX_PathData* pPathData,
                           const CFX_Matrix* pObject2Device,
                           const CFX_GraphStateData* pGraphState) override;