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/cmaps/cmap_int.h" 8 9 #include <algorithm> 10 11 #include "core/fpdfapi/cpdf_modulemgr.h" 12 #include "core/fpdfapi/font/cpdf_fontglobals.h" 13 #include "core/fpdfapi/page/cpdf_pagemodule.h" 14 15 namespace { 16 17 const FXCMAP_CMap* FindNextCMap(const FXCMAP_CMap* pMap) { 18 return pMap->m_UseOffset ? pMap + pMap->m_UseOffset : nullptr; 19 } 20 21 } // namespace 22 23 const FXCMAP_CMap* FPDFAPI_FindEmbeddedCMap(const ByteString& bsName, 24 int charset, 25 int coding) { 26 CPDF_FontGlobals* pFontGlobals = 27 CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); 28 29 const FXCMAP_CMap* pCMaps; 30 uint32_t count; 31 std::tie(count, pCMaps) = pFontGlobals->GetEmbeddedCharset(charset); 32 for (uint32_t i = 0; i < count; i++) { 33 if (bsName == pCMaps[i].m_Name) 34 return &pCMaps[i]; 35 } 36 return nullptr; 37 } 38 39 uint16_t FPDFAPI_CIDFromCharCode(const FXCMAP_CMap* pMap, uint32_t charcode) { 40 ASSERT(pMap); 41 const uint16_t loword = static_cast<uint16_t>(charcode); 42 if (charcode >> 16) { 43 while (pMap) { 44 if (pMap->m_pDWordMap) { 45 const FXCMAP_DWordCIDMap* begin = pMap->m_pDWordMap; 46 const auto* end = begin + pMap->m_DWordCount; 47 const auto* found = std::lower_bound( 48 begin, end, charcode, 49 [](const FXCMAP_DWordCIDMap& element, uint32_t charcode) { 50 uint16_t hiword = static_cast<uint16_t>(charcode >> 16); 51 if (element.m_HiWord != hiword) 52 return element.m_HiWord < hiword; 53 return element.m_LoWordHigh < static_cast<uint16_t>(charcode); 54 }); 55 if (found != end && loword >= found->m_LoWordLow && 56 loword <= found->m_LoWordHigh) { 57 return found->m_CID + loword - found->m_LoWordLow; 58 } 59 } 60 pMap = FindNextCMap(pMap); 61 } 62 return 0; 63 } 64 65 while (pMap) { 66 if (!pMap->m_pWordMap) 67 return 0; 68 if (pMap->m_WordMapType == FXCMAP_CMap::Single) { 69 struct SingleCmap { 70 uint16_t code; 71 uint16_t cid; 72 }; 73 const auto* begin = reinterpret_cast<const SingleCmap*>(pMap->m_pWordMap); 74 const auto* end = begin + pMap->m_WordCount; 75 const auto* found = std::lower_bound( 76 begin, end, loword, [](const SingleCmap& element, uint16_t code) { 77 return element.code < code; 78 }); 79 if (found != end && found->code == loword) 80 return found->cid; 81 } else { 82 ASSERT(pMap->m_WordMapType == FXCMAP_CMap::Range); 83 struct RangeCmap { 84 uint16_t low; 85 uint16_t high; 86 uint16_t cid; 87 }; 88 const auto* begin = reinterpret_cast<const RangeCmap*>(pMap->m_pWordMap); 89 const auto* end = begin + pMap->m_WordCount; 90 const auto* found = std::lower_bound( 91 begin, end, loword, [](const RangeCmap& element, uint16_t code) { 92 return element.high < code; 93 }); 94 if (found != end && loword >= found->low && loword <= found->high) 95 return found->cid + loword - found->low; 96 } 97 pMap = FindNextCMap(pMap); 98 } 99 return 0; 100 } 101 102 uint32_t FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, uint16_t cid) { 103 // TODO(dsinclair): This should be checking both pMap->m_WordMap and 104 // pMap->m_DWordMap. There was a second while() but it was never reached as 105 // the first always returns. Investigate and determine how this should 106 // really be working. (https://codereview.chromium.org/2235743003 removed the 107 // second while loop.) 108 ASSERT(pMap); 109 while (pMap) { 110 if (pMap->m_WordMapType == FXCMAP_CMap::Single) { 111 const uint16_t* pCur = pMap->m_pWordMap; 112 const uint16_t* pEnd = pMap->m_pWordMap + pMap->m_WordCount * 2; 113 while (pCur < pEnd) { 114 if (pCur[1] == cid) 115 return pCur[0]; 116 117 pCur += 2; 118 } 119 } else { 120 ASSERT(pMap->m_WordMapType == FXCMAP_CMap::Range); 121 const uint16_t* pCur = pMap->m_pWordMap; 122 const uint16_t* pEnd = pMap->m_pWordMap + pMap->m_WordCount * 3; 123 while (pCur < pEnd) { 124 if (cid >= pCur[2] && cid <= pCur[2] + pCur[1] - pCur[0]) 125 return pCur[0] + cid - pCur[2]; 126 127 pCur += 3; 128 } 129 } 130 pMap = FindNextCMap(pMap); 131 } 132 return 0; 133 } 134