1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2017 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker #include "public/fpdf_annot.h"
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include <limits.h>
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include <algorithm>
10*3ac0a46fSAndroid Build Coastguard Worker #include <string>
11*3ac0a46fSAndroid Build Coastguard Worker #include <vector>
12*3ac0a46fSAndroid Build Coastguard Worker
13*3ac0a46fSAndroid Build Coastguard Worker #include "build/build_config.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "constants/annotation_common.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_annotcontext.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_array.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_dictionary.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_system.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_defaultrenderdevice.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_helpers.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "public/cpp/fpdf_scopers.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "public/fpdf_edit.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "public/fpdf_formfill.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "public/fpdfview.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "testing/embedder_test.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "testing/embedder_test_constants.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "testing/fx_string_testhelpers.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock-matchers.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "testing/utils/hash.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/contains.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/span.h"
33*3ac0a46fSAndroid Build Coastguard Worker
34*3ac0a46fSAndroid Build Coastguard Worker using pdfium::AnnotationStampWithApChecksum;
35*3ac0a46fSAndroid Build Coastguard Worker
36*3ac0a46fSAndroid Build Coastguard Worker namespace {
37*3ac0a46fSAndroid Build Coastguard Worker
38*3ac0a46fSAndroid Build Coastguard Worker const wchar_t kStreamData[] =
39*3ac0a46fSAndroid Build Coastguard Worker L"/GS gs 0.0 0.0 0.0 RG 4 w 211.8 747.6 m 211.8 744.8 "
40*3ac0a46fSAndroid Build Coastguard Worker L"212.6 743.0 214.2 740.8 "
41*3ac0a46fSAndroid Build Coastguard Worker L"c 215.4 739.0 216.8 737.1 218.9 736.1 c 220.8 735.1 221.4 733.0 "
42*3ac0a46fSAndroid Build Coastguard Worker L"223.7 732.4 c 232.6 729.9 242.0 730.8 251.2 730.8 c 257.5 730.8 "
43*3ac0a46fSAndroid Build Coastguard Worker L"263.0 732.9 269.0 734.4 c S";
44*3ac0a46fSAndroid Build Coastguard Worker
VerifyFocusableAnnotSubtypes(FPDF_FORMHANDLE form_handle,pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_subtypes)45*3ac0a46fSAndroid Build Coastguard Worker void VerifyFocusableAnnotSubtypes(
46*3ac0a46fSAndroid Build Coastguard Worker FPDF_FORMHANDLE form_handle,
47*3ac0a46fSAndroid Build Coastguard Worker pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_subtypes) {
48*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<int>(expected_subtypes.size()),
49*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFocusableSubtypesCount(form_handle));
50*3ac0a46fSAndroid Build Coastguard Worker
51*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_ANNOTATION_SUBTYPE> actual_subtypes(
52*3ac0a46fSAndroid Build Coastguard Worker expected_subtypes.size());
53*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetFocusableSubtypes(
54*3ac0a46fSAndroid Build Coastguard Worker form_handle, actual_subtypes.data(), actual_subtypes.size()));
55*3ac0a46fSAndroid Build Coastguard Worker for (size_t i = 0; i < expected_subtypes.size(); ++i)
56*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(expected_subtypes[i], actual_subtypes[i]);
57*3ac0a46fSAndroid Build Coastguard Worker }
58*3ac0a46fSAndroid Build Coastguard Worker
SetAndVerifyFocusableAnnotSubtypes(FPDF_FORMHANDLE form_handle,pdfium::span<const FPDF_ANNOTATION_SUBTYPE> subtypes)59*3ac0a46fSAndroid Build Coastguard Worker void SetAndVerifyFocusableAnnotSubtypes(
60*3ac0a46fSAndroid Build Coastguard Worker FPDF_FORMHANDLE form_handle,
61*3ac0a46fSAndroid Build Coastguard Worker pdfium::span<const FPDF_ANNOTATION_SUBTYPE> subtypes) {
62*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetFocusableSubtypes(form_handle, subtypes.data(),
63*3ac0a46fSAndroid Build Coastguard Worker subtypes.size()));
64*3ac0a46fSAndroid Build Coastguard Worker VerifyFocusableAnnotSubtypes(form_handle, subtypes);
65*3ac0a46fSAndroid Build Coastguard Worker }
66*3ac0a46fSAndroid Build Coastguard Worker
VerifyAnnotationSubtypesAndFocusability(FPDF_FORMHANDLE form_handle,FPDF_PAGE page,pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_subtypes,pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_focusable_subtypes)67*3ac0a46fSAndroid Build Coastguard Worker void VerifyAnnotationSubtypesAndFocusability(
68*3ac0a46fSAndroid Build Coastguard Worker FPDF_FORMHANDLE form_handle,
69*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page,
70*3ac0a46fSAndroid Build Coastguard Worker pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_subtypes,
71*3ac0a46fSAndroid Build Coastguard Worker pdfium::span<const FPDF_ANNOTATION_SUBTYPE> expected_focusable_subtypes) {
72*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<int>(expected_subtypes.size()),
73*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_GetAnnotCount(page));
74*3ac0a46fSAndroid Build Coastguard Worker for (size_t i = 0; i < expected_subtypes.size(); ++i) {
75*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
76*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
77*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(expected_subtypes[i], FPDFAnnot_GetSubtype(annot.get()));
78*3ac0a46fSAndroid Build Coastguard Worker
79*3ac0a46fSAndroid Build Coastguard Worker bool expected_focusable =
80*3ac0a46fSAndroid Build Coastguard Worker pdfium::Contains(expected_focusable_subtypes, expected_subtypes[i]);
81*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(expected_focusable,
82*3ac0a46fSAndroid Build Coastguard Worker FORM_SetFocusedAnnot(form_handle, annot.get()));
83*3ac0a46fSAndroid Build Coastguard Worker
84*3ac0a46fSAndroid Build Coastguard Worker // Kill the focus so the next test starts in an unfocused state.
85*3ac0a46fSAndroid Build Coastguard Worker FORM_ForceToKillFocus(form_handle);
86*3ac0a46fSAndroid Build Coastguard Worker }
87*3ac0a46fSAndroid Build Coastguard Worker }
88*3ac0a46fSAndroid Build Coastguard Worker
VerifyUriActionInLink(FPDF_DOCUMENT doc,FPDF_LINK link,const std::string & expected_uri)89*3ac0a46fSAndroid Build Coastguard Worker void VerifyUriActionInLink(FPDF_DOCUMENT doc,
90*3ac0a46fSAndroid Build Coastguard Worker FPDF_LINK link,
91*3ac0a46fSAndroid Build Coastguard Worker const std::string& expected_uri) {
92*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(link);
93*3ac0a46fSAndroid Build Coastguard Worker
94*3ac0a46fSAndroid Build Coastguard Worker FPDF_ACTION action = FPDFLink_GetAction(link);
95*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(action);
96*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(static_cast<unsigned long>(PDFACTION_URI),
97*3ac0a46fSAndroid Build Coastguard Worker FPDFAction_GetType(action));
98*3ac0a46fSAndroid Build Coastguard Worker
99*3ac0a46fSAndroid Build Coastguard Worker unsigned long bufsize = FPDFAction_GetURIPath(doc, action, nullptr, 0);
100*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(expected_uri.size() + 1, bufsize);
101*3ac0a46fSAndroid Build Coastguard Worker
102*3ac0a46fSAndroid Build Coastguard Worker std::vector<char> buffer(bufsize);
103*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(bufsize,
104*3ac0a46fSAndroid Build Coastguard Worker FPDFAction_GetURIPath(doc, action, buffer.data(), bufsize));
105*3ac0a46fSAndroid Build Coastguard Worker EXPECT_STREQ(expected_uri.c_str(), buffer.data());
106*3ac0a46fSAndroid Build Coastguard Worker }
107*3ac0a46fSAndroid Build Coastguard Worker
108*3ac0a46fSAndroid Build Coastguard Worker } // namespace
109*3ac0a46fSAndroid Build Coastguard Worker
110*3ac0a46fSAndroid Build Coastguard Worker class FPDFAnnotEmbedderTest : public EmbedderTest {};
111*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,SetAP)112*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, SetAP) {
113*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFDocument doc(FPDF_CreateNewDocument());
114*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(doc);
115*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
116*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
117*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString ap_stream = GetFPDFWideString(kStreamData);
118*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(ap_stream);
119*3ac0a46fSAndroid Build Coastguard Worker
120*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
121*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
122*3ac0a46fSAndroid Build Coastguard Worker
123*3ac0a46fSAndroid Build Coastguard Worker // Negative case: FPDFAnnot_SetAP() should fail if bounding rect is not yet
124*3ac0a46fSAndroid Build Coastguard Worker // set on the annotation.
125*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
126*3ac0a46fSAndroid Build Coastguard Worker ap_stream.get()));
127*3ac0a46fSAndroid Build Coastguard Worker
128*3ac0a46fSAndroid Build Coastguard Worker const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
129*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
130*3ac0a46fSAndroid Build Coastguard Worker
131*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color,
132*3ac0a46fSAndroid Build Coastguard Worker /*R=*/255, /*G=*/0, /*B=*/0, /*A=*/255));
133*3ac0a46fSAndroid Build Coastguard Worker
134*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
135*3ac0a46fSAndroid Build Coastguard Worker ap_stream.get()));
136*3ac0a46fSAndroid Build Coastguard Worker
137*3ac0a46fSAndroid Build Coastguard Worker // Verify that appearance stream is created as form XObject
138*3ac0a46fSAndroid Build Coastguard Worker CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot.get());
139*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(context);
140*3ac0a46fSAndroid Build Coastguard Worker const CPDF_Dictionary* annot_dict = context->GetAnnotDict();
141*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot_dict);
142*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> ap_dict =
143*3ac0a46fSAndroid Build Coastguard Worker annot_dict->GetDictFor(pdfium::annotation::kAP);
144*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(ap_dict);
145*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> stream_dict = ap_dict->GetDictFor("N");
146*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(stream_dict);
147*3ac0a46fSAndroid Build Coastguard Worker // Check for non-existence of resources dictionary in case of opaque color
148*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> resources_dict =
149*3ac0a46fSAndroid Build Coastguard Worker stream_dict->GetDictFor("Resources");
150*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(resources_dict);
151*3ac0a46fSAndroid Build Coastguard Worker ByteString type = stream_dict->GetByteStringFor(pdfium::annotation::kType);
152*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ("XObject", type);
153*3ac0a46fSAndroid Build Coastguard Worker ByteString sub_type =
154*3ac0a46fSAndroid Build Coastguard Worker stream_dict->GetByteStringFor(pdfium::annotation::kSubtype);
155*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ("Form", sub_type);
156*3ac0a46fSAndroid Build Coastguard Worker
157*3ac0a46fSAndroid Build Coastguard Worker // Check that the appearance stream is same as we just set.
158*3ac0a46fSAndroid Build Coastguard Worker const uint32_t kStreamDataSize = std::size(kStreamData) * sizeof(FPDF_WCHAR);
159*3ac0a46fSAndroid Build Coastguard Worker unsigned long normal_length_bytes = FPDFAnnot_GetAP(
160*3ac0a46fSAndroid Build Coastguard Worker annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
161*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kStreamDataSize, normal_length_bytes);
162*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(normal_length_bytes);
163*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kStreamDataSize,
164*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
165*3ac0a46fSAndroid Build Coastguard Worker buf.data(), normal_length_bytes));
166*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kStreamData, GetPlatformWString(buf.data()));
167*3ac0a46fSAndroid Build Coastguard Worker }
168*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,SetAPWithOpacity)169*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, SetAPWithOpacity) {
170*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFDocument doc(FPDF_CreateNewDocument());
171*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(doc);
172*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
173*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
174*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString ap_stream = GetFPDFWideString(kStreamData);
175*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(ap_stream);
176*3ac0a46fSAndroid Build Coastguard Worker
177*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
178*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
179*3ac0a46fSAndroid Build Coastguard Worker
180*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color,
181*3ac0a46fSAndroid Build Coastguard Worker /*R=*/255, /*G=*/0, /*B=*/0, /*A=*/102));
182*3ac0a46fSAndroid Build Coastguard Worker
183*3ac0a46fSAndroid Build Coastguard Worker const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
184*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
185*3ac0a46fSAndroid Build Coastguard Worker
186*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
187*3ac0a46fSAndroid Build Coastguard Worker ap_stream.get()));
188*3ac0a46fSAndroid Build Coastguard Worker
189*3ac0a46fSAndroid Build Coastguard Worker CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot.get());
190*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(context);
191*3ac0a46fSAndroid Build Coastguard Worker const CPDF_Dictionary* annot_dict = context->GetAnnotDict();
192*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot_dict);
193*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> ap_dict =
194*3ac0a46fSAndroid Build Coastguard Worker annot_dict->GetDictFor(pdfium::annotation::kAP);
195*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(ap_dict);
196*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> stream_dict = ap_dict->GetDictFor("N");
197*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(stream_dict);
198*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> resources_dict =
199*3ac0a46fSAndroid Build Coastguard Worker stream_dict->GetDictFor("Resources");
200*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(stream_dict);
201*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> extGState_dict =
202*3ac0a46fSAndroid Build Coastguard Worker resources_dict->GetDictFor("ExtGState");
203*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(extGState_dict);
204*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> gs_dict = extGState_dict->GetDictFor("GS");
205*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(gs_dict);
206*3ac0a46fSAndroid Build Coastguard Worker ByteString type = gs_dict->GetByteStringFor(pdfium::annotation::kType);
207*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ("ExtGState", type);
208*3ac0a46fSAndroid Build Coastguard Worker float opacity = gs_dict->GetFloatFor("CA");
209*3ac0a46fSAndroid Build Coastguard Worker // Opacity value of 102 is represented as 0.4f (=104/255) in /CA entry.
210*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(0.4f, opacity);
211*3ac0a46fSAndroid Build Coastguard Worker ByteString blend_mode = gs_dict->GetByteStringFor("BM");
212*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ("Normal", blend_mode);
213*3ac0a46fSAndroid Build Coastguard Worker bool alpha_source_flag = gs_dict->GetBooleanFor("AIS", true);
214*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(alpha_source_flag);
215*3ac0a46fSAndroid Build Coastguard Worker }
216*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,InkListAPIValidations)217*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, InkListAPIValidations) {
218*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFDocument doc(FPDF_CreateNewDocument());
219*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(doc);
220*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
221*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
222*3ac0a46fSAndroid Build Coastguard Worker
223*3ac0a46fSAndroid Build Coastguard Worker // Create a new ink annotation.
224*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation ink_annot(
225*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
226*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(ink_annot);
227*3ac0a46fSAndroid Build Coastguard Worker CPDF_AnnotContext* context =
228*3ac0a46fSAndroid Build Coastguard Worker CPDFAnnotContextFromFPDFAnnotation(ink_annot.get());
229*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(context);
230*3ac0a46fSAndroid Build Coastguard Worker const CPDF_Dictionary* annot_dict = context->GetAnnotDict();
231*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot_dict);
232*3ac0a46fSAndroid Build Coastguard Worker
233*3ac0a46fSAndroid Build Coastguard Worker static constexpr FS_POINTF kFirstInkStroke[] = {
234*3ac0a46fSAndroid Build Coastguard Worker {80.0f, 90.0f}, {81.0f, 91.0f}, {82.0f, 92.0f},
235*3ac0a46fSAndroid Build Coastguard Worker {83.0f, 93.0f}, {84.0f, 94.0f}, {85.0f, 95.0f}};
236*3ac0a46fSAndroid Build Coastguard Worker static constexpr size_t kFirstStrokePointCount = std::size(kFirstInkStroke);
237*3ac0a46fSAndroid Build Coastguard Worker
238*3ac0a46fSAndroid Build Coastguard Worker static constexpr FS_POINTF kSecondInkStroke[] = {
239*3ac0a46fSAndroid Build Coastguard Worker {70.0f, 90.0f}, {71.0f, 91.0f}, {72.0f, 92.0f}};
240*3ac0a46fSAndroid Build Coastguard Worker static constexpr size_t kSecondStrokePointCount = std::size(kSecondInkStroke);
241*3ac0a46fSAndroid Build Coastguard Worker
242*3ac0a46fSAndroid Build Coastguard Worker static constexpr FS_POINTF kThirdInkStroke[] = {{60.0f, 90.0f},
243*3ac0a46fSAndroid Build Coastguard Worker {61.0f, 91.0f},
244*3ac0a46fSAndroid Build Coastguard Worker {62.0f, 92.0f},
245*3ac0a46fSAndroid Build Coastguard Worker {63.0f, 93.0f},
246*3ac0a46fSAndroid Build Coastguard Worker {64.0f, 94.0f}};
247*3ac0a46fSAndroid Build Coastguard Worker static constexpr size_t kThirdStrokePointCount = std::size(kThirdInkStroke);
248*3ac0a46fSAndroid Build Coastguard Worker
249*3ac0a46fSAndroid Build Coastguard Worker // Negative test: |annot| is passed as nullptr.
250*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(nullptr, kFirstInkStroke,
251*3ac0a46fSAndroid Build Coastguard Worker kFirstStrokePointCount));
252*3ac0a46fSAndroid Build Coastguard Worker
253*3ac0a46fSAndroid Build Coastguard Worker // Negative test: |annot| is not ink annotation.
254*3ac0a46fSAndroid Build Coastguard Worker // Create a new highlight annotation.
255*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation highlight_annot(
256*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_HIGHLIGHT));
257*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(highlight_annot);
258*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(highlight_annot.get(), kFirstInkStroke,
259*3ac0a46fSAndroid Build Coastguard Worker kFirstStrokePointCount));
260*3ac0a46fSAndroid Build Coastguard Worker
261*3ac0a46fSAndroid Build Coastguard Worker // Negative test: passing |point_count| as 0.
262*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), kFirstInkStroke, 0));
263*3ac0a46fSAndroid Build Coastguard Worker
264*3ac0a46fSAndroid Build Coastguard Worker // Negative test: passing |points| array as nullptr.
265*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), nullptr,
266*3ac0a46fSAndroid Build Coastguard Worker kFirstStrokePointCount));
267*3ac0a46fSAndroid Build Coastguard Worker
268*3ac0a46fSAndroid Build Coastguard Worker // Negative test: passing |point_count| more than ULONG_MAX/2.
269*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), kSecondInkStroke,
270*3ac0a46fSAndroid Build Coastguard Worker ULONG_MAX / 2 + 1));
271*3ac0a46fSAndroid Build Coastguard Worker
272*3ac0a46fSAndroid Build Coastguard Worker // InkStroke should get added to ink annotation. Also inklist should get
273*3ac0a46fSAndroid Build Coastguard Worker // created.
274*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, FPDFAnnot_AddInkStroke(ink_annot.get(), kFirstInkStroke,
275*3ac0a46fSAndroid Build Coastguard Worker kFirstStrokePointCount));
276*3ac0a46fSAndroid Build Coastguard Worker
277*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Array> inklist = annot_dict->GetArrayFor("InkList");
278*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(inklist);
279*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, inklist->size());
280*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kFirstStrokePointCount * 2, inklist->GetArrayAt(0)->size());
281*3ac0a46fSAndroid Build Coastguard Worker
282*3ac0a46fSAndroid Build Coastguard Worker // Adding another inkStroke to ink annotation with all valid paremeters.
283*3ac0a46fSAndroid Build Coastguard Worker // InkList already exists in ink_annot.
284*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_AddInkStroke(ink_annot.get(), kSecondInkStroke,
285*3ac0a46fSAndroid Build Coastguard Worker kSecondStrokePointCount));
286*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, inklist->size());
287*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kSecondStrokePointCount * 2, inklist->GetArrayAt(1)->size());
288*3ac0a46fSAndroid Build Coastguard Worker
289*3ac0a46fSAndroid Build Coastguard Worker // Adding one more InkStroke to the ink annotation. |point_count| passed is
290*3ac0a46fSAndroid Build Coastguard Worker // less than the data available in |buffer|.
291*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFAnnot_AddInkStroke(ink_annot.get(), kThirdInkStroke,
292*3ac0a46fSAndroid Build Coastguard Worker kThirdStrokePointCount - 1));
293*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3u, inklist->size());
294*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ((kThirdStrokePointCount - 1) * 2, inklist->GetArrayAt(2)->size());
295*3ac0a46fSAndroid Build Coastguard Worker }
296*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,RemoveInkList)297*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, RemoveInkList) {
298*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFDocument doc(FPDF_CreateNewDocument());
299*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(doc);
300*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
301*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
302*3ac0a46fSAndroid Build Coastguard Worker
303*3ac0a46fSAndroid Build Coastguard Worker // Negative test: |annot| is passed as nullptr.
304*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_RemoveInkList(nullptr));
305*3ac0a46fSAndroid Build Coastguard Worker
306*3ac0a46fSAndroid Build Coastguard Worker // Negative test: |annot| is not ink annotation.
307*3ac0a46fSAndroid Build Coastguard Worker // Create a new highlight annotation.
308*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation highlight_annot(
309*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_HIGHLIGHT));
310*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(highlight_annot);
311*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_RemoveInkList(highlight_annot.get()));
312*3ac0a46fSAndroid Build Coastguard Worker
313*3ac0a46fSAndroid Build Coastguard Worker // Create a new ink annotation.
314*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation ink_annot(
315*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
316*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(ink_annot);
317*3ac0a46fSAndroid Build Coastguard Worker CPDF_AnnotContext* context =
318*3ac0a46fSAndroid Build Coastguard Worker CPDFAnnotContextFromFPDFAnnotation(ink_annot.get());
319*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(context);
320*3ac0a46fSAndroid Build Coastguard Worker const CPDF_Dictionary* annot_dict = context->GetAnnotDict();
321*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot_dict);
322*3ac0a46fSAndroid Build Coastguard Worker
323*3ac0a46fSAndroid Build Coastguard Worker static constexpr FS_POINTF kInkStroke[] = {{80.0f, 90.0f}, {81.0f, 91.0f},
324*3ac0a46fSAndroid Build Coastguard Worker {82.0f, 92.0f}, {83.0f, 93.0f},
325*3ac0a46fSAndroid Build Coastguard Worker {84.0f, 94.0f}, {85.0f, 95.0f}};
326*3ac0a46fSAndroid Build Coastguard Worker static constexpr size_t kPointCount = std::size(kInkStroke);
327*3ac0a46fSAndroid Build Coastguard Worker
328*3ac0a46fSAndroid Build Coastguard Worker // InkStroke should get added to ink annotation. Also inklist should get
329*3ac0a46fSAndroid Build Coastguard Worker // created.
330*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0,
331*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_AddInkStroke(ink_annot.get(), kInkStroke, kPointCount));
332*3ac0a46fSAndroid Build Coastguard Worker
333*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Array> inklist = annot_dict->GetArrayFor("InkList");
334*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(inklist);
335*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(1u, inklist->size());
336*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kPointCount * 2, inklist->GetArrayAt(0)->size());
337*3ac0a46fSAndroid Build Coastguard Worker
338*3ac0a46fSAndroid Build Coastguard Worker // Remove inklist.
339*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_RemoveInkList(ink_annot.get()));
340*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(annot_dict->KeyExist("InkList"));
341*3ac0a46fSAndroid Build Coastguard Worker }
342*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,BadParams)343*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, BadParams) {
344*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("hello_world.pdf"));
345*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
346*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
347*3ac0a46fSAndroid Build Coastguard Worker
348*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, FPDFPage_GetAnnotCount(nullptr));
349*3ac0a46fSAndroid Build Coastguard Worker
350*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, 0));
351*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, -1));
352*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_GetAnnot(nullptr, 1));
353*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_GetAnnot(page, -1));
354*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_GetAnnot(page, 1));
355*3ac0a46fSAndroid Build Coastguard Worker
356*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_UNKNOWN, FPDFAnnot_GetSubtype(nullptr));
357*3ac0a46fSAndroid Build Coastguard Worker
358*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, FPDFAnnot_GetObjectCount(nullptr));
359*3ac0a46fSAndroid Build Coastguard Worker
360*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, 0));
361*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, -1));
362*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetObject(nullptr, 1));
363*3ac0a46fSAndroid Build Coastguard Worker
364*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_HasKey(nullptr, "foo"));
365*3ac0a46fSAndroid Build Coastguard Worker
366*3ac0a46fSAndroid Build Coastguard Worker static const wchar_t kContents[] = L"Bar";
367*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString text = GetFPDFWideString(kContents);
368*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetStringValue(nullptr, "foo", text.get()));
369*3ac0a46fSAndroid Build Coastguard Worker
370*3ac0a46fSAndroid Build Coastguard Worker FPDF_WCHAR buffer[64];
371*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetStringValue(nullptr, "foo", nullptr, 0));
372*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetStringValue(nullptr, "foo", buffer, 0));
373*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u,
374*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetStringValue(nullptr, "foo", buffer, sizeof(buffer)));
375*3ac0a46fSAndroid Build Coastguard Worker
376*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
377*3ac0a46fSAndroid Build Coastguard Worker }
378*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,BadAnnotsEntry)379*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, BadAnnotsEntry) {
380*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("bad_annots_entry.pdf"));
381*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
382*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
383*3ac0a46fSAndroid Build Coastguard Worker
384*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
385*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_GetAnnot(page, 0));
386*3ac0a46fSAndroid Build Coastguard Worker
387*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
388*3ac0a46fSAndroid Build Coastguard Worker }
389*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,RenderAnnotWithOnlyRolloverAP)390*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, RenderAnnotWithOnlyRolloverAP) {
391*3ac0a46fSAndroid Build Coastguard Worker // Open a file with one annotation and load its first page.
392*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
393*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
394*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
395*3ac0a46fSAndroid Build Coastguard Worker
396*3ac0a46fSAndroid Build Coastguard Worker // This annotation has a malformed appearance stream, which does not have its
397*3ac0a46fSAndroid Build Coastguard Worker // normal appearance defined, only its rollover appearance. In this case, its
398*3ac0a46fSAndroid Build Coastguard Worker // normal appearance should be generated, allowing the highlight annotation to
399*3ac0a46fSAndroid Build Coastguard Worker // still display.
400*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
401*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
402*3ac0a46fSAndroid Build Coastguard Worker
403*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
404*3ac0a46fSAndroid Build Coastguard Worker }
405*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,RenderMultilineMarkupAnnotWithoutAP)406*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, RenderMultilineMarkupAnnotWithoutAP) {
407*3ac0a46fSAndroid Build Coastguard Worker const char* checksum = []() {
408*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
409*3ac0a46fSAndroid Build Coastguard Worker return "ec1f4ccbd0aecfdea6d53893387a0101";
410*3ac0a46fSAndroid Build Coastguard Worker return "76512832d88017668d9acc7aacd13dae";
411*3ac0a46fSAndroid Build Coastguard Worker }();
412*3ac0a46fSAndroid Build Coastguard Worker
413*3ac0a46fSAndroid Build Coastguard Worker // Open a file with multiline markup annotations.
414*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_markup_multiline_no_ap.pdf"));
415*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
416*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
417*3ac0a46fSAndroid Build Coastguard Worker
418*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
419*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, checksum);
420*3ac0a46fSAndroid Build Coastguard Worker
421*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
422*3ac0a46fSAndroid Build Coastguard Worker }
423*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,ExtractHighlightLongContent)424*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, ExtractHighlightLongContent) {
425*3ac0a46fSAndroid Build Coastguard Worker // Open a file with one annotation and load its first page.
426*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
427*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPageNoEvents(0);
428*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
429*3ac0a46fSAndroid Build Coastguard Worker
430*3ac0a46fSAndroid Build Coastguard Worker // Check that there is a total of 1 annotation on its first page.
431*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
432*3ac0a46fSAndroid Build Coastguard Worker
433*3ac0a46fSAndroid Build Coastguard Worker // Check that the annotation is of type "highlight".
434*3ac0a46fSAndroid Build Coastguard Worker {
435*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
436*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
437*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
438*3ac0a46fSAndroid Build Coastguard Worker
439*3ac0a46fSAndroid Build Coastguard Worker // Check that the annotation color is yellow.
440*3ac0a46fSAndroid Build Coastguard Worker unsigned int R;
441*3ac0a46fSAndroid Build Coastguard Worker unsigned int G;
442*3ac0a46fSAndroid Build Coastguard Worker unsigned int B;
443*3ac0a46fSAndroid Build Coastguard Worker unsigned int A;
444*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
445*3ac0a46fSAndroid Build Coastguard Worker &G, &B, &A));
446*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(255u, R);
447*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(255u, G);
448*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, B);
449*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(255u, A);
450*3ac0a46fSAndroid Build Coastguard Worker
451*3ac0a46fSAndroid Build Coastguard Worker // Check that the author is correct.
452*3ac0a46fSAndroid Build Coastguard Worker static const char kAuthorKey[] = "T";
453*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_OBJECT_STRING,
454*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetValueType(annot.get(), kAuthorKey));
455*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
456*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetStringValue(annot.get(), kAuthorKey, nullptr, 0);
457*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(28u, length_bytes);
458*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
459*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(28u, FPDFAnnot_GetStringValue(annot.get(), kAuthorKey, buf.data(),
460*3ac0a46fSAndroid Build Coastguard Worker length_bytes));
461*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Jae Hyun Park", GetPlatformWString(buf.data()));
462*3ac0a46fSAndroid Build Coastguard Worker
463*3ac0a46fSAndroid Build Coastguard Worker // Check that the content is correct.
464*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(
465*3ac0a46fSAndroid Build Coastguard Worker FPDF_OBJECT_STRING,
466*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kContents));
467*3ac0a46fSAndroid Build Coastguard Worker length_bytes = FPDFAnnot_GetStringValue(
468*3ac0a46fSAndroid Build Coastguard Worker annot.get(), pdfium::annotation::kContents, nullptr, 0);
469*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(2690u, length_bytes);
470*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(length_bytes);
471*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2690u, FPDFAnnot_GetStringValue(annot.get(),
472*3ac0a46fSAndroid Build Coastguard Worker pdfium::annotation::kContents,
473*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
474*3ac0a46fSAndroid Build Coastguard Worker static const wchar_t kContents[] =
475*3ac0a46fSAndroid Build Coastguard Worker L"This is a note for that highlight annotation. Very long highlight "
476*3ac0a46fSAndroid Build Coastguard Worker "annotation. Long long long Long long longLong long longLong long "
477*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
478*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
479*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
480*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
481*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
482*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
483*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
484*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
485*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
486*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
487*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
488*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
489*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
490*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
491*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
492*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
493*3ac0a46fSAndroid Build Coastguard Worker "longLong long longLong long longLong long longLong long longLong long "
494*3ac0a46fSAndroid Build Coastguard Worker "longLong long long. END";
495*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kContents, GetPlatformWString(buf.data()));
496*3ac0a46fSAndroid Build Coastguard Worker
497*3ac0a46fSAndroid Build Coastguard Worker // Check that the quadpoints are correct.
498*3ac0a46fSAndroid Build Coastguard Worker FS_QUADPOINTSF quadpoints;
499*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
500*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(115.802643f, quadpoints.x1);
501*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(718.913940f, quadpoints.y1);
502*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(157.211182f, quadpoints.x4);
503*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(706.264465f, quadpoints.y4);
504*3ac0a46fSAndroid Build Coastguard Worker }
505*3ac0a46fSAndroid Build Coastguard Worker UnloadPageNoEvents(page);
506*3ac0a46fSAndroid Build Coastguard Worker }
507*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,ExtractInkMultiple)508*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, ExtractInkMultiple) {
509*3ac0a46fSAndroid Build Coastguard Worker // Open a file with three annotations and load its first page.
510*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
511*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPageNoEvents(0);
512*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
513*3ac0a46fSAndroid Build Coastguard Worker
514*3ac0a46fSAndroid Build Coastguard Worker // Check that there is a total of 3 annotation on its first page.
515*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
516*3ac0a46fSAndroid Build Coastguard Worker
517*3ac0a46fSAndroid Build Coastguard Worker {
518*3ac0a46fSAndroid Build Coastguard Worker // Check that the third annotation is of type "ink".
519*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
520*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
521*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot.get()));
522*3ac0a46fSAndroid Build Coastguard Worker
523*3ac0a46fSAndroid Build Coastguard Worker // Check that the annotation color is blue with opacity.
524*3ac0a46fSAndroid Build Coastguard Worker unsigned int R;
525*3ac0a46fSAndroid Build Coastguard Worker unsigned int G;
526*3ac0a46fSAndroid Build Coastguard Worker unsigned int B;
527*3ac0a46fSAndroid Build Coastguard Worker unsigned int A;
528*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
529*3ac0a46fSAndroid Build Coastguard Worker &G, &B, &A));
530*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, R);
531*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, G);
532*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(255u, B);
533*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(76u, A);
534*3ac0a46fSAndroid Build Coastguard Worker
535*3ac0a46fSAndroid Build Coastguard Worker // Check that there is no content.
536*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, FPDFAnnot_GetStringValue(
537*3ac0a46fSAndroid Build Coastguard Worker annot.get(), pdfium::annotation::kContents, nullptr, 0));
538*3ac0a46fSAndroid Build Coastguard Worker
539*3ac0a46fSAndroid Build Coastguard Worker // Check that the rectangle coordinates are correct.
540*3ac0a46fSAndroid Build Coastguard Worker // Note that upon rendering, the rectangle coordinates will be adjusted.
541*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF rect;
542*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
543*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(351.820404f, rect.left);
544*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(583.830688f, rect.bottom);
545*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(475.336090f, rect.right);
546*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(681.535034f, rect.top);
547*3ac0a46fSAndroid Build Coastguard Worker }
548*3ac0a46fSAndroid Build Coastguard Worker {
549*3ac0a46fSAndroid Build Coastguard Worker const char* expected_hash = []() {
550*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
551*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
552*3ac0a46fSAndroid Build Coastguard Worker return "6e00cc75639c5314c8273072915d8f92";
553*3ac0a46fSAndroid Build Coastguard Worker #else
554*3ac0a46fSAndroid Build Coastguard Worker return "1fb0dd8dd5f0b9bb8d076e48eb59296d";
555*3ac0a46fSAndroid Build Coastguard Worker #endif
556*3ac0a46fSAndroid Build Coastguard Worker }
557*3ac0a46fSAndroid Build Coastguard Worker return "354002e1c4386d38fdde29ef8d61074a";
558*3ac0a46fSAndroid Build Coastguard Worker }();
559*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
560*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, expected_hash);
561*3ac0a46fSAndroid Build Coastguard Worker }
562*3ac0a46fSAndroid Build Coastguard Worker UnloadPageNoEvents(page);
563*3ac0a46fSAndroid Build Coastguard Worker }
564*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AddIllegalSubtypeAnnotation)565*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AddIllegalSubtypeAnnotation) {
566*3ac0a46fSAndroid Build Coastguard Worker // Open a file with one annotation and load its first page.
567*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
568*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
569*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
570*3ac0a46fSAndroid Build Coastguard Worker
571*3ac0a46fSAndroid Build Coastguard Worker // Add an annotation with an illegal subtype.
572*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFPage_CreateAnnot(page, -1));
573*3ac0a46fSAndroid Build Coastguard Worker
574*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
575*3ac0a46fSAndroid Build Coastguard Worker }
576*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AddFirstTextAnnotation)577*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AddFirstTextAnnotation) {
578*3ac0a46fSAndroid Build Coastguard Worker // Open a file with no annotation and load its first page.
579*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("hello_world.pdf"));
580*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
581*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
582*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
583*3ac0a46fSAndroid Build Coastguard Worker
584*3ac0a46fSAndroid Build Coastguard Worker {
585*3ac0a46fSAndroid Build Coastguard Worker // Add a text annotation to the page.
586*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT));
587*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
588*3ac0a46fSAndroid Build Coastguard Worker
589*3ac0a46fSAndroid Build Coastguard Worker // Check that there is now 1 annotations on this page.
590*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
591*3ac0a46fSAndroid Build Coastguard Worker
592*3ac0a46fSAndroid Build Coastguard Worker // Check that the subtype of the annotation is correct.
593*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
594*3ac0a46fSAndroid Build Coastguard Worker }
595*3ac0a46fSAndroid Build Coastguard Worker
596*3ac0a46fSAndroid Build Coastguard Worker {
597*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
598*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
599*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
600*3ac0a46fSAndroid Build Coastguard Worker
601*3ac0a46fSAndroid Build Coastguard Worker // Set the color of the annotation.
602*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 51,
603*3ac0a46fSAndroid Build Coastguard Worker 102, 153, 204));
604*3ac0a46fSAndroid Build Coastguard Worker // Check that the color has been set correctly.
605*3ac0a46fSAndroid Build Coastguard Worker unsigned int R;
606*3ac0a46fSAndroid Build Coastguard Worker unsigned int G;
607*3ac0a46fSAndroid Build Coastguard Worker unsigned int B;
608*3ac0a46fSAndroid Build Coastguard Worker unsigned int A;
609*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
610*3ac0a46fSAndroid Build Coastguard Worker &G, &B, &A));
611*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(51u, R);
612*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(102u, G);
613*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(153u, B);
614*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(204u, A);
615*3ac0a46fSAndroid Build Coastguard Worker
616*3ac0a46fSAndroid Build Coastguard Worker // Change the color of the annotation.
617*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 204,
618*3ac0a46fSAndroid Build Coastguard Worker 153, 102, 51));
619*3ac0a46fSAndroid Build Coastguard Worker // Check that the color has been set correctly.
620*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, &R,
621*3ac0a46fSAndroid Build Coastguard Worker &G, &B, &A));
622*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(204u, R);
623*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(153u, G);
624*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(102u, B);
625*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(51u, A);
626*3ac0a46fSAndroid Build Coastguard Worker
627*3ac0a46fSAndroid Build Coastguard Worker // Set the annotation rectangle.
628*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF rect;
629*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
630*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0.f, rect.left);
631*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0.f, rect.right);
632*3ac0a46fSAndroid Build Coastguard Worker rect.left = 35;
633*3ac0a46fSAndroid Build Coastguard Worker rect.bottom = 150;
634*3ac0a46fSAndroid Build Coastguard Worker rect.right = 53;
635*3ac0a46fSAndroid Build Coastguard Worker rect.top = 165;
636*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
637*3ac0a46fSAndroid Build Coastguard Worker // Check that the annotation rectangle has been set correctly.
638*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
639*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(35.f, rect.left);
640*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(150.f, rect.bottom);
641*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(53.f, rect.right);
642*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(165.f, rect.top);
643*3ac0a46fSAndroid Build Coastguard Worker
644*3ac0a46fSAndroid Build Coastguard Worker // Set the content of the annotation.
645*3ac0a46fSAndroid Build Coastguard Worker static const wchar_t kContents[] = L"Hello! This is a customized content.";
646*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString text = GetFPDFWideString(kContents);
647*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetStringValue(
648*3ac0a46fSAndroid Build Coastguard Worker annot.get(), pdfium::annotation::kContents, text.get()));
649*3ac0a46fSAndroid Build Coastguard Worker // Check that the content has been set correctly.
650*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes = FPDFAnnot_GetStringValue(
651*3ac0a46fSAndroid Build Coastguard Worker annot.get(), pdfium::annotation::kContents, nullptr, 0);
652*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(74u, length_bytes);
653*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
654*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(74u, FPDFAnnot_GetStringValue(annot.get(),
655*3ac0a46fSAndroid Build Coastguard Worker pdfium::annotation::kContents,
656*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
657*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kContents, GetPlatformWString(buf.data()));
658*3ac0a46fSAndroid Build Coastguard Worker }
659*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
660*3ac0a46fSAndroid Build Coastguard Worker }
661*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AddAndSaveLinkAnnotation)662*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AddAndSaveLinkAnnotation) {
663*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("hello_world.pdf"));
664*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
665*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
666*3ac0a46fSAndroid Build Coastguard Worker {
667*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
668*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 200, 200, pdfium::HelloWorldChecksum());
669*3ac0a46fSAndroid Build Coastguard Worker }
670*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
671*3ac0a46fSAndroid Build Coastguard Worker
672*3ac0a46fSAndroid Build Coastguard Worker constexpr char kUri[] = "https://pdfium.org/";
673*3ac0a46fSAndroid Build Coastguard Worker
674*3ac0a46fSAndroid Build Coastguard Worker {
675*3ac0a46fSAndroid Build Coastguard Worker // Add a link annotation to the page and set its URI.
676*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_LINK));
677*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
678*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
679*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
680*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetURI(annot.get(), kUri));
681*3ac0a46fSAndroid Build Coastguard Worker VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
682*3ac0a46fSAndroid Build Coastguard Worker
683*3ac0a46fSAndroid Build Coastguard Worker // Negative tests:
684*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetURI(nullptr, nullptr));
685*3ac0a46fSAndroid Build Coastguard Worker VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
686*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetURI(annot.get(), nullptr));
687*3ac0a46fSAndroid Build Coastguard Worker VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
688*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetURI(nullptr, kUri));
689*3ac0a46fSAndroid Build Coastguard Worker VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
690*3ac0a46fSAndroid Build Coastguard Worker
691*3ac0a46fSAndroid Build Coastguard Worker // Position the link on top of "Hello, world!" without a border.
692*3ac0a46fSAndroid Build Coastguard Worker const FS_RECTF kRect = {19.0f, 48.0f, 85.0f, 60.0f};
693*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &kRect));
694*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetBorder(annot.get(), /*horizontal_radius=*/0.0f,
695*3ac0a46fSAndroid Build Coastguard Worker /*vertical_radius=*/0.0f,
696*3ac0a46fSAndroid Build Coastguard Worker /*border_width=*/0.0f));
697*3ac0a46fSAndroid Build Coastguard Worker
698*3ac0a46fSAndroid Build Coastguard Worker VerifyUriActionInLink(document(), FPDFLink_GetLinkAtPoint(page, 40.0, 50.0),
699*3ac0a46fSAndroid Build Coastguard Worker kUri);
700*3ac0a46fSAndroid Build Coastguard Worker }
701*3ac0a46fSAndroid Build Coastguard Worker
702*3ac0a46fSAndroid Build Coastguard Worker {
703*3ac0a46fSAndroid Build Coastguard Worker // Add an ink annotation to the page. Trying to add a link to it fails.
704*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_INK));
705*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
706*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
707*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot.get()));
708*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetURI(annot.get(), kUri));
709*3ac0a46fSAndroid Build Coastguard Worker }
710*3ac0a46fSAndroid Build Coastguard Worker
711*3ac0a46fSAndroid Build Coastguard Worker // Remove the ink annotation added above for negative testing.
712*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
713*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
714*3ac0a46fSAndroid Build Coastguard Worker
715*3ac0a46fSAndroid Build Coastguard Worker // Save the document, closing the page.
716*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
717*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
718*3ac0a46fSAndroid Build Coastguard Worker
719*3ac0a46fSAndroid Build Coastguard Worker // Reopen the document and make sure it still renders the same. Since the link
720*3ac0a46fSAndroid Build Coastguard Worker // does not have a border, it does not affect the rendering.
721*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenSavedDocument());
722*3ac0a46fSAndroid Build Coastguard Worker page = LoadSavedPage(0);
723*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
724*3ac0a46fSAndroid Build Coastguard Worker VerifySavedRendering(page, 200, 200, pdfium::HelloWorldChecksum());
725*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
726*3ac0a46fSAndroid Build Coastguard Worker
727*3ac0a46fSAndroid Build Coastguard Worker {
728*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
729*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
730*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
731*3ac0a46fSAndroid Build Coastguard Worker VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()), kUri);
732*3ac0a46fSAndroid Build Coastguard Worker VerifyUriActionInLink(document(), FPDFLink_GetLinkAtPoint(page, 40.0, 50.0),
733*3ac0a46fSAndroid Build Coastguard Worker kUri);
734*3ac0a46fSAndroid Build Coastguard Worker }
735*3ac0a46fSAndroid Build Coastguard Worker
736*3ac0a46fSAndroid Build Coastguard Worker CloseSavedPage(page);
737*3ac0a46fSAndroid Build Coastguard Worker CloseSavedDocument();
738*3ac0a46fSAndroid Build Coastguard Worker }
739*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AddAndSaveUnderlineAnnotation)740*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AddAndSaveUnderlineAnnotation) {
741*3ac0a46fSAndroid Build Coastguard Worker // Open a file with one annotation and load its first page.
742*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
743*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
744*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
745*3ac0a46fSAndroid Build Coastguard Worker
746*3ac0a46fSAndroid Build Coastguard Worker // Check that there is a total of one annotation on its first page, and verify
747*3ac0a46fSAndroid Build Coastguard Worker // its quadpoints.
748*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
749*3ac0a46fSAndroid Build Coastguard Worker FS_QUADPOINTSF quadpoints;
750*3ac0a46fSAndroid Build Coastguard Worker {
751*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
752*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
753*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
754*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(115.802643f, quadpoints.x1);
755*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(718.913940f, quadpoints.y1);
756*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(157.211182f, quadpoints.x4);
757*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(706.264465f, quadpoints.y4);
758*3ac0a46fSAndroid Build Coastguard Worker }
759*3ac0a46fSAndroid Build Coastguard Worker
760*3ac0a46fSAndroid Build Coastguard Worker // Add an underline annotation to the page and set its quadpoints.
761*3ac0a46fSAndroid Build Coastguard Worker {
762*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(
763*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE));
764*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
765*3ac0a46fSAndroid Build Coastguard Worker quadpoints.x1 = 140.802643f;
766*3ac0a46fSAndroid Build Coastguard Worker quadpoints.x3 = 140.802643f;
767*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_AppendAttachmentPoints(annot.get(), &quadpoints));
768*3ac0a46fSAndroid Build Coastguard Worker }
769*3ac0a46fSAndroid Build Coastguard Worker
770*3ac0a46fSAndroid Build Coastguard Worker // Save the document and close the page.
771*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
772*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
773*3ac0a46fSAndroid Build Coastguard Worker
774*3ac0a46fSAndroid Build Coastguard Worker // Open the saved document.
775*3ac0a46fSAndroid Build Coastguard Worker const char* checksum = []() {
776*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
777*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
778*3ac0a46fSAndroid Build Coastguard Worker return "24994ad69aa612a66d183eaf9a92aa06";
779*3ac0a46fSAndroid Build Coastguard Worker #else
780*3ac0a46fSAndroid Build Coastguard Worker return "798fa41303381c9ba6d99092f5cd4d2b";
781*3ac0a46fSAndroid Build Coastguard Worker #endif
782*3ac0a46fSAndroid Build Coastguard Worker }
783*3ac0a46fSAndroid Build Coastguard Worker return "dba153419f67b7c0c0e3d22d3e8910d5";
784*3ac0a46fSAndroid Build Coastguard Worker }();
785*3ac0a46fSAndroid Build Coastguard Worker
786*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenSavedDocument());
787*3ac0a46fSAndroid Build Coastguard Worker page = LoadSavedPage(0);
788*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
789*3ac0a46fSAndroid Build Coastguard Worker VerifySavedRendering(page, 612, 792, checksum);
790*3ac0a46fSAndroid Build Coastguard Worker
791*3ac0a46fSAndroid Build Coastguard Worker // Check that the saved document has 2 annotations on the first page
792*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
793*3ac0a46fSAndroid Build Coastguard Worker
794*3ac0a46fSAndroid Build Coastguard Worker {
795*3ac0a46fSAndroid Build Coastguard Worker // Check that the second annotation is an underline annotation and verify
796*3ac0a46fSAndroid Build Coastguard Worker // its quadpoints.
797*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 1));
798*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(new_annot);
799*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot.get()));
800*3ac0a46fSAndroid Build Coastguard Worker FS_QUADPOINTSF new_quadpoints;
801*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(
802*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAttachmentPoints(new_annot.get(), 0, &new_quadpoints));
803*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f);
804*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f);
805*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f);
806*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f);
807*3ac0a46fSAndroid Build Coastguard Worker }
808*3ac0a46fSAndroid Build Coastguard Worker
809*3ac0a46fSAndroid Build Coastguard Worker CloseSavedPage(page);
810*3ac0a46fSAndroid Build Coastguard Worker CloseSavedDocument();
811*3ac0a46fSAndroid Build Coastguard Worker }
812*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetAndSetQuadPoints)813*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetAndSetQuadPoints) {
814*3ac0a46fSAndroid Build Coastguard Worker // Open a file with four annotations and load its first page.
815*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
816*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
817*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
818*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
819*3ac0a46fSAndroid Build Coastguard Worker
820*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the highlight annotation.
821*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
822*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
823*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
824*3ac0a46fSAndroid Build Coastguard Worker
825*3ac0a46fSAndroid Build Coastguard Worker FS_QUADPOINTSF quadpoints;
826*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 0, &quadpoints));
827*3ac0a46fSAndroid Build Coastguard Worker
828*3ac0a46fSAndroid Build Coastguard Worker {
829*3ac0a46fSAndroid Build Coastguard Worker // Verify the current one set of quadpoints.
830*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(1u, FPDFAnnot_CountAttachmentPoints(annot));
831*3ac0a46fSAndroid Build Coastguard Worker
832*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
833*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
834*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
835*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
836*3ac0a46fSAndroid Build Coastguard Worker }
837*3ac0a46fSAndroid Build Coastguard Worker
838*3ac0a46fSAndroid Build Coastguard Worker {
839*3ac0a46fSAndroid Build Coastguard Worker // Update the quadpoints.
840*3ac0a46fSAndroid Build Coastguard Worker FS_QUADPOINTSF new_quadpoints = quadpoints;
841*3ac0a46fSAndroid Build Coastguard Worker new_quadpoints.y1 -= 20.f;
842*3ac0a46fSAndroid Build Coastguard Worker new_quadpoints.y2 -= 20.f;
843*3ac0a46fSAndroid Build Coastguard Worker new_quadpoints.y3 -= 20.f;
844*3ac0a46fSAndroid Build Coastguard Worker new_quadpoints.y4 -= 20.f;
845*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, 0, &new_quadpoints));
846*3ac0a46fSAndroid Build Coastguard Worker
847*3ac0a46fSAndroid Build Coastguard Worker // Verify added quadpoint set
848*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(1u, FPDFAnnot_CountAttachmentPoints(annot));
849*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 0, &quadpoints));
850*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(new_quadpoints.x1, quadpoints.x1, 0.001f);
851*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(new_quadpoints.y1, quadpoints.y1, 0.001f);
852*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(new_quadpoints.x4, quadpoints.x4, 0.001f);
853*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(new_quadpoints.y4, quadpoints.y4, 0.001f);
854*3ac0a46fSAndroid Build Coastguard Worker }
855*3ac0a46fSAndroid Build Coastguard Worker
856*3ac0a46fSAndroid Build Coastguard Worker {
857*3ac0a46fSAndroid Build Coastguard Worker // Append a new set of quadpoints.
858*3ac0a46fSAndroid Build Coastguard Worker FS_QUADPOINTSF new_quadpoints = quadpoints;
859*3ac0a46fSAndroid Build Coastguard Worker new_quadpoints.y1 += 20.f;
860*3ac0a46fSAndroid Build Coastguard Worker new_quadpoints.y2 += 20.f;
861*3ac0a46fSAndroid Build Coastguard Worker new_quadpoints.y3 += 20.f;
862*3ac0a46fSAndroid Build Coastguard Worker new_quadpoints.y4 += 20.f;
863*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_AppendAttachmentPoints(annot, &new_quadpoints));
864*3ac0a46fSAndroid Build Coastguard Worker
865*3ac0a46fSAndroid Build Coastguard Worker // Verify added quadpoint set
866*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(2u, FPDFAnnot_CountAttachmentPoints(annot));
867*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, 1, &quadpoints));
868*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(new_quadpoints.x1, quadpoints.x1, 0.001f);
869*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(new_quadpoints.y1, quadpoints.y1, 0.001f);
870*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(new_quadpoints.x4, quadpoints.x4, 0.001f);
871*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(new_quadpoints.y4, quadpoints.y4, 0.001f);
872*3ac0a46fSAndroid Build Coastguard Worker }
873*3ac0a46fSAndroid Build Coastguard Worker
874*3ac0a46fSAndroid Build Coastguard Worker {
875*3ac0a46fSAndroid Build Coastguard Worker // Setting and getting quadpoints at out-of-bound index should fail
876*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetAttachmentPoints(annot, 300000, &quadpoints));
877*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetAttachmentPoints(annot, 300000, &quadpoints));
878*3ac0a46fSAndroid Build Coastguard Worker }
879*3ac0a46fSAndroid Build Coastguard Worker
880*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CloseAnnot(annot);
881*3ac0a46fSAndroid Build Coastguard Worker
882*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the square annotation
883*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOTATION squareAnnot = FPDFPage_GetAnnot(page, 2);
884*3ac0a46fSAndroid Build Coastguard Worker
885*3ac0a46fSAndroid Build Coastguard Worker {
886*3ac0a46fSAndroid Build Coastguard Worker // Check that attempting to set its quadpoints would fail
887*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(squareAnnot);
888*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(squareAnnot));
889*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_CountAttachmentPoints(squareAnnot));
890*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetAttachmentPoints(squareAnnot, 0, &quadpoints));
891*3ac0a46fSAndroid Build Coastguard Worker }
892*3ac0a46fSAndroid Build Coastguard Worker
893*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CloseAnnot(squareAnnot);
894*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
895*3ac0a46fSAndroid Build Coastguard Worker }
896*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,ModifyRectQuadpointsWithAP)897*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, ModifyRectQuadpointsWithAP) {
898*3ac0a46fSAndroid Build Coastguard Worker const char* md5_original = []() {
899*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
900*3ac0a46fSAndroid Build Coastguard Worker return "2a9d1df839d5ec81a49f982347d9656c";
901*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
902*3ac0a46fSAndroid Build Coastguard Worker return "fc59468d154f397fd298c69f47ef565a";
903*3ac0a46fSAndroid Build Coastguard Worker #else
904*3ac0a46fSAndroid Build Coastguard Worker return "0e27376094f11490f74c65f3dc3a42c5";
905*3ac0a46fSAndroid Build Coastguard Worker #endif
906*3ac0a46fSAndroid Build Coastguard Worker }();
907*3ac0a46fSAndroid Build Coastguard Worker const char* md5_modified_highlight = []() {
908*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
909*3ac0a46fSAndroid Build Coastguard Worker return "0fb1653db0e8e8f7ce5d726bb0074bb5";
910*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
911*3ac0a46fSAndroid Build Coastguard Worker return "e64bf648f6e9354d1f3eedb47a2c9498";
912*3ac0a46fSAndroid Build Coastguard Worker #else
913*3ac0a46fSAndroid Build Coastguard Worker return "66f3caef3a7d488a4fa1ad37fc06310e";
914*3ac0a46fSAndroid Build Coastguard Worker #endif
915*3ac0a46fSAndroid Build Coastguard Worker }();
916*3ac0a46fSAndroid Build Coastguard Worker const char* md5_modified_square = []() {
917*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
918*3ac0a46fSAndroid Build Coastguard Worker return "879c77a2cb9f79ba65ffe0bbdd720ce3";
919*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
920*3ac0a46fSAndroid Build Coastguard Worker return "a66591662c8e7ad3c6059952e234bebf";
921*3ac0a46fSAndroid Build Coastguard Worker #else
922*3ac0a46fSAndroid Build Coastguard Worker return "a456dad0bc6801ee2d6408a4394af563";
923*3ac0a46fSAndroid Build Coastguard Worker #endif
924*3ac0a46fSAndroid Build Coastguard Worker }();
925*3ac0a46fSAndroid Build Coastguard Worker
926*3ac0a46fSAndroid Build Coastguard Worker // Open a file with four annotations and load its first page.
927*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
928*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
929*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
930*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
931*3ac0a46fSAndroid Build Coastguard Worker
932*3ac0a46fSAndroid Build Coastguard Worker // Check that the original file renders correctly.
933*3ac0a46fSAndroid Build Coastguard Worker {
934*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
935*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, md5_original);
936*3ac0a46fSAndroid Build Coastguard Worker }
937*3ac0a46fSAndroid Build Coastguard Worker
938*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF rect;
939*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF new_rect;
940*3ac0a46fSAndroid Build Coastguard Worker
941*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the highlight annotation which has its AP stream already defined.
942*3ac0a46fSAndroid Build Coastguard Worker {
943*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
944*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
945*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
946*3ac0a46fSAndroid Build Coastguard Worker
947*3ac0a46fSAndroid Build Coastguard Worker // Check that color cannot be set when an AP stream is defined already.
948*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color, 51,
949*3ac0a46fSAndroid Build Coastguard Worker 102, 153, 204));
950*3ac0a46fSAndroid Build Coastguard Worker
951*3ac0a46fSAndroid Build Coastguard Worker // Verify its attachment points.
952*3ac0a46fSAndroid Build Coastguard Worker FS_QUADPOINTSF quadpoints;
953*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &quadpoints));
954*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
955*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
956*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
957*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
958*3ac0a46fSAndroid Build Coastguard Worker
959*3ac0a46fSAndroid Build Coastguard Worker // Check that updating the attachment points would succeed.
960*3ac0a46fSAndroid Build Coastguard Worker quadpoints.x1 -= 50.f;
961*3ac0a46fSAndroid Build Coastguard Worker quadpoints.x2 -= 50.f;
962*3ac0a46fSAndroid Build Coastguard Worker quadpoints.x3 -= 50.f;
963*3ac0a46fSAndroid Build Coastguard Worker quadpoints.x4 -= 50.f;
964*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot.get(), 0, &quadpoints));
965*3ac0a46fSAndroid Build Coastguard Worker FS_QUADPOINTSF new_quadpoints;
966*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot.get(), 0, &new_quadpoints));
967*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(quadpoints.x1, new_quadpoints.x1);
968*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(quadpoints.y1, new_quadpoints.y1);
969*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(quadpoints.x4, new_quadpoints.x4);
970*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(quadpoints.y4, new_quadpoints.y4);
971*3ac0a46fSAndroid Build Coastguard Worker
972*3ac0a46fSAndroid Build Coastguard Worker // Check that updating quadpoints does not change the annotation's position.
973*3ac0a46fSAndroid Build Coastguard Worker {
974*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
975*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, md5_original);
976*3ac0a46fSAndroid Build Coastguard Worker }
977*3ac0a46fSAndroid Build Coastguard Worker
978*3ac0a46fSAndroid Build Coastguard Worker // Verify its annotation rectangle.
979*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
980*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(67.7299f, rect.left, 0.001f);
981*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(704.296f, rect.bottom, 0.001f);
982*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(136.325f, rect.right, 0.001f);
983*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(721.292f, rect.top, 0.001f);
984*3ac0a46fSAndroid Build Coastguard Worker
985*3ac0a46fSAndroid Build Coastguard Worker // Check that updating the rectangle would succeed.
986*3ac0a46fSAndroid Build Coastguard Worker rect.left -= 60.f;
987*3ac0a46fSAndroid Build Coastguard Worker rect.right -= 60.f;
988*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
989*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
990*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.right, new_rect.right);
991*3ac0a46fSAndroid Build Coastguard Worker }
992*3ac0a46fSAndroid Build Coastguard Worker
993*3ac0a46fSAndroid Build Coastguard Worker // Check that updating the rectangle changes the annotation's position.
994*3ac0a46fSAndroid Build Coastguard Worker {
995*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
996*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, md5_modified_highlight);
997*3ac0a46fSAndroid Build Coastguard Worker }
998*3ac0a46fSAndroid Build Coastguard Worker
999*3ac0a46fSAndroid Build Coastguard Worker {
1000*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the square annotation which has its AP stream already defined.
1001*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1002*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1003*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot.get()));
1004*3ac0a46fSAndroid Build Coastguard Worker
1005*3ac0a46fSAndroid Build Coastguard Worker // Check that updating the rectangle would succeed.
1006*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1007*3ac0a46fSAndroid Build Coastguard Worker rect.left += 70.f;
1008*3ac0a46fSAndroid Build Coastguard Worker rect.right += 70.f;
1009*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
1010*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
1011*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.right, new_rect.right);
1012*3ac0a46fSAndroid Build Coastguard Worker
1013*3ac0a46fSAndroid Build Coastguard Worker // Check that updating the rectangle changes the square annotation's
1014*3ac0a46fSAndroid Build Coastguard Worker // position.
1015*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1016*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, md5_modified_square);
1017*3ac0a46fSAndroid Build Coastguard Worker }
1018*3ac0a46fSAndroid Build Coastguard Worker
1019*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1020*3ac0a46fSAndroid Build Coastguard Worker }
1021*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,CountAttachmentPoints)1022*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, CountAttachmentPoints) {
1023*3ac0a46fSAndroid Build Coastguard Worker // Open a file with multiline markup annotations.
1024*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_markup_multiline_no_ap.pdf"));
1025*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1026*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1027*3ac0a46fSAndroid Build Coastguard Worker {
1028*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1029*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1030*3ac0a46fSAndroid Build Coastguard Worker
1031*3ac0a46fSAndroid Build Coastguard Worker // This is a three line annotation.
1032*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3u, FPDFAnnot_CountAttachmentPoints(annot.get()));
1033*3ac0a46fSAndroid Build Coastguard Worker }
1034*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1035*3ac0a46fSAndroid Build Coastguard Worker
1036*3ac0a46fSAndroid Build Coastguard Worker // null annotation should return 0
1037*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_CountAttachmentPoints(nullptr));
1038*3ac0a46fSAndroid Build Coastguard Worker }
1039*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,RemoveAnnotation)1040*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, RemoveAnnotation) {
1041*3ac0a46fSAndroid Build Coastguard Worker // Open a file with 3 annotations on its first page.
1042*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
1043*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPageNoEvents(0);
1044*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1045*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
1046*3ac0a46fSAndroid Build Coastguard Worker
1047*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF rect;
1048*3ac0a46fSAndroid Build Coastguard Worker
1049*3ac0a46fSAndroid Build Coastguard Worker // Check that the annotations have the expected rectangle coordinates.
1050*3ac0a46fSAndroid Build Coastguard Worker {
1051*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1052*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1053*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(86.1971f, rect.left, 0.001f);
1054*3ac0a46fSAndroid Build Coastguard Worker }
1055*3ac0a46fSAndroid Build Coastguard Worker
1056*3ac0a46fSAndroid Build Coastguard Worker {
1057*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
1058*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1059*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(149.8127f, rect.left, 0.001f);
1060*3ac0a46fSAndroid Build Coastguard Worker }
1061*3ac0a46fSAndroid Build Coastguard Worker
1062*3ac0a46fSAndroid Build Coastguard Worker {
1063*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1064*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1065*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(351.8204f, rect.left, 0.001f);
1066*3ac0a46fSAndroid Build Coastguard Worker }
1067*3ac0a46fSAndroid Build Coastguard Worker
1068*3ac0a46fSAndroid Build Coastguard Worker // Check that nothing happens when attempting to remove an annotation with an
1069*3ac0a46fSAndroid Build Coastguard Worker // out-of-bound index.
1070*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4));
1071*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1));
1072*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
1073*3ac0a46fSAndroid Build Coastguard Worker
1074*3ac0a46fSAndroid Build Coastguard Worker // Remove the second annotation.
1075*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
1076*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1077*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFPage_GetAnnot(page, 2));
1078*3ac0a46fSAndroid Build Coastguard Worker
1079*3ac0a46fSAndroid Build Coastguard Worker // Save the document and close the page.
1080*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1081*3ac0a46fSAndroid Build Coastguard Worker UnloadPageNoEvents(page);
1082*3ac0a46fSAndroid Build Coastguard Worker
1083*3ac0a46fSAndroid Build Coastguard Worker // TODO(npm): VerifySavedRendering changes annot rect dimensions by 1??
1084*3ac0a46fSAndroid Build Coastguard Worker // Open the saved document.
1085*3ac0a46fSAndroid Build Coastguard Worker std::string new_file = GetString();
1086*3ac0a46fSAndroid Build Coastguard Worker FPDF_FILEACCESS file_access;
1087*3ac0a46fSAndroid Build Coastguard Worker memset(&file_access, 0, sizeof(file_access));
1088*3ac0a46fSAndroid Build Coastguard Worker file_access.m_FileLen = new_file.size();
1089*3ac0a46fSAndroid Build Coastguard Worker file_access.m_GetBlock = GetBlockFromString;
1090*3ac0a46fSAndroid Build Coastguard Worker file_access.m_Param = &new_file;
1091*3ac0a46fSAndroid Build Coastguard Worker FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
1092*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(new_doc);
1093*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
1094*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(new_page);
1095*3ac0a46fSAndroid Build Coastguard Worker
1096*3ac0a46fSAndroid Build Coastguard Worker // Check that the saved document has 2 annotations on the first page.
1097*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
1098*3ac0a46fSAndroid Build Coastguard Worker
1099*3ac0a46fSAndroid Build Coastguard Worker // Check that the remaining 2 annotations are the original 1st and 3rd ones
1100*3ac0a46fSAndroid Build Coastguard Worker // by verifying their rectangle coordinates.
1101*3ac0a46fSAndroid Build Coastguard Worker {
1102*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(new_page, 0));
1103*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1104*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(86.1971f, rect.left, 0.001f);
1105*3ac0a46fSAndroid Build Coastguard Worker }
1106*3ac0a46fSAndroid Build Coastguard Worker
1107*3ac0a46fSAndroid Build Coastguard Worker {
1108*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(new_page, 1));
1109*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &rect));
1110*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(351.8204f, rect.left, 0.001f);
1111*3ac0a46fSAndroid Build Coastguard Worker }
1112*3ac0a46fSAndroid Build Coastguard Worker FPDF_ClosePage(new_page);
1113*3ac0a46fSAndroid Build Coastguard Worker FPDF_CloseDocument(new_doc);
1114*3ac0a46fSAndroid Build Coastguard Worker }
1115*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AddAndModifyPath)1116*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AddAndModifyPath) {
1117*3ac0a46fSAndroid Build Coastguard Worker const char* md5_modified_path = []() {
1118*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
1119*3ac0a46fSAndroid Build Coastguard Worker return "fb4d5fac05f7eb5d84a4100898c11197";
1120*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
1121*3ac0a46fSAndroid Build Coastguard Worker return "34614087e04b729b7b8c37739dcf9af9";
1122*3ac0a46fSAndroid Build Coastguard Worker #else
1123*3ac0a46fSAndroid Build Coastguard Worker return "31a94d22460171cd83169daf6a6956ee";
1124*3ac0a46fSAndroid Build Coastguard Worker #endif
1125*3ac0a46fSAndroid Build Coastguard Worker }();
1126*3ac0a46fSAndroid Build Coastguard Worker const char* md5_two_paths = []() {
1127*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
1128*3ac0a46fSAndroid Build Coastguard Worker return "fcf3e79b2a91d1294b9bbccff727d3c2";
1129*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
1130*3ac0a46fSAndroid Build Coastguard Worker return "6cdaf6b3e5145f435d8ccae6db5cf9af";
1131*3ac0a46fSAndroid Build Coastguard Worker #else
1132*3ac0a46fSAndroid Build Coastguard Worker return "ed49fefef45f14121f8150cde10006c4";
1133*3ac0a46fSAndroid Build Coastguard Worker #endif
1134*3ac0a46fSAndroid Build Coastguard Worker }();
1135*3ac0a46fSAndroid Build Coastguard Worker const char* md5_new_annot = []() {
1136*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
1137*3ac0a46fSAndroid Build Coastguard Worker return "7db6321c8ffe502f4e60622aa16d5417";
1138*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
1139*3ac0a46fSAndroid Build Coastguard Worker return "55dab4f158fdc284e439b88c4306373c";
1140*3ac0a46fSAndroid Build Coastguard Worker #else
1141*3ac0a46fSAndroid Build Coastguard Worker return "cc08493b1f079803930388ecc703be9d";
1142*3ac0a46fSAndroid Build Coastguard Worker #endif
1143*3ac0a46fSAndroid Build Coastguard Worker }();
1144*3ac0a46fSAndroid Build Coastguard Worker
1145*3ac0a46fSAndroid Build Coastguard Worker // Open a file with two annotations and load its first page.
1146*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
1147*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1148*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1149*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1150*3ac0a46fSAndroid Build Coastguard Worker
1151*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly.
1152*3ac0a46fSAndroid Build Coastguard Worker {
1153*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1154*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, AnnotationStampWithApChecksum());
1155*3ac0a46fSAndroid Build Coastguard Worker }
1156*3ac0a46fSAndroid Build Coastguard Worker
1157*3ac0a46fSAndroid Build Coastguard Worker {
1158*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the stamp annotation which has its AP stream already defined.
1159*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1160*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1161*3ac0a46fSAndroid Build Coastguard Worker
1162*3ac0a46fSAndroid Build Coastguard Worker // Check that this annotation has one path object and retrieve it.
1163*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1164*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(32, FPDFPage_CountObjects(page));
1165*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT path = FPDFAnnot_GetObject(annot.get(), 1);
1166*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(path);
1167*3ac0a46fSAndroid Build Coastguard Worker path = FPDFAnnot_GetObject(annot.get(), 0);
1168*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
1169*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(path);
1170*3ac0a46fSAndroid Build Coastguard Worker
1171*3ac0a46fSAndroid Build Coastguard Worker // Modify the color of the path object.
1172*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 0, 0, 0, 255));
1173*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), path));
1174*3ac0a46fSAndroid Build Coastguard Worker
1175*3ac0a46fSAndroid Build Coastguard Worker // Check that the page with the modified annotation renders correctly.
1176*3ac0a46fSAndroid Build Coastguard Worker {
1177*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1178*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, md5_modified_path);
1179*3ac0a46fSAndroid Build Coastguard Worker }
1180*3ac0a46fSAndroid Build Coastguard Worker
1181*3ac0a46fSAndroid Build Coastguard Worker // Add a second path object to the same annotation.
1182*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT dot = FPDFPageObj_CreateNewPath(7, 84);
1183*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPath_BezierTo(dot, 9, 86, 10, 87, 11, 88));
1184*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPageObj_SetStrokeColor(dot, 255, 0, 0, 100));
1185*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(dot, 14));
1186*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPath_SetDrawMode(dot, 0, 1));
1187*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), dot));
1188*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFAnnot_GetObjectCount(annot.get()));
1189*3ac0a46fSAndroid Build Coastguard Worker
1190*3ac0a46fSAndroid Build Coastguard Worker // The object is in the annontation, not in the page, so the page object
1191*3ac0a46fSAndroid Build Coastguard Worker // array should not change.
1192*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(32, FPDFPage_CountObjects(page));
1193*3ac0a46fSAndroid Build Coastguard Worker
1194*3ac0a46fSAndroid Build Coastguard Worker // Check that the page with an annotation with two paths renders correctly.
1195*3ac0a46fSAndroid Build Coastguard Worker {
1196*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1197*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, md5_two_paths);
1198*3ac0a46fSAndroid Build Coastguard Worker }
1199*3ac0a46fSAndroid Build Coastguard Worker
1200*3ac0a46fSAndroid Build Coastguard Worker // Delete the newly added path object.
1201*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_RemoveObject(annot.get(), 1));
1202*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1203*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(32, FPDFPage_CountObjects(page));
1204*3ac0a46fSAndroid Build Coastguard Worker }
1205*3ac0a46fSAndroid Build Coastguard Worker
1206*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders the same as before.
1207*3ac0a46fSAndroid Build Coastguard Worker {
1208*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1209*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, md5_modified_path);
1210*3ac0a46fSAndroid Build Coastguard Worker }
1211*3ac0a46fSAndroid Build Coastguard Worker
1212*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF rect;
1213*3ac0a46fSAndroid Build Coastguard Worker
1214*3ac0a46fSAndroid Build Coastguard Worker {
1215*3ac0a46fSAndroid Build Coastguard Worker // Create another stamp annotation and set its annotation rectangle.
1216*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
1217*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1218*3ac0a46fSAndroid Build Coastguard Worker rect.left = 200.f;
1219*3ac0a46fSAndroid Build Coastguard Worker rect.bottom = 400.f;
1220*3ac0a46fSAndroid Build Coastguard Worker rect.right = 500.f;
1221*3ac0a46fSAndroid Build Coastguard Worker rect.top = 600.f;
1222*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
1223*3ac0a46fSAndroid Build Coastguard Worker
1224*3ac0a46fSAndroid Build Coastguard Worker // Add a new path to the annotation.
1225*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500);
1226*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400));
1227*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600));
1228*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550));
1229*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450));
1230*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPageObj_SetStrokeColor(check, 0, 255, 255, 180));
1231*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(check, 8.35f));
1232*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
1233*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), check));
1234*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1235*3ac0a46fSAndroid Build Coastguard Worker
1236*3ac0a46fSAndroid Build Coastguard Worker // Check that the annotation's bounding box came from its rectangle.
1237*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF new_rect;
1238*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
1239*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.left, new_rect.left);
1240*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.bottom, new_rect.bottom);
1241*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.right, new_rect.right);
1242*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.top, new_rect.top);
1243*3ac0a46fSAndroid Build Coastguard Worker }
1244*3ac0a46fSAndroid Build Coastguard Worker
1245*3ac0a46fSAndroid Build Coastguard Worker // Save the document and close the page.
1246*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1247*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1248*3ac0a46fSAndroid Build Coastguard Worker
1249*3ac0a46fSAndroid Build Coastguard Worker // Open the saved document.
1250*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenSavedDocument());
1251*3ac0a46fSAndroid Build Coastguard Worker page = LoadSavedPage(0);
1252*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1253*3ac0a46fSAndroid Build Coastguard Worker VerifySavedRendering(page, 595, 842, md5_new_annot);
1254*3ac0a46fSAndroid Build Coastguard Worker
1255*3ac0a46fSAndroid Build Coastguard Worker // Check that the document has a correct count of annotations and objects.
1256*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
1257*3ac0a46fSAndroid Build Coastguard Worker
1258*3ac0a46fSAndroid Build Coastguard Worker {
1259*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1260*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1261*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1262*3ac0a46fSAndroid Build Coastguard Worker
1263*3ac0a46fSAndroid Build Coastguard Worker // Check that the new annotation's rectangle is as defined.
1264*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF new_rect;
1265*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(annot.get(), &new_rect));
1266*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.left, new_rect.left);
1267*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.bottom, new_rect.bottom);
1268*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.right, new_rect.right);
1269*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(rect.top, new_rect.top);
1270*3ac0a46fSAndroid Build Coastguard Worker }
1271*3ac0a46fSAndroid Build Coastguard Worker
1272*3ac0a46fSAndroid Build Coastguard Worker CloseSavedPage(page);
1273*3ac0a46fSAndroid Build Coastguard Worker CloseSavedDocument();
1274*3ac0a46fSAndroid Build Coastguard Worker }
1275*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,ModifyAnnotationFlags)1276*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, ModifyAnnotationFlags) {
1277*3ac0a46fSAndroid Build Coastguard Worker // Open a file with an annotation and load its first page.
1278*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
1279*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1280*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1281*3ac0a46fSAndroid Build Coastguard Worker
1282*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly.
1283*3ac0a46fSAndroid Build Coastguard Worker {
1284*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1285*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
1286*3ac0a46fSAndroid Build Coastguard Worker }
1287*3ac0a46fSAndroid Build Coastguard Worker
1288*3ac0a46fSAndroid Build Coastguard Worker {
1289*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the annotation.
1290*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1291*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1292*3ac0a46fSAndroid Build Coastguard Worker
1293*3ac0a46fSAndroid Build Coastguard Worker // Check that the original flag values are as expected.
1294*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFlags(annot.get());
1295*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_INVISIBLE);
1296*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
1297*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
1298*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_NOZOOM);
1299*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_NOROTATE);
1300*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_NOVIEW);
1301*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_READONLY);
1302*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_LOCKED);
1303*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_TOGGLENOVIEW);
1304*3ac0a46fSAndroid Build Coastguard Worker
1305*3ac0a46fSAndroid Build Coastguard Worker // Set the HIDDEN flag.
1306*3ac0a46fSAndroid Build Coastguard Worker flags |= FPDF_ANNOT_FLAG_HIDDEN;
1307*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), flags));
1308*3ac0a46fSAndroid Build Coastguard Worker flags = FPDFAnnot_GetFlags(annot.get());
1309*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_HIDDEN);
1310*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
1311*3ac0a46fSAndroid Build Coastguard Worker
1312*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly without rendering the annotation.
1313*3ac0a46fSAndroid Build Coastguard Worker {
1314*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1315*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, pdfium::kBlankPage612By792Checksum);
1316*3ac0a46fSAndroid Build Coastguard Worker }
1317*3ac0a46fSAndroid Build Coastguard Worker
1318*3ac0a46fSAndroid Build Coastguard Worker // Unset the HIDDEN flag.
1319*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), FPDF_ANNOT_FLAG_NONE));
1320*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetFlags(annot.get()));
1321*3ac0a46fSAndroid Build Coastguard Worker flags &= ~FPDF_ANNOT_FLAG_HIDDEN;
1322*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetFlags(annot.get(), flags));
1323*3ac0a46fSAndroid Build Coastguard Worker flags = FPDFAnnot_GetFlags(annot.get());
1324*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
1325*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
1326*3ac0a46fSAndroid Build Coastguard Worker
1327*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly as before.
1328*3ac0a46fSAndroid Build Coastguard Worker {
1329*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1330*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
1331*3ac0a46fSAndroid Build Coastguard Worker }
1332*3ac0a46fSAndroid Build Coastguard Worker }
1333*3ac0a46fSAndroid Build Coastguard Worker
1334*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1335*3ac0a46fSAndroid Build Coastguard Worker }
1336*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AddAndModifyImage)1337*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AddAndModifyImage) {
1338*3ac0a46fSAndroid Build Coastguard Worker const char* md5_new_image = []() {
1339*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
1340*3ac0a46fSAndroid Build Coastguard Worker return "476596330c0e7daa31f115005c1d36eb";
1341*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
1342*3ac0a46fSAndroid Build Coastguard Worker return "17ac49518eabbb6a7632a547269c40a3";
1343*3ac0a46fSAndroid Build Coastguard Worker #else
1344*3ac0a46fSAndroid Build Coastguard Worker return "e79446398d4508bc2cb47e6cf2a677ed";
1345*3ac0a46fSAndroid Build Coastguard Worker #endif
1346*3ac0a46fSAndroid Build Coastguard Worker }();
1347*3ac0a46fSAndroid Build Coastguard Worker const char* md5_modified_image = []() {
1348*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
1349*3ac0a46fSAndroid Build Coastguard Worker return "0047c3e7ea7658e1a963fc339f1c587d";
1350*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
1351*3ac0a46fSAndroid Build Coastguard Worker return "ce68959f74242d588af7fb82be5ba0ab";
1352*3ac0a46fSAndroid Build Coastguard Worker #else
1353*3ac0a46fSAndroid Build Coastguard Worker return "425646a517a23104b9ef22881a19b3e2";
1354*3ac0a46fSAndroid Build Coastguard Worker #endif
1355*3ac0a46fSAndroid Build Coastguard Worker }();
1356*3ac0a46fSAndroid Build Coastguard Worker
1357*3ac0a46fSAndroid Build Coastguard Worker // Open a file with two annotations and load its first page.
1358*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
1359*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1360*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1361*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1362*3ac0a46fSAndroid Build Coastguard Worker
1363*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly.
1364*3ac0a46fSAndroid Build Coastguard Worker {
1365*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1366*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, AnnotationStampWithApChecksum());
1367*3ac0a46fSAndroid Build Coastguard Worker }
1368*3ac0a46fSAndroid Build Coastguard Worker
1369*3ac0a46fSAndroid Build Coastguard Worker constexpr int kBitmapSize = 200;
1370*3ac0a46fSAndroid Build Coastguard Worker FPDF_BITMAP image_bitmap;
1371*3ac0a46fSAndroid Build Coastguard Worker
1372*3ac0a46fSAndroid Build Coastguard Worker {
1373*3ac0a46fSAndroid Build Coastguard Worker // Create a stamp annotation and set its annotation rectangle.
1374*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
1375*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1376*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF rect;
1377*3ac0a46fSAndroid Build Coastguard Worker rect.left = 200.f;
1378*3ac0a46fSAndroid Build Coastguard Worker rect.bottom = 600.f;
1379*3ac0a46fSAndroid Build Coastguard Worker rect.right = 400.f;
1380*3ac0a46fSAndroid Build Coastguard Worker rect.top = 800.f;
1381*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
1382*3ac0a46fSAndroid Build Coastguard Worker
1383*3ac0a46fSAndroid Build Coastguard Worker // Add a solid-color translucent image object to the new annotation.
1384*3ac0a46fSAndroid Build Coastguard Worker image_bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 1);
1385*3ac0a46fSAndroid Build Coastguard Worker FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize,
1386*3ac0a46fSAndroid Build Coastguard Worker 0xeeeecccc);
1387*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(image_bitmap));
1388*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(image_bitmap));
1389*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT image_object = FPDFPageObj_NewImageObj(document());
1390*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
1391*3ac0a46fSAndroid Build Coastguard Worker static constexpr FS_MATRIX kBitmapScaleMatrix{kBitmapSize, 0, 0,
1392*3ac0a46fSAndroid Build Coastguard Worker kBitmapSize, 0, 0};
1393*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFPageObj_SetMatrix(image_object, &kBitmapScaleMatrix));
1394*3ac0a46fSAndroid Build Coastguard Worker FPDFPageObj_Transform(image_object, 1, 0, 0, 1, 200, 600);
1395*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), image_object));
1396*3ac0a46fSAndroid Build Coastguard Worker }
1397*3ac0a46fSAndroid Build Coastguard Worker
1398*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly with the new image object.
1399*3ac0a46fSAndroid Build Coastguard Worker {
1400*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1401*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, md5_new_image);
1402*3ac0a46fSAndroid Build Coastguard Worker }
1403*3ac0a46fSAndroid Build Coastguard Worker
1404*3ac0a46fSAndroid Build Coastguard Worker {
1405*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the newly added stamp annotation and its image object.
1406*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1407*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1408*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1409*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT image_object = FPDFAnnot_GetObject(annot.get(), 0);
1410*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(image_object));
1411*3ac0a46fSAndroid Build Coastguard Worker
1412*3ac0a46fSAndroid Build Coastguard Worker // Modify the image in the new annotation.
1413*3ac0a46fSAndroid Build Coastguard Worker FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize,
1414*3ac0a46fSAndroid Build Coastguard Worker 0xff000000);
1415*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
1416*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), image_object));
1417*3ac0a46fSAndroid Build Coastguard Worker }
1418*3ac0a46fSAndroid Build Coastguard Worker
1419*3ac0a46fSAndroid Build Coastguard Worker // Save the document and close the page.
1420*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1421*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1422*3ac0a46fSAndroid Build Coastguard Worker FPDFBitmap_Destroy(image_bitmap);
1423*3ac0a46fSAndroid Build Coastguard Worker
1424*3ac0a46fSAndroid Build Coastguard Worker // Test that the saved document renders the modified image object correctly.
1425*3ac0a46fSAndroid Build Coastguard Worker VerifySavedDocument(595, 842, md5_modified_image);
1426*3ac0a46fSAndroid Build Coastguard Worker }
1427*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AddAndModifyText)1428*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AddAndModifyText) {
1429*3ac0a46fSAndroid Build Coastguard Worker const char* md5_new_text = []() {
1430*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
1431*3ac0a46fSAndroid Build Coastguard Worker return "1e7f98c18775d6e0f4f454747b77cc1a";
1432*3ac0a46fSAndroid Build Coastguard Worker }
1433*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_ARM64)
1434*3ac0a46fSAndroid Build Coastguard Worker return "0c3448974a4e8da2395da917935e5de1";
1435*3ac0a46fSAndroid Build Coastguard Worker #elif BUILDFLAG(IS_APPLE) && !defined(ARCH_CPU_ARM64)
1436*3ac0a46fSAndroid Build Coastguard Worker return "5d449d36926c9f212c6cdb6c276d18cc";
1437*3ac0a46fSAndroid Build Coastguard Worker #else
1438*3ac0a46fSAndroid Build Coastguard Worker return "a9532f555aca2fd099e2107fa40b61e6";
1439*3ac0a46fSAndroid Build Coastguard Worker #endif
1440*3ac0a46fSAndroid Build Coastguard Worker }();
1441*3ac0a46fSAndroid Build Coastguard Worker const char* md5_modified_text = []() {
1442*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
1443*3ac0a46fSAndroid Build Coastguard Worker return "37e35705946806f8f98c51e4e25647a2";
1444*3ac0a46fSAndroid Build Coastguard Worker }
1445*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_ARM64)
1446*3ac0a46fSAndroid Build Coastguard Worker return "9cf1c024a9d2d356bcdd14cb71a32324";
1447*3ac0a46fSAndroid Build Coastguard Worker #elif BUILDFLAG(IS_APPLE) && !defined(ARCH_CPU_ARM64)
1448*3ac0a46fSAndroid Build Coastguard Worker return "8c992808db99dbe3d74006358a671f05";
1449*3ac0a46fSAndroid Build Coastguard Worker #else
1450*3ac0a46fSAndroid Build Coastguard Worker return "03cae68322d6a6ba120e738ab325408c";
1451*3ac0a46fSAndroid Build Coastguard Worker #endif
1452*3ac0a46fSAndroid Build Coastguard Worker }();
1453*3ac0a46fSAndroid Build Coastguard Worker
1454*3ac0a46fSAndroid Build Coastguard Worker // Open a file with two annotations and load its first page.
1455*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
1456*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1457*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1458*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
1459*3ac0a46fSAndroid Build Coastguard Worker
1460*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly.
1461*3ac0a46fSAndroid Build Coastguard Worker {
1462*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1463*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, AnnotationStampWithApChecksum());
1464*3ac0a46fSAndroid Build Coastguard Worker }
1465*3ac0a46fSAndroid Build Coastguard Worker
1466*3ac0a46fSAndroid Build Coastguard Worker {
1467*3ac0a46fSAndroid Build Coastguard Worker // Create a stamp annotation and set its annotation rectangle.
1468*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
1469*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1470*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF rect;
1471*3ac0a46fSAndroid Build Coastguard Worker rect.left = 200.f;
1472*3ac0a46fSAndroid Build Coastguard Worker rect.bottom = 550.f;
1473*3ac0a46fSAndroid Build Coastguard Worker rect.right = 450.f;
1474*3ac0a46fSAndroid Build Coastguard Worker rect.top = 650.f;
1475*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &rect));
1476*3ac0a46fSAndroid Build Coastguard Worker
1477*3ac0a46fSAndroid Build Coastguard Worker // Add a translucent text object to the new annotation.
1478*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT text_object =
1479*3ac0a46fSAndroid Build Coastguard Worker FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
1480*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(text_object);
1481*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString text =
1482*3ac0a46fSAndroid Build Coastguard Worker GetFPDFWideString(L"I'm a translucent text laying on other text.");
1483*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
1484*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPageObj_SetFillColor(text_object, 0, 0, 255, 150));
1485*3ac0a46fSAndroid Build Coastguard Worker FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 600);
1486*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), text_object));
1487*3ac0a46fSAndroid Build Coastguard Worker }
1488*3ac0a46fSAndroid Build Coastguard Worker
1489*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly with the new text object.
1490*3ac0a46fSAndroid Build Coastguard Worker {
1491*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1492*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, md5_new_text);
1493*3ac0a46fSAndroid Build Coastguard Worker }
1494*3ac0a46fSAndroid Build Coastguard Worker
1495*3ac0a46fSAndroid Build Coastguard Worker {
1496*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the newly added stamp annotation and its text object.
1497*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1498*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1499*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
1500*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT text_object = FPDFAnnot_GetObject(annot.get(), 0);
1501*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_object));
1502*3ac0a46fSAndroid Build Coastguard Worker
1503*3ac0a46fSAndroid Build Coastguard Worker // Modify the text in the new annotation.
1504*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString new_text = GetFPDFWideString(L"New text!");
1505*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFText_SetText(text_object, new_text.get()));
1506*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_UpdateObject(annot.get(), text_object));
1507*3ac0a46fSAndroid Build Coastguard Worker }
1508*3ac0a46fSAndroid Build Coastguard Worker
1509*3ac0a46fSAndroid Build Coastguard Worker // Check that the page renders correctly with the modified text object.
1510*3ac0a46fSAndroid Build Coastguard Worker {
1511*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1512*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, md5_modified_text);
1513*3ac0a46fSAndroid Build Coastguard Worker }
1514*3ac0a46fSAndroid Build Coastguard Worker
1515*3ac0a46fSAndroid Build Coastguard Worker // Remove the new annotation, and check that the page renders as before.
1516*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 2));
1517*3ac0a46fSAndroid Build Coastguard Worker {
1518*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
1519*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 595, 842, AnnotationStampWithApChecksum());
1520*3ac0a46fSAndroid Build Coastguard Worker }
1521*3ac0a46fSAndroid Build Coastguard Worker
1522*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1523*3ac0a46fSAndroid Build Coastguard Worker }
1524*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetSetStringValue)1525*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetSetStringValue) {
1526*3ac0a46fSAndroid Build Coastguard Worker // Open a file with four annotations and load its first page.
1527*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
1528*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1529*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1530*3ac0a46fSAndroid Build Coastguard Worker
1531*3ac0a46fSAndroid Build Coastguard Worker static const wchar_t kNewDate[] = L"D:201706282359Z00'00'";
1532*3ac0a46fSAndroid Build Coastguard Worker
1533*3ac0a46fSAndroid Build Coastguard Worker {
1534*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the first annotation.
1535*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1536*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1537*3ac0a46fSAndroid Build Coastguard Worker
1538*3ac0a46fSAndroid Build Coastguard Worker // Check that a non-existent key does not exist.
1539*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_HasKey(annot.get(), "none"));
1540*3ac0a46fSAndroid Build Coastguard Worker
1541*3ac0a46fSAndroid Build Coastguard Worker // Check that the string value of a non-string dictionary entry is empty.
1542*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_HasKey(annot.get(), pdfium::annotation::kAP));
1543*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_OBJECT_REFERENCE,
1544*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kAP));
1545*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kAP,
1546*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1547*3ac0a46fSAndroid Build Coastguard Worker
1548*3ac0a46fSAndroid Build Coastguard Worker // Check that the string value of the hash is correct.
1549*3ac0a46fSAndroid Build Coastguard Worker static const char kHashKey[] = "AAPL:Hash";
1550*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot.get(), kHashKey));
1551*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
1552*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetStringValue(annot.get(), kHashKey, nullptr, 0);
1553*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(66u, length_bytes);
1554*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
1555*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(66u, FPDFAnnot_GetStringValue(annot.get(), kHashKey, buf.data(),
1556*3ac0a46fSAndroid Build Coastguard Worker length_bytes));
1557*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"395fbcb98d558681742f30683a62a2ad",
1558*3ac0a46fSAndroid Build Coastguard Worker GetPlatformWString(buf.data()));
1559*3ac0a46fSAndroid Build Coastguard Worker
1560*3ac0a46fSAndroid Build Coastguard Worker // Check that the string value of the modified date is correct.
1561*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot.get(), kHashKey));
1562*3ac0a46fSAndroid Build Coastguard Worker length_bytes = FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kM,
1563*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0);
1564*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(44u, length_bytes);
1565*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(length_bytes);
1566*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(44u, FPDFAnnot_GetStringValue(annot.get(), pdfium::annotation::kM,
1567*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
1568*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"D:201706071721Z00'00'", GetPlatformWString(buf.data()));
1569*3ac0a46fSAndroid Build Coastguard Worker
1570*3ac0a46fSAndroid Build Coastguard Worker // Update the date entry for the annotation.
1571*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString text = GetFPDFWideString(kNewDate);
1572*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetStringValue(annot.get(), pdfium::annotation::kM,
1573*3ac0a46fSAndroid Build Coastguard Worker text.get()));
1574*3ac0a46fSAndroid Build Coastguard Worker }
1575*3ac0a46fSAndroid Build Coastguard Worker
1576*3ac0a46fSAndroid Build Coastguard Worker // Save the document and close the page.
1577*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1578*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1579*3ac0a46fSAndroid Build Coastguard Worker
1580*3ac0a46fSAndroid Build Coastguard Worker const char* md5 = []() {
1581*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
1582*3ac0a46fSAndroid Build Coastguard Worker return "a95a65d109eda5671c793ff5f7d2a2df";
1583*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
1584*3ac0a46fSAndroid Build Coastguard Worker return "52e93c54796f7f7167edf64e81d12bd7";
1585*3ac0a46fSAndroid Build Coastguard Worker #else
1586*3ac0a46fSAndroid Build Coastguard Worker return "5143f9a98beb7b00ff40b89110a1089f";
1587*3ac0a46fSAndroid Build Coastguard Worker #endif
1588*3ac0a46fSAndroid Build Coastguard Worker }();
1589*3ac0a46fSAndroid Build Coastguard Worker
1590*3ac0a46fSAndroid Build Coastguard Worker // Open the saved annotation.
1591*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenSavedDocument());
1592*3ac0a46fSAndroid Build Coastguard Worker page = LoadSavedPage(0);
1593*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1594*3ac0a46fSAndroid Build Coastguard Worker VerifySavedRendering(page, 595, 842, md5);
1595*3ac0a46fSAndroid Build Coastguard Worker {
1596*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 0));
1597*3ac0a46fSAndroid Build Coastguard Worker
1598*3ac0a46fSAndroid Build Coastguard Worker // Check that the string value of the modified date is the newly-set value.
1599*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_OBJECT_STRING,
1600*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetValueType(new_annot.get(), pdfium::annotation::kM));
1601*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes = FPDFAnnot_GetStringValue(
1602*3ac0a46fSAndroid Build Coastguard Worker new_annot.get(), pdfium::annotation::kM, nullptr, 0);
1603*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(44u, length_bytes);
1604*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
1605*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(44u,
1606*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetStringValue(new_annot.get(), pdfium::annotation::kM,
1607*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
1608*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kNewDate, GetPlatformWString(buf.data()));
1609*3ac0a46fSAndroid Build Coastguard Worker }
1610*3ac0a46fSAndroid Build Coastguard Worker
1611*3ac0a46fSAndroid Build Coastguard Worker CloseSavedPage(page);
1612*3ac0a46fSAndroid Build Coastguard Worker CloseSavedDocument();
1613*3ac0a46fSAndroid Build Coastguard Worker }
1614*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetNumberValue)1615*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetNumberValue) {
1616*3ac0a46fSAndroid Build Coastguard Worker // Open a file with four text annotations and load its first page.
1617*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
1618*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1619*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1620*3ac0a46fSAndroid Build Coastguard Worker {
1621*3ac0a46fSAndroid Build Coastguard Worker // First two annotations do not have "MaxLen" attribute.
1622*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
1623*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
1624*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1625*3ac0a46fSAndroid Build Coastguard Worker
1626*3ac0a46fSAndroid Build Coastguard Worker // Verify that no "MaxLen" key present.
1627*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_HasKey(annot.get(), "MaxLen"));
1628*3ac0a46fSAndroid Build Coastguard Worker
1629*3ac0a46fSAndroid Build Coastguard Worker float value;
1630*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", &value));
1631*3ac0a46fSAndroid Build Coastguard Worker }
1632*3ac0a46fSAndroid Build Coastguard Worker
1633*3ac0a46fSAndroid Build Coastguard Worker // Annotation in index 2 has "MaxLen" of 10.
1634*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1635*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1636*3ac0a46fSAndroid Build Coastguard Worker
1637*3ac0a46fSAndroid Build Coastguard Worker // Verify that "MaxLen" key present.
1638*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_HasKey(annot.get(), "MaxLen"));
1639*3ac0a46fSAndroid Build Coastguard Worker
1640*3ac0a46fSAndroid Build Coastguard Worker float value;
1641*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", &value));
1642*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(10.0f, value);
1643*3ac0a46fSAndroid Build Coastguard Worker
1644*3ac0a46fSAndroid Build Coastguard Worker // Check bad inputs.
1645*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetNumberValue(nullptr, "MaxLen", &value));
1646*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), nullptr, &value));
1647*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "MaxLen", nullptr));
1648*3ac0a46fSAndroid Build Coastguard Worker // Ask for key that exists but is not a number.
1649*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetNumberValue(annot.get(), "V", &value));
1650*3ac0a46fSAndroid Build Coastguard Worker }
1651*3ac0a46fSAndroid Build Coastguard Worker
1652*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1653*3ac0a46fSAndroid Build Coastguard Worker }
1654*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetSetAP)1655*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetSetAP) {
1656*3ac0a46fSAndroid Build Coastguard Worker // Open a file with four annotations and load its first page.
1657*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
1658*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1659*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1660*3ac0a46fSAndroid Build Coastguard Worker
1661*3ac0a46fSAndroid Build Coastguard Worker {
1662*3ac0a46fSAndroid Build Coastguard Worker static const char kMd5NormalAP[] = "be903df0343fd774fadab9c8900cdf4a";
1663*3ac0a46fSAndroid Build Coastguard Worker static constexpr size_t kExpectNormalAPLength = 73970;
1664*3ac0a46fSAndroid Build Coastguard Worker
1665*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the first annotation.
1666*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1667*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1668*3ac0a46fSAndroid Build Coastguard Worker
1669*3ac0a46fSAndroid Build Coastguard Worker // Check that the string value of an AP returns the expected length.
1670*3ac0a46fSAndroid Build Coastguard Worker unsigned long normal_length_bytes = FPDFAnnot_GetAP(
1671*3ac0a46fSAndroid Build Coastguard Worker annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
1672*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kExpectNormalAPLength, normal_length_bytes);
1673*3ac0a46fSAndroid Build Coastguard Worker
1674*3ac0a46fSAndroid Build Coastguard Worker // Check that the string value of an AP is not returned if the buffer is too
1675*3ac0a46fSAndroid Build Coastguard Worker // small. The result buffer should be overwritten with an empty string.
1676*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(normal_length_bytes);
1677*3ac0a46fSAndroid Build Coastguard Worker // Write in the buffer to verify it's not overwritten.
1678*3ac0a46fSAndroid Build Coastguard Worker memcpy(buf.data(), "abcdefgh", 8);
1679*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kExpectNormalAPLength,
1680*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1681*3ac0a46fSAndroid Build Coastguard Worker buf.data(), normal_length_bytes - 1));
1682*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8));
1683*3ac0a46fSAndroid Build Coastguard Worker
1684*3ac0a46fSAndroid Build Coastguard Worker // Check that the string value of an AP is returned through a buffer that is
1685*3ac0a46fSAndroid Build Coastguard Worker // the right size.
1686*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kExpectNormalAPLength,
1687*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1688*3ac0a46fSAndroid Build Coastguard Worker buf.data(), normal_length_bytes));
1689*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kMd5NormalAP,
1690*3ac0a46fSAndroid Build Coastguard Worker GenerateMD5Base16({reinterpret_cast<uint8_t*>(buf.data()),
1691*3ac0a46fSAndroid Build Coastguard Worker normal_length_bytes}));
1692*3ac0a46fSAndroid Build Coastguard Worker
1693*3ac0a46fSAndroid Build Coastguard Worker // Check that the string value of an AP is returned through a buffer that is
1694*3ac0a46fSAndroid Build Coastguard Worker // larger than necessary.
1695*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(normal_length_bytes + 2);
1696*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kExpectNormalAPLength,
1697*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1698*3ac0a46fSAndroid Build Coastguard Worker buf.data(), normal_length_bytes + 2));
1699*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kMd5NormalAP,
1700*3ac0a46fSAndroid Build Coastguard Worker GenerateMD5Base16({reinterpret_cast<uint8_t*>(buf.data()),
1701*3ac0a46fSAndroid Build Coastguard Worker normal_length_bytes}));
1702*3ac0a46fSAndroid Build Coastguard Worker
1703*3ac0a46fSAndroid Build Coastguard Worker // Check that getting an AP for a mode that does not have an AP returns an
1704*3ac0a46fSAndroid Build Coastguard Worker // empty string.
1705*3ac0a46fSAndroid Build Coastguard Worker unsigned long rollover_length_bytes = FPDFAnnot_GetAP(
1706*3ac0a46fSAndroid Build Coastguard Worker annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
1707*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(2u, rollover_length_bytes);
1708*3ac0a46fSAndroid Build Coastguard Worker
1709*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(1000);
1710*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u,
1711*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1712*3ac0a46fSAndroid Build Coastguard Worker buf.data(), 1000));
1713*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"", GetPlatformWString(buf.data()));
1714*3ac0a46fSAndroid Build Coastguard Worker
1715*3ac0a46fSAndroid Build Coastguard Worker // Check that setting the AP for an invalid appearance mode fails.
1716*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
1717*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), -1, ap_text.get()));
1718*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_COUNT,
1719*3ac0a46fSAndroid Build Coastguard Worker ap_text.get()));
1720*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetAP(
1721*3ac0a46fSAndroid Build Coastguard Worker annot.get(), FPDF_ANNOT_APPEARANCEMODE_COUNT + 1, ap_text.get()));
1722*3ac0a46fSAndroid Build Coastguard Worker
1723*3ac0a46fSAndroid Build Coastguard Worker // Set the AP correctly now.
1724*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1725*3ac0a46fSAndroid Build Coastguard Worker ap_text.get()));
1726*3ac0a46fSAndroid Build Coastguard Worker
1727*3ac0a46fSAndroid Build Coastguard Worker // Check that the new annotation value is equal to the value we just set.
1728*3ac0a46fSAndroid Build Coastguard Worker rollover_length_bytes = FPDFAnnot_GetAP(
1729*3ac0a46fSAndroid Build Coastguard Worker annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
1730*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(24u, rollover_length_bytes);
1731*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(rollover_length_bytes);
1732*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(24u,
1733*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1734*3ac0a46fSAndroid Build Coastguard Worker buf.data(), rollover_length_bytes));
1735*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"new test ap", GetPlatformWString(buf.data()));
1736*3ac0a46fSAndroid Build Coastguard Worker
1737*3ac0a46fSAndroid Build Coastguard Worker // Check that the Normal AP was not touched when the Rollover AP was set.
1738*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(normal_length_bytes);
1739*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kExpectNormalAPLength,
1740*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1741*3ac0a46fSAndroid Build Coastguard Worker buf.data(), normal_length_bytes));
1742*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kMd5NormalAP,
1743*3ac0a46fSAndroid Build Coastguard Worker GenerateMD5Base16({reinterpret_cast<uint8_t*>(buf.data()),
1744*3ac0a46fSAndroid Build Coastguard Worker normal_length_bytes}));
1745*3ac0a46fSAndroid Build Coastguard Worker }
1746*3ac0a46fSAndroid Build Coastguard Worker
1747*3ac0a46fSAndroid Build Coastguard Worker // Save the modified document, then reopen it.
1748*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1749*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1750*3ac0a46fSAndroid Build Coastguard Worker
1751*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenSavedDocument());
1752*3ac0a46fSAndroid Build Coastguard Worker page = LoadSavedPage(0);
1753*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1754*3ac0a46fSAndroid Build Coastguard Worker {
1755*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation new_annot(FPDFPage_GetAnnot(page, 0));
1756*3ac0a46fSAndroid Build Coastguard Worker
1757*3ac0a46fSAndroid Build Coastguard Worker // Check that the new annotation value is equal to the value we set before
1758*3ac0a46fSAndroid Build Coastguard Worker // saving.
1759*3ac0a46fSAndroid Build Coastguard Worker unsigned long rollover_length_bytes = FPDFAnnot_GetAP(
1760*3ac0a46fSAndroid Build Coastguard Worker new_annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
1761*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(24u, rollover_length_bytes);
1762*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf =
1763*3ac0a46fSAndroid Build Coastguard Worker GetFPDFWideStringBuffer(rollover_length_bytes);
1764*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(24u, FPDFAnnot_GetAP(new_annot.get(),
1765*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
1766*3ac0a46fSAndroid Build Coastguard Worker buf.data(), rollover_length_bytes));
1767*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"new test ap", GetPlatformWString(buf.data()));
1768*3ac0a46fSAndroid Build Coastguard Worker }
1769*3ac0a46fSAndroid Build Coastguard Worker
1770*3ac0a46fSAndroid Build Coastguard Worker // Close saved document.
1771*3ac0a46fSAndroid Build Coastguard Worker CloseSavedPage(page);
1772*3ac0a46fSAndroid Build Coastguard Worker CloseSavedDocument();
1773*3ac0a46fSAndroid Build Coastguard Worker }
1774*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,RemoveOptionalAP)1775*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, RemoveOptionalAP) {
1776*3ac0a46fSAndroid Build Coastguard Worker // Open a file with four annotations and load its first page.
1777*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
1778*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1779*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1780*3ac0a46fSAndroid Build Coastguard Worker
1781*3ac0a46fSAndroid Build Coastguard Worker {
1782*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the first annotation.
1783*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1784*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1785*3ac0a46fSAndroid Build Coastguard Worker
1786*3ac0a46fSAndroid Build Coastguard Worker // Set Down AP. Normal AP is already set.
1787*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
1788*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1789*3ac0a46fSAndroid Build Coastguard Worker ap_text.get()));
1790*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(73970u,
1791*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1792*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1793*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(24u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1794*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1795*3ac0a46fSAndroid Build Coastguard Worker
1796*3ac0a46fSAndroid Build Coastguard Worker // Check that setting the Down AP to null removes the Down entry but keeps
1797*3ac0a46fSAndroid Build Coastguard Worker // Normal intact.
1798*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(
1799*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr));
1800*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(73970u,
1801*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1802*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1803*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1804*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1805*3ac0a46fSAndroid Build Coastguard Worker }
1806*3ac0a46fSAndroid Build Coastguard Worker
1807*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1808*3ac0a46fSAndroid Build Coastguard Worker }
1809*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,RemoveRequiredAP)1810*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, RemoveRequiredAP) {
1811*3ac0a46fSAndroid Build Coastguard Worker // Open a file with four annotations and load its first page.
1812*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
1813*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1814*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1815*3ac0a46fSAndroid Build Coastguard Worker
1816*3ac0a46fSAndroid Build Coastguard Worker {
1817*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the first annotation.
1818*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1819*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1820*3ac0a46fSAndroid Build Coastguard Worker
1821*3ac0a46fSAndroid Build Coastguard Worker // Set Down AP. Normal AP is already set.
1822*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString ap_text = GetFPDFWideString(L"new test ap");
1823*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1824*3ac0a46fSAndroid Build Coastguard Worker ap_text.get()));
1825*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(73970u,
1826*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1827*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1828*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(24u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1829*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1830*3ac0a46fSAndroid Build Coastguard Worker
1831*3ac0a46fSAndroid Build Coastguard Worker // Check that setting the Normal AP to null removes the whole AP dictionary.
1832*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1833*3ac0a46fSAndroid Build Coastguard Worker nullptr));
1834*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
1835*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1836*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_DOWN,
1837*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
1838*3ac0a46fSAndroid Build Coastguard Worker }
1839*3ac0a46fSAndroid Build Coastguard Worker
1840*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1841*3ac0a46fSAndroid Build Coastguard Worker }
1842*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,ExtractLinkedAnnotations)1843*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, ExtractLinkedAnnotations) {
1844*3ac0a46fSAndroid Build Coastguard Worker // Open a file with annotations and load its first page.
1845*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
1846*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1847*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1848*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFPage_GetAnnotIndex(page, nullptr));
1849*3ac0a46fSAndroid Build Coastguard Worker
1850*3ac0a46fSAndroid Build Coastguard Worker {
1851*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the highlight annotation which has its popup defined.
1852*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1853*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1854*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
1855*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, FPDFPage_GetAnnotIndex(page, annot.get()));
1856*3ac0a46fSAndroid Build Coastguard Worker static const char kPopupKey[] = "Popup";
1857*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_HasKey(annot.get(), kPopupKey));
1858*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(FPDF_OBJECT_REFERENCE,
1859*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetValueType(annot.get(), kPopupKey));
1860*3ac0a46fSAndroid Build Coastguard Worker
1861*3ac0a46fSAndroid Build Coastguard Worker // Retrieve and verify the popup of the highlight annotation.
1862*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation popup(
1863*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetLinkedAnnot(annot.get(), kPopupKey));
1864*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(popup);
1865*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_POPUP, FPDFAnnot_GetSubtype(popup.get()));
1866*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotIndex(page, popup.get()));
1867*3ac0a46fSAndroid Build Coastguard Worker FS_RECTF rect;
1868*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetRect(popup.get(), &rect));
1869*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(612.0f, rect.left, 0.001f);
1870*3ac0a46fSAndroid Build Coastguard Worker EXPECT_NEAR(578.792, rect.bottom, 0.001f);
1871*3ac0a46fSAndroid Build Coastguard Worker
1872*3ac0a46fSAndroid Build Coastguard Worker // Attempting to retrieve |annot|'s "IRT"-linked annotation would fail,
1873*3ac0a46fSAndroid Build Coastguard Worker // since "IRT" is not a key in |annot|'s dictionary.
1874*3ac0a46fSAndroid Build Coastguard Worker static const char kIRTKey[] = "IRT";
1875*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_HasKey(annot.get(), kIRTKey));
1876*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot.get(), kIRTKey));
1877*3ac0a46fSAndroid Build Coastguard Worker
1878*3ac0a46fSAndroid Build Coastguard Worker // Attempting to retrieve |annot|'s parent dictionary as an annotation
1879*3ac0a46fSAndroid Build Coastguard Worker // would fail, since its parent is not an annotation.
1880*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_HasKey(annot.get(), pdfium::annotation::kP));
1881*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_OBJECT_REFERENCE,
1882*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetValueType(annot.get(), pdfium::annotation::kP));
1883*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot.get(), pdfium::annotation::kP));
1884*3ac0a46fSAndroid Build Coastguard Worker }
1885*3ac0a46fSAndroid Build Coastguard Worker
1886*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1887*3ac0a46fSAndroid Build Coastguard Worker }
1888*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldFlagsTextField)1889*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldFlagsTextField) {
1890*3ac0a46fSAndroid Build Coastguard Worker // Open file with form text fields.
1891*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
1892*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1893*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1894*3ac0a46fSAndroid Build Coastguard Worker
1895*3ac0a46fSAndroid Build Coastguard Worker {
1896*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the first annotation: user-editable text field.
1897*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1898*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1899*3ac0a46fSAndroid Build Coastguard Worker
1900*3ac0a46fSAndroid Build Coastguard Worker // Check that the flag values are as expected.
1901*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
1902*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1903*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1904*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1905*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_MULTILINE);
1906*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
1907*3ac0a46fSAndroid Build Coastguard Worker }
1908*3ac0a46fSAndroid Build Coastguard Worker
1909*3ac0a46fSAndroid Build Coastguard Worker {
1910*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the second annotation: read-only text field.
1911*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
1912*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1913*3ac0a46fSAndroid Build Coastguard Worker
1914*3ac0a46fSAndroid Build Coastguard Worker // Check that the flag values are as expected.
1915*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
1916*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1917*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1918*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1919*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_MULTILINE);
1920*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
1921*3ac0a46fSAndroid Build Coastguard Worker }
1922*3ac0a46fSAndroid Build Coastguard Worker
1923*3ac0a46fSAndroid Build Coastguard Worker {
1924*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the fourth annotation: user-editable password text field.
1925*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
1926*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1927*3ac0a46fSAndroid Build Coastguard Worker
1928*3ac0a46fSAndroid Build Coastguard Worker // Check that the flag values are as expected.
1929*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
1930*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1931*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1932*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1933*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_TEXT_MULTILINE);
1934*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_TEXT_PASSWORD);
1935*3ac0a46fSAndroid Build Coastguard Worker }
1936*3ac0a46fSAndroid Build Coastguard Worker
1937*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1938*3ac0a46fSAndroid Build Coastguard Worker }
1939*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldFlagsComboBox)1940*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldFlagsComboBox) {
1941*3ac0a46fSAndroid Build Coastguard Worker // Open file with form text fields.
1942*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
1943*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1944*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1945*3ac0a46fSAndroid Build Coastguard Worker
1946*3ac0a46fSAndroid Build Coastguard Worker {
1947*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the first annotation: user-editable combobox.
1948*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
1949*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1950*3ac0a46fSAndroid Build Coastguard Worker
1951*3ac0a46fSAndroid Build Coastguard Worker // Check that the flag values are as expected.
1952*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
1953*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1954*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1955*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1956*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1957*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1958*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
1959*3ac0a46fSAndroid Build Coastguard Worker }
1960*3ac0a46fSAndroid Build Coastguard Worker
1961*3ac0a46fSAndroid Build Coastguard Worker {
1962*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the second annotation: regular combobox.
1963*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
1964*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1965*3ac0a46fSAndroid Build Coastguard Worker
1966*3ac0a46fSAndroid Build Coastguard Worker // Check that the flag values are as expected.
1967*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
1968*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
1969*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1970*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1971*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1972*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1973*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
1974*3ac0a46fSAndroid Build Coastguard Worker }
1975*3ac0a46fSAndroid Build Coastguard Worker
1976*3ac0a46fSAndroid Build Coastguard Worker {
1977*3ac0a46fSAndroid Build Coastguard Worker // Retrieve the third annotation: read-only combobox.
1978*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
1979*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
1980*3ac0a46fSAndroid Build Coastguard Worker
1981*3ac0a46fSAndroid Build Coastguard Worker // Check that the flag values are as expected.
1982*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
1983*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
1984*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
1985*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
1986*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
1987*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
1988*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
1989*3ac0a46fSAndroid Build Coastguard Worker }
1990*3ac0a46fSAndroid Build Coastguard Worker
1991*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
1992*3ac0a46fSAndroid Build Coastguard Worker }
1993*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormAnnotNull)1994*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotNull) {
1995*3ac0a46fSAndroid Build Coastguard Worker // Open file with form text fields.
1996*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form.pdf"));
1997*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
1998*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
1999*3ac0a46fSAndroid Build Coastguard Worker
2000*3ac0a46fSAndroid Build Coastguard Worker // Attempt to get an annotation where no annotation exists on page.
2001*3ac0a46fSAndroid Build Coastguard Worker static const FS_POINTF kOriginPoint = {0.0f, 0.0f};
2002*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(
2003*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kOriginPoint));
2004*3ac0a46fSAndroid Build Coastguard Worker
2005*3ac0a46fSAndroid Build Coastguard Worker static const FS_POINTF kValidPoint = {120.0f, 120.0f};
2006*3ac0a46fSAndroid Build Coastguard Worker {
2007*3ac0a46fSAndroid Build Coastguard Worker // Verify there is an annotation.
2008*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(
2009*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kValidPoint));
2010*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(annot);
2011*3ac0a46fSAndroid Build Coastguard Worker }
2012*3ac0a46fSAndroid Build Coastguard Worker
2013*3ac0a46fSAndroid Build Coastguard Worker // Try other bad inputs at a valid location.
2014*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, nullptr, &kValidPoint));
2015*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, page, &kValidPoint));
2016*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(
2017*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(form_handle(), nullptr, &kValidPoint));
2018*3ac0a46fSAndroid Build Coastguard Worker
2019*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2020*3ac0a46fSAndroid Build Coastguard Worker }
2021*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormAnnotAndCheckFlagsTextField)2022*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotAndCheckFlagsTextField) {
2023*3ac0a46fSAndroid Build Coastguard Worker // Open file with form text fields.
2024*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
2025*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2026*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2027*3ac0a46fSAndroid Build Coastguard Worker
2028*3ac0a46fSAndroid Build Coastguard Worker {
2029*3ac0a46fSAndroid Build Coastguard Worker // Retrieve user-editable text field annotation.
2030*3ac0a46fSAndroid Build Coastguard Worker static const FS_POINTF kPoint = {105.0f, 118.0f};
2031*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(
2032*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
2033*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2034*3ac0a46fSAndroid Build Coastguard Worker
2035*3ac0a46fSAndroid Build Coastguard Worker // Check that interactive form annotation flag values are as expected.
2036*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
2037*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2038*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
2039*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
2040*3ac0a46fSAndroid Build Coastguard Worker }
2041*3ac0a46fSAndroid Build Coastguard Worker
2042*3ac0a46fSAndroid Build Coastguard Worker {
2043*3ac0a46fSAndroid Build Coastguard Worker // Retrieve read-only text field annotation.
2044*3ac0a46fSAndroid Build Coastguard Worker static const FS_POINTF kPoint = {105.0f, 202.0f};
2045*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(
2046*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
2047*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2048*3ac0a46fSAndroid Build Coastguard Worker
2049*3ac0a46fSAndroid Build Coastguard Worker // Check that interactive form annotation flag values are as expected.
2050*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
2051*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
2052*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2053*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
2054*3ac0a46fSAndroid Build Coastguard Worker }
2055*3ac0a46fSAndroid Build Coastguard Worker
2056*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2057*3ac0a46fSAndroid Build Coastguard Worker }
2058*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormAnnotAndCheckFlagsComboBox)2059*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormAnnotAndCheckFlagsComboBox) {
2060*3ac0a46fSAndroid Build Coastguard Worker // Open file with form comboboxes.
2061*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2062*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2063*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2064*3ac0a46fSAndroid Build Coastguard Worker
2065*3ac0a46fSAndroid Build Coastguard Worker {
2066*3ac0a46fSAndroid Build Coastguard Worker // Retrieve user-editable combobox annotation.
2067*3ac0a46fSAndroid Build Coastguard Worker static const FS_POINTF kPoint = {102.0f, 363.0f};
2068*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(
2069*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
2070*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2071*3ac0a46fSAndroid Build Coastguard Worker
2072*3ac0a46fSAndroid Build Coastguard Worker // Check that interactive form annotation flag values are as expected.
2073*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
2074*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
2075*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2076*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
2077*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
2078*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
2079*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
2080*3ac0a46fSAndroid Build Coastguard Worker }
2081*3ac0a46fSAndroid Build Coastguard Worker
2082*3ac0a46fSAndroid Build Coastguard Worker {
2083*3ac0a46fSAndroid Build Coastguard Worker // Retrieve regular combobox annotation.
2084*3ac0a46fSAndroid Build Coastguard Worker static const FS_POINTF kPoint = {102.0f, 413.0f};
2085*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(
2086*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
2087*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2088*3ac0a46fSAndroid Build Coastguard Worker
2089*3ac0a46fSAndroid Build Coastguard Worker // Check that interactive form annotation flag values are as expected.
2090*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
2091*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
2092*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2093*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
2094*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
2095*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
2096*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
2097*3ac0a46fSAndroid Build Coastguard Worker }
2098*3ac0a46fSAndroid Build Coastguard Worker
2099*3ac0a46fSAndroid Build Coastguard Worker {
2100*3ac0a46fSAndroid Build Coastguard Worker // Retrieve read-only combobox annotation.
2101*3ac0a46fSAndroid Build Coastguard Worker static const FS_POINTF kPoint = {102.0f, 513.0f};
2102*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(
2103*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
2104*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2105*3ac0a46fSAndroid Build Coastguard Worker
2106*3ac0a46fSAndroid Build Coastguard Worker // Check that interactive form annotation flag values are as expected.
2107*3ac0a46fSAndroid Build Coastguard Worker int flags = FPDFAnnot_GetFormFieldFlags(form_handle(), annot.get());
2108*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
2109*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_REQUIRED);
2110*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_NOEXPORT);
2111*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
2112*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
2113*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_MULTI_SELECT);
2114*3ac0a46fSAndroid Build Coastguard Worker }
2115*3ac0a46fSAndroid Build Coastguard Worker
2116*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2117*3ac0a46fSAndroid Build Coastguard Worker }
2118*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,BUG_1206)2119*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, BUG_1206) {
2120*3ac0a46fSAndroid Build Coastguard Worker const char* expected_bitmap = []() {
2121*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
2122*3ac0a46fSAndroid Build Coastguard Worker return "a1ea1ceebb26922fae576cb79ce63af0";
2123*3ac0a46fSAndroid Build Coastguard Worker return "0d9fc05c6762fd788bd23fd87a4967bc";
2124*3ac0a46fSAndroid Build Coastguard Worker }();
2125*3ac0a46fSAndroid Build Coastguard Worker static constexpr size_t kExpectedSize = 1590;
2126*3ac0a46fSAndroid Build Coastguard Worker
2127*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("bug_1206.pdf"));
2128*3ac0a46fSAndroid Build Coastguard Worker
2129*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2130*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2131*3ac0a46fSAndroid Build Coastguard Worker
2132*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2133*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kExpectedSize, GetString().size());
2134*3ac0a46fSAndroid Build Coastguard Worker ClearString();
2135*3ac0a46fSAndroid Build Coastguard Worker
2136*3ac0a46fSAndroid Build Coastguard Worker for (size_t i = 0; i < 10; ++i) {
2137*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
2138*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, expected_bitmap);
2139*3ac0a46fSAndroid Build Coastguard Worker
2140*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2141*3ac0a46fSAndroid Build Coastguard Worker // TODO(https://crbug.com/pdfium/1206): This is wrong. The size should be
2142*3ac0a46fSAndroid Build Coastguard Worker // equal, not bigger.
2143*3ac0a46fSAndroid Build Coastguard Worker EXPECT_LT(kExpectedSize, GetString().size());
2144*3ac0a46fSAndroid Build Coastguard Worker ClearString();
2145*3ac0a46fSAndroid Build Coastguard Worker }
2146*3ac0a46fSAndroid Build Coastguard Worker
2147*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2148*3ac0a46fSAndroid Build Coastguard Worker }
2149*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,BUG_1212)2150*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, BUG_1212) {
2151*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("hello_world.pdf"));
2152*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2153*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2154*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
2155*3ac0a46fSAndroid Build Coastguard Worker
2156*3ac0a46fSAndroid Build Coastguard Worker static const char kTestKey[] = "test";
2157*3ac0a46fSAndroid Build Coastguard Worker static const wchar_t kData[] = L"\xf6\xe4";
2158*3ac0a46fSAndroid Build Coastguard Worker static const size_t kBufSize = 12;
2159*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(kBufSize);
2160*3ac0a46fSAndroid Build Coastguard Worker
2161*3ac0a46fSAndroid Build Coastguard Worker {
2162*3ac0a46fSAndroid Build Coastguard Worker // Add a text annotation to the page.
2163*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT));
2164*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2165*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
2166*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
2167*3ac0a46fSAndroid Build Coastguard Worker
2168*3ac0a46fSAndroid Build Coastguard Worker // Make sure there is no test key, add set a value there, and read it back.
2169*3ac0a46fSAndroid Build Coastguard Worker std::fill(buf.begin(), buf.end(), 'x');
2170*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(2u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
2171*3ac0a46fSAndroid Build Coastguard Worker kBufSize));
2172*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"", GetPlatformWString(buf.data()));
2173*3ac0a46fSAndroid Build Coastguard Worker
2174*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString text = GetFPDFWideString(kData);
2175*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetStringValue(annot.get(), kTestKey, text.get()));
2176*3ac0a46fSAndroid Build Coastguard Worker
2177*3ac0a46fSAndroid Build Coastguard Worker std::fill(buf.begin(), buf.end(), 'x');
2178*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
2179*3ac0a46fSAndroid Build Coastguard Worker kBufSize));
2180*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kData, GetPlatformWString(buf.data()));
2181*3ac0a46fSAndroid Build Coastguard Worker }
2182*3ac0a46fSAndroid Build Coastguard Worker
2183*3ac0a46fSAndroid Build Coastguard Worker {
2184*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP));
2185*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2186*3ac0a46fSAndroid Build Coastguard Worker const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
2187*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
2188*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
2189*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_STAMP, FPDFAnnot_GetSubtype(annot.get()));
2190*3ac0a46fSAndroid Build Coastguard Worker // Also do the same test for its appearance string.
2191*3ac0a46fSAndroid Build Coastguard Worker std::fill(buf.begin(), buf.end(), 'x');
2192*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(2u,
2193*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
2194*3ac0a46fSAndroid Build Coastguard Worker buf.data(), kBufSize));
2195*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"", GetPlatformWString(buf.data()));
2196*3ac0a46fSAndroid Build Coastguard Worker
2197*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFWideString text = GetFPDFWideString(kData);
2198*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
2199*3ac0a46fSAndroid Build Coastguard Worker text.get()));
2200*3ac0a46fSAndroid Build Coastguard Worker
2201*3ac0a46fSAndroid Build Coastguard Worker std::fill(buf.begin(), buf.end(), 'x');
2202*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(6u,
2203*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
2204*3ac0a46fSAndroid Build Coastguard Worker buf.data(), kBufSize));
2205*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kData, GetPlatformWString(buf.data()));
2206*3ac0a46fSAndroid Build Coastguard Worker }
2207*3ac0a46fSAndroid Build Coastguard Worker
2208*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2209*3ac0a46fSAndroid Build Coastguard Worker
2210*3ac0a46fSAndroid Build Coastguard Worker {
2211*3ac0a46fSAndroid Build Coastguard Worker // Save a copy, open the copy, and check the annotation again.
2212*3ac0a46fSAndroid Build Coastguard Worker // Note that it renders the rotation.
2213*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2214*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenSavedDocument());
2215*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE saved_page = LoadSavedPage(0);
2216*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_page);
2217*3ac0a46fSAndroid Build Coastguard Worker
2218*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(saved_page));
2219*3ac0a46fSAndroid Build Coastguard Worker {
2220*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(saved_page, 0));
2221*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2222*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
2223*3ac0a46fSAndroid Build Coastguard Worker
2224*3ac0a46fSAndroid Build Coastguard Worker std::fill(buf.begin(), buf.end(), 'x');
2225*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
2226*3ac0a46fSAndroid Build Coastguard Worker kBufSize));
2227*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kData, GetPlatformWString(buf.data()));
2228*3ac0a46fSAndroid Build Coastguard Worker }
2229*3ac0a46fSAndroid Build Coastguard Worker
2230*3ac0a46fSAndroid Build Coastguard Worker {
2231*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(saved_page, 0));
2232*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2233*3ac0a46fSAndroid Build Coastguard Worker // TODO(thestig): This return FPDF_ANNOT_UNKNOWN for some reason.
2234*3ac0a46fSAndroid Build Coastguard Worker // EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot.get()));
2235*3ac0a46fSAndroid Build Coastguard Worker
2236*3ac0a46fSAndroid Build Coastguard Worker std::fill(buf.begin(), buf.end(), 'x');
2237*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(6u, FPDFAnnot_GetStringValue(annot.get(), kTestKey, buf.data(),
2238*3ac0a46fSAndroid Build Coastguard Worker kBufSize));
2239*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kData, GetPlatformWString(buf.data()));
2240*3ac0a46fSAndroid Build Coastguard Worker }
2241*3ac0a46fSAndroid Build Coastguard Worker
2242*3ac0a46fSAndroid Build Coastguard Worker CloseSavedPage(saved_page);
2243*3ac0a46fSAndroid Build Coastguard Worker CloseSavedDocument();
2244*3ac0a46fSAndroid Build Coastguard Worker }
2245*3ac0a46fSAndroid Build Coastguard Worker }
2246*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetOptionCountCombobox)2247*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetOptionCountCombobox) {
2248*3ac0a46fSAndroid Build Coastguard Worker // Open a file with combobox widget annotations and load its first page.
2249*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2250*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2251*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2252*3ac0a46fSAndroid Build Coastguard Worker
2253*3ac0a46fSAndroid Build Coastguard Worker {
2254*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2255*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2256*3ac0a46fSAndroid Build Coastguard Worker
2257*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2258*3ac0a46fSAndroid Build Coastguard Worker
2259*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2260*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2261*3ac0a46fSAndroid Build Coastguard Worker
2262*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(26, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2263*3ac0a46fSAndroid Build Coastguard Worker
2264*3ac0a46fSAndroid Build Coastguard Worker // Check bad form handle / annot.
2265*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(nullptr, nullptr));
2266*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), nullptr));
2267*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(nullptr, annot.get()));
2268*3ac0a46fSAndroid Build Coastguard Worker }
2269*3ac0a46fSAndroid Build Coastguard Worker
2270*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2271*3ac0a46fSAndroid Build Coastguard Worker }
2272*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetOptionCountListbox)2273*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetOptionCountListbox) {
2274*3ac0a46fSAndroid Build Coastguard Worker // Open a file with listbox widget annotations and load its first page.
2275*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
2276*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2277*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2278*3ac0a46fSAndroid Build Coastguard Worker
2279*3ac0a46fSAndroid Build Coastguard Worker {
2280*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2281*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2282*3ac0a46fSAndroid Build Coastguard Worker
2283*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2284*3ac0a46fSAndroid Build Coastguard Worker
2285*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2286*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2287*3ac0a46fSAndroid Build Coastguard Worker
2288*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(26, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2289*3ac0a46fSAndroid Build Coastguard Worker }
2290*3ac0a46fSAndroid Build Coastguard Worker
2291*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2292*3ac0a46fSAndroid Build Coastguard Worker }
2293*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetOptionCountInvalidAnnotations)2294*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetOptionCountInvalidAnnotations) {
2295*3ac0a46fSAndroid Build Coastguard Worker // Open a file with ink annotations and load its first page.
2296*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
2297*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2298*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2299*3ac0a46fSAndroid Build Coastguard Worker
2300*3ac0a46fSAndroid Build Coastguard Worker {
2301*3ac0a46fSAndroid Build Coastguard Worker // annotations do not have "Opt" array and will return -1
2302*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2303*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2304*3ac0a46fSAndroid Build Coastguard Worker
2305*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2306*3ac0a46fSAndroid Build Coastguard Worker
2307*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2308*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2309*3ac0a46fSAndroid Build Coastguard Worker
2310*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetOptionCount(form_handle(), annot.get()));
2311*3ac0a46fSAndroid Build Coastguard Worker }
2312*3ac0a46fSAndroid Build Coastguard Worker
2313*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2314*3ac0a46fSAndroid Build Coastguard Worker }
2315*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetOptionLabelCombobox)2316*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelCombobox) {
2317*3ac0a46fSAndroid Build Coastguard Worker // Open a file with combobox widget annotations and load its first page.
2318*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2319*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2320*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2321*3ac0a46fSAndroid Build Coastguard Worker
2322*3ac0a46fSAndroid Build Coastguard Worker {
2323*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2324*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2325*3ac0a46fSAndroid Build Coastguard Worker
2326*3ac0a46fSAndroid Build Coastguard Worker int index = 0;
2327*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
2328*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
2329*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(8u, length_bytes);
2330*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2331*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(8u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
2332*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2333*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Foo", GetPlatformWString(buf.data()));
2334*3ac0a46fSAndroid Build Coastguard Worker
2335*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2336*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2337*3ac0a46fSAndroid Build Coastguard Worker
2338*3ac0a46fSAndroid Build Coastguard Worker index = 0;
2339*3ac0a46fSAndroid Build Coastguard Worker length_bytes =
2340*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
2341*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(12u, length_bytes);
2342*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(length_bytes);
2343*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
2344*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2345*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Apple", GetPlatformWString(buf.data()));
2346*3ac0a46fSAndroid Build Coastguard Worker
2347*3ac0a46fSAndroid Build Coastguard Worker index = 25;
2348*3ac0a46fSAndroid Build Coastguard Worker length_bytes =
2349*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
2350*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(length_bytes);
2351*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(18u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
2352*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2353*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Zucchini", GetPlatformWString(buf.data()));
2354*3ac0a46fSAndroid Build Coastguard Worker
2355*3ac0a46fSAndroid Build Coastguard Worker // Indices out of range
2356*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), -1,
2357*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
2358*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 26,
2359*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
2360*3ac0a46fSAndroid Build Coastguard Worker
2361*3ac0a46fSAndroid Build Coastguard Worker // Check bad form handle / annot.
2362*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(nullptr, nullptr, 0, nullptr, 0));
2363*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u,
2364*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(nullptr, annot.get(), 0, nullptr, 0));
2365*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u,
2366*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(form_handle(), nullptr, 0, nullptr, 0));
2367*3ac0a46fSAndroid Build Coastguard Worker }
2368*3ac0a46fSAndroid Build Coastguard Worker
2369*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2370*3ac0a46fSAndroid Build Coastguard Worker }
2371*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetOptionLabelListbox)2372*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelListbox) {
2373*3ac0a46fSAndroid Build Coastguard Worker // Open a file with listbox widget annotations and load its first page.
2374*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
2375*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2376*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2377*3ac0a46fSAndroid Build Coastguard Worker
2378*3ac0a46fSAndroid Build Coastguard Worker {
2379*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2380*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2381*3ac0a46fSAndroid Build Coastguard Worker
2382*3ac0a46fSAndroid Build Coastguard Worker int index = 0;
2383*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
2384*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
2385*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(8u, length_bytes);
2386*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2387*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(8u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
2388*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2389*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Foo", GetPlatformWString(buf.data()));
2390*3ac0a46fSAndroid Build Coastguard Worker
2391*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2392*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2393*3ac0a46fSAndroid Build Coastguard Worker
2394*3ac0a46fSAndroid Build Coastguard Worker index = 0;
2395*3ac0a46fSAndroid Build Coastguard Worker length_bytes =
2396*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
2397*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(12u, length_bytes);
2398*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(length_bytes);
2399*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
2400*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2401*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Apple", GetPlatformWString(buf.data()));
2402*3ac0a46fSAndroid Build Coastguard Worker
2403*3ac0a46fSAndroid Build Coastguard Worker index = 25;
2404*3ac0a46fSAndroid Build Coastguard Worker length_bytes =
2405*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index, nullptr, 0);
2406*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(18u, length_bytes);
2407*3ac0a46fSAndroid Build Coastguard Worker buf = GetFPDFWideStringBuffer(length_bytes);
2408*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(18u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), index,
2409*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2410*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Zucchini", GetPlatformWString(buf.data()));
2411*3ac0a46fSAndroid Build Coastguard Worker
2412*3ac0a46fSAndroid Build Coastguard Worker // indices out of range
2413*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), -1,
2414*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
2415*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 26,
2416*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
2417*3ac0a46fSAndroid Build Coastguard Worker }
2418*3ac0a46fSAndroid Build Coastguard Worker
2419*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2420*3ac0a46fSAndroid Build Coastguard Worker }
2421*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetOptionLabelInvalidAnnotations)2422*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetOptionLabelInvalidAnnotations) {
2423*3ac0a46fSAndroid Build Coastguard Worker // Open a file with ink annotations and load its first page.
2424*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
2425*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2426*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2427*3ac0a46fSAndroid Build Coastguard Worker
2428*3ac0a46fSAndroid Build Coastguard Worker {
2429*3ac0a46fSAndroid Build Coastguard Worker // annotations do not have "Opt" array and will return 0
2430*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2431*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2432*3ac0a46fSAndroid Build Coastguard Worker
2433*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 0,
2434*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
2435*3ac0a46fSAndroid Build Coastguard Worker
2436*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2437*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2438*3ac0a46fSAndroid Build Coastguard Worker
2439*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetOptionLabel(form_handle(), annot.get(), 0,
2440*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
2441*3ac0a46fSAndroid Build Coastguard Worker }
2442*3ac0a46fSAndroid Build Coastguard Worker
2443*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2444*3ac0a46fSAndroid Build Coastguard Worker }
2445*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsOptionSelectedCombobox)2446*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsOptionSelectedCombobox) {
2447*3ac0a46fSAndroid Build Coastguard Worker // Open a file with combobox widget annotations and load its first page.
2448*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2449*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2450*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2451*3ac0a46fSAndroid Build Coastguard Worker
2452*3ac0a46fSAndroid Build Coastguard Worker {
2453*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2454*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2455*3ac0a46fSAndroid Build Coastguard Worker
2456*3ac0a46fSAndroid Build Coastguard Worker // Checks for Combobox with no Values (/V) or Selected Indices (/I) objects.
2457*3ac0a46fSAndroid Build Coastguard Worker int count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2458*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(3, count);
2459*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
2460*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2461*3ac0a46fSAndroid Build Coastguard Worker }
2462*3ac0a46fSAndroid Build Coastguard Worker
2463*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2464*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2465*3ac0a46fSAndroid Build Coastguard Worker
2466*3ac0a46fSAndroid Build Coastguard Worker // Checks for Combobox with Values (/V) object which is just a string.
2467*3ac0a46fSAndroid Build Coastguard Worker count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2468*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(26, count);
2469*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
2470*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(i == 1,
2471*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2472*3ac0a46fSAndroid Build Coastguard Worker }
2473*3ac0a46fSAndroid Build Coastguard Worker
2474*3ac0a46fSAndroid Build Coastguard Worker // Checks for index outside bound i.e. (index >= CountOption()).
2475*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(),
2476*3ac0a46fSAndroid Build Coastguard Worker /*index=*/26));
2477*3ac0a46fSAndroid Build Coastguard Worker // Checks for negetive index.
2478*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(),
2479*3ac0a46fSAndroid Build Coastguard Worker /*index=*/-1));
2480*3ac0a46fSAndroid Build Coastguard Worker
2481*3ac0a46fSAndroid Build Coastguard Worker // Checks for bad form handle/annot.
2482*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_IsOptionSelected(nullptr, nullptr, /*index=*/0));
2483*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(
2484*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsOptionSelected(form_handle(), nullptr, /*index=*/0));
2485*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_IsOptionSelected(nullptr, annot.get(), /*index=*/0));
2486*3ac0a46fSAndroid Build Coastguard Worker }
2487*3ac0a46fSAndroid Build Coastguard Worker
2488*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2489*3ac0a46fSAndroid Build Coastguard Worker }
2490*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsOptionSelectedListbox)2491*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsOptionSelectedListbox) {
2492*3ac0a46fSAndroid Build Coastguard Worker // Open a file with listbox widget annotations and load its first page.
2493*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("listbox_form.pdf"));
2494*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2495*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2496*3ac0a46fSAndroid Build Coastguard Worker
2497*3ac0a46fSAndroid Build Coastguard Worker {
2498*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2499*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2500*3ac0a46fSAndroid Build Coastguard Worker
2501*3ac0a46fSAndroid Build Coastguard Worker // Checks for Listbox with no Values (/V) or Selected Indices (/I) objects.
2502*3ac0a46fSAndroid Build Coastguard Worker int count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2503*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(3, count);
2504*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
2505*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2506*3ac0a46fSAndroid Build Coastguard Worker }
2507*3ac0a46fSAndroid Build Coastguard Worker
2508*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2509*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2510*3ac0a46fSAndroid Build Coastguard Worker
2511*3ac0a46fSAndroid Build Coastguard Worker // Checks for Listbox with Values (/V) object which is just a string.
2512*3ac0a46fSAndroid Build Coastguard Worker count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2513*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(26, count);
2514*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
2515*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(i == 1,
2516*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2517*3ac0a46fSAndroid Build Coastguard Worker }
2518*3ac0a46fSAndroid Build Coastguard Worker
2519*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 3));
2520*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2521*3ac0a46fSAndroid Build Coastguard Worker
2522*3ac0a46fSAndroid Build Coastguard Worker // Checks for Listbox with only Selected indices (/I) object which is an
2523*3ac0a46fSAndroid Build Coastguard Worker // array with multiple objects.
2524*3ac0a46fSAndroid Build Coastguard Worker count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2525*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(5, count);
2526*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
2527*3ac0a46fSAndroid Build Coastguard Worker bool expected = (i == 1 || i == 3);
2528*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(expected,
2529*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2530*3ac0a46fSAndroid Build Coastguard Worker }
2531*3ac0a46fSAndroid Build Coastguard Worker
2532*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 4));
2533*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2534*3ac0a46fSAndroid Build Coastguard Worker
2535*3ac0a46fSAndroid Build Coastguard Worker // Checks for Listbox with Values (/V) object which is an array with
2536*3ac0a46fSAndroid Build Coastguard Worker // multiple objects.
2537*3ac0a46fSAndroid Build Coastguard Worker count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2538*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(5, count);
2539*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
2540*3ac0a46fSAndroid Build Coastguard Worker bool expected = (i == 2 || i == 4);
2541*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(expected,
2542*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2543*3ac0a46fSAndroid Build Coastguard Worker }
2544*3ac0a46fSAndroid Build Coastguard Worker
2545*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 5));
2546*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2547*3ac0a46fSAndroid Build Coastguard Worker
2548*3ac0a46fSAndroid Build Coastguard Worker // Checks for Listbox with both Values (/V) and Selected Indices (/I)
2549*3ac0a46fSAndroid Build Coastguard Worker // objects conflict with different lengths.
2550*3ac0a46fSAndroid Build Coastguard Worker count = FPDFAnnot_GetOptionCount(form_handle(), annot.get());
2551*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(5, count);
2552*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
2553*3ac0a46fSAndroid Build Coastguard Worker bool expected = (i == 0 || i == 2);
2554*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(expected,
2555*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsOptionSelected(form_handle(), annot.get(), i));
2556*3ac0a46fSAndroid Build Coastguard Worker }
2557*3ac0a46fSAndroid Build Coastguard Worker }
2558*3ac0a46fSAndroid Build Coastguard Worker
2559*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2560*3ac0a46fSAndroid Build Coastguard Worker }
2561*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsOptionSelectedInvalidAnnotations)2562*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsOptionSelectedInvalidAnnotations) {
2563*3ac0a46fSAndroid Build Coastguard Worker // Open a file with multiple form field annotations and load its first page.
2564*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("multiple_form_types.pdf"));
2565*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2566*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2567*3ac0a46fSAndroid Build Coastguard Worker
2568*3ac0a46fSAndroid Build Coastguard Worker {
2569*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2570*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2571*3ac0a46fSAndroid Build Coastguard Worker
2572*3ac0a46fSAndroid Build Coastguard Worker // Checks for link annotation.
2573*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(),
2574*3ac0a46fSAndroid Build Coastguard Worker /*index=*/0));
2575*3ac0a46fSAndroid Build Coastguard Worker
2576*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 3));
2577*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2578*3ac0a46fSAndroid Build Coastguard Worker
2579*3ac0a46fSAndroid Build Coastguard Worker // Checks for text field annotation.
2580*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_IsOptionSelected(form_handle(), annot.get(),
2581*3ac0a46fSAndroid Build Coastguard Worker /*index=*/0));
2582*3ac0a46fSAndroid Build Coastguard Worker }
2583*3ac0a46fSAndroid Build Coastguard Worker
2584*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2585*3ac0a46fSAndroid Build Coastguard Worker }
2586*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFontSizeCombobox)2587*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFontSizeCombobox) {
2588*3ac0a46fSAndroid Build Coastguard Worker // Open a file with combobox annotations and load its first page.
2589*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2590*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2591*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2592*3ac0a46fSAndroid Build Coastguard Worker
2593*3ac0a46fSAndroid Build Coastguard Worker {
2594*3ac0a46fSAndroid Build Coastguard Worker // All 3 widgets have Tf font size 12.
2595*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2596*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2597*3ac0a46fSAndroid Build Coastguard Worker
2598*3ac0a46fSAndroid Build Coastguard Worker float value;
2599*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2600*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12.0, value);
2601*3ac0a46fSAndroid Build Coastguard Worker
2602*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2603*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2604*3ac0a46fSAndroid Build Coastguard Worker
2605*3ac0a46fSAndroid Build Coastguard Worker float value_two;
2606*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_two));
2607*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12.0, value_two);
2608*3ac0a46fSAndroid Build Coastguard Worker
2609*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 2));
2610*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2611*3ac0a46fSAndroid Build Coastguard Worker
2612*3ac0a46fSAndroid Build Coastguard Worker float value_three;
2613*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(
2614*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_three));
2615*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12.0, value_three);
2616*3ac0a46fSAndroid Build Coastguard Worker }
2617*3ac0a46fSAndroid Build Coastguard Worker
2618*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2619*3ac0a46fSAndroid Build Coastguard Worker }
2620*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFontSizeTextField)2621*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFontSizeTextField) {
2622*3ac0a46fSAndroid Build Coastguard Worker // Open a file with textfield annotations and load its first page.
2623*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
2624*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2625*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2626*3ac0a46fSAndroid Build Coastguard Worker
2627*3ac0a46fSAndroid Build Coastguard Worker {
2628*3ac0a46fSAndroid Build Coastguard Worker // All 4 widgets have Tf font size 12.
2629*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2630*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2631*3ac0a46fSAndroid Build Coastguard Worker
2632*3ac0a46fSAndroid Build Coastguard Worker float value;
2633*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2634*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12.0, value);
2635*3ac0a46fSAndroid Build Coastguard Worker
2636*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2637*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2638*3ac0a46fSAndroid Build Coastguard Worker
2639*3ac0a46fSAndroid Build Coastguard Worker float value_two;
2640*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_two));
2641*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12.0, value_two);
2642*3ac0a46fSAndroid Build Coastguard Worker
2643*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 2));
2644*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2645*3ac0a46fSAndroid Build Coastguard Worker
2646*3ac0a46fSAndroid Build Coastguard Worker float value_three;
2647*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(
2648*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_three));
2649*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12.0, value_three);
2650*3ac0a46fSAndroid Build Coastguard Worker
2651*3ac0a46fSAndroid Build Coastguard Worker float value_four;
2652*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value_four));
2653*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(12.0, value_four);
2654*3ac0a46fSAndroid Build Coastguard Worker }
2655*3ac0a46fSAndroid Build Coastguard Worker
2656*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2657*3ac0a46fSAndroid Build Coastguard Worker }
2658*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFontSizeInvalidAnnotationTypes)2659*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFontSizeInvalidAnnotationTypes) {
2660*3ac0a46fSAndroid Build Coastguard Worker // Open a file with ink annotations and load its first page.
2661*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
2662*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2663*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2664*3ac0a46fSAndroid Build Coastguard Worker
2665*3ac0a46fSAndroid Build Coastguard Worker {
2666*3ac0a46fSAndroid Build Coastguard Worker // Annotations that do not have variable text and will return -1.
2667*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2668*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2669*3ac0a46fSAndroid Build Coastguard Worker
2670*3ac0a46fSAndroid Build Coastguard Worker float value;
2671*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2672*3ac0a46fSAndroid Build Coastguard Worker
2673*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 1));
2674*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2675*3ac0a46fSAndroid Build Coastguard Worker
2676*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2677*3ac0a46fSAndroid Build Coastguard Worker }
2678*3ac0a46fSAndroid Build Coastguard Worker
2679*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2680*3ac0a46fSAndroid Build Coastguard Worker }
2681*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFontSizeInvalidArguments)2682*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFontSizeInvalidArguments) {
2683*3ac0a46fSAndroid Build Coastguard Worker // Open a file with combobox annotations and load its first page.
2684*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2685*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2686*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2687*3ac0a46fSAndroid Build Coastguard Worker
2688*3ac0a46fSAndroid Build Coastguard Worker {
2689*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2690*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2691*3ac0a46fSAndroid Build Coastguard Worker
2692*3ac0a46fSAndroid Build Coastguard Worker // Check bad form handle / annot.
2693*3ac0a46fSAndroid Build Coastguard Worker float value;
2694*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_GetFontSize(nullptr, annot.get(), &value));
2695*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_GetFontSize(form_handle(), nullptr, &value));
2696*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_GetFontSize(nullptr, nullptr, &value));
2697*3ac0a46fSAndroid Build Coastguard Worker }
2698*3ac0a46fSAndroid Build Coastguard Worker
2699*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2700*3ac0a46fSAndroid Build Coastguard Worker }
2701*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFontSizeNegative)2702*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFontSizeNegative) {
2703*3ac0a46fSAndroid Build Coastguard Worker // Open a file with textfield annotations and load its first page.
2704*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form_negative_fontsize.pdf"));
2705*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2706*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2707*3ac0a46fSAndroid Build Coastguard Worker
2708*3ac0a46fSAndroid Build Coastguard Worker {
2709*3ac0a46fSAndroid Build Coastguard Worker // Obtain the first annotation, a text field with negative font size, -12.
2710*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2711*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2712*3ac0a46fSAndroid Build Coastguard Worker
2713*3ac0a46fSAndroid Build Coastguard Worker float value;
2714*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetFontSize(form_handle(), annot.get(), &value));
2715*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-12.0, value);
2716*3ac0a46fSAndroid Build Coastguard Worker }
2717*3ac0a46fSAndroid Build Coastguard Worker
2718*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2719*3ac0a46fSAndroid Build Coastguard Worker }
2720*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsCheckedCheckbox)2721*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsCheckedCheckbox) {
2722*3ac0a46fSAndroid Build Coastguard Worker // Open a file with checkbox and radiobuttons widget annotations and load its
2723*3ac0a46fSAndroid Build Coastguard Worker // first page.
2724*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
2725*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2726*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2727*3ac0a46fSAndroid Build Coastguard Worker
2728*3ac0a46fSAndroid Build Coastguard Worker {
2729*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
2730*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2731*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2732*3ac0a46fSAndroid Build Coastguard Worker }
2733*3ac0a46fSAndroid Build Coastguard Worker
2734*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2735*3ac0a46fSAndroid Build Coastguard Worker }
2736*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsCheckedCheckboxReadOnly)2737*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsCheckedCheckboxReadOnly) {
2738*3ac0a46fSAndroid Build Coastguard Worker // Open a file with checkbox and radiobutton widget annotations and load its
2739*3ac0a46fSAndroid Build Coastguard Worker // first page.
2740*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
2741*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2742*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2743*3ac0a46fSAndroid Build Coastguard Worker
2744*3ac0a46fSAndroid Build Coastguard Worker {
2745*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2746*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2747*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2748*3ac0a46fSAndroid Build Coastguard Worker }
2749*3ac0a46fSAndroid Build Coastguard Worker
2750*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2751*3ac0a46fSAndroid Build Coastguard Worker }
2752*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsCheckedRadioButton)2753*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsCheckedRadioButton) {
2754*3ac0a46fSAndroid Build Coastguard Worker // Open a file with checkbox and radiobutton widget annotations and load its
2755*3ac0a46fSAndroid Build Coastguard Worker // first page.
2756*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
2757*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2758*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2759*3ac0a46fSAndroid Build Coastguard Worker
2760*3ac0a46fSAndroid Build Coastguard Worker {
2761*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 5));
2762*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2763*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2764*3ac0a46fSAndroid Build Coastguard Worker
2765*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 6));
2766*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2767*3ac0a46fSAndroid Build Coastguard Worker
2768*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 7));
2769*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2770*3ac0a46fSAndroid Build Coastguard Worker }
2771*3ac0a46fSAndroid Build Coastguard Worker
2772*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2773*3ac0a46fSAndroid Build Coastguard Worker }
2774*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsCheckedRadioButtonReadOnly)2775*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsCheckedRadioButtonReadOnly) {
2776*3ac0a46fSAndroid Build Coastguard Worker // Open a file with checkbox and radiobutton widget annotations and load its
2777*3ac0a46fSAndroid Build Coastguard Worker // first page.
2778*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
2779*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2780*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2781*3ac0a46fSAndroid Build Coastguard Worker
2782*3ac0a46fSAndroid Build Coastguard Worker {
2783*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
2784*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2785*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2786*3ac0a46fSAndroid Build Coastguard Worker
2787*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 3));
2788*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2789*3ac0a46fSAndroid Build Coastguard Worker
2790*3ac0a46fSAndroid Build Coastguard Worker annot.reset(FPDFPage_GetAnnot(page, 4));
2791*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2792*3ac0a46fSAndroid Build Coastguard Worker }
2793*3ac0a46fSAndroid Build Coastguard Worker
2794*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2795*3ac0a46fSAndroid Build Coastguard Worker }
2796*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsCheckedInvalidArguments)2797*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsCheckedInvalidArguments) {
2798*3ac0a46fSAndroid Build Coastguard Worker // Open a file with checkbox and radiobuttons widget annotations and load its
2799*3ac0a46fSAndroid Build Coastguard Worker // first page.
2800*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
2801*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2802*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2803*3ac0a46fSAndroid Build Coastguard Worker
2804*3ac0a46fSAndroid Build Coastguard Worker {
2805*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2806*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2807*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(nullptr, annot.get()));
2808*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), nullptr));
2809*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(nullptr, nullptr));
2810*3ac0a46fSAndroid Build Coastguard Worker }
2811*3ac0a46fSAndroid Build Coastguard Worker
2812*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2813*3ac0a46fSAndroid Build Coastguard Worker }
2814*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,IsCheckedInvalidWidgetType)2815*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, IsCheckedInvalidWidgetType) {
2816*3ac0a46fSAndroid Build Coastguard Worker // Open a file with text widget annotations and load its first page.
2817*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form.pdf"));
2818*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2819*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2820*3ac0a46fSAndroid Build Coastguard Worker
2821*3ac0a46fSAndroid Build Coastguard Worker {
2822*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2823*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2824*3ac0a46fSAndroid Build Coastguard Worker ASSERT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot.get()));
2825*3ac0a46fSAndroid Build Coastguard Worker }
2826*3ac0a46fSAndroid Build Coastguard Worker
2827*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2828*3ac0a46fSAndroid Build Coastguard Worker }
2829*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldType)2830*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldType) {
2831*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("multiple_form_types.pdf"));
2832*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2833*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2834*3ac0a46fSAndroid Build Coastguard Worker
2835*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetFormFieldType(form_handle(), nullptr));
2836*3ac0a46fSAndroid Build Coastguard Worker
2837*3ac0a46fSAndroid Build Coastguard Worker {
2838*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
2839*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2840*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetFormFieldType(nullptr, annot.get()));
2841*3ac0a46fSAndroid Build Coastguard Worker }
2842*3ac0a46fSAndroid Build Coastguard Worker
2843*3ac0a46fSAndroid Build Coastguard Worker constexpr int kExpectedAnnotTypes[] = {-1,
2844*3ac0a46fSAndroid Build Coastguard Worker FPDF_FORMFIELD_COMBOBOX,
2845*3ac0a46fSAndroid Build Coastguard Worker FPDF_FORMFIELD_LISTBOX,
2846*3ac0a46fSAndroid Build Coastguard Worker FPDF_FORMFIELD_TEXTFIELD,
2847*3ac0a46fSAndroid Build Coastguard Worker FPDF_FORMFIELD_CHECKBOX,
2848*3ac0a46fSAndroid Build Coastguard Worker FPDF_FORMFIELD_RADIOBUTTON};
2849*3ac0a46fSAndroid Build Coastguard Worker
2850*3ac0a46fSAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(kExpectedAnnotTypes); ++i) {
2851*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
2852*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2853*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kExpectedAnnotTypes[i],
2854*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldType(form_handle(), annot.get()));
2855*3ac0a46fSAndroid Build Coastguard Worker }
2856*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2857*3ac0a46fSAndroid Build Coastguard Worker }
2858*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldValueTextField)2859*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldValueTextField) {
2860*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
2861*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2862*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2863*3ac0a46fSAndroid Build Coastguard Worker
2864*3ac0a46fSAndroid Build Coastguard Worker {
2865*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u,
2866*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldValue(form_handle(), nullptr, nullptr, 0));
2867*3ac0a46fSAndroid Build Coastguard Worker
2868*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2869*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2870*3ac0a46fSAndroid Build Coastguard Worker
2871*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u,
2872*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldValue(nullptr, annot.get(), nullptr, 0));
2873*3ac0a46fSAndroid Build Coastguard Worker
2874*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
2875*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2876*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(2u, length_bytes);
2877*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2878*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2879*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2880*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"", GetPlatformWString(buf.data()));
2881*3ac0a46fSAndroid Build Coastguard Worker }
2882*3ac0a46fSAndroid Build Coastguard Worker {
2883*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
2884*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2885*3ac0a46fSAndroid Build Coastguard Worker
2886*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
2887*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2888*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(18u, length_bytes);
2889*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2890*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(18u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2891*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2892*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Elephant", GetPlatformWString(buf.data()));
2893*3ac0a46fSAndroid Build Coastguard Worker }
2894*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2895*3ac0a46fSAndroid Build Coastguard Worker }
2896*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldValueComboBox)2897*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldValueComboBox) {
2898*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2899*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2900*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2901*3ac0a46fSAndroid Build Coastguard Worker
2902*3ac0a46fSAndroid Build Coastguard Worker {
2903*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2904*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2905*3ac0a46fSAndroid Build Coastguard Worker
2906*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
2907*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2908*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(2u, length_bytes);
2909*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2910*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2911*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2912*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"", GetPlatformWString(buf.data()));
2913*3ac0a46fSAndroid Build Coastguard Worker }
2914*3ac0a46fSAndroid Build Coastguard Worker {
2915*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
2916*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2917*3ac0a46fSAndroid Build Coastguard Worker
2918*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
2919*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(), nullptr, 0);
2920*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(14u, length_bytes);
2921*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2922*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(14u, FPDFAnnot_GetFormFieldValue(form_handle(), annot.get(),
2923*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2924*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Banana", GetPlatformWString(buf.data()));
2925*3ac0a46fSAndroid Build Coastguard Worker }
2926*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2927*3ac0a46fSAndroid Build Coastguard Worker }
2928*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldNameTextField)2929*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldNameTextField) {
2930*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("text_form.pdf"));
2931*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2932*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2933*3ac0a46fSAndroid Build Coastguard Worker
2934*3ac0a46fSAndroid Build Coastguard Worker {
2935*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u,
2936*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldName(form_handle(), nullptr, nullptr, 0));
2937*3ac0a46fSAndroid Build Coastguard Worker
2938*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2939*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2940*3ac0a46fSAndroid Build Coastguard Worker
2941*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormFieldName(nullptr, annot.get(), nullptr, 0));
2942*3ac0a46fSAndroid Build Coastguard Worker
2943*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
2944*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldName(form_handle(), annot.get(), nullptr, 0);
2945*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(18u, length_bytes);
2946*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2947*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(18u, FPDFAnnot_GetFormFieldName(form_handle(), annot.get(),
2948*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2949*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Text Box", GetPlatformWString(buf.data()));
2950*3ac0a46fSAndroid Build Coastguard Worker }
2951*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2952*3ac0a46fSAndroid Build Coastguard Worker }
2953*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldNameComboBox)2954*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldNameComboBox) {
2955*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
2956*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2957*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2958*3ac0a46fSAndroid Build Coastguard Worker
2959*3ac0a46fSAndroid Build Coastguard Worker {
2960*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
2961*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
2962*3ac0a46fSAndroid Build Coastguard Worker
2963*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
2964*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldName(form_handle(), annot.get(), nullptr, 0);
2965*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(30u, length_bytes);
2966*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
2967*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(30u, FPDFAnnot_GetFormFieldName(form_handle(), annot.get(),
2968*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
2969*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Combo_Editable", GetPlatformWString(buf.data()));
2970*3ac0a46fSAndroid Build Coastguard Worker }
2971*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
2972*3ac0a46fSAndroid Build Coastguard Worker }
2973*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,FocusableAnnotSubtypes)2974*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, FocusableAnnotSubtypes) {
2975*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annots.pdf"));
2976*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
2977*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
2978*3ac0a46fSAndroid Build Coastguard Worker
2979*3ac0a46fSAndroid Build Coastguard Worker // Verify widgets are by default focusable.
2980*3ac0a46fSAndroid Build Coastguard Worker const FPDF_ANNOTATION_SUBTYPE kDefaultSubtypes[] = {FPDF_ANNOT_WIDGET};
2981*3ac0a46fSAndroid Build Coastguard Worker VerifyFocusableAnnotSubtypes(form_handle(), kDefaultSubtypes);
2982*3ac0a46fSAndroid Build Coastguard Worker
2983*3ac0a46fSAndroid Build Coastguard Worker // Expected annot subtypes for page 0 of annots.pdf.
2984*3ac0a46fSAndroid Build Coastguard Worker const FPDF_ANNOTATION_SUBTYPE kExpectedAnnotSubtypes[] = {
2985*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOT_LINK, FPDF_ANNOT_LINK, FPDF_ANNOT_LINK,
2986*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOT_LINK, FPDF_ANNOT_HIGHLIGHT, FPDF_ANNOT_HIGHLIGHT,
2987*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOT_POPUP, FPDF_ANNOT_HIGHLIGHT, FPDF_ANNOT_WIDGET,
2988*3ac0a46fSAndroid Build Coastguard Worker };
2989*3ac0a46fSAndroid Build Coastguard Worker
2990*3ac0a46fSAndroid Build Coastguard Worker const FPDF_ANNOTATION_SUBTYPE kExpectedDefaultFocusableSubtypes[] = {
2991*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOT_WIDGET};
2992*3ac0a46fSAndroid Build Coastguard Worker VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
2993*3ac0a46fSAndroid Build Coastguard Worker kExpectedAnnotSubtypes,
2994*3ac0a46fSAndroid Build Coastguard Worker kExpectedDefaultFocusableSubtypes);
2995*3ac0a46fSAndroid Build Coastguard Worker
2996*3ac0a46fSAndroid Build Coastguard Worker // Make no annotation type focusable using the preferred method.
2997*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_SetFocusableSubtypes(form_handle(), nullptr, 0));
2998*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(0, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
2999*3ac0a46fSAndroid Build Coastguard Worker
3000*3ac0a46fSAndroid Build Coastguard Worker // Restore the focusable type count back to 1, then set it back to 0 using a
3001*3ac0a46fSAndroid Build Coastguard Worker // different method.
3002*3ac0a46fSAndroid Build Coastguard Worker SetAndVerifyFocusableAnnotSubtypes(form_handle(), kDefaultSubtypes);
3003*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(
3004*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_SetFocusableSubtypes(form_handle(), kDefaultSubtypes, 0));
3005*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(0, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
3006*3ac0a46fSAndroid Build Coastguard Worker
3007*3ac0a46fSAndroid Build Coastguard Worker VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
3008*3ac0a46fSAndroid Build Coastguard Worker kExpectedAnnotSubtypes, {});
3009*3ac0a46fSAndroid Build Coastguard Worker
3010*3ac0a46fSAndroid Build Coastguard Worker // Now make links focusable.
3011*3ac0a46fSAndroid Build Coastguard Worker const FPDF_ANNOTATION_SUBTYPE kLinkSubtypes[] = {FPDF_ANNOT_LINK};
3012*3ac0a46fSAndroid Build Coastguard Worker SetAndVerifyFocusableAnnotSubtypes(form_handle(), kLinkSubtypes);
3013*3ac0a46fSAndroid Build Coastguard Worker
3014*3ac0a46fSAndroid Build Coastguard Worker const FPDF_ANNOTATION_SUBTYPE kExpectedLinkocusableSubtypes[] = {
3015*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOT_LINK};
3016*3ac0a46fSAndroid Build Coastguard Worker VerifyAnnotationSubtypesAndFocusability(form_handle(), page,
3017*3ac0a46fSAndroid Build Coastguard Worker kExpectedAnnotSubtypes,
3018*3ac0a46fSAndroid Build Coastguard Worker kExpectedLinkocusableSubtypes);
3019*3ac0a46fSAndroid Build Coastguard Worker
3020*3ac0a46fSAndroid Build Coastguard Worker // Test invalid parameters.
3021*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetFocusableSubtypes(nullptr, kDefaultSubtypes,
3022*3ac0a46fSAndroid Build Coastguard Worker std::size(kDefaultSubtypes)));
3023*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetFocusableSubtypes(form_handle(), nullptr,
3024*3ac0a46fSAndroid Build Coastguard Worker std::size(kDefaultSubtypes)));
3025*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetFocusableSubtypesCount(nullptr));
3026*3ac0a46fSAndroid Build Coastguard Worker
3027*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_ANNOTATION_SUBTYPE> subtypes(1);
3028*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetFocusableSubtypes(nullptr, subtypes.data(),
3029*3ac0a46fSAndroid Build Coastguard Worker subtypes.size()));
3030*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(
3031*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFocusableSubtypes(form_handle(), nullptr, subtypes.size()));
3032*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(
3033*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(), 0));
3034*3ac0a46fSAndroid Build Coastguard Worker
3035*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3036*3ac0a46fSAndroid Build Coastguard Worker }
3037*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,FocusableAnnotRendering)3038*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, FocusableAnnotRendering) {
3039*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annots.pdf"));
3040*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3041*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3042*3ac0a46fSAndroid Build Coastguard Worker
3043*3ac0a46fSAndroid Build Coastguard Worker {
3044*3ac0a46fSAndroid Build Coastguard Worker const char* md5_sum = []() {
3045*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
3046*3ac0a46fSAndroid Build Coastguard Worker return "c09b129c071ec1569deb003676b617b0";
3047*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
3048*3ac0a46fSAndroid Build Coastguard Worker return "108a46c517c4eaace9982ee83e8e3296";
3049*3ac0a46fSAndroid Build Coastguard Worker #else
3050*3ac0a46fSAndroid Build Coastguard Worker return "5550d8dcb4d1af1f50e8b4bcaef2ee60";
3051*3ac0a46fSAndroid Build Coastguard Worker #endif
3052*3ac0a46fSAndroid Build Coastguard Worker }();
3053*3ac0a46fSAndroid Build Coastguard Worker // Check the initial rendering.
3054*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3055*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, md5_sum);
3056*3ac0a46fSAndroid Build Coastguard Worker }
3057*3ac0a46fSAndroid Build Coastguard Worker
3058*3ac0a46fSAndroid Build Coastguard Worker // Make links and highlights focusable.
3059*3ac0a46fSAndroid Build Coastguard Worker static constexpr FPDF_ANNOTATION_SUBTYPE kSubTypes[] = {FPDF_ANNOT_LINK,
3060*3ac0a46fSAndroid Build Coastguard Worker FPDF_ANNOT_HIGHLIGHT};
3061*3ac0a46fSAndroid Build Coastguard Worker constexpr int kSubTypesCount = std::size(kSubTypes);
3062*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(
3063*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_SetFocusableSubtypes(form_handle(), kSubTypes, kSubTypesCount));
3064*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kSubTypesCount, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
3065*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_ANNOTATION_SUBTYPE> subtypes(kSubTypesCount);
3066*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(),
3067*3ac0a46fSAndroid Build Coastguard Worker subtypes.size()));
3068*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(FPDF_ANNOT_LINK, subtypes[0]);
3069*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(FPDF_ANNOT_HIGHLIGHT, subtypes[1]);
3070*3ac0a46fSAndroid Build Coastguard Worker
3071*3ac0a46fSAndroid Build Coastguard Worker {
3072*3ac0a46fSAndroid Build Coastguard Worker const char* md5_sum = []() {
3073*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
3074*3ac0a46fSAndroid Build Coastguard Worker return "277f1b9e70031539d034d22bc6064838";
3075*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
3076*3ac0a46fSAndroid Build Coastguard Worker return "eb3869335e7a219e1b5f25c1c6037b97";
3077*3ac0a46fSAndroid Build Coastguard Worker #else
3078*3ac0a46fSAndroid Build Coastguard Worker return "805fe7bb751ac4ed2b82bb66efe6db40";
3079*3ac0a46fSAndroid Build Coastguard Worker #endif
3080*3ac0a46fSAndroid Build Coastguard Worker }();
3081*3ac0a46fSAndroid Build Coastguard Worker // Focus the first link and check the rendering.
3082*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3083*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3084*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
3085*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FORM_SetFocusedAnnot(form_handle(), annot.get()));
3086*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3087*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, md5_sum);
3088*3ac0a46fSAndroid Build Coastguard Worker }
3089*3ac0a46fSAndroid Build Coastguard Worker
3090*3ac0a46fSAndroid Build Coastguard Worker {
3091*3ac0a46fSAndroid Build Coastguard Worker const char* md5_sum = []() {
3092*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
3093*3ac0a46fSAndroid Build Coastguard Worker return "d980005939cd4ae0a199d8600a0abdf3";
3094*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
3095*3ac0a46fSAndroid Build Coastguard Worker return "d20b1978da2362d3942ea0fc6d230997";
3096*3ac0a46fSAndroid Build Coastguard Worker #else
3097*3ac0a46fSAndroid Build Coastguard Worker return "c5c5dcb462af3ef5f43b298ec048feef";
3098*3ac0a46fSAndroid Build Coastguard Worker #endif
3099*3ac0a46fSAndroid Build Coastguard Worker }();
3100*3ac0a46fSAndroid Build Coastguard Worker // Focus the first highlight and check the rendering.
3101*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 4));
3102*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3103*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
3104*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FORM_SetFocusedAnnot(form_handle(), annot.get()));
3105*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3106*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, md5_sum);
3107*3ac0a46fSAndroid Build Coastguard Worker }
3108*3ac0a46fSAndroid Build Coastguard Worker
3109*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3110*3ac0a46fSAndroid Build Coastguard Worker }
3111*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetLinkFromAnnotation)3112*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetLinkFromAnnotation) {
3113*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annots.pdf"));
3114*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3115*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3116*3ac0a46fSAndroid Build Coastguard Worker {
3117*3ac0a46fSAndroid Build Coastguard Worker constexpr char kExpectedResult[] =
3118*3ac0a46fSAndroid Build Coastguard Worker "https://cs.chromium.org/chromium/src/third_party/pdfium/public/"
3119*3ac0a46fSAndroid Build Coastguard Worker "fpdf_text.h";
3120*3ac0a46fSAndroid Build Coastguard Worker
3121*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
3122*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3123*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_LINK, FPDFAnnot_GetSubtype(annot.get()));
3124*3ac0a46fSAndroid Build Coastguard Worker VerifyUriActionInLink(document(), FPDFAnnot_GetLink(annot.get()),
3125*3ac0a46fSAndroid Build Coastguard Worker kExpectedResult);
3126*3ac0a46fSAndroid Build Coastguard Worker }
3127*3ac0a46fSAndroid Build Coastguard Worker
3128*3ac0a46fSAndroid Build Coastguard Worker {
3129*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 4));
3130*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3131*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot.get()));
3132*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetLink(annot.get()));
3133*3ac0a46fSAndroid Build Coastguard Worker }
3134*3ac0a46fSAndroid Build Coastguard Worker
3135*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetLink(nullptr));
3136*3ac0a46fSAndroid Build Coastguard Worker
3137*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3138*3ac0a46fSAndroid Build Coastguard Worker }
3139*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormControlCountRadioButton)3140*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormControlCountRadioButton) {
3141*3ac0a46fSAndroid Build Coastguard Worker // Open a file with radio button widget annotations and load its first page.
3142*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
3143*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3144*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3145*3ac0a46fSAndroid Build Coastguard Worker
3146*3ac0a46fSAndroid Build Coastguard Worker {
3147*3ac0a46fSAndroid Build Coastguard Worker // Checks for bad annot.
3148*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1,
3149*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormControlCount(form_handle(), /*annot=*/nullptr));
3150*3ac0a46fSAndroid Build Coastguard Worker
3151*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
3152*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3153*3ac0a46fSAndroid Build Coastguard Worker
3154*3ac0a46fSAndroid Build Coastguard Worker // Checks for bad form handle.
3155*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1,
3156*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormControlCount(/*hHandle=*/nullptr, annot.get()));
3157*3ac0a46fSAndroid Build Coastguard Worker
3158*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3, FPDFAnnot_GetFormControlCount(form_handle(), annot.get()));
3159*3ac0a46fSAndroid Build Coastguard Worker }
3160*3ac0a46fSAndroid Build Coastguard Worker
3161*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3162*3ac0a46fSAndroid Build Coastguard Worker }
3163*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormControlCountCheckBox)3164*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormControlCountCheckBox) {
3165*3ac0a46fSAndroid Build Coastguard Worker // Open a file with checkbox widget annotations and load its first page.
3166*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
3167*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3168*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3169*3ac0a46fSAndroid Build Coastguard Worker
3170*3ac0a46fSAndroid Build Coastguard Worker {
3171*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3172*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3173*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_GetFormControlCount(form_handle(), annot.get()));
3174*3ac0a46fSAndroid Build Coastguard Worker }
3175*3ac0a46fSAndroid Build Coastguard Worker
3176*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3177*3ac0a46fSAndroid Build Coastguard Worker }
3178*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormControlCountInvalidAnnotation)3179*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormControlCountInvalidAnnotation) {
3180*3ac0a46fSAndroid Build Coastguard Worker // Open a file with ink annotations and load its first page.
3181*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
3182*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3183*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3184*3ac0a46fSAndroid Build Coastguard Worker
3185*3ac0a46fSAndroid Build Coastguard Worker {
3186*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3187*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3188*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetFormControlCount(form_handle(), annot.get()));
3189*3ac0a46fSAndroid Build Coastguard Worker }
3190*3ac0a46fSAndroid Build Coastguard Worker
3191*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3192*3ac0a46fSAndroid Build Coastguard Worker }
3193*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormControlIndexRadioButton)3194*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormControlIndexRadioButton) {
3195*3ac0a46fSAndroid Build Coastguard Worker // Open a file with radio button widget annotations and load its first page.
3196*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
3197*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3198*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3199*3ac0a46fSAndroid Build Coastguard Worker
3200*3ac0a46fSAndroid Build Coastguard Worker {
3201*3ac0a46fSAndroid Build Coastguard Worker // Checks for bad annot.
3202*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1,
3203*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormControlIndex(form_handle(), /*annot=*/nullptr));
3204*3ac0a46fSAndroid Build Coastguard Worker
3205*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 3));
3206*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3207*3ac0a46fSAndroid Build Coastguard Worker
3208*3ac0a46fSAndroid Build Coastguard Worker // Checks for bad form handle.
3209*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1,
3210*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormControlIndex(/*hHandle=*/nullptr, annot.get()));
3211*3ac0a46fSAndroid Build Coastguard Worker
3212*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFAnnot_GetFormControlIndex(form_handle(), annot.get()));
3213*3ac0a46fSAndroid Build Coastguard Worker }
3214*3ac0a46fSAndroid Build Coastguard Worker
3215*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3216*3ac0a46fSAndroid Build Coastguard Worker }
3217*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormControlIndexCheckBox)3218*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormControlIndexCheckBox) {
3219*3ac0a46fSAndroid Build Coastguard Worker // Open a file with checkbox widget annotations and load its first page.
3220*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
3221*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3222*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3223*3ac0a46fSAndroid Build Coastguard Worker
3224*3ac0a46fSAndroid Build Coastguard Worker {
3225*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3226*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3227*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0, FPDFAnnot_GetFormControlIndex(form_handle(), annot.get()));
3228*3ac0a46fSAndroid Build Coastguard Worker }
3229*3ac0a46fSAndroid Build Coastguard Worker
3230*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3231*3ac0a46fSAndroid Build Coastguard Worker }
3232*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormControlIndexInvalidAnnotation)3233*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormControlIndexInvalidAnnotation) {
3234*3ac0a46fSAndroid Build Coastguard Worker // Open a file with ink annotations and load its first page.
3235*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
3236*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3237*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3238*3ac0a46fSAndroid Build Coastguard Worker
3239*3ac0a46fSAndroid Build Coastguard Worker {
3240*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3241*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3242*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(-1, FPDFAnnot_GetFormControlIndex(form_handle(), annot.get()));
3243*3ac0a46fSAndroid Build Coastguard Worker }
3244*3ac0a46fSAndroid Build Coastguard Worker
3245*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3246*3ac0a46fSAndroid Build Coastguard Worker }
3247*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldExportValueRadioButton)3248*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldExportValueRadioButton) {
3249*3ac0a46fSAndroid Build Coastguard Worker // Open a file with radio button widget annotations and load its first page.
3250*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
3251*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3252*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3253*3ac0a46fSAndroid Build Coastguard Worker
3254*3ac0a46fSAndroid Build Coastguard Worker {
3255*3ac0a46fSAndroid Build Coastguard Worker // Checks for bad annot.
3256*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormFieldExportValue(
3257*3ac0a46fSAndroid Build Coastguard Worker form_handle(), /*annot=*/nullptr,
3258*3ac0a46fSAndroid Build Coastguard Worker /*buffer=*/nullptr, /*buflen=*/0));
3259*3ac0a46fSAndroid Build Coastguard Worker
3260*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 6));
3261*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3262*3ac0a46fSAndroid Build Coastguard Worker
3263*3ac0a46fSAndroid Build Coastguard Worker // Checks for bad form handle.
3264*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormFieldExportValue(
3265*3ac0a46fSAndroid Build Coastguard Worker /*hHandle=*/nullptr, annot.get(),
3266*3ac0a46fSAndroid Build Coastguard Worker /*buffer=*/nullptr, /*buflen=*/0));
3267*3ac0a46fSAndroid Build Coastguard Worker
3268*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
3269*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3270*3ac0a46fSAndroid Build Coastguard Worker /*buffer=*/nullptr, /*buflen=*/0);
3271*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(14u, length_bytes);
3272*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
3273*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(14u, FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3274*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
3275*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"value2", GetPlatformWString(buf.data()));
3276*3ac0a46fSAndroid Build Coastguard Worker }
3277*3ac0a46fSAndroid Build Coastguard Worker
3278*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3279*3ac0a46fSAndroid Build Coastguard Worker }
3280*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldExportValueCheckBox)3281*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldExportValueCheckBox) {
3282*3ac0a46fSAndroid Build Coastguard Worker // Open a file with checkbox widget annotations and load its first page.
3283*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
3284*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3285*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3286*3ac0a46fSAndroid Build Coastguard Worker
3287*3ac0a46fSAndroid Build Coastguard Worker {
3288*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3289*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3290*3ac0a46fSAndroid Build Coastguard Worker
3291*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes =
3292*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3293*3ac0a46fSAndroid Build Coastguard Worker /*buffer=*/nullptr, /*buflen=*/0);
3294*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(8u, length_bytes);
3295*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
3296*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(8u, FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3297*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
3298*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"Yes", GetPlatformWString(buf.data()));
3299*3ac0a46fSAndroid Build Coastguard Worker }
3300*3ac0a46fSAndroid Build Coastguard Worker
3301*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3302*3ac0a46fSAndroid Build Coastguard Worker }
3303*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,GetFormFieldExportValueInvalidAnnotation)3304*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, GetFormFieldExportValueInvalidAnnotation) {
3305*3ac0a46fSAndroid Build Coastguard Worker // Open a file with ink annotations and load its first page.
3306*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
3307*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3308*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3309*3ac0a46fSAndroid Build Coastguard Worker
3310*3ac0a46fSAndroid Build Coastguard Worker {
3311*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3312*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3313*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormFieldExportValue(form_handle(), annot.get(),
3314*3ac0a46fSAndroid Build Coastguard Worker /*buffer=*/nullptr,
3315*3ac0a46fSAndroid Build Coastguard Worker /*buflen=*/0));
3316*3ac0a46fSAndroid Build Coastguard Worker }
3317*3ac0a46fSAndroid Build Coastguard Worker
3318*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3319*3ac0a46fSAndroid Build Coastguard Worker }
3320*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,Redactannotation)3321*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, Redactannotation) {
3322*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("redact_annot.pdf"));
3323*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3324*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3325*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
3326*3ac0a46fSAndroid Build Coastguard Worker
3327*3ac0a46fSAndroid Build Coastguard Worker {
3328*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3329*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3330*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_REDACT, FPDFAnnot_GetSubtype(annot.get()));
3331*3ac0a46fSAndroid Build Coastguard Worker }
3332*3ac0a46fSAndroid Build Coastguard Worker
3333*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3334*3ac0a46fSAndroid Build Coastguard Worker }
3335*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,PolygonAnnotation)3336*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, PolygonAnnotation) {
3337*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("polygon_annot.pdf"));
3338*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3339*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3340*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
3341*3ac0a46fSAndroid Build Coastguard Worker
3342*3ac0a46fSAndroid Build Coastguard Worker {
3343*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3344*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3345*3ac0a46fSAndroid Build Coastguard Worker
3346*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetVertices() positive testing.
3347*3ac0a46fSAndroid Build Coastguard Worker unsigned long size = FPDFAnnot_GetVertices(annot.get(), nullptr, 0);
3348*3ac0a46fSAndroid Build Coastguard Worker const size_t kExpectedSize = 3;
3349*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kExpectedSize, size);
3350*3ac0a46fSAndroid Build Coastguard Worker std::vector<FS_POINTF> vertices_buffer(size);
3351*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(size,
3352*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetVertices(annot.get(), vertices_buffer.data(), size));
3353*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(159.0f, vertices_buffer[0].x);
3354*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(296.0f, vertices_buffer[0].y);
3355*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(350.0f, vertices_buffer[1].x);
3356*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(411.0f, vertices_buffer[1].y);
3357*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(472.0f, vertices_buffer[2].x);
3358*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(243.42f, vertices_buffer[2].y);
3359*3ac0a46fSAndroid Build Coastguard Worker
3360*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetVertices() negative testing.
3361*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0U, FPDFAnnot_GetVertices(nullptr, nullptr, 0));
3362*3ac0a46fSAndroid Build Coastguard Worker
3363*3ac0a46fSAndroid Build Coastguard Worker // vertices_buffer is not overwritten if it is too small.
3364*3ac0a46fSAndroid Build Coastguard Worker vertices_buffer.resize(1);
3365*3ac0a46fSAndroid Build Coastguard Worker vertices_buffer[0].x = 42;
3366*3ac0a46fSAndroid Build Coastguard Worker vertices_buffer[0].y = 43;
3367*3ac0a46fSAndroid Build Coastguard Worker size = FPDFAnnot_GetVertices(annot.get(), vertices_buffer.data(),
3368*3ac0a46fSAndroid Build Coastguard Worker vertices_buffer.size());
3369*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kExpectedSize, size);
3370*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(42, vertices_buffer[0].x);
3371*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(43, vertices_buffer[0].y);
3372*3ac0a46fSAndroid Build Coastguard Worker }
3373*3ac0a46fSAndroid Build Coastguard Worker
3374*3ac0a46fSAndroid Build Coastguard Worker {
3375*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
3376*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3377*3ac0a46fSAndroid Build Coastguard Worker
3378*3ac0a46fSAndroid Build Coastguard Worker // This has an odd number of elements in the vertices array, ignore the last
3379*3ac0a46fSAndroid Build Coastguard Worker // element.
3380*3ac0a46fSAndroid Build Coastguard Worker unsigned long size = FPDFAnnot_GetVertices(annot.get(), nullptr, 0);
3381*3ac0a46fSAndroid Build Coastguard Worker const size_t kExpectedSize = 3;
3382*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kExpectedSize, size);
3383*3ac0a46fSAndroid Build Coastguard Worker std::vector<FS_POINTF> vertices_buffer(size);
3384*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(size,
3385*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetVertices(annot.get(), vertices_buffer.data(), size));
3386*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(259.0f, vertices_buffer[0].x);
3387*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(396.0f, vertices_buffer[0].y);
3388*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(450.0f, vertices_buffer[1].x);
3389*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(511.0f, vertices_buffer[1].y);
3390*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(572.0f, vertices_buffer[2].x);
3391*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(343.0f, vertices_buffer[2].y);
3392*3ac0a46fSAndroid Build Coastguard Worker }
3393*3ac0a46fSAndroid Build Coastguard Worker
3394*3ac0a46fSAndroid Build Coastguard Worker {
3395*3ac0a46fSAndroid Build Coastguard Worker // Wrong annotation type.
3396*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation ink_annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_INK));
3397*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0U, FPDFAnnot_GetVertices(ink_annot.get(), nullptr, 0));
3398*3ac0a46fSAndroid Build Coastguard Worker }
3399*3ac0a46fSAndroid Build Coastguard Worker
3400*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3401*3ac0a46fSAndroid Build Coastguard Worker }
3402*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,InkAnnotation)3403*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, InkAnnotation) {
3404*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("ink_annot.pdf"));
3405*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3406*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3407*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
3408*3ac0a46fSAndroid Build Coastguard Worker
3409*3ac0a46fSAndroid Build Coastguard Worker {
3410*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3411*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3412*3ac0a46fSAndroid Build Coastguard Worker
3413*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetInkListCount() and FPDFAnnot_GetInkListPath() positive
3414*3ac0a46fSAndroid Build Coastguard Worker // testing.
3415*3ac0a46fSAndroid Build Coastguard Worker unsigned long size = FPDFAnnot_GetInkListCount(annot.get());
3416*3ac0a46fSAndroid Build Coastguard Worker const size_t kExpectedSize = 1;
3417*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kExpectedSize, size);
3418*3ac0a46fSAndroid Build Coastguard Worker const unsigned long kPathIndex = 0;
3419*3ac0a46fSAndroid Build Coastguard Worker unsigned long path_size =
3420*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetInkListPath(annot.get(), kPathIndex, nullptr, 0);
3421*3ac0a46fSAndroid Build Coastguard Worker const size_t kExpectedPathSize = 3;
3422*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kExpectedPathSize, path_size);
3423*3ac0a46fSAndroid Build Coastguard Worker std::vector<FS_POINTF> path_buffer(path_size);
3424*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(path_size,
3425*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetInkListPath(annot.get(), kPathIndex,
3426*3ac0a46fSAndroid Build Coastguard Worker path_buffer.data(), path_size));
3427*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(159.0f, path_buffer[0].x);
3428*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(296.0f, path_buffer[0].y);
3429*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(350.0f, path_buffer[1].x);
3430*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(411.0f, path_buffer[1].y);
3431*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(472.0f, path_buffer[2].x);
3432*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(243.42f, path_buffer[2].y);
3433*3ac0a46fSAndroid Build Coastguard Worker
3434*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetInkListCount() and FPDFAnnot_GetInkListPath() negative
3435*3ac0a46fSAndroid Build Coastguard Worker // testing.
3436*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0U, FPDFAnnot_GetInkListCount(nullptr));
3437*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0U, FPDFAnnot_GetInkListPath(nullptr, 0, nullptr, 0));
3438*3ac0a46fSAndroid Build Coastguard Worker
3439*3ac0a46fSAndroid Build Coastguard Worker // out of bounds path_index.
3440*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0U, FPDFAnnot_GetInkListPath(nullptr, 42, nullptr, 0));
3441*3ac0a46fSAndroid Build Coastguard Worker
3442*3ac0a46fSAndroid Build Coastguard Worker // path_buffer is not overwritten if it is too small.
3443*3ac0a46fSAndroid Build Coastguard Worker path_buffer.resize(1);
3444*3ac0a46fSAndroid Build Coastguard Worker path_buffer[0].x = 42;
3445*3ac0a46fSAndroid Build Coastguard Worker path_buffer[0].y = 43;
3446*3ac0a46fSAndroid Build Coastguard Worker path_size = FPDFAnnot_GetInkListPath(
3447*3ac0a46fSAndroid Build Coastguard Worker annot.get(), kPathIndex, path_buffer.data(), path_buffer.size());
3448*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(kExpectedPathSize, path_size);
3449*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(42, path_buffer[0].x);
3450*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(43, path_buffer[0].y);
3451*3ac0a46fSAndroid Build Coastguard Worker }
3452*3ac0a46fSAndroid Build Coastguard Worker
3453*3ac0a46fSAndroid Build Coastguard Worker {
3454*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
3455*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3456*3ac0a46fSAndroid Build Coastguard Worker
3457*3ac0a46fSAndroid Build Coastguard Worker // This has an odd number of elements in the path array, ignore the last
3458*3ac0a46fSAndroid Build Coastguard Worker // element.
3459*3ac0a46fSAndroid Build Coastguard Worker unsigned long size = FPDFAnnot_GetInkListCount(annot.get());
3460*3ac0a46fSAndroid Build Coastguard Worker const size_t kExpectedSize = 1;
3461*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kExpectedSize, size);
3462*3ac0a46fSAndroid Build Coastguard Worker const unsigned long kPathIndex = 0;
3463*3ac0a46fSAndroid Build Coastguard Worker unsigned long path_size =
3464*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetInkListPath(annot.get(), kPathIndex, nullptr, 0);
3465*3ac0a46fSAndroid Build Coastguard Worker const size_t kExpectedPathSize = 3;
3466*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(kExpectedPathSize, path_size);
3467*3ac0a46fSAndroid Build Coastguard Worker std::vector<FS_POINTF> path_buffer(path_size);
3468*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(path_size,
3469*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetInkListPath(annot.get(), kPathIndex,
3470*3ac0a46fSAndroid Build Coastguard Worker path_buffer.data(), path_size));
3471*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(259.0f, path_buffer[0].x);
3472*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(396.0f, path_buffer[0].y);
3473*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(450.0f, path_buffer[1].x);
3474*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(511.0f, path_buffer[1].y);
3475*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(572.0f, path_buffer[2].x);
3476*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(343.0f, path_buffer[2].y);
3477*3ac0a46fSAndroid Build Coastguard Worker }
3478*3ac0a46fSAndroid Build Coastguard Worker
3479*3ac0a46fSAndroid Build Coastguard Worker {
3480*3ac0a46fSAndroid Build Coastguard Worker // Wrong annotation type.
3481*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation polygon_annot(
3482*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CreateAnnot(page, FPDF_ANNOT_POLYGON));
3483*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0U, FPDFAnnot_GetInkListCount(polygon_annot.get()));
3484*3ac0a46fSAndroid Build Coastguard Worker const unsigned long kPathIndex = 0;
3485*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0U, FPDFAnnot_GetInkListPath(polygon_annot.get(), kPathIndex,
3486*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
3487*3ac0a46fSAndroid Build Coastguard Worker }
3488*3ac0a46fSAndroid Build Coastguard Worker
3489*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3490*3ac0a46fSAndroid Build Coastguard Worker }
3491*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,LineAnnotation)3492*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, LineAnnotation) {
3493*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("line_annot.pdf"));
3494*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3495*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3496*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
3497*3ac0a46fSAndroid Build Coastguard Worker
3498*3ac0a46fSAndroid Build Coastguard Worker {
3499*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3500*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3501*3ac0a46fSAndroid Build Coastguard Worker
3502*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetVertices() positive testing.
3503*3ac0a46fSAndroid Build Coastguard Worker FS_POINTF start;
3504*3ac0a46fSAndroid Build Coastguard Worker FS_POINTF end;
3505*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetLine(annot.get(), &start, &end));
3506*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(159.0f, start.x);
3507*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(296.0f, start.y);
3508*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(472.0f, end.x);
3509*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(243.42f, end.y);
3510*3ac0a46fSAndroid Build Coastguard Worker
3511*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetVertices() negative testing.
3512*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetLine(nullptr, nullptr, nullptr));
3513*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetLine(annot.get(), nullptr, nullptr));
3514*3ac0a46fSAndroid Build Coastguard Worker }
3515*3ac0a46fSAndroid Build Coastguard Worker
3516*3ac0a46fSAndroid Build Coastguard Worker {
3517*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
3518*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3519*3ac0a46fSAndroid Build Coastguard Worker
3520*3ac0a46fSAndroid Build Coastguard Worker // Too few elements in the line array.
3521*3ac0a46fSAndroid Build Coastguard Worker FS_POINTF start;
3522*3ac0a46fSAndroid Build Coastguard Worker FS_POINTF end;
3523*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetLine(annot.get(), &start, &end));
3524*3ac0a46fSAndroid Build Coastguard Worker }
3525*3ac0a46fSAndroid Build Coastguard Worker
3526*3ac0a46fSAndroid Build Coastguard Worker {
3527*3ac0a46fSAndroid Build Coastguard Worker // Wrong annotation type.
3528*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation ink_annot(FPDFPage_CreateAnnot(page, FPDF_ANNOT_INK));
3529*3ac0a46fSAndroid Build Coastguard Worker FS_POINTF start;
3530*3ac0a46fSAndroid Build Coastguard Worker FS_POINTF end;
3531*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetLine(ink_annot.get(), &start, &end));
3532*3ac0a46fSAndroid Build Coastguard Worker }
3533*3ac0a46fSAndroid Build Coastguard Worker
3534*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3535*3ac0a46fSAndroid Build Coastguard Worker }
3536*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AnnotationBorder)3537*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AnnotationBorder) {
3538*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("line_annot.pdf"));
3539*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3540*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3541*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
3542*3ac0a46fSAndroid Build Coastguard Worker
3543*3ac0a46fSAndroid Build Coastguard Worker {
3544*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3545*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3546*3ac0a46fSAndroid Build Coastguard Worker
3547*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetBorder() positive testing.
3548*3ac0a46fSAndroid Build Coastguard Worker float horizontal_radius;
3549*3ac0a46fSAndroid Build Coastguard Worker float vertical_radius;
3550*3ac0a46fSAndroid Build Coastguard Worker float border_width;
3551*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(FPDFAnnot_GetBorder(annot.get(), &horizontal_radius,
3552*3ac0a46fSAndroid Build Coastguard Worker &vertical_radius, &border_width));
3553*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(0.25f, horizontal_radius);
3554*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(0.5f, vertical_radius);
3555*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(2.0f, border_width);
3556*3ac0a46fSAndroid Build Coastguard Worker
3557*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetBorder() negative testing.
3558*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetBorder(nullptr, nullptr, nullptr, nullptr));
3559*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetBorder(annot.get(), nullptr, nullptr, nullptr));
3560*3ac0a46fSAndroid Build Coastguard Worker }
3561*3ac0a46fSAndroid Build Coastguard Worker
3562*3ac0a46fSAndroid Build Coastguard Worker {
3563*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
3564*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3565*3ac0a46fSAndroid Build Coastguard Worker
3566*3ac0a46fSAndroid Build Coastguard Worker // Too few elements in the border array.
3567*3ac0a46fSAndroid Build Coastguard Worker float horizontal_radius;
3568*3ac0a46fSAndroid Build Coastguard Worker float vertical_radius;
3569*3ac0a46fSAndroid Build Coastguard Worker float border_width;
3570*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_GetBorder(annot.get(), &horizontal_radius,
3571*3ac0a46fSAndroid Build Coastguard Worker &vertical_radius, &border_width));
3572*3ac0a46fSAndroid Build Coastguard Worker
3573*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_SetBorder() positive testing.
3574*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetBorder(annot.get(), /*horizontal_radius=*/2.0f,
3575*3ac0a46fSAndroid Build Coastguard Worker /*vertical_radius=*/3.5f,
3576*3ac0a46fSAndroid Build Coastguard Worker /*border_width=*/4.0f));
3577*3ac0a46fSAndroid Build Coastguard Worker
3578*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_GetBorder(annot.get(), &horizontal_radius,
3579*3ac0a46fSAndroid Build Coastguard Worker &vertical_radius, &border_width));
3580*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(2.0f, horizontal_radius);
3581*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(3.5f, vertical_radius);
3582*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(4.0f, border_width);
3583*3ac0a46fSAndroid Build Coastguard Worker
3584*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_SetBorder() negative testing.
3585*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(FPDFAnnot_SetBorder(nullptr, /*horizontal_radius=*/1.0f,
3586*3ac0a46fSAndroid Build Coastguard Worker /*vertical_radius=*/2.5f,
3587*3ac0a46fSAndroid Build Coastguard Worker /*border_width=*/3.0f));
3588*3ac0a46fSAndroid Build Coastguard Worker }
3589*3ac0a46fSAndroid Build Coastguard Worker
3590*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3591*3ac0a46fSAndroid Build Coastguard Worker }
3592*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,AnnotationJavaScript)3593*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AnnotationJavaScript) {
3594*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annot_javascript.pdf"));
3595*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3596*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3597*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
3598*3ac0a46fSAndroid Build Coastguard Worker
3599*3ac0a46fSAndroid Build Coastguard Worker {
3600*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3601*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3602*3ac0a46fSAndroid Build Coastguard Worker
3603*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetFormAdditionalActionJavaScript() positive testing.
3604*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes = FPDFAnnot_GetFormAdditionalActionJavaScript(
3605*3ac0a46fSAndroid Build Coastguard Worker form_handle(), annot.get(), FPDF_ANNOT_AACTION_FORMAT, nullptr, 0);
3606*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(62u, length_bytes);
3607*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
3608*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(62u, FPDFAnnot_GetFormAdditionalActionJavaScript(
3609*3ac0a46fSAndroid Build Coastguard Worker form_handle(), annot.get(), FPDF_ANNOT_AACTION_FORMAT,
3610*3ac0a46fSAndroid Build Coastguard Worker buf.data(), length_bytes));
3611*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"AFDate_FormatEx(\"yyyy-mm-dd\");",
3612*3ac0a46fSAndroid Build Coastguard Worker GetPlatformWString(buf.data()));
3613*3ac0a46fSAndroid Build Coastguard Worker
3614*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetFormAdditionalActionJavaScript() negative testing.
3615*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormAdditionalActionJavaScript(
3616*3ac0a46fSAndroid Build Coastguard Worker form_handle(), nullptr, 0, nullptr, 0));
3617*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormAdditionalActionJavaScript(
3618*3ac0a46fSAndroid Build Coastguard Worker nullptr, annot.get(), 0, nullptr, 0));
3619*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormAdditionalActionJavaScript(
3620*3ac0a46fSAndroid Build Coastguard Worker form_handle(), annot.get(), 0, nullptr, 0));
3621*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(2u, FPDFAnnot_GetFormAdditionalActionJavaScript(
3622*3ac0a46fSAndroid Build Coastguard Worker form_handle(), annot.get(), FPDF_ANNOT_AACTION_KEY_STROKE,
3623*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
3624*3ac0a46fSAndroid Build Coastguard Worker }
3625*3ac0a46fSAndroid Build Coastguard Worker
3626*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3627*3ac0a46fSAndroid Build Coastguard Worker }
3628*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(FPDFAnnotEmbedderTest,FormFieldAlternateName)3629*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, FormFieldAlternateName) {
3630*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("click_form.pdf"));
3631*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(0);
3632*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3633*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(8, FPDFPage_GetAnnotCount(page));
3634*3ac0a46fSAndroid Build Coastguard Worker
3635*3ac0a46fSAndroid Build Coastguard Worker {
3636*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
3637*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3638*3ac0a46fSAndroid Build Coastguard Worker
3639*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetFormFieldAlternateName() positive testing.
3640*3ac0a46fSAndroid Build Coastguard Worker unsigned long length_bytes = FPDFAnnot_GetFormFieldAlternateName(
3641*3ac0a46fSAndroid Build Coastguard Worker form_handle(), annot.get(), nullptr, 0);
3642*3ac0a46fSAndroid Build Coastguard Worker ASSERT_EQ(34u, length_bytes);
3643*3ac0a46fSAndroid Build Coastguard Worker std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
3644*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(34u, FPDFAnnot_GetFormFieldAlternateName(
3645*3ac0a46fSAndroid Build Coastguard Worker form_handle(), annot.get(), buf.data(), length_bytes));
3646*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(L"readOnlyCheckbox", GetPlatformWString(buf.data()));
3647*3ac0a46fSAndroid Build Coastguard Worker
3648*3ac0a46fSAndroid Build Coastguard Worker // FPDFAnnot_GetFormFieldAlternateName() negative testing.
3649*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormFieldAlternateName(form_handle(), nullptr,
3650*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
3651*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, FPDFAnnot_GetFormFieldAlternateName(nullptr, annot.get(),
3652*3ac0a46fSAndroid Build Coastguard Worker nullptr, 0));
3653*3ac0a46fSAndroid Build Coastguard Worker }
3654*3ac0a46fSAndroid Build Coastguard Worker
3655*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3656*3ac0a46fSAndroid Build Coastguard Worker }
3657*3ac0a46fSAndroid Build Coastguard Worker
3658*3ac0a46fSAndroid Build Coastguard Worker // Due to https://crbug.com/pdfium/570, the AnnotationBorder test above cannot
3659*3ac0a46fSAndroid Build Coastguard Worker // actually render the line annotations inside line_annot.pdf. For now, use a
3660*3ac0a46fSAndroid Build Coastguard Worker // square annotation in annots.pdf for testing.
TEST_F(FPDFAnnotEmbedderTest,AnnotationBorderRendering)3661*3ac0a46fSAndroid Build Coastguard Worker TEST_F(FPDFAnnotEmbedderTest, AnnotationBorderRendering) {
3662*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenDocument("annots.pdf"));
3663*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page = LoadPage(1);
3664*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3665*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
3666*3ac0a46fSAndroid Build Coastguard Worker
3667*3ac0a46fSAndroid Build Coastguard Worker const char* original_checksum = []() {
3668*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
3669*3ac0a46fSAndroid Build Coastguard Worker return "238dccc7df0ac61ac580c28e1109da3c";
3670*3ac0a46fSAndroid Build Coastguard Worker }
3671*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
3672*3ac0a46fSAndroid Build Coastguard Worker return "522a4a6b6c7eab5bf95ded1f21ea372e";
3673*3ac0a46fSAndroid Build Coastguard Worker #else
3674*3ac0a46fSAndroid Build Coastguard Worker return "12127303aecd80c6288460f7c0d79f3f";
3675*3ac0a46fSAndroid Build Coastguard Worker #endif
3676*3ac0a46fSAndroid Build Coastguard Worker }();
3677*3ac0a46fSAndroid Build Coastguard Worker const char* modified_checksum = []() {
3678*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
3679*3ac0a46fSAndroid Build Coastguard Worker return "0f326acb3eb583125ca584d703ccb13b";
3680*3ac0a46fSAndroid Build Coastguard Worker }
3681*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
3682*3ac0a46fSAndroid Build Coastguard Worker return "6844019e07b83cc01723415f58218d06";
3683*3ac0a46fSAndroid Build Coastguard Worker #else
3684*3ac0a46fSAndroid Build Coastguard Worker return "73d06ff4c665fe85029acef30240dcca";
3685*3ac0a46fSAndroid Build Coastguard Worker #endif
3686*3ac0a46fSAndroid Build Coastguard Worker }();
3687*3ac0a46fSAndroid Build Coastguard Worker
3688*3ac0a46fSAndroid Build Coastguard Worker {
3689*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
3690*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(annot);
3691*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot.get()));
3692*3ac0a46fSAndroid Build Coastguard Worker
3693*3ac0a46fSAndroid Build Coastguard Worker {
3694*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3695*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, original_checksum);
3696*3ac0a46fSAndroid Build Coastguard Worker }
3697*3ac0a46fSAndroid Build Coastguard Worker
3698*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDFAnnot_SetBorder(annot.get(), /*horizontal_radius=*/2.0f,
3699*3ac0a46fSAndroid Build Coastguard Worker /*vertical_radius=*/3.5f,
3700*3ac0a46fSAndroid Build Coastguard Worker /*border_width=*/4.0f));
3701*3ac0a46fSAndroid Build Coastguard Worker
3702*3ac0a46fSAndroid Build Coastguard Worker {
3703*3ac0a46fSAndroid Build Coastguard Worker ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
3704*3ac0a46fSAndroid Build Coastguard Worker CompareBitmap(bitmap.get(), 612, 792, modified_checksum);
3705*3ac0a46fSAndroid Build Coastguard Worker }
3706*3ac0a46fSAndroid Build Coastguard Worker }
3707*3ac0a46fSAndroid Build Coastguard Worker
3708*3ac0a46fSAndroid Build Coastguard Worker // Save the document and close the page.
3709*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3710*3ac0a46fSAndroid Build Coastguard Worker UnloadPage(page);
3711*3ac0a46fSAndroid Build Coastguard Worker
3712*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(OpenSavedDocument());
3713*3ac0a46fSAndroid Build Coastguard Worker page = LoadSavedPage(1);
3714*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(page);
3715*3ac0a46fSAndroid Build Coastguard Worker VerifySavedRendering(page, 612, 792, modified_checksum);
3716*3ac0a46fSAndroid Build Coastguard Worker
3717*3ac0a46fSAndroid Build Coastguard Worker CloseSavedPage(page);
3718*3ac0a46fSAndroid Build Coastguard Worker CloseSavedDocument();
3719*3ac0a46fSAndroid Build Coastguard Worker }
3720