// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
 
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../../include/fpdfapi/fpdf_resource.h"
#include "../../../include/fpdfapi/fpdf_module.h"
#include "../fpdf_font/font_int.h"
#include "cmap_int.h"
void FPDFAPI_FindEmbeddedCMap(const char* name, int charset, int coding, const FXCMAP_CMap*& pMap)
{
    pMap = NULL;
    CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
    const FXCMAP_CMap* pCMaps = pFontGlobals->m_EmbeddedCharsets[charset].m_pMapList;
    int nCMaps = pFontGlobals->m_EmbeddedCharsets[charset].m_Count;
    for (int i = 0; i < nCMaps; i ++) {
        if (FXSYS_strcmp(name, pCMaps[i].m_Name)) {
            continue;
        }
        pMap = &pCMaps[i];
        break;
    }
}
extern "C" {
    static int compareWord(const void* p1, const void* p2)
    {
        return (*(FX_WORD*)p1) - (*(FX_WORD*)p2);
    }
};
extern "C" {
    static int compareWordRange(const void* key, const void* element)
    {
        if (*(FX_WORD*)key < * (FX_WORD*)element) {
            return -1;
        }
        if (*(FX_WORD*)key > ((FX_WORD*)element)[1]) {
            return 1;
        }
        return 0;
    }
};
extern "C" {
    static int compareDWordRange(const void* p1, const void* p2)
    {
        FX_DWORD key = *(FX_DWORD*)p1;
        FX_WORD hiword = (FX_WORD)(key >> 16);
        FX_WORD* element = (FX_WORD*)p2;
        if (hiword < element[0]) {
            return -1;
        }
        if (hiword > element[0]) {
            return 1;
        }
        FX_WORD loword = (FX_WORD)key;
        if (loword < element[1]) {
            return -1;
        }
        if (loword > element[2]) {
            return 1;
        }
        return 0;
    }
};
extern "C" {
    static int compareDWordSingle(const void* p1, const void* p2)
    {
        FX_DWORD key = *(FX_DWORD*)p1;
        FX_DWORD value = ((*(FX_WORD*)p2) << 16) | ((FX_WORD*)p2)[1];
        if (key < value) {
            return -1;
        }
        if (key > value) {
            return 1;
        }
        return 0;
    }
};
FX_WORD FPDFAPI_CIDFromCharCode(const FXCMAP_CMap* pMap, FX_DWORD charcode)
{
    if (charcode >> 16) {
        while (1) {
            if (pMap->m_DWordMapType == FXCMAP_CMap::Range) {
                FX_WORD* found = (FX_WORD*)FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 8, compareDWordRange);
                if (found) {
                    return found[3] + (FX_WORD)charcode - found[1];
                }
            } else if (pMap->m_DWordMapType == FXCMAP_CMap::Single) {
                FX_WORD* found = (FX_WORD*)FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 6, compareDWordSingle);
                if (found) {
                    return found[2];
                }
            }
            if (pMap->m_UseOffset == 0) {
                return 0;
            }
            pMap = pMap + pMap->m_UseOffset;
        }
        return 0;
    }
    FX_WORD code = (FX_WORD)charcode;
    while (1) {
        if (pMap->m_pWordMap == NULL) {
            return 0;
        }
        if (pMap->m_WordMapType == FXCMAP_CMap::Single) {
            FX_WORD* found = (FX_WORD*)FXSYS_bsearch(&code, pMap->m_pWordMap, pMap->m_WordCount, 4, compareWord);
            if (found) {
                return found[1];
            }
        } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) {
            FX_WORD* found = (FX_WORD*)FXSYS_bsearch(&code, pMap->m_pWordMap, pMap->m_WordCount, 6, compareWordRange);
            if (found) {
                return found[2] + code - found[0];
            }
        }
        if (pMap->m_UseOffset == 0) {
            return 0;
        }
        pMap = pMap + pMap->m_UseOffset;
    }
    return 0;
}
FX_DWORD FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, FX_WORD cid)
{
    while (1) {
        if (pMap->m_WordMapType == FXCMAP_CMap::Single) {
            const FX_WORD *pCur = pMap->m_pWordMap;
            const FX_WORD *pEnd = pMap->m_pWordMap + pMap->m_WordCount * 2;
            while (pCur < pEnd) {
                if (pCur[1] == cid) {
                    return pCur[0];
                }
                pCur += 2;
            }
        } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) {
            const FX_WORD *pCur = pMap->m_pWordMap;
            const FX_WORD *pEnd = pMap->m_pWordMap + pMap->m_WordCount * 3;
            while (pCur < pEnd) {
                if (cid >= pCur[2] && cid <= pCur[2] + pCur[1] - pCur[0]) {
                    return pCur[0] + cid - pCur[2];
                }
                pCur += 3;
            }
        }
        if (pMap->m_UseOffset == 0) {
            return 0;
        }
        pMap = pMap + pMap->m_UseOffset;
    }
    while (1) {
        if (pMap->m_DWordMapType == FXCMAP_CMap::Range) {
            const FX_WORD *pCur = pMap->m_pDWordMap;
            const FX_WORD *pEnd = pMap->m_pDWordMap + pMap->m_DWordCount * 4;
            while (pCur < pEnd) {
                if (cid >= pCur[3] && cid <= pCur[3] + pCur[2] - pCur[1]) {
                    return (((FX_DWORD)pCur[0] << 16) | pCur[1]) + cid - pCur[3];
                }
                pCur += 4;
            }
        } else if (pMap->m_DWordMapType == FXCMAP_CMap::Single) {
            const FX_WORD *pCur = pMap->m_pDWordMap;
            const FX_WORD *pEnd = pMap->m_pDWordMap + pMap->m_DWordCount * 3;
            while (pCur < pEnd) {
                if (pCur[2] == cid) {
                    return ((FX_DWORD)pCur[0] << 16) | pCur[1];
                }
                pCur += 3;
            }
        }
        if (pMap->m_UseOffset == 0) {
            return 0;
        }
        pMap = pMap + pMap->m_UseOffset;
    }
    return 0;
}
void FPDFAPI_LoadCID2UnicodeMap(int charset, const FX_WORD*& pMap, FX_DWORD& count)
{
    CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
    pMap = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap;
    count = pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count;
}
