From 5883300439287ab46559231ce8aed11e92bbc97c Mon Sep 17 00:00:00 2001
From: Lei Zhang <thestig@chromium.org>
Date: Fri, 26 Oct 2018 22:52:48 +0000
Subject: Replace int flags with struct FXDIB_ResampleOptions.

Using bit values in an int may not be reliable, since different parts of
the code can interpret the bits differently. e.g. FXDIB_DOWNSAMPLE and
RENDER_FORCE_DOWNSAMPLE are defined in different places, but can be used
interchangeably because they just happen to have the same value. It
works but is rather fragile.

Instead, use a struct of bools to explicitly define what different bits
mean. Remove FXDIB_DOWNSAMPLE and friends.

Change-Id: I9cf0c8f94d1ed27edf8dba22b0ab0ee67f2722cc
Reviewed-on: https://pdfium-review.googlesource.com/c/44650
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
---
 core/fxge/dib/cfx_dibbase.cpp             | 14 ++++---
 core/fxge/dib/cfx_dibbase.h               |  2 +-
 core/fxge/dib/cfx_dibitmap.cpp            | 10 +++--
 core/fxge/dib/cfx_imagerenderer.cpp       |  9 ++---
 core/fxge/dib/cfx_imagerenderer.h         |  2 +-
 core/fxge/dib/cfx_imagestretcher.cpp      | 11 +++---
 core/fxge/dib/cfx_imagestretcher.h        |  4 +-
 core/fxge/dib/cfx_imagetransformer.cpp    | 21 ++++++++---
 core/fxge/dib/cfx_imagetransformer.h      | 10 ++---
 core/fxge/dib/cstretchengine.cpp          | 62 ++++++++++++++++---------------
 core/fxge/dib/cstretchengine.h            |  6 +--
 core/fxge/dib/cstretchengine_unittest.cpp |  9 ++++-
 core/fxge/dib/fx_dib_main.cpp             | 23 ++++++++++++
 13 files changed, 112 insertions(+), 71 deletions(-)

(limited to 'core/fxge/dib')

diff --git a/core/fxge/dib/cfx_dibbase.cpp b/core/fxge/dib/cfx_dibbase.cpp
index 7fc9bef9cb..1dcbcf9e17 100644
--- a/core/fxge/dib/cfx_dibbase.cpp
+++ b/core/fxge/dib/cfx_dibbase.cpp
@@ -1171,17 +1171,19 @@ RetainPtr<CFX_DIBitmap> CFX_DIBBase::TransformTo(const CFX_Matrix& mtDest,
                                                  int* result_left,
                                                  int* result_top) {
   RetainPtr<CFX_DIBBase> holder(this);
-  CFX_ImageTransformer transformer(holder, mtDest, 0, nullptr);
+  CFX_ImageTransformer transformer(holder, mtDest, FXDIB_ResampleOptions(),
+                                   nullptr);
   transformer.Continue(nullptr);
   *result_left = transformer.result().left;
   *result_top = transformer.result().top;
   return transformer.DetachBitmap();
 }
 
-RetainPtr<CFX_DIBitmap> CFX_DIBBase::StretchTo(int dest_width,
-                                               int dest_height,
-                                               uint32_t flags,
-                                               const FX_RECT* pClip) {
+RetainPtr<CFX_DIBitmap> CFX_DIBBase::StretchTo(
+    int dest_width,
+    int dest_height,
+    const FXDIB_ResampleOptions& options,
+    const FX_RECT* pClip) {
   RetainPtr<CFX_DIBBase> holder(this);
   FX_RECT clip_rect(0, 0, abs(dest_width), abs(dest_height));
   if (pClip)
@@ -1195,7 +1197,7 @@ RetainPtr<CFX_DIBitmap> CFX_DIBBase::StretchTo(int dest_width,
 
   CFX_BitmapStorer storer;
   CFX_ImageStretcher stretcher(&storer, holder, dest_width, dest_height,
-                               clip_rect, flags);
+                               clip_rect, options);
   if (stretcher.Start())
     stretcher.Continue(nullptr);
 
diff --git a/core/fxge/dib/cfx_dibbase.h b/core/fxge/dib/cfx_dibbase.h
index 81b0691563..23d65a3cda 100644
--- a/core/fxge/dib/cfx_dibbase.h
+++ b/core/fxge/dib/cfx_dibbase.h
@@ -80,7 +80,7 @@ class CFX_DIBBase : public Retainable {
   RetainPtr<CFX_DIBitmap> CloneConvert(FXDIB_Format format);
   RetainPtr<CFX_DIBitmap> StretchTo(int dest_width,
                                     int dest_height,
-                                    uint32_t flags,
+                                    const FXDIB_ResampleOptions& options,
                                     const FX_RECT* pClip);
   RetainPtr<CFX_DIBitmap> TransformTo(const CFX_Matrix& mtDest,
                                       int* left,
diff --git a/core/fxge/dib/cfx_dibitmap.cpp b/core/fxge/dib/cfx_dibitmap.cpp
index dcf5fdc7ab..011270494c 100644
--- a/core/fxge/dib/cfx_dibitmap.cpp
+++ b/core/fxge/dib/cfx_dibitmap.cpp
@@ -329,7 +329,8 @@ bool CFX_DIBitmap::LoadChannelFromAlpha(
     if (pSrcClone->GetWidth() != m_Width ||
         pSrcClone->GetHeight() != m_Height) {
       if (pAlphaMask) {
-        pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height, 0, nullptr);
+        pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height,
+                                           FXDIB_ResampleOptions(), nullptr);
         if (!pAlphaMask)
           return false;
       }
@@ -338,8 +339,8 @@ bool CFX_DIBitmap::LoadChannelFromAlpha(
     srcOffset = 0;
   } else if (pSrcClone->GetWidth() != m_Width ||
              pSrcClone->GetHeight() != m_Height) {
-    RetainPtr<CFX_DIBitmap> pSrcMatched =
-        pSrcClone->StretchTo(m_Width, m_Height, 0, nullptr);
+    RetainPtr<CFX_DIBitmap> pSrcMatched = pSrcClone->StretchTo(
+        m_Width, m_Height, FXDIB_ResampleOptions(), nullptr);
     if (!pSrcMatched)
       return false;
 
@@ -437,7 +438,8 @@ bool CFX_DIBitmap::MultiplyAlpha(const RetainPtr<CFX_DIBBase>& pSrcBitmap) {
   RetainPtr<CFX_DIBitmap> pSrcClone = pSrcBitmap.As<CFX_DIBitmap>();
   if (pSrcBitmap->GetWidth() != m_Width ||
       pSrcBitmap->GetHeight() != m_Height) {
-    pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height, 0, nullptr);
+    pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height,
+                                      FXDIB_ResampleOptions(), nullptr);
     if (!pSrcClone)
       return false;
   }
diff --git a/core/fxge/dib/cfx_imagerenderer.cpp b/core/fxge/dib/cfx_imagerenderer.cpp
index 6eadb05997..408bec1a09 100644
--- a/core/fxge/dib/cfx_imagerenderer.cpp
+++ b/core/fxge/dib/cfx_imagerenderer.cpp
@@ -20,7 +20,7 @@ CFX_ImageRenderer::CFX_ImageRenderer(const RetainPtr<CFX_DIBitmap>& pDevice,
                                      int bitmap_alpha,
                                      uint32_t mask_color,
                                      const CFX_Matrix& matrix,
-                                     uint32_t dib_flags,
+                                     const FXDIB_ResampleOptions& options,
                                      bool bRgbByteOrder)
     : m_pDevice(pDevice),
       m_pClipRgn(pClipRgn),
@@ -50,15 +50,14 @@ CFX_ImageRenderer::CFX_ImageRenderer(const RetainPtr<CFX_DIBitmap>& pDevice,
                          true, m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder,
                          0, BlendMode::kNormal);
       m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
-          &m_Composer, pSource, dest_height, dest_width, bitmap_clip,
-          dib_flags);
+          &m_Composer, pSource, dest_height, dest_width, bitmap_clip, options);
       if (m_Stretcher->Start())
         m_Status = 1;
       return;
     }
     m_Status = 2;
     m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>(
-        pSource, m_Matrix, dib_flags, &m_ClipBox);
+        pSource, m_Matrix, options, &m_ClipBox);
     return;
   }
 
@@ -80,7 +79,7 @@ CFX_ImageRenderer::CFX_ImageRenderer(const RetainPtr<CFX_DIBitmap>& pDevice,
                      BlendMode::kNormal);
   m_Status = 1;
   m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
-      &m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags);
+      &m_Composer, pSource, dest_width, dest_height, bitmap_clip, options);
   m_Stretcher->Start();
 }
 
diff --git a/core/fxge/dib/cfx_imagerenderer.h b/core/fxge/dib/cfx_imagerenderer.h
index 01eec3a947..d97c01843f 100644
--- a/core/fxge/dib/cfx_imagerenderer.h
+++ b/core/fxge/dib/cfx_imagerenderer.h
@@ -28,7 +28,7 @@ class CFX_ImageRenderer {
                     int bitmap_alpha,
                     uint32_t mask_color,
                     const CFX_Matrix& matrix,
-                    uint32_t dib_flags,
+                    const FXDIB_ResampleOptions& options,
                     bool bRgbByteOrder);
   ~CFX_ImageRenderer();
 
diff --git a/core/fxge/dib/cfx_imagestretcher.cpp b/core/fxge/dib/cfx_imagestretcher.cpp
index 763c1db5d2..54d14f7d9d 100644
--- a/core/fxge/dib/cfx_imagestretcher.cpp
+++ b/core/fxge/dib/cfx_imagestretcher.cpp
@@ -48,10 +48,10 @@ CFX_ImageStretcher::CFX_ImageStretcher(ScanlineComposerIface* pDest,
                                        int dest_width,
                                        int dest_height,
                                        const FX_RECT& bitmap_rect,
-                                       uint32_t flags)
+                                       const FXDIB_ResampleOptions& options)
     : m_pDest(pDest),
       m_pSource(pSource),
-      m_Flags(flags),
+      m_ResampleOptions(options),
       m_bFlipX(false),
       m_bFlipY(false),
       m_DestWidth(dest_width),
@@ -119,14 +119,13 @@ bool CFX_ImageStretcher::Start() {
     return false;
   }
 
-  if (m_Flags & FXDIB_DOWNSAMPLE)
+  if (m_ResampleOptions.bInterpolateDownsample)
     return StartQuickStretch();
-
   return StartStretch();
 }
 
 bool CFX_ImageStretcher::Continue(PauseIndicatorIface* pPause) {
-  if (m_Flags & FXDIB_DOWNSAMPLE)
+  if (m_ResampleOptions.bInterpolateDownsample)
     return ContinueQuickStretch(pPause);
   return ContinueStretch(pPause);
 }
@@ -138,7 +137,7 @@ RetainPtr<CFX_DIBBase> CFX_ImageStretcher::source() {
 bool CFX_ImageStretcher::StartStretch() {
   m_pStretchEngine = pdfium::MakeUnique<CStretchEngine>(
       m_pDest.Get(), m_DestFormat, m_DestWidth, m_DestHeight, m_ClipRect,
-      m_pSource, m_Flags);
+      m_pSource, m_ResampleOptions);
   m_pStretchEngine->StartStretchHorz();
   if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) {
     m_pStretchEngine->Continue(nullptr);
diff --git a/core/fxge/dib/cfx_imagestretcher.h b/core/fxge/dib/cfx_imagestretcher.h
index 9f4e44b0d0..45544cbfbc 100644
--- a/core/fxge/dib/cfx_imagestretcher.h
+++ b/core/fxge/dib/cfx_imagestretcher.h
@@ -27,7 +27,7 @@ class CFX_ImageStretcher {
                      int dest_width,
                      int dest_height,
                      const FX_RECT& bitmap_rect,
-                     uint32_t flags);
+                     const FXDIB_ResampleOptions& options);
   ~CFX_ImageStretcher();
 
   bool Start();
@@ -46,7 +46,7 @@ class CFX_ImageStretcher {
   std::unique_ptr<CStretchEngine> m_pStretchEngine;
   std::unique_ptr<uint8_t, FxFreeDeleter> m_pScanline;
   std::unique_ptr<uint8_t, FxFreeDeleter> m_pMaskScanline;
-  const uint32_t m_Flags;
+  const FXDIB_ResampleOptions m_ResampleOptions;
   bool m_bFlipX;
   bool m_bFlipY;
   int m_DestWidth;
diff --git a/core/fxge/dib/cfx_imagetransformer.cpp b/core/fxge/dib/cfx_imagetransformer.cpp
index 29d22f4f77..9bbbaa644c 100644
--- a/core/fxge/dib/cfx_imagetransformer.cpp
+++ b/core/fxge/dib/cfx_imagetransformer.cpp
@@ -204,9 +204,9 @@ class CFX_BilinearMatrix final : public CPDF_FixedMatrix {
 
 CFX_ImageTransformer::CFX_ImageTransformer(const RetainPtr<CFX_DIBBase>& pSrc,
                                            const CFX_Matrix& matrix,
-                                           uint32_t flags,
+                                           const FXDIB_ResampleOptions& options,
                                            const FX_RECT* pClip)
-    : m_pSrc(pSrc), m_matrix(matrix), m_Flags(flags) {
+    : m_pSrc(pSrc), m_matrix(matrix), m_ResampleOptions(options) {
   FX_RECT result_rect = m_matrix.GetUnitRect().GetClosestRect();
   FX_RECT result_clip = result_rect;
   if (pClip)
@@ -225,7 +225,8 @@ CFX_ImageTransformer::CFX_ImageTransformer(const RetainPtr<CFX_DIBBase>& pSrc,
     result_clip = FXDIB_SwapClipBox(result_clip, dest_width, dest_height,
                                     m_matrix.c > 0, m_matrix.b < 0);
     m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
-        &m_Storer, m_pSrc, dest_height, dest_width, result_clip, m_Flags);
+        &m_Storer, m_pSrc, dest_height, dest_width, result_clip,
+        m_ResampleOptions);
     m_Stretcher->Start();
     m_Status = 1;
     return;
@@ -237,7 +238,8 @@ CFX_ImageTransformer::CFX_ImageTransformer(const RetainPtr<CFX_DIBBase>& pSrc,
                                                       : -floor(m_matrix.d));
     result_clip.Offset(-result_rect.left, -result_rect.top);
     m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
-        &m_Storer, m_pSrc, dest_width, dest_height, result_clip, m_Flags);
+        &m_Storer, m_pSrc, dest_width, dest_height, result_clip,
+        m_ResampleOptions);
     m_Stretcher->Start();
     m_Status = 2;
     return;
@@ -257,7 +259,8 @@ CFX_ImageTransformer::CFX_ImageTransformer(const RetainPtr<CFX_DIBBase>& pSrc,
       m_dest2stretch.TransformRect(CFX_FloatRect(result_clip)).GetOuterRect();
   m_StretchClip.Intersect(0, 0, stretch_width, stretch_height);
   m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
-      &m_Storer, m_pSrc, stretch_width, stretch_height, m_StretchClip, m_Flags);
+      &m_Storer, m_pSrc, stretch_width, stretch_height, m_StretchClip,
+      m_ResampleOptions);
   m_Stretcher->Start();
   m_Status = 3;
 }
@@ -463,6 +466,14 @@ void CFX_ImageTransformer::CalcColor(const CalcData& cdata,
   }
 }
 
+bool CFX_ImageTransformer::IsBilinear() const {
+  return !m_ResampleOptions.bInterpolateDownsample && !IsBiCubic();
+}
+
+bool CFX_ImageTransformer::IsBiCubic() const {
+  return m_ResampleOptions.bInterpolateBicubic;
+}
+
 void CFX_ImageTransformer::AdjustCoords(int* col, int* row) const {
   int& src_col = *col;
   int& src_row = *row;
diff --git a/core/fxge/dib/cfx_imagetransformer.h b/core/fxge/dib/cfx_imagetransformer.h
index 052df941d4..b0b854c333 100644
--- a/core/fxge/dib/cfx_imagetransformer.h
+++ b/core/fxge/dib/cfx_imagetransformer.h
@@ -23,7 +23,7 @@ class CFX_ImageTransformer {
  public:
   CFX_ImageTransformer(const RetainPtr<CFX_DIBBase>& pSrc,
                        const CFX_Matrix& matrix,
-                       uint32_t flags,
+                       const FXDIB_ResampleOptions& options,
                        const FX_RECT* pClip);
   ~CFX_ImageTransformer();
 
@@ -73,10 +73,8 @@ class CFX_ImageTransformer {
   void CalcMono(const CalcData& cdata, FXDIB_Format format);
   void CalcColor(const CalcData& cdata, FXDIB_Format format, int Bpp);
 
-  bool IsBilinear() const {
-    return !(m_Flags & FXDIB_DOWNSAMPLE) && !IsBiCubic();
-  }
-  bool IsBiCubic() const { return !!(m_Flags & FXDIB_BICUBIC_INTERPOL); }
+  bool IsBilinear() const;
+  bool IsBiCubic() const;
 
   int stretch_width() const { return m_StretchClip.Width(); }
   int stretch_height() const { return m_StretchClip.Height(); }
@@ -106,7 +104,7 @@ class CFX_ImageTransformer {
   CFX_Matrix m_dest2stretch;
   std::unique_ptr<CFX_ImageStretcher> m_Stretcher;
   CFX_BitmapStorer m_Storer;
-  const uint32_t m_Flags;
+  const FXDIB_ResampleOptions m_ResampleOptions;
   int m_Status = 0;
 };
 
diff --git a/core/fxge/dib/cstretchengine.cpp b/core/fxge/dib/cstretchengine.cpp
index 969ab03667..7a582b537f 100644
--- a/core/fxge/dib/cstretchengine.cpp
+++ b/core/fxge/dib/cstretchengine.cpp
@@ -43,12 +43,12 @@ bool CStretchEngine::CWeightTable::Calc(int dest_len,
                                         int src_len,
                                         int src_min,
                                         int src_max,
-                                        int flags) {
+                                        const FXDIB_ResampleOptions& options) {
   m_WeightTables.clear();
   m_dwWeightTablesSize = 0;
   const double scale = static_cast<float>(src_len) / dest_len;
   const double base = dest_len < 0 ? src_len : 0;
-  const int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1;
+  const int ext_size = options.bInterpolateBicubic ? 3 : 1;
   m_ItemSize =
       sizeof(int) * 2 +
       static_cast<int>(sizeof(int) *
@@ -60,11 +60,11 @@ bool CStretchEngine::CWeightTable::Calc(int dest_len,
 
   m_dwWeightTablesSize = (dest_max - dest_min) * m_ItemSize + 4;
   m_WeightTables.resize(m_dwWeightTablesSize);
-  if ((flags & FXDIB_NOSMOOTH) != 0 || fabs(static_cast<float>(scale)) < 1.0f) {
+  if (options.bNoSmoothing || fabs(static_cast<float>(scale)) < 1.0f) {
     for (int dest_pixel = dest_min; dest_pixel < dest_max; ++dest_pixel) {
       PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
       double src_pos = dest_pixel * scale + scale / 2 + base;
-      if (flags & FXDIB_INTERPOL) {
+      if (options.bInterpolateBilinear) {
         pixel_weights.m_SrcStart =
             static_cast<int>(floor(static_cast<float>(src_pos) - 1.0f / 2));
         pixel_weights.m_SrcEnd =
@@ -80,7 +80,7 @@ bool CStretchEngine::CWeightTable::Calc(int dest_len,
                           65536);
           pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1];
         }
-      } else if (flags & FXDIB_BICUBIC_INTERPOL) {
+      } else if (options.bInterpolateBicubic) {
         pixel_weights.m_SrcStart =
             static_cast<int>(floor(static_cast<float>(src_pos) - 1.0f / 2));
         pixel_weights.m_SrcEnd =
@@ -229,7 +229,7 @@ CStretchEngine::CStretchEngine(ScanlineComposerIface* pDestBitmap,
                                int dest_height,
                                const FX_RECT& clip_rect,
                                const RetainPtr<CFX_DIBBase>& pSrcBitmap,
-                               int flags)
+                               const FXDIB_ResampleOptions& options)
     : m_DestFormat(dest_format),
       m_DestBpp(GetBppFromFormat(dest_format)),
       m_SrcBpp(GetBppFromFormat(pSrcBitmap->GetFormat())),
@@ -256,18 +256,19 @@ CStretchEngine::CStretchEngine(ScanlineComposerIface* pDestBitmap,
     std::fill(m_DestScanline.begin(), m_DestScanline.end(), 255);
   m_InterPitch = GetPitchRoundUpTo4Bytes(m_DestClip.Width() * m_DestBpp);
   m_ExtraMaskPitch = GetPitchRoundUpTo4Bytes(m_DestClip.Width() * 8);
-  if ((flags & FXDIB_NOSMOOTH) == 0) {
-    bool bInterpol = flags & FXDIB_INTERPOL || flags & FXDIB_BICUBIC_INTERPOL;
+  if (options.bNoSmoothing) {
+    m_ResampleOptions.bNoSmoothing = true;
+    m_ResampleOptions.bInterpolateDownsample = options.bInterpolateDownsample;
+  } else {
+    bool bInterpol =
+        options.bInterpolateBilinear || options.bInterpolateBicubic;
     if (!bInterpol && abs(dest_width) != 0 &&
         abs(dest_height) / 8 < static_cast<long long>(m_SrcWidth) *
                                    m_SrcHeight / abs(dest_width)) {
-      flags = FXDIB_INTERPOL;
+      m_ResampleOptions.bInterpolateBilinear = true;
+    } else {
+      m_ResampleOptions = options;
     }
-    m_Flags = flags;
-  } else {
-    m_Flags = FXDIB_NOSMOOTH;
-    if (flags & FXDIB_DOWNSAMPLE)
-      m_Flags |= FXDIB_DOWNSAMPLE;
   }
   double scale_x = static_cast<float>(m_SrcWidth) / m_DestWidth;
   double scale_y = static_cast<float>(m_SrcHeight) / m_DestHeight;
@@ -336,9 +337,9 @@ bool CStretchEngine::StartStretchHorz() {
     m_ExtraAlphaBuf.resize(m_SrcClip.Height(), m_ExtraMaskPitch);
     m_DestMaskScanline.resize(m_ExtraMaskPitch);
   }
-  bool ret =
-      m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right,
-                         m_SrcWidth, m_SrcClip.left, m_SrcClip.right, m_Flags);
+  bool ret = m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right,
+                                m_SrcWidth, m_SrcClip.left, m_SrcClip.right,
+                                m_ResampleOptions);
   if (!ret)
     return false;
 
@@ -390,7 +391,7 @@ bool CStretchEngine::ContinueStretchHorz(PauseIndicatorIface* pPause) {
             if (src_scan[j / 8] & (1 << (7 - j % 8)))
               dest_a += pixel_weight * 255;
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL)
+          if (m_ResampleOptions.bInterpolateBicubic)
             dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue);
           *dest_scan++ = static_cast<uint8_t>(dest_a >> 16);
         }
@@ -408,7 +409,7 @@ bool CStretchEngine::ContinueStretchHorz(PauseIndicatorIface* pPause) {
             int pixel_weight = *pWeight;
             dest_a += pixel_weight * src_scan[j];
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL)
+          if (m_ResampleOptions.bInterpolateBicubic)
             dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue);
           *dest_scan++ = static_cast<uint8_t>(dest_a >> 16);
         }
@@ -429,7 +430,7 @@ bool CStretchEngine::ContinueStretchHorz(PauseIndicatorIface* pPause) {
             dest_r += pixel_weight * src_scan[j];
             dest_a += pixel_weight;
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+          if (m_ResampleOptions.bInterpolateBicubic) {
             dest_r = pdfium::clamp(dest_r, 0, kMaxDestValue);
             dest_a = pdfium::clamp(dest_a, 0, 65536);
           }
@@ -461,7 +462,7 @@ bool CStretchEngine::ContinueStretchHorz(PauseIndicatorIface* pPause) {
               dest_r_y += pixel_weight * static_cast<uint8_t>(argb_cmyk >> 8);
             }
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+          if (m_ResampleOptions.bInterpolateBicubic) {
             dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue);
             dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue);
             dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue);
@@ -498,7 +499,7 @@ bool CStretchEngine::ContinueStretchHorz(PauseIndicatorIface* pPause) {
             }
             dest_a += pixel_weight;
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+          if (m_ResampleOptions.bInterpolateBicubic) {
             dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue);
             dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue);
             dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue);
@@ -528,7 +529,7 @@ bool CStretchEngine::ContinueStretchHorz(PauseIndicatorIface* pPause) {
             dest_g_m += pixel_weight * (*src_pixel++);
             dest_r_y += pixel_weight * (*src_pixel);
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+          if (m_ResampleOptions.bInterpolateBicubic) {
             dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue);
             dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue);
             dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue);
@@ -564,7 +565,7 @@ bool CStretchEngine::ContinueStretchHorz(PauseIndicatorIface* pPause) {
             dest_r_y += pixel_weight * (*src_pixel);
             dest_a += pixel_weight;
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+          if (m_ResampleOptions.bInterpolateBicubic) {
             dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue);
             dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue);
             dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue);
@@ -592,8 +593,9 @@ void CStretchEngine::StretchVert() {
     return;
 
   CWeightTable table;
-  bool ret = table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom,
-                        m_SrcHeight, m_SrcClip.top, m_SrcClip.bottom, m_Flags);
+  bool ret =
+      table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom, m_SrcHeight,
+                 m_SrcClip.top, m_SrcClip.bottom, m_ResampleOptions);
   if (!ret)
     return;
 
@@ -619,7 +621,7 @@ void CStretchEngine::StretchVert() {
             dest_a +=
                 pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch];
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL)
+          if (m_ResampleOptions.bInterpolateBicubic)
             dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue);
           *dest_scan = static_cast<uint8_t>(dest_a >> 16);
           dest_scan += DestBpp;
@@ -645,7 +647,7 @@ void CStretchEngine::StretchVert() {
             dest_a += pixel_weight *
                       src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch];
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+          if (m_ResampleOptions.bInterpolateBicubic) {
             dest_k = pdfium::clamp(dest_k, 0, kMaxDestValue);
             dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue);
           }
@@ -675,7 +677,7 @@ void CStretchEngine::StretchVert() {
             dest_g_m += pixel_weight * (*src_pixel++);
             dest_r_y += pixel_weight * (*src_pixel);
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+          if (m_ResampleOptions.bInterpolateBicubic) {
             dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue);
             dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue);
             dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue);
@@ -718,7 +720,7 @@ void CStretchEngine::StretchVert() {
             else
               dest_a += pixel_weight * mask_v;
           }
-          if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+          if (m_ResampleOptions.bInterpolateBicubic) {
             dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue);
             dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue);
             dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue);
diff --git a/core/fxge/dib/cstretchengine.h b/core/fxge/dib/cstretchengine.h
index 6bb07c662c..c2aaca687f 100644
--- a/core/fxge/dib/cstretchengine.h
+++ b/core/fxge/dib/cstretchengine.h
@@ -26,7 +26,7 @@ class CStretchEngine {
                  int dest_height,
                  const FX_RECT& clip_rect,
                  const RetainPtr<CFX_DIBBase>& pSrcBitmap,
-                 int flags);
+                 const FXDIB_ResampleOptions& options);
   ~CStretchEngine();
 
   bool Continue(PauseIndicatorIface* pPause);
@@ -46,7 +46,7 @@ class CStretchEngine {
               int src_len,
               int src_min,
               int src_max,
-              int flags);
+              const FXDIB_ResampleOptions& options);
 
     const PixelWeight* GetPixelWeight(int pixel) const;
     PixelWeight* GetPixelWeight(int pixel) {
@@ -96,7 +96,7 @@ class CStretchEngine {
   FX_RECT m_SrcClip;
   int m_InterPitch;
   int m_ExtraMaskPitch;
-  int m_Flags;
+  FXDIB_ResampleOptions m_ResampleOptions;
   TransformMethod m_TransMethod;
   State m_State = State::kInitial;
   int m_CurRow;
diff --git a/core/fxge/dib/cstretchengine_unittest.cpp b/core/fxge/dib/cstretchengine_unittest.cpp
index 8169cae328..a79945c67d 100644
--- a/core/fxge/dib/cstretchengine_unittest.cpp
+++ b/core/fxge/dib/cstretchengine_unittest.cpp
@@ -27,6 +27,11 @@ TEST(CStretchEngine, OverflowInCtor) {
   auto dib_source = pdfium::MakeRetain<CPDF_DIBBase>();
   dib_source->Load(nullptr, stream.get());
   CStretchEngine engine(nullptr, FXDIB_8bppRgb, 500, 500, clip_rect, dib_source,
-                        0);
-  EXPECT_EQ(FXDIB_INTERPOL, engine.m_Flags);
+                        FXDIB_ResampleOptions());
+  EXPECT_FALSE(engine.m_ResampleOptions.bInterpolateDownsample);
+  EXPECT_TRUE(engine.m_ResampleOptions.bInterpolateBilinear);
+  EXPECT_FALSE(engine.m_ResampleOptions.bInterpolateBicubic);
+  EXPECT_FALSE(engine.m_ResampleOptions.bHalftone);
+  EXPECT_FALSE(engine.m_ResampleOptions.bNoSmoothing);
+  EXPECT_FALSE(engine.m_ResampleOptions.bLossy);
 }
diff --git a/core/fxge/dib/fx_dib_main.cpp b/core/fxge/dib/fx_dib_main.cpp
index 8df1322e97..dfdf7ec909 100644
--- a/core/fxge/dib/fx_dib_main.cpp
+++ b/core/fxge/dib/fx_dib_main.cpp
@@ -54,6 +54,29 @@ const int16_t SDP_Table[513] = {
     0,   0,   0,
 };
 
+FXDIB_ResampleOptions::FXDIB_ResampleOptions() = default;
+
+FXDIB_ResampleOptions::FXDIB_ResampleOptions(bool downsample,
+                                             bool bilinear,
+                                             bool bicubic,
+                                             bool halftone,
+                                             bool no_smoothing,
+                                             bool lossy)
+    : bInterpolateDownsample(downsample),
+      bInterpolateBilinear(bilinear),
+      bInterpolateBicubic(bicubic),
+      bHalftone(halftone),
+      bNoSmoothing(no_smoothing),
+      bLossy(lossy) {}
+
+bool FXDIB_ResampleOptions::HasAnyOptions() const {
+  return bInterpolateDownsample || bInterpolateBilinear ||
+         bInterpolateBicubic || bHalftone || bNoSmoothing || bLossy;
+}
+
+const FXDIB_ResampleOptions kBilinearInterpolation = {
+    false, /*bilinear=*/true, false, false, false, false};
+
 FX_RECT FXDIB_SwapClipBox(const FX_RECT& clip,
                           int width,
                           int height,
-- 
cgit v1.2.3