1 // Copyright 2016 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
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fpdfsdk/cpdfsdk_baannot.h"
8
9 #include <algorithm>
10 #include <utility>
11
12 #include "constants/annotation_common.h"
13 #include "constants/annotation_flags.h"
14 #include "core/fpdfapi/parser/cpdf_array.h"
15 #include "core/fpdfapi/parser/cpdf_dictionary.h"
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_reference.h"
20 #include "core/fpdfapi/parser/cpdf_stream.h"
21 #include "core/fpdfapi/parser/cpdf_string.h"
22 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
23 #include "fpdfsdk/cpdfsdk_pageview.h"
24
CPDFSDK_BAAnnot(CPDF_Annot * pAnnot,CPDFSDK_PageView * pPageView)25 CPDFSDK_BAAnnot::CPDFSDK_BAAnnot(CPDF_Annot* pAnnot,
26 CPDFSDK_PageView* pPageView)
27 : CPDFSDK_Annot(pPageView), m_pAnnot(pAnnot) {}
28
~CPDFSDK_BAAnnot()29 CPDFSDK_BAAnnot::~CPDFSDK_BAAnnot() {}
30
AsBAAnnot()31 CPDFSDK_BAAnnot* CPDFSDK_BAAnnot::AsBAAnnot() {
32 return this;
33 }
34
GetPDFAnnot() const35 CPDF_Annot* CPDFSDK_BAAnnot::GetPDFAnnot() const {
36 return m_pAnnot.Get();
37 }
38
GetPDFPopupAnnot() const39 CPDF_Annot* CPDFSDK_BAAnnot::GetPDFPopupAnnot() const {
40 return m_pAnnot->GetPopupAnnot();
41 }
42
GetAnnotDict() const43 CPDF_Dictionary* CPDFSDK_BAAnnot::GetAnnotDict() const {
44 return m_pAnnot->GetAnnotDict();
45 }
46
GetAPDict() const47 CPDF_Dictionary* CPDFSDK_BAAnnot::GetAPDict() const {
48 CPDF_Dictionary* pAPDict =
49 GetAnnotDict()->GetDictFor(pdfium::annotation::kAP);
50 if (pAPDict)
51 return pAPDict;
52 return GetAnnotDict()->SetNewFor<CPDF_Dictionary>(pdfium::annotation::kAP);
53 }
54
SetRect(const CFX_FloatRect & rect)55 void CPDFSDK_BAAnnot::SetRect(const CFX_FloatRect& rect) {
56 ASSERT(rect.right - rect.left >= 1.0f);
57 ASSERT(rect.top - rect.bottom >= 1.0f);
58 GetAnnotDict()->SetRectFor(pdfium::annotation::kRect, rect);
59 }
60
GetRect() const61 CFX_FloatRect CPDFSDK_BAAnnot::GetRect() const {
62 return m_pAnnot->GetRect();
63 }
64
GetAnnotSubtype() const65 CPDF_Annot::Subtype CPDFSDK_BAAnnot::GetAnnotSubtype() const {
66 return m_pAnnot->GetSubtype();
67 }
68
DrawAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device,CPDF_Annot::AppearanceMode mode,const CPDF_RenderOptions * pOptions)69 void CPDFSDK_BAAnnot::DrawAppearance(CFX_RenderDevice* pDevice,
70 const CFX_Matrix& mtUser2Device,
71 CPDF_Annot::AppearanceMode mode,
72 const CPDF_RenderOptions* pOptions) {
73 m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, mtUser2Device,
74 mode, pOptions);
75 }
76
IsAppearanceValid()77 bool CPDFSDK_BAAnnot::IsAppearanceValid() {
78 return !!GetAnnotDict()->GetDictFor(pdfium::annotation::kAP);
79 }
80
SetAnnotName(const WideString & sName)81 void CPDFSDK_BAAnnot::SetAnnotName(const WideString& sName) {
82 CPDF_Dictionary* pDict = GetAnnotDict();
83 if (sName.IsEmpty())
84 pDict->RemoveFor(pdfium::annotation::kNM);
85 else
86 pDict->SetNewFor<CPDF_String>(pdfium::annotation::kNM, sName);
87 }
88
GetAnnotName() const89 WideString CPDFSDK_BAAnnot::GetAnnotName() const {
90 return GetAnnotDict()->GetUnicodeTextFor(pdfium::annotation::kNM);
91 }
92
SetFlags(uint32_t nFlags)93 void CPDFSDK_BAAnnot::SetFlags(uint32_t nFlags) {
94 GetAnnotDict()->SetNewFor<CPDF_Number>(pdfium::annotation::kF,
95 static_cast<int>(nFlags));
96 }
97
GetFlags() const98 uint32_t CPDFSDK_BAAnnot::GetFlags() const {
99 return GetAnnotDict()->GetIntegerFor(pdfium::annotation::kF);
100 }
101
SetAppState(const ByteString & str)102 void CPDFSDK_BAAnnot::SetAppState(const ByteString& str) {
103 CPDF_Dictionary* pDict = GetAnnotDict();
104 if (str.IsEmpty())
105 pDict->RemoveFor(pdfium::annotation::kAS);
106 else
107 pDict->SetNewFor<CPDF_String>(pdfium::annotation::kAS, str, false);
108 }
109
GetAppState() const110 ByteString CPDFSDK_BAAnnot::GetAppState() const {
111 return GetAnnotDict()->GetStringFor(pdfium::annotation::kAS);
112 }
113
SetBorderWidth(int nWidth)114 void CPDFSDK_BAAnnot::SetBorderWidth(int nWidth) {
115 CPDF_Array* pBorder =
116 GetAnnotDict()->GetArrayFor(pdfium::annotation::kBorder);
117 if (pBorder) {
118 pBorder->SetNewAt<CPDF_Number>(2, nWidth);
119 } else {
120 CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS");
121 if (!pBSDict)
122 pBSDict = GetAnnotDict()->SetNewFor<CPDF_Dictionary>("BS");
123 pBSDict->SetNewFor<CPDF_Number>("W", nWidth);
124 }
125 }
126
GetBorderWidth() const127 int CPDFSDK_BAAnnot::GetBorderWidth() const {
128 if (const CPDF_Array* pBorder =
129 GetAnnotDict()->GetArrayFor(pdfium::annotation::kBorder)) {
130 return pBorder->GetIntegerAt(2);
131 }
132
133 if (CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS"))
134 return pBSDict->GetIntegerFor("W", 1);
135
136 return 1;
137 }
138
SetBorderStyle(BorderStyle nStyle)139 void CPDFSDK_BAAnnot::SetBorderStyle(BorderStyle nStyle) {
140 CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS");
141 if (!pBSDict)
142 pBSDict = GetAnnotDict()->SetNewFor<CPDF_Dictionary>("BS");
143
144 const char* name = nullptr;
145 switch (nStyle) {
146 case BorderStyle::SOLID:
147 name = "S";
148 break;
149 case BorderStyle::DASH:
150 name = "D";
151 break;
152 case BorderStyle::BEVELED:
153 name = "B";
154 break;
155 case BorderStyle::INSET:
156 name = "I";
157 break;
158 case BorderStyle::UNDERLINE:
159 name = "U";
160 break;
161 default:
162 return;
163 }
164 pBSDict->SetNewFor<CPDF_Name>("S", name);
165 }
166
GetBorderStyle() const167 BorderStyle CPDFSDK_BAAnnot::GetBorderStyle() const {
168 CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS");
169 if (pBSDict) {
170 ByteString sBorderStyle = pBSDict->GetStringFor("S", "S");
171 if (sBorderStyle == "S")
172 return BorderStyle::SOLID;
173 if (sBorderStyle == "D")
174 return BorderStyle::DASH;
175 if (sBorderStyle == "B")
176 return BorderStyle::BEVELED;
177 if (sBorderStyle == "I")
178 return BorderStyle::INSET;
179 if (sBorderStyle == "U")
180 return BorderStyle::UNDERLINE;
181 }
182
183 const CPDF_Array* pBorder =
184 GetAnnotDict()->GetArrayFor(pdfium::annotation::kBorder);
185 if (pBorder) {
186 if (pBorder->size() >= 4) {
187 const CPDF_Array* pDP = pBorder->GetArrayAt(3);
188 if (pDP && pDP->size() > 0)
189 return BorderStyle::DASH;
190 }
191 }
192
193 return BorderStyle::SOLID;
194 }
195
IsVisible() const196 bool CPDFSDK_BAAnnot::IsVisible() const {
197 uint32_t nFlags = GetFlags();
198 return !((nFlags & pdfium::annotation_flags::kInvisible) ||
199 (nFlags & pdfium::annotation_flags::kHidden) ||
200 (nFlags & pdfium::annotation_flags::kNoView));
201 }
202
GetAction() const203 CPDF_Action CPDFSDK_BAAnnot::GetAction() const {
204 return CPDF_Action(GetAnnotDict()->GetDictFor("A"));
205 }
206
GetAAction() const207 CPDF_AAction CPDFSDK_BAAnnot::GetAAction() const {
208 return CPDF_AAction(GetAnnotDict()->GetDictFor("AA"));
209 }
210
GetAAction(CPDF_AAction::AActionType eAAT)211 CPDF_Action CPDFSDK_BAAnnot::GetAAction(CPDF_AAction::AActionType eAAT) {
212 CPDF_AAction AAction = GetAAction();
213 if (AAction.ActionExist(eAAT))
214 return AAction.GetAction(eAAT);
215
216 if (eAAT == CPDF_AAction::kButtonUp)
217 return GetAction();
218
219 return CPDF_Action(nullptr);
220 }
221
SetOpenState(bool bOpenState)222 void CPDFSDK_BAAnnot::SetOpenState(bool bOpenState) {
223 if (CPDF_Annot* pAnnot = m_pAnnot->GetPopupAnnot())
224 pAnnot->SetOpenState(bOpenState);
225 }
226
GetLayoutOrder() const227 int CPDFSDK_BAAnnot::GetLayoutOrder() const {
228 if (m_pAnnot->GetSubtype() == CPDF_Annot::Subtype::POPUP)
229 return 1;
230
231 return CPDFSDK_Annot::GetLayoutOrder();
232 }
233