1 // Copyright 2014 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/include/fpdfdoc/fpdf_ap.h" 8 #include "core/include/fpdfdoc/fpdf_doc.h" 9 #include "core/include/fpdfdoc/fpdf_vt.h" 10 #include "doc_utils.h" 11 #include "pdf_vt.h" 12 13 FX_BOOL FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { 14 if (!pAnnotDict || pAnnotDict->GetConstString("Subtype") != "Widget") { 15 return FALSE; 16 } 17 CFX_ByteString field_type = FPDF_GetFieldAttr(pAnnotDict, "FT")->GetString(); 18 FX_DWORD flags = FPDF_GetFieldAttr(pAnnotDict, "Ff") 19 ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() 20 : 0; 21 if (field_type == "Tx") { 22 return CPVT_GenerateAP::GenerateTextFieldAP(pDoc, pAnnotDict); 23 } 24 if (field_type == "Ch") { 25 return (flags & (1 << 17)) 26 ? CPVT_GenerateAP::GenerateComboBoxAP(pDoc, pAnnotDict) 27 : CPVT_GenerateAP::GenerateListBoxAP(pDoc, pAnnotDict); 28 } 29 if (field_type == "Btn") { 30 if (!(flags & (1 << 16))) { 31 if (!pAnnotDict->KeyExist("AS")) { 32 if (CPDF_Dictionary* pParentDict = pAnnotDict->GetDict("Parent")) { 33 if (pParentDict->KeyExist("AS")) { 34 pAnnotDict->SetAtString("AS", pParentDict->GetString("AS")); 35 } 36 } 37 } 38 } 39 } 40 return FALSE; 41 } 42 43 class CPVT_FontMap : public IPVT_FontMap { 44 public: 45 CPVT_FontMap(CPDF_Document* pDoc, 46 CPDF_Dictionary* pResDict, 47 CPDF_Font* pDefFont, 48 const CFX_ByteString& sDefFontAlias); 49 ~CPVT_FontMap() override; 50 51 // IPVT_FontMap 52 CPDF_Font* GetPDFFont(int32_t nFontIndex) override; 53 CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) override; 54 55 static void GetAnnotSysPDFFont(CPDF_Document* pDoc, 56 CPDF_Dictionary* pResDict, 57 CPDF_Font*& pSysFont, 58 CFX_ByteString& sSysFontAlias); 59 60 private: 61 CPDF_Document* m_pDocument; 62 CPDF_Dictionary* m_pResDict; 63 CPDF_Font* m_pDefFont; 64 CFX_ByteString m_sDefFontAlias; 65 CPDF_Font* m_pSysFont; 66 CFX_ByteString m_sSysFontAlias; 67 }; 68 69 CPVT_FontMap::CPVT_FontMap(CPDF_Document* pDoc, 70 CPDF_Dictionary* pResDict, 71 CPDF_Font* pDefFont, 72 const CFX_ByteString& sDefFontAlias) 73 : m_pDocument(pDoc), 74 m_pResDict(pResDict), 75 m_pDefFont(pDefFont), 76 m_sDefFontAlias(sDefFontAlias), 77 m_pSysFont(NULL), 78 m_sSysFontAlias() {} 79 CPVT_FontMap::~CPVT_FontMap() {} 80 void CPVT_FontMap::GetAnnotSysPDFFont(CPDF_Document* pDoc, 81 CPDF_Dictionary* pResDict, 82 CPDF_Font*& pSysFont, 83 CFX_ByteString& sSysFontAlias) { 84 if (pDoc && pResDict) { 85 CFX_ByteString sFontAlias; 86 CPDF_Dictionary* pFormDict = pDoc->GetRoot()->GetDict("AcroForm"); 87 if (CPDF_Font* pPDFFont = 88 AddNativeInterFormFont(pFormDict, pDoc, sSysFontAlias)) { 89 if (CPDF_Dictionary* pFontList = pResDict->GetDict("Font")) { 90 if (!pFontList->KeyExist(sSysFontAlias)) { 91 pFontList->SetAtReference(sSysFontAlias, pDoc, 92 pPDFFont->GetFontDict()); 93 } 94 } 95 pSysFont = pPDFFont; 96 } 97 } 98 } 99 CPDF_Font* CPVT_FontMap::GetPDFFont(int32_t nFontIndex) { 100 switch (nFontIndex) { 101 case 0: 102 return m_pDefFont; 103 case 1: 104 if (!m_pSysFont) { 105 GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont, 106 m_sSysFontAlias); 107 } 108 return m_pSysFont; 109 } 110 return NULL; 111 } 112 CFX_ByteString CPVT_FontMap::GetPDFFontAlias(int32_t nFontIndex) { 113 switch (nFontIndex) { 114 case 0: 115 return m_sDefFontAlias; 116 case 1: 117 if (!m_pSysFont) { 118 GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont, 119 m_sSysFontAlias); 120 } 121 return m_sSysFontAlias; 122 } 123 return ""; 124 } 125 CPVT_Provider::CPVT_Provider(IPVT_FontMap* pFontMap) : m_pFontMap(pFontMap) { 126 ASSERT(m_pFontMap); 127 } 128 CPVT_Provider::~CPVT_Provider() {} 129 int32_t CPVT_Provider::GetCharWidth(int32_t nFontIndex, 130 FX_WORD word, 131 int32_t nWordStyle) { 132 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) { 133 FX_DWORD charcode = pPDFFont->CharCodeFromUnicode(word); 134 if (charcode != CPDF_Font::kInvalidCharCode) { 135 return pPDFFont->GetCharWidthF(charcode); 136 } 137 } 138 return 0; 139 } 140 int32_t CPVT_Provider::GetTypeAscent(int32_t nFontIndex) { 141 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) { 142 return pPDFFont->GetTypeAscent(); 143 } 144 return 0; 145 } 146 int32_t CPVT_Provider::GetTypeDescent(int32_t nFontIndex) { 147 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) { 148 return pPDFFont->GetTypeDescent(); 149 } 150 return 0; 151 } 152 int32_t CPVT_Provider::GetWordFontIndex(FX_WORD word, 153 int32_t charset, 154 int32_t nFontIndex) { 155 if (CPDF_Font* pDefFont = m_pFontMap->GetPDFFont(0)) { 156 if (pDefFont->CharCodeFromUnicode(word) != CPDF_Font::kInvalidCharCode) { 157 return 0; 158 } 159 } 160 if (CPDF_Font* pSysFont = m_pFontMap->GetPDFFont(1)) { 161 if (pSysFont->CharCodeFromUnicode(word) != CPDF_Font::kInvalidCharCode) { 162 return 1; 163 } 164 } 165 return -1; 166 } 167 FX_BOOL CPVT_Provider::IsLatinWord(FX_WORD word) { 168 if ((word >= 0x61 && word <= 0x7A) || (word >= 0x41 && word <= 0x5A) || 169 word == 0x2D || word == 0x27) { 170 return TRUE; 171 } 172 return FALSE; 173 } 174 int32_t CPVT_Provider::GetDefaultFontIndex() { 175 return 0; 176 } 177 178 static CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap, 179 int32_t nFontIndex, 180 FX_WORD Word, 181 FX_WORD SubWord) { 182 CFX_ByteString sWord; 183 if (SubWord > 0) { 184 sWord.Format("%c", SubWord); 185 return sWord; 186 } 187 188 if (!pFontMap) 189 return sWord; 190 191 if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) { 192 if (pPDFFont->GetBaseFont().Compare("Symbol") == 0 || 193 pPDFFont->GetBaseFont().Compare("ZapfDingbats") == 0) { 194 sWord.Format("%c", Word); 195 } else { 196 FX_DWORD dwCharCode = pPDFFont->CharCodeFromUnicode(Word); 197 if (dwCharCode != CPDF_Font::kInvalidCharCode) { 198 pPDFFont->AppendChar(sWord, dwCharCode); 199 } 200 } 201 } 202 return sWord; 203 } 204 205 static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) { 206 if (strWords.GetLength() > 0) { 207 return PDF_EncodeString(strWords) + " Tj\n"; 208 } 209 return ""; 210 } 211 static CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap, 212 int32_t nFontIndex, 213 FX_FLOAT fFontSize) { 214 CFX_ByteTextBuf sRet; 215 if (pFontMap) { 216 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); 217 if (sFontAlias.GetLength() > 0 && fFontSize > 0) { 218 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; 219 } 220 } 221 return sRet.GetByteString(); 222 } 223 static CPVT_Color ParseColor(const CFX_ByteString& str) { 224 CPDF_SimpleParser syntax(str); 225 syntax.SetPos(0); 226 if (syntax.FindTagParam("g", 1)) { 227 return CPVT_Color(CT_GRAY, FX_atof(syntax.GetWord())); 228 } 229 syntax.SetPos(0); 230 if (syntax.FindTagParam("rg", 3)) { 231 FX_FLOAT f1 = FX_atof(syntax.GetWord()); 232 FX_FLOAT f2 = FX_atof(syntax.GetWord()); 233 FX_FLOAT f3 = FX_atof(syntax.GetWord()); 234 return CPVT_Color(CT_RGB, f1, f2, f3); 235 } 236 syntax.SetPos(0); 237 if (syntax.FindTagParam("k", 4)) { 238 FX_FLOAT f1 = FX_atof(syntax.GetWord()); 239 FX_FLOAT f2 = FX_atof(syntax.GetWord()); 240 FX_FLOAT f3 = FX_atof(syntax.GetWord()); 241 FX_FLOAT f4 = FX_atof(syntax.GetWord()); 242 return CPVT_Color(CT_CMYK, f1, f2, f3, f4); 243 } 244 return CPVT_Color(CT_TRANSPARENT); 245 } 246 static CPVT_Color ParseColor(const CPDF_Array& array) { 247 CPVT_Color rt; 248 switch (array.GetCount()) { 249 case 1: 250 rt = CPVT_Color(CT_GRAY, array.GetFloat(0)); 251 break; 252 case 3: 253 rt = CPVT_Color(CT_RGB, array.GetFloat(0), array.GetFloat(1), 254 array.GetFloat(2)); 255 break; 256 case 4: 257 rt = CPVT_Color(CT_CMYK, array.GetFloat(0), array.GetFloat(1), 258 array.GetFloat(2), array.GetFloat(3)); 259 break; 260 } 261 return rt; 262 } 263 static FX_BOOL GenerateWidgetAP(CPDF_Document* pDoc, 264 CPDF_Dictionary* pAnnotDict, 265 const int32_t& nWidgetType) { 266 CPDF_Dictionary* pFormDict = NULL; 267 if (CPDF_Dictionary* pRootDict = pDoc->GetRoot()) { 268 pFormDict = pRootDict->GetDict("AcroForm"); 269 } 270 if (!pFormDict) { 271 return FALSE; 272 } 273 CFX_ByteString DA; 274 if (CPDF_Object* pDAObj = FPDF_GetFieldAttr(pAnnotDict, "DA")) { 275 DA = pDAObj->GetString(); 276 } 277 if (DA.IsEmpty()) { 278 DA = pFormDict->GetString("DA"); 279 } 280 if (DA.IsEmpty()) { 281 return FALSE; 282 } 283 CPDF_SimpleParser syntax(DA); 284 syntax.FindTagParam("Tf", 2); 285 CFX_ByteString sFontName = syntax.GetWord(); 286 sFontName = PDF_NameDecode(sFontName); 287 if (sFontName.IsEmpty()) { 288 return FALSE; 289 } 290 FX_FLOAT fFontSize = FX_atof(syntax.GetWord()); 291 CPVT_Color crText = ParseColor(DA); 292 FX_BOOL bUseFormRes = FALSE; 293 CPDF_Dictionary* pFontDict = NULL; 294 CPDF_Dictionary* pDRDict = pAnnotDict->GetDict("DR"); 295 if (!pDRDict) { 296 pDRDict = pFormDict->GetDict("DR"); 297 bUseFormRes = TRUE; 298 } 299 CPDF_Dictionary* pDRFontDict = NULL; 300 if (pDRDict && (pDRFontDict = pDRDict->GetDict("Font"))) { 301 pFontDict = pDRFontDict->GetDict(sFontName.Mid(1)); 302 if (!pFontDict && !bUseFormRes) { 303 pDRDict = pFormDict->GetDict("DR"); 304 pDRFontDict = pDRDict->GetDict("Font"); 305 if (pDRFontDict) { 306 pFontDict = pDRFontDict->GetDict(sFontName.Mid(1)); 307 } 308 } 309 } 310 if (!pDRFontDict) { 311 return FALSE; 312 } 313 if (!pFontDict) { 314 pFontDict = new CPDF_Dictionary; 315 pFontDict->SetAtName("Type", "Font"); 316 pFontDict->SetAtName("Subtype", "Type1"); 317 pFontDict->SetAtName("BaseFont", "Helvetica"); 318 pFontDict->SetAtName("Encoding", "WinAnsiEncoding"); 319 pDoc->AddIndirectObject(pFontDict); 320 pDRFontDict->SetAtReference(sFontName.Mid(1), pDoc, pFontDict); 321 } 322 CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict); 323 if (!pDefFont) { 324 return FALSE; 325 } 326 CPDF_Rect rcAnnot = pAnnotDict->GetRect("Rect"); 327 int32_t nRotate = 0; 328 if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDict("MK")) { 329 nRotate = pMKDict->GetInteger("R"); 330 } 331 CPDF_Rect rcBBox; 332 CFX_Matrix matrix; 333 switch (nRotate % 360) { 334 case 0: 335 rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left, 336 rcAnnot.top - rcAnnot.bottom); 337 break; 338 case 90: 339 matrix = CFX_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0); 340 rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom, 341 rcAnnot.right - rcAnnot.left); 342 break; 343 case 180: 344 matrix = CFX_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left, 345 rcAnnot.top - rcAnnot.bottom); 346 rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left, 347 rcAnnot.top - rcAnnot.bottom); 348 break; 349 case 270: 350 matrix = CFX_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom); 351 rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom, 352 rcAnnot.right - rcAnnot.left); 353 break; 354 } 355 int32_t nBorderStyle = PBS_SOLID; 356 FX_FLOAT fBorderWidth = 1; 357 CPVT_Dash dsBorder(3, 0, 0); 358 CPVT_Color crLeftTop, crRightBottom; 359 if (CPDF_Dictionary* pBSDict = pAnnotDict->GetDict("BS")) { 360 if (pBSDict->KeyExist("W")) { 361 fBorderWidth = pBSDict->GetNumber("W"); 362 } 363 if (CPDF_Array* pArray = pBSDict->GetArray("D")) { 364 dsBorder = CPVT_Dash(pArray->GetInteger(0), pArray->GetInteger(1), 365 pArray->GetInteger(2)); 366 } 367 switch (pBSDict->GetString("S").GetAt(0)) { 368 case 'S': 369 nBorderStyle = PBS_SOLID; 370 break; 371 case 'D': 372 nBorderStyle = PBS_DASH; 373 break; 374 case 'B': 375 nBorderStyle = PBS_BEVELED; 376 fBorderWidth *= 2; 377 crLeftTop = CPVT_Color(CT_GRAY, 1); 378 crRightBottom = CPVT_Color(CT_GRAY, 0.5); 379 break; 380 case 'I': 381 nBorderStyle = PBS_INSET; 382 fBorderWidth *= 2; 383 crLeftTop = CPVT_Color(CT_GRAY, 0.5); 384 crRightBottom = CPVT_Color(CT_GRAY, 0.75); 385 break; 386 case 'U': 387 nBorderStyle = PBS_UNDERLINED; 388 break; 389 } 390 } 391 CPVT_Color crBorder, crBG; 392 if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDict("MK")) { 393 if (CPDF_Array* pArray = pMKDict->GetArray("BC")) { 394 crBorder = ParseColor(*pArray); 395 } 396 if (CPDF_Array* pArray = pMKDict->GetArray("BG")) { 397 crBG = ParseColor(*pArray); 398 } 399 } 400 CFX_ByteTextBuf sAppStream; 401 CFX_ByteString sBG = CPVT_GenerateAP::GenerateColorAP(crBG, TRUE); 402 if (sBG.GetLength() > 0) { 403 sAppStream << "q\n" << sBG << rcBBox.left << " " << rcBBox.bottom << " " 404 << rcBBox.Width() << " " << rcBBox.Height() << " re f\n" 405 << "Q\n"; 406 } 407 CFX_ByteString sBorderStream = CPVT_GenerateAP::GenerateBorderAP( 408 rcBBox, fBorderWidth, crBorder, crLeftTop, crRightBottom, nBorderStyle, 409 dsBorder); 410 if (sBorderStream.GetLength() > 0) { 411 sAppStream << "q\n" << sBorderStream << "Q\n"; 412 } 413 CPDF_Rect rcBody = 414 CPDF_Rect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth, 415 rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth); 416 rcBody.Normalize(); 417 CPDF_Dictionary* pAPDict = pAnnotDict->GetDict("AP"); 418 if (!pAPDict) { 419 pAPDict = new CPDF_Dictionary; 420 pAnnotDict->SetAt("AP", pAPDict); 421 } 422 CPDF_Stream* pNormalStream = pAPDict->GetStream("N"); 423 if (!pNormalStream) { 424 pNormalStream = new CPDF_Stream(nullptr, 0, nullptr); 425 int32_t objnum = pDoc->AddIndirectObject(pNormalStream); 426 pAnnotDict->GetDict("AP")->SetAtReference("N", pDoc, objnum); 427 } 428 CPDF_Dictionary* pStreamDict = pNormalStream->GetDict(); 429 if (pStreamDict) { 430 pStreamDict->SetAtMatrix("Matrix", matrix); 431 pStreamDict->SetAtRect("BBox", rcBBox); 432 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources"); 433 if (pStreamResList) { 434 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font"); 435 if (!pStreamResFontList) { 436 pStreamResFontList = new CPDF_Dictionary; 437 pStreamResList->SetAt("Font", pStreamResFontList); 438 } 439 if (!pStreamResFontList->KeyExist(sFontName)) { 440 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); 441 } 442 } else { 443 pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone()); 444 pStreamResList = pStreamDict->GetDict("Resources"); 445 } 446 } 447 switch (nWidgetType) { 448 case 0: { 449 CFX_WideString swValue = 450 FPDF_GetFieldAttr(pAnnotDict, "V") 451 ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() 452 : CFX_WideString(); 453 int32_t nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q") 454 ? FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger() 455 : 0; 456 FX_DWORD dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff") 457 ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() 458 : 0; 459 FX_DWORD dwMaxLen = 460 FPDF_GetFieldAttr(pAnnotDict, "MaxLen") 461 ? FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger() 462 : 0; 463 CPVT_FontMap map(pDoc, 464 pStreamDict ? pStreamDict->GetDict("Resources") : NULL, 465 pDefFont, sFontName.Right(sFontName.GetLength() - 1)); 466 CPVT_Provider prd(&map); 467 CPDF_VariableText vt; 468 vt.SetProvider(&prd); 469 vt.SetPlateRect(rcBody); 470 vt.SetAlignment(nAlign); 471 if (IsFloatZero(fFontSize)) { 472 vt.SetAutoFontSize(TRUE); 473 } else { 474 vt.SetFontSize(fFontSize); 475 } 476 FX_BOOL bMultiLine = (dwFlags >> 12) & 1; 477 if (bMultiLine) { 478 vt.SetMultiLine(TRUE); 479 vt.SetAutoReturn(TRUE); 480 } 481 FX_WORD subWord = 0; 482 if ((dwFlags >> 13) & 1) { 483 subWord = '*'; 484 vt.SetPasswordChar(subWord); 485 } 486 FX_BOOL bCharArray = (dwFlags >> 24) & 1; 487 if (bCharArray) { 488 vt.SetCharArray(dwMaxLen); 489 } else { 490 vt.SetLimitChar(dwMaxLen); 491 } 492 vt.Initialize(); 493 vt.SetText(swValue.c_str()); 494 vt.RearrangeAll(); 495 CPDF_Rect rcContent = vt.GetContentRect(); 496 CPDF_Point ptOffset(0.0f, 0.0f); 497 if (!bMultiLine) { 498 ptOffset = 499 CPDF_Point(0.0f, (rcContent.Height() - rcBody.Height()) / 2.0f); 500 } 501 CFX_ByteString sBody = CPVT_GenerateAP::GenerateEditAP( 502 &map, vt.GetIterator(), ptOffset, !bCharArray, subWord); 503 if (sBody.GetLength() > 0) { 504 sAppStream << "/Tx BMC\n" 505 << "q\n"; 506 if (rcContent.Width() > rcBody.Width() || 507 rcContent.Height() > rcBody.Height()) { 508 sAppStream << rcBody.left << " " << rcBody.bottom << " " 509 << rcBody.Width() << " " << rcBody.Height() 510 << " re\nW\nn\n"; 511 } 512 sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) 513 << sBody << "ET\n" 514 << "Q\nEMC\n"; 515 } 516 } break; 517 case 1: { 518 CFX_WideString swValue = 519 FPDF_GetFieldAttr(pAnnotDict, "V") 520 ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() 521 : CFX_WideString(); 522 CPVT_FontMap map(pDoc, 523 pStreamDict ? pStreamDict->GetDict("Resources") : NULL, 524 pDefFont, sFontName.Right(sFontName.GetLength() - 1)); 525 CPVT_Provider prd(&map); 526 CPDF_VariableText vt; 527 vt.SetProvider(&prd); 528 CPDF_Rect rcButton = rcBody; 529 rcButton.left = rcButton.right - 13; 530 rcButton.Normalize(); 531 CPDF_Rect rcEdit = rcBody; 532 rcEdit.right = rcButton.left; 533 rcEdit.Normalize(); 534 vt.SetPlateRect(rcEdit); 535 if (IsFloatZero(fFontSize)) { 536 vt.SetAutoFontSize(TRUE); 537 } else { 538 vt.SetFontSize(fFontSize); 539 } 540 vt.Initialize(); 541 vt.SetText(swValue.c_str()); 542 vt.RearrangeAll(); 543 CPDF_Rect rcContent = vt.GetContentRect(); 544 CPDF_Point ptOffset = 545 CPDF_Point(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f); 546 CFX_ByteString sEdit = CPVT_GenerateAP::GenerateEditAP( 547 &map, vt.GetIterator(), ptOffset, TRUE, 0); 548 if (sEdit.GetLength() > 0) { 549 sAppStream << "/Tx BMC\n" 550 << "q\n"; 551 sAppStream << rcEdit.left << " " << rcEdit.bottom << " " 552 << rcEdit.Width() << " " << rcEdit.Height() << " re\nW\nn\n"; 553 sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) 554 << sEdit << "ET\n" 555 << "Q\nEMC\n"; 556 } 557 CFX_ByteString sButton = CPVT_GenerateAP::GenerateColorAP( 558 CPVT_Color(CT_RGB, 220.0f / 255.0f, 220.0f / 255.0f, 220.0f / 255.0f), 559 TRUE); 560 if (sButton.GetLength() > 0 && !rcButton.IsEmpty()) { 561 sAppStream << "q\n" << sButton; 562 sAppStream << rcButton.left << " " << rcButton.bottom << " " 563 << rcButton.Width() << " " << rcButton.Height() << " re f\n"; 564 sAppStream << "Q\n"; 565 CFX_ByteString sButtonBorder = CPVT_GenerateAP::GenerateBorderAP( 566 rcButton, 2, CPVT_Color(CT_GRAY, 0), CPVT_Color(CT_GRAY, 1), 567 CPVT_Color(CT_GRAY, 0.5), PBS_BEVELED, CPVT_Dash(3, 0, 0)); 568 if (sButtonBorder.GetLength() > 0) { 569 sAppStream << "q\n" << sButtonBorder << "Q\n"; 570 } 571 CPDF_Point ptCenter = CPDF_Point((rcButton.left + rcButton.right) / 2, 572 (rcButton.top + rcButton.bottom) / 2); 573 if (IsFloatBigger(rcButton.Width(), 6) && 574 IsFloatBigger(rcButton.Height(), 6)) { 575 sAppStream << "q\n" 576 << " 0 g\n"; 577 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n"; 578 sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n"; 579 sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n"; 580 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n"; 581 sAppStream << sButton << "Q\n"; 582 } 583 } 584 } break; 585 case 2: { 586 CPVT_FontMap map(pDoc, 587 pStreamDict ? pStreamDict->GetDict("Resources") : NULL, 588 pDefFont, sFontName.Right(sFontName.GetLength() - 1)); 589 CPVT_Provider prd(&map); 590 CPDF_Array* pOpts = FPDF_GetFieldAttr(pAnnotDict, "Opt") 591 ? FPDF_GetFieldAttr(pAnnotDict, "Opt")->GetArray() 592 : NULL; 593 CPDF_Array* pSels = FPDF_GetFieldAttr(pAnnotDict, "I") 594 ? FPDF_GetFieldAttr(pAnnotDict, "I")->GetArray() 595 : NULL; 596 int32_t nTop = FPDF_GetFieldAttr(pAnnotDict, "TI") 597 ? FPDF_GetFieldAttr(pAnnotDict, "TI")->GetInteger() 598 : 0; 599 CFX_ByteTextBuf sBody; 600 if (pOpts) { 601 FX_FLOAT fy = rcBody.top; 602 for (int32_t i = nTop, sz = pOpts->GetCount(); i < sz; i++) { 603 if (IsFloatSmaller(fy, rcBody.bottom)) { 604 break; 605 } 606 if (CPDF_Object* pOpt = pOpts->GetElementValue(i)) { 607 CFX_WideString swItem; 608 if (pOpt->IsString()) 609 swItem = pOpt->GetUnicodeText(); 610 else if (CPDF_Array* pArray = pOpt->AsArray()) 611 swItem = pArray->GetElementValue(1)->GetUnicodeText(); 612 613 FX_BOOL bSelected = FALSE; 614 if (pSels) { 615 for (FX_DWORD s = 0, ssz = pSels->GetCount(); s < ssz; s++) { 616 if (i == pSels->GetInteger(s)) { 617 bSelected = TRUE; 618 break; 619 } 620 } 621 } 622 CPDF_VariableText vt; 623 vt.SetProvider(&prd); 624 vt.SetPlateRect(CPDF_Rect(rcBody.left, 0.0f, rcBody.right, 0.0f)); 625 if (IsFloatZero(fFontSize)) { 626 vt.SetFontSize(12.0f); 627 } else { 628 vt.SetFontSize(fFontSize); 629 } 630 vt.Initialize(); 631 vt.SetText(swItem.c_str()); 632 vt.RearrangeAll(); 633 FX_FLOAT fItemHeight = vt.GetContentRect().Height(); 634 if (bSelected) { 635 CPDF_Rect rcItem = 636 CPDF_Rect(rcBody.left, fy - fItemHeight, rcBody.right, fy); 637 sBody << "q\n" << CPVT_GenerateAP::GenerateColorAP( 638 CPVT_Color(CT_RGB, 0, 51.0f / 255.0f, 639 113.0f / 255.0f), 640 TRUE) 641 << rcItem.left << " " << rcItem.bottom << " " 642 << rcItem.Width() << " " << rcItem.Height() << " re f\n" 643 << "Q\n"; 644 sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP( 645 CPVT_Color(CT_GRAY, 1), TRUE) 646 << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), 647 CPDF_Point(0.0f, fy), 648 TRUE, 0) 649 << "ET\n"; 650 } else { 651 sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) 652 << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), 653 CPDF_Point(0.0f, fy), 654 TRUE, 0) 655 << "ET\n"; 656 } 657 fy -= fItemHeight; 658 } 659 } 660 } 661 if (sBody.GetSize() > 0) { 662 sAppStream << "/Tx BMC\n" 663 << "q\n"; 664 sAppStream << rcBody.left << " " << rcBody.bottom << " " 665 << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n"; 666 sAppStream << sBody.GetByteString() << "Q\nEMC\n"; 667 } 668 } break; 669 } 670 if (pNormalStream) { 671 pNormalStream->SetData((uint8_t*)sAppStream.GetBuffer(), 672 sAppStream.GetSize(), FALSE, FALSE); 673 pStreamDict = pNormalStream->GetDict(); 674 if (pStreamDict) { 675 pStreamDict->SetAtMatrix("Matrix", matrix); 676 pStreamDict->SetAtRect("BBox", rcBBox); 677 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources"); 678 if (pStreamResList) { 679 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font"); 680 if (!pStreamResFontList) { 681 pStreamResFontList = new CPDF_Dictionary; 682 pStreamResList->SetAt("Font", pStreamResFontList); 683 } 684 if (!pStreamResFontList->KeyExist(sFontName)) { 685 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); 686 } 687 } else { 688 pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone()); 689 pStreamResList = pStreamDict->GetDict("Resources"); 690 } 691 } 692 } 693 return TRUE; 694 } 695 FX_BOOL CPVT_GenerateAP::GenerateTextFieldAP(CPDF_Document* pDoc, 696 CPDF_Dictionary* pAnnotDict) { 697 return GenerateWidgetAP(pDoc, pAnnotDict, 0); 698 } 699 FX_BOOL CPVT_GenerateAP::GenerateComboBoxAP(CPDF_Document* pDoc, 700 CPDF_Dictionary* pAnnotDict) { 701 return GenerateWidgetAP(pDoc, pAnnotDict, 1); 702 } 703 FX_BOOL CPVT_GenerateAP::GenerateListBoxAP(CPDF_Document* pDoc, 704 CPDF_Dictionary* pAnnotDict) { 705 return GenerateWidgetAP(pDoc, pAnnotDict, 2); 706 } 707 CFX_ByteString CPVT_GenerateAP::GenerateEditAP( 708 IPVT_FontMap* pFontMap, 709 IPDF_VariableText_Iterator* pIterator, 710 const CPDF_Point& ptOffset, 711 FX_BOOL bContinuous, 712 FX_WORD SubWord, 713 const CPVT_WordRange* pVisible) { 714 CFX_ByteTextBuf sEditStream, sLineStream, sWords; 715 CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f); 716 int32_t nCurFontIndex = -1; 717 if (pIterator) { 718 if (pVisible) { 719 pIterator->SetAt(pVisible->BeginPos); 720 } else { 721 pIterator->SetAt(0); 722 } 723 CPVT_WordPlace oldplace; 724 while (pIterator->NextWord()) { 725 CPVT_WordPlace place = pIterator->GetAt(); 726 if (pVisible && place.WordCmp(pVisible->EndPos) > 0) { 727 break; 728 } 729 if (bContinuous) { 730 if (place.LineCmp(oldplace) != 0) { 731 if (sWords.GetSize() > 0) { 732 sLineStream << GetWordRenderString(sWords.GetByteString()); 733 sEditStream << sLineStream; 734 sLineStream.Clear(); 735 sWords.Clear(); 736 } 737 CPVT_Word word; 738 if (pIterator->GetWord(word)) { 739 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, 740 word.ptWord.y + ptOffset.y); 741 } else { 742 CPVT_Line line; 743 pIterator->GetLine(line); 744 ptNew = CPDF_Point(line.ptLine.x + ptOffset.x, 745 line.ptLine.y + ptOffset.y); 746 } 747 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { 748 sLineStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y 749 << " Td\n"; 750 ptOld = ptNew; 751 } 752 } 753 CPVT_Word word; 754 if (pIterator->GetWord(word)) { 755 if (word.nFontIndex != nCurFontIndex) { 756 if (sWords.GetSize() > 0) { 757 sLineStream << GetWordRenderString(sWords.GetByteString()); 758 sWords.Clear(); 759 } 760 sLineStream << GetFontSetString(pFontMap, word.nFontIndex, 761 word.fFontSize); 762 nCurFontIndex = word.nFontIndex; 763 } 764 sWords << GetPDFWordString(pFontMap, nCurFontIndex, word.Word, 765 SubWord); 766 } 767 oldplace = place; 768 } else { 769 CPVT_Word word; 770 if (pIterator->GetWord(word)) { 771 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, 772 word.ptWord.y + ptOffset.y); 773 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { 774 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y 775 << " Td\n"; 776 ptOld = ptNew; 777 } 778 if (word.nFontIndex != nCurFontIndex) { 779 sEditStream << GetFontSetString(pFontMap, word.nFontIndex, 780 word.fFontSize); 781 nCurFontIndex = word.nFontIndex; 782 } 783 sEditStream << GetWordRenderString( 784 GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord)); 785 } 786 } 787 } 788 if (sWords.GetSize() > 0) { 789 sLineStream << GetWordRenderString(sWords.GetByteString()); 790 sEditStream << sLineStream; 791 sWords.Clear(); 792 } 793 } 794 return sEditStream.GetByteString(); 795 } 796 CFX_ByteString CPVT_GenerateAP::GenerateBorderAP( 797 const CPDF_Rect& rect, 798 FX_FLOAT fWidth, 799 const CPVT_Color& color, 800 const CPVT_Color& crLeftTop, 801 const CPVT_Color& crRightBottom, 802 int32_t nStyle, 803 const CPVT_Dash& dash) { 804 CFX_ByteTextBuf sAppStream; 805 CFX_ByteString sColor; 806 FX_FLOAT fLeft = rect.left; 807 FX_FLOAT fRight = rect.right; 808 FX_FLOAT fTop = rect.top; 809 FX_FLOAT fBottom = rect.bottom; 810 if (fWidth > 0.0f) { 811 FX_FLOAT fHalfWidth = fWidth / 2.0f; 812 switch (nStyle) { 813 default: 814 case PBS_SOLID: 815 sColor = GenerateColorAP(color, TRUE); 816 if (sColor.GetLength() > 0) { 817 sAppStream << sColor; 818 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " 819 << fTop - fBottom << " re\n"; 820 sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " 821 << fRight - fLeft - fWidth * 2 << " " 822 << fTop - fBottom - fWidth * 2 << " re\n"; 823 sAppStream << "f*\n"; 824 } 825 break; 826 case PBS_DASH: 827 sColor = GenerateColorAP(color, FALSE); 828 if (sColor.GetLength() > 0) { 829 sAppStream << sColor; 830 sAppStream << fWidth << " w" 831 << " [" << dash.nDash << " " << dash.nGap << "] " 832 << dash.nPhase << " d\n"; 833 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 834 << " m\n"; 835 sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 836 << " l\n"; 837 sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 838 << " l\n"; 839 sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 840 << " l\n"; 841 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 842 << " l S\n"; 843 } 844 break; 845 case PBS_BEVELED: 846 case PBS_INSET: 847 sColor = GenerateColorAP(crLeftTop, TRUE); 848 if (sColor.GetLength() > 0) { 849 sAppStream << sColor; 850 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth 851 << " m\n"; 852 sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth 853 << " l\n"; 854 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth 855 << " l\n"; 856 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 857 << " l\n"; 858 sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 859 << " l\n"; 860 sAppStream << fLeft + fHalfWidth * 2 << " " 861 << fBottom + fHalfWidth * 2 << " l f\n"; 862 } 863 sColor = GenerateColorAP(crRightBottom, TRUE); 864 if (sColor.GetLength() > 0) { 865 sAppStream << sColor; 866 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth 867 << " m\n"; 868 sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth 869 << " l\n"; 870 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth 871 << " l\n"; 872 sAppStream << fLeft + fHalfWidth * 2 << " " 873 << fBottom + fHalfWidth * 2 << " l\n"; 874 sAppStream << fRight - fHalfWidth * 2 << " " 875 << fBottom + fHalfWidth * 2 << " l\n"; 876 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 877 << " l f\n"; 878 } 879 sColor = GenerateColorAP(color, TRUE); 880 if (sColor.GetLength() > 0) { 881 sAppStream << sColor; 882 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " 883 << fTop - fBottom << " re\n"; 884 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " 885 << fRight - fLeft - fHalfWidth * 2 << " " 886 << fTop - fBottom - fHalfWidth * 2 << " re f*\n"; 887 } 888 break; 889 case PBS_UNDERLINED: 890 sColor = GenerateColorAP(color, FALSE); 891 if (sColor.GetLength() > 0) { 892 sAppStream << sColor; 893 sAppStream << fWidth << " w\n"; 894 sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n"; 895 sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n"; 896 } 897 break; 898 } 899 } 900 return sAppStream.GetByteString(); 901 } 902 CFX_ByteString CPVT_GenerateAP::GenerateColorAP(const CPVT_Color& color, 903 const FX_BOOL& bFillOrStroke) { 904 CFX_ByteTextBuf sColorStream; 905 switch (color.nColorType) { 906 case CT_RGB: 907 sColorStream << color.fColor1 << " " << color.fColor2 << " " 908 << color.fColor3 << " " << (bFillOrStroke ? "rg" : "RG") 909 << "\n"; 910 break; 911 case CT_GRAY: 912 sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G") 913 << "\n"; 914 break; 915 case CT_CMYK: 916 sColorStream << color.fColor1 << " " << color.fColor2 << " " 917 << color.fColor3 << " " << color.fColor4 << " " 918 << (bFillOrStroke ? "k" : "K") << "\n"; 919 break; 920 } 921 return sColorStream.GetByteString(); 922 } 923