blob: 78076842aa94df2bcd7982cb0adec6155abe401c [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
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00005#include <algorithm>
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00006#include <cwchar>
Jane Liu20eafda2017-06-07 10:33:24 -04007#include <memory>
8#include <string>
Jane Liu4fd9a472017-06-01 18:56:09 -04009#include <vector>
10
Lei Zhanga5c1daf2019-01-31 21:56:47 +000011#include "constants/annotation_common.h"
Jane Liubaa7ff42017-06-29 19:18:23 -040012#include "core/fxcrt/fx_system.h"
Tom Sepeze08d2b12018-04-25 18:49:32 +000013#include "public/cpp/fpdf_scopers.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040014#include "public/fpdf_annot.h"
Jane Liubaa7ff42017-06-29 19:18:23 -040015#include "public/fpdf_edit.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040016#include "public/fpdfview.h"
17#include "testing/embedder_test.h"
Lei Zhangb6992dd2019-02-05 23:30:20 +000018#include "testing/fx_string_testhelpers.h"
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +000019#include "testing/gmock/include/gmock/gmock-matchers.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040020#include "testing/gtest/include/gtest/gtest.h"
21
Lei Zhangab41f252018-12-23 03:10:50 +000022class FPDFAnnotEmbedderTest : public EmbedderTest {};
Jane Liu4fd9a472017-06-01 18:56:09 -040023
Lei Zhang4afee172018-01-10 20:57:15 +000024std::wstring BufferToWString(const std::vector<char>& buf) {
25 return GetPlatformWString(reinterpret_cast<FPDF_WIDESTRING>(buf.data()));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +000026}
27
Lei Zhang4afee172018-01-10 20:57:15 +000028std::string BufferToString(const std::vector<char>& buf) {
29 return GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(buf.data()));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +000030}
31
Lei Zhangab41f252018-12-23 03:10:50 +000032TEST_F(FPDFAnnotEmbedderTest, BadParams) {
Lei Zhang7557e7b2018-09-14 17:02:40 +000033 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
34 FPDF_PAGE page = LoadPage(0);
35 ASSERT_TRUE(page);
36
37 EXPECT_EQ(0, FPDFPage_GetAnnotCount(nullptr));
38
39 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, 0));
40 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, -1));
41 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, 1));
42 EXPECT_FALSE(FPDFPage_GetAnnot(page, -1));
43 EXPECT_FALSE(FPDFPage_GetAnnot(page, 1));
44
45 EXPECT_EQ(FPDF_ANNOT_UNKNOWN, FPDFAnnot_GetSubtype(nullptr));
46
47 EXPECT_EQ(0, FPDFAnnot_GetObjectCount(nullptr));
48
49 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, 0));
50 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, -1));
51 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, 1));
52
53 EXPECT_FALSE(FPDFAnnot_HasKey(nullptr, "foo"));
54
55 static constexpr wchar_t kContents[] = L"Bar";
56 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
57 GetFPDFWideString(kContents);
58 EXPECT_FALSE(FPDFAnnot_SetStringValue(nullptr, "foo", text.get()));
59
60 char buffer[128];
61 EXPECT_EQ(0u, FPDFAnnot_GetStringValue(nullptr, "foo", nullptr, 0));
62 EXPECT_EQ(0u, FPDFAnnot_GetStringValue(nullptr, "foo", buffer, 0));
63 EXPECT_EQ(0u,
64 FPDFAnnot_GetStringValue(nullptr, "foo", buffer, sizeof(buffer)));
65
66 UnloadPage(page);
67}
68
Lei Zhang3d9a0972019-03-04 19:34:09 +000069TEST_F(FPDFAnnotEmbedderTest, BadAnnotsEntry) {
70 ASSERT_TRUE(OpenDocument("bad_annots_entry.pdf"));
71 FPDF_PAGE page = LoadPage(0);
72 ASSERT_TRUE(page);
73
74 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
75 {
76 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
77 ASSERT_TRUE(annot);
78 EXPECT_EQ(-1, FPDFPage_GetAnnotIndex(page, annot.get()));
79 }
80
81 UnloadPage(page);
82}
83
Lei Zhangab41f252018-12-23 03:10:50 +000084TEST_F(FPDFAnnotEmbedderTest, RenderAnnotWithOnlyRolloverAP) {
Jane Liue17011d2017-06-21 12:18:37 -040085 // Open a file with one annotation and load its first page.
86 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +000087 FPDF_PAGE page = LoadPage(0);
Jane Liue17011d2017-06-21 12:18:37 -040088 ASSERT_TRUE(page);
89
90 // This annotation has a malformed appearance stream, which does not have its
91 // normal appearance defined, only its rollover appearance. In this case, its
92 // normal appearance should be generated, allowing the highlight annotation to
93 // still display.
Tom Sepeze08d2b12018-04-25 18:49:32 +000094 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhanga98e3662018-02-07 20:28:35 +000095 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
Jane Liue17011d2017-06-21 12:18:37 -040096
97 UnloadPage(page);
98}
99
Lei Zhangab41f252018-12-23 03:10:50 +0000100TEST_F(FPDFAnnotEmbedderTest, RenderMultilineMarkupAnnotWithoutAP) {
Ralf Sipplb3a52402018-03-19 23:30:28 +0000101 const char md5_hash[] = "76512832d88017668d9acc7aacd13dae";
Henrique Nakashima5098b252018-03-26 21:46:00 +0000102 // Open a file with multiline markup annotations.
Ralf Sipplb3a52402018-03-19 23:30:28 +0000103 ASSERT_TRUE(OpenDocument("annotation_markup_multiline_no_ap.pdf"));
104 FPDF_PAGE page = LoadPage(0);
105 ASSERT_TRUE(page);
106
Tom Sepeze08d2b12018-04-25 18:49:32 +0000107 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Ralf Sipplb3a52402018-03-19 23:30:28 +0000108 CompareBitmap(bitmap.get(), 595, 842, md5_hash);
109
110 UnloadPage(page);
111}
112
Lei Zhangab41f252018-12-23 03:10:50 +0000113TEST_F(FPDFAnnotEmbedderTest, ExtractHighlightLongContent) {
Jane Liu4fd9a472017-06-01 18:56:09 -0400114 // Open a file with one annotation and load its first page.
115 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +0000116 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu4fd9a472017-06-01 18:56:09 -0400117 ASSERT_TRUE(page);
118
119 // Check that there is a total of 1 annotation on its first page.
120 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
121
122 // Check that the annotation is of type "highlight".
Lei Zhanga21d5932018-02-05 18:28:38 +0000123 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000124 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000125 ASSERT_TRUE(annot);
126 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400127
Lei Zhanga21d5932018-02-05 18:28:38 +0000128 // Check that the annotation color is yellow.
129 unsigned int R;
130 unsigned int G;
131 unsigned int B;
132 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000133 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000134 &G, &B, &A));
135 EXPECT_EQ(255u, R);
136 EXPECT_EQ(255u, G);
137 EXPECT_EQ(0u, B);
138 EXPECT_EQ(255u, A);
Jane Liu4fd9a472017-06-01 18:56:09 -0400139
Lei Zhanga21d5932018-02-05 18:28:38 +0000140 // Check that the author is correct.
141 static constexpr char kAuthorKey[] = "T";
142 EXPECT_EQ(FPDF_OBJECT_STRING,
143 FPDFAnnot_GetValueType(annot.get(), kAuthorKey));
144 unsigned long len =
145 FPDFAnnot_GetStringValue(annot.get(), kAuthorKey, nullptr, 0);
146 std::vector<char> buf(len);
147 EXPECT_EQ(28u, FPDFAnnot_GetStringValue(annot.get(), kAuthorKey, buf.data(),
148 len));
149 EXPECT_STREQ(L"Jae Hyun Park", BufferToWString(buf).c_str());
Jane Liu4fd9a472017-06-01 18:56:09 -0400150
Lei Zhanga21d5932018-02-05 18:28:38 +0000151 // Check that the content is correct.
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000152 EXPECT_EQ(
153 FPDF_OBJECT_STRING,
154 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kContents));
155 len = FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kContents,
156 nullptr, 0);
Lei Zhanga21d5932018-02-05 18:28:38 +0000157 buf.clear();
158 buf.resize(len);
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000159 EXPECT_EQ(2690u,
160 FPDFAnnot_GetStringValue(
161 annot.get(), pdfium::annotation::kContents, buf.data(), len));
Lei Zhanga21d5932018-02-05 18:28:38 +0000162 const wchar_t contents[] =
163 L"This is a note for that highlight annotation. Very long highlight "
164 "annotation. Long long long Long long longLong long longLong long "
165 "longLong long longLong long longLong long longLong long longLong long "
166 "longLong long longLong long longLong long longLong long longLong long "
167 "longLong long longLong long longLong long longLong long longLong long "
168 "longLong long longLong long longLong long longLong long longLong long "
169 "longLong long longLong long longLong long longLong long longLong long "
170 "longLong long longLong long longLong long longLong long longLong long "
171 "longLong long longLong long longLong long longLong long longLong long "
172 "longLong long longLong long longLong long longLong long longLong long "
173 "longLong long longLong long longLong long longLong long longLong long "
174 "longLong long longLong long longLong long longLong long longLong long "
175 "longLong long longLong long longLong long longLong long longLong long "
176 "longLong long longLong long longLong long longLong long longLong long "
177 "longLong long longLong long longLong long longLong long longLong long "
178 "longLong long longLong long longLong long longLong long longLong long "
179 "longLong long longLong long longLong long longLong long longLong long "
180 "longLong long longLong long longLong long longLong long longLong long "
181 "longLong long longLong long longLong long longLong long longLong long "
182 "longLong long long. END";
183 EXPECT_STREQ(contents, BufferToWString(buf).c_str());
Jane Liu4fd9a472017-06-01 18:56:09 -0400184
Lei Zhanga21d5932018-02-05 18:28:38 +0000185 // Check that the quadpoints are correct.
186 FS_QUADPOINTSF quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000187 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000188 EXPECT_EQ(115.802643f, quadpoints.x1);
189 EXPECT_EQ(718.913940f, quadpoints.y1);
190 EXPECT_EQ(157.211182f, quadpoints.x4);
191 EXPECT_EQ(706.264465f, quadpoints.y4);
192 }
Tom Sepez507d0192018-11-07 16:37:51 +0000193 UnloadPageNoEvents(page);
Jane Liu4fd9a472017-06-01 18:56:09 -0400194}
195
Lei Zhangab41f252018-12-23 03:10:50 +0000196TEST_F(FPDFAnnotEmbedderTest, ExtractInkMultiple) {
Jane Liu4fd9a472017-06-01 18:56:09 -0400197 // Open a file with three annotations and load its first page.
198 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +0000199 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu4fd9a472017-06-01 18:56:09 -0400200 ASSERT_TRUE(page);
201
202 // Check that there is a total of 3 annotation on its first page.
203 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
204
Lei Zhanga21d5932018-02-05 18:28:38 +0000205 {
206 // Check that the third annotation is of type "ink".
Tom Sepeze08d2b12018-04-25 18:49:32 +0000207 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000208 ASSERT_TRUE(annot);
209 EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400210
Lei Zhanga21d5932018-02-05 18:28:38 +0000211 // Check that the annotation color is blue with opacity.
212 unsigned int R;
213 unsigned int G;
214 unsigned int B;
215 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000216 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000217 &G, &B, &A));
218 EXPECT_EQ(0u, R);
219 EXPECT_EQ(0u, G);
220 EXPECT_EQ(255u, B);
221 EXPECT_EQ(76u, A);
Jane Liu4fd9a472017-06-01 18:56:09 -0400222
Lei Zhanga21d5932018-02-05 18:28:38 +0000223 // Check that there is no content.
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000224 EXPECT_EQ(2u, FPDFAnnot_GetStringValue(
225 annot.get(), pdfium::annotation::kContents, nullptr, 0));
Jane Liu4fd9a472017-06-01 18:56:09 -0400226
Lei Zhanga21d5932018-02-05 18:28:38 +0000227 // Check that the rectange coordinates are correct.
228 // Note that upon rendering, the rectangle coordinates will be adjusted.
229 FS_RECTF rect;
230 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
231 EXPECT_EQ(351.820404f, rect.left);
232 EXPECT_EQ(583.830688f, rect.bottom);
233 EXPECT_EQ(475.336090f, rect.right);
234 EXPECT_EQ(681.535034f, rect.top);
235 }
Tom Sepezef43c262018-11-07 16:41:32 +0000236 {
237 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
238 CompareBitmap(bitmap.get(), 612, 792, "354002e1c4386d38fdde29ef8d61074a");
239 }
Tom Sepez507d0192018-11-07 16:37:51 +0000240 UnloadPageNoEvents(page);
Jane Liu4fd9a472017-06-01 18:56:09 -0400241}
Jane Liu20eafda2017-06-07 10:33:24 -0400242
Lei Zhangab41f252018-12-23 03:10:50 +0000243TEST_F(FPDFAnnotEmbedderTest, AddIllegalSubtypeAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400244 // Open a file with one annotation and load its first page.
245 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000246 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400247 ASSERT_TRUE(page);
248
249 // Add an annotation with an illegal subtype.
Jane Liud60e9ad2017-06-26 11:28:36 -0400250 ASSERT_FALSE(FPDFPage_CreateAnnot(page, -1));
Jane Liu20eafda2017-06-07 10:33:24 -0400251
252 UnloadPage(page);
253}
254
Lei Zhangab41f252018-12-23 03:10:50 +0000255TEST_F(FPDFAnnotEmbedderTest, AddFirstTextAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400256 // Open a file with no annotation and load its first page.
257 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000258 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400259 ASSERT_TRUE(page);
260 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
261
Lei Zhanga21d5932018-02-05 18:28:38 +0000262 {
263 // Add a text annotation to the page.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000264 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT));
Lei Zhanga21d5932018-02-05 18:28:38 +0000265 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400266
Lei Zhanga21d5932018-02-05 18:28:38 +0000267 // Check that there is now 1 annotations on this page.
268 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Jane Liu20eafda2017-06-07 10:33:24 -0400269
Lei Zhanga21d5932018-02-05 18:28:38 +0000270 // Check that the subtype of the annotation is correct.
271 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
272 }
Jane Liue10509a2017-06-20 16:47:41 -0400273
Lei Zhanga21d5932018-02-05 18:28:38 +0000274 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000275 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000276 ASSERT_TRUE(annot);
277 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu20eafda2017-06-07 10:33:24 -0400278
Lei Zhanga21d5932018-02-05 18:28:38 +0000279 // Set the color of the annotation.
280 ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 51,
281 102, 153, 204));
282 // Check that the color has been set correctly.
283 unsigned int R;
284 unsigned int G;
285 unsigned int B;
286 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000287 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000288 &G, &B, &A));
289 EXPECT_EQ(51u, R);
290 EXPECT_EQ(102u, G);
291 EXPECT_EQ(153u, B);
292 EXPECT_EQ(204u, A);
Jane Liu20eafda2017-06-07 10:33:24 -0400293
Lei Zhanga21d5932018-02-05 18:28:38 +0000294 // Change the color of the annotation.
295 ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 204,
296 153, 102, 51));
297 // Check that the color has been set correctly.
Lei Zhang75c81712018-02-08 17:22:39 +0000298 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000299 &G, &B, &A));
300 EXPECT_EQ(204u, R);
301 EXPECT_EQ(153u, G);
302 EXPECT_EQ(102u, B);
303 EXPECT_EQ(51u, A);
Jane Liu20eafda2017-06-07 10:33:24 -0400304
Lei Zhanga21d5932018-02-05 18:28:38 +0000305 // Set the annotation rectangle.
306 FS_RECTF rect;
307 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
308 EXPECT_EQ(0.f, rect.left);
309 EXPECT_EQ(0.f, rect.right);
310 rect.left = 35;
311 rect.bottom = 150;
312 rect.right = 53;
313 rect.top = 165;
314 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
315 // Check that the annotation rectangle has been set correctly.
316 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
317 EXPECT_EQ(35.f, rect.left);
318 EXPECT_EQ(150.f, rect.bottom);
319 EXPECT_EQ(53.f, rect.right);
320 EXPECT_EQ(165.f, rect.top);
Jane Liu20eafda2017-06-07 10:33:24 -0400321
Lei Zhanga21d5932018-02-05 18:28:38 +0000322 // Set the content of the annotation.
323 static constexpr wchar_t kContents[] =
324 L"Hello! This is a customized content.";
325 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
326 GetFPDFWideString(kContents);
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000327 ASSERT_TRUE(FPDFAnnot_SetStringValue(
328 annot.get(), pdfium::annotation::kContents, text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +0000329 // Check that the content has been set correctly.
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000330 unsigned long len = FPDFAnnot_GetStringValue(
331 annot.get(), pdfium::annotation::kContents, nullptr, 0);
Lei Zhanga21d5932018-02-05 18:28:38 +0000332 std::vector<char> buf(len);
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000333 EXPECT_EQ(74u,
334 FPDFAnnot_GetStringValue(
335 annot.get(), pdfium::annotation::kContents, buf.data(), len));
Lei Zhanga21d5932018-02-05 18:28:38 +0000336 EXPECT_STREQ(kContents, BufferToWString(buf).c_str());
337 }
Jane Liu20eafda2017-06-07 10:33:24 -0400338 UnloadPage(page);
339}
340
Lei Zhangab41f252018-12-23 03:10:50 +0000341TEST_F(FPDFAnnotEmbedderTest, AddAndSaveUnderlineAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400342 // Open a file with one annotation and load its first page.
343 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000344 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400345 ASSERT_TRUE(page);
346
347 // Check that there is a total of one annotation on its first page, and verify
348 // its quadpoints.
349 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Jane Liu0c6b07d2017-08-15 10:50:22 -0400350 FS_QUADPOINTSF quadpoints;
Lei Zhanga21d5932018-02-05 18:28:38 +0000351 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000352 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000353 ASSERT_TRUE(annot);
Ralf Sippl16381792018-04-12 21:20:26 +0000354 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000355 EXPECT_EQ(115.802643f, quadpoints.x1);
356 EXPECT_EQ(718.913940f, quadpoints.y1);
357 EXPECT_EQ(157.211182f, quadpoints.x4);
358 EXPECT_EQ(706.264465f, quadpoints.y4);
359 }
Jane Liu20eafda2017-06-07 10:33:24 -0400360
361 // Add an underline annotation to the page and set its quadpoints.
Lei Zhanga21d5932018-02-05 18:28:38 +0000362 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000363 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +0000364 FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE));
365 ASSERT_TRUE(annot);
366 quadpoints.x1 = 140.802643f;
367 quadpoints.x3 = 140.802643f;
Ralf Sippl16381792018-04-12 21:20:26 +0000368 ASSERT_TRUE(FPDFAnnot_AppendAttachmentPoints(annot.get(), &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000369 }
Jane Liu20eafda2017-06-07 10:33:24 -0400370
371 // Save the document, closing the page and document.
372 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +0000373 UnloadPage(page);
Jane Liu20eafda2017-06-07 10:33:24 -0400374
375 // Open the saved document.
Henrique Nakashima09b41922017-10-27 20:39:29 +0000376 const char md5[] = "dba153419f67b7c0c0e3d22d3e8910d5";
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400377
Lei Zhang0b494052019-01-31 21:41:15 +0000378 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000379 page = LoadSavedPage(0);
380 VerifySavedRendering(page, 612, 792, md5);
Jane Liu20eafda2017-06-07 10:33:24 -0400381
382 // Check that the saved document has 2 annotations on the first page
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000383 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
Jane Liu20eafda2017-06-07 10:33:24 -0400384
Lei Zhanga21d5932018-02-05 18:28:38 +0000385 {
386 // Check that the second annotation is an underline annotation and verify
387 // its quadpoints.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000388 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +0000389 ASSERT_TRUE(new_annot);
390 EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot.get()));
391 FS_QUADPOINTSF new_quadpoints;
392 ASSERT_TRUE(
Ralf Sippl16381792018-04-12 21:20:26 +0000393 FPDFAnnot_GetAttachmentPoints(new_annot.get(), 0, &new_quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000394 EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f);
395 EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f);
396 EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f);
397 EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f);
398 }
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400399
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000400 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400401 CloseSavedDocument();
Jane Liu20eafda2017-06-07 10:33:24 -0400402}
Jane Liu06462752017-06-27 16:41:14 -0400403
Lei Zhangab41f252018-12-23 03:10:50 +0000404TEST_F(FPDFAnnotEmbedderTest, GetAndSetQuadPoints) {
Ralf Sippl16381792018-04-12 21:20:26 +0000405 // Open a file with four annotations and load its first page.
406 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
407 FPDF_PAGE page = LoadPage(0);
408 ASSERT_TRUE(page);
409 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
410
411 // Retrieve the highlight annotation.
412 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
413 ASSERT_TRUE(annot);
414 ASSERT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
415
416 FS_QUADPOINTSF quadpoints;
417 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 0, &quadpoints));
418
419 {
420 // Verify the current one set of quadpoints.
421 ASSERT_EQ(1u, FPDFAnnot_CountAttachmentPoints(annot));
422
423 EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
424 EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
425 EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
426 EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
427 }
428
429 {
430 // Update the quadpoints.
431 FS_QUADPOINTSF new_quadpoints = quadpoints;
432 new_quadpoints.y1 -= 20.f;
433 new_quadpoints.y2 -= 20.f;
434 new_quadpoints.y3 -= 20.f;
435 new_quadpoints.y4 -= 20.f;
436 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, 0, &new_quadpoints));
437
438 // Verify added quadpoint set
439 ASSERT_EQ(1u, FPDFAnnot_CountAttachmentPoints(annot));
440 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 0, &quadpoints));
441 EXPECT_NEAR(new_quadpoints.x1, quadpoints.x1, 0.001f);
442 EXPECT_NEAR(new_quadpoints.y1, quadpoints.y1, 0.001f);
443 EXPECT_NEAR(new_quadpoints.x4, quadpoints.x4, 0.001f);
444 EXPECT_NEAR(new_quadpoints.y4, quadpoints.y4, 0.001f);
445 }
446
447 {
448 // Append a new set of quadpoints.
449 FS_QUADPOINTSF new_quadpoints = quadpoints;
450 new_quadpoints.y1 += 20.f;
451 new_quadpoints.y2 += 20.f;
452 new_quadpoints.y3 += 20.f;
453 new_quadpoints.y4 += 20.f;
454 ASSERT_TRUE(FPDFAnnot_AppendAttachmentPoints(annot, &new_quadpoints));
455
456 // Verify added quadpoint set
457 ASSERT_EQ(2u, FPDFAnnot_CountAttachmentPoints(annot));
458 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 1, &quadpoints));
459 EXPECT_NEAR(new_quadpoints.x1, quadpoints.x1, 0.001f);
460 EXPECT_NEAR(new_quadpoints.y1, quadpoints.y1, 0.001f);
461 EXPECT_NEAR(new_quadpoints.x4, quadpoints.x4, 0.001f);
462 EXPECT_NEAR(new_quadpoints.y4, quadpoints.y4, 0.001f);
463 }
464
465 {
466 // Setting and getting quadpoints at out-of-bound index should fail
467 EXPECT_FALSE(FPDFAnnot_SetAttachmentPoints(annot, 300000, &quadpoints));
468 EXPECT_FALSE(FPDFAnnot_GetAttachmentPoints(annot, 300000, &quadpoints));
469 }
470
471 FPDFPage_CloseAnnot(annot);
472
473 // Retrieve the square annotation
474 FPDF_ANNOTATION squareAnnot = FPDFPage_GetAnnot(page, 2);
475
476 {
477 // Check that attempting to set its quadpoints would fail
478 ASSERT_TRUE(squareAnnot);
479 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(squareAnnot));
480 EXPECT_EQ(0u, FPDFAnnot_CountAttachmentPoints(squareAnnot));
481 EXPECT_FALSE(FPDFAnnot_SetAttachmentPoints(squareAnnot, 0, &quadpoints));
482 }
483
484 FPDFPage_CloseAnnot(squareAnnot);
Ralf Sippl16381792018-04-12 21:20:26 +0000485 UnloadPage(page);
486}
487
Lei Zhangab41f252018-12-23 03:10:50 +0000488TEST_F(FPDFAnnotEmbedderTest, ModifyRectQuadpointsWithAP) {
Dan Sinclair698aed72017-09-26 16:24:49 -0400489#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
Jane Liub370e5a2017-08-16 13:24:58 -0400490 const char md5_original[] = "63af8432fab95a67cdebb7cd0e514941";
491 const char md5_modified_highlight[] = "aec26075011349dec9bace891856b5f2";
492 const char md5_modified_square[] = "057f57a32be95975775e5ec513fdcb56";
Dan Sinclair698aed72017-09-26 16:24:49 -0400493#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
Henrique Nakashima09b41922017-10-27 20:39:29 +0000494 const char md5_original[] = "0e27376094f11490f74c65f3dc3a42c5";
495 const char md5_modified_highlight[] = "66f3caef3a7d488a4fa1ad37fc06310e";
496 const char md5_modified_square[] = "a456dad0bc6801ee2d6408a4394af563";
Jane Liub370e5a2017-08-16 13:24:58 -0400497#else
Henrique Nakashima09b41922017-10-27 20:39:29 +0000498 const char md5_original[] = "0e27376094f11490f74c65f3dc3a42c5";
499 const char md5_modified_highlight[] = "66f3caef3a7d488a4fa1ad37fc06310e";
500 const char md5_modified_square[] = "a456dad0bc6801ee2d6408a4394af563";
Jane Liub370e5a2017-08-16 13:24:58 -0400501#endif
502
Jane Liu06462752017-06-27 16:41:14 -0400503 // Open a file with four annotations and load its first page.
504 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000505 FPDF_PAGE page = LoadPage(0);
Jane Liu06462752017-06-27 16:41:14 -0400506 ASSERT_TRUE(page);
507 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
508
Jane Liub370e5a2017-08-16 13:24:58 -0400509 // Check that the original file renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000510 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000511 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000512 CompareBitmap(bitmap.get(), 612, 792, md5_original);
513 }
Jane Liub370e5a2017-08-16 13:24:58 -0400514
Jane Liu0c6b07d2017-08-15 10:50:22 -0400515 FS_RECTF rect;
Jane Liu0c6b07d2017-08-15 10:50:22 -0400516 FS_RECTF new_rect;
Lei Zhanga21d5932018-02-05 18:28:38 +0000517
518 // Retrieve the highlight annotation which has its AP stream already defined.
519 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000520 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000521 ASSERT_TRUE(annot);
522 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
523
524 // Check that color cannot be set when an AP stream is defined already.
525 EXPECT_FALSE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 51,
526 102, 153, 204));
527
528 // Verify its attachment points.
529 FS_QUADPOINTSF quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000530 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000531 EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
532 EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
533 EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
534 EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
535
536 // Check that updating the attachment points would succeed.
537 quadpoints.x1 -= 50.f;
538 quadpoints.x2 -= 50.f;
539 quadpoints.x3 -= 50.f;
540 quadpoints.x4 -= 50.f;
Ralf Sippl16381792018-04-12 21:20:26 +0000541 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000542 FS_QUADPOINTSF new_quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000543 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &new_quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000544 EXPECT_EQ(quadpoints.x1, new_quadpoints.x1);
545 EXPECT_EQ(quadpoints.y1, new_quadpoints.y1);
546 EXPECT_EQ(quadpoints.x4, new_quadpoints.x4);
547 EXPECT_EQ(quadpoints.y4, new_quadpoints.y4);
548
549 // Check that updating quadpoints does not change the annotation's position.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000550 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000551 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000552 CompareBitmap(bitmap.get(), 612, 792, md5_original);
553 }
Lei Zhanga21d5932018-02-05 18:28:38 +0000554
555 // Verify its annotation rectangle.
556 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
557 EXPECT_NEAR(67.7299f, rect.left, 0.001f);
558 EXPECT_NEAR(704.296f, rect.bottom, 0.001f);
559 EXPECT_NEAR(136.325f, rect.right, 0.001f);
560 EXPECT_NEAR(721.292f, rect.top, 0.001f);
561
562 // Check that updating the rectangle would succeed.
563 rect.left -= 60.f;
564 rect.right -= 60.f;
565 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
566 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
567 EXPECT_EQ(rect.right, new_rect.right);
568 }
Jane Liu06462752017-06-27 16:41:14 -0400569
Jane Liub370e5a2017-08-16 13:24:58 -0400570 // Check that updating the rectangle changes the annotation's position.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000571 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000572 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000573 CompareBitmap(bitmap.get(), 612, 792, md5_modified_highlight);
574 }
Jane Liub370e5a2017-08-16 13:24:58 -0400575
Lei Zhanga21d5932018-02-05 18:28:38 +0000576 {
577 // Retrieve the square annotation which has its AP stream already defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000578 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000579 ASSERT_TRUE(annot);
580 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu06462752017-06-27 16:41:14 -0400581
Lei Zhanga21d5932018-02-05 18:28:38 +0000582 // Check that updating the rectangle would succeed.
583 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
584 rect.left += 70.f;
585 rect.right += 70.f;
586 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
587 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
588 EXPECT_EQ(rect.right, new_rect.right);
Jane Liu06462752017-06-27 16:41:14 -0400589
Lei Zhanga21d5932018-02-05 18:28:38 +0000590 // Check that updating the rectangle changes the square annotation's
591 // position.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000592 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000593 CompareBitmap(bitmap.get(), 612, 792, md5_modified_square);
Lei Zhanga21d5932018-02-05 18:28:38 +0000594 }
Jane Liub370e5a2017-08-16 13:24:58 -0400595
Jane Liu06462752017-06-27 16:41:14 -0400596 UnloadPage(page);
597}
Jane Liu8ce58f52017-06-29 13:40:22 -0400598
Lei Zhangab41f252018-12-23 03:10:50 +0000599TEST_F(FPDFAnnotEmbedderTest, CountAttachmentPoints) {
Henrique Nakashima5098b252018-03-26 21:46:00 +0000600 // Open a file with multiline markup annotations.
601 ASSERT_TRUE(OpenDocument("annotation_markup_multiline_no_ap.pdf"));
602 FPDF_PAGE page = LoadPage(0);
603 ASSERT_TRUE(page);
604 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000605 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Henrique Nakashima5098b252018-03-26 21:46:00 +0000606 ASSERT_TRUE(annot);
607
608 // This is a three line annotation.
609 EXPECT_EQ(3u, FPDFAnnot_CountAttachmentPoints(annot.get()));
610 }
611 UnloadPage(page);
612
613 // null annotation should return 0
614 EXPECT_EQ(0u, FPDFAnnot_CountAttachmentPoints(nullptr));
615}
616
Lei Zhangab41f252018-12-23 03:10:50 +0000617TEST_F(FPDFAnnotEmbedderTest, RemoveAnnotation) {
Jane Liu8ce58f52017-06-29 13:40:22 -0400618 // Open a file with 3 annotations on its first page.
619 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +0000620 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu8ce58f52017-06-29 13:40:22 -0400621 ASSERT_TRUE(page);
622 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
623
Jane Liu0c6b07d2017-08-15 10:50:22 -0400624 FS_RECTF rect;
Jane Liu8ce58f52017-06-29 13:40:22 -0400625
Lei Zhanga21d5932018-02-05 18:28:38 +0000626 // Check that the annotations have the expected rectangle coordinates.
627 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000628 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000629 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
630 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
631 }
Jane Liu8ce58f52017-06-29 13:40:22 -0400632
Lei Zhanga21d5932018-02-05 18:28:38 +0000633 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000634 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +0000635 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
636 EXPECT_NEAR(149.8127f, rect.left, 0.001f);
637 }
638
639 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000640 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000641 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
642 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
643 }
Jane Liu8ce58f52017-06-29 13:40:22 -0400644
645 // Check that nothing happens when attempting to remove an annotation with an
646 // out-of-bound index.
647 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4));
648 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1));
649 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
650
651 // Remove the second annotation.
652 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
653 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
654 EXPECT_FALSE(FPDFPage_GetAnnot(page, 2));
655
656 // Save the document, closing the page and document.
657 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Tom Sepez507d0192018-11-07 16:37:51 +0000658 UnloadPageNoEvents(page);
Jane Liu8ce58f52017-06-29 13:40:22 -0400659
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400660 // TODO(npm): VerifySavedRendering changes annot rect dimensions by 1??
Jane Liu8ce58f52017-06-29 13:40:22 -0400661 // Open the saved document.
662 std::string new_file = GetString();
663 FPDF_FILEACCESS file_access;
664 memset(&file_access, 0, sizeof(file_access));
665 file_access.m_FileLen = new_file.size();
666 file_access.m_GetBlock = GetBlockFromString;
667 file_access.m_Param = &new_file;
668 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
669 ASSERT_TRUE(new_doc);
670 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
671 ASSERT_TRUE(new_page);
672
673 // Check that the saved document has 2 annotations on the first page.
674 EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
675
Lei Zhanga21d5932018-02-05 18:28:38 +0000676 // Check that the remaining 2 annotations are the original 1st and 3rd ones
677 // by verifying their rectangle coordinates.
678 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000679 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(new_page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000680 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
681 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
682 }
Jane Liu8ce58f52017-06-29 13:40:22 -0400683
Lei Zhanga21d5932018-02-05 18:28:38 +0000684 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000685 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(new_page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +0000686 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
687 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
688 }
Jane Liubaa7ff42017-06-29 19:18:23 -0400689 FPDF_ClosePage(new_page);
690 FPDF_CloseDocument(new_doc);
691}
Jane Liu8ce58f52017-06-29 13:40:22 -0400692
Lei Zhangab41f252018-12-23 03:10:50 +0000693TEST_F(FPDFAnnotEmbedderTest, AddAndModifyPath) {
Dan Sinclair698aed72017-09-26 16:24:49 -0400694#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400695 const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
Dan Sinclair844d79e2018-02-16 03:46:26 +0000696 const char md5_modified_path[] = "873b92ea83ccf006e58415d866ce145b";
697 const char md5_two_paths[] = "6f1f1c91f50240e9cc9d7c87c48b93a7";
698 const char md5_new_annot[] = "078bf58f939645ac305854f31ee9a828";
Lei Zhang5e2c51c2018-07-27 22:33:34 +0000699#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
700 const char md5_original[] = "6f3cc2dd37479ce7cc072bfb0c63c275";
701 const char md5_modified_path[] = "c66293426cbf1f568502d1f7c0728fc7";
702 const char md5_two_paths[] = "122ac4625393b1dfe4be8707b73cbb13";
703 const char md5_new_annot[] = "253c7fd739646ba2568e1e8bfc782336";
Jane Liubaa7ff42017-06-29 19:18:23 -0400704#else
Henrique Nakashima09b41922017-10-27 20:39:29 +0000705 const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e";
Dan Sinclair844d79e2018-02-16 03:46:26 +0000706 const char md5_modified_path[] = "5a4a6091cff648a4ece3ce7e245e3e38";
707 const char md5_two_paths[] = "d6e4072a4415cfc6ec17201fb6be0ee0";
708 const char md5_new_annot[] = "fc338b97bf66a656916c6198697a8a28";
Jane Liubaa7ff42017-06-29 19:18:23 -0400709#endif
710
711 // Open a file with two annotations and load its first page.
712 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000713 FPDF_PAGE page = LoadPage(0);
Jane Liubaa7ff42017-06-29 19:18:23 -0400714 ASSERT_TRUE(page);
715 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
716
717 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000718 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000719 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000720 CompareBitmap(bitmap.get(), 595, 842, md5_original);
721 }
Jane Liubaa7ff42017-06-29 19:18:23 -0400722
Lei Zhanga21d5932018-02-05 18:28:38 +0000723 {
724 // Retrieve the stamp annotation which has its AP stream already defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000725 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000726 ASSERT_TRUE(annot);
Jane Liubaa7ff42017-06-29 19:18:23 -0400727
Lei Zhanga21d5932018-02-05 18:28:38 +0000728 // Check that this annotation has one path object and retrieve it.
729 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000730 ASSERT_EQ(32, FPDFPage_CountObjects(page));
Lei Zhanga21d5932018-02-05 18:28:38 +0000731 FPDF_PAGEOBJECT path = FPDFAnnot_GetObject(annot.get(), 1);
732 EXPECT_FALSE(path);
733 path = FPDFAnnot_GetObject(annot.get(), 0);
734 EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
735 EXPECT_TRUE(path);
Jane Liubaa7ff42017-06-29 19:18:23 -0400736
Lei Zhanga21d5932018-02-05 18:28:38 +0000737 // Modify the color of the path object.
738 EXPECT_TRUE(FPDFPath_SetStrokeColor(path, 0, 0, 0, 255));
739 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), path));
Jane Liubaa7ff42017-06-29 19:18:23 -0400740
Lei Zhanga21d5932018-02-05 18:28:38 +0000741 // Check that the page with the modified annotation renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000742 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000743 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000744 CompareBitmap(bitmap.get(), 595, 842, md5_modified_path);
745 }
Jane Liu7a9a38b2017-07-11 13:47:37 -0400746
Lei Zhanga21d5932018-02-05 18:28:38 +0000747 // Add a second path object to the same annotation.
748 FPDF_PAGEOBJECT dot = FPDFPageObj_CreateNewPath(7, 84);
749 EXPECT_TRUE(FPDFPath_BezierTo(dot, 9, 86, 10, 87, 11, 88));
750 EXPECT_TRUE(FPDFPath_SetStrokeColor(dot, 255, 0, 0, 100));
751 EXPECT_TRUE(FPDFPath_SetStrokeWidth(dot, 14));
752 EXPECT_TRUE(FPDFPath_SetDrawMode(dot, 0, 1));
753 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), dot));
754 EXPECT_EQ(2, FPDFAnnot_GetObjectCount(annot.get()));
Jane Liu7a9a38b2017-07-11 13:47:37 -0400755
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000756 // The object is in the annontation, not in the page, so the page object
757 // array should not change.
758 ASSERT_EQ(32, FPDFPage_CountObjects(page));
759
Lei Zhanga21d5932018-02-05 18:28:38 +0000760 // Check that the page with an annotation with two paths renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000761 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000762 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000763 CompareBitmap(bitmap.get(), 595, 842, md5_two_paths);
764 }
Jane Liu7a9a38b2017-07-11 13:47:37 -0400765
Lei Zhanga21d5932018-02-05 18:28:38 +0000766 // Delete the newly added path object.
767 EXPECT_TRUE(FPDFAnnot_RemoveObject(annot.get(), 1));
768 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000769 ASSERT_EQ(32, FPDFPage_CountObjects(page));
Lei Zhanga21d5932018-02-05 18:28:38 +0000770 }
Jane Liu7a9a38b2017-07-11 13:47:37 -0400771
772 // Check that the page renders the same as before.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000773 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000774 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000775 CompareBitmap(bitmap.get(), 595, 842, md5_modified_path);
776 }
Jane Liubaa7ff42017-06-29 19:18:23 -0400777
Jane Liubaa7ff42017-06-29 19:18:23 -0400778 FS_RECTF rect;
Jane Liubaa7ff42017-06-29 19:18:23 -0400779
Lei Zhanga21d5932018-02-05 18:28:38 +0000780 {
781 // Create another stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000782 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +0000783 ASSERT_TRUE(annot);
784 rect.left = 200.f;
785 rect.bottom = 400.f;
786 rect.right = 500.f;
787 rect.top = 600.f;
788 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
Jane Liubaa7ff42017-06-29 19:18:23 -0400789
Lei Zhanga21d5932018-02-05 18:28:38 +0000790 // Add a new path to the annotation.
791 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500);
792 EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400));
793 EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600));
794 EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550));
795 EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450));
796 EXPECT_TRUE(FPDFPath_SetStrokeColor(check, 0, 255, 255, 180));
797 EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f));
798 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
799 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), check));
800 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
801
802 // Check that the annotation's bounding box came from its rectangle.
803 FS_RECTF new_rect;
804 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
805 EXPECT_EQ(rect.left, new_rect.left);
806 EXPECT_EQ(rect.bottom, new_rect.bottom);
807 EXPECT_EQ(rect.right, new_rect.right);
808 EXPECT_EQ(rect.top, new_rect.top);
809 }
Jane Liubaa7ff42017-06-29 19:18:23 -0400810
811 // Save the document, closing the page and document.
Jane Liubaa7ff42017-06-29 19:18:23 -0400812 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +0000813 UnloadPage(page);
Jane Liubaa7ff42017-06-29 19:18:23 -0400814
815 // Open the saved document.
Lei Zhang0b494052019-01-31 21:41:15 +0000816 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000817 page = LoadSavedPage(0);
818 VerifySavedRendering(page, 595, 842, md5_new_annot);
Jane Liubaa7ff42017-06-29 19:18:23 -0400819
Jane Liu36567742017-07-06 11:13:35 -0400820 // Check that the document has a correct count of annotations and objects.
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000821 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
Jane Liubaa7ff42017-06-29 19:18:23 -0400822
Lei Zhanga21d5932018-02-05 18:28:38 +0000823 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000824 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000825 ASSERT_TRUE(annot);
826 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Jane Liubaa7ff42017-06-29 19:18:23 -0400827
Lei Zhanga21d5932018-02-05 18:28:38 +0000828 // Check that the new annotation's rectangle is as defined.
829 FS_RECTF new_rect;
830 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
831 EXPECT_EQ(rect.left, new_rect.left);
832 EXPECT_EQ(rect.bottom, new_rect.bottom);
833 EXPECT_EQ(rect.right, new_rect.right);
834 EXPECT_EQ(rect.top, new_rect.top);
835 }
836
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000837 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400838 CloseSavedDocument();
Jane Liu8ce58f52017-06-29 13:40:22 -0400839}
Jane Liub137e752017-07-05 15:04:33 -0400840
Lei Zhangab41f252018-12-23 03:10:50 +0000841TEST_F(FPDFAnnotEmbedderTest, ModifyAnnotationFlags) {
Jane Liub137e752017-07-05 15:04:33 -0400842 // Open a file with an annotation and load its first page.
843 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000844 FPDF_PAGE page = LoadPage(0);
Jane Liub137e752017-07-05 15:04:33 -0400845 ASSERT_TRUE(page);
846
847 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000848 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000849 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000850 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
851 }
Jane Liub137e752017-07-05 15:04:33 -0400852
Lei Zhanga21d5932018-02-05 18:28:38 +0000853 {
854 // Retrieve the annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000855 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000856 ASSERT_TRUE(annot);
Jane Liub137e752017-07-05 15:04:33 -0400857
Lei Zhanga21d5932018-02-05 18:28:38 +0000858 // Check that the original flag values are as expected.
859 int flags = FPDFAnnot_GetFlags(annot.get());
860 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
861 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Jane Liub137e752017-07-05 15:04:33 -0400862
Lei Zhanga21d5932018-02-05 18:28:38 +0000863 // Set the HIDDEN flag.
864 flags |= FPDF_ANNOT_FLAG_HIDDEN;
865 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), flags));
866 flags = FPDFAnnot_GetFlags(annot.get());
867 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_HIDDEN);
868 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Jane Liub137e752017-07-05 15:04:33 -0400869
Lei Zhanga21d5932018-02-05 18:28:38 +0000870 // Check that the page renders correctly without rendering the annotation.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000871 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000872 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000873 CompareBitmap(bitmap.get(), 612, 792, "1940568c9ba33bac5d0b1ee9558c76b3");
874 }
Jane Liub137e752017-07-05 15:04:33 -0400875
Lei Zhanga21d5932018-02-05 18:28:38 +0000876 // Unset the HIDDEN flag.
877 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), FPDF_ANNOT_FLAG_NONE));
878 EXPECT_FALSE(FPDFAnnot_GetFlags(annot.get()));
879 flags &= ~FPDF_ANNOT_FLAG_HIDDEN;
880 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), flags));
881 flags = FPDFAnnot_GetFlags(annot.get());
882 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
883 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Jane Liub137e752017-07-05 15:04:33 -0400884
Lei Zhanga21d5932018-02-05 18:28:38 +0000885 // Check that the page renders correctly as before.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000886 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000887 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000888 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
889 }
Lei Zhanga21d5932018-02-05 18:28:38 +0000890 }
Jane Liub137e752017-07-05 15:04:33 -0400891
Jane Liub137e752017-07-05 15:04:33 -0400892 UnloadPage(page);
893}
Jane Liu36567742017-07-06 11:13:35 -0400894
Lei Zhangab41f252018-12-23 03:10:50 +0000895TEST_F(FPDFAnnotEmbedderTest, AddAndModifyImage) {
Dan Sinclair698aed72017-09-26 16:24:49 -0400896#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400897 const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
898 const char md5_new_image[] = "ff012f5697436dfcaec25b32d1333596";
899 const char md5_modified_image[] = "86cf8cb2755a7a2046a543e66d9c1e61";
Lei Zhang5e2c51c2018-07-27 22:33:34 +0000900#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
901 const char md5_original[] = "6f3cc2dd37479ce7cc072bfb0c63c275";
902 const char md5_new_image[] = "d19c6fcfd9a170802fcfb9adfa13557e";
903 const char md5_modified_image[] = "1273cf2363570a50d1aa0c95b1318197";
Jane Liu36567742017-07-06 11:13:35 -0400904#else
Henrique Nakashima09b41922017-10-27 20:39:29 +0000905 const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e";
906 const char md5_new_image[] = "9ea8732dc9d579f68853f16892856208";
907 const char md5_modified_image[] = "74239d2a8c55c9de1dbb9cd8781895aa";
Jane Liu36567742017-07-06 11:13:35 -0400908#endif
909
910 // Open a file with two annotations and load its first page.
911 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000912 FPDF_PAGE page = LoadPage(0);
Jane Liu36567742017-07-06 11:13:35 -0400913 ASSERT_TRUE(page);
914 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
915
916 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000917 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000918 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000919 CompareBitmap(bitmap.get(), 595, 842, md5_original);
920 }
Jane Liu36567742017-07-06 11:13:35 -0400921
Jane Liu36567742017-07-06 11:13:35 -0400922 constexpr int kBitmapSize = 200;
Lei Zhanga21d5932018-02-05 18:28:38 +0000923 FPDF_BITMAP image_bitmap;
924
925 {
926 // Create a stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000927 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +0000928 ASSERT_TRUE(annot);
929 FS_RECTF rect;
930 rect.left = 200.f;
931 rect.bottom = 600.f;
932 rect.right = 400.f;
933 rect.top = 800.f;
934 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
935
936 // Add a solid-color translucent image object to the new annotation.
937 image_bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 1);
938 FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize,
939 0xeeeecccc);
940 EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(image_bitmap));
941 EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(image_bitmap));
942 FPDF_PAGEOBJECT image_object = FPDFPageObj_NewImageObj(document());
943 ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
944 ASSERT_TRUE(FPDFImageObj_SetMatrix(image_object, kBitmapSize, 0, 0,
945 kBitmapSize, 0, 0));
946 FPDFPageObj_Transform(image_object, 1, 0, 0, 1, 200, 600);
947 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), image_object));
948 }
Jane Liu36567742017-07-06 11:13:35 -0400949
950 // Check that the page renders correctly with the new image object.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000951 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000952 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000953 CompareBitmap(bitmap.get(), 595, 842, md5_new_image);
954 }
Jane Liu36567742017-07-06 11:13:35 -0400955
Lei Zhanga21d5932018-02-05 18:28:38 +0000956 {
957 // Retrieve the newly added stamp annotation and its image object.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000958 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000959 ASSERT_TRUE(annot);
960 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
961 FPDF_PAGEOBJECT image_object = FPDFAnnot_GetObject(annot.get(), 0);
962 EXPECT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(image_object));
Jane Liu36567742017-07-06 11:13:35 -0400963
Lei Zhanga21d5932018-02-05 18:28:38 +0000964 // Modify the image in the new annotation.
965 FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize,
966 0xff000000);
967 ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
968 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), image_object));
969 }
Jane Liu36567742017-07-06 11:13:35 -0400970
971 // Save the document, closing the page and document.
972 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +0000973 UnloadPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400974 FPDFBitmap_Destroy(image_bitmap);
Jane Liu36567742017-07-06 11:13:35 -0400975
976 // Test that the saved document renders the modified image object correctly.
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400977 VerifySavedDocument(595, 842, md5_modified_image);
Jane Liu36567742017-07-06 11:13:35 -0400978}
979
Lei Zhangab41f252018-12-23 03:10:50 +0000980TEST_F(FPDFAnnotEmbedderTest, AddAndModifyText) {
Dan Sinclair698aed72017-09-26 16:24:49 -0400981#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
Jane Liu7a9a38b2017-07-11 13:47:37 -0400982 const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
983 const char md5_new_text[] = "e5680ed048c2cfd9a1d27212cdf41286";
984 const char md5_modified_text[] = "79f5cfb0b07caaf936f65f6a7a57ce77";
Lei Zhang5e2c51c2018-07-27 22:33:34 +0000985#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
986 const char md5_original[] = "6f3cc2dd37479ce7cc072bfb0c63c275";
987 const char md5_new_text[] = "554d625b52144816aaabb0dd66962c55";
988 const char md5_modified_text[] = "26e94fbd3af4b1e65479327507600114";
Jane Liu36567742017-07-06 11:13:35 -0400989#else
Henrique Nakashima09b41922017-10-27 20:39:29 +0000990 const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e";
991 const char md5_new_text[] = "00b14fa2dc1c90d1b0d034e1608efef5";
992 const char md5_modified_text[] = "076c8f24a09ddc0e49f7e758edead6f0";
Jane Liu36567742017-07-06 11:13:35 -0400993#endif
994
995 // Open a file with two annotations and load its first page.
996 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000997 FPDF_PAGE page = LoadPage(0);
Jane Liu36567742017-07-06 11:13:35 -0400998 ASSERT_TRUE(page);
999 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1000
1001 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001002 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001003 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001004 CompareBitmap(bitmap.get(), 595, 842, md5_original);
1005 }
Jane Liu36567742017-07-06 11:13:35 -04001006
Lei Zhanga21d5932018-02-05 18:28:38 +00001007 {
1008 // Create a stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001009 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001010 ASSERT_TRUE(annot);
1011 FS_RECTF rect;
1012 rect.left = 200.f;
1013 rect.bottom = 550.f;
1014 rect.right = 450.f;
1015 rect.top = 650.f;
1016 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
Jane Liu36567742017-07-06 11:13:35 -04001017
Lei Zhanga21d5932018-02-05 18:28:38 +00001018 // Add a translucent text object to the new annotation.
1019 FPDF_PAGEOBJECT text_object =
1020 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
1021 EXPECT_TRUE(text_object);
1022 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
1023 GetFPDFWideString(L"I'm a translucent text laying on other text.");
1024 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
1025 EXPECT_TRUE(FPDFText_SetFillColor(text_object, 0, 0, 255, 150));
1026 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 600);
1027 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), text_object));
1028 }
Jane Liu36567742017-07-06 11:13:35 -04001029
1030 // Check that the page renders correctly with the new text object.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001031 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001032 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001033 CompareBitmap(bitmap.get(), 595, 842, md5_new_text);
1034 }
Jane Liu36567742017-07-06 11:13:35 -04001035
Lei Zhanga21d5932018-02-05 18:28:38 +00001036 {
1037 // Retrieve the newly added stamp annotation and its text object.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001038 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001039 ASSERT_TRUE(annot);
1040 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1041 FPDF_PAGEOBJECT text_object = FPDFAnnot_GetObject(annot.get(), 0);
1042 EXPECT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_object));
Jane Liu36567742017-07-06 11:13:35 -04001043
Lei Zhanga21d5932018-02-05 18:28:38 +00001044 // Modify the text in the new annotation.
1045 std::unique_ptr<unsigned short, pdfium::FreeDeleter> new_text =
1046 GetFPDFWideString(L"New text!");
1047 EXPECT_TRUE(FPDFText_SetText(text_object, new_text.get()));
1048 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), text_object));
1049 }
Jane Liu36567742017-07-06 11:13:35 -04001050
1051 // Check that the page renders correctly with the modified text object.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001052 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001053 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001054 CompareBitmap(bitmap.get(), 595, 842, md5_modified_text);
1055 }
Jane Liu36567742017-07-06 11:13:35 -04001056
1057 // Remove the new annotation, and check that the page renders as before.
1058 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 2));
Lei Zhangc113c7a2018-02-12 14:58:44 +00001059 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001060 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001061 CompareBitmap(bitmap.get(), 595, 842, md5_original);
1062 }
Jane Liu36567742017-07-06 11:13:35 -04001063
1064 UnloadPage(page);
1065}
Jane Liu2e1a32b2017-07-06 12:01:25 -04001066
Lei Zhangab41f252018-12-23 03:10:50 +00001067TEST_F(FPDFAnnotEmbedderTest, GetSetStringValue) {
Jane Liu2e1a32b2017-07-06 12:01:25 -04001068 // Open a file with four annotations and load its first page.
1069 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001070 FPDF_PAGE page = LoadPage(0);
Jane Liu2e1a32b2017-07-06 12:01:25 -04001071 ASSERT_TRUE(page);
1072
Lei Zhanga21d5932018-02-05 18:28:38 +00001073 static constexpr wchar_t kNewDate[] = L"D:201706282359Z00'00'";
Jane Liu2e1a32b2017-07-06 12:01:25 -04001074
Lei Zhanga21d5932018-02-05 18:28:38 +00001075 {
1076 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001077 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001078 ASSERT_TRUE(annot);
1079
1080 // Check that a non-existent key does not exist.
1081 EXPECT_FALSE(FPDFAnnot_HasKey(annot.get(), "none"));
1082
1083 // Check that the string value of a non-string dictionary entry is empty.
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001084 EXPECT_TRUE(FPDFAnnot_HasKey(annot.get(), pdfium::annotation::kAP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001085 EXPECT_EQ(FPDF_OBJECT_REFERENCE,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001086 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kAP));
1087 EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kAP,
1088 nullptr, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001089
1090 // Check that the string value of the hash is correct.
1091 static constexpr char kHashKey[] = "AAPL:Hash";
1092 EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot.get(), kHashKey));
1093 unsigned long len =
1094 FPDFAnnot_GetStringValue(annot.get(), kHashKey, nullptr, 0);
1095 std::vector<char> buf(len);
1096 EXPECT_EQ(66u,
1097 FPDFAnnot_GetStringValue(annot.get(), kHashKey, buf.data(), len));
1098 EXPECT_STREQ(L"395fbcb98d558681742f30683a62a2ad",
1099 BufferToWString(buf).c_str());
1100
1101 // Check that the string value of the modified date is correct.
1102 EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot.get(), kHashKey));
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001103 len = FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kM, nullptr,
1104 0);
Lei Zhanga21d5932018-02-05 18:28:38 +00001105 buf.clear();
1106 buf.resize(len);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001107 EXPECT_EQ(44u, FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kM,
1108 buf.data(), len));
Lei Zhanga21d5932018-02-05 18:28:38 +00001109 EXPECT_STREQ(L"D:201706071721Z00'00'", BufferToWString(buf).c_str());
1110
1111 // Update the date entry for the annotation.
1112 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
1113 GetFPDFWideString(kNewDate);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001114 EXPECT_TRUE(FPDFAnnot_SetStringValue(annot.get(), pdfium::annotation::kM,
1115 text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001116 }
Jane Liu2e1a32b2017-07-06 12:01:25 -04001117
1118 // Save the document, closing the page and document.
Jane Liu2e1a32b2017-07-06 12:01:25 -04001119 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001120 UnloadPage(page);
Jane Liu2e1a32b2017-07-06 12:01:25 -04001121
Dan Sinclair698aed72017-09-26 16:24:49 -04001122#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
Artem Strygind24b97e2017-08-09 18:50:59 +03001123 const char md5[] = "4d64e61c9c0f8c60ab3cc3234bb73b1c";
Lei Zhang5e2c51c2018-07-27 22:33:34 +00001124#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
1125 const char md5[] = "9ee141f698c3fcb56c050dffd6c82624";
Jane Liu2e1a32b2017-07-06 12:01:25 -04001126#else
Henrique Nakashima09b41922017-10-27 20:39:29 +00001127 const char md5[] = "c96ee1f316d7f5a1b154de9f9d467f01";
Jane Liu2e1a32b2017-07-06 12:01:25 -04001128#endif
Dan Sinclair971a6742018-03-28 19:23:25 +00001129
1130 // Open the saved annotation.
Lei Zhang0b494052019-01-31 21:41:15 +00001131 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001132 page = LoadSavedPage(0);
1133 VerifySavedRendering(page, 595, 842, md5);
Lei Zhanga21d5932018-02-05 18:28:38 +00001134 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001135 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 0));
Jane Liu2e1a32b2017-07-06 12:01:25 -04001136
Lei Zhanga21d5932018-02-05 18:28:38 +00001137 // Check that the string value of the modified date is the newly-set value.
1138 EXPECT_EQ(FPDF_OBJECT_STRING,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001139 FPDFAnnot_GetValueType(new_annot.get(), pdfium::annotation::kM));
1140 unsigned long len = FPDFAnnot_GetStringValue(
1141 new_annot.get(), pdfium::annotation::kM, nullptr, 0);
Lei Zhanga21d5932018-02-05 18:28:38 +00001142 std::vector<char> buf(len);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001143 EXPECT_EQ(44u,
1144 FPDFAnnot_GetStringValue(new_annot.get(), pdfium::annotation::kM,
1145 buf.data(), len));
Lei Zhanga21d5932018-02-05 18:28:38 +00001146 EXPECT_STREQ(kNewDate, BufferToWString(buf).c_str());
1147 }
Jane Liu2e1a32b2017-07-06 12:01:25 -04001148
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001149 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04001150 CloseSavedDocument();
Jane Liu2e1a32b2017-07-06 12:01:25 -04001151}
Diana Gage7e0c05d2017-07-19 17:33:33 -07001152
Lei Zhangab41f252018-12-23 03:10:50 +00001153TEST_F(FPDFAnnotEmbedderTest, GetSetAP) {
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001154 // Open a file with four annotations and load its first page.
1155 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001156 FPDF_PAGE page = LoadPage(0);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001157 ASSERT_TRUE(page);
1158
Lei Zhanga21d5932018-02-05 18:28:38 +00001159 {
1160 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001161 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001162 ASSERT_TRUE(annot);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001163
Lei Zhanga21d5932018-02-05 18:28:38 +00001164 // Check that the string value of an AP returns the expected length.
1165 unsigned long normal_len = FPDFAnnot_GetAP(
1166 annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
1167 EXPECT_EQ(73970u, normal_len);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001168
Lei Zhanga21d5932018-02-05 18:28:38 +00001169 // Check that the string value of an AP is not returned if the buffer is too
1170 // small. The result buffer should be overwritten with an empty string.
1171 std::vector<char> buf(normal_len - 1);
1172 // Write L"z" in the buffer to verify it's not overwritten.
1173 wcscpy(reinterpret_cast<wchar_t*>(buf.data()), L"z");
1174 EXPECT_EQ(73970u,
1175 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1176 buf.data(), buf.size()));
1177 std::string ap = BufferToString(buf);
1178 EXPECT_STREQ("z", ap.c_str());
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001179
Lei Zhanga21d5932018-02-05 18:28:38 +00001180 // Check that the string value of an AP is returned through a buffer that is
1181 // the right size.
1182 buf.clear();
1183 buf.resize(normal_len);
1184 EXPECT_EQ(73970u,
1185 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1186 buf.data(), buf.size()));
1187 ap = BufferToString(buf);
1188 EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J"));
1189 EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q"));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001190
Lei Zhanga21d5932018-02-05 18:28:38 +00001191 // Check that the string value of an AP is returned through a buffer that is
1192 // larger than necessary.
1193 buf.clear();
1194 buf.resize(normal_len + 1);
1195 EXPECT_EQ(73970u,
1196 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1197 buf.data(), buf.size()));
1198 ap = BufferToString(buf);
1199 EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J"));
1200 EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q"));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001201
Lei Zhanga21d5932018-02-05 18:28:38 +00001202 // Check that getting an AP for a mode that does not have an AP returns an
1203 // empty string.
1204 unsigned long rollover_len = FPDFAnnot_GetAP(
1205 annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
1206 EXPECT_EQ(2u, rollover_len);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001207
Lei Zhanga21d5932018-02-05 18:28:38 +00001208 buf.clear();
1209 buf.resize(1000);
1210 EXPECT_EQ(2u,
1211 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1212 buf.data(), buf.size()));
1213 EXPECT_STREQ("", BufferToString(buf).c_str());
Henrique Nakashima5970a472018-01-11 22:40:59 +00001214
Lei Zhanga21d5932018-02-05 18:28:38 +00001215 // Check that setting the AP for an invalid appearance mode fails.
1216 std::unique_ptr<unsigned short, pdfium::FreeDeleter> apText =
1217 GetFPDFWideString(L"new test ap");
1218 EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), -1, apText.get()));
1219 EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_COUNT,
1220 apText.get()));
1221 EXPECT_FALSE(FPDFAnnot_SetAP(
1222 annot.get(), FPDF_ANNOT_APPEARANCEMODE_COUNT + 1, apText.get()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001223
Lei Zhanga21d5932018-02-05 18:28:38 +00001224 // Set the AP correctly now.
1225 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1226 apText.get()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001227
Lei Zhanga21d5932018-02-05 18:28:38 +00001228 // Check that the new annotation value is equal to the value we just set.
1229 rollover_len = FPDFAnnot_GetAP(
1230 annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
1231 EXPECT_EQ(24u, rollover_len);
1232 buf.clear();
1233 buf.resize(rollover_len);
1234 EXPECT_EQ(24u,
1235 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1236 buf.data(), buf.size()));
1237 EXPECT_STREQ(L"new test ap", BufferToWString(buf).c_str());
Henrique Nakashima5970a472018-01-11 22:40:59 +00001238
Lei Zhanga21d5932018-02-05 18:28:38 +00001239 // Check that the Normal AP was not touched when the Rollover AP was set.
1240 buf.clear();
1241 buf.resize(normal_len);
1242 EXPECT_EQ(73970u,
1243 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1244 buf.data(), buf.size()));
1245 ap = BufferToString(buf);
1246 EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J"));
1247 EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q"));
1248 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001249
1250 // Save the modified document, then reopen it.
Henrique Nakashima5970a472018-01-11 22:40:59 +00001251 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001252 UnloadPage(page);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001253
Lei Zhang0b494052019-01-31 21:41:15 +00001254 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima5970a472018-01-11 22:40:59 +00001255 page = LoadSavedPage(0);
Lei Zhanga21d5932018-02-05 18:28:38 +00001256 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001257 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001258
Lei Zhanga21d5932018-02-05 18:28:38 +00001259 // Check that the new annotation value is equal to the value we set before
1260 // saving.
1261 unsigned long rollover_len = FPDFAnnot_GetAP(
1262 new_annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
1263 EXPECT_EQ(24u, rollover_len);
1264 std::vector<char> buf(rollover_len);
1265 EXPECT_EQ(24u, FPDFAnnot_GetAP(new_annot.get(),
1266 FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1267 buf.data(), buf.size()));
1268 EXPECT_STREQ(L"new test ap", BufferToWString(buf).c_str());
1269 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001270
1271 // Close saved document.
Henrique Nakashima5970a472018-01-11 22:40:59 +00001272 CloseSavedPage(page);
1273 CloseSavedDocument();
1274}
1275
Lei Zhangab41f252018-12-23 03:10:50 +00001276TEST_F(FPDFAnnotEmbedderTest, RemoveOptionalAP) {
Henrique Nakashima5970a472018-01-11 22:40:59 +00001277 // Open a file with four annotations and load its first page.
1278 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001279 FPDF_PAGE page = LoadPage(0);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001280 ASSERT_TRUE(page);
1281
Lei Zhanga21d5932018-02-05 18:28:38 +00001282 {
1283 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001284 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001285 ASSERT_TRUE(annot);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001286
Lei Zhanga21d5932018-02-05 18:28:38 +00001287 // Set Down AP. Normal AP is already set.
1288 std::unique_ptr<unsigned short, pdfium::FreeDeleter> apText =
1289 GetFPDFWideString(L"new test ap");
1290 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1291 apText.get()));
1292 EXPECT_EQ(73970u,
1293 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1294 nullptr, 0));
1295 EXPECT_EQ(24u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1296 nullptr, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001297
Lei Zhanga21d5932018-02-05 18:28:38 +00001298 // Check that setting the Down AP to null removes the Down entry but keeps
1299 // Normal intact.
1300 EXPECT_TRUE(
1301 FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr));
1302 EXPECT_EQ(73970u,
1303 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1304 nullptr, 0));
1305 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1306 nullptr, 0));
1307 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001308
Lei Zhang75c81712018-02-08 17:22:39 +00001309 UnloadPage(page);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001310}
1311
Lei Zhangab41f252018-12-23 03:10:50 +00001312TEST_F(FPDFAnnotEmbedderTest, RemoveRequiredAP) {
Henrique Nakashima5970a472018-01-11 22:40:59 +00001313 // Open a file with four annotations and load its first page.
1314 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001315 FPDF_PAGE page = LoadPage(0);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001316 ASSERT_TRUE(page);
1317
Lei Zhanga21d5932018-02-05 18:28:38 +00001318 {
1319 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001320 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001321 ASSERT_TRUE(annot);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001322
Lei Zhanga21d5932018-02-05 18:28:38 +00001323 // Set Down AP. Normal AP is already set.
1324 std::unique_ptr<unsigned short, pdfium::FreeDeleter> apText =
1325 GetFPDFWideString(L"new test ap");
1326 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1327 apText.get()));
1328 EXPECT_EQ(73970u,
1329 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1330 nullptr, 0));
1331 EXPECT_EQ(24u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1332 nullptr, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001333
Lei Zhanga21d5932018-02-05 18:28:38 +00001334 // Check that setting the Normal AP to null removes the whole AP dictionary.
1335 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1336 nullptr));
1337 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1338 nullptr, 0));
1339 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1340 nullptr, 0));
1341 }
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001342
Lei Zhang75c81712018-02-08 17:22:39 +00001343 UnloadPage(page);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001344}
1345
Lei Zhangab41f252018-12-23 03:10:50 +00001346TEST_F(FPDFAnnotEmbedderTest, ExtractLinkedAnnotations) {
Jane Liu300bb272017-08-21 14:37:53 -04001347 // Open a file with annotations and load its first page.
1348 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001349 FPDF_PAGE page = LoadPage(0);
Jane Liu300bb272017-08-21 14:37:53 -04001350 ASSERT_TRUE(page);
Jane Liud1ed1ce2017-08-24 12:31:10 -04001351 EXPECT_EQ(-1, FPDFPage_GetAnnotIndex(page, nullptr));
Jane Liu300bb272017-08-21 14:37:53 -04001352
Lei Zhanga21d5932018-02-05 18:28:38 +00001353 {
1354 // Retrieve the highlight annotation which has its popup defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001355 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001356 ASSERT_TRUE(annot);
1357 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
1358 EXPECT_EQ(0, FPDFPage_GetAnnotIndex(page, annot.get()));
1359 static constexpr char kPopupKey[] = "Popup";
1360 ASSERT_TRUE(FPDFAnnot_HasKey(annot.get(), kPopupKey));
1361 ASSERT_EQ(FPDF_OBJECT_REFERENCE,
1362 FPDFAnnot_GetValueType(annot.get(), kPopupKey));
Jane Liu300bb272017-08-21 14:37:53 -04001363
Lei Zhanga21d5932018-02-05 18:28:38 +00001364 // Retrieve and verify the popup of the highlight annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001365 ScopedFPDFAnnotation popup(
Lei Zhanga21d5932018-02-05 18:28:38 +00001366 FPDFAnnot_GetLinkedAnnot(annot.get(), kPopupKey));
1367 ASSERT_TRUE(popup);
1368 EXPECT_EQ(FPDF_ANNOT_POPUP, FPDFAnnot_GetSubtype(popup.get()));
1369 EXPECT_EQ(1, FPDFPage_GetAnnotIndex(page, popup.get()));
1370 FS_RECTF rect;
1371 ASSERT_TRUE(FPDFAnnot_GetRect(popup.get(), &rect));
1372 EXPECT_NEAR(612.0f, rect.left, 0.001f);
1373 EXPECT_NEAR(578.792, rect.bottom, 0.001f);
Jane Liu300bb272017-08-21 14:37:53 -04001374
Lei Zhanga21d5932018-02-05 18:28:38 +00001375 // Attempting to retrieve |annot|'s "IRT"-linked annotation would fail,
1376 // since "IRT" is not a key in |annot|'s dictionary.
1377 static constexpr char kIRTKey[] = "IRT";
1378 ASSERT_FALSE(FPDFAnnot_HasKey(annot.get(), kIRTKey));
1379 EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot.get(), kIRTKey));
Jane Liu300bb272017-08-21 14:37:53 -04001380
Lei Zhanga21d5932018-02-05 18:28:38 +00001381 // Attempting to retrieve |annot|'s parent dictionary as an annotation
1382 // would fail, since its parent is not an annotation.
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001383 ASSERT_TRUE(FPDFAnnot_HasKey(annot.get(), pdfium::annotation::kP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001384 EXPECT_EQ(FPDF_OBJECT_REFERENCE,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001385 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kP));
1386 EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot.get(), pdfium::annotation::kP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001387 }
Jane Liu300bb272017-08-21 14:37:53 -04001388
Jane Liu300bb272017-08-21 14:37:53 -04001389 UnloadPage(page);
1390}
1391
Lei Zhangab41f252018-12-23 03:10:50 +00001392TEST_F(FPDFAnnotEmbedderTest, GetFormFieldFlagsTextField) {
Diana Gage7e0c05d2017-07-19 17:33:33 -07001393 // Open file with form text fields.
1394 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001395 FPDF_PAGE page = LoadPage(0);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001396 ASSERT_TRUE(page);
1397
Lei Zhanga21d5932018-02-05 18:28:38 +00001398 {
1399 // Retrieve the first annotation: user-editable text field.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001400 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001401 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001402
Lei Zhanga21d5932018-02-05 18:28:38 +00001403 // Check that the flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001404 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001405 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1406 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001407
Lei Zhanga21d5932018-02-05 18:28:38 +00001408 {
1409 // Retrieve the second annotation: read-only text field.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001410 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +00001411 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001412
Lei Zhanga21d5932018-02-05 18:28:38 +00001413 // Check that the flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001414 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001415 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1416 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001417
1418 UnloadPage(page);
1419}
1420
Lei Zhangab41f252018-12-23 03:10:50 +00001421TEST_F(FPDFAnnotEmbedderTest, GetFormFieldFlagsComboBox) {
Diana Gage7e0c05d2017-07-19 17:33:33 -07001422 // Open file with form text fields.
1423 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001424 FPDF_PAGE page = LoadPage(0);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001425 ASSERT_TRUE(page);
1426
Lei Zhanga21d5932018-02-05 18:28:38 +00001427 {
1428 // Retrieve the first annotation: user-editable combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001429 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001430 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001431
Lei Zhanga21d5932018-02-05 18:28:38 +00001432 // Check that the flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001433 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001434 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1435 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1436 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1437 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001438
Lei Zhanga21d5932018-02-05 18:28:38 +00001439 {
1440 // Retrieve the second annotation: regular combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001441 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +00001442 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001443
Lei Zhanga21d5932018-02-05 18:28:38 +00001444 // Check that the flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001445 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001446 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1447 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1448 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1449 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001450
Lei Zhanga21d5932018-02-05 18:28:38 +00001451 {
1452 // Retrieve the third annotation: read-only combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001453 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001454 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001455
Lei Zhanga21d5932018-02-05 18:28:38 +00001456 // Check that the flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001457 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001458 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1459 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1460 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1461 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001462
1463 UnloadPage(page);
1464}
Diana Gage40870db2017-07-19 18:16:03 -07001465
Lei Zhangab41f252018-12-23 03:10:50 +00001466TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotNull) {
Diana Gage40870db2017-07-19 18:16:03 -07001467 // Open file with form text fields.
1468 EXPECT_TRUE(OpenDocument("text_form.pdf"));
1469 FPDF_PAGE page = LoadPage(0);
1470 ASSERT_TRUE(page);
1471
1472 // Attempt to get an annotation where no annotation exists on page.
Lei Zhang7557e7b2018-09-14 17:02:40 +00001473 EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 0, 0));
1474
1475 {
1476 // Verify there is an annotation.
1477 ScopedFPDFAnnotation annot(
1478 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 120, 120));
1479 EXPECT_TRUE(annot);
1480 }
1481
1482 // Try other bad inputs at a valid location.
1483 EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, nullptr, 120, 120));
1484 EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, page, 120, 120));
1485 EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(form_handle(), nullptr, 120, 120));
Diana Gage40870db2017-07-19 18:16:03 -07001486
1487 UnloadPage(page);
1488}
1489
Lei Zhangab41f252018-12-23 03:10:50 +00001490TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotAndCheckFlagsTextField) {
Diana Gage40870db2017-07-19 18:16:03 -07001491 // Open file with form text fields.
1492 EXPECT_TRUE(OpenDocument("text_form_multiple.pdf"));
1493 FPDF_PAGE page = LoadPage(0);
1494 ASSERT_TRUE(page);
1495
Lei Zhanga21d5932018-02-05 18:28:38 +00001496 {
1497 // Retrieve user-editable text field annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001498 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +00001499 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 118));
1500 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001501
Lei Zhanga21d5932018-02-05 18:28:38 +00001502 // Check that interactive form annotation flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001503 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001504 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1505 }
Diana Gage40870db2017-07-19 18:16:03 -07001506
Lei Zhanga21d5932018-02-05 18:28:38 +00001507 {
1508 // Retrieve read-only text field annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001509 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +00001510 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 202));
1511 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001512
Lei Zhanga21d5932018-02-05 18:28:38 +00001513 // Check that interactive form annotation flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001514 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001515 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1516 }
Diana Gage40870db2017-07-19 18:16:03 -07001517
1518 UnloadPage(page);
1519}
1520
Lei Zhangab41f252018-12-23 03:10:50 +00001521TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotAndCheckFlagsComboBox) {
Diana Gage40870db2017-07-19 18:16:03 -07001522 // Open file with form comboboxes.
1523 EXPECT_TRUE(OpenDocument("combobox_form.pdf"));
1524 FPDF_PAGE page = LoadPage(0);
1525 ASSERT_TRUE(page);
1526
Lei Zhanga21d5932018-02-05 18:28:38 +00001527 {
1528 // Retrieve user-editable combobox annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001529 ScopedFPDFAnnotation annot(
Henrique Nakashima20830922018-03-19 21:21:46 +00001530 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 363));
Lei Zhanga21d5932018-02-05 18:28:38 +00001531 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001532
Lei Zhanga21d5932018-02-05 18:28:38 +00001533 // Check that interactive form annotation flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001534 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001535 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1536 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1537 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1538 }
Diana Gage40870db2017-07-19 18:16:03 -07001539
Lei Zhanga21d5932018-02-05 18:28:38 +00001540 {
1541 // Retrieve regular combobox annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001542 ScopedFPDFAnnotation annot(
Henrique Nakashima20830922018-03-19 21:21:46 +00001543 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 413));
Lei Zhanga21d5932018-02-05 18:28:38 +00001544 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001545
Lei Zhanga21d5932018-02-05 18:28:38 +00001546 // Check that interactive form annotation flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001547 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001548 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1549 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1550 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1551 }
Diana Gage40870db2017-07-19 18:16:03 -07001552
Lei Zhanga21d5932018-02-05 18:28:38 +00001553 {
1554 // Retrieve read-only combobox annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001555 ScopedFPDFAnnotation annot(
Henrique Nakashima20830922018-03-19 21:21:46 +00001556 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 513));
Lei Zhanga21d5932018-02-05 18:28:38 +00001557 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001558
Lei Zhanga21d5932018-02-05 18:28:38 +00001559 // Check that interactive form annotation flag values are as expected.
Lei Zhange6fcdfa2019-02-14 04:07:09 +00001560 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), page, annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001561 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1562 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1563 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1564 }
Diana Gage40870db2017-07-19 18:16:03 -07001565
1566 UnloadPage(page);
1567}
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001568
Lei Zhang992e7e22019-02-04 19:20:58 +00001569TEST_F(FPDFAnnotEmbedderTest, BUG_1206) {
1570 static constexpr size_t kExpectedSize = 1609;
1571 static const char kExpectedBitmap[] = "0d9fc05c6762fd788bd23fd87a4967bc";
1572
1573 ASSERT_TRUE(OpenDocument("bug_1206.pdf"));
1574
1575 FPDF_PAGE page = LoadPage(0);
1576 ASSERT_TRUE(page);
1577
1578 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1579 EXPECT_EQ(kExpectedSize, GetString().size());
1580 ClearString();
1581
1582 for (size_t i = 0; i < 10; ++i) {
1583 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1584 CompareBitmap(bitmap.get(), 612, 792, kExpectedBitmap);
1585
1586 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1587 // TODO(https://crbug.com/pdfium/1206): This is wrong. The size should be
1588 // equal, not bigger.
1589 EXPECT_LT(kExpectedSize, GetString().size());
1590 ClearString();
1591 }
1592
1593 UnloadPage(page);
1594}
1595
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001596TEST_F(FPDFAnnotEmbedderTest, BUG_1212) {
1597 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1598 FPDF_PAGE page = LoadPage(0);
1599 ASSERT_TRUE(page);
1600 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
1601
1602 static const char kTestKey[] = "test";
1603 static constexpr wchar_t kData[] = L"\xf6\xe4";
1604 std::vector<char> buf(12);
1605
1606 {
1607 // Add a text annotation to the page.
1608 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT));
1609 ASSERT_TRUE(annot);
1610 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
1611 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
1612
1613 // Make sure there is no test key, add set a value there, and read it back.
1614 std::fill(buf.begin(), buf.end(), 'x');
1615 ASSERT_EQ(2u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
1616 buf.size()));
1617 EXPECT_STREQ(L"", BufferToWString(buf).c_str());
1618
1619 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
1620 GetFPDFWideString(kData);
1621 EXPECT_TRUE(FPDFAnnot_SetStringValue(annot.get(), kTestKey, text.get()));
1622
1623 std::fill(buf.begin(), buf.end(), 'x');
1624 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
1625 buf.size()));
1626 EXPECT_STREQ(kData, BufferToWString(buf).c_str());
1627 }
1628
Lei Zhang05ec64c2019-01-09 03:00:06 +00001629 {
1630 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
1631 ASSERT_TRUE(annot);
1632 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1633 EXPECT_EQ(FPDF_ANNOT_STAMP, FPDFAnnot_GetSubtype(annot.get()));
1634 // Also do the same test for its appearance string.
1635 std::fill(buf.begin(), buf.end(), 'x');
1636 ASSERT_EQ(2u,
1637 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1638 buf.data(), buf.size()));
1639 EXPECT_STREQ(L"", BufferToWString(buf).c_str());
1640
1641 std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
1642 GetFPDFWideString(kData);
1643 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1644 text.get()));
1645
1646 std::fill(buf.begin(), buf.end(), 'x');
1647 ASSERT_EQ(6u,
1648 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1649 buf.data(), buf.size()));
1650 EXPECT_STREQ(kData, BufferToWString(buf).c_str());
1651 }
1652
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001653 UnloadPage(page);
1654
1655 {
1656 // Save a copy, open the copy, and check the annotation again.
1657 // Note that it renders the rotation.
1658 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang0b494052019-01-31 21:41:15 +00001659 ASSERT_TRUE(OpenSavedDocument());
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001660 FPDF_PAGE saved_page = LoadSavedPage(0);
1661 ASSERT_TRUE(saved_page);
1662
Lei Zhang05ec64c2019-01-09 03:00:06 +00001663 EXPECT_EQ(2, FPDFPage_GetAnnotCount(saved_page));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001664 {
1665 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(saved_page, 0));
1666 ASSERT_TRUE(annot);
1667 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
1668
1669 std::fill(buf.begin(), buf.end(), 'x');
1670 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
1671 buf.size()));
1672 EXPECT_STREQ(kData, BufferToWString(buf).c_str());
1673 }
1674
Lei Zhang05ec64c2019-01-09 03:00:06 +00001675 {
1676 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(saved_page, 0));
1677 ASSERT_TRUE(annot);
1678 // TODO(thestig): This return FPDF_ANNOT_UNKNOWN for some reason.
1679 // EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
1680
1681 std::fill(buf.begin(), buf.end(), 'x');
1682 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
1683 buf.size()));
1684 EXPECT_STREQ(kData, BufferToWString(buf).c_str());
1685 }
1686
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001687 CloseSavedPage(saved_page);
1688 CloseSavedDocument();
1689 }
1690}
rycsmithcb752f32019-02-21 18:40:53 +00001691
1692TEST_F(FPDFAnnotEmbedderTest, GetOptionCountCombobox) {
1693 // Open a file with combobox widget annotations and load its first page.
1694 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
1695 FPDF_PAGE page = LoadPage(0);
1696 ASSERT_TRUE(page);
1697
1698 {
1699 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1700 ASSERT_TRUE(annot);
1701
1702 EXPECT_EQ(3, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1703
1704 annot.reset(FPDFPage_GetAnnot(page, 1));
1705 ASSERT_TRUE(annot);
1706
1707 EXPECT_EQ(26, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
Lei Zhange7033c82019-02-26 19:30:49 +00001708
1709 // Check bad form handle / annot.
1710 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(nullptr, nullptr));
1711 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), nullptr));
1712 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(nullptr, annot.get()));
rycsmithcb752f32019-02-21 18:40:53 +00001713 }
1714
1715 UnloadPage(page);
1716}
1717
1718TEST_F(FPDFAnnotEmbedderTest, GetOptionCountListbox) {
1719 // Open a file with listbox widget annotations and load its first page.
1720 ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
1721 FPDF_PAGE page = LoadPage(0);
1722 ASSERT_TRUE(page);
1723
1724 {
1725 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1726 ASSERT_TRUE(annot);
1727
1728 EXPECT_EQ(3, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1729
1730 annot.reset(FPDFPage_GetAnnot(page, 1));
1731 ASSERT_TRUE(annot);
1732
1733 EXPECT_EQ(26, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1734 }
1735
1736 UnloadPage(page);
1737}
1738
1739TEST_F(FPDFAnnotEmbedderTest, GetOptionCountInvalidAnnotations) {
1740 // Open a file with ink annotations and load its first page.
1741 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
1742 FPDF_PAGE page = LoadPage(0);
1743 ASSERT_TRUE(page);
1744
1745 {
1746 // annotations do not have "Opt" array and will return -1
1747 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1748 ASSERT_TRUE(annot);
1749
1750 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1751
1752 annot.reset(FPDFPage_GetAnnot(page, 1));
1753 ASSERT_TRUE(annot);
1754
1755 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1756 }
1757
1758 UnloadPage(page);
1759}
1760
1761TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelCombobox) {
1762 // Open a file with combobox widget annotations and load its first page.
1763 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
1764 FPDF_PAGE page = LoadPage(0);
1765 ASSERT_TRUE(page);
1766
1767 {
1768 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1769 ASSERT_TRUE(annot);
1770
1771 int index = 0;
1772 unsigned long len =
1773 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
1774 std::vector<char> buf(len);
1775 EXPECT_EQ(8u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
1776 buf.data(), len));
1777 EXPECT_STREQ(L"Foo", BufferToWString(buf).c_str());
1778
1779 annot.reset(FPDFPage_GetAnnot(page, 1));
1780 ASSERT_TRUE(annot);
1781
1782 index = 0;
1783 len =
1784 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
1785 buf.clear();
1786 buf.resize(len);
1787 EXPECT_EQ(12u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
1788 buf.data(), len));
1789 EXPECT_STREQ(L"Apple", BufferToWString(buf).c_str());
1790
1791 index = 25;
1792 len =
1793 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
1794 buf.clear();
1795 buf.resize(len);
1796 EXPECT_EQ(18u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
1797 buf.data(), len));
1798 EXPECT_STREQ(L"Zucchini", BufferToWString(buf).c_str());
1799
Lei Zhange7033c82019-02-26 19:30:49 +00001800 // Indices out of range
rycsmithcb752f32019-02-21 18:40:53 +00001801 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), -1,
1802 nullptr, 0));
1803 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 26,
1804 nullptr, 0));
Lei Zhange7033c82019-02-26 19:30:49 +00001805
1806 // Check bad form handle / annot.
1807 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(nullptr, nullptr, 0, nullptr, 0));
1808 EXPECT_EQ(0u,
1809 FPDFAnnot_GetOptionLabel(nullptr, annot.get(), 0, nullptr, 0));
1810 EXPECT_EQ(0u,
1811 FPDFAnnot_GetOptionLabel(form_handle(), nullptr, 0, nullptr, 0));
rycsmithcb752f32019-02-21 18:40:53 +00001812 }
1813
1814 UnloadPage(page);
1815}
1816
1817TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelListbox) {
1818 // Open a file with listbox widget annotations and load its first page.
1819 ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
1820 FPDF_PAGE page = LoadPage(0);
1821 ASSERT_TRUE(page);
1822
1823 {
1824 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1825 ASSERT_TRUE(annot);
1826
1827 int index = 0;
1828 unsigned long len =
1829 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
1830 std::vector<char> buf(len);
1831 EXPECT_EQ(8u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
1832 buf.data(), len));
1833 EXPECT_STREQ(L"Foo", BufferToWString(buf).c_str());
1834
1835 annot.reset(FPDFPage_GetAnnot(page, 1));
1836 ASSERT_TRUE(annot);
1837
1838 index = 0;
1839 len =
1840 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
1841 buf.clear();
1842 buf.resize(len);
1843 EXPECT_EQ(12u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
1844 buf.data(), len));
1845 EXPECT_STREQ(L"Apple", BufferToWString(buf).c_str());
1846
1847 index = 25;
1848 len =
1849 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
1850 buf.clear();
1851 buf.resize(len);
1852 EXPECT_EQ(18u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
1853 buf.data(), len));
1854 EXPECT_STREQ(L"Zucchini", BufferToWString(buf).c_str());
1855
1856 // indices out of range
1857 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), -1,
1858 nullptr, 0));
1859 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 26,
1860 nullptr, 0));
1861 }
1862
1863 UnloadPage(page);
1864}
1865
1866TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelInvalidAnnotations) {
1867 // Open a file with ink annotations and load its first page.
1868 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
1869 FPDF_PAGE page = LoadPage(0);
1870 ASSERT_TRUE(page);
1871
1872 {
1873 // annotations do not have "Opt" array and will return 0
1874 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1875 ASSERT_TRUE(annot);
1876
1877 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 0,
1878 nullptr, 0));
1879
1880 annot.reset(FPDFPage_GetAnnot(page, 1));
1881 ASSERT_TRUE(annot);
1882
1883 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 0,
1884 nullptr, 0));
1885 }
1886
1887 UnloadPage(page);
1888}