Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fgas / src / font / fx_gefont.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 "../fgas_base.h"\r
8 #include "fx_gefont.h"\r
9 #include "fx_fontutils.h"\r
10 #ifndef _FXPLUS\r
11 IFX_Font* IFX_Font::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage, IFX_FontMgr *pFontMgr)\r
12 {\r
13 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_\r
14     if (NULL != pFontMgr) {\r
15         return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);\r
16     }\r
17     return NULL;\r
18 #else\r
19     CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);\r
20     if (!pFont->LoadFont(pszFontFamily, dwFontStyles, wCodePage)) {\r
21         pFont->Release();\r
22         return NULL;\r
23     }\r
24     return pFont;\r
25 #endif\r
26 }\r
27 IFX_Font* IFX_Font::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength, IFX_FontMgr *pFontMgr)\r
28 {\r
29 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_\r
30     if (NULL != pFontMgr) {\r
31         return pFontMgr->LoadFont(pBuffer, iLength, 0, NULL);\r
32     }\r
33     return NULL;\r
34 #else\r
35     CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);\r
36     if (!pFont->LoadFont(pBuffer, iLength)) {\r
37         pFont->Release();\r
38         return NULL;\r
39     }\r
40     return pFont;\r
41 #endif\r
42 }\r
43 IFX_Font* IFX_Font::LoadFont(FX_LPCWSTR pszFileName, IFX_FontMgr *pFontMgr)\r
44 {\r
45 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_\r
46     if (NULL != pFontMgr) {\r
47         return pFontMgr->LoadFont(pszFileName, 0, NULL);\r
48     }\r
49     return NULL;\r
50 #else\r
51     CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);\r
52     if (!pFont->LoadFont(pszFileName)) {\r
53         pFont->Release();\r
54         return NULL;\r
55     }\r
56     return pFont;\r
57 #endif\r
58 }\r
59 IFX_Font* IFX_Font::LoadFont(IFX_Stream *pFontStream, IFX_FontMgr *pFontMgr, FX_BOOL bSaveStream)\r
60 {\r
61 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_\r
62     if (NULL != pFontMgr) {\r
63         return pFontMgr->LoadFont(pFontStream, 0, NULL);\r
64     }\r
65     return NULL;\r
66 #else\r
67     CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);\r
68     if (!pFont->LoadFont(pFontStream, bSaveStream)) {\r
69         pFont->Release();\r
70         return NULL;\r
71     }\r
72     return pFont;\r
73 #endif\r
74 }\r
75 IFX_Font* IFX_Font::LoadFont(CFX_Font *pExtFont, IFX_FontMgr *pFontMgr, FX_BOOL bTakeOver)\r
76 {\r
77     CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);\r
78     if (!pFont->LoadFont(pExtFont, bTakeOver)) {\r
79         pFont->Release();\r
80         return NULL;\r
81     }\r
82     return pFont;\r
83 }\r
84 CFX_GEFont::CFX_GEFont(IFX_FontMgr *pFontMgr)\r
85     : CFX_ThreadLock()\r
86     , m_pFont(NULL)\r
87     , m_pFontMgr(pFontMgr)\r
88     , m_iRefCount(1)\r
89     , m_bExtFont(FALSE)\r
90     , m_pStream(NULL)\r
91     , m_pFileRead(NULL)\r
92     , m_pFontEncoding(NULL)\r
93     , m_pCharWidthMap(NULL)\r
94     , m_pRectArray(NULL)\r
95     , m_pBBoxMap(NULL)\r
96     , m_wCharSet(0xFFFF)\r
97     , m_pProvider(NULL)\r
98 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_\r
99     , m_bUseLogFontStyle(FALSE)\r
100     , m_dwLogFontStyle(0)\r
101 #endif\r
102     , m_SubstFonts()\r
103     , m_FontMapper(16)\r
104 {\r
105 }\r
106 CFX_GEFont::CFX_GEFont(const CFX_GEFont &src, FX_DWORD dwFontStyles)\r
107     : CFX_ThreadLock()\r
108     , m_pFont(NULL)\r
109     , m_pFontMgr(src.m_pFontMgr)\r
110     , m_iRefCount(1)\r
111     , m_bExtFont(FALSE)\r
112     , m_pStream(NULL)\r
113     , m_pFileRead(NULL)\r
114     , m_pFontEncoding(NULL)\r
115     , m_pCharWidthMap(NULL)\r
116     , m_pRectArray(NULL)\r
117     , m_pBBoxMap(NULL)\r
118     , m_wCharSet(0xFFFF)\r
119     , m_pProvider(NULL)\r
120     , m_SubstFonts()\r
121     , m_FontMapper(16)\r
122 {\r
123     m_pFont = FX_NEW CFX_Font;\r
124     FXSYS_assert(m_pFont != NULL);\r
125     FXSYS_assert(src.m_pFont != NULL);\r
126     m_pFont->LoadClone(src.m_pFont);\r
127     CFX_SubstFont *&pSubst = m_pFont->m_pSubstFont;\r
128     if (pSubst == NULL) {\r
129         pSubst = FX_NEW CFX_SubstFont;\r
130     }\r
131     if (pSubst) {\r
132         pSubst->m_Weight = (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;\r
133         if (dwFontStyles & FX_FONTSTYLE_Italic) {\r
134             pSubst->m_SubstFlags |= FXFONT_SUBST_ITALIC;\r
135         }\r
136     }\r
137     InitFont();\r
138 }\r
139 CFX_GEFont::~CFX_GEFont()\r
140 {\r
141     FX_INT32 iCount = m_SubstFonts.GetSize();\r
142     for (FX_INT32 i = 0; i < iCount; i ++) {\r
143         IFX_Font *pFont = (IFX_Font*)m_SubstFonts[i];\r
144         pFont->Release();\r
145     }\r
146     m_SubstFonts.RemoveAll();\r
147     m_FontMapper.RemoveAll();\r
148     if (m_pFileRead != NULL) {\r
149         m_pFileRead->Release();\r
150     }\r
151     if (m_pStream != NULL) {\r
152         m_pStream->Release();\r
153     }\r
154     if (m_pFontEncoding != NULL) {\r
155         delete m_pFontEncoding;\r
156     }\r
157     if (m_pCharWidthMap != NULL) {\r
158         FXTARGET_Delete m_pCharWidthMap;\r
159     }\r
160     if (m_pRectArray != NULL) {\r
161         FXTARGET_Delete m_pRectArray;\r
162     }\r
163     if (m_pBBoxMap != NULL) {\r
164         delete m_pBBoxMap;\r
165     }\r
166     if (m_pFont != NULL && !m_bExtFont) {\r
167         delete m_pFont;\r
168     }\r
169 }\r
170 void CFX_GEFont::Release()\r
171 {\r
172     if (-- m_iRefCount < 1) {\r
173         if (m_pFontMgr != NULL) {\r
174             m_pFontMgr->RemoveFont(this);\r
175         }\r
176         delete this;\r
177     }\r
178 }\r
179 IFX_Font* CFX_GEFont::Retain()\r
180 {\r
181     ++ m_iRefCount;\r
182     return this;\r
183 }\r
184 FX_BOOL CFX_GEFont::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage)\r
185 {\r
186     if (m_pFont != NULL) {\r
187         return FALSE;\r
188     }\r
189     Lock();\r
190     CFX_ByteString csFontFamily;\r
191     if (pszFontFamily != NULL) {\r
192         csFontFamily = CFX_ByteString::FromUnicode(pszFontFamily);\r
193     }\r
194     FX_DWORD dwFlags = 0;\r
195     if (dwFontStyles & FX_FONTSTYLE_FixedPitch) {\r
196         dwFlags |= FXFONT_FIXED_PITCH;\r
197     }\r
198     if (dwFontStyles & FX_FONTSTYLE_Serif) {\r
199         dwFlags |= FXFONT_SERIF;\r
200     }\r
201     if (dwFontStyles & FX_FONTSTYLE_Symbolic) {\r
202         dwFlags |= FXFONT_SYMBOLIC;\r
203     }\r
204     if (dwFontStyles & FX_FONTSTYLE_Script) {\r
205         dwFlags |= FXFONT_SCRIPT;\r
206     }\r
207     if (dwFontStyles & FX_FONTSTYLE_Italic) {\r
208         dwFlags |= FXFONT_ITALIC;\r
209     }\r
210     if (dwFontStyles & FX_FONTSTYLE_Bold) {\r
211         dwFlags |= FXFONT_BOLD;\r
212     }\r
213     if (dwFontStyles & FX_FONTSTYLE_ExactMatch) {\r
214         dwFlags |= FXFONT_EXACTMATCH;\r
215     }\r
216     FX_INT32 iWeight = (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;\r
217     FX_WORD wCharSet = FX_GetCharsetFromCodePage(wCodePage);\r
218     if (wCharSet == 0xFFFF) {\r
219         wCharSet = FXSYS_GetACP();\r
220     }\r
221     m_wCharSet = wCharSet;\r
222     m_pFont = FX_NEW CFX_Font;\r
223     if ((dwFlags & FXFONT_ITALIC) && (dwFlags & FXFONT_BOLD)) {\r
224         csFontFamily += ",BoldItalic";\r
225     } else if (dwFlags & FXFONT_BOLD) {\r
226         csFontFamily += ",Bold";\r
227     } else if (dwFlags & FXFONT_ITALIC) {\r
228         csFontFamily += ",Italic";\r
229     }\r
230     FX_BOOL bRet = m_pFont->LoadSubst(csFontFamily, TRUE, dwFlags, iWeight, 0, wCodePage);\r
231     bRet = m_pFont->m_Face != NULL;\r
232     if (bRet) {\r
233         InitFont();\r
234     }\r
235     Unlock();\r
236     return bRet;\r
237 }\r
238 FX_BOOL CFX_GEFont::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 length)\r
239 {\r
240     if (m_pFont != NULL) {\r
241         return FALSE;\r
242     }\r
243     Lock();\r
244     m_pFont = FX_NEW CFX_Font;\r
245     FX_BOOL bRet = m_pFont->LoadEmbedded(pBuffer, length);\r
246     if (bRet) {\r
247         InitFont();\r
248     }\r
249     m_wCharSet = 0xFFFF;\r
250     Unlock();\r
251     return bRet;\r
252 }\r
253 FX_BOOL CFX_GEFont::LoadFont(FX_LPCWSTR pszFileName)\r
254 {\r
255     if (m_pFont != NULL) {\r
256         return FALSE;\r
257     }\r
258     if (m_pStream != NULL) {\r
259         return FALSE;\r
260     }\r
261     if (m_pFileRead != NULL) {\r
262         return FALSE;\r
263     }\r
264     Lock();\r
265     m_pStream = IFX_Stream::CreateStream(pszFileName, FX_STREAMACCESS_Binary | FX_STREAMACCESS_Read);\r
266     m_pFileRead = FX_CreateFileRead(m_pStream);\r
267     FX_BOOL bRet = FALSE;\r
268     if (m_pStream != NULL && m_pFileRead != NULL) {\r
269         m_pFont = FX_NEW CFX_Font;\r
270         bRet = m_pFont->LoadFile(m_pFileRead);\r
271         if (!bRet) {\r
272             m_pFileRead->Release();\r
273             m_pFileRead = NULL;\r
274         } else {\r
275             InitFont();\r
276         }\r
277     }\r
278     m_wCharSet = 0xFFFF;\r
279     Unlock();\r
280     return bRet;\r
281 }\r
282 FX_BOOL CFX_GEFont::LoadFont(IFX_Stream *pFontStream, FX_BOOL bSaveStream)\r
283 {\r
284     if (m_pFont != NULL) {\r
285         return FALSE;\r
286     }\r
287     if (pFontStream == NULL || pFontStream->GetLength() < 1) {\r
288         return FALSE;\r
289     }\r
290     if (m_pFileRead != NULL) {\r
291         return FALSE;\r
292     }\r
293     Lock();\r
294     if (bSaveStream) {\r
295         m_pStream = pFontStream;\r
296     }\r
297     m_pFileRead = FX_CreateFileRead(pFontStream);\r
298     m_pFont = FX_NEW CFX_Font;\r
299     FX_BOOL bRet = m_pFont->LoadFile(m_pFileRead);\r
300     if (!bRet) {\r
301         m_pFileRead->Release();\r
302         m_pFileRead = NULL;\r
303     } else {\r
304         InitFont();\r
305     }\r
306     m_wCharSet = 0xFFFF;\r
307     Unlock();\r
308     return bRet;\r
309 }\r
310 FX_BOOL CFX_GEFont::LoadFont(CFX_Font *pExtFont, FX_BOOL bTakeOver)\r
311 {\r
312     if (m_pFont != NULL) {\r
313         return FALSE;\r
314     }\r
315     if (pExtFont == NULL) {\r
316         return FALSE;\r
317     }\r
318     Lock();\r
319     if ((m_pFont = pExtFont) != NULL) {\r
320         m_bExtFont = !bTakeOver;\r
321         InitFont();\r
322     } else {\r
323         m_bExtFont = TRUE;\r
324     }\r
325     m_wCharSet = 0xFFFF;\r
326     Unlock();\r
327     return m_pFont != NULL;\r
328 }\r
329 void CFX_GEFont::InitFont()\r
330 {\r
331     if (m_pFont == NULL) {\r
332         return;\r
333     }\r
334     if (m_pFontEncoding == NULL) {\r
335 #ifdef FXFM_ENCODING_NONE\r
336         m_pFontEncoding = FX_CreateFontEncodingEx(m_pFont);\r
337 #else\r
338         m_pFontEncoding = FXGE_CreateUnicodeEncoding(m_pFont);\r
339 #endif\r
340     }\r
341     if (m_pCharWidthMap == NULL) {\r
342         m_pCharWidthMap = FXTARGET_New CFX_WordDiscreteArray(1024);\r
343     }\r
344     if (m_pRectArray == NULL) {\r
345         m_pRectArray = FXTARGET_New CFX_RectMassArray(16);\r
346     }\r
347     if (m_pBBoxMap == NULL) {\r
348         m_pBBoxMap = FX_NEW CFX_MapPtrToPtr(16);\r
349     }\r
350 }\r
351 IFX_Font* CFX_GEFont::Derive(FX_DWORD dwFontStyles, FX_WORD wCodePage )\r
352 {\r
353     if (GetFontStyles() == dwFontStyles) {\r
354         return Retain();\r
355     }\r
356     return FX_NEW CFX_GEFont(*this, dwFontStyles);\r
357 }\r
358 FX_BYTE CFX_GEFont::GetCharSet() const\r
359 {\r
360     FXSYS_assert(m_pFont != NULL);\r
361     if (m_wCharSet != 0xFFFF) {\r
362         return (FX_BYTE)m_wCharSet;\r
363     }\r
364     if (m_pFont->m_pSubstFont == NULL) {\r
365         return FX_CHARSET_Default;\r
366     }\r
367     return m_pFont->m_pSubstFont->m_Charset;\r
368 }\r
369 void CFX_GEFont::GetFamilyName(CFX_WideString &wsFamily) const\r
370 {\r
371     FXSYS_assert(m_pFont != NULL);\r
372     if (m_pFont->m_pSubstFont == NULL || m_pFont->m_pSubstFont->m_Family.GetLength() == 0) {\r
373         wsFamily = CFX_WideString::FromLocal(m_pFont->GetFamilyName());\r
374     } else {\r
375         wsFamily = CFX_WideString::FromLocal(m_pFont->m_pSubstFont->m_Family);\r
376     }\r
377 }\r
378 void CFX_GEFont::GetPsName(CFX_WideString &wsName) const\r
379 {\r
380     wsName = m_pFont->GetPsName();\r
381 }\r
382 FX_DWORD CFX_GEFont::GetFontStyles() const\r
383 {\r
384     FXSYS_assert(m_pFont != NULL);\r
385 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_\r
386     if (m_bUseLogFontStyle) {\r
387         return m_dwLogFontStyle;\r
388     }\r
389 #endif\r
390     FX_DWORD dwStyles = 0;\r
391     if (m_pFont->m_pSubstFont == NULL) {\r
392         if (m_pFont->IsBold()) {\r
393             dwStyles |= FX_FONTSTYLE_Bold;\r
394         }\r
395         if (m_pFont->IsItalic()) {\r
396             dwStyles |= FX_FONTSTYLE_Italic;\r
397         }\r
398     } else {\r
399         if (m_pFont->m_pSubstFont->m_Weight == FXFONT_FW_BOLD) {\r
400             dwStyles |= FX_FONTSTYLE_Bold;\r
401         }\r
402         if (m_pFont->m_pSubstFont->m_SubstFlags & FXFONT_SUBST_ITALIC) {\r
403             dwStyles |= FX_FONTSTYLE_Italic;\r
404         }\r
405     }\r
406     return dwStyles;\r
407 }\r
408 FX_BOOL CFX_GEFont::GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bCharCode)\r
409 {\r
410     return GetCharWidth(wUnicode, iWidth, TRUE, bCharCode);\r
411 }\r
412 FX_BOOL CFX_GEFont::GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bRecursive, FX_BOOL bCharCode)\r
413 {\r
414     FXSYS_assert (m_pCharWidthMap != NULL);\r
415     iWidth = m_pCharWidthMap->GetAt(wUnicode, 0);\r
416     if (iWidth < 1) {\r
417         if (!m_pProvider || !m_pProvider->GetCharWidth(this, wUnicode, iWidth, bCharCode)) {\r
418             IFX_Font *pFont = NULL;\r
419             FX_INT32 iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode);\r
420             if (iGlyph != 0xFFFF && pFont != NULL) {\r
421                 if (pFont == (IFX_Font*)this) {\r
422                     iWidth = m_pFont->GetGlyphWidth(iGlyph);\r
423                     if (iWidth < 0) {\r
424                         iWidth = -1;\r
425                     }\r
426                 } else if (((CFX_GEFont*)pFont)->GetCharWidth(wUnicode, iWidth, FALSE, bCharCode)) {\r
427                     return TRUE;\r
428                 }\r
429             } else {\r
430                 iWidth = -1;\r
431             }\r
432         }\r
433         Lock();\r
434         m_pCharWidthMap->SetAtGrow(wUnicode, (FX_SHORT)iWidth);\r
435         Unlock();\r
436     } else if (iWidth == 65535) {\r
437         iWidth = -1;\r
438     }\r
439     return iWidth > 0;\r
440 }\r
441 FX_BOOL CFX_GEFont::GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bCharCode)\r
442 {\r
443     return GetCharBBox(wUnicode, bbox, TRUE, bCharCode);\r
444 }\r
445 FX_BOOL CFX_GEFont::GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bRecursive, FX_BOOL bCharCode)\r
446 {\r
447     FXSYS_assert(m_pRectArray != NULL);\r
448     FXSYS_assert(m_pBBoxMap != NULL);\r
449     FX_LPVOID pRect = NULL;\r
450     if (!m_pBBoxMap->Lookup((void*)(FX_UINTPTR)wUnicode, pRect)) {\r
451         IFX_Font *pFont = NULL;\r
452         FX_INT32 iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode);\r
453         if (iGlyph != 0xFFFF && pFont != NULL) {\r
454             if (pFont == (IFX_Font*)this) {\r
455                 FX_RECT rtBBox;\r
456                 if (m_pFont->GetGlyphBBox(iGlyph, rtBBox)) {\r
457                     Lock();\r
458                     CFX_Rect rt;\r
459                     rt.Set(rtBBox.left, rtBBox.top, rtBBox.Width(), rtBBox.Height());\r
460                     FX_INT32 index = m_pRectArray->Add(rt);\r
461                     pRect = m_pRectArray->GetPtrAt(index);\r
462                     m_pBBoxMap->SetAt((void*)(FX_UINTPTR)wUnicode, pRect);\r
463                     Unlock();\r
464                 }\r
465             } else if (((CFX_GEFont*)pFont)->GetCharBBox(wUnicode, bbox, FALSE, bCharCode)) {\r
466                 return TRUE;\r
467             }\r
468         }\r
469     }\r
470     if (pRect == NULL) {\r
471         return FALSE;\r
472     }\r
473     bbox = *(FX_LPCRECT)pRect;\r
474     return TRUE;\r
475 }\r
476 FX_BOOL CFX_GEFont::GetBBox(CFX_Rect &bbox)\r
477 {\r
478     FX_RECT rt(0, 0, 0, 0);\r
479     FX_BOOL bRet = m_pFont->GetBBox(rt);\r
480     if (bRet) {\r
481         bbox.left = rt.left;\r
482         bbox.width = rt.Width();\r
483         bbox.top = rt.bottom;\r
484         bbox.height = -rt.Height();\r
485     }\r
486     return bRet;\r
487 }\r
488 FX_INT32 CFX_GEFont::GetItalicAngle() const\r
489 {\r
490     if (m_pFont->m_pSubstFont == NULL) {\r
491         return 0;\r
492     }\r
493     return m_pFont->m_pSubstFont->m_ItalicAngle;\r
494 }\r
495 FX_INT32 CFX_GEFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode)\r
496 {\r
497     return GetGlyphIndex(wUnicode, TRUE, NULL, bCharCode);\r
498 }\r
499 FX_INT32 CFX_GEFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bRecursive, IFX_Font **ppFont, FX_BOOL bCharCode)\r
500 {\r
501     FXSYS_assert (m_pFontEncoding != NULL);\r
502     FX_INT32 iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode);\r
503     if (iGlyphIndex > 0) {\r
504         if (ppFont != NULL) {\r
505             *ppFont = (IFX_Font*)this;\r
506         }\r
507         return iGlyphIndex;\r
508     }\r
509     FGAS_LPCFONTUSB pFontUSB = FGAS_GetUnicodeBitField(wUnicode);\r
510     if (pFontUSB == NULL) {\r
511         return 0xFFFF;\r
512     }\r
513     FX_WORD wBitField = pFontUSB->wBitField;\r
514     if (wBitField >= 128) {\r
515         return 0xFFFF;\r
516     }\r
517     IFX_Font *pFont = NULL;\r
518     m_FontMapper.Lookup((void*)(FX_UINTPTR)wUnicode, (void*&)pFont);\r
519     if (pFont != NULL && pFont != (IFX_Font*)this) {\r
520         iGlyphIndex = ((CFX_GEFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);\r
521         if (iGlyphIndex != 0xFFFF) {\r
522             FX_INT32 i = m_SubstFonts.Find(pFont);\r
523             if (i > -1) {\r
524                 iGlyphIndex |= ((i + 1) << 24);\r
525                 if (ppFont != NULL) {\r
526                     *ppFont = pFont;\r
527                 }\r
528                 return iGlyphIndex;\r
529             }\r
530         }\r
531     }\r
532     if (m_pFontMgr != NULL && bRecursive) {\r
533         CFX_WideString wsFamily;\r
534         GetFamilyName(wsFamily);\r
535 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
536         IFX_Font *pFont = m_pFontMgr->GetDefFontByUnicode(wUnicode, GetFontStyles(), (FX_LPCWSTR)wsFamily);\r
537 #else\r
538         IFX_Font *pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), (FX_LPCWSTR)wsFamily);\r
539         if (NULL == pFont) {\r
540             pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), NULL);\r
541         }\r
542 #endif\r
543         if (pFont != NULL) {\r
544             if (pFont == (IFX_Font*)this) {\r
545                 pFont->Release();\r
546                 return 0xFFFF;\r
547             }\r
548             m_FontMapper.SetAt((void*)(FX_UINTPTR)wUnicode, (void*)pFont);\r
549             FX_INT32 i = m_SubstFonts.GetSize();\r
550             m_SubstFonts.Add(pFont);\r
551             iGlyphIndex = ((CFX_GEFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);\r
552             if (iGlyphIndex != 0xFFFF) {\r
553                 iGlyphIndex |= ((i + 1) << 24);\r
554                 if (ppFont != NULL) {\r
555                     *ppFont = pFont;\r
556                 }\r
557                 return iGlyphIndex;\r
558             }\r
559         }\r
560     }\r
561     return 0xFFFF;\r
562 }\r
563 FX_INT32 CFX_GEFont::GetAscent() const\r
564 {\r
565     return m_pFont->GetAscent();\r
566 }\r
567 FX_INT32 CFX_GEFont::GetDescent() const\r
568 {\r
569     return m_pFont->GetDescent();\r
570 }\r
571 void CFX_GEFont::Reset()\r
572 {\r
573     Lock();\r
574     FX_INT32 iCount = m_SubstFonts.GetSize();\r
575     for (FX_INT32 i = 0; i < iCount; i ++) {\r
576         IFX_Font *pFont = (IFX_Font*)m_SubstFonts[i];\r
577         ((CFX_GEFont*)pFont)->Reset();\r
578     }\r
579     if (m_pCharWidthMap != NULL) {\r
580         m_pCharWidthMap->RemoveAll();\r
581     }\r
582     if (m_pBBoxMap != NULL) {\r
583         m_pBBoxMap->RemoveAll();\r
584     }\r
585     if (m_pRectArray != NULL) {\r
586         m_pRectArray->RemoveAll();\r
587     }\r
588     Unlock();\r
589 }\r
590 IFX_Font* CFX_GEFont::GetSubstFont(FX_INT32 iGlyphIndex) const\r
591 {\r
592     iGlyphIndex = ((FX_DWORD)iGlyphIndex) >> 24;\r
593     return iGlyphIndex == 0 ? (IFX_Font*)this : (IFX_Font*)m_SubstFonts[iGlyphIndex - 1];\r
594 }\r
595 #endif\r