Index: xfa/src/fgas/src/font/fx_gdifont.cpp |
diff --git a/xfa/src/fgas/src/font/fx_gdifont.cpp b/xfa/src/fgas/src/font/fx_gdifont.cpp |
index aa923b6a21552a2a03dc8deecf80f8dcea8241ad..c14db357094cffe98d945e2d5ffc5a73c8284d49 100644 |
--- a/xfa/src/fgas/src/font/fx_gdifont.cpp |
+++ b/xfa/src/fgas/src/font/fx_gdifont.cpp |
@@ -1,539 +1,539 @@ |
-// 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 "xfa/src/fgas/src/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(); |
- int32_t iGlyph; |
- FX_LPGDIGOCACHE pGlyph; |
- while (pos != NULL) { |
- pGlyph = NULL; |
- m_GlyphMap.GetNextAssoc(pos, (void*&)iGlyph, (void*&)pGlyph); |
- if (pGlyph != NULL) { |
- FX_Free(pGlyph->pOutline); |
- FX_Free(pGlyph); |
- } |
- } |
- m_GlyphMap.RemoveAll(); |
-} |
-void CFX_GdiFontCache::SetCachedGlyphOutline(FX_DWORD dwGlyph, |
- const GLYPHMETRICS& gm, |
- uint8_t* pOutline) { |
- FXSYS_assert(pOutline != NULL); |
- FX_LPGDIGOCACHE pGlyph = FX_Alloc(FX_GDIGOCACHE, 1); |
- 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(const FX_WCHAR* pszFontFamily, |
- FX_DWORD dwFontStyles, |
- FX_WORD wCodePage, |
- IFX_FontMgr* pFontMgr) { |
- CFX_GdiFont* pFont = new CFX_GdiFont(pFontMgr); |
- if (!pFont->LoadFont(pszFontFamily, dwFontStyles, wCodePage)) { |
- pFont->Release(); |
- return NULL; |
- } |
- return pFont; |
-} |
-IFX_Font* IFX_Font::LoadFont(const uint8_t* pBuffer, |
- int32_t iLength, |
- IFX_FontMgr* pFontMgr) { |
- CFX_GdiFont* pFont = new CFX_GdiFont(pFontMgr); |
- if (!pFont->LoadFont(pBuffer, iLength)) { |
- pFont->Release(); |
- return NULL; |
- } |
- return pFont; |
-} |
-IFX_Font* IFX_Font::LoadFont(const FX_WCHAR* pszFileName, |
- IFX_FontMgr* pFontMgr) { |
- CFX_GdiFont* pFont = 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 = 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() { |
- int32_t iCount = m_SubstFonts.GetSize(); |
- for (int32_t 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((const FX_WCHAR*)m_wsFontFileName); |
- } else { |
- ::RemoveFontMemResourceEx(m_hRes); |
- } |
- } |
- m_WidthCache.RemoveAll(); |
- ClearCache(); |
-} |
-void CFX_GdiFont::ClearCache() { |
- int32_t iCount = m_SubstFonts.GetSize(); |
- for (int32_t 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(const FX_WCHAR* 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 ? (uint8_t)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(const uint8_t* pBuffer, int32_t 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, (const FX_WCHAR*)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(const FX_WCHAR* 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, (const FX_WCHAR*)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); |
- int32_t iLength = pFontStream->GetLength(); |
- if (iLength < 1) { |
- return FALSE; |
- } |
- uint8_t* pBuf = FX_Alloc(uint8_t, iLength); |
- iLength = pFontStream->ReadData(pBuf, iLength); |
- FX_BOOL bRet = LoadFont(pBuf, iLength); |
- FX_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; |
-} |
-int32_t CFX_GdiFont::GetFontFamilies(Gdiplus::FontCollection& fc) { |
- int32_t iCount = fc.GetFamilyCount(); |
- if (iCount < 1) { |
- return iCount; |
- } |
- Gdiplus::FontFamily* pFontFamilies = FX_Alloc(Gdiplus::FontFamily, iCount); |
- int32_t iFind = 0; |
- fc.GetFamilies(iCount, pFontFamilies, &iFind); |
- for (int32_t i = 0; i < iCount; i++) { |
- CFX_WideString wsFamilyName; |
- FX_WCHAR* pName = wsFamilyName.GetBuffer(LF_FACESIZE); |
- pFontFamilies[i].GetFamilyName(pName); |
- wsFamilyName.ReleaseBuffer(); |
- m_FontFamilies.Add(wsFamilyName); |
- } |
- FX_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, |
- int32_t& iWidth, |
- FX_BOOL bRecursive, |
- FX_BOOL bCharCode) { |
- iWidth = (int32_t)(int16_t)m_WidthCache.GetAt(wUnicode, 0); |
- if (iWidth == 0 || iWidth == -1) { |
- IFX_Font* pFont = NULL; |
- int32_t 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, (int16_t)iWidth); |
- Unlock(); |
- } |
- return iWidth > 0; |
-} |
-FX_BOOL CFX_GdiFont::GetCharWidth(FX_WCHAR wUnicode, |
- int32_t& iWidth, |
- FX_BOOL bCharCode) { |
- return GetCharWidth(wUnicode, iWidth, TRUE, bCharCode); |
-} |
-int32_t CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, |
- FX_BOOL bRecursive, |
- IFX_Font** ppFont, |
- FX_BOOL bCharCode) { |
- int32_t 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) { |
- int32_t 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); |
- int32_t 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; |
-} |
-int32_t CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode) { |
- return GetGlyphIndex(wUnicode, TRUE, NULL, bCharCode); |
-} |
-int32_t CFX_GdiFont::GetAscent() const { |
- return m_OutlineTM.otmAscent; |
-} |
-int32_t CFX_GdiFont::GetDescent() const { |
- return m_OutlineTM.otmDescent; |
-} |
-FX_BOOL CFX_GdiFont::GetCharBBox(FX_WCHAR wUnicode, |
- CFX_Rect& bbox, |
- FX_BOOL bCharCode) { |
- int32_t 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; |
-} |
-int32_t CFX_GdiFont::GetItalicAngle() const { |
- return m_OutlineTM.otmItalicAngle / 10; |
-} |
-void CFX_GdiFont::Reset() { |
- Lock(); |
- m_WidthCache.RemoveAll(); |
- ClearCache(); |
- Unlock(); |
-} |
-IFX_Font* CFX_GdiFont::GetSubstFont(int32_t iGlyphIndex) const { |
- int32_t 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(int32_t iGlyphIndex, |
- FX_ARGB argb, |
- const MAT2* pMatrix, |
- GLYPHMETRICS& gm, |
- void* 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); |
- } |
- uint8_t* 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_Alloc(uint8_t, dwGlyphSize); |
- ::GetGlyphOutlineW(m_hDC, iGlyphIndex, uFormat, &gm, dwGlyphSize, |
- pGlyphOutline, pMatrix); |
- if (pCache == NULL) { |
- pCache = 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_DWORD*)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(int32_t iWidth, |
- int32_t iHeight, |
- uint8_t* pOutline, |
- FX_DWORD* pDIB, |
- FX_ARGB argb) { |
- int32_t padding = ((iWidth + 3) / 4) * 4 - iWidth; |
- FX_DWORD alpha; |
- int32_t 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 |
+// 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 "xfa/src/fgas/src/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(); |
+ int32_t iGlyph; |
+ FX_LPGDIGOCACHE pGlyph; |
+ while (pos != NULL) { |
+ pGlyph = NULL; |
+ m_GlyphMap.GetNextAssoc(pos, (void*&)iGlyph, (void*&)pGlyph); |
+ if (pGlyph != NULL) { |
+ FX_Free(pGlyph->pOutline); |
+ FX_Free(pGlyph); |
+ } |
+ } |
+ m_GlyphMap.RemoveAll(); |
+} |
+void CFX_GdiFontCache::SetCachedGlyphOutline(FX_DWORD dwGlyph, |
+ const GLYPHMETRICS& gm, |
+ uint8_t* pOutline) { |
+ FXSYS_assert(pOutline != NULL); |
+ FX_LPGDIGOCACHE pGlyph = FX_Alloc(FX_GDIGOCACHE, 1); |
+ 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(const FX_WCHAR* pszFontFamily, |
+ FX_DWORD dwFontStyles, |
+ FX_WORD wCodePage, |
+ IFX_FontMgr* pFontMgr) { |
+ CFX_GdiFont* pFont = new CFX_GdiFont(pFontMgr); |
+ if (!pFont->LoadFont(pszFontFamily, dwFontStyles, wCodePage)) { |
+ pFont->Release(); |
+ return NULL; |
+ } |
+ return pFont; |
+} |
+IFX_Font* IFX_Font::LoadFont(const uint8_t* pBuffer, |
+ int32_t iLength, |
+ IFX_FontMgr* pFontMgr) { |
+ CFX_GdiFont* pFont = new CFX_GdiFont(pFontMgr); |
+ if (!pFont->LoadFont(pBuffer, iLength)) { |
+ pFont->Release(); |
+ return NULL; |
+ } |
+ return pFont; |
+} |
+IFX_Font* IFX_Font::LoadFont(const FX_WCHAR* pszFileName, |
+ IFX_FontMgr* pFontMgr) { |
+ CFX_GdiFont* pFont = 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 = 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() { |
+ int32_t iCount = m_SubstFonts.GetSize(); |
+ for (int32_t 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((const FX_WCHAR*)m_wsFontFileName); |
+ } else { |
+ ::RemoveFontMemResourceEx(m_hRes); |
+ } |
+ } |
+ m_WidthCache.RemoveAll(); |
+ ClearCache(); |
+} |
+void CFX_GdiFont::ClearCache() { |
+ int32_t iCount = m_SubstFonts.GetSize(); |
+ for (int32_t 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(const FX_WCHAR* 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 ? (uint8_t)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(const uint8_t* pBuffer, int32_t 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, (const FX_WCHAR*)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(const FX_WCHAR* 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, (const FX_WCHAR*)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); |
+ int32_t iLength = pFontStream->GetLength(); |
+ if (iLength < 1) { |
+ return FALSE; |
+ } |
+ uint8_t* pBuf = FX_Alloc(uint8_t, iLength); |
+ iLength = pFontStream->ReadData(pBuf, iLength); |
+ FX_BOOL bRet = LoadFont(pBuf, iLength); |
+ FX_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; |
+} |
+int32_t CFX_GdiFont::GetFontFamilies(Gdiplus::FontCollection& fc) { |
+ int32_t iCount = fc.GetFamilyCount(); |
+ if (iCount < 1) { |
+ return iCount; |
+ } |
+ Gdiplus::FontFamily* pFontFamilies = FX_Alloc(Gdiplus::FontFamily, iCount); |
+ int32_t iFind = 0; |
+ fc.GetFamilies(iCount, pFontFamilies, &iFind); |
+ for (int32_t i = 0; i < iCount; i++) { |
+ CFX_WideString wsFamilyName; |
+ FX_WCHAR* pName = wsFamilyName.GetBuffer(LF_FACESIZE); |
+ pFontFamilies[i].GetFamilyName(pName); |
+ wsFamilyName.ReleaseBuffer(); |
+ m_FontFamilies.Add(wsFamilyName); |
+ } |
+ FX_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, |
+ int32_t& iWidth, |
+ FX_BOOL bRecursive, |
+ FX_BOOL bCharCode) { |
+ iWidth = (int32_t)(int16_t)m_WidthCache.GetAt(wUnicode, 0); |
+ if (iWidth == 0 || iWidth == -1) { |
+ IFX_Font* pFont = NULL; |
+ int32_t 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, (int16_t)iWidth); |
+ Unlock(); |
+ } |
+ return iWidth > 0; |
+} |
+FX_BOOL CFX_GdiFont::GetCharWidth(FX_WCHAR wUnicode, |
+ int32_t& iWidth, |
+ FX_BOOL bCharCode) { |
+ return GetCharWidth(wUnicode, iWidth, TRUE, bCharCode); |
+} |
+int32_t CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, |
+ FX_BOOL bRecursive, |
+ IFX_Font** ppFont, |
+ FX_BOOL bCharCode) { |
+ int32_t 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) { |
+ int32_t 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); |
+ int32_t 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; |
+} |
+int32_t CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode) { |
+ return GetGlyphIndex(wUnicode, TRUE, NULL, bCharCode); |
+} |
+int32_t CFX_GdiFont::GetAscent() const { |
+ return m_OutlineTM.otmAscent; |
+} |
+int32_t CFX_GdiFont::GetDescent() const { |
+ return m_OutlineTM.otmDescent; |
+} |
+FX_BOOL CFX_GdiFont::GetCharBBox(FX_WCHAR wUnicode, |
+ CFX_Rect& bbox, |
+ FX_BOOL bCharCode) { |
+ int32_t 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; |
+} |
+int32_t CFX_GdiFont::GetItalicAngle() const { |
+ return m_OutlineTM.otmItalicAngle / 10; |
+} |
+void CFX_GdiFont::Reset() { |
+ Lock(); |
+ m_WidthCache.RemoveAll(); |
+ ClearCache(); |
+ Unlock(); |
+} |
+IFX_Font* CFX_GdiFont::GetSubstFont(int32_t iGlyphIndex) const { |
+ int32_t 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(int32_t iGlyphIndex, |
+ FX_ARGB argb, |
+ const MAT2* pMatrix, |
+ GLYPHMETRICS& gm, |
+ void* 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); |
+ } |
+ uint8_t* 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_Alloc(uint8_t, dwGlyphSize); |
+ ::GetGlyphOutlineW(m_hDC, iGlyphIndex, uFormat, &gm, dwGlyphSize, |
+ pGlyphOutline, pMatrix); |
+ if (pCache == NULL) { |
+ pCache = 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_DWORD*)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(int32_t iWidth, |
+ int32_t iHeight, |
+ uint8_t* pOutline, |
+ FX_DWORD* pDIB, |
+ FX_ARGB argb) { |
+ int32_t padding = ((iWidth + 3) / 4) * 4 - iWidth; |
+ FX_DWORD alpha; |
+ int32_t 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 |