From 5be531ab2e5ee6fd248f2a087699c7c52880e54d Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Mon, 8 Nov 2010 11:02:27 +0000 Subject: [PATCH] bug 594865 - fall back to GDI rendering on dwrite font list failure. r=bas a=blocking2.0 --- gfx/thebes/gfxAndroidPlatform.cpp | 7 ++++- gfx/thebes/gfxDWriteFontList.cpp | 8 +++++- gfx/thebes/gfxDWriteFontList.h | 6 ++-- gfx/thebes/gfxFT2FontList.cpp | 4 ++- gfx/thebes/gfxFT2FontList.h | 2 +- gfx/thebes/gfxGDIFontList.cpp | 6 ++-- gfx/thebes/gfxGDIFontList.h | 6 ++-- gfx/thebes/gfxMacPlatformFontList.h | 2 +- gfx/thebes/gfxMacPlatformFontList.mm | 6 ++-- gfx/thebes/gfxPlatform.cpp | 18 ++++++------ gfx/thebes/gfxPlatform.h | 4 ++- gfx/thebes/gfxPlatformFontList.cpp | 6 +++- gfx/thebes/gfxPlatformFontList.h | 13 +++++---- gfx/thebes/gfxPlatformMac.cpp | 7 ++++- gfx/thebes/gfxWindowsPlatform.cpp | 42 ++++++++++++++++++++-------- gfx/thebes/gfxWindowsPlatform.h | 1 + 16 files changed, 93 insertions(+), 45 deletions(-) diff --git a/gfx/thebes/gfxAndroidPlatform.cpp b/gfx/thebes/gfxAndroidPlatform.cpp index 186a80c0d8e..33ec9e9a003 100644 --- a/gfx/thebes/gfxAndroidPlatform.cpp +++ b/gfx/thebes/gfxAndroidPlatform.cpp @@ -270,7 +270,12 @@ gfxAndroidPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& gfxPlatformFontList* gfxAndroidPlatform::CreatePlatformFontList() { - return new gfxFT2FontList(); + gfxPlatformFontList* list = new gfxFT2FontList(); + if (NS_SUCCEEDED(list->InitFontList())) { + return list; + } + gfxPlatformFontList::Shutdown(); + return nsnull; } PRBool diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index 0ebc482768d..f15866d4f9c 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -467,7 +467,7 @@ gfxDWriteFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, return entry; } -void +nsresult gfxDWriteFontList::InitFontList() { HRESULT hr; @@ -486,6 +486,10 @@ gfxDWriteFontList::InitFontList() GetSystemFontCollection(getter_AddRefs(systemFonts)); NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); + if (FAILED(hr)) { + return NS_ERROR_FAILURE; + } + for (UINT32 i = 0; i < systemFonts->GetFontFamilyCount(); i++) { nsRefPtr family; systemFonts->GetFontFamily(i, getter_AddRefs(family)); @@ -543,6 +547,8 @@ gfxDWriteFontList::InitFontList() GetFontSubstitutes(); StartLoader(kDelayBeforeLoadingFonts, kIntervalBetweenLoadingFonts); + + return NS_OK; } static void diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h index 00ecc42ca52..3bd7d8b0a04 100644 --- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -191,6 +191,9 @@ public: return static_cast(sPlatformFontList); } + // initialize font lists + virtual nsresult InitFontList(); + virtual gfxFontEntry* GetDefaultFont(const gfxFontStyle* aStyle, PRBool& aNeedsBold); @@ -210,9 +213,6 @@ public: private: friend class gfxDWriteFontFamily; - // initialize font lists - virtual void InitFontList(); - nsresult GetFontSubstitutes(); /** diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index eaa7d93687d..ac6e113533b 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -235,13 +235,15 @@ gfxFT2FontList::FindFonts() #endif // XP_WIN && ANDROID } -void +nsresult gfxFT2FontList::InitFontList() { // reset font lists gfxPlatformFontList::InitFontList(); FindFonts(); + + return NS_OK; } struct FullFontNameSearch { diff --git a/gfx/thebes/gfxFT2FontList.h b/gfx/thebes/gfxFT2FontList.h index d6c894f9bb8..2cabe44a5b4 100644 --- a/gfx/thebes/gfxFT2FontList.h +++ b/gfx/thebes/gfxFT2FontList.h @@ -65,7 +65,7 @@ public: PRUint32 aLength); protected: - virtual void InitFontList(); + virtual nsresult InitFontList(); void AppendFacesFromFontFile(const PRUnichar *aFileName); void AppendFacesFromFontFile(const char *aFileName); diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp index ac76de01d6b..8a713fcef1e 100644 --- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -638,7 +638,7 @@ gfxGDIFontList::GetFontSubstitutes() return NS_OK; } -void +nsresult gfxGDIFontList::InitFontList() { gfxFontCache *fc = gfxFontCache::GetCache(); @@ -664,8 +664,10 @@ gfxGDIFontList::InitFontList() GetFontSubstitutes(); StartLoader(kDelayBeforeLoadingFonts, kIntervalBetweenLoadingFonts); + + return NS_OK; } - + int CALLBACK gfxGDIFontList::EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe, NEWTEXTMETRICEXW *lpntme, diff --git a/gfx/thebes/gfxGDIFontList.h b/gfx/thebes/gfxGDIFontList.h index 75d526f1440..650686f6dbd 100644 --- a/gfx/thebes/gfxGDIFontList.h +++ b/gfx/thebes/gfxGDIFontList.h @@ -334,6 +334,9 @@ public: return static_cast(sPlatformFontList); } + // initialize font lists + virtual nsresult InitFontList(); + virtual gfxFontEntry* GetDefaultFont(const gfxFontStyle* aStyle, PRBool& aNeedsBold); virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, @@ -352,9 +355,6 @@ private: void InitializeFontEmbeddingProcs(); - // initialize font lists - virtual void InitFontList(); - nsresult GetFontSubstitutes(); static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe, diff --git a/gfx/thebes/gfxMacPlatformFontList.h b/gfx/thebes/gfxMacPlatformFontList.h index 51f91581750..a1cca30efb7 100644 --- a/gfx/thebes/gfxMacPlatformFontList.h +++ b/gfx/thebes/gfxMacPlatformFontList.h @@ -113,7 +113,7 @@ private: gfxMacPlatformFontList(); // initialize font lists - virtual void InitFontList(); + virtual nsresult InitFontList(); // special case font faces treated as font families (set via prefs) void InitSingleFaceList(); diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index dc1800143a6..91b9a0df8d2 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -608,7 +608,7 @@ gfxMacPlatformFontList::gfxMacPlatformFontList() : sFontManager = [NSFontManager sharedFontManager]; } -void +nsresult gfxMacPlatformFontList::InitFontList() { nsAutoreleasePool localPool; @@ -617,7 +617,7 @@ gfxMacPlatformFontList::InitFontList() // need to ignore notifications after adding each font if (mATSGeneration == currentGeneration) - return; + return NS_OK; mATSGeneration = currentGeneration; PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit) updating to generation: %d", mATSGeneration)); @@ -672,6 +672,8 @@ gfxMacPlatformFontList::InitFontList() // start the delayed cmap loader StartLoader(kDelayBeforeLoadingCmaps, kIntervalBetweenLoadingCmaps); + + return NS_OK; } void diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 23725437209..9aaf35297d6 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -256,15 +256,6 @@ gfxPlatform::Init() if (!gPlatform) return NS_ERROR_OUT_OF_MEMORY; - gPlatform->mScreenReferenceSurface = - gPlatform->CreateOffscreenSurface(gfxIntSize(1,1), - gfxASurface::CONTENT_COLOR_ALPHA); - if (!gPlatform->mScreenReferenceSurface) { - NS_ERROR("Could not initialize mScreenReferenceSurface"); - Shutdown(); - return NS_ERROR_OUT_OF_MEMORY; - } - nsresult rv; #if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others @@ -276,6 +267,15 @@ gfxPlatform::Init() } #endif + gPlatform->mScreenReferenceSurface = + gPlatform->CreateOffscreenSurface(gfxIntSize(1,1), + gfxASurface::CONTENT_COLOR_ALPHA); + if (!gPlatform->mScreenReferenceSurface) { + NS_ERROR("Could not initialize mScreenReferenceSurface"); + Shutdown(); + return NS_ERROR_OUT_OF_MEMORY; + } + rv = gfxFontCache::Init(); if (NS_FAILED(rv)) { NS_ERROR("Could not initialize gfxFontCache"); diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 2486b13e103..4adedf0c4af 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -174,7 +174,9 @@ public: virtual nsresult UpdateFontList(); /** - * Create the platform font-list object (gfxPlatformFontList concrete subclass) + * Create the platform font-list object (gfxPlatformFontList concrete subclass). + * This function is responsible to create the appropriate subclass of + * gfxPlatformFontList *and* to call its InitFontList() method. */ virtual gfxPlatformFontList *CreatePlatformFontList() { NS_NOTREACHED("oops, this platform doesn't have a gfxPlatformFontList implementation"); diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index 5dee978a07e..2464204086b 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -138,7 +138,7 @@ gfxPlatformFontList::gfxPlatformFontList(PRBool aNeedFullnamePostscriptNames) } } -void +nsresult gfxPlatformFontList::InitFontList() { mFontFamilies.Clear(); @@ -156,6 +156,10 @@ gfxPlatformFontList::InitFontList() mCodepointsWithNoFonts.reset(); mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls + + sPlatformFontList = this; + + return NS_OK; } void diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index deb0496dd5f..d747b9f7096 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -67,9 +67,10 @@ public: NS_TIME_FUNCTION; NS_ASSERTION(!sPlatformFontList, "What's this doing here?"); - sPlatformFontList = gfxPlatform::GetPlatform()->CreatePlatformFontList(); - if (!sPlatformFontList) return NS_ERROR_OUT_OF_MEMORY; - sPlatformFontList->InitFontList(); + gfxPlatform::GetPlatform()->CreatePlatformFontList(); + if (!sPlatformFontList) { + return NS_ERROR_OUT_OF_MEMORY; + } return NS_OK; } @@ -78,6 +79,9 @@ public: sPlatformFontList = nsnull; } + // initialize font lists + virtual nsresult InitFontList(); + void GetFontList (nsIAtom *aLangGroup, const nsACString& aGenericFamily, nsTArray& aListOfFonts); @@ -140,9 +144,6 @@ protected: nsRefPtr& aFamilyEntry, void* userArg); - // initialize font lists - virtual void InitFontList(); - // separate initialization for reading in name tables, since this is expensive void InitOtherFamilyNames(); diff --git a/gfx/thebes/gfxPlatformMac.cpp b/gfx/thebes/gfxPlatformMac.cpp index 6a0bbe479ad..77e87350109 100644 --- a/gfx/thebes/gfxPlatformMac.cpp +++ b/gfx/thebes/gfxPlatformMac.cpp @@ -71,7 +71,12 @@ gfxPlatformMac::~gfxPlatformMac() gfxPlatformFontList* gfxPlatformMac::CreatePlatformFontList() { - return new gfxMacPlatformFontList(); + gfxPlatformFontList* list = new gfxMacPlatformFontList(); + if (NS_SUCCEEDED(list->InitFontList())) { + return list; + } + gfxPlatformFontList::Shutdown(); + return nsnull; } already_AddRefed diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index a554017ec9f..e9b6ae93cfd 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -201,6 +201,8 @@ gfxWindowsPlatform::gfxWindowsPlatform() mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE; mUseClearTypeAlways = UNINITIALIZED_VALUE; + mUsingGDIFonts = PR_FALSE; + /* * Initialize COM */ @@ -235,8 +237,7 @@ gfxWindowsPlatform::~gfxWindowsPlatform() /* * Uninitialize COM */ - CoUninitialize(); - + CoUninitialize(); } void @@ -301,12 +302,13 @@ gfxWindowsPlatform::UpdateRenderMode() d2dDisabled = PR_FALSE; rv = pref->GetBoolPref("gfx.direct2d.force-enabled", &d2dForceEnabled); if (NS_FAILED(rv)) - d2dDisabled = PR_FALSE; + d2dForceEnabled = PR_FALSE; bool tryD2D = !d2dBlocked || d2dForceEnabled; - // Do not ever try if d2d is explicitly disabled. - if (d2dDisabled) { + // Do not ever try if d2d is explicitly disabled, + // or if we're not using DWrite fonts. + if (d2dDisabled || mUsingGDIFonts) { tryD2D = false; } @@ -406,22 +408,38 @@ gfxWindowsPlatform::VerifyD2DDevice(PRBool aAttemptForce) } #endif } + gfxPlatformFontList* gfxWindowsPlatform::CreatePlatformFontList() { + mUsingGDIFonts = PR_FALSE; + gfxPlatformFontList *pfl; #ifdef MOZ_FT2_FONTS - return new gfxFT2FontList(); + pfl = new gfxFT2FontList(); #else #ifdef CAIRO_HAS_DWRITE_FONT - if (!GetDWriteFactory()) { -#endif - return new gfxGDIFontList(); -#ifdef CAIRO_HAS_DWRITE_FONT - } else { - return new gfxDWriteFontList(); + if (GetDWriteFactory()) { + pfl = new gfxDWriteFontList(); + if (NS_SUCCEEDED(pfl->InitFontList())) { + return pfl; + } + // DWrite font initialization failed! Don't know why this would happen, + // but apparently it can - see bug 594865. + // So we're going to fall back to GDI fonts & rendering. + gfxPlatformFontList::Shutdown(); + SetRenderMode(RENDER_GDI); } #endif + pfl = new gfxGDIFontList(); + mUsingGDIFonts = PR_TRUE; #endif + + if (NS_SUCCEEDED(pfl->InitFontList())) { + return pfl; + } + + gfxPlatformFontList::Shutdown(); + return nsnull; } already_AddRefed diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index f8c646a8d1c..11a3cc70eb8 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -255,6 +255,7 @@ private: void Init(); PRBool mUseDirectWrite; + PRBool mUsingGDIFonts; #ifdef CAIRO_HAS_DWRITE_FONT nsRefPtr mDWriteFactory;