dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1 | // Copyright 2016 PDFium Authors. All rights reserved. |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
Lei Zhang | 95e854f | 2015-06-13 00:58:06 -0700 | [diff] [blame] | 4 | |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 5 | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 7 | #include "core/fpdfdoc/cpdf_interform.h" |
| 8 | |
| 9 | #include <utility> |
Dan Sinclair | 3ebd121 | 2016-03-09 09:59:23 -0500 | [diff] [blame] | 10 | #include <vector> |
| 11 | |
Lei Zhang | 2617056 | 2018-04-17 17:01:52 +0000 | [diff] [blame^] | 12 | #include "constants/stream_dict_common.h" |
dsinclair | bc5e6d2 | 2016-10-04 11:08:49 -0700 | [diff] [blame] | 13 | #include "core/fpdfapi/font/cpdf_font.h" |
| 14 | #include "core/fpdfapi/font/cpdf_fontencoding.h" |
dsinclair | 41872fa | 2016-10-04 11:29:35 -0700 | [diff] [blame] | 15 | #include "core/fpdfapi/page/cpdf_page.h" |
dsinclair | 488b7ad | 2016-10-04 11:55:50 -0700 | [diff] [blame] | 16 | #include "core/fpdfapi/parser/cfdf_document.h" |
| 17 | #include "core/fpdfapi/parser/cpdf_array.h" |
| 18 | #include "core/fpdfapi/parser/cpdf_document.h" |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 19 | #include "core/fpdfapi/parser/cpdf_name.h" |
tsepez | 10a2853 | 2016-10-10 18:45:55 -0700 | [diff] [blame] | 20 | #include "core/fpdfapi/parser/cpdf_reference.h" |
dsinclair | 488b7ad | 2016-10-04 11:55:50 -0700 | [diff] [blame] | 21 | #include "core/fpdfapi/parser/cpdf_string.h" |
Tom Sepez | a7b1559 | 2018-04-16 19:22:57 +0000 | [diff] [blame] | 22 | #include "core/fpdfapi/parser/fpdf_parser_utility.h" |
dsinclair | 1727aee | 2016-09-29 13:12:56 -0700 | [diff] [blame] | 23 | #include "core/fpdfdoc/cpdf_filespec.h" |
| 24 | #include "core/fpdfdoc/cpdf_formcontrol.h" |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 25 | #include "core/fxcrt/fx_codepage.h" |
dsinclair | 74a34fc | 2016-09-29 16:41:42 -0700 | [diff] [blame] | 26 | #include "core/fxge/cfx_substfont.h" |
| 27 | #include "core/fxge/fx_font.h" |
Tom Sepez | 6e72b2e | 2017-04-26 15:14:35 -0700 | [diff] [blame] | 28 | #include "third_party/base/ptr_util.h" |
Lei Zhang | cd2bb30 | 2015-12-22 13:49:44 -0800 | [diff] [blame] | 29 | #include "third_party/base/stl_util.h" |
Tom Sepez | eff208f | 2015-05-08 13:45:01 -0700 | [diff] [blame] | 30 | |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 31 | namespace { |
| 32 | |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 33 | const int nMaxRecursion = 32; |
Tom Sepez | eff208f | 2015-05-08 13:45:01 -0700 | [diff] [blame] | 34 | |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 35 | const struct SupportFieldEncoding { |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 36 | const char* m_name; |
Tom Sepez | 62a70f9 | 2016-03-21 15:00:20 -0700 | [diff] [blame] | 37 | uint16_t m_codePage; |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 38 | } g_fieldEncoding[] = { |
| 39 | {"BigFive", 950}, |
| 40 | {"GBK", 936}, |
| 41 | {"Shift-JIS", 932}, |
| 42 | {"UHC", 949}, |
| 43 | }; |
| 44 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 45 | WideString GetFieldValue(const CPDF_Dictionary& pFieldDict, |
| 46 | const ByteString& bsEncoding) { |
| 47 | const ByteString csBValue = pFieldDict.GetStringFor("V"); |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 48 | for (const auto& encoding : g_fieldEncoding) { |
| 49 | if (bsEncoding == encoding.m_name) |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 50 | return WideString::FromCodePage(csBValue.AsStringView(), |
| 51 | encoding.m_codePage); |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 52 | } |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 53 | ByteString csTemp = csBValue.Left(2); |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 54 | if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") |
| 55 | return PDF_DecodeText(csBValue); |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 56 | return WideString::FromLocal(csBValue.AsStringView()); |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 57 | } |
| 58 | |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 59 | void AddFont(CPDF_Dictionary*& pFormDict, |
| 60 | CPDF_Document* pDocument, |
| 61 | const CPDF_Font* pFont, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 62 | ByteString* csNameTag); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 63 | |
| 64 | void InitDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) { |
| 65 | if (!pDocument) |
| 66 | return; |
| 67 | |
| 68 | if (!pFormDict) { |
tsepez | 5913a6c | 2016-11-16 17:31:18 -0800 | [diff] [blame] | 69 | pFormDict = pDocument->NewIndirect<CPDF_Dictionary>(); |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 70 | pDocument->GetRoot()->SetNewFor<CPDF_Reference>("AcroForm", pDocument, |
| 71 | pFormDict->GetObjNum()); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 72 | } |
| 73 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 74 | ByteString csDA; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 75 | if (!pFormDict->KeyExist("DR")) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 76 | ByteString csBaseName; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 77 | uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); |
| 78 | CPDF_Font* pFont = CPDF_InterForm::AddStandardFont(pDocument, "Helvetica"); |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 79 | if (pFont) |
| 80 | AddFont(pFormDict, pDocument, pFont, &csBaseName); |
| 81 | |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 82 | if (charSet != FX_CHARSET_ANSI) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 83 | ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 84 | if (!pFont || csFontName != "Helvetica") { |
| 85 | pFont = CPDF_InterForm::AddNativeFont(pDocument); |
| 86 | if (pFont) { |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 87 | csBaseName.clear(); |
| 88 | AddFont(pFormDict, pDocument, pFont, &csBaseName); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 89 | } |
| 90 | } |
| 91 | } |
| 92 | if (pFont) |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 93 | csDA = "/" + PDF_NameEncode(csBaseName) + " 0 Tf"; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 94 | } |
| 95 | if (!csDA.IsEmpty()) |
| 96 | csDA += " "; |
| 97 | |
| 98 | csDA += "0 g"; |
| 99 | if (!pFormDict->KeyExist("DA")) |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 100 | pFormDict->SetNewFor<CPDF_String>("DA", csDA, false); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 101 | } |
| 102 | |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 103 | CPDF_Font* GetFont(CPDF_Dictionary* pFormDict, |
| 104 | CPDF_Document* pDocument, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 105 | const ByteString& csNameTag) { |
Dan Sinclair | 14094f2 | 2018-03-28 17:02:46 +0000 | [diff] [blame] | 106 | ByteString csAlias = PDF_NameDecode(csNameTag.AsStringView()); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 107 | if (!pFormDict || csAlias.IsEmpty()) |
| 108 | return nullptr; |
| 109 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 110 | CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 111 | if (!pDR) |
| 112 | return nullptr; |
| 113 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 114 | CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 115 | if (!pFonts) |
| 116 | return nullptr; |
| 117 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 118 | CPDF_Dictionary* pElement = pFonts->GetDictFor(csAlias); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 119 | if (!pElement) |
| 120 | return nullptr; |
| 121 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 122 | if (pElement->GetStringFor("Type") == "Font") |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 123 | return pDocument->LoadFont(pElement); |
| 124 | return nullptr; |
| 125 | } |
| 126 | |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 127 | CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict, |
| 128 | CPDF_Document* pDocument, |
| 129 | uint8_t charSet, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 130 | ByteString* csNameTag) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 131 | if (!pFormDict) |
| 132 | return nullptr; |
| 133 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 134 | CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 135 | if (!pDR) |
| 136 | return nullptr; |
| 137 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 138 | CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 139 | if (!pFonts) |
| 140 | return nullptr; |
| 141 | |
| 142 | for (const auto& it : *pFonts) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 143 | const ByteString& csKey = it.first; |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 144 | if (!it.second) |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 145 | continue; |
| 146 | |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 147 | CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect()); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 148 | if (!pElement) |
| 149 | continue; |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 150 | if (pElement->GetStringFor("Type") != "Font") |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 151 | continue; |
| 152 | CPDF_Font* pFind = pDocument->LoadFont(pElement); |
| 153 | if (!pFind) |
| 154 | continue; |
| 155 | |
| 156 | CFX_SubstFont* pSubst = pFind->GetSubstFont(); |
| 157 | if (!pSubst) |
| 158 | continue; |
| 159 | |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 160 | if (pSubst->m_Charset == static_cast<int>(charSet)) { |
| 161 | *csNameTag = csKey; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 162 | return pFind; |
| 163 | } |
| 164 | } |
| 165 | return nullptr; |
| 166 | } |
| 167 | |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 168 | bool FindFont(CPDF_Dictionary* pFormDict, |
| 169 | const CPDF_Font* pFont, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 170 | ByteString* csNameTag) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 171 | if (!pFormDict || !pFont) |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 172 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 173 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 174 | CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 175 | if (!pDR) |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 176 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 177 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 178 | CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 179 | if (!pFonts) |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 180 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 181 | |
| 182 | for (const auto& it : *pFonts) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 183 | const ByteString& csKey = it.first; |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 184 | if (!it.second) |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 185 | continue; |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 186 | CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect()); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 187 | if (!pElement) |
| 188 | continue; |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 189 | if (pElement->GetStringFor("Type") != "Font") |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 190 | continue; |
| 191 | if (pFont->GetFontDict() == pElement) { |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 192 | *csNameTag = csKey; |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 193 | return true; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 194 | } |
| 195 | } |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 196 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 197 | } |
| 198 | |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 199 | bool FindFont(CPDF_Dictionary* pFormDict, |
| 200 | CPDF_Document* pDocument, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 201 | ByteString csFontName, |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 202 | CPDF_Font*& pFont, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 203 | ByteString* csNameTag) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 204 | if (!pFormDict) |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 205 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 206 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 207 | CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 208 | if (!pDR) |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 209 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 210 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 211 | CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 212 | if (!pFonts) |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 213 | return false; |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 214 | |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 215 | if (csFontName.GetLength() > 0) |
| 216 | csFontName.Remove(' '); |
| 217 | |
| 218 | for (const auto& it : *pFonts) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 219 | const ByteString& csKey = it.first; |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 220 | if (!it.second) |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 221 | continue; |
| 222 | |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 223 | CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect()); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 224 | if (!pElement) |
| 225 | continue; |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 226 | if (pElement->GetStringFor("Type") != "Font") |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 227 | continue; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 228 | pFont = pDocument->LoadFont(pElement); |
| 229 | if (!pFont) |
| 230 | continue; |
| 231 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 232 | ByteString csBaseFont; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 233 | csBaseFont = pFont->GetBaseFont(); |
| 234 | csBaseFont.Remove(' '); |
| 235 | if (csBaseFont == csFontName) { |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 236 | *csNameTag = csKey; |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 237 | return true; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 238 | } |
| 239 | } |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 240 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 241 | } |
| 242 | |
| 243 | void AddFont(CPDF_Dictionary*& pFormDict, |
| 244 | CPDF_Document* pDocument, |
| 245 | const CPDF_Font* pFont, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 246 | ByteString* csNameTag) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 247 | if (!pFont) |
| 248 | return; |
| 249 | if (!pFormDict) |
| 250 | InitDict(pFormDict, pDocument); |
| 251 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 252 | ByteString csTag; |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 253 | if (FindFont(pFormDict, pFont, &csTag)) { |
| 254 | *csNameTag = csTag; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 255 | return; |
| 256 | } |
| 257 | if (!pFormDict) |
| 258 | InitDict(pFormDict, pDocument); |
| 259 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 260 | CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 261 | if (!pDR) |
| 262 | pDR = pFormDict->SetNewFor<CPDF_Dictionary>("DR"); |
| 263 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 264 | CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 265 | if (!pFonts) |
| 266 | pFonts = pDR->SetNewFor<CPDF_Dictionary>("Font"); |
| 267 | |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 268 | if (csNameTag->IsEmpty()) |
| 269 | *csNameTag = pFont->GetBaseFont(); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 270 | |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 271 | csNameTag->Remove(' '); |
| 272 | *csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, |
| 273 | csNameTag->c_str()); |
| 274 | pFonts->SetNewFor<CPDF_Reference>(*csNameTag, pDocument, |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 275 | pFont->GetFontDict()->GetObjNum()); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 276 | } |
| 277 | |
| 278 | CPDF_Font* AddNativeFont(CPDF_Dictionary*& pFormDict, |
| 279 | CPDF_Document* pDocument, |
| 280 | uint8_t charSet, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 281 | ByteString* csNameTag) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 282 | if (!pFormDict) |
| 283 | InitDict(pFormDict, pDocument); |
| 284 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 285 | ByteString csTemp; |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 286 | CPDF_Font* pFont = GetNativeFont(pFormDict, pDocument, charSet, &csTemp); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 287 | if (pFont) { |
Tom Sepez | c4a2b75 | 2017-04-07 13:56:13 -0700 | [diff] [blame] | 288 | *csNameTag = csTemp; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 289 | return pFont; |
| 290 | } |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 291 | ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 292 | if (!csFontName.IsEmpty() && |
| 293 | FindFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) { |
| 294 | return pFont; |
| 295 | } |
| 296 | pFont = CPDF_InterForm::AddNativeFont(charSet, pDocument); |
| 297 | if (pFont) |
| 298 | AddFont(pFormDict, pDocument, pFont, csNameTag); |
| 299 | |
| 300 | return pFont; |
| 301 | } |
| 302 | |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 303 | class CFieldNameExtractor { |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 304 | public: |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 305 | explicit CFieldNameExtractor(const WideString& full_name) |
tsepez | 4d31d0c | 2016-04-19 14:11:59 -0700 | [diff] [blame] | 306 | : m_FullName(full_name) { |
| 307 | m_pCur = m_FullName.c_str(); |
| 308 | m_pEnd = m_pCur + m_FullName.GetLength(); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 309 | } |
tsepez | 4d31d0c | 2016-04-19 14:11:59 -0700 | [diff] [blame] | 310 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 311 | void GetNext(const wchar_t*& pSubName, size_t& size) { |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 312 | pSubName = m_pCur; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 313 | while (m_pCur < m_pEnd && m_pCur[0] != L'.') |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 314 | m_pCur++; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 315 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 316 | size = static_cast<size_t>(m_pCur - pSubName); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 317 | if (m_pCur < m_pEnd && m_pCur[0] == L'.') |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 318 | m_pCur++; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 319 | } |
| 320 | |
| 321 | protected: |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 322 | WideString m_FullName; |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 323 | const wchar_t* m_pCur; |
| 324 | const wchar_t* m_pEnd; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 325 | }; |
tsepez | 4d31d0c | 2016-04-19 14:11:59 -0700 | [diff] [blame] | 326 | |
Dan Sinclair | 698aed7 | 2017-09-26 16:24:49 -0400 | [diff] [blame] | 327 | #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 328 | typedef struct { |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 329 | bool bFind; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 330 | LOGFONTA lf; |
| 331 | } PDF_FONTDATA; |
| 332 | |
| 333 | static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe, |
| 334 | NEWTEXTMETRICEX* lpntme, |
| 335 | DWORD FontType, |
| 336 | LPARAM lParam) { |
| 337 | if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@')) |
| 338 | return 1; |
| 339 | |
| 340 | PDF_FONTDATA* pData = (PDF_FONTDATA*)lParam; |
| 341 | memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA)); |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 342 | pData->bFind = true; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 343 | return 0; |
| 344 | } |
| 345 | |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 346 | bool RetrieveSpecificFont(LOGFONTA& lf) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 347 | PDF_FONTDATA fd; |
| 348 | memset(&fd, 0, sizeof(PDF_FONTDATA)); |
| 349 | HDC hDC = ::GetDC(nullptr); |
| 350 | EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd, |
| 351 | 0); |
| 352 | ::ReleaseDC(nullptr, hDC); |
| 353 | if (fd.bFind) |
| 354 | memcpy(&lf, &fd.lf, sizeof(LOGFONTA)); |
| 355 | |
| 356 | return fd.bFind; |
| 357 | } |
| 358 | |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 359 | bool RetrieveSpecificFont(uint8_t charSet, |
| 360 | uint8_t pitchAndFamily, |
| 361 | LPCSTR pcsFontName, |
| 362 | LOGFONTA& lf) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 363 | memset(&lf, 0, sizeof(LOGFONTA)); |
| 364 | lf.lfCharSet = charSet; |
| 365 | lf.lfPitchAndFamily = pitchAndFamily; |
| 366 | if (pcsFontName) { |
| 367 | // TODO(dsinclair): Should this be strncpy? |
Dan Sinclair | 85c8e7f | 2016-11-21 13:50:32 -0500 | [diff] [blame] | 368 | // NOLINTNEXTLINE(runtime/printf) |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 369 | strcpy(lf.lfFaceName, pcsFontName); |
| 370 | } |
| 371 | return RetrieveSpecificFont(lf); |
| 372 | } |
Dan Sinclair | 698aed7 | 2017-09-26 16:24:49 -0400 | [diff] [blame] | 373 | #endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 374 | |
| 375 | } // namespace |
| 376 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 377 | class CFieldTree { |
| 378 | public: |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 379 | class Node { |
| 380 | public: |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 381 | Node() : m_pField(nullptr), m_level(0) {} |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 382 | Node(const WideString& short_name, int level) |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 383 | : m_ShortName(short_name), m_level(level) {} |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 384 | ~Node() {} |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 385 | |
Nicolas Pena | 0b18e15 | 2017-04-05 16:34:50 -0400 | [diff] [blame] | 386 | void AddChildNode(std::unique_ptr<Node> pNode) { |
| 387 | m_Children.push_back(std::move(pNode)); |
| 388 | } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 389 | |
| 390 | size_t GetChildrenCount() const { return m_Children.size(); } |
| 391 | |
Nicolas Pena | 0b18e15 | 2017-04-05 16:34:50 -0400 | [diff] [blame] | 392 | Node* GetChildAt(size_t i) { return m_Children[i].get(); } |
| 393 | const Node* GetChildAt(size_t i) const { return m_Children[i].get(); } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 394 | |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 395 | CPDF_FormField* GetFieldAtIndex(size_t index) { |
| 396 | size_t nFieldsToGo = index; |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 397 | return GetFieldInternal(&nFieldsToGo); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 398 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 399 | |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 400 | size_t CountFields() const { return CountFieldsInternal(); } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 401 | |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 402 | void SetField(std::unique_ptr<CPDF_FormField> pField) { |
| 403 | m_pField = std::move(pField); |
| 404 | } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 405 | |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 406 | CPDF_FormField* GetField() const { return m_pField.get(); } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 407 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 408 | const WideString& GetShortName() const { return m_ShortName; } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 409 | |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 410 | int GetLevel() const { return m_level; } |
Lei Zhang | 7831f57 | 2017-04-28 11:51:08 -0700 | [diff] [blame] | 411 | |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 412 | private: |
| 413 | CPDF_FormField* GetFieldInternal(size_t* pFieldsToGo) { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 414 | if (m_pField) { |
| 415 | if (*pFieldsToGo == 0) |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 416 | return m_pField.get(); |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 417 | |
| 418 | --*pFieldsToGo; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 419 | } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 420 | for (size_t i = 0; i < GetChildrenCount(); ++i) { |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 421 | CPDF_FormField* pField = GetChildAt(i)->GetFieldInternal(pFieldsToGo); |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 422 | if (pField) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 423 | return pField; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 424 | } |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 425 | return nullptr; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 426 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 427 | |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 428 | size_t CountFieldsInternal() const { |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 429 | size_t count = 0; |
thestig | 5ef75ba | 2016-09-28 16:53:10 -0700 | [diff] [blame] | 430 | if (m_pField) |
| 431 | ++count; |
| 432 | |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 433 | for (size_t i = 0; i < GetChildrenCount(); ++i) |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 434 | count += GetChildAt(i)->CountFieldsInternal(); |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 435 | return count; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 436 | } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 437 | |
Nicolas Pena | 0b18e15 | 2017-04-05 16:34:50 -0400 | [diff] [blame] | 438 | std::vector<std::unique_ptr<Node>> m_Children; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 439 | WideString m_ShortName; |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 440 | std::unique_ptr<CPDF_FormField> m_pField; |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 441 | const int m_level; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 442 | }; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 443 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 444 | CFieldTree(); |
| 445 | ~CFieldTree(); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 446 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 447 | bool SetField(const WideString& full_name, |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 448 | std::unique_ptr<CPDF_FormField> pField); |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 449 | CPDF_FormField* GetField(const WideString& full_name); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 450 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 451 | Node* FindNode(const WideString& full_name); |
| 452 | Node* AddChild(Node* pParent, const WideString& short_name); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 453 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 454 | Node* Lookup(Node* pParent, const WideString& short_name); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 455 | |
| 456 | Node m_Root; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 457 | }; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 458 | |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 459 | CFieldTree::CFieldTree() {} |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 460 | |
Nicolas Pena | 0b18e15 | 2017-04-05 16:34:50 -0400 | [diff] [blame] | 461 | CFieldTree::~CFieldTree() {} |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 462 | |
| 463 | CFieldTree::Node* CFieldTree::AddChild(Node* pParent, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 464 | const WideString& short_name) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 465 | if (!pParent) |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 466 | return nullptr; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 467 | |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 468 | int level = pParent->GetLevel() + 1; |
| 469 | if (level > nMaxRecursion) |
| 470 | return nullptr; |
| 471 | |
| 472 | auto pNew = pdfium::MakeUnique<Node>(short_name, pParent->GetLevel() + 1); |
Nicolas Pena | 0b18e15 | 2017-04-05 16:34:50 -0400 | [diff] [blame] | 473 | Node* pChild = pNew.get(); |
| 474 | pParent->AddChildNode(std::move(pNew)); |
| 475 | return pChild; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 476 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 477 | |
| 478 | CFieldTree::Node* CFieldTree::Lookup(Node* pParent, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 479 | const WideString& short_name) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 480 | if (!pParent) |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 481 | return nullptr; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 482 | |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 483 | for (size_t i = 0; i < pParent->GetChildrenCount(); ++i) { |
| 484 | Node* pNode = pParent->GetChildAt(i); |
| 485 | if (pNode->GetShortName() == short_name) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 486 | return pNode; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 487 | } |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 488 | return nullptr; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 489 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 490 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 491 | bool CFieldTree::SetField(const WideString& full_name, |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 492 | std::unique_ptr<CPDF_FormField> pField) { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 493 | if (full_name.IsEmpty()) |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 494 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 495 | |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 496 | CFieldNameExtractor name_extractor(full_name); |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 497 | const wchar_t* pName; |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 498 | size_t nLength; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 499 | name_extractor.GetNext(pName, nLength); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 500 | Node* pNode = &m_Root; |
| 501 | Node* pLast = nullptr; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 502 | while (nLength > 0) { |
| 503 | pLast = pNode; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 504 | WideString name = WideString(pName, nLength); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 505 | pNode = Lookup(pLast, name); |
| 506 | if (!pNode) |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 507 | pNode = AddChild(pLast, name); |
Lei Zhang | 9ebdfcb | 2017-04-28 12:31:39 -0700 | [diff] [blame] | 508 | if (!pNode) |
| 509 | return false; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 510 | |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 511 | name_extractor.GetNext(pName, nLength); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 512 | } |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 513 | if (pNode == &m_Root) |
| 514 | return false; |
| 515 | |
| 516 | pNode->SetField(std::move(pField)); |
| 517 | return true; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 518 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 519 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 520 | CPDF_FormField* CFieldTree::GetField(const WideString& full_name) { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 521 | if (full_name.IsEmpty()) |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 522 | return nullptr; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 523 | |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 524 | CFieldNameExtractor name_extractor(full_name); |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 525 | const wchar_t* pName; |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 526 | size_t nLength; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 527 | name_extractor.GetNext(pName, nLength); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 528 | Node* pNode = &m_Root; |
| 529 | Node* pLast = nullptr; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 530 | while (nLength > 0 && pNode) { |
| 531 | pLast = pNode; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 532 | WideString name = WideString(pName, nLength); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 533 | pNode = Lookup(pLast, name); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 534 | name_extractor.GetNext(pName, nLength); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 535 | } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 536 | return pNode ? pNode->GetField() : nullptr; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 537 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 538 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 539 | CFieldTree::Node* CFieldTree::FindNode(const WideString& full_name) { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 540 | if (full_name.IsEmpty()) |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 541 | return nullptr; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 542 | |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 543 | CFieldNameExtractor name_extractor(full_name); |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 544 | const wchar_t* pName; |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 545 | size_t nLength; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 546 | name_extractor.GetNext(pName, nLength); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 547 | Node* pNode = &m_Root; |
| 548 | Node* pLast = nullptr; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 549 | while (nLength > 0 && pNode) { |
| 550 | pLast = pNode; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 551 | WideString name = WideString(pName, nLength); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 552 | pNode = Lookup(pLast, name); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 553 | name_extractor.GetNext(pName, nLength); |
| 554 | } |
| 555 | return pNode; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 556 | } |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 557 | |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 558 | CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, |
| 559 | CPDF_Document* pDocument, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 560 | ByteString* csNameTag) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 561 | uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); |
| 562 | return AddNativeFont(pFormDict, pDocument, charSet, csNameTag); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 563 | } |
thestig | 907a522 | 2016-06-21 14:38:27 -0700 | [diff] [blame] | 564 | |
| 565 | // static |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 566 | uint8_t CPDF_InterForm::GetNativeCharSet() { |
Dan Sinclair | 698aed7 | 2017-09-26 16:24:49 -0400 | [diff] [blame] | 567 | #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 568 | uint8_t charSet = FX_CHARSET_ANSI; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 569 | UINT iCodePage = ::GetACP(); |
| 570 | switch (iCodePage) { |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 571 | case FX_CODEPAGE_ShiftJIS: |
| 572 | charSet = FX_CHARSET_ShiftJIS; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 573 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 574 | case FX_CODEPAGE_ChineseSimplified: |
| 575 | charSet = FX_CHARSET_ChineseSimplified; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 576 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 577 | case FX_CODEPAGE_ChineseTraditional: |
| 578 | charSet = FX_CHARSET_ChineseTraditional; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 579 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 580 | case FX_CODEPAGE_MSWin_WesternEuropean: |
| 581 | charSet = FX_CHARSET_ANSI; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 582 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 583 | case FX_CODEPAGE_MSDOS_Thai: |
| 584 | charSet = FX_CHARSET_Thai; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 585 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 586 | case FX_CODEPAGE_Hangul: |
| 587 | charSet = FX_CHARSET_Hangul; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 588 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 589 | case FX_CODEPAGE_UTF16LE: |
| 590 | charSet = FX_CHARSET_ANSI; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 591 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 592 | case FX_CODEPAGE_MSWin_EasternEuropean: |
| 593 | charSet = FX_CHARSET_MSWin_EasternEuropean; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 594 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 595 | case FX_CODEPAGE_MSWin_Cyrillic: |
| 596 | charSet = FX_CHARSET_MSWin_Cyrillic; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 597 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 598 | case FX_CODEPAGE_MSWin_Greek: |
| 599 | charSet = FX_CHARSET_MSWin_Greek; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 600 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 601 | case FX_CODEPAGE_MSWin_Turkish: |
| 602 | charSet = FX_CHARSET_MSWin_Turkish; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 603 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 604 | case FX_CODEPAGE_MSWin_Hebrew: |
| 605 | charSet = FX_CHARSET_MSWin_Hebrew; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 606 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 607 | case FX_CODEPAGE_MSWin_Arabic: |
| 608 | charSet = FX_CHARSET_MSWin_Arabic; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 609 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 610 | case FX_CODEPAGE_MSWin_Baltic: |
| 611 | charSet = FX_CHARSET_MSWin_Baltic; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 612 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 613 | case FX_CODEPAGE_MSWin_Vietnamese: |
| 614 | charSet = FX_CHARSET_MSWin_Vietnamese; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 615 | break; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 616 | case FX_CODEPAGE_Johab: |
| 617 | charSet = FX_CHARSET_Johab; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 618 | break; |
| 619 | } |
| 620 | return charSet; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 621 | #else |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 622 | return 0; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 623 | #endif |
| 624 | } |
Lei Zhang | 0c0d8bd | 2015-11-17 17:50:23 -0800 | [diff] [blame] | 625 | |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 626 | CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument) |
| 627 | : m_pDocument(pDocument), |
| 628 | m_pFormDict(nullptr), |
Tom Sepez | 6e72b2e | 2017-04-26 15:14:35 -0700 | [diff] [blame] | 629 | m_pFieldTree(pdfium::MakeUnique<CFieldTree>()), |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 630 | m_pFormNotify(nullptr) { |
| 631 | CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); |
| 632 | if (!pRoot) |
| 633 | return; |
| 634 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 635 | m_pFormDict = pRoot->GetDictFor("AcroForm"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 636 | if (!m_pFormDict) |
| 637 | return; |
| 638 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 639 | CPDF_Array* pFields = m_pFormDict->GetArrayFor("Fields"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 640 | if (!pFields) |
| 641 | return; |
| 642 | |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 643 | for (size_t i = 0; i < pFields->GetCount(); ++i) |
| 644 | LoadField(pFields->GetDictAt(i), 0); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 645 | } |
| 646 | |
Tom Sepez | 655c783 | 2017-05-23 17:10:46 -0700 | [diff] [blame] | 647 | CPDF_InterForm::~CPDF_InterForm() {} |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 648 | |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 649 | bool CPDF_InterForm::s_bUpdateAP = true; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 650 | |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 651 | bool CPDF_InterForm::IsUpdateAPEnabled() { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 652 | return s_bUpdateAP; |
| 653 | } |
| 654 | |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 655 | void CPDF_InterForm::SetUpdateAP(bool bUpdateAP) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 656 | s_bUpdateAP = bUpdateAP; |
| 657 | } |
| 658 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 659 | ByteString CPDF_InterForm::GenerateNewResourceName( |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 660 | const CPDF_Dictionary* pResDict, |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 661 | const char* csType, |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 662 | int iMinLen, |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 663 | const char* csPrefix) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 664 | ByteString csStr = csPrefix; |
| 665 | ByteString csBType = csType; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 666 | if (csStr.IsEmpty()) { |
| 667 | if (csBType == "ExtGState") |
| 668 | csStr = "GS"; |
| 669 | else if (csBType == "ColorSpace") |
| 670 | csStr = "CS"; |
| 671 | else if (csBType == "Font") |
| 672 | csStr = "ZiTi"; |
| 673 | else |
| 674 | csStr = "Res"; |
| 675 | } |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 676 | ByteString csTmp = csStr; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 677 | int iCount = csStr.GetLength(); |
| 678 | int m = 0; |
| 679 | if (iMinLen > 0) { |
Lei Zhang | fe2cd4d | 2017-11-22 20:04:12 +0000 | [diff] [blame] | 680 | csTmp.clear(); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 681 | while (m < iMinLen && m < iCount) |
| 682 | csTmp += csStr[m++]; |
| 683 | while (m < iMinLen) { |
| 684 | csTmp += '0' + m % 10; |
| 685 | m++; |
| 686 | } |
| 687 | } else { |
| 688 | m = iCount; |
| 689 | } |
| 690 | if (!pResDict) |
| 691 | return csTmp; |
| 692 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 693 | CPDF_Dictionary* pDict = pResDict->GetDictFor(csType); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 694 | if (!pDict) |
| 695 | return csTmp; |
| 696 | |
| 697 | int num = 0; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 698 | ByteString bsNum; |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 699 | while (true) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 700 | ByteString csKey = csTmp + bsNum; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 701 | if (!pDict->KeyExist(csKey)) |
| 702 | return csKey; |
| 703 | if (m < iCount) |
| 704 | csTmp += csStr[m++]; |
| 705 | else |
Dan Sinclair | 1c4735a | 2017-11-16 22:08:07 +0000 | [diff] [blame] | 706 | bsNum = ByteString::Format("%d", num++); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 707 | |
| 708 | m++; |
| 709 | } |
| 710 | return csTmp; |
| 711 | } |
| 712 | |
| 713 | CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 714 | ByteString csFontName) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 715 | if (!pDocument || csFontName.IsEmpty()) |
| 716 | return nullptr; |
| 717 | |
| 718 | if (csFontName == "ZapfDingbats") |
| 719 | return pDocument->AddStandardFont(csFontName.c_str(), nullptr); |
| 720 | |
| 721 | CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI); |
| 722 | return pDocument->AddStandardFont(csFontName.c_str(), &encoding); |
| 723 | } |
| 724 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 725 | ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) { |
| 726 | ByteString csFontName; |
Dan Sinclair | 698aed7 | 2017-09-26 16:24:49 -0400 | [diff] [blame] | 727 | #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 728 | LOGFONTA lf = {}; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 729 | if (charSet == FX_CHARSET_ANSI) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 730 | csFontName = "Helvetica"; |
| 731 | return csFontName; |
| 732 | } |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 733 | bool bRet = false; |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 734 | if (charSet == FX_CHARSET_ShiftJIS) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 735 | bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, |
| 736 | "MS Mincho", lf); |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 737 | } else if (charSet == FX_CHARSET_ChineseSimplified) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 738 | bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun", |
| 739 | lf); |
Dan Sinclair | f51a02a | 2017-04-19 12:46:53 -0400 | [diff] [blame] | 740 | } else if (charSet == FX_CHARSET_ChineseTraditional) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 741 | bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU", |
| 742 | lf); |
| 743 | } |
| 744 | if (!bRet) { |
| 745 | bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, |
| 746 | "Arial Unicode MS", lf); |
| 747 | } |
| 748 | if (!bRet) { |
| 749 | bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, |
| 750 | "Microsoft Sans Serif", lf); |
| 751 | } |
| 752 | if (!bRet) { |
| 753 | bRet = |
| 754 | RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, nullptr, lf); |
| 755 | } |
| 756 | if (bRet) { |
| 757 | if (pLogFont) |
| 758 | memcpy(pLogFont, &lf, sizeof(LOGFONTA)); |
| 759 | |
| 760 | csFontName = lf.lfFaceName; |
| 761 | return csFontName; |
| 762 | } |
| 763 | #endif |
| 764 | return csFontName; |
| 765 | } |
| 766 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 767 | CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet, |
Lei Zhang | 0c0d8bd | 2015-11-17 17:50:23 -0800 | [diff] [blame] | 768 | CPDF_Document* pDocument) { |
| 769 | if (!pDocument) |
| 770 | return nullptr; |
| 771 | |
Dan Sinclair | 698aed7 | 2017-09-26 16:24:49 -0400 | [diff] [blame] | 772 | #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 773 | LOGFONTA lf; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 774 | ByteString csFontName = GetNativeFont(charSet, &lf); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 775 | if (!csFontName.IsEmpty()) { |
Lei Zhang | 0c0d8bd | 2015-11-17 17:50:23 -0800 | [diff] [blame] | 776 | if (csFontName == "Helvetica") |
| 777 | return AddStandardFont(pDocument, csFontName); |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 778 | return pDocument->AddWindowsFont(&lf, false, true); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 779 | } |
| 780 | #endif |
Lei Zhang | 0c0d8bd | 2015-11-17 17:50:23 -0800 | [diff] [blame] | 781 | return nullptr; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 782 | } |
Lei Zhang | 0c0d8bd | 2015-11-17 17:50:23 -0800 | [diff] [blame] | 783 | |
| 784 | CPDF_Font* CPDF_InterForm::AddNativeFont(CPDF_Document* pDocument) { |
| 785 | return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 786 | } |
Lei Zhang | 0c0d8bd | 2015-11-17 17:50:23 -0800 | [diff] [blame] | 787 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 788 | size_t CPDF_InterForm::CountFields(const WideString& csFieldName) const { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 789 | if (csFieldName.IsEmpty()) |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 790 | return m_pFieldTree->m_Root.CountFields(); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 791 | |
| 792 | CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName); |
Lei Zhang | 412e908 | 2015-12-14 18:34:00 -0800 | [diff] [blame] | 793 | return pNode ? pNode->CountFields() : 0; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 794 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 795 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 796 | CPDF_FormField* CPDF_InterForm::GetField(uint32_t index, |
| 797 | const WideString& csFieldName) const { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 798 | if (csFieldName.IsEmpty()) |
| 799 | return m_pFieldTree->m_Root.GetFieldAtIndex(index); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 800 | |
| 801 | CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName); |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 802 | return pNode ? pNode->GetFieldAtIndex(index) : nullptr; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 803 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 804 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 805 | CPDF_FormField* CPDF_InterForm::GetFieldByDict( |
| 806 | CPDF_Dictionary* pFieldDict) const { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 807 | if (!pFieldDict) |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 808 | return nullptr; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 809 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 810 | WideString csWName = FPDF_GetFullName(pFieldDict); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 811 | return m_pFieldTree->GetField(csWName); |
| 812 | } |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 813 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 814 | CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, |
Dan Sinclair | b45ea1f | 2017-02-21 14:27:59 -0500 | [diff] [blame] | 815 | const CFX_PointF& point, |
| 816 | |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 817 | int* z_order) const { |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 818 | CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayFor("Annots"); |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 819 | if (!pAnnotList) |
| 820 | return nullptr; |
| 821 | |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 822 | for (size_t i = pAnnotList->GetCount(); i > 0; --i) { |
| 823 | size_t annot_index = i - 1; |
Wei Li | 9b76113 | 2016-01-29 15:44:20 -0800 | [diff] [blame] | 824 | CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(annot_index); |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 825 | if (!pAnnot) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 826 | continue; |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 827 | |
| 828 | const auto it = m_ControlMap.find(pAnnot); |
| 829 | if (it == m_ControlMap.end()) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 830 | continue; |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 831 | |
tsepez | d18b867 | 2017-01-10 10:19:04 -0800 | [diff] [blame] | 832 | CPDF_FormControl* pControl = it->second.get(); |
Dan Sinclair | b45ea1f | 2017-02-21 14:27:59 -0500 | [diff] [blame] | 833 | if (!pControl->GetRect().Contains(point)) |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 834 | continue; |
| 835 | |
| 836 | if (z_order) |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 837 | *z_order = static_cast<int>(annot_index); |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 838 | return pControl; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 839 | } |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 840 | return nullptr; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 841 | } |
Tom Sepez | 2f2ffec | 2015-07-23 14:42:09 -0700 | [diff] [blame] | 842 | |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 843 | CPDF_FormControl* CPDF_InterForm::GetControlByDict( |
Lei Zhang | 1b700c3 | 2015-10-30 23:55:35 -0700 | [diff] [blame] | 844 | const CPDF_Dictionary* pWidgetDict) const { |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 845 | const auto it = m_ControlMap.find(pWidgetDict); |
tsepez | d18b867 | 2017-01-10 10:19:04 -0800 | [diff] [blame] | 846 | return it != m_ControlMap.end() ? it->second.get() : nullptr; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 847 | } |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 848 | |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 849 | bool CPDF_InterForm::NeedConstructAP() const { |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 850 | return m_pFormDict && m_pFormDict->GetBooleanFor("NeedAppearances"); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 851 | } |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 852 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 853 | int CPDF_InterForm::CountFieldsInCalculationOrder() { |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 854 | if (!m_pFormDict) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 855 | return 0; |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 856 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 857 | CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO"); |
Lei Zhang | 412e908 | 2015-12-14 18:34:00 -0800 | [diff] [blame] | 858 | return pArray ? pArray->GetCount() : 0; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 859 | } |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 860 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 861 | CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index) { |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 862 | if (!m_pFormDict || index < 0) |
| 863 | return nullptr; |
| 864 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 865 | CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO"); |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 866 | if (!pArray) |
| 867 | return nullptr; |
| 868 | |
| 869 | CPDF_Dictionary* pElement = ToDictionary(pArray->GetDirectObjectAt(index)); |
| 870 | return pElement ? GetFieldByDict(pElement) : nullptr; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 871 | } |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 872 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 873 | int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) { |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 874 | if (!m_pFormDict || !pField) |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 875 | return -1; |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 876 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 877 | CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO"); |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 878 | if (!pArray) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 879 | return -1; |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 880 | |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 881 | for (size_t i = 0; i < pArray->GetCount(); i++) { |
tsepez | bd56755 | 2016-03-29 14:51:50 -0700 | [diff] [blame] | 882 | CPDF_Object* pElement = pArray->GetDirectObjectAt(i); |
Nicolas Pena | 03f0fb0 | 2017-04-19 17:38:54 -0400 | [diff] [blame] | 883 | if (pElement == pField->GetDict()) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 884 | return i; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 885 | } |
| 886 | return -1; |
| 887 | } |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 888 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 889 | CPDF_Font* CPDF_InterForm::GetFormFont(ByteString csNameTag) const { |
Tom Sepez | d0409af | 2017-05-25 15:53:57 -0700 | [diff] [blame] | 890 | return GetFont(m_pFormDict.Get(), m_pDocument.Get(), csNameTag); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 891 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 892 | |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 893 | CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() const { |
Wei Li | 0fc6b25 | 2016-03-01 16:29:41 -0800 | [diff] [blame] | 894 | if (!m_pFormDict) |
| 895 | return CPDF_DefaultAppearance(); |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 896 | return CPDF_DefaultAppearance(m_pFormDict->GetStringFor("DA")); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 897 | } |
Wei Li | 0fc6b25 | 2016-03-01 16:29:41 -0800 | [diff] [blame] | 898 | |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 899 | int CPDF_InterForm::GetFormAlignment() const { |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 900 | return m_pFormDict ? m_pFormDict->GetIntegerFor("Q", 0) : 0; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 901 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 902 | |
dan sinclair | 7544a4b | 2018-03-08 15:19:50 +0000 | [diff] [blame] | 903 | void CPDF_InterForm::ResetForm(const std::vector<CPDF_FormField*>& fields, |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 904 | bool bIncludeOrExclude, |
| 905 | bool bNotify) { |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 906 | size_t nCount = m_pFieldTree->m_Root.CountFields(); |
| 907 | for (size_t i = 0; i < nCount; ++i) { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 908 | CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 909 | if (!pField) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 910 | continue; |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 911 | |
Lei Zhang | cd2bb30 | 2015-12-22 13:49:44 -0800 | [diff] [blame] | 912 | if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 913 | pField->ResetField(bNotify); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 914 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 915 | if (bNotify && m_pFormNotify) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 916 | m_pFormNotify->AfterFormReset(this); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 917 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 918 | |
dan sinclair | 7544a4b | 2018-03-08 15:19:50 +0000 | [diff] [blame] | 919 | void CPDF_InterForm::ResetForm(bool bNotify) { |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 920 | size_t nCount = m_pFieldTree->m_Root.CountFields(); |
| 921 | for (size_t i = 0; i < nCount; ++i) { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 922 | CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 923 | if (!pField) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 924 | continue; |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 925 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 926 | pField->ResetField(bNotify); |
| 927 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 928 | if (bNotify && m_pFormNotify) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 929 | m_pFormNotify->AfterFormReset(this); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 930 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 931 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 932 | void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 933 | if (nLevel > nMaxRecursion) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 934 | return; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 935 | if (!pFieldDict) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 936 | return; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 937 | |
tsepez | b5e8f14 | 2016-03-25 15:18:35 -0700 | [diff] [blame] | 938 | uint32_t dwParentObjNum = pFieldDict->GetObjNum(); |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 939 | CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids"); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 940 | if (!pKids) { |
| 941 | AddTerminalField(pFieldDict); |
| 942 | return; |
| 943 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 944 | |
Wei Li | 9b76113 | 2016-01-29 15:44:20 -0800 | [diff] [blame] | 945 | CPDF_Dictionary* pFirstKid = pKids->GetDictAt(0); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 946 | if (!pFirstKid) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 947 | return; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 948 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 949 | if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) { |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 950 | for (size_t i = 0; i < pKids->GetCount(); i++) { |
Wei Li | 9b76113 | 2016-01-29 15:44:20 -0800 | [diff] [blame] | 951 | CPDF_Dictionary* pChildDict = pKids->GetDictAt(i); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 952 | if (pChildDict) { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 953 | if (pChildDict->GetObjNum() != dwParentObjNum) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 954 | LoadField(pChildDict, nLevel + 1); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 955 | } |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 956 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 957 | } else { |
| 958 | AddTerminalField(pFieldDict); |
| 959 | } |
| 960 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 961 | |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 962 | bool CPDF_InterForm::HasXFAForm() const { |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 963 | return m_pFormDict && m_pFormDict->GetArrayFor("XFA"); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 964 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 965 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 966 | void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) { |
Tom Sepez | 4cb82ee | 2017-05-22 15:15:30 -0700 | [diff] [blame] | 967 | CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get(); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 968 | if (!pPageDict) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 969 | return; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 970 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 971 | CPDF_Array* pAnnots = pPageDict->GetArrayFor("Annots"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 972 | if (!pAnnots) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 973 | return; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 974 | |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 975 | for (size_t i = 0; i < pAnnots->GetCount(); i++) { |
Wei Li | 9b76113 | 2016-01-29 15:44:20 -0800 | [diff] [blame] | 976 | CPDF_Dictionary* pAnnot = pAnnots->GetDictAt(i); |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 977 | if (pAnnot && pAnnot->GetStringFor("Subtype") == "Widget") |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 978 | LoadField(pAnnot, 0); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 979 | } |
| 980 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 981 | |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 982 | void CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { |
weili | ab5a20d | 2016-12-07 11:32:52 -0800 | [diff] [blame] | 983 | if (!pFieldDict->KeyExist("FT")) { |
| 984 | // Key "FT" is required for terminal fields, it is also inheritable. |
| 985 | CPDF_Dictionary* pParentDict = pFieldDict->GetDictFor("Parent"); |
| 986 | if (!pParentDict || !pParentDict->KeyExist("FT")) |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 987 | return; |
weili | ab5a20d | 2016-12-07 11:32:52 -0800 | [diff] [blame] | 988 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 989 | |
Dan Sinclair | f1251c1 | 2015-10-20 16:24:45 -0400 | [diff] [blame] | 990 | CPDF_Dictionary* pDict = pFieldDict; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 991 | WideString csWName = FPDF_GetFullName(pFieldDict); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 992 | if (csWName.IsEmpty()) |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 993 | return; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 994 | |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 995 | CPDF_FormField* pField = nullptr; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 996 | pField = m_pFieldTree->GetField(csWName); |
Lei Zhang | 412e908 | 2015-12-14 18:34:00 -0800 | [diff] [blame] | 997 | if (!pField) { |
Dan Sinclair | f1251c1 | 2015-10-20 16:24:45 -0400 | [diff] [blame] | 998 | CPDF_Dictionary* pParent = pFieldDict; |
Lei Zhang | d983b09 | 2015-12-14 16:58:33 -0800 | [diff] [blame] | 999 | if (!pFieldDict->KeyExist("T") && |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 1000 | pFieldDict->GetStringFor("Subtype") == "Widget") { |
| 1001 | pParent = pFieldDict->GetDictFor("Parent"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1002 | if (!pParent) |
Dan Sinclair | f1251c1 | 2015-10-20 16:24:45 -0400 | [diff] [blame] | 1003 | pParent = pFieldDict; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 1004 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1005 | |
Lei Zhang | d983b09 | 2015-12-14 16:58:33 -0800 | [diff] [blame] | 1006 | if (pParent && pParent != pFieldDict && !pParent->KeyExist("FT")) { |
| 1007 | if (pFieldDict->KeyExist("FT")) { |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 1008 | CPDF_Object* pFTValue = pFieldDict->GetDirectObjectFor("FT"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1009 | if (pFTValue) |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1010 | pParent->SetFor("FT", pFTValue->Clone()); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1011 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1012 | |
Lei Zhang | d983b09 | 2015-12-14 16:58:33 -0800 | [diff] [blame] | 1013 | if (pFieldDict->KeyExist("Ff")) { |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 1014 | CPDF_Object* pFfValue = pFieldDict->GetDirectObjectFor("Ff"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1015 | if (pFfValue) |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1016 | pParent->SetFor("Ff", pFfValue->Clone()); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1017 | } |
| 1018 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1019 | |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 1020 | auto newField = pdfium::MakeUnique<CPDF_FormField>(this, pParent); |
| 1021 | pField = newField.get(); |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 1022 | CPDF_Object* pTObj = pDict->GetObjectFor("T"); |
Dan Sinclair | bf81c14 | 2015-10-26 16:54:39 -0400 | [diff] [blame] | 1023 | if (ToReference(pTObj)) { |
tsepez | 335cf09 | 2016-11-09 13:28:26 -0800 | [diff] [blame] | 1024 | std::unique_ptr<CPDF_Object> pClone = pTObj->CloneDirectObject(); |
Dan Sinclair | bf81c14 | 2015-10-26 16:54:39 -0400 | [diff] [blame] | 1025 | if (pClone) |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1026 | pDict->SetFor("T", std::move(pClone)); |
Dan Sinclair | bf81c14 | 2015-10-26 16:54:39 -0400 | [diff] [blame] | 1027 | else |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1028 | pDict->SetNewFor<CPDF_Name>("T", ""); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1029 | } |
Nicolas Pena | 08b96e7 | 2017-03-24 14:51:45 -0400 | [diff] [blame] | 1030 | if (!m_pFieldTree->SetField(csWName, std::move(newField))) |
| 1031 | return; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1032 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1033 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 1034 | CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids"); |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 1035 | if (pKids) { |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 1036 | for (size_t i = 0; i < pKids->GetCount(); i++) { |
Wei Li | 9b76113 | 2016-01-29 15:44:20 -0800 | [diff] [blame] | 1037 | CPDF_Dictionary* pKid = pKids->GetDictAt(i); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1038 | if (!pKid) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1039 | continue; |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 1040 | if (pKid->GetStringFor("Subtype") != "Widget") |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1041 | continue; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1042 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1043 | AddControl(pField, pKid); |
| 1044 | } |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 1045 | } else { |
| 1046 | if (pFieldDict->GetStringFor("Subtype") == "Widget") |
| 1047 | AddControl(pField, pFieldDict); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1048 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1049 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1050 | |
tsepez | 6aac8a8 | 2016-06-08 14:17:24 -0700 | [diff] [blame] | 1051 | CPDF_FormControl* CPDF_InterForm::AddControl(CPDF_FormField* pField, |
Dan Sinclair | f1251c1 | 2015-10-20 16:24:45 -0400 | [diff] [blame] | 1052 | CPDF_Dictionary* pWidgetDict) { |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 1053 | const auto it = m_ControlMap.find(pWidgetDict); |
| 1054 | if (it != m_ControlMap.end()) |
tsepez | d18b867 | 2017-01-10 10:19:04 -0800 | [diff] [blame] | 1055 | return it->second.get(); |
Lei Zhang | bdf72c3 | 2015-08-14 19:24:08 -0700 | [diff] [blame] | 1056 | |
tsepez | d18b867 | 2017-01-10 10:19:04 -0800 | [diff] [blame] | 1057 | auto pNew = pdfium::MakeUnique<CPDF_FormControl>(pField, pWidgetDict); |
| 1058 | CPDF_FormControl* pControl = pNew.get(); |
| 1059 | m_ControlMap[pWidgetDict] = std::move(pNew); |
Nicolas Pena | 03f0fb0 | 2017-04-19 17:38:54 -0400 | [diff] [blame] | 1060 | pField->AddFormControl(pControl); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1061 | return pControl; |
| 1062 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1063 | |
Nicolas Pena | a478dc5 | 2017-01-23 15:48:51 -0500 | [diff] [blame] | 1064 | bool CPDF_InterForm::CheckRequiredFields( |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1065 | const std::vector<CPDF_FormField*>* fields, |
| 1066 | bool bIncludeOrExclude) const { |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 1067 | size_t nCount = m_pFieldTree->m_Root.CountFields(); |
| 1068 | for (size_t i = 0; i < nCount; ++i) { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 1069 | CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1070 | if (!pField) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1071 | continue; |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1072 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1073 | int32_t iType = pField->GetType(); |
| 1074 | if (iType == CPDF_FormField::PushButton || |
| 1075 | iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) { |
| 1076 | continue; |
| 1077 | } |
tsepez | b5e8f14 | 2016-03-25 15:18:35 -0700 | [diff] [blame] | 1078 | uint32_t dwFlags = pField->GetFieldFlags(); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1079 | // TODO(thestig): Look up these magic numbers and add constants for them. |
Nicolas Pena | a478dc5 | 2017-01-23 15:48:51 -0500 | [diff] [blame] | 1080 | if (dwFlags & FORMFLAG_NOEXPORT) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1081 | continue; |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1082 | |
| 1083 | bool bFind = true; |
Lei Zhang | cd2bb30 | 2015-12-22 13:49:44 -0800 | [diff] [blame] | 1084 | if (fields) |
| 1085 | bFind = pdfium::ContainsValue(*fields, pField); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1086 | if (bIncludeOrExclude == bFind) { |
Nicolas Pena | 03f0fb0 | 2017-04-19 17:38:54 -0400 | [diff] [blame] | 1087 | const CPDF_Dictionary* pFieldDict = pField->GetDict(); |
Nicolas Pena | a478dc5 | 2017-01-23 15:48:51 -0500 | [diff] [blame] | 1088 | if ((dwFlags & FORMFLAG_REQUIRED) != 0 && |
| 1089 | pFieldDict->GetStringFor("V").IsEmpty()) { |
| 1090 | return false; |
| 1091 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1092 | } |
| 1093 | } |
Nicolas Pena | a478dc5 | 2017-01-23 15:48:51 -0500 | [diff] [blame] | 1094 | return true; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1095 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1096 | |
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 1097 | std::unique_ptr<CFDF_Document> CPDF_InterForm::ExportToFDF( |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1098 | const WideString& pdf_path, |
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 1099 | bool bSimpleFileSpec) const { |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1100 | std::vector<CPDF_FormField*> fields; |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 1101 | size_t nCount = m_pFieldTree->m_Root.CountFields(); |
| 1102 | for (size_t i = 0; i < nCount; ++i) |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 1103 | fields.push_back(m_pFieldTree->m_Root.GetFieldAtIndex(i)); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1104 | return ExportToFDF(pdf_path, fields, true, bSimpleFileSpec); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 1105 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1106 | |
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 1107 | std::unique_ptr<CFDF_Document> CPDF_InterForm::ExportToFDF( |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1108 | const WideString& pdf_path, |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1109 | const std::vector<CPDF_FormField*>& fields, |
| 1110 | bool bIncludeOrExclude, |
| 1111 | bool bSimpleFileSpec) const { |
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 1112 | std::unique_ptr<CFDF_Document> pDoc = CFDF_Document::CreateNewDoc(); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1113 | if (!pDoc) |
thestig | 4997b22 | 2016-06-07 10:46:22 -0700 | [diff] [blame] | 1114 | return nullptr; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1115 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 1116 | CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDictFor("FDF"); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1117 | if (!pdf_path.IsEmpty()) { |
| 1118 | if (bSimpleFileSpec) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1119 | WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path); |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1120 | pMainDict->SetNewFor<CPDF_String>( |
Lei Zhang | 2617056 | 2018-04-17 17:01:52 +0000 | [diff] [blame^] | 1121 | pdfium::stream::kF, ByteString::FromUnicode(wsFilePath), false); |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1122 | pMainDict->SetNewFor<CPDF_String>("UF", PDF_EncodeText(wsFilePath), |
| 1123 | false); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1124 | } else { |
Tom Sepez | 6e72b2e | 2017-04-26 15:14:35 -0700 | [diff] [blame] | 1125 | auto pNewDict = |
| 1126 | pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool()); |
| 1127 | pNewDict->SetNewFor<CPDF_Name>("Type", "Filespec"); |
| 1128 | CPDF_FileSpec filespec(pNewDict.get()); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1129 | filespec.SetFileName(pdf_path); |
Tom Sepez | 6e72b2e | 2017-04-26 15:14:35 -0700 | [diff] [blame] | 1130 | pMainDict->SetFor("F", std::move(pNewDict)); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 1131 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1132 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1133 | |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1134 | CPDF_Array* pFields = pMainDict->SetNewFor<CPDF_Array>("Fields"); |
thestig | 7c292e0 | 2016-09-28 14:14:26 -0700 | [diff] [blame] | 1135 | size_t nCount = m_pFieldTree->m_Root.CountFields(); |
| 1136 | for (size_t i = 0; i < nCount; ++i) { |
thestig | 3b440ac | 2016-09-28 10:57:16 -0700 | [diff] [blame] | 1137 | CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1138 | if (!pField || pField->GetType() == CPDF_FormField::PushButton) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1139 | continue; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1140 | |
tsepez | b5e8f14 | 2016-03-25 15:18:35 -0700 | [diff] [blame] | 1141 | uint32_t dwFlags = pField->GetFieldFlags(); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1142 | if (dwFlags & 0x04) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1143 | continue; |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1144 | |
Lei Zhang | cd2bb30 | 2015-12-22 13:49:44 -0800 | [diff] [blame] | 1145 | if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) { |
Nicolas Pena | 03f0fb0 | 2017-04-19 17:38:54 -0400 | [diff] [blame] | 1146 | if ((dwFlags & 0x02) != 0 && |
| 1147 | pField->GetDict()->GetStringFor("V").IsEmpty()) { |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1148 | continue; |
Nicolas Pena | 03f0fb0 | 2017-04-19 17:38:54 -0400 | [diff] [blame] | 1149 | } |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1150 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1151 | WideString fullname = FPDF_GetFullName(pField->GetFieldDict()); |
tsepez | 8a3aa45 | 2016-11-16 12:26:06 -0800 | [diff] [blame] | 1152 | auto pFieldDict = |
| 1153 | pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool()); |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1154 | pFieldDict->SetNewFor<CPDF_String>("T", fullname); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1155 | if (pField->GetType() == CPDF_FormField::CheckBox || |
| 1156 | pField->GetType() == CPDF_FormField::RadioButton) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1157 | WideString csExport = pField->GetCheckValue(false); |
| 1158 | ByteString csBExport = PDF_EncodeText(csExport); |
Nicolas Pena | 03f0fb0 | 2017-04-19 17:38:54 -0400 | [diff] [blame] | 1159 | CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->GetDict(), "Opt"); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1160 | if (pOpt) |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1161 | pFieldDict->SetNewFor<CPDF_String>("V", csBExport, false); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1162 | else |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1163 | pFieldDict->SetNewFor<CPDF_Name>("V", csBExport); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1164 | } else { |
Nicolas Pena | 03f0fb0 | 2017-04-19 17:38:54 -0400 | [diff] [blame] | 1165 | CPDF_Object* pV = FPDF_GetFieldAttr(pField->GetDict(), "V"); |
Lei Zhang | d88a364 | 2015-11-10 09:38:57 -0800 | [diff] [blame] | 1166 | if (pV) |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1167 | pFieldDict->SetFor("V", pV->CloneDirectObject()); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1168 | } |
tsepez | 8a3aa45 | 2016-11-16 12:26:06 -0800 | [diff] [blame] | 1169 | pFields->Add(std::move(pFieldDict)); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 1170 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1171 | } |
| 1172 | return pDoc; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 1173 | } |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 1174 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1175 | void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1176 | const WideString& parent_name, |
tsepez | 12f3e4a | 2016-11-02 15:17:29 -0700 | [diff] [blame] | 1177 | bool bNotify, |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1178 | int nLevel) { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1179 | WideString name; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1180 | if (!parent_name.IsEmpty()) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1181 | name = parent_name + L"."; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1182 | |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 1183 | name += pFieldDict->GetUnicodeTextFor("T"); |
| 1184 | CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids"); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1185 | if (pKids) { |
Wei Li | e1aebd4 | 2016-04-11 10:02:09 -0700 | [diff] [blame] | 1186 | for (size_t i = 0; i < pKids->GetCount(); i++) { |
Wei Li | 9b76113 | 2016-01-29 15:44:20 -0800 | [diff] [blame] | 1187 | CPDF_Dictionary* pKid = pKids->GetDictAt(i); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1188 | if (!pKid) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1189 | continue; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1190 | if (nLevel <= nMaxRecursion) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1191 | FDF_ImportField(pKid, name, bNotify, nLevel + 1); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 1192 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1193 | return; |
| 1194 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1195 | if (!pFieldDict->KeyExist("V")) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1196 | return; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1197 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1198 | CPDF_FormField* pField = m_pFieldTree->GetField(name); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1199 | if (!pField) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1200 | return; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1201 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1202 | WideString csWValue = GetFieldValue(*pFieldDict, m_bsEncoding); |
Ryan Harrison | 9baf31f | 2018-01-12 18:36:30 +0000 | [diff] [blame] | 1203 | FormFieldType fieldType = pField->GetFieldType(); |
Lei Zhang | 96660d6 | 2015-12-14 18:27:25 -0800 | [diff] [blame] | 1204 | if (bNotify && m_pFormNotify) { |
Ryan Harrison | 9baf31f | 2018-01-12 18:36:30 +0000 | [diff] [blame] | 1205 | if (fieldType == FormFieldType::kListBox) { |
dan sinclair | 507fb4e | 2018-03-08 15:14:09 +0000 | [diff] [blame] | 1206 | if (!m_pFormNotify->BeforeSelectionChange(pField, csWValue)) |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1207 | return; |
Ryan Harrison | 9baf31f | 2018-01-12 18:36:30 +0000 | [diff] [blame] | 1208 | } else if (fieldType == FormFieldType::kComboBox || |
| 1209 | fieldType == FormFieldType::kTextField) { |
dan sinclair | 507fb4e | 2018-03-08 15:14:09 +0000 | [diff] [blame] | 1210 | if (!m_pFormNotify->BeforeValueChange(pField, csWValue)) |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 1211 | return; |
| 1212 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1213 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1214 | pField->SetValue(csWValue); |
| 1215 | CPDF_FormField::Type eType = pField->GetType(); |
| 1216 | if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) && |
| 1217 | pFieldDict->KeyExist("Opt")) { |
Nicolas Pena | 03f0fb0 | 2017-04-19 17:38:54 -0400 | [diff] [blame] | 1218 | pField->SetOpt(pFieldDict->GetDirectObjectFor("Opt")->CloneDirectObject()); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1219 | } |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1220 | |
Lei Zhang | 96660d6 | 2015-12-14 18:27:25 -0800 | [diff] [blame] | 1221 | if (bNotify && m_pFormNotify) { |
Ryan Harrison | 9baf31f | 2018-01-12 18:36:30 +0000 | [diff] [blame] | 1222 | if (fieldType == FormFieldType::kCheckBox || |
| 1223 | fieldType == FormFieldType::kRadioButton) { |
Tom Sepez | ed5d7aa | 2016-02-02 16:02:03 -0800 | [diff] [blame] | 1224 | m_pFormNotify->AfterCheckedStatusChange(pField); |
Ryan Harrison | 9baf31f | 2018-01-12 18:36:30 +0000 | [diff] [blame] | 1225 | } else if (fieldType == FormFieldType::kListBox) { |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1226 | m_pFormNotify->AfterSelectionChange(pField); |
Ryan Harrison | 9baf31f | 2018-01-12 18:36:30 +0000 | [diff] [blame] | 1227 | } else if (fieldType == FormFieldType::kComboBox || |
| 1228 | fieldType == FormFieldType::kTextField) { |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1229 | m_pFormNotify->AfterValueChange(pField); |
Ryan Harrison | 9baf31f | 2018-01-12 18:36:30 +0000 | [diff] [blame] | 1230 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1231 | } |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 1232 | } |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 1233 | |
thestig | db1a24e | 2016-05-23 16:55:09 -0700 | [diff] [blame] | 1234 | void CPDF_InterForm::SetFormNotify(IPDF_FormNotify* pNotify) { |
| 1235 | m_pFormNotify = pNotify; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 1236 | } |