From 0964d8dc9a0dcf50fed408353a213abc522aed33 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 21 Dec 2010 13:26:09 -0600 Subject: [PATCH] SM5SVN 9419e1e: Only unload fonts if not used by the next screen. [shakesoda] --- Docs/Changelog_sm-ssc.txt | 5 +++++ src/Font.cpp | 15 +++++++------- src/FontManager.cpp | 42 ++++++++++++++++++++++++++------------- src/FontManager.h | 1 + src/ScreenManager.cpp | 38 ++++++++++++++++++----------------- 5 files changed, 62 insertions(+), 39 deletions(-) diff --git a/Docs/Changelog_sm-ssc.txt b/Docs/Changelog_sm-ssc.txt index 424f519263..271b07ddfd 100644 --- a/Docs/Changelog_sm-ssc.txt +++ b/Docs/Changelog_sm-ssc.txt @@ -13,6 +13,11 @@ _____________________________________________________________________________ sm-ssc v1.2 | 201012xx -------------------------------------------------------------------------------- +20101221 +-------- +* SM5SVN r28586: Only unload fonts if not used by the next screen. [shakesoda] +* [ScreenSelectMaster] Fix DoSwitchAnyways to actually work again. + 20101220 -------- * [Actor] Add bezier (_fallback/02 Actor.lua) [FSX] diff --git a/src/Font.cpp b/src/Font.cpp index e012dcb898..1dd992d98b 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -223,9 +223,7 @@ int Font::GetLineHeightInSourcePixels( const wstring &szLine ) const Font::Font() { - //LOG->Trace( "Font::LoadFromFontName(%s)", sASCIITexturePath.c_str() ); - - m_iRefCount = 1; + m_iRefCount = 0; m_pDefault = NULL; m_bRightToLeft = false; // [sm-ssc] don't show strokes by default @@ -239,10 +237,11 @@ Font::~Font() void Font::Unload() { + LOG->Trace("Font:Unload '%s'",path.c_str()); for( unsigned i = 0; i < m_apPages.size(); ++i ) delete m_apPages[i]; m_apPages.clear(); - + m_iCharToGlyph.clear(); m_pDefault = NULL; @@ -656,6 +655,8 @@ void Font::Load( const RString &sIniPath, RString sChars ) { ASSERT_M( !GetExtension(sIniPath).CompareNoCase("ini"), sIniPath ); + LOG->Trace( "Font: Loading new font '%s'",sIniPath.c_str()); + // Check for recursion (recursive imports). for( unsigned i = 0; i < LoadStack.size(); ++i ) { @@ -725,9 +726,9 @@ void Font::Load( const RString &sIniPath, RString sChars ) continue; } - Font subfont; - subfont.Load(path, ""); - MergeFont(subfont); + Font *subfont=FONT->LoadFont(path,""); + MergeFont(*subfont); + FONT->UnloadFont(subfont); } } diff --git a/src/FontManager.cpp b/src/FontManager.cpp index 7830f60675..064594703f 100644 --- a/src/FontManager.cpp +++ b/src/FontManager.cpp @@ -22,7 +22,9 @@ FontManager::~FontManager() { const FontName &fn = i->first; Font* pFont = i->second; - LOG->Trace( "FONT LEAK: '%s', RefCount = %d.", fn.first.c_str(), pFont->m_iRefCount ); + if(pFont->m_iRefCount>0) { + LOG->Trace( "FONT LEAK: '%s', RefCount = %d.", fn.first.c_str(), pFont->m_iRefCount ); + } delete pFont; } } @@ -38,6 +40,7 @@ void FontManager::ReloadFonts() Font* FontManager::LoadFont( const RString &sFontOrTextureFilePath, RString sChars ) { + Font *pFont; // Convert the path to lowercase so that we don't load duplicates. // Really, this does not solve the duplicate problem. We could have two copies // of the same bitmap if there are equivalent but different paths @@ -48,15 +51,16 @@ Font* FontManager::LoadFont( const RString &sFontOrTextureFilePath, RString sCha map::iterator p = g_mapPathToFont.find( NewName ); if( p != g_mapPathToFont.end() ) { - Font *pFont=p->second; - pFont->m_iRefCount++; - return pFont; + pFont=p->second; + } + else { + pFont= new Font; + pFont->Load(sFontOrTextureFilePath, sChars); + g_mapPathToFont[NewName] = pFont; } - Font *f = new Font; - f->Load(sFontOrTextureFilePath, sChars); - g_mapPathToFont[NewName] = f; - return f; + ++pFont->m_iRefCount; + return pFont; } Font *FontManager::CopyFont( Font *pFont ) @@ -75,19 +79,29 @@ void FontManager::UnloadFont( Font *fp ) if(i->second != fp) continue; + ASSERT_M(fp->m_iRefCount>0,"Attempting to unload a font with zero ref count!"); + i->second->m_iRefCount--; - if( fp->m_iRefCount == 0 ) - { - delete i->second; // free the texture - g_mapPathToFont.erase( i ); // and remove the key in the map - } return; } - + FAIL_M( ssprintf("Unloaded an unknown font (%p)", fp) ); } +void FontManager::PruneFonts() { + for( std::map::iterator i = g_mapPathToFont.begin();i != g_mapPathToFont.end();) { + Font *fp=i->second; + if(fp->m_iRefCount==0) { + delete fp; + g_mapPathToFont.erase(i); + i = g_mapPathToFont.end(); + } else { + ++i; + } + } +} + /* * (c) 2001-2003 Chris Danford, Glenn Maynard * All rights reserved. diff --git a/src/FontManager.h b/src/FontManager.h index 1aad869ce7..9124d694f9 100644 --- a/src/FontManager.h +++ b/src/FontManager.h @@ -15,6 +15,7 @@ public: Font* LoadFont( const RString &sFontOrTextureFilePath, RString sChars = "" ); Font *CopyFont( Font *pFont ); void UnloadFont( Font *fp ); + void PruneFonts(); /* Warning: This reloads fonts completely, so all BitmapTexts need to be * reset, too. If this isn't done, best case they end up with old font diff --git a/src/ScreenManager.cpp b/src/ScreenManager.cpp index 2d7bc9e720..920af22797 100644 --- a/src/ScreenManager.cpp +++ b/src/ScreenManager.cpp @@ -67,6 +67,7 @@ #include "SongManager.h" #include "RageTextureManager.h" #include "ThemeManager.h" +#include "FontManager.h" #include "Screen.h" #include "ScreenDimensions.h" #include "Foreach.h" @@ -75,6 +76,7 @@ ScreenManager* SCREENMAN = NULL; // global and accessable from anywhere in our program static Preference g_bDelayedScreenLoad( "DelayedScreenLoad", false ); +static Preference g_bPruneFonts( "PruneFonts", true ); // Screen registration static map *g_pmapRegistrees = NULL; @@ -566,6 +568,11 @@ void ScreenManager::PrepareScreen( const RString &sScreenName ) } } + // Prune any unused fonts now that we have had a chance to reference the fonts + if(g_bPruneFonts) { + FONT->PruneFonts(); + } + TEXTUREMAN->DiagnosticOutput(); } @@ -660,19 +667,17 @@ void ScreenManager::LoadDelayedScreen() * cleanup, so it doesn't get deleted by cleanup. */ bool bLoaded = ActivatePreparedScreenAndBackground( sScreenName ); - vector apActorsToDelete; - if( g_setGroupedScreens.find(sScreenName) == g_setGroupedScreens.end() ) - { - /* It's time to delete all old prepared screens. Depending on DelayedScreenLoad, - * we can either delete the screens before or after we load the new screen. - * Either way, we must remove them from the prepared list before we prepare - * new screens. - * If DelayedScreenLoad is true, delete them now; this lowers memory - * requirements, but results in redundant loads as we unload common data. */ - if( g_bDelayedScreenLoad ) - DeletePreparedScreens(); - else - GrabPreparedActors( apActorsToDelete ); + bool deletePrepared=g_setGroupedScreens.find(sScreenName) == g_setGroupedScreens.end(); + + /* It's time to delete all old prepared screens. Depending on DelayedScreenLoad, + * we can either delete the screens before or after we load the new screen. + * Either way, we must remove them from the prepared list before we prepare + * new screens. + * If DelayedScreenLoad is true, delete them now; this lowers memory + * requirements, but results in redundant loads as we unload common data. */ + if( deletePrepared && g_bDelayedScreenLoad ) { + DeletePreparedScreens(); + deletePrepared=false; } // If the screen wasn't already prepared, load it. @@ -689,12 +694,9 @@ void ScreenManager::LoadDelayedScreen() ASSERT( bLoaded ); } - if( !apActorsToDelete.empty() ) + if( deletePrepared ) { - BeforeDeleteScreen(); - FOREACH( Actor*, apActorsToDelete, a ) - SAFE_DELETE( *a ); - AfterDeleteScreen(); + DeletePreparedScreens(); } MESSAGEMAN->Broadcast( Message_ScreenChanged );