[rust png] Deduplicate code into a new `GetScanlineSize` method.

Identical code for computing the scanline size was scattered across
multiple format-specific methods of `ProgressiveDecoder`.  This CL
deduplicates this code into a single method.

The deduplicated expression _seems_ a bit different in `GifStartDecode`,
but it is actually the same, because `GifDetectImageTypeInBuffer` always
sets `src_components_count_ = 1`.

Bug: 444045690
Change-Id: I1f86e510bbe5175434c79322bd647c8f75f3a2a6
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/137031
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/progressive_decoder.cpp b/core/fxcodec/progressive_decoder.cpp
index 7448d67..7a0348e 100644
--- a/core/fxcodec/progressive_decoder.cpp
+++ b/core/fxcodec/progressive_decoder.cpp
@@ -374,7 +374,7 @@
 
 FXCODEC_STATUS ProgressiveDecoder::BmpStartDecode() {
   SetTransMethod();
-  scanline_size_ = FxAlignToBoundary<4>(src_width_ * src_components_count_);
+  scanline_size_ = GetScanlineSize();
   decode_buf_.resize(scanline_size_);
   FXDIB_ResampleOptions options;
   options.bInterpolateBilinear = true;
@@ -442,8 +442,7 @@
 FXCODEC_STATUS ProgressiveDecoder::GifStartDecode() {
   src_format_ = FXCodec_8bppRgb;
   SetTransMethod();
-  int scanline_size = FxAlignToBoundary<4>(src_width_);
-  decode_buf_.resize(scanline_size);
+  decode_buf_.resize(GetScanlineSize());
   FXDIB_ResampleOptions options;
   options.bInterpolateBilinear = true;
   weight_horz_.CalculateWeights(src_width_, 0, src_width_, src_width_, 0,
@@ -533,7 +532,7 @@
       return status_;
     }
   }
-  decode_buf_.resize(FxAlignToBoundary<4>(src_width_ * src_components_count_));
+  decode_buf_.resize(GetScanlineSize());
   FXDIB_ResampleOptions options;
   options.bInterpolateBilinear = true;
   weight_horz_.CalculateWeights(src_width_, 0, src_width_, src_width_, 0,
@@ -635,8 +634,7 @@
   src_components_count_ = 4;
   src_format_ = FXCodec_Argb;
   SetTransMethod();
-  int scanline_size = FxAlignToBoundary<4>(src_width_ * src_components_count_);
-  decode_buf_.resize(scanline_size);
+  decode_buf_.resize(GetScanlineSize());
   status_ = FXCODEC_STATUS::kDecodeToBeContinued;
   return status_;
 }
@@ -1258,4 +1256,15 @@
   }
 }
 
+int ProgressiveDecoder::GetScanlineSize() const {
+  // Can't be called before basic image metadata is decoded.
+  CHECK_NE(src_components_count_, 0);
+  CHECK_NE(src_width_, 0);
+
+  FX_SAFE_INT32 result = src_width_;
+  result *= src_components_count_;
+
+  return FxAlignToBoundary<4>(result).ValueOrDie();
+}
+
 }  // namespace fxcodec
diff --git a/core/fxcodec/progressive_decoder.h b/core/fxcodec/progressive_decoder.h
index f1776c3..994ffac 100644
--- a/core/fxcodec/progressive_decoder.h
+++ b/core/fxcodec/progressive_decoder.h
@@ -180,6 +180,12 @@
                 uint8_t* src_scan,
                 FXCodec_Format src_format);
 
+  // Computes the size of a single decoded image row (in bytes).
+  //
+  // This needs to be called *after* sufficient image metadata has been decoded
+  // (i.e. `src_width_` and `src_components_count_` need to be known).
+  int GetScanlineSize() const;
+
   FXCODEC_STATUS status_ = FXCODEC_STATUS::kDecodeFinished;
   FXCODEC_IMAGE_TYPE image_type_ = FXCODEC_IMAGE_UNKNOWN;
   RetainPtr<IFX_SeekableReadStream> file_;