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