// 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

typedef void* FXFT_Library;
class CPDF_CMapManager : public CFX_Object
{
public:
    CPDF_CMapManager();
    ~CPDF_CMapManager();
    FX_LPVOID				GetPackage(FX_BOOL bPrompt);
    CPDF_CMap*				GetPredefinedCMap(const CFX_ByteString& name, FX_BOOL bPrompt);
    CPDF_CID2UnicodeMap*	GetCID2UnicodeMap(int charset, FX_BOOL bPrompt);
    void					ReloadAll();
private:
    CPDF_CMap*				LoadPredefinedCMap(const CFX_ByteString& name,  FX_BOOL bPrompt);
    CPDF_CID2UnicodeMap*	LoadCID2UnicodeMap(int charset, FX_BOOL bPrompt);
    void					DropAll(FX_BOOL bReload);
#ifndef _FPDFAPI_MINI_
    FX_BOOL					m_bPrompted;
    FX_LPVOID				m_pPackage;
#endif
    CFX_MapByteStringToPtr	m_CMaps;
    CPDF_CID2UnicodeMap*	m_CID2UnicodeMaps[6];
};
class CPDF_FontGlobals : public CFX_Object
{
public:
    CPDF_FontGlobals();
    ~CPDF_FontGlobals();
    void				ClearAll();
    void				Clear(void* key);
    CPDF_Font*			Find(void* key, int index);
    void				Set(void* key, int index, CPDF_Font* pFont);
    CFX_MapPtrToPtr		m_pStockMap;
    CPDF_CMapManager	m_CMapManager;
    struct {
        const struct FXCMAP_CMap*	m_pMapList;
        int				m_Count;
    } m_EmbeddedCharsets[5];
    struct {
        const FX_WORD*	m_pMap;
        int				m_Count;
    } m_EmbeddedToUnicodes[5];
    FX_LPBYTE			m_pContrastRamps;
};
struct _CMap_CodeRange {
    int			m_CharSize;
    FX_BYTE		m_Lower[4];
    FX_BYTE		m_Upper[4];
};
class CPDF_CMapParser : public CFX_Object
{
public:
    CPDF_CMapParser();
    ~CPDF_CMapParser() {}
    FX_BOOL	Initialize(CPDF_CMap*);
    void	ParseWord(FX_BSTR str);
    CFX_BinaryBuf	m_AddMaps;
private:
    CPDF_CMap*	m_pCMap;
    int				m_Status;
    int				m_CodeSeq;
    FX_DWORD		m_CodePoints[4];
    CFX_ArrayTemplate<_CMap_CodeRange>	m_CodeRanges;
    CFX_ByteString	m_Registry, m_Ordering, m_Supplement;
    CFX_ByteString	m_LastWord;
};
#define CIDCODING_UNKNOWN	0
#define CIDCODING_GB		1
#define CIDCODING_BIG5		2
#define CIDCODING_JIS		3
#define CIDCODING_KOREA		4
#define CIDCODING_UCS2		5
#define CIDCODING_CID		6
#define CIDCODING_UTF16		7
class CPDF_CMap : public CFX_Object
{
public:
    CPDF_CMap();
    FX_BOOL					LoadPredefined(CPDF_CMapManager* pMgr, const FX_CHAR* name, FX_BOOL bPromptCJK);
    FX_BOOL					LoadEmbedded(FX_LPCBYTE pData, FX_DWORD dwSize);
    void					Release();
    FX_BOOL					IsLoaded() const
    {
        return m_bLoaded;
    }
    int						GetCharset()
    {
        return m_Charset;
    }
    FX_BOOL					IsVertWriting() const
    {
        return m_bVertical;
    }
    FX_WORD					CIDFromCharCode(FX_DWORD charcode) const;
    FX_DWORD				CharCodeFromCID(FX_WORD CID) const;
    int						GetCharSize(FX_DWORD charcode) const;
    FX_DWORD				GetNextChar(const FX_CHAR* pString, int& offset) const;
    int						CountChar(const FX_CHAR* pString, int size) const;
    int						AppendChar(FX_LPSTR str, FX_DWORD charcode) const;
    typedef enum {OneByte, TwoBytes, MixedTwoBytes, MixedFourBytes} CodingScheme;
protected:
    ~CPDF_CMap();
    friend class			CPDF_CMapParser;
    friend class			CPDF_CMapManager;
    friend class			CPDF_CIDFont;
protected:
    CFX_ByteString			m_PredefinedCMap;
    FX_BOOL					m_bVertical;
    int						m_Charset, m_Coding;
    CodingScheme			m_CodingScheme;
    int						m_nCodeRanges;
    FX_BYTE*				m_pLeadingBytes;
    FX_WORD*				m_pMapping;
    FX_LPBYTE				m_pAddMapping;
    FX_BOOL					m_bLoaded;
    const FXCMAP_CMap*		m_pEmbedMap;
    CPDF_CMap*				m_pUseMap;
};
class CPDF_PredefinedCMap
{
public:
    FX_LPCSTR	m_pName;
    int			m_Charset;
    int			m_Coding;
    CPDF_CMap::CodingScheme	m_CodingScheme;
    FX_DWORD	m_LeadingSegCount;
    FX_BYTE		m_LeadingSegs[4];
};
typedef struct _FileHeader {
    FX_BYTE		btTag[4];
    FX_BYTE		btVersion;
    FX_BYTE		btFormat;
    FX_BYTE		btReserved1[2];
    FX_DWORD	dwStartIndex;
    FX_DWORD	dwEndIndex;
    FX_DWORD	dwDataSize;
    FX_DWORD	dwDataOffset;
    FX_DWORD	dwRecordSize;
} FXMP_FILEHEADER;
class CPDF_FXMP : public CFX_Object
{
public:
    CPDF_FXMP()
    {
        m_pHeader = NULL;
        m_pTable = NULL;
    }
    ~CPDF_FXMP()
    {
        if (m_pHeader) {
            FX_Free(m_pHeader);
        }
    }
    FX_BOOL		IsLoaded()
    {
        return m_pTable != NULL;
    }
    FX_BOOL		LoadFile(FX_LPVOID pPackage, FX_LPCSTR fileid);
    FX_LPBYTE	GetRecord(FX_DWORD index);
private:
    FXMP_FILEHEADER*	m_pHeader;
    FX_LPBYTE	m_pTable;
};
class CPDF_CID2UnicodeMap : public CFX_Object
{
public:
    CPDF_CID2UnicodeMap();
    ~CPDF_CID2UnicodeMap();
    FX_BOOL		Initialize();
    FX_BOOL		IsLoaded();
    void		Load(CPDF_CMapManager* pMgr, int charset, FX_BOOL bPromptCJK);
    FX_WCHAR	UnicodeFromCID(FX_WORD CID);
protected:
    int			m_Charset;
    const FX_WORD*	m_pEmbeddedMap;
    FX_DWORD	m_EmbeddedCount;
#ifndef _FPDFAPI_MINI_
    CPDF_FXMP*	m_pExternalMap;
#endif
};
class CPDF_ToUnicodeMap : public CFX_Object
{
public:
    void					Load(CPDF_Stream* pStream);
    CFX_WideString			Lookup(FX_DWORD charcode);
    FX_DWORD				ReverseLookup(FX_WCHAR unicode);
protected:
    CFX_CMapDWordToDWord	m_Map;
    CPDF_CID2UnicodeMap*	m_pBaseMap;
    CFX_WideTextBuf			m_MultiCharBuf;
};
class CPDF_FontCharMap : public CFX_CharMap, public CFX_Object
{
public:
    CPDF_FontCharMap(CPDF_Font* pFont);
    CPDF_Font*		m_pFont;
};