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_cmaps/cmap_int.h" | |
8 | |
9 #include "core/fpdfapi/cpdf_modulemgr.h" | |
10 #include "core/fpdfapi/fpdf_font/font_int.h" | |
11 #include "core/fpdfapi/fpdf_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 } | |
OLD | NEW |