Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h" | 9 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h" |
| 10 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | 10 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" |
| 11 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" | 11 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" |
| 12 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h" | 12 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h" |
| 13 #include "core/fpdfapi/fpdf_render/include/cpdf_rendercontext.h" | 13 #include "core/fpdfapi/fpdf_render/include/cpdf_rendercontext.h" |
| 14 #include "core/fpdfdoc/include/fpdf_doc.h" | 14 #include "core/fpdfdoc/include/fpdf_doc.h" |
| 15 | 15 |
| 16 namespace { | |
| 17 | |
| 18 const FX_CHAR* const g_sHighlightingMode[] = { | |
| 19 // Must match order of HighlightingMode enum. | |
| 20 "N", "I", "O", "P", "T"}; | |
| 21 | |
| 22 } // namespace | |
| 23 | |
| 16 CPDF_FormControl::CPDF_FormControl(CPDF_FormField* pField, | 24 CPDF_FormControl::CPDF_FormControl(CPDF_FormField* pField, |
| 17 CPDF_Dictionary* pWidgetDict) { | 25 CPDF_Dictionary* pWidgetDict) |
| 18 m_pField = pField; | 26 : m_pField(pField), |
| 19 m_pWidgetDict = pWidgetDict; | 27 m_pWidgetDict(pWidgetDict), |
| 20 m_pForm = m_pField->m_pForm; | 28 m_pForm(m_pField->m_pForm) {} |
| 21 } | 29 |
| 22 CFX_FloatRect CPDF_FormControl::GetRect() const { | 30 CFX_FloatRect CPDF_FormControl::GetRect() const { |
| 23 return m_pWidgetDict->GetRectBy("Rect"); | 31 return m_pWidgetDict->GetRectBy("Rect"); |
| 24 } | 32 } |
| 33 | |
| 25 CFX_ByteString CPDF_FormControl::GetOnStateName() const { | 34 CFX_ByteString CPDF_FormControl::GetOnStateName() const { |
| 26 ASSERT(GetType() == CPDF_FormField::CheckBox || | 35 ASSERT(GetType() == CPDF_FormField::CheckBox || |
| 27 GetType() == CPDF_FormField::RadioButton); | 36 GetType() == CPDF_FormField::RadioButton); |
| 28 CFX_ByteString csOn; | 37 CFX_ByteString csOn; |
| 29 CPDF_Dictionary* pAP = m_pWidgetDict->GetDictBy("AP"); | 38 CPDF_Dictionary* pAP = m_pWidgetDict->GetDictBy("AP"); |
| 30 if (!pAP) { | 39 if (!pAP) |
| 31 return csOn; | 40 return csOn; |
| 32 } | 41 |
| 33 CPDF_Dictionary* pN = pAP->GetDictBy("N"); | 42 CPDF_Dictionary* pN = pAP->GetDictBy("N"); |
| 34 if (!pN) { | 43 if (!pN) |
| 35 return csOn; | 44 return csOn; |
| 36 } | 45 |
| 37 for (const auto& it : *pN) { | 46 for (const auto& it : *pN) { |
| 38 if (it.first != "Off") { | 47 if (it.first != "Off") |
| 39 return it.first; | 48 return it.first; |
| 40 } | |
| 41 } | 49 } |
| 42 return CFX_ByteString(); | 50 return CFX_ByteString(); |
| 43 } | 51 } |
| 52 | |
| 44 void CPDF_FormControl::SetOnStateName(const CFX_ByteString& csOn) { | 53 void CPDF_FormControl::SetOnStateName(const CFX_ByteString& csOn) { |
| 45 ASSERT(GetType() == CPDF_FormField::CheckBox || | 54 ASSERT(GetType() == CPDF_FormField::CheckBox || |
| 46 GetType() == CPDF_FormField::RadioButton); | 55 GetType() == CPDF_FormField::RadioButton); |
| 47 CFX_ByteString csValue = csOn; | 56 CFX_ByteString csValue = csOn; |
| 48 if (csValue.IsEmpty()) { | 57 if (csValue.IsEmpty()) { |
| 49 csValue = "Yes"; | 58 csValue = "Yes"; |
| 50 } | 59 } |
| 51 if (csValue == "Off") { | 60 if (csValue == "Off") { |
| 52 csValue = "Yes"; | 61 csValue = "Yes"; |
| 53 } | 62 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 GetType() == CPDF_FormField::CheckBox) { | 101 GetType() == CPDF_FormField::CheckBox) { |
| 93 if (ToArray(FPDF_GetFieldAttr(m_pField->m_pDict, "Opt"))) { | 102 if (ToArray(FPDF_GetFieldAttr(m_pField->m_pDict, "Opt"))) { |
| 94 int iIndex = m_pField->GetControlIndex(this); | 103 int iIndex = m_pField->GetControlIndex(this); |
| 95 csOn.Format("%d", iIndex); | 104 csOn.Format("%d", iIndex); |
| 96 } | 105 } |
| 97 } | 106 } |
| 98 if (csOn.IsEmpty()) | 107 if (csOn.IsEmpty()) |
| 99 csOn = "Yes"; | 108 csOn = "Yes"; |
| 100 return csOn; | 109 return csOn; |
| 101 } | 110 } |
| 102 CFX_WideString CPDF_FormControl::GetExportValue() { | 111 |
| 112 CFX_WideString CPDF_FormControl::GetExportValue() const { | |
| 103 ASSERT(GetType() == CPDF_FormField::CheckBox || | 113 ASSERT(GetType() == CPDF_FormField::CheckBox || |
| 104 GetType() == CPDF_FormField::RadioButton); | 114 GetType() == CPDF_FormField::RadioButton); |
| 105 CFX_ByteString csOn = GetOnStateName(); | 115 CFX_ByteString csOn = GetOnStateName(); |
| 106 if (GetType() == CPDF_FormField::RadioButton || | 116 if (GetType() == CPDF_FormField::RadioButton || |
| 107 GetType() == CPDF_FormField::CheckBox) { | 117 GetType() == CPDF_FormField::CheckBox) { |
| 108 if (CPDF_Array* pArray = | 118 if (CPDF_Array* pArray = |
| 109 ToArray(FPDF_GetFieldAttr(m_pField->m_pDict, "Opt"))) { | 119 ToArray(FPDF_GetFieldAttr(m_pField->m_pDict, "Opt"))) { |
| 110 int iIndex = m_pField->GetControlIndex(this); | 120 int iIndex = m_pField->GetControlIndex(this); |
| 111 csOn = pArray->GetStringAt(iIndex); | 121 csOn = pArray->GetStringAt(iIndex); |
| 112 } | 122 } |
| 113 } | 123 } |
| 114 if (csOn.IsEmpty()) { | 124 if (csOn.IsEmpty()) |
| 115 csOn = "Yes"; | 125 csOn = "Yes"; |
| 116 } | 126 return PDF_DecodeText(csOn); |
| 117 CFX_WideString csWOn = PDF_DecodeText(csOn); | |
| 118 return csWOn; | |
| 119 } | 127 } |
| 120 | 128 |
| 121 bool CPDF_FormControl::IsChecked() const { | 129 bool CPDF_FormControl::IsChecked() const { |
| 122 ASSERT(GetType() == CPDF_FormField::CheckBox || | 130 ASSERT(GetType() == CPDF_FormField::CheckBox || |
| 123 GetType() == CPDF_FormField::RadioButton); | 131 GetType() == CPDF_FormField::RadioButton); |
| 124 CFX_ByteString csOn = GetOnStateName(); | 132 CFX_ByteString csOn = GetOnStateName(); |
| 125 CFX_ByteString csAS = m_pWidgetDict->GetStringBy("AS"); | 133 CFX_ByteString csAS = m_pWidgetDict->GetStringBy("AS"); |
| 126 return csAS == csOn; | 134 return csAS == csOn; |
| 127 } | 135 } |
| 128 | 136 |
| 129 bool CPDF_FormControl::IsDefaultChecked() const { | 137 bool CPDF_FormControl::IsDefaultChecked() const { |
| 130 ASSERT(GetType() == CPDF_FormField::CheckBox || | 138 ASSERT(GetType() == CPDF_FormField::CheckBox || |
| 131 GetType() == CPDF_FormField::RadioButton); | 139 GetType() == CPDF_FormField::RadioButton); |
| 132 CPDF_Object* pDV = FPDF_GetFieldAttr(m_pField->m_pDict, "DV"); | 140 CPDF_Object* pDV = FPDF_GetFieldAttr(m_pField->m_pDict, "DV"); |
| 133 if (!pDV) { | 141 if (!pDV) { |
| 134 return FALSE; | 142 return FALSE; |
| 135 } | 143 } |
| 136 CFX_ByteString csDV = pDV->GetString(); | 144 CFX_ByteString csDV = pDV->GetString(); |
| 137 CFX_ByteString csOn = GetOnStateName(); | 145 CFX_ByteString csOn = GetOnStateName(); |
| 138 return (csDV == csOn); | 146 return (csDV == csOn); |
| 139 } | 147 } |
| 140 | 148 |
| 141 void CPDF_FormControl::CheckControl(FX_BOOL bChecked) { | 149 void CPDF_FormControl::CheckControl(FX_BOOL bChecked) { |
| 142 ASSERT(GetType() == CPDF_FormField::CheckBox || | 150 ASSERT(GetType() == CPDF_FormField::CheckBox || |
| 143 GetType() == CPDF_FormField::RadioButton); | 151 GetType() == CPDF_FormField::RadioButton); |
| 144 CFX_ByteString csOn = GetOnStateName(); | 152 CFX_ByteString csOn = GetOnStateName(); |
| 145 CFX_ByteString csOldAS = m_pWidgetDict->GetStringBy("AS", "Off"); | 153 CFX_ByteString csOldAS = m_pWidgetDict->GetStringBy("AS", "Off"); |
| 146 CFX_ByteString csAS = "Off"; | 154 CFX_ByteString csAS = "Off"; |
| 147 if (bChecked) { | 155 if (bChecked) |
| 148 csAS = csOn; | 156 csAS = csOn; |
| 149 } | 157 if (csOldAS == csAS) |
| 150 if (csOldAS == csAS) { | |
| 151 return; | 158 return; |
| 152 } | |
| 153 m_pWidgetDict->SetAtName("AS", csAS); | 159 m_pWidgetDict->SetAtName("AS", csAS); |
| 154 m_pForm->m_bUpdated = TRUE; | |
| 155 } | 160 } |
| 156 CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, | 161 |
| 157 CPDF_Annot::AppearanceMode mode); | |
| 158 void CPDF_FormControl::DrawControl(CFX_RenderDevice* pDevice, | 162 void CPDF_FormControl::DrawControl(CFX_RenderDevice* pDevice, |
| 159 CFX_Matrix* pMatrix, | 163 CFX_Matrix* pMatrix, |
| 160 CPDF_Page* pPage, | 164 CPDF_Page* pPage, |
| 161 CPDF_Annot::AppearanceMode mode, | 165 CPDF_Annot::AppearanceMode mode, |
| 162 const CPDF_RenderOptions* pOptions) { | 166 const CPDF_RenderOptions* pOptions) { |
| 163 if (m_pWidgetDict->GetIntegerBy("F") & ANNOTFLAG_HIDDEN) { | 167 if (m_pWidgetDict->GetIntegerBy("F") & ANNOTFLAG_HIDDEN) |
| 164 return; | 168 return; |
| 165 } | 169 |
| 166 CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pWidgetDict, mode); | 170 CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pWidgetDict, mode); |
| 167 if (!pStream) { | 171 if (!pStream) |
| 168 return; | 172 return; |
| 169 } | 173 |
| 170 CFX_FloatRect form_bbox = pStream->GetDict()->GetRectBy("BBox"); | 174 CFX_FloatRect form_bbox = pStream->GetDict()->GetRectBy("BBox"); |
| 171 CFX_Matrix form_matrix = pStream->GetDict()->GetMatrixBy("Matrix"); | 175 CFX_Matrix form_matrix = pStream->GetDict()->GetMatrixBy("Matrix"); |
| 172 form_matrix.TransformRect(form_bbox); | 176 form_matrix.TransformRect(form_bbox); |
| 173 CFX_FloatRect arect = m_pWidgetDict->GetRectBy("Rect"); | 177 CFX_FloatRect arect = m_pWidgetDict->GetRectBy("Rect"); |
| 174 CFX_Matrix matrix; | 178 CFX_Matrix matrix; |
| 175 matrix.MatchRect(arect, form_bbox); | 179 matrix.MatchRect(arect, form_bbox); |
| 176 matrix.Concat(*pMatrix); | 180 matrix.Concat(*pMatrix); |
| 177 CPDF_Form form(m_pField->m_pForm->m_pDocument, | 181 CPDF_Form form(m_pField->m_pForm->m_pDocument, |
| 178 m_pField->m_pForm->m_pFormDict->GetDictBy("DR"), pStream); | 182 m_pField->m_pForm->m_pFormDict->GetDictBy("DR"), pStream); |
| 179 form.ParseContent(nullptr, nullptr, nullptr); | 183 form.ParseContent(nullptr, nullptr, nullptr); |
| 180 CPDF_RenderContext context(pPage); | 184 CPDF_RenderContext context(pPage); |
| 181 context.AppendLayer(&form, &matrix); | 185 context.AppendLayer(&form, &matrix); |
| 182 context.Render(pDevice, pOptions, nullptr); | 186 context.Render(pDevice, pOptions, nullptr); |
| 183 } | 187 } |
| 184 static const FX_CHAR* const g_sHighlightingMode[] = { | 188 |
| 185 // Must match order of HiglightingMode enum. | |
| 186 "N", "I", "O", "P", "T", nullptr}; | |
| 187 CPDF_FormControl::HighlightingMode CPDF_FormControl::GetHighlightingMode() { | 189 CPDF_FormControl::HighlightingMode CPDF_FormControl::GetHighlightingMode() { |
| 188 if (!m_pWidgetDict) { | 190 if (!m_pWidgetDict) |
| 189 return Invert; | 191 return Invert; |
| 190 } | 192 |
| 191 CFX_ByteString csH = m_pWidgetDict->GetStringBy("H", "I"); | 193 CFX_ByteString csH = m_pWidgetDict->GetStringBy("H", "I"); |
| 192 for (int i = 0; g_sHighlightingMode[i]; ++i) { | 194 for (size_t i = 0; FX_ArraySize(g_sHighlightingMode); ++i) { |
|
Wei Li
2016/05/23 22:26:14
i < FX_ArraySize(g_sHighlightingMode)?
Lei Zhang
2016/05/23 22:52:46
Uh, yes.
| |
| 193 if (csH == g_sHighlightingMode[i]) | 195 if (csH == g_sHighlightingMode[i]) |
| 194 return static_cast<HighlightingMode>(i); | 196 return static_cast<HighlightingMode>(i); |
| 195 } | 197 } |
| 196 return Invert; | 198 return Invert; |
| 197 } | 199 } |
| 198 | 200 |
| 199 CPDF_ApSettings CPDF_FormControl::GetMK() const { | 201 CPDF_ApSettings CPDF_FormControl::GetMK() const { |
| 200 return CPDF_ApSettings(m_pWidgetDict ? m_pWidgetDict->GetDictBy("MK") | 202 return CPDF_ApSettings(m_pWidgetDict ? m_pWidgetDict->GetDictBy("MK") |
| 201 : nullptr); | 203 : nullptr); |
| 202 } | 204 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 | 236 |
| 235 CPDF_IconFit CPDF_FormControl::GetIconFit() { | 237 CPDF_IconFit CPDF_FormControl::GetIconFit() { |
| 236 return GetMK().GetIconFit(); | 238 return GetMK().GetIconFit(); |
| 237 } | 239 } |
| 238 | 240 |
| 239 int CPDF_FormControl::GetTextPosition() { | 241 int CPDF_FormControl::GetTextPosition() { |
| 240 return GetMK().GetTextPosition(); | 242 return GetMK().GetTextPosition(); |
| 241 } | 243 } |
| 242 | 244 |
| 243 CPDF_Action CPDF_FormControl::GetAction() { | 245 CPDF_Action CPDF_FormControl::GetAction() { |
| 244 if (!m_pWidgetDict) { | 246 if (!m_pWidgetDict) |
| 245 return CPDF_Action(); | 247 return CPDF_Action(); |
| 246 } | 248 |
| 247 if (m_pWidgetDict->KeyExist("A")) { | 249 if (m_pWidgetDict->KeyExist("A")) |
| 248 return CPDF_Action(m_pWidgetDict->GetDictBy("A")); | 250 return CPDF_Action(m_pWidgetDict->GetDictBy("A")); |
| 249 } | 251 |
| 250 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "A"); | 252 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "A"); |
| 251 if (!pObj) { | 253 if (!pObj) |
| 252 return CPDF_Action(); | 254 return CPDF_Action(); |
| 253 } | 255 |
| 254 return CPDF_Action(pObj->GetDict()); | 256 return CPDF_Action(pObj->GetDict()); |
| 255 } | 257 } |
| 256 | 258 |
| 257 CPDF_AAction CPDF_FormControl::GetAdditionalAction() { | 259 CPDF_AAction CPDF_FormControl::GetAdditionalAction() { |
| 258 if (!m_pWidgetDict) | 260 if (!m_pWidgetDict) |
| 259 return CPDF_AAction(); | 261 return CPDF_AAction(); |
| 260 | 262 |
| 261 if (m_pWidgetDict->KeyExist("AA")) | 263 if (m_pWidgetDict->KeyExist("AA")) |
| 262 return CPDF_AAction(m_pWidgetDict->GetDictBy("AA")); | 264 return CPDF_AAction(m_pWidgetDict->GetDictBy("AA")); |
| 263 return m_pField->GetAdditionalAction(); | 265 return m_pField->GetAdditionalAction(); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 428 } | 430 } |
| 429 | 431 |
| 430 CPDF_IconFit CPDF_ApSettings::GetIconFit() const { | 432 CPDF_IconFit CPDF_ApSettings::GetIconFit() const { |
| 431 return CPDF_IconFit(m_pDict ? m_pDict->GetDictBy("IF") : nullptr); | 433 return CPDF_IconFit(m_pDict ? m_pDict->GetDictBy("IF") : nullptr); |
| 432 } | 434 } |
| 433 | 435 |
| 434 int CPDF_ApSettings::GetTextPosition() const { | 436 int CPDF_ApSettings::GetTextPosition() const { |
| 435 return m_pDict ? m_pDict->GetIntegerBy("TP", TEXTPOS_CAPTION) | 437 return m_pDict ? m_pDict->GetIntegerBy("TP", TEXTPOS_CAPTION) |
| 436 : TEXTPOS_CAPTION; | 438 : TEXTPOS_CAPTION; |
| 437 } | 439 } |
| OLD | NEW |