• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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