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 607727 d5b7263f383d0d822b683138c914926b01c7f5cd
parent 607726 e738e018fe57aa713c5b977c985b8809188ef591
child 607728 d22cfe83584a2c1adc247d0d0999a263fbfa8e03
push id68095
push userbmo:rbarker@mozilla.com
push dateWed, 12 Jul 2017 20:01:47 +0000
reviewersjrmuizel
bugs1376026
milestone56.0a1
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;