FreeType: Fixed mem leak and adjustments
This commit is contained in:
@@ -73,12 +73,7 @@ bool CFontManager::Initialize()
|
|||||||
|
|
||||||
void CFontManager::Destroy()
|
void CFontManager::Destroy()
|
||||||
{
|
{
|
||||||
for (auto& pair : m_faceCache)
|
m_resolvedPathCache.clear();
|
||||||
{
|
|
||||||
if (pair.second)
|
|
||||||
FT_Done_Face(pair.second);
|
|
||||||
}
|
|
||||||
m_faceCache.clear();
|
|
||||||
m_fontPathMap.clear();
|
m_fontPathMap.clear();
|
||||||
|
|
||||||
if (m_ftLibrary)
|
if (m_ftLibrary)
|
||||||
@@ -142,7 +137,7 @@ std::string CFontManager::ResolveFontPath(const char* faceName)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Face CFontManager::GetFace(const char* faceName)
|
FT_Face CFontManager::CreateFace(const char* faceName)
|
||||||
{
|
{
|
||||||
if (!m_bInitialized)
|
if (!m_bInitialized)
|
||||||
{
|
{
|
||||||
@@ -150,24 +145,34 @@ FT_Face CFontManager::GetFace(const char* faceName)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string path = ResolveFontPath(faceName);
|
if (!faceName || !faceName[0])
|
||||||
if (path.empty())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Check cache
|
std::string lowerName = ToLower(faceName);
|
||||||
auto it = m_faceCache.find(path);
|
|
||||||
if (it != m_faceCache.end())
|
|
||||||
return it->second;
|
|
||||||
|
|
||||||
// Load new face
|
// Check resolved path cache (avoids repeated disk stat calls)
|
||||||
|
std::string path;
|
||||||
|
auto cacheIt = m_resolvedPathCache.find(lowerName);
|
||||||
|
if (cacheIt != m_resolvedPathCache.end())
|
||||||
|
{
|
||||||
|
path = cacheIt->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path = ResolveFontPath(faceName);
|
||||||
|
if (path.empty())
|
||||||
|
return nullptr;
|
||||||
|
m_resolvedPathCache[lowerName] = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new FT_Face — caller owns it
|
||||||
FT_Face face = nullptr;
|
FT_Face face = nullptr;
|
||||||
FT_Error err = FT_New_Face(m_ftLibrary, path.c_str(), 0, &face);
|
FT_Error err = FT_New_Face(m_ftLibrary, path.c_str(), 0, &face);
|
||||||
if (err != 0 || !face)
|
if (err != 0 || !face)
|
||||||
{
|
{
|
||||||
TraceError("CFontManager::GetFace - FT_New_Face failed for '%s' (error %d)", path.c_str(), err);
|
TraceError("CFontManager::CreateFace - FT_New_Face failed for '%s' (error %d)", path.c_str(), err);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_faceCache[path] = face;
|
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ public:
|
|||||||
bool Initialize();
|
bool Initialize();
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
// Get an FT_Face for a given face name. The face is owned by CFontManager.
|
// Create a NEW FT_Face for the given font name.
|
||||||
// Callers must NOT call FT_Done_Face on it.
|
// The caller OWNS the returned face and must call FT_Done_Face on it when done.
|
||||||
FT_Face GetFace(const char* faceName);
|
FT_Face CreateFace(const char* faceName);
|
||||||
|
|
||||||
FT_Library GetLibrary() const { return m_ftLibrary; }
|
FT_Library GetLibrary() const { return m_ftLibrary; }
|
||||||
|
|
||||||
@@ -34,6 +34,6 @@ private:
|
|||||||
// faceName (lowercase) -> file path
|
// faceName (lowercase) -> file path
|
||||||
std::unordered_map<std::string, std::string> m_fontPathMap;
|
std::unordered_map<std::string, std::string> m_fontPathMap;
|
||||||
|
|
||||||
// filePath -> FT_Face (cached, shared across sizes)
|
// faceName (lowercase) -> resolved file system path (caches disk lookups)
|
||||||
std::unordered_map<std::string, FT_Face> m_faceCache;
|
std::unordered_map<std::string, std::string> m_resolvedPathCache;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,6 +10,20 @@
|
|||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
#include FT_GLYPH_H
|
#include FT_GLYPH_H
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
// Precomputed gamma LUT to sharpen FreeType's grayscale anti-aliasing.
|
||||||
|
// GDI ClearType has high-contrast edges; FreeType grayscale is softer.
|
||||||
|
// Gamma < 1.0 boosts mid-range alpha, making edges crisper.
|
||||||
|
static struct SAlphaGammaLUT {
|
||||||
|
unsigned char table[256];
|
||||||
|
SAlphaGammaLUT() {
|
||||||
|
table[0] = 0;
|
||||||
|
for (int i = 1; i < 256; ++i)
|
||||||
|
table[i] = (unsigned char)(pow(i / 255.0, 0.80) * 255.0 + 0.5);
|
||||||
|
}
|
||||||
|
} s_alphaGammaLUT;
|
||||||
|
|
||||||
CGraphicFontTexture::CGraphicFontTexture()
|
CGraphicFontTexture::CGraphicFontTexture()
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize();
|
||||||
@@ -53,19 +67,55 @@ void CGraphicFontTexture::Destroy()
|
|||||||
stl_wipe(m_pFontTextureVector);
|
stl_wipe(m_pFontTextureVector);
|
||||||
m_charInfoMap.clear();
|
m_charInfoMap.clear();
|
||||||
|
|
||||||
// FT_Face is owned by CFontManager, do NOT free it here
|
if (m_ftFace)
|
||||||
m_ftFace = nullptr;
|
{
|
||||||
|
FT_Done_Face(m_ftFace);
|
||||||
|
m_ftFace = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGraphicFontTexture::CreateDeviceObjects()
|
bool CGraphicFontTexture::CreateDeviceObjects()
|
||||||
{
|
{
|
||||||
|
if (!m_ftFace)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// After device reset: wipe GPU textures, clear atlas state, and
|
||||||
|
// re-render all previously cached characters on demand.
|
||||||
|
// We keep m_charInfoMap keys but clear the entries so glyphs get re-rasterized.
|
||||||
|
std::vector<TCharacterKey> cachedKeys;
|
||||||
|
cachedKeys.reserve(m_charInfoMap.size());
|
||||||
|
for (const auto& pair : m_charInfoMap)
|
||||||
|
cachedKeys.push_back(pair.first);
|
||||||
|
|
||||||
|
stl_wipe(m_pFontTextureVector);
|
||||||
|
m_charInfoMap.clear();
|
||||||
|
m_x = 0;
|
||||||
|
m_y = 0;
|
||||||
|
m_step = 0;
|
||||||
|
m_isDirty = false;
|
||||||
|
|
||||||
|
// Reset CPU atlas buffer
|
||||||
|
if (m_pAtlasBuffer)
|
||||||
|
memset(m_pAtlasBuffer, 0, m_atlasWidth * m_atlasHeight * sizeof(DWORD));
|
||||||
|
|
||||||
|
// Create first GPU texture page
|
||||||
|
if (!AppendTexture())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Re-rasterize all previously cached glyphs
|
||||||
|
for (TCharacterKey key : cachedKeys)
|
||||||
|
UpdateCharacterInfomation(key);
|
||||||
|
|
||||||
|
UpdateTexture();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphicFontTexture::DestroyDeviceObjects()
|
void CGraphicFontTexture::DestroyDeviceObjects()
|
||||||
{
|
{
|
||||||
|
m_lpd3dTexture = NULL;
|
||||||
|
stl_wipe(m_pFontTextureVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGraphicFontTexture::Create(const char* c_szFontName, int fontSize, bool bItalic)
|
bool CGraphicFontTexture::Create(const char* c_szFontName, int fontSize, bool bItalic)
|
||||||
@@ -97,19 +147,17 @@ bool CGraphicFontTexture::Create(const char* c_szFontName, int fontSize, bool bI
|
|||||||
m_pAtlasBuffer = new DWORD[width * height];
|
m_pAtlasBuffer = new DWORD[width * height];
|
||||||
memset(m_pAtlasBuffer, 0, width * height * sizeof(DWORD));
|
memset(m_pAtlasBuffer, 0, width * height * sizeof(DWORD));
|
||||||
|
|
||||||
// Get FT_Face from FontManager
|
// Store UTF-8 name for device reset re-creation
|
||||||
m_ftFace = CFontManager::Instance().GetFace(c_szFontName);
|
m_fontNameUTF8 = c_szFontName ? c_szFontName : "";
|
||||||
|
|
||||||
|
// Create a per-instance FT_Face (this instance owns it)
|
||||||
|
m_ftFace = CFontManager::Instance().CreateFace(c_szFontName);
|
||||||
if (!m_ftFace)
|
if (!m_ftFace)
|
||||||
{
|
{
|
||||||
TraceError("CGraphicFontTexture::Create - Failed to get face for '%s'", c_szFontName ? c_szFontName : "(null)");
|
TraceError("CGraphicFontTexture::Create - Failed to create face for '%s'", c_szFontName ? c_szFontName : "(null)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tracef(" FontTexture: loaded '%s' size=%d family='%s' style='%s'\n",
|
|
||||||
c_szFontName ? c_szFontName : "(null)", fontSize,
|
|
||||||
m_ftFace->family_name ? m_ftFace->family_name : "?",
|
|
||||||
m_ftFace->style_name ? m_ftFace->style_name : "?");
|
|
||||||
|
|
||||||
// Set pixel size
|
// Set pixel size
|
||||||
int pixelSize = (fontSize < 0) ? -fontSize : fontSize;
|
int pixelSize = (fontSize < 0) ? -fontSize : fontSize;
|
||||||
if (pixelSize == 0)
|
if (pixelSize == 0)
|
||||||
@@ -207,26 +255,6 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
|||||||
if (!m_ftFace)
|
if (!m_ftFace)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Re-apply face state (FT_Face is shared across instances via CFontManager)
|
|
||||||
int pixelSize = (m_fontSize < 0) ? -m_fontSize : m_fontSize;
|
|
||||||
if (pixelSize == 0)
|
|
||||||
pixelSize = 12;
|
|
||||||
FT_Set_Pixel_Sizes(m_ftFace, 0, pixelSize);
|
|
||||||
|
|
||||||
if (m_bItalic)
|
|
||||||
{
|
|
||||||
FT_Matrix matrix;
|
|
||||||
matrix.xx = 0x10000L;
|
|
||||||
matrix.xy = 0x5800L;
|
|
||||||
matrix.yx = 0;
|
|
||||||
matrix.yy = 0x10000L;
|
|
||||||
FT_Set_Transform(m_ftFace, &matrix, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FT_Set_Transform(m_ftFace, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyValue == 0x08)
|
if (keyValue == 0x08)
|
||||||
keyValue = L' ';
|
keyValue = L' ';
|
||||||
|
|
||||||
@@ -248,8 +276,9 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
|||||||
|
|
||||||
int glyphBitmapWidth = bitmap.width;
|
int glyphBitmapWidth = bitmap.width;
|
||||||
int glyphBitmapHeight = bitmap.rows;
|
int glyphBitmapHeight = bitmap.rows;
|
||||||
|
int bearingX = slot->bitmap_left;
|
||||||
int bearingY = slot->bitmap_top;
|
int bearingY = slot->bitmap_top;
|
||||||
float advance = (float)(slot->advance.x >> 6);
|
float advance = ceilf((float)(slot->advance.x) / 64.0f);
|
||||||
|
|
||||||
// Normalize glyph placement to common baseline
|
// Normalize glyph placement to common baseline
|
||||||
// yOffset = distance from atlas row top to where the glyph bitmap starts
|
// yOffset = distance from atlas row top to where the glyph bitmap starts
|
||||||
@@ -273,6 +302,7 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
|||||||
rNewCharInfo.right = 0;
|
rNewCharInfo.right = 0;
|
||||||
rNewCharInfo.bottom = 0;
|
rNewCharInfo.bottom = 0;
|
||||||
rNewCharInfo.advance = advance;
|
rNewCharInfo.advance = advance;
|
||||||
|
rNewCharInfo.bearingX = 0.0f;
|
||||||
return &rNewCharInfo;
|
return &rNewCharInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +349,10 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
|||||||
{
|
{
|
||||||
unsigned char alpha = srcRow[col];
|
unsigned char alpha = srcRow[col];
|
||||||
if (alpha)
|
if (alpha)
|
||||||
dstRow[col] = ((DWORD)alpha << 24) | 0x00FFFFFF; // White + alpha
|
{
|
||||||
|
alpha = s_alphaGammaLUT.table[alpha];
|
||||||
|
dstRow[col] = ((DWORD)alpha << 24) | 0x00FFFFFF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +369,7 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
|||||||
rNewCharInfo.right = float(m_x + cellWidth) * rhwidth;
|
rNewCharInfo.right = float(m_x + cellWidth) * rhwidth;
|
||||||
rNewCharInfo.bottom = float(m_y + cellHeight) * rhheight;
|
rNewCharInfo.bottom = float(m_y + cellHeight) * rhheight;
|
||||||
rNewCharInfo.advance = advance;
|
rNewCharInfo.advance = advance;
|
||||||
|
rNewCharInfo.bearingX = (float)bearingX;
|
||||||
|
|
||||||
m_x += cellWidth;
|
m_x += cellWidth;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ class CGraphicFontTexture : public CGraphicTexture
|
|||||||
float right;
|
float right;
|
||||||
float bottom;
|
float bottom;
|
||||||
float advance;
|
float advance;
|
||||||
|
float bearingX;
|
||||||
} TCharacterInfomation;
|
} TCharacterInfomation;
|
||||||
|
|
||||||
typedef std::vector<TCharacterInfomation*> TPCharacterInfomationVector;
|
typedef std::vector<TCharacterInfomation*> TPCharacterInfomationVector;
|
||||||
@@ -75,6 +77,7 @@ class CGraphicFontTexture : public CGraphicTexture
|
|||||||
bool m_isDirty;
|
bool m_isDirty;
|
||||||
|
|
||||||
TCHAR m_fontName[LF_FACESIZE];
|
TCHAR m_fontName[LF_FACESIZE];
|
||||||
|
std::string m_fontNameUTF8; // stored for device reset re-creation
|
||||||
LONG m_fontSize;
|
LONG m_fontSize;
|
||||||
bool m_bItalic;
|
bool m_bItalic;
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ CGraphicText::TType CGraphicText::Type()
|
|||||||
|
|
||||||
bool CGraphicText::OnLoad(int /*iSize*/, const void* /*c_pvBuf*/)
|
bool CGraphicText::OnLoad(int /*iSize*/, const void* /*c_pvBuf*/)
|
||||||
{
|
{
|
||||||
static char strName[32];
|
char strName[32];
|
||||||
int size;
|
int size;
|
||||||
bool bItalic = false;
|
bool bItalic = false;
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ bool CGraphicText::OnLoad(int /*iSize*/, const void* /*c_pvBuf*/)
|
|||||||
strName[nameLen] = '\0';
|
strName[nameLen] = '\0';
|
||||||
++p;
|
++p;
|
||||||
|
|
||||||
static char num[8];
|
char num[8];
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (*p && isdigit(*p))
|
while (*p && isdigit(*p))
|
||||||
|
|||||||
@@ -534,9 +534,7 @@ void CGraphicTextInstance::Render(RECT * pClipRect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::unordered_map<LPDIRECT3DTEXTURE9, std::vector<SVertex>> s_vtxBatches;
|
static std::unordered_map<LPDIRECT3DTEXTURE9, std::vector<SVertex>> s_vtxBatches;
|
||||||
for (auto& [pTexture, vtxBatch] : s_vtxBatches) {
|
s_vtxBatches.clear();
|
||||||
vtxBatch.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||||
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||||
@@ -612,7 +610,7 @@ void CGraphicTextInstance::Render(RECT * pClipRect)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fFontSx = fCurX - 0.5f;
|
fFontSx = fCurX + pCurCharInfo->bearingX - 0.5f;
|
||||||
fFontSy = fCurY - 0.5f;
|
fFontSy = fCurY - 0.5f;
|
||||||
fFontEx = fFontSx + fFontWidth;
|
fFontEx = fFontSx + fFontWidth;
|
||||||
fFontEy = fFontSy + fFontHeight;
|
fFontEy = fFontSy + fFontHeight;
|
||||||
@@ -717,7 +715,7 @@ void CGraphicTextInstance::Render(RECT * pClipRect)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fFontSx = fCurX-0.5f;
|
fFontSx = fCurX + pCurCharInfo->bearingX - 0.5f;
|
||||||
fFontSy = fCurY-0.5f;
|
fFontSy = fCurY-0.5f;
|
||||||
fFontEx = fFontSx + fFontWidth;
|
fFontEx = fFontSx + fFontWidth;
|
||||||
fFontEy = fFontSy + fFontHeight;
|
fFontEy = fFontSy + fFontHeight;
|
||||||
|
|||||||
@@ -8,17 +8,22 @@
|
|||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_BITMAP_H
|
#include FT_BITMAP_H
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
// Same gamma LUT as GrpFontTexture for consistent text sharpness
|
||||||
|
static struct STextBarGammaLUT {
|
||||||
|
unsigned char table[256];
|
||||||
|
STextBarGammaLUT() {
|
||||||
|
table[0] = 0;
|
||||||
|
for (int i = 1; i < 256; ++i)
|
||||||
|
table[i] = (unsigned char)(pow(i / 255.0, 0.80) * 255.0 + 0.5);
|
||||||
|
}
|
||||||
|
} s_textBarGammaLUT;
|
||||||
|
|
||||||
void CTextBar::__SetFont(int fontSize, bool isBold)
|
void CTextBar::__SetFont(int fontSize, bool isBold)
|
||||||
{
|
{
|
||||||
m_ftFace = CFontManager::Instance().GetFace("Tahoma");
|
// Create a per-instance FT_Face (this instance owns it)
|
||||||
if (!m_ftFace)
|
m_ftFace = CFontManager::Instance().CreateFace("Tahoma");
|
||||||
return;
|
|
||||||
|
|
||||||
__ApplyFaceState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTextBar::__ApplyFaceState()
|
|
||||||
{
|
|
||||||
if (!m_ftFace)
|
if (!m_ftFace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -27,7 +32,7 @@ void CTextBar::__ApplyFaceState()
|
|||||||
pixelSize = 12;
|
pixelSize = 12;
|
||||||
|
|
||||||
FT_Set_Pixel_Sizes(m_ftFace, 0, pixelSize);
|
FT_Set_Pixel_Sizes(m_ftFace, 0, pixelSize);
|
||||||
FT_Set_Transform(m_ftFace, NULL, NULL); // TextBar never uses italic
|
FT_Set_Transform(m_ftFace, NULL, NULL);
|
||||||
|
|
||||||
m_ascender = (int)(m_ftFace->size->metrics.ascender >> 6);
|
m_ascender = (int)(m_ftFace->size->metrics.ascender >> 6);
|
||||||
m_lineHeight = (int)(m_ftFace->size->metrics.height >> 6);
|
m_lineHeight = (int)(m_ftFace->size->metrics.height >> 6);
|
||||||
@@ -57,9 +62,6 @@ void CTextBar::GetTextExtent(const char* c_szText, SIZE* p_size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-apply face state (shared FT_Face may have been changed by another user)
|
|
||||||
__ApplyFaceState();
|
|
||||||
|
|
||||||
std::wstring wText = Utf8ToWide(c_szText);
|
std::wstring wText = Utf8ToWide(c_szText);
|
||||||
|
|
||||||
int totalAdvance = 0;
|
int totalAdvance = 0;
|
||||||
@@ -70,7 +72,7 @@ void CTextBar::GetTextExtent(const char* c_szText, SIZE* p_size)
|
|||||||
glyphIndex = FT_Get_Char_Index(m_ftFace, L' ');
|
glyphIndex = FT_Get_Char_Index(m_ftFace, L' ');
|
||||||
|
|
||||||
if (FT_Load_Glyph(m_ftFace, glyphIndex, FT_LOAD_DEFAULT) == 0)
|
if (FT_Load_Glyph(m_ftFace, glyphIndex, FT_LOAD_DEFAULT) == 0)
|
||||||
totalAdvance += (int)(m_ftFace->glyph->advance.x >> 6);
|
totalAdvance += (int)ceilf((float)(m_ftFace->glyph->advance.x) / 64.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_size->cx = totalAdvance;
|
p_size->cx = totalAdvance;
|
||||||
@@ -82,9 +84,6 @@ void CTextBar::TextOut(int ix, int iy, const char * c_szText)
|
|||||||
if (!c_szText || !*c_szText || !m_ftFace)
|
if (!c_szText || !*c_szText || !m_ftFace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Re-apply face state (shared FT_Face may have been changed by another user)
|
|
||||||
__ApplyFaceState();
|
|
||||||
|
|
||||||
DWORD* pdwBuf = (DWORD*)m_dib.GetPointer();
|
DWORD* pdwBuf = (DWORD*)m_dib.GetPointer();
|
||||||
if (!pdwBuf)
|
if (!pdwBuf)
|
||||||
return;
|
return;
|
||||||
@@ -111,9 +110,9 @@ void CTextBar::TextOut(int ix, int iy, const char * c_szText)
|
|||||||
|
|
||||||
FT_GlyphSlot slot = m_ftFace->glyph;
|
FT_GlyphSlot slot = m_ftFace->glyph;
|
||||||
|
|
||||||
// Apply synthetic bold by embolden
|
// Apply synthetic bold (32 = 0.5px embolden; 64 = 1px was too aggressive)
|
||||||
if (m_isBold && slot->bitmap.buffer)
|
if (m_isBold && slot->bitmap.buffer)
|
||||||
FT_Bitmap_Embolden(CFontManager::Instance().GetLibrary(), &slot->bitmap, 64, 0);
|
FT_Bitmap_Embolden(CFontManager::Instance().GetLibrary(), &slot->bitmap, 32, 0);
|
||||||
|
|
||||||
FT_Bitmap& bitmap = slot->bitmap;
|
FT_Bitmap& bitmap = slot->bitmap;
|
||||||
|
|
||||||
@@ -138,8 +137,7 @@ void CTextBar::TextOut(int ix, int iy, const char * c_szText)
|
|||||||
unsigned char alpha = srcRow[col];
|
unsigned char alpha = srcRow[col];
|
||||||
if (alpha)
|
if (alpha)
|
||||||
{
|
{
|
||||||
// D3DFMT_A8R8G8B8 = ARGB in DWORD
|
alpha = s_textBarGammaLUT.table[alpha];
|
||||||
// colorRGB is stored as 0x00BBGGRR, convert to ARGB
|
|
||||||
DWORD r = (colorRGB >> 0) & 0xFF;
|
DWORD r = (colorRGB >> 0) & 0xFF;
|
||||||
DWORD g = (colorRGB >> 8) & 0xFF;
|
DWORD g = (colorRGB >> 8) & 0xFF;
|
||||||
DWORD b = (colorRGB >> 16) & 0xFF;
|
DWORD b = (colorRGB >> 16) & 0xFF;
|
||||||
@@ -148,7 +146,7 @@ void CTextBar::TextOut(int ix, int iy, const char * c_szText)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
penX += (int)(slot->advance.x >> 6);
|
penX += (int)ceilf((float)(slot->advance.x) / 64.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
@@ -171,5 +169,9 @@ CTextBar::CTextBar(int fontSize, bool isBold)
|
|||||||
|
|
||||||
CTextBar::~CTextBar()
|
CTextBar::~CTextBar()
|
||||||
{
|
{
|
||||||
// FT_Face is owned by CFontManager, do NOT free it here
|
if (m_ftFace)
|
||||||
|
{
|
||||||
|
FT_Done_Face(m_ftFace);
|
||||||
|
m_ftFace = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ class CTextBar : public CDibBar
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void __SetFont(int fontSize, bool isBold);
|
void __SetFont(int fontSize, bool isBold);
|
||||||
void __ApplyFaceState();
|
|
||||||
|
|
||||||
void OnCreate();
|
void OnCreate();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user