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 id30646
push userryanvm@gmail.com
push dateSat, 03 Sep 2016 15:33:40 +0000
treeherdermozilla-central@1789229965bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1298484
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;