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