blob: c08460e7458813edcee2177a93bfe3ddac8246dc [file] [log] [blame]
Jane Liu4fd9a472017-06-01 18:56:09 -04001// Copyright 2017 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
Jane Liu20eafda2017-06-07 10:33:24 -04005#include <memory>
6#include <string>
Jane Liu4fd9a472017-06-01 18:56:09 -04007#include <vector>
8
Jane Liubaa7ff42017-06-29 19:18:23 -04009#include "core/fxcrt/fx_system.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040010#include "public/fpdf_annot.h"
Jane Liubaa7ff42017-06-29 19:18:23 -040011#include "public/fpdf_edit.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040012#include "public/fpdfview.h"
13#include "testing/embedder_test.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
Jane Liu20eafda2017-06-07 10:33:24 -040016class FPDFAnnotEmbeddertest : public EmbedderTest, public TestSaver {};
Jane Liu4fd9a472017-06-01 18:56:09 -040017
Jane Liue17011d2017-06-21 12:18:37 -040018TEST_F(FPDFAnnotEmbeddertest, RenderAnnotWithOnlyRolloverAP) {
19 // Open a file with one annotation and load its first page.
20 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
21 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
22 ASSERT_TRUE(page);
23
24 // This annotation has a malformed appearance stream, which does not have its
25 // normal appearance defined, only its rollover appearance. In this case, its
26 // normal appearance should be generated, allowing the highlight annotation to
27 // still display.
Jane Liubaa7ff42017-06-29 19:18:23 -040028 FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liue17011d2017-06-21 12:18:37 -040029 CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
30 FPDFBitmap_Destroy(bitmap);
31
32 UnloadPage(page);
33}
34
Jane Liu4fd9a472017-06-01 18:56:09 -040035TEST_F(FPDFAnnotEmbeddertest, ExtractHighlightLongContent) {
36 // Open a file with one annotation and load its first page.
37 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
38 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
39 ASSERT_TRUE(page);
40
41 // Check that there is a total of 1 annotation on its first page.
42 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
43
44 // Check that the annotation is of type "highlight".
Jane Liud60e9ad2017-06-26 11:28:36 -040045 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
46 ASSERT_TRUE(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -040047 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
48
49 // Check that the annotation color is yellow.
50 unsigned int R;
51 unsigned int G;
52 unsigned int B;
53 unsigned int A;
54 EXPECT_TRUE(
55 FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
56 EXPECT_EQ(255u, R);
57 EXPECT_EQ(255u, G);
58 EXPECT_EQ(0u, B);
59 EXPECT_EQ(255u, A);
60
61 // Check that the author is correct.
62 unsigned long len =
63 FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Author, nullptr, 0);
64 std::vector<char> buf(len);
65 EXPECT_EQ(28u, FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Author, buf.data(),
66 len));
67 EXPECT_STREQ(L"Jae Hyun Park",
68 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
69 .c_str());
70
71 // Check that the content is correct.
72 len = FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Contents, nullptr, 0);
73 buf.clear();
74 buf.resize(len);
75 EXPECT_EQ(2690u, FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Contents,
76 buf.data(), len));
77 const wchar_t contents[] =
78 L"This is a note for that highlight annotation. Very long highlight "
79 "annotation. Long long long Long long longLong long longLong long "
80 "longLong long longLong long longLong long longLong long longLong long "
81 "longLong long longLong long longLong long longLong long longLong long "
82 "longLong long longLong long longLong long longLong long longLong long "
83 "longLong long longLong long longLong long longLong long longLong long "
84 "longLong long longLong long longLong long longLong long longLong long "
85 "longLong long longLong long longLong long longLong long longLong long "
86 "longLong long longLong long longLong long longLong long longLong long "
87 "longLong long longLong long longLong long longLong long longLong long "
88 "longLong long longLong long longLong long longLong long longLong long "
89 "longLong long longLong long longLong long longLong long longLong long "
90 "longLong long longLong long longLong long longLong long longLong long "
91 "longLong long longLong long longLong long longLong long longLong long "
92 "longLong long longLong long longLong long longLong long longLong long "
93 "longLong long longLong long longLong long longLong long longLong long "
94 "longLong long longLong long longLong long longLong long longLong long "
95 "longLong long longLong long longLong long longLong long longLong long "
96 "longLong long longLong long longLong long longLong long longLong long "
97 "longLong long long. END";
98 EXPECT_STREQ(contents,
99 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
100 .c_str());
101
102 // Check that the quadpoints are correct.
Jane Liud60e9ad2017-06-26 11:28:36 -0400103 FS_QUADPOINTSF quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400104 EXPECT_EQ(115.802643f, quadpoints.x1);
105 EXPECT_EQ(718.913940f, quadpoints.y1);
106 EXPECT_EQ(157.211182f, quadpoints.x4);
107 EXPECT_EQ(706.264465f, quadpoints.y4);
108
Jane Liue10509a2017-06-20 16:47:41 -0400109 FPDFPage_CloseAnnot(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400110 UnloadPage(page);
111}
112
113TEST_F(FPDFAnnotEmbeddertest, ExtractInkMultiple) {
114 // Open a file with three annotations and load its first page.
115 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
116 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
117 ASSERT_TRUE(page);
118
119 // Check that there is a total of 3 annotation on its first page.
120 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
121
Jane Liu20eafda2017-06-07 10:33:24 -0400122 // Check that the third annotation is of type "ink".
Jane Liud60e9ad2017-06-26 11:28:36 -0400123 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 2);
124 ASSERT_TRUE(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400125 EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot));
126
127 // Check that the annotation color is blue with opacity.
128 unsigned int R;
129 unsigned int G;
130 unsigned int B;
131 unsigned int A;
132 EXPECT_TRUE(
133 FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
134 EXPECT_EQ(0u, R);
135 EXPECT_EQ(0u, G);
136 EXPECT_EQ(255u, B);
137 EXPECT_EQ(76u, A);
138
139 // Check that there is no content.
140 EXPECT_EQ(2u,
141 FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Contents, nullptr, 0));
142
143 // Check that the rectange coordinates are correct.
144 // Note that upon rendering, the rectangle coordinates will be adjusted.
Jane Liud60e9ad2017-06-26 11:28:36 -0400145 FS_RECTF rect = FPDFAnnot_GetRect(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400146 EXPECT_EQ(351.820404f, rect.left);
147 EXPECT_EQ(583.830688f, rect.bottom);
148 EXPECT_EQ(475.336090f, rect.right);
149 EXPECT_EQ(681.535034f, rect.top);
150
Jane Liue10509a2017-06-20 16:47:41 -0400151 FPDFPage_CloseAnnot(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400152 UnloadPage(page);
153}
Jane Liu20eafda2017-06-07 10:33:24 -0400154
155TEST_F(FPDFAnnotEmbeddertest, AddIllegalSubtypeAnnotation) {
156 // Open a file with one annotation and load its first page.
157 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
158 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
159 ASSERT_TRUE(page);
160
161 // Add an annotation with an illegal subtype.
Jane Liud60e9ad2017-06-26 11:28:36 -0400162 ASSERT_FALSE(FPDFPage_CreateAnnot(page, -1));
Jane Liu20eafda2017-06-07 10:33:24 -0400163
164 UnloadPage(page);
165}
166
Jane Liud321ef92017-06-14 09:56:22 -0400167TEST_F(FPDFAnnotEmbeddertest, AddFirstTextAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400168 // Open a file with no annotation and load its first page.
169 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
170 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
171 ASSERT_TRUE(page);
172 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
173
Jane Liueda65252017-06-07 11:31:27 -0400174 // Add a text annotation to the page.
Jane Liud60e9ad2017-06-26 11:28:36 -0400175 FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT);
176 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400177
178 // Check that there is now 1 annotations on this page.
179 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
180
181 // Check that the subtype of the annotation is correct.
182 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot));
Jane Liue10509a2017-06-20 16:47:41 -0400183 FPDFPage_CloseAnnot(annot);
184
Jane Liud60e9ad2017-06-26 11:28:36 -0400185 annot = FPDFPage_GetAnnot(page, 0);
186 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400187 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot));
188
189 // Set the color of the annotation.
190 ASSERT_TRUE(
191 FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204));
192 // Check that the color has been set correctly.
193 unsigned int R;
194 unsigned int G;
195 unsigned int B;
196 unsigned int A;
197 EXPECT_TRUE(
198 FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
199 EXPECT_EQ(51u, R);
200 EXPECT_EQ(102u, G);
201 EXPECT_EQ(153u, B);
202 EXPECT_EQ(204u, A);
203
204 // Change the color of the annotation.
205 ASSERT_TRUE(
206 FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 204, 153, 102, 51));
207 // Check that the color has been set correctly.
208 EXPECT_TRUE(
209 FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
210 EXPECT_EQ(204u, R);
211 EXPECT_EQ(153u, G);
212 EXPECT_EQ(102u, B);
213 EXPECT_EQ(51u, A);
214
215 // Set the annotation rectangle.
Jane Liud60e9ad2017-06-26 11:28:36 -0400216 FS_RECTF rect = FPDFAnnot_GetRect(annot);
217 EXPECT_EQ(0.f, rect.left);
218 EXPECT_EQ(0.f, rect.right);
Jane Liu20eafda2017-06-07 10:33:24 -0400219 rect.left = 35;
220 rect.bottom = 150;
221 rect.right = 53;
222 rect.top = 165;
Jane Liu06462752017-06-27 16:41:14 -0400223 ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
Jane Liu20eafda2017-06-07 10:33:24 -0400224 // Check that the annotation rectangle has been set correctly.
Jane Liud60e9ad2017-06-26 11:28:36 -0400225 rect = FPDFAnnot_GetRect(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400226 EXPECT_EQ(35.f, rect.left);
227 EXPECT_EQ(150.f, rect.bottom);
228 EXPECT_EQ(53.f, rect.right);
229 EXPECT_EQ(165.f, rect.top);
230
231 // Set the content of the annotation.
232 const wchar_t contents[] = L"Hello! This is a customized content.";
233 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
234 GetFPDFWideString(contents);
235 ASSERT_TRUE(
236 FPDFAnnot_SetText(annot, FPDFANNOT_TEXTTYPE_Contents, text.get()));
237 // Check that the content has been set correctly.
238 unsigned long len =
239 FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Contents, nullptr, 0);
240 std::vector<char> buf(len);
241 EXPECT_EQ(74u, FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Contents,
242 buf.data(), len));
243 EXPECT_STREQ(contents,
244 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
245 .c_str());
246
Jane Liue10509a2017-06-20 16:47:41 -0400247 FPDFPage_CloseAnnot(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400248 UnloadPage(page);
249}
250
251TEST_F(FPDFAnnotEmbeddertest, AddAndSaveUnderlineAnnotation) {
252 // Open a file with one annotation and load its first page.
253 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
254 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
255 ASSERT_TRUE(page);
256
257 // Check that there is a total of one annotation on its first page, and verify
258 // its quadpoints.
259 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Jane Liud60e9ad2017-06-26 11:28:36 -0400260 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
261 ASSERT_TRUE(annot);
262 FS_QUADPOINTSF quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400263 EXPECT_EQ(115.802643f, quadpoints.x1);
264 EXPECT_EQ(718.913940f, quadpoints.y1);
265 EXPECT_EQ(157.211182f, quadpoints.x4);
266 EXPECT_EQ(706.264465f, quadpoints.y4);
Jane Liue10509a2017-06-20 16:47:41 -0400267 FPDFPage_CloseAnnot(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400268
269 // Add an underline annotation to the page and set its quadpoints.
Jane Liud60e9ad2017-06-26 11:28:36 -0400270 annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE);
271 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400272 quadpoints.x1 = 140.802643f;
273 quadpoints.x3 = 140.802643f;
Jane Liu06462752017-06-27 16:41:14 -0400274 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
Jane Liue10509a2017-06-20 16:47:41 -0400275 FPDFPage_CloseAnnot(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400276
277 // Save the document, closing the page and document.
278 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
279 FPDF_ClosePage(page);
280
281 // Open the saved document.
282 std::string new_file = GetString();
283 FPDF_FILEACCESS file_access;
284 memset(&file_access, 0, sizeof(file_access));
285 file_access.m_FileLen = new_file.size();
286 file_access.m_GetBlock = GetBlockFromString;
287 file_access.m_Param = &new_file;
288 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
289 ASSERT_TRUE(new_doc);
290 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
291 ASSERT_TRUE(new_page);
292
293 // Check that the saved document has 2 annotations on the first page
294 EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
295
296 // Check that the second annotation is an underline annotation and verify
297 // its quadpoints.
Jane Liud60e9ad2017-06-26 11:28:36 -0400298 FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(new_page, 1);
299 ASSERT_TRUE(new_annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400300 EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot));
Jane Liud60e9ad2017-06-26 11:28:36 -0400301 FS_QUADPOINTSF new_quadpoints = FPDFAnnot_GetAttachmentPoints(new_annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400302 EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f);
303 EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f);
304 EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f);
305 EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f);
306
Jane Liue10509a2017-06-20 16:47:41 -0400307 FPDFPage_CloseAnnot(new_annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400308 FPDF_ClosePage(new_page);
309 FPDF_CloseDocument(new_doc);
310}
Jane Liu06462752017-06-27 16:41:14 -0400311
312TEST_F(FPDFAnnotEmbeddertest, ModifyRectQuadpointsWithAP) {
313 // Open a file with four annotations and load its first page.
314 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
315 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
316 ASSERT_TRUE(page);
317 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
318
319 // Retrieve the highlight annotation which has its AP stream already defined.
320 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
321 ASSERT_TRUE(annot);
322 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
323
324 // Check that color cannot be set when an AP stream is defined already.
325 EXPECT_FALSE(
326 FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204));
327
328 // Check that when getting the attachment points, bounding box points are
329 // returned since this is a markup annotation with AP defined.
330 FS_QUADPOINTSF quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
331 EXPECT_NEAR(0.f, quadpoints.x1, 0.001f);
332 EXPECT_NEAR(16.9955f, quadpoints.y1, 0.001f);
333 EXPECT_NEAR(68.5953f, quadpoints.x4, 0.001f);
334 EXPECT_NEAR(0.f, quadpoints.y4, 0.001f);
335
336 // Check that when new attachment points define a smaller bounding box, the
337 // bounding box does not get updated.
338 quadpoints.x1 = 1.0f;
339 quadpoints.x3 = 1.0f;
340 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
341 FS_QUADPOINTSF new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
342 EXPECT_NE(quadpoints.x1, new_quadpoints.x1);
343
344 // Check that the bounding box gets updated successfully when valid attachment
345 // points are set.
346 quadpoints.x1 = 0.f;
347 quadpoints.y1 = 721.792f;
348 quadpoints.x2 = 133.055f;
349 quadpoints.y2 = 721.792f;
350 quadpoints.x3 = 0.f;
351 quadpoints.x4 = 133.055f;
352 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
353 new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
354 EXPECT_EQ(quadpoints.x1, new_quadpoints.x1);
355 EXPECT_EQ(quadpoints.y1, new_quadpoints.y1);
356 EXPECT_EQ(quadpoints.x4, new_quadpoints.x4);
357 EXPECT_EQ(quadpoints.y4, new_quadpoints.y4);
358
359 // Check that when getting the annotation rectangle, rectangle points are
360 // returned, but not bounding box points.
361 FS_RECTF rect = FPDFAnnot_GetRect(annot);
362 EXPECT_NEAR(67.7299f, rect.left, 0.001f);
363 EXPECT_NEAR(704.296f, rect.bottom, 0.001f);
364 EXPECT_NEAR(136.325f, rect.right, 0.001f);
365 EXPECT_NEAR(721.292f, rect.top, 0.001f);
366
367 // Check that the rectangle gets updated successfully when a valid rectangle
368 // is set, and that the bounding box is not modified.
369 rect.left = 0.f;
370 rect.bottom = 0.f;
371 rect.right = 134.055f;
372 rect.top = 722.792f;
373 ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
374 FS_RECTF new_rect = FPDFAnnot_GetRect(annot);
375 EXPECT_EQ(rect.right, new_rect.right);
376 new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
377 EXPECT_NE(rect.right, new_quadpoints.x2);
378
379 FPDFPage_CloseAnnot(annot);
380
381 // Retrieve the square annotation which has its AP stream already defined.
382 annot = FPDFPage_GetAnnot(page, 2);
383 ASSERT_TRUE(annot);
384 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot));
385
386 // Check that the rectangle and the bounding box get updated successfully when
387 // a valid rectangle is set, since this is not a markup annotation.
388 rect = FPDFAnnot_GetRect(annot);
389 rect.right += 1.f;
390 ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
391 new_rect = FPDFAnnot_GetRect(annot);
392 EXPECT_EQ(rect.right, new_rect.right);
393
394 FPDFPage_CloseAnnot(annot);
395 UnloadPage(page);
396}
Jane Liu8ce58f52017-06-29 13:40:22 -0400397
398TEST_F(FPDFAnnotEmbeddertest, RemoveAnnotation) {
399 // Open a file with 3 annotations on its first page.
400 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
401 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
402 ASSERT_TRUE(page);
403 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
404
405 // Check that the annotations have the expected rectangle coordinates.
406 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
407 FS_RECTF rect = FPDFAnnot_GetRect(annot);
408 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
409 FPDFPage_CloseAnnot(annot);
410
411 annot = FPDFPage_GetAnnot(page, 1);
412 rect = FPDFAnnot_GetRect(annot);
413 EXPECT_NEAR(149.8127f, rect.left, 0.001f);
414 FPDFPage_CloseAnnot(annot);
415
416 annot = FPDFPage_GetAnnot(page, 2);
417 rect = FPDFAnnot_GetRect(annot);
418 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
419 FPDFPage_CloseAnnot(annot);
420
421 // Check that nothing happens when attempting to remove an annotation with an
422 // out-of-bound index.
423 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4));
424 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1));
425 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
426
427 // Remove the second annotation.
428 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
429 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
430 EXPECT_FALSE(FPDFPage_GetAnnot(page, 2));
431
432 // Save the document, closing the page and document.
433 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
434 FPDF_ClosePage(page);
435
436 // Open the saved document.
437 std::string new_file = GetString();
438 FPDF_FILEACCESS file_access;
439 memset(&file_access, 0, sizeof(file_access));
440 file_access.m_FileLen = new_file.size();
441 file_access.m_GetBlock = GetBlockFromString;
442 file_access.m_Param = &new_file;
443 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
444 ASSERT_TRUE(new_doc);
445 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
446 ASSERT_TRUE(new_page);
447
448 // Check that the saved document has 2 annotations on the first page.
449 EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
450
451 // Check that the remaining 2 annotations are the original 1st and 3rd ones by
452 // verifying their rectangle coordinates.
453 annot = FPDFPage_GetAnnot(new_page, 0);
454 rect = FPDFAnnot_GetRect(annot);
455 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
456 FPDFPage_CloseAnnot(annot);
457
458 annot = FPDFPage_GetAnnot(new_page, 1);
459 rect = FPDFAnnot_GetRect(annot);
460 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
461 FPDFPage_CloseAnnot(annot);
Jane Liubaa7ff42017-06-29 19:18:23 -0400462 FPDF_ClosePage(new_page);
463 FPDF_CloseDocument(new_doc);
464}
Jane Liu8ce58f52017-06-29 13:40:22 -0400465
Jane Liubaa7ff42017-06-29 19:18:23 -0400466TEST_F(FPDFAnnotEmbeddertest, AddAndModifyPath) {
467#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
468 const char md5[] = "c35408717759562d1f8bf33d317483d2";
469 const char md5_2[] = "cf3cea74bd46497520ff6c4d1ea228c8";
470 const char md5_3[] = "ee5372b31fede117fc83b9384598aa25";
471#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
472 const char md5[] = "bdf96279ab82d9f484874db3f0c03429";
473 const char md5_2[] = "5f2b32b7aa93bc1e62a7a7971f54bdd7";
474 const char md5_3[] = "272661f3e5c9516aac4b5beb3ae1b36a";
475#else
476 const char md5[] = "07d4168715553b4294525f840c40aa1c";
477 const char md5_2[] = "dd5ba8996af67d0e5add418195e4d61b";
478 const char md5_3[] = "c60c2cc2c4e7b13be90bd77cc4502f97";
479#endif
480
481 // Open a file with two annotations and load its first page.
482 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
483 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
484 ASSERT_TRUE(page);
485 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
486
487 // Check that the page renders correctly.
488 FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
489 CompareBitmap(bitmap, 595, 842, md5);
490 FPDFBitmap_Destroy(bitmap);
491
492 // Retrieve the stamp annotation which has its AP stream already defined.
493 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
494 ASSERT_TRUE(annot);
495
496 // Check that this annotation has one path object and retrieve it.
497 EXPECT_EQ(1, FPDFAnnot_GetPathObjectCount(annot));
498 FPDF_PAGEOBJECT path = FPDFAnnot_GetPathObject(annot, 1);
499 EXPECT_FALSE(path);
500 path = FPDFAnnot_GetPathObject(annot, 0);
501 EXPECT_TRUE(path);
502
503 // Modify the color of the path object.
504 EXPECT_TRUE(FPDFPath_SetStrokeColor(path, 0, 0, 0, 255));
505 EXPECT_TRUE(FPDFAnnot_UpdatePathObject(annot, path));
506 FPDFPage_CloseAnnot(annot);
507
508 // Check that the page with the modified annotation renders correctly.
509 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
510 CompareBitmap(bitmap, 595, 842, md5_2);
511 FPDFBitmap_Destroy(bitmap);
512
513 // Create another stamp annotation and set its annotation rectangle.
514 annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP);
515 ASSERT_TRUE(annot);
516 FS_RECTF rect;
517 rect.left = 200.f;
518 rect.bottom = 400.f;
519 rect.right = 500.f;
520 rect.top = 600.f;
521 EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect));
522
523 // Add a new path to the annotation.
524 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500);
525 EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400));
526 EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600));
527 EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550));
528 EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450));
529 EXPECT_TRUE(FPDFPath_SetStrokeColor(check, 0, 255, 255, 180));
530 EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f));
531 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
532 EXPECT_TRUE(FPDFAnnot_AppendPathObject(annot, check));
533 EXPECT_EQ(1, FPDFAnnot_GetPathObjectCount(annot));
534
535 // Check that the annotation's bounding box came from its rectangle.
536 FS_RECTF new_rect = FPDFAnnot_GetRect(annot);
537 EXPECT_EQ(rect.left, new_rect.left);
538 EXPECT_EQ(rect.bottom, new_rect.bottom);
539 EXPECT_EQ(rect.right, new_rect.right);
540 EXPECT_EQ(rect.top, new_rect.top);
541
542 // Save the document, closing the page and document.
543 FPDFPage_CloseAnnot(annot);
544 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
545 FPDF_ClosePage(page);
546
547 // Open the saved document.
548 std::string new_file = GetString();
549 FPDF_FILEACCESS file_access;
550 memset(&file_access, 0, sizeof(file_access));
551 file_access.m_FileLen = new_file.size();
552 file_access.m_GetBlock = GetBlockFromString;
553 file_access.m_Param = &new_file;
554 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
555 ASSERT_TRUE(new_doc);
556 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
557 ASSERT_TRUE(new_page);
558
559 // Check that the saved document has a correct count of annotations and paths.
560 EXPECT_EQ(3, FPDFPage_GetAnnotCount(new_page));
561 annot = FPDFPage_GetAnnot(new_page, 2);
562 ASSERT_TRUE(annot);
563 EXPECT_EQ(1, FPDFAnnot_GetPathObjectCount(annot));
564
565 // Check that the new annotation's rectangle is as defined.
566 new_rect = FPDFAnnot_GetRect(annot);
567 EXPECT_EQ(rect.left, new_rect.left);
568 EXPECT_EQ(rect.bottom, new_rect.bottom);
569 EXPECT_EQ(rect.right, new_rect.right);
570 EXPECT_EQ(rect.top, new_rect.top);
571
572 // Check that the saved page renders correctly.
573 bitmap = RenderPageWithFlags(new_page, nullptr, FPDF_ANNOT);
574 CompareBitmap(bitmap, 595, 842, md5_3);
575 FPDFBitmap_Destroy(bitmap);
576
577 FPDFPage_CloseAnnot(annot);
Jane Liu8ce58f52017-06-29 13:40:22 -0400578 FPDF_ClosePage(new_page);
579 FPDF_CloseDocument(new_doc);
580}