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