summaryrefslogtreecommitdiff
path: root/xfa/src/fgas/src/font/fx_gdifont.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/src/fgas/src/font/fx_gdifont.cpp')
-rw-r--r--xfa/src/fgas/src/font/fx_gdifont.cpp532
1 files changed, 532 insertions, 0 deletions
diff --git a/xfa/src/fgas/src/font/fx_gdifont.cpp b/xfa/src/fgas/src/font/fx_gdifont.cpp
new file mode 100644
index 0000000000..e9ab665b5a
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_gdifont.cpp
@@ -0,0 +1,532 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../fgas_base.h"
+#include "fx_gdifont.h"
+#include "fx_stdfontmgr.h"
+#ifdef _FXPLUS
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_
+CFX_GdiFontCache::CFX_GdiFontCache()
+ : m_GlyphMap(128)
+{
+}
+CFX_GdiFontCache::~CFX_GdiFontCache()
+{
+ FX_POSITION pos = m_GlyphMap.GetStartPosition();
+ FX_INT32 iGlyph;
+ FX_LPGDIGOCACHE pGlyph;
+ while (pos != NULL) {
+ pGlyph = NULL;
+ m_GlyphMap.GetNextAssoc(pos, (void*&)iGlyph, (void*&)pGlyph);
+ if (pGlyph != NULL) {
+ FDE_Free(pGlyph->pOutline);
+ FDE_Free(pGlyph);
+ }
+ }
+ m_GlyphMap.RemoveAll();
+}
+void CFX_GdiFontCache::SetCachedGlyphOutline(FX_DWORD dwGlyph, const GLYPHMETRICS &gm, FX_LPBYTE pOutline)
+{
+ FXSYS_assert(pOutline != NULL);
+ FX_LPGDIGOCACHE pGlyph = (FX_LPGDIGOCACHE)FDE_Alloc(sizeof(FX_GDIGOCACHE));
+ pGlyph->gm = gm;
+ pGlyph->pOutline = pOutline;
+ m_GlyphMap.SetAt((void*)dwGlyph, (void*)pGlyph);
+}
+FX_LPCGDIGOCACHE CFX_GdiFontCache::GetCachedGlyphOutline(FX_DWORD dwGlyph) const
+{
+ FX_LPCGDIGOCACHE pGlyph = NULL;
+ if (!m_GlyphMap.Lookup((void*)dwGlyph, (void*&)pGlyph)) {
+ return FALSE;
+ }
+ return pGlyph;
+}
+IFX_Font* IFX_Font::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage, IFX_FontMgr *pFontMgr)
+{
+ CFX_GdiFont *pFont = FX_NEW CFX_GdiFont(pFontMgr);
+ if (!pFont->LoadFont(pszFontFamily, dwFontStyles, wCodePage)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+IFX_Font* IFX_Font::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength, IFX_FontMgr *pFontMgr)
+{
+ CFX_GdiFont *pFont = FX_NEW CFX_GdiFont(pFontMgr);
+ if (!pFont->LoadFont(pBuffer, iLength)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+IFX_Font* IFX_Font::LoadFont(FX_LPCWSTR pszFileName, IFX_FontMgr *pFontMgr)
+{
+ CFX_GdiFont *pFont = FX_NEW CFX_GdiFont(pFontMgr);
+ if (!pFont->LoadFont(pszFileName)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+IFX_Font* IFX_Font::LoadFont(IFX_Stream *pFontStream, IFX_FontMgr *pFontMgr, FX_BOOL bSaveStream )
+{
+ CFX_GdiFont *pFont = FX_NEW CFX_GdiFont(pFontMgr);
+ if (!pFont->LoadFont(pFontStream)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+IFX_Font* IFX_Font::LoadFont(CFX_Font *pExtFont, IFX_FontMgr *pFontMgr)
+{
+ FXSYS_assert(FALSE);
+ return NULL;
+}
+#define FX_GDIFONT_FONTCACHESIZE 8
+CFX_GdiFont::CFX_GdiFont(IFX_FontMgr *pFontMgr)
+ : m_pFontMgr(pFontMgr)
+ , m_iRefCount(1)
+ , m_WidthCache(1024)
+ , m_hOldFont(NULL)
+ , m_hFont(NULL)
+ , m_hDC(NULL)
+ , m_wsFontFileName()
+ , m_FontFamilies()
+ , m_hRes(NULL)
+ , m_dwStyles(0)
+ , m_SubstFonts()
+ , m_FontMapper(16)
+ , m_FontCache(FX_GDIFONT_FONTCACHESIZE)
+{
+ m_hDC = ::CreateCompatibleDC(NULL);
+ FX_memset(&m_LogFont, 0, sizeof(m_LogFont));
+ FXSYS_assert(m_hDC != NULL);
+}
+CFX_GdiFont::~CFX_GdiFont()
+{
+ FX_INT32 iCount = m_SubstFonts.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ IFX_Font *pFont = (IFX_Font*)m_SubstFonts[i];
+ pFont->Release();
+ }
+ m_SubstFonts.RemoveAll();
+ m_FontMapper.RemoveAll();
+ if (m_hFont != NULL) {
+ ::SelectObject(m_hDC, m_hOldFont);
+ ::DeleteObject(m_hFont);
+ }
+ ::DeleteDC(m_hDC);
+ if (m_hRes != NULL) {
+ if (m_wsFontFileName.GetLength() > 0) {
+ ::RemoveFontResourceW((FX_LPCWSTR)m_wsFontFileName);
+ } else {
+ ::RemoveFontMemResourceEx(m_hRes);
+ }
+ }
+ m_WidthCache.RemoveAll();
+ ClearCache();
+}
+void CFX_GdiFont::ClearCache()
+{
+ FX_INT32 iCount = m_SubstFonts.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ IFX_Font *pFont = (IFX_Font*)m_SubstFonts[i];
+ ((CFX_GdiFont*)pFont)->ClearCache();
+ }
+ FX_POSITION pos = m_FontCache.GetStartPosition();
+ FX_DWORD dwMAT2;
+ CFX_GdiFontCache *pCache;
+ while (pos != NULL) {
+ pCache = NULL;
+ m_FontCache.GetNextAssoc(pos, (void*&)dwMAT2, (void*&)pCache);
+ if (pCache != NULL) {
+ delete pCache;
+ }
+ }
+ m_FontCache.RemoveAll();
+}
+void CFX_GdiFont::Release()
+{
+ if (-- m_iRefCount < 1) {
+ if (m_pFontMgr != NULL) {
+ m_pFontMgr->RemoveFont(this);
+ }
+ delete this;
+ }
+}
+IFX_Font* CFX_GdiFont::Retain()
+{
+ ++ m_iRefCount;
+ return this;
+}
+FX_BOOL CFX_GdiFont::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage)
+{
+ FXSYS_assert(m_hFont == NULL);
+ LOGFONTW lf;
+ FX_memset(&lf, 0, sizeof(lf));
+ lf.lfHeight = -1000;
+ lf.lfWeight = (dwFontStyles & FX_FONTSTYLE_Bold) ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = (dwFontStyles & FX_FONTSTYLE_Italic) != 0;
+ lf.lfPitchAndFamily = (dwFontStyles & FX_FONTSTYLE_FixedPitch) ? FIXED_PITCH : VARIABLE_PITCH;
+ if (dwFontStyles & FX_FONTSTYLE_Serif) {
+ lf.lfPitchAndFamily |= FF_ROMAN;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Script) {
+ lf.lfPitchAndFamily |= FF_SCRIPT;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Symbolic) {
+ lf.lfCharSet = SYMBOL_CHARSET;
+ } else {
+ FX_WORD wCharSet = FX_GetCharsetFromCodePage(wCodePage);
+ lf.lfCharSet = wCharSet != 0xFFFF ? (FX_BYTE)wCharSet : DEFAULT_CHARSET;
+ }
+ if (pszFontFamily == NULL) {
+ lf.lfFaceName[0] = L'\0';
+ } else {
+ FXSYS_wcsncpy(lf.lfFaceName, pszFontFamily, 31);
+ }
+ return LoadFont(lf);
+}
+FX_BOOL CFX_GdiFont::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength)
+{
+ FXSYS_assert(m_hFont == NULL && pBuffer != NULL && iLength > 0);
+ Gdiplus::PrivateFontCollection pfc;
+ if (pfc.AddMemoryFont(pBuffer, iLength) != Gdiplus::Ok) {
+ return FALSE;
+ }
+ if (GetFontFamilies(pfc) < 1) {
+ return FALSE;
+ }
+ FX_DWORD dwCount = 0;
+ m_hRes = ::AddFontMemResourceEx((void*)pBuffer, iLength, 0, &dwCount);
+ if (m_hRes == NULL) {
+ return FALSE;
+ }
+ CFX_WideString wsFamily = m_FontFamilies[0];
+ m_hFont = ::CreateFontW(-1000, 0, 0, 0, FW_NORMAL, FALSE, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, (FX_LPCWSTR)wsFamily);
+ if (m_hFont == NULL) {
+ ::RemoveFontMemResourceEx(m_hRes);
+ m_hRes = NULL;
+ return FALSE;
+ }
+ RetrieveFontStyles();
+ m_hOldFont = ::SelectObject(m_hDC, m_hFont);
+ ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
+ return TRUE;
+}
+FX_BOOL CFX_GdiFont::LoadFont(FX_LPCWSTR pszFileName)
+{
+ FXSYS_assert(m_hFont == NULL && pszFileName != NULL);
+ Gdiplus::PrivateFontCollection pfc;
+ if (pfc.AddFontFile(pszFileName) != Gdiplus::Ok) {
+ return FALSE;
+ }
+ if (GetFontFamilies(pfc) < 1) {
+ return FALSE;
+ }
+ m_wsFontFileName = pszFileName;
+ m_hRes = (HANDLE)::AddFontResourceW(pszFileName);
+ if (m_hRes == NULL) {
+ return FALSE;
+ }
+ CFX_WideString wsFamily = m_FontFamilies[0];
+ m_hFont = ::CreateFontW(-1000, 0, 0, 0, FW_NORMAL, FALSE, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, (FX_LPCWSTR)wsFamily);
+ if (m_hFont == NULL) {
+ ::RemoveFontResourceW(pszFileName);
+ m_hRes = NULL;
+ return FALSE;
+ }
+ RetrieveFontStyles();
+ ::SelectObject(m_hDC, m_hFont);
+ ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
+ return TRUE;
+}
+FX_BOOL CFX_GdiFont::LoadFont(IFX_Stream *pFontStream)
+{
+ FXSYS_assert(m_hFont == NULL && pFontStream != NULL);
+ FX_INT32 iLength = pFontStream->GetLength();
+ if (iLength < 1) {
+ return FALSE;
+ }
+ FX_LPBYTE pBuf = (FX_LPBYTE)FDE_Alloc(iLength);
+ if (pBuf == NULL) {
+ return FALSE;
+ }
+ iLength = pFontStream->ReadData(pBuf, iLength);
+ FX_BOOL bRet = LoadFont(pBuf, iLength);
+ FDE_Free(pBuf);
+ return bRet;
+}
+FX_BOOL CFX_GdiFont::LoadFont(const LOGFONTW &lf)
+{
+ FXSYS_assert(m_hFont == NULL);
+ m_hFont = ::CreateFontIndirectW((LPLOGFONTW)&lf);
+ if (m_hFont == NULL) {
+ return FALSE;
+ }
+ RetrieveFontStyles();
+ ::SelectObject(m_hDC, m_hFont);
+ ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
+ return TRUE;
+}
+FX_INT32 CFX_GdiFont::GetFontFamilies(Gdiplus::FontCollection &fc)
+{
+ FX_INT32 iCount = fc.GetFamilyCount();
+ if (iCount < 1) {
+ return iCount;
+ }
+ Gdiplus::FontFamily *pFontFamilies = (Gdiplus::FontFamily*)FDE_Alloc(iCount * sizeof(Gdiplus::FontFamily));
+ if (pFontFamilies == NULL) {
+ return -1;
+ }
+ FX_INT32 iFind = 0;
+ fc.GetFamilies(iCount, pFontFamilies, &iFind);
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ CFX_WideString wsFamilyName;
+ FX_LPWSTR pName = wsFamilyName.GetBuffer(LF_FACESIZE);
+ pFontFamilies[i].GetFamilyName(pName);
+ wsFamilyName.ReleaseBuffer();
+ m_FontFamilies.Add(wsFamilyName);
+ }
+ FDE_Free(pFontFamilies);
+ return iCount;
+}
+void CFX_GdiFont::RetrieveFontStyles()
+{
+ FXSYS_assert(m_hFont != NULL);
+ FX_memset(&m_LogFont, 0, sizeof(m_LogFont));
+ ::GetObjectW(m_hFont, sizeof(m_LogFont), &m_LogFont);
+ m_dwStyles = FX_GetGdiFontStyles(m_LogFont);
+}
+void CFX_GdiFont::GetFamilyName(CFX_WideString &wsFamily) const
+{
+ FXSYS_assert(m_hFont != NULL);
+ wsFamily = m_LogFont.lfFaceName;
+}
+FX_BOOL CFX_GdiFont::GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bRecursive, FX_BOOL bCharCode)
+{
+ iWidth = (FX_INT32)(FX_SHORT)m_WidthCache.GetAt(wUnicode, 0);
+ if (iWidth == 0 || iWidth == -1) {
+ IFX_Font *pFont = NULL;
+ FX_INT32 iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode);
+ if (iGlyph != 0xFFFF && pFont != NULL) {
+ if (pFont == (IFX_Font*)this) {
+ if (!::GetCharWidthI(m_hDC, iGlyph, 1, NULL, &iWidth)) {
+ iWidth = -1;
+ }
+ } else if (((CFX_GdiFont*)pFont)->GetCharWidth(wUnicode, iWidth, FALSE, bCharCode)) {
+ return TRUE;
+ }
+ } else {
+ iWidth = -1;
+ }
+ Lock();
+ m_WidthCache.SetAtGrow(wUnicode, (FX_SHORT)iWidth);
+ Unlock();
+ }
+ return iWidth > 0;
+}
+FX_BOOL CFX_GdiFont::GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bCharCode)
+{
+ return GetCharWidth(wUnicode, iWidth, TRUE, bCharCode);
+}
+FX_INT32 CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bRecursive, IFX_Font **ppFont, FX_BOOL bCharCode)
+{
+ FX_INT32 iGlyph = 0XFFFF;
+ if (::GetGlyphIndicesW(m_hDC, &wUnicode, 1, (LPWORD)&iGlyph, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR && iGlyph != 0xFFFF) {
+ if (ppFont != NULL) {
+ *ppFont = (IFX_Font*)this;
+ }
+ return iGlyph;
+ }
+ FX_LPCFONTUSB pFontUSB = FX_GetUnicodeBitField(wUnicode);
+ if (pFontUSB == NULL) {
+ return 0xFFFF;
+ }
+ FX_WORD wBitField = pFontUSB->wBitField;
+ if (wBitField >= 128) {
+ return 0xFFFF;
+ }
+ IFX_Font *pFont = NULL;
+ m_FontMapper.Lookup((void*)wBitField, (void*&)pFont);
+ if (pFont != NULL && pFont != (IFX_Font*)this) {
+ iGlyph = ((CFX_GdiFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);
+ if (iGlyph != 0xFFFF) {
+ FX_INT32 i = m_SubstFonts.Find(pFont);
+ if (i > -1) {
+ iGlyph |= ((i + 1) << 24);
+ if (ppFont != NULL) {
+ *ppFont = pFont;
+ }
+ return iGlyph;
+ }
+ }
+ }
+ if (m_pFontMgr != NULL && bRecursive) {
+ IFX_Font *pFont = m_pFontMgr->GetDefFontByUnicode(wUnicode, m_dwStyles, m_LogFont.lfFaceName);
+ if (pFont != NULL) {
+ if (pFont == (IFX_Font*)this) {
+ pFont->Release();
+ return 0xFFFF;
+ }
+ m_FontMapper.SetAt((void*)wBitField, (void*)pFont);
+ FX_INT32 i = m_SubstFonts.GetSize();
+ m_SubstFonts.Add(pFont);
+ iGlyph = ((CFX_GdiFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);
+ if (iGlyph != 0xFFFF) {
+ iGlyph |= ((i + 1) << 24);
+ if (ppFont != NULL) {
+ *ppFont = pFont;
+ }
+ return iGlyph;
+ }
+ }
+ }
+ return 0xFFFF;
+}
+FX_INT32 CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode)
+{
+ return GetGlyphIndex(wUnicode, TRUE, NULL, bCharCode);
+}
+FX_INT32 CFX_GdiFont::GetAscent() const
+{
+ return m_OutlineTM.otmAscent;
+}
+FX_INT32 CFX_GdiFont::GetDescent() const
+{
+ return m_OutlineTM.otmDescent;
+}
+FX_BOOL CFX_GdiFont::GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bCharCode)
+{
+ FX_INT32 iGlyphIndex = GetGlyphIndex(wUnicode, bCharCode);
+ if (iGlyphIndex == 0xFFFF) {
+ return FALSE;
+ }
+ IFX_Font *pFont = GetSubstFont(iGlyphIndex);
+ if (pFont == NULL) {
+ return FALSE;
+ }
+ GLYPHMETRICS gm;
+ iGlyphIndex &= 0x00FFFFFF;
+ static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
+ if (::GetGlyphOutlineW(((CFX_GdiFont*)pFont)->m_hDC, iGlyphIndex, GGO_GLYPH_INDEX | GGO_METRICS, &gm, 0, NULL, &mat2) != GDI_ERROR) {
+ bbox.left = gm.gmptGlyphOrigin.x;
+ bbox.top = gm.gmptGlyphOrigin.y;
+ bbox.width = gm.gmBlackBoxX;
+ bbox.height = gm.gmBlackBoxY;
+ return TRUE;
+ }
+ return FALSE;
+}
+FX_BOOL CFX_GdiFont::GetBBox(CFX_Rect &bbox)
+{
+ bbox.left = m_OutlineTM.otmrcFontBox.left;
+ bbox.top = m_OutlineTM.otmrcFontBox.top;
+ bbox.width = m_OutlineTM.otmrcFontBox.right - m_OutlineTM.otmrcFontBox.left;
+ bbox.height = m_OutlineTM.otmrcFontBox.bottom - m_OutlineTM.otmrcFontBox.top;
+ return TRUE;
+}
+FX_INT32 CFX_GdiFont::GetItalicAngle() const
+{
+ return m_OutlineTM.otmItalicAngle / 10;
+}
+void CFX_GdiFont::Reset()
+{
+ Lock();
+ m_WidthCache.RemoveAll();
+ ClearCache();
+ Unlock();
+}
+IFX_Font* CFX_GdiFont::GetSubstFont(FX_INT32 iGlyphIndex) const
+{
+ FX_INT32 iHigher = (iGlyphIndex & 0x7F000000) >> 24;
+ if (iHigher == 0) {
+ return (IFX_Font*)this;
+ }
+ if (iHigher > m_SubstFonts.GetSize()) {
+ return (IFX_Font*)this;
+ }
+ return (IFX_Font*)m_SubstFonts[iHigher - 1];
+}
+FX_DWORD CFX_GdiFont::GetGlyphDIBits(FX_INT32 iGlyphIndex, FX_ARGB argb, const MAT2 *pMatrix, GLYPHMETRICS &gm, FX_LPVOID pBuffer, FX_DWORD bufSize)
+{
+ static const UINT uFormat = GGO_GLYPH_INDEX | GGO_GRAY8_BITMAP;
+ IFX_Font *pFont = GetSubstFont(iGlyphIndex);
+ if (pFont == NULL) {
+ return 0;
+ }
+ if (pFont != (IFX_Font*)this) {
+ return ((CFX_GdiFont*)pFont)->GetGlyphDIBits(iGlyphIndex & 0x00FFFFFF, argb, pMatrix, gm, pBuffer, bufSize);
+ }
+ FX_LPBYTE pGlyphOutline = NULL;
+ FXSYS_assert(pMatrix != NULL);
+ FX_DWORD dwMAT2 = GetMAT2HashCode((const FIXED*)pMatrix);
+ CFX_GdiFontCache *pCache = NULL;
+ if (m_FontCache.Lookup((void*)dwMAT2, (void*&)pCache) && pCache != NULL) {
+ FX_LPCGDIGOCACHE pGO = pCache->GetCachedGlyphOutline(iGlyphIndex);
+ if (pGO != NULL) {
+ gm = pGO->gm;
+ pGlyphOutline = pGO->pOutline;
+ }
+ }
+ if (pGlyphOutline == NULL) {
+ FX_DWORD dwGlyphSize = ::GetGlyphOutlineW(m_hDC, iGlyphIndex, uFormat, &gm, 0, NULL, pMatrix);
+ if (dwGlyphSize == 0 || dwGlyphSize == GDI_ERROR) {
+ return 0;
+ }
+ pGlyphOutline = (FX_LPBYTE)FX_Alloc(dwGlyphSize);
+ ::GetGlyphOutlineW(m_hDC, iGlyphIndex, uFormat, &gm, dwGlyphSize, pGlyphOutline, pMatrix);
+ if (pCache == NULL) {
+ pCache = FX_NEW CFX_GdiFontCache;
+ if (m_FontCache.GetCount() >= FX_GDIFONT_FONTCACHESIZE) {
+ ClearCache();
+ }
+ m_FontCache.SetAt((void*)dwMAT2, (void*)pCache);
+ }
+ pCache->SetCachedGlyphOutline(iGlyphIndex, gm, pGlyphOutline);
+ }
+ FX_DWORD dwDibSize = gm.gmBlackBoxX * 4 * gm.gmBlackBoxY;
+ if (pBuffer == NULL || bufSize < dwDibSize) {
+ return dwDibSize;
+ }
+ CreateGlyphBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, pGlyphOutline, (FX_LPDWORD)pBuffer, argb);
+ return dwDibSize;
+}
+FX_DWORD CFX_GdiFont::GetHashCode() const
+{
+ return FX_GetFontHashCode(FX_GetCodePageFromCharset(m_LogFont.lfCharSet), FX_GetGdiFontStyles(m_LogFont));
+}
+FX_DWORD CFX_GdiFont::GetMAT2HashCode(const FIXED *pFixed)
+{
+ FXSYS_assert(pFixed != NULL);
+ FX_DWORD dwHash1 = 0, dwHash2 = 5381, dwRet;
+ for (int i = 0; i < 4; i ++) {
+ dwRet = *((const FX_DWORD*)pFixed);
+ dwHash1 = 1313 * dwHash1 + dwRet;
+ dwHash2 += (dwHash2 << 5) + dwRet;
+ pFixed ++;
+ }
+ return ((dwHash1 & 0x0000FFFF) << 16) | (dwHash2 & 0x0000FFFF);
+}
+void CFX_GdiFont::CreateGlyphBitmap(FX_INT32 iWidth, FX_INT32 iHeight, FX_LPBYTE pOutline, FX_LPDWORD pDIB, FX_ARGB argb)
+{
+ FX_INT32 padding = ((iWidth + 3) / 4) * 4 - iWidth;
+ FX_DWORD alpha;
+ FX_INT32 i, j;
+ for (j = iHeight - 1; j >= 0; --j) {
+ for (i = iWidth - 1; i >= 0; --i) {
+ if ((alpha = *pOutline++) == 0) {
+ *pDIB++ = 0;
+ } else {
+ alpha = (argb >> 24) * (alpha * 4 - 1) / 256;
+ *pDIB++ = (alpha << 24) | (argb & 0x00FFFFFF);
+ }
+ }
+ pOutline += padding;
+ }
+}
+#endif
+#endif