Bug 1249600. Don't draw text if we can't get an SkTypeface. r=bas a=ritu CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Wed, 01 Jun 2016 17:19:10 -0700
changeset 378951 96437abde2ecbab4f3ac771320c213debde6b43c
parent 378950 d0fe39beef305a4459898df3cb54add2778288af
child 378952 6e2399cf03e2f260740f6a0fc3f1fd0bc53b78ea
push id21011
push usermak77@bonardo.net
push dateThu, 16 Jun 2016 13:40:45 +0000
reviewersbas, ritu
bugs1249600
milestone47.0
Bug 1249600. Don't draw text if we can't get an SkTypeface. r=bas a=ritu CLOSED TREE
gfx/2d/DrawTargetSkia.cpp
gfx/2d/ScaledFontDWrite.cpp
gfx/2d/ScaledFontDWrite.h
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -577,19 +577,23 @@ DrawTargetSkia::FillGlyphs(ScaledFont *a
       aFont->GetType() != FontType::GDI &&
       aFont->GetType() != FontType::DWRITE) {
     return;
   }
 
   MarkChanged();
 
   ScaledFontBase* skiaFont = static_cast<ScaledFontBase*>(aFont);
+  SkTypeface* typeface = skiaFont->GetSkTypeface();
+  if (!typeface) {
+    return;
+  }
 
   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
-  paint.mPaint.setTypeface(skiaFont->GetSkTypeface());
+  paint.mPaint.setTypeface(typeface);
   paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
   paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
 
   bool shouldLCDRenderText = ShouldLCDRenderText(aFont->GetType(), aOptions.mAntialiasMode);
   paint.mPaint.setLCDRenderText(shouldLCDRenderText);
 
   if (aRenderingOptions && aRenderingOptions->GetType() == FontType::CAIRO) {
     const GlyphRenderingOptionsCairo* cairoOptions =
--- a/gfx/2d/ScaledFontDWrite.cpp
+++ b/gfx/2d/ScaledFontDWrite.cpp
@@ -15,16 +15,18 @@
 #endif
 
 #include <vector>
 
 #ifdef USE_CAIRO_SCALED_FONT
 #include "cairo-win32.h"
 #endif
 
+#include "nsDebug.h"
+
 namespace mozilla {
 namespace gfx {
 
 static BYTE
 GetSystemTextQuality()
 {
   BOOL font_smoothing;
   UINT smoothing_type;
@@ -110,50 +112,90 @@ ScaledFontDWrite::GetPathForGlyphs(const
 
   CopyGlyphsToSink(aBuffer, pathBuilderD2D->GetSink());
 
   return pathBuilder->Finish();
 }
 
 
 #ifdef USE_SKIA
+bool
+ScaledFontDWrite::DefaultToArialFont(IDWriteFontCollection* aSystemFonts)
+{
+  // If we can't find the same font face as we're given, fallback to arial
+  static const WCHAR fontFamilyName[] = L"Arial";
+
+  UINT32 fontIndex;
+  BOOL exists;
+  HRESULT hr = aSystemFonts->FindFamilyName(fontFamilyName, &fontIndex, &exists);
+  if (FAILED(hr)) {
+    gfxCriticalNote << "Failed to get backup arial font font from system fonts. Code: " << hexa(hr);
+    return false;
+  }
+
+  hr = aSystemFonts->GetFontFamily(fontIndex, getter_AddRefs(mFontFamily));
+  if (FAILED(hr)) {
+    gfxCriticalNote << "Failed to get font family for arial. Code: " << hexa(hr);
+    return false;
+  }
+
+  hr = mFontFamily->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL,
+                                         DWRITE_FONT_STRETCH_NORMAL,
+                                         DWRITE_FONT_STYLE_NORMAL,
+                                         getter_AddRefs(mFont));
+  if (FAILED(hr)) {
+    gfxCriticalNote << "Failed to get a matching font for arial. Code: " << hexa(hr);
+    return false;
+  }
+
+  return true;
+}
+
 // This can happen if we have mixed backends which create DWrite
 // fonts in a mixed environment. e.g. a cairo content backend
 // but Skia canvas backend.
-void
+bool
 ScaledFontDWrite::GetFontDataFromSystemFonts(IDWriteFactory* aFactory)
 {
   MOZ_ASSERT(mFontFace);
   RefPtr<IDWriteFontCollection> systemFonts;
   HRESULT hr = aFactory->GetSystemFontCollection(getter_AddRefs(systemFonts));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to get system font collection from file data. Code: " << hexa(hr);
-    return;
+    gfxCriticalNote << "Failed to get system font collection from file data. Code: " << hexa(hr);
+    return false;
   }
 
   hr = systemFonts->GetFontFromFontFace(mFontFace, getter_AddRefs(mFont));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to get system font from font face. Code: " << hexa(hr);
-    return;
+    gfxCriticalNote << "Failed to get system font from font face. Code: " << hexa(hr);
+    return DefaultToArialFont(systemFonts);
   }
 
   hr = mFont->GetFontFamily(getter_AddRefs(mFontFamily));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to get font family from font face. Code: " << hexa(hr);
-    return;
+    gfxCriticalNote << "Failed to get font family from font face. Code: " << hexa(hr);
+    return false;
   }
+
+  return true;
 }
 
 SkTypeface*
 ScaledFontDWrite::GetSkTypeface()
 {
   if (!mTypeface) {
     IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
+    if (!factory) {
+      return nullptr;
+    }
+
     if (!mFont || !mFontFamily) {
-      GetFontDataFromSystemFonts(factory);
+      if (!GetFontDataFromSystemFonts(factory)) {
+        return nullptr;
+      }
     }
 
     mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily);
   }
   return mTypeface;
 }
 #endif
 
--- a/gfx/2d/ScaledFontDWrite.h
+++ b/gfx/2d/ScaledFontDWrite.h
@@ -41,17 +41,18 @@ public:
   void CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink *aSink);
 
   virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton);
 
   virtual AntialiasMode GetDefaultAAMode();
 
 #ifdef USE_SKIA
   virtual SkTypeface* GetSkTypeface();
-  void GetFontDataFromSystemFonts(IDWriteFactory* aFactory);
+  bool GetFontDataFromSystemFonts(IDWriteFactory* aFactory);
+  bool DefaultToArialFont(IDWriteFontCollection* aSystemFonts);
 #endif
 
   // The font and font family are only used with Skia
   RefPtr<IDWriteFont> mFont;
   RefPtr<IDWriteFontFamily> mFontFamily;
   RefPtr<IDWriteFontFace> mFontFace;
 
 protected: