зеркало из https://github.com/mozilla/pjs.git
Bug 375757. Cache gfxFont objects. r=pavlov
This commit is contained in:
Родитель
4a73d20e5e
Коммит
0f4cb4d2f1
|
@ -50,6 +50,7 @@ class gfxAtsuiFontGroup;
|
|||
class gfxAtsuiFont : public gfxFont {
|
||||
public:
|
||||
gfxAtsuiFont(ATSUFontID fontID,
|
||||
const nsAString& name,
|
||||
const gfxFontStyle *fontStyle);
|
||||
virtual ~gfxAtsuiFont();
|
||||
|
||||
|
|
|
@ -44,12 +44,16 @@
|
|||
#include "nsString.h"
|
||||
#include "gfxPoint.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "gfxSkipChars.h"
|
||||
#include "gfxRect.h"
|
||||
#include "nsExpirationTracker.h"
|
||||
|
||||
class gfxContext;
|
||||
class gfxTextRun;
|
||||
class nsIAtom;
|
||||
class gfxFont;
|
||||
class gfxFontGroup;
|
||||
typedef struct _cairo cairo_t;
|
||||
|
||||
|
@ -74,6 +78,7 @@ struct THEBES_API gfxFontStyle {
|
|||
const nsACString& aLangGroup,
|
||||
float aSizeAdjust, PRPackedBool aSystemFont,
|
||||
PRPackedBool aFamilyNameQuirks);
|
||||
gfxFontStyle(const gfxFontStyle& aStyle);
|
||||
|
||||
// The style of font (normal, italic, oblique)
|
||||
PRUint8 style : 7;
|
||||
|
@ -113,6 +118,12 @@ struct THEBES_API gfxFontStyle {
|
|||
// needs to be done.
|
||||
float sizeAdjust;
|
||||
|
||||
PLDHashNumber Hash() const {
|
||||
return ((style + (systemFont << 7) + (familyNameQuirks << 8) +
|
||||
(weight << 9)) + PRUint32(size*1000) + PRUint32(sizeAdjust*1000)) ^
|
||||
HashString(langGroup);
|
||||
}
|
||||
|
||||
void ComputeWeightAndOffset(PRInt8 *outBaseWeight,
|
||||
PRInt8 *outOffset) const;
|
||||
|
||||
|
@ -120,27 +131,144 @@ struct THEBES_API gfxFontStyle {
|
|||
return (size == other.size) &&
|
||||
(style == other.style) &&
|
||||
(systemFont == other.systemFont) &&
|
||||
(variant == other.variant) &&
|
||||
(familyNameQuirks == other.familyNameQuirks) &&
|
||||
(weight == other.weight) &&
|
||||
(decorations == other.decorations) &&
|
||||
(langGroup.Equals(other.langGroup)) &&
|
||||
(sizeAdjust == other.sizeAdjust);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Font cache design:
|
||||
*
|
||||
* The mFonts hashtable contains most fonts, indexed by (name, style).
|
||||
* It does not add a reference to the fonts it contains.
|
||||
* When a font's refcount decreases to zero, instead of deleting it we
|
||||
* add it to our expiration tracker.
|
||||
* The expiration tracker tracks fonts with zero refcount. After a certain
|
||||
* period of time, such fonts expire and are deleted.
|
||||
*
|
||||
* We're using 3 generations with a ten-second generation interval, so
|
||||
* zero-refcount fonts will be deleted 20-30 seconds after their refcount
|
||||
* goes to zero, if timer events fire in a timely manner.
|
||||
*/
|
||||
class THEBES_API gfxFontCache : public nsExpirationTracker<gfxFont,3> {
|
||||
public:
|
||||
enum { TIMEOUT_SECONDS = 1 }; // XXX change this to 10 later
|
||||
gfxFontCache()
|
||||
: nsExpirationTracker<gfxFont,3>(TIMEOUT_SECONDS*1000) { mFonts.Init(); }
|
||||
~gfxFontCache() {
|
||||
// Expire everything that has a zero refcount, so we don't leak them.
|
||||
AgeAllGenerations();
|
||||
// All fonts should be gone. Otherwise we will crash releasing them
|
||||
// later, since this cache no longer exists
|
||||
NS_ASSERTION(mFonts.Count() == 0,
|
||||
"Fonts still alive while shutting down gfxFontCache");
|
||||
// Note that we have to delete everything through the expiration
|
||||
// tracker, since there might be fonts not in the hashtable but in
|
||||
// the tracker.
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the global gfxFontCache. You must call Init() before
|
||||
* calling this method --- the result will not be null.
|
||||
*/
|
||||
static gfxFontCache* GetCache() {
|
||||
return gGlobalCache;
|
||||
}
|
||||
|
||||
static nsresult Init();
|
||||
// It's OK to call this even if Init() has not been called.
|
||||
static void Shutdown();
|
||||
|
||||
// Look up a font in the cache. Returns an addrefed pointer, or null
|
||||
// if there's nothing matching in the cache
|
||||
already_AddRefed<gfxFont> Lookup(const nsAString &aName,
|
||||
const gfxFontStyle *aFontGroup);
|
||||
// We created a new font (presumably because Lookup returned null);
|
||||
// put it in the cache. The font's refcount should be nonzero. It is
|
||||
// allowable to add a new font even if there is one already in the
|
||||
// cache with the same key; we'll forget about the old one.
|
||||
void AddNew(gfxFont *aFont);
|
||||
|
||||
// The font's refcount has gone to zero; give ownership of it to
|
||||
// the cache. We delete it if it's not acquired again after a certain
|
||||
// amount of time.
|
||||
void NotifyReleased(gfxFont *aFont);
|
||||
|
||||
// This gets called when the timeout has expired on a zero-refcount
|
||||
// font; we just delete it.
|
||||
virtual void NotifyExpired(gfxFont *aFont);
|
||||
|
||||
protected:
|
||||
void DestroyFont(gfxFont *aFont);
|
||||
|
||||
static gfxFontCache *gGlobalCache;
|
||||
|
||||
struct Key {
|
||||
const nsAString& mString;
|
||||
const gfxFontStyle* mStyle;
|
||||
Key(const nsAString& aString, const gfxFontStyle* aStyle)
|
||||
: mString(aString), mStyle(aStyle) {}
|
||||
};
|
||||
|
||||
class HashEntry : public PLDHashEntryHdr {
|
||||
public:
|
||||
typedef const Key& KeyType;
|
||||
typedef const Key* KeyTypePointer;
|
||||
|
||||
// When constructing a new entry in the hashtable, we'll leave this
|
||||
// blank. The caller of Put() will fill this in.
|
||||
HashEntry(KeyTypePointer aStr) : mFont(nsnull) { }
|
||||
HashEntry(const HashEntry& toCopy) : mFont(toCopy.mFont) { }
|
||||
~HashEntry() { }
|
||||
|
||||
PRBool KeyEquals(const KeyTypePointer aKey) const;
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
static PLDHashNumber HashKey(const KeyTypePointer aKey) {
|
||||
return HashString(aKey->mString) ^ aKey->mStyle->Hash();
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = PR_TRUE };
|
||||
|
||||
gfxFont* mFont;
|
||||
};
|
||||
|
||||
nsTHashtable<HashEntry> mFonts;
|
||||
};
|
||||
|
||||
/* a SPECIFIC single font family */
|
||||
class THEBES_API gfxFont {
|
||||
THEBES_INLINE_DECL_REFCOUNTING(gfxFont)
|
||||
public:
|
||||
nsrefcnt AddRef(void) {
|
||||
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
NS_LOG_ADDREF(this, mRefCnt, "gfxFont", sizeof(*this));
|
||||
return mRefCnt;
|
||||
}
|
||||
nsrefcnt Release(void) {
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
--mRefCnt;
|
||||
NS_LOG_RELEASE(this, mRefCnt, "gfxFont");
|
||||
if (mRefCnt == 0) {
|
||||
// Don't delete just yet; return the object to the cache for
|
||||
// possibly recycling within some time limit
|
||||
gfxFontCache::GetCache()->NotifyReleased(this);
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
PRInt32 GetRefCount() { return mRefCnt; }
|
||||
|
||||
protected:
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
||||
public:
|
||||
gfxFont(const nsAString &aName, const gfxFontStyle *aFontGroup);
|
||||
virtual ~gfxFont() {}
|
||||
|
||||
const nsString& GetName() const { return mName; }
|
||||
const gfxFontStyle *GetStyle() const { return mStyle; }
|
||||
const gfxFontStyle *GetStyle() const { return &mStyle; }
|
||||
|
||||
virtual nsString GetUniqueName() = 0;
|
||||
|
||||
|
@ -283,14 +411,17 @@ public:
|
|||
PRUint32 aStart, PRUint32 aLength)
|
||||
{ return PR_FALSE; }
|
||||
|
||||
// Expiration tracking
|
||||
nsExpirationState *GetExpirationState() { return &mExpirationState; }
|
||||
|
||||
protected:
|
||||
// The family name of the font
|
||||
nsString mName;
|
||||
nsString mName;
|
||||
nsExpirationState mExpirationState;
|
||||
gfxFontStyle mStyle;
|
||||
|
||||
// This is called by the default Draw() implementation above.
|
||||
virtual void SetupCairoFont(cairo_t *aCR) = 0;
|
||||
|
||||
const gfxFontStyle *mStyle;
|
||||
};
|
||||
|
||||
class THEBES_API gfxTextRunFactory {
|
||||
|
|
|
@ -123,17 +123,6 @@ public:
|
|||
NS_STATIC_CAST(gfxFont*, mFonts[i]));
|
||||
}
|
||||
|
||||
gfxPangoFont *GetCachedFont(const nsAString& aName) const {
|
||||
nsRefPtr<gfxPangoFont> font;
|
||||
if (mFontCache.Get(aName, &font))
|
||||
return font;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void PutCachedFont(const nsAString& aName, gfxPangoFont *aFont) {
|
||||
mFontCache.Put(aName, aFont);
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class FontSelector;
|
||||
|
||||
|
@ -167,7 +156,6 @@ protected:
|
|||
void *closure);
|
||||
|
||||
private:
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<gfxPangoFont> > mFontCache;
|
||||
nsTArray<gfxFontStyle> mAdditionalStyles;
|
||||
};
|
||||
|
||||
|
|
|
@ -497,17 +497,6 @@ public:
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
gfxWindowsFont *GetCachedFont(const nsAString& aName) const {
|
||||
nsRefPtr<gfxWindowsFont> font;
|
||||
if (mFontCache.Get(aName, &font))
|
||||
return font;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void PutCachedFont(const nsAString& aName, gfxWindowsFont *aFont) {
|
||||
mFontCache.Put(aName, aFont);
|
||||
}
|
||||
|
||||
protected:
|
||||
static PRBool MakeFont(const nsAString& fontName,
|
||||
const nsACString& genericName,
|
||||
|
@ -519,11 +508,7 @@ protected:
|
|||
void InitTextRunUniscribe(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
|
||||
|
||||
private:
|
||||
friend class gfxWindowsTextRun;
|
||||
|
||||
nsCString mGenericFamily;
|
||||
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<gfxWindowsFont> > mFontCache;
|
||||
};
|
||||
|
||||
#endif /* GFX_WINDOWSFONTS_H */
|
||||
|
|
|
@ -72,8 +72,9 @@ OSStatus ATSClearGlyphVector(void *glyphVectorPtr);
|
|||
#endif
|
||||
|
||||
gfxAtsuiFont::gfxAtsuiFont(ATSUFontID fontID,
|
||||
const nsAString& name,
|
||||
const gfxFontStyle *fontStyle)
|
||||
: gfxFont(EmptyString(), fontStyle),
|
||||
: gfxFont(name, fontStyle),
|
||||
mFontStyle(fontStyle), mATSUFontID(fontID), mATSUStyle(nsnull),
|
||||
mAdjustedSize(0)
|
||||
{
|
||||
|
@ -112,7 +113,7 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef)
|
|||
};
|
||||
|
||||
gfxFloat size =
|
||||
PR_MAX(((mAdjustedSize != 0) ? mAdjustedSize : mStyle->size), 1.0f);
|
||||
PR_MAX(((mAdjustedSize != 0) ? mAdjustedSize : GetStyle()->size), 1.0f);
|
||||
|
||||
//fprintf (stderr, "string: '%s', size: %f\n", NS_ConvertUTF16toUTF8(aString).get(), size);
|
||||
|
||||
|
@ -153,10 +154,10 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef)
|
|||
mMetrics.xHeight = GetCharHeight('x');
|
||||
|
||||
if (mAdjustedSize == 0) {
|
||||
if (mStyle->sizeAdjust != 0) {
|
||||
if (GetStyle()->sizeAdjust != 0) {
|
||||
gfxFloat aspect = mMetrics.xHeight / size;
|
||||
mAdjustedSize =
|
||||
PR_MAX(ROUND(size * (mStyle->sizeAdjust / aspect)), 1.0f);
|
||||
PR_MAX(ROUND(size * (GetStyle()->sizeAdjust / aspect)), 1.0f);
|
||||
InitMetrics(aFontID, aFontRef);
|
||||
return;
|
||||
}
|
||||
|
@ -212,7 +213,7 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef)
|
|||
nsString
|
||||
gfxAtsuiFont::GetUniqueName()
|
||||
{
|
||||
return gfxQuartzFontCache::SharedFontCache()->GetPostscriptNameForFontID(mATSUFontID);
|
||||
return mName;
|
||||
}
|
||||
|
||||
float
|
||||
|
@ -273,6 +274,33 @@ gfxAtsuiFont::GetMetrics()
|
|||
return mMetrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the font in the gfxFont cache. If we don't find it, create one.
|
||||
* In either case, add a ref, append it to the aFonts array, and return it ---
|
||||
* except for OOM in which case we do nothing and return null.
|
||||
*/
|
||||
static gfxAtsuiFont *
|
||||
GetOrMakeFont(ATSUFontID aFontID, const gfxFontStyle *aStyle,
|
||||
nsTArray<nsRefPtr<gfxFont> > *aFonts)
|
||||
{
|
||||
const nsAString& name =
|
||||
gfxQuartzFontCache::SharedFontCache()->GetPostscriptNameForFontID(aFontID);
|
||||
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(name, aStyle);
|
||||
if (!font) {
|
||||
font = new gfxAtsuiFont(aFontID, name, aStyle);
|
||||
if (!font)
|
||||
return nsnull;
|
||||
gfxFontCache::GetCache()->AddNew(font);
|
||||
}
|
||||
// Add it to aFonts without unncessary refcount adjustment
|
||||
nsRefPtr<gfxFont> *destination = aFonts->AppendElement();
|
||||
if (!destination)
|
||||
return nsnull;
|
||||
destination->swap(font);
|
||||
gfxFont *f = *destination;
|
||||
return static_cast<gfxAtsuiFont *>(f);
|
||||
}
|
||||
|
||||
gfxAtsuiFontGroup::gfxAtsuiFontGroup(const nsAString& families,
|
||||
const gfxFontStyle *aStyle)
|
||||
: gfxFontGroup(families, aStyle)
|
||||
|
@ -291,7 +319,7 @@ gfxAtsuiFontGroup::gfxAtsuiFontGroup(const nsAString& families,
|
|||
// a specific langGroup. Let's just pick the default OSX
|
||||
// user font.
|
||||
ATSUFontID fontID = gfxQuartzFontCache::SharedFontCache()->GetDefaultATSUFontID (aStyle);
|
||||
mFonts.AppendElement(new gfxAtsuiFont(fontID, aStyle));
|
||||
GetOrMakeFont(fontID, aStyle, &mFonts);
|
||||
}
|
||||
|
||||
// Create the fallback structure
|
||||
|
@ -331,7 +359,7 @@ gfxAtsuiFontGroup::FindATSUFont(const nsAString& aName,
|
|||
|
||||
if (fontID != kATSUInvalidFontID) {
|
||||
//printf ("FindATSUFont! %s %d -> %d\n", NS_ConvertUTF16toUTF8(aName).get(), fontStyle->weight, (int)fontID);
|
||||
fontGroup->mFonts.AppendElement(new gfxAtsuiFont(fontID, fontStyle));
|
||||
GetOrMakeFont(fontID, fontStyle, &fontGroup->mFonts);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
@ -464,10 +492,7 @@ gfxAtsuiFontGroup::FindFontFor(ATSUFontID fid)
|
|||
return font;
|
||||
}
|
||||
|
||||
font = new gfxAtsuiFont(fid, GetStyle());
|
||||
mFonts.AppendElement(font);
|
||||
|
||||
return font;
|
||||
return GetOrMakeFont(fid, GetStyle(), &mFonts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsIPref.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsExpirationTracker.h"
|
||||
|
||||
#include "gfxFont.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
@ -53,8 +54,97 @@
|
|||
|
||||
#include "nsCRT.h"
|
||||
|
||||
gfxFontCache *gfxFontCache::gGlobalCache = nsnull;
|
||||
|
||||
nsresult
|
||||
gfxFontCache::Init()
|
||||
{
|
||||
NS_ASSERTION(!gGlobalCache, "Where did this come from?");
|
||||
gGlobalCache = new gfxFontCache();
|
||||
return gGlobalCache ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontCache::Shutdown()
|
||||
{
|
||||
delete gGlobalCache;
|
||||
gGlobalCache = nsnull;
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxFontCache::HashEntry::KeyEquals(const KeyTypePointer aKey) const
|
||||
{
|
||||
return aKey->mString.Equals(mFont->GetName()) &&
|
||||
aKey->mStyle->Equals(*mFont->GetStyle());
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFont>
|
||||
gfxFontCache::Lookup(const nsAString &aName,
|
||||
const gfxFontStyle *aStyle)
|
||||
{
|
||||
Key key(aName, aStyle);
|
||||
HashEntry *entry = mFonts.GetEntry(key);
|
||||
if (!entry)
|
||||
return nsnull;
|
||||
|
||||
gfxFont *font = entry->mFont;
|
||||
NS_ADDREF(font);
|
||||
if (font->GetExpirationState()->IsTracked()) {
|
||||
RemoveObject(font);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontCache::AddNew(gfxFont *aFont)
|
||||
{
|
||||
Key key(aFont->GetName(), aFont->GetStyle());
|
||||
HashEntry *entry = mFonts.PutEntry(key);
|
||||
if (!entry)
|
||||
return;
|
||||
if (entry->mFont) {
|
||||
// This is weird. Someone's asking us to overwrite an existing font.
|
||||
// Oh well, make it happen ... just ensure that we're not tracking
|
||||
// the old font
|
||||
if (entry->mFont->GetExpirationState()->IsTracked()) {
|
||||
RemoveObject(entry->mFont);
|
||||
}
|
||||
}
|
||||
entry->mFont = aFont;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontCache::NotifyReleased(gfxFont *aFont)
|
||||
{
|
||||
nsresult rv = AddObject(aFont);
|
||||
if (NS_FAILED(rv)) {
|
||||
// We couldn't track it for some reason. Kill it now.
|
||||
DestroyFont(aFont);
|
||||
}
|
||||
// Note that we might have fonts that aren't in the hashtable, perhaps because
|
||||
// of OOM adding to the hashtable or because someone did an AddNew where
|
||||
// we already had a font. These fonts are added to the expiration tracker
|
||||
// anyway, even though Lookup can't resurrect them. Eventually they will
|
||||
// expire and be deleted.
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontCache::NotifyExpired(gfxFont *aFont)
|
||||
{
|
||||
RemoveObject(aFont);
|
||||
DestroyFont(aFont);
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontCache::DestroyFont(gfxFont *aFont)
|
||||
{
|
||||
Key key(aFont->GetName(), aFont->GetStyle());
|
||||
mFonts.RemoveEntry(key);
|
||||
delete aFont;
|
||||
}
|
||||
|
||||
gfxFont::gfxFont(const nsAString &aName, const gfxFontStyle *aFontStyle) :
|
||||
mName(aName), mStyle(aFontStyle)
|
||||
mName(aName), mStyle(*aFontStyle)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -505,6 +595,14 @@ gfxFontStyle::gfxFontStyle(PRUint8 aStyle, PRUint8 aVariant,
|
|||
}
|
||||
}
|
||||
|
||||
gfxFontStyle::gfxFontStyle(const gfxFontStyle& aStyle) :
|
||||
style(aStyle.style), systemFont(aStyle.systemFont), variant(aStyle.variant),
|
||||
familyNameQuirks(aStyle.familyNameQuirks), weight(aStyle.weight),
|
||||
decorations(aStyle.decorations), size(aStyle.size),
|
||||
langGroup(aStyle.langGroup), sizeAdjust(aStyle.sizeAdjust)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontStyle::ComputeWeightAndOffset(PRInt8 *outBaseWeight, PRInt8 *outOffset) const
|
||||
{
|
||||
|
|
|
@ -127,6 +127,26 @@ gfxPangoFontGroup::FontCallback (const nsAString& fontName,
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the font in the gfxFont cache. If we don't find it, create one.
|
||||
* In either case, add a ref, append it to the aFonts array, and return it ---
|
||||
* except for OOM in which case we do nothing and return null.
|
||||
*/
|
||||
static already_AddRefed<gfxPangoFont>
|
||||
GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle)
|
||||
{
|
||||
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aName, aStyle);
|
||||
if (!font) {
|
||||
font = new gfxPangoFont(aName, aStyle);
|
||||
if (!font)
|
||||
return nsnull;
|
||||
gfxFontCache::GetCache()->AddNew(font);
|
||||
}
|
||||
gfxFont *f = nsnull;
|
||||
font.swap(f);
|
||||
return static_cast<gfxPangoFont *>(f);
|
||||
}
|
||||
|
||||
gfxPangoFontGroup::gfxPangoFontGroup (const nsAString& families,
|
||||
const gfxFontStyle *aStyle)
|
||||
: gfxFontGroup(families, aStyle)
|
||||
|
@ -135,8 +155,6 @@ gfxPangoFontGroup::gfxPangoFontGroup (const nsAString& families,
|
|||
|
||||
nsStringArray familyArray;
|
||||
|
||||
mFontCache.Init(15);
|
||||
|
||||
ForEachFont (FontCallback, &familyArray);
|
||||
|
||||
FindGenericFontFromStyle (FontCallback, &familyArray);
|
||||
|
@ -149,8 +167,12 @@ gfxPangoFontGroup::gfxPangoFontGroup (const nsAString& families,
|
|||
familyArray.AppendString(NS_LITERAL_STRING("sans-serif"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < familyArray.Count(); i++)
|
||||
mFonts.AppendElement(new gfxPangoFont(*familyArray[i], &mStyle));
|
||||
for (int i = 0; i < familyArray.Count(); i++) {
|
||||
nsRefPtr<gfxPangoFont> font = GetOrMakeFont(*familyArray[i], &mStyle);
|
||||
if (font) {
|
||||
mFonts.AppendElement(font);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfxPangoFontGroup::~gfxPangoFontGroup()
|
||||
|
@ -327,12 +349,12 @@ gfxPangoFont::RealizeFont(PRBool force)
|
|||
mPangoFontDesc = pango_font_description_new();
|
||||
|
||||
pango_font_description_set_family(mPangoFontDesc, NS_ConvertUTF16toUTF8(mName).get());
|
||||
gfxFloat size = mAdjustedSize ? mAdjustedSize : mStyle->size;
|
||||
gfxFloat size = mAdjustedSize ? mAdjustedSize : GetStyle()->size;
|
||||
MOZ_pango_font_description_set_absolute_size(mPangoFontDesc, size * PANGO_SCALE);
|
||||
pango_font_description_set_style(mPangoFontDesc, ThebesStyleToPangoStyle(mStyle));
|
||||
pango_font_description_set_weight(mPangoFontDesc, ThebesStyleToPangoWeight(mStyle));
|
||||
pango_font_description_set_style(mPangoFontDesc, ThebesStyleToPangoStyle(GetStyle()));
|
||||
pango_font_description_set_weight(mPangoFontDesc, ThebesStyleToPangoWeight(GetStyle()));
|
||||
|
||||
//printf ("%s, %f, %d, %d\n", NS_ConvertUTF16toUTF8(mName).get(), mStyle->size, ThebesStyleToPangoStyle(mStyle), ThebesStyleToPangoWeight(mStyle));
|
||||
//printf ("%s, %f, %d, %d\n", NS_ConvertUTF16toUTF8(mName).get(), GetStyle()->size, ThebesStyleToPangoStyle(GetStyle()), ThebesStyleToPangoWeight(GetStyle()));
|
||||
#ifndef THEBES_USE_PANGO_CAIRO
|
||||
mPangoCtx = pango_xft_get_context(GDK_DISPLAY(), 0);
|
||||
gdk_pango_context_set_colormap(mPangoCtx, gdk_rgb_get_cmap());
|
||||
|
@ -340,8 +362,8 @@ gfxPangoFont::RealizeFont(PRBool force)
|
|||
mPangoCtx = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(pango_cairo_font_map_get_default()));
|
||||
#endif
|
||||
|
||||
if (!mStyle->langGroup.IsEmpty())
|
||||
pango_context_set_language(mPangoCtx, GetPangoLanguage(mStyle->langGroup));
|
||||
if (!GetStyle()->langGroup.IsEmpty())
|
||||
pango_context_set_language(mPangoCtx, GetPangoLanguage(GetStyle()->langGroup));
|
||||
|
||||
pango_context_set_font_description(mPangoCtx, mPangoFontDesc);
|
||||
|
||||
|
@ -350,15 +372,15 @@ gfxPangoFont::RealizeFont(PRBool force)
|
|||
if (mAdjustedSize != 0)
|
||||
return;
|
||||
|
||||
mAdjustedSize = mStyle->size;
|
||||
if (mStyle->sizeAdjust == 0)
|
||||
mAdjustedSize = GetStyle()->size;
|
||||
if (GetStyle()->sizeAdjust == 0)
|
||||
return;
|
||||
|
||||
gfxSize isz, lsz;
|
||||
GetSize("x", 1, isz, lsz);
|
||||
gfxFloat aspect = isz.height / mStyle->size;
|
||||
gfxFloat aspect = isz.height / GetStyle()->size;
|
||||
mAdjustedSize =
|
||||
PR_MAX(NS_round(mStyle->size*(mStyle->sizeAdjust/aspect)), 1.0);
|
||||
PR_MAX(NS_round(GetStyle()->size*(GetStyle()->sizeAdjust/aspect)), 1.0);
|
||||
RealizeFont(PR_TRUE);
|
||||
}
|
||||
|
||||
|
@ -523,7 +545,7 @@ gfxPangoFont::GetMetrics()
|
|||
PangoFontMetrics *pfm = pango_font_get_metrics (font, NULL);
|
||||
|
||||
// ??
|
||||
mMetrics.emHeight = mAdjustedSize ? mAdjustedSize : mStyle->size;
|
||||
mMetrics.emHeight = mAdjustedSize ? mAdjustedSize : GetStyle()->size;
|
||||
|
||||
mMetrics.maxAscent = pango_font_metrics_get_ascent(pfm) / FLOAT_PANGO_SCALE;
|
||||
mMetrics.maxDescent = pango_font_metrics_get_descent(pfm) / FLOAT_PANGO_SCALE;
|
||||
|
@ -582,7 +604,7 @@ gfxPangoFont::GetMetrics()
|
|||
void
|
||||
gfxPangoFont::GetMozLang(nsACString &aMozLang)
|
||||
{
|
||||
aMozLang.Assign(mStyle->langGroup);
|
||||
aMozLang.Assign(GetStyle()->langGroup);
|
||||
}
|
||||
|
||||
PangoFont *
|
||||
|
@ -1250,12 +1272,10 @@ public:
|
|||
if (ExistsFont(fs, aName))
|
||||
return PR_TRUE;
|
||||
|
||||
nsRefPtr<gfxPangoFont> font = fs->mGroup->GetCachedFont(aName);
|
||||
if (!font) {
|
||||
font = new gfxPangoFont(aName, fs->mGroup->GetStyle());
|
||||
fs->mGroup->PutCachedFont(aName, font);
|
||||
nsRefPtr<gfxPangoFont> font = GetOrMakeFont(aName, fs->mGroup->GetStyle());
|
||||
if (font) {
|
||||
fs->mFonts.AppendElement(font);
|
||||
}
|
||||
fs->mFonts.AppendElement(font);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,13 @@ gfxPlatform::Init()
|
|||
}
|
||||
#endif
|
||||
|
||||
rv = gfxFontCache::Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Could not initialize gfxFontCache");
|
||||
Shutdown();
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = gfxTextRunCache::Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Could not initialize gfxTextRunCache");
|
||||
|
@ -117,6 +124,7 @@ gfxPlatform::Shutdown()
|
|||
// These may be called before the corresponding subsystems have actually
|
||||
// started up. That's OK, they can handle it.
|
||||
gfxTextRunCache::Shutdown();
|
||||
gfxFontCache::Shutdown();
|
||||
#if defined(XP_MACOSX)
|
||||
gfxQuartzFontCache::Shutdown();
|
||||
#endif
|
||||
|
|
|
@ -761,6 +761,7 @@ gfxQuartzFontCache::GetPostscriptNameForFontID(ATSUFontID fid)
|
|||
nsRefPtr<FontEntry> fe;
|
||||
|
||||
if (!mFontIDTable.Get(PRUint32(fid), &fe)) {
|
||||
NS_WARNING("Invalid font");
|
||||
return NS_LITERAL_STRING("INVALID_FONT");
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ gfxWindowsFont::MakeHFONT()
|
|||
}
|
||||
|
||||
PRInt8 baseWeight, weightDistance;
|
||||
mStyle->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||
GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||
|
||||
HDC dc = nsnull;
|
||||
|
||||
|
@ -223,7 +223,7 @@ gfxWindowsFont::MakeHFONT()
|
|||
if (!dc)
|
||||
dc = GetDC((HWND)nsnull);
|
||||
|
||||
FillLogFont(mStyle->size, tryWeight);
|
||||
FillLogFont(GetStyle()->size, tryWeight);
|
||||
mFont = CreateFontIndirectW(&mLogFont);
|
||||
HGDIOBJ oldFont = SelectObject(dc, mFont);
|
||||
TEXTMETRIC metrics;
|
||||
|
@ -259,8 +259,8 @@ gfxWindowsFont::MakeHFONT()
|
|||
if (chosenWeight == 0)
|
||||
chosenWeight = baseWeight * 100;
|
||||
|
||||
mAdjustedSize = mStyle->size;
|
||||
if (mStyle->sizeAdjust > 0) {
|
||||
mAdjustedSize = GetStyle()->size;
|
||||
if (GetStyle()->sizeAdjust > 0) {
|
||||
if (!mFont) {
|
||||
FillLogFont(mAdjustedSize, chosenWeight);
|
||||
mFont = CreateFontIndirectW(&mLogFont);
|
||||
|
@ -270,7 +270,7 @@ gfxWindowsFont::MakeHFONT()
|
|||
ComputeMetrics();
|
||||
gfxFloat aspect = mMetrics->xHeight / mMetrics->emHeight;
|
||||
mAdjustedSize =
|
||||
PR_MAX(ROUND(mStyle->size * (mStyle->sizeAdjust / aspect)), 1.0f);
|
||||
PR_MAX(ROUND(GetStyle()->size * (GetStyle()->sizeAdjust / aspect)), 1.0f);
|
||||
|
||||
if (mMetrics != oldMetrics) {
|
||||
delete mMetrics;
|
||||
|
@ -417,8 +417,8 @@ gfxWindowsFont::FillLogFont(gfxFloat aSize, PRInt16 aWeight)
|
|||
mLogFont.lfWidth = 0;
|
||||
mLogFont.lfEscapement = 0;
|
||||
mLogFont.lfOrientation = 0;
|
||||
mLogFont.lfUnderline = (mStyle->decorations & FONT_DECORATION_UNDERLINE) ? TRUE : FALSE;
|
||||
mLogFont.lfStrikeOut = (mStyle->decorations & FONT_DECORATION_STRIKEOUT) ? TRUE : FALSE;
|
||||
mLogFont.lfUnderline = (GetStyle()->decorations & FONT_DECORATION_UNDERLINE) ? TRUE : FALSE;
|
||||
mLogFont.lfStrikeOut = (GetStyle()->decorations & FONT_DECORATION_STRIKEOUT) ? TRUE : FALSE;
|
||||
mLogFont.lfCharSet = DEFAULT_CHARSET;
|
||||
#ifndef WINCE
|
||||
mLogFont.lfOutPrecision = OUT_TT_PRECIS;
|
||||
|
@ -428,7 +428,7 @@ gfxWindowsFont::FillLogFont(gfxFloat aSize, PRInt16 aWeight)
|
|||
mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
|
||||
mLogFont.lfQuality = DEFAULT_QUALITY;
|
||||
mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||||
mLogFont.lfItalic = (mStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? TRUE : FALSE;
|
||||
mLogFont.lfItalic = (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? TRUE : FALSE;
|
||||
mLogFont.lfWeight = aWeight;
|
||||
|
||||
int len = PR_MIN(mName.Length(), LF_FACESIZE - 1);
|
||||
|
@ -489,6 +489,26 @@ gfxWindowsFont::SetupCairoFont(cairo_t *aCR)
|
|||
*
|
||||
**********************************************************************/
|
||||
|
||||
/**
|
||||
* Look up the font in the gfxFont cache. If we don't find it, create one.
|
||||
* In either case, add a ref, append it to the aFonts array, and return it ---
|
||||
* except for OOM in which case we do nothing and return null.
|
||||
*/
|
||||
static already_AddRefed<gfxWindowsFont>
|
||||
GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle)
|
||||
{
|
||||
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aName, aStyle);
|
||||
if (!font) {
|
||||
font = new gfxWindowsFont(aName, aStyle);
|
||||
if (!font)
|
||||
return nsnull;
|
||||
gfxFontCache::GetCache()->AddNew(font);
|
||||
}
|
||||
gfxFont *f = nsnull;
|
||||
font.swap(f);
|
||||
return static_cast<gfxWindowsFont *>(f);
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxWindowsFontGroup::MakeFont(const nsAString& aName,
|
||||
const nsACString& aGenericName,
|
||||
|
@ -500,8 +520,10 @@ gfxWindowsFontGroup::MakeFont(const nsAString& aName,
|
|||
if (fg->HasFontNamed(aName))
|
||||
return PR_TRUE;
|
||||
|
||||
gfxWindowsFont *font = new gfxWindowsFont(aName, fg->GetStyle());
|
||||
fg->AppendFont(font);
|
||||
nsRefPtr<gfxWindowsFont> font = GetOrMakeFont(aName, fg->GetStyle());
|
||||
if (font) {
|
||||
fg->AppendFont(font);
|
||||
}
|
||||
|
||||
if (!aGenericName.IsEmpty() && fg->GetGenericFamily().IsEmpty())
|
||||
fg->mGenericFamily = aGenericName;
|
||||
|
@ -514,8 +536,6 @@ gfxWindowsFontGroup::MakeFont(const nsAString& aName,
|
|||
gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle)
|
||||
: gfxFontGroup(aFamilies, aStyle)
|
||||
{
|
||||
mFontCache.Init(25);
|
||||
|
||||
ForEachFont(MakeFont, this);
|
||||
|
||||
if (mGenericFamily.IsEmpty())
|
||||
|
@ -930,14 +950,11 @@ public:
|
|||
if (aName.Equals(item->mFonts[i]->GetName()))
|
||||
return PR_TRUE;
|
||||
|
||||
|
||||
nsRefPtr<gfxWindowsFont> font = item->mGroup->GetCachedFont(aName);
|
||||
if (!font) {
|
||||
font = new gfxWindowsFont(aName, item->mGroup->GetStyle());
|
||||
item->mGroup->PutCachedFont(aName, font);
|
||||
nsRefPtr<gfxWindowsFont> font =
|
||||
GetOrMakeFont(aName, item->mGroup->GetStyle());
|
||||
if (font) {
|
||||
item->mFonts.AppendElement(font);
|
||||
}
|
||||
item->mFonts.AppendElement(font);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче