Add high-resolution re-rendering test
Adds a test for repeatedly rendering a PDF page containing a single
full-page, high-resolution (600 DPI) image. This should cache the
derived SkImage, but currently does not.
Bug: pdfium:2034
Change-Id: I80dff81abbb0b7009fe3ea46d1fe3f21554fcf19
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/108050
Reviewed-by: Nigi <nigi@chromium.org>
Commit-Queue: K. Moon <kmoon@chromium.org>
diff --git a/core/fxge/BUILD.gn b/core/fxge/BUILD.gn
index c526c06..dcb17d4 100644
--- a/core/fxge/BUILD.gn
+++ b/core/fxge/BUILD.gn
@@ -236,6 +236,8 @@
deps += [
":fxge",
"../../fpdfsdk",
+ "../fpdfapi/page",
+ "../fpdfapi/render",
"//skia",
]
}
diff --git a/core/fxge/skia/fx_skia_device_embeddertest.cpp b/core/fxge/skia/fx_skia_device_embeddertest.cpp
index 517d863..8e8ee2c 100644
--- a/core/fxge/skia/fx_skia_device_embeddertest.cpp
+++ b/core/fxge/skia/fx_skia_device_embeddertest.cpp
@@ -5,7 +5,11 @@
#include "core/fxge/skia/fx_skia_device.h"
#include <memory>
+#include <set>
+#include <utility>
+#include "core/fpdfapi/page/cpdf_page.h"
+#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_font.h"
@@ -15,13 +19,22 @@
#include "core/fxge/cfx_textrenderoptions.h"
#include "core/fxge/text_char_pos.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
+#include "fpdfsdk/cpdfsdk_renderpage.h"
#include "public/cpp/fpdf_scopers.h"
#include "public/fpdfview.h"
+#include "testing/embedder_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
namespace {
+using ::testing::NiceMock;
+using ::testing::SizeIs;
+using ::testing::WithArg;
+
struct State {
enum class Change { kNo, kYes };
enum class Save { kNo, kYes };
@@ -141,6 +154,47 @@
EXPECT_EQ(state.m_pixel, pixel);
}
+void RenderPageToSkCanvas(FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ SkCanvas* canvas) {
+ CPDF_Page* cpdf_page = CPDFPageFromFPDFPage(page);
+
+ auto context = std::make_unique<CPDF_PageRenderContext>();
+ CPDF_PageRenderContext* unowned_context = context.get();
+
+ CPDF_Page::RenderContextClearer clearer(cpdf_page);
+ cpdf_page->SetRenderContext(std::move(context));
+
+ auto default_device = std::make_unique<CFX_DefaultRenderDevice>();
+ default_device->AttachCanvas(canvas);
+ unowned_context->m_pDevice = std::move(default_device);
+
+ CPDFSDK_RenderPageWithContext(unowned_context, cpdf_page, start_x, start_y,
+ size_x, size_y, /*rotate=*/0, /*flags=*/0,
+ /*color_scheme=*/nullptr,
+ /*need_to_restore=*/true, /*pause=*/nullptr);
+}
+
+class MockCanvas : public SkNoDrawCanvas {
+ public:
+ MockCanvas(int width, int height) : SkNoDrawCanvas(width, height) {}
+
+ MOCK_METHOD(void,
+ onDrawImageRect2,
+ (const SkImage*,
+ const SkRect&,
+ const SkRect&,
+ const SkSamplingOptions&,
+ const SkPaint*,
+ SrcRectConstraint),
+ (override));
+};
+
+using FxgeSkiaEmbedderTest = EmbedderTest;
+
} // namespace
TEST(fxge, SkiaStateEmpty) {
@@ -182,3 +236,36 @@
return;
Harness(&OutOfSequenceClipTest, {});
}
+
+TEST_F(FxgeSkiaEmbedderTest, RenderBigImageTwice) {
+ static constexpr int kCanvasWidth = 306;
+ static constexpr int kCanvasHeight = 396;
+
+ if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ GTEST_SKIP() << "Skia is not the default renderer";
+ }
+
+ ASSERT_TRUE(OpenDocument("bug_2034.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ std::set<int> image_ids;
+ NiceMock<MockCanvas> canvas(kCanvasWidth, kCanvasHeight);
+ EXPECT_CALL(canvas, onDrawImageRect2)
+ .WillRepeatedly(WithArg<0>([&image_ids](const SkImage* image) {
+ ASSERT_TRUE(image);
+ image_ids.insert(image->uniqueID());
+ }));
+
+ RenderPageToSkCanvas(page, /*start_x=*/0, /*start_y=*/0,
+ /*size_x=*/kCanvasWidth, /*size_y=*/kCanvasHeight / 2,
+ &canvas);
+ RenderPageToSkCanvas(page, /*start_x=*/0, /*start_y=*/kCanvasHeight / 2,
+ /*size_x=*/kCanvasWidth, /*size_y=*/kCanvasHeight / 2,
+ &canvas);
+
+ // TODO(crbug.com/pdfium/2034): This should be 1, not 2.
+ EXPECT_THAT(image_ids, SizeIs(2));
+
+ UnloadPage(page);
+}
diff --git a/testing/resources/bug_2034.idat b/testing/resources/bug_2034.idat
new file mode 100644
index 0000000..873c408
--- /dev/null
+++ b/testing/resources/bug_2034.idat
Binary files differ
diff --git a/testing/resources/bug_2034.in b/testing/resources/bug_2034.in
new file mode 100644
index 0000000..f762659
--- /dev/null
+++ b/testing/resources/bug_2034.in
@@ -0,0 +1,65 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+ /MediaBox [0 0 612 792]
+ /Resources <<
+ /XObject <<
+ /HighResolutionImage 5 0 R
+ >>
+ >>
+>>
+endobj
+{{object 4 0}} <<
+ {{streamlen}}
+>>
+stream
+q
+ 612 0 0 792 0 0 cm
+ /HighResolutionImage Do
+Q
+endstream
+endobj
+
+% Image meant to simulate scanner output: full page, 600 DPI, in RGB color.
+{{object 5 0}} <<
+ /Type /XObject
+ /Subtype /Image
+ /BitsPerComponent 4
+ /ColorSpace [
+ /Indexed
+ /DeviceRGB
+ 4
+ <000000 FF0000 00FF00 0000FF FFFFFF>
+ ]
+ /DecodeParms <<
+ /BitsPerComponent 4
+ /Columns 5100
+ /Predictor 10
+ >>
+ /Filter /FlateDecode
+ /Height 6600
+ /Width 5100
+ {{streamlen}}
+>>
+stream
+{{include bug_2034.idat}}
+endstream
+endobj
+
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_2034.pdf b/testing/resources/bug_2034.pdf
new file mode 100644
index 0000000..78ddedf
--- /dev/null
+++ b/testing/resources/bug_2034.pdf
Binary files differ