Use CFX_DIBBase::GetPitch() in CFX_PSRenderer.

Use the bitmaps's actual pitch instead of a custom pitch calculation.

Bug: chromium:1363393
Change-Id: I075576817d02994c7a2f47d8b610691bdbc7abdc
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97630
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index 1ed4ea2..243c038 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -522,12 +522,12 @@
   buf << "[" << matrix.a << " " << matrix.b << " " << matrix.c << " "
       << matrix.d << " " << matrix.e << " " << matrix.f << "]cm ";
 
-  int width = pSource->GetWidth();
-  int height = pSource->GetHeight();
+  const int width = pSource->GetWidth();
+  const int height = pSource->GetHeight();
+  const int pitch = pSource->GetPitch();
   buf << width << " " << height;
 
   if (pSource->GetBPP() == 1 && !pSource->HasPalette()) {
-    const int pitch = (width + 7) / 8;
     const uint32_t src_size = height * pitch;
     DataVector<uint8_t> src_buf(src_size);
     {
@@ -539,7 +539,7 @@
     }
 
     FaxCompressResult compress_result =
-        FaxCompressData(std::move(src_buf), width, height);
+        FaxCompressData(std::move(src_buf), width, height, pitch);
     if (pSource->IsMaskFormat()) {
       SetColor(color);
       m_bColorSet = false;
@@ -845,15 +845,16 @@
 CFX_PSRenderer::FaxCompressResult CFX_PSRenderer::FaxCompressData(
     DataVector<uint8_t> src_buf,
     int width,
-    int height) const {
+    int height,
+    int pitch) const {
   FaxCompressResult result;
   if (width * height <= 128) {
-    src_buf.resize((width + 7) / 8 * height);
+    src_buf.resize(pitch * height);
     result.data = std::move(src_buf);
     result.compressed = false;
   } else {
-    result.data = m_pEncoderIface->pFaxEncodeFunc(src_buf, width, height,
-                                                  (width + 7) / 8);
+    result.data =
+        m_pEncoderIface->pFaxEncodeFunc(src_buf, width, height, pitch);
     result.compressed = true;
   }
   return result;
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h
index df04f8c..31214de 100644
--- a/core/fxge/win32/cfx_psrenderer.h
+++ b/core/fxge/win32/cfx_psrenderer.h
@@ -161,7 +161,8 @@
                             fxcrt::ostringstream& buf);
   FaxCompressResult FaxCompressData(DataVector<uint8_t> src_buf,
                                     int width,
-                                    int height) const;
+                                    int height,
+                                    int pitch) const;
   absl::optional<PSCompressResult> PSCompressData(
       pdfium::span<const uint8_t> src_span) const;
   void WritePreambleString(ByteStringView str);
diff --git a/core/fxge/win32/cfx_psrenderer_unittest.cpp b/core/fxge/win32/cfx_psrenderer_unittest.cpp
index c701265..f448e37 100644
--- a/core/fxge/win32/cfx_psrenderer_unittest.cpp
+++ b/core/fxge/win32/cfx_psrenderer_unittest.cpp
@@ -3,11 +3,44 @@
 // found in the LICENSE file.
 
 #include "core/fxge/win32/cfx_psrenderer.h"
+
 #include "core/fxcrt/bytestring.h"
+#include "core/fxcrt/data_vector.h"
+#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_stream.h"
+#include "core/fxcrt/retain_ptr.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
+#include "core/fxge/dib/fx_dib.h"
+#include "core/fxge/win32/cfx_psfonttracker.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/base/span.h"
 
+namespace {
+
+DataVector<uint8_t> FakeA85Encode(pdfium::span<const uint8_t> src_span) {
+  return DataVector<uint8_t>({'d', 'u', 'm', 'm', 'y', 'a', '8', '5'});
+}
+
+class TestWriteStream final : public IFX_RetainableWriteStream {
+ public:
+  CONSTRUCT_VIA_MAKE_RETAIN;
+
+  // IFX_RetainableWriteStream:
+  bool WriteBlock(const void* pData, size_t size) override {
+    const uint8_t* data_as_uint8 = static_cast<const uint8_t*>(pData);
+    data_.insert(data_.end(), data_as_uint8, data_as_uint8 + size);
+    return true;
+  }
+
+  pdfium::span<const uint8_t> GetSpan() const { return data_; }
+
+ private:
+  DataVector<uint8_t> data_;
+};
+
+}  // namespace
+
 TEST(PSRendererTest, GenerateType42SfntData) {
   absl::optional<ByteString> result;
 
@@ -138,3 +171,45 @@
       /*glyphs_per_descendant_font=*/3);
   EXPECT_STREQ(kExpected2DescendantFontResult, result.c_str());
 }
+
+TEST(PSRendererTest, DrawDIBits) {
+  static constexpr char kExpectedOutput[] = R"(
+save
+/im/initmatrix load def
+/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load def/h/closepath load def
+/f/fill load def/F/eofill load def/s/stroke load def/W/clip load def/W*/eoclip load def
+/rg/setrgbcolor load def/k/setcmykcolor load def
+/J/setlinecap load def/j/setlinejoin load def/w/setlinewidth load def/M/setmiterlimit load def/d/setdash load def
+/q/gsave load def/Q/grestore load def/iM/imagemask load def
+/Tj/show load def/Ff/findfont load def/Fs/scalefont load def/Sf/setfont load def
+/cm/concat load def/Cm/currentmatrix load def/mx/matrix load def/sm/setmatrix load def
+q
+[1 0 0 1 0 0]cm 10 2 1[10 0 0 -2 0 2]currentfile/ASCII85Decode filter false 1 colorimage
+dummya85
+Q
+
+restore
+)";
+  auto output_stream = pdfium::MakeRetain<TestWriteStream>();
+
+  {
+    constexpr int kWidth = 10;
+    constexpr int kHeight = 2;
+    CFX_PSFontTracker font_tracker;
+    const EncoderIface encoder_interface{&FakeA85Encode, nullptr, nullptr,
+                                         nullptr, nullptr};
+    CFX_PSRenderer renderer(&font_tracker, &encoder_interface);
+    renderer.Init(output_stream, CFX_PSRenderer::RenderingLevel::kLevel2,
+                  kWidth, kHeight);
+
+    auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
+    bool result = bitmap->Create(kWidth, kHeight, FXDIB_Format::k1bppRgb);
+    ASSERT_TRUE(result);
+    bitmap->Clear(0);
+    ASSERT_TRUE(renderer.DrawDIBits(bitmap, /*color=*/0, CFX_Matrix(),
+                                    FXDIB_ResampleOptions()));
+  }
+
+  ByteString output(output_stream->GetSpan());
+  EXPECT_STREQ(output.c_str(), kExpectedOutput);
+}