Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fpdf_progressive_render_embeddertest.cpp
Go to the documentation of this file.
1// Copyright 2019 The PDFium Authors
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 <stdint.h>
6
7#include <utility>
8
9#include "build/build_config.h"
10#include "core/fxge/cfx_defaultrenderdevice.h"
11#include "core/fxge/dib/fx_dib.h"
12#include "public/fpdf_progressive.h"
13#include "testing/embedder_test.h"
14#include "testing/embedder_test_constants.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "third_party/base/check.h"
17
18namespace {
19
20constexpr FX_ARGB kBlack = 0xFF000000;
21constexpr FX_ARGB kBlue = 0xFF0000FF;
22constexpr FX_ARGB kGreen = 0xFF00FF00;
23constexpr FX_ARGB kRed = 0xFFFF0000;
24constexpr FX_ARGB kWhite = 0xFFFFFFFF;
25
26const char* AnnotationStampWithApBaseContentChecksum() {
27 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
28#if BUILDFLAG(IS_WIN)
29 return "7f8437212ef1cd33ff505ece5a7e99f8";
30#elif BUILDFLAG(IS_APPLE)
31 return "346c4463cf822e39e29a602a504b9153";
32#else
33 return "4fedc838daa6762cf7eee180986a0f1b";
34#endif
35 }
36#if BUILDFLAG(IS_APPLE)
37 return "243f3d6267d9db09198fed9f8c4957fd";
38#else
39 return "e31414933c9ff3950773981e5bf61678";
40#endif
41}
42
43} // namespace
44
46 public:
47 class FakePause : public IFSDK_PAUSE {
48 public:
49 explicit FakePause(bool should_pause) : should_pause_(should_pause) {
50 IFSDK_PAUSE::version = 1;
51 IFSDK_PAUSE::user = nullptr;
52 IFSDK_PAUSE::NeedToPauseNow = Pause_NeedToPauseNow;
53 }
54 ~FakePause() = default;
55 static FPDF_BOOL Pause_NeedToPauseNow(IFSDK_PAUSE* param) {
56 return static_cast<FakePause*>(param)->should_pause_;
57 }
58
59 private:
60 const bool should_pause_;
61 };
62
63 // StartRenderPageWithFlags() with no flags.
64 // The call returns true if the rendering is complete.
65 bool StartRenderPage(FPDF_PAGE page, IFSDK_PAUSE* pause);
66
67 // Start rendering of |page| into a bitmap with the ability to |pause| the
68 // rendering with the specified rendering |flags|.
69 // The call returns true if the rendering is complete.
70 //
71 // See public/fpdfview.h for a list of page rendering flags.
72 bool StartRenderPageWithFlags(FPDF_PAGE page, IFSDK_PAUSE* pause, int flags);
73
74 // Start rendering of |page| into a bitmap with the ability to pause the
75 // rendering with the specified rendering |flags| and the specified
76 // |color_scheme|. This also takes in the |background_color| for the bitmap.
77 // The call returns true if the rendering is complete.
78 //
79 // See public/fpdfview.h for the list of page rendering flags and
80 // the list of colors in the scheme.
82 FPDF_PAGE page,
83 IFSDK_PAUSE* pause,
84 int flags,
85 const FPDF_COLORSCHEME* color_scheme,
86 uint32_t background_color);
87
88 // Continue rendering of |page| into the bitmap created in
89 // StartRenderPageWithFlags().
90 // The call returns true if the rendering is complete.
91 bool ContinueRenderPage(FPDF_PAGE page, IFSDK_PAUSE* pause);
92
93 // Simplified form of FinishRenderPageWithForms() with no form handle.
95
96 // Finish rendering of |page| into the bitmap created in
97 // StartRenderPageWithFlags(). This also renders the forms associated with
98 // the page. The form handle associated with |page| should be passed in via
99 // |handle|. If |handle| is nullptr, then forms on the page will not be
100 // rendered.
101 // This returns the bitmap generated by the progressive render calls.
103 FPDF_FORMHANDLE handle);
104
105 // Convert the |page| into a bitmap with a |background_color|, using the
106 // color scheme render API with the specific |flags| and |color_scheme|.
107 // The form handle associated with |page| should be passed in via |handle|.
108 // If |handle| is nullptr, then forms on the page will not be rendered.
109 // This returns the bitmap generated by the progressive render calls.
110 //
111 // See public/fpdfview.h for a list of page rendering flags and
112 // the color scheme that can be applied for rendering.
114 FPDF_PAGE page,
115 FPDF_FORMHANDLE handle,
116 int flags,
117 const FPDF_COLORSCHEME* color_scheme,
118 FX_ARGB background_color);
119
120 protected:
121 // Utility method to render the |page_num| of the currently loaded Pdf
122 // using RenderPageWithForcedColorScheme() passing in the render options
123 // and expected values for bitmap verification.
125 int flags,
126 const FPDF_COLORSCHEME* color_scheme,
127 FX_ARGB background_color,
128 int bitmap_width,
129 int bitmap_height,
130 const char* md5);
131
132 private:
133 // Keeps the bitmap used for progressive rendering alive until
134 // FPDF_RenderPage_Close() is called after which the bitmap is returned
135 // to the caller.
136 ScopedFPDFBitmap progressive_render_bitmap_;
137 int progressive_render_flags_ = 0;
138};
139
141 IFSDK_PAUSE* pause) {
142 return StartRenderPageWithFlags(page, pause, 0);
143}
144
146 FPDF_PAGE page,
147 IFSDK_PAUSE* pause,
148 int flags) {
149 int width = static_cast<int>(FPDF_GetPageWidth(page));
150 int height = static_cast<int>(FPDF_GetPageHeight(page));
151 progressive_render_flags_ = flags;
152 int alpha = FPDFPage_HasTransparency(page) ? 1 : 0;
153 progressive_render_bitmap_ =
154 ScopedFPDFBitmap(FPDFBitmap_Create(width, height, alpha));
155 FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF;
156 FPDFBitmap_FillRect(progressive_render_bitmap_.get(), 0, 0, width, height,
157 fill_color);
158 int rv = FPDF_RenderPageBitmap_Start(progressive_render_bitmap_.get(), page,
159 0, 0, width, height, 0,
160 progressive_render_flags_, pause);
161 return rv != FPDF_RENDER_TOBECONTINUED;
162}
163
166 FPDF_PAGE page,
167 IFSDK_PAUSE* pause,
168 int flags,
169 const FPDF_COLORSCHEME* color_scheme,
170 uint32_t background_color) {
171 int width = static_cast<int>(FPDF_GetPageWidth(page));
172 int height = static_cast<int>(FPDF_GetPageHeight(page));
173 progressive_render_flags_ = flags;
174 int alpha = FPDFPage_HasTransparency(page) ? 1 : 0;
175 progressive_render_bitmap_ =
176 ScopedFPDFBitmap(FPDFBitmap_Create(width, height, alpha));
177 DCHECK(progressive_render_bitmap_);
178 FPDFBitmap_FillRect(progressive_render_bitmap_.get(), 0, 0, width, height,
179 background_color);
180 int rv = FPDF_RenderPageBitmapWithColorScheme_Start(
181 progressive_render_bitmap_.get(), page, 0, 0, width, height, 0,
182 progressive_render_flags_, color_scheme, pause);
183 return rv != FPDF_RENDER_TOBECONTINUED;
184}
185
187 IFSDK_PAUSE* pause) {
188 DCHECK(progressive_render_bitmap_);
189
190 int rv = FPDF_RenderPage_Continue(page, pause);
191 return rv != FPDF_RENDER_TOBECONTINUED;
192}
193
195 FPDF_PAGE page) {
196 return FinishRenderPageWithForms(page, /*handle=*/nullptr);
197}
198
200 FPDF_PAGE page,
201 FPDF_FORMHANDLE handle) {
202 DCHECK(progressive_render_bitmap_);
203
204 int width = static_cast<int>(FPDF_GetPageWidth(page));
205 int height = static_cast<int>(FPDF_GetPageHeight(page));
206 FPDF_FFLDraw(handle, progressive_render_bitmap_.get(), page, 0, 0, width,
207 height, 0, progressive_render_flags_);
209 return std::move(progressive_render_bitmap_);
210}
211
214 FPDF_PAGE page,
215 FPDF_FORMHANDLE handle,
216 int flags,
217 const FPDF_COLORSCHEME* color_scheme,
218 FX_ARGB background_color) {
219 FakePause pause(true);
221 page, &pause, flags, color_scheme, background_color) ==
223 EXPECT_FALSE(render_done);
224
225 while (!render_done) {
226 render_done = ContinueRenderPage(page, &pause);
227 }
228 return FinishRenderPageWithForms(page, form_handle());
229}
230
232 // Test rendering of page content using progressive render APIs
233 // without pausing the rendering.
234 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
235 FPDF_PAGE page = LoadPage(0);
236 ASSERT_TRUE(page);
237 FakePause pause(false);
238 EXPECT_TRUE(StartRenderPage(page, &pause));
239 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
240 CompareBitmap(bitmap.get(), 595, 842,
241 AnnotationStampWithApBaseContentChecksum());
242 UnloadPage(page);
243}
244
246 // Test rendering of page content using progressive render APIs
247 // with pause in rendering.
248 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
249 FPDF_PAGE page = LoadPage(0);
250 ASSERT_TRUE(page);
251 FakePause pause(true);
252 bool render_done = StartRenderPage(page, &pause);
253 EXPECT_FALSE(render_done);
254
255 while (!render_done) {
256 render_done = ContinueRenderPage(page, &pause);
257 }
258 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
259 CompareBitmap(bitmap.get(), 595, 842,
260 AnnotationStampWithApBaseContentChecksum());
261 UnloadPage(page);
262}
263
265 // Test rendering of the page with annotations using progressive render APIs
266 // with pause in rendering.
267 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
268 FPDF_PAGE page = LoadPage(0);
269 ASSERT_TRUE(page);
270 FakePause pause(true);
271 bool render_done = StartRenderPageWithFlags(page, &pause, FPDF_ANNOT);
272 EXPECT_FALSE(render_done);
273
274 while (!render_done) {
275 render_done = ContinueRenderPage(page, &pause);
276 }
277 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
278 CompareBitmap(bitmap.get(), 595, 842,
280 UnloadPage(page);
281}
282
284 // Test rendering of the page with forms using progressive render APIs
285 // with pause in rendering.
286 ASSERT_TRUE(OpenDocument("text_form.pdf"));
287 FPDF_PAGE page = LoadPage(0);
288 ASSERT_TRUE(page);
289 FakePause pause(true);
290 bool render_done = StartRenderPage(page, &pause);
291 EXPECT_FALSE(render_done);
292
293 while (!render_done) {
294 render_done = ContinueRenderPage(page, &pause);
295 }
296 ScopedFPDFBitmap bitmap = FinishRenderPageWithForms(page, form_handle());
297 CompareBitmap(bitmap.get(), 300, 300, pdfium::TextFormChecksum());
298 UnloadPage(page);
299}
300
302 int page_num,
303 int flags,
304 const FPDF_COLORSCHEME* color_scheme,
305 FX_ARGB background_color,
306 int bitmap_width,
307 int bitmap_height,
308 const char* md5) {
309 ASSERT_TRUE(document());
310
311 FPDF_PAGE page = LoadPage(page_num);
312 ASSERT_TRUE(page);
313
314 ScopedFPDFBitmap bitmap = RenderPageWithForcedColorScheme(
315 page, form_handle(), flags, color_scheme, background_color);
316 ASSERT_TRUE(bitmap);
317 CompareBitmap(bitmap.get(), bitmap_width, bitmap_height, md5);
318 UnloadPage(page);
319}
320
322 // Test rendering of text with forced color scheme on.
323 const char* content_with_text_checksum = []() {
324 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
325#if BUILDFLAG(IS_WIN)
326 return "e970b97a719ce4d8efdfcbc316255aac";
327#elif BUILDFLAG(IS_APPLE)
328 return "9eba0a0147f1d9685514d274e03d574e";
329#else
330 return "edd919ec8b59fab1f16b5f2adb1175f3";
331#endif
332 }
333#if BUILDFLAG(IS_APPLE)
334 return "ee4ec12f54ce8d117a73bd9b85a8954d";
335#else
336 return "704db63ed2bf77254ecaa8035b85f21a";
337#endif // BUILDFLAG(IS_APPLE)
338 }();
339
340 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
341
342 FPDF_COLORSCHEME color_scheme{kBlack, kWhite, kWhite, kWhite};
343 VerifyRenderingWithColorScheme(/*page_num=*/0, /*flags=*/0, &color_scheme,
344 kBlack, 200, 200, content_with_text_checksum);
345}
346
348 // Test rendering of paths with forced color scheme on.
349 const char* rectangles_checksum = []() {
350 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
351 return "4b0f850a94698d07b6cd2814d1b4ccb7";
352 }
353 return "249f59b0d066c4f6bd89782a80822219";
354 }();
355
356 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
357
358 FPDF_COLORSCHEME color_scheme{kWhite, kRed, kBlue, kBlue};
359 VerifyRenderingWithColorScheme(/*page_num=*/0, /*flags=*/0, &color_scheme,
360 kBlack, 200, 300, rectangles_checksum);
361}
362
365 // Test rendering of paths with forced color scheme on and conversion from
366 // fill to stroke enabled. The fill paths should be rendered as stroke.
367 const char* rectangles_checksum = []() {
368 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
369 return "c1cbbd2ce6921f608a3c55140592419b";
370 }
371 return "0ebcc11e617635eca1fa9ce475383a80";
372 }();
373
374 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
375
376 FPDF_COLORSCHEME color_scheme{kWhite, kRed, kBlue, kBlue};
377 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_CONVERT_FILL_TO_STROKE,
378 &color_scheme, kBlack, 200, 300,
379 rectangles_checksum);
380}
381
383 // Test rendering of highlight with forced color scheme on.
384 //
385 // Note: The fill color rendered for highlight is different from the normal
386 // path since highlights have Multiply blend mode, while the other path has
387 // Normal blend mode.
388 const char* content_with_highlight_fill_checksum = []() {
389 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
390#if BUILDFLAG(IS_WIN)
391 return "8ed2cbc6a362752fabdf9b50d3358c96";
392#elif BUILDFLAG(IS_APPLE)
393 return "fcd4dd021656f692f346780acaa24895";
394#else
395 return "49dcfcfdc38d200bb3d57a2ca3086034";
396#endif
397 }
398#if BUILDFLAG(IS_APPLE)
399 return "a820afec9b99d3d3f2e9e9382bbad7c1";
400#else
401 return "a08a0639f89446f66f3689ee8e08b9fe";
402#endif // BUILDFLAG(IS_APPLE)
403 }();
404
405 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
406
407 FPDF_COLORSCHEME color_scheme{kRed, kGreen, kWhite, kWhite};
408 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT, &color_scheme,
409 kBlue, 612, 792,
410 content_with_highlight_fill_checksum);
411}
412
415 // Test rendering of highlight with forced color and converting fill to
416 // stroke. The highlight should be rendered as a stroke of the rect.
417 //
418 // Note: The stroke color rendered for highlight is different from the normal
419 // path since highlights have Multiply blend mode, while the other path has
420 // Normal blend mode.
421
422 const char* md5_content_with_highlight = []() {
423 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
424#if BUILDFLAG(IS_WIN)
425 return "9389330c006d3e6054057992624684a8";
426#elif BUILDFLAG(IS_APPLE)
427 return "b7039f73f2d8a3ac3e1ef1492e425b99";
428#else
429 return "c609e8810fba2f12db8f8a2b043d97bd";
430#endif
431 }
432#if BUILDFLAG(IS_APPLE)
433 return "8837bea0b3520164b1784e513c882a2d";
434#else
435 return "3dd8c02f5c06bac85e0d2c8bf37d1dc4";
436#endif // BUILDFLAG(IS_APPLE)
437 }();
438
439 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
440
441 FPDF_COLORSCHEME color_scheme{kRed, kGreen, kWhite, kWhite};
442 VerifyRenderingWithColorScheme(
443 /*page_num=*/0, FPDF_ANNOT | FPDF_CONVERT_FILL_TO_STROKE, &color_scheme,
444 kBlue, 612, 792, md5_content_with_highlight);
445}
446
448 // Test rendering of multiple ink with forced color scheme on.
449 const char* content_with_ink_checksum = []() {
450 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
451#if BUILDFLAG(IS_WIN)
452 return "f6dfec1a38800973e57bba5da4fe77fe";
453#elif BUILDFLAG(IS_APPLE)
454 return "5108aa537b6ecc37b3f0a35b76c1b379";
455#else
456 return "b39d9f68ff71963d82c43eb20caa8f4d";
457#endif
458 }
459 return "797bce7dc6c50ee86b095405df9fe5aa";
460 }();
461
462 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
463
464 FPDF_COLORSCHEME color_scheme{kBlack, kGreen, kRed, kRed};
465 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT, &color_scheme,
466 kBlack, 612, 792, content_with_ink_checksum);
467}
468
470 // Test rendering of static annotation with forced color scheme on.
471 const char* content_with_stamp_checksum = []() {
472 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
473#if BUILDFLAG(IS_WIN)
474 return "9365cd179a0109640bb2b7456f211524";
475#elif BUILDFLAG(IS_APPLE)
476 return "42d4d73d939cb4a1b40d003985eaf11e";
477#else
478 return "6e028012a4854ebfd9ee92da862bf679";
479#endif
480 }
481#if BUILDFLAG(IS_APPLE)
482 return "8170c539e95f22f14eb8f266a5f1bbed";
483#else
484 return "d1fd087e59d4dcebf47b56570bdb8c22";
485#endif
486 }();
487
488 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
489
490 FPDF_COLORSCHEME color_scheme{kBlue, kGreen, kRed, kRed};
491 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT, &color_scheme,
492 kWhite, 595, 842, content_with_stamp_checksum);
493}
494
496 // Test rendering of form does not change with forced color scheme on.
497 const char* content_with_form_checksum = []() {
498 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
499 return "9f75d98afc6d6313bd87e6562ea6df15";
500 }
501 return "080f7a4381606659301440e1b14dca35";
502 }();
503
504 ASSERT_TRUE(OpenDocument("annotiter.pdf"));
505
506 FPDF_COLORSCHEME color_scheme{kGreen, kGreen, kRed, kRed};
507 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT, &color_scheme,
508 kWhite, 612, 792, content_with_form_checksum);
509
510 // Verify that the MD5 hash matches when rendered without |color_scheme|.
511 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT,
512 /*color_scheme=*/nullptr, kWhite, 612, 792,
513 content_with_form_checksum);
514}
static void CompareBitmap(FPDF_BITMAP bitmap, int expected_width, int expected_height, const char *expected_md5sum)
void UnloadPage(FPDF_PAGE page)
FPDF_DOCUMENT document() const
FPDF_PAGE LoadPage(int page_number)
bool StartRenderPage(FPDF_PAGE page, IFSDK_PAUSE *pause)
bool ContinueRenderPage(FPDF_PAGE page, IFSDK_PAUSE *pause)
ScopedFPDFBitmap FinishRenderPageWithForms(FPDF_PAGE page, FPDF_FORMHANDLE handle)
ScopedFPDFBitmap RenderPageWithForcedColorScheme(FPDF_PAGE page, FPDF_FORMHANDLE handle, int flags, const FPDF_COLORSCHEME *color_scheme, FX_ARGB background_color)
bool StartRenderPageWithFlags(FPDF_PAGE page, IFSDK_PAUSE *pause, int flags)
bool StartRenderPageWithColorSchemeAndBackground(FPDF_PAGE page, IFSDK_PAUSE *pause, int flags, const FPDF_COLORSCHEME *color_scheme, uint32_t background_color)
void VerifyRenderingWithColorScheme(int page_num, int flags, const FPDF_COLORSCHEME *color_scheme, FX_ARGB background_color, int bitmap_width, int bitmap_height, const char *md5)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_HasTransparency(FPDF_PAGE page)
#define FPDF_RENDER_TOBECONTINUED
FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage_Close(FPDF_PAGE page)
FPDF_EXPORT int FPDF_CALLCONV FPDF_RenderPage_Continue(FPDF_PAGE page, IFSDK_PAUSE *pause)
TEST_F(FPDFProgressiveRenderEmbedderTest, RenderWithoutPause)
FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page)
FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page)
#define FPDF_CONVERT_FILL_TO_STROKE
Definition fpdfview.h:835
#define FPDF_ANNOT
Definition fpdfview.h:804
const char * AnnotationStampWithApChecksum()
const char * TextFormChecksum()