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/fxcrt/check.h"
11#include "core/fxge/cfx_defaultrenderdevice.h"
12#include "core/fxge/dib/fx_dib.h"
13#include "public/fpdf_progressive.h"
14#include "testing/embedder_test.h"
15#include "testing/embedder_test_constants.h"
16#include "testing/gtest/include/gtest/gtest.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 if (!FPDFBitmap_FillRect(progressive_render_bitmap_.get(), 0, 0, width,
157 height, fill_color)) {
158 return false;
159 }
160 int rv = FPDF_RenderPageBitmap_Start(progressive_render_bitmap_.get(), page,
161 0, 0, width, height, 0,
162 progressive_render_flags_, pause);
163 return rv != FPDF_RENDER_TOBECONTINUED;
164}
165
168 FPDF_PAGE page,
169 IFSDK_PAUSE* pause,
170 int flags,
171 const FPDF_COLORSCHEME* color_scheme,
172 uint32_t background_color) {
173 int width = static_cast<int>(FPDF_GetPageWidth(page));
174 int height = static_cast<int>(FPDF_GetPageHeight(page));
175 progressive_render_flags_ = flags;
176 int alpha = FPDFPage_HasTransparency(page) ? 1 : 0;
177 progressive_render_bitmap_ =
178 ScopedFPDFBitmap(FPDFBitmap_Create(width, height, alpha));
179 DCHECK(progressive_render_bitmap_);
180 if (!FPDFBitmap_FillRect(progressive_render_bitmap_.get(), 0, 0, width,
181 height, background_color)) {
182 return false;
183 }
184 int rv = FPDF_RenderPageBitmapWithColorScheme_Start(
185 progressive_render_bitmap_.get(), page, 0, 0, width, height, 0,
186 progressive_render_flags_, color_scheme, pause);
187 return rv != FPDF_RENDER_TOBECONTINUED;
188}
189
191 IFSDK_PAUSE* pause) {
192 DCHECK(progressive_render_bitmap_);
193
194 int rv = FPDF_RenderPage_Continue(page, pause);
195 return rv != FPDF_RENDER_TOBECONTINUED;
196}
197
199 FPDF_PAGE page) {
200 return FinishRenderPageWithForms(page, /*handle=*/nullptr);
201}
202
204 FPDF_PAGE page,
205 FPDF_FORMHANDLE handle) {
206 DCHECK(progressive_render_bitmap_);
207
208 int width = static_cast<int>(FPDF_GetPageWidth(page));
209 int height = static_cast<int>(FPDF_GetPageHeight(page));
210 FPDF_FFLDraw(handle, progressive_render_bitmap_.get(), page, 0, 0, width,
211 height, 0, progressive_render_flags_);
213 return std::move(progressive_render_bitmap_);
214}
215
218 FPDF_PAGE page,
219 FPDF_FORMHANDLE handle,
220 int flags,
221 const FPDF_COLORSCHEME* color_scheme,
222 FX_ARGB background_color) {
223 FakePause pause(true);
225 page, &pause, flags, color_scheme, background_color) ==
227 EXPECT_FALSE(render_done);
228
229 while (!render_done) {
230 render_done = ContinueRenderPage(page, &pause);
231 }
232 return FinishRenderPageWithForms(page, form_handle());
233}
234
236 // Test rendering of page content using progressive render APIs
237 // without pausing the rendering.
238 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
239 FPDF_PAGE page = LoadPage(0);
240 ASSERT_TRUE(page);
241 FakePause pause(false);
242 EXPECT_TRUE(StartRenderPage(page, &pause));
243 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
244 CompareBitmap(bitmap.get(), 595, 842,
245 AnnotationStampWithApBaseContentChecksum());
246 UnloadPage(page);
247}
248
250 // Test rendering of page content using progressive render APIs
251 // with pause in rendering.
252 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
253 FPDF_PAGE page = LoadPage(0);
254 ASSERT_TRUE(page);
255 FakePause pause(true);
256 bool render_done = StartRenderPage(page, &pause);
257 EXPECT_FALSE(render_done);
258
259 while (!render_done) {
260 render_done = ContinueRenderPage(page, &pause);
261 }
262 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
263 CompareBitmap(bitmap.get(), 595, 842,
264 AnnotationStampWithApBaseContentChecksum());
265 UnloadPage(page);
266}
267
269 // Test rendering of the page with annotations using progressive render APIs
270 // with pause in rendering.
271 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
272 FPDF_PAGE page = LoadPage(0);
273 ASSERT_TRUE(page);
274 FakePause pause(true);
275 bool render_done = StartRenderPageWithFlags(page, &pause, FPDF_ANNOT);
276 EXPECT_FALSE(render_done);
277
278 while (!render_done) {
279 render_done = ContinueRenderPage(page, &pause);
280 }
281 ScopedFPDFBitmap bitmap = FinishRenderPage(page);
282 CompareBitmap(bitmap.get(), 595, 842,
284 UnloadPage(page);
285}
286
288 // Test rendering of the page with forms using progressive render APIs
289 // with pause in rendering.
290 ASSERT_TRUE(OpenDocument("text_form.pdf"));
291 FPDF_PAGE page = LoadPage(0);
292 ASSERT_TRUE(page);
293 FakePause pause(true);
294 bool render_done = StartRenderPage(page, &pause);
295 EXPECT_FALSE(render_done);
296
297 while (!render_done) {
298 render_done = ContinueRenderPage(page, &pause);
299 }
300 ScopedFPDFBitmap bitmap = FinishRenderPageWithForms(page, form_handle());
301 CompareBitmap(bitmap.get(), 300, 300, pdfium::TextFormChecksum());
302 UnloadPage(page);
303}
304
306 int page_num,
307 int flags,
308 const FPDF_COLORSCHEME* color_scheme,
309 FX_ARGB background_color,
310 int bitmap_width,
311 int bitmap_height,
312 const char* md5) {
313 ASSERT_TRUE(document());
314
315 FPDF_PAGE page = LoadPage(page_num);
316 ASSERT_TRUE(page);
317
318 ScopedFPDFBitmap bitmap = RenderPageWithForcedColorScheme(
319 page, form_handle(), flags, color_scheme, background_color);
320 ASSERT_TRUE(bitmap);
321 CompareBitmap(bitmap.get(), bitmap_width, bitmap_height, md5);
322 UnloadPage(page);
323}
324
326 // Test rendering of text with forced color scheme on.
327 const char* content_with_text_checksum = []() {
328 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
329#if BUILDFLAG(IS_WIN)
330 return "e970b97a719ce4d8efdfcbc316255aac";
331#elif BUILDFLAG(IS_APPLE)
332 return "9eba0a0147f1d9685514d274e03d574e";
333#else
334 return "edd919ec8b59fab1f16b5f2adb1175f3";
335#endif
336 }
337#if BUILDFLAG(IS_APPLE)
338 return "ee4ec12f54ce8d117a73bd9b85a8954d";
339#else
340 return "704db63ed2bf77254ecaa8035b85f21a";
341#endif // BUILDFLAG(IS_APPLE)
342 }();
343
344 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
345
346 FPDF_COLORSCHEME color_scheme{kBlack, kWhite, kWhite, kWhite};
347 VerifyRenderingWithColorScheme(/*page_num=*/0, /*flags=*/0, &color_scheme,
348 kBlack, 200, 200, content_with_text_checksum);
349}
350
352 // Test rendering of paths with forced color scheme on.
353 const char* rectangles_checksum = []() {
354 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
355 return "4b0f850a94698d07b6cd2814d1b4ccb7";
356 }
357 return "249f59b0d066c4f6bd89782a80822219";
358 }();
359
360 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
361
362 FPDF_COLORSCHEME color_scheme{kWhite, kRed, kBlue, kBlue};
363 VerifyRenderingWithColorScheme(/*page_num=*/0, /*flags=*/0, &color_scheme,
364 kBlack, 200, 300, rectangles_checksum);
365}
366
369 // Test rendering of paths with forced color scheme on and conversion from
370 // fill to stroke enabled. The fill paths should be rendered as stroke.
371 const char* rectangles_checksum = []() {
372 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
373 return "c1cbbd2ce6921f608a3c55140592419b";
374 }
375 return "0ebcc11e617635eca1fa9ce475383a80";
376 }();
377
378 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
379
380 FPDF_COLORSCHEME color_scheme{kWhite, kRed, kBlue, kBlue};
381 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_CONVERT_FILL_TO_STROKE,
382 &color_scheme, kBlack, 200, 300,
383 rectangles_checksum);
384}
385
387 // Test rendering of highlight with forced color scheme on.
388 //
389 // Note: The fill color rendered for highlight is different from the normal
390 // path since highlights have Multiply blend mode, while the other path has
391 // Normal blend mode.
392 const char* content_with_highlight_fill_checksum = []() {
393 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
394#if BUILDFLAG(IS_WIN)
395 return "8ed2cbc6a362752fabdf9b50d3358c96";
396#elif BUILDFLAG(IS_APPLE)
397 return "fcd4dd021656f692f346780acaa24895";
398#else
399 return "49dcfcfdc38d200bb3d57a2ca3086034";
400#endif
401 }
402#if BUILDFLAG(IS_APPLE)
403 return "a820afec9b99d3d3f2e9e9382bbad7c1";
404#else
405 return "a08a0639f89446f66f3689ee8e08b9fe";
406#endif // BUILDFLAG(IS_APPLE)
407 }();
408
409 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
410
411 FPDF_COLORSCHEME color_scheme{kRed, kGreen, kWhite, kWhite};
412 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT, &color_scheme,
413 kBlue, 612, 792,
414 content_with_highlight_fill_checksum);
415}
416
419 // Test rendering of highlight with forced color and converting fill to
420 // stroke. The highlight should be rendered as a stroke of the rect.
421 //
422 // Note: The stroke color rendered for highlight is different from the normal
423 // path since highlights have Multiply blend mode, while the other path has
424 // Normal blend mode.
425
426 const char* md5_content_with_highlight = []() {
427 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
428#if BUILDFLAG(IS_WIN)
429 return "9389330c006d3e6054057992624684a8";
430#elif BUILDFLAG(IS_APPLE)
431 return "b7039f73f2d8a3ac3e1ef1492e425b99";
432#else
433 return "c609e8810fba2f12db8f8a2b043d97bd";
434#endif
435 }
436#if BUILDFLAG(IS_APPLE)
437 return "8837bea0b3520164b1784e513c882a2d";
438#else
439 return "3dd8c02f5c06bac85e0d2c8bf37d1dc4";
440#endif // BUILDFLAG(IS_APPLE)
441 }();
442
443 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
444
445 FPDF_COLORSCHEME color_scheme{kRed, kGreen, kWhite, kWhite};
446 VerifyRenderingWithColorScheme(
447 /*page_num=*/0, FPDF_ANNOT | FPDF_CONVERT_FILL_TO_STROKE, &color_scheme,
448 kBlue, 612, 792, md5_content_with_highlight);
449}
450
452 // Test rendering of multiple ink with forced color scheme on.
453 const char* content_with_ink_checksum = []() {
454 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
455#if BUILDFLAG(IS_WIN)
456 return "cddb7472b064782b2866aa3dc87ca73e";
457#elif BUILDFLAG(IS_APPLE)
458 return "0ef02da77fc1e08455148ecadd257e06";
459#else
460 return "bd9d457356dba5fcf33ec9afdaefcab8";
461#endif
462 }
463 return "797bce7dc6c50ee86b095405df9fe5aa";
464 }();
465
466 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
467
468 FPDF_COLORSCHEME color_scheme{kBlack, kGreen, kRed, kRed};
469 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT, &color_scheme,
470 kBlack, 612, 792, content_with_ink_checksum);
471}
472
474 // Test rendering of static annotation with forced color scheme on.
475 const char* content_with_stamp_checksum = []() {
476 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
477#if BUILDFLAG(IS_WIN)
478 return "c35d1256f6684da13023a0e74622c885";
479#elif BUILDFLAG(IS_APPLE)
480 return "bb302d8808633fede3b6e2e39ac8aaa7";
481#else
482 return "1bd68054628cf193b399a16638ecb5f9";
483#endif
484 }
485#if BUILDFLAG(IS_APPLE)
486 return "8170c539e95f22f14eb8f266a5f1bbed";
487#else
488 return "d1fd087e59d4dcebf47b56570bdb8c22";
489#endif
490 }();
491
492 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
493
494 FPDF_COLORSCHEME color_scheme{kBlue, kGreen, kRed, kRed};
495 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT, &color_scheme,
496 kWhite, 595, 842, content_with_stamp_checksum);
497}
498
500 // Test rendering of form does not change with forced color scheme on.
501 const char* content_with_form_checksum = []() {
502 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
503 return "9f75d98afc6d6313bd87e6562ea6df15";
504 }
505 return "080f7a4381606659301440e1b14dca35";
506 }();
507
508 ASSERT_TRUE(OpenDocument("annotiter.pdf"));
509
510 FPDF_COLORSCHEME color_scheme{kGreen, kGreen, kRed, kRed};
511 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT, &color_scheme,
512 kWhite, 612, 792, content_with_form_checksum);
513
514 // Verify that the MD5 hash matches when rendered without |color_scheme|.
515 VerifyRenderingWithColorScheme(/*page_num=*/0, FPDF_ANNOT,
516 /*color_scheme=*/nullptr, kWhite, 612, 792,
517 content_with_form_checksum);
518}
#define DCHECK
Definition check.h:33
FPDF_PAGE LoadPage(int page_index)
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
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:821
#define FPDF_ANNOT
Definition fpdfview.h:790
uint32_t FX_ARGB
Definition fx_dib.h:36
const char * AnnotationStampWithApChecksum()
const char * TextFormChecksum()