Bug 1376026 - fix plumbing of DWrite parameters for Skia fonts to not depend on gfxPlatform. r=jrmuizel
authorLee Salzman <lsalzman@mozilla.com>
Fri, 30 Jun 2017 14:09:05 -0400
changeset 368649 d5b7263f383d0d822b683138c914926b01c7f5cd
parent 368648 e738e018fe57aa713c5b977c985b8809188ef591
child 368650 d22cfe83584a2c1adc247d0d0999a263fbfa8e03
push id32167
push usercbook@mozilla.com
push dateThu, 13 Jul 2017 14:35:41 +0000
treeherdermozilla-central@d4e6f45db733 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1376026
milestone56.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 1376026 - fix plumbing of DWrite parameters for Skia fonts to not depend on gfxPlatform. r=jrmuizel MozReview-Commit-ID: 5K9201eCSv
gfx/2d/2D.h
gfx/2d/DrawTargetD2D1.cpp
gfx/2d/DrawTargetD2D1.h
gfx/2d/Factory.cpp
gfx/2d/InlineTranslator.cpp
gfx/2d/InlineTranslator.h
gfx/2d/NativeFontResourceDWrite.cpp
gfx/2d/RecordedEvent.h
gfx/2d/RecordedEventImpl.h
gfx/2d/ScaledFontDWrite.cpp
gfx/2d/ScaledFontDWrite.h
gfx/skia/skia/include/ports/SkTypeface_win.h
gfx/skia/skia/src/ports/SkFontHost_win.cpp
gfx/skia/skia/src/ports/SkTypeface_win_dw.cpp
gfx/skia/skia/src/ports/SkTypeface_win_dw.h
gfx/thebes/gfxDWriteCommon.cpp
gfx/thebes/gfxDWriteCommon.h
gfx/thebes/gfxDWriteFontList.cpp
gfx/thebes/gfxDWriteFonts.cpp
gfx/thebes/gfxDWriteFonts.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
layout/printing/PrintTranslator.cpp
layout/printing/PrintTranslator.h
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -1515,22 +1515,23 @@ public:
                                       const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize);
 #endif
 
   /**
    * This creates a NativeFontResource from TrueType data.
    *
    * @param aData Pointer to the data
    * @param aSize Size of the TrueType data
-   * @param aType Type of NativeFontResource that should be created.
+   * @param aBackendType Type of the reference DrawTarget the font should be created for.
+   * @param aFontType Type of NativeFontResource that should be created.
    * @param aFontContext Optional native font context to be used to create the NativeFontResource.
    * @return a NativeFontResource of nullptr if failed.
    */
   static already_AddRefed<NativeFontResource>
-    CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType, void* aFontContext = nullptr);
+    CreateNativeFontResource(uint8_t *aData, uint32_t aSize, BackendType aBackendType, FontType aFontType, void* aFontContext = nullptr);
 
   /**
    * This creates an unscaled font of the given type based on font descriptor
    * data retrieved from ScaledFont::GetFontDescriptor.
    */
   static already_AddRefed<UnscaledFont>
     CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength);
 
@@ -1656,44 +1657,46 @@ public:
 #ifdef WIN32
   static already_AddRefed<DrawTarget> CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat);
 
   /*
    * Attempts to create and install a D2D1 device from the supplied Direct3D11 device.
    * Returns true on success, or false on failure and leaves the D2D1/Direct3D11 devices unset.
    */
   static bool SetDirect3D11Device(ID3D11Device *aDevice);
-  static bool SetDWriteFactory(IDWriteFactory *aFactory);
   static ID3D11Device *GetDirect3D11Device();
   static ID2D1Device *GetD2D1Device();
   static uint32_t GetD2D1DeviceSeq();
   static IDWriteFactory *GetDWriteFactory();
+  static IDWriteFactory* EnsureDWriteFactory();
   static bool SupportsD2D1();
 
-  static already_AddRefed<GlyphRenderingOptions>
-    CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams);
-
   static uint64_t GetD2DVRAMUsageDrawTarget();
   static uint64_t GetD2DVRAMUsageSourceSurface();
   static void D2DCleanup();
 
   static already_AddRefed<ScaledFont>
     CreateScaledFontForDWriteFont(IDWriteFontFace* aFontFace,
                                   const gfxFontStyle* aStyle,
                                   const RefPtr<UnscaledFont>& aUnscaledFont,
                                   Float aSize,
                                   bool aUseEmbeddedBitmap,
-                                  bool aForceGDIMode);
+                                  bool aForceGDIMode,
+                                  IDWriteRenderingParams *aParams,
+                                  Float aGamma,
+                                  Float aContrast);
 
   static void UpdateSystemTextQuality();
 
 private:
   static ID2D1Device *mD2D1Device;
   static ID3D11Device *mD3D11Device;
   static IDWriteFactory *mDWriteFactory;
+  static bool mDWriteFactoryInitialized;
+  static Mutex* mDWriteFactoryLock;
 #endif
 
   static DrawEventRecorder *mRecorder;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -12,32 +12,33 @@
 #include "RadialGradientEffectD2D1.h"
 
 #include "HelpersD2D.h"
 #include "FilterNodeD2D1.h"
 #include "ExtendInputEffectD2D1.h"
 #include "Tools.h"
 #include "nsAppRunner.h"
 
+#include "mozilla/Mutex.h"
+
 using namespace std;
 
 // decltype is not usable for overloaded functions.
 typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
     D2D1_FACTORY_TYPE factoryType,
     REFIID iid,
     CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
     void **factory
 );
 
 namespace mozilla {
 namespace gfx {
 
 uint64_t DrawTargetD2D1::mVRAMUsageDT;
 uint64_t DrawTargetD2D1::mVRAMUsageSS;
-IDWriteFactory *DrawTargetD2D1::mDWriteFactory;
 ID2D1Factory1* DrawTargetD2D1::mFactory = nullptr;
 
 ID2D1Factory1 *D2DFactory1()
 {
   return DrawTargetD2D1::factory();
 }
 
 DrawTargetD2D1::DrawTargetD2D1()
@@ -603,35 +604,26 @@ DrawTargetD2D1::Fill(const Path *aPath,
   FinalizeDrawing(aOptions.mCompositionOp, aPattern);
 }
 
 void
 DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
                            const GlyphBuffer &aBuffer,
                            const Pattern &aPattern,
                            const DrawOptions &aOptions,
-                           const GlyphRenderingOptions *aRenderingOptions)
+                           const GlyphRenderingOptions*)
 {
   if (aFont->GetType() != FontType::DWRITE) {
     gfxDebug() << *this << ": Ignoring drawing call for incompatible font.";
     return;
   }
 
   ScaledFontDWrite *font = static_cast<ScaledFontDWrite*>(aFont);
 
-  IDWriteRenderingParams *params = nullptr;
-  if (aRenderingOptions) {
-    if (aRenderingOptions->GetType() != FontType::DWRITE) {
-      gfxDebug() << *this << ": Ignoring incompatible GlyphRenderingOptions.";
-      // This should never happen.
-      MOZ_ASSERT(false);
-    } else {
-      params = static_cast<const GlyphRenderingOptionsDWrite*>(aRenderingOptions)->mParams;
-    }
-  }
+  IDWriteRenderingParams *params = font->mParams;
 
   AntialiasMode aaMode = font->GetDefaultAAMode();
 
   if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
     aaMode = aOptions.mAntialiasMode;
   }
 
   PrepareForDrawing(aOptions.mCompositionOp, aPattern);
@@ -1251,43 +1243,16 @@ DrawTargetD2D1::factory()
   }
 
   ExtendInputEffectD2D1::Register(mFactory);
   RadialGradientEffectD2D1::Register(mFactory);
 
   return mFactory;
 }
 
-IDWriteFactory*
-DrawTargetD2D1::GetDWriteFactory()
-{
-  if (mDWriteFactory) {
-    return mDWriteFactory;
-  }
-
-  decltype(DWriteCreateFactory)* createDWriteFactory;
-  HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll");
-  createDWriteFactory = (decltype(DWriteCreateFactory)*)
-    GetProcAddress(dwriteModule, "DWriteCreateFactory");
-
-  if (!createDWriteFactory) {
-    gfxWarning() << "Failed to locate DWriteCreateFactory function.";
-    return nullptr;
-  }
-
-  HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
-                                   reinterpret_cast<IUnknown**>(&mDWriteFactory));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create DWrite Factory.";
-  }
-
-  return mDWriteFactory;
-}
-
 void
 DrawTargetD2D1::CleanupD2D()
 {
   if (mFactory) {
     RadialGradientEffectD2D1::Unregister(mFactory);
     ExtendInputEffectD2D1::Unregister(mFactory);
     mFactory->Release();
     mFactory = nullptr;
--- a/gfx/2d/DrawTargetD2D1.h
+++ b/gfx/2d/DrawTargetD2D1.h
@@ -150,17 +150,16 @@ public:
 
   already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface *aSurface, ExtendMode aExtendMode) {
     Matrix mat;
     return GetImageForSurface(aSurface, mat, aExtendMode, nullptr);
   }
 
   static ID2D1Factory1 *factory();
   static void CleanupD2D();
-  static IDWriteFactory *GetDWriteFactory();
 
   operator std::string() const {
     std::stringstream stream;
     stream << "DrawTargetD2D 1.1 (" << this << ")";
     return stream.str();
   }
 
   static uint32_t GetMaxSurfaceSize() {
@@ -289,17 +288,16 @@ private:
   // When a BlendEffect has been drawn to a command list, and that command list is
   // subsequently used -again- as an input to a blend effect for a command list,
   // this causes an infinite recursion inside D2D as it tries to resolve the bounds.
   // If we resolve the current command list before this happens
   // we can avoid the subsequent hang. (See bug 1293586)
   bool mDidComplexBlendWithListInList;
 
   static ID2D1Factory1 *mFactory;
-  static IDWriteFactory *mDWriteFactory;
   // This value is uesed to verify if the DrawTarget is created by a stale device.
   uint32_t mDeviceSeq;
 
   // List of effects we use
   bool EnsureLuminanceEffect();
   RefPtr<ID2D1Effect> mLuminanceEffect;
 };
 
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -40,16 +40,17 @@
 
 #ifdef WIN32
 #include "DrawTargetD2D1.h"
 #include "ScaledFontDWrite.h"
 #include "NativeFontResourceDWrite.h"
 #include <d3d10_1.h>
 #include "HelpersD2D.h"
 #include "HelpersWinFonts.h"
+#include "mozilla/Mutex.h"
 #endif
 
 #include "DrawTargetDual.h"
 #include "DrawTargetTiled.h"
 #include "DrawTargetWrapAndRecord.h"
 #include "DrawTargetRecording.h"
 
 #include "SourceSurfaceRawData.h"
@@ -198,31 +199,37 @@ FT_Library Factory::mFTLibrary = nullptr
 Mutex* Factory::mFTLock = nullptr;
 #endif
 
 #ifdef WIN32
 static uint32_t mDeviceSeq = 0;
 ID3D11Device *Factory::mD3D11Device = nullptr;
 ID2D1Device *Factory::mD2D1Device = nullptr;
 IDWriteFactory *Factory::mDWriteFactory = nullptr;
+bool Factory::mDWriteFactoryInitialized = false;
+Mutex* Factory::mDWriteFactoryLock = nullptr;
 #endif
 
 DrawEventRecorder *Factory::mRecorder;
 
 mozilla::gfx::Config* Factory::sConfig = nullptr;
 
 void
 Factory::Init(const Config& aConfig)
 {
   MOZ_ASSERT(!sConfig);
   sConfig = new Config(aConfig);
 
 #ifdef MOZ_ENABLE_FREETYPE
   mFTLock = new Mutex("Factory::mFTLock");
 #endif
+
+#ifdef WIN32
+  mDWriteFactoryLock = new Mutex("Factory::mDWriteFactoryLock");
+#endif
 }
 
 void
 Factory::ShutDown()
 {
   if (sConfig) {
     delete sConfig->mLogForwarder;
     delete sConfig;
@@ -231,16 +238,23 @@ Factory::ShutDown()
 
 #ifdef MOZ_ENABLE_FREETYPE
   mFTLibrary = nullptr;
   if (mFTLock) {
     delete mFTLock;
     mFTLock = nullptr;
   }
 #endif
+
+#ifdef WIN32
+  if (mDWriteFactoryLock) {
+    delete mDWriteFactoryLock;
+    mDWriteFactoryLock = nullptr;
+  }
+#endif
 }
 
 bool
 Factory::HasSSE2()
 {
 #if defined(__SSE2__) || defined(_M_X64) || \
     (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
   // gcc with -msse2 (default on OSX and x86-64)
@@ -537,48 +551,36 @@ Factory::CreateScaledFontForNativeFont(c
 #endif
   default:
     gfxWarning() << "Invalid native font type specified.";
     return nullptr;
   }
 }
 
 already_AddRefed<NativeFontResource>
-Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType, void* aFontContext)
+Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, BackendType aBackendType, FontType aFontType, void* aFontContext)
 {
-  switch (aType) {
+  switch (aFontType) {
 #ifdef WIN32
   case FontType::DWRITE:
     {
-      return NativeFontResourceDWrite::Create(aData, aSize,
-                                              /* aNeedsCairo = */ false);
+      bool needsCairo = aBackendType == BackendType::CAIRO ||
+                        aBackendType == BackendType::SKIA;
+      return NativeFontResourceDWrite::Create(aData, aSize, needsCairo);
     }
-#endif
-  case FontType::CAIRO:
-#ifdef USE_SKIA
-  case FontType::SKIA:
+  case FontType::GDI:
+    return NativeFontResourceGDI::Create(aData, aSize);
+#elif defined(XP_DARWIN)
+  case FontType::MAC:
+    return NativeFontResourceMac::Create(aData, aSize);
+#elif defined(MOZ_WIDGET_GTK)
+  case FontType::FONTCONFIG:
+    return NativeFontResourceFontconfig::Create(aData, aSize,
+                                                static_cast<FT_Library>(aFontContext));
 #endif
-    {
-#ifdef WIN32
-      if (GetDWriteFactory()) {
-        return NativeFontResourceDWrite::Create(aData, aSize,
-                                                /* aNeedsCairo = */ true);
-      } else {
-        return NativeFontResourceGDI::Create(aData, aSize);
-      }
-#elif defined(XP_DARWIN)
-      return NativeFontResourceMac::Create(aData, aSize);
-#elif defined(MOZ_WIDGET_GTK)
-      return NativeFontResourceFontconfig::Create(aData, aSize,
-                                                  static_cast<FT_Library>(aFontContext));
-#else
-      gfxWarning() << "Unable to create cairo scaled font from truetype data";
-      return nullptr;
-#endif
-    }
   default:
     gfxWarning() << "Unable to create requested font resource from truetype data";
     return nullptr;
   }
 }
 
 already_AddRefed<UnscaledFont>
 Factory::CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength)
@@ -741,23 +743,16 @@ Factory::CreateDrawTargetForD3D11Texture
 
   gfxWarning() << "Failed to create draw target for D3D11 texture.";
 
   // Failed
   return nullptr;
 }
 
 bool
-Factory::SetDWriteFactory(IDWriteFactory *aFactory)
-{
-  mDWriteFactory = aFactory;
-  return true;
-}
-
-bool
 Factory::SetDirect3D11Device(ID3D11Device *aDevice)
 {
   mD3D11Device = aDevice;
 
   if (mD2D1Device) {
     mD2D1Device->Release();
     mD2D1Device = nullptr;
   }
@@ -802,28 +797,53 @@ Factory::GetD2D1DeviceSeq()
 }
 
 IDWriteFactory*
 Factory::GetDWriteFactory()
 {
   return mDWriteFactory;
 }
 
+IDWriteFactory*
+Factory::EnsureDWriteFactory()
+{
+  MOZ_ASSERT(mDWriteFactoryLock);
+  MutexAutoLock lock(*mDWriteFactoryLock);
+
+  if (mDWriteFactoryInitialized) {
+    return mDWriteFactory;
+  }
+
+  mDWriteFactoryInitialized = true;
+
+  HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll");
+  decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
+    GetProcAddress(dwriteModule, "DWriteCreateFactory");
+
+  if (!createDWriteFactory) {
+    gfxWarning() << "Failed to locate DWriteCreateFactory function.";
+    return nullptr;
+  }
+
+  HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
+                                   reinterpret_cast<IUnknown**>(&mDWriteFactory));
+
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to create DWrite Factory.";
+  }
+
+  return mDWriteFactory;
+}
+
 bool
 Factory::SupportsD2D1()
 {
   return !!D2DFactory1();
 }
 
-already_AddRefed<GlyphRenderingOptions>
-Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams)
-{
-  return MakeAndAddRef<GlyphRenderingOptionsDWrite>(aParams);
-}
-
 BYTE sSystemTextQuality = CLEARTYPE_QUALITY;
 void
 Factory::UpdateSystemTextQuality()
 {
 #ifdef WIN32
   gfx::UpdateSystemTextQuality();
 #endif
 }
@@ -851,20 +871,24 @@ Factory::D2DCleanup()
 }
 
 already_AddRefed<ScaledFont>
 Factory::CreateScaledFontForDWriteFont(IDWriteFontFace* aFontFace,
                                        const gfxFontStyle* aStyle,
                                        const RefPtr<UnscaledFont>& aUnscaledFont,
                                        float aSize,
                                        bool aUseEmbeddedBitmap,
-                                       bool aForceGDIMode)
+                                       bool aForceGDIMode,
+                                       IDWriteRenderingParams* aParams,
+                                       Float aGamma,
+                                       Float aContrast)
 {
   return MakeAndAddRef<ScaledFontDWrite>(aFontFace, aUnscaledFont, aSize,
                                          aUseEmbeddedBitmap, aForceGDIMode,
+                                         aParams, aGamma, aContrast,
                                          aStyle);
 }
 
 #endif // XP_WIN
 
 #ifdef USE_SKIA_GPU
 already_AddRefed<DrawTarget>
 Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext,
--- a/gfx/2d/InlineTranslator.cpp
+++ b/gfx/2d/InlineTranslator.cpp
@@ -97,25 +97,10 @@ InlineTranslator::CreateDrawTarget(Refer
                                   const gfx::IntSize &aSize,
                                   gfx::SurfaceFormat aFormat)
 {
   RefPtr<DrawTarget> drawTarget = mBaseDT;
   AddDrawTarget(aRefPtr, drawTarget);
   return drawTarget.forget();
 }
 
-FontType
-InlineTranslator::GetDesiredFontType()
-{
-  switch (mBaseDT->GetBackendType()) {
-    case BackendType::DIRECT2D:
-      return FontType::DWRITE;
-    case BackendType::CAIRO:
-      return FontType::CAIRO;
-    case BackendType::SKIA:
-      return FontType::SKIA;
-    default:
-      return FontType::CAIRO;
-  }
-}
-
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/2d/InlineTranslator.h
+++ b/gfx/2d/InlineTranslator.h
@@ -168,18 +168,16 @@ public:
 
 
   already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
                                                 const gfx::IntSize &aSize,
                                                 gfx::SurfaceFormat aFormat) final;
 
   mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
 
-  mozilla::gfx::FontType GetDesiredFontType() final;
-
   void* GetFontContext() final { return mFontContext; }
 
 private:
   RefPtr<DrawTarget> mBaseDT;
   void*              mFontContext;
 
   nsRefPtrHashtable<nsPtrHashKey<void>, DrawTarget> mDrawTargets;
   nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
--- a/gfx/2d/NativeFontResourceDWrite.cpp
+++ b/gfx/2d/NativeFontResourceDWrite.cpp
@@ -4,17 +4,16 @@
  * 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/. */
 
 #include "NativeFontResourceDWrite.h"
 #include "UnscaledFontDWrite.h"
 
 #include <unordered_map>
 
-#include "DrawTargetD2D1.h"
 #include "Logging.h"
 #include "mozilla/RefPtr.h"
 
 namespace mozilla {
 namespace gfx {
 
 static Atomic<uint64_t> sNextFontFileKey;
 static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
@@ -65,17 +64,17 @@ public:
     * loader, the key must be a uint64_t that has been generated by incrementing
     * sNextFontFileKey.
     * Also note that this is _not_ threadsafe.
     */
   static IDWriteFontFileLoader* Instance()
   {
     if (!mInstance) {
       mInstance = new DWriteFontFileLoader();
-      DrawTargetD2D1::GetDWriteFactory()->
+      Factory::GetDWriteFactory()->
           RegisterFontFileLoader(mInstance);
     }
     return mInstance;
   }
 
 private:
   static IDWriteFontFileLoader* mInstance;
 };
@@ -217,17 +216,17 @@ DWriteFontFileStream::ReleaseFileFragmen
 {
 }
 
 /* static */
 already_AddRefed<NativeFontResourceDWrite>
 NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength,
                                  bool aNeedsCairo)
 {
-  IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
+  IDWriteFactory *factory = Factory::EnsureDWriteFactory();
   if (!factory) {
     gfxWarning() << "Failed to get DWrite Factory.";
     return nullptr;
   }
 
   uint64_t fontFileKey = sNextFontFileKey++;
   RefPtr<IDWriteFontFileStream> ffsRef =
     new DWriteFontFileStream(aFontData, aDataLength, fontFileKey);
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -19,17 +19,17 @@ struct PathOp;
 class PathRecording;
 
 const uint32_t kMagicInt = 0xc001feed;
 
 // A change in major revision means a change in event binary format, causing
 // loss of backwards compatibility. Old streams will not work in a player
 // using a newer major revision. And new streams will not work in a player
 // using an older major revision.
-const uint16_t kMajorRevision = 9;
+const uint16_t kMajorRevision = 10;
 // A change in minor revision means additions of new events. New streams will
 // not play in older players.
 const uint16_t kMinorRevision = 0;
 
 struct ReferencePtr
 {
   ReferencePtr()
     : mLongPtr(0)
@@ -106,17 +106,16 @@ public:
   virtual void RemoveUnscaledFont(ReferencePtr aRefPtr) = 0;
   virtual void AddNativeFontResource(uint64_t aKey,
                                      NativeFontResource *aNativeFontResource) = 0;
 
   virtual already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
                                                         const IntSize &aSize,
                                                         SurfaceFormat aFormat);
   virtual DrawTarget *GetReferenceDrawTarget() = 0;
-  virtual FontType GetDesiredFontType() = 0;
   virtual void* GetFontContext() { return nullptr; }
 };
 
 struct ColorPatternStorage
 {
   Color mColor;
 };
 
--- a/gfx/2d/RecordedEventImpl.h
+++ b/gfx/2d/RecordedEventImpl.h
@@ -872,17 +872,19 @@ public:
   static void FontDataProc(const uint8_t *aData, uint32_t aSize,
                            uint32_t aIndex, void* aBaton)
   {
     auto recordedFontData = static_cast<RecordedFontData*>(aBaton);
     recordedFontData->SetFontData(aData, aSize, aIndex);
   }
 
   explicit RecordedFontData(UnscaledFont *aUnscaledFont)
-    : RecordedEventDerived(FONTDATA), mData(nullptr)
+    : RecordedEventDerived(FONTDATA)
+    , mType(aUnscaledFont->GetType())
+    , mData(nullptr)
   {
     mGetFontFileDataSucceeded = aUnscaledFont->GetFontFileData(&FontDataProc, this);
   }
 
   ~RecordedFontData();
 
   bool IsValid() const { return mGetFontFileDataSucceeded; }
 
@@ -896,16 +898,17 @@ public:
 
   void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex);
 
   bool GetFontDetails(RecordedFontDetails& fontDetails);
 
 private:
   friend class RecordedEvent;
 
+  FontType mType;
   uint8_t* mData;
   RecordedFontDetails mFontDetails;
 
   bool mGetFontFileDataSucceeded;
 
   template<class S>
   MOZ_IMPLICIT RecordedFontData(S &aStream);
 };
@@ -2678,32 +2681,33 @@ RecordedFontData::~RecordedFontData()
   delete[] mData;
 }
 
 inline bool
 RecordedFontData::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<NativeFontResource> fontResource =
     Factory::CreateNativeFontResource(mData, mFontDetails.size,
-                                      aTranslator->GetDesiredFontType(),
-                                      aTranslator->GetFontContext());
+                                      aTranslator->GetReferenceDrawTarget()->GetBackendType(),
+                                      mType, aTranslator->GetFontContext());
   if (!fontResource) {
     return false;
   }
 
   aTranslator->AddNativeFontResource(mFontDetails.fontDataKey, fontResource);
   return true;
 }
 
 template<class S>
 void
 RecordedFontData::Record(S &aStream) const
 {
   MOZ_ASSERT(mGetFontFileDataSucceeded);
 
+  WriteElement(aStream, mType);
   WriteElement(aStream, mFontDetails.fontDataKey);
   WriteElement(aStream, mFontDetails.size);
   aStream.write((const char*)mData, mFontDetails.size);
 }
 
 inline void
 RecordedFontData::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
@@ -2732,18 +2736,20 @@ RecordedFontData::GetFontDetails(Recorde
   fontDetails.size = mFontDetails.size;
   fontDetails.index = mFontDetails.index;
   return true;
 }
 
 template<class S>
 RecordedFontData::RecordedFontData(S &aStream)
   : RecordedEventDerived(FONTDATA)
+  , mType(FontType::SKIA)
   , mData(nullptr)
 {
+  ReadElement(aStream, mType);
   ReadElement(aStream, mFontDetails.fontDataKey);
   ReadElement(aStream, mFontDetails.size);
   mData = new uint8_t[mFontDetails.size];
   aStream.read((char*)mData, mFontDetails.size);
 }
 
 inline
 RecordedFontDescriptor::~RecordedFontDescriptor()
--- a/gfx/2d/ScaledFontDWrite.cpp
+++ b/gfx/2d/ScaledFontDWrite.cpp
@@ -1,18 +1,18 @@
 /* -*- 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/. */
 
-#include "DrawTargetD2D1.h"
 #include "ScaledFontDWrite.h"
 #include "UnscaledFontDWrite.h"
 #include "PathD2D.h"
 #include "gfxFont.h"
+#include "Logging.h"
 
 using namespace std;
 
 #ifdef USE_SKIA
 #include "PathSkia.h"
 #include "skia/include/core/SkPaint.h"
 #include "skia/include/core/SkPath.h"
 #include "skia/include/ports/SkTypeface_win.h"
@@ -103,26 +103,34 @@ DWriteFontStretchFromStretch(int16_t aSt
     }
 }
 
 ScaledFontDWrite::ScaledFontDWrite(IDWriteFontFace *aFontFace,
                                    const RefPtr<UnscaledFont>& aUnscaledFont,
                                    Float aSize,
                                    bool aUseEmbeddedBitmap,
                                    bool aForceGDIMode,
+                                   IDWriteRenderingParams* aParams,
+                                   Float aGamma,
+                                   Float aContrast,
                                    const gfxFontStyle* aStyle)
     : ScaledFontBase(aUnscaledFont, aSize)
     , mFontFace(aFontFace)
     , mUseEmbeddedBitmap(aUseEmbeddedBitmap)
     , mForceGDIMode(aForceGDIMode)
+    , mParams(aParams)
+    , mGamma(aGamma)
+    , mContrast(aContrast)
 {
-  mStyle = SkFontStyle(aStyle->weight,
-                       DWriteFontStretchFromStretch(aStyle->stretch),
-                       aStyle->style == NS_FONT_STYLE_NORMAL ?
-                       SkFontStyle::kUpright_Slant : SkFontStyle::kItalic_Slant);
+  if (aStyle) {
+    mStyle = SkFontStyle(aStyle->weight,
+                         DWriteFontStretchFromStretch(aStyle->stretch),
+                         aStyle->style == NS_FONT_STYLE_NORMAL ?
+                         SkFontStyle::kUpright_Slant : SkFontStyle::kItalic_Slant);
+  }
 }
 
 already_AddRefed<Path>
 ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget)
 {
   if (aTarget->GetBackendType() != BackendType::DIRECT2D && aTarget->GetBackendType() != BackendType::DIRECT2D1_1) {
     return ScaledFontBase::GetPathForGlyphs(aBuffer, aTarget);
   }
@@ -138,22 +146,22 @@ ScaledFontDWrite::GetPathForGlyphs(const
 }
 
 
 #ifdef USE_SKIA
 SkTypeface*
 ScaledFontDWrite::GetSkTypeface()
 {
   if (!mTypeface) {
-    IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
+    IDWriteFactory *factory = Factory::GetDWriteFactory();
     if (!factory) {
       return nullptr;
     }
 
-    mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mStyle, mForceGDIMode);
+    mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mStyle, mForceGDIMode, mGamma, mContrast);
   }
   return mTypeface;
 }
 #endif
 
 void
 ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, const Matrix *aTransformHint)
 {
@@ -267,22 +275,44 @@ UnscaledFontDWrite::GetFontFileData(Font
 
   aDataCallback((uint8_t*)fragmentStart, fileSize, mFontFace->GetIndex(), aBaton);
 
   stream->ReleaseFileFragment(context);
 
   return true;
 }
 
+bool
+ScaledFontDWrite::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton)
+{
+  InstanceData instance(this);
+  aCb(reinterpret_cast<uint8_t*>(&instance), sizeof(instance), aBaton);
+  return true;
+}
+
 already_AddRefed<ScaledFont>
 UnscaledFontDWrite::CreateScaledFont(Float aGlyphSize,
                                      const uint8_t* aInstanceData,
                                      uint32_t aInstanceDataLength)
 {
-  RefPtr<ScaledFontBase> scaledFont = new ScaledFontDWrite(mFontFace, this, aGlyphSize);
+  if (aInstanceDataLength < sizeof(ScaledFontDWrite::InstanceData)) {
+    gfxWarning() << "DWrite scaled font instance data is truncated.";
+    return nullptr;
+  }
+
+  const ScaledFontDWrite::InstanceData *instanceData =
+    reinterpret_cast<const ScaledFontDWrite::InstanceData*>(aInstanceData);
+  RefPtr<ScaledFontBase> scaledFont =
+    new ScaledFontDWrite(mFontFace, this, aGlyphSize,
+                         instanceData->mUseEmbeddedBitmap,
+                         instanceData->mForceGDIMode,
+                         nullptr,
+                         instanceData->mGamma,
+                         instanceData->mContrast);
+
   if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) {
     gfxWarning() << "Unable to create cairo scaled font DWrite font.";
     return nullptr;
   }
 
   return scaledFont.forget();
 }
 
--- a/gfx/2d/ScaledFontDWrite.h
+++ b/gfx/2d/ScaledFontDWrite.h
@@ -10,81 +10,101 @@
 #include "ScaledFontBase.h"
 
 struct ID2D1GeometrySink;
 struct gfxFontStyle;
 
 namespace mozilla {
 namespace gfx {
 
+class NativeFontResourceDWrite;
+class UnscaledFontDWrite;
+
 class ScaledFontDWrite final : public ScaledFontBase
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDWrite, override)
   ScaledFontDWrite(IDWriteFontFace *aFont,
                    const RefPtr<UnscaledFont>& aUnscaledFont,
                    Float aSize)
     : ScaledFontBase(aUnscaledFont, aSize)
     , mFontFace(aFont)
     , mUseEmbeddedBitmap(false)
     , mForceGDIMode(false)
+    , mGamma(2.2f)
+    , mContrast(1.0f)
   {}
 
   ScaledFontDWrite(IDWriteFontFace *aFontFace,
                    const RefPtr<UnscaledFont>& aUnscaledFont,
                    Float aSize,
                    bool aUseEmbeddedBitmap,
                    bool aForceGDIMode,
-                   const gfxFontStyle* aStyle);
+                   IDWriteRenderingParams *aParams,
+                   Float aContrast,
+                   Float aGamma,
+                   const gfxFontStyle* aStyle = nullptr);
 
   FontType GetType() const override { return FontType::DWRITE; }
 
   already_AddRefed<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) override;
   void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, const Matrix *aTransformHint) override;
 
   void CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink *aSink);
 
   void GetGlyphDesignMetrics(const uint16_t* aGlyphIndices, uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics) override;
 
   bool CanSerialize() override { return true; }
 
+  bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override;
+
   AntialiasMode GetDefaultAAMode() override;
 
   bool UseEmbeddedBitmaps() { return mUseEmbeddedBitmap; }
   bool ForceGDIMode() { return mForceGDIMode; }
 
 #ifdef USE_SKIA
   SkTypeface* GetSkTypeface() override;
   SkFontStyle mStyle;
 #endif
 
   RefPtr<IDWriteFontFace> mFontFace;
   bool mUseEmbeddedBitmap;
   bool mForceGDIMode;
+  // DrawTargetD2D1 requires the IDWriteRenderingParams,
+  // but we also separately need to store the gamma and contrast
+  // since Skia needs to be able to access these without having
+  // to use the full set of DWrite parameters (which would be
+  // required to recreate an IDWriteRenderingParams) in a
+  // DrawTargetRecording playback.
+  RefPtr<IDWriteRenderingParams> mParams;
+  Float mGamma;
+  Float mContrast;
 
 protected:
 #ifdef USE_CAIRO_SCALED_FONT
   cairo_font_face_t* GetCairoFontFace() override;
 #endif
-};
-
-class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions
-{
-public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsDWrite, override)
-  explicit GlyphRenderingOptionsDWrite(IDWriteRenderingParams *aParams)
-    : mParams(aParams)
-  {
-  }
-
-  FontType GetType() const override { return FontType::DWRITE; }
 
 private:
-  friend class DrawTargetD2D;
-  friend class DrawTargetD2D1;
+  friend class NativeFontResourceDWrite;
+  friend class UnscaledFontDWrite;
 
-  RefPtr<IDWriteRenderingParams> mParams;
+  struct InstanceData
+  {
+    explicit InstanceData(ScaledFontDWrite* aScaledFont)
+      : mUseEmbeddedBitmap(aScaledFont->mUseEmbeddedBitmap)
+      , mForceGDIMode(aScaledFont->mForceGDIMode)
+      , mGamma(aScaledFont->mGamma)
+      , mContrast(aScaledFont->mContrast)
+    {}
+
+    bool mUseEmbeddedBitmap;
+    bool mForceGDIMode;
+    Float mGamma;
+    Float mContrast;
+  };
 };
 
 }
 }
 
 #endif /* MOZILLA_GFX_SCALEDFONTDWRITE_H_ */
--- a/gfx/skia/skia/include/ports/SkTypeface_win.h
+++ b/gfx/skia/skia/include/ports/SkTypeface_win.h
@@ -48,17 +48,19 @@ struct IDWriteFontFallback;
 /**
  *  Like the other Typeface create methods, this returns a new reference to the
  *  corresponding typeface for the specified dwrite font. The caller is responsible
  *  for calling unref() when it is finished.
  */
 SK_API SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFactory* aFactory,
                                                   IDWriteFontFace* aFontFace,
                                                   SkFontStyle aStyle,
-                                                  bool aForceGDI);
+                                                  bool aForceGDI,
+                                                  float aGamma,
+                                                  float aContrast);
 
 SK_API sk_sp<SkFontMgr> SkFontMgr_New_GDI();
 SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory = NULL,
                                                   IDWriteFontCollection* collection = NULL);
 SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory,
                                                   IDWriteFontCollection* collection,
                                                   IDWriteFontFallback* fallback);
 
--- a/gfx/skia/skia/src/ports/SkFontHost_win.cpp
+++ b/gfx/skia/skia/src/ports/SkFontHost_win.cpp
@@ -336,19 +336,21 @@ SkTypeface* SkCreateTypefaceFromLOGFONT(
 
 /***
  * This guy is public.
  */
 
 SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFactory* aFactory,
                                            IDWriteFontFace* aFontFace,
                                            SkFontStyle aStyle,
-                                           bool aForceGDI)
+                                           bool aForceGDI,
+                                           float aGamma,
+                                           float aContrast)
 {
-  return DWriteFontTypeface::Create(aFactory, aFontFace, aStyle, aForceGDI);
+  return DWriteFontTypeface::Create(aFactory, aFontFace, aStyle, aForceGDI, aGamma, aContrast);
 }
 
 /**
  *  The created SkTypeface takes ownership of fontMemResource.
  */
 SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HANDLE fontMemResource) {
     LOGFONT lf = origLF;
     make_canonical(&lf);
--- a/gfx/skia/skia/src/ports/SkTypeface_win_dw.cpp
+++ b/gfx/skia/skia/src/ports/SkTypeface_win_dw.cpp
@@ -246,20 +246,16 @@ SkStreamAsset* DWriteFontTypeface::onOpe
     return new SkDWriteFontFileStream(fontFileStream.get());
 }
 
 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
                                                            const SkDescriptor* desc) const {
     return new SkScalerContext_DW(sk_ref_sp(const_cast<DWriteFontTypeface*>(this)), effects, desc);
 }
 
-#ifdef MOZ_SKIA
-IDWriteRenderingParams* GetDwriteRenderingParams(bool aGDI);
-#endif
-
 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
     if (rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) {
         rec->fMaskFormat = SkMask::kA8_Format;
         rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag;
     }
 
     unsigned flagsWeDontSupport = SkScalerContext::kVertical_Flag |
                                   SkScalerContext::kDevKernText_Flag |
@@ -283,23 +279,21 @@ void DWriteFontTypeface::onFilterRec(SkS
             float gamma = defaultRenderingParams->GetGamma();
             rec->setDeviceGamma(gamma);
             rec->setPaintGamma(gamma);
 
             rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
         }
     }
 #elif defined(MOZ_SKIA)
-    IDWriteRenderingParams* params = GetDwriteRenderingParams(ForceGDI());
-    SkASSERT(params);
-    rec->setContrast(params->GetEnhancedContrast());
+    rec->setContrast(fContrast);
 
     // GDI gamma should be 2.3
     // See the LUT gamma values comment for GDI fonts.
-    float gamma = ForceGDI() ? 2.3f : params->GetGamma();
+    float gamma = ForceGDI() ? 2.3f : fGamma;
     rec->setDeviceGamma(gamma);
     rec->setPaintGamma(gamma);
 #endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 //PDF Support
 
--- a/gfx/skia/skia/src/ports/SkTypeface_win_dw.h
+++ b/gfx/skia/skia/src/ports/SkTypeface_win_dw.h
@@ -48,16 +48,18 @@ private:
         : SkTypeface(style, false)
         , fFactory(SkRefComPtr(factory))
         , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
         , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
         , fDWriteFontFamily(SkSafeRefComPtr(fontFamily))
         , fDWriteFont(SkSafeRefComPtr(font))
         , fDWriteFontFace(SkRefComPtr(fontFace))
         , fForceGDI(false)
+        , fGamma(2.2f)
+        , fContrast(1.0f)
     {
         if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace1))) {
             // IUnknown::QueryInterface states that if it fails, punk will be set to nullptr.
             // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
             SkASSERT_RELEASE(nullptr == fDWriteFontFace1.get());
         }
         if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace2))) {
             SkASSERT_RELEASE(nullptr == fDWriteFontFace2.get());
@@ -76,22 +78,26 @@ public:
     SkTScopedComPtr<IDWriteFont> fDWriteFont;
     SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
     SkTScopedComPtr<IDWriteFontFace1> fDWriteFontFace1;
     SkTScopedComPtr<IDWriteFontFace2> fDWriteFontFace2;
 
     static DWriteFontTypeface* Create(IDWriteFactory* factory,
                                       IDWriteFontFace* fontFace,
                                       SkFontStyle aStyle,
-                                      bool aForceGDI) {
+                                      bool aForceGDI,
+                                      float aGamma,
+                                      float aContrast) {
         DWriteFontTypeface* typeface =
                 new DWriteFontTypeface(aStyle, factory, fontFace,
                                        nullptr, nullptr,
                                        nullptr, nullptr);
         typeface->fForceGDI = aForceGDI;
+        typeface->fGamma = aGamma;
+        typeface->fContrast = aContrast;
         return typeface;
     }
 
     static DWriteFontTypeface* Create(IDWriteFactory* factory,
                                       IDWriteFontFace* fontFace,
                                       IDWriteFont* font,
                                       IDWriteFontFamily* fontFamily,
                                       IDWriteFontFileLoader* fontFileLoader = nullptr,
@@ -134,11 +140,13 @@ protected:
         return -1;
     }
     int onGetTableTags(SkFontTableTag tags[]) const override;
     size_t onGetTableData(SkFontTableTag, size_t offset, size_t length, void* data) const override;
 
 private:
     typedef SkTypeface INHERITED;
     bool fForceGDI;
+    float fGamma;
+    float fContrast;
 };
 
 #endif
--- a/gfx/thebes/gfxDWriteCommon.cpp
+++ b/gfx/thebes/gfxDWriteCommon.cpp
@@ -153,17 +153,17 @@ gfxDWriteFontFileLoader::CreateStreamFro
 HRESULT
 gfxDWriteFontFileLoader::CreateCustomFontFile(FallibleTArray<uint8_t>& aFontData,
                                               IDWriteFontFile** aFontFile,
                                               IDWriteFontFileStream** aFontFileStream)
 {
   MOZ_ASSERT(aFontFile);
   MOZ_ASSERT(aFontFileStream);
 
-  IDWriteFactory *factory = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
+  IDWriteFactory *factory = mozilla::gfx::Factory::GetDWriteFactory();
   if (!factory) {
     gfxCriticalError() << "Failed to get DWrite Factory in CreateCustomFontFile.";
     return E_FAIL;
   }
 
   uint64_t fontFileKey = sNextFontFileKey++;
   RefPtr<IDWriteFontFileStream> ffsRef = new gfxDWriteFontFileStream(&aFontData, fontFileKey);
   sFontFileStreams[fontFileKey] = ffsRef;
--- a/gfx/thebes/gfxDWriteCommon.h
+++ b/gfx/thebes/gfxDWriteCommon.h
@@ -122,17 +122,17 @@ public:
     /**
      * Gets the singleton loader instance. Note that when using this font
      * loader, the key must be a pointer to a unint64_t.
      */
     static IDWriteFontFileLoader* Instance()
     {
         if (!mInstance) {
             mInstance = new gfxDWriteFontFileLoader();
-            gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
+            mozilla::gfx::Factory::GetDWriteFactory()->
                 RegisterFontFileLoader(mInstance);
         }
         return mInstance;
     }
 
     /**
      * Creates a IDWriteFontFile and IDWriteFontFileStream from aFontData.
      * aFontData will be empty on return as it swaps out the data.
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -608,17 +608,17 @@ gfxDWriteFontEntry::CreateFontFace(IDWri
 {
     // initialize mFontFace if this hasn't been done before
     if (!mFontFace) {
         HRESULT hr;
         if (mFont) {
             hr = mFont->CreateFontFace(getter_AddRefs(mFontFace));
         } else if (mFontFile) {
             IDWriteFontFile *fontFile = mFontFile.get();
-            hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
+            hr = Factory::GetDWriteFactory()->
                 CreateFontFace(mFaceType,
                                1,
                                &fontFile,
                                0,
                                DWRITE_FONT_SIMULATIONS_NONE,
                                getter_AddRefs(mFontFace));
         } else {
             NS_NOTREACHED("invalid font entry");
@@ -639,17 +639,17 @@ gfxDWriteFontEntry::CreateFontFace(IDWri
         if (FAILED(mFontFace->GetFiles(&numberOfFiles, nullptr))) {
             return NS_ERROR_FAILURE;
         }
         AutoTArray<IDWriteFontFile*,1> files;
         files.AppendElements(numberOfFiles);
         if (FAILED(mFontFace->GetFiles(&numberOfFiles, files.Elements()))) {
             return NS_ERROR_FAILURE;
         }
-        HRESULT hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
+        HRESULT hr = Factory::GetDWriteFactory()->
             CreateFontFace(mFontFace->GetType(),
                            numberOfFiles,
                            files.Elements(),
                            mFontFace->GetIndex(),
                            aSimulations,
                            aFontFace);
         for (UINT32 i = 0; i < numberOfFiles; ++i) {
             files[i]->Release();
@@ -878,28 +878,28 @@ gfxDWriteFontList::InitFontListForPlatfo
     HRESULT hr;
     mGDIFontTableAccess =
         Preferences::GetBool("gfx.font_rendering.directwrite.use_gdi_table_loading",
                              false);
 
     mFontSubstitutes.Clear();
     mNonExistingFonts.Clear();
 
-    hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
+    hr = Factory::GetDWriteFactory()->
         GetGdiInterop(getter_AddRefs(mGDIInterop));
     if (FAILED(hr)) {
         Telemetry::Accumulate(Telemetry::DWRITEFONT_INIT_PROBLEM,
                               uint32_t(errGDIInterop));
         return NS_ERROR_FAILURE;
     }
 
     QueryPerformanceCounter(&t2); // base-class/interop initialization
 
     RefPtr<IDWriteFactory> factory =
-        gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
+        Factory::GetDWriteFactory();
 
     hr = factory->GetSystemFontCollection(getter_AddRefs(mSystemFonts));
     NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!");
 
     if (FAILED(hr)) {
         Telemetry::Accumulate(Telemetry::DWRITEFONT_INIT_PROBLEM,
                               uint32_t(errSystemFontCollection));
         return NS_ERROR_FAILURE;
@@ -1420,17 +1420,17 @@ gfxDWriteFontList::GlobalFontFallback(co
                                                        aMatchStyle,
                                                        aCmapCount,
                                                        aMatchedFamily);
     }
 
     HRESULT hr;
 
     RefPtr<IDWriteFactory> dwFactory =
-        gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
+        Factory::GetDWriteFactory();
     if (!dwFactory) {
         return nullptr;
     }
 
     // initialize fallback renderer
     if (!mFallbackRenderer) {
         mFallbackRenderer = new DWriteFontFallbackRenderer(dwFactory);
     }
--- a/gfx/thebes/gfxDWriteFonts.cpp
+++ b/gfx/thebes/gfxDWriteFonts.cpp
@@ -594,29 +594,16 @@ gfxDWriteFont::GetGlyphWidth(DrawTarget&
         return width;
     }
 
     width = NS_lround(MeasureGlyphWidth(aGID) * 65536.0);
     mGlyphWidths->Put(aGID, width);
     return width;
 }
 
-already_AddRefed<GlyphRenderingOptions>
-gfxDWriteFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams)
-{
-  if (mUseClearType) {
-    return Factory::CreateDWriteGlyphRenderingOptions(
-      gfxWindowsPlatform::GetPlatform()->GetRenderingParams(GetForceGDIClassic() ?
-        gfxWindowsPlatform::TEXT_RENDERING_GDI_CLASSIC : gfxWindowsPlatform::TEXT_RENDERING_NORMAL));
-  } else {
-    return Factory::CreateDWriteGlyphRenderingOptions(gfxWindowsPlatform::GetPlatform()->
-      GetRenderingParams(gfxWindowsPlatform::TEXT_RENDERING_NO_CLEARTYPE));
-  }
-}
-
 bool
 gfxDWriteFont::GetForceGDIClassic()
 {
     return static_cast<gfxDWriteFontEntry*>(mFontEntry.get())->GetForceGDIClassic() &&
          cairo_dwrite_get_cleartype_rendering_mode() < 0 &&
          GetAdjustedSize() <=
             gfxDWriteFontList::PlatformFontList()->GetForceGDIClassicMaxFontSize();
 }
@@ -702,31 +689,37 @@ gfxDWriteFont::GetScaledFont(mozilla::gf
   nativeFont.mType = NativeFontType::DWRITE_FONT_FACE;
   nativeFont.mFont = GetFontFace();
 
   if (wantCairo) {
     mAzureScaledFont = Factory::CreateScaledFontWithCairo(nativeFont,
                                                         GetUnscaledFont(),
                                                         GetAdjustedSize(),
                                                         GetCairoScaledFont());
-  } else if (aTarget->GetBackendType() == BackendType::SKIA) {
+  } else {
     gfxDWriteFontEntry *fe =
         static_cast<gfxDWriteFontEntry*>(mFontEntry.get());
     bool useEmbeddedBitmap = (fe->IsCJKFont() && HasBitmapStrikeForSize(NS_lround(mAdjustedSize)));
+    bool forceGDI = GetForceGDIClassic();
+
+    IDWriteRenderingParams* params = gfxWindowsPlatform::GetPlatform()->GetRenderingParams(
+      mUseClearType ?
+        (forceGDI ?
+          gfxWindowsPlatform::TEXT_RENDERING_GDI_CLASSIC : gfxWindowsPlatform::TEXT_RENDERING_NORMAL) :
+        gfxWindowsPlatform::TEXT_RENDERING_NO_CLEARTYPE);
 
     const gfxFontStyle* fontStyle = GetStyle();
     mAzureScaledFont =
             Factory::CreateScaledFontForDWriteFont(mFontFace, fontStyle,
                                                    GetUnscaledFont(),
                                                    GetAdjustedSize(),
                                                    useEmbeddedBitmap,
-                                                   GetForceGDIClassic());
-  } else {
-    mAzureScaledFont = Factory::CreateScaledFontForNativeFont(nativeFont,
-                                                            GetUnscaledFont(),
-                                                            GetAdjustedSize());
+                                                   forceGDI,
+                                                   params,
+                                                   params->GetGamma(),
+                                                   params->GetEnhancedContrast());
   }
 
   mAzureScaledFontIsCairo = wantCairo;
 
   RefPtr<ScaledFont> scaledFont(mAzureScaledFont);
   return scaledFont.forget();
 }
--- a/gfx/thebes/gfxDWriteFonts.h
+++ b/gfx/thebes/gfxDWriteFonts.h
@@ -56,19 +56,16 @@ public:
                                Spacing *aSpacing,
                                mozilla::gfx::ShapedTextFlags aOrientation) override;
 
     virtual bool ProvidesGlyphWidths() const override;
 
     virtual int32_t GetGlyphWidth(DrawTarget& aDrawTarget,
                                   uint16_t aGID) override;
 
-    virtual already_AddRefed<mozilla::gfx::GlyphRenderingOptions>
-    GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr) override;
-
     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontCacheSizes* aSizes) const override;
     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontCacheSizes* aSizes) const override;
 
     virtual FontType GetType() const override { return FONT_TYPE_DWRITE; }
 
     virtual already_AddRefed<mozilla::gfx::ScaledFont>
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -75,24 +75,16 @@
 #include "D3D11Checks.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla::image;
 
-IDWriteRenderingParams* GetDwriteRenderingParams(bool aGDI)
-{
-  gfxWindowsPlatform::TextRenderingMode mode = aGDI ?
-    gfxWindowsPlatform::TEXT_RENDERING_GDI_CLASSIC :
-    gfxWindowsPlatform::TEXT_RENDERING_NORMAL;
-  return gfxWindowsPlatform::GetPlatform()->GetRenderingParams(mode);
-}
-
 DCFromDrawTarget::DCFromDrawTarget(DrawTarget& aDrawTarget)
 {
   mDC = nullptr;
   if (aDrawTarget.GetBackendType() == BackendType::CAIRO) {
     cairo_t* ctx = static_cast<cairo_t*>
       (aDrawTarget.GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
     if (ctx) {
       cairo_surface_t* surf = cairo_get_group_target(ctx);
@@ -358,17 +350,17 @@ gfxWindowsPlatform::InitAcceleration()
   DeviceManagerDx::Init();
 
   InitializeConfig();
   InitializeDevices();
   UpdateANGLEConfig();
   UpdateRenderMode();
 
   // If we have Skia and we didn't init dwrite already, do it now.
-  if (!mDWriteFactory && GetDefaultContentBackend() == BackendType::SKIA) {
+  if (!DWriteEnabled() && GetDefaultContentBackend() == BackendType::SKIA) {
     InitDWriteSupport();
   }
 
   // CanUseHardwareVideoDecoding depends on DeviceManagerDx state,
   // so update the cached value now.
   UpdateCanUseHardwareVideoDecoding();
 }
 
@@ -384,36 +376,20 @@ gfxWindowsPlatform::CanUseHardwareVideoD
   }
   return !dm->IsWARP() && gfxPlatform::CanUseHardwareVideoDecoding();
 }
 
 bool
 gfxWindowsPlatform::InitDWriteSupport()
 {
   mozilla::ScopedGfxFeatureReporter reporter("DWrite");
-  decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
-      GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory");
-  if (!createDWriteFactory) {
+  if (!Factory::EnsureDWriteFactory()) {
     return false;
   }
 
-  // I need a direct pointer to be able to cast to IUnknown**, I also need to
-  // remember to release this because the nsRefPtr will AddRef it.
-  RefPtr<IDWriteFactory> factory;
-  HRESULT hr = createDWriteFactory(
-      DWRITE_FACTORY_TYPE_SHARED,
-      __uuidof(IDWriteFactory),
-      (IUnknown **)((IDWriteFactory **)getter_AddRefs(factory)));
-  if (FAILED(hr) || !factory) {
-    return false;
-  }
-
-  mDWriteFactory = factory;
-  Factory::SetDWriteFactory(mDWriteFactory);
-
   SetupClearTypeParams();
   reporter.SetSuccessful();
   return true;
 }
 
 bool
 gfxWindowsPlatform::HandleDeviceReset()
 {
@@ -510,17 +486,17 @@ gfxWindowsPlatform::GetContentBackendFor
 
 gfxPlatformFontList*
 gfxWindowsPlatform::CreatePlatformFontList()
 {
     gfxPlatformFontList *pfl;
 
     // bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd
     // crashers so blacklist them altogether
-    if (IsNotWin7PreRTM() && GetDWriteFactory()) {
+    if (IsNotWin7PreRTM() && DWriteEnabled()) {
         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();
@@ -574,32 +550,17 @@ gfxWindowsPlatform::CreateOffscreenSurfa
 
     return surf.forget();
 }
 
 already_AddRefed<ScaledFont>
 gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
     if (aFont->GetType() == gfxFont::FONT_TYPE_DWRITE) {
-        gfxDWriteFont *font = static_cast<gfxDWriteFont*>(aFont);
-
-        NativeFont nativeFont;
-        nativeFont.mType = NativeFontType::DWRITE_FONT_FACE;
-        nativeFont.mFont = font->GetFontFace();
-
-        if (aTarget->GetBackendType() == BackendType::CAIRO) {
-          return Factory::CreateScaledFontWithCairo(nativeFont,
-                                                    font->GetUnscaledFont(),
-                                                    font->GetAdjustedSize(),
-                                                    font->GetCairoScaledFont());
-        }
-
-        return Factory::CreateScaledFontForNativeFont(nativeFont,
-                                                      font->GetUnscaledFont(),
-                                                      font->GetAdjustedSize());
+        return aFont->GetScaledFont(aTarget);
     }
 
     NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_GDI,
         "Fonts on windows should be GDI or DWrite!");
 
     NativeFont nativeFont;
     nativeFont.mType = NativeFontType::GDI_FONT_FACE;
     LOGFONT lf;
@@ -1137,17 +1098,17 @@ gfxWindowsPlatform::FontsPrefsChanged(co
 #define DISPLAY1_REGISTRY_KEY \
     HKEY_CURRENT_USER, L"Software\\Microsoft\\Avalon.Graphics\\DISPLAY1"
 
 #define ENHANCED_CONTRAST_VALUE_NAME L"EnhancedContrastLevel"
 
 void
 gfxWindowsPlatform::SetupClearTypeParams()
 {
-    if (GetDWriteFactory()) {
+    if (DWriteEnabled()) {
         // any missing prefs will default to invalid (-1) and be ignored;
         // out-of-range values will also be ignored
         FLOAT gamma = -1.0;
         FLOAT contrast = -1.0;
         FLOAT level = -1.0;
         int geometry = -1;
         int mode = -1;
         int32_t value;
@@ -1192,17 +1153,17 @@ gfxWindowsPlatform::SetupClearTypeParams
             mMeasuringMode = DWRITE_MEASURING_MODE_GDI_NATURAL;
             break;
         default:
             mMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
             break;
         }
 
         RefPtr<IDWriteRenderingParams> defaultRenderingParams;
-        GetDWriteFactory()->CreateRenderingParams(getter_AddRefs(defaultRenderingParams));
+        Factory::GetDWriteFactory()->CreateRenderingParams(getter_AddRefs(defaultRenderingParams));
         // For EnhancedContrast, we override the default if the user has not set it
         // in the registry (by using the ClearType Tuner).
         if (contrast < 0.0 || contrast > 10.0) {
             HKEY hKey;
             LONG res = RegOpenKeyExW(DISPLAY1_REGISTRY_KEY,
                                      0, KEY_READ, &hKey);
             if (res == ERROR_SUCCESS) {
                 res = RegQueryValueExW(hKey, ENHANCED_CONTRAST_VALUE_NAME,
@@ -1248,24 +1209,24 @@ gfxWindowsPlatform::SetupClearTypeParams
 
         if (renderMode < DWRITE_RENDERING_MODE_DEFAULT ||
             renderMode > DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC) {
             renderMode = defaultRenderingParams->GetRenderingMode();
         }
 
         mRenderingParams[TEXT_RENDERING_NO_CLEARTYPE] = defaultRenderingParams;
 
-        HRESULT hr = GetDWriteFactory()->CreateCustomRenderingParams(
+        HRESULT hr = Factory::GetDWriteFactory()->CreateCustomRenderingParams(
             gamma, contrast, level, dwriteGeometry, renderMode,
             getter_AddRefs(mRenderingParams[TEXT_RENDERING_NORMAL]));
         if (FAILED(hr) || !mRenderingParams[TEXT_RENDERING_NORMAL]) {
             mRenderingParams[TEXT_RENDERING_NORMAL] = defaultRenderingParams;
         }
 
-        hr = GetDWriteFactory()->CreateCustomRenderingParams(
+        hr = Factory::GetDWriteFactory()->CreateCustomRenderingParams(
             gamma, contrast, level,
             dwriteGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
             getter_AddRefs(mRenderingParams[TEXT_RENDERING_GDI_CLASSIC]));
         if (FAILED(hr) || !mRenderingParams[TEXT_RENDERING_GDI_CLASSIC]) {
             mRenderingParams[TEXT_RENDERING_GDI_CLASSIC] =
                 defaultRenderingParams;
         }
     }
@@ -1577,17 +1538,17 @@ gfxWindowsPlatform::InitializeD2D()
 
   if (!dm->TextureSharingWorks()) {
     d2d1.SetFailed(FeatureStatus::Failed, "Direct3D11 device does not support texture sharing",
                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_TXT_SHARING"));
     return;
   }
 
   // Using Direct2D depends on DWrite support.
-  if (!mDWriteFactory && !InitDWriteSupport()) {
+  if (!DWriteEnabled() && !InitDWriteSupport()) {
     d2d1.SetFailed(FeatureStatus::Failed, "Failed to initialize DirectWrite support",
                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_DWRITE"));
     return;
   }
 
   // Verify that Direct2D device creation succeeded.
   RefPtr<ID3D11Device> contentDevice = dm->GetContentDevice();
   if (!Factory::SetDirect3D11Device(contentDevice)) {
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -187,18 +187,17 @@ public:
 
     // returns ClearType tuning information for each display
     static void GetCleartypeParams(nsTArray<ClearTypeParameterInfo>& aParams);
 
     virtual void FontsPrefsChanged(const char *aPref) override;
 
     void SetupClearTypeParams();
 
-    IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
-    inline bool DWriteEnabled() { return !!mDWriteFactory; }
+    inline bool DWriteEnabled() const { return !!mozilla::gfx::Factory::GetDWriteFactory(); }
     inline DWRITE_MEASURING_MODE DWriteMeasuringMode() { return mMeasuringMode; }
 
     IDWriteRenderingParams *GetRenderingParams(TextRenderingMode aRenderMode)
     { return mRenderingParams[aRenderMode]; }
 
 public:
     bool DwmCompositionEnabled();
 
@@ -255,17 +254,16 @@ private:
 
     void InitializeConfig();
     void InitializeD3D9Config();
     void InitializeD3D11Config();
     void InitializeD2DConfig();
     void InitializeDirectDrawConfig();
     void InitializeAdvancedLayersConfig();
 
-    RefPtr<IDWriteFactory> mDWriteFactory;
     RefPtr<IDWriteRenderingParams> mRenderingParams[TEXT_RENDERING_COUNT];
     DWRITE_MEASURING_MODE mMeasuringMode;
 
     RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
 
     nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
 };
 
--- a/layout/printing/PrintTranslator.cpp
+++ b/layout/printing/PrintTranslator.cpp
@@ -78,25 +78,10 @@ PrintTranslator::CreateDrawTarget(Refere
     return nullptr;
   }
 
   RefPtr<DrawTarget> drawTarget = context->GetDrawTarget();
   AddDrawTarget(aRefPtr, drawTarget);
   return drawTarget.forget();
 }
 
-FontType
-PrintTranslator::GetDesiredFontType()
-{
-  switch (mBaseDT->GetBackendType()) {
-    case BackendType::DIRECT2D:
-      return FontType::DWRITE;
-    case BackendType::CAIRO:
-      return FontType::CAIRO;
-    case BackendType::SKIA:
-      return FontType::SKIA;
-    default:
-      return FontType::CAIRO;
-  }
-}
-
 } // namespace layout
 } // namespace mozilla
--- a/layout/printing/PrintTranslator.h
+++ b/layout/printing/PrintTranslator.h
@@ -170,18 +170,16 @@ public:
   }
 
   already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
                                                 const gfx::IntSize &aSize,
                                                 gfx::SurfaceFormat aFormat) final;
 
   mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
 
-  mozilla::gfx::FontType GetDesiredFontType() final;
-
 private:
   RefPtr<nsDeviceContext> mDeviceContext;
   RefPtr<DrawTarget> mBaseDT;
 
   nsRefPtrHashtable<nsPtrHashKey<void>, DrawTarget> mDrawTargets;
   nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
   nsRefPtrHashtable<nsPtrHashKey<void>, SourceSurface> mSourceSurfaces;
   nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;