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