• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "xfa/src/fgas/src/fgas_base.h"
8 #include "fx_gdifont.h"
9 #include "fx_stdfontmgr.h"
10 #ifdef _FXPLUS
11 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
12     _FX_OS_ == _FX_WIN64_
CFX_GdiFontCache()13 CFX_GdiFontCache::CFX_GdiFontCache() : m_GlyphMap(128) {}
~CFX_GdiFontCache()14 CFX_GdiFontCache::~CFX_GdiFontCache() {
15   FX_POSITION pos = m_GlyphMap.GetStartPosition();
16   int32_t iGlyph;
17   FX_LPGDIGOCACHE pGlyph;
18   while (pos != NULL) {
19     pGlyph = NULL;
20     m_GlyphMap.GetNextAssoc(pos, (void*&)iGlyph, (void*&)pGlyph);
21     if (pGlyph != NULL) {
22       FX_Free(pGlyph->pOutline);
23       FX_Free(pGlyph);
24     }
25   }
26   m_GlyphMap.RemoveAll();
27 }
SetCachedGlyphOutline(FX_DWORD dwGlyph,const GLYPHMETRICS & gm,uint8_t * pOutline)28 void CFX_GdiFontCache::SetCachedGlyphOutline(FX_DWORD dwGlyph,
29                                              const GLYPHMETRICS& gm,
30                                              uint8_t* pOutline) {
31   FXSYS_assert(pOutline != NULL);
32   FX_LPGDIGOCACHE pGlyph = FX_Alloc(FX_GDIGOCACHE, 1);
33   pGlyph->gm = gm;
34   pGlyph->pOutline = pOutline;
35   m_GlyphMap.SetAt((void*)dwGlyph, (void*)pGlyph);
36 }
GetCachedGlyphOutline(FX_DWORD dwGlyph) const37 FX_LPCGDIGOCACHE CFX_GdiFontCache::GetCachedGlyphOutline(
38     FX_DWORD dwGlyph) const {
39   FX_LPCGDIGOCACHE pGlyph = NULL;
40   if (!m_GlyphMap.Lookup((void*)dwGlyph, (void*&)pGlyph)) {
41     return FALSE;
42   }
43   return pGlyph;
44 }
LoadFont(const FX_WCHAR * pszFontFamily,FX_DWORD dwFontStyles,FX_WORD wCodePage,IFX_FontMgr * pFontMgr)45 IFX_Font* IFX_Font::LoadFont(const FX_WCHAR* pszFontFamily,
46                              FX_DWORD dwFontStyles,
47                              FX_WORD wCodePage,
48                              IFX_FontMgr* pFontMgr) {
49   CFX_GdiFont* pFont = new CFX_GdiFont(pFontMgr);
50   if (!pFont->LoadFont(pszFontFamily, dwFontStyles, wCodePage)) {
51     pFont->Release();
52     return NULL;
53   }
54   return pFont;
55 }
LoadFont(const uint8_t * pBuffer,int32_t iLength,IFX_FontMgr * pFontMgr)56 IFX_Font* IFX_Font::LoadFont(const uint8_t* pBuffer,
57                              int32_t iLength,
58                              IFX_FontMgr* pFontMgr) {
59   CFX_GdiFont* pFont = new CFX_GdiFont(pFontMgr);
60   if (!pFont->LoadFont(pBuffer, iLength)) {
61     pFont->Release();
62     return NULL;
63   }
64   return pFont;
65 }
LoadFont(const FX_WCHAR * pszFileName,IFX_FontMgr * pFontMgr)66 IFX_Font* IFX_Font::LoadFont(const FX_WCHAR* pszFileName,
67                              IFX_FontMgr* pFontMgr) {
68   CFX_GdiFont* pFont = new CFX_GdiFont(pFontMgr);
69   if (!pFont->LoadFont(pszFileName)) {
70     pFont->Release();
71     return NULL;
72   }
73   return pFont;
74 }
LoadFont(IFX_Stream * pFontStream,IFX_FontMgr * pFontMgr,FX_BOOL bSaveStream)75 IFX_Font* IFX_Font::LoadFont(IFX_Stream* pFontStream,
76                              IFX_FontMgr* pFontMgr,
77                              FX_BOOL bSaveStream) {
78   CFX_GdiFont* pFont = new CFX_GdiFont(pFontMgr);
79   if (!pFont->LoadFont(pFontStream)) {
80     pFont->Release();
81     return NULL;
82   }
83   return pFont;
84 }
LoadFont(CFX_Font * pExtFont,IFX_FontMgr * pFontMgr)85 IFX_Font* IFX_Font::LoadFont(CFX_Font* pExtFont, IFX_FontMgr* pFontMgr) {
86   FXSYS_assert(FALSE);
87   return NULL;
88 }
89 #define FX_GDIFONT_FONTCACHESIZE 8
CFX_GdiFont(IFX_FontMgr * pFontMgr)90 CFX_GdiFont::CFX_GdiFont(IFX_FontMgr* pFontMgr)
91     : m_pFontMgr(pFontMgr),
92       m_iRefCount(1),
93       m_WidthCache(1024),
94       m_hOldFont(NULL),
95       m_hFont(NULL),
96       m_hDC(NULL),
97       m_wsFontFileName(),
98       m_FontFamilies(),
99       m_hRes(NULL),
100       m_dwStyles(0),
101       m_SubstFonts(),
102       m_FontMapper(16),
103       m_FontCache(FX_GDIFONT_FONTCACHESIZE) {
104   m_hDC = ::CreateCompatibleDC(NULL);
105   FX_memset(&m_LogFont, 0, sizeof(m_LogFont));
106   FXSYS_assert(m_hDC != NULL);
107 }
~CFX_GdiFont()108 CFX_GdiFont::~CFX_GdiFont() {
109   int32_t iCount = m_SubstFonts.GetSize();
110   for (int32_t i = 0; i < iCount; i++) {
111     IFX_Font* pFont = (IFX_Font*)m_SubstFonts[i];
112     pFont->Release();
113   }
114   m_SubstFonts.RemoveAll();
115   m_FontMapper.RemoveAll();
116   if (m_hFont != NULL) {
117     ::SelectObject(m_hDC, m_hOldFont);
118     ::DeleteObject(m_hFont);
119   }
120   ::DeleteDC(m_hDC);
121   if (m_hRes != NULL) {
122     if (m_wsFontFileName.GetLength() > 0) {
123       ::RemoveFontResourceW((const FX_WCHAR*)m_wsFontFileName);
124     } else {
125       ::RemoveFontMemResourceEx(m_hRes);
126     }
127   }
128   m_WidthCache.RemoveAll();
129   ClearCache();
130 }
ClearCache()131 void CFX_GdiFont::ClearCache() {
132   int32_t iCount = m_SubstFonts.GetSize();
133   for (int32_t i = 0; i < iCount; i++) {
134     IFX_Font* pFont = (IFX_Font*)m_SubstFonts[i];
135     ((CFX_GdiFont*)pFont)->ClearCache();
136   }
137   FX_POSITION pos = m_FontCache.GetStartPosition();
138   FX_DWORD dwMAT2;
139   CFX_GdiFontCache* pCache;
140   while (pos != NULL) {
141     pCache = NULL;
142     m_FontCache.GetNextAssoc(pos, (void*&)dwMAT2, (void*&)pCache);
143     if (pCache != NULL) {
144       delete pCache;
145     }
146   }
147   m_FontCache.RemoveAll();
148 }
Release()149 void CFX_GdiFont::Release() {
150   if (--m_iRefCount < 1) {
151     if (m_pFontMgr != NULL) {
152       m_pFontMgr->RemoveFont(this);
153     }
154     delete this;
155   }
156 }
Retain()157 IFX_Font* CFX_GdiFont::Retain() {
158   ++m_iRefCount;
159   return this;
160 }
LoadFont(const FX_WCHAR * pszFontFamily,FX_DWORD dwFontStyles,FX_WORD wCodePage)161 FX_BOOL CFX_GdiFont::LoadFont(const FX_WCHAR* pszFontFamily,
162                               FX_DWORD dwFontStyles,
163                               FX_WORD wCodePage) {
164   FXSYS_assert(m_hFont == NULL);
165   LOGFONTW lf;
166   FX_memset(&lf, 0, sizeof(lf));
167   lf.lfHeight = -1000;
168   lf.lfWeight = (dwFontStyles & FX_FONTSTYLE_Bold) ? FW_BOLD : FW_NORMAL;
169   lf.lfItalic = (dwFontStyles & FX_FONTSTYLE_Italic) != 0;
170   lf.lfPitchAndFamily =
171       (dwFontStyles & FX_FONTSTYLE_FixedPitch) ? FIXED_PITCH : VARIABLE_PITCH;
172   if (dwFontStyles & FX_FONTSTYLE_Serif) {
173     lf.lfPitchAndFamily |= FF_ROMAN;
174   }
175   if (dwFontStyles & FX_FONTSTYLE_Script) {
176     lf.lfPitchAndFamily |= FF_SCRIPT;
177   }
178   if (dwFontStyles & FX_FONTSTYLE_Symbolic) {
179     lf.lfCharSet = SYMBOL_CHARSET;
180   } else {
181     FX_WORD wCharSet = FX_GetCharsetFromCodePage(wCodePage);
182     lf.lfCharSet = wCharSet != 0xFFFF ? (uint8_t)wCharSet : DEFAULT_CHARSET;
183   }
184   if (pszFontFamily == NULL) {
185     lf.lfFaceName[0] = L'\0';
186   } else {
187     FXSYS_wcsncpy(lf.lfFaceName, pszFontFamily, 31);
188   }
189   return LoadFont(lf);
190 }
LoadFont(const uint8_t * pBuffer,int32_t iLength)191 FX_BOOL CFX_GdiFont::LoadFont(const uint8_t* pBuffer, int32_t iLength) {
192   FXSYS_assert(m_hFont == NULL && pBuffer != NULL && iLength > 0);
193   Gdiplus::PrivateFontCollection pfc;
194   if (pfc.AddMemoryFont(pBuffer, iLength) != Gdiplus::Ok) {
195     return FALSE;
196   }
197   if (GetFontFamilies(pfc) < 1) {
198     return FALSE;
199   }
200   FX_DWORD dwCount = 0;
201   m_hRes = ::AddFontMemResourceEx((void*)pBuffer, iLength, 0, &dwCount);
202   if (m_hRes == NULL) {
203     return FALSE;
204   }
205   CFX_WideString wsFamily = m_FontFamilies[0];
206   m_hFont =
207       ::CreateFontW(-1000, 0, 0, 0, FW_NORMAL, FALSE, 0, 0, DEFAULT_CHARSET, 0,
208                     0, 0, 0, (const FX_WCHAR*)wsFamily);
209   if (m_hFont == NULL) {
210     ::RemoveFontMemResourceEx(m_hRes);
211     m_hRes = NULL;
212     return FALSE;
213   }
214   RetrieveFontStyles();
215   m_hOldFont = ::SelectObject(m_hDC, m_hFont);
216   ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
217   return TRUE;
218 }
LoadFont(const FX_WCHAR * pszFileName)219 FX_BOOL CFX_GdiFont::LoadFont(const FX_WCHAR* pszFileName) {
220   FXSYS_assert(m_hFont == NULL && pszFileName != NULL);
221   Gdiplus::PrivateFontCollection pfc;
222   if (pfc.AddFontFile(pszFileName) != Gdiplus::Ok) {
223     return FALSE;
224   }
225   if (GetFontFamilies(pfc) < 1) {
226     return FALSE;
227   }
228   m_wsFontFileName = pszFileName;
229   m_hRes = (HANDLE)::AddFontResourceW(pszFileName);
230   if (m_hRes == NULL) {
231     return FALSE;
232   }
233   CFX_WideString wsFamily = m_FontFamilies[0];
234   m_hFont =
235       ::CreateFontW(-1000, 0, 0, 0, FW_NORMAL, FALSE, 0, 0, DEFAULT_CHARSET, 0,
236                     0, 0, 0, (const FX_WCHAR*)wsFamily);
237   if (m_hFont == NULL) {
238     ::RemoveFontResourceW(pszFileName);
239     m_hRes = NULL;
240     return FALSE;
241   }
242   RetrieveFontStyles();
243   ::SelectObject(m_hDC, m_hFont);
244   ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
245   return TRUE;
246 }
LoadFont(IFX_Stream * pFontStream)247 FX_BOOL CFX_GdiFont::LoadFont(IFX_Stream* pFontStream) {
248   FXSYS_assert(m_hFont == NULL && pFontStream != NULL);
249   int32_t iLength = pFontStream->GetLength();
250   if (iLength < 1) {
251     return FALSE;
252   }
253   uint8_t* pBuf = FX_Alloc(uint8_t, iLength);
254   iLength = pFontStream->ReadData(pBuf, iLength);
255   FX_BOOL bRet = LoadFont(pBuf, iLength);
256   FX_Free(pBuf);
257   return bRet;
258 }
LoadFont(const LOGFONTW & lf)259 FX_BOOL CFX_GdiFont::LoadFont(const LOGFONTW& lf) {
260   FXSYS_assert(m_hFont == NULL);
261   m_hFont = ::CreateFontIndirectW((LPLOGFONTW)&lf);
262   if (m_hFont == NULL) {
263     return FALSE;
264   }
265   RetrieveFontStyles();
266   ::SelectObject(m_hDC, m_hFont);
267   ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
268   return TRUE;
269 }
GetFontFamilies(Gdiplus::FontCollection & fc)270 int32_t CFX_GdiFont::GetFontFamilies(Gdiplus::FontCollection& fc) {
271   int32_t iCount = fc.GetFamilyCount();
272   if (iCount < 1) {
273     return iCount;
274   }
275   Gdiplus::FontFamily* pFontFamilies = FX_Alloc(Gdiplus::FontFamily, iCount);
276   int32_t iFind = 0;
277   fc.GetFamilies(iCount, pFontFamilies, &iFind);
278   for (int32_t i = 0; i < iCount; i++) {
279     CFX_WideString wsFamilyName;
280     FX_WCHAR* pName = wsFamilyName.GetBuffer(LF_FACESIZE);
281     pFontFamilies[i].GetFamilyName(pName);
282     wsFamilyName.ReleaseBuffer();
283     m_FontFamilies.Add(wsFamilyName);
284   }
285   FX_Free(pFontFamilies);
286   return iCount;
287 }
RetrieveFontStyles()288 void CFX_GdiFont::RetrieveFontStyles() {
289   FXSYS_assert(m_hFont != NULL);
290   FX_memset(&m_LogFont, 0, sizeof(m_LogFont));
291   ::GetObjectW(m_hFont, sizeof(m_LogFont), &m_LogFont);
292   m_dwStyles = FX_GetGdiFontStyles(m_LogFont);
293 }
GetFamilyName(CFX_WideString & wsFamily) const294 void CFX_GdiFont::GetFamilyName(CFX_WideString& wsFamily) const {
295   FXSYS_assert(m_hFont != NULL);
296   wsFamily = m_LogFont.lfFaceName;
297 }
GetCharWidth(FX_WCHAR wUnicode,int32_t & iWidth,FX_BOOL bRecursive,FX_BOOL bCharCode)298 FX_BOOL CFX_GdiFont::GetCharWidth(FX_WCHAR wUnicode,
299                                   int32_t& iWidth,
300                                   FX_BOOL bRecursive,
301                                   FX_BOOL bCharCode) {
302   iWidth = (int32_t)(int16_t)m_WidthCache.GetAt(wUnicode, 0);
303   if (iWidth == 0 || iWidth == -1) {
304     IFX_Font* pFont = NULL;
305     int32_t iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode);
306     if (iGlyph != 0xFFFF && pFont != NULL) {
307       if (pFont == (IFX_Font*)this) {
308         if (!::GetCharWidthI(m_hDC, iGlyph, 1, NULL, &iWidth)) {
309           iWidth = -1;
310         }
311       } else if (((CFX_GdiFont*)pFont)
312                      ->GetCharWidth(wUnicode, iWidth, FALSE, bCharCode)) {
313         return TRUE;
314       }
315     } else {
316       iWidth = -1;
317     }
318     Lock();
319     m_WidthCache.SetAtGrow(wUnicode, (int16_t)iWidth);
320     Unlock();
321   }
322   return iWidth > 0;
323 }
GetCharWidth(FX_WCHAR wUnicode,int32_t & iWidth,FX_BOOL bCharCode)324 FX_BOOL CFX_GdiFont::GetCharWidth(FX_WCHAR wUnicode,
325                                   int32_t& iWidth,
326                                   FX_BOOL bCharCode) {
327   return GetCharWidth(wUnicode, iWidth, TRUE, bCharCode);
328 }
GetGlyphIndex(FX_WCHAR wUnicode,FX_BOOL bRecursive,IFX_Font ** ppFont,FX_BOOL bCharCode)329 int32_t CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode,
330                                    FX_BOOL bRecursive,
331                                    IFX_Font** ppFont,
332                                    FX_BOOL bCharCode) {
333   int32_t iGlyph = 0XFFFF;
334   if (::GetGlyphIndicesW(m_hDC, &wUnicode, 1, (LPWORD)&iGlyph,
335                          GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR &&
336       iGlyph != 0xFFFF) {
337     if (ppFont != NULL) {
338       *ppFont = (IFX_Font*)this;
339     }
340     return iGlyph;
341   }
342   FX_LPCFONTUSB pFontUSB = FX_GetUnicodeBitField(wUnicode);
343   if (pFontUSB == NULL) {
344     return 0xFFFF;
345   }
346   FX_WORD wBitField = pFontUSB->wBitField;
347   if (wBitField >= 128) {
348     return 0xFFFF;
349   }
350   IFX_Font* pFont = NULL;
351   m_FontMapper.Lookup((void*)wBitField, (void*&)pFont);
352   if (pFont != NULL && pFont != (IFX_Font*)this) {
353     iGlyph =
354         ((CFX_GdiFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);
355     if (iGlyph != 0xFFFF) {
356       int32_t i = m_SubstFonts.Find(pFont);
357       if (i > -1) {
358         iGlyph |= ((i + 1) << 24);
359         if (ppFont != NULL) {
360           *ppFont = pFont;
361         }
362         return iGlyph;
363       }
364     }
365   }
366   if (m_pFontMgr != NULL && bRecursive) {
367     IFX_Font* pFont = m_pFontMgr->GetDefFontByUnicode(wUnicode, m_dwStyles,
368                                                       m_LogFont.lfFaceName);
369     if (pFont != NULL) {
370       if (pFont == (IFX_Font*)this) {
371         pFont->Release();
372         return 0xFFFF;
373       }
374       m_FontMapper.SetAt((void*)wBitField, (void*)pFont);
375       int32_t i = m_SubstFonts.GetSize();
376       m_SubstFonts.Add(pFont);
377       iGlyph = ((CFX_GdiFont*)pFont)
378                    ->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);
379       if (iGlyph != 0xFFFF) {
380         iGlyph |= ((i + 1) << 24);
381         if (ppFont != NULL) {
382           *ppFont = pFont;
383         }
384         return iGlyph;
385       }
386     }
387   }
388   return 0xFFFF;
389 }
GetGlyphIndex(FX_WCHAR wUnicode,FX_BOOL bCharCode)390 int32_t CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode) {
391   return GetGlyphIndex(wUnicode, TRUE, NULL, bCharCode);
392 }
GetAscent() const393 int32_t CFX_GdiFont::GetAscent() const {
394   return m_OutlineTM.otmAscent;
395 }
GetDescent() const396 int32_t CFX_GdiFont::GetDescent() const {
397   return m_OutlineTM.otmDescent;
398 }
GetCharBBox(FX_WCHAR wUnicode,CFX_Rect & bbox,FX_BOOL bCharCode)399 FX_BOOL CFX_GdiFont::GetCharBBox(FX_WCHAR wUnicode,
400                                  CFX_Rect& bbox,
401                                  FX_BOOL bCharCode) {
402   int32_t iGlyphIndex = GetGlyphIndex(wUnicode, bCharCode);
403   if (iGlyphIndex == 0xFFFF) {
404     return FALSE;
405   }
406   IFX_Font* pFont = GetSubstFont(iGlyphIndex);
407   if (pFont == NULL) {
408     return FALSE;
409   }
410   GLYPHMETRICS gm;
411   iGlyphIndex &= 0x00FFFFFF;
412   static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
413   if (::GetGlyphOutlineW(((CFX_GdiFont*)pFont)->m_hDC, iGlyphIndex,
414                          GGO_GLYPH_INDEX | GGO_METRICS, &gm, 0, NULL,
415                          &mat2) != GDI_ERROR) {
416     bbox.left = gm.gmptGlyphOrigin.x;
417     bbox.top = gm.gmptGlyphOrigin.y;
418     bbox.width = gm.gmBlackBoxX;
419     bbox.height = gm.gmBlackBoxY;
420     return TRUE;
421   }
422   return FALSE;
423 }
GetBBox(CFX_Rect & bbox)424 FX_BOOL CFX_GdiFont::GetBBox(CFX_Rect& bbox) {
425   bbox.left = m_OutlineTM.otmrcFontBox.left;
426   bbox.top = m_OutlineTM.otmrcFontBox.top;
427   bbox.width = m_OutlineTM.otmrcFontBox.right - m_OutlineTM.otmrcFontBox.left;
428   bbox.height = m_OutlineTM.otmrcFontBox.bottom - m_OutlineTM.otmrcFontBox.top;
429   return TRUE;
430 }
GetItalicAngle() const431 int32_t CFX_GdiFont::GetItalicAngle() const {
432   return m_OutlineTM.otmItalicAngle / 10;
433 }
Reset()434 void CFX_GdiFont::Reset() {
435   Lock();
436   m_WidthCache.RemoveAll();
437   ClearCache();
438   Unlock();
439 }
GetSubstFont(int32_t iGlyphIndex) const440 IFX_Font* CFX_GdiFont::GetSubstFont(int32_t iGlyphIndex) const {
441   int32_t iHigher = (iGlyphIndex & 0x7F000000) >> 24;
442   if (iHigher == 0) {
443     return (IFX_Font*)this;
444   }
445   if (iHigher > m_SubstFonts.GetSize()) {
446     return (IFX_Font*)this;
447   }
448   return (IFX_Font*)m_SubstFonts[iHigher - 1];
449 }
GetGlyphDIBits(int32_t iGlyphIndex,FX_ARGB argb,const MAT2 * pMatrix,GLYPHMETRICS & gm,void * pBuffer,FX_DWORD bufSize)450 FX_DWORD CFX_GdiFont::GetGlyphDIBits(int32_t iGlyphIndex,
451                                      FX_ARGB argb,
452                                      const MAT2* pMatrix,
453                                      GLYPHMETRICS& gm,
454                                      void* pBuffer,
455                                      FX_DWORD bufSize) {
456   static const UINT uFormat = GGO_GLYPH_INDEX | GGO_GRAY8_BITMAP;
457   IFX_Font* pFont = GetSubstFont(iGlyphIndex);
458   if (pFont == NULL) {
459     return 0;
460   }
461   if (pFont != (IFX_Font*)this) {
462     return ((CFX_GdiFont*)pFont)
463         ->GetGlyphDIBits(iGlyphIndex & 0x00FFFFFF, argb, pMatrix, gm, pBuffer,
464                          bufSize);
465   }
466   uint8_t* pGlyphOutline = NULL;
467   FXSYS_assert(pMatrix != NULL);
468   FX_DWORD dwMAT2 = GetMAT2HashCode((const FIXED*)pMatrix);
469   CFX_GdiFontCache* pCache = NULL;
470   if (m_FontCache.Lookup((void*)dwMAT2, (void*&)pCache) && pCache != NULL) {
471     FX_LPCGDIGOCACHE pGO = pCache->GetCachedGlyphOutline(iGlyphIndex);
472     if (pGO != NULL) {
473       gm = pGO->gm;
474       pGlyphOutline = pGO->pOutline;
475     }
476   }
477   if (pGlyphOutline == NULL) {
478     FX_DWORD dwGlyphSize =
479         ::GetGlyphOutlineW(m_hDC, iGlyphIndex, uFormat, &gm, 0, NULL, pMatrix);
480     if (dwGlyphSize == 0 || dwGlyphSize == GDI_ERROR) {
481       return 0;
482     }
483     pGlyphOutline = FX_Alloc(uint8_t, dwGlyphSize);
484     ::GetGlyphOutlineW(m_hDC, iGlyphIndex, uFormat, &gm, dwGlyphSize,
485                        pGlyphOutline, pMatrix);
486     if (pCache == NULL) {
487       pCache = new CFX_GdiFontCache;
488       if (m_FontCache.GetCount() >= FX_GDIFONT_FONTCACHESIZE) {
489         ClearCache();
490       }
491       m_FontCache.SetAt((void*)dwMAT2, (void*)pCache);
492     }
493     pCache->SetCachedGlyphOutline(iGlyphIndex, gm, pGlyphOutline);
494   }
495   FX_DWORD dwDibSize = gm.gmBlackBoxX * 4 * gm.gmBlackBoxY;
496   if (pBuffer == NULL || bufSize < dwDibSize) {
497     return dwDibSize;
498   }
499   CreateGlyphBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, pGlyphOutline,
500                     (FX_DWORD*)pBuffer, argb);
501   return dwDibSize;
502 }
GetHashCode() const503 FX_DWORD CFX_GdiFont::GetHashCode() const {
504   return FX_GetFontHashCode(FX_GetCodePageFromCharset(m_LogFont.lfCharSet),
505                             FX_GetGdiFontStyles(m_LogFont));
506 }
GetMAT2HashCode(const FIXED * pFixed)507 FX_DWORD CFX_GdiFont::GetMAT2HashCode(const FIXED* pFixed) {
508   FXSYS_assert(pFixed != NULL);
509   FX_DWORD dwHash1 = 0, dwHash2 = 5381, dwRet;
510   for (int i = 0; i < 4; i++) {
511     dwRet = *((const FX_DWORD*)pFixed);
512     dwHash1 = 1313 * dwHash1 + dwRet;
513     dwHash2 += (dwHash2 << 5) + dwRet;
514     pFixed++;
515   }
516   return ((dwHash1 & 0x0000FFFF) << 16) | (dwHash2 & 0x0000FFFF);
517 }
CreateGlyphBitmap(int32_t iWidth,int32_t iHeight,uint8_t * pOutline,FX_DWORD * pDIB,FX_ARGB argb)518 void CFX_GdiFont::CreateGlyphBitmap(int32_t iWidth,
519                                     int32_t iHeight,
520                                     uint8_t* pOutline,
521                                     FX_DWORD* pDIB,
522                                     FX_ARGB argb) {
523   int32_t padding = ((iWidth + 3) / 4) * 4 - iWidth;
524   FX_DWORD alpha;
525   int32_t i, j;
526   for (j = iHeight - 1; j >= 0; --j) {
527     for (i = iWidth - 1; i >= 0; --i) {
528       if ((alpha = *pOutline++) == 0) {
529         *pDIB++ = 0;
530       } else {
531         alpha = (argb >> 24) * (alpha * 4 - 1) / 256;
532         *pDIB++ = (alpha << 24) | (argb & 0x00FFFFFF);
533       }
534     }
535     pOutline += padding;
536   }
537 }
538 #endif
539 #endif
540