7#include "core/fpdfdoc/cpdf_interactiveform.h"
14#include "build/build_config.h"
15#include "constants/form_fields.h"
16#include "constants/form_flags.h"
17#include "constants/stream_dict_common.h"
18#include "core/fpdfapi/font/cpdf_font.h"
19#include "core/fpdfapi/font/cpdf_fontencoding.h"
20#include "core/fpdfapi/page/cpdf_docpagedata.h"
21#include "core/fpdfapi/page/cpdf_page.h"
22#include "core/fpdfapi/parser/cfdf_document.h"
23#include "core/fpdfapi/parser/cpdf_array.h"
24#include "core/fpdfapi/parser/cpdf_dictionary.h"
25#include "core/fpdfapi/parser/cpdf_document.h"
26#include "core/fpdfapi/parser/cpdf_name.h"
27#include "core/fpdfapi/parser/cpdf_reference.h"
28#include "core/fpdfapi/parser/cpdf_stream.h"
29#include "core/fpdfapi/parser/cpdf_string.h"
30#include "core/fpdfapi/parser/fpdf_parser_utility.h"
31#include "core/fpdfdoc/cpdf_filespec.h"
32#include "core/fpdfdoc/cpdf_formcontrol.h"
33#include "core/fxcrt/check.h"
34#include "core/fxcrt/compiler_specific.h"
35#include "core/fxcrt/containers/contains.h"
36#include "core/fxcrt/fx_codepage.h"
37#include "core/fxcrt/fx_memcpy_wrappers.h"
38#include "core/fxcrt/numerics/safe_conversions.h"
39#include "core/fxcrt/stl_util.h"
40#include "core/fxge/fx_font.h"
43#include "core/fxcrt/win/win_util.h"
48const int nMaxRecursion = 32;
56int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe,
57 NEWTEXTMETRICEX* lpntme,
60 if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName,
'@'))
63 PDF_FONTDATA* pData = (PDF_FONTDATA*)lParam;
64 pData->lf = lpelfe->elfLogFont;
69bool RetrieveSpecificFont(FX_Charset charSet,
73 static_assert(std::is_aggregate_v<std::remove_reference_t<
decltype(lf)>>);
74 lf.lfCharSet =
static_cast<
int>(charSet);
75 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
79 strcpy(lf.lfFaceName, pcsFontName);
83 static_assert(std::is_aggregate_v<
decltype(fd)>);
84 HDC hDC = ::GetDC(
nullptr);
85 EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd,
87 ::ReleaseDC(
nullptr, hDC);
89 UNSAFE_TODO(FXSYS_memcpy(&lf, &fd.lf,
sizeof(LOGFONTA)));
99 if (charSet == FX_Charset::kANSI) {
100 return CFX_Font::kDefaultAnsiFontName;
103 if (!pdfium::IsUser32AndGdi32Available()) {
111 const ByteString default_font_name =
112 CFX_Font::GetDefaultFontNameByCharset(charSet);
113 if (!default_font_name.IsEmpty())
114 bRet = RetrieveSpecificFont(charSet, default_font_name.c_str(), lf);
117 RetrieveSpecificFont(charSet, CFX_Font::kUniversalDefaultFontName, lf);
120 bRet = RetrieveSpecificFont(charSet,
"Microsoft Sans Serif", lf);
122 bRet = RetrieveSpecificFont(charSet,
nullptr, lf);
125 UNSAFE_TODO(FXSYS_memcpy(pLogFont, &lf,
sizeof(LOGFONTA)));
127 csFontName = lf.lfFaceName;
135 static const char kDummyFontName[] =
"ZiTi";
138 csStr
= kDummyFontName;
140 const size_t szCount = csStr.GetLength();
143 while (m < strlen(kDummyFontName) && m < szCount)
145 while (m < strlen(kDummyFontName)) {
146 csTmp +=
'0' + m % 10;
157 if (!pDict->KeyExist(csKey))
180 ByteString csFontName = GetNativeFontName(charSet, &lf);
181 if (!csFontName.IsEmpty()) {
182 if (csFontName == CFX_Font::kDefaultAnsiFontName)
183 return AddStandardFont(pDocument);
184 return CPDF_DocPageData::FromDocument(pDocument)->AddWindowsFont(&lf);
199 if (!ValidateFontResourceDict(pFonts.Get()))
203 for (
const auto& it : locker) {
204 const ByteString& csKey = it.first;
205 RetainPtr<
const CPDF_Dictionary> pElement =
206 ToDictionary(it.second->GetDirect());
207 if (!ValidateDictType(pElement.Get(),
"Font"))
209 if (pFont->FontDictIs(pElement)) {
222 if (csFontName.IsEmpty())
230 if (!ValidateFontResourceDict(pFonts.Get()))
233 csFontName.Remove(
' ');
235 for (
const auto& it : locker) {
236 const ByteString& csKey = it.first;
237 RetainPtr<CPDF_Dictionary> pElement =
238 ToDictionary(it.second->GetMutableDirect());
239 if (!ValidateDictType(pElement.Get(),
"Font"))
242 auto* pData = CPDF_DocPageData::FromDocument(pDocument);
243 pFont = pData->GetFont(std::move(pElement));
247 ByteString csBaseFont = pFont->GetBaseFontName();
248 csBaseFont.Remove(
' ');
249 if (csBaseFont == csFontName) {
265 if (FindFont(pFormDict, pFont.Get(), &csTag)) {
266 *csNameTag =
std::move(csTag);
273 if (csNameTag->IsEmpty())
274 *csNameTag = pFont->GetBaseFontName();
276 csNameTag->Remove(
' ');
277 *csNameTag = GenerateNewFontResourceName(pDR.Get(), *csNameTag);
278 pFonts->SetNewFor<CPDF_Reference>(*csNameTag, pDocument,
279 pFont->GetFontDictObjNum());
288 pDocument->GetMutableRoot()->SetNewFor<CPDF_Reference>(
289 "AcroForm", pDocument, pFormDict->GetObjNum());
295 AddFont(pFormDict.Get(), pDocument, pFont, &csBaseName);
298 ByteString csFontName = GetNativeFontName(charSet,
nullptr);
300 pFont = AddNativeFont(charSet, pDocument);
303 AddFont(pFormDict.Get(), pDocument, pFont, &csBaseName);
311 pFormDict->SetNewFor<CPDF_String>(
"DA", csDA);
324 if (!ValidateFontResourceDict(pFonts.Get()))
328 for (
const auto& it : locker) {
329 const ByteString& csKey = it.first;
330 RetainPtr<CPDF_Dictionary> pElement =
331 ToDictionary(it.second->GetMutableDirect());
332 if (!ValidateDictType(pElement.Get(),
"Font"))
335 auto* pData = CPDF_DocPageData::FromDocument(pDocument);
336 RetainPtr<CPDF_Font> pFind = pData->GetFont(std::move(pElement));
340 auto maybe_charset = pFind->GetSubstFontCharset();
341 if (maybe_charset.has_value() && maybe_charset.value() == charSet) {
349class CFieldNameExtractor {
351 explicit CFieldNameExtractor(
const WideString& full_name)
352 : m_FullName(full_name) {}
355 size_t start_pos = m_iCur;
356 while (m_iCur < m_FullName.GetLength() && m_FullName[m_iCur] != L'.')
359 size_t length = m_iCur - start_pos;
360 if (m_iCur < m_FullName.GetLength() && m_FullName[m_iCur] == L'.')
363 return m_FullName.AsStringView().Substr(start_pos, length);
383 m_Children.push_back(std::move(pNode));
392 size_t nFieldsToGo = index;
393 return GetFieldInternal(&nFieldsToGo);
398 void SetField(std::unique_ptr<CPDF_FormField> pField) {
399 m_pField = std::move(pField);
409 if (*pFieldsToGo == 0)
410 return m_pField.get();
414 for (size_t i = 0; i < GetChildrenCount(); ++i) {
415 CPDF_FormField* pField = GetChildAt(i)->GetFieldInternal(pFieldsToGo);
422 size_t CountFieldsInternal()
const {
427 for (size_t i = 0; i < GetChildrenCount(); ++i)
428 count += GetChildAt(i)->CountFieldsInternal();
432 std::vector<std::unique_ptr<Node>> m_Children;
434 std::unique_ptr<CPDF_FormField> m_pField;
442 std::unique_ptr<CPDF_FormField> pField);
451 std::unique_ptr<Node> m_pRoot;
464 if (level > nMaxRecursion)
468 Node* pChild = pNew.get();
469 pParent->AddChildNode(
std::move(pNew));
477 for (size_t i = 0; i < pParent->GetChildrenCount(); ++i) {
478 Node* pNode = pParent->GetChildAt(i);
486 std::unique_ptr<CPDF_FormField> pField) {
487 if (full_name.IsEmpty())
491 Node* pLast =
nullptr;
492 CFieldNameExtractor name_extractor(full_name);
495 if (name_view.IsEmpty())
508 pNode->SetField(
std::move(pField));
513 if (full_name.IsEmpty())
517 Node* pLast =
nullptr;
518 CFieldNameExtractor name_extractor(full_name);
521 if (name_view.IsEmpty())
530 if (full_name.IsEmpty())
534 Node* pLast =
nullptr;
535 CFieldNameExtractor name_extractor(full_name);
538 if (name_view.IsEmpty())
552 m_pFormDict = pRoot->GetMutableDictFor(
"AcroForm");
560 for (size_t i = 0; i < pFields->size(); ++i)
561 LoadField(pFields->GetMutableDictAt(i), 0);
575 s_bUpdateAP = bUpdateAP;
586 pDocument->GetMutableRoot()->GetMutableDictFor(
"AcroForm");
588 pFormDict = InitDict(pDocument);
593 GetNativeFont(pFormDict.Get(), pDocument, charSet, &csTemp);
595 *csNameTag =
std::move(csTemp);
598 ByteString csFontName = GetNativeFontName(charSet,
nullptr);
599 if (FindFontFromDoc(pFormDict.Get(), pDocument, csFontName, pFont, csNameTag))
602 pFont = AddNativeFont(charSet, pDocument);
606 AddFont(pFormDict.Get(), pDocument, pFont, csNameTag);
611 if (csFieldName.IsEmpty())
612 return m_pFieldTree->GetRoot()->CountFields();
615 return pNode ? pNode->CountFields() : 0;
621 if (csFieldName.IsEmpty())
622 return m_pFieldTree->GetRoot()->GetFieldAtIndex(index);
625 return pNode ? pNode->GetFieldAtIndex(index) :
nullptr;
634 return m_pFieldTree->GetField(csWName);
638 const CPDF_Page* pPage,
640 int* z_order)
const {
645 for (size_t i = pAnnotList->size(); i > 0; --i) {
646 size_t annot_index = i - 1;
648 pAnnotList->GetDictAt(annot_index);
652 const auto it = m_ControlMap.find(pAnnot.Get());
653 if (it == m_ControlMap.end())
661 *z_order =
static_cast<
int>(annot_index);
669 const auto it = m_ControlMap.find(pWidgetDict);
670 return it != m_ControlMap.end() ? it->second.get() :
nullptr;
674 return m_pFormDict && m_pFormDict->GetBooleanFor(
"NeedAppearances",
false);
682 return pArray ?
fxcrt::CollectionSize<
int>(*pArray) : 0;
686 if (!m_pFormDict || index < 0)
694 ToDictionary(pArray->GetDirectObjectAt(index));
707 std::optional<size_t> maybe_found = pArray->Find(pField
->GetFieldDict());
708 if (!maybe_found.has_value())
711 return pdfium::checked_cast<
int>(maybe_found.value());
716 ByteString csAlias = PDF_NameDecode(csNameTag.AsStringView());
717 if (!m_pFormDict || csAlias.IsEmpty())
725 if (!ValidateFontResourceDict(pFonts.Get()))
729 if (!ValidateDictType(pElement.Get(),
"Font"))
737 auto* pData = CPDF_DocPageData::FromDocument(m_pDocument);
738 return pData->GetFont(
std::move(pElement));
742 return CPDF_DefaultAppearance(
743 m_pFormDict ? m_pFormDict->GetByteStringFor(
"DA") :
"");
747 return m_pFormDict ? m_pFormDict->GetIntegerFor(
"Q", 0) : 0;
751 bool bIncludeOrExclude) {
753 const size_t nCount = pRoot->CountFields();
754 for (size_t i = 0; i < nCount; ++i) {
759 if (bIncludeOrExclude ==
pdfium::Contains(fields, pField))
763 m_pFormNotify->AfterFormReset(
this);
772 return m_ControlLists[pdfium::WrapUnowned(pField)];
777 if (nLevel > nMaxRecursion)
782 uint32_t dwParentObjNum = pFieldDict->GetObjNum();
784 pFieldDict->GetMutableArrayFor(pdfium::form_fields::kKids);
786 AddTerminalField(
std::move(pFieldDict));
796 AddTerminalField(
std::move(pFieldDict));
799 for (size_t i = 0; i < pKids->size(); i++) {
801 if (pChildDict && pChildDict->GetObjNum() != dwParentObjNum)
802 LoadField(
std::move(pChildDict), nLevel + 1);
811 for (size_t i = 0; i < pAnnots->size(); i++) {
813 if (pAnnot && pAnnot->GetNameFor(
"Subtype") ==
"Widget")
814 LoadField(
std::move(pAnnot), 0);
823 pFieldDict->GetDictFor(pdfium::form_fields::kParent);
829 if (csWName.IsEmpty())
833 pField = m_pFieldTree->GetField(csWName);
837 pFieldDict->GetNameFor(
"Subtype") ==
"Widget") {
840 pParent = pFieldDict;
843 if (pParent && pParent != pFieldDict &&
847 pFieldDict->GetDirectObjectFor(pdfium::form_fields::kFT);
854 pFieldDict->GetDirectObjectFor(pdfium::form_fields::kFf);
861 pField = newField.get();
863 pFieldDict->GetObjectFor(pdfium::form_fields::kT);
864 if (ToReference(pTObj)) {
871 if (!m_pFieldTree->SetField(csWName, std::move(newField)))
876 pFieldDict->GetMutableArrayFor(pdfium::form_fields::kKids);
878 if (pFieldDict->GetNameFor(
"Subtype") ==
"Widget")
879 AddControl(pField,
std::move(pFieldDict));
882 for (size_t i = 0; i < pKids->size(); i++) {
884 if (pKid && pKid->GetNameFor(
"Subtype") ==
"Widget")
885 AddControl(pField,
std::move(pKid));
893 const auto it = m_ControlMap.find(pWidgetDict.Get());
894 if (it != m_ControlMap.end())
895 return it->second.get();
899 m_ControlMap[pWidgetDict] = std::move(pNew);
900 m_ControlLists[pdfium::WrapUnowned(pField)].emplace_back(pControl);
905 const std::vector<CPDF_FormField*>* fields,
906 bool bIncludeOrExclude)
const {
908 const size_t nCount = pRoot->CountFields();
909 for (size_t i = 0; i < nCount; ++i) {
925 bFind =
pdfium::Contains(*fields, pField);
926 if (bIncludeOrExclude == bFind) {
939 std::vector<CPDF_FormField*> fields;
941 const size_t nCount = pRoot->CountFields();
942 for (size_t i = 0; i < nCount; ++i)
943 fields.push_back(pRoot->GetFieldAtIndex(i));
944 return ExportToFDF(pdf_path, fields,
true);
949 const std::vector<CPDF_FormField*>& fields,
950 bool bIncludeOrExclude)
const {
951 std::unique_ptr<CFDF_Document> pDoc = CFDF_Document::CreateNewDoc();
956 pDoc->GetMutableRoot()->GetMutableDictFor(
"FDF");
957 if (!pdf_path.IsEmpty()) {
959 pNewDict->SetNewFor<CPDF_Name>(
"Type",
"Filespec");
962 pNewDict->SetNewFor<CPDF_String>(
"UF", wsStr.AsStringView());
963 pMainDict->SetFor(
"F", pNewDict);
966 auto pFields = pMainDict->SetNewFor<
CPDF_Array>(
"Fields");
968 const size_t nCount = pRoot->CountFields();
969 for (size_t i = 0; i < nCount; ++i) {
978 if (bIncludeOrExclude !=
pdfium::Contains(fields, pField))
981 if ((dwFlags & pdfium::form_flags::kRequired) != 0 &&
982 pField->GetFieldDict()
983 ->GetByteStringFor(pdfium::form_fields::kV)
992 fullname.AsStringView());
996 ByteString csBExport = PDF_EncodeText(csExport.AsStringView());
1005 pField->GetFieldAttr(pdfium::form_fields::kV);
1009 pFields->Append(pFieldDict);
1015 m_pFormNotify = pNotify;
1020 return !m_pFormNotify || m_pFormNotify->BeforeValueChange(pField, csValue);
1025 m_pFormNotify->AfterValueChange(pField);
1031 return !m_pFormNotify ||
1032 m_pFormNotify->BeforeSelectionChange(pField, csValue);
1037 m_pFormNotify->AfterSelectionChange(pField);
1043 m_pFormNotify->AfterCheckedStatusChange(pField);
fxcrt::ByteString ByteString
bool Contains(const CFX_PointF &point) const
static const char kDefaultAnsiFontName[]
void AddChildNode(std::unique_ptr< Node > pNode)
CPDF_FormField * GetFieldAtIndex(size_t index)
size_t GetChildrenCount() const
CPDF_FormField * GetField() const
size_t CountFields() const
Node(const WideString &short_name, int level)
const Node * GetChildAt(size_t i) const
void SetField(std::unique_ptr< CPDF_FormField > pField)
WideString GetShortName() const
Node * GetChildAt(size_t i)
bool SetField(const WideString &full_name, std::unique_ptr< CPDF_FormField > pField)
CPDF_FormField * GetField(const WideString &full_name)
Node * AddChild(Node *pParent, const WideString &short_name)
Node * Lookup(Node *pParent, WideStringView short_name)
Node * FindNode(const WideString &full_name)
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
static CPDF_DocPageData * FromDocument(const CPDF_Document *pDoc)
RetainPtr< CPDF_Font > AddStandardFont(const ByteString &fontName, const CPDF_FontEncoding *pEncoding)
static WideString EncodeFileName(const WideString &filepath)
CPDF_FontEncoding(FontEncoding predefined_encoding)
static ByteString FormatInteger(int i)
ByteString & operator+=(const char *str)
ByteString & operator=(const char *str)
ByteString & operator=(ByteString &&that) noexcept
bool operator!=(const char *ptr) const
ByteString ToDefANSI() const
ByteString PDF_NameEncode(const ByteString &orig)
FX_Charset FX_GetCharsetFromCodePage(FX_CodePage codepage)
CFX_PTemplate< float > CFX_PointF
ByteString operator+(const ByteString &str1, const ByteString &str2)
ByteString operator+(const ByteString &str1, const char *str2)
ByteString operator+(const char *str1, const ByteString &str2)
fxcrt::WideStringView WideStringView
fxcrt::WideString WideString