Bug 1298484. Use cleartype and convert to grayscale AA for skia windows fonts if cleartype is disabled system wide. r=lsalzman
authorMason Chang <mchang@mozilla.com>
Fri, 02 Sep 2016 15:00:29 -0700
changeset 312572 88222d0a92668a99c47602aa2a0968df4ebe7e98
parent 312571 f52595d3b9f33f3b48efa6f61fa3f5719d94bdc7
child 312573 701075b5e63c16a45fa0b9bbac8001e88ff98454
push id20450
push userryanvm@gmail.com
push dateSat, 03 Sep 2016 15:45:57 +0000
treeherderfx-team@5e1165d6f7ae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1298484
milestone51.0a1
Bug 1298484. Use cleartype and convert to grayscale AA for skia windows fonts if cleartype is disabled system wide. r=lsalzman
gfx/2d/2D.h
gfx/2d/DrawTargetSkia.cpp
gfx/2d/HelpersWinFonts.h
gfx/2d/ScaledFontDWrite.cpp
gfx/2d/ScaledFontDWrite.h
gfx/2d/ScaledFontWin.cpp
gfx/2d/ScaledFontWin.h
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -667,16 +667,17 @@ class ScaledFont : public RefCounted<Sca
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont)
   virtual ~ScaledFont() {}
 
   typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, void *aBaton);
   typedef void (*FontDescriptorOutput)(const uint8_t *aData, uint32_t aLength, Float aFontSize, void *aBaton);
 
   virtual FontType GetType() const = 0;
+  virtual AntialiasMode GetDefaultAAMode() { return AntialiasMode::DEFAULT; }
 
   /** This allows getting a path that describes the outline of a set of glyphs.
    * A target is passed in so that the guarantee is made the returned path
    * can be used with any DrawTarget that has the same backend as the one
    * passed in.
    */
   virtual already_AddRefed<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) = 0;
 
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -1178,32 +1178,40 @@ static bool
 ShouldUseCGToFillGlyphs(const GlyphRenderingOptions* aOptions, const Pattern& aPattern)
 {
   return HasFontSmoothingBackgroundColor(aOptions) &&
           aPattern.GetType() == PatternType::COLOR;
 }
 
 #endif
 
-void
-DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
-                           const GlyphBuffer &aBuffer,
-                           const Pattern &aPattern,
-                           const DrawOptions &aOptions,
-                           const GlyphRenderingOptions *aRenderingOptions)
+static bool
+CanDrawFont(ScaledFont* aFont)
 {
   switch (aFont->GetType()) {
   case FontType::SKIA:
   case FontType::CAIRO:
   case FontType::FONTCONFIG:
   case FontType::MAC:
   case FontType::GDI:
   case FontType::DWRITE:
-    break;
+    return true;
   default:
+    return false;
+  }
+}
+
+void
+DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
+                           const GlyphBuffer &aBuffer,
+                           const Pattern &aPattern,
+                           const DrawOptions &aOptions,
+                           const GlyphRenderingOptions *aRenderingOptions)
+{
+  if (!CanDrawFont(aFont)) {
     return;
   }
 
   MarkChanged();
 
 #ifdef MOZ_WIDGET_COCOA
   if (ShouldUseCGToFillGlyphs(aRenderingOptions, aPattern)) {
     if (FillGlyphsWithCG(aFont, aBuffer, aPattern, aOptions, aRenderingOptions)) {
@@ -1214,35 +1222,42 @@ DrawTargetSkia::FillGlyphs(ScaledFont *a
 
   ScaledFontBase* skiaFont = static_cast<ScaledFontBase*>(aFont);
   SkTypeface* typeface = skiaFont->GetSkTypeface();
   if (!typeface) {
     return;
   }
 
   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
+  AntialiasMode aaMode = aFont->GetDefaultAAMode();
+  if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
+    aaMode = aOptions.mAntialiasMode;
+  }
+  bool aaEnabled = aaMode != AntialiasMode::NONE;
+
+  paint.mPaint.setAntiAlias(aaEnabled);
   paint.mPaint.setTypeface(typeface);
   paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
   paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
 
-  bool shouldLCDRenderText = ShouldLCDRenderText(aFont->GetType(), aOptions.mAntialiasMode);
+  bool shouldLCDRenderText = ShouldLCDRenderText(aFont->GetType(), aaMode);
   paint.mPaint.setLCDRenderText(shouldLCDRenderText);
 
   bool useSubpixelText = true;
 
   switch (aFont->GetType()) {
   case FontType::SKIA:
   case FontType::CAIRO:
   case FontType::FONTCONFIG:
     // SkFontHost_cairo does not support subpixel text positioning,
     // so only enable it for other font hosts.
     useSubpixelText = false;
     break;
   case FontType::MAC:
-    if (aOptions.mAntialiasMode == AntialiasMode::GRAY) {
+    if (aaMode == AntialiasMode::GRAY) {
       // Normally, Skia enables LCD FontSmoothing which creates thicker fonts
       // and also enables subpixel AA. CoreGraphics without font smoothing
       // explicitly creates thinner fonts and grayscale AA.
       // CoreGraphics doesn't support a configuration that produces thicker
       // fonts with grayscale AA as LCD Font Smoothing enables or disables both.
       // However, Skia supports it by enabling font smoothing (producing subpixel AA)
       // and converts it to grayscale AA. Since Skia doesn't support subpixel AA on
       // transparent backgrounds, we still want font smoothing for the thicker fonts,
@@ -1252,24 +1267,25 @@ DrawTargetSkia::FillGlyphs(ScaledFont *a
       // we want to have grayscale AA with no smoothing at all. This means
       // disabling the LCD font smoothing behaviour.
       // To accomplish this we have to explicitly disable hinting,
       // and disable LCDRenderText.
       paint.mPaint.setHinting(SkPaint::kNo_Hinting);
     }
     break;
   case FontType::GDI:
+  {
     if (!shouldLCDRenderText) {
-      // If we have non LCD GDI text, Cairo currently always uses cleartype fonts and
-      // converts them to grayscale. Force Skia to do the same, otherwise we use
-      // GDI fonts with the ANTIALIASED_QUALITY which is generally bolder than
-      // Cleartype fonts.
+      // If we have non LCD GDI text, render the fonts as cleartype and convert them
+      // to grayscale. This seems to be what Chrome and IE are doing on Windows 7.
+      // This also applies if cleartype is disabled system wide.
       paint.mPaint.setFlags(paint.mPaint.getFlags() | SkPaint::kGenA8FromLCD_Flag);
     }
     break;
+  }
   default:
     break;
   }
 
   paint.mPaint.setSubpixelText(useSubpixelText);
 
   std::vector<uint16_t> indices;
   std::vector<SkPoint> offsets;
new file mode 100644
--- /dev/null
+++ b/gfx/2d/HelpersWinFonts.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+namespace mozilla {
+namespace gfx {
+
+// Cleartype can be dynamically enabled/disabled, so we have to check it
+// everytime we want to render some text.
+static BYTE
+GetSystemTextQuality()
+{
+  BOOL font_smoothing;
+  UINT smoothing_type;
+
+  if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
+    return DEFAULT_QUALITY;
+  }
+
+  if (font_smoothing) {
+      if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE,
+                                0, &smoothing_type, 0)) {
+        return DEFAULT_QUALITY;
+      }
+
+      if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) {
+        return CLEARTYPE_QUALITY;
+      }
+
+      return ANTIALIASED_QUALITY;
+  }
+
+  return DEFAULT_QUALITY;
+}
+
+static AntialiasMode
+GetSystemDefaultAAMode()
+{
+  AntialiasMode defaultMode = AntialiasMode::SUBPIXEL;
+
+  switch (GetSystemTextQuality()) {
+  case CLEARTYPE_QUALITY:
+    defaultMode = AntialiasMode::SUBPIXEL;
+    break;
+  case ANTIALIASED_QUALITY:
+    defaultMode = AntialiasMode::GRAY;
+    break;
+  case DEFAULT_QUALITY:
+    defaultMode = AntialiasMode::NONE;
+    break;
+  }
+
+  return defaultMode;
+}
+
+} // namespace gfx
+} // namespace mozilla
--- a/gfx/2d/ScaledFontDWrite.cpp
+++ b/gfx/2d/ScaledFontDWrite.cpp
@@ -17,45 +17,21 @@ using namespace std;
 #endif
 
 #include <vector>
 
 #ifdef USE_CAIRO_SCALED_FONT
 #include "cairo-win32.h"
 #endif
 
+#include "HelpersWinFonts.h"
+
 namespace mozilla {
 namespace gfx {
 
-static BYTE
-GetSystemTextQuality()
-{
-  BOOL font_smoothing;
-  UINT smoothing_type;
-
-  if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
-    return DEFAULT_QUALITY;
-  }
-
-  if (font_smoothing) {
-      if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE,
-                                0, &smoothing_type, 0)) {
-        return DEFAULT_QUALITY;
-      }
-
-      if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) {
-        return CLEARTYPE_QUALITY;
-      }
-
-      return ANTIALIASED_QUALITY;
-  }
-
-  return DEFAULT_QUALITY;
-}
-
 #define GASP_TAG 0x70736167
 #define GASP_DOGRAY 0x2
 
 static inline unsigned short
 readShort(const char *aBuf)
 {
   return (*aBuf << 8) | *(aBuf + 1);
 }
@@ -310,29 +286,17 @@ ScaledFontDWrite::GetFontFileData(FontFi
   stream->ReleaseFileFragment(context);
 
   return true;
 }
 
 AntialiasMode
 ScaledFontDWrite::GetDefaultAAMode()
 {
-  AntialiasMode defaultMode = AntialiasMode::SUBPIXEL;
-
-  switch (GetSystemTextQuality()) {
-  case CLEARTYPE_QUALITY:
-    defaultMode = AntialiasMode::SUBPIXEL;
-    break;
-  case ANTIALIASED_QUALITY:
-    defaultMode = AntialiasMode::GRAY;
-    break;
-  case DEFAULT_QUALITY:
-    defaultMode = AntialiasMode::NONE;
-    break;
-  }
+  AntialiasMode defaultMode = GetSystemDefaultAAMode();
 
   if (defaultMode == AntialiasMode::GRAY) {
     if (!DoGrayscale(mFontFace, mSize)) {
       defaultMode = AntialiasMode::NONE;
     }
   }
   return defaultMode;
 }
--- a/gfx/2d/ScaledFontDWrite.h
+++ b/gfx/2d/ScaledFontDWrite.h
@@ -39,17 +39,17 @@ public:
   virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint);
 
   void CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink *aSink);
 
   virtual void GetGlyphDesignMetrics(const uint16_t* aGlyphIndices, uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics);
 
   virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton);
 
-  virtual AntialiasMode GetDefaultAAMode();
+  virtual AntialiasMode GetDefaultAAMode() override;
 
 #ifdef USE_SKIA
   virtual SkTypeface* GetSkTypeface();
   bool GetFontDataFromSystemFonts(IDWriteFactory* aFactory);
   bool DefaultToArialFont(IDWriteFontCollection* aSystemFonts);
 #endif
 
   // The font and font family are only used with Skia
--- a/gfx/2d/ScaledFontWin.cpp
+++ b/gfx/2d/ScaledFontWin.cpp
@@ -13,16 +13,18 @@
 #ifdef USE_SKIA
 #include "skia/include/ports/SkTypeface_win.h"
 #endif
 
 #ifdef USE_CAIRO_SCALED_FONT
 #include "cairo-win32.h"
 #endif
 
+#include "HelpersWinFonts.h"
+
 namespace mozilla {
 namespace gfx {
 
 ScaledFontWin::ScaledFontWin(LOGFONT* aFont, Float aSize)
   : ScaledFontBase(aSize)
   , mLogFont(*aFont)
 {
 }
@@ -81,16 +83,22 @@ ScaledFontWin::GetFontFileData(FontFileD
 
 bool
 ScaledFontWin::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
 {
   aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), mSize, aBaton);
   return true;
 }
 
+AntialiasMode
+ScaledFontWin::GetDefaultAAMode()
+{
+  return GetSystemDefaultAAMode();
+}
+
 #ifdef USE_SKIA
 SkTypeface* ScaledFontWin::GetSkTypeface()
 {
   if (!mTypeface) {
     mTypeface = SkCreateTypefaceFromLOGFONT(mLogFont);
   }
   return mTypeface;
 }
--- a/gfx/2d/ScaledFontWin.h
+++ b/gfx/2d/ScaledFontWin.h
@@ -17,16 +17,17 @@ public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin)
   ScaledFontWin(LOGFONT* aFont, Float aSize);
 
   virtual FontType GetType() const { return FontType::GDI; }
 
   bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
 
   virtual bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
+  virtual AntialiasMode GetDefaultAAMode() override;
 
 #ifdef USE_SKIA
   virtual SkTypeface* GetSkTypeface();
 #endif
 
 protected:
 #ifdef USE_CAIRO_SCALED_FONT
   cairo_font_face_t* GetCairoFontFace() override;