blob: f877617b4935e97817a340d0a82cc403d49c2db4 [file] [log] [blame]
Tom Sepezd483eb42016-01-06 10:03:59 -08001// Copyright 2016 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
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05005#include <memory>
6#include <string>
7
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05008#include "core/fpdfapi/page/cpdf_page.h"
9#include "core/fpdfapi/parser/cpdf_dictionary.h"
Nicolas Pena0fc185e2017-02-08 12:13:20 -050010#include "core/fxcrt/fx_system.h"
Nicolas Penaa4ad01f2017-02-15 16:26:48 -050011#include "fpdfsdk/fsdk_define.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080012#include "public/fpdf_edit.h"
13#include "public/fpdfview.h"
14#include "testing/embedder_test.h"
Tom Sepez0aec19b2016-01-07 12:22:44 -080015#include "testing/gmock/include/gmock/gmock-matchers.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080016#include "testing/gtest/include/gtest/gtest.h"
Tom Sepez0aec19b2016-01-07 12:22:44 -080017#include "testing/test_support.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080018
Tom Sepez0aec19b2016-01-07 12:22:44 -080019class FPDFEditEmbeddertest : public EmbedderTest, public TestSaver {};
Tom Sepezd483eb42016-01-06 10:03:59 -080020
etienneb7712c262016-04-26 08:13:45 -070021namespace {
thestigdc7ec032016-11-21 15:32:52 -080022
etienneb7712c262016-04-26 08:13:45 -070023const char kExpectedPDF[] =
24 "%PDF-1.7\r\n"
25 "%\xA1\xB3\xC5\xD7\r\n"
26 "1 0 obj\r\n"
27 "<</Pages 2 0 R /Type/Catalog>>\r\n"
28 "endobj\r\n"
29 "2 0 obj\r\n"
30 "<</Count 1/Kids\\[ 4 0 R \\]/Type/Pages>>\r\n"
31 "endobj\r\n"
32 "3 0 obj\r\n"
33 "<</CreationDate\\(D:.*\\)/Creator\\(PDFium\\)>>\r\n"
34 "endobj\r\n"
35 "4 0 obj\r\n"
36 "<</Contents 5 0 R /MediaBox\\[ 0 0 640 480\\]"
37 "/Parent 2 0 R /Resources<<>>/Rotate 0/Type/Page"
38 ">>\r\n"
39 "endobj\r\n"
40 "5 0 obj\r\n"
41 "<</Filter/FlateDecode/Length 8>>stream\r\n"
42 // Character '_' is matching '\0' (see comment below).
43 "x\x9C\x3____\x1\r\n"
44 "endstream\r\n"
45 "endobj\r\n"
46 "xref\r\n"
47 "0 6\r\n"
48 "0000000000 65535 f\r\n"
49 "0000000017 00000 n\r\n"
50 "0000000066 00000 n\r\n"
51 "0000000122 00000 n\r\n"
52 "0000000192 00000 n\r\n"
53 "0000000301 00000 n\r\n"
54 "trailer\r\n"
55 "<<\r\n"
56 "/Root 1 0 R\r\n"
57 "/Info 3 0 R\r\n"
58 "/Size 6/ID\\[<.*><.*>\\]>>\r\n"
59 "startxref\r\n"
60 "379\r\n"
61 "%%EOF\r\n";
thestigdc7ec032016-11-21 15:32:52 -080062
63int GetBlockFromString(void* param,
64 unsigned long pos,
65 unsigned char* buf,
66 unsigned long size) {
67 std::string* new_file = static_cast<std::string*>(param);
68 if (!new_file || pos + size < pos)
69 return 0;
70
71 unsigned long file_size = new_file->size();
72 if (pos + size > file_size)
73 return 0;
74
75 memcpy(buf, new_file->data() + pos, size);
76 return 1;
77}
78
etienneb7712c262016-04-26 08:13:45 -070079} // namespace
80
Tom Sepezd483eb42016-01-06 10:03:59 -080081TEST_F(FPDFEditEmbeddertest, EmptyCreation) {
82 EXPECT_TRUE(CreateEmptyDocument());
weili9b777de2016-08-19 16:19:46 -070083 FPDF_PAGE page = FPDFPage_New(document(), 0, 640.0, 480.0);
Tom Sepezd483eb42016-01-06 10:03:59 -080084 EXPECT_NE(nullptr, page);
85 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Tom Sepez0aec19b2016-01-07 12:22:44 -080086 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
etienneb7712c262016-04-26 08:13:45 -070087
88 // The MatchesRegexp doesn't support embedded NUL ('\0') characters. They are
89 // replaced by '_' for the purpose of the test.
90 std::string result = GetString();
91 std::replace(result.begin(), result.end(), '\0', '_');
92 EXPECT_THAT(result, testing::MatchesRegex(
93 std::string(kExpectedPDF, sizeof(kExpectedPDF))));
weili9b777de2016-08-19 16:19:46 -070094 FPDF_ClosePage(page);
Tom Sepezd483eb42016-01-06 10:03:59 -080095}
thestigdc7ec032016-11-21 15:32:52 -080096
97// Regression test for https://crbug.com/667012
98TEST_F(FPDFEditEmbeddertest, RasterizePDF) {
99 const char kAllBlackMd5sum[] = "5708fc5c4a8bd0abde99c8e8f0390615";
100
101 // Get the bitmap for the original document/
102 FPDF_BITMAP orig_bitmap;
103 {
104 EXPECT_TRUE(OpenDocument("black.pdf"));
105 FPDF_PAGE orig_page = LoadPage(0);
106 EXPECT_NE(nullptr, orig_page);
107 orig_bitmap = RenderPage(orig_page);
108 CompareBitmap(orig_bitmap, 612, 792, kAllBlackMd5sum);
109 UnloadPage(orig_page);
110 }
111
112 // Create a new document from |orig_bitmap| and save it.
113 {
114 FPDF_DOCUMENT temp_doc = FPDF_CreateNewDocument();
115 FPDF_PAGE temp_page = FPDFPage_New(temp_doc, 0, 612, 792);
116
117 // Add the bitmap to an image object and add the image object to the output
118 // page.
119 FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImgeObj(temp_doc);
120 EXPECT_TRUE(FPDFImageObj_SetBitmap(&temp_page, 1, temp_img, orig_bitmap));
121 EXPECT_TRUE(FPDFImageObj_SetMatrix(temp_img, 612, 0, 0, 792, 0, 0));
122 FPDFPage_InsertObject(temp_page, temp_img);
123 EXPECT_TRUE(FPDFPage_GenerateContent(temp_page));
124 EXPECT_TRUE(FPDF_SaveAsCopy(temp_doc, this, 0));
125 FPDF_ClosePage(temp_page);
126 FPDF_CloseDocument(temp_doc);
127 }
128 FPDFBitmap_Destroy(orig_bitmap);
129
130 // Get the generated content. Make sure it is at least as big as the original
131 // PDF.
132 std::string new_file = GetString();
133 EXPECT_GT(new_file.size(), 923U);
134
135 // Read |new_file| in, and verify its rendered bitmap.
136 {
137 FPDF_FILEACCESS file_access;
138 memset(&file_access, 0, sizeof(file_access));
139 file_access.m_FileLen = new_file.size();
140 file_access.m_GetBlock = GetBlockFromString;
141 file_access.m_Param = &new_file;
142
143 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
144 EXPECT_EQ(1, FPDF_GetPageCount(document_));
145 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
146 EXPECT_NE(nullptr, new_page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500147 FPDF_BITMAP new_bitmap = RenderPage(new_page);
thestigdc7ec032016-11-21 15:32:52 -0800148 CompareBitmap(new_bitmap, 612, 792, kAllBlackMd5sum);
149 FPDF_ClosePage(new_page);
150 FPDF_CloseDocument(new_doc);
151 FPDFBitmap_Destroy(new_bitmap);
152 }
153}
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500154
155TEST_F(FPDFEditEmbeddertest, AddPaths) {
156 // Start with a blank page
157 FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
158 FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792);
159
160 // We will first add a red rectangle
161 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
162 ASSERT_NE(nullptr, red_rect);
163 // Expect false when trying to set colors out of range
164 EXPECT_FALSE(FPDFPath_SetStrokeColor(red_rect, 100, 100, 100, 300));
165 EXPECT_FALSE(FPDFPath_SetFillColor(red_rect, 200, 256, 200, 0));
166
167 // Fill rectangle with red and insert to the page
168 EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255));
169 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
170 FPDFPage_InsertObject(page, red_rect);
171 EXPECT_TRUE(FPDFPage_GenerateContent(page));
172 FPDF_BITMAP page_bitmap = RenderPage(page);
173 CompareBitmap(page_bitmap, 612, 792, "66d02eaa6181e2c069ce2ea99beda497");
174 FPDFBitmap_Destroy(page_bitmap);
175
176 // Now add to that a green rectangle with some medium alpha
177 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(100, 100, 40, 40);
178 EXPECT_TRUE(FPDFPath_SetFillColor(green_rect, 0, 255, 0, 128));
179 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_WINDING, 0));
180 FPDFPage_InsertObject(page, green_rect);
181 EXPECT_TRUE(FPDFPage_GenerateContent(page));
182 page_bitmap = RenderPage(page);
183 CompareBitmap(page_bitmap, 612, 792, "7b0b87604594e773add528fae567a558");
184 FPDFBitmap_Destroy(page_bitmap);
185
186 // Add a black triangle.
187 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(400, 100);
188 EXPECT_TRUE(FPDFPath_SetFillColor(black_path, 0, 0, 0, 200));
189 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
190 EXPECT_TRUE(FPDFPath_LineTo(black_path, 400, 200));
191 EXPECT_TRUE(FPDFPath_LineTo(black_path, 300, 100));
192 EXPECT_TRUE(FPDFPath_Close(black_path));
193 FPDFPage_InsertObject(page, black_path);
194 EXPECT_TRUE(FPDFPage_GenerateContent(page));
195 page_bitmap = RenderPage(page);
196 CompareBitmap(page_bitmap, 612, 792, "eadc8020a14dfcf091da2688733d8806");
197 FPDFBitmap_Destroy(page_bitmap);
198
199 // Now add a more complex blue path.
200 FPDF_PAGEOBJECT blue_path = FPDFPageObj_CreateNewPath(200, 200);
201 EXPECT_TRUE(FPDFPath_SetFillColor(blue_path, 0, 0, 255, 255));
202 EXPECT_TRUE(FPDFPath_SetDrawMode(blue_path, FPDF_FILLMODE_WINDING, 0));
203 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 230, 230));
204 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 250, 250, 280, 280, 300, 300));
205 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 325, 325));
206 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 350, 325));
207 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 375, 330, 390, 360, 400, 400));
208 EXPECT_TRUE(FPDFPath_Close(blue_path));
209 FPDFPage_InsertObject(page, blue_path);
210 EXPECT_TRUE(FPDFPage_GenerateContent(page));
211 page_bitmap = RenderPage(page);
212 CompareBitmap(page_bitmap, 612, 792, "9823e1a21bd9b72b6a442ba4f12af946");
213 FPDFBitmap_Destroy(page_bitmap);
214
215 // Now save the result, closing the page and document
216 EXPECT_TRUE(FPDF_SaveAsCopy(doc, this, 0));
217 FPDF_ClosePage(page);
218 FPDF_CloseDocument(doc);
219 std::string new_file = GetString();
220
221 // Render the saved result
222 FPDF_FILEACCESS file_access;
223 memset(&file_access, 0, sizeof(file_access));
224 file_access.m_FileLen = new_file.size();
225 file_access.m_GetBlock = GetBlockFromString;
226 file_access.m_Param = &new_file;
227 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
228 ASSERT_NE(nullptr, new_doc);
229 EXPECT_EQ(1, FPDF_GetPageCount(new_doc));
230 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
231 ASSERT_NE(nullptr, new_page);
232 FPDF_BITMAP new_bitmap = RenderPage(new_page);
233 CompareBitmap(new_bitmap, 612, 792, "9823e1a21bd9b72b6a442ba4f12af946");
234 FPDFBitmap_Destroy(new_bitmap);
235 FPDF_ClosePage(new_page);
236 FPDF_CloseDocument(new_doc);
237}
238
239TEST_F(FPDFEditEmbeddertest, PathOnTopOfText) {
240 // Load document with some text
241 EXPECT_TRUE(OpenDocument("hello_world.pdf"));
242 FPDF_PAGE page = LoadPage(0);
243 EXPECT_NE(nullptr, page);
244
245 // Add an opaque rectangle on top of some of the text.
246 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
247 EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255));
248 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
249 FPDFPage_InsertObject(page, red_rect);
250 EXPECT_TRUE(FPDFPage_GenerateContent(page));
251
252 // Add a transparent triangle on top of other part of the text.
253 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(20, 50);
254 EXPECT_TRUE(FPDFPath_SetFillColor(black_path, 0, 0, 0, 100));
255 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
256 EXPECT_TRUE(FPDFPath_LineTo(black_path, 30, 80));
257 EXPECT_TRUE(FPDFPath_LineTo(black_path, 40, 10));
258 EXPECT_TRUE(FPDFPath_Close(black_path));
259 FPDFPage_InsertObject(page, black_path);
260 EXPECT_TRUE(FPDFPage_GenerateContent(page));
261
262 // Render and check the result. Text is slightly different on Mac.
263 FPDF_BITMAP bitmap = RenderPage(page);
264#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
265 const char md5[] = "2f7c0deee10a9490538e195af64beb67";
266#else
267 const char md5[] = "17c942c76ff229200f2c98073bb60d85";
268#endif
269 CompareBitmap(bitmap, 200, 200, md5);
270 FPDFBitmap_Destroy(bitmap);
271 UnloadPage(page);
272}
Nicolas Pena2eb1a702017-02-09 18:17:33 -0500273
274TEST_F(FPDFEditEmbeddertest, AddStrokedPaths) {
275 // Start with a blank page
276 FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
277 FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792);
278
279 // Add a large stroked rectangle (fill color should not affect it).
280 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(20, 20, 200, 400);
281 EXPECT_TRUE(FPDFPath_SetFillColor(rect, 255, 0, 0, 255));
282 EXPECT_TRUE(FPDFPath_SetStrokeColor(rect, 0, 255, 0, 255));
283 EXPECT_TRUE(FPDFPath_SetStrokeWidth(rect, 15.0f));
284 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, 0, 1));
285 FPDFPage_InsertObject(page, rect);
286 EXPECT_TRUE(FPDFPage_GenerateContent(page));
287 FPDF_BITMAP page_bitmap = RenderPage(page);
288 CompareBitmap(page_bitmap, 612, 792, "64bd31f862a89e0a9e505a5af6efd506");
289 FPDFBitmap_Destroy(page_bitmap);
290
291 // Add crossed-checkmark
292 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(300, 500);
293 EXPECT_TRUE(FPDFPath_LineTo(check, 400, 400));
294 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 600));
295 EXPECT_TRUE(FPDFPath_MoveTo(check, 400, 600));
296 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 400));
297 EXPECT_TRUE(FPDFPath_SetStrokeColor(check, 128, 128, 128, 180));
298 EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f));
299 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
300 FPDFPage_InsertObject(page, check);
301 EXPECT_TRUE(FPDFPage_GenerateContent(page));
302 page_bitmap = RenderPage(page);
303 CompareBitmap(page_bitmap, 612, 792, "4b6f3b9d25c4e194821217d5016c3724");
304 FPDFBitmap_Destroy(page_bitmap);
305
306 // Add stroked and filled oval-ish path.
307 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(250, 100);
308 EXPECT_TRUE(FPDFPath_BezierTo(path, 180, 166, 180, 233, 250, 300));
309 EXPECT_TRUE(FPDFPath_LineTo(path, 255, 305));
310 EXPECT_TRUE(FPDFPath_BezierTo(path, 325, 233, 325, 166, 255, 105));
311 EXPECT_TRUE(FPDFPath_Close(path));
312 EXPECT_TRUE(FPDFPath_SetFillColor(path, 200, 128, 128, 100));
313 EXPECT_TRUE(FPDFPath_SetStrokeColor(path, 128, 200, 128, 150));
314 EXPECT_TRUE(FPDFPath_SetStrokeWidth(path, 10.5f));
315 EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 1));
316 FPDFPage_InsertObject(page, path);
317 EXPECT_TRUE(FPDFPage_GenerateContent(page));
318 page_bitmap = RenderPage(page);
319 CompareBitmap(page_bitmap, 612, 792, "ff3e6a22326754944cc6e56609acd73b");
320 FPDFBitmap_Destroy(page_bitmap);
321 FPDF_ClosePage(page);
322 FPDF_CloseDocument(doc);
323}
Nicolas Pena49058402017-02-14 18:26:20 -0500324
325TEST_F(FPDFEditEmbeddertest, AddStandardFontText) {
326 // Start with a blank page
327 FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
328 FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792);
329
330 // Add some text to the page
331 FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(doc, "Arial", 12.0f);
332 EXPECT_TRUE(text1);
333 EXPECT_TRUE(FPDFText_SetText(text1, "I'm at the bottom of the page"));
334 FPDFPageObj_Transform(text1, 1, 0, 0, 1, 20, 20);
335 FPDFPage_InsertObject(page, text1);
336 EXPECT_TRUE(FPDFPage_GenerateContent(page));
337 FPDF_BITMAP page_bitmap = RenderPage(page);
338#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
339 const char md5[] = "e19c90395d73cb9f37a6c3b0e8b18a9e";
340#else
341 const char md5[] = "7c3a36ba7cec01688a16a14bfed9ecfc";
342#endif
343 CompareBitmap(page_bitmap, 612, 792, md5);
344 FPDFBitmap_Destroy(page_bitmap);
345
346 // Try another font
347 FPDF_PAGEOBJECT text2 =
348 FPDFPageObj_NewTextObj(doc, "TimesNewRomanBold", 15.0f);
349 EXPECT_TRUE(text2);
350 EXPECT_TRUE(FPDFText_SetText(text2, "Hi, I'm Bold. Times New Roman Bold."));
351 FPDFPageObj_Transform(text2, 1, 0, 0, 1, 100, 600);
352 FPDFPage_InsertObject(page, text2);
353 EXPECT_TRUE(FPDFPage_GenerateContent(page));
354 page_bitmap = RenderPage(page);
355#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
356 const char md5_2[] = "8e1c43dca6be68d364dbc283f5521041";
357#else
358 const char md5_2[] = "e0e0873e3a2634a6394a431a51ce90ff";
359#endif
360 CompareBitmap(page_bitmap, 612, 792, md5_2);
361 FPDFBitmap_Destroy(page_bitmap);
362
363 // And some randomly transformed text
364 FPDF_PAGEOBJECT text3 = FPDFPageObj_NewTextObj(doc, "Courier-Bold", 20.0f);
365 EXPECT_TRUE(text3);
366 EXPECT_TRUE(FPDFText_SetText(text3, "Can you read me? <:)>"));
367 FPDFPageObj_Transform(text3, 1, 1.5, 2, 0.5, 200, 200);
368 FPDFPage_InsertObject(page, text3);
369 EXPECT_TRUE(FPDFPage_GenerateContent(page));
370 page_bitmap = RenderPage(page);
371#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
372 const char md5_3[] = "c6e5df448428793c7e4b0c820bd8c85e";
373#else
374 const char md5_3[] = "903ee10b6a9f0be51ecad0a1a0eeb171";
375#endif
376 CompareBitmap(page_bitmap, 612, 792, md5_3);
377 FPDFBitmap_Destroy(page_bitmap);
378
379 // TODO(npm): Why are there issues with text rotated by 90 degrees?
380 // TODO(npm): FPDF_SaveAsCopy not giving the desired result after this.
381 FPDF_ClosePage(page);
382 FPDF_CloseDocument(doc);
383}
Nicolas Penaa4ad01f2017-02-15 16:26:48 -0500384
385TEST_F(FPDFEditEmbeddertest, DoubleGenerating) {
386 // Start with a blank page
387 FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
388 FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792);
389
390 // Add a red rectangle with some non-default alpha
391 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
392 EXPECT_TRUE(FPDFPath_SetFillColor(rect, 255, 0, 0, 128));
393 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, FPDF_FILLMODE_WINDING, 0));
394 FPDFPage_InsertObject(page, rect);
395 EXPECT_TRUE(FPDFPage_GenerateContent(page));
396
397 // Check the ExtGState
398 CPDF_Page* the_page = CPDFPageFromFPDFPage(page);
399 CPDF_Dictionary* graphics_dict =
400 the_page->m_pResources->GetDictFor("ExtGState");
401 ASSERT_TRUE(graphics_dict);
402 EXPECT_EQ(1, static_cast<int>(graphics_dict->GetCount()));
403
404 // Check the bitmap
405 FPDF_BITMAP page_bitmap = RenderPage(page);
406 CompareBitmap(page_bitmap, 612, 792, "5384da3406d62360ffb5cac4476fff1c");
407 FPDFBitmap_Destroy(page_bitmap);
408
409 // Never mind, my new favorite color is blue, increase alpha
410 EXPECT_TRUE(FPDFPath_SetFillColor(rect, 0, 0, 255, 180));
411 EXPECT_TRUE(FPDFPage_GenerateContent(page));
412 EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
413
414 // Check that bitmap displays changed content
415 page_bitmap = RenderPage(page);
416 CompareBitmap(page_bitmap, 612, 792, "2e51656f5073b0bee611d9cd086aa09c");
417 FPDFBitmap_Destroy(page_bitmap);
418
419 // And now generate, without changes
420 EXPECT_TRUE(FPDFPage_GenerateContent(page));
421 EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
422 page_bitmap = RenderPage(page);
423 CompareBitmap(page_bitmap, 612, 792, "2e51656f5073b0bee611d9cd086aa09c");
424 FPDFBitmap_Destroy(page_bitmap);
425
426 // Add some text to the page
427 FPDF_PAGEOBJECT text = FPDFPageObj_NewTextObj(doc, "Arial", 12.0f);
428 EXPECT_TRUE(FPDFText_SetText(text, "Something something #text# something"));
429 FPDFPageObj_Transform(text, 1, 0, 0, 1, 300, 300);
430 FPDFPage_InsertObject(page, text);
431 EXPECT_TRUE(FPDFPage_GenerateContent(page));
432 CPDF_Dictionary* font_dict = the_page->m_pResources->GetDictFor("Font");
433 ASSERT_TRUE(font_dict);
434 EXPECT_EQ(1, static_cast<int>(font_dict->GetCount()));
435
436 // Generate yet again, check dicts are reasonably sized
437 EXPECT_TRUE(FPDFPage_GenerateContent(page));
438 EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
439 EXPECT_EQ(1, static_cast<int>(font_dict->GetCount()));
440 FPDF_ClosePage(page);
441 FPDF_CloseDocument(doc);
442}