| OLD | NEW |
| (Empty) |
| 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 <algorithm> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "core/fpdfapi/fpdf_font/include/cpdf_font.h" | |
| 11 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | |
| 12 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" | |
| 13 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" | |
| 14 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h" | |
| 15 #include "core/fpdfdoc/doc_utils.h" | |
| 16 #include "core/fpdfdoc/include/cpdf_defaultappearance.h" | |
| 17 #include "core/fpdfdoc/include/cpdf_formcontrol.h" | |
| 18 #include "core/fpdfdoc/include/cpdf_interform.h" | |
| 19 #include "core/fxge/include/fx_font.h" | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 const int FPDFDOC_UTILS_MAXRECURSION = 32; | |
| 24 | |
| 25 CPDF_Object* SearchNumberNode(const CPDF_Dictionary* pNode, int num) { | |
| 26 CPDF_Array* pLimits = pNode->GetArrayBy("Limits"); | |
| 27 if (pLimits && | |
| 28 (num < pLimits->GetIntegerAt(0) || num > pLimits->GetIntegerAt(1))) { | |
| 29 return nullptr; | |
| 30 } | |
| 31 CPDF_Array* pNumbers = pNode->GetArrayBy("Nums"); | |
| 32 if (pNumbers) { | |
| 33 for (size_t i = 0; i < pNumbers->GetCount() / 2; i++) { | |
| 34 int index = pNumbers->GetIntegerAt(i * 2); | |
| 35 if (num == index) { | |
| 36 return pNumbers->GetDirectObjectAt(i * 2 + 1); | |
| 37 } | |
| 38 if (index > num) { | |
| 39 break; | |
| 40 } | |
| 41 } | |
| 42 return nullptr; | |
| 43 } | |
| 44 CPDF_Array* pKids = pNode->GetArrayBy("Kids"); | |
| 45 if (!pKids) { | |
| 46 return nullptr; | |
| 47 } | |
| 48 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
| 49 CPDF_Dictionary* pKid = pKids->GetDictAt(i); | |
| 50 if (!pKid) { | |
| 51 continue; | |
| 52 } | |
| 53 CPDF_Object* pFound = SearchNumberNode(pKid, num); | |
| 54 if (pFound) { | |
| 55 return pFound; | |
| 56 } | |
| 57 } | |
| 58 return nullptr; | |
| 59 } | |
| 60 | |
| 61 } // namespace | |
| 62 | |
| 63 CPDF_Object* CPDF_NumberTree::LookupValue(int num) const { | |
| 64 return SearchNumberNode(m_pRoot, num); | |
| 65 } | |
| 66 | |
| 67 CFX_WideString GetFullName(CPDF_Dictionary* pFieldDict) { | |
| 68 CFX_WideString full_name; | |
| 69 CPDF_Dictionary* pLevel = pFieldDict; | |
| 70 while (pLevel) { | |
| 71 CFX_WideString short_name = pLevel->GetUnicodeTextBy("T"); | |
| 72 if (short_name != L"") { | |
| 73 if (full_name == L"") { | |
| 74 full_name = short_name; | |
| 75 } else { | |
| 76 full_name = short_name + L"." + full_name; | |
| 77 } | |
| 78 } | |
| 79 pLevel = pLevel->GetDictBy("Parent"); | |
| 80 } | |
| 81 return full_name; | |
| 82 } | |
| 83 FX_BOOL CPDF_DefaultAppearance::HasFont() { | |
| 84 if (m_csDA.IsEmpty()) { | |
| 85 return FALSE; | |
| 86 } | |
| 87 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 88 return syntax.FindTagParamFromStart("Tf", 2); | |
| 89 } | |
| 90 CFX_ByteString CPDF_DefaultAppearance::GetFontString() { | |
| 91 CFX_ByteString csFont; | |
| 92 if (m_csDA.IsEmpty()) { | |
| 93 return csFont; | |
| 94 } | |
| 95 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 96 if (syntax.FindTagParamFromStart("Tf", 2)) { | |
| 97 csFont += syntax.GetWord(); | |
| 98 csFont += " "; | |
| 99 csFont += syntax.GetWord(); | |
| 100 csFont += " "; | |
| 101 csFont += syntax.GetWord(); | |
| 102 } | |
| 103 return csFont; | |
| 104 } | |
| 105 void CPDF_DefaultAppearance::GetFont(CFX_ByteString& csFontNameTag, | |
| 106 FX_FLOAT& fFontSize) { | |
| 107 csFontNameTag = ""; | |
| 108 fFontSize = 0; | |
| 109 if (m_csDA.IsEmpty()) { | |
| 110 return; | |
| 111 } | |
| 112 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 113 if (syntax.FindTagParamFromStart("Tf", 2)) { | |
| 114 csFontNameTag = CFX_ByteString(syntax.GetWord()); | |
| 115 csFontNameTag.Delete(0, 1); | |
| 116 fFontSize = FX_atof(syntax.GetWord()); | |
| 117 } | |
| 118 csFontNameTag = PDF_NameDecode(csFontNameTag); | |
| 119 } | |
| 120 FX_BOOL CPDF_DefaultAppearance::HasColor(FX_BOOL bStrokingOperation) { | |
| 121 if (m_csDA.IsEmpty()) { | |
| 122 return FALSE; | |
| 123 } | |
| 124 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 125 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) { | |
| 126 return TRUE; | |
| 127 } | |
| 128 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) { | |
| 129 return TRUE; | |
| 130 } | |
| 131 return syntax.FindTagParamFromStart(bStrokingOperation ? "K" : "k", 4); | |
| 132 } | |
| 133 CFX_ByteString CPDF_DefaultAppearance::GetColorString( | |
| 134 FX_BOOL bStrokingOperation) { | |
| 135 CFX_ByteString csColor; | |
| 136 if (m_csDA.IsEmpty()) { | |
| 137 return csColor; | |
| 138 } | |
| 139 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 140 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) { | |
| 141 csColor += syntax.GetWord(); | |
| 142 csColor += " "; | |
| 143 csColor += syntax.GetWord(); | |
| 144 return csColor; | |
| 145 } | |
| 146 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) { | |
| 147 csColor += syntax.GetWord(); | |
| 148 csColor += " "; | |
| 149 csColor += syntax.GetWord(); | |
| 150 csColor += " "; | |
| 151 csColor += syntax.GetWord(); | |
| 152 csColor += " "; | |
| 153 csColor += syntax.GetWord(); | |
| 154 return csColor; | |
| 155 } | |
| 156 if (syntax.FindTagParamFromStart(bStrokingOperation ? "K" : "k", 4)) { | |
| 157 csColor += syntax.GetWord(); | |
| 158 csColor += " "; | |
| 159 csColor += syntax.GetWord(); | |
| 160 csColor += " "; | |
| 161 csColor += syntax.GetWord(); | |
| 162 csColor += " "; | |
| 163 csColor += syntax.GetWord(); | |
| 164 csColor += " "; | |
| 165 csColor += syntax.GetWord(); | |
| 166 } | |
| 167 return csColor; | |
| 168 } | |
| 169 void CPDF_DefaultAppearance::GetColor(int& iColorType, | |
| 170 FX_FLOAT fc[4], | |
| 171 FX_BOOL bStrokingOperation) { | |
| 172 iColorType = COLORTYPE_TRANSPARENT; | |
| 173 for (int c = 0; c < 4; c++) { | |
| 174 fc[c] = 0; | |
| 175 } | |
| 176 if (m_csDA.IsEmpty()) { | |
| 177 return; | |
| 178 } | |
| 179 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 180 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) { | |
| 181 iColorType = COLORTYPE_GRAY; | |
| 182 fc[0] = FX_atof(syntax.GetWord()); | |
| 183 return; | |
| 184 } | |
| 185 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) { | |
| 186 iColorType = COLORTYPE_RGB; | |
| 187 fc[0] = FX_atof(syntax.GetWord()); | |
| 188 fc[1] = FX_atof(syntax.GetWord()); | |
| 189 fc[2] = FX_atof(syntax.GetWord()); | |
| 190 return; | |
| 191 } | |
| 192 if (syntax.FindTagParamFromStart(bStrokingOperation ? "K" : "k", 4)) { | |
| 193 iColorType = COLORTYPE_CMYK; | |
| 194 fc[0] = FX_atof(syntax.GetWord()); | |
| 195 fc[1] = FX_atof(syntax.GetWord()); | |
| 196 fc[2] = FX_atof(syntax.GetWord()); | |
| 197 fc[3] = FX_atof(syntax.GetWord()); | |
| 198 } | |
| 199 } | |
| 200 void CPDF_DefaultAppearance::GetColor(FX_ARGB& color, | |
| 201 int& iColorType, | |
| 202 FX_BOOL bStrokingOperation) { | |
| 203 color = 0; | |
| 204 iColorType = COLORTYPE_TRANSPARENT; | |
| 205 if (m_csDA.IsEmpty()) { | |
| 206 return; | |
| 207 } | |
| 208 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 209 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) { | |
| 210 iColorType = COLORTYPE_GRAY; | |
| 211 FX_FLOAT g = FX_atof(syntax.GetWord()) * 255 + 0.5f; | |
| 212 color = ArgbEncode(255, (int)g, (int)g, (int)g); | |
| 213 return; | |
| 214 } | |
| 215 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) { | |
| 216 iColorType = COLORTYPE_RGB; | |
| 217 FX_FLOAT r = FX_atof(syntax.GetWord()) * 255 + 0.5f; | |
| 218 FX_FLOAT g = FX_atof(syntax.GetWord()) * 255 + 0.5f; | |
| 219 FX_FLOAT b = FX_atof(syntax.GetWord()) * 255 + 0.5f; | |
| 220 color = ArgbEncode(255, (int)r, (int)g, (int)b); | |
| 221 return; | |
| 222 } | |
| 223 if (syntax.FindTagParamFromStart(bStrokingOperation ? "K" : "k", 4)) { | |
| 224 iColorType = COLORTYPE_CMYK; | |
| 225 FX_FLOAT c = FX_atof(syntax.GetWord()); | |
| 226 FX_FLOAT m = FX_atof(syntax.GetWord()); | |
| 227 FX_FLOAT y = FX_atof(syntax.GetWord()); | |
| 228 FX_FLOAT k = FX_atof(syntax.GetWord()); | |
| 229 FX_FLOAT r = 1.0f - std::min(1.0f, c + k); | |
| 230 FX_FLOAT g = 1.0f - std::min(1.0f, m + k); | |
| 231 FX_FLOAT b = 1.0f - std::min(1.0f, y + k); | |
| 232 color = ArgbEncode(255, (int)(r * 255 + 0.5f), (int)(g * 255 + 0.5f), | |
| 233 (int)(b * 255 + 0.5f)); | |
| 234 } | |
| 235 } | |
| 236 FX_BOOL CPDF_DefaultAppearance::HasTextMatrix() { | |
| 237 if (m_csDA.IsEmpty()) { | |
| 238 return FALSE; | |
| 239 } | |
| 240 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 241 return syntax.FindTagParamFromStart("Tm", 6); | |
| 242 } | |
| 243 CFX_ByteString CPDF_DefaultAppearance::GetTextMatrixString() { | |
| 244 CFX_ByteString csTM; | |
| 245 if (m_csDA.IsEmpty()) { | |
| 246 return csTM; | |
| 247 } | |
| 248 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 249 if (syntax.FindTagParamFromStart("Tm", 6)) { | |
| 250 for (int i = 0; i < 6; i++) { | |
| 251 csTM += syntax.GetWord(); | |
| 252 csTM += " "; | |
| 253 } | |
| 254 csTM += syntax.GetWord(); | |
| 255 } | |
| 256 return csTM; | |
| 257 } | |
| 258 CFX_Matrix CPDF_DefaultAppearance::GetTextMatrix() { | |
| 259 CFX_Matrix tm; | |
| 260 if (m_csDA.IsEmpty()) { | |
| 261 return tm; | |
| 262 } | |
| 263 CPDF_SimpleParser syntax(m_csDA.AsStringC()); | |
| 264 if (syntax.FindTagParamFromStart("Tm", 6)) { | |
| 265 FX_FLOAT f[6]; | |
| 266 for (int i = 0; i < 6; i++) { | |
| 267 f[i] = FX_atof(syntax.GetWord()); | |
| 268 } | |
| 269 tm.Set(f[0], f[1], f[2], f[3], f[4], f[5]); | |
| 270 } | |
| 271 return tm; | |
| 272 } | |
| 273 | |
| 274 void InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) { | |
| 275 if (!pDocument) | |
| 276 return; | |
| 277 | |
| 278 if (!pFormDict) { | |
| 279 pFormDict = new CPDF_Dictionary; | |
| 280 uint32_t dwObjNum = pDocument->AddIndirectObject(pFormDict); | |
| 281 CPDF_Dictionary* pRoot = pDocument->GetRoot(); | |
| 282 pRoot->SetAtReference("AcroForm", pDocument, dwObjNum); | |
| 283 } | |
| 284 CFX_ByteString csDA; | |
| 285 if (!pFormDict->KeyExist("DR")) { | |
| 286 CFX_ByteString csBaseName; | |
| 287 CFX_ByteString csDefault; | |
| 288 uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); | |
| 289 CPDF_Font* pFont = CPDF_InterForm::AddStandardFont(pDocument, "Helvetica"); | |
| 290 if (pFont) { | |
| 291 AddInterFormFont(pFormDict, pDocument, pFont, csBaseName); | |
| 292 csDefault = csBaseName; | |
| 293 } | |
| 294 if (charSet != FXFONT_ANSI_CHARSET) { | |
| 295 CFX_ByteString csFontName = | |
| 296 CPDF_InterForm::GetNativeFont(charSet, nullptr); | |
| 297 if (!pFont || csFontName != "Helvetica") { | |
| 298 pFont = CPDF_InterForm::AddNativeFont(pDocument); | |
| 299 if (pFont) { | |
| 300 csBaseName = ""; | |
| 301 AddInterFormFont(pFormDict, pDocument, pFont, csBaseName); | |
| 302 csDefault = csBaseName; | |
| 303 } | |
| 304 } | |
| 305 } | |
| 306 if (pFont) { | |
| 307 csDA = "/" + PDF_NameEncode(csDefault) + " 0 Tf"; | |
| 308 } | |
| 309 } | |
| 310 if (!csDA.IsEmpty()) { | |
| 311 csDA += " "; | |
| 312 } | |
| 313 csDA += "0 g"; | |
| 314 if (!pFormDict->KeyExist("DA")) { | |
| 315 pFormDict->SetAtString("DA", csDA); | |
| 316 } | |
| 317 } | |
| 318 uint32_t CountInterFormFonts(CPDF_Dictionary* pFormDict) { | |
| 319 if (!pFormDict) { | |
| 320 return 0; | |
| 321 } | |
| 322 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 323 if (!pDR) { | |
| 324 return 0; | |
| 325 } | |
| 326 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 327 if (!pFonts) { | |
| 328 return 0; | |
| 329 } | |
| 330 uint32_t dwCount = 0; | |
| 331 for (const auto& it : *pFonts) { | |
| 332 CPDF_Object* pObj = it.second; | |
| 333 if (!pObj) { | |
| 334 continue; | |
| 335 } | |
| 336 if (CPDF_Dictionary* pDirect = ToDictionary(pObj->GetDirect())) { | |
| 337 if (pDirect->GetStringBy("Type") == "Font") { | |
| 338 dwCount++; | |
| 339 } | |
| 340 } | |
| 341 } | |
| 342 return dwCount; | |
| 343 } | |
| 344 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, | |
| 345 CPDF_Document* pDocument, | |
| 346 uint32_t index, | |
| 347 CFX_ByteString& csNameTag) { | |
| 348 if (!pFormDict) { | |
| 349 return nullptr; | |
| 350 } | |
| 351 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 352 if (!pDR) { | |
| 353 return nullptr; | |
| 354 } | |
| 355 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 356 if (!pFonts) { | |
| 357 return nullptr; | |
| 358 } | |
| 359 uint32_t dwCount = 0; | |
| 360 for (const auto& it : *pFonts) { | |
| 361 const CFX_ByteString& csKey = it.first; | |
| 362 CPDF_Object* pObj = it.second; | |
| 363 if (!pObj) { | |
| 364 continue; | |
| 365 } | |
| 366 CPDF_Dictionary* pElement = ToDictionary(pObj->GetDirect()); | |
| 367 if (!pElement) | |
| 368 continue; | |
| 369 if (pElement->GetStringBy("Type") != "Font") | |
| 370 continue; | |
| 371 if (dwCount == index) { | |
| 372 csNameTag = csKey; | |
| 373 return pDocument->LoadFont(pElement); | |
| 374 } | |
| 375 dwCount++; | |
| 376 } | |
| 377 return nullptr; | |
| 378 } | |
| 379 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, | |
| 380 CPDF_Document* pDocument, | |
| 381 CFX_ByteString csNameTag) { | |
| 382 CFX_ByteString csAlias = PDF_NameDecode(csNameTag); | |
| 383 if (!pFormDict || csAlias.IsEmpty()) { | |
| 384 return nullptr; | |
| 385 } | |
| 386 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 387 if (!pDR) { | |
| 388 return nullptr; | |
| 389 } | |
| 390 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 391 if (!pFonts) { | |
| 392 return nullptr; | |
| 393 } | |
| 394 CPDF_Dictionary* pElement = pFonts->GetDictBy(csAlias); | |
| 395 if (!pElement) { | |
| 396 return nullptr; | |
| 397 } | |
| 398 if (pElement->GetStringBy("Type") == "Font") { | |
| 399 return pDocument->LoadFont(pElement); | |
| 400 } | |
| 401 return nullptr; | |
| 402 } | |
| 403 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, | |
| 404 CPDF_Document* pDocument, | |
| 405 CFX_ByteString csFontName, | |
| 406 CFX_ByteString& csNameTag) { | |
| 407 if (!pFormDict || csFontName.IsEmpty()) { | |
| 408 return nullptr; | |
| 409 } | |
| 410 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 411 if (!pDR) { | |
| 412 return nullptr; | |
| 413 } | |
| 414 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 415 if (!pFonts) { | |
| 416 return nullptr; | |
| 417 } | |
| 418 for (const auto& it : *pFonts) { | |
| 419 const CFX_ByteString& csKey = it.first; | |
| 420 CPDF_Object* pObj = it.second; | |
| 421 if (!pObj) { | |
| 422 continue; | |
| 423 } | |
| 424 CPDF_Dictionary* pElement = ToDictionary(pObj->GetDirect()); | |
| 425 if (!pElement) | |
| 426 continue; | |
| 427 if (pElement->GetStringBy("Type") != "Font") | |
| 428 continue; | |
| 429 | |
| 430 CPDF_Font* pFind = pDocument->LoadFont(pElement); | |
| 431 if (!pFind) | |
| 432 continue; | |
| 433 | |
| 434 CFX_ByteString csBaseFont; | |
| 435 csBaseFont = pFind->GetBaseFont(); | |
| 436 csBaseFont.Remove(' '); | |
| 437 if (csBaseFont == csFontName) { | |
| 438 csNameTag = csKey; | |
| 439 return pFind; | |
| 440 } | |
| 441 } | |
| 442 return nullptr; | |
| 443 } | |
| 444 CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, | |
| 445 CPDF_Document* pDocument, | |
| 446 uint8_t charSet, | |
| 447 CFX_ByteString& csNameTag) { | |
| 448 if (!pFormDict) { | |
| 449 return nullptr; | |
| 450 } | |
| 451 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 452 if (!pDR) { | |
| 453 return nullptr; | |
| 454 } | |
| 455 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 456 if (!pFonts) { | |
| 457 return nullptr; | |
| 458 } | |
| 459 for (const auto& it : *pFonts) { | |
| 460 const CFX_ByteString& csKey = it.first; | |
| 461 CPDF_Object* pObj = it.second; | |
| 462 if (!pObj) { | |
| 463 continue; | |
| 464 } | |
| 465 CPDF_Dictionary* pElement = ToDictionary(pObj->GetDirect()); | |
| 466 if (!pElement) | |
| 467 continue; | |
| 468 if (pElement->GetStringBy("Type") != "Font") | |
| 469 continue; | |
| 470 CPDF_Font* pFind = pDocument->LoadFont(pElement); | |
| 471 if (!pFind) { | |
| 472 continue; | |
| 473 } | |
| 474 CFX_SubstFont* pSubst = pFind->GetSubstFont(); | |
| 475 if (!pSubst) { | |
| 476 continue; | |
| 477 } | |
| 478 if (pSubst->m_Charset == (int)charSet) { | |
| 479 csNameTag = csKey; | |
| 480 return pFind; | |
| 481 } | |
| 482 } | |
| 483 return nullptr; | |
| 484 } | |
| 485 | |
| 486 CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, | |
| 487 CPDF_Document* pDocument, | |
| 488 CFX_ByteString& csNameTag) { | |
| 489 csNameTag.clear(); | |
| 490 uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); | |
| 491 CPDF_Font* pFont = GetDefaultInterFormFont(pFormDict, pDocument); | |
| 492 if (pFont) { | |
| 493 CFX_SubstFont* pSubst = pFont->GetSubstFont(); | |
| 494 if (pSubst && pSubst->m_Charset == (int)charSet) { | |
| 495 FindInterFormFont(pFormDict, pFont, csNameTag); | |
| 496 return pFont; | |
| 497 } | |
| 498 } | |
| 499 return GetNativeInterFormFont(pFormDict, pDocument, charSet, csNameTag); | |
| 500 } | |
| 501 | |
| 502 FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, | |
| 503 const CPDF_Font* pFont, | |
| 504 CFX_ByteString& csNameTag) { | |
| 505 if (!pFormDict || !pFont) { | |
| 506 return FALSE; | |
| 507 } | |
| 508 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 509 if (!pDR) { | |
| 510 return FALSE; | |
| 511 } | |
| 512 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 513 if (!pFonts) { | |
| 514 return FALSE; | |
| 515 } | |
| 516 for (const auto& it : *pFonts) { | |
| 517 const CFX_ByteString& csKey = it.first; | |
| 518 CPDF_Object* pObj = it.second; | |
| 519 if (!pObj) { | |
| 520 continue; | |
| 521 } | |
| 522 CPDF_Dictionary* pElement = ToDictionary(pObj->GetDirect()); | |
| 523 if (!pElement) | |
| 524 continue; | |
| 525 if (pElement->GetStringBy("Type") != "Font") { | |
| 526 continue; | |
| 527 } | |
| 528 if (pFont->GetFontDict() == pElement) { | |
| 529 csNameTag = csKey; | |
| 530 return TRUE; | |
| 531 } | |
| 532 } | |
| 533 return FALSE; | |
| 534 } | |
| 535 FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, | |
| 536 CPDF_Document* pDocument, | |
| 537 CFX_ByteString csFontName, | |
| 538 CPDF_Font*& pFont, | |
| 539 CFX_ByteString& csNameTag) { | |
| 540 if (!pFormDict) { | |
| 541 return FALSE; | |
| 542 } | |
| 543 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 544 if (!pDR) { | |
| 545 return FALSE; | |
| 546 } | |
| 547 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 548 if (!pFonts) { | |
| 549 return FALSE; | |
| 550 } | |
| 551 if (csFontName.GetLength() > 0) { | |
| 552 csFontName.Remove(' '); | |
| 553 } | |
| 554 for (const auto& it : *pFonts) { | |
| 555 const CFX_ByteString& csKey = it.first; | |
| 556 CPDF_Object* pObj = it.second; | |
| 557 if (!pObj) { | |
| 558 continue; | |
| 559 } | |
| 560 CPDF_Dictionary* pElement = ToDictionary(pObj->GetDirect()); | |
| 561 if (!pElement) | |
| 562 continue; | |
| 563 if (pElement->GetStringBy("Type") != "Font") { | |
| 564 continue; | |
| 565 } | |
| 566 pFont = pDocument->LoadFont(pElement); | |
| 567 if (!pFont) { | |
| 568 continue; | |
| 569 } | |
| 570 CFX_ByteString csBaseFont; | |
| 571 csBaseFont = pFont->GetBaseFont(); | |
| 572 csBaseFont.Remove(' '); | |
| 573 if (csBaseFont == csFontName) { | |
| 574 csNameTag = csKey; | |
| 575 return TRUE; | |
| 576 } | |
| 577 } | |
| 578 return FALSE; | |
| 579 } | |
| 580 void AddInterFormFont(CPDF_Dictionary*& pFormDict, | |
| 581 CPDF_Document* pDocument, | |
| 582 const CPDF_Font* pFont, | |
| 583 CFX_ByteString& csNameTag) { | |
| 584 if (!pFont) { | |
| 585 return; | |
| 586 } | |
| 587 if (!pFormDict) { | |
| 588 InitInterFormDict(pFormDict, pDocument); | |
| 589 } | |
| 590 CFX_ByteString csTag; | |
| 591 if (FindInterFormFont(pFormDict, pFont, csTag)) { | |
| 592 csNameTag = csTag; | |
| 593 return; | |
| 594 } | |
| 595 if (!pFormDict) { | |
| 596 InitInterFormDict(pFormDict, pDocument); | |
| 597 } | |
| 598 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 599 if (!pDR) { | |
| 600 pDR = new CPDF_Dictionary; | |
| 601 pFormDict->SetAt("DR", pDR); | |
| 602 } | |
| 603 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 604 if (!pFonts) { | |
| 605 pFonts = new CPDF_Dictionary; | |
| 606 pDR->SetAt("Font", pFonts); | |
| 607 } | |
| 608 if (csNameTag.IsEmpty()) { | |
| 609 csNameTag = pFont->GetBaseFont(); | |
| 610 } | |
| 611 csNameTag.Remove(' '); | |
| 612 csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, | |
| 613 csNameTag.c_str()); | |
| 614 pFonts->SetAtReference(csNameTag, pDocument, pFont->GetFontDict()); | |
| 615 } | |
| 616 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, | |
| 617 CPDF_Document* pDocument, | |
| 618 uint8_t charSet, | |
| 619 CFX_ByteString& csNameTag) { | |
| 620 if (!pFormDict) { | |
| 621 InitInterFormDict(pFormDict, pDocument); | |
| 622 } | |
| 623 CFX_ByteString csTemp; | |
| 624 CPDF_Font* pFont = | |
| 625 GetNativeInterFormFont(pFormDict, pDocument, charSet, csTemp); | |
| 626 if (pFont) { | |
| 627 csNameTag = csTemp; | |
| 628 return pFont; | |
| 629 } | |
| 630 CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet); | |
| 631 if (!csFontName.IsEmpty() && | |
| 632 FindInterFormFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) { | |
| 633 return pFont; | |
| 634 } | |
| 635 pFont = CPDF_InterForm::AddNativeFont(charSet, pDocument); | |
| 636 if (pFont) { | |
| 637 AddInterFormFont(pFormDict, pDocument, pFont, csNameTag); | |
| 638 } | |
| 639 return pFont; | |
| 640 } | |
| 641 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, | |
| 642 CPDF_Document* pDocument, | |
| 643 CFX_ByteString& csNameTag) { | |
| 644 uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); | |
| 645 return AddNativeInterFormFont(pFormDict, pDocument, charSet, csNameTag); | |
| 646 } | |
| 647 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont) { | |
| 648 if (!pFormDict || !pFont) { | |
| 649 return; | |
| 650 } | |
| 651 CFX_ByteString csTag; | |
| 652 if (!FindInterFormFont(pFormDict, pFont, csTag)) { | |
| 653 return; | |
| 654 } | |
| 655 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 656 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 657 pFonts->RemoveAt(csTag); | |
| 658 } | |
| 659 | |
| 660 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag) { | |
| 661 if (!pFormDict || csNameTag.IsEmpty()) { | |
| 662 return; | |
| 663 } | |
| 664 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); | |
| 665 if (!pDR) { | |
| 666 return; | |
| 667 } | |
| 668 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); | |
| 669 if (!pFonts) { | |
| 670 return; | |
| 671 } | |
| 672 pFonts->RemoveAt(csNameTag); | |
| 673 } | |
| 674 | |
| 675 CPDF_Font* GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, | |
| 676 CPDF_Document* pDocument) { | |
| 677 if (!pFormDict) { | |
| 678 return nullptr; | |
| 679 } | |
| 680 CPDF_DefaultAppearance cDA(pFormDict->GetStringBy("DA")); | |
| 681 CFX_ByteString csFontNameTag; | |
| 682 FX_FLOAT fFontSize; | |
| 683 cDA.GetFont(csFontNameTag, fFontSize); | |
| 684 return GetInterFormFont(pFormDict, pDocument, csFontNameTag); | |
| 685 } | |
| 686 | |
| 687 CPDF_IconFit::ScaleMethod CPDF_IconFit::GetScaleMethod() { | |
| 688 if (!m_pDict) { | |
| 689 return Always; | |
| 690 } | |
| 691 CFX_ByteString csSW = m_pDict->GetStringBy("SW", "A"); | |
| 692 if (csSW == "B") { | |
| 693 return Bigger; | |
| 694 } | |
| 695 if (csSW == "S") { | |
| 696 return Smaller; | |
| 697 } | |
| 698 if (csSW == "N") { | |
| 699 return Never; | |
| 700 } | |
| 701 return Always; | |
| 702 } | |
| 703 FX_BOOL CPDF_IconFit::IsProportionalScale() { | |
| 704 if (!m_pDict) { | |
| 705 return TRUE; | |
| 706 } | |
| 707 return m_pDict->GetStringBy("S", "P") != "A"; | |
| 708 } | |
| 709 void CPDF_IconFit::GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom) { | |
| 710 fLeft = fBottom = 0.5; | |
| 711 if (!m_pDict) { | |
| 712 return; | |
| 713 } | |
| 714 CPDF_Array* pA = m_pDict->GetArrayBy("A"); | |
| 715 if (pA) { | |
| 716 uint32_t dwCount = pA->GetCount(); | |
| 717 if (dwCount > 0) { | |
| 718 fLeft = pA->GetNumberAt(0); | |
| 719 } | |
| 720 if (dwCount > 1) { | |
| 721 fBottom = pA->GetNumberAt(1); | |
| 722 } | |
| 723 } | |
| 724 } | |
| 725 | |
| 726 bool CPDF_IconFit::GetFittingBounds() { | |
| 727 return m_pDict ? m_pDict->GetBooleanBy("FB") : false; | |
| 728 } | |
| 729 | |
| 730 std::vector<bool> SaveCheckedFieldStatus(CPDF_FormField* pField) { | |
| 731 std::vector<bool> result; | |
| 732 int iCount = pField->CountControls(); | |
| 733 for (int i = 0; i < iCount; ++i) { | |
| 734 if (CPDF_FormControl* pControl = pField->GetControl(i)) | |
| 735 result.push_back(pControl->IsChecked()); | |
| 736 } | |
| 737 return result; | |
| 738 } | |
| 739 | |
| 740 CPDF_Object* FPDF_GetFieldAttr(CPDF_Dictionary* pFieldDict, | |
| 741 const FX_CHAR* name, | |
| 742 int nLevel) { | |
| 743 if (nLevel > FPDFDOC_UTILS_MAXRECURSION) { | |
| 744 return nullptr; | |
| 745 } | |
| 746 if (!pFieldDict) { | |
| 747 return nullptr; | |
| 748 } | |
| 749 CPDF_Object* pAttr = pFieldDict->GetDirectObjectBy(name); | |
| 750 if (pAttr) { | |
| 751 return pAttr; | |
| 752 } | |
| 753 CPDF_Dictionary* pParent = pFieldDict->GetDictBy("Parent"); | |
| 754 if (!pParent) { | |
| 755 return nullptr; | |
| 756 } | |
| 757 return FPDF_GetFieldAttr(pParent, name, nLevel + 1); | |
| 758 } | |
| OLD | NEW |