bug 708075 - observe memory-pressure notification and discard cached gfxShapedWord records. r=roc

This commit is contained in:
Jonathan Kew 2012-01-13 11:37:46 +00:00
parent 187a7dbe69
commit c0b92e301e
2 changed files with 61 additions and 0 deletions

View File

@ -69,6 +69,7 @@
#include "nsCompressedCharMap.h"
#include "nsStyleConsts.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "cairo.h"
#include "gfxFontTest.h"
@ -81,6 +82,7 @@
using namespace mozilla;
using namespace mozilla::gfx;
using mozilla::services::GetObserverService;
gfxFontCache *gfxFontCache::gGlobalCache = nsnull;
@ -954,6 +956,39 @@ gfxFontFamily::FindFont(const nsAString& aPostscriptName)
return nsnull;
}
/*
* gfxFontCache - global cache of gfxFont instances.
* Expires unused fonts after a short interval;
* notifies fonts to age their cached shaped-word records;
* observes memory-pressure notification and tells fonts to clear their
* shaped-word caches to free up memory.
*/
// Observer for the memory-pressure notification, to trigger
// flushing of the shaped-word caches
class MemoryPressureObserver : public nsIObserver,
public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
};
NS_IMPL_ISUPPORTS2(MemoryPressureObserver, nsIObserver, nsISupportsWeakReference)
NS_IMETHODIMP
MemoryPressureObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *someData)
{
if (!nsCRT::strcmp(aTopic, "memory-pressure")) {
gfxFontCache *fontCache = gfxFontCache::GetCache();
if (fontCache) {
fontCache->FlushShapedWordCaches();
}
}
return NS_OK;
}
nsresult
gfxFontCache::Init()
@ -986,6 +1021,12 @@ gfxFontCache::gfxFontCache()
: nsExpirationTracker<gfxFont,3>(FONT_TIMEOUT_SECONDS * 1000)
{
mFonts.Init();
nsCOMPtr<nsIObserverService> obs = GetObserverService();
if (obs) {
obs->AddObserver(new MemoryPressureObserver, "memory-pressure", false);
}
mWordCacheExpirationTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mWordCacheExpirationTimer) {
mWordCacheExpirationTimer->
@ -1102,6 +1143,14 @@ gfxFontCache::WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache)
cache->mFonts.EnumerateEntries(AgeCachedWordsForFont, nsnull);
}
/*static*/
PLDHashOperator
gfxFontCache::ClearCachedWordsForFont(HashEntry* aHashEntry, void* aUserData)
{
aHashEntry->mFont->ClearCachedWords();
return PL_DHASH_NEXT;
}
void
gfxFont::RunMetrics::CombineWith(const RunMetrics& aOther, bool aOtherIsOnLeft)
{

View File

@ -732,6 +732,10 @@ public:
AgeAllGenerations();
}
void FlushShapedWordCaches() {
mFonts.EnumerateEntries(ClearCachedWordsForFont, nsnull);
}
protected:
void DestroyFont(gfxFont *aFont);
@ -767,6 +771,7 @@ protected:
nsTHashtable<HashEntry> mFonts;
static PLDHashOperator ClearCachedWordsForFont(HashEntry* aHashEntry, void*);
static PLDHashOperator AgeCachedWordsForFont(HashEntry* aHashEntry, void*);
static void WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache);
nsCOMPtr<nsITimer> mWordCacheExpirationTimer;
@ -1405,6 +1410,13 @@ public:
}
}
// Discard all cached word records; called on memory-pressure notification.
void ClearCachedWords() {
if (mWordCache.IsInitialized()) {
mWordCache.Clear();
}
}
protected:
// Call the appropriate shaper to generate glyphs for aText and store
// them into aShapedWord.