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);
+}