blob: 58a00067a7932d0c55a7b386dc1fe699d9bc9d03 [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.
Jane Liu2e1a32b2017-07-06 12:01:25 -040062 std::unique_ptr<unsigned short, pdfium::FreeDeleter> author_key =
63 GetFPDFWideString(L"T");
64 EXPECT_EQ(FPDF_OBJECT_STRING,
65 FPDFAnnot_GetValueType(annot, author_key.get()));
Jane Liu4fd9a472017-06-01 18:56:09 -040066 unsigned long len =
Jane Liu2e1a32b2017-07-06 12:01:25 -040067 FPDFAnnot_GetStringValue(annot, author_key.get(), nullptr, 0);
Jane Liu4fd9a472017-06-01 18:56:09 -040068 std::vector<char> buf(len);
Jane Liu2e1a32b2017-07-06 12:01:25 -040069 EXPECT_EQ(28u,
70 FPDFAnnot_GetStringValue(annot, author_key.get(), buf.data(), len));
Jane Liu4fd9a472017-06-01 18:56:09 -040071 EXPECT_STREQ(L"Jae Hyun Park",
72 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
73 .c_str());
74
75 // Check that the content is correct.
Jane Liu2e1a32b2017-07-06 12:01:25 -040076 std::unique_ptr<unsigned short, pdfium::FreeDeleter> contents_key =
77 GetFPDFWideString(L"Contents");
78 EXPECT_EQ(FPDF_OBJECT_STRING,
79 FPDFAnnot_GetValueType(annot, contents_key.get()));
80 len = FPDFAnnot_GetStringValue(annot, contents_key.get(), nullptr, 0);
Jane Liu4fd9a472017-06-01 18:56:09 -040081 buf.clear();
82 buf.resize(len);
Jane Liu2e1a32b2017-07-06 12:01:25 -040083 EXPECT_EQ(2690u, FPDFAnnot_GetStringValue(annot, contents_key.get(),
84 buf.data(), len));
Jane Liu4fd9a472017-06-01 18:56:09 -040085 const wchar_t contents[] =
86 L"This is a note for that highlight annotation. Very long highlight "
87 "annotation. Long long long Long 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 longLong long longLong long longLong long longLong long "
98 "longLong long longLong long longLong long longLong long longLong long "
99 "longLong long longLong long longLong long longLong long longLong long "
100 "longLong long longLong long longLong long longLong long longLong long "
101 "longLong long longLong long longLong long longLong long longLong long "
102 "longLong long longLong long longLong long longLong long longLong long "
103 "longLong long longLong long longLong long longLong long longLong long "
104 "longLong long longLong long longLong long longLong long longLong long "
105 "longLong long long. END";
106 EXPECT_STREQ(contents,
107 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
108 .c_str());
109
110 // Check that the quadpoints are correct.
Jane Liud60e9ad2017-06-26 11:28:36 -0400111 FS_QUADPOINTSF quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400112 EXPECT_EQ(115.802643f, quadpoints.x1);
113 EXPECT_EQ(718.913940f, quadpoints.y1);
114 EXPECT_EQ(157.211182f, quadpoints.x4);
115 EXPECT_EQ(706.264465f, quadpoints.y4);
116
Jane Liue10509a2017-06-20 16:47:41 -0400117 FPDFPage_CloseAnnot(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400118 UnloadPage(page);
119}
120
121TEST_F(FPDFAnnotEmbeddertest, ExtractInkMultiple) {
122 // Open a file with three annotations and load its first page.
123 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
124 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
125 ASSERT_TRUE(page);
126
127 // Check that there is a total of 3 annotation on its first page.
128 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
129
Jane Liu20eafda2017-06-07 10:33:24 -0400130 // Check that the third annotation is of type "ink".
Jane Liud60e9ad2017-06-26 11:28:36 -0400131 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 2);
132 ASSERT_TRUE(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400133 EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot));
134
135 // Check that the annotation color is blue with opacity.
136 unsigned int R;
137 unsigned int G;
138 unsigned int B;
139 unsigned int A;
140 EXPECT_TRUE(
141 FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
142 EXPECT_EQ(0u, R);
143 EXPECT_EQ(0u, G);
144 EXPECT_EQ(255u, B);
145 EXPECT_EQ(76u, A);
146
147 // Check that there is no content.
Jane Liu2e1a32b2017-07-06 12:01:25 -0400148 std::unique_ptr<unsigned short, pdfium::FreeDeleter> contents_key =
149 GetFPDFWideString(L"Contents");
Jane Liu4fd9a472017-06-01 18:56:09 -0400150 EXPECT_EQ(2u,
Jane Liu2e1a32b2017-07-06 12:01:25 -0400151 FPDFAnnot_GetStringValue(annot, contents_key.get(), nullptr, 0));
Jane Liu4fd9a472017-06-01 18:56:09 -0400152
153 // Check that the rectange coordinates are correct.
154 // Note that upon rendering, the rectangle coordinates will be adjusted.
Jane Liud60e9ad2017-06-26 11:28:36 -0400155 FS_RECTF rect = FPDFAnnot_GetRect(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400156 EXPECT_EQ(351.820404f, rect.left);
157 EXPECT_EQ(583.830688f, rect.bottom);
158 EXPECT_EQ(475.336090f, rect.right);
159 EXPECT_EQ(681.535034f, rect.top);
160
Jane Liue10509a2017-06-20 16:47:41 -0400161 FPDFPage_CloseAnnot(annot);
Jane Liu4fd9a472017-06-01 18:56:09 -0400162 UnloadPage(page);
163}
Jane Liu20eafda2017-06-07 10:33:24 -0400164
165TEST_F(FPDFAnnotEmbeddertest, AddIllegalSubtypeAnnotation) {
166 // Open a file with one annotation and load its first page.
167 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
168 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
169 ASSERT_TRUE(page);
170
171 // Add an annotation with an illegal subtype.
Jane Liud60e9ad2017-06-26 11:28:36 -0400172 ASSERT_FALSE(FPDFPage_CreateAnnot(page, -1));
Jane Liu20eafda2017-06-07 10:33:24 -0400173
174 UnloadPage(page);
175}
176
Jane Liud321ef92017-06-14 09:56:22 -0400177TEST_F(FPDFAnnotEmbeddertest, AddFirstTextAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400178 // Open a file with no annotation and load its first page.
179 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
180 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
181 ASSERT_TRUE(page);
182 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
183
Jane Liueda65252017-06-07 11:31:27 -0400184 // Add a text annotation to the page.
Jane Liud60e9ad2017-06-26 11:28:36 -0400185 FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT);
186 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400187
188 // Check that there is now 1 annotations on this page.
189 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
190
191 // Check that the subtype of the annotation is correct.
192 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot));
Jane Liue10509a2017-06-20 16:47:41 -0400193 FPDFPage_CloseAnnot(annot);
194
Jane Liud60e9ad2017-06-26 11:28:36 -0400195 annot = FPDFPage_GetAnnot(page, 0);
196 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400197 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot));
198
199 // Set the color of the annotation.
200 ASSERT_TRUE(
201 FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204));
202 // Check that the color has been set correctly.
203 unsigned int R;
204 unsigned int G;
205 unsigned int B;
206 unsigned int A;
207 EXPECT_TRUE(
208 FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
209 EXPECT_EQ(51u, R);
210 EXPECT_EQ(102u, G);
211 EXPECT_EQ(153u, B);
212 EXPECT_EQ(204u, A);
213
214 // Change the color of the annotation.
215 ASSERT_TRUE(
216 FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 204, 153, 102, 51));
217 // Check that the color has been set correctly.
218 EXPECT_TRUE(
219 FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
220 EXPECT_EQ(204u, R);
221 EXPECT_EQ(153u, G);
222 EXPECT_EQ(102u, B);
223 EXPECT_EQ(51u, A);
224
225 // Set the annotation rectangle.
Jane Liud60e9ad2017-06-26 11:28:36 -0400226 FS_RECTF rect = FPDFAnnot_GetRect(annot);
227 EXPECT_EQ(0.f, rect.left);
228 EXPECT_EQ(0.f, rect.right);
Jane Liu20eafda2017-06-07 10:33:24 -0400229 rect.left = 35;
230 rect.bottom = 150;
231 rect.right = 53;
232 rect.top = 165;
Jane Liu06462752017-06-27 16:41:14 -0400233 ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
Jane Liu20eafda2017-06-07 10:33:24 -0400234 // Check that the annotation rectangle has been set correctly.
Jane Liud60e9ad2017-06-26 11:28:36 -0400235 rect = FPDFAnnot_GetRect(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400236 EXPECT_EQ(35.f, rect.left);
237 EXPECT_EQ(150.f, rect.bottom);
238 EXPECT_EQ(53.f, rect.right);
239 EXPECT_EQ(165.f, rect.top);
240
241 // Set the content of the annotation.
Jane Liu2e1a32b2017-07-06 12:01:25 -0400242 std::unique_ptr<unsigned short, pdfium::FreeDeleter> contents_key =
243 GetFPDFWideString(L"Contents");
Jane Liu20eafda2017-06-07 10:33:24 -0400244 const wchar_t contents[] = L"Hello! This is a customized content.";
245 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
246 GetFPDFWideString(contents);
Jane Liu2e1a32b2017-07-06 12:01:25 -0400247 ASSERT_TRUE(FPDFAnnot_SetStringValue(annot, contents_key.get(), text.get()));
Jane Liu20eafda2017-06-07 10:33:24 -0400248 // Check that the content has been set correctly.
249 unsigned long len =
Jane Liu2e1a32b2017-07-06 12:01:25 -0400250 FPDFAnnot_GetStringValue(annot, contents_key.get(), nullptr, 0);
Jane Liu20eafda2017-06-07 10:33:24 -0400251 std::vector<char> buf(len);
Jane Liu2e1a32b2017-07-06 12:01:25 -0400252 EXPECT_EQ(74u, FPDFAnnot_GetStringValue(annot, contents_key.get(), buf.data(),
253 len));
Jane Liu20eafda2017-06-07 10:33:24 -0400254 EXPECT_STREQ(contents,
255 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
256 .c_str());
257
Jane Liue10509a2017-06-20 16:47:41 -0400258 FPDFPage_CloseAnnot(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400259 UnloadPage(page);
260}
261
262TEST_F(FPDFAnnotEmbeddertest, AddAndSaveUnderlineAnnotation) {
263 // Open a file with one annotation and load its first page.
264 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
265 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
266 ASSERT_TRUE(page);
267
268 // Check that there is a total of one annotation on its first page, and verify
269 // its quadpoints.
270 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Jane Liud60e9ad2017-06-26 11:28:36 -0400271 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
272 ASSERT_TRUE(annot);
273 FS_QUADPOINTSF quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400274 EXPECT_EQ(115.802643f, quadpoints.x1);
275 EXPECT_EQ(718.913940f, quadpoints.y1);
276 EXPECT_EQ(157.211182f, quadpoints.x4);
277 EXPECT_EQ(706.264465f, quadpoints.y4);
Jane Liue10509a2017-06-20 16:47:41 -0400278 FPDFPage_CloseAnnot(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400279
280 // Add an underline annotation to the page and set its quadpoints.
Jane Liud60e9ad2017-06-26 11:28:36 -0400281 annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE);
282 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400283 quadpoints.x1 = 140.802643f;
284 quadpoints.x3 = 140.802643f;
Jane Liu06462752017-06-27 16:41:14 -0400285 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
Jane Liue10509a2017-06-20 16:47:41 -0400286 FPDFPage_CloseAnnot(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400287
288 // Save the document, closing the page and document.
289 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
290 FPDF_ClosePage(page);
291
292 // Open the saved document.
Nicolas Pena3ff54002017-07-05 11:55:35 -0400293 const char md5[] = "184b67b322edaee27994b3232544b8b3";
294 TestSaved(612, 792, md5);
Jane Liu20eafda2017-06-07 10:33:24 -0400295
296 // Check that the saved document has 2 annotations on the first page
Nicolas Pena3ff54002017-07-05 11:55:35 -0400297 EXPECT_EQ(2, FPDFPage_GetAnnotCount(m_SavedPage));
Jane Liu20eafda2017-06-07 10:33:24 -0400298
299 // Check that the second annotation is an underline annotation and verify
300 // its quadpoints.
Nicolas Pena3ff54002017-07-05 11:55:35 -0400301 FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(m_SavedPage, 1);
Jane Liud60e9ad2017-06-26 11:28:36 -0400302 ASSERT_TRUE(new_annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400303 EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot));
Jane Liud60e9ad2017-06-26 11:28:36 -0400304 FS_QUADPOINTSF new_quadpoints = FPDFAnnot_GetAttachmentPoints(new_annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400305 EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f);
306 EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f);
307 EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f);
308 EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f);
309
Jane Liue10509a2017-06-20 16:47:41 -0400310 FPDFPage_CloseAnnot(new_annot);
Nicolas Pena3ff54002017-07-05 11:55:35 -0400311 CloseSaved();
Jane Liu20eafda2017-06-07 10:33:24 -0400312}
Jane Liu06462752017-06-27 16:41:14 -0400313
314TEST_F(FPDFAnnotEmbeddertest, ModifyRectQuadpointsWithAP) {
315 // Open a file with four annotations and load its first page.
316 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
317 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
318 ASSERT_TRUE(page);
319 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
320
321 // Retrieve the highlight annotation which has its AP stream already defined.
322 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
323 ASSERT_TRUE(annot);
324 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
325
326 // Check that color cannot be set when an AP stream is defined already.
327 EXPECT_FALSE(
328 FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204));
329
330 // Check that when getting the attachment points, bounding box points are
331 // returned since this is a markup annotation with AP defined.
332 FS_QUADPOINTSF quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
333 EXPECT_NEAR(0.f, quadpoints.x1, 0.001f);
334 EXPECT_NEAR(16.9955f, quadpoints.y1, 0.001f);
335 EXPECT_NEAR(68.5953f, quadpoints.x4, 0.001f);
336 EXPECT_NEAR(0.f, quadpoints.y4, 0.001f);
337
338 // Check that when new attachment points define a smaller bounding box, the
339 // bounding box does not get updated.
340 quadpoints.x1 = 1.0f;
341 quadpoints.x3 = 1.0f;
342 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
343 FS_QUADPOINTSF new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
344 EXPECT_NE(quadpoints.x1, new_quadpoints.x1);
345
346 // Check that the bounding box gets updated successfully when valid attachment
347 // points are set.
348 quadpoints.x1 = 0.f;
349 quadpoints.y1 = 721.792f;
350 quadpoints.x2 = 133.055f;
351 quadpoints.y2 = 721.792f;
352 quadpoints.x3 = 0.f;
353 quadpoints.x4 = 133.055f;
354 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
355 new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
356 EXPECT_EQ(quadpoints.x1, new_quadpoints.x1);
357 EXPECT_EQ(quadpoints.y1, new_quadpoints.y1);
358 EXPECT_EQ(quadpoints.x4, new_quadpoints.x4);
359 EXPECT_EQ(quadpoints.y4, new_quadpoints.y4);
360
361 // Check that when getting the annotation rectangle, rectangle points are
362 // returned, but not bounding box points.
363 FS_RECTF rect = FPDFAnnot_GetRect(annot);
364 EXPECT_NEAR(67.7299f, rect.left, 0.001f);
365 EXPECT_NEAR(704.296f, rect.bottom, 0.001f);
366 EXPECT_NEAR(136.325f, rect.right, 0.001f);
367 EXPECT_NEAR(721.292f, rect.top, 0.001f);
368
369 // Check that the rectangle gets updated successfully when a valid rectangle
370 // is set, and that the bounding box is not modified.
371 rect.left = 0.f;
372 rect.bottom = 0.f;
373 rect.right = 134.055f;
374 rect.top = 722.792f;
375 ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
376 FS_RECTF new_rect = FPDFAnnot_GetRect(annot);
377 EXPECT_EQ(rect.right, new_rect.right);
378 new_quadpoints = FPDFAnnot_GetAttachmentPoints(annot);
379 EXPECT_NE(rect.right, new_quadpoints.x2);
380
381 FPDFPage_CloseAnnot(annot);
382
383 // Retrieve the square annotation which has its AP stream already defined.
384 annot = FPDFPage_GetAnnot(page, 2);
385 ASSERT_TRUE(annot);
386 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot));
387
388 // Check that the rectangle and the bounding box get updated successfully when
389 // a valid rectangle is set, since this is not a markup annotation.
390 rect = FPDFAnnot_GetRect(annot);
391 rect.right += 1.f;
392 ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
393 new_rect = FPDFAnnot_GetRect(annot);
394 EXPECT_EQ(rect.right, new_rect.right);
395
396 FPDFPage_CloseAnnot(annot);
397 UnloadPage(page);
398}
Jane Liu8ce58f52017-06-29 13:40:22 -0400399
400TEST_F(FPDFAnnotEmbeddertest, RemoveAnnotation) {
401 // Open a file with 3 annotations on its first page.
402 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
403 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
404 ASSERT_TRUE(page);
405 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
406
407 // Check that the annotations have the expected rectangle coordinates.
408 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
409 FS_RECTF rect = FPDFAnnot_GetRect(annot);
410 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
411 FPDFPage_CloseAnnot(annot);
412
413 annot = FPDFPage_GetAnnot(page, 1);
414 rect = FPDFAnnot_GetRect(annot);
415 EXPECT_NEAR(149.8127f, rect.left, 0.001f);
416 FPDFPage_CloseAnnot(annot);
417
418 annot = FPDFPage_GetAnnot(page, 2);
419 rect = FPDFAnnot_GetRect(annot);
420 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
421 FPDFPage_CloseAnnot(annot);
422
423 // Check that nothing happens when attempting to remove an annotation with an
424 // out-of-bound index.
425 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4));
426 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1));
427 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
428
429 // Remove the second annotation.
430 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
431 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
432 EXPECT_FALSE(FPDFPage_GetAnnot(page, 2));
433
434 // Save the document, closing the page and document.
435 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
436 FPDF_ClosePage(page);
437
Nicolas Pena3ff54002017-07-05 11:55:35 -0400438 // TODO(npm): TestSaved changes annot rect dimensions by 1??
Jane Liu8ce58f52017-06-29 13:40:22 -0400439 // Open the saved document.
440 std::string new_file = GetString();
441 FPDF_FILEACCESS file_access;
442 memset(&file_access, 0, sizeof(file_access));
443 file_access.m_FileLen = new_file.size();
444 file_access.m_GetBlock = GetBlockFromString;
445 file_access.m_Param = &new_file;
446 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
447 ASSERT_TRUE(new_doc);
448 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
449 ASSERT_TRUE(new_page);
450
451 // Check that the saved document has 2 annotations on the first page.
452 EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
453
454 // Check that the remaining 2 annotations are the original 1st and 3rd ones by
455 // verifying their rectangle coordinates.
456 annot = FPDFPage_GetAnnot(new_page, 0);
457 rect = FPDFAnnot_GetRect(annot);
458 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
459 FPDFPage_CloseAnnot(annot);
460
461 annot = FPDFPage_GetAnnot(new_page, 1);
462 rect = FPDFAnnot_GetRect(annot);
463 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
464 FPDFPage_CloseAnnot(annot);
Jane Liubaa7ff42017-06-29 19:18:23 -0400465 FPDF_ClosePage(new_page);
466 FPDF_CloseDocument(new_doc);
467}
Jane Liu8ce58f52017-06-29 13:40:22 -0400468
Jane Liubaa7ff42017-06-29 19:18:23 -0400469TEST_F(FPDFAnnotEmbeddertest, AddAndModifyPath) {
470#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400471 const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
472 const char md5_modified_path[] = "cf3cea74bd46497520ff6c4d1ea228c8";
473 const char md5_two_paths[] = "e8994452fc4385337bae5522354e10ff";
474 const char md5_new_annot[] = "ee5372b31fede117fc83b9384598aa25";
Jane Liubaa7ff42017-06-29 19:18:23 -0400475#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400476 const char md5_original[] = "4f64add0190ede63f7bb9eb1e2e83edb";
477 const char md5_modified_path[] = "681f0d0738dded0722e146f6c219bfac";
478 const char md5_two_paths[] = "67c7e90fc3b64e20f6b69a1744f7f4f0";
479 const char md5_new_annot[] = "262187984451bae2fe826067d68623ff";
Jane Liubaa7ff42017-06-29 19:18:23 -0400480#else
Jane Liu7a9a38b2017-07-11 13:47:37 -0400481 const char md5_original[] = "02e1c6adff8fee4aeabd91c2c2e4be43";
482 const char md5_modified_path[] = "87a78cbacd8509b961a67be56b5665a2";
483 const char md5_two_paths[] = "76e985c18b73ceacf409f77f978176d4";
484 const char md5_new_annot[] = "c95de7a9a1f61faca03d953961a319b9";
Jane Liubaa7ff42017-06-29 19:18:23 -0400485#endif
486
487 // Open a file with two annotations and load its first page.
488 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
489 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
490 ASSERT_TRUE(page);
491 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
492
493 // Check that the page renders correctly.
494 FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liu7a9a38b2017-07-11 13:47:37 -0400495 CompareBitmap(bitmap, 595, 842, md5_original);
Jane Liubaa7ff42017-06-29 19:18:23 -0400496 FPDFBitmap_Destroy(bitmap);
497
498 // Retrieve the stamp annotation which has its AP stream already defined.
499 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
500 ASSERT_TRUE(annot);
501
502 // Check that this annotation has one path object and retrieve it.
Jane Liu36567742017-07-06 11:13:35 -0400503 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
504 FPDF_PAGEOBJECT path = FPDFAnnot_GetObject(annot, 1);
Jane Liubaa7ff42017-06-29 19:18:23 -0400505 EXPECT_FALSE(path);
Jane Liu36567742017-07-06 11:13:35 -0400506 path = FPDFAnnot_GetObject(annot, 0);
507 EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
Jane Liubaa7ff42017-06-29 19:18:23 -0400508 EXPECT_TRUE(path);
509
510 // Modify the color of the path object.
511 EXPECT_TRUE(FPDFPath_SetStrokeColor(path, 0, 0, 0, 255));
Jane Liu36567742017-07-06 11:13:35 -0400512 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, path));
Jane Liubaa7ff42017-06-29 19:18:23 -0400513
514 // Check that the page with the modified annotation renders correctly.
515 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liu7a9a38b2017-07-11 13:47:37 -0400516 CompareBitmap(bitmap, 595, 842, md5_modified_path);
517 FPDFBitmap_Destroy(bitmap);
518
519 // Add a second path object to the same annotation.
520 FPDF_PAGEOBJECT dot = FPDFPageObj_CreateNewPath(7, 84);
521 EXPECT_TRUE(FPDFPath_BezierTo(dot, 9, 86, 10, 87, 11, 88));
522 EXPECT_TRUE(FPDFPath_SetStrokeColor(dot, 255, 0, 0, 100));
523 EXPECT_TRUE(FPDFPath_SetStrokeWidth(dot, 14));
524 EXPECT_TRUE(FPDFPath_SetDrawMode(dot, 0, 1));
525 EXPECT_TRUE(FPDFAnnot_AppendObject(annot, dot));
526 EXPECT_EQ(2, FPDFAnnot_GetObjectCount(annot));
527
528 // Check that the page with an annotation with two paths renders correctly.
529 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
530 CompareBitmap(bitmap, 595, 842, md5_two_paths);
531 FPDFBitmap_Destroy(bitmap);
532
533 // Delete the newly added path object.
534 EXPECT_TRUE(FPDFAnnot_RemoveObject(annot, 1));
535 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
536 FPDFPage_CloseAnnot(annot);
537
538 // Check that the page renders the same as before.
539 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
540 CompareBitmap(bitmap, 595, 842, md5_modified_path);
Jane Liubaa7ff42017-06-29 19:18:23 -0400541 FPDFBitmap_Destroy(bitmap);
542
543 // Create another stamp annotation and set its annotation rectangle.
544 annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP);
545 ASSERT_TRUE(annot);
546 FS_RECTF rect;
547 rect.left = 200.f;
548 rect.bottom = 400.f;
549 rect.right = 500.f;
550 rect.top = 600.f;
551 EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect));
552
553 // Add a new path to the annotation.
554 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500);
555 EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400));
556 EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600));
557 EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550));
558 EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450));
559 EXPECT_TRUE(FPDFPath_SetStrokeColor(check, 0, 255, 255, 180));
560 EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f));
561 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
Jane Liu36567742017-07-06 11:13:35 -0400562 EXPECT_TRUE(FPDFAnnot_AppendObject(annot, check));
563 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
Jane Liubaa7ff42017-06-29 19:18:23 -0400564
565 // Check that the annotation's bounding box came from its rectangle.
566 FS_RECTF 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 // Save the document, closing the page and document.
573 FPDFPage_CloseAnnot(annot);
574 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
575 FPDF_ClosePage(page);
576
577 // Open the saved document.
Jane Liu7a9a38b2017-07-11 13:47:37 -0400578 TestSaved(595, 842, md5_new_annot);
Jane Liubaa7ff42017-06-29 19:18:23 -0400579
Jane Liu36567742017-07-06 11:13:35 -0400580 // Check that the document has a correct count of annotations and objects.
Nicolas Pena3ff54002017-07-05 11:55:35 -0400581 EXPECT_EQ(3, FPDFPage_GetAnnotCount(m_SavedPage));
582 annot = FPDFPage_GetAnnot(m_SavedPage, 2);
Jane Liubaa7ff42017-06-29 19:18:23 -0400583 ASSERT_TRUE(annot);
Jane Liu36567742017-07-06 11:13:35 -0400584 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
Jane Liubaa7ff42017-06-29 19:18:23 -0400585
586 // Check that the new annotation's rectangle is as defined.
587 new_rect = FPDFAnnot_GetRect(annot);
588 EXPECT_EQ(rect.left, new_rect.left);
589 EXPECT_EQ(rect.bottom, new_rect.bottom);
590 EXPECT_EQ(rect.right, new_rect.right);
591 EXPECT_EQ(rect.top, new_rect.top);
592
Jane Liubaa7ff42017-06-29 19:18:23 -0400593 FPDFPage_CloseAnnot(annot);
Nicolas Pena3ff54002017-07-05 11:55:35 -0400594 CloseSaved();
Jane Liu8ce58f52017-06-29 13:40:22 -0400595}
Jane Liub137e752017-07-05 15:04:33 -0400596
597TEST_F(FPDFAnnotEmbeddertest, ModifyAnnotationFlags) {
598 // Open a file with an annotation and load its first page.
599 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
600 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
601 ASSERT_TRUE(page);
602
603 // Check that the page renders correctly.
604 FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
605 CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
606 FPDFBitmap_Destroy(bitmap);
607
608 // Retrieve the annotation.
609 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
610 ASSERT_TRUE(annot);
611
612 // Check that the original flag values are as expected.
613 int flags = FPDFAnnot_GetFlags(annot);
614 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
615 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
616
617 // Set the HIDDEN flag.
618 flags |= FPDF_ANNOT_FLAG_HIDDEN;
619 EXPECT_TRUE(FPDFAnnot_SetFlags(annot, flags));
620 flags = FPDFAnnot_GetFlags(annot);
621 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_HIDDEN);
622 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
623
624 // Check that the page renders correctly without rendering the annotation.
625 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
626 CompareBitmap(bitmap, 612, 792, "1940568c9ba33bac5d0b1ee9558c76b3");
627 FPDFBitmap_Destroy(bitmap);
628
629 // Unset the HIDDEN flag.
630 EXPECT_TRUE(FPDFAnnot_SetFlags(annot, FPDF_ANNOT_FLAG_NONE));
631 EXPECT_FALSE(FPDFAnnot_GetFlags(annot));
632 flags &= ~FPDF_ANNOT_FLAG_HIDDEN;
633 EXPECT_TRUE(FPDFAnnot_SetFlags(annot, flags));
634 flags = FPDFAnnot_GetFlags(annot);
635 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
636 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
637
638 // Check that the page renders correctly as before.
639 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
640 CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
641 FPDFBitmap_Destroy(bitmap);
642
643 FPDFPage_CloseAnnot(annot);
644 UnloadPage(page);
645}
Jane Liu36567742017-07-06 11:13:35 -0400646
647TEST_F(FPDFAnnotEmbeddertest, AddAndModifyImage) {
648#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400649 const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
650 const char md5_new_image[] = "ff012f5697436dfcaec25b32d1333596";
651 const char md5_modified_image[] = "86cf8cb2755a7a2046a543e66d9c1e61";
Jane Liu36567742017-07-06 11:13:35 -0400652#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400653 const char md5_original[] = "4f64add0190ede63f7bb9eb1e2e83edb";
654 const char md5_new_image[] = "6fb176c20996cc554d0210d8c8b6138f";
655 const char md5_modified_image[] = "546959714dfb0dcd7e7b00259e8d178c";
Jane Liu36567742017-07-06 11:13:35 -0400656#else
Jane Liu7a9a38b2017-07-11 13:47:37 -0400657 const char md5_original[] = "02e1c6adff8fee4aeabd91c2c2e4be43";
658 const char md5_new_image[] = "e7658232abd8977cdc3367dd02aee04a";
659 const char md5_modified_image[] = "f393432b9a9b452ea69022f46c8b3f75";
Jane Liu36567742017-07-06 11:13:35 -0400660#endif
661
662 // Open a file with two annotations and load its first page.
663 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
664 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
665 ASSERT_TRUE(page);
666 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
667
668 // Check that the page renders correctly.
669 FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liu7a9a38b2017-07-11 13:47:37 -0400670 CompareBitmap(bitmap, 595, 842, md5_original);
Jane Liu36567742017-07-06 11:13:35 -0400671 FPDFBitmap_Destroy(bitmap);
672
673 // Create a stamp annotation and set its annotation rectangle.
674 FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP);
675 ASSERT_TRUE(annot);
676 FS_RECTF rect;
677 rect.left = 200.f;
678 rect.bottom = 600.f;
679 rect.right = 400.f;
680 rect.top = 800.f;
681 EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect));
682
683 // Add a solid-color translucent image object to the new annotation.
684 constexpr int kBitmapSize = 200;
685 FPDF_BITMAP image_bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 1);
686 FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize, 0xeeeecccc);
687 EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(image_bitmap));
688 EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(image_bitmap));
689 FPDF_PAGEOBJECT image_object = FPDFPageObj_NewImageObj(document());
690 ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
691 ASSERT_TRUE(FPDFImageObj_SetMatrix(image_object, kBitmapSize, 0, 0,
692 kBitmapSize, 0, 0));
693 FPDFPageObj_Transform(image_object, 1, 0, 0, 1, 200, 600);
694 EXPECT_TRUE(FPDFAnnot_AppendObject(annot, image_object));
695 FPDFPage_CloseAnnot(annot);
696
697 // Check that the page renders correctly with the new image object.
698 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liu7a9a38b2017-07-11 13:47:37 -0400699 CompareBitmap(bitmap, 595, 842, md5_new_image);
Jane Liu36567742017-07-06 11:13:35 -0400700 FPDFBitmap_Destroy(bitmap);
701
702 // Retrieve the newly added stamp annotation and its image object.
703 annot = FPDFPage_GetAnnot(page, 2);
704 ASSERT_TRUE(annot);
705 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
706 image_object = FPDFAnnot_GetObject(annot, 0);
707 EXPECT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(image_object));
708
709 // Modify the image in the new annotation.
710 FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize, 0xff000000);
711 ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
712 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, image_object));
713 FPDFPage_CloseAnnot(annot);
714
715 // Save the document, closing the page and document.
716 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
717 FPDF_ClosePage(page);
718
719 // Test that the saved document renders the modified image object correctly.
Jane Liu7a9a38b2017-07-11 13:47:37 -0400720 TestSaved(595, 842, md5_modified_image);
Jane Liu36567742017-07-06 11:13:35 -0400721
722 FPDFBitmap_Destroy(image_bitmap);
723 CloseSaved();
724}
725
726TEST_F(FPDFAnnotEmbeddertest, AddAndModifyText) {
727#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400728 const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
729 const char md5_new_text[] = "e5680ed048c2cfd9a1d27212cdf41286";
730 const char md5_modified_text[] = "79f5cfb0b07caaf936f65f6a7a57ce77";
Jane Liu36567742017-07-06 11:13:35 -0400731#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400732 const char md5_original[] = "4f64add0190ede63f7bb9eb1e2e83edb";
733 const char md5_new_text[] = "998abae4962f8f41e094e7612d8339fc";
734 const char md5_modified_text[] = "e89b82ca4589b8f0b45fff42ca3a96a4";
Jane Liu36567742017-07-06 11:13:35 -0400735#else
Jane Liu7a9a38b2017-07-11 13:47:37 -0400736 const char md5_original[] = "02e1c6adff8fee4aeabd91c2c2e4be43";
737 const char md5_new_text[] = "3fbbaec4d846ccf2be89e09daae0273d";
738 const char md5_modified_text[] = "2ad0acaf2d8990bcdf48e1d12e6c44ad";
Jane Liu36567742017-07-06 11:13:35 -0400739#endif
740
741 // Open a file with two annotations and load its first page.
742 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
743 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
744 ASSERT_TRUE(page);
745 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
746
747 // Check that the page renders correctly.
748 FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liu7a9a38b2017-07-11 13:47:37 -0400749 CompareBitmap(bitmap, 595, 842, md5_original);
Jane Liu36567742017-07-06 11:13:35 -0400750 FPDFBitmap_Destroy(bitmap);
751
752 // Create a stamp annotation and set its annotation rectangle.
753 FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP);
754 ASSERT_TRUE(annot);
755 FS_RECTF rect;
756 rect.left = 200.f;
757 rect.bottom = 550.f;
758 rect.right = 450.f;
759 rect.top = 650.f;
760 EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect));
761
762 // Add a translucent text object to the new annotation.
763 FPDF_PAGEOBJECT text_object =
764 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
765 EXPECT_TRUE(text_object);
766 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
767 GetFPDFWideString(L"I'm a translucent text laying on other text.");
768 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
769 EXPECT_TRUE(FPDFText_SetFillColor(text_object, 0, 0, 255, 150));
770 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 600);
771 EXPECT_TRUE(FPDFAnnot_AppendObject(annot, text_object));
772 FPDFPage_CloseAnnot(annot);
773
774 // Check that the page renders correctly with the new text object.
775 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liu7a9a38b2017-07-11 13:47:37 -0400776 CompareBitmap(bitmap, 595, 842, md5_new_text);
Jane Liu36567742017-07-06 11:13:35 -0400777 FPDFBitmap_Destroy(bitmap);
778
779 // Retrieve the newly added stamp annotation and its text object.
780 annot = FPDFPage_GetAnnot(page, 2);
781 ASSERT_TRUE(annot);
782 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
783 text_object = FPDFAnnot_GetObject(annot, 0);
784 EXPECT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_object));
785
786 // Modify the text in the new annotation.
787 std::unique_ptr<unsigned short, pdfium::FreeDeleter> new_text =
788 GetFPDFWideString(L"New text!");
789 EXPECT_TRUE(FPDFText_SetText(text_object, new_text.get()));
790 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, text_object));
791 FPDFPage_CloseAnnot(annot);
792
793 // Check that the page renders correctly with the modified text object.
794 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liu7a9a38b2017-07-11 13:47:37 -0400795 CompareBitmap(bitmap, 595, 842, md5_modified_text);
Jane Liu36567742017-07-06 11:13:35 -0400796 FPDFBitmap_Destroy(bitmap);
797
798 // Remove the new annotation, and check that the page renders as before.
799 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 2));
800 bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
Jane Liu7a9a38b2017-07-11 13:47:37 -0400801 CompareBitmap(bitmap, 595, 842, md5_original);
Jane Liu36567742017-07-06 11:13:35 -0400802 FPDFBitmap_Destroy(bitmap);
803
804 UnloadPage(page);
805}
Jane Liu2e1a32b2017-07-06 12:01:25 -0400806
807TEST_F(FPDFAnnotEmbeddertest, GetSetStringValue) {
808 // Open a file with four annotations and load its first page.
809 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
810 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
811 ASSERT_TRUE(page);
812
813 // Retrieve the first annotation.
814 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
815 ASSERT_TRUE(annot);
816
817 // Check that a non-existent key does not exist.
818 EXPECT_FALSE(FPDFAnnot_HasKey(annot, GetFPDFWideString(L"none").get()));
819
820 // Check that the string value of a non-string dictionary entry is empty.
821 std::unique_ptr<unsigned short, pdfium::FreeDeleter> ap_key =
822 GetFPDFWideString(L"AP");
823 EXPECT_TRUE(FPDFAnnot_HasKey(annot, ap_key.get()));
824 EXPECT_EQ(FPDF_OBJECT_REFERENCE, FPDFAnnot_GetValueType(annot, ap_key.get()));
825 EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot, ap_key.get(), nullptr, 0));
826
827 // Check that the string value of the hash is correct.
828 std::unique_ptr<unsigned short, pdfium::FreeDeleter> hash_key =
829 GetFPDFWideString(L"AAPL:Hash");
830 EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot, hash_key.get()));
831 unsigned long len =
832 FPDFAnnot_GetStringValue(annot, hash_key.get(), nullptr, 0);
833 std::vector<char> buf(len);
834 EXPECT_EQ(66u,
835 FPDFAnnot_GetStringValue(annot, hash_key.get(), buf.data(), len));
836 EXPECT_STREQ(L"395fbcb98d558681742f30683a62a2ad",
837 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
838 .c_str());
839
840 // Check that the string value of the modified date is correct.
841 std::unique_ptr<unsigned short, pdfium::FreeDeleter> date_key =
842 GetFPDFWideString(L"M");
843 EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot, hash_key.get()));
844 len = FPDFAnnot_GetStringValue(annot, date_key.get(), nullptr, 0);
845 buf.clear();
846 buf.resize(len);
847 EXPECT_EQ(44u,
848 FPDFAnnot_GetStringValue(annot, date_key.get(), buf.data(), len));
849 EXPECT_STREQ(L"D:201706071721Z00'00'",
850 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
851 .c_str());
852
853 // Update the date entry for the annotation.
854 const wchar_t new_date[] = L"D:201706282359Z00'00'";
855 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
856 GetFPDFWideString(new_date);
857 EXPECT_TRUE(FPDFAnnot_SetStringValue(annot, date_key.get(), text.get()));
858
859 // Save the document, closing the page and document.
860 FPDFPage_CloseAnnot(annot);
861 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
862 FPDF_ClosePage(page);
863
864 // Open the saved annotation.
865#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
866 const char md5[] = "c35408717759562d1f8bf33d317483d2";
867#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
Nicolas Pena00c3cfd2017-07-10 17:29:54 -0400868 const char md5[] = "4f64add0190ede63f7bb9eb1e2e83edb";
Jane Liu2e1a32b2017-07-06 12:01:25 -0400869#else
Nicolas Pena00c3cfd2017-07-10 17:29:54 -0400870 const char md5[] = "02e1c6adff8fee4aeabd91c2c2e4be43";
Jane Liu2e1a32b2017-07-06 12:01:25 -0400871#endif
872 TestSaved(595, 842, md5);
873 FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(m_SavedPage, 0);
874
875 // Check that the string value of the modified date is the newly-set value.
876 EXPECT_EQ(FPDF_OBJECT_STRING,
877 FPDFAnnot_GetValueType(new_annot, date_key.get()));
878 len = FPDFAnnot_GetStringValue(new_annot, date_key.get(), nullptr, 0);
879 buf.clear();
880 buf.resize(len);
881 EXPECT_EQ(44u, FPDFAnnot_GetStringValue(new_annot, date_key.get(), buf.data(),
882 len));
883 EXPECT_STREQ(new_date,
884 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
885 .c_str());
886
887 FPDFPage_CloseAnnot(new_annot);
888 CloseSaved();
889}
Diana Gage7e0c05d2017-07-19 17:33:33 -0700890
891TEST_F(FPDFAnnotEmbeddertest, GetFormFieldFlagsTextField) {
892 // Open file with form text fields.
893 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
894 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
895 ASSERT_TRUE(page);
896
897 // Retrieve the first annotation: user-editable text field.
898 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
899 ASSERT_TRUE(annot);
900
901 // Check that the flag values are as expected.
902 int flags = FPDFAnnot_GetFormFieldFlags(page, annot);
903 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
904 FPDFPage_CloseAnnot(annot);
905
906 // Retrieve the second annotation: read-only text field.
907 annot = FPDFPage_GetAnnot(page, 1);
908 ASSERT_TRUE(annot);
909
910 // Check that the flag values are as expected.
911 flags = FPDFAnnot_GetFormFieldFlags(page, annot);
912 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
913 FPDFPage_CloseAnnot(annot);
914
915 UnloadPage(page);
916}
917
918TEST_F(FPDFAnnotEmbeddertest, GetFormFieldFlagsComboBox) {
919 // Open file with form text fields.
920 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
921 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
922 ASSERT_TRUE(page);
923
924 // Retrieve the first annotation: user-editable combobox.
925 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
926 ASSERT_TRUE(annot);
927
928 // Check that the flag values are as expected.
929 int flags = FPDFAnnot_GetFormFieldFlags(page, annot);
930 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
931 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
932 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
933 FPDFPage_CloseAnnot(annot);
934
935 // Retrieve the second annotation: regular combobox.
936 annot = FPDFPage_GetAnnot(page, 1);
937 ASSERT_TRUE(annot);
938
939 // Check that the flag values are as expected.
940 flags = FPDFAnnot_GetFormFieldFlags(page, annot);
941 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
942 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
943 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
944 FPDFPage_CloseAnnot(annot);
945
946 // Retrieve the third annotation: read-only combobox.
947 annot = FPDFPage_GetAnnot(page, 2);
948 ASSERT_TRUE(annot);
949
950 // Check that the flag values are as expected.
951 flags = FPDFAnnot_GetFormFieldFlags(page, annot);
952 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
953 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
954 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
955 FPDFPage_CloseAnnot(annot);
956
957 UnloadPage(page);
958}
Diana Gage40870db2017-07-19 18:16:03 -0700959
960TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotNull) {
961 // Open file with form text fields.
962 EXPECT_TRUE(OpenDocument("text_form.pdf"));
963 FPDF_PAGE page = LoadPage(0);
964 ASSERT_TRUE(page);
965
966 // Attempt to get an annotation where no annotation exists on page.
967 FPDF_ANNOTATION annot =
968 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 0, 0);
969 EXPECT_FALSE(annot);
970
971 UnloadPage(page);
972}
973
974TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotAndCheckFlagsTextField) {
975 // Open file with form text fields.
976 EXPECT_TRUE(OpenDocument("text_form_multiple.pdf"));
977 FPDF_PAGE page = LoadPage(0);
978 ASSERT_TRUE(page);
979
980 // Retrieve user-editable text field annotation.
981 FPDF_ANNOTATION annot =
982 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 118);
983 ASSERT_TRUE(annot);
984
985 // Check that interactive form annotation flag values are as expected.
986 int flags = FPDFAnnot_GetFormFieldFlags(page, annot);
987 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
988 FPDFPage_CloseAnnot(annot);
989
990 // Retrieve read-only text field annotation.
991 annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 202);
992 ASSERT_TRUE(annot);
993
994 // Check that interactive form annotation flag values are as expected.
995 flags = FPDFAnnot_GetFormFieldFlags(page, annot);
996 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
997 FPDFPage_CloseAnnot(annot);
998
999 UnloadPage(page);
1000}
1001
1002TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotAndCheckFlagsComboBox) {
1003 // Open file with form comboboxes.
1004 EXPECT_TRUE(OpenDocument("combobox_form.pdf"));
1005 FPDF_PAGE page = LoadPage(0);
1006 ASSERT_TRUE(page);
1007
1008 // Retrieve user-editable combobox annotation.
1009 FPDF_ANNOTATION annot =
1010 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 63);
1011 ASSERT_TRUE(annot);
1012
1013 // Check that interactive form annotation flag values are as expected.
1014 int flags = FPDFAnnot_GetFormFieldFlags(page, annot);
1015 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1016 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1017 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1018 FPDFPage_CloseAnnot(annot);
1019
1020 // Retrieve regular combobox annotation.
1021 annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 113);
1022 ASSERT_TRUE(annot);
1023
1024 // Check that interactive form annotation flag values are as expected.
1025 flags = FPDFAnnot_GetFormFieldFlags(page, annot);
1026 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1027 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1028 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1029 FPDFPage_CloseAnnot(annot);
1030
1031 // Retrieve read-only combobox annotation.
1032 annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 213);
1033 ASSERT_TRUE(annot);
1034
1035 // Check that interactive form annotation flag values are as expected.
1036 flags = FPDFAnnot_GetFormFieldFlags(page, annot);
1037 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1038 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1039 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1040 FPDFPage_CloseAnnot(annot);
1041
1042 UnloadPage(page);
1043}