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