blob: 6eccf74c9172dca45d42e2d5c8e4e58ea6683f67 [file] [log] [blame]
Jane Liu4fd9a472017-06-01 18:56:09 -04001// Copyright 2017 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00005#include <algorithm>
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00006#include <cwchar>
Jane Liu20eafda2017-06-07 10:33:24 -04007#include <memory>
8#include <string>
Jane Liu4fd9a472017-06-01 18:56:09 -04009#include <vector>
10
Lei Zhange4cdac52019-04-30 16:45:57 +000011#include "build/build_config.h"
Lei Zhanga5c1daf2019-01-31 21:56:47 +000012#include "constants/annotation_common.h"
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +000013#include "core/fxcrt/fx_memory.h"
Jane Liubaa7ff42017-06-29 19:18:23 -040014#include "core/fxcrt/fx_system.h"
Tom Sepeze08d2b12018-04-25 18:49:32 +000015#include "public/cpp/fpdf_scopers.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040016#include "public/fpdf_annot.h"
Jane Liubaa7ff42017-06-29 19:18:23 -040017#include "public/fpdf_edit.h"
Mansi Awasthi07bf7e62020-01-24 10:34:17 +000018#include "public/fpdf_formfill.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040019#include "public/fpdfview.h"
20#include "testing/embedder_test.h"
Hui Yingstb4baceb2020-04-28 23:46:10 +000021#include "testing/embedder_test_constants.h"
Lei Zhangb6992dd2019-02-05 23:30:20 +000022#include "testing/fx_string_testhelpers.h"
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +000023#include "testing/gmock/include/gmock/gmock-matchers.h"
Jane Liu4fd9a472017-06-01 18:56:09 -040024#include "testing/gtest/include/gtest/gtest.h"
Lei Zhang5bf8c7f2019-04-08 17:50:11 +000025#include "testing/utils/hash.h"
Lei Zhang9b444002020-04-17 17:35:23 +000026#include "third_party/base/span.h"
Lei Zhangc9b72992020-04-22 01:03:52 +000027#include "third_party/base/stl_util.h"
Lei Zhang9b444002020-04-17 17:35:23 +000028
29namespace {
30
Hui Yingstb4baceb2020-04-28 23:46:10 +000031#if defined(OS_WIN)
32const char kAnnotationStampWithApChecksum[] =
33 "6aa001a77ec05d0f1b0d1d22e28744d4";
34#elif defined(OS_MACOSX)
35const char kAnnotationStampWithApChecksum[] =
36 "80d7b6cc7b13a78d77a6151bc846e80b";
37#else
38const char kAnnotationStampWithApChecksum[] =
39 "b42cef463483e668eaf4055a65e4f1f5";
40#endif
41
Lei Zhang9b444002020-04-17 17:35:23 +000042void VerifyFocusableAnnotSubtypes(
43 FPDF_FORMHANDLE form_handle,
44 pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_subtypes) {
45 ASSERT_EQ(static_cast<int>(expected_subtypes.size()),
46 FPDFAnnot_GetFocusableSubtypesCount(form_handle));
47
48 std::vector<FPDF_ANNOTATION_SUBTYPE> actual_subtypes(
49 expected_subtypes.size());
50 ASSERT_TRUE(FPDFAnnot_GetFocusableSubtypes(
51 form_handle, actual_subtypes.data(), actual_subtypes.size()));
52 for (size_t i = 0; i < expected_subtypes.size(); ++i)
53 ASSERT_EQ(expected_subtypes[i], actual_subtypes[i]);
54}
55
56void SetAndVerifyFocusableAnnotSubtypes(
57 FPDF_FORMHANDLE form_handle,
58 pdfium::span<const FPDF_ANNOTATION_SUBTYPE> subtypes) {
59 ASSERT_TRUE(FPDFAnnot_SetFocusableSubtypes(form_handle, subtypes.data(),
60 subtypes.size()));
61 VerifyFocusableAnnotSubtypes(form_handle, subtypes);
62}
63
64void VerifyAnnotationSubtypesAndFocusability(
65 FPDF_FORMHANDLE form_handle,
66 FPDF_PAGE page,
67 pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_subtypes,
68 pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_focusable_subtypes) {
69 ASSERT_EQ(static_cast<int>(expected_subtypes.size()),
70 FPDFPage_GetAnnotCount(page));
71 for (size_t i = 0; i < expected_subtypes.size(); ++i) {
72 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
73 ASSERT_TRUE(annot);
74 EXPECT_EQ(expected_subtypes[i], FPDFAnnot_GetSubtype(annot.get()));
75
76 bool expected_focusable = pdfium::ContainsValue(expected_focusable_subtypes,
77 expected_subtypes[i]);
78 EXPECT_EQ(expected_focusable,
79 FORM_SetFocusedAnnot(form_handle, annot.get()));
80
81 // Kill the focus so the next test starts in an unfocused state.
82 FORM_ForceToKillFocus(form_handle);
83 }
84}
85
86} // namespace
Jane Liu4fd9a472017-06-01 18:56:09 -040087
Lei Zhangab41f252018-12-23 03:10:50 +000088class FPDFAnnotEmbedderTest : public EmbedderTest {};
Jane Liu4fd9a472017-06-01 18:56:09 -040089
Lei Zhangab41f252018-12-23 03:10:50 +000090TEST_F(FPDFAnnotEmbedderTest, BadParams) {
Lei Zhang7557e7b2018-09-14 17:02:40 +000091 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
92 FPDF_PAGE page = LoadPage(0);
93 ASSERT_TRUE(page);
94
95 EXPECT_EQ(0, FPDFPage_GetAnnotCount(nullptr));
96
97 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, 0));
98 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, -1));
99 EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, 1));
100 EXPECT_FALSE(FPDFPage_GetAnnot(page, -1));
101 EXPECT_FALSE(FPDFPage_GetAnnot(page, 1));
102
103 EXPECT_EQ(FPDF_ANNOT_UNKNOWN, FPDFAnnot_GetSubtype(nullptr));
104
105 EXPECT_EQ(0, FPDFAnnot_GetObjectCount(nullptr));
106
107 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, 0));
108 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, -1));
109 EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, 1));
110
111 EXPECT_FALSE(FPDFAnnot_HasKey(nullptr, "foo"));
112
Lei Zhang4f556b82019-04-08 16:32:41 +0000113 static const wchar_t kContents[] = L"Bar";
Lei Zhangf0f67682019-04-08 17:03:21 +0000114 ScopedFPDFWideString text = GetFPDFWideString(kContents);
Lei Zhang7557e7b2018-09-14 17:02:40 +0000115 EXPECT_FALSE(FPDFAnnot_SetStringValue(nullptr, "foo", text.get()));
116
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000117 FPDF_WCHAR buffer[64];
Lei Zhang7557e7b2018-09-14 17:02:40 +0000118 EXPECT_EQ(0u, FPDFAnnot_GetStringValue(nullptr, "foo", nullptr, 0));
119 EXPECT_EQ(0u, FPDFAnnot_GetStringValue(nullptr, "foo", buffer, 0));
120 EXPECT_EQ(0u,
121 FPDFAnnot_GetStringValue(nullptr, "foo", buffer, sizeof(buffer)));
122
123 UnloadPage(page);
124}
125
Lei Zhang3d9a0972019-03-04 19:34:09 +0000126TEST_F(FPDFAnnotEmbedderTest, BadAnnotsEntry) {
127 ASSERT_TRUE(OpenDocument("bad_annots_entry.pdf"));
128 FPDF_PAGE page = LoadPage(0);
129 ASSERT_TRUE(page);
130
131 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Lei Zhang98dc8c02019-03-04 19:40:30 +0000132 EXPECT_FALSE(FPDFPage_GetAnnot(page, 0));
Lei Zhang3d9a0972019-03-04 19:34:09 +0000133
134 UnloadPage(page);
135}
136
Lei Zhangab41f252018-12-23 03:10:50 +0000137TEST_F(FPDFAnnotEmbedderTest, RenderAnnotWithOnlyRolloverAP) {
Jane Liue17011d2017-06-21 12:18:37 -0400138 // Open a file with one annotation and load its first page.
139 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000140 FPDF_PAGE page = LoadPage(0);
Jane Liue17011d2017-06-21 12:18:37 -0400141 ASSERT_TRUE(page);
142
143 // This annotation has a malformed appearance stream, which does not have its
144 // normal appearance defined, only its rollover appearance. In this case, its
145 // normal appearance should be generated, allowing the highlight annotation to
146 // still display.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000147 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhanga98e3662018-02-07 20:28:35 +0000148 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
Jane Liue17011d2017-06-21 12:18:37 -0400149
150 UnloadPage(page);
151}
152
Lei Zhang03e5e682019-09-16 19:45:55 +0000153// TODO(crbug.com/pdfium/11): Fix this test and enable.
154#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
155#define MAYBE_RenderMultilineMarkupAnnotWithoutAP \
156 DISABLED_RenderMultilineMarkupAnnotWithoutAP
157#else
158#define MAYBE_RenderMultilineMarkupAnnotWithoutAP \
159 RenderMultilineMarkupAnnotWithoutAP
160#endif
161TEST_F(FPDFAnnotEmbedderTest, MAYBE_RenderMultilineMarkupAnnotWithoutAP) {
Lei Zhang4f556b82019-04-08 16:32:41 +0000162 static const char kMd5[] = "76512832d88017668d9acc7aacd13dae";
Henrique Nakashima5098b252018-03-26 21:46:00 +0000163 // Open a file with multiline markup annotations.
Ralf Sipplb3a52402018-03-19 23:30:28 +0000164 ASSERT_TRUE(OpenDocument("annotation_markup_multiline_no_ap.pdf"));
165 FPDF_PAGE page = LoadPage(0);
166 ASSERT_TRUE(page);
167
Tom Sepeze08d2b12018-04-25 18:49:32 +0000168 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000169 CompareBitmap(bitmap.get(), 595, 842, kMd5);
Ralf Sipplb3a52402018-03-19 23:30:28 +0000170
171 UnloadPage(page);
172}
173
Lei Zhangab41f252018-12-23 03:10:50 +0000174TEST_F(FPDFAnnotEmbedderTest, ExtractHighlightLongContent) {
Jane Liu4fd9a472017-06-01 18:56:09 -0400175 // Open a file with one annotation and load its first page.
176 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +0000177 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu4fd9a472017-06-01 18:56:09 -0400178 ASSERT_TRUE(page);
179
180 // Check that there is a total of 1 annotation on its first page.
181 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
182
183 // Check that the annotation is of type "highlight".
Lei Zhanga21d5932018-02-05 18:28:38 +0000184 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000185 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000186 ASSERT_TRUE(annot);
187 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400188
Lei Zhanga21d5932018-02-05 18:28:38 +0000189 // Check that the annotation color is yellow.
190 unsigned int R;
191 unsigned int G;
192 unsigned int B;
193 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000194 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000195 &G, &B, &A));
196 EXPECT_EQ(255u, R);
197 EXPECT_EQ(255u, G);
198 EXPECT_EQ(0u, B);
199 EXPECT_EQ(255u, A);
Jane Liu4fd9a472017-06-01 18:56:09 -0400200
Lei Zhanga21d5932018-02-05 18:28:38 +0000201 // Check that the author is correct.
Lei Zhang4f556b82019-04-08 16:32:41 +0000202 static const char kAuthorKey[] = "T";
Lei Zhanga21d5932018-02-05 18:28:38 +0000203 EXPECT_EQ(FPDF_OBJECT_STRING,
204 FPDFAnnot_GetValueType(annot.get(), kAuthorKey));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000205 unsigned long length_bytes =
Lei Zhanga21d5932018-02-05 18:28:38 +0000206 FPDFAnnot_GetStringValue(annot.get(), kAuthorKey, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000207 ASSERT_EQ(28u, length_bytes);
208 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhanga21d5932018-02-05 18:28:38 +0000209 EXPECT_EQ(28u, FPDFAnnot_GetStringValue(annot.get(), kAuthorKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000210 length_bytes));
211 EXPECT_EQ(L"Jae Hyun Park", GetPlatformWString(buf.data()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400212
Lei Zhanga21d5932018-02-05 18:28:38 +0000213 // Check that the content is correct.
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000214 EXPECT_EQ(
215 FPDF_OBJECT_STRING,
216 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kContents));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000217 length_bytes = FPDFAnnot_GetStringValue(
218 annot.get(), pdfium::annotation::kContents, nullptr, 0);
219 ASSERT_EQ(2690u, length_bytes);
220 buf = GetFPDFWideStringBuffer(length_bytes);
221 EXPECT_EQ(2690u, FPDFAnnot_GetStringValue(annot.get(),
222 pdfium::annotation::kContents,
223 buf.data(), length_bytes));
Lei Zhang4f556b82019-04-08 16:32:41 +0000224 static const wchar_t kContents[] =
Lei Zhanga21d5932018-02-05 18:28:38 +0000225 L"This is a note for that highlight annotation. Very long highlight "
226 "annotation. Long long long Long long longLong long longLong long "
227 "longLong long longLong long longLong long longLong long longLong long "
228 "longLong long longLong long longLong long longLong long longLong long "
229 "longLong long longLong long longLong long longLong long longLong long "
230 "longLong long longLong long longLong long longLong long longLong long "
231 "longLong long longLong long longLong long longLong long longLong long "
232 "longLong long longLong long longLong long longLong long longLong long "
233 "longLong long longLong long longLong long longLong long longLong long "
234 "longLong long longLong long longLong long longLong long longLong long "
235 "longLong long longLong long longLong long longLong long longLong long "
236 "longLong long longLong long longLong long longLong long longLong long "
237 "longLong long longLong long longLong long longLong long longLong long "
238 "longLong long longLong long longLong long longLong long longLong long "
239 "longLong long longLong long longLong long longLong long longLong long "
240 "longLong long longLong long longLong long longLong long longLong long "
241 "longLong long longLong long longLong long longLong long longLong long "
242 "longLong long longLong long longLong long longLong long longLong long "
243 "longLong long longLong long longLong long longLong long longLong long "
244 "longLong long long. END";
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000245 EXPECT_EQ(kContents, GetPlatformWString(buf.data()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400246
Lei Zhanga21d5932018-02-05 18:28:38 +0000247 // Check that the quadpoints are correct.
248 FS_QUADPOINTSF quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000249 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000250 EXPECT_EQ(115.802643f, quadpoints.x1);
251 EXPECT_EQ(718.913940f, quadpoints.y1);
252 EXPECT_EQ(157.211182f, quadpoints.x4);
253 EXPECT_EQ(706.264465f, quadpoints.y4);
254 }
Tom Sepez507d0192018-11-07 16:37:51 +0000255 UnloadPageNoEvents(page);
Jane Liu4fd9a472017-06-01 18:56:09 -0400256}
257
Lei Zhang03e5e682019-09-16 19:45:55 +0000258// TODO(crbug.com/pdfium/11): Fix this test and enable.
259#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
260#define MAYBE_ExtractInkMultiple DISABLED_ExtractInkMultiple
261#else
262#define MAYBE_ExtractInkMultiple ExtractInkMultiple
263#endif
264TEST_F(FPDFAnnotEmbedderTest, MAYBE_ExtractInkMultiple) {
Jane Liu4fd9a472017-06-01 18:56:09 -0400265 // Open a file with three annotations and load its first page.
266 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +0000267 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu4fd9a472017-06-01 18:56:09 -0400268 ASSERT_TRUE(page);
269
270 // Check that there is a total of 3 annotation on its first page.
271 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
272
Lei Zhanga21d5932018-02-05 18:28:38 +0000273 {
274 // Check that the third annotation is of type "ink".
Tom Sepeze08d2b12018-04-25 18:49:32 +0000275 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000276 ASSERT_TRUE(annot);
277 EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu4fd9a472017-06-01 18:56:09 -0400278
Lei Zhanga21d5932018-02-05 18:28:38 +0000279 // Check that the annotation color is blue with opacity.
280 unsigned int R;
281 unsigned int G;
282 unsigned int B;
283 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000284 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000285 &G, &B, &A));
286 EXPECT_EQ(0u, R);
287 EXPECT_EQ(0u, G);
288 EXPECT_EQ(255u, B);
289 EXPECT_EQ(76u, A);
Jane Liu4fd9a472017-06-01 18:56:09 -0400290
Lei Zhanga21d5932018-02-05 18:28:38 +0000291 // Check that there is no content.
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000292 EXPECT_EQ(2u, FPDFAnnot_GetStringValue(
293 annot.get(), pdfium::annotation::kContents, nullptr, 0));
Jane Liu4fd9a472017-06-01 18:56:09 -0400294
Lei Zhang4f556b82019-04-08 16:32:41 +0000295 // Check that the rectangle coordinates are correct.
Lei Zhanga21d5932018-02-05 18:28:38 +0000296 // Note that upon rendering, the rectangle coordinates will be adjusted.
297 FS_RECTF rect;
298 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
299 EXPECT_EQ(351.820404f, rect.left);
300 EXPECT_EQ(583.830688f, rect.bottom);
301 EXPECT_EQ(475.336090f, rect.right);
302 EXPECT_EQ(681.535034f, rect.top);
303 }
Tom Sepezef43c262018-11-07 16:41:32 +0000304 {
305 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
306 CompareBitmap(bitmap.get(), 612, 792, "354002e1c4386d38fdde29ef8d61074a");
307 }
Tom Sepez507d0192018-11-07 16:37:51 +0000308 UnloadPageNoEvents(page);
Jane Liu4fd9a472017-06-01 18:56:09 -0400309}
Jane Liu20eafda2017-06-07 10:33:24 -0400310
Lei Zhangab41f252018-12-23 03:10:50 +0000311TEST_F(FPDFAnnotEmbedderTest, AddIllegalSubtypeAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400312 // Open a file with one annotation and load its first page.
313 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000314 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400315 ASSERT_TRUE(page);
316
317 // Add an annotation with an illegal subtype.
Jane Liud60e9ad2017-06-26 11:28:36 -0400318 ASSERT_FALSE(FPDFPage_CreateAnnot(page, -1));
Jane Liu20eafda2017-06-07 10:33:24 -0400319
320 UnloadPage(page);
321}
322
Lei Zhangab41f252018-12-23 03:10:50 +0000323TEST_F(FPDFAnnotEmbedderTest, AddFirstTextAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400324 // Open a file with no annotation and load its first page.
325 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000326 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400327 ASSERT_TRUE(page);
328 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
329
Lei Zhanga21d5932018-02-05 18:28:38 +0000330 {
331 // Add a text annotation to the page.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000332 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT));
Lei Zhanga21d5932018-02-05 18:28:38 +0000333 ASSERT_TRUE(annot);
Jane Liu20eafda2017-06-07 10:33:24 -0400334
Lei Zhanga21d5932018-02-05 18:28:38 +0000335 // Check that there is now 1 annotations on this page.
336 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Jane Liu20eafda2017-06-07 10:33:24 -0400337
Lei Zhanga21d5932018-02-05 18:28:38 +0000338 // Check that the subtype of the annotation is correct.
339 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
340 }
Jane Liue10509a2017-06-20 16:47:41 -0400341
Lei Zhanga21d5932018-02-05 18:28:38 +0000342 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000343 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000344 ASSERT_TRUE(annot);
345 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu20eafda2017-06-07 10:33:24 -0400346
Lei Zhanga21d5932018-02-05 18:28:38 +0000347 // Set the color of the annotation.
348 ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 51,
349 102, 153, 204));
350 // Check that the color has been set correctly.
351 unsigned int R;
352 unsigned int G;
353 unsigned int B;
354 unsigned int A;
Lei Zhang75c81712018-02-08 17:22:39 +0000355 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000356 &G, &B, &A));
357 EXPECT_EQ(51u, R);
358 EXPECT_EQ(102u, G);
359 EXPECT_EQ(153u, B);
360 EXPECT_EQ(204u, A);
Jane Liu20eafda2017-06-07 10:33:24 -0400361
Lei Zhanga21d5932018-02-05 18:28:38 +0000362 // Change the color of the annotation.
363 ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 204,
364 153, 102, 51));
365 // Check that the color has been set correctly.
Lei Zhang75c81712018-02-08 17:22:39 +0000366 ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
Lei Zhanga21d5932018-02-05 18:28:38 +0000367 &G, &B, &A));
368 EXPECT_EQ(204u, R);
369 EXPECT_EQ(153u, G);
370 EXPECT_EQ(102u, B);
371 EXPECT_EQ(51u, A);
Jane Liu20eafda2017-06-07 10:33:24 -0400372
Lei Zhanga21d5932018-02-05 18:28:38 +0000373 // Set the annotation rectangle.
374 FS_RECTF rect;
375 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
376 EXPECT_EQ(0.f, rect.left);
377 EXPECT_EQ(0.f, rect.right);
378 rect.left = 35;
379 rect.bottom = 150;
380 rect.right = 53;
381 rect.top = 165;
382 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
383 // Check that the annotation rectangle has been set correctly.
384 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
385 EXPECT_EQ(35.f, rect.left);
386 EXPECT_EQ(150.f, rect.bottom);
387 EXPECT_EQ(53.f, rect.right);
388 EXPECT_EQ(165.f, rect.top);
Jane Liu20eafda2017-06-07 10:33:24 -0400389
Lei Zhanga21d5932018-02-05 18:28:38 +0000390 // Set the content of the annotation.
Lei Zhang4f556b82019-04-08 16:32:41 +0000391 static const wchar_t kContents[] = L"Hello! This is a customized content.";
Lei Zhangf0f67682019-04-08 17:03:21 +0000392 ScopedFPDFWideString text = GetFPDFWideString(kContents);
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000393 ASSERT_TRUE(FPDFAnnot_SetStringValue(
394 annot.get(), pdfium::annotation::kContents, text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +0000395 // Check that the content has been set correctly.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000396 unsigned long length_bytes = FPDFAnnot_GetStringValue(
Lei Zhanga5c1daf2019-01-31 21:56:47 +0000397 annot.get(), pdfium::annotation::kContents, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +0000398 ASSERT_EQ(74u, length_bytes);
399 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
400 EXPECT_EQ(74u, FPDFAnnot_GetStringValue(annot.get(),
401 pdfium::annotation::kContents,
402 buf.data(), length_bytes));
403 EXPECT_EQ(kContents, GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +0000404 }
Jane Liu20eafda2017-06-07 10:33:24 -0400405 UnloadPage(page);
406}
407
Lei Zhang03e5e682019-09-16 19:45:55 +0000408// TODO(crbug.com/pdfium/11): Fix this test and enable.
409#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
410#define MAYBE_AddAndSaveUnderlineAnnotation \
411 DISABLED_AddAndSaveUnderlineAnnotation
412#else
413#define MAYBE_AddAndSaveUnderlineAnnotation AddAndSaveUnderlineAnnotation
414#endif
415TEST_F(FPDFAnnotEmbedderTest, MAYBE_AddAndSaveUnderlineAnnotation) {
Jane Liu20eafda2017-06-07 10:33:24 -0400416 // Open a file with one annotation and load its first page.
417 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000418 FPDF_PAGE page = LoadPage(0);
Jane Liu20eafda2017-06-07 10:33:24 -0400419 ASSERT_TRUE(page);
420
421 // Check that there is a total of one annotation on its first page, and verify
422 // its quadpoints.
423 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
Jane Liu0c6b07d2017-08-15 10:50:22 -0400424 FS_QUADPOINTSF quadpoints;
Lei Zhanga21d5932018-02-05 18:28:38 +0000425 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000426 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000427 ASSERT_TRUE(annot);
Ralf Sippl16381792018-04-12 21:20:26 +0000428 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000429 EXPECT_EQ(115.802643f, quadpoints.x1);
430 EXPECT_EQ(718.913940f, quadpoints.y1);
431 EXPECT_EQ(157.211182f, quadpoints.x4);
432 EXPECT_EQ(706.264465f, quadpoints.y4);
433 }
Jane Liu20eafda2017-06-07 10:33:24 -0400434
435 // Add an underline annotation to the page and set its quadpoints.
Lei Zhanga21d5932018-02-05 18:28:38 +0000436 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000437 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +0000438 FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE));
439 ASSERT_TRUE(annot);
440 quadpoints.x1 = 140.802643f;
441 quadpoints.x3 = 140.802643f;
Ralf Sippl16381792018-04-12 21:20:26 +0000442 ASSERT_TRUE(FPDFAnnot_AppendAttachmentPoints(annot.get(), &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000443 }
Jane Liu20eafda2017-06-07 10:33:24 -0400444
445 // Save the document, closing the page and document.
446 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +0000447 UnloadPage(page);
Jane Liu20eafda2017-06-07 10:33:24 -0400448
449 // Open the saved document.
Lei Zhang4f556b82019-04-08 16:32:41 +0000450 static const char kMd5[] = "dba153419f67b7c0c0e3d22d3e8910d5";
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400451
Lei Zhang0b494052019-01-31 21:41:15 +0000452 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000453 page = LoadSavedPage(0);
Lei Zhang4f556b82019-04-08 16:32:41 +0000454 VerifySavedRendering(page, 612, 792, kMd5);
Jane Liu20eafda2017-06-07 10:33:24 -0400455
456 // Check that the saved document has 2 annotations on the first page
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000457 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
Jane Liu20eafda2017-06-07 10:33:24 -0400458
Lei Zhanga21d5932018-02-05 18:28:38 +0000459 {
460 // Check that the second annotation is an underline annotation and verify
461 // its quadpoints.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000462 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +0000463 ASSERT_TRUE(new_annot);
464 EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot.get()));
465 FS_QUADPOINTSF new_quadpoints;
466 ASSERT_TRUE(
Ralf Sippl16381792018-04-12 21:20:26 +0000467 FPDFAnnot_GetAttachmentPoints(new_annot.get(), 0, &new_quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000468 EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f);
469 EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f);
470 EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f);
471 EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f);
472 }
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400473
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000474 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400475 CloseSavedDocument();
Jane Liu20eafda2017-06-07 10:33:24 -0400476}
Jane Liu06462752017-06-27 16:41:14 -0400477
Lei Zhangab41f252018-12-23 03:10:50 +0000478TEST_F(FPDFAnnotEmbedderTest, GetAndSetQuadPoints) {
Ralf Sippl16381792018-04-12 21:20:26 +0000479 // Open a file with four annotations and load its first page.
480 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
481 FPDF_PAGE page = LoadPage(0);
482 ASSERT_TRUE(page);
483 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
484
485 // Retrieve the highlight annotation.
486 FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
487 ASSERT_TRUE(annot);
488 ASSERT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
489
490 FS_QUADPOINTSF quadpoints;
491 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 0, &quadpoints));
492
493 {
494 // Verify the current one set of quadpoints.
495 ASSERT_EQ(1u, FPDFAnnot_CountAttachmentPoints(annot));
496
497 EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
498 EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
499 EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
500 EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
501 }
502
503 {
504 // Update the quadpoints.
505 FS_QUADPOINTSF new_quadpoints = quadpoints;
506 new_quadpoints.y1 -= 20.f;
507 new_quadpoints.y2 -= 20.f;
508 new_quadpoints.y3 -= 20.f;
509 new_quadpoints.y4 -= 20.f;
510 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, 0, &new_quadpoints));
511
512 // Verify added quadpoint set
513 ASSERT_EQ(1u, FPDFAnnot_CountAttachmentPoints(annot));
514 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 0, &quadpoints));
515 EXPECT_NEAR(new_quadpoints.x1, quadpoints.x1, 0.001f);
516 EXPECT_NEAR(new_quadpoints.y1, quadpoints.y1, 0.001f);
517 EXPECT_NEAR(new_quadpoints.x4, quadpoints.x4, 0.001f);
518 EXPECT_NEAR(new_quadpoints.y4, quadpoints.y4, 0.001f);
519 }
520
521 {
522 // Append a new set of quadpoints.
523 FS_QUADPOINTSF new_quadpoints = quadpoints;
524 new_quadpoints.y1 += 20.f;
525 new_quadpoints.y2 += 20.f;
526 new_quadpoints.y3 += 20.f;
527 new_quadpoints.y4 += 20.f;
528 ASSERT_TRUE(FPDFAnnot_AppendAttachmentPoints(annot, &new_quadpoints));
529
530 // Verify added quadpoint set
531 ASSERT_EQ(2u, FPDFAnnot_CountAttachmentPoints(annot));
532 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 1, &quadpoints));
533 EXPECT_NEAR(new_quadpoints.x1, quadpoints.x1, 0.001f);
534 EXPECT_NEAR(new_quadpoints.y1, quadpoints.y1, 0.001f);
535 EXPECT_NEAR(new_quadpoints.x4, quadpoints.x4, 0.001f);
536 EXPECT_NEAR(new_quadpoints.y4, quadpoints.y4, 0.001f);
537 }
538
539 {
540 // Setting and getting quadpoints at out-of-bound index should fail
541 EXPECT_FALSE(FPDFAnnot_SetAttachmentPoints(annot, 300000, &quadpoints));
542 EXPECT_FALSE(FPDFAnnot_GetAttachmentPoints(annot, 300000, &quadpoints));
543 }
544
545 FPDFPage_CloseAnnot(annot);
546
547 // Retrieve the square annotation
548 FPDF_ANNOTATION squareAnnot = FPDFPage_GetAnnot(page, 2);
549
550 {
551 // Check that attempting to set its quadpoints would fail
552 ASSERT_TRUE(squareAnnot);
553 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(squareAnnot));
554 EXPECT_EQ(0u, FPDFAnnot_CountAttachmentPoints(squareAnnot));
555 EXPECT_FALSE(FPDFAnnot_SetAttachmentPoints(squareAnnot, 0, &quadpoints));
556 }
557
558 FPDFPage_CloseAnnot(squareAnnot);
Ralf Sippl16381792018-04-12 21:20:26 +0000559 UnloadPage(page);
560}
561
Lei Zhang03e5e682019-09-16 19:45:55 +0000562// TODO(crbug.com/pdfium/11): Fix this test and enable.
563#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
564#define MAYBE_ModifyRectQuadpointsWithAP DISABLED_ModifyRectQuadpointsWithAP
565#else
566#define MAYBE_ModifyRectQuadpointsWithAP ModifyRectQuadpointsWithAP
567#endif
568TEST_F(FPDFAnnotEmbedderTest, MAYBE_ModifyRectQuadpointsWithAP) {
Lei Zhange4cdac52019-04-30 16:45:57 +0000569#if defined(OS_MACOSX)
Lei Zhang0f6b4342020-02-25 20:00:39 +0000570 static const char kMd5Original[] = "fc59468d154f397fd298c69f47ef565a";
Lei Zhang4f556b82019-04-08 16:32:41 +0000571 static const char kMd5ModifiedHighlight[] =
Lei Zhang0f6b4342020-02-25 20:00:39 +0000572 "e64bf648f6e9354d1f3eedb47a2c9498";
573 static const char kMd5ModifiedSquare[] = "a66591662c8e7ad3c6059952e234bebf";
Lei Zhange67bcc72019-04-30 18:55:58 +0000574#elif defined(OS_WIN)
Lei Zhang4f556b82019-04-08 16:32:41 +0000575 static const char kMd5Original[] = "0e27376094f11490f74c65f3dc3a42c5";
576 static const char kMd5ModifiedHighlight[] =
577 "66f3caef3a7d488a4fa1ad37fc06310e";
578 static const char kMd5ModifiedSquare[] = "a456dad0bc6801ee2d6408a4394af563";
Jane Liub370e5a2017-08-16 13:24:58 -0400579#else
Lei Zhang4f556b82019-04-08 16:32:41 +0000580 static const char kMd5Original[] = "0e27376094f11490f74c65f3dc3a42c5";
581 static const char kMd5ModifiedHighlight[] =
582 "66f3caef3a7d488a4fa1ad37fc06310e";
583 static const char kMd5ModifiedSquare[] = "a456dad0bc6801ee2d6408a4394af563";
Jane Liub370e5a2017-08-16 13:24:58 -0400584#endif
585
Jane Liu06462752017-06-27 16:41:14 -0400586 // Open a file with four annotations and load its first page.
587 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000588 FPDF_PAGE page = LoadPage(0);
Jane Liu06462752017-06-27 16:41:14 -0400589 ASSERT_TRUE(page);
590 EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
591
Jane Liub370e5a2017-08-16 13:24:58 -0400592 // Check that the original file renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000593 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000594 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000595 CompareBitmap(bitmap.get(), 612, 792, kMd5Original);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000596 }
Jane Liub370e5a2017-08-16 13:24:58 -0400597
Jane Liu0c6b07d2017-08-15 10:50:22 -0400598 FS_RECTF rect;
Jane Liu0c6b07d2017-08-15 10:50:22 -0400599 FS_RECTF new_rect;
Lei Zhanga21d5932018-02-05 18:28:38 +0000600
601 // Retrieve the highlight annotation which has its AP stream already defined.
602 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000603 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000604 ASSERT_TRUE(annot);
605 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
606
607 // Check that color cannot be set when an AP stream is defined already.
608 EXPECT_FALSE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 51,
609 102, 153, 204));
610
611 // Verify its attachment points.
612 FS_QUADPOINTSF quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000613 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000614 EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
615 EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
616 EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
617 EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
618
619 // Check that updating the attachment points would succeed.
620 quadpoints.x1 -= 50.f;
621 quadpoints.x2 -= 50.f;
622 quadpoints.x3 -= 50.f;
623 quadpoints.x4 -= 50.f;
Ralf Sippl16381792018-04-12 21:20:26 +0000624 ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot.get(), 0, &quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000625 FS_QUADPOINTSF new_quadpoints;
Ralf Sippl16381792018-04-12 21:20:26 +0000626 ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &new_quadpoints));
Lei Zhanga21d5932018-02-05 18:28:38 +0000627 EXPECT_EQ(quadpoints.x1, new_quadpoints.x1);
628 EXPECT_EQ(quadpoints.y1, new_quadpoints.y1);
629 EXPECT_EQ(quadpoints.x4, new_quadpoints.x4);
630 EXPECT_EQ(quadpoints.y4, new_quadpoints.y4);
631
632 // Check that updating quadpoints does not change the annotation's position.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000633 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000634 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000635 CompareBitmap(bitmap.get(), 612, 792, kMd5Original);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000636 }
Lei Zhanga21d5932018-02-05 18:28:38 +0000637
638 // Verify its annotation rectangle.
639 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
640 EXPECT_NEAR(67.7299f, rect.left, 0.001f);
641 EXPECT_NEAR(704.296f, rect.bottom, 0.001f);
642 EXPECT_NEAR(136.325f, rect.right, 0.001f);
643 EXPECT_NEAR(721.292f, rect.top, 0.001f);
644
645 // Check that updating the rectangle would succeed.
646 rect.left -= 60.f;
647 rect.right -= 60.f;
648 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
649 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
650 EXPECT_EQ(rect.right, new_rect.right);
651 }
Jane Liu06462752017-06-27 16:41:14 -0400652
Jane Liub370e5a2017-08-16 13:24:58 -0400653 // Check that updating the rectangle changes the annotation's position.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000654 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000655 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000656 CompareBitmap(bitmap.get(), 612, 792, kMd5ModifiedHighlight);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000657 }
Jane Liub370e5a2017-08-16 13:24:58 -0400658
Lei Zhanga21d5932018-02-05 18:28:38 +0000659 {
660 // Retrieve the square annotation which has its AP stream already defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000661 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000662 ASSERT_TRUE(annot);
663 EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot.get()));
Jane Liu06462752017-06-27 16:41:14 -0400664
Lei Zhanga21d5932018-02-05 18:28:38 +0000665 // Check that updating the rectangle would succeed.
666 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
667 rect.left += 70.f;
668 rect.right += 70.f;
669 ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
670 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
671 EXPECT_EQ(rect.right, new_rect.right);
Jane Liu06462752017-06-27 16:41:14 -0400672
Lei Zhanga21d5932018-02-05 18:28:38 +0000673 // Check that updating the rectangle changes the square annotation's
674 // position.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000675 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000676 CompareBitmap(bitmap.get(), 612, 792, kMd5ModifiedSquare);
Lei Zhanga21d5932018-02-05 18:28:38 +0000677 }
Jane Liub370e5a2017-08-16 13:24:58 -0400678
Jane Liu06462752017-06-27 16:41:14 -0400679 UnloadPage(page);
680}
Jane Liu8ce58f52017-06-29 13:40:22 -0400681
Lei Zhangab41f252018-12-23 03:10:50 +0000682TEST_F(FPDFAnnotEmbedderTest, CountAttachmentPoints) {
Henrique Nakashima5098b252018-03-26 21:46:00 +0000683 // Open a file with multiline markup annotations.
684 ASSERT_TRUE(OpenDocument("annotation_markup_multiline_no_ap.pdf"));
685 FPDF_PAGE page = LoadPage(0);
686 ASSERT_TRUE(page);
687 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000688 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Henrique Nakashima5098b252018-03-26 21:46:00 +0000689 ASSERT_TRUE(annot);
690
691 // This is a three line annotation.
692 EXPECT_EQ(3u, FPDFAnnot_CountAttachmentPoints(annot.get()));
693 }
694 UnloadPage(page);
695
696 // null annotation should return 0
697 EXPECT_EQ(0u, FPDFAnnot_CountAttachmentPoints(nullptr));
698}
699
Lei Zhangab41f252018-12-23 03:10:50 +0000700TEST_F(FPDFAnnotEmbedderTest, RemoveAnnotation) {
Jane Liu8ce58f52017-06-29 13:40:22 -0400701 // Open a file with 3 annotations on its first page.
702 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
Tom Sepez507d0192018-11-07 16:37:51 +0000703 FPDF_PAGE page = LoadPageNoEvents(0);
Jane Liu8ce58f52017-06-29 13:40:22 -0400704 ASSERT_TRUE(page);
705 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
706
Jane Liu0c6b07d2017-08-15 10:50:22 -0400707 FS_RECTF rect;
Jane Liu8ce58f52017-06-29 13:40:22 -0400708
Lei Zhanga21d5932018-02-05 18:28:38 +0000709 // Check that the annotations have the expected rectangle coordinates.
710 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000711 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000712 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
713 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
714 }
Jane Liu8ce58f52017-06-29 13:40:22 -0400715
Lei Zhanga21d5932018-02-05 18:28:38 +0000716 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000717 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +0000718 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
719 EXPECT_NEAR(149.8127f, rect.left, 0.001f);
720 }
721
722 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000723 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000724 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
725 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
726 }
Jane Liu8ce58f52017-06-29 13:40:22 -0400727
728 // Check that nothing happens when attempting to remove an annotation with an
729 // out-of-bound index.
730 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4));
731 EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1));
732 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
733
734 // Remove the second annotation.
735 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
736 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
737 EXPECT_FALSE(FPDFPage_GetAnnot(page, 2));
738
739 // Save the document, closing the page and document.
740 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Tom Sepez507d0192018-11-07 16:37:51 +0000741 UnloadPageNoEvents(page);
Jane Liu8ce58f52017-06-29 13:40:22 -0400742
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400743 // TODO(npm): VerifySavedRendering changes annot rect dimensions by 1??
Jane Liu8ce58f52017-06-29 13:40:22 -0400744 // Open the saved document.
745 std::string new_file = GetString();
746 FPDF_FILEACCESS file_access;
747 memset(&file_access, 0, sizeof(file_access));
748 file_access.m_FileLen = new_file.size();
749 file_access.m_GetBlock = GetBlockFromString;
750 file_access.m_Param = &new_file;
751 FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
752 ASSERT_TRUE(new_doc);
753 FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
754 ASSERT_TRUE(new_page);
755
756 // Check that the saved document has 2 annotations on the first page.
757 EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
758
Lei Zhanga21d5932018-02-05 18:28:38 +0000759 // Check that the remaining 2 annotations are the original 1st and 3rd ones
760 // by verifying their rectangle coordinates.
761 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000762 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(new_page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000763 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
764 EXPECT_NEAR(86.1971f, rect.left, 0.001f);
765 }
Jane Liu8ce58f52017-06-29 13:40:22 -0400766
Lei Zhanga21d5932018-02-05 18:28:38 +0000767 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000768 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(new_page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +0000769 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
770 EXPECT_NEAR(351.8204f, rect.left, 0.001f);
771 }
Jane Liubaa7ff42017-06-29 19:18:23 -0400772 FPDF_ClosePage(new_page);
773 FPDF_CloseDocument(new_doc);
774}
Jane Liu8ce58f52017-06-29 13:40:22 -0400775
Lei Zhang03e5e682019-09-16 19:45:55 +0000776// TODO(crbug.com/pdfium/11): Fix this test and enable.
777#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
778#define MAYBE_AddAndModifyPath DISABLED_AddAndModifyPath
779#else
780#define MAYBE_AddAndModifyPath AddAndModifyPath
781#endif
782TEST_F(FPDFAnnotEmbedderTest, MAYBE_AddAndModifyPath) {
Lei Zhange4cdac52019-04-30 16:45:57 +0000783#if defined(OS_MACOSX)
Lei Zhang0f6b4342020-02-25 20:00:39 +0000784 static const char kMd5ModifiedPath[] = "8cfae6d547fc5d6702f5f1ac631beb5e";
785 static const char kMd5TwoPaths[] = "9677e4892bb02950d3e4dbe74470578f";
786 static const char kMd5NewAnnot[] = "e8ebddac4db8c0a4b556ddf79aa1a26d";
Lei Zhange67bcc72019-04-30 18:55:58 +0000787#elif defined(OS_WIN)
Lei Zhanga2b70732019-06-25 08:34:22 +0000788 static const char kMd5ModifiedPath[] = "a7a8d675a6ddbcbdfecee65a33ba19e1";
789 static const char kMd5TwoPaths[] = "7c0bdd4552329704c47a7cce47edbbd6";
790 static const char kMd5NewAnnot[] = "3c48d492b4f62941fed0fb62f729f31e";
Jane Liubaa7ff42017-06-29 19:18:23 -0400791#else
Lei Zhanga2b70732019-06-25 08:34:22 +0000792 static const char kMd5ModifiedPath[] = "6ff77d6d1fec4ea571fabe0c7a19b517";
793 static const char kMd5TwoPaths[] = "ca37ad549e74ac5b359a055708f3e7b6";
794 static const char kMd5NewAnnot[] = "0d7a0e33fbf41ff7fa5d732ab2c5edff";
Jane Liubaa7ff42017-06-29 19:18:23 -0400795#endif
796
797 // Open a file with two annotations and load its first page.
798 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000799 FPDF_PAGE page = LoadPage(0);
Jane Liubaa7ff42017-06-29 19:18:23 -0400800 ASSERT_TRUE(page);
801 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
802
803 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000804 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000805 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000806 CompareBitmap(bitmap.get(), 595, 842, kAnnotationStampWithApChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000807 }
Jane Liubaa7ff42017-06-29 19:18:23 -0400808
Lei Zhanga21d5932018-02-05 18:28:38 +0000809 {
810 // Retrieve the stamp annotation which has its AP stream already defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000811 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000812 ASSERT_TRUE(annot);
Jane Liubaa7ff42017-06-29 19:18:23 -0400813
Lei Zhanga21d5932018-02-05 18:28:38 +0000814 // Check that this annotation has one path object and retrieve it.
815 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000816 ASSERT_EQ(32, FPDFPage_CountObjects(page));
Lei Zhanga21d5932018-02-05 18:28:38 +0000817 FPDF_PAGEOBJECT path = FPDFAnnot_GetObject(annot.get(), 1);
818 EXPECT_FALSE(path);
819 path = FPDFAnnot_GetObject(annot.get(), 0);
820 EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
821 EXPECT_TRUE(path);
Jane Liubaa7ff42017-06-29 19:18:23 -0400822
Lei Zhanga21d5932018-02-05 18:28:38 +0000823 // Modify the color of the path object.
Lei Zhang3475b482019-05-13 18:30:57 +0000824 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 0, 0, 0, 255));
Lei Zhanga21d5932018-02-05 18:28:38 +0000825 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), path));
Jane Liubaa7ff42017-06-29 19:18:23 -0400826
Lei Zhanga21d5932018-02-05 18:28:38 +0000827 // Check that the page with the modified annotation renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000828 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000829 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000830 CompareBitmap(bitmap.get(), 595, 842, kMd5ModifiedPath);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000831 }
Jane Liu7a9a38b2017-07-11 13:47:37 -0400832
Lei Zhanga21d5932018-02-05 18:28:38 +0000833 // Add a second path object to the same annotation.
834 FPDF_PAGEOBJECT dot = FPDFPageObj_CreateNewPath(7, 84);
835 EXPECT_TRUE(FPDFPath_BezierTo(dot, 9, 86, 10, 87, 11, 88));
Lei Zhang3475b482019-05-13 18:30:57 +0000836 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(dot, 255, 0, 0, 100));
837 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(dot, 14));
Lei Zhanga21d5932018-02-05 18:28:38 +0000838 EXPECT_TRUE(FPDFPath_SetDrawMode(dot, 0, 1));
839 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), dot));
840 EXPECT_EQ(2, FPDFAnnot_GetObjectCount(annot.get()));
Jane Liu7a9a38b2017-07-11 13:47:37 -0400841
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000842 // The object is in the annontation, not in the page, so the page object
843 // array should not change.
844 ASSERT_EQ(32, FPDFPage_CountObjects(page));
845
Lei Zhanga21d5932018-02-05 18:28:38 +0000846 // Check that the page with an annotation with two paths renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000847 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000848 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000849 CompareBitmap(bitmap.get(), 595, 842, kMd5TwoPaths);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000850 }
Jane Liu7a9a38b2017-07-11 13:47:37 -0400851
Lei Zhanga21d5932018-02-05 18:28:38 +0000852 // Delete the newly added path object.
853 EXPECT_TRUE(FPDFAnnot_RemoveObject(annot.get(), 1));
854 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000855 ASSERT_EQ(32, FPDFPage_CountObjects(page));
Lei Zhanga21d5932018-02-05 18:28:38 +0000856 }
Jane Liu7a9a38b2017-07-11 13:47:37 -0400857
858 // Check that the page renders the same as before.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000859 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000860 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +0000861 CompareBitmap(bitmap.get(), 595, 842, kMd5ModifiedPath);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000862 }
Jane Liubaa7ff42017-06-29 19:18:23 -0400863
Jane Liubaa7ff42017-06-29 19:18:23 -0400864 FS_RECTF rect;
Jane Liubaa7ff42017-06-29 19:18:23 -0400865
Lei Zhanga21d5932018-02-05 18:28:38 +0000866 {
867 // Create another stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000868 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +0000869 ASSERT_TRUE(annot);
870 rect.left = 200.f;
871 rect.bottom = 400.f;
872 rect.right = 500.f;
873 rect.top = 600.f;
874 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
Jane Liubaa7ff42017-06-29 19:18:23 -0400875
Lei Zhanga21d5932018-02-05 18:28:38 +0000876 // Add a new path to the annotation.
877 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500);
878 EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400));
879 EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600));
880 EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550));
881 EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450));
Lei Zhang3475b482019-05-13 18:30:57 +0000882 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(check, 0, 255, 255, 180));
883 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(check, 8.35f));
Lei Zhanga21d5932018-02-05 18:28:38 +0000884 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
885 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), check));
886 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
887
888 // Check that the annotation's bounding box came from its rectangle.
889 FS_RECTF new_rect;
890 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
891 EXPECT_EQ(rect.left, new_rect.left);
892 EXPECT_EQ(rect.bottom, new_rect.bottom);
893 EXPECT_EQ(rect.right, new_rect.right);
894 EXPECT_EQ(rect.top, new_rect.top);
895 }
Jane Liubaa7ff42017-06-29 19:18:23 -0400896
897 // Save the document, closing the page and document.
Jane Liubaa7ff42017-06-29 19:18:23 -0400898 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +0000899 UnloadPage(page);
Jane Liubaa7ff42017-06-29 19:18:23 -0400900
901 // Open the saved document.
Lei Zhang0b494052019-01-31 21:41:15 +0000902 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000903 page = LoadSavedPage(0);
Lei Zhang4f556b82019-04-08 16:32:41 +0000904 VerifySavedRendering(page, 595, 842, kMd5NewAnnot);
Jane Liubaa7ff42017-06-29 19:18:23 -0400905
Jane Liu36567742017-07-06 11:13:35 -0400906 // Check that the document has a correct count of annotations and objects.
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000907 EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
Jane Liubaa7ff42017-06-29 19:18:23 -0400908
Lei Zhanga21d5932018-02-05 18:28:38 +0000909 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000910 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +0000911 ASSERT_TRUE(annot);
912 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
Jane Liubaa7ff42017-06-29 19:18:23 -0400913
Lei Zhanga21d5932018-02-05 18:28:38 +0000914 // Check that the new annotation's rectangle is as defined.
915 FS_RECTF new_rect;
916 ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
917 EXPECT_EQ(rect.left, new_rect.left);
918 EXPECT_EQ(rect.bottom, new_rect.bottom);
919 EXPECT_EQ(rect.right, new_rect.right);
920 EXPECT_EQ(rect.top, new_rect.top);
921 }
922
Henrique Nakashima8baea3c2017-11-10 20:27:23 +0000923 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400924 CloseSavedDocument();
Jane Liu8ce58f52017-06-29 13:40:22 -0400925}
Jane Liub137e752017-07-05 15:04:33 -0400926
Lei Zhangab41f252018-12-23 03:10:50 +0000927TEST_F(FPDFAnnotEmbedderTest, ModifyAnnotationFlags) {
Jane Liub137e752017-07-05 15:04:33 -0400928 // Open a file with an annotation and load its first page.
929 ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +0000930 FPDF_PAGE page = LoadPage(0);
Jane Liub137e752017-07-05 15:04:33 -0400931 ASSERT_TRUE(page);
932
933 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000934 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000935 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000936 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
937 }
Jane Liub137e752017-07-05 15:04:33 -0400938
Lei Zhanga21d5932018-02-05 18:28:38 +0000939 {
940 // Retrieve the annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000941 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +0000942 ASSERT_TRUE(annot);
Jane Liub137e752017-07-05 15:04:33 -0400943
Lei Zhanga21d5932018-02-05 18:28:38 +0000944 // Check that the original flag values are as expected.
945 int flags = FPDFAnnot_GetFlags(annot.get());
946 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
947 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Jane Liub137e752017-07-05 15:04:33 -0400948
Lei Zhanga21d5932018-02-05 18:28:38 +0000949 // Set the HIDDEN flag.
950 flags |= FPDF_ANNOT_FLAG_HIDDEN;
951 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), flags));
952 flags = FPDFAnnot_GetFlags(annot.get());
953 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_HIDDEN);
954 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Jane Liub137e752017-07-05 15:04:33 -0400955
Lei Zhanga21d5932018-02-05 18:28:38 +0000956 // Check that the page renders correctly without rendering the annotation.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000957 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000958 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000959 CompareBitmap(bitmap.get(), 612, 792, pdfium::kBlankPage612By792Checksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000960 }
Jane Liub137e752017-07-05 15:04:33 -0400961
Lei Zhanga21d5932018-02-05 18:28:38 +0000962 // Unset the HIDDEN flag.
963 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), FPDF_ANNOT_FLAG_NONE));
964 EXPECT_FALSE(FPDFAnnot_GetFlags(annot.get()));
965 flags &= ~FPDF_ANNOT_FLAG_HIDDEN;
966 EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), flags));
967 flags = FPDFAnnot_GetFlags(annot.get());
968 EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
969 EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
Jane Liub137e752017-07-05 15:04:33 -0400970
Lei Zhanga21d5932018-02-05 18:28:38 +0000971 // Check that the page renders correctly as before.
Lei Zhangc113c7a2018-02-12 14:58:44 +0000972 {
Tom Sepeze08d2b12018-04-25 18:49:32 +0000973 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhangc113c7a2018-02-12 14:58:44 +0000974 CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
975 }
Lei Zhanga21d5932018-02-05 18:28:38 +0000976 }
Jane Liub137e752017-07-05 15:04:33 -0400977
Jane Liub137e752017-07-05 15:04:33 -0400978 UnloadPage(page);
979}
Jane Liu36567742017-07-06 11:13:35 -0400980
Lei Zhang03e5e682019-09-16 19:45:55 +0000981// TODO(crbug.com/pdfium/11): Fix this test and enable.
982#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
983#define MAYBE_AddAndModifyImage DISABLED_AddAndModifyImage
984#else
985#define MAYBE_AddAndModifyImage AddAndModifyImage
986#endif
987TEST_F(FPDFAnnotEmbedderTest, MAYBE_AddAndModifyImage) {
Lei Zhange4cdac52019-04-30 16:45:57 +0000988#if defined(OS_MACOSX)
Lei Zhang0f6b4342020-02-25 20:00:39 +0000989 static const char kMd5NewImage[] = "dd18709d90c245a12ce0b8c4d092bea9";
990 static const char kMd5ModifiedImage[] = "8d6f478ff8c7e67d49b253f1af587a99";
Lei Zhange67bcc72019-04-30 18:55:58 +0000991#elif defined(OS_WIN)
Lei Zhanga2b70732019-06-25 08:34:22 +0000992 static const char kMd5NewImage[] = "3d77d06a971bcb9fb54db082f1082c8b";
993 static const char kMd5ModifiedImage[] = "dc4f4afc26c345418330d31c065020e1";
Jane Liu36567742017-07-06 11:13:35 -0400994#else
Lei Zhanga2b70732019-06-25 08:34:22 +0000995 static const char kMd5NewImage[] = "528e6243dc29d54f36b61e0d3287d935";
996 static const char kMd5ModifiedImage[] = "6d9e59f3e57a1ff82fb258356b7eb731";
Jane Liu36567742017-07-06 11:13:35 -0400997#endif
998
999 // Open a file with two annotations and load its first page.
1000 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001001 FPDF_PAGE page = LoadPage(0);
Jane Liu36567742017-07-06 11:13:35 -04001002 ASSERT_TRUE(page);
1003 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1004
1005 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001006 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001007 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001008 CompareBitmap(bitmap.get(), 595, 842, kAnnotationStampWithApChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001009 }
Jane Liu36567742017-07-06 11:13:35 -04001010
Jane Liu36567742017-07-06 11:13:35 -04001011 constexpr int kBitmapSize = 200;
Lei Zhanga21d5932018-02-05 18:28:38 +00001012 FPDF_BITMAP image_bitmap;
1013
1014 {
1015 // Create a stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001016 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001017 ASSERT_TRUE(annot);
1018 FS_RECTF rect;
1019 rect.left = 200.f;
1020 rect.bottom = 600.f;
1021 rect.right = 400.f;
1022 rect.top = 800.f;
1023 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
1024
1025 // Add a solid-color translucent image object to the new annotation.
1026 image_bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 1);
1027 FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize,
1028 0xeeeecccc);
1029 EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(image_bitmap));
1030 EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(image_bitmap));
1031 FPDF_PAGEOBJECT image_object = FPDFPageObj_NewImageObj(document());
1032 ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
1033 ASSERT_TRUE(FPDFImageObj_SetMatrix(image_object, kBitmapSize, 0, 0,
1034 kBitmapSize, 0, 0));
1035 FPDFPageObj_Transform(image_object, 1, 0, 0, 1, 200, 600);
1036 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), image_object));
1037 }
Jane Liu36567742017-07-06 11:13:35 -04001038
1039 // Check that the page renders correctly with the new image object.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001040 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001041 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001042 CompareBitmap(bitmap.get(), 595, 842, kMd5NewImage);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001043 }
Jane Liu36567742017-07-06 11:13:35 -04001044
Lei Zhanga21d5932018-02-05 18:28:38 +00001045 {
1046 // Retrieve the newly added stamp annotation and its image object.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001047 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001048 ASSERT_TRUE(annot);
1049 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1050 FPDF_PAGEOBJECT image_object = FPDFAnnot_GetObject(annot.get(), 0);
1051 EXPECT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(image_object));
Jane Liu36567742017-07-06 11:13:35 -04001052
Lei Zhanga21d5932018-02-05 18:28:38 +00001053 // Modify the image in the new annotation.
1054 FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize,
1055 0xff000000);
1056 ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
1057 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), image_object));
1058 }
Jane Liu36567742017-07-06 11:13:35 -04001059
1060 // Save the document, closing the page and document.
1061 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001062 UnloadPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04001063 FPDFBitmap_Destroy(image_bitmap);
Jane Liu36567742017-07-06 11:13:35 -04001064
1065 // Test that the saved document renders the modified image object correctly.
Lei Zhang4f556b82019-04-08 16:32:41 +00001066 VerifySavedDocument(595, 842, kMd5ModifiedImage);
Jane Liu36567742017-07-06 11:13:35 -04001067}
1068
Lei Zhang03e5e682019-09-16 19:45:55 +00001069// TODO(crbug.com/pdfium/11): Fix this test and enable.
1070#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1071#define MAYBE_AddAndModifyText DISABLED_AddAndModifyText
1072#else
1073#define MAYBE_AddAndModifyText AddAndModifyText
1074#endif
1075TEST_F(FPDFAnnotEmbedderTest, MAYBE_AddAndModifyText) {
Lei Zhange4cdac52019-04-30 16:45:57 +00001076#if defined(OS_MACOSX)
Lei Zhang0f6b4342020-02-25 20:00:39 +00001077 static const char kMd5NewText[] = "e657266260b88c964938efe6c9b292da";
1078 static const char kMd5ModifiedText[] = "7accdf2bac64463101783221f53d3188";
Lei Zhange67bcc72019-04-30 18:55:58 +00001079#elif defined(OS_WIN)
Lei Zhanga2b70732019-06-25 08:34:22 +00001080 static const char kMd5NewText[] = "204cc01749a70b8afc246a4ca33c7eb6";
1081 static const char kMd5ModifiedText[] = "641261a45e8dfd68c89b80bfd237660d";
Jane Liu36567742017-07-06 11:13:35 -04001082#else
Lei Zhanga2b70732019-06-25 08:34:22 +00001083 static const char kMd5NewText[] = "00197ad6206f763febad5719e5935306";
1084 static const char kMd5ModifiedText[] = "85853bc0aaa5a4e3af04e58b9cbfff23";
Jane Liu36567742017-07-06 11:13:35 -04001085#endif
1086
1087 // Open a file with two annotations and load its first page.
1088 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001089 FPDF_PAGE page = LoadPage(0);
Jane Liu36567742017-07-06 11:13:35 -04001090 ASSERT_TRUE(page);
1091 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1092
1093 // Check that the page renders correctly.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001094 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001095 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001096 CompareBitmap(bitmap.get(), 595, 842, kAnnotationStampWithApChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001097 }
Jane Liu36567742017-07-06 11:13:35 -04001098
Lei Zhanga21d5932018-02-05 18:28:38 +00001099 {
1100 // Create a stamp annotation and set its annotation rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001101 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001102 ASSERT_TRUE(annot);
1103 FS_RECTF rect;
1104 rect.left = 200.f;
1105 rect.bottom = 550.f;
1106 rect.right = 450.f;
1107 rect.top = 650.f;
1108 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
Jane Liu36567742017-07-06 11:13:35 -04001109
Lei Zhanga21d5932018-02-05 18:28:38 +00001110 // Add a translucent text object to the new annotation.
1111 FPDF_PAGEOBJECT text_object =
1112 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
1113 EXPECT_TRUE(text_object);
Lei Zhangf0f67682019-04-08 17:03:21 +00001114 ScopedFPDFWideString text =
Lei Zhanga21d5932018-02-05 18:28:38 +00001115 GetFPDFWideString(L"I'm a translucent text laying on other text.");
1116 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
Lei Zhang3475b482019-05-13 18:30:57 +00001117 EXPECT_TRUE(FPDFPageObj_SetFillColor(text_object, 0, 0, 255, 150));
Lei Zhanga21d5932018-02-05 18:28:38 +00001118 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 600);
1119 EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), text_object));
1120 }
Jane Liu36567742017-07-06 11:13:35 -04001121
1122 // Check that the page renders correctly with the new text object.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001123 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001124 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001125 CompareBitmap(bitmap.get(), 595, 842, kMd5NewText);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001126 }
Jane Liu36567742017-07-06 11:13:35 -04001127
Lei Zhanga21d5932018-02-05 18:28:38 +00001128 {
1129 // Retrieve the newly added stamp annotation and its text object.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001130 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001131 ASSERT_TRUE(annot);
1132 EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1133 FPDF_PAGEOBJECT text_object = FPDFAnnot_GetObject(annot.get(), 0);
1134 EXPECT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_object));
Jane Liu36567742017-07-06 11:13:35 -04001135
Lei Zhanga21d5932018-02-05 18:28:38 +00001136 // Modify the text in the new annotation.
Lei Zhangf0f67682019-04-08 17:03:21 +00001137 ScopedFPDFWideString new_text = GetFPDFWideString(L"New text!");
Lei Zhanga21d5932018-02-05 18:28:38 +00001138 EXPECT_TRUE(FPDFText_SetText(text_object, new_text.get()));
1139 EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), text_object));
1140 }
Jane Liu36567742017-07-06 11:13:35 -04001141
1142 // Check that the page renders correctly with the modified text object.
Lei Zhangc113c7a2018-02-12 14:58:44 +00001143 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001144 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Lei Zhang4f556b82019-04-08 16:32:41 +00001145 CompareBitmap(bitmap.get(), 595, 842, kMd5ModifiedText);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001146 }
Jane Liu36567742017-07-06 11:13:35 -04001147
1148 // Remove the new annotation, and check that the page renders as before.
1149 EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 2));
Lei Zhangc113c7a2018-02-12 14:58:44 +00001150 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001151 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001152 CompareBitmap(bitmap.get(), 595, 842, kAnnotationStampWithApChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00001153 }
Jane Liu36567742017-07-06 11:13:35 -04001154
1155 UnloadPage(page);
1156}
Jane Liu2e1a32b2017-07-06 12:01:25 -04001157
Lei Zhang03e5e682019-09-16 19:45:55 +00001158// TODO(crbug.com/pdfium/11): Fix this test and enable.
1159#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1160#define MAYBE_GetSetStringValue DISABLED_GetSetStringValue
1161#else
1162#define MAYBE_GetSetStringValue GetSetStringValue
1163#endif
1164TEST_F(FPDFAnnotEmbedderTest, MAYBE_GetSetStringValue) {
Jane Liu2e1a32b2017-07-06 12:01:25 -04001165 // Open a file with four annotations and load its first page.
1166 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001167 FPDF_PAGE page = LoadPage(0);
Jane Liu2e1a32b2017-07-06 12:01:25 -04001168 ASSERT_TRUE(page);
1169
Lei Zhang4f556b82019-04-08 16:32:41 +00001170 static const wchar_t kNewDate[] = L"D:201706282359Z00'00'";
Jane Liu2e1a32b2017-07-06 12:01:25 -04001171
Lei Zhanga21d5932018-02-05 18:28:38 +00001172 {
1173 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001174 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001175 ASSERT_TRUE(annot);
1176
1177 // Check that a non-existent key does not exist.
1178 EXPECT_FALSE(FPDFAnnot_HasKey(annot.get(), "none"));
1179
1180 // Check that the string value of a non-string dictionary entry is empty.
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001181 EXPECT_TRUE(FPDFAnnot_HasKey(annot.get(), pdfium::annotation::kAP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001182 EXPECT_EQ(FPDF_OBJECT_REFERENCE,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001183 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kAP));
1184 EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kAP,
1185 nullptr, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001186
1187 // Check that the string value of the hash is correct.
Lei Zhang4f556b82019-04-08 16:32:41 +00001188 static const char kHashKey[] = "AAPL:Hash";
Lei Zhanga21d5932018-02-05 18:28:38 +00001189 EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot.get(), kHashKey));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001190 unsigned long length_bytes =
Lei Zhanga21d5932018-02-05 18:28:38 +00001191 FPDFAnnot_GetStringValue(annot.get(), kHashKey, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001192 ASSERT_EQ(66u, length_bytes);
1193 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
1194 EXPECT_EQ(66u, FPDFAnnot_GetStringValue(annot.get(), kHashKey, buf.data(),
1195 length_bytes));
1196 EXPECT_EQ(L"395fbcb98d558681742f30683a62a2ad",
1197 GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001198
1199 // Check that the string value of the modified date is correct.
1200 EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot.get(), kHashKey));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001201 length_bytes = FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kM,
1202 nullptr, 0);
1203 ASSERT_EQ(44u, length_bytes);
1204 buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001205 EXPECT_EQ(44u, FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kM,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001206 buf.data(), length_bytes));
1207 EXPECT_EQ(L"D:201706071721Z00'00'", GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001208
1209 // Update the date entry for the annotation.
Lei Zhangf0f67682019-04-08 17:03:21 +00001210 ScopedFPDFWideString text = GetFPDFWideString(kNewDate);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001211 EXPECT_TRUE(FPDFAnnot_SetStringValue(annot.get(), pdfium::annotation::kM,
1212 text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001213 }
Jane Liu2e1a32b2017-07-06 12:01:25 -04001214
1215 // Save the document, closing the page and document.
Jane Liu2e1a32b2017-07-06 12:01:25 -04001216 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001217 UnloadPage(page);
Jane Liu2e1a32b2017-07-06 12:01:25 -04001218
Lei Zhange4cdac52019-04-30 16:45:57 +00001219#if defined(OS_MACOSX)
Lei Zhang0f6b4342020-02-25 20:00:39 +00001220 static const char kMd5[] = "5e7e185b386ad21ca83b0287268c50fb";
Lei Zhange67bcc72019-04-30 18:55:58 +00001221#elif defined(OS_WIN)
Lei Zhanga2b70732019-06-25 08:34:22 +00001222 static const char kMd5[] = "20b612ebd46babcb44c48c903e2c5a48";
Jane Liu2e1a32b2017-07-06 12:01:25 -04001223#else
Lei Zhanga2b70732019-06-25 08:34:22 +00001224 static const char kMd5[] = "1d7bea2042c6fea0558ff2aef05811b5";
Jane Liu2e1a32b2017-07-06 12:01:25 -04001225#endif
Dan Sinclair971a6742018-03-28 19:23:25 +00001226
1227 // Open the saved annotation.
Lei Zhang0b494052019-01-31 21:41:15 +00001228 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001229 page = LoadSavedPage(0);
Lei Zhang4f556b82019-04-08 16:32:41 +00001230 VerifySavedRendering(page, 595, 842, kMd5);
Lei Zhanga21d5932018-02-05 18:28:38 +00001231 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001232 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 0));
Jane Liu2e1a32b2017-07-06 12:01:25 -04001233
Lei Zhanga21d5932018-02-05 18:28:38 +00001234 // Check that the string value of the modified date is the newly-set value.
1235 EXPECT_EQ(FPDF_OBJECT_STRING,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001236 FPDFAnnot_GetValueType(new_annot.get(), pdfium::annotation::kM));
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001237 unsigned long length_bytes = FPDFAnnot_GetStringValue(
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001238 new_annot.get(), pdfium::annotation::kM, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001239 ASSERT_EQ(44u, length_bytes);
1240 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001241 EXPECT_EQ(44u,
1242 FPDFAnnot_GetStringValue(new_annot.get(), pdfium::annotation::kM,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001243 buf.data(), length_bytes));
1244 EXPECT_EQ(kNewDate, GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001245 }
Jane Liu2e1a32b2017-07-06 12:01:25 -04001246
Henrique Nakashima8baea3c2017-11-10 20:27:23 +00001247 CloseSavedPage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04001248 CloseSavedDocument();
Jane Liu2e1a32b2017-07-06 12:01:25 -04001249}
Diana Gage7e0c05d2017-07-19 17:33:33 -07001250
rycsmith3e785602019-03-05 21:48:36 +00001251TEST_F(FPDFAnnotEmbedderTest, GetNumberValue) {
Mansi Awasthi0b5da672020-01-23 18:17:18 +00001252 // Open a file with four text annotations and load its first page.
rycsmith3e785602019-03-05 21:48:36 +00001253 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
1254 FPDF_PAGE page = LoadPage(0);
1255 ASSERT_TRUE(page);
1256 {
1257 // First two annotations do not have "MaxLen" attribute.
1258 for (int i = 0; i < 2; i++) {
1259 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
1260 ASSERT_TRUE(annot);
1261
1262 // Verify that no "MaxLen" key present.
1263 EXPECT_FALSE(FPDFAnnot_HasKey(annot.get(), "MaxLen"));
1264
1265 float value;
1266 EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", &value));
1267 }
1268
1269 // Annotation in index 2 has "MaxLen" of 10.
1270 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1271 ASSERT_TRUE(annot);
1272
1273 // Verify that "MaxLen" key present.
1274 EXPECT_TRUE(FPDFAnnot_HasKey(annot.get(), "MaxLen"));
1275
1276 float value;
1277 EXPECT_TRUE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", &value));
1278 EXPECT_FLOAT_EQ(10.0f, value);
1279
1280 // Check bad inputs.
1281 EXPECT_FALSE(FPDFAnnot_GetNumberValue(nullptr, "MaxLen", &value));
1282 EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), nullptr, &value));
1283 EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", nullptr));
1284 // Ask for key that exists but is not a number.
1285 EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "V", &value));
1286 }
1287
1288 UnloadPage(page);
1289}
1290
Lei Zhangab41f252018-12-23 03:10:50 +00001291TEST_F(FPDFAnnotEmbedderTest, GetSetAP) {
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001292 // Open a file with four annotations and load its first page.
1293 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001294 FPDF_PAGE page = LoadPage(0);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001295 ASSERT_TRUE(page);
1296
Lei Zhanga21d5932018-02-05 18:28:38 +00001297 {
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001298 static const char kMd5NormalAP[] = "be903df0343fd774fadab9c8900cdf4a";
1299 static constexpr size_t kExpectNormalAPLength = 73970;
1300
Lei Zhanga21d5932018-02-05 18:28:38 +00001301 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001302 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001303 ASSERT_TRUE(annot);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001304
Lei Zhanga21d5932018-02-05 18:28:38 +00001305 // Check that the string value of an AP returns the expected length.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001306 unsigned long normal_length_bytes = FPDFAnnot_GetAP(
Lei Zhanga21d5932018-02-05 18:28:38 +00001307 annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001308 ASSERT_EQ(kExpectNormalAPLength, normal_length_bytes);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001309
Lei Zhanga21d5932018-02-05 18:28:38 +00001310 // Check that the string value of an AP is not returned if the buffer is too
1311 // small. The result buffer should be overwritten with an empty string.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001312 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(normal_length_bytes);
1313 // Write in the buffer to verify it's not overwritten.
1314 memcpy(buf.data(), "abcdefgh", 8);
1315 EXPECT_EQ(kExpectNormalAPLength,
Lei Zhanga21d5932018-02-05 18:28:38 +00001316 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001317 buf.data(), normal_length_bytes - 1));
1318 EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001319
Lei Zhanga21d5932018-02-05 18:28:38 +00001320 // Check that the string value of an AP is returned through a buffer that is
1321 // the right size.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001322 EXPECT_EQ(kExpectNormalAPLength,
Lei Zhanga21d5932018-02-05 18:28:38 +00001323 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001324 buf.data(), normal_length_bytes));
1325 EXPECT_EQ(kMd5NormalAP,
1326 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()),
1327 normal_length_bytes));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001328
Lei Zhanga21d5932018-02-05 18:28:38 +00001329 // Check that the string value of an AP is returned through a buffer that is
1330 // larger than necessary.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001331 buf = GetFPDFWideStringBuffer(normal_length_bytes + 2);
1332 EXPECT_EQ(kExpectNormalAPLength,
Lei Zhanga21d5932018-02-05 18:28:38 +00001333 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001334 buf.data(), normal_length_bytes + 2));
1335 EXPECT_EQ(kMd5NormalAP,
1336 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()),
1337 normal_length_bytes));
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001338
Lei Zhanga21d5932018-02-05 18:28:38 +00001339 // Check that getting an AP for a mode that does not have an AP returns an
1340 // empty string.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001341 unsigned long rollover_length_bytes = FPDFAnnot_GetAP(
Lei Zhanga21d5932018-02-05 18:28:38 +00001342 annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001343 ASSERT_EQ(2u, rollover_length_bytes);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001344
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001345 buf = GetFPDFWideStringBuffer(1000);
Lei Zhanga21d5932018-02-05 18:28:38 +00001346 EXPECT_EQ(2u,
1347 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001348 buf.data(), 1000));
1349 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001350
Lei Zhanga21d5932018-02-05 18:28:38 +00001351 // Check that setting the AP for an invalid appearance mode fails.
Lei Zhangf0f67682019-04-08 17:03:21 +00001352 ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
Lei Zhang4f556b82019-04-08 16:32:41 +00001353 EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), -1, ap_text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001354 EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_COUNT,
Lei Zhang4f556b82019-04-08 16:32:41 +00001355 ap_text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001356 EXPECT_FALSE(FPDFAnnot_SetAP(
Lei Zhang4f556b82019-04-08 16:32:41 +00001357 annot.get(), FPDF_ANNOT_APPEARANCEMODE_COUNT + 1, ap_text.get()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001358
Lei Zhanga21d5932018-02-05 18:28:38 +00001359 // Set the AP correctly now.
1360 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang4f556b82019-04-08 16:32:41 +00001361 ap_text.get()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001362
Lei Zhanga21d5932018-02-05 18:28:38 +00001363 // Check that the new annotation value is equal to the value we just set.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001364 rollover_length_bytes = FPDFAnnot_GetAP(
Lei Zhanga21d5932018-02-05 18:28:38 +00001365 annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001366 ASSERT_EQ(24u, rollover_length_bytes);
1367 buf = GetFPDFWideStringBuffer(rollover_length_bytes);
Lei Zhanga21d5932018-02-05 18:28:38 +00001368 EXPECT_EQ(24u,
1369 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001370 buf.data(), rollover_length_bytes));
1371 EXPECT_EQ(L"new test ap", GetPlatformWString(buf.data()));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001372
Lei Zhanga21d5932018-02-05 18:28:38 +00001373 // Check that the Normal AP was not touched when the Rollover AP was set.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001374 buf = GetFPDFWideStringBuffer(normal_length_bytes);
1375 EXPECT_EQ(kExpectNormalAPLength,
Lei Zhanga21d5932018-02-05 18:28:38 +00001376 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001377 buf.data(), normal_length_bytes));
1378 EXPECT_EQ(kMd5NormalAP,
1379 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()),
1380 normal_length_bytes));
Lei Zhanga21d5932018-02-05 18:28:38 +00001381 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001382
1383 // Save the modified document, then reopen it.
Henrique Nakashima5970a472018-01-11 22:40:59 +00001384 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang75c81712018-02-08 17:22:39 +00001385 UnloadPage(page);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001386
Lei Zhang0b494052019-01-31 21:41:15 +00001387 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima5970a472018-01-11 22:40:59 +00001388 page = LoadSavedPage(0);
Lei Zhanga21d5932018-02-05 18:28:38 +00001389 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00001390 ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001391
Lei Zhanga21d5932018-02-05 18:28:38 +00001392 // Check that the new annotation value is equal to the value we set before
1393 // saving.
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001394 unsigned long rollover_length_bytes = FPDFAnnot_GetAP(
Lei Zhanga21d5932018-02-05 18:28:38 +00001395 new_annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001396 ASSERT_EQ(24u, rollover_length_bytes);
1397 std::vector<FPDF_WCHAR> buf =
1398 GetFPDFWideStringBuffer(rollover_length_bytes);
Lei Zhanga21d5932018-02-05 18:28:38 +00001399 EXPECT_EQ(24u, FPDFAnnot_GetAP(new_annot.get(),
1400 FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001401 buf.data(), rollover_length_bytes));
1402 EXPECT_EQ(L"new test ap", GetPlatformWString(buf.data()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001403 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001404
1405 // Close saved document.
Henrique Nakashima5970a472018-01-11 22:40:59 +00001406 CloseSavedPage(page);
1407 CloseSavedDocument();
1408}
1409
Lei Zhangab41f252018-12-23 03:10:50 +00001410TEST_F(FPDFAnnotEmbedderTest, RemoveOptionalAP) {
Henrique Nakashima5970a472018-01-11 22:40:59 +00001411 // Open a file with four annotations and load its first page.
1412 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001413 FPDF_PAGE page = LoadPage(0);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001414 ASSERT_TRUE(page);
1415
Lei Zhanga21d5932018-02-05 18:28:38 +00001416 {
1417 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001418 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001419 ASSERT_TRUE(annot);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001420
Lei Zhanga21d5932018-02-05 18:28:38 +00001421 // Set Down AP. Normal AP is already set.
Lei Zhangf0f67682019-04-08 17:03:21 +00001422 ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
Lei Zhanga21d5932018-02-05 18:28:38 +00001423 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
Lei Zhang4f556b82019-04-08 16:32:41 +00001424 ap_text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001425 EXPECT_EQ(73970u,
1426 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1427 nullptr, 0));
1428 EXPECT_EQ(24u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1429 nullptr, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001430
Lei Zhanga21d5932018-02-05 18:28:38 +00001431 // Check that setting the Down AP to null removes the Down entry but keeps
1432 // Normal intact.
1433 EXPECT_TRUE(
1434 FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr));
1435 EXPECT_EQ(73970u,
1436 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1437 nullptr, 0));
1438 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1439 nullptr, 0));
1440 }
Henrique Nakashima5970a472018-01-11 22:40:59 +00001441
Lei Zhang75c81712018-02-08 17:22:39 +00001442 UnloadPage(page);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001443}
1444
Lei Zhangab41f252018-12-23 03:10:50 +00001445TEST_F(FPDFAnnotEmbedderTest, RemoveRequiredAP) {
Henrique Nakashima5970a472018-01-11 22:40:59 +00001446 // Open a file with four annotations and load its first page.
1447 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001448 FPDF_PAGE page = LoadPage(0);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001449 ASSERT_TRUE(page);
1450
Lei Zhanga21d5932018-02-05 18:28:38 +00001451 {
1452 // Retrieve the first annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001453 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001454 ASSERT_TRUE(annot);
Henrique Nakashima5970a472018-01-11 22:40:59 +00001455
Lei Zhanga21d5932018-02-05 18:28:38 +00001456 // Set Down AP. Normal AP is already set.
Lei Zhangf0f67682019-04-08 17:03:21 +00001457 ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
Lei Zhanga21d5932018-02-05 18:28:38 +00001458 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
Lei Zhang4f556b82019-04-08 16:32:41 +00001459 ap_text.get()));
Lei Zhanga21d5932018-02-05 18:28:38 +00001460 EXPECT_EQ(73970u,
1461 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1462 nullptr, 0));
1463 EXPECT_EQ(24u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1464 nullptr, 0));
Henrique Nakashima5970a472018-01-11 22:40:59 +00001465
Lei Zhanga21d5932018-02-05 18:28:38 +00001466 // Check that setting the Normal AP to null removes the whole AP dictionary.
1467 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1468 nullptr));
1469 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1470 nullptr, 0));
1471 EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1472 nullptr, 0));
1473 }
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001474
Lei Zhang75c81712018-02-08 17:22:39 +00001475 UnloadPage(page);
Henrique Nakashimaa74e75d2018-01-10 18:06:55 +00001476}
1477
Lei Zhangab41f252018-12-23 03:10:50 +00001478TEST_F(FPDFAnnotEmbedderTest, ExtractLinkedAnnotations) {
Jane Liu300bb272017-08-21 14:37:53 -04001479 // Open a file with annotations and load its first page.
1480 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001481 FPDF_PAGE page = LoadPage(0);
Jane Liu300bb272017-08-21 14:37:53 -04001482 ASSERT_TRUE(page);
Jane Liud1ed1ce2017-08-24 12:31:10 -04001483 EXPECT_EQ(-1, FPDFPage_GetAnnotIndex(page, nullptr));
Jane Liu300bb272017-08-21 14:37:53 -04001484
Lei Zhanga21d5932018-02-05 18:28:38 +00001485 {
1486 // Retrieve the highlight annotation which has its popup defined.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001487 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001488 ASSERT_TRUE(annot);
1489 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
1490 EXPECT_EQ(0, FPDFPage_GetAnnotIndex(page, annot.get()));
Lei Zhang4f556b82019-04-08 16:32:41 +00001491 static const char kPopupKey[] = "Popup";
Lei Zhanga21d5932018-02-05 18:28:38 +00001492 ASSERT_TRUE(FPDFAnnot_HasKey(annot.get(), kPopupKey));
1493 ASSERT_EQ(FPDF_OBJECT_REFERENCE,
1494 FPDFAnnot_GetValueType(annot.get(), kPopupKey));
Jane Liu300bb272017-08-21 14:37:53 -04001495
Lei Zhanga21d5932018-02-05 18:28:38 +00001496 // Retrieve and verify the popup of the highlight annotation.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001497 ScopedFPDFAnnotation popup(
Lei Zhanga21d5932018-02-05 18:28:38 +00001498 FPDFAnnot_GetLinkedAnnot(annot.get(), kPopupKey));
1499 ASSERT_TRUE(popup);
1500 EXPECT_EQ(FPDF_ANNOT_POPUP, FPDFAnnot_GetSubtype(popup.get()));
1501 EXPECT_EQ(1, FPDFPage_GetAnnotIndex(page, popup.get()));
1502 FS_RECTF rect;
1503 ASSERT_TRUE(FPDFAnnot_GetRect(popup.get(), &rect));
1504 EXPECT_NEAR(612.0f, rect.left, 0.001f);
1505 EXPECT_NEAR(578.792, rect.bottom, 0.001f);
Jane Liu300bb272017-08-21 14:37:53 -04001506
Lei Zhanga21d5932018-02-05 18:28:38 +00001507 // Attempting to retrieve |annot|'s "IRT"-linked annotation would fail,
1508 // since "IRT" is not a key in |annot|'s dictionary.
Lei Zhang4f556b82019-04-08 16:32:41 +00001509 static const char kIRTKey[] = "IRT";
Lei Zhanga21d5932018-02-05 18:28:38 +00001510 ASSERT_FALSE(FPDFAnnot_HasKey(annot.get(), kIRTKey));
1511 EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot.get(), kIRTKey));
Jane Liu300bb272017-08-21 14:37:53 -04001512
Lei Zhanga21d5932018-02-05 18:28:38 +00001513 // Attempting to retrieve |annot|'s parent dictionary as an annotation
1514 // would fail, since its parent is not an annotation.
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001515 ASSERT_TRUE(FPDFAnnot_HasKey(annot.get(), pdfium::annotation::kP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001516 EXPECT_EQ(FPDF_OBJECT_REFERENCE,
Lei Zhanga5c1daf2019-01-31 21:56:47 +00001517 FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kP));
1518 EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot.get(), pdfium::annotation::kP));
Lei Zhanga21d5932018-02-05 18:28:38 +00001519 }
Jane Liu300bb272017-08-21 14:37:53 -04001520
Jane Liu300bb272017-08-21 14:37:53 -04001521 UnloadPage(page);
1522}
1523
Lei Zhangab41f252018-12-23 03:10:50 +00001524TEST_F(FPDFAnnotEmbedderTest, GetFormFieldFlagsTextField) {
Diana Gage7e0c05d2017-07-19 17:33:33 -07001525 // Open file with form text fields.
1526 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001527 FPDF_PAGE page = LoadPage(0);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001528 ASSERT_TRUE(page);
1529
Lei Zhanga21d5932018-02-05 18:28:38 +00001530 {
1531 // Retrieve the first annotation: user-editable text field.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001532 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001533 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001534
Lei Zhanga21d5932018-02-05 18:28:38 +00001535 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001536 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001537 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
Mansi Awasthi0b5da672020-01-23 18:17:18 +00001538 EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
Lei Zhanga21d5932018-02-05 18:28:38 +00001539 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001540
Lei Zhanga21d5932018-02-05 18:28:38 +00001541 {
1542 // Retrieve the second annotation: read-only text field.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001543 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +00001544 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001545
Lei Zhanga21d5932018-02-05 18:28:38 +00001546 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001547 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001548 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
Mansi Awasthi0b5da672020-01-23 18:17:18 +00001549 EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
1550 }
1551
1552 {
1553 // Retrieve the fourth annotation: user-editable password text field.
1554 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
1555 ASSERT_TRUE(annot);
1556
1557 // Check that the flag values are as expected.
1558 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
1559 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1560 EXPECT_TRUE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
Lei Zhanga21d5932018-02-05 18:28:38 +00001561 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001562
1563 UnloadPage(page);
1564}
1565
Lei Zhangab41f252018-12-23 03:10:50 +00001566TEST_F(FPDFAnnotEmbedderTest, GetFormFieldFlagsComboBox) {
Diana Gage7e0c05d2017-07-19 17:33:33 -07001567 // Open file with form text fields.
1568 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00001569 FPDF_PAGE page = LoadPage(0);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001570 ASSERT_TRUE(page);
1571
Lei Zhanga21d5932018-02-05 18:28:38 +00001572 {
1573 // Retrieve the first annotation: user-editable combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001574 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
Lei Zhanga21d5932018-02-05 18:28:38 +00001575 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001576
Lei Zhanga21d5932018-02-05 18:28:38 +00001577 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001578 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001579 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1580 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1581 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1582 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001583
Lei Zhanga21d5932018-02-05 18:28:38 +00001584 {
1585 // Retrieve the second annotation: regular combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001586 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Lei Zhanga21d5932018-02-05 18:28:38 +00001587 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001588
Lei Zhanga21d5932018-02-05 18:28:38 +00001589 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001590 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001591 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1592 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1593 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1594 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001595
Lei Zhanga21d5932018-02-05 18:28:38 +00001596 {
1597 // Retrieve the third annotation: read-only combobox.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001598 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
Lei Zhanga21d5932018-02-05 18:28:38 +00001599 ASSERT_TRUE(annot);
Diana Gage7e0c05d2017-07-19 17:33:33 -07001600
Lei Zhanga21d5932018-02-05 18:28:38 +00001601 // Check that the flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001602 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001603 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1604 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1605 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1606 }
Diana Gage7e0c05d2017-07-19 17:33:33 -07001607
1608 UnloadPage(page);
1609}
Diana Gage40870db2017-07-19 18:16:03 -07001610
Lei Zhangab41f252018-12-23 03:10:50 +00001611TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotNull) {
Diana Gage40870db2017-07-19 18:16:03 -07001612 // Open file with form text fields.
1613 EXPECT_TRUE(OpenDocument("text_form.pdf"));
1614 FPDF_PAGE page = LoadPage(0);
1615 ASSERT_TRUE(page);
1616
1617 // Attempt to get an annotation where no annotation exists on page.
Lei Zhang8da98232019-12-11 23:29:33 +00001618 static const FS_POINTF kOriginPoint = {0.0f, 0.0f};
1619 EXPECT_FALSE(
1620 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kOriginPoint));
Lei Zhang7557e7b2018-09-14 17:02:40 +00001621
Lei Zhang8da98232019-12-11 23:29:33 +00001622 static const FS_POINTF kValidPoint = {120.0f, 120.0f};
Lei Zhang7557e7b2018-09-14 17:02:40 +00001623 {
1624 // Verify there is an annotation.
1625 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00001626 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kValidPoint));
Lei Zhang7557e7b2018-09-14 17:02:40 +00001627 EXPECT_TRUE(annot);
1628 }
1629
1630 // Try other bad inputs at a valid location.
Lei Zhang8da98232019-12-11 23:29:33 +00001631 EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, nullptr, &kValidPoint));
1632 EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, page, &kValidPoint));
1633 EXPECT_FALSE(
1634 FPDFAnnot_GetFormFieldAtPoint(form_handle(), nullptr, &kValidPoint));
Diana Gage40870db2017-07-19 18:16:03 -07001635
1636 UnloadPage(page);
1637}
1638
Lei Zhangab41f252018-12-23 03:10:50 +00001639TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotAndCheckFlagsTextField) {
Diana Gage40870db2017-07-19 18:16:03 -07001640 // Open file with form text fields.
1641 EXPECT_TRUE(OpenDocument("text_form_multiple.pdf"));
1642 FPDF_PAGE page = LoadPage(0);
1643 ASSERT_TRUE(page);
1644
Lei Zhanga21d5932018-02-05 18:28:38 +00001645 {
1646 // Retrieve user-editable text field annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00001647 static const FS_POINTF kPoint = {105.0f, 118.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00001648 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00001649 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00001650 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001651
Lei Zhanga21d5932018-02-05 18:28:38 +00001652 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001653 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001654 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1655 }
Diana Gage40870db2017-07-19 18:16:03 -07001656
Lei Zhanga21d5932018-02-05 18:28:38 +00001657 {
1658 // Retrieve read-only text field annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00001659 static const FS_POINTF kPoint = {105.0f, 202.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00001660 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00001661 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00001662 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001663
Lei Zhanga21d5932018-02-05 18:28:38 +00001664 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001665 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001666 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1667 }
Diana Gage40870db2017-07-19 18:16:03 -07001668
1669 UnloadPage(page);
1670}
1671
Lei Zhangab41f252018-12-23 03:10:50 +00001672TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotAndCheckFlagsComboBox) {
Diana Gage40870db2017-07-19 18:16:03 -07001673 // Open file with form comboboxes.
1674 EXPECT_TRUE(OpenDocument("combobox_form.pdf"));
1675 FPDF_PAGE page = LoadPage(0);
1676 ASSERT_TRUE(page);
1677
Lei Zhanga21d5932018-02-05 18:28:38 +00001678 {
1679 // Retrieve user-editable combobox annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00001680 static const FS_POINTF kPoint = {102.0f, 363.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00001681 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00001682 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00001683 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001684
Lei Zhanga21d5932018-02-05 18:28:38 +00001685 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001686 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001687 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1688 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1689 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1690 }
Diana Gage40870db2017-07-19 18:16:03 -07001691
Lei Zhanga21d5932018-02-05 18:28:38 +00001692 {
1693 // Retrieve regular combobox annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00001694 static const FS_POINTF kPoint = {102.0f, 413.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00001695 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00001696 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00001697 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001698
Lei Zhanga21d5932018-02-05 18:28:38 +00001699 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001700 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001701 EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1702 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1703 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1704 }
Diana Gage40870db2017-07-19 18:16:03 -07001705
Lei Zhanga21d5932018-02-05 18:28:38 +00001706 {
1707 // Retrieve read-only combobox annotation.
Lei Zhang8da98232019-12-11 23:29:33 +00001708 static const FS_POINTF kPoint = {102.0f, 513.0f};
Tom Sepeze08d2b12018-04-25 18:49:32 +00001709 ScopedFPDFAnnotation annot(
Lei Zhang8da98232019-12-11 23:29:33 +00001710 FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
Lei Zhanga21d5932018-02-05 18:28:38 +00001711 ASSERT_TRUE(annot);
Diana Gage40870db2017-07-19 18:16:03 -07001712
Lei Zhanga21d5932018-02-05 18:28:38 +00001713 // Check that interactive form annotation flag values are as expected.
Lei Zhanga9d33bd2019-07-31 05:37:31 +00001714 int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
Lei Zhanga21d5932018-02-05 18:28:38 +00001715 EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1716 EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1717 EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1718 }
Diana Gage40870db2017-07-19 18:16:03 -07001719
1720 UnloadPage(page);
1721}
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001722
Lei Zhang03e5e682019-09-16 19:45:55 +00001723// TODO(crbug.com/pdfium/11): Fix this test and enable.
1724#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1725#define MAYBE_BUG_1206 DISABLED_BUG_1206
1726#else
1727#define MAYBE_BUG_1206 BUG_1206
1728#endif
1729TEST_F(FPDFAnnotEmbedderTest, MAYBE_BUG_1206) {
Lei Zhang992e7e22019-02-04 19:20:58 +00001730 static constexpr size_t kExpectedSize = 1609;
1731 static const char kExpectedBitmap[] = "0d9fc05c6762fd788bd23fd87a4967bc";
1732
1733 ASSERT_TRUE(OpenDocument("bug_1206.pdf"));
1734
1735 FPDF_PAGE page = LoadPage(0);
1736 ASSERT_TRUE(page);
1737
1738 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1739 EXPECT_EQ(kExpectedSize, GetString().size());
1740 ClearString();
1741
1742 for (size_t i = 0; i < 10; ++i) {
1743 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1744 CompareBitmap(bitmap.get(), 612, 792, kExpectedBitmap);
1745
1746 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1747 // TODO(https://crbug.com/pdfium/1206): This is wrong. The size should be
1748 // equal, not bigger.
1749 EXPECT_LT(kExpectedSize, GetString().size());
1750 ClearString();
1751 }
1752
1753 UnloadPage(page);
1754}
1755
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001756TEST_F(FPDFAnnotEmbedderTest, BUG_1212) {
1757 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1758 FPDF_PAGE page = LoadPage(0);
1759 ASSERT_TRUE(page);
1760 EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
1761
1762 static const char kTestKey[] = "test";
Lei Zhang4f556b82019-04-08 16:32:41 +00001763 static const wchar_t kData[] = L"\xf6\xe4";
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001764 static const size_t kBufSize = 12;
1765 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(kBufSize);
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001766
1767 {
1768 // Add a text annotation to the page.
1769 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT));
1770 ASSERT_TRUE(annot);
1771 EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
1772 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
1773
1774 // Make sure there is no test key, add set a value there, and read it back.
1775 std::fill(buf.begin(), buf.end(), 'x');
1776 ASSERT_EQ(2u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001777 kBufSize));
1778 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001779
Lei Zhangf0f67682019-04-08 17:03:21 +00001780 ScopedFPDFWideString text = GetFPDFWideString(kData);
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001781 EXPECT_TRUE(FPDFAnnot_SetStringValue(annot.get(), kTestKey, text.get()));
1782
1783 std::fill(buf.begin(), buf.end(), 'x');
1784 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001785 kBufSize));
1786 EXPECT_EQ(kData, GetPlatformWString(buf.data()));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001787 }
1788
Lei Zhang05ec64c2019-01-09 03:00:06 +00001789 {
1790 ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
1791 ASSERT_TRUE(annot);
Shikha Walia87ad4172019-11-08 20:55:19 +00001792 const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
Shikha Waliab54d7ad2019-11-06 02:06:33 +00001793 EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
Lei Zhang05ec64c2019-01-09 03:00:06 +00001794 EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1795 EXPECT_EQ(FPDF_ANNOT_STAMP, FPDFAnnot_GetSubtype(annot.get()));
1796 // Also do the same test for its appearance string.
1797 std::fill(buf.begin(), buf.end(), 'x');
1798 ASSERT_EQ(2u,
1799 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001800 buf.data(), kBufSize));
1801 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
Lei Zhang05ec64c2019-01-09 03:00:06 +00001802
Lei Zhangf0f67682019-04-08 17:03:21 +00001803 ScopedFPDFWideString text = GetFPDFWideString(kData);
Lei Zhang05ec64c2019-01-09 03:00:06 +00001804 EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1805 text.get()));
1806
1807 std::fill(buf.begin(), buf.end(), 'x');
1808 ASSERT_EQ(6u,
1809 FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001810 buf.data(), kBufSize));
1811 EXPECT_EQ(kData, GetPlatformWString(buf.data()));
Lei Zhang05ec64c2019-01-09 03:00:06 +00001812 }
1813
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001814 UnloadPage(page);
1815
1816 {
1817 // Save a copy, open the copy, and check the annotation again.
1818 // Note that it renders the rotation.
1819 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhang0b494052019-01-31 21:41:15 +00001820 ASSERT_TRUE(OpenSavedDocument());
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001821 FPDF_PAGE saved_page = LoadSavedPage(0);
1822 ASSERT_TRUE(saved_page);
1823
Lei Zhang05ec64c2019-01-09 03:00:06 +00001824 EXPECT_EQ(2, FPDFPage_GetAnnotCount(saved_page));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001825 {
1826 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(saved_page, 0));
1827 ASSERT_TRUE(annot);
1828 EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
1829
1830 std::fill(buf.begin(), buf.end(), 'x');
1831 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001832 kBufSize));
1833 EXPECT_EQ(kData, GetPlatformWString(buf.data()));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001834 }
1835
Lei Zhang05ec64c2019-01-09 03:00:06 +00001836 {
1837 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(saved_page, 0));
1838 ASSERT_TRUE(annot);
1839 // TODO(thestig): This return FPDF_ANNOT_UNKNOWN for some reason.
1840 // EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
1841
1842 std::fill(buf.begin(), buf.end(), 'x');
1843 ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001844 kBufSize));
1845 EXPECT_EQ(kData, GetPlatformWString(buf.data()));
Lei Zhang05ec64c2019-01-09 03:00:06 +00001846 }
1847
Lei Zhangf5fcd9e2018-12-23 03:11:50 +00001848 CloseSavedPage(saved_page);
1849 CloseSavedDocument();
1850 }
1851}
rycsmithcb752f32019-02-21 18:40:53 +00001852
1853TEST_F(FPDFAnnotEmbedderTest, GetOptionCountCombobox) {
1854 // Open a file with combobox widget annotations and load its first page.
1855 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
1856 FPDF_PAGE page = LoadPage(0);
1857 ASSERT_TRUE(page);
1858
1859 {
1860 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1861 ASSERT_TRUE(annot);
1862
1863 EXPECT_EQ(3, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1864
1865 annot.reset(FPDFPage_GetAnnot(page, 1));
1866 ASSERT_TRUE(annot);
1867
1868 EXPECT_EQ(26, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
Lei Zhange7033c82019-02-26 19:30:49 +00001869
1870 // Check bad form handle / annot.
1871 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(nullptr, nullptr));
1872 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), nullptr));
1873 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(nullptr, annot.get()));
rycsmithcb752f32019-02-21 18:40:53 +00001874 }
1875
1876 UnloadPage(page);
1877}
1878
1879TEST_F(FPDFAnnotEmbedderTest, GetOptionCountListbox) {
1880 // Open a file with listbox widget annotations and load its first page.
1881 ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
1882 FPDF_PAGE page = LoadPage(0);
1883 ASSERT_TRUE(page);
1884
1885 {
1886 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1887 ASSERT_TRUE(annot);
1888
1889 EXPECT_EQ(3, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1890
1891 annot.reset(FPDFPage_GetAnnot(page, 1));
1892 ASSERT_TRUE(annot);
1893
1894 EXPECT_EQ(26, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1895 }
1896
1897 UnloadPage(page);
1898}
1899
1900TEST_F(FPDFAnnotEmbedderTest, GetOptionCountInvalidAnnotations) {
1901 // Open a file with ink annotations and load its first page.
1902 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
1903 FPDF_PAGE page = LoadPage(0);
1904 ASSERT_TRUE(page);
1905
1906 {
1907 // annotations do not have "Opt" array and will return -1
1908 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1909 ASSERT_TRUE(annot);
1910
1911 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1912
1913 annot.reset(FPDFPage_GetAnnot(page, 1));
1914 ASSERT_TRUE(annot);
1915
1916 EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
1917 }
1918
1919 UnloadPage(page);
1920}
1921
1922TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelCombobox) {
1923 // Open a file with combobox widget annotations and load its first page.
1924 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
1925 FPDF_PAGE page = LoadPage(0);
1926 ASSERT_TRUE(page);
1927
1928 {
1929 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1930 ASSERT_TRUE(annot);
1931
1932 int index = 0;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001933 unsigned long length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00001934 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001935 ASSERT_EQ(8u, length_bytes);
1936 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00001937 EXPECT_EQ(8u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001938 buf.data(), length_bytes));
1939 EXPECT_EQ(L"Foo", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00001940
1941 annot.reset(FPDFPage_GetAnnot(page, 1));
1942 ASSERT_TRUE(annot);
1943
1944 index = 0;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001945 length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00001946 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001947 ASSERT_EQ(12u, length_bytes);
1948 buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00001949 EXPECT_EQ(12u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001950 buf.data(), length_bytes));
1951 EXPECT_EQ(L"Apple", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00001952
1953 index = 25;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001954 length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00001955 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001956 buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00001957 EXPECT_EQ(18u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001958 buf.data(), length_bytes));
1959 EXPECT_EQ(L"Zucchini", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00001960
Lei Zhange7033c82019-02-26 19:30:49 +00001961 // Indices out of range
rycsmithcb752f32019-02-21 18:40:53 +00001962 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), -1,
1963 nullptr, 0));
1964 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 26,
1965 nullptr, 0));
Lei Zhange7033c82019-02-26 19:30:49 +00001966
1967 // Check bad form handle / annot.
1968 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(nullptr, nullptr, 0, nullptr, 0));
1969 EXPECT_EQ(0u,
1970 FPDFAnnot_GetOptionLabel(nullptr, annot.get(), 0, nullptr, 0));
1971 EXPECT_EQ(0u,
1972 FPDFAnnot_GetOptionLabel(form_handle(), nullptr, 0, nullptr, 0));
rycsmithcb752f32019-02-21 18:40:53 +00001973 }
1974
1975 UnloadPage(page);
1976}
1977
1978TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelListbox) {
1979 // Open a file with listbox widget annotations and load its first page.
1980 ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
1981 FPDF_PAGE page = LoadPage(0);
1982 ASSERT_TRUE(page);
1983
1984 {
1985 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1986 ASSERT_TRUE(annot);
1987
1988 int index = 0;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001989 unsigned long length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00001990 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001991 ASSERT_EQ(8u, length_bytes);
1992 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00001993 EXPECT_EQ(8u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00001994 buf.data(), length_bytes));
1995 EXPECT_EQ(L"Foo", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00001996
1997 annot.reset(FPDFPage_GetAnnot(page, 1));
1998 ASSERT_TRUE(annot);
1999
2000 index = 0;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002001 length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00002002 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002003 ASSERT_EQ(12u, length_bytes);
2004 buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00002005 EXPECT_EQ(12u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002006 buf.data(), length_bytes));
2007 EXPECT_EQ(L"Apple", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00002008
2009 index = 25;
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002010 length_bytes =
rycsmithcb752f32019-02-21 18:40:53 +00002011 FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002012 ASSERT_EQ(18u, length_bytes);
2013 buf = GetFPDFWideStringBuffer(length_bytes);
rycsmithcb752f32019-02-21 18:40:53 +00002014 EXPECT_EQ(18u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
Lei Zhang5bf8c7f2019-04-08 17:50:11 +00002015 buf.data(), length_bytes));
2016 EXPECT_EQ(L"Zucchini", GetPlatformWString(buf.data()));
rycsmithcb752f32019-02-21 18:40:53 +00002017
2018 // indices out of range
2019 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), -1,
2020 nullptr, 0));
2021 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 26,
2022 nullptr, 0));
2023 }
2024
2025 UnloadPage(page);
2026}
2027
2028TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelInvalidAnnotations) {
2029 // Open a file with ink annotations and load its first page.
2030 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
2031 FPDF_PAGE page = LoadPage(0);
2032 ASSERT_TRUE(page);
2033
2034 {
2035 // annotations do not have "Opt" array and will return 0
2036 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2037 ASSERT_TRUE(annot);
2038
2039 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 0,
2040 nullptr, 0));
2041
2042 annot.reset(FPDFPage_GetAnnot(page, 1));
2043 ASSERT_TRUE(annot);
2044
2045 EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 0,
2046 nullptr, 0));
2047 }
2048
2049 UnloadPage(page);
2050}
Ryan Smith09c23b12019-04-25 18:09:06 +00002051
2052TEST_F(FPDFAnnotEmbedderTest, GetFontSizeCombobox) {
2053 // Open a file with combobox annotations and load its first page.
2054 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2055 FPDF_PAGE page = LoadPage(0);
2056 ASSERT_TRUE(page);
2057
2058 {
2059 // All 3 widgets have Tf font size 12.
2060 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2061 ASSERT_TRUE(annot);
2062
2063 float value;
2064 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2065 EXPECT_EQ(12.0, value);
2066
2067 annot.reset(FPDFPage_GetAnnot(page, 1));
2068 ASSERT_TRUE(annot);
2069
2070 float value_two;
2071 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_two));
2072 EXPECT_EQ(12.0, value_two);
2073
2074 annot.reset(FPDFPage_GetAnnot(page, 2));
2075 ASSERT_TRUE(annot);
2076
2077 float value_three;
2078 ASSERT_TRUE(
2079 FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_three));
2080 EXPECT_EQ(12.0, value_three);
2081 }
2082
2083 UnloadPage(page);
2084}
2085
2086TEST_F(FPDFAnnotEmbedderTest, GetFontSizeTextField) {
2087 // Open a file with textfield annotations and load its first page.
2088 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
2089 FPDF_PAGE page = LoadPage(0);
2090 ASSERT_TRUE(page);
2091
2092 {
Mansi Awasthi0b5da672020-01-23 18:17:18 +00002093 // All 4 widgets have Tf font size 12.
Ryan Smith09c23b12019-04-25 18:09:06 +00002094 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2095 ASSERT_TRUE(annot);
2096
2097 float value;
2098 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2099 EXPECT_EQ(12.0, value);
2100
2101 annot.reset(FPDFPage_GetAnnot(page, 1));
2102 ASSERT_TRUE(annot);
2103
2104 float value_two;
2105 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_two));
2106 EXPECT_EQ(12.0, value_two);
2107
2108 annot.reset(FPDFPage_GetAnnot(page, 2));
2109 ASSERT_TRUE(annot);
2110
2111 float value_three;
2112 ASSERT_TRUE(
2113 FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_three));
2114 EXPECT_EQ(12.0, value_three);
Mansi Awasthi0b5da672020-01-23 18:17:18 +00002115
2116 float value_four;
2117 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_four));
2118 EXPECT_EQ(12.0, value_four);
Ryan Smith09c23b12019-04-25 18:09:06 +00002119 }
2120
2121 UnloadPage(page);
2122}
2123
2124TEST_F(FPDFAnnotEmbedderTest, GetFontSizeInvalidAnnotationTypes) {
2125 // Open a file with ink annotations and load its first page.
2126 ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
2127 FPDF_PAGE page = LoadPage(0);
2128 ASSERT_TRUE(page);
2129
2130 {
2131 // Annotations that do not have variable text and will return -1.
2132 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2133 ASSERT_TRUE(annot);
2134
2135 float value;
2136 ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2137
2138 annot.reset(FPDFPage_GetAnnot(page, 1));
2139 ASSERT_TRUE(annot);
2140
2141 ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2142 }
2143
2144 UnloadPage(page);
2145}
2146
2147TEST_F(FPDFAnnotEmbedderTest, GetFontSizeInvalidArguments) {
2148 // Open a file with combobox annotations and load its first page.
2149 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2150 FPDF_PAGE page = LoadPage(0);
2151 ASSERT_TRUE(page);
2152
2153 {
2154 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2155 ASSERT_TRUE(annot);
2156
2157 // Check bad form handle / annot.
2158 float value;
2159 ASSERT_FALSE(FPDFAnnot_GetFontSize(nullptr, annot.get(), &value));
2160 ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), nullptr, &value));
2161 ASSERT_FALSE(FPDFAnnot_GetFontSize(nullptr, nullptr, &value));
2162 }
2163
2164 UnloadPage(page);
2165}
2166
2167TEST_F(FPDFAnnotEmbedderTest, GetFontSizeNegative) {
2168 // Open a file with textfield annotations and load its first page.
2169 ASSERT_TRUE(OpenDocument("text_form_negative_fontsize.pdf"));
2170 FPDF_PAGE page = LoadPage(0);
2171 ASSERT_TRUE(page);
2172
2173 {
2174 // Obtain the first annotation, a text field with negative font size, -12.
2175 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2176 ASSERT_TRUE(annot);
2177
2178 float value;
2179 ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2180 EXPECT_EQ(-12.0, value);
2181 }
2182
2183 UnloadPage(page);
2184}
Ryan Smith23fdf892019-07-17 21:51:26 +00002185
2186TEST_F(FPDFAnnotEmbedderTest, IsCheckedCheckbox) {
2187 // Open a file with checkbox and radiobuttons widget annotations and load its
2188 // first page.
2189 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2190 FPDF_PAGE page = LoadPage(0);
2191 ASSERT_TRUE(page);
2192
2193 {
2194 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
2195 ASSERT_TRUE(annot);
2196 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2197 }
2198
2199 UnloadPage(page);
2200}
2201
2202TEST_F(FPDFAnnotEmbedderTest, IsCheckedCheckboxReadOnly) {
2203 // Open a file with checkbox and radiobutton widget annotations and load its
2204 // first page.
2205 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2206 FPDF_PAGE page = LoadPage(0);
2207 ASSERT_TRUE(page);
2208
2209 {
2210 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2211 ASSERT_TRUE(annot);
2212 ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2213 }
2214
2215 UnloadPage(page);
2216}
2217
2218TEST_F(FPDFAnnotEmbedderTest, IsCheckedRadioButton) {
2219 // Open a file with checkbox and radiobutton widget annotations and load its
2220 // first page.
2221 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2222 FPDF_PAGE page = LoadPage(0);
2223 ASSERT_TRUE(page);
2224
2225 {
2226 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 5));
2227 ASSERT_TRUE(annot);
2228 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2229
2230 annot.reset(FPDFPage_GetAnnot(page, 6));
2231 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2232
2233 annot.reset(FPDFPage_GetAnnot(page, 7));
2234 ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2235 }
2236
2237 UnloadPage(page);
2238}
2239
2240TEST_F(FPDFAnnotEmbedderTest, IsCheckedRadioButtonReadOnly) {
2241 // Open a file with checkbox and radiobutton widget annotations and load its
2242 // first page.
2243 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2244 FPDF_PAGE page = LoadPage(0);
2245 ASSERT_TRUE(page);
2246
2247 {
2248 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
2249 ASSERT_TRUE(annot);
2250 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2251
2252 annot.reset(FPDFPage_GetAnnot(page, 3));
2253 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2254
2255 annot.reset(FPDFPage_GetAnnot(page, 4));
2256 ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2257 }
2258
2259 UnloadPage(page);
2260}
2261
2262TEST_F(FPDFAnnotEmbedderTest, IsCheckedInvalidArguments) {
2263 // Open a file with checkbox and radiobuttons widget annotations and load its
2264 // first page.
2265 ASSERT_TRUE(OpenDocument("click_form.pdf"));
2266 FPDF_PAGE page = LoadPage(0);
2267 ASSERT_TRUE(page);
2268
2269 {
2270 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2271 ASSERT_TRUE(annot);
2272 ASSERT_FALSE(FPDFAnnot_IsChecked(nullptr, annot.get()));
2273 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), nullptr));
2274 ASSERT_FALSE(FPDFAnnot_IsChecked(nullptr, nullptr));
2275 }
2276
2277 UnloadPage(page);
2278}
2279
2280TEST_F(FPDFAnnotEmbedderTest, IsCheckedInvalidWidgetType) {
2281 // Open a file with text widget annotations and load its first page.
2282 ASSERT_TRUE(OpenDocument("text_form.pdf"));
2283 FPDF_PAGE page = LoadPage(0);
2284 ASSERT_TRUE(page);
2285
2286 {
2287 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2288 ASSERT_TRUE(annot);
2289 ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2290 }
2291
2292 UnloadPage(page);
2293}
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002294
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002295TEST_F(FPDFAnnotEmbedderTest, GetFormFieldType) {
2296 ASSERT_TRUE(OpenDocument("multiple_form_types.pdf"));
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002297 FPDF_PAGE page = LoadPage(0);
2298 ASSERT_TRUE(page);
2299
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002300 EXPECT_EQ(-1, FPDFAnnot_GetFormFieldType(form_handle(), nullptr));
2301
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002302 {
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002303 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002304 ASSERT_TRUE(annot);
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002305 EXPECT_EQ(-1, FPDFAnnot_GetFormFieldType(nullptr, annot.get()));
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002306 }
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002307
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002308 constexpr int kExpectedAnnotTypes[] = {-1,
2309 FPDF_FORMFIELD_COMBOBOX,
2310 FPDF_FORMFIELD_LISTBOX,
2311 FPDF_FORMFIELD_TEXTFIELD,
2312 FPDF_FORMFIELD_CHECKBOX,
2313 FPDF_FORMFIELD_RADIOBUTTON};
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002314
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002315 for (size_t i = 0; i < FX_ArraySize(kExpectedAnnotTypes); ++i) {
2316 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002317 ASSERT_TRUE(annot);
Ankit Kumar8c7e4ad2020-02-07 08:56:49 +00002318 EXPECT_EQ(kExpectedAnnotTypes[i],
Mansi Awasthi07bf7e62020-01-24 10:34:17 +00002319 FPDFAnnot_GetFormFieldType(form_handle(), annot.get()));
2320 }
2321 UnloadPage(page);
2322}
2323
2324TEST_F(FPDFAnnotEmbedderTest, GetFormFieldValueTextField) {
2325 ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
2326 FPDF_PAGE page = LoadPage(0);
2327 ASSERT_TRUE(page);
2328
2329 {
2330 EXPECT_EQ(0u,
2331 FPDFAnnot_GetFormFieldValue(form_handle(), nullptr, nullptr, 0));
2332
2333 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2334 ASSERT_TRUE(annot);
2335
2336 EXPECT_EQ(0u,
2337 FPDFAnnot_GetFormFieldValue(nullptr, annot.get(), nullptr, 0));
2338
2339 unsigned long length_bytes =
2340 FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2341 ASSERT_EQ(2u, length_bytes);
2342 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2343 EXPECT_EQ(2u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2344 buf.data(), length_bytes));
2345 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
2346 }
2347 {
2348 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
2349 ASSERT_TRUE(annot);
2350
2351 unsigned long length_bytes =
2352 FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2353 ASSERT_EQ(18u, length_bytes);
2354 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2355 EXPECT_EQ(18u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2356 buf.data(), length_bytes));
2357 EXPECT_EQ(L"Elephant", GetPlatformWString(buf.data()));
2358 }
2359 UnloadPage(page);
2360}
2361
2362TEST_F(FPDFAnnotEmbedderTest, GetFormFieldValueComboBox) {
2363 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2364 FPDF_PAGE page = LoadPage(0);
2365 ASSERT_TRUE(page);
2366
2367 {
2368 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2369 ASSERT_TRUE(annot);
2370
2371 unsigned long length_bytes =
2372 FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2373 ASSERT_EQ(2u, length_bytes);
2374 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2375 EXPECT_EQ(2u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2376 buf.data(), length_bytes));
2377 EXPECT_EQ(L"", GetPlatformWString(buf.data()));
2378 }
2379 {
2380 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
2381 ASSERT_TRUE(annot);
2382
2383 unsigned long length_bytes =
2384 FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2385 ASSERT_EQ(14u, length_bytes);
2386 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2387 EXPECT_EQ(14u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2388 buf.data(), length_bytes));
2389 EXPECT_EQ(L"Banana", GetPlatformWString(buf.data()));
2390 }
2391 UnloadPage(page);
2392}
2393
2394TEST_F(FPDFAnnotEmbedderTest, GetFormFieldNameTextField) {
2395 ASSERT_TRUE(OpenDocument("text_form.pdf"));
2396 FPDF_PAGE page = LoadPage(0);
2397 ASSERT_TRUE(page);
2398
2399 {
2400 EXPECT_EQ(0u,
2401 FPDFAnnot_GetFormFieldName(form_handle(), nullptr, nullptr, 0));
2402
2403 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2404 ASSERT_TRUE(annot);
2405
2406 EXPECT_EQ(0u, FPDFAnnot_GetFormFieldName(nullptr, annot.get(), nullptr, 0));
2407
2408 unsigned long length_bytes =
2409 FPDFAnnot_GetFormFieldName(form_handle(), annot.get(), nullptr, 0);
2410 ASSERT_EQ(18u, length_bytes);
2411 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2412 EXPECT_EQ(18u, FPDFAnnot_GetFormFieldName(form_handle(), annot.get(),
2413 buf.data(), length_bytes));
2414 EXPECT_EQ(L"Text Box", GetPlatformWString(buf.data()));
2415 }
2416 UnloadPage(page);
2417}
2418
2419TEST_F(FPDFAnnotEmbedderTest, GetFormFieldNameComboBox) {
2420 ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2421 FPDF_PAGE page = LoadPage(0);
2422 ASSERT_TRUE(page);
2423
2424 {
2425 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2426 ASSERT_TRUE(annot);
2427
2428 unsigned long length_bytes =
2429 FPDFAnnot_GetFormFieldName(form_handle(), annot.get(), nullptr, 0);
2430 ASSERT_EQ(30u, length_bytes);
2431 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2432 EXPECT_EQ(30u, FPDFAnnot_GetFormFieldName(form_handle(), annot.get(),
2433 buf.data(), length_bytes));
2434 EXPECT_EQ(L"Combo_Editable", GetPlatformWString(buf.data()));
2435 }
2436 UnloadPage(page);
2437}
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002438
Lei Zhang9b444002020-04-17 17:35:23 +00002439TEST_F(FPDFAnnotEmbedderTest, FocusableAnnotSubtypes) {
2440 ASSERT_TRUE(OpenDocument("annots.pdf"));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002441 FPDF_PAGE page = LoadPage(0);
2442 ASSERT_TRUE(page);
2443
Lei Zhang9b444002020-04-17 17:35:23 +00002444 // Verify widgets are by default focusable.
2445 const FPDF_ANNOTATION_SUBTYPE kDefaultSubtypes[] = {FPDF_ANNOT_WIDGET};
2446 VerifyFocusableAnnotSubtypes(form_handle(), kDefaultSubtypes);
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002447
Lei Zhang9b444002020-04-17 17:35:23 +00002448 // Expected annot subtypes for page 0 of annots.pdf.
2449 const FPDF_ANNOTATION_SUBTYPE kExpectedAnnotSubtypes[] = {
2450 FPDF_ANNOT_LINK, FPDF_ANNOT_LINK, FPDF_ANNOT_LINK,
2451 FPDF_ANNOT_LINK, FPDF_ANNOT_HIGHLIGHT, FPDF_ANNOT_HIGHLIGHT,
2452 FPDF_ANNOT_POPUP, FPDF_ANNOT_HIGHLIGHT, FPDF_ANNOT_WIDGET,
2453 };
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002454
Lei Zhang9b444002020-04-17 17:35:23 +00002455 const FPDF_ANNOTATION_SUBTYPE kExpectedDefaultFocusableSubtypes[] = {
Ankit Kumar69cab672020-04-20 19:50:41 +00002456 FPDF_ANNOT_WIDGET};
Lei Zhang9b444002020-04-17 17:35:23 +00002457 VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
2458 kExpectedAnnotSubtypes,
2459 kExpectedDefaultFocusableSubtypes);
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002460
Lei Zhang9b444002020-04-17 17:35:23 +00002461 // Make no annotation type focusable using the preferred method.
2462 ASSERT_TRUE(FPDFAnnot_SetFocusableSubtypes(form_handle(), nullptr, 0));
2463 ASSERT_EQ(0, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002464
Lei Zhang9b444002020-04-17 17:35:23 +00002465 // Restore the focusable type count back to 1, then set it back to 0 using a
2466 // different method.
2467 SetAndVerifyFocusableAnnotSubtypes(form_handle(), kDefaultSubtypes);
2468 ASSERT_TRUE(
2469 FPDFAnnot_SetFocusableSubtypes(form_handle(), kDefaultSubtypes, 0));
2470 ASSERT_EQ(0, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002471
Lei Zhang9b444002020-04-17 17:35:23 +00002472 VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
Ankit Kumar906ac572020-04-21 05:58:04 +00002473 kExpectedAnnotSubtypes, {});
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002474
Lei Zhang9b444002020-04-17 17:35:23 +00002475 // Now make links focusable.
2476 const FPDF_ANNOTATION_SUBTYPE kLinkSubtypes[] = {FPDF_ANNOT_LINK};
2477 SetAndVerifyFocusableAnnotSubtypes(form_handle(), kLinkSubtypes);
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002478
Lei Zhang9b444002020-04-17 17:35:23 +00002479 const FPDF_ANNOTATION_SUBTYPE kExpectedLinkocusableSubtypes[] = {
Ankit Kumar906ac572020-04-21 05:58:04 +00002480 FPDF_ANNOT_LINK};
Lei Zhang9b444002020-04-17 17:35:23 +00002481 VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
2482 kExpectedAnnotSubtypes,
2483 kExpectedLinkocusableSubtypes);
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002484
Lei Zhang9b444002020-04-17 17:35:23 +00002485 // Test invalid parameters.
2486 EXPECT_FALSE(FPDFAnnot_SetFocusableSubtypes(nullptr, kDefaultSubtypes,
2487 FX_ArraySize(kDefaultSubtypes)));
2488 EXPECT_FALSE(FPDFAnnot_SetFocusableSubtypes(form_handle(), nullptr,
2489 FX_ArraySize(kDefaultSubtypes)));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002490 EXPECT_EQ(-1, FPDFAnnot_GetFocusableSubtypesCount(nullptr));
2491
Lei Zhang9b444002020-04-17 17:35:23 +00002492 std::vector<FPDF_ANNOTATION_SUBTYPE> subtypes(1);
2493 EXPECT_FALSE(FPDFAnnot_GetFocusableSubtypes(nullptr, subtypes.data(),
2494 subtypes.size()));
2495 EXPECT_FALSE(
2496 FPDFAnnot_GetFocusableSubtypes(form_handle(), nullptr, subtypes.size()));
2497 EXPECT_FALSE(
2498 FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(), 0));
Neha Gupta1eb6ddd2020-03-19 08:37:15 +00002499
2500 UnloadPage(page);
2501}
Lei Zhang671aece2020-04-14 19:02:26 +00002502
Hui Yingst609f7d62020-04-23 23:14:13 +00002503// TODO(crbug.com/pdfium/11): Fix this test and enable.
2504#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2505#define MAYBE_FocusableAnnotRendering DISABLED_FocusableAnnotRendering
2506#else
2507#define MAYBE_FocusableAnnotRendering FocusableAnnotRendering
2508#endif
2509TEST_F(FPDFAnnotEmbedderTest, MAYBE_FocusableAnnotRendering) {
Lei Zhang671aece2020-04-14 19:02:26 +00002510 ASSERT_TRUE(OpenDocument("annots.pdf"));
2511 FPDF_PAGE page = LoadPage(0);
2512 ASSERT_TRUE(page);
2513
2514 {
2515#if defined(OS_WIN)
2516 static const char kMd5sum[] = "3877bec7cb3e3144eaa6d10f38bf7a30";
2517#elif defined(OS_MACOSX)
2518 static const char kMd5sum[] = "04b16db5026b5490a50fb6ff0954c867";
2519#else
2520 static const char kMd5sum[] = "40a7354d1f653127bcdac10e15f81654";
2521#endif
2522 // Check the initial rendering.
2523 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
2524 CompareBitmap(bitmap.get(), 612, 792, kMd5sum);
2525 }
2526
2527 // Make links and highlights focusable.
2528 static constexpr FPDF_ANNOTATION_SUBTYPE kSubTypes[] = {FPDF_ANNOT_LINK,
2529 FPDF_ANNOT_HIGHLIGHT};
2530 constexpr int kSubTypesCount = FX_ArraySize(kSubTypes);
2531 ASSERT_TRUE(
2532 FPDFAnnot_SetFocusableSubtypes(form_handle(), kSubTypes, kSubTypesCount));
2533 ASSERT_EQ(kSubTypesCount, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
2534 std::vector<FPDF_ANNOTATION_SUBTYPE> subtypes(kSubTypesCount);
2535 ASSERT_TRUE(FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(),
2536 subtypes.size()));
2537 ASSERT_EQ(FPDF_ANNOT_LINK, subtypes[0]);
2538 ASSERT_EQ(FPDF_ANNOT_HIGHLIGHT, subtypes[1]);
2539
2540 {
2541#if defined(OS_WIN)
2542 static const char kMd5sum[] = "a30f1bd1cac022d08ceb100df4940b5f";
2543#elif defined(OS_MACOSX)
2544 static const char kMd5sum[] = "3f984a164f2f6d6e3d69f27fd430e346";
2545#else
2546 static const char kMd5sum[] = "e4c4de73addabf10672c308870e8a4ee";
2547#endif
2548 // Focus the first link and check the rendering.
2549 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2550 ASSERT_TRUE(annot);
2551 EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
2552 EXPECT_TRUE(FORM_SetFocusedAnnot(form_handle(), annot.get()));
2553 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
2554 CompareBitmap(bitmap.get(), 612, 792, kMd5sum);
2555 }
2556
2557 {
2558#if defined(OS_WIN)
2559 static const char kMd5sum[] = "467f5a4db98fcadd5121807ff4e2eb10";
2560#elif defined(OS_MACOSX)
2561 static const char kMd5sum[] = "c6d6f9dc7090e8eaf3867ba714023b1e";
2562#else
2563 static const char kMd5sum[] = "65e831885e16b7ecc977cce2e4a27110";
2564#endif
2565 // Focus the first highlight and check the rendering.
2566 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 4));
2567 ASSERT_TRUE(annot);
2568 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
2569 EXPECT_TRUE(FORM_SetFocusedAnnot(form_handle(), annot.get()));
2570 ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
2571 CompareBitmap(bitmap.get(), 612, 792, kMd5sum);
2572 }
2573
2574 UnloadPage(page);
2575}
Badhri Ravikumarcd628912020-05-07 19:23:51 +00002576
2577TEST_F(FPDFAnnotEmbedderTest, GetLinkFromAnnotation) {
2578 ASSERT_TRUE(OpenDocument("annots.pdf"));
2579 FPDF_PAGE page = LoadPage(0);
2580 ASSERT_TRUE(page);
2581 {
2582 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
2583 ASSERT_TRUE(annot);
2584 EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
2585 FPDF_LINK link_annot = FPDFAnnot_GetLink(annot.get());
2586 ASSERT_TRUE(link_annot);
2587
2588 FPDF_ACTION action = FPDFLink_GetAction(link_annot);
2589 ASSERT_TRUE(action);
2590 EXPECT_EQ(static_cast<unsigned long>(PDFACTION_URI),
2591 FPDFAction_GetType(action));
2592
2593 constexpr char kExpectedResult[] =
2594 "https://cs.chromium.org/chromium/src/third_party/pdfium/public/"
2595 "fpdf_text.h";
2596 constexpr unsigned long kExpectedLength = FX_ArraySize(kExpectedResult);
2597 unsigned long bufsize =
2598 FPDFAction_GetURIPath(document(), action, nullptr, 0);
2599 ASSERT_EQ(kExpectedLength, bufsize);
2600
2601 char buffer[1024];
2602 EXPECT_EQ(bufsize,
2603 FPDFAction_GetURIPath(document(), action, buffer, bufsize));
2604 EXPECT_STREQ(kExpectedResult, buffer);
2605 }
2606
2607 {
2608 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 4));
2609 ASSERT_TRUE(annot);
2610 EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
2611 EXPECT_FALSE(FPDFAnnot_GetLink(annot.get()));
2612 }
2613
2614 EXPECT_FALSE(FPDFAnnot_GetLink(nullptr));
2615
2616 UnloadPage(page);
2617}