1 // Copyright 2019 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <utility>
6
7 #include "build/build_config.h"
8 #include "core/fxcrt/fx_system.h"
9 #include "public/fpdf_progressive.h"
10 #include "testing/embedder_test.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 class FPDFProgressiveRenderEmbedderTest : public EmbedderTest {
14 public:
15 // StartRenderPageWithFlags() with no flags.
16 // The call returns true if the rendering is complete.
17 bool StartRenderPage(FPDF_PAGE page, IFSDK_PAUSE* pause);
18
19 // Start rendering of |page| into a bitmap with the ability to pause the
20 // rendering with the specified rendering |flags|.
21 // The call returns true if the rendering is complete.
22 //
23 // See public/fpdfview.h for a list of page rendering flags.
24 bool StartRenderPageWithFlags(FPDF_PAGE page, IFSDK_PAUSE* pause, int flags);
25
26 // Continue rendering of |page| into the bitmap created in
27 // StartRenderPageWithFlags().
28 // The call returns true if the rendering is complete.
29 bool ContinueRenderPage(FPDF_PAGE page, IFSDK_PAUSE* pause);
30
31 // Simplified form of FinishRenderPageWithForms() with no form handle.
32 ScopedFPDFBitmap FinishRenderPage(FPDF_PAGE page);
33
34 // Finish rendering of |page| into the bitmap created in
35 // StartRenderPageWithFlags(). This also renders the forms associated with
36 // the page. The form handle associated with |page| should be passed in via
37 // |handle|. If |handle| is nullptr, then forms on the page will not be
38 // rendered.
39 // This returns the bitmap generated by the progressive render calls.
40 ScopedFPDFBitmap FinishRenderPageWithForms(FPDF_PAGE page,
41 FPDF_FORMHANDLE handle);
42
43 private:
44 // Keeps the bitmap used for progressive rendering alive until
45 // FPDF_RenderPage_Close() is called after which the bitmap is returned
46 // to the caller.
47 ScopedFPDFBitmap progressive_render_bitmap_;
48 int progressive_render_flags_ = 0;
49 };
50
StartRenderPage(FPDF_PAGE page,IFSDK_PAUSE * pause)51 bool FPDFProgressiveRenderEmbedderTest::StartRenderPage(FPDF_PAGE page,
52 IFSDK_PAUSE* pause) {
53 return StartRenderPageWithFlags(page, pause, 0);
54 }
55
StartRenderPageWithFlags(FPDF_PAGE page,IFSDK_PAUSE * pause,int flags)56 bool FPDFProgressiveRenderEmbedderTest::StartRenderPageWithFlags(
57 FPDF_PAGE page,
58 IFSDK_PAUSE* pause,
59 int flags) {
60 int width = static_cast<int>(FPDF_GetPageWidth(page));
61 int height = static_cast<int>(FPDF_GetPageHeight(page));
62 progressive_render_flags_ = flags;
63 int alpha = FPDFPage_HasTransparency(page) ? 1 : 0;
64 progressive_render_bitmap_ =
65 ScopedFPDFBitmap(FPDFBitmap_Create(width, height, alpha));
66 FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF;
67 FPDFBitmap_FillRect(progressive_render_bitmap_.get(), 0, 0, width, height,
68 fill_color);
69 int rv = FPDF_RenderPageBitmap_Start(progressive_render_bitmap_.get(), page,
70 0, 0, width, height, 0,
71 progressive_render_flags_, pause);
72 return rv != FPDF_RENDER_TOBECONTINUED;
73 }
74
ContinueRenderPage(FPDF_PAGE page,IFSDK_PAUSE * pause)75 bool FPDFProgressiveRenderEmbedderTest::ContinueRenderPage(FPDF_PAGE page,
76 IFSDK_PAUSE* pause) {
77 ASSERT(progressive_render_bitmap_);
78
79 int rv = FPDF_RenderPage_Continue(page, pause);
80 return rv != FPDF_RENDER_TOBECONTINUED;
81 }
82
FinishRenderPage(FPDF_PAGE page)83 ScopedFPDFBitmap FPDFProgressiveRenderEmbedderTest::FinishRenderPage(
84 FPDF_PAGE page) {
85 return FinishRenderPageWithForms(page, /*handle=*/nullptr);
86 }
87
FinishRenderPageWithForms(FPDF_PAGE page,FPDF_FORMHANDLE handle)88 ScopedFPDFBitmap FPDFProgressiveRenderEmbedderTest::FinishRenderPageWithForms(
89 FPDF_PAGE page,
90 FPDF_FORMHANDLE handle) {
91 ASSERT(progressive_render_bitmap_);
92
93 int width = static_cast<int>(FPDF_GetPageWidth(page));
94 int height = static_cast<int>(FPDF_GetPageHeight(page));
95 FPDF_FFLDraw(handle, progressive_render_bitmap_.get(), page, 0, 0, width,
96 height, 0, progressive_render_flags_);
97 FPDF_RenderPage_Close(page);
98 return std::move(progressive_render_bitmap_);
99 }
100
101 class FakePause : public IFSDK_PAUSE {
102 public:
FakePause(bool should_pause)103 explicit FakePause(bool should_pause) : should_pause_(should_pause) {
104 IFSDK_PAUSE::version = 1;
105 IFSDK_PAUSE::user = nullptr;
106 IFSDK_PAUSE::NeedToPauseNow = Pause_NeedToPauseNow;
107 }
108 ~FakePause() = default;
109
Pause_NeedToPauseNow(IFSDK_PAUSE * param)110 static FPDF_BOOL Pause_NeedToPauseNow(IFSDK_PAUSE* param) {
111 return static_cast<FakePause*>(param)->should_pause_;
112 }
113
114 private:
115 const bool should_pause_ = false;
116 };
117
118 // TODO(crbug.com/pdfium/11): Fix this test and enable.
119 #if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
120 #define MAYBE_RenderWithoutPause DISABLED_RenderWithoutPause
121 #else
122 #define MAYBE_RenderWithoutPause RenderWithoutPause
123 #endif
TEST_F(FPDFProgressiveRenderEmbedderTest,MAYBE_RenderWithoutPause)124 TEST_F(FPDFProgressiveRenderEmbedderTest, MAYBE_RenderWithoutPause) {
125 #if defined(OS_WIN)
126 static constexpr char kMd5BaseContent[] = "649d6792ea50faf98c013c2d81710595";
127 #elif defined(OS_MACOSX)
128 static constexpr char kMd5BaseContent[] = "5f933aac2a74434be1b4d0bdb5334f0b";
129 #else
130 static constexpr char kMd5BaseContent[] = "a24edc7740f1d6f76899652dcf825dea";
131 #endif
132
133 // Test rendering of page content using progressive render APIs
134 // without pausing the rendering.
135 EXPECT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
136 FPDF_PAGE page = LoadPage(0);
137 ASSERT_TRUE(page);
138 FakePause pause(false);
139 EXPECT_TRUE(StartRenderPage(page, &pause));
140 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
141 CompareBitmap(bitmap.get(), 595, 842, kMd5BaseContent);
142 UnloadPage(page);
143 }
144
145 // TODO(crbug.com/pdfium/11): Fix this test and enable.
146 #if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
147 #define MAYBE_RenderWithPause DISABLED_RenderWithPause
148 #else
149 #define MAYBE_RenderWithPause RenderWithPause
150 #endif
TEST_F(FPDFProgressiveRenderEmbedderTest,MAYBE_RenderWithPause)151 TEST_F(FPDFProgressiveRenderEmbedderTest, MAYBE_RenderWithPause) {
152 #if defined(OS_WIN)
153 static constexpr char kMd5BaseContent[] = "649d6792ea50faf98c013c2d81710595";
154 #elif defined(OS_MACOSX)
155 static constexpr char kMd5BaseContent[] = "5f933aac2a74434be1b4d0bdb5334f0b";
156 #else
157 static constexpr char kMd5BaseContent[] = "a24edc7740f1d6f76899652dcf825dea";
158 #endif
159
160 // Test rendering of page content using progressive render APIs
161 // with pause in rendering.
162 EXPECT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
163 FPDF_PAGE page = LoadPage(0);
164 ASSERT_TRUE(page);
165 FakePause pause(true);
166 bool render_done = StartRenderPage(page, &pause);
167 EXPECT_FALSE(render_done);
168
169 while (!render_done) {
170 render_done = ContinueRenderPage(page, &pause);
171 }
172 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
173 CompareBitmap(bitmap.get(), 595, 842, kMd5BaseContent);
174 UnloadPage(page);
175 }
176
177 // TODO(crbug.com/pdfium/11): Fix this test and enable.
178 #if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
179 #define MAYBE_RenderAnnotWithPause DISABLED_RenderAnnotWithPause
180 #else
181 #define MAYBE_RenderAnnotWithPause RenderAnnotWithPause
182 #endif
TEST_F(FPDFProgressiveRenderEmbedderTest,MAYBE_RenderAnnotWithPause)183 TEST_F(FPDFProgressiveRenderEmbedderTest, MAYBE_RenderAnnotWithPause) {
184 #if defined(OS_WIN)
185 static constexpr char kMd5ContentWithAnnot[] =
186 "6aa001a77ec05d0f1b0d1d22e28744d4";
187 #elif defined(OS_MACOSX)
188 static constexpr char kMd5ContentWithAnnot[] =
189 "c35408717759562d1f8bf33d317483d2";
190 #else
191 static constexpr char kMd5ContentWithAnnot[] =
192 "b42cef463483e668eaf4055a65e4f1f5";
193 #endif
194
195 // Test rendering of the page with annotations using progressive render APIs
196 // with pause in rendering.
197 EXPECT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
198 FPDF_PAGE page = LoadPage(0);
199 ASSERT_TRUE(page);
200 FakePause pause(true);
201 bool render_done = StartRenderPageWithFlags(page, &pause, FPDF_ANNOT);
202 EXPECT_FALSE(render_done);
203
204 while (!render_done) {
205 render_done = ContinueRenderPage(page, &pause);
206 }
207 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
208 CompareBitmap(bitmap.get(), 595, 842, kMd5ContentWithAnnot);
209 UnloadPage(page);
210 }
211
212 // TODO(crbug.com/pdfium/11): Fix this test and enable.
213 #if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
214 #define MAYBE_RenderFormsWithPause DISABLED_RenderFormsWithPause
215 #else
216 #define MAYBE_RenderFormsWithPause RenderFormsWithPause
217 #endif
TEST_F(FPDFProgressiveRenderEmbedderTest,MAYBE_RenderFormsWithPause)218 TEST_F(FPDFProgressiveRenderEmbedderTest, MAYBE_RenderFormsWithPause) {
219 #if defined(OS_WIN)
220 static constexpr char kMd5ContentWithForms[] =
221 "d3204faa62b607f0bd3893c9c22cabcb";
222 #elif defined(OS_MACOSX)
223 static constexpr char kMd5ContentWithForms[] =
224 "5f11dbe575fe197a37c3fb422559f8ff";
225 #else
226 static constexpr char kMd5ContentWithForms[] =
227 "b890950d4b9bc163b1a96797f3004b53";
228 #endif
229
230 // Test rendering of the page with forms using progressive render APIs
231 // with pause in rendering.
232 EXPECT_TRUE(OpenDocument("text_form.pdf"));
233 FPDF_PAGE page = LoadPage(0);
234 ASSERT_TRUE(page);
235 FakePause pause(true);
236 bool render_done = StartRenderPage(page, &pause);
237 EXPECT_FALSE(render_done);
238
239 while (!render_done) {
240 render_done = ContinueRenderPage(page, &pause);
241 }
242 ScopedFPDFBitmap bitmap = FinishRenderPageWithForms(page, form_handle_);
243 CompareBitmap(bitmap.get(), 300, 300, kMd5ContentWithForms);
244 UnloadPage(page);
245 }
246