Move switches out of inner loop in FlatePredictorScanlineDecoder

In GetNextLineWithoutPredictedPitch(), make the switch decision first
before running the loop, rather than every time in the loop. Add
CopyAndAdvanceLine() as a helper method to avoid repeating code.

Change-Id: I9fa99a9806c6088218b5d9da6b71abc06d8f7c39
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119254
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcodec/flate/flatemodule.cpp b/core/fxcodec/flate/flatemodule.cpp
index 644b0f7..1714e26 100644
--- a/core/fxcodec/flate/flatemodule.cpp
+++ b/core/fxcodec/flate/flatemodule.cpp
@@ -647,6 +647,7 @@
  private:
   void GetNextLineWithPredictedPitch();
   void GetNextLineWithoutPredictedPitch();
+  size_t CopyAndAdvanceLine(size_t bytes_to_go);
 
   const PredictorType m_Predictor;
   int m_Colors = 0;
@@ -745,34 +746,40 @@
   const uint32_t row_size =
       fxge::CalculatePitch8OrDie(m_BitsPerComponent, m_Colors, m_Columns);
   const uint32_t bytes_per_pixel = (m_BitsPerComponent * m_Colors + 7) / 8;
-  while (bytes_to_go) {
-    switch (m_Predictor) {
-      case PredictorType::kPng: {
+  switch (m_Predictor) {
+    case PredictorType::kPng: {
+      while (bytes_to_go) {
         FlateOutput(m_pFlate.get(), m_PredictRaw);
         PNG_PredictLine(m_PredictBuffer, m_PredictRaw, m_LastLine, row_size,
                         bytes_per_pixel);
         fxcrt::spancpy(m_LastLine.span(), m_PredictBuffer.span());
-        break;
+        bytes_to_go = CopyAndAdvanceLine(bytes_to_go);
       }
-      case PredictorType::kFlate: {
+      break;
+    }
+    case PredictorType::kFlate: {
+      while (bytes_to_go) {
         FlateOutput(m_pFlate.get(), m_PredictBuffer);
         TIFF_PredictLine(m_PredictBuffer, m_BitsPerComponent, m_Colors,
                          m_Columns);
-        break;
+        bytes_to_go = CopyAndAdvanceLine(bytes_to_go);
       }
-      case PredictorType::kNone: {
-        NOTREACHED_NORETURN();
-      }
+      break;
     }
-    size_t read_bytes =
-        m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch;
-    fxcrt::spancpy(m_Scanline.subspan(m_Pitch - bytes_to_go),
-                   m_PredictBuffer.first(read_bytes));
-    m_LeftOver += m_PredictPitch - read_bytes;
-    bytes_to_go -= read_bytes;
+    case PredictorType::kNone: {
+      NOTREACHED_NORETURN();
+    }
   }
 }
 
+size_t FlatePredictorScanlineDecoder::CopyAndAdvanceLine(size_t bytes_to_go) {
+  size_t read_bytes = std::min<size_t>(m_PredictPitch, bytes_to_go);
+  fxcrt::spancpy(m_Scanline.subspan(m_Pitch - bytes_to_go),
+                 m_PredictBuffer.first(read_bytes));
+  m_LeftOver += m_PredictPitch - read_bytes;
+  return bytes_to_go - read_bytes;
+}
+
 }  // namespace
 
 // static