Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 1 | // Copyright 2017 PDFium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 5 | #include "public/fpdf_annot.h" |
| 6 | |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 7 | #include <memory> |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 8 | #include <utility> |
| 9 | |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 10 | #include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h" |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 11 | #include "core/fpdfapi/page/cpdf_form.h" |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 12 | #include "core/fpdfapi/page/cpdf_page.h" |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 13 | #include "core/fpdfapi/page/cpdf_pageobject.h" |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 14 | #include "core/fpdfapi/parser/cpdf_array.h" |
| 15 | #include "core/fpdfapi/parser/cpdf_dictionary.h" |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 16 | #include "core/fpdfapi/parser/cpdf_document.h" |
| 17 | #include "core/fpdfapi/parser/cpdf_name.h" |
| 18 | #include "core/fpdfapi/parser/cpdf_number.h" |
| 19 | #include "core/fpdfapi/parser/cpdf_string.h" |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 20 | #include "core/fpdfdoc/cpdf_annot.h" |
Diana Gage | 7e0c05d | 2017-07-19 17:33:33 -0700 | [diff] [blame] | 21 | #include "core/fpdfdoc/cpdf_formfield.h" |
Lei Zhang | c345065 | 2018-10-11 16:54:42 +0000 | [diff] [blame] | 22 | #include "core/fpdfdoc/cpdf_interactiveform.h" |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 23 | #include "core/fpdfdoc/cpvt_generateap.h" |
Dan Sinclair | 8e7f932 | 2017-10-16 11:35:42 -0400 | [diff] [blame] | 24 | #include "core/fxge/cfx_color.h" |
Tom Sepez | 525147a | 2018-05-03 17:19:53 +0000 | [diff] [blame] | 25 | #include "fpdfsdk/cpdf_annotcontext.h" |
Dan Sinclair | 00d47a6 | 2018-03-28 18:39:04 +0000 | [diff] [blame] | 26 | #include "fpdfsdk/cpdfsdk_helpers.h" |
Lei Zhang | 99f5bbb | 2018-10-09 21:31:28 +0000 | [diff] [blame] | 27 | #include "third_party/base/ptr_util.h" |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 28 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 29 | namespace { |
| 30 | |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 31 | // These checks ensure the consistency of annotation subtype values across core/ |
| 32 | // and public. |
| 33 | static_assert(static_cast<int>(CPDF_Annot::Subtype::UNKNOWN) == |
| 34 | FPDF_ANNOT_UNKNOWN, |
| 35 | "CPDF_Annot::UNKNOWN value mismatch"); |
| 36 | static_assert(static_cast<int>(CPDF_Annot::Subtype::TEXT) == FPDF_ANNOT_TEXT, |
| 37 | "CPDF_Annot::TEXT value mismatch"); |
| 38 | static_assert(static_cast<int>(CPDF_Annot::Subtype::LINK) == FPDF_ANNOT_LINK, |
| 39 | "CPDF_Annot::LINK value mismatch"); |
| 40 | static_assert(static_cast<int>(CPDF_Annot::Subtype::FREETEXT) == |
| 41 | FPDF_ANNOT_FREETEXT, |
| 42 | "CPDF_Annot::FREETEXT value mismatch"); |
| 43 | static_assert(static_cast<int>(CPDF_Annot::Subtype::LINE) == FPDF_ANNOT_LINE, |
| 44 | "CPDF_Annot::LINE value mismatch"); |
| 45 | static_assert(static_cast<int>(CPDF_Annot::Subtype::SQUARE) == |
| 46 | FPDF_ANNOT_SQUARE, |
| 47 | "CPDF_Annot::SQUARE value mismatch"); |
| 48 | static_assert(static_cast<int>(CPDF_Annot::Subtype::CIRCLE) == |
| 49 | FPDF_ANNOT_CIRCLE, |
| 50 | "CPDF_Annot::CIRCLE value mismatch"); |
| 51 | static_assert(static_cast<int>(CPDF_Annot::Subtype::POLYGON) == |
| 52 | FPDF_ANNOT_POLYGON, |
| 53 | "CPDF_Annot::POLYGON value mismatch"); |
| 54 | static_assert(static_cast<int>(CPDF_Annot::Subtype::POLYLINE) == |
| 55 | FPDF_ANNOT_POLYLINE, |
| 56 | "CPDF_Annot::POLYLINE value mismatch"); |
| 57 | static_assert(static_cast<int>(CPDF_Annot::Subtype::HIGHLIGHT) == |
| 58 | FPDF_ANNOT_HIGHLIGHT, |
| 59 | "CPDF_Annot::HIGHLIGHT value mismatch"); |
| 60 | static_assert(static_cast<int>(CPDF_Annot::Subtype::UNDERLINE) == |
| 61 | FPDF_ANNOT_UNDERLINE, |
| 62 | "CPDF_Annot::UNDERLINE value mismatch"); |
| 63 | static_assert(static_cast<int>(CPDF_Annot::Subtype::SQUIGGLY) == |
| 64 | FPDF_ANNOT_SQUIGGLY, |
| 65 | "CPDF_Annot::SQUIGGLY value mismatch"); |
| 66 | static_assert(static_cast<int>(CPDF_Annot::Subtype::STRIKEOUT) == |
| 67 | FPDF_ANNOT_STRIKEOUT, |
| 68 | "CPDF_Annot::STRIKEOUT value mismatch"); |
| 69 | static_assert(static_cast<int>(CPDF_Annot::Subtype::STAMP) == FPDF_ANNOT_STAMP, |
| 70 | "CPDF_Annot::STAMP value mismatch"); |
| 71 | static_assert(static_cast<int>(CPDF_Annot::Subtype::CARET) == FPDF_ANNOT_CARET, |
| 72 | "CPDF_Annot::CARET value mismatch"); |
| 73 | static_assert(static_cast<int>(CPDF_Annot::Subtype::INK) == FPDF_ANNOT_INK, |
| 74 | "CPDF_Annot::INK value mismatch"); |
| 75 | static_assert(static_cast<int>(CPDF_Annot::Subtype::POPUP) == FPDF_ANNOT_POPUP, |
| 76 | "CPDF_Annot::POPUP value mismatch"); |
| 77 | static_assert(static_cast<int>(CPDF_Annot::Subtype::FILEATTACHMENT) == |
| 78 | FPDF_ANNOT_FILEATTACHMENT, |
| 79 | "CPDF_Annot::FILEATTACHMENT value mismatch"); |
| 80 | static_assert(static_cast<int>(CPDF_Annot::Subtype::SOUND) == FPDF_ANNOT_SOUND, |
| 81 | "CPDF_Annot::SOUND value mismatch"); |
| 82 | static_assert(static_cast<int>(CPDF_Annot::Subtype::MOVIE) == FPDF_ANNOT_MOVIE, |
| 83 | "CPDF_Annot::MOVIE value mismatch"); |
| 84 | static_assert(static_cast<int>(CPDF_Annot::Subtype::WIDGET) == |
| 85 | FPDF_ANNOT_WIDGET, |
| 86 | "CPDF_Annot::WIDGET value mismatch"); |
| 87 | static_assert(static_cast<int>(CPDF_Annot::Subtype::SCREEN) == |
| 88 | FPDF_ANNOT_SCREEN, |
| 89 | "CPDF_Annot::SCREEN value mismatch"); |
| 90 | static_assert(static_cast<int>(CPDF_Annot::Subtype::PRINTERMARK) == |
| 91 | FPDF_ANNOT_PRINTERMARK, |
| 92 | "CPDF_Annot::PRINTERMARK value mismatch"); |
| 93 | static_assert(static_cast<int>(CPDF_Annot::Subtype::TRAPNET) == |
| 94 | FPDF_ANNOT_TRAPNET, |
| 95 | "CPDF_Annot::TRAPNET value mismatch"); |
| 96 | static_assert(static_cast<int>(CPDF_Annot::Subtype::WATERMARK) == |
| 97 | FPDF_ANNOT_WATERMARK, |
| 98 | "CPDF_Annot::WATERMARK value mismatch"); |
| 99 | static_assert(static_cast<int>(CPDF_Annot::Subtype::THREED) == |
| 100 | FPDF_ANNOT_THREED, |
| 101 | "CPDF_Annot::THREED value mismatch"); |
| 102 | static_assert(static_cast<int>(CPDF_Annot::Subtype::RICHMEDIA) == |
| 103 | FPDF_ANNOT_RICHMEDIA, |
| 104 | "CPDF_Annot::RICHMEDIA value mismatch"); |
| 105 | static_assert(static_cast<int>(CPDF_Annot::Subtype::XFAWIDGET) == |
| 106 | FPDF_ANNOT_XFAWIDGET, |
| 107 | "CPDF_Annot::XFAWIDGET value mismatch"); |
| 108 | |
Henrique Nakashima | a74e75d | 2018-01-10 18:06:55 +0000 | [diff] [blame] | 109 | // These checks ensure the consistency of annotation appearance mode values |
| 110 | // across core/ and public. |
| 111 | static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::Normal) == |
| 112 | FPDF_ANNOT_APPEARANCEMODE_NORMAL, |
| 113 | "CPDF_Annot::AppearanceMode::Normal value mismatch"); |
| 114 | static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::Rollover) == |
| 115 | FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, |
| 116 | "CPDF_Annot::AppearanceMode::Rollover value mismatch"); |
| 117 | static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::Down) == |
| 118 | FPDF_ANNOT_APPEARANCEMODE_DOWN, |
| 119 | "CPDF_Annot::AppearanceMode::Down value mismatch"); |
| 120 | |
Jane Liu | 2e1a32b | 2017-07-06 12:01:25 -0400 | [diff] [blame] | 121 | // These checks ensure the consistency of dictionary value types across core/ |
| 122 | // and public/. |
| 123 | static_assert(static_cast<int>(CPDF_Object::Type::BOOLEAN) == |
| 124 | FPDF_OBJECT_BOOLEAN, |
| 125 | "CPDF_Object::BOOLEAN value mismatch"); |
| 126 | static_assert(static_cast<int>(CPDF_Object::Type::NUMBER) == FPDF_OBJECT_NUMBER, |
| 127 | "CPDF_Object::NUMBER value mismatch"); |
| 128 | static_assert(static_cast<int>(CPDF_Object::Type::STRING) == FPDF_OBJECT_STRING, |
| 129 | "CPDF_Object::STRING value mismatch"); |
| 130 | static_assert(static_cast<int>(CPDF_Object::Type::NAME) == FPDF_OBJECT_NAME, |
| 131 | "CPDF_Object::NAME value mismatch"); |
| 132 | static_assert(static_cast<int>(CPDF_Object::Type::ARRAY) == FPDF_OBJECT_ARRAY, |
| 133 | "CPDF_Object::ARRAY value mismatch"); |
| 134 | static_assert(static_cast<int>(CPDF_Object::Type::DICTIONARY) == |
| 135 | FPDF_OBJECT_DICTIONARY, |
| 136 | "CPDF_Object::DICTIONARY value mismatch"); |
| 137 | static_assert(static_cast<int>(CPDF_Object::Type::STREAM) == FPDF_OBJECT_STREAM, |
| 138 | "CPDF_Object::STREAM value mismatch"); |
| 139 | static_assert(static_cast<int>(CPDF_Object::Type::NULLOBJ) == |
| 140 | FPDF_OBJECT_NULLOBJ, |
| 141 | "CPDF_Object::NULLOBJ value mismatch"); |
| 142 | static_assert(static_cast<int>(CPDF_Object::Type::REFERENCE) == |
| 143 | FPDF_OBJECT_REFERENCE, |
| 144 | "CPDF_Object::REFERENCE value mismatch"); |
| 145 | |
Lei Zhang | fffdeeb | 2018-05-28 17:51:28 +0000 | [diff] [blame] | 146 | bool HasAPStream(CPDF_Dictionary* pAnnotDict) { |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 147 | return !!GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); |
Jane Liu | 0646275 | 2017-06-27 16:41:14 -0400 | [diff] [blame] | 148 | } |
| 149 | |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 150 | void UpdateContentStream(CPDF_Form* pForm, CPDF_Stream* pStream) { |
| 151 | ASSERT(pForm); |
| 152 | ASSERT(pStream); |
| 153 | |
| 154 | CPDF_PageContentGenerator generator(pForm); |
| 155 | std::ostringstream buf; |
| 156 | generator.ProcessPageObjects(&buf); |
Tom Sepez | 367ed46 | 2018-08-23 23:52:53 +0000 | [diff] [blame] | 157 | pStream->SetDataFromStringstreamAndRemoveFilter(&buf); |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 158 | } |
Jane Liu | 2e1a32b | 2017-07-06 12:01:25 -0400 | [diff] [blame] | 159 | |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 160 | void SetQuadPointsAtIndex(CPDF_Array* array, |
| 161 | size_t quad_index, |
| 162 | const FS_QUADPOINTSF* quad_points) { |
| 163 | ASSERT(array); |
| 164 | ASSERT(quad_points); |
| 165 | ASSERT(IsValidQuadPointsIndex(array, quad_index)); |
| 166 | |
| 167 | size_t nIndex = quad_index * 8; |
| 168 | array->SetNewAt<CPDF_Number>(nIndex, quad_points->x1); |
| 169 | array->SetNewAt<CPDF_Number>(++nIndex, quad_points->y1); |
| 170 | array->SetNewAt<CPDF_Number>(++nIndex, quad_points->x2); |
| 171 | array->SetNewAt<CPDF_Number>(++nIndex, quad_points->y2); |
| 172 | array->SetNewAt<CPDF_Number>(++nIndex, quad_points->x3); |
| 173 | array->SetNewAt<CPDF_Number>(++nIndex, quad_points->y3); |
| 174 | array->SetNewAt<CPDF_Number>(++nIndex, quad_points->x4); |
| 175 | array->SetNewAt<CPDF_Number>(++nIndex, quad_points->y4); |
| 176 | } |
| 177 | |
| 178 | void AppendQuadPoints(CPDF_Array* array, const FS_QUADPOINTSF* quad_points) { |
| 179 | ASSERT(quad_points); |
| 180 | ASSERT(array); |
| 181 | |
| 182 | array->AddNew<CPDF_Number>(quad_points->x1); |
| 183 | array->AddNew<CPDF_Number>(quad_points->y1); |
| 184 | array->AddNew<CPDF_Number>(quad_points->x2); |
| 185 | array->AddNew<CPDF_Number>(quad_points->y2); |
| 186 | array->AddNew<CPDF_Number>(quad_points->x3); |
| 187 | array->AddNew<CPDF_Number>(quad_points->y3); |
| 188 | array->AddNew<CPDF_Number>(quad_points->x4); |
| 189 | array->AddNew<CPDF_Number>(quad_points->y4); |
| 190 | } |
| 191 | |
Lei Zhang | fffdeeb | 2018-05-28 17:51:28 +0000 | [diff] [blame] | 192 | void UpdateBBox(CPDF_Dictionary* annot_dict) { |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 193 | // Update BBox entry in appearance stream based on the bounding rectangle |
| 194 | // of the annotation's quadpoints. |
| 195 | CPDF_Stream* pStream = |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 196 | GetAnnotAP(annot_dict, CPDF_Annot::AppearanceMode::Normal); |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 197 | if (pStream) { |
| 198 | CFX_FloatRect boundingRect = |
| 199 | CPDF_Annot::BoundingRectFromQuadPoints(annot_dict); |
| 200 | if (boundingRect.Contains(pStream->GetDict()->GetRectFor("BBox"))) |
| 201 | pStream->GetDict()->SetRectFor("BBox", boundingRect); |
| 202 | } |
| 203 | } |
| 204 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 205 | } // namespace |
| 206 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 207 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 208 | FPDFAnnot_IsSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) { |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 209 | // The supported subtypes must also be communicated in the user doc. |
Henrique Nakashima | ae0853d | 2018-02-12 18:29:57 +0000 | [diff] [blame] | 210 | return subtype == FPDF_ANNOT_CIRCLE || subtype == FPDF_ANNOT_FREETEXT || |
| 211 | subtype == FPDF_ANNOT_HIGHLIGHT || subtype == FPDF_ANNOT_INK || |
| 212 | subtype == FPDF_ANNOT_POPUP || subtype == FPDF_ANNOT_SQUARE || |
| 213 | subtype == FPDF_ANNOT_SQUIGGLY || subtype == FPDF_ANNOT_STAMP || |
| 214 | subtype == FPDF_ANNOT_STRIKEOUT || subtype == FPDF_ANNOT_TEXT || |
| 215 | subtype == FPDF_ANNOT_UNDERLINE; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 216 | } |
| 217 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 218 | FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 219 | FPDFPage_CreateAnnot(FPDF_PAGE page, FPDF_ANNOTATION_SUBTYPE subtype) { |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 220 | CPDF_Page* pPage = CPDFPageFromFPDFPage(page); |
| 221 | if (!pPage || !FPDFAnnot_IsSupportedSubtype(subtype)) |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 222 | return nullptr; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 223 | |
| 224 | auto pDict = pdfium::MakeUnique<CPDF_Dictionary>( |
Lei Zhang | 8f63763 | 2018-05-07 23:36:26 +0000 | [diff] [blame] | 225 | pPage->GetDocument()->GetByteStringPool()); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 226 | pDict->SetNewFor<CPDF_Name>("Type", "Annot"); |
| 227 | pDict->SetNewFor<CPDF_Name>("Subtype", |
| 228 | CPDF_Annot::AnnotSubtypeToString( |
| 229 | static_cast<CPDF_Annot::Subtype>(subtype))); |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 230 | auto pNewAnnot = |
| 231 | pdfium::MakeUnique<CPDF_AnnotContext>(pDict.get(), pPage, nullptr); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 232 | |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 233 | CPDF_Array* pAnnotList = pPage->GetDict()->GetArrayFor("Annots"); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 234 | if (!pAnnotList) |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 235 | pAnnotList = pPage->GetDict()->SetNewFor<CPDF_Array>("Annots"); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 236 | pAnnotList->Add(std::move(pDict)); |
Tom Sepez | 525147a | 2018-05-03 17:19:53 +0000 | [diff] [blame] | 237 | |
| 238 | // Caller takes ownership. |
| 239 | return FPDFAnnotationFromCPDFAnnotContext(pNewAnnot.release()); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 240 | } |
| 241 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 242 | FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotCount(FPDF_PAGE page) { |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 243 | CPDF_Page* pPage = CPDFPageFromFPDFPage(page); |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 244 | if (!pPage || !pPage->GetDict()) |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 245 | return 0; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 246 | |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 247 | CPDF_Array* pAnnots = pPage->GetDict()->GetArrayFor("Annots"); |
Lei Zhang | f40380f | 2018-10-12 18:31:51 +0000 | [diff] [blame^] | 248 | return pAnnots ? pAnnots->size() : 0; |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 249 | } |
| 250 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 251 | FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV FPDFPage_GetAnnot(FPDF_PAGE page, |
| 252 | int index) { |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 253 | CPDF_Page* pPage = CPDFPageFromFPDFPage(page); |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 254 | if (!pPage || !pPage->GetDict() || index < 0) |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 255 | return nullptr; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 256 | |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 257 | CPDF_Array* pAnnots = pPage->GetDict()->GetArrayFor("Annots"); |
Lei Zhang | f40380f | 2018-10-12 18:31:51 +0000 | [diff] [blame^] | 258 | if (!pAnnots || static_cast<size_t>(index) >= pAnnots->size()) |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 259 | return nullptr; |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 260 | |
| 261 | CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(index)); |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 262 | auto pNewAnnot = pdfium::MakeUnique<CPDF_AnnotContext>(pDict, pPage, nullptr); |
Tom Sepez | 525147a | 2018-05-03 17:19:53 +0000 | [diff] [blame] | 263 | |
| 264 | // Caller takes ownership. |
| 265 | return FPDFAnnotationFromCPDFAnnotContext(pNewAnnot.release()); |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 266 | } |
| 267 | |
Jane Liu | d1ed1ce | 2017-08-24 12:31:10 -0400 | [diff] [blame] | 268 | FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotIndex(FPDF_PAGE page, |
| 269 | FPDF_ANNOTATION annot) { |
| 270 | CPDF_Page* pPage = CPDFPageFromFPDFPage(page); |
| 271 | CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 272 | if (!pPage || !pPage->GetDict() || !pAnnot || !pAnnot->GetAnnotDict()) |
Jane Liu | d1ed1ce | 2017-08-24 12:31:10 -0400 | [diff] [blame] | 273 | return -1; |
| 274 | |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 275 | CPDF_Array* pAnnots = pPage->GetDict()->GetArrayFor("Annots"); |
Jane Liu | d1ed1ce | 2017-08-24 12:31:10 -0400 | [diff] [blame] | 276 | if (!pAnnots) |
| 277 | return -1; |
| 278 | |
| 279 | CPDF_Dictionary* pDict = pAnnot->GetAnnotDict(); |
| 280 | auto it = |
| 281 | std::find_if(pAnnots->begin(), pAnnots->end(), |
| 282 | [pDict](const std::unique_ptr<CPDF_Object>& candidate) { |
| 283 | return candidate->GetDirect() == pDict; |
| 284 | }); |
| 285 | |
| 286 | if (it == pAnnots->end()) |
| 287 | return -1; |
| 288 | |
| 289 | return it - pAnnots->begin(); |
| 290 | } |
| 291 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 292 | FPDF_EXPORT void FPDF_CALLCONV FPDFPage_CloseAnnot(FPDF_ANNOTATION annot) { |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 293 | delete CPDFAnnotContextFromFPDFAnnotation(annot); |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 294 | } |
| 295 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 296 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_RemoveAnnot(FPDF_PAGE page, |
| 297 | int index) { |
Jane Liu | 8ce58f5 | 2017-06-29 13:40:22 -0400 | [diff] [blame] | 298 | CPDF_Page* pPage = CPDFPageFromFPDFPage(page); |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 299 | if (!pPage || !pPage->GetDict() || index < 0) |
Jane Liu | 8ce58f5 | 2017-06-29 13:40:22 -0400 | [diff] [blame] | 300 | return false; |
| 301 | |
Henrique Nakashima | 888af47 | 2018-06-07 19:43:42 +0000 | [diff] [blame] | 302 | CPDF_Array* pAnnots = pPage->GetDict()->GetArrayFor("Annots"); |
Lei Zhang | f40380f | 2018-10-12 18:31:51 +0000 | [diff] [blame^] | 303 | if (!pAnnots || static_cast<size_t>(index) >= pAnnots->size()) |
Jane Liu | 8ce58f5 | 2017-06-29 13:40:22 -0400 | [diff] [blame] | 304 | return false; |
| 305 | |
| 306 | pAnnots->RemoveAt(index); |
| 307 | return true; |
| 308 | } |
| 309 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 310 | FPDF_EXPORT FPDF_ANNOTATION_SUBTYPE FPDF_CALLCONV |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 311 | FPDFAnnot_GetSubtype(FPDF_ANNOTATION annot) { |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 312 | if (!annot) |
| 313 | return FPDF_ANNOT_UNKNOWN; |
| 314 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 315 | CPDF_Dictionary* pAnnotDict = |
| 316 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 317 | if (!pAnnotDict) |
| 318 | return FPDF_ANNOT_UNKNOWN; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 319 | |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 320 | return static_cast<FPDF_ANNOTATION_SUBTYPE>( |
| 321 | CPDF_Annot::StringToAnnotSubtype(pAnnotDict->GetStringFor("Subtype"))); |
| 322 | } |
| 323 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 324 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 325 | FPDFAnnot_IsObjectSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) { |
| 326 | // The supported subtypes must also be communicated in the user doc. |
| 327 | return subtype == FPDF_ANNOT_INK || subtype == FPDF_ANNOT_STAMP; |
| 328 | } |
| 329 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 330 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
| 331 | FPDFAnnot_UpdateObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) { |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 332 | CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 333 | CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(obj); |
| 334 | if (!pAnnot || !pAnnot->GetAnnotDict() || !pAnnot->HasForm() || !pObj) |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 335 | return false; |
| 336 | |
| 337 | // Check that the annotation type is supported by this method. |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 338 | if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot))) |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 339 | return false; |
| 340 | |
| 341 | // Check that the annotation already has an appearance stream, since an |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 342 | // existing object is to be updated. |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 343 | CPDF_Stream* pStream = |
| 344 | GetAnnotAP(pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 345 | if (!pStream) |
| 346 | return false; |
| 347 | |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 348 | // Check that the object is already in this annotation's object list. |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 349 | CPDF_Form* pForm = pAnnot->GetForm(); |
Henrique Nakashima | 6b26e1a | 2018-04-16 21:48:37 +0000 | [diff] [blame] | 350 | const CPDF_PageObjectList* pObjList = pForm->GetPageObjectList(); |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 351 | auto it = |
| 352 | std::find_if(pObjList->begin(), pObjList->end(), |
| 353 | [pObj](const std::unique_ptr<CPDF_PageObject>& candidate) { |
| 354 | return candidate.get() == pObj; |
| 355 | }); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 356 | if (it == pObjList->end()) |
| 357 | return false; |
| 358 | |
| 359 | // Update the content stream data in the annotation's AP stream. |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 360 | UpdateContentStream(pForm, pStream); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 361 | return true; |
| 362 | } |
| 363 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 364 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
| 365 | FPDFAnnot_AppendObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) { |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 366 | CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 367 | CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(obj); |
| 368 | if (!pAnnot || !pObj) |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 369 | return false; |
| 370 | |
| 371 | CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict(); |
| 372 | CPDF_Page* pPage = pAnnot->GetPage(); |
| 373 | if (!pAnnotDict || !pPage) |
| 374 | return false; |
| 375 | |
| 376 | // Check that the annotation type is supported by this method. |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 377 | if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot))) |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 378 | return false; |
| 379 | |
| 380 | // If the annotation does not have an AP stream yet, generate and set it. |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 381 | CPDF_Stream* pStream = |
| 382 | GetAnnotAP(pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 383 | if (!pStream) { |
Lei Zhang | 8f63763 | 2018-05-07 23:36:26 +0000 | [diff] [blame] | 384 | CPVT_GenerateAP::GenerateEmptyAP(pPage->GetDocument(), pAnnotDict); |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 385 | pStream = GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 386 | if (!pStream) |
| 387 | return false; |
| 388 | } |
| 389 | |
| 390 | // Get the annotation's corresponding form object for parsing its AP stream. |
| 391 | if (!pAnnot->HasForm()) |
| 392 | pAnnot->SetForm(pStream); |
| 393 | |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 394 | // Check that the object did not come from the same annotation. If this check |
| 395 | // succeeds, then it is assumed that the object came from |
| 396 | // FPDFPageObj_CreateNew{Path|Rect}() or FPDFPageObj_New{Text|Image}Obj(). |
| 397 | // Note that an object that came from a different annotation must not be |
| 398 | // passed here, since an object cannot belong to more than one annotation. |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 399 | CPDF_Form* pForm = pAnnot->GetForm(); |
Henrique Nakashima | 6b26e1a | 2018-04-16 21:48:37 +0000 | [diff] [blame] | 400 | const CPDF_PageObjectList* pObjList = pForm->GetPageObjectList(); |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 401 | auto it = |
| 402 | std::find_if(pObjList->begin(), pObjList->end(), |
| 403 | [pObj](const std::unique_ptr<CPDF_PageObject>& candidate) { |
| 404 | return candidate.get() == pObj; |
| 405 | }); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 406 | if (it != pObjList->end()) |
| 407 | return false; |
| 408 | |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 409 | // Append the object to the object list. |
Henrique Nakashima | 6b26e1a | 2018-04-16 21:48:37 +0000 | [diff] [blame] | 410 | pForm->AppendPageObject(pdfium::WrapUnique(pObj)); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 411 | |
| 412 | // Set the content stream data in the annotation's AP stream. |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 413 | UpdateContentStream(pForm, pStream); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 414 | return true; |
| 415 | } |
| 416 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 417 | FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetObjectCount(FPDF_ANNOTATION annot) { |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 418 | CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 419 | if (!pAnnot || !pAnnot->GetAnnotDict()) |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 420 | return 0; |
| 421 | |
| 422 | if (!pAnnot->HasForm()) { |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 423 | CPDF_Stream* pStream = |
| 424 | GetAnnotAP(pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 425 | if (!pStream) |
| 426 | return 0; |
| 427 | |
| 428 | pAnnot->SetForm(pStream); |
| 429 | } |
Jane Liu | 57f228d | 2017-07-13 18:10:30 -0400 | [diff] [blame] | 430 | return pdfium::CollectionSize<int>(*pAnnot->GetForm()->GetPageObjectList()); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 431 | } |
| 432 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 433 | FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV |
| 434 | FPDFAnnot_GetObject(FPDF_ANNOTATION annot, int index) { |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 435 | CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); |
Jane Liu | 3656774 | 2017-07-06 11:13:35 -0400 | [diff] [blame] | 436 | if (!pAnnot || !pAnnot->GetAnnotDict() || index < 0) |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 437 | return nullptr; |
| 438 | |
| 439 | if (!pAnnot->HasForm()) { |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 440 | CPDF_Stream* pStream = |
| 441 | GetAnnotAP(pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 442 | if (!pStream) |
| 443 | return nullptr; |
| 444 | |
| 445 | pAnnot->SetForm(pStream); |
| 446 | } |
| 447 | |
Tom Sepez | 525147a | 2018-05-03 17:19:53 +0000 | [diff] [blame] | 448 | return FPDFPageObjectFromCPDFPageObject( |
| 449 | pAnnot->GetForm()->GetPageObjectByIndex(index)); |
Jane Liu | baa7ff4 | 2017-06-29 19:18:23 -0400 | [diff] [blame] | 450 | } |
| 451 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 452 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
| 453 | FPDFAnnot_RemoveObject(FPDF_ANNOTATION annot, int index) { |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 454 | CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); |
| 455 | if (!pAnnot || !pAnnot->GetAnnotDict() || !pAnnot->HasForm() || index < 0) |
| 456 | return false; |
| 457 | |
| 458 | // Check that the annotation type is supported by this method. |
| 459 | if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot))) |
| 460 | return false; |
| 461 | |
| 462 | // Check that the annotation already has an appearance stream, since an |
| 463 | // existing object is to be deleted. |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 464 | CPDF_Stream* pStream = |
| 465 | GetAnnotAP(pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal); |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 466 | if (!pStream) |
| 467 | return false; |
| 468 | |
Henrique Nakashima | 6b26e1a | 2018-04-16 21:48:37 +0000 | [diff] [blame] | 469 | if (!pAnnot->GetForm()->ErasePageObjectAtIndex(index)) |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 470 | return false; |
| 471 | |
Jane Liu | 7a9a38b | 2017-07-11 13:47:37 -0400 | [diff] [blame] | 472 | UpdateContentStream(pAnnot->GetForm(), pStream); |
| 473 | return true; |
| 474 | } |
| 475 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 476 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetColor(FPDF_ANNOTATION annot, |
| 477 | FPDFANNOT_COLORTYPE type, |
| 478 | unsigned int R, |
| 479 | unsigned int G, |
| 480 | unsigned int B, |
| 481 | unsigned int A) { |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 482 | if (!annot || R > 255 || G > 255 || B > 255 || A > 255) |
| 483 | return false; |
| 484 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 485 | CPDF_Dictionary* pAnnotDict = |
| 486 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 487 | if (!pAnnotDict) |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 488 | return false; |
| 489 | |
Jane Liu | 0646275 | 2017-06-27 16:41:14 -0400 | [diff] [blame] | 490 | // For annotations with their appearance streams already defined, the path |
| 491 | // stream's own color definitions take priority over the annotation color |
| 492 | // definitions set by this method, hence this method will simply fail. |
| 493 | if (HasAPStream(pAnnotDict)) |
| 494 | return false; |
| 495 | |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 496 | // Set the opacity of the annotation. |
| 497 | pAnnotDict->SetNewFor<CPDF_Number>("CA", A / 255.f); |
| 498 | |
| 499 | // Set the color of the annotation. |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 500 | ByteString key = type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C"; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 501 | CPDF_Array* pColor = pAnnotDict->GetArrayFor(key); |
| 502 | if (pColor) |
Lei Zhang | 59c1ac0 | 2017-06-09 11:04:41 -0700 | [diff] [blame] | 503 | pColor->Clear(); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 504 | else |
| 505 | pColor = pAnnotDict->SetNewFor<CPDF_Array>(key); |
| 506 | |
| 507 | pColor->AddNew<CPDF_Number>(R / 255.f); |
| 508 | pColor->AddNew<CPDF_Number>(G / 255.f); |
| 509 | pColor->AddNew<CPDF_Number>(B / 255.f); |
| 510 | |
| 511 | return true; |
| 512 | } |
| 513 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 514 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetColor(FPDF_ANNOTATION annot, |
| 515 | FPDFANNOT_COLORTYPE type, |
| 516 | unsigned int* R, |
| 517 | unsigned int* G, |
| 518 | unsigned int* B, |
| 519 | unsigned int* A) { |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 520 | if (!annot || !R || !G || !B || !A) |
| 521 | return false; |
| 522 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 523 | CPDF_Dictionary* pAnnotDict = |
| 524 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 525 | if (!pAnnotDict) |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 526 | return false; |
| 527 | |
Jane Liu | 0646275 | 2017-06-27 16:41:14 -0400 | [diff] [blame] | 528 | // For annotations with their appearance streams already defined, the path |
| 529 | // stream's own color definitions take priority over the annotation color |
| 530 | // definitions retrieved by this method, hence this method will simply fail. |
| 531 | if (HasAPStream(pAnnotDict)) |
| 532 | return false; |
| 533 | |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 534 | CPDF_Array* pColor = pAnnotDict->GetArrayFor( |
| 535 | type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C"); |
| 536 | *A = |
| 537 | (pAnnotDict->KeyExist("CA") ? pAnnotDict->GetNumberFor("CA") : 1) * 255.f; |
| 538 | if (!pColor) { |
| 539 | // Use default color. The default colors must be consistent with the ones |
| 540 | // used to generate AP. See calls to GetColorStringWithDefault() in |
| 541 | // CPVT_GenerateAP::Generate*AP(). |
| 542 | if (pAnnotDict->GetStringFor("Subtype") == "Highlight") { |
| 543 | *R = 255; |
| 544 | *G = 255; |
| 545 | *B = 0; |
| 546 | } else { |
| 547 | *R = 0; |
| 548 | *G = 0; |
| 549 | *B = 0; |
| 550 | } |
| 551 | return true; |
| 552 | } |
Dan Sinclair | 8e7f932 | 2017-10-16 11:35:42 -0400 | [diff] [blame] | 553 | |
| 554 | CFX_Color color = CFX_Color::ParseColor(*pColor); |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 555 | switch (color.nColorType) { |
Dan Sinclair | 8e7f932 | 2017-10-16 11:35:42 -0400 | [diff] [blame] | 556 | case CFX_Color::kRGB: |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 557 | *R = color.fColor1 * 255.f; |
| 558 | *G = color.fColor2 * 255.f; |
| 559 | *B = color.fColor3 * 255.f; |
| 560 | break; |
Dan Sinclair | 8e7f932 | 2017-10-16 11:35:42 -0400 | [diff] [blame] | 561 | case CFX_Color::kGray: |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 562 | *R = 255.f * color.fColor1; |
| 563 | *G = 255.f * color.fColor1; |
| 564 | *B = 255.f * color.fColor1; |
| 565 | break; |
Dan Sinclair | 8e7f932 | 2017-10-16 11:35:42 -0400 | [diff] [blame] | 566 | case CFX_Color::kCMYK: |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 567 | *R = 255.f * (1 - color.fColor1) * (1 - color.fColor4); |
| 568 | *G = 255.f * (1 - color.fColor2) * (1 - color.fColor4); |
| 569 | *B = 255.f * (1 - color.fColor3) * (1 - color.fColor4); |
| 570 | break; |
Dan Sinclair | 8e7f932 | 2017-10-16 11:35:42 -0400 | [diff] [blame] | 571 | case CFX_Color::kTransparent: |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 572 | *R = 0; |
| 573 | *G = 0; |
| 574 | *B = 0; |
| 575 | break; |
| 576 | } |
| 577 | return true; |
| 578 | } |
| 579 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 580 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 581 | FPDFAnnot_HasAttachmentPoints(FPDF_ANNOTATION annot) { |
| 582 | if (!annot) |
| 583 | return false; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 584 | |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 585 | FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot); |
| 586 | return subtype == FPDF_ANNOT_LINK || subtype == FPDF_ANNOT_HIGHLIGHT || |
| 587 | subtype == FPDF_ANNOT_UNDERLINE || subtype == FPDF_ANNOT_SQUIGGLY || |
| 588 | subtype == FPDF_ANNOT_STRIKEOUT; |
| 589 | } |
| 590 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 591 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 592 | FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot, |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 593 | size_t quad_index, |
Lei Zhang | c3cffbe | 2018-03-21 13:37:46 +0000 | [diff] [blame] | 594 | const FS_QUADPOINTSF* quad_points) { |
Henrique Nakashima | 5098b25 | 2018-03-26 21:46:00 +0000 | [diff] [blame] | 595 | if (!FPDFAnnot_HasAttachmentPoints(annot) || !quad_points) |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 596 | return false; |
| 597 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 598 | CPDF_Dictionary* pAnnotDict = |
| 599 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 600 | CPDF_Array* pQuadPointsArray = GetQuadPointsArrayFromDictionary(pAnnotDict); |
| 601 | if (!IsValidQuadPointsIndex(pQuadPointsArray, quad_index)) |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 602 | return false; |
| 603 | |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 604 | SetQuadPointsAtIndex(pQuadPointsArray, quad_index, quad_points); |
| 605 | UpdateBBox(pAnnotDict); |
| 606 | return true; |
| 607 | } |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 608 | |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 609 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
| 610 | FPDFAnnot_AppendAttachmentPoints(FPDF_ANNOTATION annot, |
| 611 | const FS_QUADPOINTSF* quad_points) { |
| 612 | if (!FPDFAnnot_HasAttachmentPoints(annot) || !quad_points) |
| 613 | return false; |
Jane Liu | 0646275 | 2017-06-27 16:41:14 -0400 | [diff] [blame] | 614 | |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 615 | CPDF_Dictionary* pAnnotDict = |
| 616 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
| 617 | CPDF_Array* pQuadPointsArray = GetQuadPointsArrayFromDictionary(pAnnotDict); |
| 618 | if (!pQuadPointsArray) |
| 619 | pQuadPointsArray = AddQuadPointsArrayToDictionary(pAnnotDict); |
| 620 | AppendQuadPoints(pQuadPointsArray, quad_points); |
| 621 | UpdateBBox(pAnnotDict); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 622 | return true; |
| 623 | } |
| 624 | |
Henrique Nakashima | 5098b25 | 2018-03-26 21:46:00 +0000 | [diff] [blame] | 625 | FPDF_EXPORT size_t FPDF_CALLCONV |
| 626 | FPDFAnnot_CountAttachmentPoints(FPDF_ANNOTATION annot) { |
| 627 | if (!FPDFAnnot_HasAttachmentPoints(annot)) |
| 628 | return 0; |
| 629 | |
| 630 | CPDF_Dictionary* pAnnotDict = |
| 631 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
| 632 | const CPDF_Array* pArray = GetQuadPointsArrayFromDictionary(pAnnotDict); |
Lei Zhang | f40380f | 2018-10-12 18:31:51 +0000 | [diff] [blame^] | 633 | return pArray ? pArray->size() / 8 : 0; |
Henrique Nakashima | 5098b25 | 2018-03-26 21:46:00 +0000 | [diff] [blame] | 634 | } |
| 635 | |
Jane Liu | 0c6b07d | 2017-08-15 10:50:22 -0400 | [diff] [blame] | 636 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
| 637 | FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot, |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 638 | size_t quad_index, |
Lei Zhang | c3cffbe | 2018-03-21 13:37:46 +0000 | [diff] [blame] | 639 | FS_QUADPOINTSF* quad_points) { |
Henrique Nakashima | 5098b25 | 2018-03-26 21:46:00 +0000 | [diff] [blame] | 640 | if (!FPDFAnnot_HasAttachmentPoints(annot) || !quad_points) |
Jane Liu | 0c6b07d | 2017-08-15 10:50:22 -0400 | [diff] [blame] | 641 | return false; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 642 | |
Ralf Sippl | 1638179 | 2018-04-12 21:20:26 +0000 | [diff] [blame] | 643 | CPDF_Dictionary* pAnnotDict = |
| 644 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
| 645 | if (!pAnnotDict) |
| 646 | return false; |
| 647 | |
| 648 | const CPDF_Array* pArray = GetQuadPointsArrayFromDictionary(pAnnotDict); |
| 649 | if (!pArray) |
| 650 | return false; |
| 651 | |
| 652 | return GetQuadPointsAtIndex(pArray, quad_index, quad_points); |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 653 | } |
| 654 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 655 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetRect(FPDF_ANNOTATION annot, |
| 656 | const FS_RECTF* rect) { |
Jane Liu | 0646275 | 2017-06-27 16:41:14 -0400 | [diff] [blame] | 657 | if (!annot || !rect) |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 658 | return false; |
| 659 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 660 | CPDF_Dictionary* pAnnotDict = |
| 661 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 662 | if (!pAnnotDict) |
| 663 | return false; |
| 664 | |
Lei Zhang | 367e7de | 2017-10-31 13:32:17 +0000 | [diff] [blame] | 665 | CFX_FloatRect newRect = CFXFloatRectFromFSRECTF(*rect); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 666 | |
Jane Liu | 0646275 | 2017-06-27 16:41:14 -0400 | [diff] [blame] | 667 | // Update the "Rect" entry in the annotation dictionary. |
| 668 | pAnnotDict->SetRectFor("Rect", newRect); |
| 669 | |
| 670 | // If the annotation's appearance stream is defined, the annotation is of a |
| 671 | // type that does not have quadpoints, and the new rectangle is bigger than |
| 672 | // the current bounding box, then update the "BBox" entry in the AP |
| 673 | // dictionary too, since its "BBox" entry comes from annotation dictionary's |
| 674 | // "Rect" entry. |
| 675 | if (FPDFAnnot_HasAttachmentPoints(annot)) |
| 676 | return true; |
| 677 | |
| 678 | CPDF_Stream* pStream = |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 679 | GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); |
Jane Liu | 0646275 | 2017-06-27 16:41:14 -0400 | [diff] [blame] | 680 | if (pStream && newRect.Contains(pStream->GetDict()->GetRectFor("BBox"))) |
| 681 | pStream->GetDict()->SetRectFor("BBox", newRect); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 682 | return true; |
| 683 | } |
| 684 | |
Jane Liu | 0c6b07d | 2017-08-15 10:50:22 -0400 | [diff] [blame] | 685 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetRect(FPDF_ANNOTATION annot, |
| 686 | FS_RECTF* rect) { |
| 687 | if (!annot || !rect) |
| 688 | return false; |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 689 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 690 | CPDF_Dictionary* pAnnotDict = |
| 691 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 692 | if (!pAnnotDict) |
Jane Liu | 0c6b07d | 2017-08-15 10:50:22 -0400 | [diff] [blame] | 693 | return false; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 694 | |
Lei Zhang | 367e7de | 2017-10-31 13:32:17 +0000 | [diff] [blame] | 695 | FSRECTFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"), rect); |
Jane Liu | 0c6b07d | 2017-08-15 10:50:22 -0400 | [diff] [blame] | 696 | return true; |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 697 | } |
| 698 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 699 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_HasKey(FPDF_ANNOTATION annot, |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 700 | FPDF_BYTESTRING key) { |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 701 | if (!annot) |
| 702 | return false; |
| 703 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 704 | CPDF_Dictionary* pAnnotDict = |
| 705 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 706 | if (!pAnnotDict) |
| 707 | return false; |
| 708 | |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 709 | return pAnnotDict->KeyExist(key); |
Jane Liu | 2e1a32b | 2017-07-06 12:01:25 -0400 | [diff] [blame] | 710 | } |
| 711 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 712 | FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 713 | FPDFAnnot_GetValueType(FPDF_ANNOTATION annot, FPDF_BYTESTRING key) { |
Jane Liu | 2e1a32b | 2017-07-06 12:01:25 -0400 | [diff] [blame] | 714 | if (!FPDFAnnot_HasKey(annot, key)) |
| 715 | return FPDF_OBJECT_UNKNOWN; |
| 716 | |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 717 | auto* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); |
| 718 | CPDF_Object* pObj = pAnnot->GetAnnotDict()->GetObjectFor(key); |
| 719 | return pObj ? pObj->GetType() : FPDF_OBJECT_UNKNOWN; |
Jane Liu | 2e1a32b | 2017-07-06 12:01:25 -0400 | [diff] [blame] | 720 | } |
| 721 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 722 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
| 723 | FPDFAnnot_SetStringValue(FPDF_ANNOTATION annot, |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 724 | FPDF_BYTESTRING key, |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 725 | FPDF_WIDESTRING value) { |
Jane Liu | 2e1a32b | 2017-07-06 12:01:25 -0400 | [diff] [blame] | 726 | if (!annot) |
| 727 | return false; |
| 728 | |
| 729 | CPDF_Dictionary* pAnnotDict = |
| 730 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
| 731 | if (!pAnnotDict) |
| 732 | return false; |
| 733 | |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 734 | pAnnotDict->SetNewFor<CPDF_String>( |
| 735 | key, CFXByteStringFromFPDFWideString(value), false); |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 736 | return true; |
| 737 | } |
| 738 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 739 | FPDF_EXPORT unsigned long FPDF_CALLCONV |
| 740 | FPDFAnnot_GetStringValue(FPDF_ANNOTATION annot, |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 741 | FPDF_BYTESTRING key, |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 742 | void* buffer, |
| 743 | unsigned long buflen) { |
Jane Liu | d60e9ad | 2017-06-26 11:28:36 -0400 | [diff] [blame] | 744 | if (!annot) |
| 745 | return 0; |
| 746 | |
Jane Liu | e10509a | 2017-06-20 16:47:41 -0400 | [diff] [blame] | 747 | CPDF_Dictionary* pAnnotDict = |
| 748 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 749 | if (!pAnnotDict) |
| 750 | return 0; |
Jane Liu | 20eafda | 2017-06-07 10:33:24 -0400 | [diff] [blame] | 751 | |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 752 | return Utf16EncodeMaybeCopyAndReturnLength(pAnnotDict->GetUnicodeTextFor(key), |
| 753 | buffer, buflen); |
Jane Liu | 4fd9a47 | 2017-06-01 18:56:09 -0400 | [diff] [blame] | 754 | } |
Jane Liu | b137e75 | 2017-07-05 15:04:33 -0400 | [diff] [blame] | 755 | |
Henrique Nakashima | 5970a47 | 2018-01-11 22:40:59 +0000 | [diff] [blame] | 756 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV |
| 757 | FPDFAnnot_SetAP(FPDF_ANNOTATION annot, |
| 758 | FPDF_ANNOT_APPEARANCEMODE appearanceMode, |
| 759 | FPDF_WIDESTRING value) { |
| 760 | if (appearanceMode < 0 || appearanceMode >= FPDF_ANNOT_APPEARANCEMODE_COUNT) |
| 761 | return false; |
| 762 | |
| 763 | if (!annot) |
| 764 | return false; |
| 765 | |
| 766 | CPDF_Dictionary* pAnnotDict = |
| 767 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
| 768 | if (!pAnnotDict) |
| 769 | return false; |
| 770 | |
| 771 | constexpr const char* modeKeyForMode[] = {"N", "R", "D"}; |
| 772 | static_assert(FX_ArraySize(modeKeyForMode) == FPDF_ANNOT_APPEARANCEMODE_COUNT, |
| 773 | "length of modeKeyForMode should be equal to " |
| 774 | "FPDF_ANNOT_APPEARANCEMODE_COUNT"); |
| 775 | const char* modeKey = modeKeyForMode[appearanceMode]; |
| 776 | |
| 777 | CPDF_Dictionary* pApDict = pAnnotDict->GetDictFor("AP"); |
| 778 | |
| 779 | // If value is null, we're in remove mode. Otherwise, we're in add/update |
| 780 | // mode. |
| 781 | if (value) { |
| 782 | if (!pApDict) |
| 783 | pApDict = pAnnotDict->SetNewFor<CPDF_Dictionary>("AP"); |
| 784 | |
| 785 | ByteString newValue = CFXByteStringFromFPDFWideString(value); |
| 786 | auto pNewApStream = pdfium::MakeUnique<CPDF_Stream>(); |
Tom Sepez | 367ed46 | 2018-08-23 23:52:53 +0000 | [diff] [blame] | 787 | pNewApStream->SetData(newValue.AsRawSpan()); |
Henrique Nakashima | 5970a47 | 2018-01-11 22:40:59 +0000 | [diff] [blame] | 788 | pApDict->SetFor(modeKey, std::move(pNewApStream)); |
| 789 | } else { |
| 790 | if (pApDict) { |
| 791 | if (appearanceMode == FPDF_ANNOT_APPEARANCEMODE_NORMAL) |
| 792 | pAnnotDict->RemoveFor("AP"); |
| 793 | else |
| 794 | pApDict->RemoveFor(modeKey); |
| 795 | } |
| 796 | } |
| 797 | |
| 798 | return true; |
| 799 | } |
| 800 | |
Henrique Nakashima | a74e75d | 2018-01-10 18:06:55 +0000 | [diff] [blame] | 801 | FPDF_EXPORT unsigned long FPDF_CALLCONV |
| 802 | FPDFAnnot_GetAP(FPDF_ANNOTATION annot, |
| 803 | FPDF_ANNOT_APPEARANCEMODE appearanceMode, |
| 804 | void* buffer, |
| 805 | unsigned long buflen) { |
| 806 | if (appearanceMode < 0 || appearanceMode >= FPDF_ANNOT_APPEARANCEMODE_COUNT) |
| 807 | return 0; |
| 808 | |
| 809 | if (!annot) |
| 810 | return 0; |
| 811 | |
| 812 | CPDF_Dictionary* pAnnotDict = |
| 813 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
| 814 | if (!pAnnotDict) |
| 815 | return 0; |
| 816 | |
| 817 | CPDF_Annot::AppearanceMode mode = |
| 818 | static_cast<CPDF_Annot::AppearanceMode>(appearanceMode); |
| 819 | |
Tom Sepez | 456e970 | 2018-08-29 19:35:37 +0000 | [diff] [blame] | 820 | CPDF_Stream* pStream = GetAnnotAPNoFallback(pAnnotDict, mode); |
Lei Zhang | 4afee17 | 2018-01-10 20:57:15 +0000 | [diff] [blame] | 821 | return Utf16EncodeMaybeCopyAndReturnLength( |
| 822 | pStream ? pStream->GetUnicodeText() : L"", buffer, buflen); |
Henrique Nakashima | a74e75d | 2018-01-10 18:06:55 +0000 | [diff] [blame] | 823 | } |
| 824 | |
Jane Liu | 300bb27 | 2017-08-21 14:37:53 -0400 | [diff] [blame] | 825 | FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 826 | FPDFAnnot_GetLinkedAnnot(FPDF_ANNOTATION annot, FPDF_BYTESTRING key) { |
Jane Liu | 300bb27 | 2017-08-21 14:37:53 -0400 | [diff] [blame] | 827 | CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); |
| 828 | if (!pAnnot || !pAnnot->GetAnnotDict()) |
| 829 | return nullptr; |
| 830 | |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 831 | CPDF_Dictionary* pLinkedDict = pAnnot->GetAnnotDict()->GetDictFor(key); |
Jane Liu | 300bb27 | 2017-08-21 14:37:53 -0400 | [diff] [blame] | 832 | if (!pLinkedDict || pLinkedDict->GetStringFor("Type") != "Annot") |
| 833 | return nullptr; |
| 834 | |
| 835 | auto pLinkedAnnot = pdfium::MakeUnique<CPDF_AnnotContext>( |
| 836 | pLinkedDict, pAnnot->GetPage(), nullptr); |
Tom Sepez | 525147a | 2018-05-03 17:19:53 +0000 | [diff] [blame] | 837 | |
| 838 | // Caller takes ownership. |
| 839 | return FPDFAnnotationFromCPDFAnnotContext(pLinkedAnnot.release()); |
Jane Liu | 300bb27 | 2017-08-21 14:37:53 -0400 | [diff] [blame] | 840 | } |
| 841 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 842 | FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetFlags(FPDF_ANNOTATION annot) { |
Jane Liu | b137e75 | 2017-07-05 15:04:33 -0400 | [diff] [blame] | 843 | if (!annot) |
| 844 | return FPDF_ANNOT_FLAG_NONE; |
| 845 | |
| 846 | CPDF_Dictionary* pAnnotDict = |
| 847 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
Lei Zhang | df064df | 2017-08-31 02:33:27 -0700 | [diff] [blame] | 848 | return pAnnotDict ? pAnnotDict->GetIntegerFor("F") : FPDF_ANNOT_FLAG_NONE; |
Jane Liu | b137e75 | 2017-07-05 15:04:33 -0400 | [diff] [blame] | 849 | } |
| 850 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 851 | FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetFlags(FPDF_ANNOTATION annot, |
| 852 | int flags) { |
Jane Liu | b137e75 | 2017-07-05 15:04:33 -0400 | [diff] [blame] | 853 | if (!annot) |
| 854 | return false; |
| 855 | |
| 856 | CPDF_Dictionary* pAnnotDict = |
| 857 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
| 858 | if (!pAnnotDict) |
| 859 | return false; |
| 860 | |
| 861 | pAnnotDict->SetNewFor<CPDF_Number>("F", flags); |
| 862 | return true; |
| 863 | } |
Diana Gage | 7e0c05d | 2017-07-19 17:33:33 -0700 | [diff] [blame] | 864 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 865 | FPDF_EXPORT int FPDF_CALLCONV |
| 866 | FPDFAnnot_GetFormFieldFlags(FPDF_PAGE page, FPDF_ANNOTATION annot) { |
Diana Gage | 7e0c05d | 2017-07-19 17:33:33 -0700 | [diff] [blame] | 867 | CPDF_Page* pPage = CPDFPageFromFPDFPage(page); |
| 868 | if (!pPage || !annot) |
| 869 | return FPDF_FORMFLAG_NONE; |
| 870 | |
| 871 | CPDF_Dictionary* pAnnotDict = |
| 872 | CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); |
| 873 | if (!pAnnotDict) |
| 874 | return FPDF_FORMFLAG_NONE; |
| 875 | |
Lei Zhang | 073ecf4 | 2018-10-11 16:56:00 +0000 | [diff] [blame] | 876 | CPDF_InteractiveForm interactive_form(pPage->GetDocument()); |
| 877 | CPDF_FormField* pFormField = interactive_form.GetFieldByDict(pAnnotDict); |
Diana Gage | 7e0c05d | 2017-07-19 17:33:33 -0700 | [diff] [blame] | 878 | return pFormField ? pFormField->GetFieldFlags() : FPDF_FORMFLAG_NONE; |
| 879 | } |
Diana Gage | 40870db | 2017-07-19 18:16:03 -0700 | [diff] [blame] | 880 | |
Dan Sinclair | 00d2ad1 | 2017-08-10 14:13:02 -0400 | [diff] [blame] | 881 | FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV |
Diana Gage | 40870db | 2017-07-19 18:16:03 -0700 | [diff] [blame] | 882 | FPDFAnnot_GetFormFieldAtPoint(FPDF_FORMHANDLE hHandle, |
| 883 | FPDF_PAGE page, |
| 884 | double page_x, |
| 885 | double page_y) { |
| 886 | CPDF_Page* pPage = CPDFPageFromFPDFPage(page); |
| 887 | if (!hHandle || !pPage) |
| 888 | return nullptr; |
| 889 | |
Lei Zhang | 073ecf4 | 2018-10-11 16:56:00 +0000 | [diff] [blame] | 890 | CPDF_InteractiveForm interactive_form(pPage->GetDocument()); |
Diana Gage | 40870db | 2017-07-19 18:16:03 -0700 | [diff] [blame] | 891 | int annot_index = -1; |
Lei Zhang | 073ecf4 | 2018-10-11 16:56:00 +0000 | [diff] [blame] | 892 | CPDF_FormControl* pFormCtrl = interactive_form.GetControlAtPoint( |
Diana Gage | 40870db | 2017-07-19 18:16:03 -0700 | [diff] [blame] | 893 | pPage, CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)), |
| 894 | &annot_index); |
| 895 | if (!pFormCtrl || annot_index == -1) |
| 896 | return nullptr; |
| 897 | return FPDFPage_GetAnnot(page, annot_index); |
| 898 | } |