diff --git a/gfx/public/Makefile.in b/gfx/public/Makefile.in index a2c9ec8f85f..8344d1bad1c 100644 --- a/gfx/public/Makefile.in +++ b/gfx/public/Makefile.in @@ -63,7 +63,6 @@ EXPORTS = \ nsIImage.h \ nsGfxCIID.h \ nsIRegion.h \ - nsDeviceContext.h \ nsITheme.h \ nsThemeConstants.h \ $(NULL) diff --git a/gfx/public/nsDeviceContext.h b/gfx/public/nsDeviceContext.h deleted file mode 100644 index 99465840266..00000000000 --- a/gfx/public/nsDeviceContext.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roland Mainz - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsDeviceContext_h___ -#define nsDeviceContext_h___ - -#include "nsIDeviceContext.h" -#include "nsIDeviceContextSpec.h" -#include "nsCOMPtr.h" -#include "nsIAtom.h" -#include "nsTArray.h" -#include "nsIObserver.h" -#include "nsIObserverService.h" -#include "nsWeakReference.h" -#include "gfxCore.h" - -class nsIImageRequest; -class nsHashtable; - -class NS_GFX nsFontCache -{ -public: - nsFontCache(); - virtual ~nsFontCache(); - - virtual nsresult Init(nsIDeviceContext* aContext); - virtual nsresult GetDeviceContext(nsIDeviceContext *&aContext) const; - virtual nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup, - gfxUserFontSet* aUserFontSet, - nsIFontMetrics *&aMetrics); - - nsresult FontMetricsDeleted(const nsIFontMetrics* aFontMetrics); - nsresult Compact(); - nsresult Flush(); - /* printer device context classes may create their own - * subclasses of nsFontCache (and override this method) and override - * DeviceContextImpl::CreateFontCache (see bug 81311). - */ - virtual nsresult CreateFontMetricsInstance(nsIFontMetrics** fm); - -protected: - nsTArray mFontMetrics; - nsIDeviceContext *mContext; // we do not addref this since - // ownership is implied. MMP. -}; - -// inherit visibility from the NS_GFX class declaration -#undef IMETHOD_VISIBILITY -#define IMETHOD_VISIBILITY - -class NS_GFX DeviceContextImpl : public nsIDeviceContext, - public nsIObserver, - public nsSupportsWeakReference -{ -public: - DeviceContextImpl(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - - NS_IMETHOD Init(nsNativeWidget aWidget); - - NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext); - NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext); - NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext){return NS_ERROR_NOT_IMPLEMENTED;} - NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext); - - NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup, - gfxUserFontSet* aUserFontSet, - nsIFontMetrics*& aMetrics); - NS_IMETHOD GetMetricsFor(const nsFont& aFont, - gfxUserFontSet* aUserFontSet, - nsIFontMetrics*& aMetrics); - - NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName); - - NS_IMETHOD GetLocalFontName(const nsString& aFaceName, nsString& aLocalName, - PRBool& aAliased); - - NS_IMETHOD CreateFontCache(); - NS_IMETHOD FontMetricsDeleted(const nsIFontMetrics* aFontMetrics); - NS_IMETHOD FlushFontCache(void); - - NS_IMETHOD GetDepth(PRUint32& aDepth); - - NS_IMETHOD GetPaletteInfo(nsPaletteInfo& aPaletteInfo); - - NS_IMETHOD PrepareDocument(PRUnichar * aTitle, - PRUnichar* aPrintToFileName) { return NS_OK; } - NS_IMETHOD AbortDocument(void) { return NS_OK; } - - NS_IMETHOD PrepareNativeWidget(nsIWidget *aWidget, void **aOut); - NS_IMETHOD ClearCachedSystemFonts(); - -private: - /* Helper methods for |CreateRenderingContext|&co. */ - nsresult InitRenderingContext(nsIRenderingContext *aContext, nsIWidget *aWindow); - -protected: - virtual ~DeviceContextImpl(); - - void CommonInit(void); - nsresult CreateIconILGroupContext(); - virtual nsresult CreateFontAliasTable(); - nsresult AliasFont(const nsString& aFont, - const nsString& aAlias, const nsString& aAltAlias, - PRBool aForceAlias); - void GetLocaleLangGroup(void); - - nsFontCache *mFontCache; - nsCOMPtr mLocaleLangGroup; // XXX temp fix for performance bug - erik - nsHashtable* mFontAliasTable; - -public: - nsNativeWidget mWidget; -#ifdef NS_DEBUG - PRBool mInitialized; -#endif -}; - -#undef IMETHOD_VISIBILITY -#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN - -#endif /* nsDeviceContext_h___ */ diff --git a/gfx/src/Makefile.in b/gfx/src/Makefile.in index c14c6a47a68..bc6c692a7f9 100644 --- a/gfx/src/Makefile.in +++ b/gfx/src/Makefile.in @@ -67,7 +67,6 @@ endif CPPSRCS = \ nsColor.cpp \ - nsDeviceContext.cpp \ nsFont.cpp \ nsRect.cpp \ nsRegion.cpp \ diff --git a/gfx/src/nsDeviceContext.cpp b/gfx/src/nsDeviceContext.cpp deleted file mode 100644 index 40c12876433..00000000000 --- a/gfx/src/nsDeviceContext.cpp +++ /dev/null @@ -1,609 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roland Mainz - * IBM Corp. - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsDeviceContext.h" -#include "nsFont.h" -#include "nsIView.h" -#include "nsGfxCIID.h" -#include "nsIFontMetrics.h" -#include "nsHashtable.h" -#include "nsILanguageAtomService.h" -#include "nsIServiceManager.h" -#include "nsUnicharUtils.h" -#include "nsCRT.h" -#include "nsIRenderingContext.h" -#include "gfxUserFontSet.h" -#include "nsIThebesFontMetrics.h" - -NS_IMPL_ISUPPORTS3(DeviceContextImpl, nsIDeviceContext, nsIObserver, nsISupportsWeakReference) - -DeviceContextImpl::DeviceContextImpl() -{ - mAppUnitsPerDevPixel = -1; - mAppUnitsPerInch = -1; - mAppUnitsPerDevNotScaledPixel = -1; - mPixelScale = 1.0f; - - mFontCache = nsnull; - mWidget = nsnull; - mFontAliasTable = nsnull; - -#ifdef NS_DEBUG - mInitialized = PR_FALSE; -#endif -} - -static PRBool DeleteValue(nsHashKey* aKey, void* aValue, void* closure) -{ - delete ((nsString*)aValue); - return PR_TRUE; -} - -DeviceContextImpl::~DeviceContextImpl() -{ - nsCOMPtr obs(do_GetService("@mozilla.org/observer-service;1")); - if (obs) - obs->RemoveObserver(this, "memory-pressure"); - - if (nsnull != mFontCache) - { - delete mFontCache; - mFontCache = nsnull; - } - - if (nsnull != mFontAliasTable) { - mFontAliasTable->Enumerate(DeleteValue); - delete mFontAliasTable; - } - -} - -NS_IMETHODIMP -DeviceContextImpl::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aSomeData) -{ - if (mFontCache && !nsCRT::strcmp(aTopic, "memory-pressure")) { - mFontCache->Compact(); - } - return NS_OK; -} - -NS_IMETHODIMP DeviceContextImpl::Init(nsNativeWidget aWidget) -{ - mWidget = aWidget; - - CommonInit(); - - return NS_OK; -} - -void DeviceContextImpl::CommonInit(void) -{ -#ifdef NS_DEBUG - NS_ASSERTION(!mInitialized, "device context is initialized twice!"); - mInitialized = PR_TRUE; -#endif - - // register as a memory-pressure observer to free font resources - // in low-memory situations. - nsCOMPtr obs(do_GetService("@mozilla.org/observer-service;1")); - if (obs) - obs->AddObserver(this, "memory-pressure", PR_TRUE); -} - -NS_IMETHODIMP DeviceContextImpl::CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext) -{ - nsresult rv; - - aContext = nsnull; - nsCOMPtr pContext; - rv = CreateRenderingContextInstance(*getter_AddRefs(pContext)); - if (NS_SUCCEEDED(rv)) { - rv = InitRenderingContext(pContext, aView->GetWidget()); - if (NS_SUCCEEDED(rv)) { - aContext = pContext; - NS_ADDREF(aContext); - } - } - - return rv; -} - -NS_IMETHODIMP DeviceContextImpl::CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext) -{ - nsresult rv; - - aContext = nsnull; - nsCOMPtr pContext; - rv = CreateRenderingContextInstance(*getter_AddRefs(pContext)); - if (NS_SUCCEEDED(rv)) { - rv = InitRenderingContext(pContext, aWidget); - if (NS_SUCCEEDED(rv)) { - aContext = pContext; - NS_ADDREF(aContext); - } - } - - return rv; -} - -NS_IMETHODIMP DeviceContextImpl::CreateRenderingContextInstance(nsIRenderingContext *&aContext) -{ - static NS_DEFINE_CID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID); - - nsresult rv; - nsCOMPtr pContext = do_CreateInstance(kRenderingContextCID, &rv); - if (NS_SUCCEEDED(rv)) { - aContext = pContext; - NS_ADDREF(aContext); - } - return rv; -} - -nsresult DeviceContextImpl::InitRenderingContext(nsIRenderingContext *aContext, nsIWidget *aWin) -{ - return aContext->Init(this, aWin); -} - -NS_IMETHODIMP DeviceContextImpl::CreateFontCache() -{ - mFontCache = new nsFontCache(); - if (!mFontCache) { - return NS_ERROR_OUT_OF_MEMORY; - } - return mFontCache->Init(this); -} - -NS_IMETHODIMP DeviceContextImpl::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics) -{ - if (mFontCache) { - mFontCache->FontMetricsDeleted(aFontMetrics); - } - return NS_OK; -} - -void -DeviceContextImpl::GetLocaleLangGroup(void) -{ - if (!mLocaleLangGroup) { - nsCOMPtr langService; - langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID); - if (langService) { - mLocaleLangGroup = langService->GetLocaleLanguageGroup(); - } - if (!mLocaleLangGroup) { - mLocaleLangGroup = do_GetAtom("x-western"); - } - } -} - -NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont, - nsIAtom* aLangGroup, gfxUserFontSet *aUserFontSet, nsIFontMetrics*& aMetrics) -{ - if (nsnull == mFontCache) { - nsresult rv = CreateFontCache(); - if (NS_FAILED(rv)) { - aMetrics = nsnull; - return rv; - } - // XXX temporary fix for performance problem -- erik - GetLocaleLangGroup(); - } - - // XXX figure out why aLangGroup is NULL sometimes - if (!aLangGroup) { - aLangGroup = mLocaleLangGroup; - } - - return mFontCache->GetMetricsFor(aFont, aLangGroup, aUserFontSet, aMetrics); -} - -NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont, - gfxUserFontSet *aUserFontSet, - nsIFontMetrics*& aMetrics) -{ - if (nsnull == mFontCache) { - nsresult rv = CreateFontCache(); - if (NS_FAILED(rv)) { - aMetrics = nsnull; - return rv; - } - // XXX temporary fix for performance problem -- erik - GetLocaleLangGroup(); - } - return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup, aUserFontSet, - aMetrics); -} - -NS_IMETHODIMP DeviceContextImpl::GetDepth(PRUint32& aDepth) -{ - aDepth = 24; - return NS_OK; -} - -NS_IMETHODIMP DeviceContextImpl::GetPaletteInfo(nsPaletteInfo& aPaletteInfo) -{ - aPaletteInfo.isPaletteDevice = PR_FALSE; - aPaletteInfo.sizePalette = 0; - aPaletteInfo.numReserved = 0; - aPaletteInfo.palette = nsnull; - return NS_OK; -} - -struct FontEnumData { - FontEnumData(nsIDeviceContext* aDC, nsString& aFaceName) - : mDC(aDC), mFaceName(aFaceName) - {} - nsIDeviceContext* mDC; - nsString& mFaceName; -}; - -static PRBool FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData) -{ - FontEnumData* data = (FontEnumData*)aData; - // XXX for now, all generic fonts are presumed to exist - // we may want to actually check if there's an installed conversion - if (aGeneric) { - data->mFaceName = aFamily; - return PR_FALSE; // found one, stop. - } - else { - nsAutoString local; - PRBool aliased; - data->mDC->GetLocalFontName(aFamily, local, aliased); - if (aliased || (NS_SUCCEEDED(data->mDC->CheckFontExistence(local)))) { - data->mFaceName = local; - return PR_FALSE; // found one, stop. - } - } - return PR_TRUE; // didn't exist, continue looking -} - -NS_IMETHODIMP DeviceContextImpl::FirstExistingFont(const nsFont& aFont, nsString& aFaceName) -{ - FontEnumData data(this, aFaceName); - if (aFont.EnumerateFamilies(FontEnumCallback, &data)) { - return NS_ERROR_FAILURE; // ran out - } - return NS_OK; -} - -class FontAliasKey: public nsHashKey -{ -public: - FontAliasKey(const nsString& aString) - {mString.Assign(aString);} - - virtual PRUint32 HashCode(void) const; - virtual PRBool Equals(const nsHashKey *aKey) const; - virtual nsHashKey *Clone(void) const; - - nsString mString; -}; - -PRUint32 FontAliasKey::HashCode(void) const -{ - PRUint32 hash = 0; - const PRUnichar* string = mString.get(); - PRUnichar ch; - while ((ch = *string++) != 0) { - // FYI: hash = hash*37 + ch - ch = ToUpperCase(ch); - hash = ((hash << 5) + (hash << 2) + hash) + ch; - } - return hash; -} - -PRBool FontAliasKey::Equals(const nsHashKey *aKey) const -{ - return mString.Equals(((FontAliasKey*)aKey)->mString, nsCaseInsensitiveStringComparator()); -} - -nsHashKey* FontAliasKey::Clone(void) const -{ - return new FontAliasKey(mString); -} -nsresult DeviceContextImpl::CreateFontAliasTable() -{ - nsresult result = NS_OK; - - if (nsnull == mFontAliasTable) { - mFontAliasTable = new nsHashtable(); - if (nsnull != mFontAliasTable) { - - nsAutoString times; times.AssignLiteral("Times"); - nsAutoString timesNewRoman; timesNewRoman.AssignLiteral("Times New Roman"); - nsAutoString timesRoman; timesRoman.AssignLiteral("Times Roman"); - nsAutoString arial; arial.AssignLiteral("Arial"); - nsAutoString helvetica; helvetica.AssignLiteral("Helvetica"); - nsAutoString courier; courier.AssignLiteral("Courier"); - nsAutoString courierNew; courierNew.AssignLiteral("Courier New"); - nsAutoString nullStr; - - AliasFont(times, timesNewRoman, timesRoman, PR_FALSE); - AliasFont(timesRoman, timesNewRoman, times, PR_FALSE); - AliasFont(timesNewRoman, timesRoman, times, PR_FALSE); - AliasFont(arial, helvetica, nullStr, PR_FALSE); - AliasFont(helvetica, arial, nullStr, PR_FALSE); - AliasFont(courier, courierNew, nullStr, PR_TRUE); - AliasFont(courierNew, courier, nullStr, PR_FALSE); - } - else { - result = NS_ERROR_OUT_OF_MEMORY; - } - } - return result; -} - -nsresult DeviceContextImpl::AliasFont(const nsString& aFont, - const nsString& aAlias, const nsString& aAltAlias, - PRBool aForceAlias) -{ - nsresult result = NS_OK; - - if (nsnull != mFontAliasTable) { - if (aForceAlias || NS_FAILED(CheckFontExistence(aFont))) { - if (NS_SUCCEEDED(CheckFontExistence(aAlias))) { - nsString* entry = new nsString(aAlias); - if (nsnull != entry) { - FontAliasKey key(aFont); - mFontAliasTable->Put(&key, entry); - } - else { - result = NS_ERROR_OUT_OF_MEMORY; - } - } - else if (!aAltAlias.IsEmpty() && NS_SUCCEEDED(CheckFontExistence(aAltAlias))) { - nsString* entry = new nsString(aAltAlias); - if (nsnull != entry) { - FontAliasKey key(aFont); - mFontAliasTable->Put(&key, entry); - } - else { - result = NS_ERROR_OUT_OF_MEMORY; - } - } - } - } - else { - result = NS_ERROR_FAILURE; - } - return result; -} - -NS_IMETHODIMP DeviceContextImpl::GetLocalFontName(const nsString& aFaceName, nsString& aLocalName, - PRBool& aAliased) -{ - nsresult result = NS_OK; - - if (nsnull == mFontAliasTable) { - result = CreateFontAliasTable(); - } - - if (nsnull != mFontAliasTable) { - FontAliasKey key(aFaceName); - const nsString* alias = (const nsString*)mFontAliasTable->Get(&key); - if (nsnull != alias) { - aLocalName = *alias; - aAliased = PR_TRUE; - } - else { - aLocalName = aFaceName; - aAliased = PR_FALSE; - } - } - return result; -} - -NS_IMETHODIMP DeviceContextImpl::FlushFontCache(void) -{ - if (nsnull != mFontCache) - mFontCache->Flush(); - - return NS_OK; -} - -///////////////////////////////////////////////////////////// - -nsFontCache::nsFontCache() -{ - MOZ_COUNT_CTOR(nsFontCache); - mContext = nsnull; -} - -nsFontCache::~nsFontCache() -{ - MOZ_COUNT_DTOR(nsFontCache); - Flush(); -} - -nsresult -nsFontCache::Init(nsIDeviceContext* aContext) -{ - NS_PRECONDITION(nsnull != aContext, "null ptr"); - // Note: we don't hold a reference to the device context, because it - // holds a reference to us and we don't want circular references - mContext = aContext; - return NS_OK; -} - -nsresult -nsFontCache::GetDeviceContext(nsIDeviceContext *&aContext) const -{ - aContext = mContext; - NS_IF_ADDREF(aContext); - return NS_OK; -} - -nsresult -nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup, - gfxUserFontSet *aUserFontSet, nsIFontMetrics *&aMetrics) -{ - // First check our cache - // start from the end, which is where we put the most-recent-used element - - nsIFontMetrics* fm; - PRInt32 n = mFontMetrics.Length() - 1; - for (PRInt32 i = n; i >= 0; --i) { - fm = mFontMetrics[i]; - nsIThebesFontMetrics* tfm = static_cast(fm); - if (fm->Font().Equals(aFont) && tfm->GetUserFontSet() == aUserFontSet) { - nsCOMPtr langGroup; - fm->GetLangGroup(getter_AddRefs(langGroup)); - if (aLangGroup == langGroup.get()) { - if (i != n) { - // promote it to the end of the cache - mFontMetrics.RemoveElementAt(i); - mFontMetrics.AppendElement(fm); - } - tfm->GetThebesFontGroup()->UpdateFontList(); - NS_ADDREF(aMetrics = fm); - return NS_OK; - } - } - } - - // It's not in the cache. Get font metrics and then cache them. - - aMetrics = nsnull; - nsresult rv = CreateFontMetricsInstance(&fm); - if (NS_FAILED(rv)) return rv; - rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet); - if (NS_SUCCEEDED(rv)) { - // the mFontMetrics list has the "head" at the end, because append is - // cheaper than insert - mFontMetrics.AppendElement(fm); - aMetrics = fm; - NS_ADDREF(aMetrics); - return NS_OK; - } - fm->Destroy(); - NS_RELEASE(fm); - - // One reason why Init() fails is because the system is running out of resources. - // e.g., on Win95/98 only a very limited number of GDI objects are available. - // Compact the cache and try again. - - Compact(); - rv = CreateFontMetricsInstance(&fm); - if (NS_FAILED(rv)) return rv; - rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet); - if (NS_SUCCEEDED(rv)) { - mFontMetrics.AppendElement(fm); - aMetrics = fm; - NS_ADDREF(aMetrics); - return NS_OK; - } - fm->Destroy(); - NS_RELEASE(fm); - - // could not setup a new one, send an old one (XXX search a "best match"?) - - n = mFontMetrics.Length() - 1; // could have changed in Compact() - if (n >= 0) { - aMetrics = mFontMetrics[n]; - NS_ADDREF(aMetrics); - return NS_OK; - } - - NS_POSTCONDITION(NS_SUCCEEDED(rv), "font metrics should not be null - bug 136248"); - return rv; -} - -/* PostScript module may override this method to create - * nsIFontMetrics objects with their own classes - */ -nsresult -nsFontCache::CreateFontMetricsInstance(nsIFontMetrics** fm) -{ - static NS_DEFINE_CID(kFontMetricsCID, NS_FONT_METRICS_CID); - return CallCreateInstance(kFontMetricsCID, fm); -} - -nsresult nsFontCache::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics) -{ - mFontMetrics.RemoveElement(aFontMetrics); - return NS_OK; -} - -nsresult nsFontCache::Compact() -{ - // Need to loop backward because the running element can be removed on the way - for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) { - nsIFontMetrics* fm = mFontMetrics[i]; - nsIFontMetrics* oldfm = fm; - // Destroy() isn't here because we want our device context to be notified - NS_RELEASE(fm); // this will reset fm to nsnull - // if the font is really gone, it would have called back in - // FontMetricsDeleted() and would have removed itself - if (mFontMetrics.IndexOf(oldfm) >= 0) { - // nope, the font is still there, so let's hold onto it too - NS_ADDREF(oldfm); - } - } - return NS_OK; -} - -nsresult nsFontCache::Flush() -{ - for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) { - nsIFontMetrics* fm = mFontMetrics[i]; - // Destroy() will unhook our device context from the fm so that we won't - // waste time in triggering the notification of FontMetricsDeleted() - // in the subsequent release - fm->Destroy(); - NS_RELEASE(fm); - } - - mFontMetrics.Clear(); - - return NS_OK; -} - -NS_IMETHODIMP -DeviceContextImpl::PrepareNativeWidget(nsIWidget *aWidget, void **aOut) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -DeviceContextImpl::ClearCachedSystemFonts() -{ - return NS_OK; -} diff --git a/gfx/src/thebes/Makefile.in b/gfx/src/thebes/Makefile.in index a29bca57526..64d1a904ce2 100644 --- a/gfx/src/thebes/Makefile.in +++ b/gfx/src/thebes/Makefile.in @@ -57,6 +57,7 @@ REQUIRES = xpcom \ string \ thebes \ widget \ + locale \ view \ pref \ unicharutil \ @@ -65,6 +66,10 @@ REQUIRES = xpcom \ qcms \ $(NULL) +ifeq (,$(filter windows,$(MOZ_WIDGET_TOOLKIT))) +REQUIRES += uconv +endif + CPPSRCS = \ nsThebesDeviceContext.cpp \ nsThebesImage.cpp \ diff --git a/gfx/src/thebes/nsThebesDeviceContext.cpp b/gfx/src/thebes/nsThebesDeviceContext.cpp index 6018815eb0f..f3d7eeaf72c 100644 --- a/gfx/src/thebes/nsThebesDeviceContext.cpp +++ b/gfx/src/thebes/nsThebesDeviceContext.cpp @@ -37,12 +37,20 @@ * * ***** END LICENSE BLOCK ***** */ +#include "nsFont.h" +#include "nsGfxCIID.h" +#include "nsIFontMetrics.h" +#include "nsHashtable.h" +#include "nsILanguageAtomService.h" +#include "nsUnicharUtils.h" + #include "nsIServiceManager.h" #include "nsIPrefService.h" #include "nsCRT.h" #include "nsThebesDeviceContext.h" #include "nsThebesRenderingContext.h" +#include "gfxUserFontSet.h" #include "nsIWidget.h" #include "nsIView.h" @@ -114,7 +122,176 @@ static int x11_error_handler (Display *dpy, XErrorEvent *err) { PRLogModuleInfo* gThebesGFXLog = nsnull; #endif -NS_IMPL_ISUPPORTS_INHERITED0(nsThebesDeviceContext, DeviceContextImpl) +class nsFontCache +{ +public: + nsFontCache(); + ~nsFontCache(); + + nsresult Init(nsIDeviceContext* aContext); + nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup, + gfxUserFontSet* aUserFontSet, + nsIFontMetrics*& aMetrics); + + nsresult FontMetricsDeleted(const nsIFontMetrics* aFontMetrics); + nsresult Compact(); + nsresult Flush(); + nsresult CreateFontMetricsInstance(nsIFontMetrics** fm); + +protected: + nsTArray mFontMetrics; + nsIDeviceContext *mContext; // we do not addref this since + // ownership is implied. MMP. +}; + +nsFontCache::nsFontCache() +{ + MOZ_COUNT_CTOR(nsFontCache); + mContext = nsnull; +} + +nsFontCache::~nsFontCache() +{ + MOZ_COUNT_DTOR(nsFontCache); + Flush(); +} + +nsresult +nsFontCache::Init(nsIDeviceContext* aContext) +{ + NS_PRECONDITION(nsnull != aContext, "null ptr"); + // Note: we don't hold a reference to the device context, because it + // holds a reference to us and we don't want circular references + mContext = aContext; + return NS_OK; +} + +nsresult +nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup, + gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics) +{ + // First check our cache + // start from the end, which is where we put the most-recent-used element + + nsIFontMetrics* fm; + PRInt32 n = mFontMetrics.Length() - 1; + for (PRInt32 i = n; i >= 0; --i) { + fm = mFontMetrics[i]; + nsIThebesFontMetrics* tfm = static_cast(fm); + if (fm->Font().Equals(aFont) && tfm->GetUserFontSet() == aUserFontSet) { + nsCOMPtr langGroup; + fm->GetLangGroup(getter_AddRefs(langGroup)); + if (aLangGroup == langGroup.get()) { + if (i != n) { + // promote it to the end of the cache + mFontMetrics.RemoveElementAt(i); + mFontMetrics.AppendElement(fm); + } + tfm->GetThebesFontGroup()->UpdateFontList(); + NS_ADDREF(aMetrics = fm); + return NS_OK; + } + } + } + + // It's not in the cache. Get font metrics and then cache them. + + aMetrics = nsnull; + nsresult rv = CreateFontMetricsInstance(&fm); + if (NS_FAILED(rv)) return rv; + rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet); + if (NS_SUCCEEDED(rv)) { + // the mFontMetrics list has the "head" at the end, because append + // is cheaper than insert + mFontMetrics.AppendElement(fm); + aMetrics = fm; + NS_ADDREF(aMetrics); + return NS_OK; + } + fm->Destroy(); + NS_RELEASE(fm); + + // One reason why Init() fails is because the system is running out of + // resources. e.g., on Win95/98 only a very limited number of GDI + // objects are available. Compact the cache and try again. + + Compact(); + rv = CreateFontMetricsInstance(&fm); + if (NS_FAILED(rv)) return rv; + rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet); + if (NS_SUCCEEDED(rv)) { + mFontMetrics.AppendElement(fm); + aMetrics = fm; + NS_ADDREF(aMetrics); + return NS_OK; + } + fm->Destroy(); + NS_RELEASE(fm); + + // could not setup a new one, send an old one (XXX search a "best + // match"?) + + n = mFontMetrics.Length() - 1; // could have changed in Compact() + if (n >= 0) { + aMetrics = mFontMetrics[n]; + NS_ADDREF(aMetrics); + return NS_OK; + } + + NS_POSTCONDITION(NS_SUCCEEDED(rv), "font metrics should not be null - bug 136248"); + return rv; +} + +nsresult +nsFontCache::CreateFontMetricsInstance(nsIFontMetrics** fm) +{ + static NS_DEFINE_CID(kFontMetricsCID, NS_FONT_METRICS_CID); + return CallCreateInstance(kFontMetricsCID, fm); +} + +nsresult nsFontCache::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics) +{ + mFontMetrics.RemoveElement(aFontMetrics); + return NS_OK; +} + +nsresult nsFontCache::Compact() +{ + // Need to loop backward because the running element can be removed on + // the way + for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) { + nsIFontMetrics* fm = mFontMetrics[i]; + nsIFontMetrics* oldfm = fm; + // Destroy() isn't here because we want our device context to be + // notified + NS_RELEASE(fm); // this will reset fm to nsnull + // if the font is really gone, it would have called back in + // FontMetricsDeleted() and would have removed itself + if (mFontMetrics.IndexOf(oldfm) >= 0) { + // nope, the font is still there, so let's hold onto it too + NS_ADDREF(oldfm); + } + } + return NS_OK; +} + +nsresult nsFontCache::Flush() +{ + for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) { + nsIFontMetrics* fm = mFontMetrics[i]; + // Destroy() will unhook our device context from the fm so that we + // won't waste time in triggering the notification of + // FontMetricsDeleted() in the subsequent release + fm->Destroy(); + NS_RELEASE(fm); + } + + mFontMetrics.Clear(); + + return NS_OK; +} + +NS_IMPL_ISUPPORTS3(nsThebesDeviceContext, nsIDeviceContext, nsIObserver, nsISupportsWeakReference) nsThebesDeviceContext::nsThebesDeviceContext() { @@ -125,6 +302,19 @@ nsThebesDeviceContext::nsThebesDeviceContext() PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("#### Creating DeviceContext %p\n", this)); + mAppUnitsPerDevPixel = nscoord(-1); + mAppUnitsPerInch = nscoord(-1); + mAppUnitsPerDevNotScaledPixel = nscoord(-1); + mPixelScale = 1.0f; + + mFontCache = nsnull; + mWidget = nsnull; + mFontAliasTable = nsnull; + +#ifdef NS_DEBUG + mInitialized = PR_FALSE; +#endif + mDepth = 0; mWidth = 0; mHeight = 0; @@ -136,8 +326,281 @@ nsThebesDeviceContext::nsThebesDeviceContext() #endif } +static PRBool DeleteValue(nsHashKey* aKey, void* aValue, void* closure) +{ + delete ((nsString*)aValue); + return PR_TRUE; +} + nsThebesDeviceContext::~nsThebesDeviceContext() { + nsCOMPtr obs(do_GetService("@mozilla.org/observer-service;1")); + if (obs) + obs->RemoveObserver(this, "memory-pressure"); + + if (nsnull != mFontCache) { + delete mFontCache; + mFontCache = nsnull; + } + + if (nsnull != mFontAliasTable) { + mFontAliasTable->Enumerate(DeleteValue); + delete mFontAliasTable; + } +} + +NS_IMETHODIMP +nsThebesDeviceContext::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aSomeData) +{ + if (mFontCache && !nsCRT::strcmp(aTopic, "memory-pressure")) { + mFontCache->Compact(); + } + return NS_OK; +} + +NS_IMETHODIMP nsThebesDeviceContext::CreateFontCache() +{ + mFontCache = new nsFontCache(); + if (!mFontCache) { + return NS_ERROR_OUT_OF_MEMORY; + } + return mFontCache->Init(this); +} + +NS_IMETHODIMP nsThebesDeviceContext::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics) +{ + if (mFontCache) { + mFontCache->FontMetricsDeleted(aFontMetrics); + } + return NS_OK; +} + +void +nsThebesDeviceContext::GetLocaleLangGroup(void) +{ + if (!mLocaleLangGroup) { + nsCOMPtr langService; + langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID); + if (langService) { + mLocaleLangGroup = langService->GetLocaleLanguageGroup(); + } + if (!mLocaleLangGroup) { + mLocaleLangGroup = do_GetAtom("x-western"); + } + } +} + +NS_IMETHODIMP nsThebesDeviceContext::GetMetricsFor(const nsFont& aFont, + nsIAtom* aLangGroup, gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics) +{ + if (nsnull == mFontCache) { + nsresult rv = CreateFontCache(); + if (NS_FAILED(rv)) { + aMetrics = nsnull; + return rv; + } + // XXX temporary fix for performance problem -- erik + GetLocaleLangGroup(); + } + + // XXX figure out why aLangGroup is NULL sometimes + if (!aLangGroup) { + aLangGroup = mLocaleLangGroup; + } + + return mFontCache->GetMetricsFor(aFont, aLangGroup, aUserFontSet, aMetrics); +} + +NS_IMETHODIMP nsThebesDeviceContext::GetMetricsFor(const nsFont& aFont, + gfxUserFontSet* aUserFontSet, + nsIFontMetrics*& aMetrics) +{ + if (nsnull == mFontCache) { + nsresult rv = CreateFontCache(); + if (NS_FAILED(rv)) { + aMetrics = nsnull; + return rv; + } + // XXX temporary fix for performance problem -- erik + GetLocaleLangGroup(); + } + return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup, aUserFontSet, + aMetrics); +} + +struct FontEnumData { + FontEnumData(nsIDeviceContext* aDC, nsString& aFaceName) + : mDC(aDC), mFaceName(aFaceName) + {} + nsIDeviceContext* mDC; + nsString& mFaceName; +}; + +static PRBool FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData) +{ + FontEnumData* data = (FontEnumData*)aData; + // XXX for now, all generic fonts are presumed to exist + // we may want to actually check if there's an installed conversion + if (aGeneric) { + data->mFaceName = aFamily; + return PR_FALSE; // found one, stop. + } + else { + nsAutoString local; + PRBool aliased; + data->mDC->GetLocalFontName(aFamily, local, aliased); + if (aliased || (NS_SUCCEEDED(data->mDC->CheckFontExistence(local)))) { + data->mFaceName = local; + return PR_FALSE; // found one, stop. + } + } + return PR_TRUE; // didn't exist, continue looking +} + +NS_IMETHODIMP nsThebesDeviceContext::FirstExistingFont(const nsFont& aFont, nsString& aFaceName) +{ + FontEnumData data(this, aFaceName); + if (aFont.EnumerateFamilies(FontEnumCallback, &data)) { + return NS_ERROR_FAILURE; // ran out + } + return NS_OK; +} + +class FontAliasKey: public nsHashKey +{ +public: + FontAliasKey(const nsString& aString) + { mString.Assign(aString); } + + virtual PRUint32 HashCode(void) const; + virtual PRBool Equals(const nsHashKey *aKey) const; + virtual nsHashKey *Clone(void) const; + + nsString mString; +}; + +PRUint32 FontAliasKey::HashCode(void) const +{ + PRUint32 hash = 0; + const PRUnichar* string = mString.get(); + PRUnichar ch; + while ((ch = *string++) != 0) { + // FYI: hash = hash*37 + ch + ch = ToUpperCase(ch); + hash = ((hash << 5) + (hash << 2) + hash) + ch; + } + return hash; +} + +PRBool FontAliasKey::Equals(const nsHashKey *aKey) const +{ + return mString.Equals(((FontAliasKey*)aKey)->mString, nsCaseInsensitiveStringComparator()); +} + +nsHashKey* FontAliasKey::Clone(void) const +{ + return new FontAliasKey(mString); +} + +nsresult nsThebesDeviceContext::CreateFontAliasTable() +{ + nsresult result = NS_OK; + + if (nsnull == mFontAliasTable) { + mFontAliasTable = new nsHashtable(); + if (nsnull != mFontAliasTable) { + + nsAutoString times; times.AssignLiteral("Times"); + nsAutoString timesNewRoman; timesNewRoman.AssignLiteral("Times New Roman"); + nsAutoString timesRoman; timesRoman.AssignLiteral("Times Roman"); + nsAutoString arial; arial.AssignLiteral("Arial"); + nsAutoString helvetica; helvetica.AssignLiteral("Helvetica"); + nsAutoString courier; courier.AssignLiteral("Courier"); + nsAutoString courierNew; courierNew.AssignLiteral("Courier New"); + nsAutoString nullStr; + + AliasFont(times, timesNewRoman, timesRoman, PR_FALSE); + AliasFont(timesRoman, timesNewRoman, times, PR_FALSE); + AliasFont(timesNewRoman, timesRoman, times, PR_FALSE); + AliasFont(arial, helvetica, nullStr, PR_FALSE); + AliasFont(helvetica, arial, nullStr, PR_FALSE); + AliasFont(courier, courierNew, nullStr, PR_TRUE); + AliasFont(courierNew, courier, nullStr, PR_FALSE); + } + else { + result = NS_ERROR_OUT_OF_MEMORY; + } + } + return result; +} + +nsresult nsThebesDeviceContext::AliasFont(const nsString& aFont, + const nsString& aAlias, + const nsString& aAltAlias, + PRBool aForceAlias) +{ + nsresult result = NS_OK; + + if (nsnull != mFontAliasTable) { + if (aForceAlias || NS_FAILED(CheckFontExistence(aFont))) { + if (NS_SUCCEEDED(CheckFontExistence(aAlias))) { + nsString* entry = new nsString(aAlias); + if (nsnull != entry) { + FontAliasKey key(aFont); + mFontAliasTable->Put(&key, entry); + } + else { + result = NS_ERROR_OUT_OF_MEMORY; + } + } + else if (!aAltAlias.IsEmpty() && NS_SUCCEEDED(CheckFontExistence(aAltAlias))) { + nsString* entry = new nsString(aAltAlias); + if (nsnull != entry) { + FontAliasKey key(aFont); + mFontAliasTable->Put(&key, entry); + } + else { + result = NS_ERROR_OUT_OF_MEMORY; + } + } + } + } + else { + result = NS_ERROR_FAILURE; + } + return result; +} + +NS_IMETHODIMP nsThebesDeviceContext::GetLocalFontName(const nsString& aFaceName, + nsString& aLocalName, + PRBool& aAliased) +{ + nsresult result = NS_OK; + + if (nsnull == mFontAliasTable) { + result = CreateFontAliasTable(); + } + + if (nsnull != mFontAliasTable) { + FontAliasKey key(aFaceName); + const nsString* alias = (const nsString*)mFontAliasTable->Get(&key); + if (nsnull != alias) { + aLocalName = *alias; + aAliased = PR_TRUE; + } + else { + aLocalName = aFaceName; + aAliased = PR_FALSE; + } + } + return result; +} + +NS_IMETHODIMP nsThebesDeviceContext::FlushFontCache(void) +{ + if (nsnull != mFontCache) + mFontCache->Flush(); + return NS_OK; } /* static */ void @@ -286,7 +749,16 @@ nsThebesDeviceContext::Init(nsNativeWidget aWidget) SetDPI(); - CommonInit(); +#ifdef NS_DEBUG + NS_ASSERTION(!mInitialized, "device context is initialized twice!"); + mInitialized = PR_TRUE; +#endif + + // register as a memory-pressure observer to free font resources + // in low-memory situations. + nsCOMPtr obs(do_GetService("@mozilla.org/observer-service;1")); + if (obs) + obs->AddObserver(this, "memory-pressure", PR_TRUE); #if defined(MOZ_ENABLE_GTK2) && defined(MOZ_X11) if (getenv ("MOZ_X_SYNC")) { @@ -466,7 +938,6 @@ nsThebesDeviceContext::GetPaletteInfo(nsPaletteInfo& aPaletteInfo) return NS_OK; } - NS_IMETHODIMP nsThebesDeviceContext::ConvertPixel(nscolor aColor, PRUint32 & aPixel) { @@ -553,7 +1024,7 @@ nsThebesDeviceContext::InitForPrinting(nsIDeviceContextSpec *aDevice) NS_IMETHODIMP -nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle, +nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle, PRUnichar* aPrintToFileName) { return NS_OK; @@ -561,9 +1032,9 @@ nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle, NS_IMETHODIMP -nsThebesDeviceContext::BeginDocument(PRUnichar* aTitle, +nsThebesDeviceContext::BeginDocument(PRUnichar* aTitle, PRUnichar* aPrintToFileName, - PRInt32 aStartPage, + PRInt32 aStartPage, PRInt32 aEndPage) { static const PRUnichar kEmpty[] = { '\0' }; @@ -660,7 +1131,7 @@ nsThebesDeviceContext::ComputeClientRectUsingScreen(nsRect* outRect) if (screen) { PRInt32 x, y, width, height; screen->GetAvailRect(&x, &y, &width, &height); - + // convert to device units outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel()); outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel()); @@ -681,20 +1152,18 @@ nsThebesDeviceContext::ComputeFullAreaUsingScreen(nsRect* outRect) if ( screen ) { PRInt32 x, y, width, height; screen->GetRect ( &x, &y, &width, &height ); - + // convert to device units outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel()); outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel()); outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel()); outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel()); - + mWidth = outRect->width; mHeight = outRect->height; } - } - // // FindScreen // diff --git a/gfx/src/thebes/nsThebesDeviceContext.h b/gfx/src/thebes/nsThebesDeviceContext.h index 77b9c650d29..122b2dd9329 100644 --- a/gfx/src/thebes/nsThebesDeviceContext.h +++ b/gfx/src/thebes/nsThebesDeviceContext.h @@ -41,16 +41,20 @@ #define _NS_THEBESDEVICECONTEXT_H_ #include "nsIScreenManager.h" - -#include "nsDeviceContext.h" +#include "nsIDeviceContext.h" +#include "nsIDeviceContextSpec.h" +#include "nsCOMPtr.h" +#include "nsIAtom.h" +#include "nsIObserver.h" +#include "nsIObserverService.h" +#include "nsWeakReference.h" +#include "gfxContext.h" #include "nsRefPtrHashtable.h" #include "nsHashKeys.h" #include "prlog.h" -#include "gfxContext.h" - #ifdef PR_LOGGING extern PRLogModuleInfo* gThebesGFXLog; #endif @@ -61,7 +65,12 @@ extern PRLogModuleInfo* gThebesGFXLog; #include "gfxOS2Surface.h" #endif -class nsThebesDeviceContext : public DeviceContextImpl +class nsHashtable; +class nsFontCache; + +class nsThebesDeviceContext : public nsIDeviceContext, + public nsIObserver, + public nsSupportsWeakReference { public: nsThebesDeviceContext(); @@ -69,16 +78,32 @@ public: static void Shutdown(); - NS_DECL_ISUPPORTS_INHERITED + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER NS_IMETHOD Init(nsNativeWidget aWidget); NS_IMETHOD InitForPrinting(nsIDeviceContextSpec *aDevSpec); NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext); - NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext); NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext); NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext); + NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup, + gfxUserFontSet* aUserFontSet, + nsIFontMetrics*& aMetrics); + NS_IMETHOD GetMetricsFor(const nsFont& aFont, + gfxUserFontSet* aUserFontSet, + nsIFontMetrics*& aMetrics); + + NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName); + + NS_IMETHOD GetLocalFontName(const nsString& aFaceName, nsString& aLocalName, + PRBool& aAliased); + + NS_IMETHOD CreateFontCache(); + NS_IMETHOD FontMetricsDeleted(const nsIFontMetrics* aFontMetrics); + NS_IMETHOD FlushFontCache(void); + NS_IMETHOD SupportsNativeWidgets(PRBool& aSupportsWidgets); NS_IMETHOD PrepareNativeWidget(nsIWidget *aWidget, void **aOut); @@ -93,7 +118,7 @@ public: NS_IMETHOD ConvertPixel(nscolor aColor, PRUint32& aPixel); - NS_IMETHOD GetDeviceSurfaceDimensions(PRInt32& aWidth, PRInt32& aHeight); + NS_IMETHOD GetDeviceSurfaceDimensions(nscoord& aWidth, nscoord& aHeight); NS_IMETHOD GetRect(nsRect& aRect); NS_IMETHOD GetClientRect(nsRect& aRect); @@ -126,6 +151,11 @@ public: #endif protected: + virtual nsresult CreateFontAliasTable(); + nsresult AliasFont(const nsString& aFont, + const nsString& aAlias, const nsString& aAltAlias, + PRBool aForceAlias); + void GetLocaleLangGroup(void); nsresult SetDPI(); void ComputeClientRectUsingScreen(nsRect *outRect); void ComputeFullAreaUsingScreen(nsRect *outRect); @@ -133,7 +163,14 @@ protected: void CalcPrintingSize(); void UpdateScaledAppUnits(); - PRUint32 mDepth; + PRUint32 mDepth; + nsFontCache* mFontCache; + nsCOMPtr mLocaleLangGroup; // XXX temp fix for performance bug - erik + nsHashtable* mFontAliasTable; + nsNativeWidget mWidget; +#ifdef NS_DEBUG + PRBool mInitialized; +#endif private: nsCOMPtr mScreenManager;