Initial commit.
[pdfium.git] / core / src / fpdfapi / fpdf_cmaps / fpdf_cmaps.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../include/fpdfapi/fpdf_resource.h"\r
8 #include "../../../include/fpdfapi/fpdf_module.h"\r
9 #include "../fpdf_font/font_int.h"\r
10 #include "cmap_int.h"\r
11 void FPDFAPI_FindEmbeddedCMap(const char* name, int charset, int coding, const FXCMAP_CMap*& pMap)\r
12 {\r
13     pMap = NULL;\r
14     CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();\r
15     const FXCMAP_CMap* pCMaps = pFontGlobals->m_EmbeddedCharsets[charset].m_pMapList;\r
16     int nCMaps = pFontGlobals->m_EmbeddedCharsets[charset].m_Count;\r
17     for (int i = 0; i < nCMaps; i ++) {\r
18         if (FXSYS_strcmp(name, pCMaps[i].m_Name)) {\r
19             continue;\r
20         }\r
21         pMap = &pCMaps[i];\r
22         break;\r
23     }\r
24 }\r
25 extern "C" {\r
26     static int compareWord(const void* p1, const void* p2)\r
27     {\r
28         return (*(FX_WORD*)p1) - (*(FX_WORD*)p2);\r
29     }\r
30 };\r
31 extern "C" {\r
32     static int compareWordRange(const void* key, const void* element)\r
33     {\r
34         if (*(FX_WORD*)key < * (FX_WORD*)element) {\r
35             return -1;\r
36         }\r
37         if (*(FX_WORD*)key > ((FX_WORD*)element)[1]) {\r
38             return 1;\r
39         }\r
40         return 0;\r
41     }\r
42 };\r
43 extern "C" {\r
44     static int compareDWordRange(const void* p1, const void* p2)\r
45     {\r
46         FX_DWORD key = *(FX_DWORD*)p1;\r
47         FX_WORD hiword = (FX_WORD)(key >> 16);\r
48         FX_WORD* element = (FX_WORD*)p2;\r
49         if (hiword < element[0]) {\r
50             return -1;\r
51         }\r
52         if (hiword > element[0]) {\r
53             return 1;\r
54         }\r
55         FX_WORD loword = (FX_WORD)key;\r
56         if (loword < element[1]) {\r
57             return -1;\r
58         }\r
59         if (loword > element[2]) {\r
60             return 1;\r
61         }\r
62         return 0;\r
63     }\r
64 };\r
65 extern "C" {\r
66     static int compareDWordSingle(const void* p1, const void* p2)\r
67     {\r
68         FX_DWORD key = *(FX_DWORD*)p1;\r
69         FX_DWORD value = ((*(FX_WORD*)p2) << 16) | ((FX_WORD*)p2)[1];\r
70         if (key < value) {\r
71             return -1;\r
72         }\r
73         if (key > value) {\r
74             return 1;\r
75         }\r
76         return 0;\r
77     }\r
78 };\r
79 FX_WORD FPDFAPI_CIDFromCharCode(const FXCMAP_CMap* pMap, FX_DWORD charcode)\r
80 {\r
81     if (charcode >> 16) {\r
82         while (1) {\r
83             if (pMap->m_DWordMapType == FXCMAP_CMap::Range) {\r
84                 FX_WORD* found = (FX_WORD*)FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 8, compareDWordRange);\r
85                 if (found) {\r
86                     return found[3] + (FX_WORD)charcode - found[1];\r
87                 }\r
88             } else if (pMap->m_DWordMapType == FXCMAP_CMap::Single) {\r
89                 FX_WORD* found = (FX_WORD*)FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 6, compareDWordSingle);\r
90                 if (found) {\r
91                     return found[2];\r
92                 }\r
93             }\r
94             if (pMap->m_UseOffset == 0) {\r
95                 return 0;\r
96             }\r
97             pMap = pMap + pMap->m_UseOffset;\r
98         }\r
99         return 0;\r
100     }\r
101     FX_WORD code = (FX_WORD)charcode;\r
102     while (1) {\r
103         if (pMap->m_pWordMap == NULL) {\r
104             return 0;\r
105         }\r
106         if (pMap->m_WordMapType == FXCMAP_CMap::Single) {\r
107             FX_WORD* found = (FX_WORD*)FXSYS_bsearch(&code, pMap->m_pWordMap, pMap->m_WordCount, 4, compareWord);\r
108             if (found) {\r
109                 return found[1];\r
110             }\r
111         } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) {\r
112             FX_WORD* found = (FX_WORD*)FXSYS_bsearch(&code, pMap->m_pWordMap, pMap->m_WordCount, 6, compareWordRange);\r
113             if (found) {\r
114                 return found[2] + code - found[0];\r
115             }\r
116         }\r
117         if (pMap->m_UseOffset == 0) {\r
118             return 0;\r
119         }\r
120         pMap = pMap + pMap->m_UseOffset;\r
121     }\r
122     return 0;\r
123 }\r
124 FX_DWORD FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, FX_WORD cid)\r
125 {\r
126     while (1) {\r
127         if (pMap->m_WordMapType == FXCMAP_CMap::Single) {\r
128             const FX_WORD *pCur = pMap->m_pWordMap;\r
129             const FX_WORD *pEnd = pMap->m_pWordMap + pMap->m_WordCount * 2;\r
130             while (pCur < pEnd) {\r
131                 if (pCur[1] == cid) {\r
132                     return pCur[0];\r
133                 }\r
134                 pCur += 2;\r
135             }\r
136         } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) {\r
137             const FX_WORD *pCur = pMap->m_pWordMap;\r
138             const FX_WORD *pEnd = pMap->m_pWordMap + pMap->m_WordCount * 3;\r
139             while (pCur < pEnd) {\r
140                 if (cid >= pCur[2] && cid <= pCur[2] + pCur[1] - pCur[0]) {\r
141                     return pCur[0] + cid - pCur[2];\r
142                 }\r
143                 pCur += 3;\r
144             }\r
145         }\r
146         if (pMap->m_UseOffset == 0) {\r
147             return 0;\r
148         }\r
149         pMap = pMap + pMap->m_UseOffset;\r
150     }\r
151     while (1) {\r
152         if (pMap->m_DWordMapType == FXCMAP_CMap::Range) {\r
153             const FX_WORD *pCur = pMap->m_pDWordMap;\r
154             const FX_WORD *pEnd = pMap->m_pDWordMap + pMap->m_DWordCount * 4;\r
155             while (pCur < pEnd) {\r
156                 if (cid >= pCur[3] && cid <= pCur[3] + pCur[2] - pCur[1]) {\r
157                     return (((FX_DWORD)pCur[0] << 16) | pCur[1]) + cid - pCur[3];\r
158                 }\r
159                 pCur += 4;\r
160             }\r
161         } else if (pMap->m_DWordMapType == FXCMAP_CMap::Single) {\r
162             const FX_WORD *pCur = pMap->m_pDWordMap;\r
163             const FX_WORD *pEnd = pMap->m_pDWordMap + pMap->m_DWordCount * 3;\r
164             while (pCur < pEnd) {\r
165                 if (pCur[2] == cid) {\r
166                     return ((FX_DWORD)pCur[0] << 16) | pCur[1];\r
167                 }\r
168                 pCur += 3;\r
169             }\r
170         }\r
171         if (pMap->m_UseOffset == 0) {\r
172             return 0;\r
173         }\r
174         pMap = pMap + pMap->m_UseOffset;\r
175     }\r
176     return 0;\r
177 }\r
178 void FPDFAPI_LoadCID2UnicodeMap(int charset, const FX_WORD*& pMap, FX_DWORD& count)\r
179 {\r
180     CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();\r
181     pMap = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap;\r
182     count = pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count;\r
183 }\r