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/fxge/fx_ge.h"
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../../include/fxge/fx_freetype.h"
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "text_int.h"
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define EM_ADJUST(em, a) (em == 0?(a): (a)*1000/em)
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovextern void _FPDFAPI_GetInternalFontData(int id1, FX_LPCBYTE& data, FX_DWORD& size);
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_Font::CFX_Font()
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pSubstFont = NULL;
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Face = NULL;
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bEmbedded = FALSE;
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bVertical = FALSE;
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pFontData = NULL;
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pFontDataAllocation = NULL;
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_dwSize = 0;
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pOwnedStream = NULL;
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pGsubData = NULL;
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pPlatformFont = NULL;
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pPlatformFontCollection = NULL;
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pDwFont = NULL;
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_hHandle = NULL;
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bDwLoaded = FALSE;
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_Font::~CFX_Font()
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pSubstFont) {
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        delete m_pSubstFont;
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pSubstFont = NULL;
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FOXIT_CHROME_BUILD
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pFontDataAllocation) {
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_Free(m_pFontDataAllocation);
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pFontDataAllocation = NULL;
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face) {
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FOXIT_CHROME_BUILD
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXFT_Library library = FXFT_Get_Face_FreeType(m_Face);
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (FXFT_Get_Face_External_Stream(m_Face)) {
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FXFT_Clear_Face_External_Stream(m_Face);
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if(m_bEmbedded) {
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            DeleteFace();
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face);
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pOwnedStream) {
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_Free(m_pOwnedStream);
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pOwnedStream = NULL;
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pGsubData) {
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_Free(m_pGsubData);
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pGsubData = NULL;
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if (_FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_ && (!defined(_FPDFAPI_MINI_)))
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ReleasePlatformResource();
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFX_Font::DeleteFace()
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Done_Face(m_Face);
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Face = NULL;
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::LoadSubst(const CFX_ByteString& face_name, FX_BOOL bTrueType, FX_DWORD flags,
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            int weight, int italic_angle, int CharsetCP, FX_BOOL bVertical)
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bEmbedded = FALSE;
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bVertical = bVertical;
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pSubstFont = FX_NEW CFX_SubstFont;
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pSubstFont) {
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle,
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             CharsetCP, m_pSubstFont);
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if(m_pSubstFont->m_ExtHandle) {
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pPlatformFont = m_pSubstFont->m_ExtHandle;
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pSubstFont->m_ExtHandle = NULL;
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face) {
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pFontData = FXFT_Get_Face_Stream_Base(m_Face);
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_dwSize = FXFT_Get_Face_Stream_Size(m_Face);
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovextern "C" {
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset,
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                unsigned char* buffer, unsigned long count)
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (count == 0) {
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return 0;
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        IFX_FileRead* pFile = (IFX_FileRead*)stream->descriptor.pointer;
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int res = pFile->ReadBlock(buffer, offset, count);
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (res) {
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return count;
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void _FTStreamClose(FXFT_Stream stream)
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream)
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Stream stream1 = (FXFT_Stream)FX_Alloc(FX_BYTE, sizeof (FXFT_StreamRec));
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!stream1) {
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    stream1->base = NULL;
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    stream1->size = (unsigned long)pFile->GetSize();
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    stream1->pos = 0;
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    stream1->descriptor.pointer = pFile;
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    stream1->close = _FTStreamClose;
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    stream1->read = _FTStreamRead;
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Open_Args args;
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    args.flags = FT_OPEN_STREAM;
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    args.stream = stream1;
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (FXFT_Open_Face(library, &args, 0, Face)) {
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_Free(stream1);
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (stream) {
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *stream = stream1;
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::LoadFile(IFX_FileRead* pFile)
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bEmbedded = FALSE;
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Library library;
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) {
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary);
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary;
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Stream stream = NULL;
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_LoadFile(library, &m_Face, pFile, &stream)) {
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pOwnedStream = stream;
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Set_Pixel_Sizes(m_Face, 0, 64);
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CFX_Font::GetGlyphWidth(FX_DWORD glyph_index)
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_Face) {
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pSubstFont && (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM)) {
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        AdjustMMParams(glyph_index, 0, 0);
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int err = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (err) {
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Glyph_HoriAdvance(m_Face));
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return width;
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic FXFT_Face FT_LoadFont(FX_LPBYTE pData, int size)
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Library library;
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) {
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary);
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary;
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Face face;
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int error = FXFT_New_Memory_Face(library, pData, size, 0, &face);
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (error) {
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FXFT_Set_Pixel_Sizes(face, 64, 64);
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (error) {
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return face;
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::LoadEmbedded(FX_LPCBYTE data, FX_DWORD size)
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FOXIT_CHROME_BUILD
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pFontDataAllocation = FX_Alloc(FX_BYTE, size);
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pFontDataAllocation) {
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(m_pFontDataAllocation, data, size);
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Face = FT_LoadFont((FX_LPBYTE)m_pFontDataAllocation, size);
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pFontData = (FX_LPBYTE)m_pFontDataAllocation;
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Face = FT_LoadFont((FX_LPBYTE)data, size);
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pFontData = (FX_LPBYTE)data;
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bEmbedded = TRUE;
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_dwSize = size;
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return m_Face != NULL;
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::IsTTFont()
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT;
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CFX_Font::GetAscent() const
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int ascent = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Ascender(m_Face));
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ascent;
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CFX_Font::GetDescent() const
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int descent = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Descender(m_Face));
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return descent;
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::GetGlyphBBox(FX_DWORD glyph_index, FX_RECT &bbox)
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (FXFT_Is_Face_Tricky(m_Face)) {
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72);
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (error) {
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (error) {
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXFT_BBox cbox;
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Glyph glyph;
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FXFT_Get_Glyph(((FXFT_Face)m_Face)->glyph, &glyph);
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (error) {
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox);
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int pixel_size_x = ((FXFT_Face)m_Face)->size->metrics.x_ppem,
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pixel_size_y = ((FXFT_Face)m_Face)->size->metrics.y_ppem;
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pixel_size_x == 0 || pixel_size_y == 0) {
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.left = cbox.xMin;
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.right = cbox.xMax;
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.top = cbox.yMax;
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.bottom = cbox.yMin;
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.left = cbox.xMin * 1000 / pixel_size_x;
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.right = cbox.xMax * 1000 / pixel_size_x;
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.top = cbox.yMax * 1000 / pixel_size_y;
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.bottom = cbox.yMin * 1000 / pixel_size_y;
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bbox.top > FXFT_Get_Face_Ascender(m_Face)) {
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.top = FXFT_Get_Face_Ascender(m_Face);
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bbox.bottom < FXFT_Get_Face_Descender(m_Face)) {
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bbox.bottom = FXFT_Get_Face_Descender(m_Face);
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Done_Glyph(glyph);
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0;
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int em = FXFT_Get_Face_UnitsPerEM(m_Face);
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (em == 0) {
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face);
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face);
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face);
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face);
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em;
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.top = (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) * 1000 / em;
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.right = (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) * 1000 / em;
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em;
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::IsItalic()
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL ret = FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC;
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ret) {
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_ByteString str(FXFT_Get_Face_Style_Name(m_Face));
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        str.MakeLower();
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (str.Find("italic") != -1) {
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ret = TRUE;
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ret;
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::IsBold()
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD;
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::IsFixedWidth()
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FXFT_Is_Face_fixedwidth(m_Face);
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_WideString CFX_Font::GetPsName() const
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return CFX_WideString();
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_WideString psName = CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(m_Face));
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (psName.IsEmpty()) {
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        psName =  CFX_WideString::FromLocal("Untitled");
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return psName;
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_ByteString CFX_Font::GetFamilyName() const
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL && m_pSubstFont == NULL) {
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return CFX_ByteString();
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face) {
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face));
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return m_pSubstFont->m_Family;
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_ByteString CFX_Font::GetFaceName() const
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL && m_pSubstFont == NULL) {
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return CFX_ByteString();
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face) {
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_ByteString facename;
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_ByteString style = CFX_ByteString(FXFT_Get_Face_Style_Name(m_Face));
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        facename = GetFamilyName();
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (facename.IsEmpty()) {
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            facename = "Untitled";
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!style.IsEmpty() && style != "Regular") {
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            facename += " " + style;
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return facename;
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return m_pSubstFont->m_Family;
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_Font::GetBBox(FX_RECT &bbox)
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int em = FXFT_Get_Face_UnitsPerEM(m_Face);
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (em == 0) {
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.left = FXFT_Get_Face_xMin(m_Face);
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.bottom = FXFT_Get_Face_yMax(m_Face);
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.top = FXFT_Get_Face_yMin(m_Face);
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.right = FXFT_Get_Face_xMax(m_Face);
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em;
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em;
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em;
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em;
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CFX_Font::GetHeight()
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int height = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Height(m_Face));
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return height;
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CFX_Font::GetMaxAdvanceWidth()
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_MaxAdvanceWidth(m_Face));
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return width;
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CFX_Font::GetULPos()
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int pos = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_UnderLinePosition(m_Face));
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return pos;
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CFX_Font::GetULthickness()
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Face == NULL) {
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int thickness = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_UnderLineThickness(m_Face));
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return thickness;
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_UnicodeEncoding::CFX_UnicodeEncoding(CFX_Font* pFont)
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pFont = pFont;
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_DWORD CFX_UnicodeEncoding::GlyphFromCharCode(FX_DWORD charcode)
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Face face =  m_pFont->GetFace();
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!face) {
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return charcode;
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE) == 0) {
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FXFT_Get_Char_Index(face, charcode);
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pFont->m_pSubstFont && m_pFont->m_pSubstFont->m_Charset == 2) {
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_DWORD index = 0;
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (FXFT_Select_Charmap(face, FXFT_ENCODING_MS_SYMBOL) == 0) {
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            index = FXFT_Get_Char_Index(face, charcode);
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!index && !FXFT_Select_Charmap(face, FXFT_ENCODING_APPLE_ROMAN)) {
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FXFT_Get_Char_Index(face, charcode);
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return charcode;
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_DWORD CFX_UnicodeEncoding::GlyphFromCharCodeEx(FX_DWORD charcode, int encoding)
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXFT_Face face =  m_pFont->GetFace();
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!face) {
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return charcode;
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (encoding == ENCODING_UNICODE) {
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return	GlyphFromCharCode(charcode);
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int nmaps = FXFT_Get_Face_CharmapCount(m_pFont->m_Face);
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int i = 0;
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        while (i < nmaps) {
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int encoding = FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i++]);
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (encoding != FXFT_ENCODING_UNICODE) {
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FXFT_Select_Charmap(face, encoding);
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FXFT_Get_Char_Index(face, charcode);
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_FontEncoding* FXGE_CreateUnicodeEncoding(CFX_Font* pFont)
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_UnicodeEncoding* pEncoding = NULL;
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pEncoding = FX_NEW CFX_UnicodeEncoding(pFont);
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return pEncoding;
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
459