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[] = "83e9f5222c4c959b0b63a5cd24f773a1";
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[] = "83e9f5222c4c959b0b63a5cd24f773a1";
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       "80d7b6cc7b13a78d77a6151bc846e80b";
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       "d485541d958fef08d24e8eca3e537023";
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