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 || 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")? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() : 0; 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; 257 if (CPDF_Object* pDAObj = FPDF_GetFieldAttr(pAnnotDict, "DA")) { 258 DA = pDAObj->GetString(); 259 } 260 if (DA.IsEmpty()) { 261 DA = pFormDict->GetString("DA"); 262 } 263 if (DA.IsEmpty()) { 264 return FALSE; 265 } 266 CPDF_SimpleParser syntax(DA); 267 syntax.FindTagParam("Tf", 2); 268 CFX_ByteString sFontName = syntax.GetWord(); 269 sFontName = PDF_NameDecode(sFontName); 270 if (sFontName.IsEmpty()) { 271 return FALSE; 272 } 273 FX_FLOAT fFontSize = FX_atof(syntax.GetWord()); 274 CPVT_Color crText = ParseColor(DA); 275 FX_BOOL bUseFormRes = FALSE; 276 CPDF_Dictionary * pFontDict = NULL; 277 CPDF_Dictionary* pDRDict = pAnnotDict->GetDict(FX_BSTRC("DR")); 278 if (pDRDict == NULL) { 279 pDRDict = pFormDict->GetDict(FX_BSTRC("DR")); 280 bUseFormRes = TRUE; 281 } 282 CPDF_Dictionary * pDRFontDict = NULL; 283 if (pDRDict && (pDRFontDict = pDRDict->GetDict("Font"))) { 284 pFontDict = pDRFontDict->GetDict(sFontName.Mid(1)); 285 if (!pFontDict && !bUseFormRes) { 286 pDRDict = pFormDict->GetDict(FX_BSTRC("DR")); 287 pDRFontDict = pDRDict->GetDict("Font"); 288 if (pDRFontDict) { 289 pFontDict = pDRFontDict->GetDict(sFontName.Mid(1)); 290 } 291 } 292 } 293 if (!pDRFontDict) { 294 return FALSE; 295 } 296 if (!pFontDict) { 297 pFontDict = CPDF_Dictionary::Create(); 298 if (pFontDict == NULL) { 299 return FALSE; 300 } 301 pFontDict->SetAtName(FX_BSTRC("Type"), "Font"); 302 pFontDict->SetAtName(FX_BSTRC("Subtype"), "Type1"); 303 pFontDict->SetAtName(FX_BSTRC("BaseFont"), "Helvetica"); 304 pFontDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding"); 305 pDoc->AddIndirectObject(pFontDict); 306 pDRFontDict->SetAtReference(sFontName.Mid(1), pDoc, pFontDict); 307 } 308 CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict); 309 if (!pDefFont) { 310 return FALSE; 311 } 312 CPDF_Rect rcAnnot = pAnnotDict->GetRect("Rect"); 313 FX_INT32 nRotate = 0; 314 if (CPDF_Dictionary * pMKDict = pAnnotDict->GetDict("MK")) { 315 nRotate = pMKDict->GetInteger("R"); 316 } 317 CPDF_Rect rcBBox; 318 CPDF_Matrix matrix; 319 switch (nRotate % 360) { 320 case 0: 321 rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom); 322 break; 323 case 90: 324 matrix = CPDF_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0); 325 rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom, rcAnnot.right - rcAnnot.left); 326 break; 327 case 180: 328 matrix = CPDF_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom); 329 rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom); 330 break; 331 case 270: 332 matrix = CPDF_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom); 333 rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom, rcAnnot.right - rcAnnot.left); 334 break; 335 } 336 FX_INT32 nBorderStyle = PBS_SOLID; 337 FX_FLOAT fBorderWidth = 1; 338 CPVT_Dash dsBorder(3, 0, 0); 339 CPVT_Color crLeftTop, crRightBottom; 340 if (CPDF_Dictionary * pBSDict = pAnnotDict->GetDict("BS")) { 341 if (pBSDict->KeyExist("W")) { 342 fBorderWidth = pBSDict->GetNumber("W"); 343 } 344 if (CPDF_Array * pArray = pBSDict->GetArray("D")) { 345 dsBorder = CPVT_Dash(pArray->GetInteger(0), pArray->GetInteger(1), pArray->GetInteger(2)); 346 } 347 switch (pBSDict->GetString("S").GetAt(0)) { 348 case 'S': 349 nBorderStyle = PBS_SOLID; 350 break; 351 case 'D': 352 nBorderStyle = PBS_DASH; 353 break; 354 case 'B': 355 nBorderStyle = PBS_BEVELED; 356 fBorderWidth *= 2; 357 crLeftTop = CPVT_Color(CT_GRAY, 1); 358 crRightBottom = CPVT_Color(CT_GRAY, 0.5); 359 break; 360 case 'I': 361 nBorderStyle = PBS_INSET; 362 fBorderWidth *= 2; 363 crLeftTop = CPVT_Color(CT_GRAY, 0.5); 364 crRightBottom = CPVT_Color(CT_GRAY, 0.75); 365 break; 366 case 'U': 367 nBorderStyle = PBS_UNDERLINED; 368 break; 369 } 370 } 371 CPVT_Color crBorder, crBG; 372 if (CPDF_Dictionary * pMKDict = pAnnotDict->GetDict("MK")) { 373 if (CPDF_Array * pArray = pMKDict->GetArray("BC")) { 374 crBorder = ParseColor(*pArray); 375 } 376 if (CPDF_Array * pArray = pMKDict->GetArray("BG")) { 377 crBG = ParseColor(*pArray); 378 } 379 } 380 CFX_ByteTextBuf sAppStream; 381 CFX_ByteString sBG = CPVT_GenerateAP::GenerateColorAP(crBG, TRUE); 382 if (sBG.GetLength() > 0) { 383 sAppStream << "q\n" << sBG << rcBBox.left << " " << rcBBox.bottom << " " 384 << rcBBox.Width() << " " << rcBBox.Height() << " re f\n" << "Q\n"; 385 } 386 CFX_ByteString sBorderStream = CPVT_GenerateAP::GenerateBorderAP(rcBBox, fBorderWidth, 387 crBorder, crLeftTop, crRightBottom, nBorderStyle, dsBorder); 388 if (sBorderStream.GetLength() > 0) { 389 sAppStream << "q\n" << sBorderStream << "Q\n"; 390 } 391 CPDF_Rect rcBody = CPDF_Rect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth, 392 rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth); 393 rcBody.Normalize(); 394 CPDF_Dictionary* pAPDict = pAnnotDict->GetDict("AP"); 395 if (pAPDict == NULL) { 396 pAPDict = CPDF_Dictionary::Create(); 397 if (pAPDict == NULL) { 398 return FALSE; 399 } 400 pAnnotDict->SetAt("AP", pAPDict); 401 } 402 CPDF_Stream* pNormalStream = pAPDict->GetStream("N"); 403 if (pNormalStream == NULL) { 404 pNormalStream = CPDF_Stream::Create(NULL, 0, NULL); 405 if (pNormalStream == NULL) { 406 return FALSE; 407 } 408 FX_INT32 objnum = pDoc->AddIndirectObject(pNormalStream); 409 pAnnotDict->GetDict("AP")->SetAtReference("N", pDoc, objnum); 410 } 411 CPDF_Dictionary * pStreamDict = pNormalStream->GetDict(); 412 if (pStreamDict) { 413 pStreamDict->SetAtMatrix("Matrix", matrix); 414 pStreamDict->SetAtRect("BBox", rcBBox); 415 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources"); 416 if (pStreamResList) { 417 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font"); 418 if (!pStreamResFontList) { 419 pStreamResFontList = CPDF_Dictionary::Create(); 420 if (pStreamResFontList == NULL) { 421 return FALSE; 422 } 423 pStreamResList->SetAt("Font", pStreamResFontList); 424 } 425 if (!pStreamResFontList->KeyExist(sFontName)) { 426 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); 427 } 428 } else { 429 pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone()); 430 pStreamResList = pStreamDict->GetDict("Resources"); 431 } 432 } 433 switch (nWidgetType) { 434 case 0: { 435 CFX_WideString swValue = FPDF_GetFieldAttr(pAnnotDict, "V")? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() : CFX_WideString(); 436 FX_INT32 nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q")? FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger() : 0; 437 FX_DWORD dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff")? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() : 0; 438 FX_DWORD dwMaxLen = FPDF_GetFieldAttr(pAnnotDict, "MaxLen") ? FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger() : 0; 439 CPVT_FontMap map(pDoc, pStreamDict ? pStreamDict->GetDict("Resources") : NULL , pDefFont, sFontName.Right(sFontName.GetLength() - 1)); 440 CPVT_Provider prd(&map); 441 CPDF_VariableText vt; 442 vt.SetProvider(&prd); 443 vt.SetPlateRect(rcBody); 444 vt.SetAlignment(nAlign); 445 if (IsFloatZero(fFontSize)) { 446 vt.SetAutoFontSize(TRUE); 447 } else { 448 vt.SetFontSize(fFontSize); 449 } 450 FX_BOOL bMultiLine = (dwFlags >> 12) & 1; 451 if (bMultiLine) { 452 vt.SetMultiLine(TRUE); 453 vt.SetAutoReturn(TRUE); 454 } 455 FX_WORD subWord = 0; 456 if ((dwFlags >> 13) & 1) { 457 subWord = '*'; 458 vt.SetPasswordChar(subWord); 459 } 460 FX_BOOL bCharArray = (dwFlags >> 24) & 1; 461 if (bCharArray) { 462 vt.SetCharArray(dwMaxLen); 463 } else { 464 vt.SetLimitChar(dwMaxLen); 465 } 466 vt.Initialize(); 467 vt.SetText(swValue.c_str()); 468 vt.RearrangeAll(); 469 CPDF_Rect rcContent = vt.GetContentRect(); 470 CPDF_Point ptOffset(0.0f, 0.0f); 471 if (!bMultiLine) { 472 ptOffset = CPDF_Point(0.0f, (rcContent.Height() - rcBody.Height()) / 2.0f); 473 } 474 CFX_ByteString sBody = CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), ptOffset, !bCharArray, subWord); 475 if (sBody.GetLength() > 0) { 476 sAppStream << "/Tx BMC\n" << "q\n"; 477 if (rcContent.Width() > rcBody.Width() || 478 rcContent.Height() > rcBody.Height()) { 479 sAppStream << rcBody.left << " " << rcBody.bottom << " " 480 << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n"; 481 } 482 sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) << sBody << "ET\n" << "Q\nEMC\n"; 483 } 484 } 485 break; 486 case 1: { 487 CFX_WideString swValue = FPDF_GetFieldAttr(pAnnotDict, "V") ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() : CFX_WideString(); 488 CPVT_FontMap map(pDoc, pStreamDict ? pStreamDict->GetDict("Resources"):NULL, pDefFont, sFontName.Right(sFontName.GetLength() - 1)); 489 CPVT_Provider prd(&map); 490 CPDF_VariableText vt; 491 vt.SetProvider(&prd); 492 CPDF_Rect rcButton = rcBody; 493 rcButton.left = rcButton.right - 13; 494 rcButton.Normalize(); 495 CPDF_Rect rcEdit = rcBody; 496 rcEdit.right = rcButton.left; 497 rcEdit.Normalize(); 498 vt.SetPlateRect(rcEdit); 499 if (IsFloatZero(fFontSize)) { 500 vt.SetAutoFontSize(TRUE); 501 } else { 502 vt.SetFontSize(fFontSize); 503 } 504 vt.Initialize(); 505 vt.SetText(swValue.c_str()); 506 vt.RearrangeAll(); 507 CPDF_Rect rcContent = vt.GetContentRect(); 508 CPDF_Point ptOffset = CPDF_Point(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f); 509 CFX_ByteString sEdit = CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), ptOffset, TRUE, 0); 510 if (sEdit.GetLength() > 0) { 511 sAppStream << "/Tx BMC\n" << "q\n"; 512 sAppStream << rcEdit.left << " " << rcEdit.bottom << " " 513 << rcEdit.Width() << " " << rcEdit.Height() << " re\nW\nn\n"; 514 sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) << sEdit << "ET\n" << "Q\nEMC\n"; 515 } 516 CFX_ByteString sButton = CPVT_GenerateAP::GenerateColorAP(CPVT_Color(CT_RGB, 220.0f / 255.0f, 220.0f / 255.0f, 220.0f / 255.0f), TRUE); 517 if (sButton.GetLength() > 0 && !rcButton.IsEmpty()) { 518 sAppStream << "q\n" << sButton; 519 sAppStream << rcButton.left << " " << rcButton.bottom << " " 520 << rcButton.Width() << " " << rcButton.Height() << " re f\n"; 521 sAppStream << "Q\n"; 522 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)); 523 if (sButtonBorder.GetLength() > 0) { 524 sAppStream << "q\n" << sButtonBorder << "Q\n"; 525 } 526 CPDF_Point ptCenter = CPDF_Point((rcButton.left + rcButton.right) / 2, (rcButton.top + rcButton.bottom) / 2); 527 if (IsFloatBigger(rcButton.Width(), 6) && IsFloatBigger(rcButton.Height(), 6)) { 528 sAppStream << "q\n" << " 0 g\n"; 529 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n"; 530 sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n"; 531 sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n"; 532 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n"; 533 sAppStream << sButton << "Q\n"; 534 } 535 } 536 } 537 break; 538 case 2: { 539 CPVT_FontMap map(pDoc, pStreamDict ? pStreamDict->GetDict("Resources"):NULL, pDefFont, sFontName.Right(sFontName.GetLength() - 1)); 540 CPVT_Provider prd(&map); 541 CPDF_Array * pOpts = FPDF_GetFieldAttr(pAnnotDict, "Opt") ? FPDF_GetFieldAttr(pAnnotDict, "Opt")->GetArray() : NULL; 542 CPDF_Array * pSels = FPDF_GetFieldAttr(pAnnotDict, "I") ? FPDF_GetFieldAttr(pAnnotDict, "I")->GetArray() : NULL; 543 FX_INT32 nTop = FPDF_GetFieldAttr(pAnnotDict, "TI") ? FPDF_GetFieldAttr(pAnnotDict, "TI")->GetInteger() : 0; 544 CFX_ByteTextBuf sBody; 545 if (pOpts) { 546 FX_FLOAT fy = rcBody.top; 547 for (FX_INT32 i = nTop, sz = pOpts->GetCount(); i < sz; i++) { 548 if (IsFloatSmaller(fy, rcBody.bottom)) { 549 break; 550 } 551 if (CPDF_Object* pOpt = pOpts->GetElementValue(i)) { 552 CFX_WideString swItem; 553 if (pOpt->GetType() == PDFOBJ_STRING) { 554 swItem = pOpt->GetUnicodeText(); 555 } else if (pOpt->GetType() == PDFOBJ_ARRAY) { 556 swItem = ((CPDF_Array*)pOpt)->GetElementValue(1)->GetUnicodeText(); 557 } 558 FX_BOOL bSelected = FALSE; 559 if (pSels) { 560 for (FX_DWORD s = 0, ssz = pSels->GetCount(); s < ssz; s++) { 561 if (i == pSels->GetInteger(s)) { 562 bSelected = TRUE; 563 break; 564 } 565 } 566 } 567 CPDF_VariableText vt; 568 vt.SetProvider(&prd); 569 vt.SetPlateRect(CPDF_Rect(rcBody.left, 0.0f, rcBody.right, 0.0f)); 570 if (IsFloatZero(fFontSize)) { 571 vt.SetFontSize(12.0f); 572 } else { 573 vt.SetFontSize(fFontSize); 574 } 575 vt.Initialize(); 576 vt.SetText(swItem.c_str()); 577 vt.RearrangeAll(); 578 FX_FLOAT fItemHeight = vt.GetContentRect().Height(); 579 if (bSelected) { 580 CPDF_Rect rcItem = CPDF_Rect(rcBody.left, fy - fItemHeight, rcBody.right, fy); 581 sBody << "q\n" << CPVT_GenerateAP::GenerateColorAP(CPVT_Color(CT_RGB, 0, 51.0f / 255.0f, 113.0f / 255.0f), TRUE) 582 << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width() << " " << rcItem.Height() << " re f\n" << "Q\n"; 583 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"; 584 } else { 585 sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), CPDF_Point(0.0f, fy), TRUE, 0) << "ET\n"; 586 } 587 fy -= fItemHeight; 588 } 589 } 590 } 591 if (sBody.GetSize() > 0) { 592 sAppStream << "/Tx BMC\n" << "q\n"; 593 sAppStream << rcBody.left << " " << rcBody.bottom << " " 594 << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n"; 595 sAppStream << sBody.GetByteString() << "Q\nEMC\n"; 596 } 597 } 598 break; 599 } 600 if (pNormalStream) { 601 pNormalStream->SetData((FX_BYTE*)sAppStream.GetBuffer(), sAppStream.GetSize(), FALSE, FALSE); 602 pStreamDict = pNormalStream->GetDict(); 603 if (pStreamDict) { 604 pStreamDict->SetAtMatrix("Matrix", matrix); 605 pStreamDict->SetAtRect("BBox", rcBBox); 606 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources"); 607 if (pStreamResList) { 608 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font"); 609 if (!pStreamResFontList) { 610 pStreamResFontList = CPDF_Dictionary::Create(); 611 if (pStreamResFontList == NULL) { 612 return FALSE; 613 } 614 pStreamResList->SetAt("Font", pStreamResFontList); 615 } 616 if (!pStreamResFontList->KeyExist(sFontName)) { 617 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); 618 } 619 } else { 620 pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone()); 621 pStreamResList = pStreamDict->GetDict("Resources"); 622 } 623 } 624 } 625 return TRUE; 626 } 627 FX_BOOL CPVT_GenerateAP::GenerateTextFieldAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) 628 { 629 return GenerateWidgetAP(pDoc, pAnnotDict, 0); 630 } 631 FX_BOOL CPVT_GenerateAP::GenerateComboBoxAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) 632 { 633 return GenerateWidgetAP(pDoc, pAnnotDict, 1); 634 } 635 FX_BOOL CPVT_GenerateAP::GenerateListBoxAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) 636 { 637 return GenerateWidgetAP(pDoc, pAnnotDict, 2); 638 } 639 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) 640 { 641 CFX_ByteTextBuf sEditStream, sLineStream, sWords; 642 CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f); 643 FX_INT32 nCurFontIndex = -1; 644 if (pIterator) { 645 if (pVisible) { 646 pIterator->SetAt(pVisible->BeginPos); 647 } else { 648 pIterator->SetAt(0); 649 } 650 CPVT_WordPlace oldplace; 651 while (pIterator->NextWord()) { 652 CPVT_WordPlace place = pIterator->GetAt(); 653 if (pVisible && place.WordCmp(pVisible->EndPos) > 0) { 654 break; 655 } 656 if (bContinuous) { 657 if (place.LineCmp(oldplace) != 0) { 658 if (sWords.GetSize() > 0) { 659 sLineStream << GetWordRenderString(sWords.GetByteString()); 660 sEditStream << sLineStream; 661 sLineStream.Clear(); 662 sWords.Clear(); 663 } 664 CPVT_Word word; 665 if (pIterator->GetWord(word)) { 666 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y); 667 } else { 668 CPVT_Line line; 669 pIterator->GetLine(line); 670 ptNew = CPDF_Point(line.ptLine.x + ptOffset.x, line.ptLine.y + ptOffset.y); 671 } 672 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { 673 sLineStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " Td\n"; 674 ptOld = ptNew; 675 } 676 } 677 CPVT_Word word; 678 if (pIterator->GetWord(word)) { 679 if (word.nFontIndex != nCurFontIndex) { 680 if (sWords.GetSize() > 0) { 681 sLineStream << GetWordRenderString(sWords.GetByteString()); 682 sWords.Clear(); 683 } 684 sLineStream << GetFontSetString(pFontMap, word.nFontIndex, word.fFontSize); 685 nCurFontIndex = word.nFontIndex; 686 } 687 sWords << GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord); 688 } 689 oldplace = place; 690 } else { 691 CPVT_Word word; 692 if (pIterator->GetWord(word)) { 693 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y); 694 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { 695 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " Td\n"; 696 ptOld = ptNew; 697 } 698 if (word.nFontIndex != nCurFontIndex) { 699 sEditStream << GetFontSetString(pFontMap, word.nFontIndex, word.fFontSize); 700 nCurFontIndex = word.nFontIndex; 701 } 702 sEditStream << GetWordRenderString(GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord)); 703 } 704 } 705 } 706 if (sWords.GetSize() > 0) { 707 sLineStream << GetWordRenderString(sWords.GetByteString()); 708 sEditStream << sLineStream; 709 sWords.Clear(); 710 } 711 } 712 return sEditStream.GetByteString(); 713 } 714 CFX_ByteString CPVT_GenerateAP::GenerateBorderAP(const CPDF_Rect & rect, FX_FLOAT fWidth, 715 const CPVT_Color & color, const CPVT_Color & crLeftTop, const CPVT_Color & crRightBottom, 716 FX_INT32 nStyle, const CPVT_Dash & dash) 717 { 718 CFX_ByteTextBuf sAppStream; 719 CFX_ByteString sColor; 720 FX_FLOAT fLeft = rect.left; 721 FX_FLOAT fRight = rect.right; 722 FX_FLOAT fTop = rect.top; 723 FX_FLOAT fBottom = rect.bottom; 724 if (fWidth > 0.0f) { 725 FX_FLOAT fHalfWidth = fWidth / 2.0f; 726 switch (nStyle) { 727 default: 728 case PBS_SOLID: 729 sColor = GenerateColorAP(color, TRUE); 730 if (sColor.GetLength() > 0) { 731 sAppStream << sColor; 732 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " << fTop - fBottom << " re\n"; 733 sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " 734 << fRight - fLeft - fWidth * 2 << " " << fTop - fBottom - fWidth * 2 << " re\n"; 735 sAppStream << "f*\n"; 736 } 737 break; 738 case PBS_DASH: 739 sColor = GenerateColorAP(color, FALSE); 740 if (sColor.GetLength() > 0) { 741 sAppStream << sColor; 742 sAppStream << fWidth << " w" << " [" << dash.nDash << " " << dash.nGap << "] " << dash.nPhase << " d\n"; 743 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " m\n"; 744 sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 << " l\n"; 745 sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 << " l\n"; 746 sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 << " l\n"; 747 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " l S\n"; 748 } 749 break; 750 case PBS_BEVELED: 751 case PBS_INSET: 752 sColor = GenerateColorAP(crLeftTop, TRUE); 753 if (sColor.GetLength() > 0) { 754 sAppStream << sColor; 755 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " m\n"; 756 sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth << " l\n"; 757 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " l\n"; 758 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 << " l\n"; 759 sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 << " l\n"; 760 sAppStream << fLeft + fHalfWidth * 2 << " " << fBottom + fHalfWidth * 2 << " l f\n"; 761 } 762 sColor = GenerateColorAP(crRightBottom, TRUE); 763 if (sColor.GetLength() > 0) { 764 sAppStream << sColor; 765 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " m\n"; 766 sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth << " l\n"; 767 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " l\n"; 768 sAppStream << fLeft + fHalfWidth * 2 << " " << fBottom + fHalfWidth * 2 << " l\n"; 769 sAppStream << fRight - fHalfWidth * 2 << " " << fBottom + fHalfWidth * 2 << " l\n"; 770 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 << " l f\n"; 771 } 772 sColor = GenerateColorAP(color, TRUE); 773 if (sColor.GetLength() > 0) { 774 sAppStream << sColor; 775 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " << fTop - fBottom << " re\n"; 776 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " 777 << fRight - fLeft - fHalfWidth * 2 << " " << fTop - fBottom - fHalfWidth * 2 << " re f*\n"; 778 } 779 break; 780 case PBS_UNDERLINED: 781 sColor = GenerateColorAP(color, FALSE); 782 if (sColor.GetLength() > 0) { 783 sAppStream << sColor; 784 sAppStream << fWidth << " w\n"; 785 sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n"; 786 sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n"; 787 } 788 break; 789 } 790 } 791 return sAppStream.GetByteString(); 792 } 793 CFX_ByteString CPVT_GenerateAP::GenerateColorAP(const CPVT_Color & color, const FX_BOOL & bFillOrStroke) 794 { 795 CFX_ByteTextBuf sColorStream; 796 switch (color.nColorType) { 797 case CT_RGB: 798 sColorStream << color.fColor1 << " " << color.fColor2 << " " << color.fColor3 << " " 799 << (bFillOrStroke ? "rg" : "RG") << "\n"; 800 break; 801 case CT_GRAY: 802 sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G") << "\n"; 803 break; 804 case CT_CMYK: 805 sColorStream << color.fColor1 << " " << color.fColor2 << " " << color.fColor3 << " " << color.fColor4 << " " 806 << (bFillOrStroke ? "k" : "K") << "\n"; 807 break; 808 } 809 return sColorStream.GetByteString(); 810 } 811