| 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 "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | |
| 8 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" | |
| 9 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h" | |
| 10 #include "core/fpdfdoc/doc_utils.h" | |
| 11 #include "core/fpdfdoc/cpdf_pagelabel.h" | |
| 12 #include "core/fpdfdoc/include/cpdf_filespec.h" | |
| 13 #include "core/fpdfdoc/include/cpdf_nametree.h" | |
| 14 #include "core/fpdfdoc/include/ipdf_formnotify.h" | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 const int nMaxRecursion = 32; | |
| 19 const FX_CHAR* const g_sZoomModes[] = {"XYZ", "Fit", "FitH", "FitV", "FitR", | |
| 20 "FitB", "FitBH", "FitBV", nullptr}; | |
| 21 | |
| 22 } // namespace | |
| 23 | |
| 24 int CPDF_Dest::GetPageIndex(CPDF_Document* pDoc) { | |
| 25 CPDF_Array* pArray = ToArray(m_pObj); | |
| 26 if (!pArray) | |
| 27 return 0; | |
| 28 | |
| 29 CPDF_Object* pPage = pArray->GetDirectObjectAt(0); | |
| 30 if (!pPage) | |
| 31 return 0; | |
| 32 if (pPage->IsNumber()) | |
| 33 return pPage->GetInteger(); | |
| 34 if (!pPage->IsDictionary()) | |
| 35 return 0; | |
| 36 return pDoc->GetPageIndex(pPage->GetObjNum()); | |
| 37 } | |
| 38 | |
| 39 uint32_t CPDF_Dest::GetPageObjNum() { | |
| 40 CPDF_Array* pArray = ToArray(m_pObj); | |
| 41 if (!pArray) | |
| 42 return 0; | |
| 43 | |
| 44 CPDF_Object* pPage = pArray->GetDirectObjectAt(0); | |
| 45 if (!pPage) | |
| 46 return 0; | |
| 47 if (pPage->IsNumber()) | |
| 48 return pPage->GetInteger(); | |
| 49 if (pPage->IsDictionary()) | |
| 50 return pPage->GetObjNum(); | |
| 51 return 0; | |
| 52 } | |
| 53 | |
| 54 int CPDF_Dest::GetZoomMode() { | |
| 55 CPDF_Array* pArray = ToArray(m_pObj); | |
| 56 if (!pArray) | |
| 57 return 0; | |
| 58 | |
| 59 CPDF_Object* pObj = pArray->GetDirectObjectAt(1); | |
| 60 if (!pObj) | |
| 61 return 0; | |
| 62 | |
| 63 CFX_ByteString mode = pObj->GetString(); | |
| 64 for (int i = 0; g_sZoomModes[i]; ++i) { | |
| 65 if (mode == g_sZoomModes[i]) | |
| 66 return i + 1; | |
| 67 } | |
| 68 | |
| 69 return 0; | |
| 70 } | |
| 71 | |
| 72 FX_FLOAT CPDF_Dest::GetParam(int index) { | |
| 73 CPDF_Array* pArray = ToArray(m_pObj); | |
| 74 return pArray ? pArray->GetNumberAt(2 + index) : 0; | |
| 75 } | |
| 76 | |
| 77 CFX_ByteString CPDF_Dest::GetRemoteName() { | |
| 78 return m_pObj ? m_pObj->GetString() : CFX_ByteString(); | |
| 79 } | |
| 80 | |
| 81 CPDF_NameTree::CPDF_NameTree(CPDF_Document* pDoc, | |
| 82 const CFX_ByteString& category) | |
| 83 : m_pRoot(nullptr) { | |
| 84 CPDF_Dictionary* pRoot = pDoc->GetRoot(); | |
| 85 if (!pRoot) | |
| 86 return; | |
| 87 | |
| 88 CPDF_Dictionary* pNames = pRoot->GetDictBy("Names"); | |
| 89 if (!pNames) | |
| 90 return; | |
| 91 | |
| 92 m_pRoot = pNames->GetDictBy(category); | |
| 93 } | |
| 94 | |
| 95 static CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, | |
| 96 const CFX_ByteString& csName, | |
| 97 size_t& nIndex, | |
| 98 CPDF_Array** ppFind, | |
| 99 int nLevel = 0) { | |
| 100 if (nLevel > nMaxRecursion) { | |
| 101 return nullptr; | |
| 102 } | |
| 103 CPDF_Array* pLimits = pNode->GetArrayBy("Limits"); | |
| 104 if (pLimits) { | |
| 105 CFX_ByteString csLeft = pLimits->GetStringAt(0); | |
| 106 CFX_ByteString csRight = pLimits->GetStringAt(1); | |
| 107 if (csLeft.Compare(csRight.AsStringC()) > 0) { | |
| 108 CFX_ByteString csTmp = csRight; | |
| 109 csRight = csLeft; | |
| 110 csLeft = csTmp; | |
| 111 } | |
| 112 if (csName.Compare(csLeft.AsStringC()) < 0 || | |
| 113 csName.Compare(csRight.AsStringC()) > 0) { | |
| 114 return nullptr; | |
| 115 } | |
| 116 } | |
| 117 CPDF_Array* pNames = pNode->GetArrayBy("Names"); | |
| 118 if (pNames) { | |
| 119 size_t dwCount = pNames->GetCount() / 2; | |
| 120 for (size_t i = 0; i < dwCount; i++) { | |
| 121 CFX_ByteString csValue = pNames->GetStringAt(i * 2); | |
| 122 int32_t iCompare = csValue.Compare(csName.AsStringC()); | |
| 123 if (iCompare <= 0) { | |
| 124 if (ppFind) { | |
| 125 *ppFind = pNames; | |
| 126 } | |
| 127 if (iCompare < 0) { | |
| 128 continue; | |
| 129 } | |
| 130 } else { | |
| 131 break; | |
| 132 } | |
| 133 nIndex += i; | |
| 134 return pNames->GetDirectObjectAt(i * 2 + 1); | |
| 135 } | |
| 136 nIndex += dwCount; | |
| 137 return nullptr; | |
| 138 } | |
| 139 CPDF_Array* pKids = pNode->GetArrayBy("Kids"); | |
| 140 if (!pKids) { | |
| 141 return nullptr; | |
| 142 } | |
| 143 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
| 144 CPDF_Dictionary* pKid = pKids->GetDictAt(i); | |
| 145 if (!pKid) { | |
| 146 continue; | |
| 147 } | |
| 148 CPDF_Object* pFound = | |
| 149 SearchNameNode(pKid, csName, nIndex, ppFind, nLevel + 1); | |
| 150 if (pFound) { | |
| 151 return pFound; | |
| 152 } | |
| 153 } | |
| 154 return nullptr; | |
| 155 } | |
| 156 | |
| 157 static CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, | |
| 158 size_t nIndex, | |
| 159 size_t& nCurIndex, | |
| 160 CFX_ByteString& csName, | |
| 161 CPDF_Array** ppFind, | |
| 162 int nLevel = 0) { | |
| 163 if (nLevel > nMaxRecursion) | |
| 164 return nullptr; | |
| 165 | |
| 166 CPDF_Array* pNames = pNode->GetArrayBy("Names"); | |
| 167 if (pNames) { | |
| 168 size_t nCount = pNames->GetCount() / 2; | |
| 169 if (nIndex >= nCurIndex + nCount) { | |
| 170 nCurIndex += nCount; | |
| 171 return nullptr; | |
| 172 } | |
| 173 if (ppFind) | |
| 174 *ppFind = pNames; | |
| 175 csName = pNames->GetStringAt((nIndex - nCurIndex) * 2); | |
| 176 return pNames->GetDirectObjectAt((nIndex - nCurIndex) * 2 + 1); | |
| 177 } | |
| 178 CPDF_Array* pKids = pNode->GetArrayBy("Kids"); | |
| 179 if (!pKids) | |
| 180 return nullptr; | |
| 181 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
| 182 CPDF_Dictionary* pKid = pKids->GetDictAt(i); | |
| 183 if (!pKid) | |
| 184 continue; | |
| 185 CPDF_Object* pFound = | |
| 186 SearchNameNode(pKid, nIndex, nCurIndex, csName, ppFind, nLevel + 1); | |
| 187 if (pFound) | |
| 188 return pFound; | |
| 189 } | |
| 190 return nullptr; | |
| 191 } | |
| 192 | |
| 193 static size_t CountNames(CPDF_Dictionary* pNode, int nLevel = 0) { | |
| 194 if (nLevel > nMaxRecursion) { | |
| 195 return 0; | |
| 196 } | |
| 197 CPDF_Array* pNames = pNode->GetArrayBy("Names"); | |
| 198 if (pNames) { | |
| 199 return pNames->GetCount() / 2; | |
| 200 } | |
| 201 CPDF_Array* pKids = pNode->GetArrayBy("Kids"); | |
| 202 if (!pKids) { | |
| 203 return 0; | |
| 204 } | |
| 205 size_t nCount = 0; | |
| 206 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
| 207 CPDF_Dictionary* pKid = pKids->GetDictAt(i); | |
| 208 if (!pKid) { | |
| 209 continue; | |
| 210 } | |
| 211 nCount += CountNames(pKid, nLevel + 1); | |
| 212 } | |
| 213 return nCount; | |
| 214 } | |
| 215 | |
| 216 size_t CPDF_NameTree::GetCount() const { | |
| 217 if (!m_pRoot) { | |
| 218 return 0; | |
| 219 } | |
| 220 return ::CountNames(m_pRoot); | |
| 221 } | |
| 222 | |
| 223 int CPDF_NameTree::GetIndex(const CFX_ByteString& csName) const { | |
| 224 if (!m_pRoot) { | |
| 225 return -1; | |
| 226 } | |
| 227 size_t nIndex = 0; | |
| 228 if (!SearchNameNode(m_pRoot, csName, nIndex, nullptr)) { | |
| 229 return -1; | |
| 230 } | |
| 231 return nIndex; | |
| 232 } | |
| 233 | |
| 234 CPDF_Object* CPDF_NameTree::LookupValue(int nIndex, | |
| 235 CFX_ByteString& csName) const { | |
| 236 if (!m_pRoot) { | |
| 237 return nullptr; | |
| 238 } | |
| 239 size_t nCurIndex = 0; | |
| 240 return SearchNameNode(m_pRoot, nIndex, nCurIndex, csName, nullptr); | |
| 241 } | |
| 242 | |
| 243 CPDF_Object* CPDF_NameTree::LookupValue(const CFX_ByteString& csName) const { | |
| 244 if (!m_pRoot) { | |
| 245 return nullptr; | |
| 246 } | |
| 247 size_t nIndex = 0; | |
| 248 return SearchNameNode(m_pRoot, csName, nIndex, nullptr); | |
| 249 } | |
| 250 | |
| 251 CPDF_Array* CPDF_NameTree::LookupNamedDest(CPDF_Document* pDoc, | |
| 252 const CFX_ByteString& sName) { | |
| 253 CPDF_Object* pValue = LookupValue(sName); | |
| 254 if (!pValue) { | |
| 255 CPDF_Dictionary* pDests = pDoc->GetRoot()->GetDictBy("Dests"); | |
| 256 if (!pDests) | |
| 257 return nullptr; | |
| 258 pValue = pDests->GetDirectObjectBy(sName); | |
| 259 } | |
| 260 if (!pValue) | |
| 261 return nullptr; | |
| 262 if (CPDF_Array* pArray = pValue->AsArray()) | |
| 263 return pArray; | |
| 264 if (CPDF_Dictionary* pDict = pValue->AsDictionary()) | |
| 265 return pDict->GetArrayBy("D"); | |
| 266 return nullptr; | |
| 267 } | |
| 268 | |
| 269 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ | |
| 270 _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 271 static CFX_WideString ChangeSlashToPlatform(const FX_WCHAR* str) { | |
| 272 CFX_WideString result; | |
| 273 while (*str) { | |
| 274 if (*str == '/') { | |
| 275 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
| 276 result += ':'; | |
| 277 #else | |
| 278 result += '\\'; | |
| 279 #endif | |
| 280 } else { | |
| 281 result += *str; | |
| 282 } | |
| 283 str++; | |
| 284 } | |
| 285 return result; | |
| 286 } | |
| 287 | |
| 288 static CFX_WideString ChangeSlashToPDF(const FX_WCHAR* str) { | |
| 289 CFX_WideString result; | |
| 290 while (*str) { | |
| 291 if (*str == '\\' || *str == ':') { | |
| 292 result += '/'; | |
| 293 } else { | |
| 294 result += *str; | |
| 295 } | |
| 296 str++; | |
| 297 } | |
| 298 return result; | |
| 299 } | |
| 300 #endif // _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_WINDOWS_ | |
| 301 | |
| 302 CFX_WideString CPDF_FileSpec::DecodeFileName(const CFX_WideStringC& filepath) { | |
| 303 if (filepath.GetLength() <= 1) | |
| 304 return CFX_WideString(); | |
| 305 | |
| 306 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
| 307 if (filepath.Left(sizeof("/Mac") - 1) == CFX_WideStringC(L"/Mac")) | |
| 308 return ChangeSlashToPlatform(filepath.c_str() + 1); | |
| 309 return ChangeSlashToPlatform(filepath.c_str()); | |
| 310 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 311 if (filepath.GetAt(0) != '/') | |
| 312 return ChangeSlashToPlatform(filepath.c_str()); | |
| 313 if (filepath.GetAt(1) == '/') | |
| 314 return ChangeSlashToPlatform(filepath.c_str() + 1); | |
| 315 if (filepath.GetAt(2) == '/') { | |
| 316 CFX_WideString result; | |
| 317 result += filepath.GetAt(1); | |
| 318 result += ':'; | |
| 319 result += ChangeSlashToPlatform(filepath.c_str() + 2); | |
| 320 return result; | |
| 321 } | |
| 322 CFX_WideString result; | |
| 323 result += '\\'; | |
| 324 result += ChangeSlashToPlatform(filepath.c_str()); | |
| 325 return result; | |
| 326 #else | |
| 327 return CFX_WideString(filepath); | |
| 328 #endif | |
| 329 } | |
| 330 | |
| 331 bool CPDF_FileSpec::GetFileName(CFX_WideString* csFileName) const { | |
| 332 if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) { | |
| 333 *csFileName = pDict->GetUnicodeTextBy("UF"); | |
| 334 if (csFileName->IsEmpty()) { | |
| 335 *csFileName = | |
| 336 CFX_WideString::FromLocal(pDict->GetStringBy("F").AsStringC()); | |
| 337 } | |
| 338 if (pDict->GetStringBy("FS") == "URL") | |
| 339 return true; | |
| 340 if (csFileName->IsEmpty()) { | |
| 341 if (pDict->KeyExist("DOS")) { | |
| 342 *csFileName = | |
| 343 CFX_WideString::FromLocal(pDict->GetStringBy("DOS").AsStringC()); | |
| 344 } else if (pDict->KeyExist("Mac")) { | |
| 345 *csFileName = | |
| 346 CFX_WideString::FromLocal(pDict->GetStringBy("Mac").AsStringC()); | |
| 347 } else if (pDict->KeyExist("Unix")) { | |
| 348 *csFileName = | |
| 349 CFX_WideString::FromLocal(pDict->GetStringBy("Unix").AsStringC()); | |
| 350 } else { | |
| 351 return false; | |
| 352 } | |
| 353 } | |
| 354 } else if (m_pObj->IsString()) { | |
| 355 *csFileName = CFX_WideString::FromLocal(m_pObj->GetString().AsStringC()); | |
| 356 } else { | |
| 357 return false; | |
| 358 } | |
| 359 *csFileName = DecodeFileName(csFileName->AsStringC()); | |
| 360 return true; | |
| 361 } | |
| 362 | |
| 363 CPDF_FileSpec::CPDF_FileSpec() { | |
| 364 m_pObj = new CPDF_Dictionary; | |
| 365 m_pObj->AsDictionary()->SetAtName("Type", "Filespec"); | |
| 366 } | |
| 367 | |
| 368 CFX_WideString CPDF_FileSpec::EncodeFileName(const CFX_WideStringC& filepath) { | |
| 369 if (filepath.GetLength() <= 1) { | |
| 370 return CFX_WideString(); | |
| 371 } | |
| 372 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 373 if (filepath.GetAt(1) == ':') { | |
| 374 CFX_WideString result; | |
| 375 result = '/'; | |
| 376 result += filepath.GetAt(0); | |
| 377 if (filepath.GetAt(2) != '\\') { | |
| 378 result += '/'; | |
| 379 } | |
| 380 result += ChangeSlashToPDF(filepath.c_str() + 2); | |
| 381 return result; | |
| 382 } | |
| 383 if (filepath.GetAt(0) == '\\' && filepath.GetAt(1) == '\\') { | |
| 384 return ChangeSlashToPDF(filepath.c_str() + 1); | |
| 385 } | |
| 386 if (filepath.GetAt(0) == '\\') { | |
| 387 CFX_WideString result; | |
| 388 result = '/'; | |
| 389 result += ChangeSlashToPDF(filepath.c_str()); | |
| 390 return result; | |
| 391 } | |
| 392 return ChangeSlashToPDF(filepath.c_str()); | |
| 393 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
| 394 if (filepath.Left(sizeof("Mac") - 1) == FX_WSTRC(L"Mac")) { | |
| 395 CFX_WideString result; | |
| 396 result = '/'; | |
| 397 result += ChangeSlashToPDF(filepath.c_str()); | |
| 398 return result; | |
| 399 } | |
| 400 return ChangeSlashToPDF(filepath.c_str()); | |
| 401 #else | |
| 402 return CFX_WideString(filepath); | |
| 403 #endif | |
| 404 } | |
| 405 | |
| 406 void CPDF_FileSpec::SetFileName(const CFX_WideStringC& wsFileName) { | |
| 407 if (!m_pObj) | |
| 408 return; | |
| 409 | |
| 410 CFX_WideString wsStr = EncodeFileName(wsFileName); | |
| 411 if (m_pObj->IsString()) { | |
| 412 m_pObj->SetString(CFX_ByteString::FromUnicode(wsStr)); | |
| 413 } else if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) { | |
| 414 pDict->SetAtString("F", CFX_ByteString::FromUnicode(wsStr)); | |
| 415 pDict->SetAtString("UF", PDF_EncodeText(wsStr)); | |
| 416 } | |
| 417 } | |
| 418 | |
| 419 static CFX_WideString _MakeRoman(int num) { | |
| 420 const int arabic[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; | |
| 421 const CFX_WideString roman[] = {L"m", L"cm", L"d", L"cd", L"c", | |
| 422 L"xc", L"l", L"xl", L"x", L"ix", | |
| 423 L"v", L"iv", L"i"}; | |
| 424 const int nMaxNum = 1000000; | |
| 425 num %= nMaxNum; | |
| 426 int i = 0; | |
| 427 CFX_WideString wsRomanNumber; | |
| 428 while (num > 0) { | |
| 429 while (num >= arabic[i]) { | |
| 430 num = num - arabic[i]; | |
| 431 wsRomanNumber += roman[i]; | |
| 432 } | |
| 433 i = i + 1; | |
| 434 } | |
| 435 return wsRomanNumber; | |
| 436 } | |
| 437 | |
| 438 static CFX_WideString _MakeLetters(int num) { | |
| 439 if (num == 0) { | |
| 440 return CFX_WideString(); | |
| 441 } | |
| 442 CFX_WideString wsLetters; | |
| 443 const int nMaxCount = 1000; | |
| 444 const int nLetterCount = 26; | |
| 445 num -= 1; | |
| 446 int count = num / nLetterCount + 1; | |
| 447 count %= nMaxCount; | |
| 448 FX_WCHAR ch = L'a' + num % nLetterCount; | |
| 449 for (int i = 0; i < count; i++) { | |
| 450 wsLetters += ch; | |
| 451 } | |
| 452 return wsLetters; | |
| 453 } | |
| 454 | |
| 455 static CFX_WideString _GetLabelNumPortion(int num, | |
| 456 const CFX_ByteString& bsStyle) { | |
| 457 CFX_WideString wsNumPortion; | |
| 458 if (bsStyle.IsEmpty()) { | |
| 459 return wsNumPortion; | |
| 460 } | |
| 461 if (bsStyle == "D") { | |
| 462 wsNumPortion.Format(L"%d", num); | |
| 463 } else if (bsStyle == "R") { | |
| 464 wsNumPortion = _MakeRoman(num); | |
| 465 wsNumPortion.MakeUpper(); | |
| 466 } else if (bsStyle == "r") { | |
| 467 wsNumPortion = _MakeRoman(num); | |
| 468 } else if (bsStyle == "A") { | |
| 469 wsNumPortion = _MakeLetters(num); | |
| 470 wsNumPortion.MakeUpper(); | |
| 471 } else if (bsStyle == "a") { | |
| 472 wsNumPortion = _MakeLetters(num); | |
| 473 } | |
| 474 return wsNumPortion; | |
| 475 } | |
| 476 | |
| 477 IPDF_FormNotify::~IPDF_FormNotify() {} | |
| 478 | |
| 479 int IPDF_FormNotify::BeforeValueChange(CPDF_FormField* pField, | |
| 480 const CFX_WideString& csValue) { | |
| 481 return 0; | |
| 482 } | |
| 483 | |
| 484 void IPDF_FormNotify::AfterValueChange(CPDF_FormField* pField) {} | |
| 485 | |
| 486 int IPDF_FormNotify::BeforeSelectionChange(CPDF_FormField* pField, | |
| 487 const CFX_WideString& csValue) { | |
| 488 return 0; | |
| 489 } | |
| 490 | |
| 491 void IPDF_FormNotify::AfterSelectionChange(CPDF_FormField* pField) {} | |
| 492 | |
| 493 void IPDF_FormNotify::AfterCheckedStatusChange(CPDF_FormField* pField) {} | |
| 494 | |
| 495 int IPDF_FormNotify::BeforeFormReset(CPDF_InterForm* pForm) { | |
| 496 return 0; | |
| 497 } | |
| 498 | |
| 499 void IPDF_FormNotify::AfterFormReset(CPDF_InterForm* pForm) {} | |
| 500 | |
| 501 int IPDF_FormNotify::BeforeFormImportData(CPDF_InterForm* pForm) { | |
| 502 return 0; | |
| 503 } | |
| 504 | |
| 505 void IPDF_FormNotify::AfterFormImportData(CPDF_InterForm* pForm) {} | |
| 506 | |
| 507 CPDF_PageLabel::CPDF_PageLabel(CPDF_Document* pDocument) | |
| 508 : m_pDocument(pDocument) {} | |
| 509 | |
| 510 CFX_WideString CPDF_PageLabel::GetLabel(int nPage) const { | |
| 511 CFX_WideString wsLabel; | |
| 512 if (!m_pDocument) { | |
| 513 return wsLabel; | |
| 514 } | |
| 515 CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot(); | |
| 516 if (!pPDFRoot) { | |
| 517 return wsLabel; | |
| 518 } | |
| 519 CPDF_Dictionary* pLabels = pPDFRoot->GetDictBy("PageLabels"); | |
| 520 CPDF_NumberTree numberTree(pLabels); | |
| 521 CPDF_Object* pValue = nullptr; | |
| 522 int n = nPage; | |
| 523 while (n >= 0) { | |
| 524 pValue = numberTree.LookupValue(n); | |
| 525 if (pValue) { | |
| 526 break; | |
| 527 } | |
| 528 n--; | |
| 529 } | |
| 530 if (pValue) { | |
| 531 pValue = pValue->GetDirect(); | |
| 532 if (CPDF_Dictionary* pLabel = pValue->AsDictionary()) { | |
| 533 if (pLabel->KeyExist("P")) { | |
| 534 wsLabel += pLabel->GetUnicodeTextBy("P"); | |
| 535 } | |
| 536 CFX_ByteString bsNumberingStyle = pLabel->GetStringBy("S", ""); | |
| 537 int nLabelNum = nPage - n + pLabel->GetIntegerBy("St", 1); | |
| 538 CFX_WideString wsNumPortion = | |
| 539 _GetLabelNumPortion(nLabelNum, bsNumberingStyle); | |
| 540 wsLabel += wsNumPortion; | |
| 541 return wsLabel; | |
| 542 } | |
| 543 } | |
| 544 wsLabel.Format(L"%d", nPage + 1); | |
| 545 return wsLabel; | |
| 546 } | |
| 547 | |
| 548 int32_t CPDF_PageLabel::GetPageByLabel(const CFX_ByteStringC& bsLabel) const { | |
| 549 if (!m_pDocument) | |
| 550 return -1; | |
| 551 | |
| 552 CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot(); | |
| 553 if (!pPDFRoot) | |
| 554 return -1; | |
| 555 | |
| 556 int nPages = m_pDocument->GetPageCount(); | |
| 557 for (int i = 0; i < nPages; i++) { | |
| 558 if (PDF_EncodeText(GetLabel(i)).Compare(bsLabel)) | |
| 559 return i; | |
| 560 } | |
| 561 | |
| 562 int nPage = FXSYS_atoi(CFX_ByteString(bsLabel).c_str()); // NUL terminate. | |
| 563 return nPage > 0 && nPage <= nPages ? nPage : -1; | |
| 564 } | |
| 565 | |
| 566 int32_t CPDF_PageLabel::GetPageByLabel(const CFX_WideStringC& wsLabel) const { | |
| 567 return GetPageByLabel(PDF_EncodeText(wsLabel.c_str()).AsStringC()); | |
| 568 } | |
| OLD | NEW |