De-duplicate some code between ProgressiveDecoder and CStretchEngine.

The more complex code in CStretchEngine reduces[1] to the simplified
code in ProgressiveDecoder when the arguments are passed as indicated.

1. a bounded max size is now enforced.

Change-Id: I269459d384df23af63b502deef779c4c8e9d3f0e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/82133
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/progressive_decoder.cpp b/core/fxcodec/progressive_decoder.cpp
index 8d4e9d5..899e92a 100644
--- a/core/fxcodec/progressive_decoder.cpp
+++ b/core/fxcodec/progressive_decoder.cpp
@@ -64,79 +64,6 @@
 
 }  // namespace
 
-ProgressiveDecoder::WeightTable::WeightTable() = default;
-
-ProgressiveDecoder::WeightTable::~WeightTable() = default;
-
-void ProgressiveDecoder::WeightTable::CalculateWeights(int dest_len,
-                                                       int src_len) {
-  CHECK_GE(dest_len, 0);
-  double scale = static_cast<double>(src_len) / dest_len;
-  const size_t weight_count = static_cast<size_t>(ceil(fabs(scale))) + 1;
-  m_ItemSize = PixelWeight::TotalBytesForWeightCount(weight_count);
-  FX_SAFE_SIZE_T safe_size = m_ItemSize;
-  safe_size *= dest_len;
-  m_pWeightTables.resize(safe_size.ValueOrDie());
-  m_DestMin = 0;
-  if (fabs(scale) < 1.0) {
-    for (int dest_pixel = 0; dest_pixel < dest_len; dest_pixel++) {
-      PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
-      double src_pos = dest_pixel * scale + scale / 2;
-      pixel_weights.m_SrcStart = (int)floor((float)src_pos - 1.0f / 2);
-      pixel_weights.m_SrcEnd = (int)floor((float)src_pos + 1.0f / 2);
-      pixel_weights.m_SrcStart = std::max(pixel_weights.m_SrcStart, 0);
-      pixel_weights.m_SrcEnd = std::min(pixel_weights.m_SrcEnd, src_len - 1);
-      if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) {
-        pixel_weights.m_Weights[0] = 65536;
-      } else {
-        pixel_weights.m_Weights[1] = FXSYS_roundf(
-            (float)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 65536);
-        pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1];
-      }
-    }
-    return;
-  }
-  for (int dest_pixel = 0; dest_pixel < dest_len; dest_pixel++) {
-    PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
-    double src_start = dest_pixel * scale;
-    double src_end = src_start + scale;
-    int start_i;
-    int end_i;
-    if (src_start < src_end) {
-      start_i = (int)floor((float)src_start);
-      end_i = (int)ceil((float)src_end);
-    } else {
-      start_i = (int)floor((float)src_end);
-      end_i = (int)ceil((float)src_start);
-    }
-    start_i = std::max(start_i, 0);
-    end_i = std::min(end_i, src_len - 1);
-    if (start_i > end_i) {
-      pixel_weights.m_SrcStart = start_i;
-      pixel_weights.m_SrcEnd = start_i;
-      continue;
-    }
-    pixel_weights.m_SrcStart = start_i;
-    pixel_weights.m_SrcEnd = end_i;
-    for (int j = start_i; j <= end_i; j++) {
-      double dest_start = ((float)j) / scale;
-      double dest_end = ((float)(j + 1)) / scale;
-      if (dest_start > dest_end) {
-        std::swap(dest_start, dest_end);
-      }
-      double area_start = std::max(dest_start, static_cast<double>(dest_pixel));
-      double area_end = std::min(dest_end, static_cast<double>(dest_pixel + 1));
-      double weight = area_start >= area_end ? 0.0 : area_end - area_start;
-      if (weight == 0 && j == end_i) {
-        pixel_weights.m_SrcEnd--;
-        break;
-      }
-      pixel_weights.m_Weights[j - start_i] =
-          FXSYS_roundf((float)(weight * 65536));
-    }
-  }
-}
-
 ProgressiveDecoder::HorzTable::HorzTable() = default;
 
 ProgressiveDecoder::HorzTable::~HorzTable() = default;
@@ -792,7 +719,10 @@
   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
   m_ScanlineSize = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
   m_pDecodeBuf.reset(FX_Alloc(uint8_t, m_ScanlineSize));
-  m_WeightHorz.CalculateWeights(m_sizeX, m_clipBox.Width());
+  FXDIB_ResampleOptions options;
+  options.bInterpolateBilinear = true;
+  m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
+                                m_clipBox.Width(), options);
   m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
   return m_status;
@@ -864,7 +794,10 @@
   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
   int scanline_size = FxAlignToBoundary<4>(m_SrcWidth);
   m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size));
-  m_WeightHorz.CalculateWeights(m_sizeX, m_clipBox.Width());
+  FXDIB_ResampleOptions options;
+  options.bInterpolateBilinear = true;
+  m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
+                                m_clipBox.Width(), options);
   m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
   m_FrameCur = 0;
   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
@@ -1056,7 +989,10 @@
   int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale;
   scanline_size = FxAlignToBoundary<4>(scanline_size * m_SrcComponents);
   m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size));
-  m_WeightHorz.CalculateWeights(m_sizeX, m_clipBox.Width());
+  FXDIB_ResampleOptions options;
+  options.bInterpolateBilinear = true;
+  m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
+                                m_clipBox.Width(), options);
   m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
   switch (m_SrcComponents) {
     case 1:
diff --git a/core/fxcodec/progressive_decoder.h b/core/fxcodec/progressive_decoder.h
index 1f25302..d8b4b78 100644
--- a/core/fxcodec/progressive_decoder.h
+++ b/core/fxcodec/progressive_decoder.h
@@ -17,6 +17,7 @@
 #include "core/fxcrt/fx_memory_wrappers.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/retain_ptr.h"
+#include "core/fxge/dib/cstretchengine.h"
 #include "core/fxge/dib/fx_dib.h"
 
 #ifdef PDF_ENABLE_XFA_BMP
@@ -120,21 +121,7 @@
 #endif  // PDF_ENABLE_XFA_BMP
 
  private:
-  class WeightTable {
-   public:
-    WeightTable();
-    ~WeightTable();
-
-    void CalculateWeights(int dest_len, int src_len);
-    PixelWeight* GetPixelWeight(int pixel) {
-      return reinterpret_cast<PixelWeight*>(m_pWeightTables.data() +
-                                            (pixel - m_DestMin) * m_ItemSize);
-    }
-
-    int m_DestMin;
-    int m_ItemSize;
-    std::vector<uint8_t, FxAllocAllocator<uint8_t>> m_pWeightTables;
-  };
+  using WeightTable = CStretchEngine::CWeightTable;
 
   class HorzTable {
    public:
diff --git a/core/fxge/dib/cstretchengine.h b/core/fxge/dib/cstretchengine.h
index 79fc60b..600212f 100644
--- a/core/fxge/dib/cstretchengine.h
+++ b/core/fxge/dib/cstretchengine.h
@@ -40,7 +40,6 @@
     return m_ResampleOptions;
   }
 
- private:
   class CWeightTable {
    public:
     CWeightTable();
@@ -69,6 +68,7 @@
     std::vector<uint8_t, FxAllocAllocator<uint8_t>> m_WeightTables;
   };
 
+ private:
   enum class State : uint8_t { kInitial, kHorizontal, kVertical };
 
   enum class TransformMethod : uint8_t {