[Skia] Fix rendering issue for converting 1 bpp image source
This CL makes the following changes to fix the process of upsampling
non-grayscale 1 bit-per-pixel images:
- Move the process for handling 1-bpp image from
Fill32BppDestStorageWithPalette() to a new helper function
Fill32BppDestStorageWith1BppSource().
- For a 1 bit-per-pixel image, even if it's not a grayscale image, it
should have only two colors. Remove the process of building a new
palette with the size of 256 since it's not needed.
- As BuildPaletteFrom1BppSource() is no longer needed outside of
core/fxge/dib/cfx_imagestretcher.cpp, move it into anonymous
namespace.
Bug: chromium:1383708, chromium:1400882
Change-Id: I77557ed3b61b745b5ee98def5dc359ba80b8f85f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/102610
Commit-Queue: Nigi <nigi@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/dib/cfx_imagestretcher.cpp b/core/fxge/dib/cfx_imagestretcher.cpp
index 61af22a..f9b828a 100644
--- a/core/fxge/dib/cfx_imagestretcher.cpp
+++ b/core/fxge/dib/cfx_imagestretcher.cpp
@@ -34,31 +34,16 @@
return format;
}
-} // namespace
+// Builds a new palette with a size of `CFX_DIBBase::kPaletteSize` from the
+// existing palette in `source`. Note: The caller must make sure that the
+// parameters meet the following conditions:
+// source - The format must be `FXDIB_Format::k1bppRgb` and it must
+// have a palette.
+// palette_span - The size must be `CFX_DIBBase::kPaletteSize` to be able
+// to hold the new palette.
-CFX_ImageStretcher::CFX_ImageStretcher(
- ScanlineComposerIface* pDest,
- const RetainPtr<const CFX_DIBBase>& pSource,
- int dest_width,
- int dest_height,
- const FX_RECT& bitmap_rect,
- const FXDIB_ResampleOptions& options)
- : m_pDest(pDest),
- m_pSource(pSource),
- m_ResampleOptions(options),
- m_DestWidth(dest_width),
- m_DestHeight(dest_height),
- m_ClipRect(bitmap_rect),
- m_DestFormat(GetStretchedFormat(*pSource)) {
- DCHECK(m_ClipRect.Valid());
-}
-
-CFX_ImageStretcher::~CFX_ImageStretcher() = default;
-
-// static
-void CFX_ImageStretcher::BuildPaletteFrom1BppSource(
- const RetainPtr<const CFX_DIBBase>& source,
- pdfium::span<FX_ARGB> palette_span) {
+void BuildPaletteFrom1BppSource(const RetainPtr<const CFX_DIBBase>& source,
+ pdfium::span<FX_ARGB> palette_span) {
DCHECK_EQ(FXDIB_Format::k1bppRgb, source->GetFormat());
DCHECK(source->HasPalette());
DCHECK_EQ(CFX_DIBBase::kPaletteSize, palette_span.size());
@@ -84,6 +69,27 @@
}
}
+} // namespace
+
+CFX_ImageStretcher::CFX_ImageStretcher(
+ ScanlineComposerIface* pDest,
+ const RetainPtr<const CFX_DIBBase>& pSource,
+ int dest_width,
+ int dest_height,
+ const FX_RECT& bitmap_rect,
+ const FXDIB_ResampleOptions& options)
+ : m_pDest(pDest),
+ m_pSource(pSource),
+ m_ResampleOptions(options),
+ m_DestWidth(dest_width),
+ m_DestHeight(dest_height),
+ m_ClipRect(bitmap_rect),
+ m_DestFormat(GetStretchedFormat(*pSource)) {
+ DCHECK(m_ClipRect.Valid());
+}
+
+CFX_ImageStretcher::~CFX_ImageStretcher() = default;
+
bool CFX_ImageStretcher::Start() {
if (m_DestWidth == 0 || m_DestHeight == 0)
return false;
diff --git a/core/fxge/dib/cfx_imagestretcher.h b/core/fxge/dib/cfx_imagestretcher.h
index 58c5634..7e51dc7 100644
--- a/core/fxge/dib/cfx_imagestretcher.h
+++ b/core/fxge/dib/cfx_imagestretcher.h
@@ -14,7 +14,6 @@
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/dib/fx_dib.h"
#include "core/fxge/dib/scanlinecomposer_iface.h"
-#include "third_party/base/span.h"
class CFX_DIBBase;
class CStretchEngine;
@@ -30,17 +29,6 @@
const FXDIB_ResampleOptions& options);
~CFX_ImageStretcher();
- // Builds a new palette with a size of `CFX_DIBBase::kPaletteSize` from the
- // existing palette in `source`. Note: The caller must make sure that the
- // parameters meet the following conditions:
- // source - The format must be `FXDIB_Format::k1bppRgb` and it must
- // have a palette.
- // palette_span - The size must be `CFX_DIBBase::kPaletteSize` to be able
- // to hold the new palette.
- static void BuildPaletteFrom1BppSource(
- const RetainPtr<const CFX_DIBBase>& source,
- pdfium::span<FX_ARGB> palette_span);
-
bool Start();
bool Continue(PauseIndicatorIface* pPause);
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index e64fc14..449f6b0 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -39,7 +39,6 @@
#include "core/fxge/cfx_textrenderoptions.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/dib/cfx_imagerenderer.h"
-#include "core/fxge/dib/cfx_imagestretcher.h"
#include "core/fxge/dib/cstretchengine.h"
#include "core/fxge/dib/fx_dib.h"
#include "core/fxge/text_char_pos.h"
@@ -155,11 +154,39 @@
FXARGB_R(color) == FXARGB_B(color);
}
+// Called by Upsample, return a 32 bit-per-pixel buffer filled with 2 colors
+// from a 1 bit-per-pixel source palette.
+DataVector<uint32_t> Fill32BppDestStorageWith1BppSource(
+ const RetainPtr<CFX_DIBBase>& source) {
+ DCHECK_EQ(1, source->GetBPP());
+ int width = source->GetWidth();
+ int height = source->GetHeight();
+ void* buffer = source->GetBuffer().data();
+ DCHECK(buffer);
+
+ uint32_t color0 = source->GetPaletteArgb(0);
+ uint32_t color1 = source->GetPaletteArgb(1);
+ DataVector<uint32_t> dst32_storage(Fx2DSizeOrDie(width, height));
+ pdfium::span<SkPMColor> dst32_pixels(dst32_storage);
+
+ for (int y = 0; y < height; ++y) {
+ const uint8_t* src_row =
+ static_cast<const uint8_t*>(buffer) + y * source->GetPitch();
+ pdfium::span<uint32_t> dst_row = dst32_pixels.subspan(y * width);
+ for (int x = 0; x < width; ++x) {
+ bool use_color1 = src_row[x / 8] & (1 << (7 - x % 8));
+ dst_row[x] = use_color1 ? color1 : color0;
+ }
+ }
+ return dst32_storage;
+}
+
// Called by Upsample(), returns a 32 bit-per-pixel buffer filled with colors
// from `palette`.
DataVector<uint32_t> Fill32BppDestStorageWithPalette(
const RetainPtr<CFX_DIBBase>& source,
pdfium::span<const uint32_t> palette) {
+ DCHECK_EQ(8, source->GetBPP());
int width = source->GetWidth();
int height = source->GetHeight();
void* buffer = source->GetBuffer().data();
@@ -593,22 +620,12 @@
if (pSource->GetFormat() == FXDIB_Format::k1bppRgb &&
pSource->HasPalette()) {
- // When `pSource` has 1 bit per pixel, its palette will contain 2
- // colors, and the R,G,B channels of either color will have equal
- // values. However, there are cases that R,G,B are not all the same and
- // these 2 colors stand for the boundaries of a range of colors to be
- // used for bitmap rendering. We need to handle the color palette
- // differently depending on these conditions.
uint32_t palette_color0 = pSource->GetPaletteArgb(0);
uint32_t palette_color1 = pSource->GetPaletteArgb(1);
- bool use_two_colors = IsRGBColorGrayScale(palette_color0) &&
- IsRGBColorGrayScale(palette_color1);
- if (!use_two_colors) {
- // If more than 2 colors are provided, calculate the range of colors
- // and store them in `new_palette`
- FX_ARGB new_palette[CFX_DIBBase::kPaletteSize];
- CFX_ImageStretcher::BuildPaletteFrom1BppSource(pSource, new_palette);
- dst32_storage = Fill32BppDestStorageWithPalette(pSource, new_palette);
+ bool use_gray_colors = IsRGBColorGrayScale(palette_color0) &&
+ IsRGBColorGrayScale(palette_color1);
+ if (!use_gray_colors) {
+ dst32_storage = Fill32BppDestStorageWith1BppSource(pSource);
buffer = dst32_storage.data();
rowBytes = width * sizeof(uint32_t);
colorType = Get32BitSkColorType(bRgbByteOrder);
diff --git a/testing/SUPPRESSIONS b/testing/SUPPRESSIONS
index 9768236..f022c38 100644
--- a/testing/SUPPRESSIONS
+++ b/testing/SUPPRESSIONS
@@ -491,9 +491,6 @@
# TODO(chromium:1356149): Remove after associated bug is fixed
bug_1356149.in mac * * agg
-# TODO(chromium:1383708): Remove after associated bug is fixed
-bug_1383708.in * * * skia
-
# TODO(pdfium:1457): Remove after associated bug is fixed
bug_1457.in * * * *
diff --git a/testing/resources/pixel/bug_1383708_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1383708_expected_skia.pdf.0.png
new file mode 100644
index 0000000..36119e0
--- /dev/null
+++ b/testing/resources/pixel/bug_1383708_expected_skia.pdf.0.png
Binary files differ