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
compareWord(const void * p1,const void * p2)15 static int compareWord(const void* p1, const void* p2) {
16 return (*(uint16_t*)p1) - (*(uint16_t*)p2);
17 }
18
compareWordRange(const void * key,const void * element)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
compareDWordRange(const void * p1,const void * p2)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
compareDWordSingle(const void * p1,const void * p2)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
FPDFAPI_FindEmbeddedCMap(const CFX_ByteString & bsName,int charset,int coding,const FXCMAP_CMap * & pMap)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
FPDFAPI_CIDFromCharCode(const FXCMAP_CMap * pMap,uint32_t charcode)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
FPDFAPI_CharCodeFromCID(const FXCMAP_CMap * pMap,uint16_t cid)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