xref: /aosp_15_r20/external/pdfium/fpdfsdk/fpdf_annot.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 <memory>
8*3ac0a46fSAndroid Build Coastguard Worker #include <sstream>
9*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
10*3ac0a46fSAndroid Build Coastguard Worker #include <vector>
11*3ac0a46fSAndroid Build Coastguard Worker 
12*3ac0a46fSAndroid Build Coastguard Worker #include "constants/annotation_common.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_annotcontext.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_form.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_page.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_pageobject.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_array.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_boolean.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_dictionary.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_document.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_name.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_number.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_reference.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_stream.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_string.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/fpdf_parser_utility.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_annot.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_color_utils.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_formfield.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_generateap.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_interactiveform.h"
33*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_safe_types.h"
34*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_string_wrappers.h"
35*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/stl_util.h"
36*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_color.h"
37*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
38*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_helpers.h"
39*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_interactiveform.h"
40*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
41*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/contains.h"
42*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/memory/ptr_util.h"
43*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/numerics/safe_conversions.h"
44*3ac0a46fSAndroid Build Coastguard Worker 
45*3ac0a46fSAndroid Build Coastguard Worker namespace {
46*3ac0a46fSAndroid Build Coastguard Worker 
47*3ac0a46fSAndroid Build Coastguard Worker // These checks ensure the consistency of annotation subtype values across core/
48*3ac0a46fSAndroid Build Coastguard Worker // and public.
49*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::UNKNOWN) ==
50*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_UNKNOWN,
51*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::UNKNOWN value mismatch");
52*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::TEXT) == FPDF_ANNOT_TEXT,
53*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::TEXT value mismatch");
54*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::LINK) == FPDF_ANNOT_LINK,
55*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::LINK value mismatch");
56*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::FREETEXT) ==
57*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_FREETEXT,
58*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::FREETEXT value mismatch");
59*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::LINE) == FPDF_ANNOT_LINE,
60*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::LINE value mismatch");
61*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::SQUARE) ==
62*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_SQUARE,
63*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::SQUARE value mismatch");
64*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::CIRCLE) ==
65*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_CIRCLE,
66*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::CIRCLE value mismatch");
67*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::POLYGON) ==
68*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_POLYGON,
69*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::POLYGON value mismatch");
70*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::POLYLINE) ==
71*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_POLYLINE,
72*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::POLYLINE value mismatch");
73*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::HIGHLIGHT) ==
74*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_HIGHLIGHT,
75*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::HIGHLIGHT value mismatch");
76*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::UNDERLINE) ==
77*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_UNDERLINE,
78*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::UNDERLINE value mismatch");
79*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::SQUIGGLY) ==
80*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_SQUIGGLY,
81*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::SQUIGGLY value mismatch");
82*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::STRIKEOUT) ==
83*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_STRIKEOUT,
84*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::STRIKEOUT value mismatch");
85*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::STAMP) == FPDF_ANNOT_STAMP,
86*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::STAMP value mismatch");
87*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::CARET) == FPDF_ANNOT_CARET,
88*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::CARET value mismatch");
89*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::INK) == FPDF_ANNOT_INK,
90*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::INK value mismatch");
91*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::POPUP) == FPDF_ANNOT_POPUP,
92*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::POPUP value mismatch");
93*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::FILEATTACHMENT) ==
94*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_FILEATTACHMENT,
95*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::FILEATTACHMENT value mismatch");
96*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::SOUND) == FPDF_ANNOT_SOUND,
97*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::SOUND value mismatch");
98*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::MOVIE) == FPDF_ANNOT_MOVIE,
99*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::MOVIE value mismatch");
100*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::WIDGET) ==
101*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_WIDGET,
102*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::WIDGET value mismatch");
103*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::SCREEN) ==
104*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_SCREEN,
105*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::SCREEN value mismatch");
106*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::PRINTERMARK) ==
107*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_PRINTERMARK,
108*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::PRINTERMARK value mismatch");
109*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::TRAPNET) ==
110*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_TRAPNET,
111*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::TRAPNET value mismatch");
112*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::WATERMARK) ==
113*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_WATERMARK,
114*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::WATERMARK value mismatch");
115*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::THREED) ==
116*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_THREED,
117*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::THREED value mismatch");
118*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::RICHMEDIA) ==
119*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_RICHMEDIA,
120*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::RICHMEDIA value mismatch");
121*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::XFAWIDGET) ==
122*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_XFAWIDGET,
123*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::XFAWIDGET value mismatch");
124*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::Subtype::REDACT) ==
125*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_REDACT,
126*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::REDACT value mismatch");
127*3ac0a46fSAndroid Build Coastguard Worker 
128*3ac0a46fSAndroid Build Coastguard Worker // These checks ensure the consistency of annotation appearance mode values
129*3ac0a46fSAndroid Build Coastguard Worker // across core/ and public.
130*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::kNormal) ==
131*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_APPEARANCEMODE_NORMAL,
132*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::AppearanceMode::Normal value mismatch");
133*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::kRollover) ==
134*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
135*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::AppearanceMode::Rollover value mismatch");
136*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::kDown) ==
137*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_APPEARANCEMODE_DOWN,
138*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Annot::AppearanceMode::Down value mismatch");
139*3ac0a46fSAndroid Build Coastguard Worker 
140*3ac0a46fSAndroid Build Coastguard Worker // These checks ensure the consistency of dictionary value types across core/
141*3ac0a46fSAndroid Build Coastguard Worker // and public/.
142*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kBoolean) ==
143*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_OBJECT_BOOLEAN,
144*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kBoolean value mismatch");
145*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kNumber) ==
146*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_OBJECT_NUMBER,
147*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kNumber value mismatch");
148*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kString) ==
149*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_OBJECT_STRING,
150*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kString value mismatch");
151*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kName) == FPDF_OBJECT_NAME,
152*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kName value mismatch");
153*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kArray) == FPDF_OBJECT_ARRAY,
154*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kArray value mismatch");
155*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kDictionary) ==
156*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_OBJECT_DICTIONARY,
157*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kDictionary value mismatch");
158*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kStream) ==
159*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_OBJECT_STREAM,
160*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kStream value mismatch");
161*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kNullobj) ==
162*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_OBJECT_NULLOBJ,
163*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kNullobj value mismatch");
164*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_Object::Type::kReference) ==
165*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_OBJECT_REFERENCE,
166*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_Object::kReference value mismatch");
167*3ac0a46fSAndroid Build Coastguard Worker 
168*3ac0a46fSAndroid Build Coastguard Worker // These checks ensure the consistency of annotation additional action event
169*3ac0a46fSAndroid Build Coastguard Worker // values across core/ and public.
170*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_AAction::kKeyStroke) ==
171*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_AACTION_KEY_STROKE,
172*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_AAction::kKeyStroke value mismatch");
173*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_AAction::kFormat) ==
174*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_AACTION_FORMAT,
175*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_AAction::kFormat value mismatch");
176*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_AAction::kValidate) ==
177*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_AACTION_VALIDATE,
178*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_AAction::kValidate value mismatch");
179*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_AAction::kCalculate) ==
180*3ac0a46fSAndroid Build Coastguard Worker                   FPDF_ANNOT_AACTION_CALCULATE,
181*3ac0a46fSAndroid Build Coastguard Worker               "CPDF_AAction::kCalculate value mismatch");
182*3ac0a46fSAndroid Build Coastguard Worker 
HasAPStream(CPDF_Dictionary * pAnnotDict)183*3ac0a46fSAndroid Build Coastguard Worker bool HasAPStream(CPDF_Dictionary* pAnnotDict) {
184*3ac0a46fSAndroid Build Coastguard Worker   return !!GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::kNormal);
185*3ac0a46fSAndroid Build Coastguard Worker }
186*3ac0a46fSAndroid Build Coastguard Worker 
UpdateContentStream(CPDF_Form * pForm,CPDF_Stream * pStream)187*3ac0a46fSAndroid Build Coastguard Worker void UpdateContentStream(CPDF_Form* pForm, CPDF_Stream* pStream) {
188*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(pForm);
189*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(pStream);
190*3ac0a46fSAndroid Build Coastguard Worker 
191*3ac0a46fSAndroid Build Coastguard Worker   CPDF_PageContentGenerator generator(pForm);
192*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream buf;
193*3ac0a46fSAndroid Build Coastguard Worker   generator.ProcessPageObjects(&buf);
194*3ac0a46fSAndroid Build Coastguard Worker   pStream->SetDataFromStringstreamAndRemoveFilter(&buf);
195*3ac0a46fSAndroid Build Coastguard Worker }
196*3ac0a46fSAndroid Build Coastguard Worker 
SetQuadPointsAtIndex(CPDF_Array * array,size_t quad_index,const FS_QUADPOINTSF * quad_points)197*3ac0a46fSAndroid Build Coastguard Worker void SetQuadPointsAtIndex(CPDF_Array* array,
198*3ac0a46fSAndroid Build Coastguard Worker                           size_t quad_index,
199*3ac0a46fSAndroid Build Coastguard Worker                           const FS_QUADPOINTSF* quad_points) {
200*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(array);
201*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(quad_points);
202*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(IsValidQuadPointsIndex(array, quad_index));
203*3ac0a46fSAndroid Build Coastguard Worker 
204*3ac0a46fSAndroid Build Coastguard Worker   size_t nIndex = quad_index * 8;
205*3ac0a46fSAndroid Build Coastguard Worker   array->SetNewAt<CPDF_Number>(nIndex, quad_points->x1);
206*3ac0a46fSAndroid Build Coastguard Worker   array->SetNewAt<CPDF_Number>(++nIndex, quad_points->y1);
207*3ac0a46fSAndroid Build Coastguard Worker   array->SetNewAt<CPDF_Number>(++nIndex, quad_points->x2);
208*3ac0a46fSAndroid Build Coastguard Worker   array->SetNewAt<CPDF_Number>(++nIndex, quad_points->y2);
209*3ac0a46fSAndroid Build Coastguard Worker   array->SetNewAt<CPDF_Number>(++nIndex, quad_points->x3);
210*3ac0a46fSAndroid Build Coastguard Worker   array->SetNewAt<CPDF_Number>(++nIndex, quad_points->y3);
211*3ac0a46fSAndroid Build Coastguard Worker   array->SetNewAt<CPDF_Number>(++nIndex, quad_points->x4);
212*3ac0a46fSAndroid Build Coastguard Worker   array->SetNewAt<CPDF_Number>(++nIndex, quad_points->y4);
213*3ac0a46fSAndroid Build Coastguard Worker }
214*3ac0a46fSAndroid Build Coastguard Worker 
AppendQuadPoints(CPDF_Array * array,const FS_QUADPOINTSF * quad_points)215*3ac0a46fSAndroid Build Coastguard Worker void AppendQuadPoints(CPDF_Array* array, const FS_QUADPOINTSF* quad_points) {
216*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(quad_points);
217*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(array);
218*3ac0a46fSAndroid Build Coastguard Worker 
219*3ac0a46fSAndroid Build Coastguard Worker   array->AppendNew<CPDF_Number>(quad_points->x1);
220*3ac0a46fSAndroid Build Coastguard Worker   array->AppendNew<CPDF_Number>(quad_points->y1);
221*3ac0a46fSAndroid Build Coastguard Worker   array->AppendNew<CPDF_Number>(quad_points->x2);
222*3ac0a46fSAndroid Build Coastguard Worker   array->AppendNew<CPDF_Number>(quad_points->y2);
223*3ac0a46fSAndroid Build Coastguard Worker   array->AppendNew<CPDF_Number>(quad_points->x3);
224*3ac0a46fSAndroid Build Coastguard Worker   array->AppendNew<CPDF_Number>(quad_points->y3);
225*3ac0a46fSAndroid Build Coastguard Worker   array->AppendNew<CPDF_Number>(quad_points->x4);
226*3ac0a46fSAndroid Build Coastguard Worker   array->AppendNew<CPDF_Number>(quad_points->y4);
227*3ac0a46fSAndroid Build Coastguard Worker }
228*3ac0a46fSAndroid Build Coastguard Worker 
UpdateBBox(CPDF_Dictionary * annot_dict)229*3ac0a46fSAndroid Build Coastguard Worker void UpdateBBox(CPDF_Dictionary* annot_dict) {
230*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(annot_dict);
231*3ac0a46fSAndroid Build Coastguard Worker   // Update BBox entry in appearance stream based on the bounding rectangle
232*3ac0a46fSAndroid Build Coastguard Worker   // of the annotation's quadpoints.
233*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pStream =
234*3ac0a46fSAndroid Build Coastguard Worker       GetAnnotAP(annot_dict, CPDF_Annot::AppearanceMode::kNormal);
235*3ac0a46fSAndroid Build Coastguard Worker   if (pStream) {
236*3ac0a46fSAndroid Build Coastguard Worker     CFX_FloatRect boundingRect =
237*3ac0a46fSAndroid Build Coastguard Worker         CPDF_Annot::BoundingRectFromQuadPoints(annot_dict);
238*3ac0a46fSAndroid Build Coastguard Worker     if (boundingRect.Contains(pStream->GetDict()->GetRectFor("BBox")))
239*3ac0a46fSAndroid Build Coastguard Worker       pStream->GetMutableDict()->SetRectFor("BBox", boundingRect);
240*3ac0a46fSAndroid Build Coastguard Worker   }
241*3ac0a46fSAndroid Build Coastguard Worker }
242*3ac0a46fSAndroid Build Coastguard Worker 
GetAnnotDictFromFPDFAnnotation(const FPDF_ANNOTATION annot)243*3ac0a46fSAndroid Build Coastguard Worker const CPDF_Dictionary* GetAnnotDictFromFPDFAnnotation(
244*3ac0a46fSAndroid Build Coastguard Worker     const FPDF_ANNOTATION annot) {
245*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot);
246*3ac0a46fSAndroid Build Coastguard Worker   return context ? context->GetAnnotDict() : nullptr;
247*3ac0a46fSAndroid Build Coastguard Worker }
248*3ac0a46fSAndroid Build Coastguard Worker 
GetMutableAnnotDictFromFPDFAnnotation(FPDF_ANNOTATION annot)249*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Dictionary> GetMutableAnnotDictFromFPDFAnnotation(
250*3ac0a46fSAndroid Build Coastguard Worker     FPDF_ANNOTATION annot) {
251*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot);
252*3ac0a46fSAndroid Build Coastguard Worker   return context ? context->GetMutableAnnotDict() : nullptr;
253*3ac0a46fSAndroid Build Coastguard Worker }
254*3ac0a46fSAndroid Build Coastguard Worker 
SetExtGStateInResourceDict(CPDF_Document * pDoc,const CPDF_Dictionary * pAnnotDict,const ByteString & sBlendMode)255*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Dictionary> SetExtGStateInResourceDict(
256*3ac0a46fSAndroid Build Coastguard Worker     CPDF_Document* pDoc,
257*3ac0a46fSAndroid Build Coastguard Worker     const CPDF_Dictionary* pAnnotDict,
258*3ac0a46fSAndroid Build Coastguard Worker     const ByteString& sBlendMode) {
259*3ac0a46fSAndroid Build Coastguard Worker   auto pGSDict =
260*3ac0a46fSAndroid Build Coastguard Worker       pdfium::MakeRetain<CPDF_Dictionary>(pAnnotDict->GetByteStringPool());
261*3ac0a46fSAndroid Build Coastguard Worker 
262*3ac0a46fSAndroid Build Coastguard Worker   // ExtGState represents a graphics state parameter dictionary.
263*3ac0a46fSAndroid Build Coastguard Worker   pGSDict->SetNewFor<CPDF_Name>("Type", "ExtGState");
264*3ac0a46fSAndroid Build Coastguard Worker 
265*3ac0a46fSAndroid Build Coastguard Worker   // CA respresents current stroking alpha specifying constant opacity
266*3ac0a46fSAndroid Build Coastguard Worker   // value that should be used in transparent imaging model.
267*3ac0a46fSAndroid Build Coastguard Worker   float fOpacity = pAnnotDict->GetFloatFor("CA");
268*3ac0a46fSAndroid Build Coastguard Worker 
269*3ac0a46fSAndroid Build Coastguard Worker   pGSDict->SetNewFor<CPDF_Number>("CA", fOpacity);
270*3ac0a46fSAndroid Build Coastguard Worker 
271*3ac0a46fSAndroid Build Coastguard Worker   // ca represents fill color alpha specifying constant opacity
272*3ac0a46fSAndroid Build Coastguard Worker   // value that should be used in transparent imaging model.
273*3ac0a46fSAndroid Build Coastguard Worker   pGSDict->SetNewFor<CPDF_Number>("ca", fOpacity);
274*3ac0a46fSAndroid Build Coastguard Worker 
275*3ac0a46fSAndroid Build Coastguard Worker   // AIS represents alpha source flag specifying whether current alpha
276*3ac0a46fSAndroid Build Coastguard Worker   // constant shall be interpreted as shape value (true) or opacity value
277*3ac0a46fSAndroid Build Coastguard Worker   // (false).
278*3ac0a46fSAndroid Build Coastguard Worker   pGSDict->SetNewFor<CPDF_Boolean>("AIS", false);
279*3ac0a46fSAndroid Build Coastguard Worker 
280*3ac0a46fSAndroid Build Coastguard Worker   // BM represents Blend Mode
281*3ac0a46fSAndroid Build Coastguard Worker   pGSDict->SetNewFor<CPDF_Name>("BM", sBlendMode);
282*3ac0a46fSAndroid Build Coastguard Worker 
283*3ac0a46fSAndroid Build Coastguard Worker   auto pExtGStateDict =
284*3ac0a46fSAndroid Build Coastguard Worker       pdfium::MakeRetain<CPDF_Dictionary>(pAnnotDict->GetByteStringPool());
285*3ac0a46fSAndroid Build Coastguard Worker 
286*3ac0a46fSAndroid Build Coastguard Worker   pExtGStateDict->SetFor("GS", pGSDict);
287*3ac0a46fSAndroid Build Coastguard Worker 
288*3ac0a46fSAndroid Build Coastguard Worker   auto pResourceDict = pDoc->New<CPDF_Dictionary>();
289*3ac0a46fSAndroid Build Coastguard Worker   pResourceDict->SetFor("ExtGState", pExtGStateDict);
290*3ac0a46fSAndroid Build Coastguard Worker   return pResourceDict;
291*3ac0a46fSAndroid Build Coastguard Worker }
292*3ac0a46fSAndroid Build Coastguard Worker 
GetFormField(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot)293*3ac0a46fSAndroid Build Coastguard Worker CPDF_FormField* GetFormField(FPDF_FORMHANDLE hHandle, FPDF_ANNOTATION annot) {
294*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
295*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
296*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
297*3ac0a46fSAndroid Build Coastguard Worker 
298*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
299*3ac0a46fSAndroid Build Coastguard Worker   if (!pForm)
300*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
301*3ac0a46fSAndroid Build Coastguard Worker 
302*3ac0a46fSAndroid Build Coastguard Worker   CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
303*3ac0a46fSAndroid Build Coastguard Worker   return pPDFForm->GetFieldByDict(pAnnotDict);
304*3ac0a46fSAndroid Build Coastguard Worker }
305*3ac0a46fSAndroid Build Coastguard Worker 
GetRadioButtonOrCheckBoxWidget(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot)306*3ac0a46fSAndroid Build Coastguard Worker const CPDFSDK_Widget* GetRadioButtonOrCheckBoxWidget(FPDF_FORMHANDLE hHandle,
307*3ac0a46fSAndroid Build Coastguard Worker                                                      FPDF_ANNOTATION annot) {
308*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
309*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
310*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
311*3ac0a46fSAndroid Build Coastguard Worker 
312*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
313*3ac0a46fSAndroid Build Coastguard Worker   if (!pForm)
314*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
315*3ac0a46fSAndroid Build Coastguard Worker 
316*3ac0a46fSAndroid Build Coastguard Worker   CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
317*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormField* pFormField = pPDFForm->GetFieldByDict(pAnnotDict);
318*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormField || (pFormField->GetType() != CPDF_FormField::kCheckBox &&
319*3ac0a46fSAndroid Build Coastguard Worker                       pFormField->GetType() != CPDF_FormField::kRadioButton)) {
320*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
321*3ac0a46fSAndroid Build Coastguard Worker   }
322*3ac0a46fSAndroid Build Coastguard Worker 
323*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pFormControl = pPDFForm->GetControlByDict(pAnnotDict);
324*3ac0a46fSAndroid Build Coastguard Worker   return pFormControl ? pForm->GetWidget(pFormControl) : nullptr;
325*3ac0a46fSAndroid Build Coastguard Worker }
326*3ac0a46fSAndroid Build Coastguard Worker 
GetInkList(FPDF_ANNOTATION annot)327*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Array> GetInkList(FPDF_ANNOTATION annot) {
328*3ac0a46fSAndroid Build Coastguard Worker   FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot);
329*3ac0a46fSAndroid Build Coastguard Worker   if (subtype != FPDF_ANNOT_INK)
330*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
331*3ac0a46fSAndroid Build Coastguard Worker 
332*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* annot_dict = GetAnnotDictFromFPDFAnnotation(annot);
333*3ac0a46fSAndroid Build Coastguard Worker   return annot_dict ? annot_dict->GetArrayFor(pdfium::annotation::kInkList)
334*3ac0a46fSAndroid Build Coastguard Worker                     : nullptr;
335*3ac0a46fSAndroid Build Coastguard Worker }
336*3ac0a46fSAndroid Build Coastguard Worker 
337*3ac0a46fSAndroid Build Coastguard Worker }  // namespace
338*3ac0a46fSAndroid Build Coastguard Worker 
339*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_IsSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype)340*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) {
341*3ac0a46fSAndroid Build Coastguard Worker   // The supported subtypes must also be communicated in the user doc.
342*3ac0a46fSAndroid Build Coastguard Worker   switch (subtype) {
343*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_CIRCLE:
344*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_FREETEXT:
345*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_HIGHLIGHT:
346*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_INK:
347*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_LINK:
348*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_POPUP:
349*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_SQUARE:
350*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_SQUIGGLY:
351*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_STAMP:
352*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_STRIKEOUT:
353*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_TEXT:
354*3ac0a46fSAndroid Build Coastguard Worker     case FPDF_ANNOT_UNDERLINE:
355*3ac0a46fSAndroid Build Coastguard Worker       return true;
356*3ac0a46fSAndroid Build Coastguard Worker     default:
357*3ac0a46fSAndroid Build Coastguard Worker       return false;
358*3ac0a46fSAndroid Build Coastguard Worker   }
359*3ac0a46fSAndroid Build Coastguard Worker }
360*3ac0a46fSAndroid Build Coastguard Worker 
361*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
FPDFPage_CreateAnnot(FPDF_PAGE page,FPDF_ANNOTATION_SUBTYPE subtype)362*3ac0a46fSAndroid Build Coastguard Worker FPDFPage_CreateAnnot(FPDF_PAGE page, FPDF_ANNOTATION_SUBTYPE subtype) {
363*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
364*3ac0a46fSAndroid Build Coastguard Worker   if (!pPage || !FPDFAnnot_IsSupportedSubtype(subtype))
365*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
366*3ac0a46fSAndroid Build Coastguard Worker 
367*3ac0a46fSAndroid Build Coastguard Worker   auto pDict = pPage->GetDocument()->New<CPDF_Dictionary>();
368*3ac0a46fSAndroid Build Coastguard Worker   pDict->SetNewFor<CPDF_Name>(pdfium::annotation::kType, "Annot");
369*3ac0a46fSAndroid Build Coastguard Worker   pDict->SetNewFor<CPDF_Name>(pdfium::annotation::kSubtype,
370*3ac0a46fSAndroid Build Coastguard Worker                               CPDF_Annot::AnnotSubtypeToString(
371*3ac0a46fSAndroid Build Coastguard Worker                                   static_cast<CPDF_Annot::Subtype>(subtype)));
372*3ac0a46fSAndroid Build Coastguard Worker   auto pNewAnnot =
373*3ac0a46fSAndroid Build Coastguard Worker       std::make_unique<CPDF_AnnotContext>(pDict, IPDFPageFromFPDFPage(page));
374*3ac0a46fSAndroid Build Coastguard Worker 
375*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Array> pAnnotList = pPage->GetOrCreateAnnotsArray();
376*3ac0a46fSAndroid Build Coastguard Worker   pAnnotList->Append(pDict);
377*3ac0a46fSAndroid Build Coastguard Worker 
378*3ac0a46fSAndroid Build Coastguard Worker   // Caller takes ownership.
379*3ac0a46fSAndroid Build Coastguard Worker   return FPDFAnnotationFromCPDFAnnotContext(pNewAnnot.release());
380*3ac0a46fSAndroid Build Coastguard Worker }
381*3ac0a46fSAndroid Build Coastguard Worker 
FPDFPage_GetAnnotCount(FPDF_PAGE page)382*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotCount(FPDF_PAGE page) {
383*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
384*3ac0a46fSAndroid Build Coastguard Worker   if (!pPage)
385*3ac0a46fSAndroid Build Coastguard Worker     return 0;
386*3ac0a46fSAndroid Build Coastguard Worker 
387*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> pAnnots = pPage->GetAnnotsArray();
388*3ac0a46fSAndroid Build Coastguard Worker   return pAnnots ? fxcrt::CollectionSize<int>(*pAnnots) : 0;
389*3ac0a46fSAndroid Build Coastguard Worker }
390*3ac0a46fSAndroid Build Coastguard Worker 
FPDFPage_GetAnnot(FPDF_PAGE page,int index)391*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV FPDFPage_GetAnnot(FPDF_PAGE page,
392*3ac0a46fSAndroid Build Coastguard Worker                                                             int index) {
393*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
394*3ac0a46fSAndroid Build Coastguard Worker   if (!pPage || index < 0)
395*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
396*3ac0a46fSAndroid Build Coastguard Worker 
397*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Array> pAnnots = pPage->GetMutableAnnotsArray();
398*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnots || static_cast<size_t>(index) >= pAnnots->size())
399*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
400*3ac0a46fSAndroid Build Coastguard Worker 
401*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pDict =
402*3ac0a46fSAndroid Build Coastguard Worker       ToDictionary(pAnnots->GetMutableDirectObjectAt(index));
403*3ac0a46fSAndroid Build Coastguard Worker   if (!pDict)
404*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
405*3ac0a46fSAndroid Build Coastguard Worker 
406*3ac0a46fSAndroid Build Coastguard Worker   auto pNewAnnot = std::make_unique<CPDF_AnnotContext>(
407*3ac0a46fSAndroid Build Coastguard Worker       std::move(pDict), IPDFPageFromFPDFPage(page));
408*3ac0a46fSAndroid Build Coastguard Worker 
409*3ac0a46fSAndroid Build Coastguard Worker   // Caller takes ownership.
410*3ac0a46fSAndroid Build Coastguard Worker   return FPDFAnnotationFromCPDFAnnotContext(pNewAnnot.release());
411*3ac0a46fSAndroid Build Coastguard Worker }
412*3ac0a46fSAndroid Build Coastguard Worker 
FPDFPage_GetAnnotIndex(FPDF_PAGE page,FPDF_ANNOTATION annot)413*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotIndex(FPDF_PAGE page,
414*3ac0a46fSAndroid Build Coastguard Worker                                                      FPDF_ANNOTATION annot) {
415*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
416*3ac0a46fSAndroid Build Coastguard Worker   if (!pPage)
417*3ac0a46fSAndroid Build Coastguard Worker     return -1;
418*3ac0a46fSAndroid Build Coastguard Worker 
419*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
420*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
421*3ac0a46fSAndroid Build Coastguard Worker     return -1;
422*3ac0a46fSAndroid Build Coastguard Worker 
423*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> pAnnots = pPage->GetAnnotsArray();
424*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnots)
425*3ac0a46fSAndroid Build Coastguard Worker     return -1;
426*3ac0a46fSAndroid Build Coastguard Worker 
427*3ac0a46fSAndroid Build Coastguard Worker   CPDF_ArrayLocker locker(pAnnots);
428*3ac0a46fSAndroid Build Coastguard Worker   auto it = std::find_if(locker.begin(), locker.end(),
429*3ac0a46fSAndroid Build Coastguard Worker                          [pAnnotDict](const RetainPtr<CPDF_Object>& candidate) {
430*3ac0a46fSAndroid Build Coastguard Worker                            return candidate->GetDirect() == pAnnotDict;
431*3ac0a46fSAndroid Build Coastguard Worker                          });
432*3ac0a46fSAndroid Build Coastguard Worker 
433*3ac0a46fSAndroid Build Coastguard Worker   if (it == locker.end())
434*3ac0a46fSAndroid Build Coastguard Worker     return -1;
435*3ac0a46fSAndroid Build Coastguard Worker 
436*3ac0a46fSAndroid Build Coastguard Worker   return pdfium::base::checked_cast<int>(it - locker.begin());
437*3ac0a46fSAndroid Build Coastguard Worker }
438*3ac0a46fSAndroid Build Coastguard Worker 
FPDFPage_CloseAnnot(FPDF_ANNOTATION annot)439*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT void FPDF_CALLCONV FPDFPage_CloseAnnot(FPDF_ANNOTATION annot) {
440*3ac0a46fSAndroid Build Coastguard Worker   delete CPDFAnnotContextFromFPDFAnnotation(annot);
441*3ac0a46fSAndroid Build Coastguard Worker }
442*3ac0a46fSAndroid Build Coastguard Worker 
FPDFPage_RemoveAnnot(FPDF_PAGE page,int index)443*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_RemoveAnnot(FPDF_PAGE page,
444*3ac0a46fSAndroid Build Coastguard Worker                                                          int index) {
445*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
446*3ac0a46fSAndroid Build Coastguard Worker   if (!pPage || index < 0)
447*3ac0a46fSAndroid Build Coastguard Worker     return false;
448*3ac0a46fSAndroid Build Coastguard Worker 
449*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Array> pAnnots = pPage->GetMutableAnnotsArray();
450*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnots || static_cast<size_t>(index) >= pAnnots->size())
451*3ac0a46fSAndroid Build Coastguard Worker     return false;
452*3ac0a46fSAndroid Build Coastguard Worker 
453*3ac0a46fSAndroid Build Coastguard Worker   pAnnots->RemoveAt(index);
454*3ac0a46fSAndroid Build Coastguard Worker   return true;
455*3ac0a46fSAndroid Build Coastguard Worker }
456*3ac0a46fSAndroid Build Coastguard Worker 
457*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_ANNOTATION_SUBTYPE FPDF_CALLCONV
FPDFAnnot_GetSubtype(FPDF_ANNOTATION annot)458*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetSubtype(FPDF_ANNOTATION annot) {
459*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
460*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
461*3ac0a46fSAndroid Build Coastguard Worker     return FPDF_ANNOT_UNKNOWN;
462*3ac0a46fSAndroid Build Coastguard Worker 
463*3ac0a46fSAndroid Build Coastguard Worker   return static_cast<FPDF_ANNOTATION_SUBTYPE>(CPDF_Annot::StringToAnnotSubtype(
464*3ac0a46fSAndroid Build Coastguard Worker       pAnnotDict->GetNameFor(pdfium::annotation::kSubtype)));
465*3ac0a46fSAndroid Build Coastguard Worker }
466*3ac0a46fSAndroid Build Coastguard Worker 
467*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_IsObjectSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype)468*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsObjectSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) {
469*3ac0a46fSAndroid Build Coastguard Worker   // The supported subtypes must also be communicated in the user doc.
470*3ac0a46fSAndroid Build Coastguard Worker   return subtype == FPDF_ANNOT_INK || subtype == FPDF_ANNOT_STAMP;
471*3ac0a46fSAndroid Build Coastguard Worker }
472*3ac0a46fSAndroid Build Coastguard Worker 
473*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_UpdateObject(FPDF_ANNOTATION annot,FPDF_PAGEOBJECT obj)474*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_UpdateObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) {
475*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
476*3ac0a46fSAndroid Build Coastguard Worker   CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(obj);
477*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot || !pAnnot->HasForm() || !pObj)
478*3ac0a46fSAndroid Build Coastguard Worker     return false;
479*3ac0a46fSAndroid Build Coastguard Worker 
480*3ac0a46fSAndroid Build Coastguard Worker   // Check that the annotation type is supported by this method.
481*3ac0a46fSAndroid Build Coastguard Worker   if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot)))
482*3ac0a46fSAndroid Build Coastguard Worker     return false;
483*3ac0a46fSAndroid Build Coastguard Worker 
484*3ac0a46fSAndroid Build Coastguard Worker   // Check that the annotation already has an appearance stream, since an
485*3ac0a46fSAndroid Build Coastguard Worker   // existing object is to be updated.
486*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict = pAnnot->GetMutableAnnotDict();
487*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pStream =
488*3ac0a46fSAndroid Build Coastguard Worker       GetAnnotAP(pAnnotDict.Get(), CPDF_Annot::AppearanceMode::kNormal);
489*3ac0a46fSAndroid Build Coastguard Worker   if (!pStream)
490*3ac0a46fSAndroid Build Coastguard Worker     return false;
491*3ac0a46fSAndroid Build Coastguard Worker 
492*3ac0a46fSAndroid Build Coastguard Worker   // Check that the object is already in this annotation's object list.
493*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Form* pForm = pAnnot->GetForm();
494*3ac0a46fSAndroid Build Coastguard Worker   if (!pdfium::Contains(*pForm, fxcrt::MakeFakeUniquePtr(pObj)))
495*3ac0a46fSAndroid Build Coastguard Worker     return false;
496*3ac0a46fSAndroid Build Coastguard Worker 
497*3ac0a46fSAndroid Build Coastguard Worker   // Update the content stream data in the annotation's AP stream.
498*3ac0a46fSAndroid Build Coastguard Worker   UpdateContentStream(pForm, pStream.Get());
499*3ac0a46fSAndroid Build Coastguard Worker   return true;
500*3ac0a46fSAndroid Build Coastguard Worker }
501*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_AddInkStroke(FPDF_ANNOTATION annot,const FS_POINTF * points,size_t point_count)502*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_AddInkStroke(FPDF_ANNOTATION annot,
503*3ac0a46fSAndroid Build Coastguard Worker                                                      const FS_POINTF* points,
504*3ac0a46fSAndroid Build Coastguard Worker                                                      size_t point_count) {
505*3ac0a46fSAndroid Build Coastguard Worker   if (FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_INK || !points ||
506*3ac0a46fSAndroid Build Coastguard Worker       point_count == 0 ||
507*3ac0a46fSAndroid Build Coastguard Worker       !pdfium::base::IsValueInRangeForNumericType<int32_t>(point_count)) {
508*3ac0a46fSAndroid Build Coastguard Worker     return -1;
509*3ac0a46fSAndroid Build Coastguard Worker   }
510*3ac0a46fSAndroid Build Coastguard Worker 
511*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> annot_dict =
512*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
513*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Array> inklist = annot_dict->GetOrCreateArrayFor("InkList");
514*3ac0a46fSAndroid Build Coastguard Worker   FX_SAFE_SIZE_T safe_ink_size = inklist->size();
515*3ac0a46fSAndroid Build Coastguard Worker   safe_ink_size += 1;
516*3ac0a46fSAndroid Build Coastguard Worker   if (!safe_ink_size.IsValid<int32_t>())
517*3ac0a46fSAndroid Build Coastguard Worker     return -1;
518*3ac0a46fSAndroid Build Coastguard Worker 
519*3ac0a46fSAndroid Build Coastguard Worker   auto ink_coord_list = inklist->AppendNew<CPDF_Array>();
520*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < point_count; i++) {
521*3ac0a46fSAndroid Build Coastguard Worker     ink_coord_list->AppendNew<CPDF_Number>(points[i].x);
522*3ac0a46fSAndroid Build Coastguard Worker     ink_coord_list->AppendNew<CPDF_Number>(points[i].y);
523*3ac0a46fSAndroid Build Coastguard Worker   }
524*3ac0a46fSAndroid Build Coastguard Worker   return static_cast<int>(inklist->size() - 1);
525*3ac0a46fSAndroid Build Coastguard Worker }
526*3ac0a46fSAndroid Build Coastguard Worker 
527*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_RemoveInkList(FPDF_ANNOTATION annot)528*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_RemoveInkList(FPDF_ANNOTATION annot) {
529*3ac0a46fSAndroid Build Coastguard Worker   if (FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_INK)
530*3ac0a46fSAndroid Build Coastguard Worker     return false;
531*3ac0a46fSAndroid Build Coastguard Worker 
532*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> annot_dict =
533*3ac0a46fSAndroid Build Coastguard Worker       CPDFAnnotContextFromFPDFAnnotation(annot)->GetMutableAnnotDict();
534*3ac0a46fSAndroid Build Coastguard Worker   annot_dict->RemoveFor("InkList");
535*3ac0a46fSAndroid Build Coastguard Worker   return true;
536*3ac0a46fSAndroid Build Coastguard Worker }
537*3ac0a46fSAndroid Build Coastguard Worker 
538*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_AppendObject(FPDF_ANNOTATION annot,FPDF_PAGEOBJECT obj)539*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_AppendObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) {
540*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
541*3ac0a46fSAndroid Build Coastguard Worker   CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(obj);
542*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot || !pObj)
543*3ac0a46fSAndroid Build Coastguard Worker     return false;
544*3ac0a46fSAndroid Build Coastguard Worker 
545*3ac0a46fSAndroid Build Coastguard Worker   // Check that the annotation type is supported by this method.
546*3ac0a46fSAndroid Build Coastguard Worker   if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot)))
547*3ac0a46fSAndroid Build Coastguard Worker     return false;
548*3ac0a46fSAndroid Build Coastguard Worker 
549*3ac0a46fSAndroid Build Coastguard Worker   // If the annotation does not have an AP stream yet, generate and set it.
550*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict = pAnnot->GetMutableAnnotDict();
551*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pStream =
552*3ac0a46fSAndroid Build Coastguard Worker       GetAnnotAP(pAnnotDict.Get(), CPDF_Annot::AppearanceMode::kNormal);
553*3ac0a46fSAndroid Build Coastguard Worker   if (!pStream) {
554*3ac0a46fSAndroid Build Coastguard Worker     CPDF_GenerateAP::GenerateEmptyAP(pAnnot->GetPage()->GetDocument(),
555*3ac0a46fSAndroid Build Coastguard Worker                                      pAnnotDict.Get());
556*3ac0a46fSAndroid Build Coastguard Worker     pStream = GetAnnotAP(pAnnotDict.Get(), CPDF_Annot::AppearanceMode::kNormal);
557*3ac0a46fSAndroid Build Coastguard Worker     if (!pStream)
558*3ac0a46fSAndroid Build Coastguard Worker       return false;
559*3ac0a46fSAndroid Build Coastguard Worker   }
560*3ac0a46fSAndroid Build Coastguard Worker 
561*3ac0a46fSAndroid Build Coastguard Worker   // Get the annotation's corresponding form object for parsing its AP stream.
562*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot->HasForm())
563*3ac0a46fSAndroid Build Coastguard Worker     pAnnot->SetForm(pStream);
564*3ac0a46fSAndroid Build Coastguard Worker 
565*3ac0a46fSAndroid Build Coastguard Worker   // Check that the object did not come from the same annotation. If this check
566*3ac0a46fSAndroid Build Coastguard Worker   // succeeds, then it is assumed that the object came from
567*3ac0a46fSAndroid Build Coastguard Worker   // FPDFPageObj_CreateNew{Path|Rect}() or FPDFPageObj_New{Text|Image}Obj().
568*3ac0a46fSAndroid Build Coastguard Worker   // Note that an object that came from a different annotation must not be
569*3ac0a46fSAndroid Build Coastguard Worker   // passed here, since an object cannot belong to more than one annotation.
570*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Form* pForm = pAnnot->GetForm();
571*3ac0a46fSAndroid Build Coastguard Worker   if (pdfium::Contains(*pForm, fxcrt::MakeFakeUniquePtr(pObj)))
572*3ac0a46fSAndroid Build Coastguard Worker     return false;
573*3ac0a46fSAndroid Build Coastguard Worker 
574*3ac0a46fSAndroid Build Coastguard Worker   // Append the object to the object list.
575*3ac0a46fSAndroid Build Coastguard Worker   pForm->AppendPageObject(pdfium::WrapUnique(pObj));
576*3ac0a46fSAndroid Build Coastguard Worker 
577*3ac0a46fSAndroid Build Coastguard Worker   // Set the content stream data in the annotation's AP stream.
578*3ac0a46fSAndroid Build Coastguard Worker   UpdateContentStream(pForm, pStream.Get());
579*3ac0a46fSAndroid Build Coastguard Worker   return true;
580*3ac0a46fSAndroid Build Coastguard Worker }
581*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_GetObjectCount(FPDF_ANNOTATION annot)582*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetObjectCount(FPDF_ANNOTATION annot) {
583*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
584*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot)
585*3ac0a46fSAndroid Build Coastguard Worker     return 0;
586*3ac0a46fSAndroid Build Coastguard Worker 
587*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot->HasForm()) {
588*3ac0a46fSAndroid Build Coastguard Worker     RetainPtr<CPDF_Dictionary> pDict = pAnnot->GetMutableAnnotDict();
589*3ac0a46fSAndroid Build Coastguard Worker     RetainPtr<CPDF_Stream> pStream =
590*3ac0a46fSAndroid Build Coastguard Worker         GetAnnotAP(pDict.Get(), CPDF_Annot::AppearanceMode::kNormal);
591*3ac0a46fSAndroid Build Coastguard Worker     if (!pStream)
592*3ac0a46fSAndroid Build Coastguard Worker       return 0;
593*3ac0a46fSAndroid Build Coastguard Worker 
594*3ac0a46fSAndroid Build Coastguard Worker     pAnnot->SetForm(std::move(pStream));
595*3ac0a46fSAndroid Build Coastguard Worker   }
596*3ac0a46fSAndroid Build Coastguard Worker   return pdfium::base::checked_cast<int>(
597*3ac0a46fSAndroid Build Coastguard Worker       pAnnot->GetForm()->GetPageObjectCount());
598*3ac0a46fSAndroid Build Coastguard Worker }
599*3ac0a46fSAndroid Build Coastguard Worker 
600*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
FPDFAnnot_GetObject(FPDF_ANNOTATION annot,int index)601*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetObject(FPDF_ANNOTATION annot, int index) {
602*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
603*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot || index < 0)
604*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
605*3ac0a46fSAndroid Build Coastguard Worker 
606*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot->HasForm()) {
607*3ac0a46fSAndroid Build Coastguard Worker     RetainPtr<CPDF_Dictionary> pAnnotDict = pAnnot->GetMutableAnnotDict();
608*3ac0a46fSAndroid Build Coastguard Worker     RetainPtr<CPDF_Stream> pStream =
609*3ac0a46fSAndroid Build Coastguard Worker         GetAnnotAP(pAnnotDict.Get(), CPDF_Annot::AppearanceMode::kNormal);
610*3ac0a46fSAndroid Build Coastguard Worker     if (!pStream)
611*3ac0a46fSAndroid Build Coastguard Worker       return nullptr;
612*3ac0a46fSAndroid Build Coastguard Worker 
613*3ac0a46fSAndroid Build Coastguard Worker     pAnnot->SetForm(std::move(pStream));
614*3ac0a46fSAndroid Build Coastguard Worker   }
615*3ac0a46fSAndroid Build Coastguard Worker 
616*3ac0a46fSAndroid Build Coastguard Worker   return FPDFPageObjectFromCPDFPageObject(
617*3ac0a46fSAndroid Build Coastguard Worker       pAnnot->GetForm()->GetPageObjectByIndex(index));
618*3ac0a46fSAndroid Build Coastguard Worker }
619*3ac0a46fSAndroid Build Coastguard Worker 
620*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_RemoveObject(FPDF_ANNOTATION annot,int index)621*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_RemoveObject(FPDF_ANNOTATION annot, int index) {
622*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
623*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot || !pAnnot->HasForm() || index < 0)
624*3ac0a46fSAndroid Build Coastguard Worker     return false;
625*3ac0a46fSAndroid Build Coastguard Worker 
626*3ac0a46fSAndroid Build Coastguard Worker   // Check that the annotation type is supported by this method.
627*3ac0a46fSAndroid Build Coastguard Worker   if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot)))
628*3ac0a46fSAndroid Build Coastguard Worker     return false;
629*3ac0a46fSAndroid Build Coastguard Worker 
630*3ac0a46fSAndroid Build Coastguard Worker   // Check that the annotation already has an appearance stream, since an
631*3ac0a46fSAndroid Build Coastguard Worker   // existing object is to be deleted.
632*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict = pAnnot->GetMutableAnnotDict();
633*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pStream =
634*3ac0a46fSAndroid Build Coastguard Worker       GetAnnotAP(pAnnotDict.Get(), CPDF_Annot::AppearanceMode::kNormal);
635*3ac0a46fSAndroid Build Coastguard Worker   if (!pStream)
636*3ac0a46fSAndroid Build Coastguard Worker     return false;
637*3ac0a46fSAndroid Build Coastguard Worker 
638*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot->GetForm()->ErasePageObjectAtIndex(index))
639*3ac0a46fSAndroid Build Coastguard Worker     return false;
640*3ac0a46fSAndroid Build Coastguard Worker 
641*3ac0a46fSAndroid Build Coastguard Worker   UpdateContentStream(pAnnot->GetForm(), pStream.Get());
642*3ac0a46fSAndroid Build Coastguard Worker   return true;
643*3ac0a46fSAndroid Build Coastguard Worker }
644*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_SetColor(FPDF_ANNOTATION annot,FPDFANNOT_COLORTYPE type,unsigned int R,unsigned int G,unsigned int B,unsigned int A)645*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetColor(FPDF_ANNOTATION annot,
646*3ac0a46fSAndroid Build Coastguard Worker                                                        FPDFANNOT_COLORTYPE type,
647*3ac0a46fSAndroid Build Coastguard Worker                                                        unsigned int R,
648*3ac0a46fSAndroid Build Coastguard Worker                                                        unsigned int G,
649*3ac0a46fSAndroid Build Coastguard Worker                                                        unsigned int B,
650*3ac0a46fSAndroid Build Coastguard Worker                                                        unsigned int A) {
651*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
652*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
653*3ac0a46fSAndroid Build Coastguard Worker 
654*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict || R > 255 || G > 255 || B > 255 || A > 255)
655*3ac0a46fSAndroid Build Coastguard Worker     return false;
656*3ac0a46fSAndroid Build Coastguard Worker 
657*3ac0a46fSAndroid Build Coastguard Worker   // For annotations with their appearance streams already defined, the path
658*3ac0a46fSAndroid Build Coastguard Worker   // stream's own color definitions take priority over the annotation color
659*3ac0a46fSAndroid Build Coastguard Worker   // definitions set by this method, hence this method will simply fail.
660*3ac0a46fSAndroid Build Coastguard Worker   if (HasAPStream(pAnnotDict.Get()))
661*3ac0a46fSAndroid Build Coastguard Worker     return false;
662*3ac0a46fSAndroid Build Coastguard Worker 
663*3ac0a46fSAndroid Build Coastguard Worker   // Set the opacity of the annotation.
664*3ac0a46fSAndroid Build Coastguard Worker   pAnnotDict->SetNewFor<CPDF_Number>("CA", A / 255.f);
665*3ac0a46fSAndroid Build Coastguard Worker 
666*3ac0a46fSAndroid Build Coastguard Worker   // Set the color of the annotation.
667*3ac0a46fSAndroid Build Coastguard Worker   ByteString key = type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C";
668*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Array> pColor = pAnnotDict->GetMutableArrayFor(key);
669*3ac0a46fSAndroid Build Coastguard Worker   if (pColor)
670*3ac0a46fSAndroid Build Coastguard Worker     pColor->Clear();
671*3ac0a46fSAndroid Build Coastguard Worker   else
672*3ac0a46fSAndroid Build Coastguard Worker     pColor = pAnnotDict->SetNewFor<CPDF_Array>(key);
673*3ac0a46fSAndroid Build Coastguard Worker 
674*3ac0a46fSAndroid Build Coastguard Worker   pColor->AppendNew<CPDF_Number>(R / 255.f);
675*3ac0a46fSAndroid Build Coastguard Worker   pColor->AppendNew<CPDF_Number>(G / 255.f);
676*3ac0a46fSAndroid Build Coastguard Worker   pColor->AppendNew<CPDF_Number>(B / 255.f);
677*3ac0a46fSAndroid Build Coastguard Worker 
678*3ac0a46fSAndroid Build Coastguard Worker   return true;
679*3ac0a46fSAndroid Build Coastguard Worker }
680*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_GetColor(FPDF_ANNOTATION annot,FPDFANNOT_COLORTYPE type,unsigned int * R,unsigned int * G,unsigned int * B,unsigned int * A)681*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetColor(FPDF_ANNOTATION annot,
682*3ac0a46fSAndroid Build Coastguard Worker                                                        FPDFANNOT_COLORTYPE type,
683*3ac0a46fSAndroid Build Coastguard Worker                                                        unsigned int* R,
684*3ac0a46fSAndroid Build Coastguard Worker                                                        unsigned int* G,
685*3ac0a46fSAndroid Build Coastguard Worker                                                        unsigned int* B,
686*3ac0a46fSAndroid Build Coastguard Worker                                                        unsigned int* A) {
687*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
688*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
689*3ac0a46fSAndroid Build Coastguard Worker 
690*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict || !R || !G || !B || !A)
691*3ac0a46fSAndroid Build Coastguard Worker     return false;
692*3ac0a46fSAndroid Build Coastguard Worker 
693*3ac0a46fSAndroid Build Coastguard Worker   // For annotations with their appearance streams already defined, the path
694*3ac0a46fSAndroid Build Coastguard Worker   // stream's own color definitions take priority over the annotation color
695*3ac0a46fSAndroid Build Coastguard Worker   // definitions retrieved by this method, hence this method will simply fail.
696*3ac0a46fSAndroid Build Coastguard Worker   if (HasAPStream(pAnnotDict.Get()))
697*3ac0a46fSAndroid Build Coastguard Worker     return false;
698*3ac0a46fSAndroid Build Coastguard Worker 
699*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> pColor = pAnnotDict->GetArrayFor(
700*3ac0a46fSAndroid Build Coastguard Worker       type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C");
701*3ac0a46fSAndroid Build Coastguard Worker   *A = (pAnnotDict->KeyExist("CA") ? pAnnotDict->GetFloatFor("CA") : 1) * 255.f;
702*3ac0a46fSAndroid Build Coastguard Worker   if (!pColor) {
703*3ac0a46fSAndroid Build Coastguard Worker     // Use default color. The default colors must be consistent with the ones
704*3ac0a46fSAndroid Build Coastguard Worker     // used to generate AP. See calls to GetColorStringWithDefault() in
705*3ac0a46fSAndroid Build Coastguard Worker     // CPDF_GenerateAP::Generate*AP().
706*3ac0a46fSAndroid Build Coastguard Worker     if (pAnnotDict->GetNameFor(pdfium::annotation::kSubtype) == "Highlight") {
707*3ac0a46fSAndroid Build Coastguard Worker       *R = 255;
708*3ac0a46fSAndroid Build Coastguard Worker       *G = 255;
709*3ac0a46fSAndroid Build Coastguard Worker       *B = 0;
710*3ac0a46fSAndroid Build Coastguard Worker     } else {
711*3ac0a46fSAndroid Build Coastguard Worker       *R = 0;
712*3ac0a46fSAndroid Build Coastguard Worker       *G = 0;
713*3ac0a46fSAndroid Build Coastguard Worker       *B = 0;
714*3ac0a46fSAndroid Build Coastguard Worker     }
715*3ac0a46fSAndroid Build Coastguard Worker     return true;
716*3ac0a46fSAndroid Build Coastguard Worker   }
717*3ac0a46fSAndroid Build Coastguard Worker 
718*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color color = fpdfdoc::CFXColorFromArray(*pColor);
719*3ac0a46fSAndroid Build Coastguard Worker   switch (color.nColorType) {
720*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kRGB:
721*3ac0a46fSAndroid Build Coastguard Worker       *R = color.fColor1 * 255.f;
722*3ac0a46fSAndroid Build Coastguard Worker       *G = color.fColor2 * 255.f;
723*3ac0a46fSAndroid Build Coastguard Worker       *B = color.fColor3 * 255.f;
724*3ac0a46fSAndroid Build Coastguard Worker       break;
725*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kGray:
726*3ac0a46fSAndroid Build Coastguard Worker       *R = 255.f * color.fColor1;
727*3ac0a46fSAndroid Build Coastguard Worker       *G = 255.f * color.fColor1;
728*3ac0a46fSAndroid Build Coastguard Worker       *B = 255.f * color.fColor1;
729*3ac0a46fSAndroid Build Coastguard Worker       break;
730*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kCMYK:
731*3ac0a46fSAndroid Build Coastguard Worker       *R = 255.f * (1 - color.fColor1) * (1 - color.fColor4);
732*3ac0a46fSAndroid Build Coastguard Worker       *G = 255.f * (1 - color.fColor2) * (1 - color.fColor4);
733*3ac0a46fSAndroid Build Coastguard Worker       *B = 255.f * (1 - color.fColor3) * (1 - color.fColor4);
734*3ac0a46fSAndroid Build Coastguard Worker       break;
735*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kTransparent:
736*3ac0a46fSAndroid Build Coastguard Worker       *R = 0;
737*3ac0a46fSAndroid Build Coastguard Worker       *G = 0;
738*3ac0a46fSAndroid Build Coastguard Worker       *B = 0;
739*3ac0a46fSAndroid Build Coastguard Worker       break;
740*3ac0a46fSAndroid Build Coastguard Worker   }
741*3ac0a46fSAndroid Build Coastguard Worker   return true;
742*3ac0a46fSAndroid Build Coastguard Worker }
743*3ac0a46fSAndroid Build Coastguard Worker 
744*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_HasAttachmentPoints(FPDF_ANNOTATION annot)745*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_HasAttachmentPoints(FPDF_ANNOTATION annot) {
746*3ac0a46fSAndroid Build Coastguard Worker   if (!annot)
747*3ac0a46fSAndroid Build Coastguard Worker     return false;
748*3ac0a46fSAndroid Build Coastguard Worker 
749*3ac0a46fSAndroid Build Coastguard Worker   FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot);
750*3ac0a46fSAndroid Build Coastguard Worker   return subtype == FPDF_ANNOT_LINK || subtype == FPDF_ANNOT_HIGHLIGHT ||
751*3ac0a46fSAndroid Build Coastguard Worker          subtype == FPDF_ANNOT_UNDERLINE || subtype == FPDF_ANNOT_SQUIGGLY ||
752*3ac0a46fSAndroid Build Coastguard Worker          subtype == FPDF_ANNOT_STRIKEOUT;
753*3ac0a46fSAndroid Build Coastguard Worker }
754*3ac0a46fSAndroid Build Coastguard Worker 
755*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot,size_t quad_index,const FS_QUADPOINTSF * quad_points)756*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot,
757*3ac0a46fSAndroid Build Coastguard Worker                               size_t quad_index,
758*3ac0a46fSAndroid Build Coastguard Worker                               const FS_QUADPOINTSF* quad_points) {
759*3ac0a46fSAndroid Build Coastguard Worker   if (!FPDFAnnot_HasAttachmentPoints(annot) || !quad_points)
760*3ac0a46fSAndroid Build Coastguard Worker     return false;
761*3ac0a46fSAndroid Build Coastguard Worker 
762*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
763*3ac0a46fSAndroid Build Coastguard Worker       CPDFAnnotContextFromFPDFAnnotation(annot)->GetMutableAnnotDict();
764*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Array> pQuadPointsArray =
765*3ac0a46fSAndroid Build Coastguard Worker       GetMutableQuadPointsArrayFromDictionary(pAnnotDict.Get());
766*3ac0a46fSAndroid Build Coastguard Worker   if (!IsValidQuadPointsIndex(pQuadPointsArray.Get(), quad_index))
767*3ac0a46fSAndroid Build Coastguard Worker     return false;
768*3ac0a46fSAndroid Build Coastguard Worker 
769*3ac0a46fSAndroid Build Coastguard Worker   SetQuadPointsAtIndex(pQuadPointsArray.Get(), quad_index, quad_points);
770*3ac0a46fSAndroid Build Coastguard Worker   UpdateBBox(pAnnotDict.Get());
771*3ac0a46fSAndroid Build Coastguard Worker   return true;
772*3ac0a46fSAndroid Build Coastguard Worker }
773*3ac0a46fSAndroid Build Coastguard Worker 
774*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_AppendAttachmentPoints(FPDF_ANNOTATION annot,const FS_QUADPOINTSF * quad_points)775*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_AppendAttachmentPoints(FPDF_ANNOTATION annot,
776*3ac0a46fSAndroid Build Coastguard Worker                                  const FS_QUADPOINTSF* quad_points) {
777*3ac0a46fSAndroid Build Coastguard Worker   if (!FPDFAnnot_HasAttachmentPoints(annot) || !quad_points)
778*3ac0a46fSAndroid Build Coastguard Worker     return false;
779*3ac0a46fSAndroid Build Coastguard Worker 
780*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
781*3ac0a46fSAndroid Build Coastguard Worker       CPDFAnnotContextFromFPDFAnnotation(annot)->GetMutableAnnotDict();
782*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Array> pQuadPointsArray =
783*3ac0a46fSAndroid Build Coastguard Worker       GetMutableQuadPointsArrayFromDictionary(pAnnotDict.Get());
784*3ac0a46fSAndroid Build Coastguard Worker   if (!pQuadPointsArray)
785*3ac0a46fSAndroid Build Coastguard Worker     pQuadPointsArray = AddQuadPointsArrayToDictionary(pAnnotDict.Get());
786*3ac0a46fSAndroid Build Coastguard Worker   AppendQuadPoints(pQuadPointsArray.Get(), quad_points);
787*3ac0a46fSAndroid Build Coastguard Worker   UpdateBBox(pAnnotDict.Get());
788*3ac0a46fSAndroid Build Coastguard Worker   return true;
789*3ac0a46fSAndroid Build Coastguard Worker }
790*3ac0a46fSAndroid Build Coastguard Worker 
791*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT size_t FPDF_CALLCONV
FPDFAnnot_CountAttachmentPoints(FPDF_ANNOTATION annot)792*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_CountAttachmentPoints(FPDF_ANNOTATION annot) {
793*3ac0a46fSAndroid Build Coastguard Worker   if (!FPDFAnnot_HasAttachmentPoints(annot))
794*3ac0a46fSAndroid Build Coastguard Worker     return 0;
795*3ac0a46fSAndroid Build Coastguard Worker 
796*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict =
797*3ac0a46fSAndroid Build Coastguard Worker       CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
798*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> pArray =
799*3ac0a46fSAndroid Build Coastguard Worker       GetQuadPointsArrayFromDictionary(pAnnotDict);
800*3ac0a46fSAndroid Build Coastguard Worker   return pArray ? pArray->size() / 8 : 0;
801*3ac0a46fSAndroid Build Coastguard Worker }
802*3ac0a46fSAndroid Build Coastguard Worker 
803*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot,size_t quad_index,FS_QUADPOINTSF * quad_points)804*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot,
805*3ac0a46fSAndroid Build Coastguard Worker                               size_t quad_index,
806*3ac0a46fSAndroid Build Coastguard Worker                               FS_QUADPOINTSF* quad_points) {
807*3ac0a46fSAndroid Build Coastguard Worker   if (!FPDFAnnot_HasAttachmentPoints(annot) || !quad_points)
808*3ac0a46fSAndroid Build Coastguard Worker     return false;
809*3ac0a46fSAndroid Build Coastguard Worker 
810*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict =
811*3ac0a46fSAndroid Build Coastguard Worker       CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
812*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> pArray =
813*3ac0a46fSAndroid Build Coastguard Worker       GetQuadPointsArrayFromDictionary(pAnnotDict);
814*3ac0a46fSAndroid Build Coastguard Worker   if (!pArray)
815*3ac0a46fSAndroid Build Coastguard Worker     return false;
816*3ac0a46fSAndroid Build Coastguard Worker 
817*3ac0a46fSAndroid Build Coastguard Worker   return GetQuadPointsAtIndex(std::move(pArray), quad_index, quad_points);
818*3ac0a46fSAndroid Build Coastguard Worker }
819*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_SetRect(FPDF_ANNOTATION annot,const FS_RECTF * rect)820*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetRect(FPDF_ANNOTATION annot,
821*3ac0a46fSAndroid Build Coastguard Worker                                                       const FS_RECTF* rect) {
822*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
823*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
824*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict || !rect)
825*3ac0a46fSAndroid Build Coastguard Worker     return false;
826*3ac0a46fSAndroid Build Coastguard Worker 
827*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect newRect = CFXFloatRectFromFSRectF(*rect);
828*3ac0a46fSAndroid Build Coastguard Worker 
829*3ac0a46fSAndroid Build Coastguard Worker   // Update the "Rect" entry in the annotation dictionary.
830*3ac0a46fSAndroid Build Coastguard Worker   pAnnotDict->SetRectFor(pdfium::annotation::kRect, newRect);
831*3ac0a46fSAndroid Build Coastguard Worker 
832*3ac0a46fSAndroid Build Coastguard Worker   // If the annotation's appearance stream is defined, the annotation is of a
833*3ac0a46fSAndroid Build Coastguard Worker   // type that does not have quadpoints, and the new rectangle is bigger than
834*3ac0a46fSAndroid Build Coastguard Worker   // the current bounding box, then update the "BBox" entry in the AP
835*3ac0a46fSAndroid Build Coastguard Worker   // dictionary too, since its "BBox" entry comes from annotation dictionary's
836*3ac0a46fSAndroid Build Coastguard Worker   // "Rect" entry.
837*3ac0a46fSAndroid Build Coastguard Worker   if (FPDFAnnot_HasAttachmentPoints(annot))
838*3ac0a46fSAndroid Build Coastguard Worker     return true;
839*3ac0a46fSAndroid Build Coastguard Worker 
840*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pStream =
841*3ac0a46fSAndroid Build Coastguard Worker       GetAnnotAP(pAnnotDict.Get(), CPDF_Annot::AppearanceMode::kNormal);
842*3ac0a46fSAndroid Build Coastguard Worker   if (pStream && newRect.Contains(pStream->GetDict()->GetRectFor("BBox")))
843*3ac0a46fSAndroid Build Coastguard Worker     pStream->GetMutableDict()->SetRectFor("BBox", newRect);
844*3ac0a46fSAndroid Build Coastguard Worker   return true;
845*3ac0a46fSAndroid Build Coastguard Worker }
846*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_GetRect(FPDF_ANNOTATION annot,FS_RECTF * rect)847*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetRect(FPDF_ANNOTATION annot,
848*3ac0a46fSAndroid Build Coastguard Worker                                                       FS_RECTF* rect) {
849*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
850*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict || !rect)
851*3ac0a46fSAndroid Build Coastguard Worker     return false;
852*3ac0a46fSAndroid Build Coastguard Worker 
853*3ac0a46fSAndroid Build Coastguard Worker   *rect = FSRectFFromCFXFloatRect(
854*3ac0a46fSAndroid Build Coastguard Worker       pAnnotDict->GetRectFor(pdfium::annotation::kRect));
855*3ac0a46fSAndroid Build Coastguard Worker   return true;
856*3ac0a46fSAndroid Build Coastguard Worker }
857*3ac0a46fSAndroid Build Coastguard Worker 
858*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetVertices(FPDF_ANNOTATION annot,FS_POINTF * buffer,unsigned long length)859*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetVertices(FPDF_ANNOTATION annot,
860*3ac0a46fSAndroid Build Coastguard Worker                       FS_POINTF* buffer,
861*3ac0a46fSAndroid Build Coastguard Worker                       unsigned long length) {
862*3ac0a46fSAndroid Build Coastguard Worker   FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot);
863*3ac0a46fSAndroid Build Coastguard Worker   if (subtype != FPDF_ANNOT_POLYGON && subtype != FPDF_ANNOT_POLYLINE)
864*3ac0a46fSAndroid Build Coastguard Worker     return 0;
865*3ac0a46fSAndroid Build Coastguard Worker 
866*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* annot_dict = GetAnnotDictFromFPDFAnnotation(annot);
867*3ac0a46fSAndroid Build Coastguard Worker   if (!annot_dict)
868*3ac0a46fSAndroid Build Coastguard Worker     return 0;
869*3ac0a46fSAndroid Build Coastguard Worker 
870*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> vertices =
871*3ac0a46fSAndroid Build Coastguard Worker       annot_dict->GetArrayFor(pdfium::annotation::kVertices);
872*3ac0a46fSAndroid Build Coastguard Worker   if (!vertices)
873*3ac0a46fSAndroid Build Coastguard Worker     return 0;
874*3ac0a46fSAndroid Build Coastguard Worker 
875*3ac0a46fSAndroid Build Coastguard Worker   // Truncate to an even number.
876*3ac0a46fSAndroid Build Coastguard Worker   const unsigned long points_len =
877*3ac0a46fSAndroid Build Coastguard Worker       fxcrt::CollectionSize<unsigned long>(*vertices) / 2;
878*3ac0a46fSAndroid Build Coastguard Worker   if (buffer && length >= points_len) {
879*3ac0a46fSAndroid Build Coastguard Worker     for (unsigned long i = 0; i < points_len; ++i) {
880*3ac0a46fSAndroid Build Coastguard Worker       buffer[i].x = vertices->GetFloatAt(i * 2);
881*3ac0a46fSAndroid Build Coastguard Worker       buffer[i].y = vertices->GetFloatAt(i * 2 + 1);
882*3ac0a46fSAndroid Build Coastguard Worker     }
883*3ac0a46fSAndroid Build Coastguard Worker   }
884*3ac0a46fSAndroid Build Coastguard Worker   return points_len;
885*3ac0a46fSAndroid Build Coastguard Worker }
886*3ac0a46fSAndroid Build Coastguard Worker 
887*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetInkListCount(FPDF_ANNOTATION annot)888*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetInkListCount(FPDF_ANNOTATION annot) {
889*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> ink_list = GetInkList(annot);
890*3ac0a46fSAndroid Build Coastguard Worker   return ink_list ? fxcrt::CollectionSize<unsigned long>(*ink_list) : 0;
891*3ac0a46fSAndroid Build Coastguard Worker }
892*3ac0a46fSAndroid Build Coastguard Worker 
893*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetInkListPath(FPDF_ANNOTATION annot,unsigned long path_index,FS_POINTF * buffer,unsigned long length)894*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetInkListPath(FPDF_ANNOTATION annot,
895*3ac0a46fSAndroid Build Coastguard Worker                          unsigned long path_index,
896*3ac0a46fSAndroid Build Coastguard Worker                          FS_POINTF* buffer,
897*3ac0a46fSAndroid Build Coastguard Worker                          unsigned long length) {
898*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> ink_list = GetInkList(annot);
899*3ac0a46fSAndroid Build Coastguard Worker   if (!ink_list)
900*3ac0a46fSAndroid Build Coastguard Worker     return 0;
901*3ac0a46fSAndroid Build Coastguard Worker 
902*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> path = ink_list->GetArrayAt(path_index);
903*3ac0a46fSAndroid Build Coastguard Worker   if (!path)
904*3ac0a46fSAndroid Build Coastguard Worker     return 0;
905*3ac0a46fSAndroid Build Coastguard Worker 
906*3ac0a46fSAndroid Build Coastguard Worker   // Truncate to an even number.
907*3ac0a46fSAndroid Build Coastguard Worker   const unsigned long points_len =
908*3ac0a46fSAndroid Build Coastguard Worker       fxcrt::CollectionSize<unsigned long>(*path) / 2;
909*3ac0a46fSAndroid Build Coastguard Worker   if (buffer && length >= points_len) {
910*3ac0a46fSAndroid Build Coastguard Worker     for (unsigned long i = 0; i < points_len; ++i) {
911*3ac0a46fSAndroid Build Coastguard Worker       buffer[i].x = path->GetFloatAt(i * 2);
912*3ac0a46fSAndroid Build Coastguard Worker       buffer[i].y = path->GetFloatAt(i * 2 + 1);
913*3ac0a46fSAndroid Build Coastguard Worker     }
914*3ac0a46fSAndroid Build Coastguard Worker   }
915*3ac0a46fSAndroid Build Coastguard Worker   return points_len;
916*3ac0a46fSAndroid Build Coastguard Worker }
917*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_GetLine(FPDF_ANNOTATION annot,FS_POINTF * start,FS_POINTF * end)918*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetLine(FPDF_ANNOTATION annot,
919*3ac0a46fSAndroid Build Coastguard Worker                                                       FS_POINTF* start,
920*3ac0a46fSAndroid Build Coastguard Worker                                                       FS_POINTF* end) {
921*3ac0a46fSAndroid Build Coastguard Worker   if (!start || !end)
922*3ac0a46fSAndroid Build Coastguard Worker     return false;
923*3ac0a46fSAndroid Build Coastguard Worker 
924*3ac0a46fSAndroid Build Coastguard Worker   FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot);
925*3ac0a46fSAndroid Build Coastguard Worker   if (subtype != FPDF_ANNOT_LINE)
926*3ac0a46fSAndroid Build Coastguard Worker     return false;
927*3ac0a46fSAndroid Build Coastguard Worker 
928*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* annot_dict = GetAnnotDictFromFPDFAnnotation(annot);
929*3ac0a46fSAndroid Build Coastguard Worker   if (!annot_dict)
930*3ac0a46fSAndroid Build Coastguard Worker     return false;
931*3ac0a46fSAndroid Build Coastguard Worker 
932*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> line =
933*3ac0a46fSAndroid Build Coastguard Worker       annot_dict->GetArrayFor(pdfium::annotation::kL);
934*3ac0a46fSAndroid Build Coastguard Worker   if (!line || line->size() < 4)
935*3ac0a46fSAndroid Build Coastguard Worker     return false;
936*3ac0a46fSAndroid Build Coastguard Worker 
937*3ac0a46fSAndroid Build Coastguard Worker   start->x = line->GetFloatAt(0);
938*3ac0a46fSAndroid Build Coastguard Worker   start->y = line->GetFloatAt(1);
939*3ac0a46fSAndroid Build Coastguard Worker   end->x = line->GetFloatAt(2);
940*3ac0a46fSAndroid Build Coastguard Worker   end->y = line->GetFloatAt(3);
941*3ac0a46fSAndroid Build Coastguard Worker   return true;
942*3ac0a46fSAndroid Build Coastguard Worker }
943*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_SetBorder(FPDF_ANNOTATION annot,float horizontal_radius,float vertical_radius,float border_width)944*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetBorder(FPDF_ANNOTATION annot,
945*3ac0a46fSAndroid Build Coastguard Worker                                                         float horizontal_radius,
946*3ac0a46fSAndroid Build Coastguard Worker                                                         float vertical_radius,
947*3ac0a46fSAndroid Build Coastguard Worker                                                         float border_width) {
948*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> annot_dict =
949*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
950*3ac0a46fSAndroid Build Coastguard Worker   if (!annot_dict)
951*3ac0a46fSAndroid Build Coastguard Worker     return false;
952*3ac0a46fSAndroid Build Coastguard Worker 
953*3ac0a46fSAndroid Build Coastguard Worker   // Remove the appearance stream. Otherwise PDF viewers will render that and
954*3ac0a46fSAndroid Build Coastguard Worker   // not use the border values.
955*3ac0a46fSAndroid Build Coastguard Worker   annot_dict->RemoveFor(pdfium::annotation::kAP);
956*3ac0a46fSAndroid Build Coastguard Worker 
957*3ac0a46fSAndroid Build Coastguard Worker   auto border = annot_dict->SetNewFor<CPDF_Array>(pdfium::annotation::kBorder);
958*3ac0a46fSAndroid Build Coastguard Worker   border->AppendNew<CPDF_Number>(horizontal_radius);
959*3ac0a46fSAndroid Build Coastguard Worker   border->AppendNew<CPDF_Number>(vertical_radius);
960*3ac0a46fSAndroid Build Coastguard Worker   border->AppendNew<CPDF_Number>(border_width);
961*3ac0a46fSAndroid Build Coastguard Worker   return true;
962*3ac0a46fSAndroid Build Coastguard Worker }
963*3ac0a46fSAndroid Build Coastguard Worker 
964*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_GetBorder(FPDF_ANNOTATION annot,float * horizontal_radius,float * vertical_radius,float * border_width)965*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetBorder(FPDF_ANNOTATION annot,
966*3ac0a46fSAndroid Build Coastguard Worker                     float* horizontal_radius,
967*3ac0a46fSAndroid Build Coastguard Worker                     float* vertical_radius,
968*3ac0a46fSAndroid Build Coastguard Worker                     float* border_width) {
969*3ac0a46fSAndroid Build Coastguard Worker   if (!horizontal_radius || !vertical_radius || !border_width)
970*3ac0a46fSAndroid Build Coastguard Worker     return false;
971*3ac0a46fSAndroid Build Coastguard Worker 
972*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* annot_dict = GetAnnotDictFromFPDFAnnotation(annot);
973*3ac0a46fSAndroid Build Coastguard Worker   if (!annot_dict)
974*3ac0a46fSAndroid Build Coastguard Worker     return false;
975*3ac0a46fSAndroid Build Coastguard Worker 
976*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> border =
977*3ac0a46fSAndroid Build Coastguard Worker       annot_dict->GetArrayFor(pdfium::annotation::kBorder);
978*3ac0a46fSAndroid Build Coastguard Worker   if (!border || border->size() < 3)
979*3ac0a46fSAndroid Build Coastguard Worker     return false;
980*3ac0a46fSAndroid Build Coastguard Worker 
981*3ac0a46fSAndroid Build Coastguard Worker   *horizontal_radius = border->GetFloatAt(0);
982*3ac0a46fSAndroid Build Coastguard Worker   *vertical_radius = border->GetFloatAt(1);
983*3ac0a46fSAndroid Build Coastguard Worker   *border_width = border->GetFloatAt(2);
984*3ac0a46fSAndroid Build Coastguard Worker   return true;
985*3ac0a46fSAndroid Build Coastguard Worker }
986*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_HasKey(FPDF_ANNOTATION annot,FPDF_BYTESTRING key)987*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_HasKey(FPDF_ANNOTATION annot,
988*3ac0a46fSAndroid Build Coastguard Worker                                                      FPDF_BYTESTRING key) {
989*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
990*3ac0a46fSAndroid Build Coastguard Worker   return pAnnotDict && pAnnotDict->KeyExist(key);
991*3ac0a46fSAndroid Build Coastguard Worker }
992*3ac0a46fSAndroid Build Coastguard Worker 
993*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV
FPDFAnnot_GetValueType(FPDF_ANNOTATION annot,FPDF_BYTESTRING key)994*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetValueType(FPDF_ANNOTATION annot, FPDF_BYTESTRING key) {
995*3ac0a46fSAndroid Build Coastguard Worker   if (!FPDFAnnot_HasKey(annot, key))
996*3ac0a46fSAndroid Build Coastguard Worker     return FPDF_OBJECT_UNKNOWN;
997*3ac0a46fSAndroid Build Coastguard Worker 
998*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
999*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Object> pObj = pAnnot->GetAnnotDict()->GetObjectFor(key);
1000*3ac0a46fSAndroid Build Coastguard Worker   return pObj ? pObj->GetType() : FPDF_OBJECT_UNKNOWN;
1001*3ac0a46fSAndroid Build Coastguard Worker }
1002*3ac0a46fSAndroid Build Coastguard Worker 
1003*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_SetStringValue(FPDF_ANNOTATION annot,FPDF_BYTESTRING key,FPDF_WIDESTRING value)1004*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_SetStringValue(FPDF_ANNOTATION annot,
1005*3ac0a46fSAndroid Build Coastguard Worker                          FPDF_BYTESTRING key,
1006*3ac0a46fSAndroid Build Coastguard Worker                          FPDF_WIDESTRING value) {
1007*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
1008*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
1009*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
1010*3ac0a46fSAndroid Build Coastguard Worker     return false;
1011*3ac0a46fSAndroid Build Coastguard Worker 
1012*3ac0a46fSAndroid Build Coastguard Worker   pAnnotDict->SetNewFor<CPDF_String>(
1013*3ac0a46fSAndroid Build Coastguard Worker       key, WideStringFromFPDFWideString(value).AsStringView());
1014*3ac0a46fSAndroid Build Coastguard Worker   return true;
1015*3ac0a46fSAndroid Build Coastguard Worker }
1016*3ac0a46fSAndroid Build Coastguard Worker 
1017*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetStringValue(FPDF_ANNOTATION annot,FPDF_BYTESTRING key,FPDF_WCHAR * buffer,unsigned long buflen)1018*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetStringValue(FPDF_ANNOTATION annot,
1019*3ac0a46fSAndroid Build Coastguard Worker                          FPDF_BYTESTRING key,
1020*3ac0a46fSAndroid Build Coastguard Worker                          FPDF_WCHAR* buffer,
1021*3ac0a46fSAndroid Build Coastguard Worker                          unsigned long buflen) {
1022*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
1023*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
1024*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1025*3ac0a46fSAndroid Build Coastguard Worker 
1026*3ac0a46fSAndroid Build Coastguard Worker   return Utf16EncodeMaybeCopyAndReturnLength(pAnnotDict->GetUnicodeTextFor(key),
1027*3ac0a46fSAndroid Build Coastguard Worker                                              buffer, buflen);
1028*3ac0a46fSAndroid Build Coastguard Worker }
1029*3ac0a46fSAndroid Build Coastguard Worker 
1030*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_GetNumberValue(FPDF_ANNOTATION annot,FPDF_BYTESTRING key,float * value)1031*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetNumberValue(FPDF_ANNOTATION annot,
1032*3ac0a46fSAndroid Build Coastguard Worker                          FPDF_BYTESTRING key,
1033*3ac0a46fSAndroid Build Coastguard Worker                          float* value) {
1034*3ac0a46fSAndroid Build Coastguard Worker   if (!value)
1035*3ac0a46fSAndroid Build Coastguard Worker     return false;
1036*3ac0a46fSAndroid Build Coastguard Worker 
1037*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
1038*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
1039*3ac0a46fSAndroid Build Coastguard Worker     return false;
1040*3ac0a46fSAndroid Build Coastguard Worker 
1041*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Object> p = pAnnotDict->GetObjectFor(key);
1042*3ac0a46fSAndroid Build Coastguard Worker   if (!p || p->GetType() != FPDF_OBJECT_NUMBER)
1043*3ac0a46fSAndroid Build Coastguard Worker     return false;
1044*3ac0a46fSAndroid Build Coastguard Worker 
1045*3ac0a46fSAndroid Build Coastguard Worker   *value = p->GetNumber();
1046*3ac0a46fSAndroid Build Coastguard Worker   return true;
1047*3ac0a46fSAndroid Build Coastguard Worker }
1048*3ac0a46fSAndroid Build Coastguard Worker 
1049*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_SetAP(FPDF_ANNOTATION annot,FPDF_ANNOT_APPEARANCEMODE appearanceMode,FPDF_WIDESTRING value)1050*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_SetAP(FPDF_ANNOTATION annot,
1051*3ac0a46fSAndroid Build Coastguard Worker                 FPDF_ANNOT_APPEARANCEMODE appearanceMode,
1052*3ac0a46fSAndroid Build Coastguard Worker                 FPDF_WIDESTRING value) {
1053*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
1054*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
1055*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
1056*3ac0a46fSAndroid Build Coastguard Worker     return false;
1057*3ac0a46fSAndroid Build Coastguard Worker 
1058*3ac0a46fSAndroid Build Coastguard Worker   if (appearanceMode < 0 || appearanceMode >= FPDF_ANNOT_APPEARANCEMODE_COUNT)
1059*3ac0a46fSAndroid Build Coastguard Worker     return false;
1060*3ac0a46fSAndroid Build Coastguard Worker 
1061*3ac0a46fSAndroid Build Coastguard Worker   static constexpr const char* kModeKeyForMode[] = {"N", "R", "D"};
1062*3ac0a46fSAndroid Build Coastguard Worker   static_assert(std::size(kModeKeyForMode) == FPDF_ANNOT_APPEARANCEMODE_COUNT,
1063*3ac0a46fSAndroid Build Coastguard Worker                 "length of kModeKeyForMode should be equal to "
1064*3ac0a46fSAndroid Build Coastguard Worker                 "FPDF_ANNOT_APPEARANCEMODE_COUNT");
1065*3ac0a46fSAndroid Build Coastguard Worker   const char* modeKey = kModeKeyForMode[appearanceMode];
1066*3ac0a46fSAndroid Build Coastguard Worker 
1067*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pApDict =
1068*3ac0a46fSAndroid Build Coastguard Worker       pAnnotDict->GetMutableDictFor(pdfium::annotation::kAP);
1069*3ac0a46fSAndroid Build Coastguard Worker 
1070*3ac0a46fSAndroid Build Coastguard Worker   // If value is null, we're in remove mode. Otherwise, we're in add/update
1071*3ac0a46fSAndroid Build Coastguard Worker   // mode.
1072*3ac0a46fSAndroid Build Coastguard Worker   if (value) {
1073*3ac0a46fSAndroid Build Coastguard Worker     // Annotation object's non-empty bounding rect will be used as the /BBox
1074*3ac0a46fSAndroid Build Coastguard Worker     // for the associated /XObject object
1075*3ac0a46fSAndroid Build Coastguard Worker     CFX_FloatRect rect = pAnnotDict->GetRectFor(pdfium::annotation::kRect);
1076*3ac0a46fSAndroid Build Coastguard Worker     constexpr float kMinSize = 0.000001f;
1077*3ac0a46fSAndroid Build Coastguard Worker     if (rect.Width() < kMinSize || rect.Height() < kMinSize)
1078*3ac0a46fSAndroid Build Coastguard Worker       return false;
1079*3ac0a46fSAndroid Build Coastguard Worker 
1080*3ac0a46fSAndroid Build Coastguard Worker     CPDF_AnnotContext* pAnnotContext =
1081*3ac0a46fSAndroid Build Coastguard Worker         CPDFAnnotContextFromFPDFAnnotation(annot);
1082*3ac0a46fSAndroid Build Coastguard Worker 
1083*3ac0a46fSAndroid Build Coastguard Worker     CPDF_Document* pDoc = pAnnotContext->GetPage()->GetDocument();
1084*3ac0a46fSAndroid Build Coastguard Worker     if (!pDoc)
1085*3ac0a46fSAndroid Build Coastguard Worker       return false;
1086*3ac0a46fSAndroid Build Coastguard Worker 
1087*3ac0a46fSAndroid Build Coastguard Worker     auto pNewIndirectStream = pDoc->NewIndirect<CPDF_Stream>();
1088*3ac0a46fSAndroid Build Coastguard Worker     ByteString newAPStream =
1089*3ac0a46fSAndroid Build Coastguard Worker         PDF_EncodeText(WideStringFromFPDFWideString(value).AsStringView());
1090*3ac0a46fSAndroid Build Coastguard Worker     pNewIndirectStream->SetData(newAPStream.raw_span());
1091*3ac0a46fSAndroid Build Coastguard Worker 
1092*3ac0a46fSAndroid Build Coastguard Worker     RetainPtr<CPDF_Dictionary> pStreamDict =
1093*3ac0a46fSAndroid Build Coastguard Worker         pNewIndirectStream->GetMutableDict();
1094*3ac0a46fSAndroid Build Coastguard Worker     pStreamDict->SetNewFor<CPDF_Name>(pdfium::annotation::kType, "XObject");
1095*3ac0a46fSAndroid Build Coastguard Worker     pStreamDict->SetNewFor<CPDF_Name>(pdfium::annotation::kSubtype, "Form");
1096*3ac0a46fSAndroid Build Coastguard Worker     pStreamDict->SetRectFor("BBox", rect);
1097*3ac0a46fSAndroid Build Coastguard Worker     // Transparency values are specified in range [0.0f, 1.0f]. We are strictly
1098*3ac0a46fSAndroid Build Coastguard Worker     // checking for value < 1 and not <= 1 so that the output PDF size does not
1099*3ac0a46fSAndroid Build Coastguard Worker     // unnecessarily bloat up by creating a new dictionary in case of solid
1100*3ac0a46fSAndroid Build Coastguard Worker     // color.
1101*3ac0a46fSAndroid Build Coastguard Worker     if (pAnnotDict->KeyExist("CA") && pAnnotDict->GetFloatFor("CA") < 1.0f) {
1102*3ac0a46fSAndroid Build Coastguard Worker       RetainPtr<CPDF_Dictionary> pResourceDict =
1103*3ac0a46fSAndroid Build Coastguard Worker           SetExtGStateInResourceDict(pDoc, pAnnotDict.Get(), "Normal");
1104*3ac0a46fSAndroid Build Coastguard Worker       pStreamDict->SetFor("Resources", pResourceDict);
1105*3ac0a46fSAndroid Build Coastguard Worker     }
1106*3ac0a46fSAndroid Build Coastguard Worker 
1107*3ac0a46fSAndroid Build Coastguard Worker     // Storing reference to indirect object in annotation's AP
1108*3ac0a46fSAndroid Build Coastguard Worker     if (!pApDict) {
1109*3ac0a46fSAndroid Build Coastguard Worker       pApDict = pAnnotDict->SetNewFor<CPDF_Dictionary>(pdfium::annotation::kAP);
1110*3ac0a46fSAndroid Build Coastguard Worker     }
1111*3ac0a46fSAndroid Build Coastguard Worker     pApDict->SetNewFor<CPDF_Reference>(modeKey, pDoc,
1112*3ac0a46fSAndroid Build Coastguard Worker                                        pNewIndirectStream->GetObjNum());
1113*3ac0a46fSAndroid Build Coastguard Worker   } else {
1114*3ac0a46fSAndroid Build Coastguard Worker     if (pApDict) {
1115*3ac0a46fSAndroid Build Coastguard Worker       if (appearanceMode == FPDF_ANNOT_APPEARANCEMODE_NORMAL)
1116*3ac0a46fSAndroid Build Coastguard Worker         pAnnotDict->RemoveFor(pdfium::annotation::kAP);
1117*3ac0a46fSAndroid Build Coastguard Worker       else
1118*3ac0a46fSAndroid Build Coastguard Worker         pApDict->RemoveFor(modeKey);
1119*3ac0a46fSAndroid Build Coastguard Worker     }
1120*3ac0a46fSAndroid Build Coastguard Worker   }
1121*3ac0a46fSAndroid Build Coastguard Worker 
1122*3ac0a46fSAndroid Build Coastguard Worker   return true;
1123*3ac0a46fSAndroid Build Coastguard Worker }
1124*3ac0a46fSAndroid Build Coastguard Worker 
1125*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetAP(FPDF_ANNOTATION annot,FPDF_ANNOT_APPEARANCEMODE appearanceMode,FPDF_WCHAR * buffer,unsigned long buflen)1126*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetAP(FPDF_ANNOTATION annot,
1127*3ac0a46fSAndroid Build Coastguard Worker                 FPDF_ANNOT_APPEARANCEMODE appearanceMode,
1128*3ac0a46fSAndroid Build Coastguard Worker                 FPDF_WCHAR* buffer,
1129*3ac0a46fSAndroid Build Coastguard Worker                 unsigned long buflen) {
1130*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
1131*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
1132*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
1133*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1134*3ac0a46fSAndroid Build Coastguard Worker 
1135*3ac0a46fSAndroid Build Coastguard Worker   if (appearanceMode < 0 || appearanceMode >= FPDF_ANNOT_APPEARANCEMODE_COUNT)
1136*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1137*3ac0a46fSAndroid Build Coastguard Worker 
1138*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Annot::AppearanceMode mode =
1139*3ac0a46fSAndroid Build Coastguard Worker       static_cast<CPDF_Annot::AppearanceMode>(appearanceMode);
1140*3ac0a46fSAndroid Build Coastguard Worker 
1141*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pStream = GetAnnotAPNoFallback(pAnnotDict.Get(), mode);
1142*3ac0a46fSAndroid Build Coastguard Worker   return Utf16EncodeMaybeCopyAndReturnLength(
1143*3ac0a46fSAndroid Build Coastguard Worker       pStream ? pStream->GetUnicodeText() : WideString(), buffer, buflen);
1144*3ac0a46fSAndroid Build Coastguard Worker }
1145*3ac0a46fSAndroid Build Coastguard Worker 
1146*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
FPDFAnnot_GetLinkedAnnot(FPDF_ANNOTATION annot,FPDF_BYTESTRING key)1147*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetLinkedAnnot(FPDF_ANNOTATION annot, FPDF_BYTESTRING key) {
1148*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
1149*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnot)
1150*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
1151*3ac0a46fSAndroid Build Coastguard Worker 
1152*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pLinkedDict =
1153*3ac0a46fSAndroid Build Coastguard Worker       pAnnot->GetMutableAnnotDict()->GetMutableDictFor(key);
1154*3ac0a46fSAndroid Build Coastguard Worker   if (!pLinkedDict || pLinkedDict->GetNameFor("Type") != "Annot")
1155*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
1156*3ac0a46fSAndroid Build Coastguard Worker 
1157*3ac0a46fSAndroid Build Coastguard Worker   auto pLinkedAnnot = std::make_unique<CPDF_AnnotContext>(
1158*3ac0a46fSAndroid Build Coastguard Worker       std::move(pLinkedDict), pAnnot->GetPage());
1159*3ac0a46fSAndroid Build Coastguard Worker 
1160*3ac0a46fSAndroid Build Coastguard Worker   // Caller takes ownership.
1161*3ac0a46fSAndroid Build Coastguard Worker   return FPDFAnnotationFromCPDFAnnotContext(pLinkedAnnot.release());
1162*3ac0a46fSAndroid Build Coastguard Worker }
1163*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_GetFlags(FPDF_ANNOTATION annot)1164*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetFlags(FPDF_ANNOTATION annot) {
1165*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
1166*3ac0a46fSAndroid Build Coastguard Worker   return pAnnotDict ? pAnnotDict->GetIntegerFor(pdfium::annotation::kF)
1167*3ac0a46fSAndroid Build Coastguard Worker                     : FPDF_ANNOT_FLAG_NONE;
1168*3ac0a46fSAndroid Build Coastguard Worker }
1169*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_SetFlags(FPDF_ANNOTATION annot,int flags)1170*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetFlags(FPDF_ANNOTATION annot,
1171*3ac0a46fSAndroid Build Coastguard Worker                                                        int flags) {
1172*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pAnnotDict =
1173*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
1174*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
1175*3ac0a46fSAndroid Build Coastguard Worker     return false;
1176*3ac0a46fSAndroid Build Coastguard Worker 
1177*3ac0a46fSAndroid Build Coastguard Worker   pAnnotDict->SetNewFor<CPDF_Number>(pdfium::annotation::kF, flags);
1178*3ac0a46fSAndroid Build Coastguard Worker   return true;
1179*3ac0a46fSAndroid Build Coastguard Worker }
1180*3ac0a46fSAndroid Build Coastguard Worker 
1181*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFAnnot_GetFormFieldFlags(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot)1182*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldFlags(FPDF_FORMHANDLE hHandle, FPDF_ANNOTATION annot) {
1183*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1184*3ac0a46fSAndroid Build Coastguard Worker   return pFormField ? pFormField->GetFieldFlags() : FPDF_FORMFLAG_NONE;
1185*3ac0a46fSAndroid Build Coastguard Worker }
1186*3ac0a46fSAndroid Build Coastguard Worker 
1187*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
FPDFAnnot_GetFormFieldAtPoint(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,const FS_POINTF * point)1188*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
1189*3ac0a46fSAndroid Build Coastguard Worker                               FPDF_PAGE page,
1190*3ac0a46fSAndroid Build Coastguard Worker                               const FS_POINTF* point) {
1191*3ac0a46fSAndroid Build Coastguard Worker   if (!point)
1192*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
1193*3ac0a46fSAndroid Build Coastguard Worker 
1194*3ac0a46fSAndroid Build Coastguard Worker   const CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
1195*3ac0a46fSAndroid Build Coastguard Worker   if (!pForm)
1196*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
1197*3ac0a46fSAndroid Build Coastguard Worker 
1198*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
1199*3ac0a46fSAndroid Build Coastguard Worker   if (!pPage)
1200*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
1201*3ac0a46fSAndroid Build Coastguard Worker 
1202*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
1203*3ac0a46fSAndroid Build Coastguard Worker   int annot_index = -1;
1204*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormControl* pFormCtrl = pPDFForm->GetControlAtPoint(
1205*3ac0a46fSAndroid Build Coastguard Worker       pPage, CFXPointFFromFSPointF(*point), &annot_index);
1206*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormCtrl || annot_index == -1)
1207*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
1208*3ac0a46fSAndroid Build Coastguard Worker   return FPDFPage_GetAnnot(page, annot_index);
1209*3ac0a46fSAndroid Build Coastguard Worker }
1210*3ac0a46fSAndroid Build Coastguard Worker 
1211*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetFormFieldName(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot,FPDF_WCHAR * buffer,unsigned long buflen)1212*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldName(FPDF_FORMHANDLE hHandle,
1213*3ac0a46fSAndroid Build Coastguard Worker                            FPDF_ANNOTATION annot,
1214*3ac0a46fSAndroid Build Coastguard Worker                            FPDF_WCHAR* buffer,
1215*3ac0a46fSAndroid Build Coastguard Worker                            unsigned long buflen) {
1216*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1217*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormField)
1218*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1219*3ac0a46fSAndroid Build Coastguard Worker   return Utf16EncodeMaybeCopyAndReturnLength(pFormField->GetFullName(), buffer,
1220*3ac0a46fSAndroid Build Coastguard Worker                                              buflen);
1221*3ac0a46fSAndroid Build Coastguard Worker }
1222*3ac0a46fSAndroid Build Coastguard Worker 
1223*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFAnnot_GetFormFieldType(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot)1224*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldType(FPDF_FORMHANDLE hHandle, FPDF_ANNOTATION annot) {
1225*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1226*3ac0a46fSAndroid Build Coastguard Worker   return pFormField ? static_cast<int>(pFormField->GetFieldType()) : -1;
1227*3ac0a46fSAndroid Build Coastguard Worker }
1228*3ac0a46fSAndroid Build Coastguard Worker 
1229*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetFormAdditionalActionJavaScript(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot,int event,FPDF_WCHAR * buffer,unsigned long buflen)1230*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormAdditionalActionJavaScript(FPDF_FORMHANDLE hHandle,
1231*3ac0a46fSAndroid Build Coastguard Worker                                             FPDF_ANNOTATION annot,
1232*3ac0a46fSAndroid Build Coastguard Worker                                             int event,
1233*3ac0a46fSAndroid Build Coastguard Worker                                             FPDF_WCHAR* buffer,
1234*3ac0a46fSAndroid Build Coastguard Worker                                             unsigned long buflen) {
1235*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1236*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormField)
1237*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1238*3ac0a46fSAndroid Build Coastguard Worker 
1239*3ac0a46fSAndroid Build Coastguard Worker   if (event < FPDF_ANNOT_AACTION_KEY_STROKE ||
1240*3ac0a46fSAndroid Build Coastguard Worker       event > FPDF_ANNOT_AACTION_CALCULATE) {
1241*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1242*3ac0a46fSAndroid Build Coastguard Worker   }
1243*3ac0a46fSAndroid Build Coastguard Worker 
1244*3ac0a46fSAndroid Build Coastguard Worker   auto type = static_cast<CPDF_AAction::AActionType>(event);
1245*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AAction additional_action = pFormField->GetAdditionalAction();
1246*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Action action = additional_action.GetAction(type);
1247*3ac0a46fSAndroid Build Coastguard Worker   return Utf16EncodeMaybeCopyAndReturnLength(action.GetJavaScript(), buffer,
1248*3ac0a46fSAndroid Build Coastguard Worker                                              buflen);
1249*3ac0a46fSAndroid Build Coastguard Worker }
1250*3ac0a46fSAndroid Build Coastguard Worker 
1251*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetFormFieldAlternateName(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot,FPDF_WCHAR * buffer,unsigned long buflen)1252*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldAlternateName(FPDF_FORMHANDLE hHandle,
1253*3ac0a46fSAndroid Build Coastguard Worker                                     FPDF_ANNOTATION annot,
1254*3ac0a46fSAndroid Build Coastguard Worker                                     FPDF_WCHAR* buffer,
1255*3ac0a46fSAndroid Build Coastguard Worker                                     unsigned long buflen) {
1256*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1257*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormField)
1258*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1259*3ac0a46fSAndroid Build Coastguard Worker 
1260*3ac0a46fSAndroid Build Coastguard Worker   return Utf16EncodeMaybeCopyAndReturnLength(pFormField->GetAlternateName(),
1261*3ac0a46fSAndroid Build Coastguard Worker                                              buffer, buflen);
1262*3ac0a46fSAndroid Build Coastguard Worker }
1263*3ac0a46fSAndroid Build Coastguard Worker 
1264*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetFormFieldValue(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot,FPDF_WCHAR * buffer,unsigned long buflen)1265*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldValue(FPDF_FORMHANDLE hHandle,
1266*3ac0a46fSAndroid Build Coastguard Worker                             FPDF_ANNOTATION annot,
1267*3ac0a46fSAndroid Build Coastguard Worker                             FPDF_WCHAR* buffer,
1268*3ac0a46fSAndroid Build Coastguard Worker                             unsigned long buflen) {
1269*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1270*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormField)
1271*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1272*3ac0a46fSAndroid Build Coastguard Worker   return Utf16EncodeMaybeCopyAndReturnLength(pFormField->GetValue(), buffer,
1273*3ac0a46fSAndroid Build Coastguard Worker                                              buflen);
1274*3ac0a46fSAndroid Build Coastguard Worker }
1275*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_GetOptionCount(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot)1276*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetOptionCount(FPDF_FORMHANDLE hHandle,
1277*3ac0a46fSAndroid Build Coastguard Worker                                                        FPDF_ANNOTATION annot) {
1278*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1279*3ac0a46fSAndroid Build Coastguard Worker   return pFormField ? pFormField->CountOptions() : -1;
1280*3ac0a46fSAndroid Build Coastguard Worker }
1281*3ac0a46fSAndroid Build Coastguard Worker 
1282*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetOptionLabel(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot,int index,FPDF_WCHAR * buffer,unsigned long buflen)1283*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetOptionLabel(FPDF_FORMHANDLE hHandle,
1284*3ac0a46fSAndroid Build Coastguard Worker                          FPDF_ANNOTATION annot,
1285*3ac0a46fSAndroid Build Coastguard Worker                          int index,
1286*3ac0a46fSAndroid Build Coastguard Worker                          FPDF_WCHAR* buffer,
1287*3ac0a46fSAndroid Build Coastguard Worker                          unsigned long buflen) {
1288*3ac0a46fSAndroid Build Coastguard Worker   if (index < 0)
1289*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1290*3ac0a46fSAndroid Build Coastguard Worker 
1291*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1292*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormField || index >= pFormField->CountOptions())
1293*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1294*3ac0a46fSAndroid Build Coastguard Worker 
1295*3ac0a46fSAndroid Build Coastguard Worker   WideString ws = pFormField->GetOptionLabel(index);
1296*3ac0a46fSAndroid Build Coastguard Worker   return Utf16EncodeMaybeCopyAndReturnLength(ws, buffer, buflen);
1297*3ac0a46fSAndroid Build Coastguard Worker }
1298*3ac0a46fSAndroid Build Coastguard Worker 
1299*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_IsOptionSelected(FPDF_FORMHANDLE handle,FPDF_ANNOTATION annot,int index)1300*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_IsOptionSelected(FPDF_FORMHANDLE handle,
1301*3ac0a46fSAndroid Build Coastguard Worker                            FPDF_ANNOTATION annot,
1302*3ac0a46fSAndroid Build Coastguard Worker                            int index) {
1303*3ac0a46fSAndroid Build Coastguard Worker   if (index < 0)
1304*3ac0a46fSAndroid Build Coastguard Worker     return false;
1305*3ac0a46fSAndroid Build Coastguard Worker 
1306*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_FormField* form_field = GetFormField(handle, annot);
1307*3ac0a46fSAndroid Build Coastguard Worker   if (!form_field || index >= form_field->CountOptions())
1308*3ac0a46fSAndroid Build Coastguard Worker     return false;
1309*3ac0a46fSAndroid Build Coastguard Worker 
1310*3ac0a46fSAndroid Build Coastguard Worker   if (form_field->GetFieldType() != FormFieldType::kComboBox &&
1311*3ac0a46fSAndroid Build Coastguard Worker       form_field->GetFieldType() != FormFieldType::kListBox) {
1312*3ac0a46fSAndroid Build Coastguard Worker     return false;
1313*3ac0a46fSAndroid Build Coastguard Worker   }
1314*3ac0a46fSAndroid Build Coastguard Worker 
1315*3ac0a46fSAndroid Build Coastguard Worker   return form_field->IsItemSelected(index);
1316*3ac0a46fSAndroid Build Coastguard Worker }
1317*3ac0a46fSAndroid Build Coastguard Worker 
1318*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_GetFontSize(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot,float * value)1319*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFontSize(FPDF_FORMHANDLE hHandle,
1320*3ac0a46fSAndroid Build Coastguard Worker                       FPDF_ANNOTATION annot,
1321*3ac0a46fSAndroid Build Coastguard Worker                       float* value) {
1322*3ac0a46fSAndroid Build Coastguard Worker   if (!value)
1323*3ac0a46fSAndroid Build Coastguard Worker     return false;
1324*3ac0a46fSAndroid Build Coastguard Worker 
1325*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
1326*3ac0a46fSAndroid Build Coastguard Worker   if (!pForm)
1327*3ac0a46fSAndroid Build Coastguard Worker     return false;
1328*3ac0a46fSAndroid Build Coastguard Worker 
1329*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
1330*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
1331*3ac0a46fSAndroid Build Coastguard Worker     return false;
1332*3ac0a46fSAndroid Build Coastguard Worker 
1333*3ac0a46fSAndroid Build Coastguard Worker   CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
1334*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pFormControl = pPDFForm->GetControlByDict(pAnnotDict);
1335*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormControl)
1336*3ac0a46fSAndroid Build Coastguard Worker     return false;
1337*3ac0a46fSAndroid Build Coastguard Worker 
1338*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl);
1339*3ac0a46fSAndroid Build Coastguard Worker   if (!pWidget)
1340*3ac0a46fSAndroid Build Coastguard Worker     return false;
1341*3ac0a46fSAndroid Build Coastguard Worker 
1342*3ac0a46fSAndroid Build Coastguard Worker   *value = pWidget->GetFontSize();
1343*3ac0a46fSAndroid Build Coastguard Worker   return true;
1344*3ac0a46fSAndroid Build Coastguard Worker }
1345*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_IsChecked(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot)1346*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_IsChecked(FPDF_FORMHANDLE hHandle,
1347*3ac0a46fSAndroid Build Coastguard Worker                                                         FPDF_ANNOTATION annot) {
1348*3ac0a46fSAndroid Build Coastguard Worker   const CPDFSDK_Widget* pWidget =
1349*3ac0a46fSAndroid Build Coastguard Worker       GetRadioButtonOrCheckBoxWidget(hHandle, annot);
1350*3ac0a46fSAndroid Build Coastguard Worker   return pWidget && pWidget->IsChecked();
1351*3ac0a46fSAndroid Build Coastguard Worker }
1352*3ac0a46fSAndroid Build Coastguard Worker 
1353*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_SetFocusableSubtypes(FPDF_FORMHANDLE hHandle,const FPDF_ANNOTATION_SUBTYPE * subtypes,size_t count)1354*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_SetFocusableSubtypes(FPDF_FORMHANDLE hHandle,
1355*3ac0a46fSAndroid Build Coastguard Worker                                const FPDF_ANNOTATION_SUBTYPE* subtypes,
1356*3ac0a46fSAndroid Build Coastguard Worker                                size_t count) {
1357*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_FormFillEnvironment* pFormFillEnv =
1358*3ac0a46fSAndroid Build Coastguard Worker       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
1359*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormFillEnv)
1360*3ac0a46fSAndroid Build Coastguard Worker     return false;
1361*3ac0a46fSAndroid Build Coastguard Worker 
1362*3ac0a46fSAndroid Build Coastguard Worker   if (count > 0 && !subtypes)
1363*3ac0a46fSAndroid Build Coastguard Worker     return false;
1364*3ac0a46fSAndroid Build Coastguard Worker 
1365*3ac0a46fSAndroid Build Coastguard Worker   std::vector<CPDF_Annot::Subtype> focusable_annot_types;
1366*3ac0a46fSAndroid Build Coastguard Worker   focusable_annot_types.reserve(count);
1367*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < count; ++i) {
1368*3ac0a46fSAndroid Build Coastguard Worker     focusable_annot_types.push_back(
1369*3ac0a46fSAndroid Build Coastguard Worker         static_cast<CPDF_Annot::Subtype>(subtypes[i]));
1370*3ac0a46fSAndroid Build Coastguard Worker   }
1371*3ac0a46fSAndroid Build Coastguard Worker 
1372*3ac0a46fSAndroid Build Coastguard Worker   pFormFillEnv->SetFocusableAnnotSubtypes(focusable_annot_types);
1373*3ac0a46fSAndroid Build Coastguard Worker   return true;
1374*3ac0a46fSAndroid Build Coastguard Worker }
1375*3ac0a46fSAndroid Build Coastguard Worker 
1376*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFAnnot_GetFocusableSubtypesCount(FPDF_FORMHANDLE hHandle)1377*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFocusableSubtypesCount(FPDF_FORMHANDLE hHandle) {
1378*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_FormFillEnvironment* pFormFillEnv =
1379*3ac0a46fSAndroid Build Coastguard Worker       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
1380*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormFillEnv)
1381*3ac0a46fSAndroid Build Coastguard Worker     return -1;
1382*3ac0a46fSAndroid Build Coastguard Worker 
1383*3ac0a46fSAndroid Build Coastguard Worker   return fxcrt::CollectionSize<int>(pFormFillEnv->GetFocusableAnnotSubtypes());
1384*3ac0a46fSAndroid Build Coastguard Worker }
1385*3ac0a46fSAndroid Build Coastguard Worker 
1386*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFAnnot_GetFocusableSubtypes(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION_SUBTYPE * subtypes,size_t count)1387*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFocusableSubtypes(FPDF_FORMHANDLE hHandle,
1388*3ac0a46fSAndroid Build Coastguard Worker                                FPDF_ANNOTATION_SUBTYPE* subtypes,
1389*3ac0a46fSAndroid Build Coastguard Worker                                size_t count) {
1390*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_FormFillEnvironment* pFormFillEnv =
1391*3ac0a46fSAndroid Build Coastguard Worker       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
1392*3ac0a46fSAndroid Build Coastguard Worker   if (!pFormFillEnv)
1393*3ac0a46fSAndroid Build Coastguard Worker     return false;
1394*3ac0a46fSAndroid Build Coastguard Worker 
1395*3ac0a46fSAndroid Build Coastguard Worker   if (!subtypes)
1396*3ac0a46fSAndroid Build Coastguard Worker     return false;
1397*3ac0a46fSAndroid Build Coastguard Worker 
1398*3ac0a46fSAndroid Build Coastguard Worker   const std::vector<CPDF_Annot::Subtype>& focusable_annot_types =
1399*3ac0a46fSAndroid Build Coastguard Worker       pFormFillEnv->GetFocusableAnnotSubtypes();
1400*3ac0a46fSAndroid Build Coastguard Worker 
1401*3ac0a46fSAndroid Build Coastguard Worker   // Host should allocate enough memory to get the list of currently supported
1402*3ac0a46fSAndroid Build Coastguard Worker   // focusable subtypes.
1403*3ac0a46fSAndroid Build Coastguard Worker   if (count < focusable_annot_types.size())
1404*3ac0a46fSAndroid Build Coastguard Worker     return false;
1405*3ac0a46fSAndroid Build Coastguard Worker 
1406*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < focusable_annot_types.size(); ++i) {
1407*3ac0a46fSAndroid Build Coastguard Worker     subtypes[i] =
1408*3ac0a46fSAndroid Build Coastguard Worker         static_cast<FPDF_ANNOTATION_SUBTYPE>(focusable_annot_types[i]);
1409*3ac0a46fSAndroid Build Coastguard Worker   }
1410*3ac0a46fSAndroid Build Coastguard Worker 
1411*3ac0a46fSAndroid Build Coastguard Worker   return true;
1412*3ac0a46fSAndroid Build Coastguard Worker }
1413*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_GetLink(FPDF_ANNOTATION annot)1414*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_LINK FPDF_CALLCONV FPDFAnnot_GetLink(FPDF_ANNOTATION annot) {
1415*3ac0a46fSAndroid Build Coastguard Worker   if (FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_LINK)
1416*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
1417*3ac0a46fSAndroid Build Coastguard Worker 
1418*3ac0a46fSAndroid Build Coastguard Worker   // Unretained reference in public API. NOLINTNEXTLINE
1419*3ac0a46fSAndroid Build Coastguard Worker   return FPDFLinkFromCPDFDictionary(
1420*3ac0a46fSAndroid Build Coastguard Worker       CPDFAnnotContextFromFPDFAnnotation(annot)->GetMutableAnnotDict());
1421*3ac0a46fSAndroid Build Coastguard Worker }
1422*3ac0a46fSAndroid Build Coastguard Worker 
1423*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFAnnot_GetFormControlCount(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot)1424*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormControlCount(FPDF_FORMHANDLE hHandle, FPDF_ANNOTATION annot) {
1425*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormField* pFormField = GetFormField(hHandle, annot);
1426*3ac0a46fSAndroid Build Coastguard Worker   return pFormField ? pFormField->CountControls() : -1;
1427*3ac0a46fSAndroid Build Coastguard Worker }
1428*3ac0a46fSAndroid Build Coastguard Worker 
1429*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFAnnot_GetFormControlIndex(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot)1430*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormControlIndex(FPDF_FORMHANDLE hHandle, FPDF_ANNOTATION annot) {
1431*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
1432*3ac0a46fSAndroid Build Coastguard Worker   if (!pAnnotDict)
1433*3ac0a46fSAndroid Build Coastguard Worker     return -1;
1434*3ac0a46fSAndroid Build Coastguard Worker 
1435*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
1436*3ac0a46fSAndroid Build Coastguard Worker   if (!pForm)
1437*3ac0a46fSAndroid Build Coastguard Worker     return -1;
1438*3ac0a46fSAndroid Build Coastguard Worker 
1439*3ac0a46fSAndroid Build Coastguard Worker   CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
1440*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormField* pFormField = pPDFForm->GetFieldByDict(pAnnotDict);
1441*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pFormControl = pPDFForm->GetControlByDict(pAnnotDict);
1442*3ac0a46fSAndroid Build Coastguard Worker   return pFormField ? pFormField->GetControlIndex(pFormControl) : -1;
1443*3ac0a46fSAndroid Build Coastguard Worker }
1444*3ac0a46fSAndroid Build Coastguard Worker 
1445*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAnnot_GetFormFieldExportValue(FPDF_FORMHANDLE hHandle,FPDF_ANNOTATION annot,FPDF_WCHAR * buffer,unsigned long buflen)1446*3ac0a46fSAndroid Build Coastguard Worker FPDFAnnot_GetFormFieldExportValue(FPDF_FORMHANDLE hHandle,
1447*3ac0a46fSAndroid Build Coastguard Worker                                   FPDF_ANNOTATION annot,
1448*3ac0a46fSAndroid Build Coastguard Worker                                   FPDF_WCHAR* buffer,
1449*3ac0a46fSAndroid Build Coastguard Worker                                   unsigned long buflen) {
1450*3ac0a46fSAndroid Build Coastguard Worker   const CPDFSDK_Widget* pWidget =
1451*3ac0a46fSAndroid Build Coastguard Worker       GetRadioButtonOrCheckBoxWidget(hHandle, annot);
1452*3ac0a46fSAndroid Build Coastguard Worker   if (!pWidget)
1453*3ac0a46fSAndroid Build Coastguard Worker     return 0;
1454*3ac0a46fSAndroid Build Coastguard Worker 
1455*3ac0a46fSAndroid Build Coastguard Worker   return Utf16EncodeMaybeCopyAndReturnLength(pWidget->GetExportValue(), buffer,
1456*3ac0a46fSAndroid Build Coastguard Worker                                              buflen);
1457*3ac0a46fSAndroid Build Coastguard Worker }
1458*3ac0a46fSAndroid Build Coastguard Worker 
FPDFAnnot_SetURI(FPDF_ANNOTATION annot,const char * uri)1459*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetURI(FPDF_ANNOTATION annot,
1460*3ac0a46fSAndroid Build Coastguard Worker                                                      const char* uri) {
1461*3ac0a46fSAndroid Build Coastguard Worker   if (!uri || FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_LINK)
1462*3ac0a46fSAndroid Build Coastguard Worker     return false;
1463*3ac0a46fSAndroid Build Coastguard Worker 
1464*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> annot_dict =
1465*3ac0a46fSAndroid Build Coastguard Worker       GetMutableAnnotDictFromFPDFAnnotation(annot);
1466*3ac0a46fSAndroid Build Coastguard Worker   auto action = annot_dict->SetNewFor<CPDF_Dictionary>("A");
1467*3ac0a46fSAndroid Build Coastguard Worker   action->SetNewFor<CPDF_Name>("Type", "Action");
1468*3ac0a46fSAndroid Build Coastguard Worker   action->SetNewFor<CPDF_Name>("S", "URI");
1469*3ac0a46fSAndroid Build Coastguard Worker   action->SetNewFor<CPDF_String>("URI", uri, /*bHex=*/false);
1470*3ac0a46fSAndroid Build Coastguard Worker   return true;
1471*3ac0a46fSAndroid Build Coastguard Worker }
1472