Recursively-loaded fonts are loaded completely--they'll never be
copies of already-loaded fonts. This simplifies things, and isn't likely to be a real problem; we'll have just a few copies of the default font, and the underlying texture is still refcounted.
This commit is contained in:
+24
-7
@@ -28,9 +28,9 @@ FontPage::FontPage()
|
|||||||
m_pTexture = NULL;
|
m_pTexture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontPage::Load( const CString &TexturePath, const FontPageSettings &cfg )
|
void FontPage::Load( const FontPageSettings &cfg )
|
||||||
{
|
{
|
||||||
m_sTexturePath = TexturePath;
|
m_sTexturePath = cfg.TexturePath;
|
||||||
|
|
||||||
// load texture
|
// load texture
|
||||||
m_sTexturePath.MakeLower();
|
m_sTexturePath.MakeLower();
|
||||||
@@ -76,10 +76,10 @@ void FontPage::Load( const CString &TexturePath, const FontPageSettings &cfg )
|
|||||||
* and ascender. */
|
* and ascender. */
|
||||||
if(cfg.Baseline != -1 && cfg.Top == -1)
|
if(cfg.Baseline != -1 && cfg.Top == -1)
|
||||||
RageException::Throw("Font %s has Baseline but no Top; must have both or neither",
|
RageException::Throw("Font %s has Baseline but no Top; must have both or neither",
|
||||||
TexturePath.GetString());
|
m_sTexturePath.GetString());
|
||||||
if(cfg.Baseline == -1 && cfg.Top != -1)
|
if(cfg.Baseline == -1 && cfg.Top != -1)
|
||||||
RageException::Throw("Font %s has Baseline but no Top; must have both or neither",
|
RageException::Throw("Font %s has Baseline but no Top; must have both or neither",
|
||||||
TexturePath.GetString());
|
m_sTexturePath.GetString());
|
||||||
|
|
||||||
int baseline=0;
|
int baseline=0;
|
||||||
if(cfg.Baseline == -1 && cfg.Top == -1)
|
if(cfg.Baseline == -1 && cfg.Top == -1)
|
||||||
@@ -103,7 +103,7 @@ void FontPage::Load( const CString &TexturePath, const FontPageSettings &cfg )
|
|||||||
SetExtraPixels(cfg.DrawExtraPixelsLeft, cfg.DrawExtraPixelsRight);
|
SetExtraPixels(cfg.DrawExtraPixelsLeft, cfg.DrawExtraPixelsRight);
|
||||||
|
|
||||||
LOG->Trace("Font %s: height %i, baseline %i ( == top %i)",
|
LOG->Trace("Font %s: height %i, baseline %i ( == top %i)",
|
||||||
TexturePath.GetString(), height, baseline, baseline-height);
|
m_sTexturePath.GetString(), height, baseline, baseline-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontPage::SetTextureCoords(const vector<int> &widths)
|
void FontPage::SetTextureCoords(const vector<int> &widths)
|
||||||
@@ -226,20 +226,37 @@ Font::Font()
|
|||||||
//LOG->Trace( "Font::LoadFromFontName(%s)", sASCIITexturePath.GetString() );
|
//LOG->Trace( "Font::LoadFromFontName(%s)", sASCIITexturePath.GetString() );
|
||||||
|
|
||||||
m_iRefCount = 1;
|
m_iRefCount = 1;
|
||||||
|
def = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::~Font()
|
Font::~Font()
|
||||||
|
{
|
||||||
|
Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::Unload()
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for(i = 0; i < pages.size(); ++i)
|
for(i = 0; i < pages.size(); ++i)
|
||||||
delete pages[i];
|
delete pages[i];
|
||||||
|
pages.clear();
|
||||||
|
|
||||||
/* Free any fonts that we merged into us. */
|
/* Free any fonts that we merged into us. These aren't managed by
|
||||||
|
* FontManager (we own them), so just delete them. */
|
||||||
for(i = 0; i < merged_fonts.size(); ++i)
|
for(i = 0; i < merged_fonts.size(); ++i)
|
||||||
FONT->UnloadFont(merged_fonts[i]);
|
delete merged_fonts[i];
|
||||||
|
merged_fonts.clear();
|
||||||
|
|
||||||
|
m_iCharToGlyph.clear();
|
||||||
|
def = NULL;
|
||||||
|
path.clear();
|
||||||
|
|
||||||
|
/* Don't clear the refcount. We've unloaded, but that doesn't mean things
|
||||||
|
* aren't still pointing to us. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Font::AddPage(FontPage *fp)
|
void Font::AddPage(FontPage *fp)
|
||||||
{
|
{
|
||||||
pages.push_back(fp);
|
pages.push_back(fp);
|
||||||
|
|||||||
@@ -34,7 +34,10 @@ struct glyph {
|
|||||||
RectF rect;
|
RectF rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FontPageSettings {
|
struct FontPageSettings
|
||||||
|
{
|
||||||
|
CString TexturePath;
|
||||||
|
|
||||||
int DrawExtraPixelsLeft,
|
int DrawExtraPixelsLeft,
|
||||||
DrawExtraPixelsRight,
|
DrawExtraPixelsRight,
|
||||||
AddToAllWidths,
|
AddToAllWidths,
|
||||||
@@ -74,7 +77,7 @@ public:
|
|||||||
FontPage();
|
FontPage();
|
||||||
~FontPage();
|
~FontPage();
|
||||||
|
|
||||||
void Load( const CString &sASCIITexturePath, const FontPageSettings &cfg );
|
void Load( const FontPageSettings &cfg );
|
||||||
|
|
||||||
/* Page-global properties. */
|
/* Page-global properties. */
|
||||||
int height;
|
int height;
|
||||||
@@ -110,6 +113,8 @@ public:
|
|||||||
/* Steal all of a font's pages. */
|
/* Steal all of a font's pages. */
|
||||||
void MergeFont(Font *f);
|
void MergeFont(Font *f);
|
||||||
|
|
||||||
|
void Unload();
|
||||||
|
|
||||||
/* Load font-wide settings. */
|
/* Load font-wide settings. */
|
||||||
void CapsOnly();
|
void CapsOnly();
|
||||||
|
|
||||||
|
|||||||
@@ -32,17 +32,12 @@ FontManager::FontManager()
|
|||||||
|
|
||||||
FontManager::~FontManager()
|
FontManager::~FontManager()
|
||||||
{
|
{
|
||||||
/* It's not safe to delete fonts that still have references left, because fonts
|
|
||||||
* will also release other fonts when they're deleted (we'd have to make sure
|
|
||||||
* to delete top-level fonts first). Since this should never happen anyway,
|
|
||||||
* and we only delete FontManager when we're shutting down, let's just warn
|
|
||||||
* about font leaks and not actually free them. */
|
|
||||||
for( std::map<CString, Font*>::iterator i = m_mapPathToFont.begin();
|
for( std::map<CString, Font*>::iterator i = m_mapPathToFont.begin();
|
||||||
i != m_mapPathToFont.end(); ++i)
|
i != m_mapPathToFont.end(); ++i)
|
||||||
{
|
{
|
||||||
Font* pFont = i->second;
|
Font* pFont = i->second;
|
||||||
LOG->Trace( "FONT LEAK: '%s', RefCount = %d.", i->first.GetString(), pFont->m_iRefCount );
|
LOG->Trace( "FONT LEAK: '%s', RefCount = %d.", i->first.GetString(), pFont->m_iRefCount );
|
||||||
// delete pFont;
|
delete pFont;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,9 +58,39 @@ bool FontManager::ExtractGameGlyph(longchar ch, int &c, Game &g)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, const CString &PageName, int NumFrames)
|
void FontManager::ReloadFonts()
|
||||||
{
|
{
|
||||||
|
map<CString, Font*> m_mapPathToFont;
|
||||||
|
|
||||||
|
for(map<CString, Font*>::iterator i = m_mapPathToFont.begin();
|
||||||
|
i != m_mapPathToFont.end(); ++i)
|
||||||
|
{
|
||||||
|
CString path = i->first;
|
||||||
|
Font *f = i->second;
|
||||||
|
f->Unload();
|
||||||
|
f->Load(f);
|
||||||
|
|
||||||
|
// i->
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, const CString &TexturePath, const CString &PageName, CString sChars)
|
||||||
|
{
|
||||||
|
cfg.TexturePath = TexturePath;
|
||||||
|
|
||||||
|
/* If we have any characters to map, add them. */
|
||||||
|
for( unsigned n=0; n<sChars.size(); n++ )
|
||||||
|
{
|
||||||
|
char c = sChars[n];
|
||||||
|
cfg.CharToGlyphNo[c] = n;
|
||||||
|
}
|
||||||
|
int NumFrames = RageTexture::GetFrameCountFromFileName(TexturePath);
|
||||||
if(NumFrames == 128 || NumFrames == 256)
|
if(NumFrames == 128 || NumFrames == 256)
|
||||||
{
|
{
|
||||||
/* If it's 128 or 256 frames, default to ASCII or ISO-8859-1,
|
/* If it's 128 or 256 frames, default to ASCII or ISO-8859-1,
|
||||||
@@ -81,8 +106,12 @@ void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, cons
|
|||||||
for( longchar i=0; i<NumFrames; i++ )
|
for( longchar i=0; i<NumFrames; i++ )
|
||||||
cfg.CharToGlyphNo[i] = i;
|
cfg.CharToGlyphNo[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
ini.RenameKey("Char Widths", "main");
|
ini.RenameKey("Char Widths", "main");
|
||||||
|
|
||||||
|
LOG->Trace("Loading font page '%s' settings from page name '%s'",
|
||||||
|
TexturePath.GetString(), PageName.GetString());
|
||||||
|
|
||||||
ini.GetValueI( PageName, "DrawExtraPixelsLeft", cfg.DrawExtraPixelsLeft );
|
ini.GetValueI( PageName, "DrawExtraPixelsLeft", cfg.DrawExtraPixelsLeft );
|
||||||
ini.GetValueI( PageName, "DrawExtraPixelsRight", cfg.DrawExtraPixelsRight );
|
ini.GetValueI( PageName, "DrawExtraPixelsRight", cfg.DrawExtraPixelsRight );
|
||||||
ini.GetValueI( PageName, "AddToAllWidths", cfg.AddToAllWidths );
|
ini.GetValueI( PageName, "AddToAllWidths", cfg.AddToAllWidths );
|
||||||
@@ -151,12 +180,7 @@ void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, cons
|
|||||||
|
|
||||||
if(game != GAME_INVALID) c = MakeGameGlyph(c, game);
|
if(game != GAME_INVALID) c = MakeGameGlyph(c, game);
|
||||||
|
|
||||||
int frame = atoi(data);
|
cfg.CharToGlyphNo[c] = atoi(data);
|
||||||
if(frame >= NumFrames)
|
|
||||||
RageException::Throw( "Font definition '%s' maps to frame %i, but font only has %i frames",
|
|
||||||
ini.GetPath().GetString(), frame, NumFrames );
|
|
||||||
|
|
||||||
cfg.CharToGlyphNo[c] = frame;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
@@ -312,7 +336,7 @@ Font *FontManager::LoadFontInt(const CString &sFontOrTextureFilePath, CString sC
|
|||||||
{
|
{
|
||||||
LoadingDefaultFont = true;
|
LoadingDefaultFont = true;
|
||||||
CString path = THEME->GetPathTo("Fonts", "default font");
|
CString path = THEME->GetPathTo("Fonts", "default font");
|
||||||
pFont->MergeFont(FONT->LoadFont(path));
|
pFont->MergeFont(LoadFontInt(path, ""));
|
||||||
LoadingDefaultFont = false;
|
LoadingDefaultFont = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +344,7 @@ Font *FontManager::LoadFontInt(const CString &sFontOrTextureFilePath, CString sC
|
|||||||
for(unsigned i = 0; i < ImportList.size(); ++i)
|
for(unsigned i = 0; i < ImportList.size(); ++i)
|
||||||
{
|
{
|
||||||
CString path = THEME->GetPathTo("Fonts", ImportList[i]);
|
CString path = THEME->GetPathTo("Fonts", ImportList[i]);
|
||||||
pFont->MergeFont(FONT->LoadFont(path));
|
pFont->MergeFont(LoadFontInt(path, ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,30 +353,26 @@ Font *FontManager::LoadFontInt(const CString &sFontOrTextureFilePath, CString sC
|
|||||||
{
|
{
|
||||||
FontPage *fp = new FontPage;
|
FontPage *fp = new FontPage;
|
||||||
|
|
||||||
int frames = RageTexture::GetFrameCountFromFileName(TexturePaths[i]);
|
|
||||||
|
|
||||||
/* Grab the page name, eg "foo" from "Normal [foo].png". */
|
/* Grab the page name, eg "foo" from "Normal [foo].png". */
|
||||||
CString pagename = GetPageNameFromFileName(TexturePaths[i]);
|
CString pagename = GetPageNameFromFileName(TexturePaths[i]);
|
||||||
|
|
||||||
/* Load settings for this page from the INI. */
|
/* Load settings for this page from the INI. */
|
||||||
FontPageSettings cfg;
|
FontPageSettings cfg;
|
||||||
|
LoadFontPageSettings(cfg, ini, TexturePaths[i], pagename, sChars);
|
||||||
/* If we have any characters to map, add them. */
|
|
||||||
for( unsigned n=0; n<sChars.size(); n++ )
|
|
||||||
{
|
|
||||||
char c = sChars[n];
|
|
||||||
cfg.CharToGlyphNo[c] = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Go. */
|
/* Go. */
|
||||||
LoadFontPageSettings(cfg, ini, pagename, frames);
|
fp->Load(cfg);
|
||||||
fp->Load(TexturePaths[i], cfg);
|
|
||||||
|
|
||||||
/* Expect at least as many frames as we have premapped characters. */
|
/* Expect at least as many frames as we have premapped characters. */
|
||||||
if( unsigned(fp->m_pTexture->GetNumFrames()) < sChars.size() )
|
/* Make sure that we don't map characters to frames we don't actually
|
||||||
RageException::Throw( "The font '%s' has %d frames; expected at least %i frames.",
|
* have. This can happen if the font is too small for an sChars. */
|
||||||
fp->m_pTexture->GetNumFrames(), sChars.size() );
|
for(map<longchar,int>::const_iterator it = fp->m_iCharToGlyphNo.begin();
|
||||||
|
it != fp->m_iCharToGlyphNo.end(); ++it)
|
||||||
|
{
|
||||||
|
if(it->second < fp->m_pTexture->GetNumFrames()) continue; /* OK */
|
||||||
|
RageException::Throw( "The font '%s' maps %s to frame %i, but the font only has %i frames.",
|
||||||
|
TexturePaths[i].GetString(), WcharDisplayText(wchar_t(it->first)).GetString(), it->second, fp->m_pTexture->GetNumFrames() );
|
||||||
|
}
|
||||||
|
|
||||||
LOG->Trace("Adding page %s (%s) to %s; %i glyphs",
|
LOG->Trace("Adding page %s (%s) to %s; %i glyphs",
|
||||||
TexturePaths[i].GetString(), pagename.GetString(),
|
TexturePaths[i].GetString(), pagename.GetString(),
|
||||||
@@ -408,7 +428,7 @@ Font* FontManager::LoadFont( const CString &sFontOrTextureFilePath, CString sCha
|
|||||||
InitCharAliases();
|
InitCharAliases();
|
||||||
|
|
||||||
// Convert the path to lowercase so that we don't load duplicates.
|
// Convert the path to lowercase so that we don't load duplicates.
|
||||||
// Really, this does not solve the duplicate problem. We could have to copies
|
// Really, this does not solve the duplicate problem. We could have two copies
|
||||||
// of the same bitmap if there are equivalent but different paths
|
// of the same bitmap if there are equivalent but different paths
|
||||||
// (e.g. "graphics\blah.png" and "..\stepmania\graphics\blah.png" ).
|
// (e.g. "graphics\blah.png" and "..\stepmania\graphics\blah.png" ).
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ protected:
|
|||||||
map<CString, Font*> m_mapPathToFont;
|
map<CString, Font*> m_mapPathToFont;
|
||||||
static Font *LoadFontInt(const CString &sFontOrTextureFilePath, CString sChars);
|
static Font *LoadFontInt(const CString &sFontOrTextureFilePath, CString sChars);
|
||||||
static CString GetPageNameFromFileName(const CString &fn);
|
static CString GetPageNameFromFileName(const CString &fn);
|
||||||
static void LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, const CString &PageName, int NumFrames);
|
static void LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, const CString &TexturePath, const CString &PageName, CString sChars);
|
||||||
static void GetFontPaths(const CString &sFontOrTextureFilePath,
|
static void GetFontPaths(const CString &sFontOrTextureFilePath,
|
||||||
CStringArray &TexturePaths, CString &IniPath);
|
CStringArray &TexturePaths, CString &IniPath);
|
||||||
static void InitCharAliases();
|
static void InitCharAliases();
|
||||||
|
|||||||
Reference in New Issue
Block a user