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 "core/fpdfapi/cpdf_modulemgr.h" 10 #include "core/fpdfapi/font/font_int.h" 11 #include "core/fpdfapi/page/cpdf_pagemodule.h" 12 13 extern "C" { 14 15 static int compareWord(const void* p1, const void* p2) { 16 return (*(uint16_t*)p1) - (*(uint16_t*)p2); 17 } 18 19 static int compareWordRange(const void* key, const void* element) { 20 if (*(uint16_t*)key < *(uint16_t*)element) 21 return -1; 22 if (*(uint16_t*)key > ((uint16_t*)element)[1]) 23 return 1; 24 return 0; 25 } 26 27 static int compareDWordRange(const void* p1, const void* p2) { 28 uint32_t key = *(uint32_t*)p1; 29 uint16_t hiword = (uint16_t)(key >> 16); 30 uint16_t* element = (uint16_t*)p2; 31 if (hiword < element[0]) 32 return -1; 33 if (hiword > element[0]) 34 return 1; 35 36 uint16_t loword = (uint16_t)key; 37 if (loword < element[1]) 38 return -1; 39 if (loword > element[2]) 40 return 1; 41 return 0; 42 } 43 44 static int compareDWordSingle(const void* p1, const void* p2) { 45 uint32_t key = *(uint32_t*)p1; 46 uint32_t value = ((*(uint16_t*)p2) << 16) | ((uint16_t*)p2)[1]; 47 if (key < value) 48 return -1; 49 if (key > value) 50 return 1; 51 return 0; 52 } 53 54 }; // extern "C" 55 56 void FPDFAPI_FindEmbeddedCMap(const CFX_ByteString& bsName, 57 int charset, 58 int coding, 59 const FXCMAP_CMap*& pMap) { 60 pMap = nullptr; 61 CPDF_FontGlobals* pFontGlobals = 62 CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); 63 const FXCMAP_CMap* pCMaps = 64 pFontGlobals->m_EmbeddedCharsets[charset].m_pMapList; 65 for (uint32_t i = 0; i < pFontGlobals->m_EmbeddedCharsets[charset].m_Count; 66 i++) { 67 if (bsName == pCMaps[i].m_Name) { 68 pMap = &pCMaps[i]; 69 break; 70 } 71 } 72 } 73 74 uint16_t FPDFAPI_CIDFromCharCode(const FXCMAP_CMap* pMap, uint32_t charcode) { 75 if (charcode >> 16) { 76 while (1) { 77 if (pMap->m_DWordMapType == FXCMAP_CMap::Range) { 78 uint16_t* found = static_cast<uint16_t*>( 79 FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 8, 80 compareDWordRange)); 81 if (found) 82 return found[3] + (uint16_t)charcode - found[1]; 83 84 } else if (pMap->m_DWordMapType == FXCMAP_CMap::Single) { 85 uint16_t* found = static_cast<uint16_t*>( 86 FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 6, 87 compareDWordSingle)); 88 if (found) 89 return found[2]; 90 } 91 if (pMap->m_UseOffset == 0) 92 return 0; 93 94 pMap = pMap + pMap->m_UseOffset; 95 } 96 return 0; 97 } 98 99 uint16_t code = (uint16_t)charcode; 100 while (1) { 101 if (!pMap->m_pWordMap) 102 return 0; 103 if (pMap->m_WordMapType == FXCMAP_CMap::Single) { 104 uint16_t* found = static_cast<uint16_t*>(FXSYS_bsearch( 105 &code, pMap->m_pWordMap, pMap->m_WordCount, 4, compareWord)); 106 if (found) 107 return found[1]; 108 109 } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) { 110 uint16_t* found = static_cast<uint16_t*>(FXSYS_bsearch( 111 &code, pMap->m_pWordMap, pMap->m_WordCount, 6, compareWordRange)); 112 if (found) 113 return found[2] + code - found[0]; 114 } 115 if (pMap->m_UseOffset == 0) 116 return 0; 117 118 pMap = pMap + pMap->m_UseOffset; 119 } 120 return 0; 121 } 122 123 uint32_t FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, uint16_t cid) { 124 // TODO(dsinclair): This should be checking both pMap->m_WordMap and 125 // pMap->m_DWordMap. There was a second while() but it was never reached as 126 // the first always returns. Investigate and determine how this should 127 // really be working. (https://codereview.chromium.org/2235743003 removed the 128 // second while loop.) 129 while (1) { 130 if (pMap->m_WordMapType == FXCMAP_CMap::Single) { 131 const uint16_t* pCur = pMap->m_pWordMap; 132 const uint16_t* pEnd = pMap->m_pWordMap + pMap->m_WordCount * 2; 133 while (pCur < pEnd) { 134 if (pCur[1] == cid) 135 return pCur[0]; 136 137 pCur += 2; 138 } 139 } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) { 140 const uint16_t* pCur = pMap->m_pWordMap; 141 const uint16_t* pEnd = pMap->m_pWordMap + pMap->m_WordCount * 3; 142 while (pCur < pEnd) { 143 if (cid >= pCur[2] && cid <= pCur[2] + pCur[1] - pCur[0]) 144 return pCur[0] + cid - pCur[2]; 145 146 pCur += 3; 147 } 148 } 149 if (pMap->m_UseOffset == 0) 150 return 0; 151 152 pMap = pMap + pMap->m_UseOffset; 153 } 154 } 155