blob: 5055768a2531331e848562b1ace0892335699667 [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
Tom Sepez204ab052020-06-12 21:33:48 +00005#include "public/fpdf_annot.h"
6
7#include <limits.h>
8
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00009#include <algorithm>
Jane Liu20eafda2017-06-07 10:33:24 -040010#include <string>
Jane Liu4fd9a472017-06-01 18:56:09 -040011#include <vector>
12
Lei Zhange4cdac52019-04-30 16:45:57 +000013#include "build/build_config.h"
Lei Zhanga5c1daf2019-01-31 21:56:47 +000014#include "constants/annotation_common.h"
Tom Sepez204ab052020-06-12 21:33:48 +000015#include "core/fpdfapi/page/cpdf_annotcontext.h"
Tom Sepez204ab052020-06-12 21:33:48 +000016#include "core/fpdfapi/parser/cpdf_array.h"
17#include "core/fpdfapi/parser/cpdf_dictionary.h"
Jane Liubaa7ff42017-06-29 19:18:23 -040018#include "core/fxcrt/fx_system.h"
Tom Sepez204ab052020-06-12 21:33:48 +000019#include "fpdfsdk/cpdfsdk_helpers.h"
Tom Sepeze08d2b12018-04-25 18:49:32 +000020#include "public/cpp/fpdf_scopers.h"
Jane Liubaa7ff42017-06-29 19:18:23 -040021#include "public/fpdf_edit.h"
Mansi Awasthi07bf7e62020-01-24 10:34:17 +000022#include "public/fpdf_formfill.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040023#include "public/fpdfview.h"
24#include "testing/embedder_test.h"
Hui Yingstb4baceb2020-04-28 23:46:10 +000025#include "testing/embedder_test_constants.h"
Lei Zhangb6992dd2019-02-05 23:30:20 +000026#include "testing/fx_string_testhelpers.h"
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +000027#include "testing/gmock/include/gmock/gmock-matchers.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040028#include "testing/gtest/include/gtest/gtest.h"
Lei Zhang5bf8c7f2019-04-08 17:50:11 +000029#include "testing/utils/hash.h"
Lei Zhang87e3d7a2021-06-17 19:40:28 +000030#include "third_party/base/containers/contains.h"
Lei Zhang532886d2021-06-17 19:10:08 +000031#include "third_party/base/cxx17_backports.h"
Lei Zhang9b444002020-04-17 17:35:23 +000032#include "third_party/base/span.h"
33
Hui Yingst30bfcc52020-07-27 23:54:40 +000034using pdfium::kAnnotationStampWithApChecksum;
35
Lei Zhang9b444002020-04-17 17:35:23 +000036namespace {
37
Tom Sepez204ab052020-06-12 21:33:48 +000038const wchar_t kStreamData[] =
39 L"/GS gs 0.0 0.0 0.0 RG 4 w 211.8 747.6 m 211.8 744.8 "
40 L"212.6 743.0 214.2 740.8 "
41 L"c 215.4 739.0 216.8 737.1 218.9 736.1 c 220.8 735.1 221.4 733.0 "
42 L"223.7 732.4 c 232.6 729.9 242.0 730.8 251.2 730.8 c 257.5 730.8 "
43 L"263.0 732.9 269.0 734.4 c S";
44
Lei Zhang9b444002020-04-17 17:35:23 +000045void VerifyFocusableAnnotSubtypes(
46 FPDF_FORMHANDLE form_handle,
47 pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_subtypes) {
48 ASSERT_EQ(static_cast<int>(expected_subtypes.size()),
49 FPDFAnnot_GetFocusableSubtypesCount(form_handle));
50
51 std::vector<FPDF_ANNOTATION_SUBTYPE> actual_subtypes(
52 expected_subtypes.size());
53 ASSERT_TRUE(FPDFAnnot_GetFocusableSubtypes(
54 form_handle, actual_subtypes.data(), actual_subtypes.size()));
55 for (size_t i = 0; i < expected_subtypes.size(); ++i)
56 ASSERT_EQ(expected_subtypes[i], actual_subtypes[i]);
57}
58
59void SetAndVerifyFocusableAnnotSubtypes(
60 FPDF_FORMHANDLE form_handle,
61 pdfium::span<const FPDF_ANNOTATION_SUBTYPE> subtypes) {
62 ASSERT_TRUE(FPDFAnnot_SetFocusableSubtypes(form_handle, subtypes.data(),
63 subtypes.size()));
64 VerifyFocusableAnnotSubtypes(form_handle, subtypes);
65}
66
67void VerifyAnnotationSubtypesAndFocusability(
68 FPDF_FORMHANDLE form_handle,
69 FPDF_PAGE page,
70 pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_subtypes,
71 pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_focusable_subtypes) {
72 ASSERT_EQ(static_cast<int>(expected_subtypes.size()),
73 FPDFPage_GetAnnotCount(page));
74 for (size_t i = 0; i < expected_subtypes.size(); ++i) {
75 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
76 ASSERT_TRUE(annot);
77 EXPECT_EQ(expected_subtypes[i], FPDFAnnot_GetSubtype(annot.get()));
78
Lei Zhangf245ae62020-05-15 21:49:46 +000079 bool expected_focusable =
80 pdfium::Contains(expected_focusable_subtypes, expected_subtypes[i]);
Lei Zhang9b444002020-04-17 17:35:23 +000081 EXPECT_EQ(expected_focusable,
82 FORM_SetFocusedAnnot(form_handle, annot.get()));
83
84 // Kill the focus so the next test starts in an unfocused state.
85 FORM_ForceToKillFocus(form_handle);
86 }
87}
88
Lei Zhang306874b2021-04-16 00:33:36 +000089void VerifyUriActionInLink(FPDF_DOCUMENT doc,
90 FPDF_LINK link,
91 const std::string& expected_uri) {
92 ASSERT_TRUE(link);
93
94 FPDF_ACTION action = FPDFLink_GetAction(link);
95 ASSERT_TRUE(action);
96 EXPECT_EQ(static_cast<unsigned long>(PDFACTION_URI),
97 FPDFAction_GetType(action));
98
99 unsigned long bufsize = FPDFAction_GetURIPath(doc, action, nullptr, 0);
100 ASSERT_EQ(expected_uri.size() + 1, bufsize);
101
102 std::vector<char> buffer(bufsize);
103 EXPECT_EQ(bufsize,
104 FPDFAction_GetURIPath(doc, action, buffer.data(), bufsize));
105 EXPECT_STREQ(expected_uri.c_str(), buffer.data());
106}
107
Lei Zhang9b444002020-04-17 17:35:23 +0000108} // namespace
Jane Liu4fd9a472017-06-01 18:56:09 -0400109
Lei Zhangab41f252018-12-23 03:10:50 +0000110class FPDFAnnotEmbedderTest : public EmbedderTest {};
Jane Liu4fd9a472017-06-01 18:56:09 -0400111
Tom Sepez204ab052020-06-12 21:33:48 +0000112TEST_F(FPDFAnnotEmbedderTest, SetAP) {
113 ScopedFPDFDocument doc(FPDF_CreateNewDocument());
114 ASSERT_TRUE(doc);
115 ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
116 ASSERT_TRUE(page);
117 ScopedFPDFWideString ap_stream = GetFPDFWideString(kStreamData);
118 ASSERT_TRUE(ap_stream);
119
120 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
121 ASSERT_TRUE(annot);
122
123 // Negative case: FPDFAnnot_SetAP() should fail if bounding rect is not yet
124 // set on the annotation.
125 EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
126 ap_stream.get()));
127
128 const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
129 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
130
131 ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color,
132 /*R=*/255, /*G=*/0, /*B=*/0, /*A=*/255));
133
134 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
135 ap_stream.get()));
136
137 // Verify that appearance stream is created as form XObject
138 CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot.get());
139 ASSERT_TRUE(context);
140 CPDF_Dictionary* annot_dict = context->GetAnnotDict();
141 ASSERT_TRUE(annot_dict);
142 CPDF_Dictionary* ap_dict = annot_dict->GetDictFor(pdfium::annotation::kAP);
143 ASSERT_TRUE(ap_dict);
144 CPDF_Dictionary* stream_dict = ap_dict->GetDictFor("N");
145 ASSERT_TRUE(stream_dict);
146 // Check for non-existence of resources dictionary in case of opaque color
147 CPDF_Dictionary* resources_dict = stream_dict->GetDictFor("Resources");
148 ASSERT_FALSE(resources_dict);
149 ByteString type = stream_dict->GetStringFor(pdfium::annotation::kType);
150 EXPECT_EQ("XObject", type);
151 ByteString sub_type = stream_dict->GetStringFor(pdfium::annotation::kSubtype);
152 EXPECT_EQ("Form", sub_type);
153
154 // Check that the appearance stream is same as we just set.
155 const uint32_t kStreamDataSize =
156 pdfium::size(kStreamData) * sizeof(FPDF_WCHAR);
157 unsigned long normal_length_bytes = FPDFAnnot_GetAP(
158 annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
159 ASSERT_EQ(kStreamDataSize, normal_length_bytes);
160 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(normal_length_bytes);
161 EXPECT_EQ(kStreamDataSize,
162 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
163 buf.data(), normal_length_bytes));
164 EXPECT_EQ(kStreamData, GetPlatformWString(buf.data()));
165}
166
167TEST_F(FPDFAnnotEmbedderTest, SetAPWithOpacity) {
168 ScopedFPDFDocument doc(FPDF_CreateNewDocument());
169 ASSERT_TRUE(doc);
170 ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
171 ASSERT_TRUE(page);
172 ScopedFPDFWideString ap_stream = GetFPDFWideString(kStreamData);
173 ASSERT_TRUE(ap_stream);
174
175 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
176 ASSERT_TRUE(annot);
177
178 ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color,
179 /*R=*/255, /*G=*/0, /*B=*/0, /*A=*/102));
180
181 const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
182 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
183
184 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
185 ap_stream.get()));
186
187 CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot.get());
188 ASSERT_TRUE(context);
189 CPDF_Dictionary* annot_dict = context->GetAnnotDict();
190 ASSERT_TRUE(annot_dict);
191 CPDF_Dictionary* ap_dict = annot_dict->GetDictFor(pdfium::annotation::kAP);
192 ASSERT_TRUE(ap_dict);
193 CPDF_Dictionary* stream_dict = ap_dict->GetDictFor("N");
194 ASSERT_TRUE(stream_dict);
195 CPDF_Dictionary* resources_dict = stream_dict->GetDictFor("Resources");
196 ASSERT_TRUE(stream_dict);
197 CPDF_Dictionary* extGState_dict = resources_dict->GetDictFor("ExtGState");
198 ASSERT_TRUE(extGState_dict);
199 CPDF_Dictionary* gs_dict = extGState_dict->GetDictFor("GS");
200 ASSERT_TRUE(gs_dict);
201 ByteString type = gs_dict->GetStringFor(pdfium::annotation::kType);
202 EXPECT_EQ("ExtGState", type);
203 float opacity = gs_dict->GetNumberFor("CA");
204 // Opacity value of 102 is represented as 0.4f (=104/255) in /CA entry.
205 EXPECT_FLOAT_EQ(0.4f, opacity);
206 ByteString blend_mode = gs_dict->GetStringFor("BM");
207 EXPECT_EQ("Normal", blend_mode);
208 bool alpha_source_flag = gs_dict->GetBooleanFor("AIS", true);
209 EXPECT_FALSE(alpha_source_flag);
210}
211
212TEST_F(FPDFAnnotEmbedderTest, InkListAPIValidations) {
213 ScopedFPDFDocument doc(FPDF_CreateNewDocument());
214 ASSERT_TRUE(doc);
215 ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
216 ASSERT_TRUE(page);
217
218 // Create a new ink annotation.
219 ScopedFPDFAnnotation ink_annot(
220 FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
221 ASSERT_TRUE(ink_annot);
222 CPDF_AnnotContext* context =
223 CPDFAnnotContextFromFPDFAnnotation(ink_annot.get());
224 ASSERT_TRUE(context);
225 CPDF_Dictionary* annot_dict = context->GetAnnotDict();
226 ASSERT_TRUE(annot_dict);
227
228 static constexpr FS_POINTF kFirstInkStroke[] = {
229 {80.0f, 90.0f}, {81.0f, 91.0f}, {82.0f, 92.0f},
230 {83.0f, 93.0f}, {84.0f, 94.0f}, {85.0f, 95.0f}};
231 static constexpr size_t kFirstStrokePointCount =
232 pdfium::size(kFirstInkStroke);
233
234 static constexpr FS_POINTF kSecondInkStroke[] = {
235 {70.0f, 90.0f}, {71.0f, 91.0f}, {72.0f, 92.0f}};
236 static constexpr size_t kSecondStrokePointCount =
237 pdfium::size(kSecondInkStroke);
238
239 static constexpr FS_POINTF kThirdInkStroke[] = {{60.0f, 90.0f},
240 {61.0f, 91.0f},
241 {62.0f, 92.0f},
242 {63.0f, 93.0f},
243 {64.0f, 94.0f}};
244 static constexpr size_t kThirdStrokePointCount =
245 pdfium::size(kThirdInkStroke);
246
247 // Negative test: |annot| is passed as nullptr.
248 EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(nullptr, kFirstInkStroke,
249 kFirstStrokePointCount));
250
251 // Negative test: |annot| is not ink annotation.
252 // Create a new highlight annotation.
253 ScopedFPDFAnnotation highlight_annot(
254 FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_HIGHLIGHT));
255 ASSERT_TRUE(highlight_annot);
256 EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(highlight_annot.get(), kFirstInkStroke,
257 kFirstStrokePointCount));
258
259 // Negative test: passing |point_count| as 0.
260 EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), kFirstInkStroke, 0));
261
262 // Negative test: passing |points| array as nullptr.
263 EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), nullptr,
264 kFirstStrokePointCount));
265
266 // Negative test: passing |point_count| more than ULONG_MAX/2.
267 EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), kSecondInkStroke,
268 ULONG_MAX / 2 + 1));
269
270 // InkStroke should get added to ink annotation. Also inklist should get
271 // created.
272 EXPECT_EQ(0, FPDFAnnot_AddInkStroke(ink_annot.get(), kFirstInkStroke,
273 kFirstStrokePointCount));
274
275 CPDF_Array* inklist = annot_dict->GetArrayFor("InkList");
276 ASSERT_TRUE(inklist);
277 EXPECT_EQ(1u, inklist->size());
278 EXPECT_EQ(kFirstStrokePointCount * 2, inklist->GetArrayAt(0)->size());
279
280 // Adding another inkStroke to ink annotation with all valid paremeters.
281 // InkList already exists in ink_annot.
282 EXPECT_EQ(1, FPDFAnnot_AddInkStroke(ink_annot.get(), kSecondInkStroke,
283 kSecondStrokePointCount));
284 EXPECT_EQ(2u, inklist->size());
285 EXPECT_EQ(kSecondStrokePointCount * 2, inklist->GetArrayAt(1)->size());
286
287 // Adding one more InkStroke to the ink annotation. |point_count| passed is
288 // less than the data available in |buffer|.
289 EXPECT_EQ(2, FPDFAnnot_AddInkStroke(ink_annot.get(), kThirdInkStroke,
290 kThirdStrokePointCount - 1));
291 EXPECT_EQ(3u, inklist->size());
292 EXPECT_EQ((kThirdStrokePointCount - 1) * 2, inklist->GetArrayAt(2)->size());
293}
294
295TEST_F(FPDFAnnotEmbedderTest, RemoveInkList) {
296 ScopedFPDFDocument doc(FPDF_CreateNewDocument());
297 ASSERT_TRUE(doc);
298 ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
299 ASSERT_TRUE(page);
300
301 // Negative test: |annot| is passed as nullptr.
302 EXPECT_FALSE(FPDFAnnot_RemoveInkList(nullptr));
303
304 // Negative test: |annot| is not ink annotation.
305 // Create a new highlight annotation.
306 ScopedFPDFAnnotation highlight_annot(
307 FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_HIGHLIGHT));
308 ASSERT_TRUE(highlight_annot);
309 EXPECT_FALSE(FPDFAnnot_RemoveInkList(highlight_annot.get()));
310
311 // Create a new ink annotation.
312 ScopedFPDFAnnotation ink_annot(
313 FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
314 ASSERT_TRUE(ink_annot);
315 CPDF_AnnotContext* context =
316 CPDFAnnotContextFromFPDFAnnotation(ink_annot.get());
317 ASSERT_TRUE(context);
318 CPDF_Dictionary* annot_dict = context->GetAnnotDict();
319 ASSERT_TRUE(annot_dict);
320
321 static constexpr FS_POINTF kInkStroke[] = {{80.0f, 90.0f}, {81.0f, 91.0f},
322 {82.0f, 92.0f}, {83.0f, 93.0f},
323 {84.0f, 94.0f}, {85.0f, 95.0f}};
324 static constexpr size_t kPointCount = pdfium::size(kInkStroke);
325
326 // InkStroke should get added to ink annotation. Also inklist should get
327 // created.
328 EXPECT_EQ(0,
329 FPDFAnnot_AddInkStroke(ink_annot.get(), kInkStroke, kPointCount));
330
331 CPDF_Array* inklist = annot_dict->GetArrayFor("InkList");
332 ASSERT_TRUE(inklist);
333 ASSERT_EQ(1u, inklist->size());
334 EXPECT_EQ(kPointCount * 2, inklist->GetArrayAt(0)->size());
335
336 // Remove inklist.
337 EXPECT_TRUE(FPDFAnnot_RemoveInkList(ink_annot.get()));
338 EXPECT_FALSE(annot_dict->KeyExist("InkList"));
339}
340
Lei Zhangab41f252018-12-23 03:10:50 +0000341TEST_F(FPDFAnnotEmbedderTest, BadParams) {
Lei Zhang7557e7b2018-09-14 17:02:40 +0000342 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
343 FPDF_PAGE page = LoadPage(0);
344 ASSERT_TRUE(page);
345
346 EXPECT_EQ(0, FPDFPage_GetAnnotCount(nullptr));
347
348 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, 0));
349 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, -1));
350 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, 1));
351 EXPECT_FALSE(FPDFPage_GetAnnot(page, -1));
352 EXPECT_FALSE(FPDFPage_GetAnnot(page, 1));
353
354 EXPECT_EQ(FPDF_ANNOT_UNKNOWN, FPDFAnnot_GetSubtype(nullptr));
355
356 EXPECT_EQ(0, FPDFAnnot_GetObjectCount(nullptr));
357
358 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, 0));
359 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, -1));
360 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, 1));
361
362 EXPECT_FALSE(FPDFAnnot_HasKey(nullptr, "foo"));
363
Lei Zhang4f556b82019-04-08 16:32:41 +0000364 static const wchar_t kContents[] = L"Bar";
Lei Zhangf0f67682019-04-08 17:03:21 +0000365 ScopedFPDFWideString text = GetFPDFWideString(kContents);
Lei Zhang7557e7b2018-09-14 17:02:40 +0000366 EXPECT_FALSE(FPDFAnnot_SetStringValue(nullptr, "foo", text.get()));
367
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000368 FPDF_WCHAR buffer[64];
Lei Zhang7557e7b2018-09-14 17:02:40 +0000369 EXPECT_EQ(0u, FPDFAnnot_GetStringValue(nullptr, "foo", nullptr, 0));
370 EXPECT_EQ(0u, FPDFAnnot_GetStringValue(nullptr, "foo", buffer, 0));
371 EXPECT_EQ(0u,
372 FPDFAnnot_GetStringValue(nullptr, "foo", buffer, sizeof(buffer)));
373
374 UnloadPage(page);
375}
376
Lei Zhang3d9a0972019-03-04 19:34:09 +0000377TEST_F(FPDFAnnotEmbedderTest, BadAnnotsEntry) {
378 ASSERT_TRUE(OpenDocument("bad_annots_entry.pdf"));
379 FPDF_PAGE page = LoadPage(0);
380 ASSERT_TRUE(page);
381
382 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Lei Zhang98dc8c02019-03-04 19:40:30 +0000383 EXPECT_FALSE(FPDFPage_GetAnnot(page, 0));
Lei Zhang3d9a0972019-03-04 19:34:09 +0000384
385 UnloadPage(page);
386}
387
Lei Zhangab41f252018-12-23 03:10:50 +0000388TEST_F(FPDFAnnotEmbedderTest, RenderAnnotWithOnlyRolloverAP) {
Jane Liue17011d2017-06-21 12:18:37 -0400389 // Open a file with one annotation and load its first page.
390 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000391 FPDF_PAGE page = LoadPage(0);
Jane Liue17011d2017-06-21 12:18:37 -0400392 ASSERT_TRUE(page);
393
394 // This annotation has a malformed appearance stream, which does not have its
395 // normal appearance defined, only its rollover appearance. In this case, its
396 // normal appearance should be generated, allowing the highlight annotation to
397 // still display.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000398 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhanga98e3662018-02-07 20:28:35 +0000399 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
Jane Liue17011d2017-06-21 12:18:37 -0400400
401 UnloadPage(page);
402}
403
Hui Yingstd5b6f632020-07-22 01:31:59 +0000404TEST_F(FPDFAnnotEmbedderTest, RenderMultilineMarkupAnnotWithoutAP) {
Lei Zhang03e5e682019-09-16 19:45:55 +0000405#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingstd5b6f632020-07-22 01:31:59 +0000406 static const char kChecksum[] = "ec1f4ccbd0aecfdea6d53893387a0101";
Lei Zhang03e5e682019-09-16 19:45:55 +0000407#else
Hui Yingstd5b6f632020-07-22 01:31:59 +0000408 static const char kChecksum[] = "76512832d88017668d9acc7aacd13dae";
Lei Zhang03e5e682019-09-16 19:45:55 +0000409#endif
Henrique Nakashima5098b252018-03-26 21:46:00 +0000410 // Open a file with multiline markup annotations.
Ralf Sipplb3a52402018-03-19 23:30:28 +0000411 ASSERT_TRUE(OpenDocument("annotation_markup_multiline_no_ap.pdf"));
412 FPDF_PAGE page = LoadPage(0);
413 ASSERT_TRUE(page);
414
Tom Sepeze08d2b12018-04-25 18:49:32 +0000415 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstd5b6f632020-07-22 01:31:59 +0000416 CompareBitmap(bitmap.get(), 595, 842, kChecksum);
Ralf Sipplb3a52402018-03-19 23:30:28 +0000417
418 UnloadPage(page);
419}
420
Lei Zhangab41f252018-12-23 03:10:50 +0000421TEST_F(FPDFAnnotEmbedderTest, ExtractHighlightLongContent) {
Jane Liu4fd9a472017-06-01 18:56:09 -0400422 // Open a file with one annotation and load its first page.
423 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +0000424 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu4fd9a472017-06-01 18:56:09 -0400425 ASSERT_TRUE(page);
426
427 // Check that there is a total of 1 annotation on its first page.
428 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
429
430 // Check that the annotation is of type "highlight".
Lei Zhanga21d5932018-02-05 18:28:38 +0000431 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000432 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000433 ASSERT_TRUE(annot);
434 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400435
Lei Zhanga21d5932018-02-05 18:28:38 +0000436 // Check that the annotation color is yellow.
437 unsigned int R;
438 unsigned int G;
439 unsigned int B;
440 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000441 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000442 &G, &B, &A));
443 EXPECT_EQ(255u, R);
444 EXPECT_EQ(255u, G);
445 EXPECT_EQ(0u, B);
446 EXPECT_EQ(255u, A);
Jane Liu4fd9a472017-06-01 18:56:09 -0400447
Lei Zhanga21d5932018-02-05 18:28:38 +0000448 // Check that the author is correct.
Lei Zhang4f556b82019-04-08 16:32:41 +0000449 static const char kAuthorKey[] = "T";
Lei Zhanga21d5932018-02-05 18:28:38 +0000450 EXPECT_EQ(FPDF_OBJECT_STRING,
451 FPDFAnnot_GetValueType(annot.get(), kAuthorKey));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000452 unsigned long length_bytes =
Lei Zhanga21d5932018-02-05 18:28:38 +0000453 FPDFAnnot_GetStringValue(annot.get(), kAuthorKey, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000454 ASSERT_EQ(28u, length_bytes);
455 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhanga21d5932018-02-05 18:28:38 +0000456 EXPECT_EQ(28u, FPDFAnnot_GetStringValue(annot.get(), kAuthorKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000457 length_bytes));
458 EXPECT_EQ(L"Jae Hyun Park", GetPlatformWString(buf.data()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400459
Lei Zhanga21d5932018-02-05 18:28:38 +0000460 // Check that the content is correct.
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000461 EXPECT_EQ(
462 FPDF_OBJECT_STRING,
463 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kContents));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000464 length_bytes = FPDFAnnot_GetStringValue(
465 annot.get(), pdfium::annotation::kContents, nullptr, 0);
466 ASSERT_EQ(2690u, length_bytes);
467 buf = GetFPDFWideStringBuffer(length_bytes);
468 EXPECT_EQ(2690u, FPDFAnnot_GetStringValue(annot.get(),
469 pdfium::annotation::kContents,
470 buf.data(), length_bytes));
Lei Zhang4f556b82019-04-08 16:32:41 +0000471 static const wchar_t kContents[] =
Lei Zhanga21d5932018-02-05 18:28:38 +0000472 L"This is a note for that highlight annotation. Very long highlight "
473 "annotation. Long long long Long long longLong long longLong long "
474 "longLong long longLong long longLong long longLong long longLong long "
475 "longLong long longLong long longLong long longLong long longLong long "
476 "longLong long longLong long longLong long longLong long longLong long "
477 "longLong long longLong long longLong long longLong long longLong long "
478 "longLong long longLong long longLong long longLong long longLong long "
479 "longLong long longLong long longLong long longLong long longLong long "
480 "longLong long longLong long longLong long longLong long longLong long "
481 "longLong long longLong long longLong long longLong long longLong long "
482 "longLong long longLong long longLong long longLong long longLong long "
483 "longLong long longLong long longLong long longLong long longLong long "
484 "longLong long longLong long longLong long longLong long longLong long "
485 "longLong long longLong long longLong long longLong long longLong long "
486 "longLong long longLong long longLong long longLong long longLong long "
487 "longLong long longLong long longLong long longLong long longLong long "
488 "longLong long longLong long longLong long longLong long longLong long "
489 "longLong long longLong long longLong long longLong long longLong long "
490 "longLong long longLong long longLong long longLong long longLong long "
491 "longLong long long. END";
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000492 EXPECT_EQ(kContents, GetPlatformWString(buf.data()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400493
Lei Zhanga21d5932018-02-05 18:28:38 +0000494 // Check that the quadpoints are correct.
495 FS_QUADPOINTSF quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000496 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000497 EXPECT_EQ(115.802643f, quadpoints.x1);
498 EXPECT_EQ(718.913940f, quadpoints.y1);
499 EXPECT_EQ(157.211182f, quadpoints.x4);
500 EXPECT_EQ(706.264465f, quadpoints.y4);
501 }
Tom Sepez507d0192018-11-07 16:37:51 +0000502 UnloadPageNoEvents(page);
Jane Liu4fd9a472017-06-01 18:56:09 -0400503}
504
Hui Yingst9b6b1542020-07-27 16:11:12 +0000505TEST_F(FPDFAnnotEmbedderTest, ExtractInkMultiple) {
Jane Liu4fd9a472017-06-01 18:56:09 -0400506 // Open a file with three annotations and load its first page.
507 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +0000508 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu4fd9a472017-06-01 18:56:09 -0400509 ASSERT_TRUE(page);
510
511 // Check that there is a total of 3 annotation on its first page.
512 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
513
Lei Zhanga21d5932018-02-05 18:28:38 +0000514 {
515 // Check that the third annotation is of type "ink".
Tom Sepeze08d2b12018-04-25 18:49:32 +0000516 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000517 ASSERT_TRUE(annot);
518 EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400519
Lei Zhanga21d5932018-02-05 18:28:38 +0000520 // Check that the annotation color is blue with opacity.
521 unsigned int R;
522 unsigned int G;
523 unsigned int B;
524 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000525 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000526 &G, &B, &A));
527 EXPECT_EQ(0u, R);
528 EXPECT_EQ(0u, G);
529 EXPECT_EQ(255u, B);
530 EXPECT_EQ(76u, A);
Jane Liu4fd9a472017-06-01 18:56:09 -0400531
Lei Zhanga21d5932018-02-05 18:28:38 +0000532 // Check that there is no content.
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000533 EXPECT_EQ(2u, FPDFAnnot_GetStringValue(
534 annot.get(), pdfium::annotation::kContents, nullptr, 0));
Jane Liu4fd9a472017-06-01 18:56:09 -0400535
Lei Zhang4f556b82019-04-08 16:32:41 +0000536 // Check that the rectangle coordinates are correct.
Lei Zhanga21d5932018-02-05 18:28:38 +0000537 // Note that upon rendering, the rectangle coordinates will be adjusted.
538 FS_RECTF rect;
539 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
540 EXPECT_EQ(351.820404f, rect.left);
541 EXPECT_EQ(583.830688f, rect.bottom);
542 EXPECT_EQ(475.336090f, rect.right);
543 EXPECT_EQ(681.535034f, rect.top);
544 }
Tom Sepezef43c262018-11-07 16:41:32 +0000545 {
Hui Yingste1215fc2022-03-26 22:29:08 +0000546#if defined(_SKIA_SUPPORT_)
Hui Yingst57daee82020-10-09 05:47:20 +0000547 static constexpr char kExpectedHash[] = "fad91b9c968fe8019a774f5e2419b8fc";
Hui Yingste1215fc2022-03-26 22:29:08 +0000548#elif defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst9b6b1542020-07-27 16:11:12 +0000549 static constexpr char kExpectedHash[] = "acddfe688a117ead56af7b249a2cf8a1";
Lei Zhangf997abe2022-01-12 19:14:23 +0000550#elif BUILDFLAG(IS_WIN)
Lei Zhang430b5322020-07-06 22:23:36 +0000551 static constexpr char kExpectedHash[] = "49d0a81c636531a337429325273d0508";
552#else
553 static constexpr char kExpectedHash[] = "354002e1c4386d38fdde29ef8d61074a";
Hui Yingst57daee82020-10-09 05:47:20 +0000554#endif
Tom Sepezef43c262018-11-07 16:41:32 +0000555 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang430b5322020-07-06 22:23:36 +0000556 CompareBitmap(bitmap.get(), 612, 792, kExpectedHash);
Tom Sepezef43c262018-11-07 16:41:32 +0000557 }
Tom Sepez507d0192018-11-07 16:37:51 +0000558 UnloadPageNoEvents(page);
Jane Liu4fd9a472017-06-01 18:56:09 -0400559}
Jane Liu20eafda2017-06-07 10:33:24 -0400560
Lei Zhangab41f252018-12-23 03:10:50 +0000561TEST_F(FPDFAnnotEmbedderTest, AddIllegalSubtypeAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400562 // Open a file with one annotation and load its first page.
563 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000564 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400565 ASSERT_TRUE(page);
566
567 // Add an annotation with an illegal subtype.
Jane Liud60e9ad2017-06-26 11:28:36 -0400568 ASSERT_FALSE(FPDFPage_CreateAnnot(page, -1));
Jane Liu20eafda2017-06-07 10:33:24 -0400569
570 UnloadPage(page);
571}
572
Lei Zhangab41f252018-12-23 03:10:50 +0000573TEST_F(FPDFAnnotEmbedderTest, AddFirstTextAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400574 // Open a file with no annotation and load its first page.
575 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000576 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400577 ASSERT_TRUE(page);
578 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
579
Lei Zhanga21d5932018-02-05 18:28:38 +0000580 {
581 // Add a text annotation to the page.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000582 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT));
Lei Zhanga21d5932018-02-05 18:28:38 +0000583 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400584
Lei Zhanga21d5932018-02-05 18:28:38 +0000585 // Check that there is now 1 annotations on this page.
586 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Jane Liu20eafda2017-06-07 10:33:24 -0400587
Lei Zhanga21d5932018-02-05 18:28:38 +0000588 // Check that the subtype of the annotation is correct.
589 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
590 }
Jane Liue10509a2017-06-20 16:47:41 -0400591
Lei Zhanga21d5932018-02-05 18:28:38 +0000592 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000593 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000594 ASSERT_TRUE(annot);
595 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu20eafda2017-06-07 10:33:24 -0400596
Lei Zhanga21d5932018-02-05 18:28:38 +0000597 // Set the color of the annotation.
598 ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 51,
599 102, 153, 204));
600 // Check that the color has been set correctly.
601 unsigned int R;
602 unsigned int G;
603 unsigned int B;
604 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000605 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000606 &G, &B, &A));
607 EXPECT_EQ(51u, R);
608 EXPECT_EQ(102u, G);
609 EXPECT_EQ(153u, B);
610 EXPECT_EQ(204u, A);
Jane Liu20eafda2017-06-07 10:33:24 -0400611
Lei Zhanga21d5932018-02-05 18:28:38 +0000612 // Change the color of the annotation.
613 ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 204,
614 153, 102, 51));
615 // Check that the color has been set correctly.
Lei Zhang75c81712018-02-08 17:22:39 +0000616 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000617 &G, &B, &A));
618 EXPECT_EQ(204u, R);
619 EXPECT_EQ(153u, G);
620 EXPECT_EQ(102u, B);
621 EXPECT_EQ(51u, A);
Jane Liu20eafda2017-06-07 10:33:24 -0400622
Lei Zhanga21d5932018-02-05 18:28:38 +0000623 // Set the annotation rectangle.
624 FS_RECTF rect;
625 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
626 EXPECT_EQ(0.f, rect.left);
627 EXPECT_EQ(0.f, rect.right);
628 rect.left = 35;
629 rect.bottom = 150;
630 rect.right = 53;
631 rect.top = 165;
632 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
633 // Check that the annotation rectangle has been set correctly.
634 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
635 EXPECT_EQ(35.f, rect.left);
636 EXPECT_EQ(150.f, rect.bottom);
637 EXPECT_EQ(53.f, rect.right);
638 EXPECT_EQ(165.f, rect.top);
Jane Liu20eafda2017-06-07 10:33:24 -0400639
Lei Zhanga21d5932018-02-05 18:28:38 +0000640 // Set the content of the annotation.
Lei Zhang4f556b82019-04-08 16:32:41 +0000641 static const wchar_t kContents[] = L"Hello! This is a customized content.";
Lei Zhangf0f67682019-04-08 17:03:21 +0000642 ScopedFPDFWideString text = GetFPDFWideString(kContents);
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000643 ASSERT_TRUE(FPDFAnnot_SetStringValue(
644 annot.get(), pdfium::annotation::kContents, text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +0000645 // Check that the content has been set correctly.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000646 unsigned long length_bytes = FPDFAnnot_GetStringValue(
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000647 annot.get(), pdfium::annotation::kContents, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000648 ASSERT_EQ(74u, length_bytes);
649 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
650 EXPECT_EQ(74u, FPDFAnnot_GetStringValue(annot.get(),
651 pdfium::annotation::kContents,
652 buf.data(), length_bytes));
653 EXPECT_EQ(kContents, GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +0000654 }
Jane Liu20eafda2017-06-07 10:33:24 -0400655 UnloadPage(page);
656}
657
Lei Zhang81395aa2021-04-16 00:40:46 +0000658TEST_F(FPDFAnnotEmbedderTest, AddAndSaveLinkAnnotation) {
659 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
660 FPDF_PAGE page = LoadPage(0);
661 ASSERT_TRUE(page);
662 {
663 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
664 CompareBitmap(bitmap.get(), 200, 200, pdfium::kHelloWorldChecksum);
665 }
666 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
667
668 constexpr char kUri[] = "https://pdfium.org/";
669
670 {
671 // Add a link annotation to the page and set its URI.
672 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_LINK));
673 ASSERT_TRUE(annot);
674 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
675 EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
676 EXPECT_TRUE(FPDFAnnot_SetURI(annot.get(), kUri));
677 VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
678
679 // Negative tests:
680 EXPECT_FALSE(FPDFAnnot_SetURI(nullptr, nullptr));
681 VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
682 EXPECT_FALSE(FPDFAnnot_SetURI(annot.get(), nullptr));
683 VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
684 EXPECT_FALSE(FPDFAnnot_SetURI(nullptr, kUri));
685 VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
686
687 // Position the link on top of "Hello, world!" without a border.
688 const FS_RECTF kRect = {19.0f, 48.0f, 85.0f, 60.0f};
689 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &kRect));
690 EXPECT_TRUE(FPDFAnnot_SetBorder(annot.get(), /*horizontal_radius=*/0.0f,
691 /*vertical_radius=*/0.0f,
692 /*border_width=*/0.0f));
693
694 VerifyUriActionInLink(document(), FPDFLink_GetLinkAtPoint(page, 40.0, 50.0),
695 kUri);
696 }
697
698 {
699 // Add an ink annotation to the page. Trying to add a link to it fails.
700 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_INK));
701 ASSERT_TRUE(annot);
702 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
703 EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot.get()));
704 EXPECT_FALSE(FPDFAnnot_SetURI(annot.get(), kUri));
705 }
706
707 // Remove the ink annotation added above for negative testing.
708 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
709 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
710
711 // Save the document, closing the page.
712 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
713 UnloadPage(page);
714
715 // Reopen the document and make sure it still renders the same. Since the link
716 // does not have a border, it does not affect the rendering.
717 ASSERT_TRUE(OpenSavedDocument());
718 page = LoadSavedPage(0);
719 ASSERT_TRUE(page);
720 VerifySavedRendering(page, 200, 200, pdfium::kHelloWorldChecksum);
721 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
722
723 {
724 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
725 ASSERT_TRUE(annot);
726 EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
727 VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
728 VerifyUriActionInLink(document(), FPDFLink_GetLinkAtPoint(page, 40.0, 50.0),
729 kUri);
730 }
731
732 CloseSavedPage(page);
733 CloseSavedDocument();
734}
735
Hui Yingstb3490322020-07-22 00:53:29 +0000736TEST_F(FPDFAnnotEmbedderTest, AddAndSaveUnderlineAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400737 // Open a file with one annotation and load its first page.
738 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000739 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400740 ASSERT_TRUE(page);
741
742 // Check that there is a total of one annotation on its first page, and verify
743 // its quadpoints.
744 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Jane Liu0c6b07d2017-08-15 10:50:22 -0400745 FS_QUADPOINTSF quadpoints;
Lei Zhanga21d5932018-02-05 18:28:38 +0000746 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000747 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000748 ASSERT_TRUE(annot);
Ralf Sippl16381792018-04-12 21:20:26 +0000749 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000750 EXPECT_EQ(115.802643f, quadpoints.x1);
751 EXPECT_EQ(718.913940f, quadpoints.y1);
752 EXPECT_EQ(157.211182f, quadpoints.x4);
753 EXPECT_EQ(706.264465f, quadpoints.y4);
754 }
Jane Liu20eafda2017-06-07 10:33:24 -0400755
756 // Add an underline annotation to the page and set its quadpoints.
Lei Zhanga21d5932018-02-05 18:28:38 +0000757 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000758 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +0000759 FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE));
760 ASSERT_TRUE(annot);
761 quadpoints.x1 = 140.802643f;
762 quadpoints.x3 = 140.802643f;
Ralf Sippl16381792018-04-12 21:20:26 +0000763 ASSERT_TRUE(FPDFAnnot_AppendAttachmentPoints(annot.get(), &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000764 }
Jane Liu20eafda2017-06-07 10:33:24 -0400765
Lei Zhangec618142021-04-13 17:36:46 +0000766 // Save the document and close the page.
Jane Liu20eafda2017-06-07 10:33:24 -0400767 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +0000768 UnloadPage(page);
Jane Liu20eafda2017-06-07 10:33:24 -0400769
770 // Open the saved document.
Hui Yingste1215fc2022-03-26 22:29:08 +0000771#if defined(_SKIA_SUPPORT_)
Hui Yingst57daee82020-10-09 05:47:20 +0000772 static const char kChecksum[] = "899387ae792390cd0d83cf7e2bbebfb5";
Hui Yingste1215fc2022-03-26 22:29:08 +0000773#elif defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst57daee82020-10-09 05:47:20 +0000774 static const char kChecksum[] = "e40e235ee35f47ff28dda009aaaf36df";
Hui Yingstb3490322020-07-22 00:53:29 +0000775#else
776 static const char kChecksum[] = "dba153419f67b7c0c0e3d22d3e8910d5";
777#endif
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400778
Lei Zhang0b494052019-01-31 21:41:15 +0000779 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000780 page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +0000781 ASSERT_TRUE(page);
Hui Yingstb3490322020-07-22 00:53:29 +0000782 VerifySavedRendering(page, 612, 792, kChecksum);
Jane Liu20eafda2017-06-07 10:33:24 -0400783
784 // Check that the saved document has 2 annotations on the first page
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000785 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
Jane Liu20eafda2017-06-07 10:33:24 -0400786
Lei Zhanga21d5932018-02-05 18:28:38 +0000787 {
788 // Check that the second annotation is an underline annotation and verify
789 // its quadpoints.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000790 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +0000791 ASSERT_TRUE(new_annot);
792 EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot.get()));
793 FS_QUADPOINTSF new_quadpoints;
794 ASSERT_TRUE(
Ralf Sippl16381792018-04-12 21:20:26 +0000795 FPDFAnnot_GetAttachmentPoints(new_annot.get(), 0, &new_quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000796 EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f);
797 EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f);
798 EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f);
799 EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f);
800 }
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400801
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000802 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400803 CloseSavedDocument();
Jane Liu20eafda2017-06-07 10:33:24 -0400804}
Jane Liu06462752017-06-27 16:41:14 -0400805
Lei Zhangab41f252018-12-23 03:10:50 +0000806TEST_F(FPDFAnnotEmbedderTest, GetAndSetQuadPoints) {
Ralf Sippl16381792018-04-12 21:20:26 +0000807 // Open a file with four annotations and load its first page.
808 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
809 FPDF_PAGE page = LoadPage(0);
810 ASSERT_TRUE(page);
811 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
812
813 // Retrieve the highlight annotation.
814 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
815 ASSERT_TRUE(annot);
816 ASSERT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
817
818 FS_QUADPOINTSF quadpoints;
819 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 0, &quadpoints));
820
821 {
822 // Verify the current one set of quadpoints.
823 ASSERT_EQ(1u, FPDFAnnot_CountAttachmentPoints(annot));
824
825 EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
826 EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
827 EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
828 EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
829 }
830
831 {
832 // Update the quadpoints.
833 FS_QUADPOINTSF new_quadpoints = quadpoints;
834 new_quadpoints.y1 -= 20.f;
835 new_quadpoints.y2 -= 20.f;
836 new_quadpoints.y3 -= 20.f;
837 new_quadpoints.y4 -= 20.f;
838 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, 0, &new_quadpoints));
839
840 // Verify added quadpoint set
841 ASSERT_EQ(1u, FPDFAnnot_CountAttachmentPoints(annot));
842 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 0, &quadpoints));
843 EXPECT_NEAR(new_quadpoints.x1, quadpoints.x1, 0.001f);
844 EXPECT_NEAR(new_quadpoints.y1, quadpoints.y1, 0.001f);
845 EXPECT_NEAR(new_quadpoints.x4, quadpoints.x4, 0.001f);
846 EXPECT_NEAR(new_quadpoints.y4, quadpoints.y4, 0.001f);
847 }
848
849 {
850 // Append a new set of quadpoints.
851 FS_QUADPOINTSF new_quadpoints = quadpoints;
852 new_quadpoints.y1 += 20.f;
853 new_quadpoints.y2 += 20.f;
854 new_quadpoints.y3 += 20.f;
855 new_quadpoints.y4 += 20.f;
856 ASSERT_TRUE(FPDFAnnot_AppendAttachmentPoints(annot, &new_quadpoints));
857
858 // Verify added quadpoint set
859 ASSERT_EQ(2u, FPDFAnnot_CountAttachmentPoints(annot));
860 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 1, &quadpoints));
861 EXPECT_NEAR(new_quadpoints.x1, quadpoints.x1, 0.001f);
862 EXPECT_NEAR(new_quadpoints.y1, quadpoints.y1, 0.001f);
863 EXPECT_NEAR(new_quadpoints.x4, quadpoints.x4, 0.001f);
864 EXPECT_NEAR(new_quadpoints.y4, quadpoints.y4, 0.001f);
865 }
866
867 {
868 // Setting and getting quadpoints at out-of-bound index should fail
869 EXPECT_FALSE(FPDFAnnot_SetAttachmentPoints(annot, 300000, &quadpoints));
870 EXPECT_FALSE(FPDFAnnot_GetAttachmentPoints(annot, 300000, &quadpoints));
871 }
872
873 FPDFPage_CloseAnnot(annot);
874
875 // Retrieve the square annotation
876 FPDF_ANNOTATION squareAnnot = FPDFPage_GetAnnot(page, 2);
877
878 {
879 // Check that attempting to set its quadpoints would fail
880 ASSERT_TRUE(squareAnnot);
881 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(squareAnnot));
882 EXPECT_EQ(0u, FPDFAnnot_CountAttachmentPoints(squareAnnot));
883 EXPECT_FALSE(FPDFAnnot_SetAttachmentPoints(squareAnnot, 0, &quadpoints));
884 }
885
886 FPDFPage_CloseAnnot(squareAnnot);
Ralf Sippl16381792018-04-12 21:20:26 +0000887 UnloadPage(page);
888}
889
Hui Yingstb64cd122020-07-27 16:01:02 +0000890// TODO(crbug.com/pdfium/1569): Fix this issue and enable the test for Skia.
891#if defined(_SKIA_SUPPORT_)
Lei Zhang03e5e682019-09-16 19:45:55 +0000892#define MAYBE_ModifyRectQuadpointsWithAP DISABLED_ModifyRectQuadpointsWithAP
893#else
894#define MAYBE_ModifyRectQuadpointsWithAP ModifyRectQuadpointsWithAP
895#endif
896TEST_F(FPDFAnnotEmbedderTest, MAYBE_ModifyRectQuadpointsWithAP) {
Hui Yingstb64cd122020-07-27 16:01:02 +0000897#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingste1215fc2022-03-26 22:29:08 +0000898 static const char kMd5Original[] = "127c2d3b4452555e3317827b0dbbb6a0";
Lei Zhang4f556b82019-04-08 16:32:41 +0000899 static const char kMd5ModifiedHighlight[] =
Hui Yingste1215fc2022-03-26 22:29:08 +0000900 "6ffe732be6f80540b60921c4803b590a";
901 static const char kMd5ModifiedSquare[] = "9ecbeea7f54abea298b53ce79d301f4a";
Hui Yingstb64cd122020-07-27 16:01:02 +0000902#else
Hui Yingste1215fc2022-03-26 22:29:08 +0000903#if BUILDFLAG(IS_APPLE)
Hui Yingstb64cd122020-07-27 16:01:02 +0000904 static const char kMd5Original[] = "fc59468d154f397fd298c69f47ef565a";
905 static const char kMd5ModifiedHighlight[] =
906 "e64bf648f6e9354d1f3eedb47a2c9498";
907 static const char kMd5ModifiedSquare[] = "a66591662c8e7ad3c6059952e234bebf";
Jane Liub370e5a2017-08-16 13:24:58 -0400908#else
Lei Zhang4f556b82019-04-08 16:32:41 +0000909 static const char kMd5Original[] = "0e27376094f11490f74c65f3dc3a42c5";
910 static const char kMd5ModifiedHighlight[] =
911 "66f3caef3a7d488a4fa1ad37fc06310e";
912 static const char kMd5ModifiedSquare[] = "a456dad0bc6801ee2d6408a4394af563";
Hui Yingste1215fc2022-03-26 22:29:08 +0000913#endif // BUILDFLAG(IS_APPLE)
Hui Yingstb64cd122020-07-27 16:01:02 +0000914#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Jane Liub370e5a2017-08-16 13:24:58 -0400915
Jane Liu06462752017-06-27 16:41:14 -0400916 // Open a file with four annotations and load its first page.
917 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000918 FPDF_PAGE page = LoadPage(0);
Jane Liu06462752017-06-27 16:41:14 -0400919 ASSERT_TRUE(page);
920 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
921
Jane Liub370e5a2017-08-16 13:24:58 -0400922 // Check that the original file renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000923 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000924 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000925 CompareBitmap(bitmap.get(), 612, 792, kMd5Original);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000926 }
Jane Liub370e5a2017-08-16 13:24:58 -0400927
Jane Liu0c6b07d2017-08-15 10:50:22 -0400928 FS_RECTF rect;
Jane Liu0c6b07d2017-08-15 10:50:22 -0400929 FS_RECTF new_rect;
Lei Zhanga21d5932018-02-05 18:28:38 +0000930
931 // Retrieve the highlight annotation which has its AP stream already defined.
932 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000933 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000934 ASSERT_TRUE(annot);
935 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
936
937 // Check that color cannot be set when an AP stream is defined already.
938 EXPECT_FALSE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 51,
939 102, 153, 204));
940
941 // Verify its attachment points.
942 FS_QUADPOINTSF quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000943 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000944 EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
945 EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
946 EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
947 EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
948
949 // Check that updating the attachment points would succeed.
950 quadpoints.x1 -= 50.f;
951 quadpoints.x2 -= 50.f;
952 quadpoints.x3 -= 50.f;
953 quadpoints.x4 -= 50.f;
Ralf Sippl16381792018-04-12 21:20:26 +0000954 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000955 FS_QUADPOINTSF new_quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000956 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &new_quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000957 EXPECT_EQ(quadpoints.x1, new_quadpoints.x1);
958 EXPECT_EQ(quadpoints.y1, new_quadpoints.y1);
959 EXPECT_EQ(quadpoints.x4, new_quadpoints.x4);
960 EXPECT_EQ(quadpoints.y4, new_quadpoints.y4);
961
962 // Check that updating quadpoints does not change the annotation's position.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000963 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000964 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000965 CompareBitmap(bitmap.get(), 612, 792, kMd5Original);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000966 }
Lei Zhanga21d5932018-02-05 18:28:38 +0000967
968 // Verify its annotation rectangle.
969 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
970 EXPECT_NEAR(67.7299f, rect.left, 0.001f);
971 EXPECT_NEAR(704.296f, rect.bottom, 0.001f);
972 EXPECT_NEAR(136.325f, rect.right, 0.001f);
973 EXPECT_NEAR(721.292f, rect.top, 0.001f);
974
975 // Check that updating the rectangle would succeed.
976 rect.left -= 60.f;
977 rect.right -= 60.f;
978 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
979 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
980 EXPECT_EQ(rect.right, new_rect.right);
981 }
Jane Liu06462752017-06-27 16:41:14 -0400982
Jane Liub370e5a2017-08-16 13:24:58 -0400983 // Check that updating the rectangle changes the annotation's position.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000984 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000985 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000986 CompareBitmap(bitmap.get(), 612, 792, kMd5ModifiedHighlight);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000987 }
Jane Liub370e5a2017-08-16 13:24:58 -0400988
Lei Zhanga21d5932018-02-05 18:28:38 +0000989 {
990 // Retrieve the square annotation which has its AP stream already defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000991 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000992 ASSERT_TRUE(annot);
993 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu06462752017-06-27 16:41:14 -0400994
Lei Zhanga21d5932018-02-05 18:28:38 +0000995 // Check that updating the rectangle would succeed.
996 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
997 rect.left += 70.f;
998 rect.right += 70.f;
999 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
1000 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
1001 EXPECT_EQ(rect.right, new_rect.right);
Jane Liu06462752017-06-27 16:41:14 -04001002
Lei Zhanga21d5932018-02-05 18:28:38 +00001003 // Check that updating the rectangle changes the square annotation's
1004 // position.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001005 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001006 CompareBitmap(bitmap.get(), 612, 792, kMd5ModifiedSquare);
Lei Zhanga21d5932018-02-05 18:28:38 +00001007 }
Jane Liub370e5a2017-08-16 13:24:58 -04001008
Jane Liu06462752017-06-27 16:41:14 -04001009 UnloadPage(page);
1010}
Jane Liu8ce58f52017-06-29 13:40:22 -04001011
Lei Zhangab41f252018-12-23 03:10:50 +00001012TEST_F(FPDFAnnotEmbedderTest, CountAttachmentPoints) {
Henrique Nakashima5098b252018-03-26 21:46:00 +00001013 // Open a file with multiline markup annotations.
1014 ASSERT_TRUE(OpenDocument("annotation_markup_multiline_no_ap.pdf"));
1015 FPDF_PAGE page = LoadPage(0);
1016 ASSERT_TRUE(page);
1017 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001018 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Henrique Nakashima5098b252018-03-26 21:46:00 +00001019 ASSERT_TRUE(annot);
1020
1021 // This is a three line annotation.
1022 EXPECT_EQ(3u, FPDFAnnot_CountAttachmentPoints(annot.get()));
1023 }
1024 UnloadPage(page);
1025
1026 // null annotation should return 0
1027 EXPECT_EQ(0u, FPDFAnnot_CountAttachmentPoints(nullptr));
1028}
1029
Lei Zhangab41f252018-12-23 03:10:50 +00001030TEST_F(FPDFAnnotEmbedderTest, RemoveAnnotation) {
Jane Liu8ce58f52017-06-29 13:40:22 -04001031 // Open a file with 3 annotations on its first page.
1032 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +00001033 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu8ce58f52017-06-29 13:40:22 -04001034 ASSERT_TRUE(page);
1035 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
1036
Jane Liu0c6b07d2017-08-15 10:50:22 -04001037 FS_RECTF rect;
Jane Liu8ce58f52017-06-29 13:40:22 -04001038
Lei Zhanga21d5932018-02-05 18:28:38 +00001039 // Check that the annotations have the expected rectangle coordinates.
1040 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001041 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001042 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1043 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
1044 }
Jane Liu8ce58f52017-06-29 13:40:22 -04001045
Lei Zhanga21d5932018-02-05 18:28:38 +00001046 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001047 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +00001048 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1049 EXPECT_NEAR(149.8127f, rect.left, 0.001f);
1050 }
1051
1052 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001053 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001054 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1055 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
1056 }
Jane Liu8ce58f52017-06-29 13:40:22 -04001057
1058 // Check that nothing happens when attempting to remove an annotation with an
1059 // out-of-bound index.
1060 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4));
1061 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1));
1062 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
1063
1064 // Remove the second annotation.
1065 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
1066 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1067 EXPECT_FALSE(FPDFPage_GetAnnot(page, 2));
1068
Lei Zhangec618142021-04-13 17:36:46 +00001069 // Save the document and close the page.
Jane Liu8ce58f52017-06-29 13:40:22 -04001070 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Tom Sepez507d0192018-11-07 16:37:51 +00001071 UnloadPageNoEvents(page);
Jane Liu8ce58f52017-06-29 13:40:22 -04001072
Dan Sinclair04e4dc82017-10-18 12:17:14 -04001073 // TODO(npm): VerifySavedRendering changes annot rect dimensions by 1??
Jane Liu8ce58f52017-06-29 13:40:22 -04001074 // Open the saved document.
1075 std::string new_file = GetString();
1076 FPDF_FILEACCESS file_access;
1077 memset(&file_access, 0, sizeof(file_access));
1078 file_access.m_FileLen = new_file.size();
1079 file_access.m_GetBlock = GetBlockFromString;
1080 file_access.m_Param = &new_file;
1081 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
1082 ASSERT_TRUE(new_doc);
1083 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
1084 ASSERT_TRUE(new_page);
1085
1086 // Check that the saved document has 2 annotations on the first page.
1087 EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
1088
Lei Zhanga21d5932018-02-05 18:28:38 +00001089 // Check that the remaining 2 annotations are the original 1st and 3rd ones
1090 // by verifying their rectangle coordinates.
1091 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001092 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(new_page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001093 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1094 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
1095 }
Jane Liu8ce58f52017-06-29 13:40:22 -04001096
Lei Zhanga21d5932018-02-05 18:28:38 +00001097 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001098 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(new_page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +00001099 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1100 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
1101 }
Jane Liubaa7ff42017-06-29 19:18:23 -04001102 FPDF_ClosePage(new_page);
1103 FPDF_CloseDocument(new_doc);
1104}
Jane Liu8ce58f52017-06-29 13:40:22 -04001105
Hui Yingst4a21df02020-05-13 03:15:44 +00001106TEST_F(FPDFAnnotEmbedderTest, AddAndModifyPath) {
Lei Zhang03e5e682019-09-16 19:45:55 +00001107#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001108 static const char kMd5ModifiedPath[] = "b820e4ae359db95cbac9823937c6da1a";
1109 static const char kMd5TwoPaths[] = "c53837b7bb6a9a21a846aa786526aa56";
1110 static const char kMd5NewAnnot[] = "4f0f4217156e4251036f369184a48967";
Lei Zhang42d30c22022-01-12 19:24:43 +00001111#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001112 static const char kMd5ModifiedPath[] = "e31421f86c61d4e9cda138f15f561ca3";
1113 static const char kMd5TwoPaths[] = "58d932492f9d485d6a4bc0ba76c04557";
1114 static const char kMd5NewAnnot[] = "61f9ad13f2fd235753db198cf9704773";
Jane Liubaa7ff42017-06-29 19:18:23 -04001115#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00001116 static const char kMd5ModifiedPath[] = "980e7636d864f7f7d323a31ad4e8fa04";
1117 static const char kMd5TwoPaths[] = "4c779c394b6790f8cf80305b566b663b";
1118 static const char kMd5NewAnnot[] = "97effd68dcf86273f68d126d6b45152e";
Jane Liubaa7ff42017-06-29 19:18:23 -04001119#endif
1120
1121 // Open a file with two annotations and load its first page.
1122 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001123 FPDF_PAGE page = LoadPage(0);
Jane Liubaa7ff42017-06-29 19:18:23 -04001124 ASSERT_TRUE(page);
1125 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1126
1127 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001128 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001129 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001130 CompareBitmap(bitmap.get(), 595, 842, kAnnotationStampWithApChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001131 }
Jane Liubaa7ff42017-06-29 19:18:23 -04001132
Lei Zhanga21d5932018-02-05 18:28:38 +00001133 {
1134 // Retrieve the stamp annotation which has its AP stream already defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001135 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001136 ASSERT_TRUE(annot);
Jane Liubaa7ff42017-06-29 19:18:23 -04001137
Lei Zhanga21d5932018-02-05 18:28:38 +00001138 // Check that this annotation has one path object and retrieve it.
1139 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001140 ASSERT_EQ(32, FPDFPage_CountObjects(page));
Lei Zhanga21d5932018-02-05 18:28:38 +00001141 FPDF_PAGEOBJECT path = FPDFAnnot_GetObject(annot.get(), 1);
1142 EXPECT_FALSE(path);
1143 path = FPDFAnnot_GetObject(annot.get(), 0);
1144 EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
1145 EXPECT_TRUE(path);
Jane Liubaa7ff42017-06-29 19:18:23 -04001146
Lei Zhanga21d5932018-02-05 18:28:38 +00001147 // Modify the color of the path object.
Lei Zhang3475b482019-05-13 18:30:57 +00001148 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 0, 0, 0, 255));
Lei Zhanga21d5932018-02-05 18:28:38 +00001149 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), path));
Jane Liubaa7ff42017-06-29 19:18:23 -04001150
Lei Zhanga21d5932018-02-05 18:28:38 +00001151 // Check that the page with the modified annotation renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001152 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001153 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001154 CompareBitmap(bitmap.get(), 595, 842, kMd5ModifiedPath);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001155 }
Jane Liu7a9a38b2017-07-11 13:47:37 -04001156
Lei Zhanga21d5932018-02-05 18:28:38 +00001157 // Add a second path object to the same annotation.
1158 FPDF_PAGEOBJECT dot = FPDFPageObj_CreateNewPath(7, 84);
1159 EXPECT_TRUE(FPDFPath_BezierTo(dot, 9, 86, 10, 87, 11, 88));
Lei Zhang3475b482019-05-13 18:30:57 +00001160 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(dot, 255, 0, 0, 100));
1161 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(dot, 14));
Lei Zhanga21d5932018-02-05 18:28:38 +00001162 EXPECT_TRUE(FPDFPath_SetDrawMode(dot, 0, 1));
1163 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), dot));
1164 EXPECT_EQ(2, FPDFAnnot_GetObjectCount(annot.get()));
Jane Liu7a9a38b2017-07-11 13:47:37 -04001165
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001166 // The object is in the annontation, not in the page, so the page object
1167 // array should not change.
1168 ASSERT_EQ(32, FPDFPage_CountObjects(page));
1169
Lei Zhanga21d5932018-02-05 18:28:38 +00001170 // Check that the page with an annotation with two paths renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001171 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001172 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001173 CompareBitmap(bitmap.get(), 595, 842, kMd5TwoPaths);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001174 }
Jane Liu7a9a38b2017-07-11 13:47:37 -04001175
Lei Zhanga21d5932018-02-05 18:28:38 +00001176 // Delete the newly added path object.
1177 EXPECT_TRUE(FPDFAnnot_RemoveObject(annot.get(), 1));
1178 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001179 ASSERT_EQ(32, FPDFPage_CountObjects(page));
Lei Zhanga21d5932018-02-05 18:28:38 +00001180 }
Jane Liu7a9a38b2017-07-11 13:47:37 -04001181
1182 // Check that the page renders the same as before.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001183 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001184 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001185 CompareBitmap(bitmap.get(), 595, 842, kMd5ModifiedPath);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001186 }
Jane Liubaa7ff42017-06-29 19:18:23 -04001187
Jane Liubaa7ff42017-06-29 19:18:23 -04001188 FS_RECTF rect;
Jane Liubaa7ff42017-06-29 19:18:23 -04001189
Lei Zhanga21d5932018-02-05 18:28:38 +00001190 {
1191 // Create another stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001192 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001193 ASSERT_TRUE(annot);
1194 rect.left = 200.f;
1195 rect.bottom = 400.f;
1196 rect.right = 500.f;
1197 rect.top = 600.f;
1198 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
Jane Liubaa7ff42017-06-29 19:18:23 -04001199
Lei Zhanga21d5932018-02-05 18:28:38 +00001200 // Add a new path to the annotation.
1201 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500);
1202 EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400));
1203 EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600));
1204 EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550));
1205 EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450));
Lei Zhang3475b482019-05-13 18:30:57 +00001206 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(check, 0, 255, 255, 180));
1207 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(check, 8.35f));
Lei Zhanga21d5932018-02-05 18:28:38 +00001208 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
1209 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), check));
1210 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1211
1212 // Check that the annotation's bounding box came from its rectangle.
1213 FS_RECTF new_rect;
1214 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
1215 EXPECT_EQ(rect.left, new_rect.left);
1216 EXPECT_EQ(rect.bottom, new_rect.bottom);
1217 EXPECT_EQ(rect.right, new_rect.right);
1218 EXPECT_EQ(rect.top, new_rect.top);
1219 }
Jane Liubaa7ff42017-06-29 19:18:23 -04001220
Lei Zhangec618142021-04-13 17:36:46 +00001221 // Save the document and close the page.
Jane Liubaa7ff42017-06-29 19:18:23 -04001222 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001223 UnloadPage(page);
Jane Liubaa7ff42017-06-29 19:18:23 -04001224
1225 // Open the saved document.
Lei Zhang0b494052019-01-31 21:41:15 +00001226 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001227 page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001228 ASSERT_TRUE(page);
Lei Zhang4f556b82019-04-08 16:32:41 +00001229 VerifySavedRendering(page, 595, 842, kMd5NewAnnot);
Jane Liubaa7ff42017-06-29 19:18:23 -04001230
Jane Liu36567742017-07-06 11:13:35 -04001231 // Check that the document has a correct count of annotations and objects.
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001232 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
Jane Liubaa7ff42017-06-29 19:18:23 -04001233
Lei Zhanga21d5932018-02-05 18:28:38 +00001234 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001235 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001236 ASSERT_TRUE(annot);
1237 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Jane Liubaa7ff42017-06-29 19:18:23 -04001238
Lei Zhanga21d5932018-02-05 18:28:38 +00001239 // Check that the new annotation's rectangle is as defined.
1240 FS_RECTF new_rect;
1241 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
1242 EXPECT_EQ(rect.left, new_rect.left);
1243 EXPECT_EQ(rect.bottom, new_rect.bottom);
1244 EXPECT_EQ(rect.right, new_rect.right);
1245 EXPECT_EQ(rect.top, new_rect.top);
1246 }
1247
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001248 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04001249 CloseSavedDocument();
Jane Liu8ce58f52017-06-29 13:40:22 -04001250}
Jane Liub137e752017-07-05 15:04:33 -04001251
Lei Zhangab41f252018-12-23 03:10:50 +00001252TEST_F(FPDFAnnotEmbedderTest, ModifyAnnotationFlags) {
Jane Liub137e752017-07-05 15:04:33 -04001253 // Open a file with an annotation and load its first page.
1254 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001255 FPDF_PAGE page = LoadPage(0);
Jane Liub137e752017-07-05 15:04:33 -04001256 ASSERT_TRUE(page);
1257
1258 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001259 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001260 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001261 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
1262 }
Jane Liub137e752017-07-05 15:04:33 -04001263
Lei Zhanga21d5932018-02-05 18:28:38 +00001264 {
1265 // Retrieve the annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001266 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001267 ASSERT_TRUE(annot);
Jane Liub137e752017-07-05 15:04:33 -04001268
Lei Zhanga21d5932018-02-05 18:28:38 +00001269 // Check that the original flag values are as expected.
1270 int flags = FPDFAnnot_GetFlags(annot.get());
Tom Sepez45c2fd02021-05-12 19:46:13 +00001271 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_INVISIBLE);
Lei Zhanga21d5932018-02-05 18:28:38 +00001272 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
1273 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001274 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_NOZOOM);
1275 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_NOROTATE);
1276 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_NOVIEW);
1277 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_READONLY);
1278 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_LOCKED);
1279 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_TOGGLENOVIEW);
Jane Liub137e752017-07-05 15:04:33 -04001280
Lei Zhanga21d5932018-02-05 18:28:38 +00001281 // Set the HIDDEN flag.
1282 flags |= FPDF_ANNOT_FLAG_HIDDEN;
1283 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), flags));
1284 flags = FPDFAnnot_GetFlags(annot.get());
1285 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_HIDDEN);
1286 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Jane Liub137e752017-07-05 15:04:33 -04001287
Lei Zhanga21d5932018-02-05 18:28:38 +00001288 // Check that the page renders correctly without rendering the annotation.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001289 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001290 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001291 CompareBitmap(bitmap.get(), 612, 792, pdfium::kBlankPage612By792Checksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001292 }
Jane Liub137e752017-07-05 15:04:33 -04001293
Lei Zhanga21d5932018-02-05 18:28:38 +00001294 // Unset the HIDDEN flag.
1295 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), FPDF_ANNOT_FLAG_NONE));
1296 EXPECT_FALSE(FPDFAnnot_GetFlags(annot.get()));
1297 flags &= ~FPDF_ANNOT_FLAG_HIDDEN;
1298 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), flags));
1299 flags = FPDFAnnot_GetFlags(annot.get());
1300 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
1301 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Jane Liub137e752017-07-05 15:04:33 -04001302
Lei Zhanga21d5932018-02-05 18:28:38 +00001303 // Check that the page renders correctly as before.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001304 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001305 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001306 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
1307 }
Lei Zhanga21d5932018-02-05 18:28:38 +00001308 }
Jane Liub137e752017-07-05 15:04:33 -04001309
Jane Liub137e752017-07-05 15:04:33 -04001310 UnloadPage(page);
1311}
Jane Liu36567742017-07-06 11:13:35 -04001312
Hui Yingstdd9a3f62020-06-16 18:14:21 +00001313// TODO(crbug.com/pdfium/1541): Fix this test and enable.
1314#if defined(_SKIA_SUPPORT_)
Lei Zhang03e5e682019-09-16 19:45:55 +00001315#define MAYBE_AddAndModifyImage DISABLED_AddAndModifyImage
1316#else
1317#define MAYBE_AddAndModifyImage AddAndModifyImage
1318#endif
1319TEST_F(FPDFAnnotEmbedderTest, MAYBE_AddAndModifyImage) {
Hui Yingstdd9a3f62020-06-16 18:14:21 +00001320#if defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001321 static const char kMd5NewImage[] = "beb7db3647706d7fe4689f92073847aa";
1322 static const char kMd5ModifiedImage[] = "baa9b065469268e215ef958fe6987d6b";
Hui Yingstdd9a3f62020-06-16 18:14:21 +00001323#else
Lei Zhang42d30c22022-01-12 19:24:43 +00001324#if BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001325 static const char kMd5NewImage[] = "c6fcbceb2f079bef10458ac60db3a10c";
1326 static const char kMd5ModifiedImage[] = "8068eb568e5c1c5fbe84e98f7a980ac3";
Jane Liu36567742017-07-06 11:13:35 -04001327#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00001328 static const char kMd5NewImage[] = "62c2706511cb50e32e7caeb82b1d3d49";
1329 static const char kMd5ModifiedImage[] = "83093ce9fac746db69fbd2fb394434ac";
Jane Liu36567742017-07-06 11:13:35 -04001330#endif
Hui Yingstdd9a3f62020-06-16 18:14:21 +00001331#endif // defined(_SKIA_SUPPORT_PATHS_)
Jane Liu36567742017-07-06 11:13:35 -04001332
1333 // Open a file with two annotations and load its first page.
1334 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001335 FPDF_PAGE page = LoadPage(0);
Jane Liu36567742017-07-06 11:13:35 -04001336 ASSERT_TRUE(page);
1337 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1338
1339 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001340 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001341 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001342 CompareBitmap(bitmap.get(), 595, 842, kAnnotationStampWithApChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001343 }
Jane Liu36567742017-07-06 11:13:35 -04001344
Jane Liu36567742017-07-06 11:13:35 -04001345 constexpr int kBitmapSize = 200;
Lei Zhanga21d5932018-02-05 18:28:38 +00001346 FPDF_BITMAP image_bitmap;
1347
1348 {
1349 // Create a stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001350 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001351 ASSERT_TRUE(annot);
1352 FS_RECTF rect;
1353 rect.left = 200.f;
1354 rect.bottom = 600.f;
1355 rect.right = 400.f;
1356 rect.top = 800.f;
1357 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
1358
1359 // Add a solid-color translucent image object to the new annotation.
1360 image_bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 1);
1361 FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize,
1362 0xeeeecccc);
1363 EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(image_bitmap));
1364 EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(image_bitmap));
1365 FPDF_PAGEOBJECT image_object = FPDFPageObj_NewImageObj(document());
1366 ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
Lei Zhangc8601bf2021-06-29 23:19:27 +00001367 static constexpr FS_MATRIX kBitmapScaleMatrix{kBitmapSize, 0, 0,
1368 kBitmapSize, 0, 0};
1369 ASSERT_TRUE(FPDFPageObj_SetMatrix(image_object, &kBitmapScaleMatrix));
Lei Zhanga21d5932018-02-05 18:28:38 +00001370 FPDFPageObj_Transform(image_object, 1, 0, 0, 1, 200, 600);
1371 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), image_object));
1372 }
Jane Liu36567742017-07-06 11:13:35 -04001373
1374 // Check that the page renders correctly with the new image object.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001375 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001376 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001377 CompareBitmap(bitmap.get(), 595, 842, kMd5NewImage);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001378 }
Jane Liu36567742017-07-06 11:13:35 -04001379
Lei Zhanga21d5932018-02-05 18:28:38 +00001380 {
1381 // Retrieve the newly added stamp annotation and its image object.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001382 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001383 ASSERT_TRUE(annot);
1384 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1385 FPDF_PAGEOBJECT image_object = FPDFAnnot_GetObject(annot.get(), 0);
1386 EXPECT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(image_object));
Jane Liu36567742017-07-06 11:13:35 -04001387
Lei Zhanga21d5932018-02-05 18:28:38 +00001388 // Modify the image in the new annotation.
1389 FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize,
1390 0xff000000);
1391 ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
1392 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), image_object));
1393 }
Jane Liu36567742017-07-06 11:13:35 -04001394
Lei Zhangec618142021-04-13 17:36:46 +00001395 // Save the document and close the page.
Jane Liu36567742017-07-06 11:13:35 -04001396 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001397 UnloadPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04001398 FPDFBitmap_Destroy(image_bitmap);
Jane Liu36567742017-07-06 11:13:35 -04001399
1400 // Test that the saved document renders the modified image object correctly.
Lei Zhang4f556b82019-04-08 16:32:41 +00001401 VerifySavedDocument(595, 842, kMd5ModifiedImage);
Jane Liu36567742017-07-06 11:13:35 -04001402}
1403
Hui Yingst6cd754f2020-05-14 04:05:25 +00001404TEST_F(FPDFAnnotEmbedderTest, AddAndModifyText) {
Lei Zhang03e5e682019-09-16 19:45:55 +00001405#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001406 static const char kMd5NewText[] = "310d9de5f17fb288fb243f5dbaf2b6dc";
1407 static const char kMd5ModifiedText[] = "22be42c136c3bf5a8ecea3dd83770a02";
Lei Zhang42d30c22022-01-12 19:24:43 +00001408#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001409 static const char kMd5NewText[] = "57a0fb3fba33e17de26bcde4c40b9a75";
1410 static const char kMd5ModifiedText[] = "072574999f2e3f36774ee0b5bc94d4dd";
Jane Liu36567742017-07-06 11:13:35 -04001411#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00001412 static const char kMd5NewText[] = "1c4198c38f890c208c5cbaad57be4dc6";
1413 static const char kMd5ModifiedText[] = "cfa78d01406865f41f486bd34a8b9f7b";
Jane Liu36567742017-07-06 11:13:35 -04001414#endif
1415
1416 // Open a file with two annotations and load its first page.
1417 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001418 FPDF_PAGE page = LoadPage(0);
Jane Liu36567742017-07-06 11:13:35 -04001419 ASSERT_TRUE(page);
1420 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1421
1422 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001423 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001424 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001425 CompareBitmap(bitmap.get(), 595, 842, kAnnotationStampWithApChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001426 }
Jane Liu36567742017-07-06 11:13:35 -04001427
Lei Zhanga21d5932018-02-05 18:28:38 +00001428 {
1429 // Create a stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001430 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001431 ASSERT_TRUE(annot);
1432 FS_RECTF rect;
1433 rect.left = 200.f;
1434 rect.bottom = 550.f;
1435 rect.right = 450.f;
1436 rect.top = 650.f;
1437 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
Jane Liu36567742017-07-06 11:13:35 -04001438
Lei Zhanga21d5932018-02-05 18:28:38 +00001439 // Add a translucent text object to the new annotation.
1440 FPDF_PAGEOBJECT text_object =
1441 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
1442 EXPECT_TRUE(text_object);
Lei Zhangf0f67682019-04-08 17:03:21 +00001443 ScopedFPDFWideString text =
Lei Zhanga21d5932018-02-05 18:28:38 +00001444 GetFPDFWideString(L"I'm a translucent text laying on other text.");
1445 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
Lei Zhang3475b482019-05-13 18:30:57 +00001446 EXPECT_TRUE(FPDFPageObj_SetFillColor(text_object, 0, 0, 255, 150));
Lei Zhanga21d5932018-02-05 18:28:38 +00001447 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 600);
1448 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), text_object));
1449 }
Jane Liu36567742017-07-06 11:13:35 -04001450
1451 // Check that the page renders correctly with the new text object.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001452 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001453 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001454 CompareBitmap(bitmap.get(), 595, 842, kMd5NewText);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001455 }
Jane Liu36567742017-07-06 11:13:35 -04001456
Lei Zhanga21d5932018-02-05 18:28:38 +00001457 {
1458 // Retrieve the newly added stamp annotation and its text object.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001459 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001460 ASSERT_TRUE(annot);
1461 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1462 FPDF_PAGEOBJECT text_object = FPDFAnnot_GetObject(annot.get(), 0);
1463 EXPECT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_object));
Jane Liu36567742017-07-06 11:13:35 -04001464
Lei Zhanga21d5932018-02-05 18:28:38 +00001465 // Modify the text in the new annotation.
Lei Zhangf0f67682019-04-08 17:03:21 +00001466 ScopedFPDFWideString new_text = GetFPDFWideString(L"New text!");
Lei Zhanga21d5932018-02-05 18:28:38 +00001467 EXPECT_TRUE(FPDFText_SetText(text_object, new_text.get()));
1468 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), text_object));
1469 }
Jane Liu36567742017-07-06 11:13:35 -04001470
1471 // Check that the page renders correctly with the modified text object.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001472 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001473 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001474 CompareBitmap(bitmap.get(), 595, 842, kMd5ModifiedText);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001475 }
Jane Liu36567742017-07-06 11:13:35 -04001476
1477 // Remove the new annotation, and check that the page renders as before.
1478 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 2));
Lei Zhangc113c7a2018-02-12 14:58:44 +00001479 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001480 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001481 CompareBitmap(bitmap.get(), 595, 842, kAnnotationStampWithApChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001482 }
Jane Liu36567742017-07-06 11:13:35 -04001483
1484 UnloadPage(page);
1485}
Jane Liu2e1a32b2017-07-06 12:01:25 -04001486
Hui Yingst9b6b1542020-07-27 16:11:12 +00001487TEST_F(FPDFAnnotEmbedderTest, GetSetStringValue) {
Jane Liu2e1a32b2017-07-06 12:01:25 -04001488 // Open a file with four annotations and load its first page.
1489 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001490 FPDF_PAGE page = LoadPage(0);
Jane Liu2e1a32b2017-07-06 12:01:25 -04001491 ASSERT_TRUE(page);
1492
Lei Zhang4f556b82019-04-08 16:32:41 +00001493 static const wchar_t kNewDate[] = L"D:201706282359Z00'00'";
Jane Liu2e1a32b2017-07-06 12:01:25 -04001494
Lei Zhanga21d5932018-02-05 18:28:38 +00001495 {
1496 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001497 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001498 ASSERT_TRUE(annot);
1499
1500 // Check that a non-existent key does not exist.
1501 EXPECT_FALSE(FPDFAnnot_HasKey(annot.get(), "none"));
1502
1503 // Check that the string value of a non-string dictionary entry is empty.
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001504 EXPECT_TRUE(FPDFAnnot_HasKey(annot.get(), pdfium::annotation::kAP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001505 EXPECT_EQ(FPDF_OBJECT_REFERENCE,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001506 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kAP));
1507 EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kAP,
1508 nullptr, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001509
1510 // Check that the string value of the hash is correct.
Lei Zhang4f556b82019-04-08 16:32:41 +00001511 static const char kHashKey[] = "AAPL:Hash";
Lei Zhanga21d5932018-02-05 18:28:38 +00001512 EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot.get(), kHashKey));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001513 unsigned long length_bytes =
Lei Zhanga21d5932018-02-05 18:28:38 +00001514 FPDFAnnot_GetStringValue(annot.get(), kHashKey, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001515 ASSERT_EQ(66u, length_bytes);
1516 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
1517 EXPECT_EQ(66u, FPDFAnnot_GetStringValue(annot.get(), kHashKey, buf.data(),
1518 length_bytes));
1519 EXPECT_EQ(L"395fbcb98d558681742f30683a62a2ad",
1520 GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001521
1522 // Check that the string value of the modified date is correct.
1523 EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot.get(), kHashKey));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001524 length_bytes = FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kM,
1525 nullptr, 0);
1526 ASSERT_EQ(44u, length_bytes);
1527 buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001528 EXPECT_EQ(44u, FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kM,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001529 buf.data(), length_bytes));
1530 EXPECT_EQ(L"D:201706071721Z00'00'", GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001531
1532 // Update the date entry for the annotation.
Lei Zhangf0f67682019-04-08 17:03:21 +00001533 ScopedFPDFWideString text = GetFPDFWideString(kNewDate);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001534 EXPECT_TRUE(FPDFAnnot_SetStringValue(annot.get(), pdfium::annotation::kM,
1535 text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001536 }
Jane Liu2e1a32b2017-07-06 12:01:25 -04001537
Lei Zhangec618142021-04-13 17:36:46 +00001538 // Save the document and close the page.
Jane Liu2e1a32b2017-07-06 12:01:25 -04001539 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001540 UnloadPage(page);
Jane Liu2e1a32b2017-07-06 12:01:25 -04001541
Hui Yingst9b6b1542020-07-27 16:11:12 +00001542#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001543 static const char kMd5[] = "aa0e47d966c60d59102a2466542e0e46";
Lei Zhang42d30c22022-01-12 19:24:43 +00001544#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001545 static const char kMd5[] = "cd90315b250dfe08265ce0ac335c5f76";
Hui Yingst9b6b1542020-07-27 16:11:12 +00001546#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00001547 static const char kMd5[] = "c4fb6911f2a87f490be196f8898de738";
Jane Liu2e1a32b2017-07-06 12:01:25 -04001548#endif
Dan Sinclair971a6742018-03-28 19:23:25 +00001549
1550 // Open the saved annotation.
Lei Zhang0b494052019-01-31 21:41:15 +00001551 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001552 page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001553 ASSERT_TRUE(page);
Lei Zhang4f556b82019-04-08 16:32:41 +00001554 VerifySavedRendering(page, 595, 842, kMd5);
Lei Zhanga21d5932018-02-05 18:28:38 +00001555 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001556 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 0));
Jane Liu2e1a32b2017-07-06 12:01:25 -04001557
Lei Zhanga21d5932018-02-05 18:28:38 +00001558 // Check that the string value of the modified date is the newly-set value.
1559 EXPECT_EQ(FPDF_OBJECT_STRING,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001560 FPDFAnnot_GetValueType(new_annot.get(), pdfium::annotation::kM));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001561 unsigned long length_bytes = FPDFAnnot_GetStringValue(
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001562 new_annot.get(), pdfium::annotation::kM, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001563 ASSERT_EQ(44u, length_bytes);
1564 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001565 EXPECT_EQ(44u,
1566 FPDFAnnot_GetStringValue(new_annot.get(), pdfium::annotation::kM,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001567 buf.data(), length_bytes));
1568 EXPECT_EQ(kNewDate, GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001569 }
Jane Liu2e1a32b2017-07-06 12:01:25 -04001570
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001571 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04001572 CloseSavedDocument();
Jane Liu2e1a32b2017-07-06 12:01:25 -04001573}
Diana Gage7e0c05d2017-07-19 17:33:33 -07001574
rycsmith3e785602019-03-05 21:48:36 +00001575TEST_F(FPDFAnnotEmbedderTest, GetNumberValue) {
Mansi Awasthi0b5da672020-01-23 18:17:18 +00001576 // Open a file with four text annotations and load its first page.
rycsmith3e785602019-03-05 21:48:36 +00001577 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
1578 FPDF_PAGE page = LoadPage(0);
1579 ASSERT_TRUE(page);
1580 {
1581 // First two annotations do not have "MaxLen" attribute.
1582 for (int i = 0; i < 2; i++) {
1583 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
1584 ASSERT_TRUE(annot);
1585
1586 // Verify that no "MaxLen" key present.
1587 EXPECT_FALSE(FPDFAnnot_HasKey(annot.get(), "MaxLen"));
1588
1589 float value;
1590 EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", &value));
1591 }
1592
1593 // Annotation in index 2 has "MaxLen" of 10.
1594 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1595 ASSERT_TRUE(annot);
1596
1597 // Verify that "MaxLen" key present.
1598 EXPECT_TRUE(FPDFAnnot_HasKey(annot.get(), "MaxLen"));
1599
1600 float value;
1601 EXPECT_TRUE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", &value));
1602 EXPECT_FLOAT_EQ(10.0f, value);
1603
1604 // Check bad inputs.
1605 EXPECT_FALSE(FPDFAnnot_GetNumberValue(nullptr, "MaxLen", &value));
1606 EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), nullptr, &value));
1607 EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", nullptr));
1608 // Ask for key that exists but is not a number.
1609 EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "V", &value));
1610 }
1611
1612 UnloadPage(page);
1613}
1614
Lei Zhangab41f252018-12-23 03:10:50 +00001615TEST_F(FPDFAnnotEmbedderTest, GetSetAP) {
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001616 // Open a file with four annotations and load its first page.
1617 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001618 FPDF_PAGE page = LoadPage(0);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001619 ASSERT_TRUE(page);
1620
Lei Zhanga21d5932018-02-05 18:28:38 +00001621 {
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001622 static const char kMd5NormalAP[] = "be903df0343fd774fadab9c8900cdf4a";
1623 static constexpr size_t kExpectNormalAPLength = 73970;
1624
Lei Zhanga21d5932018-02-05 18:28:38 +00001625 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001626 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001627 ASSERT_TRUE(annot);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001628
Lei Zhanga21d5932018-02-05 18:28:38 +00001629 // Check that the string value of an AP returns the expected length.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001630 unsigned long normal_length_bytes = FPDFAnnot_GetAP(
Lei Zhanga21d5932018-02-05 18:28:38 +00001631 annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001632 ASSERT_EQ(kExpectNormalAPLength, normal_length_bytes);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001633
Lei Zhanga21d5932018-02-05 18:28:38 +00001634 // Check that the string value of an AP is not returned if the buffer is too
1635 // small. The result buffer should be overwritten with an empty string.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001636 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(normal_length_bytes);
1637 // Write in the buffer to verify it's not overwritten.
1638 memcpy(buf.data(), "abcdefgh", 8);
1639 EXPECT_EQ(kExpectNormalAPLength,
Lei Zhanga21d5932018-02-05 18:28:38 +00001640 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001641 buf.data(), normal_length_bytes - 1));
1642 EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001643
Lei Zhanga21d5932018-02-05 18:28:38 +00001644 // Check that the string value of an AP is returned through a buffer that is
1645 // the right size.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001646 EXPECT_EQ(kExpectNormalAPLength,
Lei Zhanga21d5932018-02-05 18:28:38 +00001647 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001648 buf.data(), normal_length_bytes));
1649 EXPECT_EQ(kMd5NormalAP,
1650 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()),
1651 normal_length_bytes));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001652
Lei Zhanga21d5932018-02-05 18:28:38 +00001653 // Check that the string value of an AP is returned through a buffer that is
1654 // larger than necessary.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001655 buf = GetFPDFWideStringBuffer(normal_length_bytes + 2);
1656 EXPECT_EQ(kExpectNormalAPLength,
Lei Zhanga21d5932018-02-05 18:28:38 +00001657 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001658 buf.data(), normal_length_bytes + 2));
1659 EXPECT_EQ(kMd5NormalAP,
1660 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()),
1661 normal_length_bytes));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001662
Lei Zhanga21d5932018-02-05 18:28:38 +00001663 // Check that getting an AP for a mode that does not have an AP returns an
1664 // empty string.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001665 unsigned long rollover_length_bytes = FPDFAnnot_GetAP(
Lei Zhanga21d5932018-02-05 18:28:38 +00001666 annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001667 ASSERT_EQ(2u, rollover_length_bytes);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001668
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001669 buf = GetFPDFWideStringBuffer(1000);
Lei Zhanga21d5932018-02-05 18:28:38 +00001670 EXPECT_EQ(2u,
1671 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001672 buf.data(), 1000));
1673 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001674
Lei Zhanga21d5932018-02-05 18:28:38 +00001675 // Check that setting the AP for an invalid appearance mode fails.
Lei Zhangf0f67682019-04-08 17:03:21 +00001676 ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
Lei Zhang4f556b82019-04-08 16:32:41 +00001677 EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), -1, ap_text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001678 EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_COUNT,
Lei Zhang4f556b82019-04-08 16:32:41 +00001679 ap_text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001680 EXPECT_FALSE(FPDFAnnot_SetAP(
Lei Zhang4f556b82019-04-08 16:32:41 +00001681 annot.get(), FPDF_ANNOT_APPEARANCEMODE_COUNT + 1, ap_text.get()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001682
Lei Zhanga21d5932018-02-05 18:28:38 +00001683 // Set the AP correctly now.
1684 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang4f556b82019-04-08 16:32:41 +00001685 ap_text.get()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001686
Lei Zhanga21d5932018-02-05 18:28:38 +00001687 // Check that the new annotation value is equal to the value we just set.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001688 rollover_length_bytes = FPDFAnnot_GetAP(
Lei Zhanga21d5932018-02-05 18:28:38 +00001689 annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001690 ASSERT_EQ(24u, rollover_length_bytes);
1691 buf = GetFPDFWideStringBuffer(rollover_length_bytes);
Lei Zhanga21d5932018-02-05 18:28:38 +00001692 EXPECT_EQ(24u,
1693 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001694 buf.data(), rollover_length_bytes));
1695 EXPECT_EQ(L"new test ap", GetPlatformWString(buf.data()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001696
Lei Zhanga21d5932018-02-05 18:28:38 +00001697 // Check that the Normal AP was not touched when the Rollover AP was set.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001698 buf = GetFPDFWideStringBuffer(normal_length_bytes);
1699 EXPECT_EQ(kExpectNormalAPLength,
Lei Zhanga21d5932018-02-05 18:28:38 +00001700 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001701 buf.data(), normal_length_bytes));
1702 EXPECT_EQ(kMd5NormalAP,
1703 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()),
1704 normal_length_bytes));
Lei Zhanga21d5932018-02-05 18:28:38 +00001705 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001706
1707 // Save the modified document, then reopen it.
Henrique Nakashima5970a472018-01-11 22:40:59 +00001708 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001709 UnloadPage(page);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001710
Lei Zhang0b494052019-01-31 21:41:15 +00001711 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima5970a472018-01-11 22:40:59 +00001712 page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001713 ASSERT_TRUE(page);
Lei Zhanga21d5932018-02-05 18:28:38 +00001714 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001715 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001716
Lei Zhanga21d5932018-02-05 18:28:38 +00001717 // Check that the new annotation value is equal to the value we set before
1718 // saving.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001719 unsigned long rollover_length_bytes = FPDFAnnot_GetAP(
Lei Zhanga21d5932018-02-05 18:28:38 +00001720 new_annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001721 ASSERT_EQ(24u, rollover_length_bytes);
1722 std::vector<FPDF_WCHAR> buf =
1723 GetFPDFWideStringBuffer(rollover_length_bytes);
Lei Zhanga21d5932018-02-05 18:28:38 +00001724 EXPECT_EQ(24u, FPDFAnnot_GetAP(new_annot.get(),
1725 FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001726 buf.data(), rollover_length_bytes));
1727 EXPECT_EQ(L"new test ap", GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001728 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001729
1730 // Close saved document.
Henrique Nakashima5970a472018-01-11 22:40:59 +00001731 CloseSavedPage(page);
1732 CloseSavedDocument();
1733}
1734
Lei Zhangab41f252018-12-23 03:10:50 +00001735TEST_F(FPDFAnnotEmbedderTest, RemoveOptionalAP) {
Henrique Nakashima5970a472018-01-11 22:40:59 +00001736 // Open a file with four annotations and load its first page.
1737 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001738 FPDF_PAGE page = LoadPage(0);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001739 ASSERT_TRUE(page);
1740
Lei Zhanga21d5932018-02-05 18:28:38 +00001741 {
1742 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001743 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001744 ASSERT_TRUE(annot);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001745
Lei Zhanga21d5932018-02-05 18:28:38 +00001746 // Set Down AP. Normal AP is already set.
Lei Zhangf0f67682019-04-08 17:03:21 +00001747 ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
Lei Zhanga21d5932018-02-05 18:28:38 +00001748 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
Lei Zhang4f556b82019-04-08 16:32:41 +00001749 ap_text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001750 EXPECT_EQ(73970u,
1751 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1752 nullptr, 0));
1753 EXPECT_EQ(24u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1754 nullptr, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001755
Lei Zhanga21d5932018-02-05 18:28:38 +00001756 // Check that setting the Down AP to null removes the Down entry but keeps
1757 // Normal intact.
1758 EXPECT_TRUE(
1759 FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr));
1760 EXPECT_EQ(73970u,
1761 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1762 nullptr, 0));
1763 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1764 nullptr, 0));
1765 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001766
Lei Zhang75c81712018-02-08 17:22:39 +00001767 UnloadPage(page);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001768}
1769
Lei Zhangab41f252018-12-23 03:10:50 +00001770TEST_F(FPDFAnnotEmbedderTest, RemoveRequiredAP) {
Henrique Nakashima5970a472018-01-11 22:40:59 +00001771 // Open a file with four annotations and load its first page.
1772 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001773 FPDF_PAGE page = LoadPage(0);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001774 ASSERT_TRUE(page);
1775
Lei Zhanga21d5932018-02-05 18:28:38 +00001776 {
1777 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001778 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001779 ASSERT_TRUE(annot);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001780
Lei Zhanga21d5932018-02-05 18:28:38 +00001781 // Set Down AP. Normal AP is already set.
Lei Zhangf0f67682019-04-08 17:03:21 +00001782 ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
Lei Zhanga21d5932018-02-05 18:28:38 +00001783 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
Lei Zhang4f556b82019-04-08 16:32:41 +00001784 ap_text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001785 EXPECT_EQ(73970u,
1786 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1787 nullptr, 0));
1788 EXPECT_EQ(24u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1789 nullptr, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001790
Lei Zhanga21d5932018-02-05 18:28:38 +00001791 // Check that setting the Normal AP to null removes the whole AP dictionary.
1792 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1793 nullptr));
1794 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1795 nullptr, 0));
1796 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1797 nullptr, 0));
1798 }
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001799
Lei Zhang75c81712018-02-08 17:22:39 +00001800 UnloadPage(page);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001801}
1802
Lei Zhangab41f252018-12-23 03:10:50 +00001803TEST_F(FPDFAnnotEmbedderTest, ExtractLinkedAnnotations) {
Jane Liu300bb272017-08-21 14:37:53 -04001804 // Open a file with annotations and load its first page.
1805 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001806 FPDF_PAGE page = LoadPage(0);
Jane Liu300bb272017-08-21 14:37:53 -04001807 ASSERT_TRUE(page);
Jane Liud1ed1ce2017-08-24 12:31:10 -04001808 EXPECT_EQ(-1, FPDFPage_GetAnnotIndex(page, nullptr));
Jane Liu300bb272017-08-21 14:37:53 -04001809
Lei Zhanga21d5932018-02-05 18:28:38 +00001810 {
1811 // Retrieve the highlight annotation which has its popup defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001812 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001813 ASSERT_TRUE(annot);
1814 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
1815 EXPECT_EQ(0, FPDFPage_GetAnnotIndex(page, annot.get()));
Lei Zhang4f556b82019-04-08 16:32:41 +00001816 static const char kPopupKey[] = "Popup";
Lei Zhanga21d5932018-02-05 18:28:38 +00001817 ASSERT_TRUE(FPDFAnnot_HasKey(annot.get(), kPopupKey));
1818 ASSERT_EQ(FPDF_OBJECT_REFERENCE,
1819 FPDFAnnot_GetValueType(annot.get(), kPopupKey));
Jane Liu300bb272017-08-21 14:37:53 -04001820
Lei Zhanga21d5932018-02-05 18:28:38 +00001821 // Retrieve and verify the popup of the highlight annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001822 ScopedFPDFAnnotation popup(
Lei Zhanga21d5932018-02-05 18:28:38 +00001823 FPDFAnnot_GetLinkedAnnot(annot.get(), kPopupKey));
1824 ASSERT_TRUE(popup);
1825 EXPECT_EQ(FPDF_ANNOT_POPUP, FPDFAnnot_GetSubtype(popup.get()));
1826 EXPECT_EQ(1, FPDFPage_GetAnnotIndex(page, popup.get()));
1827 FS_RECTF rect;
1828 ASSERT_TRUE(FPDFAnnot_GetRect(popup.get(), &rect));
1829 EXPECT_NEAR(612.0f, rect.left, 0.001f);
1830 EXPECT_NEAR(578.792, rect.bottom, 0.001f);
Jane Liu300bb272017-08-21 14:37:53 -04001831
Lei Zhanga21d5932018-02-05 18:28:38 +00001832 // Attempting to retrieve |annot|'s "IRT"-linked annotation would fail,
1833 // since "IRT" is not a key in |annot|'s dictionary.
Lei Zhang4f556b82019-04-08 16:32:41 +00001834 static const char kIRTKey[] = "IRT";
Lei Zhanga21d5932018-02-05 18:28:38 +00001835 ASSERT_FALSE(FPDFAnnot_HasKey(annot.get(), kIRTKey));
1836 EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot.get(), kIRTKey));
Jane Liu300bb272017-08-21 14:37:53 -04001837
Lei Zhanga21d5932018-02-05 18:28:38 +00001838 // Attempting to retrieve |annot|'s parent dictionary as an annotation
1839 // would fail, since its parent is not an annotation.
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001840 ASSERT_TRUE(FPDFAnnot_HasKey(annot.get(), pdfium::annotation::kP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001841 EXPECT_EQ(FPDF_OBJECT_REFERENCE,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001842 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kP));
1843 EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot.get(), pdfium::annotation::kP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001844 }
Jane Liu300bb272017-08-21 14:37:53 -04001845
Jane Liu300bb272017-08-21 14:37:53 -04001846 UnloadPage(page);
1847}
1848
Lei Zhangab41f252018-12-23 03:10:50 +00001849TEST_F(FPDFAnnotEmbedderTest, GetFormFieldFlagsTextField) {
Diana Gage7e0c05d2017-07-19 17:33:33 -07001850 // Open file with form text fields.
1851 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001852 FPDF_PAGE page = LoadPage(0);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001853 ASSERT_TRUE(page);
1854
Lei Zhanga21d5932018-02-05 18:28:38 +00001855 {
1856 // Retrieve the first annotation: user-editable text field.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001857 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001858 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001859
Lei Zhanga21d5932018-02-05 18:28:38 +00001860 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001861 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001862 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001863 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1864 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1865 EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_MULTILINE);
Mansi Awasthi0b5da672020-01-23 18:17:18 +00001866 EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
Lei Zhanga21d5932018-02-05 18:28:38 +00001867 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001868
Lei Zhanga21d5932018-02-05 18:28:38 +00001869 {
1870 // Retrieve the second annotation: read-only text field.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001871 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +00001872 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001873
Lei Zhanga21d5932018-02-05 18:28:38 +00001874 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001875 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001876 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001877 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1878 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1879 EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_MULTILINE);
Mansi Awasthi0b5da672020-01-23 18:17:18 +00001880 EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
1881 }
1882
1883 {
1884 // Retrieve the fourth annotation: user-editable password text field.
1885 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
1886 ASSERT_TRUE(annot);
1887
1888 // Check that the flag values are as expected.
1889 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
1890 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001891 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1892 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1893 EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_MULTILINE);
Mansi Awasthi0b5da672020-01-23 18:17:18 +00001894 EXPECT_TRUE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
Lei Zhanga21d5932018-02-05 18:28:38 +00001895 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001896
1897 UnloadPage(page);
1898}
1899
Lei Zhangab41f252018-12-23 03:10:50 +00001900TEST_F(FPDFAnnotEmbedderTest, GetFormFieldFlagsComboBox) {
Diana Gage7e0c05d2017-07-19 17:33:33 -07001901 // Open file with form text fields.
1902 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001903 FPDF_PAGE page = LoadPage(0);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001904 ASSERT_TRUE(page);
1905
Lei Zhanga21d5932018-02-05 18:28:38 +00001906 {
1907 // Retrieve the first annotation: user-editable combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001908 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001909 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001910
Lei Zhanga21d5932018-02-05 18:28:38 +00001911 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001912 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001913 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001914 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1915 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
Lei Zhanga21d5932018-02-05 18:28:38 +00001916 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1917 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001918 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
Lei Zhanga21d5932018-02-05 18:28:38 +00001919 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001920
Lei Zhanga21d5932018-02-05 18:28:38 +00001921 {
1922 // Retrieve the second annotation: regular combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001923 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +00001924 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001925
Lei Zhanga21d5932018-02-05 18:28:38 +00001926 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001927 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001928 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001929 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1930 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
Lei Zhanga21d5932018-02-05 18:28:38 +00001931 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1932 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001933 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
Lei Zhanga21d5932018-02-05 18:28:38 +00001934 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001935
Lei Zhanga21d5932018-02-05 18:28:38 +00001936 {
1937 // Retrieve the third annotation: read-only combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001938 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001939 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001940
Lei Zhanga21d5932018-02-05 18:28:38 +00001941 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001942 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001943 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001944 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1945 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
Lei Zhanga21d5932018-02-05 18:28:38 +00001946 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1947 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
Tom Sepez45c2fd02021-05-12 19:46:13 +00001948 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
Lei Zhanga21d5932018-02-05 18:28:38 +00001949 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001950
1951 UnloadPage(page);
1952}
Diana Gage40870db2017-07-19 18:16:03 -07001953
Lei Zhangab41f252018-12-23 03:10:50 +00001954TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotNull) {
Diana Gage40870db2017-07-19 18:16:03 -07001955 // Open file with form text fields.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001956 ASSERT_TRUE(OpenDocument("text_form.pdf"));
Diana Gage40870db2017-07-19 18:16:03 -07001957 FPDF_PAGE page = LoadPage(0);
1958 ASSERT_TRUE(page);
1959
1960 // Attempt to get an annotation where no annotation exists on page.
Lei Zhang8da98232019-12-11 23:29:33 +00001961 static const FS_POINTF kOriginPoint = {0.0f, 0.0f};
1962 EXPECT_FALSE(
1963 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kOriginPoint));
Lei Zhang7557e7b2018-09-14 17:02:40 +00001964
Lei Zhang8da98232019-12-11 23:29:33 +00001965 static const FS_POINTF kValidPoint = {120.0f, 120.0f};
Lei Zhang7557e7b2018-09-14 17:02:40 +00001966 {
1967 // Verify there is an annotation.
1968 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00001969 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kValidPoint));
Lei Zhang7557e7b2018-09-14 17:02:40 +00001970 EXPECT_TRUE(annot);
1971 }
1972
1973 // Try other bad inputs at a valid location.
Lei Zhang8da98232019-12-11 23:29:33 +00001974 EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, nullptr, &kValidPoint));
1975 EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, page, &kValidPoint));
1976 EXPECT_FALSE(
1977 FPDFAnnot_GetFormFieldAtPoint(form_handle(), nullptr, &kValidPoint));
Diana Gage40870db2017-07-19 18:16:03 -07001978
1979 UnloadPage(page);
1980}
1981
Lei Zhangab41f252018-12-23 03:10:50 +00001982TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotAndCheckFlagsTextField) {
Diana Gage40870db2017-07-19 18:16:03 -07001983 // Open file with form text fields.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001984 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
Diana Gage40870db2017-07-19 18:16:03 -07001985 FPDF_PAGE page = LoadPage(0);
1986 ASSERT_TRUE(page);
1987
Lei Zhanga21d5932018-02-05 18:28:38 +00001988 {
1989 // Retrieve user-editable text field annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00001990 static const FS_POINTF kPoint = {105.0f, 118.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00001991 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00001992 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00001993 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001994
Lei Zhanga21d5932018-02-05 18:28:38 +00001995 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001996 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Tom Sepez45c2fd02021-05-12 19:46:13 +00001997 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1998 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
Lei Zhanga21d5932018-02-05 18:28:38 +00001999 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
2000 }
Diana Gage40870db2017-07-19 18:16:03 -07002001
Lei Zhanga21d5932018-02-05 18:28:38 +00002002 {
2003 // Retrieve read-only text field annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00002004 static const FS_POINTF kPoint = {105.0f, 202.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00002005 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00002006 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00002007 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07002008
Lei Zhanga21d5932018-02-05 18:28:38 +00002009 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00002010 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00002011 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00002012 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2013 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
Lei Zhanga21d5932018-02-05 18:28:38 +00002014 }
Diana Gage40870db2017-07-19 18:16:03 -07002015
2016 UnloadPage(page);
2017}
2018
Lei Zhangab41f252018-12-23 03:10:50 +00002019TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotAndCheckFlagsComboBox) {
Diana Gage40870db2017-07-19 18:16:03 -07002020 // Open file with form comboboxes.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002021 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
Diana Gage40870db2017-07-19 18:16:03 -07002022 FPDF_PAGE page = LoadPage(0);
2023 ASSERT_TRUE(page);
2024
Lei Zhanga21d5932018-02-05 18:28:38 +00002025 {
2026 // Retrieve user-editable combobox annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00002027 static const FS_POINTF kPoint = {102.0f, 363.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00002028 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00002029 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00002030 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07002031
Lei Zhanga21d5932018-02-05 18:28:38 +00002032 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00002033 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00002034 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00002035 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2036 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
Lei Zhanga21d5932018-02-05 18:28:38 +00002037 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
2038 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
Tom Sepez45c2fd02021-05-12 19:46:13 +00002039 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
Lei Zhanga21d5932018-02-05 18:28:38 +00002040 }
Diana Gage40870db2017-07-19 18:16:03 -07002041
Lei Zhanga21d5932018-02-05 18:28:38 +00002042 {
2043 // Retrieve regular combobox annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00002044 static const FS_POINTF kPoint = {102.0f, 413.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00002045 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00002046 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00002047 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07002048
Lei Zhanga21d5932018-02-05 18:28:38 +00002049 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00002050 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00002051 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00002052 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2053 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
Lei Zhanga21d5932018-02-05 18:28:38 +00002054 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
2055 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
Tom Sepez45c2fd02021-05-12 19:46:13 +00002056 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
Lei Zhanga21d5932018-02-05 18:28:38 +00002057 }
Diana Gage40870db2017-07-19 18:16:03 -07002058
Lei Zhanga21d5932018-02-05 18:28:38 +00002059 {
2060 // Retrieve read-only combobox annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00002061 static const FS_POINTF kPoint = {102.0f, 513.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00002062 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00002063 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00002064 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07002065
Lei Zhanga21d5932018-02-05 18:28:38 +00002066 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00002067 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00002068 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
Tom Sepez45c2fd02021-05-12 19:46:13 +00002069 EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2070 EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
Lei Zhanga21d5932018-02-05 18:28:38 +00002071 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
2072 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
Tom Sepez45c2fd02021-05-12 19:46:13 +00002073 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
Lei Zhanga21d5932018-02-05 18:28:38 +00002074 }
Diana Gage40870db2017-07-19 18:16:03 -07002075
2076 UnloadPage(page);
2077}
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002078
Hui Yingst603dcd82020-11-09 22:36:46 +00002079TEST_F(FPDFAnnotEmbedderTest, BUG_1206) {
Lei Zhang03e5e682019-09-16 19:45:55 +00002080#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst603dcd82020-11-09 22:36:46 +00002081 static const char kExpectedBitmap[] = "a1ea1ceebb26922fae576cb79ce63af0";
Lei Zhang03e5e682019-09-16 19:45:55 +00002082#else
Lei Zhang992e7e22019-02-04 19:20:58 +00002083 static const char kExpectedBitmap[] = "0d9fc05c6762fd788bd23fd87a4967bc";
Hui Yingst603dcd82020-11-09 22:36:46 +00002084#endif
Tom Andersond4fe5f72021-12-03 20:52:52 +00002085 static constexpr size_t kExpectedSize = 1590;
Lei Zhang992e7e22019-02-04 19:20:58 +00002086
2087 ASSERT_TRUE(OpenDocument("bug_1206.pdf"));
2088
2089 FPDF_PAGE page = LoadPage(0);
2090 ASSERT_TRUE(page);
2091
2092 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2093 EXPECT_EQ(kExpectedSize, GetString().size());
2094 ClearString();
2095
2096 for (size_t i = 0; i < 10; ++i) {
2097 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
2098 CompareBitmap(bitmap.get(), 612, 792, kExpectedBitmap);
2099
2100 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2101 // TODO(https://crbug.com/pdfium/1206): This is wrong. The size should be
2102 // equal, not bigger.
2103 EXPECT_LT(kExpectedSize, GetString().size());
2104 ClearString();
2105 }
2106
2107 UnloadPage(page);
2108}
2109
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002110TEST_F(FPDFAnnotEmbedderTest, BUG_1212) {
2111 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
2112 FPDF_PAGE page = LoadPage(0);
2113 ASSERT_TRUE(page);
2114 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
2115
2116 static const char kTestKey[] = "test";
Lei Zhang4f556b82019-04-08 16:32:41 +00002117 static const wchar_t kData[] = L"\xf6\xe4";
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002118 static const size_t kBufSize = 12;
2119 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(kBufSize);
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002120
2121 {
2122 // Add a text annotation to the page.
2123 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT));
2124 ASSERT_TRUE(annot);
2125 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
2126 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
2127
2128 // Make sure there is no test key, add set a value there, and read it back.
2129 std::fill(buf.begin(), buf.end(), 'x');
2130 ASSERT_EQ(2u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002131 kBufSize));
2132 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002133
Lei Zhangf0f67682019-04-08 17:03:21 +00002134 ScopedFPDFWideString text = GetFPDFWideString(kData);
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002135 EXPECT_TRUE(FPDFAnnot_SetStringValue(annot.get(), kTestKey, text.get()));
2136
2137 std::fill(buf.begin(), buf.end(), 'x');
2138 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002139 kBufSize));
2140 EXPECT_EQ(kData, GetPlatformWString(buf.data()));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002141 }
2142
Lei Zhang05ec64c2019-01-09 03:00:06 +00002143 {
2144 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
2145 ASSERT_TRUE(annot);
Shikha Walia87ad4172019-11-08 20:55:19 +00002146 const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
Shikha Waliab54d7ad2019-11-06 02:06:33 +00002147 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
Lei Zhang05ec64c2019-01-09 03:00:06 +00002148 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
2149 EXPECT_EQ(FPDF_ANNOT_STAMP, FPDFAnnot_GetSubtype(annot.get()));
2150 // Also do the same test for its appearance string.
2151 std::fill(buf.begin(), buf.end(), 'x');
2152 ASSERT_EQ(2u,
2153 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002154 buf.data(), kBufSize));
2155 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
Lei Zhang05ec64c2019-01-09 03:00:06 +00002156
Lei Zhangf0f67682019-04-08 17:03:21 +00002157 ScopedFPDFWideString text = GetFPDFWideString(kData);
Lei Zhang05ec64c2019-01-09 03:00:06 +00002158 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
2159 text.get()));
2160
2161 std::fill(buf.begin(), buf.end(), 'x');
2162 ASSERT_EQ(6u,
2163 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002164 buf.data(), kBufSize));
2165 EXPECT_EQ(kData, GetPlatformWString(buf.data()));
Lei Zhang05ec64c2019-01-09 03:00:06 +00002166 }
2167
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002168 UnloadPage(page);
2169
2170 {
2171 // Save a copy, open the copy, and check the annotation again.
2172 // Note that it renders the rotation.
2173 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang0b494052019-01-31 21:41:15 +00002174 ASSERT_TRUE(OpenSavedDocument());
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002175 FPDF_PAGE saved_page = LoadSavedPage(0);
2176 ASSERT_TRUE(saved_page);
2177
Lei Zhang05ec64c2019-01-09 03:00:06 +00002178 EXPECT_EQ(2, FPDFPage_GetAnnotCount(saved_page));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002179 {
2180 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(saved_page, 0));
2181 ASSERT_TRUE(annot);
2182 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
2183
2184 std::fill(buf.begin(), buf.end(), 'x');
2185 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002186 kBufSize));
2187 EXPECT_EQ(kData, GetPlatformWString(buf.data()));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002188 }
2189
Lei Zhang05ec64c2019-01-09 03:00:06 +00002190 {
2191 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(saved_page, 0));
2192 ASSERT_TRUE(annot);
2193 // TODO(thestig): This return FPDF_ANNOT_UNKNOWN for some reason.
2194 // EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
2195
2196 std::fill(buf.begin(), buf.end(), 'x');
2197 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002198 kBufSize));
2199 EXPECT_EQ(kData, GetPlatformWString(buf.data()));
Lei Zhang05ec64c2019-01-09 03:00:06 +00002200 }
2201
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00002202 CloseSavedPage(saved_page);
2203 CloseSavedDocument();
2204 }
2205}
rycsmithcb752f32019-02-21 18:40:53 +00002206
2207TEST_F(FPDFAnnotEmbedderTest, GetOptionCountCombobox) {
2208 // Open a file with combobox widget annotations and load its first page.
2209 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2210 FPDF_PAGE page = LoadPage(0);
2211 ASSERT_TRUE(page);
2212
2213 {
2214 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2215 ASSERT_TRUE(annot);
2216
2217 EXPECT_EQ(3, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2218
2219 annot.reset(FPDFPage_GetAnnot(page, 1));
2220 ASSERT_TRUE(annot);
2221
2222 EXPECT_EQ(26, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
Lei Zhange7033c82019-02-26 19:30:49 +00002223
2224 // Check bad form handle / annot.
2225 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(nullptr, nullptr));
2226 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), nullptr));
2227 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(nullptr, annot.get()));
rycsmithcb752f32019-02-21 18:40:53 +00002228 }
2229
2230 UnloadPage(page);
2231}
2232
2233TEST_F(FPDFAnnotEmbedderTest, GetOptionCountListbox) {
2234 // Open a file with listbox widget annotations and load its first page.
2235 ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
2236 FPDF_PAGE page = LoadPage(0);
2237 ASSERT_TRUE(page);
2238
2239 {
2240 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2241 ASSERT_TRUE(annot);
2242
2243 EXPECT_EQ(3, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2244
2245 annot.reset(FPDFPage_GetAnnot(page, 1));
2246 ASSERT_TRUE(annot);
2247
2248 EXPECT_EQ(26, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2249 }
2250
2251 UnloadPage(page);
2252}
2253
2254TEST_F(FPDFAnnotEmbedderTest, GetOptionCountInvalidAnnotations) {
2255 // Open a file with ink annotations and load its first page.
2256 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
2257 FPDF_PAGE page = LoadPage(0);
2258 ASSERT_TRUE(page);
2259
2260 {
2261 // annotations do not have "Opt" array and will return -1
2262 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2263 ASSERT_TRUE(annot);
2264
2265 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2266
2267 annot.reset(FPDFPage_GetAnnot(page, 1));
2268 ASSERT_TRUE(annot);
2269
2270 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2271 }
2272
2273 UnloadPage(page);
2274}
2275
2276TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelCombobox) {
2277 // Open a file with combobox widget annotations and load its first page.
2278 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2279 FPDF_PAGE page = LoadPage(0);
2280 ASSERT_TRUE(page);
2281
2282 {
2283 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2284 ASSERT_TRUE(annot);
2285
2286 int index = 0;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002287 unsigned long length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00002288 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002289 ASSERT_EQ(8u, length_bytes);
2290 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00002291 EXPECT_EQ(8u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002292 buf.data(), length_bytes));
2293 EXPECT_EQ(L"Foo", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00002294
2295 annot.reset(FPDFPage_GetAnnot(page, 1));
2296 ASSERT_TRUE(annot);
2297
2298 index = 0;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002299 length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00002300 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002301 ASSERT_EQ(12u, length_bytes);
2302 buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00002303 EXPECT_EQ(12u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002304 buf.data(), length_bytes));
2305 EXPECT_EQ(L"Apple", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00002306
2307 index = 25;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002308 length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00002309 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002310 buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00002311 EXPECT_EQ(18u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002312 buf.data(), length_bytes));
2313 EXPECT_EQ(L"Zucchini", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00002314
Lei Zhange7033c82019-02-26 19:30:49 +00002315 // Indices out of range
rycsmithcb752f32019-02-21 18:40:53 +00002316 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), -1,
2317 nullptr, 0));
2318 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 26,
2319 nullptr, 0));
Lei Zhange7033c82019-02-26 19:30:49 +00002320
2321 // Check bad form handle / annot.
2322 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(nullptr, nullptr, 0, nullptr, 0));
2323 EXPECT_EQ(0u,
2324 FPDFAnnot_GetOptionLabel(nullptr, annot.get(), 0, nullptr, 0));
2325 EXPECT_EQ(0u,
2326 FPDFAnnot_GetOptionLabel(form_handle(), nullptr, 0, nullptr, 0));
rycsmithcb752f32019-02-21 18:40:53 +00002327 }
2328
2329 UnloadPage(page);
2330}
2331
2332TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelListbox) {
2333 // Open a file with listbox widget annotations and load its first page.
2334 ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
2335 FPDF_PAGE page = LoadPage(0);
2336 ASSERT_TRUE(page);
2337
2338 {
2339 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2340 ASSERT_TRUE(annot);
2341
2342 int index = 0;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002343 unsigned long length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00002344 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002345 ASSERT_EQ(8u, length_bytes);
2346 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00002347 EXPECT_EQ(8u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002348 buf.data(), length_bytes));
2349 EXPECT_EQ(L"Foo", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00002350
2351 annot.reset(FPDFPage_GetAnnot(page, 1));
2352 ASSERT_TRUE(annot);
2353
2354 index = 0;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002355 length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00002356 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002357 ASSERT_EQ(12u, length_bytes);
2358 buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00002359 EXPECT_EQ(12u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002360 buf.data(), length_bytes));
2361 EXPECT_EQ(L"Apple", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00002362
2363 index = 25;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002364 length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00002365 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002366 ASSERT_EQ(18u, length_bytes);
2367 buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00002368 EXPECT_EQ(18u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002369 buf.data(), length_bytes));
2370 EXPECT_EQ(L"Zucchini", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00002371
2372 // indices out of range
2373 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), -1,
2374 nullptr, 0));
2375 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 26,
2376 nullptr, 0));
2377 }
2378
2379 UnloadPage(page);
2380}
2381
2382TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelInvalidAnnotations) {
2383 // Open a file with ink annotations and load its first page.
2384 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
2385 FPDF_PAGE page = LoadPage(0);
2386 ASSERT_TRUE(page);
2387
2388 {
2389 // annotations do not have "Opt" array and will return 0
2390 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2391 ASSERT_TRUE(annot);
2392
2393 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 0,
2394 nullptr, 0));
2395
2396 annot.reset(FPDFPage_GetAnnot(page, 1));
2397 ASSERT_TRUE(annot);
2398
2399 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 0,
2400 nullptr, 0));
2401 }
2402
2403 UnloadPage(page);
2404}
Ryan Smith09c23b12019-04-25 18:09:06 +00002405
Mansi Awasthi2acdf792020-05-12 08:48:04 +00002406TEST_F(FPDFAnnotEmbedderTest, IsOptionSelectedCombobox) {
2407 // Open a file with combobox widget annotations and load its first page.
2408 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2409 FPDF_PAGE page = LoadPage(0);
2410 ASSERT_TRUE(page);
2411
2412 {
2413 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2414 ASSERT_TRUE(annot);
2415
2416 // Checks for Combobox with no Values (/V) or Selected Indices (/I) objects.
2417 int count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2418 ASSERT_EQ(3, count);
2419 for (int i = 0; i < count; i++) {
2420 EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2421 }
2422
2423 annot.reset(FPDFPage_GetAnnot(page, 1));
2424 ASSERT_TRUE(annot);
2425
2426 // Checks for Combobox with Values (/V) object which is just a string.
2427 count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2428 ASSERT_EQ(26, count);
2429 for (int i = 0; i < count; i++) {
2430 EXPECT_EQ(i == 1,
2431 FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2432 }
2433
2434 // Checks for index outside bound i.e. (index >= CountOption()).
2435 EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(),
2436 /*index=*/26));
2437 // Checks for negetive index.
2438 EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(),
2439 /*index=*/-1));
2440
2441 // Checks for bad form handle/annot.
2442 EXPECT_FALSE(FPDFAnnot_IsOptionSelected(nullptr, nullptr, /*index=*/0));
2443 EXPECT_FALSE(
2444 FPDFAnnot_IsOptionSelected(form_handle(), nullptr, /*index=*/0));
2445 EXPECT_FALSE(FPDFAnnot_IsOptionSelected(nullptr, annot.get(), /*index=*/0));
2446 }
2447
2448 UnloadPage(page);
2449}
2450
2451TEST_F(FPDFAnnotEmbedderTest, IsOptionSelectedListbox) {
2452 // Open a file with listbox widget annotations and load its first page.
2453 ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
2454 FPDF_PAGE page = LoadPage(0);
2455 ASSERT_TRUE(page);
2456
2457 {
2458 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2459 ASSERT_TRUE(annot);
2460
2461 // Checks for Listbox with no Values (/V) or Selected Indices (/I) objects.
2462 int count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2463 ASSERT_EQ(3, count);
2464 for (int i = 0; i < count; i++) {
2465 EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2466 }
2467
2468 annot.reset(FPDFPage_GetAnnot(page, 1));
2469 ASSERT_TRUE(annot);
2470
2471 // Checks for Listbox with Values (/V) object which is just a string.
2472 count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2473 ASSERT_EQ(26, count);
2474 for (int i = 0; i < count; i++) {
2475 EXPECT_EQ(i == 1,
2476 FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2477 }
2478
2479 annot.reset(FPDFPage_GetAnnot(page, 3));
2480 ASSERT_TRUE(annot);
2481
2482 // Checks for Listbox with only Selected indices (/I) object which is an
2483 // array with multiple objects.
2484 count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2485 ASSERT_EQ(5, count);
2486 for (int i = 0; i < count; i++) {
2487 bool expected = (i == 1 || i == 3);
2488 EXPECT_EQ(expected,
2489 FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2490 }
2491
2492 annot.reset(FPDFPage_GetAnnot(page, 4));
2493 ASSERT_TRUE(annot);
2494
2495 // Checks for Listbox with Values (/V) object which is an array with
2496 // multiple objects.
2497 count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2498 ASSERT_EQ(5, count);
2499 for (int i = 0; i < count; i++) {
2500 bool expected = (i == 2 || i == 4);
2501 EXPECT_EQ(expected,
2502 FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2503 }
2504
2505 annot.reset(FPDFPage_GetAnnot(page, 5));
2506 ASSERT_TRUE(annot);
2507
2508 // Checks for Listbox with both Values (/V) and Selected Indices (/I)
2509 // objects conflict with different lengths.
2510 count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2511 ASSERT_EQ(5, count);
2512 for (int i = 0; i < count; i++) {
2513 bool expected = (i == 0 || i == 2);
2514 EXPECT_EQ(expected,
2515 FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2516 }
2517 }
2518
2519 UnloadPage(page);
2520}
2521
2522TEST_F(FPDFAnnotEmbedderTest, IsOptionSelectedInvalidAnnotations) {
2523 // Open a file with multiple form field annotations and load its first page.
2524 ASSERT_TRUE(OpenDocument("multiple_form_types.pdf"));
2525 FPDF_PAGE page = LoadPage(0);
2526 ASSERT_TRUE(page);
2527
2528 {
2529 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2530 ASSERT_TRUE(annot);
2531
2532 // Checks for link annotation.
2533 EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(),
2534 /*index=*/0));
2535
2536 annot.reset(FPDFPage_GetAnnot(page, 3));
2537 ASSERT_TRUE(annot);
2538
2539 // Checks for text field annotation.
2540 EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(),
2541 /*index=*/0));
2542 }
2543
2544 UnloadPage(page);
2545}
2546
Ryan Smith09c23b12019-04-25 18:09:06 +00002547TEST_F(FPDFAnnotEmbedderTest, GetFontSizeCombobox) {
2548 // Open a file with combobox annotations and load its first page.
2549 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2550 FPDF_PAGE page = LoadPage(0);
2551 ASSERT_TRUE(page);
2552
2553 {
2554 // All 3 widgets have Tf font size 12.
2555 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2556 ASSERT_TRUE(annot);
2557
2558 float value;
2559 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2560 EXPECT_EQ(12.0, value);
2561
2562 annot.reset(FPDFPage_GetAnnot(page, 1));
2563 ASSERT_TRUE(annot);
2564
2565 float value_two;
2566 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_two));
2567 EXPECT_EQ(12.0, value_two);
2568
2569 annot.reset(FPDFPage_GetAnnot(page, 2));
2570 ASSERT_TRUE(annot);
2571
2572 float value_three;
2573 ASSERT_TRUE(
2574 FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_three));
2575 EXPECT_EQ(12.0, value_three);
2576 }
2577
2578 UnloadPage(page);
2579}
2580
2581TEST_F(FPDFAnnotEmbedderTest, GetFontSizeTextField) {
2582 // Open a file with textfield annotations and load its first page.
2583 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
2584 FPDF_PAGE page = LoadPage(0);
2585 ASSERT_TRUE(page);
2586
2587 {
Mansi Awasthi0b5da672020-01-23 18:17:18 +00002588 // All 4 widgets have Tf font size 12.
Ryan Smith09c23b12019-04-25 18:09:06 +00002589 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2590 ASSERT_TRUE(annot);
2591
2592 float value;
2593 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2594 EXPECT_EQ(12.0, value);
2595
2596 annot.reset(FPDFPage_GetAnnot(page, 1));
2597 ASSERT_TRUE(annot);
2598
2599 float value_two;
2600 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_two));
2601 EXPECT_EQ(12.0, value_two);
2602
2603 annot.reset(FPDFPage_GetAnnot(page, 2));
2604 ASSERT_TRUE(annot);
2605
2606 float value_three;
2607 ASSERT_TRUE(
2608 FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_three));
2609 EXPECT_EQ(12.0, value_three);
Mansi Awasthi0b5da672020-01-23 18:17:18 +00002610
2611 float value_four;
2612 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_four));
2613 EXPECT_EQ(12.0, value_four);
Ryan Smith09c23b12019-04-25 18:09:06 +00002614 }
2615
2616 UnloadPage(page);
2617}
2618
2619TEST_F(FPDFAnnotEmbedderTest, GetFontSizeInvalidAnnotationTypes) {
2620 // Open a file with ink annotations and load its first page.
2621 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
2622 FPDF_PAGE page = LoadPage(0);
2623 ASSERT_TRUE(page);
2624
2625 {
2626 // Annotations that do not have variable text and will return -1.
2627 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2628 ASSERT_TRUE(annot);
2629
2630 float value;
2631 ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2632
2633 annot.reset(FPDFPage_GetAnnot(page, 1));
2634 ASSERT_TRUE(annot);
2635
2636 ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2637 }
2638
2639 UnloadPage(page);
2640}
2641
2642TEST_F(FPDFAnnotEmbedderTest, GetFontSizeInvalidArguments) {
2643 // Open a file with combobox annotations and load its first page.
2644 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2645 FPDF_PAGE page = LoadPage(0);
2646 ASSERT_TRUE(page);
2647
2648 {
2649 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2650 ASSERT_TRUE(annot);
2651
2652 // Check bad form handle / annot.
2653 float value;
2654 ASSERT_FALSE(FPDFAnnot_GetFontSize(nullptr, annot.get(), &value));
2655 ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), nullptr, &value));
2656 ASSERT_FALSE(FPDFAnnot_GetFontSize(nullptr, nullptr, &value));
2657 }
2658
2659 UnloadPage(page);
2660}
2661
2662TEST_F(FPDFAnnotEmbedderTest, GetFontSizeNegative) {
2663 // Open a file with textfield annotations and load its first page.
2664 ASSERT_TRUE(OpenDocument("text_form_negative_fontsize.pdf"));
2665 FPDF_PAGE page = LoadPage(0);
2666 ASSERT_TRUE(page);
2667
2668 {
2669 // Obtain the first annotation, a text field with negative font size, -12.
2670 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2671 ASSERT_TRUE(annot);
2672
2673 float value;
2674 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2675 EXPECT_EQ(-12.0, value);
2676 }
2677
2678 UnloadPage(page);
2679}
Ryan Smith23fdf892019-07-17 21:51:26 +00002680
2681TEST_F(FPDFAnnotEmbedderTest, IsCheckedCheckbox) {
2682 // Open a file with checkbox and radiobuttons widget annotations and load its
2683 // first page.
2684 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2685 FPDF_PAGE page = LoadPage(0);
2686 ASSERT_TRUE(page);
2687
2688 {
2689 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
2690 ASSERT_TRUE(annot);
2691 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2692 }
2693
2694 UnloadPage(page);
2695}
2696
2697TEST_F(FPDFAnnotEmbedderTest, IsCheckedCheckboxReadOnly) {
2698 // Open a file with checkbox and radiobutton widget annotations and load its
2699 // first page.
2700 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2701 FPDF_PAGE page = LoadPage(0);
2702 ASSERT_TRUE(page);
2703
2704 {
2705 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2706 ASSERT_TRUE(annot);
2707 ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2708 }
2709
2710 UnloadPage(page);
2711}
2712
2713TEST_F(FPDFAnnotEmbedderTest, IsCheckedRadioButton) {
2714 // Open a file with checkbox and radiobutton widget annotations and load its
2715 // first page.
2716 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2717 FPDF_PAGE page = LoadPage(0);
2718 ASSERT_TRUE(page);
2719
2720 {
2721 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 5));
2722 ASSERT_TRUE(annot);
2723 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2724
2725 annot.reset(FPDFPage_GetAnnot(page, 6));
2726 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2727
2728 annot.reset(FPDFPage_GetAnnot(page, 7));
2729 ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2730 }
2731
2732 UnloadPage(page);
2733}
2734
2735TEST_F(FPDFAnnotEmbedderTest, IsCheckedRadioButtonReadOnly) {
2736 // Open a file with checkbox and radiobutton widget annotations and load its
2737 // first page.
2738 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2739 FPDF_PAGE page = LoadPage(0);
2740 ASSERT_TRUE(page);
2741
2742 {
2743 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
2744 ASSERT_TRUE(annot);
2745 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2746
2747 annot.reset(FPDFPage_GetAnnot(page, 3));
2748 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2749
2750 annot.reset(FPDFPage_GetAnnot(page, 4));
2751 ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2752 }
2753
2754 UnloadPage(page);
2755}
2756
2757TEST_F(FPDFAnnotEmbedderTest, IsCheckedInvalidArguments) {
2758 // Open a file with checkbox and radiobuttons widget annotations and load its
2759 // first page.
2760 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2761 FPDF_PAGE page = LoadPage(0);
2762 ASSERT_TRUE(page);
2763
2764 {
2765 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2766 ASSERT_TRUE(annot);
2767 ASSERT_FALSE(FPDFAnnot_IsChecked(nullptr, annot.get()));
2768 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), nullptr));
2769 ASSERT_FALSE(FPDFAnnot_IsChecked(nullptr, nullptr));
2770 }
2771
2772 UnloadPage(page);
2773}
2774
2775TEST_F(FPDFAnnotEmbedderTest, IsCheckedInvalidWidgetType) {
2776 // Open a file with text widget annotations and load its first page.
2777 ASSERT_TRUE(OpenDocument("text_form.pdf"));
2778 FPDF_PAGE page = LoadPage(0);
2779 ASSERT_TRUE(page);
2780
2781 {
2782 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2783 ASSERT_TRUE(annot);
2784 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2785 }
2786
2787 UnloadPage(page);
2788}
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002789
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002790TEST_F(FPDFAnnotEmbedderTest, GetFormFieldType) {
2791 ASSERT_TRUE(OpenDocument("multiple_form_types.pdf"));
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002792 FPDF_PAGE page = LoadPage(0);
2793 ASSERT_TRUE(page);
2794
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002795 EXPECT_EQ(-1, FPDFAnnot_GetFormFieldType(form_handle(), nullptr));
2796
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002797 {
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002798 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002799 ASSERT_TRUE(annot);
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002800 EXPECT_EQ(-1, FPDFAnnot_GetFormFieldType(nullptr, annot.get()));
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002801 }
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002802
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002803 constexpr int kExpectedAnnotTypes[] = {-1,
2804 FPDF_FORMFIELD_COMBOBOX,
2805 FPDF_FORMFIELD_LISTBOX,
2806 FPDF_FORMFIELD_TEXTFIELD,
2807 FPDF_FORMFIELD_CHECKBOX,
2808 FPDF_FORMFIELD_RADIOBUTTON};
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002809
Lei Zhang4501a502020-05-18 16:52:59 +00002810 for (size_t i = 0; i < pdfium::size(kExpectedAnnotTypes); ++i) {
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002811 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002812 ASSERT_TRUE(annot);
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002813 EXPECT_EQ(kExpectedAnnotTypes[i],
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002814 FPDFAnnot_GetFormFieldType(form_handle(), annot.get()));
2815 }
2816 UnloadPage(page);
2817}
2818
2819TEST_F(FPDFAnnotEmbedderTest, GetFormFieldValueTextField) {
2820 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
2821 FPDF_PAGE page = LoadPage(0);
2822 ASSERT_TRUE(page);
2823
2824 {
2825 EXPECT_EQ(0u,
2826 FPDFAnnot_GetFormFieldValue(form_handle(), nullptr, nullptr, 0));
2827
2828 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2829 ASSERT_TRUE(annot);
2830
2831 EXPECT_EQ(0u,
2832 FPDFAnnot_GetFormFieldValue(nullptr, annot.get(), nullptr, 0));
2833
2834 unsigned long length_bytes =
2835 FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2836 ASSERT_EQ(2u, length_bytes);
2837 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2838 EXPECT_EQ(2u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2839 buf.data(), length_bytes));
2840 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
2841 }
2842 {
2843 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
2844 ASSERT_TRUE(annot);
2845
2846 unsigned long length_bytes =
2847 FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2848 ASSERT_EQ(18u, length_bytes);
2849 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2850 EXPECT_EQ(18u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2851 buf.data(), length_bytes));
2852 EXPECT_EQ(L"Elephant", GetPlatformWString(buf.data()));
2853 }
2854 UnloadPage(page);
2855}
2856
2857TEST_F(FPDFAnnotEmbedderTest, GetFormFieldValueComboBox) {
2858 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2859 FPDF_PAGE page = LoadPage(0);
2860 ASSERT_TRUE(page);
2861
2862 {
2863 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2864 ASSERT_TRUE(annot);
2865
2866 unsigned long length_bytes =
2867 FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2868 ASSERT_EQ(2u, length_bytes);
2869 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2870 EXPECT_EQ(2u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2871 buf.data(), length_bytes));
2872 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
2873 }
2874 {
2875 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
2876 ASSERT_TRUE(annot);
2877
2878 unsigned long length_bytes =
2879 FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2880 ASSERT_EQ(14u, length_bytes);
2881 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2882 EXPECT_EQ(14u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2883 buf.data(), length_bytes));
2884 EXPECT_EQ(L"Banana", GetPlatformWString(buf.data()));
2885 }
2886 UnloadPage(page);
2887}
2888
2889TEST_F(FPDFAnnotEmbedderTest, GetFormFieldNameTextField) {
2890 ASSERT_TRUE(OpenDocument("text_form.pdf"));
2891 FPDF_PAGE page = LoadPage(0);
2892 ASSERT_TRUE(page);
2893
2894 {
2895 EXPECT_EQ(0u,
2896 FPDFAnnot_GetFormFieldName(form_handle(), nullptr, nullptr, 0));
2897
2898 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2899 ASSERT_TRUE(annot);
2900
2901 EXPECT_EQ(0u, FPDFAnnot_GetFormFieldName(nullptr, annot.get(), nullptr, 0));
2902
2903 unsigned long length_bytes =
2904 FPDFAnnot_GetFormFieldName(form_handle(), annot.get(), nullptr, 0);
2905 ASSERT_EQ(18u, length_bytes);
2906 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2907 EXPECT_EQ(18u, FPDFAnnot_GetFormFieldName(form_handle(), annot.get(),
2908 buf.data(), length_bytes));
2909 EXPECT_EQ(L"Text Box", GetPlatformWString(buf.data()));
2910 }
2911 UnloadPage(page);
2912}
2913
2914TEST_F(FPDFAnnotEmbedderTest, GetFormFieldNameComboBox) {
2915 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2916 FPDF_PAGE page = LoadPage(0);
2917 ASSERT_TRUE(page);
2918
2919 {
2920 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2921 ASSERT_TRUE(annot);
2922
2923 unsigned long length_bytes =
2924 FPDFAnnot_GetFormFieldName(form_handle(), annot.get(), nullptr, 0);
2925 ASSERT_EQ(30u, length_bytes);
2926 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2927 EXPECT_EQ(30u, FPDFAnnot_GetFormFieldName(form_handle(), annot.get(),
2928 buf.data(), length_bytes));
2929 EXPECT_EQ(L"Combo_Editable", GetPlatformWString(buf.data()));
2930 }
2931 UnloadPage(page);
2932}
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002933
Lei Zhang9b444002020-04-17 17:35:23 +00002934TEST_F(FPDFAnnotEmbedderTest, FocusableAnnotSubtypes) {
2935 ASSERT_TRUE(OpenDocument("annots.pdf"));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002936 FPDF_PAGE page = LoadPage(0);
2937 ASSERT_TRUE(page);
2938
Lei Zhang9b444002020-04-17 17:35:23 +00002939 // Verify widgets are by default focusable.
2940 const FPDF_ANNOTATION_SUBTYPE kDefaultSubtypes[] = {FPDF_ANNOT_WIDGET};
2941 VerifyFocusableAnnotSubtypes(form_handle(), kDefaultSubtypes);
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002942
Lei Zhang9b444002020-04-17 17:35:23 +00002943 // Expected annot subtypes for page 0 of annots.pdf.
2944 const FPDF_ANNOTATION_SUBTYPE kExpectedAnnotSubtypes[] = {
2945 FPDF_ANNOT_LINK, FPDF_ANNOT_LINK, FPDF_ANNOT_LINK,
2946 FPDF_ANNOT_LINK, FPDF_ANNOT_HIGHLIGHT, FPDF_ANNOT_HIGHLIGHT,
2947 FPDF_ANNOT_POPUP, FPDF_ANNOT_HIGHLIGHT, FPDF_ANNOT_WIDGET,
2948 };
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002949
Lei Zhang9b444002020-04-17 17:35:23 +00002950 const FPDF_ANNOTATION_SUBTYPE kExpectedDefaultFocusableSubtypes[] = {
Ankit Kumar69cab672020-04-20 19:50:41 +00002951 FPDF_ANNOT_WIDGET};
Lei Zhang9b444002020-04-17 17:35:23 +00002952 VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
2953 kExpectedAnnotSubtypes,
2954 kExpectedDefaultFocusableSubtypes);
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002955
Lei Zhang9b444002020-04-17 17:35:23 +00002956 // Make no annotation type focusable using the preferred method.
2957 ASSERT_TRUE(FPDFAnnot_SetFocusableSubtypes(form_handle(), nullptr, 0));
2958 ASSERT_EQ(0, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002959
Lei Zhang9b444002020-04-17 17:35:23 +00002960 // Restore the focusable type count back to 1, then set it back to 0 using a
2961 // different method.
2962 SetAndVerifyFocusableAnnotSubtypes(form_handle(), kDefaultSubtypes);
2963 ASSERT_TRUE(
2964 FPDFAnnot_SetFocusableSubtypes(form_handle(), kDefaultSubtypes, 0));
2965 ASSERT_EQ(0, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002966
Lei Zhang9b444002020-04-17 17:35:23 +00002967 VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
Ankit Kumar906ac572020-04-21 05:58:04 +00002968 kExpectedAnnotSubtypes, {});
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002969
Lei Zhang9b444002020-04-17 17:35:23 +00002970 // Now make links focusable.
2971 const FPDF_ANNOTATION_SUBTYPE kLinkSubtypes[] = {FPDF_ANNOT_LINK};
2972 SetAndVerifyFocusableAnnotSubtypes(form_handle(), kLinkSubtypes);
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002973
Lei Zhang9b444002020-04-17 17:35:23 +00002974 const FPDF_ANNOTATION_SUBTYPE kExpectedLinkocusableSubtypes[] = {
Ankit Kumar906ac572020-04-21 05:58:04 +00002975 FPDF_ANNOT_LINK};
Lei Zhang9b444002020-04-17 17:35:23 +00002976 VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
2977 kExpectedAnnotSubtypes,
2978 kExpectedLinkocusableSubtypes);
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002979
Lei Zhang9b444002020-04-17 17:35:23 +00002980 // Test invalid parameters.
2981 EXPECT_FALSE(FPDFAnnot_SetFocusableSubtypes(nullptr, kDefaultSubtypes,
Lei Zhang4501a502020-05-18 16:52:59 +00002982 pdfium::size(kDefaultSubtypes)));
Lei Zhang9b444002020-04-17 17:35:23 +00002983 EXPECT_FALSE(FPDFAnnot_SetFocusableSubtypes(form_handle(), nullptr,
Lei Zhang4501a502020-05-18 16:52:59 +00002984 pdfium::size(kDefaultSubtypes)));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002985 EXPECT_EQ(-1, FPDFAnnot_GetFocusableSubtypesCount(nullptr));
2986
Lei Zhang9b444002020-04-17 17:35:23 +00002987 std::vector<FPDF_ANNOTATION_SUBTYPE> subtypes(1);
2988 EXPECT_FALSE(FPDFAnnot_GetFocusableSubtypes(nullptr, subtypes.data(),
2989 subtypes.size()));
2990 EXPECT_FALSE(
2991 FPDFAnnot_GetFocusableSubtypes(form_handle(), nullptr, subtypes.size()));
2992 EXPECT_FALSE(
2993 FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(), 0));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002994
2995 UnloadPage(page);
2996}
Lei Zhang671aece2020-04-14 19:02:26 +00002997
Hui Yingstea3816d2020-07-28 22:35:11 +00002998TEST_F(FPDFAnnotEmbedderTest, FocusableAnnotRendering) {
Lei Zhang671aece2020-04-14 19:02:26 +00002999 ASSERT_TRUE(OpenDocument("annots.pdf"));
3000 FPDF_PAGE page = LoadPage(0);
3001 ASSERT_TRUE(page);
3002
3003 {
Hui Yingstea3816d2020-07-28 22:35:11 +00003004#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003005 static const char kMd5sum[] = "b4c8f1dab175508810c476d078ebc5a6";
Lei Zhang42d30c22022-01-12 19:24:43 +00003006#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003007 static const char kMd5sum[] = "108a46c517c4eaace9982ee83e8e3296";
Lei Zhang671aece2020-04-14 19:02:26 +00003008#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00003009 static const char kMd5sum[] = "5550d8dcb4d1af1f50e8b4bcaef2ee60";
Lei Zhang671aece2020-04-14 19:02:26 +00003010#endif
3011 // Check the initial rendering.
3012 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3013 CompareBitmap(bitmap.get(), 612, 792, kMd5sum);
3014 }
3015
3016 // Make links and highlights focusable.
3017 static constexpr FPDF_ANNOTATION_SUBTYPE kSubTypes[] = {FPDF_ANNOT_LINK,
3018 FPDF_ANNOT_HIGHLIGHT};
Lei Zhang4501a502020-05-18 16:52:59 +00003019 constexpr int kSubTypesCount = pdfium::size(kSubTypes);
Lei Zhang671aece2020-04-14 19:02:26 +00003020 ASSERT_TRUE(
3021 FPDFAnnot_SetFocusableSubtypes(form_handle(), kSubTypes, kSubTypesCount));
3022 ASSERT_EQ(kSubTypesCount, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
3023 std::vector<FPDF_ANNOTATION_SUBTYPE> subtypes(kSubTypesCount);
3024 ASSERT_TRUE(FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(),
3025 subtypes.size()));
3026 ASSERT_EQ(FPDF_ANNOT_LINK, subtypes[0]);
3027 ASSERT_EQ(FPDF_ANNOT_HIGHLIGHT, subtypes[1]);
3028
3029 {
Hui Yingstea3816d2020-07-28 22:35:11 +00003030#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003031 static const char kMd5sum[] = "9173db3a892bc1697eef5cdaed19eda6";
Lei Zhang42d30c22022-01-12 19:24:43 +00003032#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003033 static const char kMd5sum[] = "eb3869335e7a219e1b5f25c1c6037b97";
Lei Zhang671aece2020-04-14 19:02:26 +00003034#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00003035 static const char kMd5sum[] = "805fe7bb751ac4ed2b82bb66efe6db40";
Lei Zhang671aece2020-04-14 19:02:26 +00003036#endif
3037 // Focus the first link and check the rendering.
3038 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3039 ASSERT_TRUE(annot);
3040 EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
3041 EXPECT_TRUE(FORM_SetFocusedAnnot(form_handle(), annot.get()));
3042 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3043 CompareBitmap(bitmap.get(), 612, 792, kMd5sum);
3044 }
3045
3046 {
Hui Yingstea3816d2020-07-28 22:35:11 +00003047#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003048 static const char kMd5sum[] = "174dbdb218c2b14011c9c1db67fe41c3";
Lei Zhang42d30c22022-01-12 19:24:43 +00003049#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003050 static const char kMd5sum[] = "d20b1978da2362d3942ea0fc6d230997";
Lei Zhang671aece2020-04-14 19:02:26 +00003051#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00003052 static const char kMd5sum[] = "c5c5dcb462af3ef5f43b298ec048feef";
Lei Zhang671aece2020-04-14 19:02:26 +00003053#endif
3054 // Focus the first highlight and check the rendering.
3055 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 4));
3056 ASSERT_TRUE(annot);
3057 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
3058 EXPECT_TRUE(FORM_SetFocusedAnnot(form_handle(), annot.get()));
3059 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3060 CompareBitmap(bitmap.get(), 612, 792, kMd5sum);
3061 }
3062
3063 UnloadPage(page);
3064}
Badhri Ravikumarcd628912020-05-07 19:23:51 +00003065
3066TEST_F(FPDFAnnotEmbedderTest, GetLinkFromAnnotation) {
3067 ASSERT_TRUE(OpenDocument("annots.pdf"));
3068 FPDF_PAGE page = LoadPage(0);
3069 ASSERT_TRUE(page);
3070 {
Badhri Ravikumarcd628912020-05-07 19:23:51 +00003071 constexpr char kExpectedResult[] =
3072 "https://cs.chromium.org/chromium/src/third_party/pdfium/public/"
3073 "fpdf_text.h";
Badhri Ravikumarcd628912020-05-07 19:23:51 +00003074
Lei Zhang306874b2021-04-16 00:33:36 +00003075 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
3076 ASSERT_TRUE(annot);
3077 EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
3078 VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()),
3079 kExpectedResult);
Badhri Ravikumarcd628912020-05-07 19:23:51 +00003080 }
3081
3082 {
3083 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 4));
3084 ASSERT_TRUE(annot);
3085 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
3086 EXPECT_FALSE(FPDFAnnot_GetLink(annot.get()));
3087 }
3088
3089 EXPECT_FALSE(FPDFAnnot_GetLink(nullptr));
3090
3091 UnloadPage(page);
3092}
Mansi Awasthi23bba0e2020-05-15 12:18:25 +00003093
3094TEST_F(FPDFAnnotEmbedderTest, GetFormControlCountRadioButton) {
3095 // Open a file with radio button widget annotations and load its first page.
3096 ASSERT_TRUE(OpenDocument("click_form.pdf"));
3097 FPDF_PAGE page = LoadPage(0);
3098 ASSERT_TRUE(page);
3099
3100 {
3101 // Checks for bad annot.
3102 EXPECT_EQ(-1,
3103 FPDFAnnot_GetFormControlCount(form_handle(), /*annot=*/nullptr));
3104
3105 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
3106 ASSERT_TRUE(annot);
3107
3108 // Checks for bad form handle.
3109 EXPECT_EQ(-1,
3110 FPDFAnnot_GetFormControlCount(/*hHandle=*/nullptr, annot.get()));
3111
3112 EXPECT_EQ(3, FPDFAnnot_GetFormControlCount(form_handle(), annot.get()));
3113 }
3114
3115 UnloadPage(page);
3116}
3117
3118TEST_F(FPDFAnnotEmbedderTest, GetFormControlCountCheckBox) {
3119 // Open a file with checkbox widget annotations and load its first page.
3120 ASSERT_TRUE(OpenDocument("click_form.pdf"));
3121 FPDF_PAGE page = LoadPage(0);
3122 ASSERT_TRUE(page);
3123
3124 {
3125 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3126 ASSERT_TRUE(annot);
3127 EXPECT_EQ(1, FPDFAnnot_GetFormControlCount(form_handle(), annot.get()));
3128 }
3129
3130 UnloadPage(page);
3131}
3132
3133TEST_F(FPDFAnnotEmbedderTest, GetFormControlCountInvalidAnnotation) {
3134 // Open a file with ink annotations and load its first page.
3135 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
3136 FPDF_PAGE page = LoadPage(0);
3137 ASSERT_TRUE(page);
3138
3139 {
3140 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3141 ASSERT_TRUE(annot);
3142 EXPECT_EQ(-1, FPDFAnnot_GetFormControlCount(form_handle(), annot.get()));
3143 }
3144
3145 UnloadPage(page);
3146}
3147
3148TEST_F(FPDFAnnotEmbedderTest, GetFormControlIndexRadioButton) {
3149 // Open a file with radio button widget annotations and load its first page.
3150 ASSERT_TRUE(OpenDocument("click_form.pdf"));
3151 FPDF_PAGE page = LoadPage(0);
3152 ASSERT_TRUE(page);
3153
3154 {
3155 // Checks for bad annot.
3156 EXPECT_EQ(-1,
3157 FPDFAnnot_GetFormControlIndex(form_handle(), /*annot=*/nullptr));
3158
3159 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
3160 ASSERT_TRUE(annot);
3161
3162 // Checks for bad form handle.
3163 EXPECT_EQ(-1,
3164 FPDFAnnot_GetFormControlIndex(/*hHandle=*/nullptr, annot.get()));
3165
3166 EXPECT_EQ(1, FPDFAnnot_GetFormControlIndex(form_handle(), annot.get()));
3167 }
3168
3169 UnloadPage(page);
3170}
3171
3172TEST_F(FPDFAnnotEmbedderTest, GetFormControlIndexCheckBox) {
3173 // Open a file with checkbox widget annotations and load its first page.
3174 ASSERT_TRUE(OpenDocument("click_form.pdf"));
3175 FPDF_PAGE page = LoadPage(0);
3176 ASSERT_TRUE(page);
3177
3178 {
3179 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3180 ASSERT_TRUE(annot);
3181 EXPECT_EQ(0, FPDFAnnot_GetFormControlIndex(form_handle(), annot.get()));
3182 }
3183
3184 UnloadPage(page);
3185}
3186
3187TEST_F(FPDFAnnotEmbedderTest, GetFormControlIndexInvalidAnnotation) {
3188 // Open a file with ink annotations and load its first page.
3189 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
3190 FPDF_PAGE page = LoadPage(0);
3191 ASSERT_TRUE(page);
3192
3193 {
3194 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3195 ASSERT_TRUE(annot);
3196 EXPECT_EQ(-1, FPDFAnnot_GetFormControlIndex(form_handle(), annot.get()));
3197 }
3198
3199 UnloadPage(page);
3200}
3201
3202TEST_F(FPDFAnnotEmbedderTest, GetFormFieldExportValueRadioButton) {
3203 // Open a file with radio button widget annotations and load its first page.
3204 ASSERT_TRUE(OpenDocument("click_form.pdf"));
3205 FPDF_PAGE page = LoadPage(0);
3206 ASSERT_TRUE(page);
3207
3208 {
3209 // Checks for bad annot.
3210 EXPECT_EQ(0u, FPDFAnnot_GetFormFieldExportValue(
3211 form_handle(), /*annot=*/nullptr,
3212 /*buffer=*/nullptr, /*buflen=*/0));
3213
3214 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 6));
3215 ASSERT_TRUE(annot);
3216
3217 // Checks for bad form handle.
3218 EXPECT_EQ(0u, FPDFAnnot_GetFormFieldExportValue(
3219 /*hHandle=*/nullptr, annot.get(),
3220 /*buffer=*/nullptr, /*buflen=*/0));
3221
3222 unsigned long length_bytes =
3223 FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3224 /*buffer=*/nullptr, /*buflen=*/0);
3225 ASSERT_EQ(14u, length_bytes);
3226 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
3227 EXPECT_EQ(14u, FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3228 buf.data(), length_bytes));
3229 EXPECT_EQ(L"value2", GetPlatformWString(buf.data()));
3230 }
3231
3232 UnloadPage(page);
3233}
3234
3235TEST_F(FPDFAnnotEmbedderTest, GetFormFieldExportValueCheckBox) {
3236 // Open a file with checkbox widget annotations and load its first page.
3237 ASSERT_TRUE(OpenDocument("click_form.pdf"));
3238 FPDF_PAGE page = LoadPage(0);
3239 ASSERT_TRUE(page);
3240
3241 {
3242 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3243 ASSERT_TRUE(annot);
3244
3245 unsigned long length_bytes =
3246 FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3247 /*buffer=*/nullptr, /*buflen=*/0);
3248 ASSERT_EQ(8u, length_bytes);
3249 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
3250 EXPECT_EQ(8u, FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3251 buf.data(), length_bytes));
3252 EXPECT_EQ(L"Yes", GetPlatformWString(buf.data()));
3253 }
3254
3255 UnloadPage(page);
3256}
3257
3258TEST_F(FPDFAnnotEmbedderTest, GetFormFieldExportValueInvalidAnnotation) {
3259 // Open a file with ink annotations and load its first page.
3260 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
3261 FPDF_PAGE page = LoadPage(0);
3262 ASSERT_TRUE(page);
3263
3264 {
3265 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3266 ASSERT_TRUE(annot);
3267 EXPECT_EQ(0u, FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3268 /*buffer=*/nullptr,
3269 /*buflen=*/0));
3270 }
3271
3272 UnloadPage(page);
3273}
Miklos Vajnad1a24fb2020-10-26 18:07:13 +00003274
3275TEST_F(FPDFAnnotEmbedderTest, Redactannotation) {
3276 ASSERT_TRUE(OpenDocument("redact_annot.pdf"));
3277 FPDF_PAGE page = LoadPage(0);
3278 ASSERT_TRUE(page);
3279 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
3280
3281 {
3282 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3283 ASSERT_TRUE(annot);
3284 EXPECT_EQ(FPDF_ANNOT_REDACT, FPDFAnnot_GetSubtype(annot.get()));
3285 }
3286
3287 UnloadPage(page);
3288}
Miklos Vajna09ecef62020-11-10 21:50:38 +00003289
3290TEST_F(FPDFAnnotEmbedderTest, PolygonAnnotation) {
3291 ASSERT_TRUE(OpenDocument("polygon_annot.pdf"));
3292 FPDF_PAGE page = LoadPage(0);
3293 ASSERT_TRUE(page);
3294 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
3295
3296 {
3297 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3298 ASSERT_TRUE(annot);
3299
Miklos Vajna8f7b1ae2020-11-17 16:53:14 +00003300 // FPDFAnnot_GetVertices() positive testing.
Miklos Vajna09ecef62020-11-10 21:50:38 +00003301 unsigned long size = FPDFAnnot_GetVertices(annot.get(), nullptr, 0);
3302 const size_t kExpectedSize = 3;
3303 ASSERT_EQ(kExpectedSize, size);
3304 std::vector<FS_POINTF> vertices_buffer(size);
3305 EXPECT_EQ(size,
3306 FPDFAnnot_GetVertices(annot.get(), vertices_buffer.data(), size));
3307 EXPECT_FLOAT_EQ(159.0f, vertices_buffer[0].x);
3308 EXPECT_FLOAT_EQ(296.0f, vertices_buffer[0].y);
3309 EXPECT_FLOAT_EQ(350.0f, vertices_buffer[1].x);
3310 EXPECT_FLOAT_EQ(411.0f, vertices_buffer[1].y);
3311 EXPECT_FLOAT_EQ(472.0f, vertices_buffer[2].x);
3312 EXPECT_FLOAT_EQ(243.42f, vertices_buffer[2].y);
3313
3314 // FPDFAnnot_GetVertices() negative testing.
3315 EXPECT_EQ(0U, FPDFAnnot_GetVertices(nullptr, nullptr, 0));
3316
3317 // vertices_buffer is not overwritten if it is too small.
3318 vertices_buffer.resize(1);
3319 vertices_buffer[0].x = 42;
3320 vertices_buffer[0].y = 43;
3321 size = FPDFAnnot_GetVertices(annot.get(), vertices_buffer.data(),
3322 vertices_buffer.size());
3323 EXPECT_EQ(kExpectedSize, size);
3324 EXPECT_FLOAT_EQ(42, vertices_buffer[0].x);
3325 EXPECT_FLOAT_EQ(43, vertices_buffer[0].y);
3326 }
3327
3328 {
3329 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
3330 ASSERT_TRUE(annot);
3331
3332 // This has an odd number of elements in the vertices array, ignore the last
3333 // element.
3334 unsigned long size = FPDFAnnot_GetVertices(annot.get(), nullptr, 0);
3335 const size_t kExpectedSize = 3;
3336 ASSERT_EQ(kExpectedSize, size);
3337 std::vector<FS_POINTF> vertices_buffer(size);
3338 EXPECT_EQ(size,
3339 FPDFAnnot_GetVertices(annot.get(), vertices_buffer.data(), size));
3340 EXPECT_FLOAT_EQ(259.0f, vertices_buffer[0].x);
3341 EXPECT_FLOAT_EQ(396.0f, vertices_buffer[0].y);
3342 EXPECT_FLOAT_EQ(450.0f, vertices_buffer[1].x);
3343 EXPECT_FLOAT_EQ(511.0f, vertices_buffer[1].y);
3344 EXPECT_FLOAT_EQ(572.0f, vertices_buffer[2].x);
3345 EXPECT_FLOAT_EQ(343.0f, vertices_buffer[2].y);
3346 }
3347
3348 {
3349 // Wrong annotation type.
3350 ScopedFPDFAnnotation ink_annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_INK));
3351 EXPECT_EQ(0U, FPDFAnnot_GetVertices(ink_annot.get(), nullptr, 0));
3352 }
3353
3354 UnloadPage(page);
3355}
Miklos Vajna8f7b1ae2020-11-17 16:53:14 +00003356
3357TEST_F(FPDFAnnotEmbedderTest, InkAnnotation) {
3358 ASSERT_TRUE(OpenDocument("ink_annot.pdf"));
3359 FPDF_PAGE page = LoadPage(0);
3360 ASSERT_TRUE(page);
3361 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
3362
3363 {
3364 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3365 ASSERT_TRUE(annot);
3366
3367 // FPDFAnnot_GetInkListCount() and FPDFAnnot_GetInkListPath() positive
3368 // testing.
3369 unsigned long size = FPDFAnnot_GetInkListCount(annot.get());
3370 const size_t kExpectedSize = 1;
3371 ASSERT_EQ(kExpectedSize, size);
3372 const unsigned long kPathIndex = 0;
3373 unsigned long path_size =
3374 FPDFAnnot_GetInkListPath(annot.get(), kPathIndex, nullptr, 0);
3375 const size_t kExpectedPathSize = 3;
3376 ASSERT_EQ(kExpectedPathSize, path_size);
3377 std::vector<FS_POINTF> path_buffer(path_size);
3378 EXPECT_EQ(path_size,
3379 FPDFAnnot_GetInkListPath(annot.get(), kPathIndex,
3380 path_buffer.data(), path_size));
3381 EXPECT_FLOAT_EQ(159.0f, path_buffer[0].x);
3382 EXPECT_FLOAT_EQ(296.0f, path_buffer[0].y);
3383 EXPECT_FLOAT_EQ(350.0f, path_buffer[1].x);
3384 EXPECT_FLOAT_EQ(411.0f, path_buffer[1].y);
3385 EXPECT_FLOAT_EQ(472.0f, path_buffer[2].x);
3386 EXPECT_FLOAT_EQ(243.42f, path_buffer[2].y);
3387
3388 // FPDFAnnot_GetInkListCount() and FPDFAnnot_GetInkListPath() negative
3389 // testing.
3390 EXPECT_EQ(0U, FPDFAnnot_GetInkListCount(nullptr));
3391 EXPECT_EQ(0U, FPDFAnnot_GetInkListPath(nullptr, 0, nullptr, 0));
3392
3393 // out of bounds path_index.
3394 EXPECT_EQ(0U, FPDFAnnot_GetInkListPath(nullptr, 42, nullptr, 0));
3395
3396 // path_buffer is not overwritten if it is too small.
3397 path_buffer.resize(1);
3398 path_buffer[0].x = 42;
3399 path_buffer[0].y = 43;
3400 path_size = FPDFAnnot_GetInkListPath(
3401 annot.get(), kPathIndex, path_buffer.data(), path_buffer.size());
3402 EXPECT_EQ(kExpectedSize, size);
3403 EXPECT_FLOAT_EQ(42, path_buffer[0].x);
3404 EXPECT_FLOAT_EQ(43, path_buffer[0].y);
3405 }
3406
3407 {
3408 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
3409 ASSERT_TRUE(annot);
3410
3411 // This has an odd number of elements in the path array, ignore the last
3412 // element.
3413 unsigned long size = FPDFAnnot_GetInkListCount(annot.get());
3414 const size_t kExpectedSize = 1;
3415 ASSERT_EQ(kExpectedSize, size);
3416 const unsigned long kPathIndex = 0;
3417 unsigned long path_size =
3418 FPDFAnnot_GetInkListPath(annot.get(), kPathIndex, nullptr, 0);
3419 const size_t kExpectedPathSize = 3;
3420 ASSERT_EQ(kExpectedPathSize, path_size);
3421 std::vector<FS_POINTF> path_buffer(path_size);
3422 EXPECT_EQ(path_size,
3423 FPDFAnnot_GetInkListPath(annot.get(), kPathIndex,
3424 path_buffer.data(), path_size));
3425 EXPECT_FLOAT_EQ(259.0f, path_buffer[0].x);
3426 EXPECT_FLOAT_EQ(396.0f, path_buffer[0].y);
3427 EXPECT_FLOAT_EQ(450.0f, path_buffer[1].x);
3428 EXPECT_FLOAT_EQ(511.0f, path_buffer[1].y);
3429 EXPECT_FLOAT_EQ(572.0f, path_buffer[2].x);
3430 EXPECT_FLOAT_EQ(343.0f, path_buffer[2].y);
3431 }
3432
3433 {
3434 // Wrong annotation type.
3435 ScopedFPDFAnnotation polygon_annot(
3436 FPDFPage_CreateAnnot(page, FPDF_ANNOT_POLYGON));
3437 EXPECT_EQ(0U, FPDFAnnot_GetInkListCount(polygon_annot.get()));
3438 const unsigned long kPathIndex = 0;
3439 EXPECT_EQ(0U, FPDFAnnot_GetInkListPath(polygon_annot.get(), kPathIndex,
3440 nullptr, 0));
3441 }
3442
3443 UnloadPage(page);
3444}
Miklos Vajna30f45a62020-12-04 19:12:31 +00003445
3446TEST_F(FPDFAnnotEmbedderTest, LineAnnotation) {
3447 ASSERT_TRUE(OpenDocument("line_annot.pdf"));
3448 FPDF_PAGE page = LoadPage(0);
3449 ASSERT_TRUE(page);
3450 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
3451
3452 {
3453 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3454 ASSERT_TRUE(annot);
3455
3456 // FPDFAnnot_GetVertices() positive testing.
3457 FS_POINTF start;
3458 FS_POINTF end;
3459 ASSERT_TRUE(FPDFAnnot_GetLine(annot.get(), &start, &end));
3460 EXPECT_FLOAT_EQ(159.0f, start.x);
3461 EXPECT_FLOAT_EQ(296.0f, start.y);
3462 EXPECT_FLOAT_EQ(472.0f, end.x);
3463 EXPECT_FLOAT_EQ(243.42f, end.y);
3464
3465 // FPDFAnnot_GetVertices() negative testing.
3466 EXPECT_FALSE(FPDFAnnot_GetLine(nullptr, nullptr, nullptr));
3467 EXPECT_FALSE(FPDFAnnot_GetLine(annot.get(), nullptr, nullptr));
3468 }
3469
3470 {
3471 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
3472 ASSERT_TRUE(annot);
3473
3474 // Too few elements in the line array.
3475 FS_POINTF start;
3476 FS_POINTF end;
3477 EXPECT_FALSE(FPDFAnnot_GetLine(annot.get(), &start, &end));
3478 }
3479
3480 {
3481 // Wrong annotation type.
3482 ScopedFPDFAnnotation ink_annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_INK));
3483 FS_POINTF start;
3484 FS_POINTF end;
3485 EXPECT_FALSE(FPDFAnnot_GetLine(ink_annot.get(), &start, &end));
3486 }
3487
3488 UnloadPage(page);
3489}
Miklos Vajna305d2ed2020-12-15 17:28:49 +00003490
3491TEST_F(FPDFAnnotEmbedderTest, AnnotationBorder) {
3492 ASSERT_TRUE(OpenDocument("line_annot.pdf"));
3493 FPDF_PAGE page = LoadPage(0);
3494 ASSERT_TRUE(page);
3495 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
3496
3497 {
3498 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3499 ASSERT_TRUE(annot);
3500
3501 // FPDFAnnot_GetBorder() positive testing.
3502 float horizontal_radius;
3503 float vertical_radius;
3504 float border_width;
3505 ASSERT_TRUE(FPDFAnnot_GetBorder(annot.get(), &horizontal_radius,
3506 &vertical_radius, &border_width));
3507 EXPECT_FLOAT_EQ(0.25f, horizontal_radius);
3508 EXPECT_FLOAT_EQ(0.5f, vertical_radius);
3509 EXPECT_FLOAT_EQ(2.0f, border_width);
3510
3511 // FPDFAnnot_GetBorder() negative testing.
3512 EXPECT_FALSE(FPDFAnnot_GetBorder(nullptr, nullptr, nullptr, nullptr));
3513 EXPECT_FALSE(FPDFAnnot_GetBorder(annot.get(), nullptr, nullptr, nullptr));
3514 }
3515
3516 {
3517 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
3518 ASSERT_TRUE(annot);
3519
3520 // Too few elements in the border array.
3521 float horizontal_radius;
3522 float vertical_radius;
3523 float border_width;
3524 EXPECT_FALSE(FPDFAnnot_GetBorder(annot.get(), &horizontal_radius,
3525 &vertical_radius, &border_width));
Lei Zhang21ea6652021-04-15 23:24:46 +00003526
3527 // FPDFAnnot_SetBorder() positive testing.
3528 EXPECT_TRUE(FPDFAnnot_SetBorder(annot.get(), /*horizontal_radius=*/2.0f,
3529 /*vertical_radius=*/3.5f,
3530 /*border_width=*/4.0f));
3531
3532 EXPECT_TRUE(FPDFAnnot_GetBorder(annot.get(), &horizontal_radius,
3533 &vertical_radius, &border_width));
3534 EXPECT_FLOAT_EQ(2.0f, horizontal_radius);
3535 EXPECT_FLOAT_EQ(3.5f, vertical_radius);
3536 EXPECT_FLOAT_EQ(4.0f, border_width);
3537
3538 // FPDFAnnot_SetBorder() negative testing.
3539 EXPECT_FALSE(FPDFAnnot_SetBorder(nullptr, /*horizontal_radius=*/1.0f,
3540 /*vertical_radius=*/2.5f,
3541 /*border_width=*/3.0f));
Miklos Vajna305d2ed2020-12-15 17:28:49 +00003542 }
3543
3544 UnloadPage(page);
3545}
Lei Zhang24de1492021-04-19 18:06:43 +00003546
3547// Due to https://crbug.com/pdfium/570, the AnnotationBorder test above cannot
3548// actually render the line annotations inside line_annot.pdf. For now, use a
3549// square annotation in annots.pdf for testing.
3550TEST_F(FPDFAnnotEmbedderTest, AnnotationBorderRendering) {
3551 ASSERT_TRUE(OpenDocument("annots.pdf"));
3552 FPDF_PAGE page = LoadPage(1);
3553 ASSERT_TRUE(page);
3554 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
3555
3556#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003557 constexpr char kOriginalChecksum[] = "4f35703e89202bcc8419ca2df739bb4e";
3558 constexpr char kModifiedChecksum[] = "cee0a1b41f33d487af8fb70c4c82e3c9";
Lei Zhang42d30c22022-01-12 19:24:43 +00003559#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003560 constexpr char kOriginalChecksum[] = "522a4a6b6c7eab5bf95ded1f21ea372e";
3561 constexpr char kModifiedChecksum[] = "6844019e07b83cc01723415f58218d06";
Lei Zhang24de1492021-04-19 18:06:43 +00003562#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00003563 constexpr char kOriginalChecksum[] = "12127303aecd80c6288460f7c0d79f3f";
3564 constexpr char kModifiedChecksum[] = "73d06ff4c665fe85029acef30240dcca";
Lei Zhang24de1492021-04-19 18:06:43 +00003565#endif
3566
3567 {
3568 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
3569 ASSERT_TRUE(annot);
3570 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot.get()));
3571
3572 {
3573 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3574 CompareBitmap(bitmap.get(), 612, 792, kOriginalChecksum);
3575 }
3576
3577 EXPECT_TRUE(FPDFAnnot_SetBorder(annot.get(), /*horizontal_radius=*/2.0f,
3578 /*vertical_radius=*/3.5f,
3579 /*border_width=*/4.0f));
3580
3581 {
3582 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3583 CompareBitmap(bitmap.get(), 612, 792, kModifiedChecksum);
3584 }
3585 }
3586
3587 // Save the document and close the page.
3588 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3589 UnloadPage(page);
3590
3591 ASSERT_TRUE(OpenSavedDocument());
3592 page = LoadSavedPage(1);
3593 ASSERT_TRUE(page);
3594 VerifySavedRendering(page, 612, 792, kModifiedChecksum);
3595
3596 CloseSavedPage(page);
3597 CloseSavedDocument();
3598}