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