blob: beaedf91af3a974e4b52844655f1f28ff5a07dba [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
Nicolas Pena3ff54002017-07-05 11:55:35 -040016class FPDFAnnotEmbeddertest : public EmbedderTest {};
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.
Nicolas Pena3ff54002017-07-05 11:55:35 -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.
Nicolas Pena3ff54002017-07-05 11:55:35 -0400282 const char md5[] = "184b67b322edaee27994b3232544b8b3";
283 TestSaved(612, 792, md5);
Jane Liu20eafda2017-06-07 10:33:24 -0400284
285 // Check that the saved document has 2 annotations on the first page
Nicolas Pena3ff54002017-07-05 11:55:35 -0400286 EXPECT_EQ(2, FPDFPage_GetAnnotCount(m_SavedPage));
Jane Liu20eafda2017-06-07 10:33:24 -0400287
288 // Check that the second annotation is an underline annotation and verify
289 // its quadpoints.
Nicolas Pena3ff54002017-07-05 11:55:35 -0400290 FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(m_SavedPage, 1);
Jane Liud60e9ad2017-06-26 11:28:36 -0400291 ASSERT_TRUE(new_annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400292 EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot));
Jane Liud60e9ad2017-06-26 11:28:36 -0400293 FS_QUADPOINTSF new_quadpoints = FPDFAnnot_GetAttachmentPoints(new_annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400294 EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f);
295 EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f);
296 EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f);
297 EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f);
298
Jane Liue10509a2017-06-20 16:47:41 -0400299 FPDFPage_CloseAnnot(new_annot);
Nicolas Pena3ff54002017-07-05 11:55:35 -0400300 CloseSaved();
Jane Liu20eafda2017-06-07 10:33:24 -0400301}
Jane Liu06462752017-06-27 16:41:14 -0400302
303TEST_F(FPDFAnnotEmbeddertest, ModifyRectQuadpointsWithAP) {
304 // Open a file with four annotations and load its first page.
305 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
306 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
307 ASSERT_TRUE(page);
308 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
309
310 // Retrieve the highlight annotation which has its AP stream already defined.
311 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
312 ASSERT_TRUE(annot);
313 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
314
315 // Check that color cannot be set when an AP stream is defined already.
316 EXPECT_FALSE(
317 FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204));
318
319 // Check that when getting the attachment points, bounding box points are
320 // returned since this is a markup annotation with AP defined.
321 FS_QUADPOINTSF quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
322 EXPECT_NEAR(0.f, quadpoints.x1, 0.001f);
323 EXPECT_NEAR(16.9955f, quadpoints.y1, 0.001f);
324 EXPECT_NEAR(68.5953f, quadpoints.x4, 0.001f);
325 EXPECT_NEAR(0.f, quadpoints.y4, 0.001f);
326
327 // Check that when new attachment points define a smaller bounding box, the
328 // bounding box does not get updated.
329 quadpoints.x1 = 1.0f;
330 quadpoints.x3 = 1.0f;
331 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
332 FS_QUADPOINTSF new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
333 EXPECT_NE(quadpoints.x1, new_quadpoints.x1);
334
335 // Check that the bounding box gets updated successfully when valid attachment
336 // points are set.
337 quadpoints.x1 = 0.f;
338 quadpoints.y1 = 721.792f;
339 quadpoints.x2 = 133.055f;
340 quadpoints.y2 = 721.792f;
341 quadpoints.x3 = 0.f;
342 quadpoints.x4 = 133.055f;
343 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
344 new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
345 EXPECT_EQ(quadpoints.x1, new_quadpoints.x1);
346 EXPECT_EQ(quadpoints.y1, new_quadpoints.y1);
347 EXPECT_EQ(quadpoints.x4, new_quadpoints.x4);
348 EXPECT_EQ(quadpoints.y4, new_quadpoints.y4);
349
350 // Check that when getting the annotation rectangle, rectangle points are
351 // returned, but not bounding box points.
352 FS_RECTF rect = FPDFAnnot_GetRect(annot);
353 EXPECT_NEAR(67.7299f, rect.left, 0.001f);
354 EXPECT_NEAR(704.296f, rect.bottom, 0.001f);
355 EXPECT_NEAR(136.325f, rect.right, 0.001f);
356 EXPECT_NEAR(721.292f, rect.top, 0.001f);
357
358 // Check that the rectangle gets updated successfully when a valid rectangle
359 // is set, and that the bounding box is not modified.
360 rect.left = 0.f;
361 rect.bottom = 0.f;
362 rect.right = 134.055f;
363 rect.top = 722.792f;
364 ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
365 FS_RECTF new_rect = FPDFAnnot_GetRect(annot);
366 EXPECT_EQ(rect.right, new_rect.right);
367 new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
368 EXPECT_NE(rect.right, new_quadpoints.x2);
369
370 FPDFPage_CloseAnnot(annot);
371
372 // Retrieve the square annotation which has its AP stream already defined.
373 annot = FPDFPage_GetAnnot(page, 2);
374 ASSERT_TRUE(annot);
375 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot));
376
377 // Check that the rectangle and the bounding box get updated successfully when
378 // a valid rectangle is set, since this is not a markup annotation.
379 rect = FPDFAnnot_GetRect(annot);
380 rect.right += 1.f;
381 ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
382 new_rect = FPDFAnnot_GetRect(annot);
383 EXPECT_EQ(rect.right, new_rect.right);
384
385 FPDFPage_CloseAnnot(annot);
386 UnloadPage(page);
387}
Jane Liu8ce58f52017-06-29 13:40:22 -0400388
389TEST_F(FPDFAnnotEmbeddertest, RemoveAnnotation) {
390 // Open a file with 3 annotations on its first page.
391 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
392 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
393 ASSERT_TRUE(page);
394 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
395
396 // Check that the annotations have the expected rectangle coordinates.
397 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
398 FS_RECTF rect = FPDFAnnot_GetRect(annot);
399 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
400 FPDFPage_CloseAnnot(annot);
401
402 annot = FPDFPage_GetAnnot(page, 1);
403 rect = FPDFAnnot_GetRect(annot);
404 EXPECT_NEAR(149.8127f, rect.left, 0.001f);
405 FPDFPage_CloseAnnot(annot);
406
407 annot = FPDFPage_GetAnnot(page, 2);
408 rect = FPDFAnnot_GetRect(annot);
409 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
410 FPDFPage_CloseAnnot(annot);
411
412 // Check that nothing happens when attempting to remove an annotation with an
413 // out-of-bound index.
414 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4));
415 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1));
416 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
417
418 // Remove the second annotation.
419 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
420 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
421 EXPECT_FALSE(FPDFPage_GetAnnot(page, 2));
422
423 // Save the document, closing the page and document.
424 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
425 FPDF_ClosePage(page);
426
Nicolas Pena3ff54002017-07-05 11:55:35 -0400427 // TODO(npm): TestSaved changes annot rect dimensions by 1??
Jane Liu8ce58f52017-06-29 13:40:22 -0400428 // Open the saved document.
429 std::string new_file = GetString();
430 FPDF_FILEACCESS file_access;
431 memset(&file_access, 0, sizeof(file_access));
432 file_access.m_FileLen = new_file.size();
433 file_access.m_GetBlock = GetBlockFromString;
434 file_access.m_Param = &new_file;
435 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
436 ASSERT_TRUE(new_doc);
437 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
438 ASSERT_TRUE(new_page);
439
440 // Check that the saved document has 2 annotations on the first page.
441 EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
442
443 // Check that the remaining 2 annotations are the original 1st and 3rd ones by
444 // verifying their rectangle coordinates.
445 annot = FPDFPage_GetAnnot(new_page, 0);
446 rect = FPDFAnnot_GetRect(annot);
447 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
448 FPDFPage_CloseAnnot(annot);
449
450 annot = FPDFPage_GetAnnot(new_page, 1);
451 rect = FPDFAnnot_GetRect(annot);
452 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
453 FPDFPage_CloseAnnot(annot);
Jane Liubaa7ff42017-06-29 19:18:23 -0400454 FPDF_ClosePage(new_page);
455 FPDF_CloseDocument(new_doc);
456}
Jane Liu8ce58f52017-06-29 13:40:22 -0400457
Jane Liubaa7ff42017-06-29 19:18:23 -0400458TEST_F(FPDFAnnotEmbeddertest, AddAndModifyPath) {
459#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
460 const char md5[] = "c35408717759562d1f8bf33d317483d2";
461 const char md5_2[] = "cf3cea74bd46497520ff6c4d1ea228c8";
462 const char md5_3[] = "ee5372b31fede117fc83b9384598aa25";
463#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
464 const char md5[] = "bdf96279ab82d9f484874db3f0c03429";
465 const char md5_2[] = "5f2b32b7aa93bc1e62a7a7971f54bdd7";
466 const char md5_3[] = "272661f3e5c9516aac4b5beb3ae1b36a";
467#else
468 const char md5[] = "07d4168715553b4294525f840c40aa1c";
469 const char md5_2[] = "dd5ba8996af67d0e5add418195e4d61b";
470 const char md5_3[] = "c60c2cc2c4e7b13be90bd77cc4502f97";
471#endif
472
473 // Open a file with two annotations and load its first page.
474 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
475 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
476 ASSERT_TRUE(page);
477 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
478
479 // Check that the page renders correctly.
480 FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
481 CompareBitmap(bitmap, 595, 842, md5);
482 FPDFBitmap_Destroy(bitmap);
483
484 // Retrieve the stamp annotation which has its AP stream already defined.
485 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
486 ASSERT_TRUE(annot);
487
488 // Check that this annotation has one path object and retrieve it.
489 EXPECT_EQ(1, FPDFAnnot_GetPathObjectCount(annot));
490 FPDF_PAGEOBJECT path = FPDFAnnot_GetPathObject(annot, 1);
491 EXPECT_FALSE(path);
492 path = FPDFAnnot_GetPathObject(annot, 0);
493 EXPECT_TRUE(path);
494
495 // Modify the color of the path object.
496 EXPECT_TRUE(FPDFPath_SetStrokeColor(path, 0, 0, 0, 255));
497 EXPECT_TRUE(FPDFAnnot_UpdatePathObject(annot, path));
498 FPDFPage_CloseAnnot(annot);
499
500 // Check that the page with the modified annotation renders correctly.
501 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
502 CompareBitmap(bitmap, 595, 842, md5_2);
503 FPDFBitmap_Destroy(bitmap);
504
505 // Create another stamp annotation and set its annotation rectangle.
506 annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP);
507 ASSERT_TRUE(annot);
508 FS_RECTF rect;
509 rect.left = 200.f;
510 rect.bottom = 400.f;
511 rect.right = 500.f;
512 rect.top = 600.f;
513 EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect));
514
515 // Add a new path to the annotation.
516 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500);
517 EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400));
518 EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600));
519 EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550));
520 EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450));
521 EXPECT_TRUE(FPDFPath_SetStrokeColor(check, 0, 255, 255, 180));
522 EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f));
523 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
524 EXPECT_TRUE(FPDFAnnot_AppendPathObject(annot, check));
525 EXPECT_EQ(1, FPDFAnnot_GetPathObjectCount(annot));
526
527 // Check that the annotation's bounding box came from its rectangle.
528 FS_RECTF new_rect = FPDFAnnot_GetRect(annot);
529 EXPECT_EQ(rect.left, new_rect.left);
530 EXPECT_EQ(rect.bottom, new_rect.bottom);
531 EXPECT_EQ(rect.right, new_rect.right);
532 EXPECT_EQ(rect.top, new_rect.top);
533
534 // Save the document, closing the page and document.
535 FPDFPage_CloseAnnot(annot);
536 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
537 FPDF_ClosePage(page);
538
539 // Open the saved document.
Nicolas Pena3ff54002017-07-05 11:55:35 -0400540 TestSaved(595, 842, md5_3);
Jane Liubaa7ff42017-06-29 19:18:23 -0400541
542 // Check that the saved document has a correct count of annotations and paths.
Nicolas Pena3ff54002017-07-05 11:55:35 -0400543 EXPECT_EQ(3, FPDFPage_GetAnnotCount(m_SavedPage));
544 annot = FPDFPage_GetAnnot(m_SavedPage, 2);
Jane Liubaa7ff42017-06-29 19:18:23 -0400545 ASSERT_TRUE(annot);
546 EXPECT_EQ(1, FPDFAnnot_GetPathObjectCount(annot));
547
548 // Check that the new annotation's rectangle is as defined.
549 new_rect = FPDFAnnot_GetRect(annot);
550 EXPECT_EQ(rect.left, new_rect.left);
551 EXPECT_EQ(rect.bottom, new_rect.bottom);
552 EXPECT_EQ(rect.right, new_rect.right);
553 EXPECT_EQ(rect.top, new_rect.top);
554
Jane Liubaa7ff42017-06-29 19:18:23 -0400555 FPDFPage_CloseAnnot(annot);
Nicolas Pena3ff54002017-07-05 11:55:35 -0400556 CloseSaved();
Jane Liu8ce58f52017-06-29 13:40:22 -0400557}
Jane Liub137e752017-07-05 15:04:33 -0400558
559TEST_F(FPDFAnnotEmbeddertest, ModifyAnnotationFlags) {
560 // Open a file with an annotation and load its first page.
561 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
562 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
563 ASSERT_TRUE(page);
564
565 // Check that the page renders correctly.
566 FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
567 CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
568 FPDFBitmap_Destroy(bitmap);
569
570 // Retrieve the annotation.
571 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
572 ASSERT_TRUE(annot);
573
574 // Check that the original flag values are as expected.
575 int flags = FPDFAnnot_GetFlags(annot);
576 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
577 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
578
579 // Set the HIDDEN flag.
580 flags |= FPDF_ANNOT_FLAG_HIDDEN;
581 EXPECT_TRUE(FPDFAnnot_SetFlags(annot, flags));
582 flags = FPDFAnnot_GetFlags(annot);
583 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_HIDDEN);
584 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
585
586 // Check that the page renders correctly without rendering the annotation.
587 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
588 CompareBitmap(bitmap, 612, 792, "1940568c9ba33bac5d0b1ee9558c76b3");
589 FPDFBitmap_Destroy(bitmap);
590
591 // Unset the HIDDEN flag.
592 EXPECT_TRUE(FPDFAnnot_SetFlags(annot, FPDF_ANNOT_FLAG_NONE));
593 EXPECT_FALSE(FPDFAnnot_GetFlags(annot));
594 flags &= ~FPDF_ANNOT_FLAG_HIDDEN;
595 EXPECT_TRUE(FPDFAnnot_SetFlags(annot, flags));
596 flags = FPDFAnnot_GetFlags(annot);
597 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
598 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
599
600 // Check that the page renders correctly as before.
601 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
602 CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
603 FPDFBitmap_Destroy(bitmap);
604
605 FPDFPage_CloseAnnot(annot);
606 UnloadPage(page);
607}