DirectWrite font host for skia.
https://codereview.appspot.com/5417063/


git-svn-id: http://skia.googlecode.com/svn/trunk@5128 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkAdvancedTypefaceMetrics.cpp b/src/core/SkAdvancedTypefaceMetrics.cpp
index a8a6083..c3cb3d8 100644
--- a/src/core/SkAdvancedTypefaceMetrics.cpp
+++ b/src/core/SkAdvancedTypefaceMetrics.cpp
@@ -12,6 +12,10 @@
 
 SK_DEFINE_INST_COUNT(SkAdvancedTypefaceMetrics)
 
+#if defined(SK_BUILD_FOR_WIN) && defined(SK_FONTHOST_WIN_DW)
+#include <DWrite.h>
+#endif
+
 #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -253,13 +257,20 @@
 
 // Make AdvanceMetric template functions available for linking with typename
 // WidthRange and VerticalAdvanceRange.
-#if defined(SK_BUILD_FOR_WIN)
+#if defined(SK_BUILD_FOR_WIN) && !defined(SK_FONTHOST_WIN_DW)
 template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
         HDC hdc,
         int num_glyphs,
         const uint32_t* subsetGlyphIDs,
         uint32_t subsetGlyphIDsLength,
         bool (*getAdvance)(HDC hdc, int gId, int16_t* data));
+#elif defined(SK_BUILD_FOR_WIN) && defined(SK_FONTHOST_WIN_DW)
+template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
+        IDWriteFontFace* fontFace,
+        int num_glyphs,
+        const uint32_t* subsetGlyphIDs,
+        uint32_t subsetGlyphIDsLength,
+        bool (*getAdvance)(IDWriteFontFace* fontFace, int gId, int16_t* data));
 #elif defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
 template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
         FT_Face face,
diff --git a/src/ports/SkFontHost_win_dw.cpp b/src/ports/SkFontHost_win_dw.cpp
new file mode 100644
index 0000000..c3a13a0
--- /dev/null
+++ b/src/ports/SkFontHost_win_dw.cpp
@@ -0,0 +1,1519 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTypes.h"
+#undef GetGlyphIndices
+
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkColorFilter.h"
+#include "SkDWriteFontFileStream.h"
+#include "SkDWriteGeometrySink.h"
+#include "SkDescriptor.h"
+#include "SkEndian.h"
+#include "SkFontHost.h"
+#include "SkGlyph.h"
+#include "SkHRESULT.h"
+#include "SkMaskGamma.h"
+#include "SkOTTable_head.h"
+#include "SkOTTable_hhea.h"
+#include "SkOTTable_OS_2.h"
+#include "SkOTTable_post.h"
+#include "SkPath.h"
+#include "SkStream.h"
+#include "SkString.h"
+#include "SkTScopedComPtr.h"
+#include "SkThread.h"
+#include "SkTypeface_win.h"
+#include "SkTypefaceCache.h"
+#include "SkUtils.h"
+
+#include <dwrite.h>
+
+SK_DECLARE_STATIC_MUTEX(gFTMutex);
+
+static bool isLCD(const SkScalerContext::Rec& rec) {
+    return SkMask::kLCD16_Format == rec.fMaskFormat ||
+           SkMask::kLCD32_Format == rec.fMaskFormat;
+}
+
+SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
+  // Zero means that we don't have any fallback fonts for this fontID.
+  // This function is implemented on Android, but doesn't have much
+  // meaning here.
+  return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class DWriteOffscreen {
+public:
+    DWriteOffscreen() : fWidth(0), fHeight(0) {
+    }
+
+    void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
+        fFontFace = fontFace;
+        fFontSize = fontSize;
+        fXform = xform;
+    }
+
+    const void* draw(const SkGlyph&, bool isBW);
+
+private:
+    uint16_t fWidth;
+    uint16_t fHeight;
+    IDWriteFontFace* fFontFace;
+    FLOAT fFontSize;
+    DWRITE_MATRIX fXform;
+    SkTDArray<uint8_t> fBits;
+};
+
+typedef HRESULT (WINAPI *DWriteCreateFactoryProc)(
+    __in DWRITE_FACTORY_TYPE factoryType,
+    __in REFIID iid,
+    __out IUnknown **factory
+);
+
+static HRESULT get_dwrite_factory(IDWriteFactory** factory) {
+    static IDWriteFactory* gDWriteFactory = NULL;
+
+    if (gDWriteFactory != NULL) {
+        *factory = gDWriteFactory;
+        return S_OK;
+    }
+
+    DWriteCreateFactoryProc dWriteCreateFactoryProc =
+        reinterpret_cast<DWriteCreateFactoryProc>(
+            GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory")
+        )
+    ;
+    
+    if (!dWriteCreateFactoryProc) {
+        return E_UNEXPECTED;
+    }
+
+    HRM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
+                                __uuidof(IDWriteFactory),
+                                reinterpret_cast<IUnknown**>(&gDWriteFactory)),
+        "Could not create DirectWrite factory.");
+    
+    *factory = gDWriteFactory;
+    return S_OK;
+}
+
+const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
+    IDWriteFactory* factory;
+    HRNM(get_dwrite_factory(&factory), "Could not get factory.");
+
+    if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
+        fWidth = SkMax32(fWidth, glyph.fWidth);
+        fHeight = SkMax32(fHeight, glyph.fHeight);
+
+        if (isBW) {
+            fBits.setCount(fWidth * fHeight);
+        } else {
+            fBits.setCount(fWidth * fHeight * 3);
+        }
+    }
+
+    // erase
+    memset(fBits.begin(), 0, fBits.count());
+
+    fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
+    fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
+
+    FLOAT advance = 0.0f;
+
+    UINT16 index = glyph.getGlyphID();
+
+    DWRITE_GLYPH_OFFSET offset;
+    offset.advanceOffset = 0.0f;
+    offset.ascenderOffset = 0.0f;
+
+    DWRITE_GLYPH_RUN run;
+    run.glyphCount = 1;
+    run.glyphAdvances = &advance;
+    run.fontFace = fFontFace;
+    run.fontEmSize = fFontSize;
+    run.bidiLevel = 0;
+    run.glyphIndices = &index;
+    run.isSideways = FALSE;
+    run.glyphOffsets = &offset;
+
+    DWRITE_RENDERING_MODE renderingMode;
+    DWRITE_TEXTURE_TYPE textureType;
+    if (isBW) {
+        renderingMode = DWRITE_RENDERING_MODE_ALIASED;
+        textureType = DWRITE_TEXTURE_ALIASED_1x1;
+    } else {
+        renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
+        textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
+    }
+    SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
+    HRNM(factory->CreateGlyphRunAnalysis(&run,
+                                         1.0f, // pixelsPerDip,
+                                         &fXform,
+                                         renderingMode,
+                                         DWRITE_MEASURING_MODE_NATURAL,
+                                         0.0f, // baselineOriginX,
+                                         0.0f, // baselineOriginY,
+                                         &glyphRunAnalysis),
+         "Could not create glyph run analysis.");
+    
+    //NOTE: this assumes that the glyph has already been measured
+    //with an exact same glyph run analysis.
+    RECT bbox;
+    bbox.left = glyph.fLeft;
+    bbox.top = glyph.fTop;
+    bbox.right = glyph.fLeft + glyph.fWidth;
+    bbox.bottom = glyph.fTop + glyph.fHeight;
+    HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
+                                              &bbox,
+                                              fBits.begin(),
+                                              fBits.count()),
+         "Could not draw mask.");
+    return fBits.begin();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static SkTypeface::Style get_style(IDWriteFont* font) {
+    int style = SkTypeface::kNormal;
+    DWRITE_FONT_WEIGHT weight = font->GetWeight();
+    if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
+        style |= SkTypeface::kBold;
+    }
+    DWRITE_FONT_STYLE angle = font->GetStyle();
+    if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
+        style |= SkTypeface::kItalic;
+    }
+    return static_cast<SkTypeface::Style>(style);
+}
+
+class DWriteFontTypeface : public SkTypeface {
+private:
+    DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
+                       IDWriteFontFace* fontFace,
+                       IDWriteFont* font,
+                       IDWriteFontFamily* fontFamily,
+                       IDWriteFontFileLoader* fontFileLoader = NULL,
+                       IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
+        : SkTypeface(style, fontID, false)
+        , fDWriteFontCollectionLoader(fontCollectionLoader)
+        , fDWriteFontFileLoader(fontFileLoader)
+        , fDWriteFontFamily(fontFamily)
+        , fDWriteFont(font)
+        , fDWriteFontFace(fontFace) {
+
+        if (fontCollectionLoader != NULL) {
+            fontCollectionLoader->AddRef();
+        }
+        if (fontFileLoader != NULL) {
+            fontFileLoader->AddRef();
+        }
+        fontFamily->AddRef();
+        font->AddRef();
+        fontFace->AddRef();
+    }
+
+public:
+    SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
+    SkTScopedComPtr<IDWriteFontFileLoader> fDWriteFontFileLoader;
+    SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
+    SkTScopedComPtr<IDWriteFont> fDWriteFont;
+    SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
+
+    static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
+                                      IDWriteFont* font,
+                                      IDWriteFontFamily* fontFamily,
+                                      IDWriteFontFileLoader* fontFileLoader = NULL,
+                                      IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
+        SkTypeface::Style style = get_style(font);
+        SkFontID fontID = SkTypefaceCache::NewFontID();
+        return SkNEW_ARGS(DWriteFontTypeface, (style, fontID, fontFace, font, fontFamily,
+                                               fontFileLoader, fontCollectionLoader));
+    }
+
+    ~DWriteFontTypeface() {
+        if (fDWriteFontCollectionLoader.get() == NULL) return;
+
+        IDWriteFactory* factory;
+        HRVM(get_dwrite_factory(&factory), "Could not get factory.");
+        HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
+        HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
+    }
+};
+
+class SkScalerContext_Windows : public SkScalerContext {
+public:
+    SkScalerContext_Windows(const SkDescriptor* desc);
+    virtual ~SkScalerContext_Windows();
+
+protected:
+    virtual unsigned generateGlyphCount() SK_OVERRIDE;
+    virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
+    virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
+    virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
+    virtual void generateImage(const SkGlyph& glyph,
+                               SkMaskGamma::PreBlend* maskPreBlend) SK_OVERRIDE;
+    virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
+    virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
+                                     SkPaint::FontMetrics* mY) SK_OVERRIDE;
+
+private:
+    DWriteOffscreen fOffscreen;
+    DWRITE_MATRIX fXform;
+    SkAutoTUnref<DWriteFontTypeface> fTypeface;
+    int fGlyphCount;
+};
+
+#define SK_DWRITE_DEFAULT_FONT_NAMED 1
+#define SK_DWRITE_DEFAULT_FONT_MESSAGE 2
+#define SK_DWRITE_DEFAULT_FONT_THEME 3
+#define SK_DWRITE_DEFAULT_FONT_SHELLDLG 4
+#define SK_DWRITE_DEFAULT_FONT_GDI 5
+#define SK_DWRITE_DEFAULT_FONT_STRATEGY SK_DWRITE_DEFAULT_FONT_MESSAGE
+
+static HRESULT get_default_font(IDWriteFont** font) {
+    IDWriteFactory* factory;
+    HRM(get_dwrite_factory(&factory), "Could not get factory.");
+
+#if SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_NAMED
+    SkTScopedComPtr<IDWriteFontCollection> sysFonts;
+    HRM(factory->GetSystemFontCollection(&sysFonts, false),
+        "Could not get system font collection.");
+
+    UINT32 index;
+    BOOL exists;
+    //hr = sysFonts->FindFamilyName(L"Georgia", &index, &exists);
+    HRM(sysFonts->FindFamilyName(L"Microsoft Sans Serif", &index, &exists),
+        "Could not access family names.");
+
+    if (!exists) {
+        SkDEBUGF(("The hard coded font family does not exist."));
+        return E_UNEXPECTED;
+    }
+    
+    SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+    HRM(sysFonts->GetFontFamily(index, &fontFamily),
+        "Could not load the requested font family.");
+
+    HRM(fontFamily->GetFont(0, font), "Could not get first font from family.");
+
+#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_MESSAGE
+    SkTScopedComPtr<IDWriteGdiInterop> gdi;
+    HRM(factory->GetGdiInterop(&gdi), "Could not get GDI interop.");
+
+    NONCLIENTMETRICSW metrics;
+    metrics.cbSize = sizeof(metrics);
+    if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
+                                   sizeof(metrics),
+                                   &metrics,
+                                   0)) {
+        return E_UNEXPECTED;
+    }
+    HRM(gdi->CreateFontFromLOGFONT(&metrics.lfMessageFont, font),
+        "Could not create DWrite font from LOGFONT.");
+
+#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_THEME
+    //Theme body font?
+
+#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_SHELLDLG
+    //"MS Shell Dlg" or "MS Shell Dlg 2"?
+
+#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_GDI
+    //Never works.
+    SkTScopedComPtr<IDWriteGdiInterop> gdi;
+    HRM(factory->GetGdiInterop(&gdi), "Could not get GDI interop.");
+
+    static LOGFONTW gDefaultFont = {};
+    gDefaultFont.lfFaceName
+    HRM(gdi->CreateFontFromLOGFONT(&gDefaultFont, font),
+        "Could not create DWrite font from LOGFONT.";
+#endif
+    return S_OK;
+}
+
+static bool are_same(IUnknown* a, IUnknown* b) {
+    SkTScopedComPtr<IUnknown> iunkA;
+    if (FAILED(a->QueryInterface(&iunkA))) {
+        return false;
+    }
+
+    SkTScopedComPtr<IUnknown> iunkB;
+    if (FAILED(b->QueryInterface(&iunkB))) {
+        return false;
+    }
+
+    return iunkA.get() == iunkB.get();
+}
+static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
+    //Check to see if the two fonts are identical.
+    DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
+    IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
+    if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
+        return true;
+    }
+
+    //Check if the two fonts share the same loader and have the same key.
+    SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
+    SkTScopedComPtr<IDWriteFontFace> dwFontFace;
+    HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
+    HRB(dwFont->CreateFontFace(&dwFontFace));
+    if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
+        return true;
+    }
+
+    UINT32 dwFaceNumFiles;
+    UINT32 dwNumFiles;
+    HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
+    HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
+    if (dwFaceNumFiles != dwNumFiles) {
+        return false;
+    }
+
+    SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
+    SkTScopedComPtr<IDWriteFontFile> dwFontFile;
+    HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
+    HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
+
+    //for (each file) { //we currently only admit fonts from one file.
+    SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
+    SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
+    HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
+    HRB(dwFontFile->GetLoader(&dwFontFileLoader));
+    if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
+        return false;
+    }
+    //}
+
+    const void* dwFaceFontRefKey;
+    UINT32 dwFaceFontRefKeySize;
+    const void* dwFontRefKey;
+    UINT32 dwFontRefKeySize;
+    HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
+    HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
+    if (dwFaceFontRefKeySize != dwFontRefKeySize) {
+        return false;
+    }
+    if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
+        return false;
+    }
+
+    //TODO: better means than comparing name strings?
+    //NOTE: .tfc and fake bold/italic will end up here.
+    SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
+    SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
+    HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
+    HRB(dwFont->GetFontFamily(&dwFontFamily));
+
+    SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
+    SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
+    HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
+    HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
+
+    SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
+    SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
+    HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
+    HRB(dwFont->GetFaceNames(&dwFontNames));
+
+    UINT32 dwFaceFontFamilyNameLength;
+    UINT32 dwFaceFontNameLength;
+    HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
+    HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
+
+    UINT32 dwFontFamilyNameLength;
+    UINT32 dwFontNameLength;
+    HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
+    HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
+
+    if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
+        dwFaceFontNameLength != dwFontNameLength)
+    {
+        return false;
+    }
+
+    SkTDArray<wchar_t> dwFaceFontFamilyNameChar(new wchar_t[dwFaceFontFamilyNameLength+1], dwFaceFontFamilyNameLength+1);
+    SkTDArray<wchar_t> dwFaceFontNameChar(new wchar_t[dwFaceFontNameLength+1], dwFaceFontNameLength+1);
+    HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.begin(), dwFaceFontFamilyNameChar.count()));
+    HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.begin(), dwFaceFontNameChar.count()));
+
+    SkTDArray<wchar_t> dwFontFamilyNameChar(new wchar_t[dwFontFamilyNameLength+1], dwFontFamilyNameLength+1);
+    SkTDArray<wchar_t> dwFontNameChar(new wchar_t[dwFontNameLength+1], dwFontNameLength+1);
+    HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.begin(), dwFontFamilyNameChar.count()));
+    HRB(dwFontNames->GetString(0, dwFontNameChar.begin(), dwFontNameChar.count()));
+
+    return wcscmp(dwFaceFontFamilyNameChar.begin(), dwFontFamilyNameChar.begin()) == 0 &&
+           wcscmp(dwFaceFontNameChar.begin(), dwFontNameChar.begin()) == 0;
+}
+
+SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
+                                           IDWriteFont* font,
+                                           IDWriteFontFamily* fontFamily,
+                                           IDWriteFontFileLoader* fontFileLoader = NULL,
+                                           IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
+    SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByDWriteFont, font);
+    if (face) {
+        face->ref();
+    } else {
+        face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
+                                          fontFileLoader, fontCollectionLoader);
+        SkTypefaceCache::Add(face, get_style(font), fontCollectionLoader != NULL);
+    }
+    return face;
+}
+
+void SkDWriteFontFromTypeface(const SkTypeface* face, IDWriteFont** font) {
+    if (NULL == face) {
+        HRVM(get_default_font(font), "Could not get default font.");
+    } else {
+        *font = static_cast<const DWriteFontTypeface*>(face)->fDWriteFont.get();
+        (*font)->AddRef();
+    }
+}
+static DWriteFontTypeface* GetDWriteFontByID(SkFontID fontID) {
+    return static_cast<DWriteFontTypeface*>(SkTypefaceCache::FindByID(fontID));
+}
+
+SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)
+        : SkScalerContext(desc)
+        , fGlyphCount(-1) {
+    SkAutoMutexAcquire ac(gFTMutex);
+
+    fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
+    fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
+    fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
+    fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
+    fXform.dx = 0;
+    fXform.dy = 0;
+
+    fTypeface.reset(GetDWriteFontByID(fRec.fFontID));
+    fTypeface.get()->ref();
+
+    fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
+}
+
+SkScalerContext_Windows::~SkScalerContext_Windows() {
+}
+
+unsigned SkScalerContext_Windows::generateGlyphCount() {
+    if (fGlyphCount < 0) {
+        fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
+    }
+    return fGlyphCount;
+}
+
+uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
+    uint16_t index = 0;
+    fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
+    return index;
+}
+
+void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
+    //Delta is the difference between the right/left side bearing metric
+    //and where the right/left side bearing ends up after hinting.
+    //DirectWrite does not provide this information.
+    glyph->fRsbDelta = 0;
+    glyph->fLsbDelta = 0;
+    
+    glyph->fAdvanceX = 0;
+    glyph->fAdvanceY = 0;
+
+    uint16_t glyphId = glyph->getGlyphID();
+    DWRITE_GLYPH_METRICS gm;
+    HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
+         "Could not get design metrics.");
+
+    DWRITE_FONT_METRICS dwfm;
+    fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
+
+    SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
+                                       SkIntToScalar(gm.advanceWidth),
+                                       SkIntToScalar(dwfm.designUnitsPerEm));
+    
+    if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
+        advanceX = SkScalarRoundToScalar(advanceX);
+    }
+
+    SkVector vecs[1] = { { advanceX, 0 } };
+    SkMatrix mat;
+    mat.setAll(fRec.fPost2x2[0][0], fRec.fPost2x2[0][1], 0,
+               fRec.fPost2x2[1][0], fRec.fPost2x2[1][1], 0,
+               0, 0, SkScalarToPersp(SK_Scalar1));
+    mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
+
+    glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
+    glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
+}
+
+void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
+    glyph->fWidth = 0;
+
+    this->generateAdvance(glyph);
+
+    //Measure raster size.
+    fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
+    fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
+
+    FLOAT advance = 0;
+
+    UINT16 glyphId = glyph->getGlyphID();
+
+    DWRITE_GLYPH_OFFSET offset;
+    offset.advanceOffset = 0.0f;
+    offset.ascenderOffset = 0.0f;
+
+    DWRITE_GLYPH_RUN run;
+    run.glyphCount = 1;
+    run.glyphAdvances = &advance;
+    run.fontFace = fTypeface->fDWriteFontFace.get();
+    run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
+    run.bidiLevel = 0;
+    run.glyphIndices = &glyphId;
+    run.isSideways = FALSE;
+    run.glyphOffsets = &offset;
+
+    IDWriteFactory* factory;
+    HRVM(get_dwrite_factory(&factory), "Could not get factory.");
+
+    const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
+    DWRITE_RENDERING_MODE renderingMode;
+    DWRITE_TEXTURE_TYPE textureType;
+    if (isBW) {
+        renderingMode = DWRITE_RENDERING_MODE_ALIASED;
+        textureType = DWRITE_TEXTURE_ALIASED_1x1;
+    } else {
+        renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
+        textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
+    }
+
+    SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
+    HRVM(factory->CreateGlyphRunAnalysis(&run,
+                                         1.0f, // pixelsPerDip,
+                                         &fXform,
+                                         renderingMode,
+                                         DWRITE_MEASURING_MODE_NATURAL,
+                                         0.0f, // baselineOriginX,
+                                         0.0f, // baselineOriginY,
+                                         &glyphRunAnalysis),
+         "Could not create glyph run analysis.");
+    
+    RECT bbox;
+    HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
+         "Could not get texture bounds.");
+
+    glyph->fWidth = SkToU16(bbox.right - bbox.left);
+    glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
+    glyph->fLeft = SkToS16(bbox.left);
+    glyph->fTop = SkToS16(bbox.top);
+}
+
+void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx,
+                                                  SkPaint::FontMetrics* my) {
+    if (!(mx || my))
+      return;
+
+    DWRITE_FONT_METRICS dwfm;
+    fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
+
+    if (mx) {
+        mx->fTop = SkScalarMulDiv(-fRec.fTextSize,
+                                  SkIntToScalar(dwfm.ascent),
+                                  SkIntToScalar(dwfm.designUnitsPerEm));
+        mx->fAscent = mx->fTop;
+        mx->fDescent = SkScalarMulDiv(fRec.fTextSize,
+                                      SkIntToScalar(dwfm.descent),
+                                      SkIntToScalar(dwfm.designUnitsPerEm));
+        mx->fBottom = mx->fDescent;
+        //TODO, can be less than zero
+        mx->fLeading = SkScalarMulDiv(fRec.fTextSize,
+                                      SkIntToScalar(dwfm.lineGap),
+                                      SkIntToScalar(dwfm.designUnitsPerEm));
+    }
+
+    if (my) {
+        my->fTop = SkScalarMulDiv(-fRec.fTextSize,
+                                  SkIntToScalar(dwfm.ascent),
+                                  SkIntToScalar(dwfm.designUnitsPerEm));
+        my->fAscent = my->fTop;
+        my->fDescent = SkScalarMulDiv(fRec.fTextSize,
+                                      SkIntToScalar(dwfm.descent),
+                                      SkIntToScalar(dwfm.designUnitsPerEm));
+        my->fBottom = my->fDescent;
+        //TODO, can be less than zero
+        my->fLeading = SkScalarMulDiv(fRec.fTextSize,
+                                      SkIntToScalar(dwfm.lineGap),
+                                      SkIntToScalar(dwfm.designUnitsPerEm));
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkColorPriv.h"
+
+static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
+    const int width = glyph.fWidth;
+    const size_t dstRB = (width + 7) >> 3;
+    uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
+
+    int byteCount = width >> 3;
+    int bitCount = width & 7;
+
+    for (int y = 0; y < glyph.fHeight; ++y) {
+        if (byteCount > 0) {
+            for (int i = 0; i < byteCount; ++i) {
+                unsigned byte = 0;
+                byte |= src[0] & (1 << 7);
+                byte |= src[1] & (1 << 6);
+                byte |= src[2] & (1 << 5);
+                byte |= src[3] & (1 << 4);
+                byte |= src[4] & (1 << 3);
+                byte |= src[5] & (1 << 2);
+                byte |= src[6] & (1 << 1);
+                byte |= src[7] & (1 << 0);
+                dst[i] = byte;
+                src += 8;
+            }
+        }
+        if (bitCount > 0) {
+            unsigned byte = 0;
+            unsigned mask = 0x80;
+            for (int i = 0; i < bitCount; i++) {
+                byte |= (src[i]) & mask;
+                mask >>= 1;
+            }
+            dst[byteCount] = byte;
+        }
+        src += bitCount;
+        dst += dstRB;
+    }
+}
+
+template<bool APPLY_PREBLEND>
+static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
+    const size_t dstRB = glyph.rowBytes();
+    const U16CPU width = glyph.fWidth;
+    uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
+
+    for (U16CPU y = 0; y < glyph.fHeight; y++) {
+        for (U16CPU i = 0; i < width; i++) {
+            U8CPU r = *(src++);
+            U8CPU g = *(src++);
+            U8CPU b = *(src++);
+            dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
+        }
+        dst = (uint8_t*)((char*)dst + dstRB);
+    }
+}
+
+template<bool APPLY_PREBLEND>
+static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
+                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
+    const size_t dstRB = glyph.rowBytes();
+    const U16CPU width = glyph.fWidth;
+    uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
+
+    for (U16CPU y = 0; y < glyph.fHeight; y++) {
+        for (U16CPU i = 0; i < width; i++) {
+            U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
+            U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
+            U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
+            dst[i] = SkPack888ToRGB16(r, g, b);
+        }
+        dst = (uint16_t*)((char*)dst + dstRB);
+    }
+}
+
+template<bool APPLY_PREBLEND>
+static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
+                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
+    const size_t dstRB = glyph.rowBytes();
+    const U16CPU width = glyph.fWidth;
+    SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
+
+    for (U16CPU y = 0; y < glyph.fHeight; y++) {
+        for (U16CPU i = 0; i < width; i++) {
+            U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
+            U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
+            U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
+            dst[i] = SkPackARGB32(0xFF, r, g, b);
+        }
+        dst = (SkPMColor*)((char*)dst + dstRB);
+    }
+}
+
+void SkScalerContext_Windows::generateImage(const SkGlyph& glyph,
+                                            SkMaskGamma::PreBlend* maskPreBlend) {
+    SkAutoMutexAcquire ac(gFTMutex);
+
+    //Must be careful not to use these if maskPreBlend == NULL
+    const uint8_t* tableR = NULL;
+    const uint8_t* tableG = NULL;
+    const uint8_t* tableB = NULL;
+    if (maskPreBlend) {
+        tableR = maskPreBlend->fR;
+        tableG = maskPreBlend->fG;
+        tableB = maskPreBlend->fB;
+    }
+
+    const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
+    const bool isAA = !isLCD(fRec);
+
+    //Create the mask.
+    const void* bits = fOffscreen.draw(glyph, isBW);
+    if (!bits) {
+        sk_bzero(glyph.fImage, glyph.computeImageSize());
+        return;
+    }
+
+    //Copy the mask into the glyph.
+    int width = glyph.fWidth;
+    size_t dstRB = glyph.rowBytes();
+    const uint8_t* src = (const uint8_t*)bits;
+    if (isBW) {
+        bilevel_to_bw(src, glyph);
+    } else if (isAA) {
+        if (maskPreBlend) {
+            rgb_to_a8<true>(src, glyph, tableG);
+        } else {
+            rgb_to_a8<false>(src, glyph, tableG);
+        }
+    } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
+        if (maskPreBlend) {
+            rgb_to_lcd16<true>(src, glyph, tableR, tableG, tableB);
+        } else {
+            rgb_to_lcd16<false>(src, glyph, tableR, tableG, tableB);
+        }
+    } else {
+        SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
+        if (maskPreBlend) {
+            rgb_to_lcd32<true>(src, glyph, tableR, tableG, tableB);
+        } else {
+            rgb_to_lcd32<true>(src, glyph, tableR, tableG, tableB);
+        }
+    }
+}
+
+void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
+    SkAutoMutexAcquire ac(gFTMutex);
+
+    SkASSERT(&glyph && path);
+
+    path->reset();
+
+    SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
+    HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
+         "Could not create geometry to path converter.");
+    uint16_t glyphId = glyph.getGlyphID();
+    //TODO: convert to<->from DIUs? This would make a difference if hinting.
+    //It may not be needed, it appears that DirectWrite only hints at em size.
+    HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
+                                       &glyphId,
+                                       NULL, //advances
+                                       NULL, //offsets
+                                       1, //num glyphs
+                                       FALSE, //sideways
+                                       FALSE, //rtl
+                                       geometryToPath.get()),
+         "Could not create glyph outline.");
+}
+
+void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
+    SkASSERT(!"SkFontHost::Serialize unimplemented");
+}
+
+SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
+    SkASSERT(!"SkFontHost::Deserialize unimplemented");
+    return NULL;
+}
+
+class StreamFontFileLoader : public IDWriteFontFileLoader {
+public:
+    // IUnknown methods
+    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+    virtual ULONG STDMETHODCALLTYPE AddRef();
+    virtual ULONG STDMETHODCALLTYPE Release();
+
+    // IDWriteFontFileLoader methods
+    virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
+        void const* fontFileReferenceKey,
+        UINT32 fontFileReferenceKeySize,
+        IDWriteFontFileStream** fontFileStream);
+
+    static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
+        *streamFontFileLoader = new StreamFontFileLoader(stream);
+        if (NULL == streamFontFileLoader) {
+            return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+private:
+    StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(stream) {
+        stream->ref();
+    }
+
+    ULONG fRefCount;
+    SkAutoTUnref<SkStream> fStream;
+};
+
+HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
+    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
+        *ppvObject = this;
+        AddRef();
+        return S_OK;
+    } else {
+        *ppvObject = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+ULONG StreamFontFileLoader::AddRef() {
+    return InterlockedIncrement(&fRefCount);
+}
+
+ULONG StreamFontFileLoader::Release() {
+    ULONG newCount = InterlockedDecrement(&fRefCount);
+    if (0 == newCount) {
+        delete this;
+    }
+    return newCount;
+}
+
+HRESULT StreamFontFileLoader::CreateStreamFromKey(
+    void const* fontFileReferenceKey,
+    UINT32 fontFileReferenceKeySize,
+    IDWriteFontFileStream** fontFileStream)
+{
+    SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
+    HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
+    *fontFileStream = stream.release();
+    return S_OK;
+}
+
+class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
+public:
+    // IUnknown methods
+    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+    virtual ULONG STDMETHODCALLTYPE AddRef();
+    virtual ULONG STDMETHODCALLTYPE Release();
+
+    // IDWriteFontFileEnumerator methods
+    virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
+    virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
+
+    static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
+                          StreamFontFileEnumerator** streamFontFileEnumerator) {
+        *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
+        if (NULL == streamFontFileEnumerator) {
+            return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+private:
+    StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
+    ULONG fRefCount;
+
+    SkTScopedComPtr<IDWriteFactory> fFactory;
+    SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
+    SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
+    bool fHasNext;
+};
+
+StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
+                                                   IDWriteFontFileLoader* fontFileLoader)
+    : fRefCount(1)
+    , fFactory(factory)
+    , fCurrentFile()
+    , fFontFileLoader(fontFileLoader)
+    , fHasNext(true)
+{
+    factory->AddRef();
+    fontFileLoader->AddRef();
+}
+
+HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
+    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
+        *ppvObject = this;
+        AddRef();
+        return S_OK;
+    } else {
+        *ppvObject = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+ULONG StreamFontFileEnumerator::AddRef() {
+    return InterlockedIncrement(&fRefCount);
+}
+
+ULONG StreamFontFileEnumerator::Release() {
+    ULONG newCount = InterlockedDecrement(&fRefCount);
+    if (0 == newCount) {
+        delete this;
+    }
+    return newCount;
+}
+
+HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
+    *hasCurrentFile = FALSE;
+
+    if (!fHasNext) {
+        return S_OK;
+    }
+    fHasNext = false;
+
+    UINT32 dummy = 0;
+    HR(fFactory->CreateCustomFontFileReference(
+            &dummy, //cannot be NULL
+            sizeof(dummy), //even if this is 0
+            fFontFileLoader.get(),
+            &fCurrentFile));
+
+    *hasCurrentFile = TRUE;
+    return S_OK;
+}
+
+HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
+    if (fCurrentFile.get() == NULL) {
+        *fontFile = NULL;
+        return E_FAIL;
+    }
+
+    fCurrentFile.get()->AddRef();
+    *fontFile = fCurrentFile.get();
+    return  S_OK;
+}
+
+class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
+public:
+    // IUnknown methods
+    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+    virtual ULONG STDMETHODCALLTYPE AddRef();
+    virtual ULONG STDMETHODCALLTYPE Release();
+
+    // IDWriteFontCollectionLoader methods
+    virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
+        IDWriteFactory* factory,
+        void const* collectionKey,
+        UINT32 collectionKeySize,
+        IDWriteFontFileEnumerator** fontFileEnumerator);
+
+    static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
+                          StreamFontCollectionLoader** streamFontCollectionLoader) {
+        *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
+        if (NULL == streamFontCollectionLoader) {
+            return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+private:
+    StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
+        : fRefCount(1)
+        , fFontFileLoader(fontFileLoader)
+    {
+        fontFileLoader->AddRef();
+    }
+
+    ULONG fRefCount;
+    SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
+};
+
+HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
+    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
+        *ppvObject = this;
+        AddRef();
+        return S_OK;
+    } else {
+        *ppvObject = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+ULONG StreamFontCollectionLoader::AddRef() {
+    return InterlockedIncrement(&fRefCount);
+}
+
+ULONG StreamFontCollectionLoader::Release() {
+    ULONG newCount = InterlockedDecrement(&fRefCount);
+    if (0 == newCount) {
+        delete this;
+    }
+    return newCount;
+}
+
+HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
+    IDWriteFactory* factory,
+    void const* collectionKey,
+    UINT32 collectionKeySize,
+    IDWriteFontFileEnumerator** fontFileEnumerator)
+{
+    SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
+    HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
+    *fontFileEnumerator = enumerator.release();
+    return S_OK;
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
+    IDWriteFactory* factory;
+    HRN(get_dwrite_factory(&factory));
+
+    SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
+    HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
+    HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
+
+    SkTScopedComPtr<StreamFontCollectionLoader> streamFontCollectionLoader;
+    HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &streamFontCollectionLoader));
+    HRN(factory->RegisterFontCollectionLoader(streamFontCollectionLoader.get()));
+
+    SkTScopedComPtr<IDWriteFontCollection> streamFontCollection;
+    HRN(factory->CreateCustomFontCollection(streamFontCollectionLoader.get(), NULL, 0,
+                                            &streamFontCollection));
+
+    SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+    HRN(streamFontCollection->GetFontFamily(0, &fontFamily));
+
+    SkTScopedComPtr<IDWriteFont> font;
+    HRN(fontFamily->GetFont(0, &font));
+
+    SkTScopedComPtr<IDWriteFontFace> fontFace;
+    HRN(font->CreateFontFace(&fontFace));
+
+    return SkCreateTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get(),
+                                          fontFileLoader.get(), streamFontCollectionLoader.get());
+}
+
+SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
+    DWriteFontTypeface* typeface = GetDWriteFontByID(uniqueID);
+    if (NULL == typeface) {
+        return NULL;
+    }
+
+    UINT32 numFiles;
+    HRNM(typeface->fDWriteFontFace->GetFiles(&numFiles, NULL),
+         "Could not get number of font files.");
+    if (numFiles != 1) {
+        return NULL;
+    }
+
+    SkTScopedComPtr<IDWriteFontFile> fontFile;
+    HRNM(typeface->fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
+
+    const void* fontFileKey;
+    UINT32 fontFileKeySize;
+    HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
+         "Could not get font file reference key.");
+
+    SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
+    HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
+
+    SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
+    HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
+                                             &fontFileStream),
+         "Could not create font file stream.");
+
+    return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
+}
+
+SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
+    return SkNEW_ARGS(SkScalerContext_Windows, (desc));
+}
+
+static HRESULT get_by_family_name(const char familyName[], IDWriteFontFamily** fontFamily) {
+    IDWriteFactory* factory;
+    HR(get_dwrite_factory(&factory));
+
+    SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
+    HR(factory->GetSystemFontCollection(&sysFontCollection, FALSE));
+
+    // Get the buffer size needed first.
+    int wlen = ::MultiByteToWideChar(CP_UTF8, 0, familyName,-1, NULL, 0);
+    if (0 == wlen) {
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+    // Allocate a buffer
+    SkTDArray<wchar_t> wideFamilyName(new wchar_t[wlen], wlen);
+    // Now actually convert the string.
+    wlen = ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
+                                    wideFamilyName.begin(), wlen);
+    if (0 == wlen) {
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    UINT32 index;
+    BOOL exists;
+    HR(sysFontCollection->FindFamilyName(wideFamilyName.begin(), &index, &exists));
+
+    if (exists) {
+        HR(sysFontCollection->GetFontFamily(index, fontFamily));
+        return S_OK;
+    }
+    return S_FALSE;
+}
+
+/** Return the closest matching typeface given either an existing family
+ (specified by a typeface in that family) or by a familyName, and a
+ requested style.
+ 1) If familyFace is null, use familyName.
+ 2) If familyName is null, use familyFace.
+ 3) If both are null, return the default font that best matches style
+ This MUST not return NULL.
+ */
+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
+                                       const char familyName[],
+                                       SkTypeface::Style style) {
+    HRESULT hr;
+    SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+    SkTScopedComPtr<IDWriteFontCollectionLoader> fontCollectionLoader;
+    SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
+    if (familyFace) {
+        const DWriteFontTypeface* face = static_cast<const DWriteFontTypeface*>(familyFace);
+        face->fDWriteFontFamily.get()->AddRef();
+        *(&fontFamily) = face->fDWriteFontFamily.get();
+
+        if (face->fDWriteFontCollectionLoader.get() != NULL) {
+            face->fDWriteFontCollectionLoader.get()->AddRef();
+            *(&fontCollectionLoader) = face->fDWriteFontCollectionLoader.get();
+
+            face->fDWriteFontFileLoader.get()->AddRef();
+            *(&fontFileLoader) = face->fDWriteFontFileLoader.get();
+        }
+
+    } else if (familyName) {
+        hr = get_by_family_name(familyName, &fontFamily);
+    }
+
+    if (NULL == fontFamily.get()) {
+        //No good family found, go with default.
+        SkTScopedComPtr<IDWriteFont> font;
+        hr = get_default_font(&font);
+        hr = font->GetFontFamily(&fontFamily);
+    }
+
+    SkTScopedComPtr<IDWriteFont> font;
+    DWRITE_FONT_WEIGHT weight = (style & SkTypeface::kBold)
+                                 ? DWRITE_FONT_WEIGHT_BOLD
+                                 : DWRITE_FONT_WEIGHT_NORMAL;
+    DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_UNDEFINED;
+    DWRITE_FONT_STYLE italic = (style & SkTypeface::kItalic)
+                                ? DWRITE_FONT_STYLE_ITALIC
+                                : DWRITE_FONT_STYLE_NORMAL;
+    hr = fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font);
+
+    SkTScopedComPtr<IDWriteFontFace> fontFace;
+    hr = font->CreateFontFace(&fontFace);
+
+    return SkCreateTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get(),
+                                          fontFileLoader.get(), fontCollectionLoader.get());
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
+    printf("SkFontHost::CreateTypefaceFromFile unimplemented");
+    return NULL;
+}
+
+void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
+    unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
+                                  SkScalerContext::kAutohinting_Flag |
+                                  SkScalerContext::kEmbeddedBitmapText_Flag |
+                                  SkScalerContext::kEmbolden_Flag |
+                                  SkScalerContext::kLCD_BGROrder_Flag |
+                                  SkScalerContext::kLCD_Vertical_Flag;
+    rec->fFlags &= ~flagsWeDontSupport;
+
+    SkPaint::Hinting h = rec->getHinting();
+    // DirectWrite does not provide for hinting hints.
+    h = SkPaint::kSlight_Hinting;
+    rec->setHinting(h);
+
+#if SK_FONT_HOST_USE_SYSTEM_SETTINGS
+    IDWriteFactory* factory;
+    if (SUCCEEDED(get_dwrite_factory(&factory))) {
+        SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
+        if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
+            float gamma = defaultRenderingParams->GetGamma();
+            rec->setDeviceGamma(SkFloatToScalar(gamma));
+            rec->setPaintGamma(SkFloatToScalar(gamma));
+            
+            rec->setContrast(SkFloatToScalar(defaultRenderingParams->GetEnhancedContrast()));
+        }
+    }
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//PDF Support
+
+using namespace skia_advanced_typeface_metrics_utils;
+
+// Construct Glyph to Unicode table.
+// Unicode code points that require conjugate pairs in utf16 are not
+// supported.
+// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
+// require parsing the TTF cmap table (platform 4, encoding 12) directly instead
+// of calling GetFontUnicodeRange().
+// TODO(bungeman): This never does what anyone wants.
+// What is really wanted is the text to glyphs mapping
+static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
+                                      const unsigned glyphCount,
+                                      SkTDArray<SkUnichar>* glyphToUnicode) {
+    HRESULT hr = S_OK;
+
+    //Do this like free type instead
+    UINT32 count = 0;
+    for (UINT32 c = 0; c < 0x10FFFF; ++c) {
+        UINT16 glyph;
+        hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
+        if (glyph > 0) {
+            ++count;
+        }
+    }
+
+    SkAutoTArray<UINT32> chars(count);
+    count = 0;
+    for (UINT32 c = 0; c < 0x10FFFF; ++c) {
+        UINT16 glyph;
+        hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
+        if (glyph > 0) {
+            chars[count] = c;
+            ++count;
+        }
+    }
+
+    SkAutoTArray<UINT16> glyph(count);
+    fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
+
+    USHORT maxGlyph = 0;
+    for (USHORT j = 0; j < count; ++j) {
+        if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
+    }
+
+    glyphToUnicode->setCount(maxGlyph+1);
+    for (size_t j = 0; j < maxGlyph+1u; ++j) {
+        (*glyphToUnicode)[j] = 0;
+    }
+
+    //'invert'
+    for (USHORT j = 0; j < count; ++j) {
+        if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
+            (*glyphToUnicode)[glyph[j]] = chars[j];
+        }
+    }
+}
+
+static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
+    SkASSERT(advance);
+
+    UINT16 glyphId = gId;
+    DWRITE_GLYPH_METRICS gm;
+    HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
+
+    if (FAILED(hr)) {
+        *advance = 0;
+        return false;
+    }
+
+    *advance = gm.advanceWidth;
+    return true;
+}
+
+template<typename T>
+class AutoDWriteTable {
+public:
+    AutoDWriteTable(IDWriteFontFace* fontFace)
+        : fFontFace(fontFace)
+        , fExists(FALSE) {
+
+        //fontFace->AddRef();
+        const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0,
+                                                    T::TAG1,
+                                                    T::TAG2,
+                                                    T::TAG3);
+        HRESULT hr = fontFace->TryGetFontTable(tag,
+            reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
+    }
+    ~AutoDWriteTable() {
+        if (fExists) {
+            fFontFace->ReleaseFontTable(fLock);
+        }
+    }
+    const T* operator->() const { return fData; }
+
+    const T* fData;
+    UINT32 fSize;
+    BOOL fExists;
+private:
+    //SkTScopedComPtr<IDWriteFontFace> fFontFace;
+    IDWriteFontFace* fFontFace;
+    void* fLock;
+};
+
+// static
+SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
+        uint32_t fontID,
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
+        const uint32_t* glyphIDs,
+        uint32_t glyphIDsCount) {
+
+    SkAdvancedTypefaceMetrics* info = NULL;
+
+    HRESULT hr = S_OK;
+
+    DWriteFontTypeface* typeface = GetDWriteFontByID(fontID);
+
+    const unsigned glyphCount = typeface->fDWriteFontFace->GetGlyphCount();
+
+    DWRITE_FONT_METRICS dwfm;
+    typeface->fDWriteFontFace->GetMetrics(&dwfm);
+
+    info = new SkAdvancedTypefaceMetrics;
+    info->fEmSize = dwfm.designUnitsPerEm;
+    info->fMultiMaster = false;
+    info->fLastGlyphID = SkToU16(glyphCount - 1);
+    info->fStyle = 0;
+
+
+    SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
+    SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
+    hr = typeface->fDWriteFontFamily->GetFamilyNames(&familyNames);
+    hr = typeface->fDWriteFont->GetFaceNames(&faceNames);
+
+    UINT32 familyNameLength;
+    hr = familyNames->GetStringLength(0, &familyNameLength);
+
+    UINT32 faceNameLength;
+    hr = faceNames->GetStringLength(0, &faceNameLength);
+
+    size_t size = familyNameLength+1+faceNameLength+1;
+    SkTDArray<wchar_t> wFamilyName(new wchar_t[size], size);
+    hr = familyNames->GetString(0, wFamilyName.begin(), size);
+    wFamilyName[familyNameLength] = L' ';
+    hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
+
+    size_t str_len = WideCharToMultiByte(CP_UTF8, 0, wFamilyName.begin(), -1, NULL, 0, NULL, NULL);
+    if (0 == str_len) {
+        //TODO: error
+    }
+    SkTDArray<char> familyName(new char[str_len], str_len);
+    str_len = WideCharToMultiByte(CP_UTF8, 0, wFamilyName.begin(), -1, familyName.begin(), str_len, NULL, NULL);
+    if (0 == str_len) {
+        //TODO: error
+    }
+    info->fFontName.set(familyName.begin(), str_len);
+
+    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
+        populate_glyph_to_unicode(typeface->fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
+    }
+
+    DWRITE_FONT_FACE_TYPE fontType = typeface->fDWriteFontFace->GetType();
+    if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
+        fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
+        info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
+    } else {
+        info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
+        info->fItalicAngle = 0;
+        info->fAscent = dwfm.ascent;;
+        info->fDescent = dwfm.descent;
+        info->fStemV = 0;
+        info->fCapHeight = dwfm.capHeight;
+        info->fBBox = SkIRect::MakeEmpty();
+        return info;
+    }
+
+    AutoDWriteTable<SkOTTableHead> headTable(typeface->fDWriteFontFace.get());
+    AutoDWriteTable<SkOTTablePostScript> postTable(typeface->fDWriteFontFace.get());
+    AutoDWriteTable<SkOTTableHorizontalHeader> hheaTable(typeface->fDWriteFontFace.get());
+    AutoDWriteTable<SkOTTableOS2> os2Table(typeface->fDWriteFontFace.get());
+    if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
+        info->fItalicAngle = 0;
+        info->fAscent = dwfm.ascent;;
+        info->fDescent = dwfm.descent;
+        info->fStemV = 0;
+        info->fCapHeight = dwfm.capHeight;
+        info->fBBox = SkIRect::MakeEmpty();
+        return info;
+    }
+
+    //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
+    //but have full width, latin half-width, and half-width kana.
+    bool fixedWidth = (postTable->isFixedPitch &&
+                      (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
+    //Monospace
+    if (fixedWidth) {
+        info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
+    }
+    //Italic
+    if (os2Table->version.v0.fsSelection.field.Italic) {
+        info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
+    }
+    //Symbolic (uses more than base latin).
+    info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
+    //Script
+    if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
+        info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
+    //Serif
+    } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
+               SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
+               SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
+        info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
+    }
+
+    info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
+
+    info->fAscent = SkToS16(dwfm.ascent);
+    info->fDescent = SkToS16(dwfm.descent);
+    info->fCapHeight = SkToS16(dwfm.capHeight);
+
+    info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
+                                    (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
+                                    (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
+                                    (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
+
+    //TODO: is this even desired? It seems PDF only wants this value for Type1
+    //fonts, and we only get here for TrueType fonts.
+    info->fStemV = 0;
+    /*
+    // Figure out a good guess for StemV - Min width of i, I, !, 1.
+    // This probably isn't very good with an italic font.
+    int16_t min_width = SHRT_MAX;
+    info->fStemV = 0;
+    char stem_chars[] = {'i', 'I', '!', '1'};
+    for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
+        ABC abcWidths;
+        if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
+            int16_t width = abcWidths.abcB;
+            if (width > 0 && width < min_width) {
+                min_width = width;
+                info->fStemV = min_width;
+            }
+        }
+    }
+    */
+    
+    // If Restricted, the font may not be embedded in a document.
+    // If not Restricted, the font can be embedded.
+    // If PreviewPrint, the embedding is read-only.
+    if (os2Table->version.v0.fsType.field.Restricted) {
+        info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
+    } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
+        if (fixedWidth) {
+            appendRange(&info->fGlyphWidths, 0);
+            int16_t advance;
+            getWidthAdvance(typeface->fDWriteFontFace.get(), 1, &advance);
+            info->fGlyphWidths->fAdvance.append(1, &advance);
+            finishRange(info->fGlyphWidths.get(), 0,
+                        SkAdvancedTypefaceMetrics::WidthRange::kDefault);
+        } else {
+            info->fGlyphWidths.reset(
+                getAdvanceData(typeface->fDWriteFontFace.get(),
+                               glyphCount,
+                               glyphIDs,
+                               glyphIDsCount,
+                               getWidthAdvance));
+        }
+    }
+
+    return info;
+}
diff --git a/src/utils/SkFloatUtils.h b/src/utils/SkFloatUtils.h
new file mode 100644
index 0000000..101aac7
--- /dev/null
+++ b/src/utils/SkFloatUtils.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFloatUtils_DEFINED
+#define SkFloatUtils_DEFINED
+
+#include "SkTypes.h"
+#include <limits.h>
+#include <float.h>
+
+template <size_t size>
+class SkTypeWithSize {
+public:
+    // Prevents using SkTypeWithSize<N> with non-specialized N.
+    typedef void UInt;
+};
+
+template <>
+class SkTypeWithSize<32> {
+public:
+    typedef uint32_t UInt;
+};
+
+template <>
+class SkTypeWithSize<64> {
+public:
+    typedef uint64_t UInt;
+};
+
+template <typename RawType>
+struct SkNumericLimits {
+    static const int digits = 0;
+};
+
+template <>
+struct SkNumericLimits<double> {
+    static const int digits = DBL_MANT_DIG;
+};
+
+template <>
+struct SkNumericLimits<float> {
+    static const int digits = FLT_MANT_DIG;
+};
+
+//See
+//http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison/3423299#3423299
+//http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-internal.h
+//http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+
+template <typename RawType, unsigned int ULPs>
+class SkFloatingPoint {
+public:
+    /** Bits is a unsigned integer the same size as the floating point number. */
+    typedef typename SkTypeWithSize<sizeof(RawType) * CHAR_BIT>::UInt Bits;
+
+    /** # of bits in a number. */
+    static const size_t kBitCount = CHAR_BIT * sizeof(RawType);
+
+    /** # of fraction bits in a number. */
+    static const size_t kFractionBitCount = SkNumericLimits<RawType>::digits - 1;
+
+    /** # of exponent bits in a number. */
+    static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+    /** The mask for the sign bit. */
+    static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+    /** The mask for the fraction bits. */
+    static const Bits kFractionBitMask =
+        ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+    /** The mask for the exponent bits. */
+    static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+    /** How many ULP's (Units in the Last Place) to tolerate when comparing. */
+    static const size_t kMaxUlps = ULPs;
+
+    /**
+     *  Constructs a FloatingPoint from a raw floating-point number.
+     *
+     *  On an Intel CPU, passing a non-normalized NAN (Not a Number)
+     *  around may change its bits, although the new value is guaranteed
+     *  to be also a NAN.  Therefore, don't expect this constructor to
+     *  preserve the bits in x when x is a NAN.
+     */
+    explicit SkFloatingPoint(const RawType& x) { fU.value = x; }
+
+    /** Returns the exponent bits of this number. */
+    Bits exponent_bits() const { return kExponentBitMask & fU.bits; }
+
+    /** Returns the fraction bits of this number. */
+    Bits fraction_bits() const { return kFractionBitMask & fU.bits; }
+
+    /** Returns true iff this is NAN (not a number). */
+    bool is_nan() const {
+        // It's a NAN if both of the folloowing are true:
+        // * the exponent bits are all ones
+        // * the fraction bits are not all zero.
+        return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+    }
+
+    /**
+     *  Returns true iff this number is at most kMaxUlps ULP's away from ths.
+     *  In particular, this function:
+     *   - returns false if either number is (or both are) NAN.
+     *   - treats really large numbers as almost equal to infinity.
+     *   - thinks +0.0 and -0.0 are 0 DLP's apart.
+     */
+    bool AlmostEquals(const SkFloatingPoint& rhs) const {
+        // Any comparison operation involving a NAN must return false.
+        if (is_nan() || rhs.is_nan()) return false;
+
+        const Bits dist = DistanceBetweenSignAndMagnitudeNumbers(fU.bits,
+                                                                 rhs.fU.bits);
+        //SkDEBUGF(("(%f, %f, %d) ", u_.value_, rhs.u_.value_, dist));
+        return dist <= kMaxUlps;
+    }
+
+private:
+    /** The data type used to store the actual floating-point number. */
+    union FloatingPointUnion {
+        /** The raw floating-point number. */
+        RawType value;
+        /** The bits that represent the number. */
+        Bits bits;
+    };
+
+    /**
+     *  Converts an integer from the sign-and-magnitude representation to
+     *  the biased representation. More precisely, let N be 2 to the
+     *  power of (kBitCount - 1), an integer x is represented by the
+     *  unsigned number x + N.
+     *
+     *  For instance,
+     *
+     *    -N + 1 (the most negative number representable using
+     *           sign-and-magnitude) is represented by 1;
+     *    0      is represented by N; and
+     *    N - 1  (the biggest number representable using
+     *           sign-and-magnitude) is represented by 2N - 1.
+     *
+     *  Read http://en.wikipedia.org/wiki/Signed_number_representations
+     *  for more details on signed number representations.
+     */
+    static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+        if (kSignBitMask & sam) {
+            // sam represents a negative number.
+            return ~sam + 1;
+        } else {
+            // sam represents a positive number.
+            return kSignBitMask | sam;
+        }
+    }
+
+    /**
+     *  Given two numbers in the sign-and-magnitude representation,
+     *  returns the distance between them as an unsigned number.
+     */
+    static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+                                                       const Bits &sam2) {
+        const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+        const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+        return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+    }
+
+    FloatingPointUnion fU;
+};
+
+#endif
diff --git a/src/utils/win/SkDWriteFontFileStream.cpp b/src/utils/win/SkDWriteFontFileStream.cpp
new file mode 100644
index 0000000..1569158
--- /dev/null
+++ b/src/utils/win/SkDWriteFontFileStream.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTypes.h"
+#include "SkDWriteFontFileStream.h"
+#include "SkHRESULT.h"
+
+#include <dwrite.h>
+#include <limits>
+
+///////////////////////////////////////////////////////////////////////////////
+//  SkIDWriteFontFileStream
+
+SkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream)
+    : fFontFileStream(fontFileStream)
+    , fPos(0)
+    , fLockedMemory(NULL)
+    , fFragmentLock(NULL) {
+    fontFileStream->AddRef();
+}
+
+SkDWriteFontFileStream::~SkDWriteFontFileStream() {
+    if (fFragmentLock) {
+        fFontFileStream->ReleaseFileFragment(fFragmentLock);
+    }
+}
+
+const void* SkDWriteFontFileStream::getMemoryBase() {
+    if (fLockedMemory) {
+        return fLockedMemory;
+    }
+
+    UINT64 fileSize;
+    HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size");
+    HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock),
+         "Could not lock file fragment.");
+    return fLockedMemory;
+}
+
+bool SkDWriteFontFileStream::rewind() {
+    fPos = 0;
+    return true;
+}
+
+size_t SkDWriteFontFileStream::read(void* buffer, size_t size) {
+    HRESULT hr = S_OK;
+
+    if (NULL == buffer) {
+        UINT64 realFileSize = 0;
+        hr = fFontFileStream->GetFileSize(&realFileSize);
+        if (realFileSize > (std::numeric_limits<size_t>::max)()) {
+            return 0;
+        }
+        size_t fileSize = static_cast<size_t>(realFileSize);
+        if (size == 0) {
+            return fileSize;
+        } else {
+            if (fPos + size > fileSize) {
+                size_t skipped = fileSize - fPos;
+                fPos = fileSize;
+                return skipped;
+            } else {
+                fPos += size;
+                return size;
+            }
+        }
+    }
+
+    const void* start;
+    void* fragmentLock;
+    hr = fFontFileStream->ReadFileFragment(&start, fPos, size, &fragmentLock);
+    if (SUCCEEDED(hr)) {
+        memcpy(buffer, start, size);
+        fFontFileStream->ReleaseFileFragment(fragmentLock);
+        fPos += size;
+        return size;
+    }
+
+    //The read may have failed because we asked for too much data.
+    UINT64 realFileSize = 0;
+    hr = fFontFileStream->GetFileSize(&realFileSize);
+    if (realFileSize > (std::numeric_limits<size_t>::max)()) {
+        return 0;
+    }
+    size_t fileSize = static_cast<size_t>(realFileSize);
+    if (fPos + size > fileSize) {
+        size_t read = fileSize - fPos;
+        hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock);
+        if (SUCCEEDED(hr)) {
+            memcpy(buffer, start, read);
+            fFontFileStream->ReleaseFileFragment(fragmentLock);
+            fPos = fileSize;
+            return read;
+        }
+        return 0;
+    } else {
+        //This means we were within bounds, but failed for some other reason.
+        return 0;
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//  SkIDWriteFontFileStreamWrapper
+
+HRESULT SkDWriteFontFileStreamWrapper::Create(SkStream* stream, SkDWriteFontFileStreamWrapper** streamFontFileStream) {
+    *streamFontFileStream = new SkDWriteFontFileStreamWrapper(stream);
+    if (NULL == streamFontFileStream) {
+        return E_OUTOFMEMORY;
+    }
+    return S_OK;
+}
+
+SkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStream* stream)
+    : fRefCount(1), fStream(stream) {
+    stream->ref();
+}
+
+HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
+    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
+        *ppvObject = this;
+        AddRef();
+        return S_OK;
+    } else {
+        *ppvObject = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::AddRef() {
+    return InterlockedIncrement(&fRefCount);
+}
+
+ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::Release() {
+    ULONG newCount = InterlockedDecrement(&fRefCount);
+    if (0 == newCount) {
+        delete this;
+    }
+    return newCount;
+}
+
+HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
+    void const** fragmentStart,
+    UINT64 fileOffset,
+    UINT64 fragmentSize,
+    void** fragmentContext)
+{
+    // The loader is responsible for doing a bounds check.
+    UINT64 fileSize;
+    this->GetFileSize(&fileSize);
+    if (fileOffset > fileSize || fragmentSize > fileSize - fileOffset) {
+        *fragmentStart = NULL;
+        *fragmentContext = NULL;
+        return E_FAIL;
+    }
+
+    if (fileOffset + fragmentSize > (std::numeric_limits<size_t>::max)()) {
+        return E_FAIL;
+    }
+
+    const void* data = fStream->getMemoryBase();
+    if (NULL != data) {
+        *fragmentStart = static_cast<BYTE const*>(data) + static_cast<size_t>(fileOffset);
+        *fragmentContext = NULL;
+
+    } else {
+        //May be called from multiple threads.
+        SkAutoMutexAcquire ama(fStreamMutex);
+
+        *fragmentStart = NULL;
+        *fragmentContext = NULL;
+
+        if (!fStream->rewind()) {
+            return E_FAIL;
+        }
+        if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) {
+            return E_FAIL;
+        }
+        SkAutoTDeleteArray<uint8_t> streamData(new uint8_t[static_cast<size_t>(fragmentSize)]);
+        if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
+            return E_FAIL;
+        }
+
+        *fragmentStart = streamData.get();
+        *fragmentContext = streamData.detach();
+    }
+    return S_OK;
+}
+
+void STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
+    if (NULL == fragmentContext) {
+        return;
+    }
+    delete [] fragmentContext;
+}
+
+HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
+    *fileSize = fStream->getLength();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) {
+    // The concept of last write time does not apply to this loader.
+    *lastWriteTime = 0;
+    return E_NOTIMPL;
+}
diff --git a/src/utils/win/SkDWriteFontFileStream.h b/src/utils/win/SkDWriteFontFileStream.h
new file mode 100644
index 0000000..cd5787e
--- /dev/null
+++ b/src/utils/win/SkDWriteFontFileStream.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDWriteFontFileStream_DEFINED
+#define SkDWriteFontFileStream_DEFINED
+
+#include "SkTypes.h"
+
+#include "SkStream.h"
+#include "SkTScopedComPtr.h"
+
+#include <dwrite.h>
+
+/**
+ *  An SkStream backed by an IDWriteFontFileStream.
+ *  This allows Skia code to read an IDWriteFontFileStream.
+ */
+class SkDWriteFontFileStream : public SkStream {
+public:
+    explicit SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream);
+    virtual ~SkDWriteFontFileStream();
+    
+    virtual bool rewind() SK_OVERRIDE;
+    virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
+    virtual const void* getMemoryBase() SK_OVERRIDE;
+
+private:
+    SkTScopedComPtr<IDWriteFontFileStream> fFontFileStream;
+    size_t fPos;
+    const void* fLockedMemory;
+    void* fFragmentLock;
+};
+
+/**
+ *  An IDWriteFontFileStream backed by an SkStream.
+ *  This allows DirectWrite to read an SkStream.
+ */
+class SkDWriteFontFileStreamWrapper : public IDWriteFontFileStream {
+public:
+    // IUnknown methods
+    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+    virtual ULONG STDMETHODCALLTYPE AddRef();
+    virtual ULONG STDMETHODCALLTYPE Release();
+
+    // IDWriteFontFileStream methods
+    virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(
+        void const** fragmentStart,
+        UINT64 fileOffset,
+        UINT64 fragmentSize,
+        void** fragmentContext);
+
+    virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
+    virtual HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* fileSize);
+    virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* lastWriteTime);
+
+    static HRESULT Create(SkStream* stream, SkDWriteFontFileStreamWrapper** streamFontFileStream);
+
+private:
+    explicit SkDWriteFontFileStreamWrapper(SkStream* stream);
+
+    ULONG fRefCount;
+    SkAutoTUnref<SkStream> fStream;
+    SkMutex fStreamMutex;
+};
+#endif
diff --git a/src/utils/win/SkDWriteGeometrySink.cpp b/src/utils/win/SkDWriteGeometrySink.cpp
new file mode 100644
index 0000000..4aec3bb
--- /dev/null
+++ b/src/utils/win/SkDWriteGeometrySink.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTypes.h"
+
+#include "SkDWriteGeometrySink.h"
+#include "SkFloatUtils.h"
+#include "SkPath.h"
+
+#include <dwrite.h>
+#include <d2d1.h>
+
+SkDWriteGeometrySink::SkDWriteGeometrySink(SkPath* path) : fRefCount(1), fPath(path) { }
+
+SkDWriteGeometrySink::~SkDWriteGeometrySink() { }
+
+HRESULT STDMETHODCALLTYPE SkDWriteGeometrySink::QueryInterface(REFIID iid, void **object) {
+    if (NULL == object) {
+        return E_INVALIDARG;
+    }
+    if (iid == __uuidof(IUnknown) || iid == __uuidof(IDWriteGeometrySink)) {
+        *object = static_cast<IDWriteGeometrySink*>(this);
+        this->AddRef();
+        return S_OK;
+    } else {
+        *object = NULL;
+        return E_NOINTERFACE; 
+    }
+}
+
+ULONG STDMETHODCALLTYPE SkDWriteGeometrySink::AddRef(void) {
+    return static_cast<ULONG>(InterlockedIncrement(&fRefCount));
+}
+
+ULONG STDMETHODCALLTYPE SkDWriteGeometrySink::Release(void) {
+    ULONG res = static_cast<ULONG>(InterlockedDecrement(&fRefCount));
+    if (0 == res) {
+        delete this;
+    }
+    return res;
+}
+
+void STDMETHODCALLTYPE SkDWriteGeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) {
+    switch (fillMode) {
+    case D2D1_FILL_MODE_ALTERNATE:
+        fPath->setFillType(SkPath::kEvenOdd_FillType);
+        break;
+    case D2D1_FILL_MODE_WINDING:
+        fPath->setFillType(SkPath::kWinding_FillType);
+        break;
+    default:
+        SkASSERT(!"Unknown D2D1_FILL_MODE.");
+        break;
+    }
+}
+
+void STDMETHODCALLTYPE SkDWriteGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) {
+    if (vertexFlags == D2D1_PATH_SEGMENT_NONE || vertexFlags == D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN) {
+        SkASSERT(!"Invalid D2D1_PATH_SEGMENT value.");
+    }
+}
+
+void STDMETHODCALLTYPE SkDWriteGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) {
+    fPath->moveTo(SkFloatToScalar(startPoint.x), SkFloatToScalar(startPoint.y));
+    if (figureBegin == D2D1_FIGURE_BEGIN_HOLLOW) {
+        SkASSERT(!"Invalid D2D1_FIGURE_BEGIN value.");
+    }
+}
+
+void STDMETHODCALLTYPE SkDWriteGeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) {
+    for (const D2D1_POINT_2F *end = &points[pointsCount]; points < end; ++points) {
+        fPath->lineTo(SkFloatToScalar(points->x), SkFloatToScalar(points->y));
+    }
+}
+
+static bool approximately_equal(float a, float b) {
+    const SkFloatingPoint<float, 10> lhs(a), rhs(b);
+    return lhs.AlmostEquals(rhs);
+}
+
+typedef struct {
+    float x;
+    float y;
+} Cubic[4], Quadratic[3];
+
+static bool check_quadratic(const Cubic& cubic, Quadratic& reduction) {
+    float dx10 = cubic[1].x - cubic[0].x;
+    float dx23 = cubic[2].x - cubic[3].x;
+    float midX = cubic[0].x + dx10 * 3 / 2;
+    //NOTE: !approximately_equal(midX - cubic[3].x, dx23 * 3 / 2)
+    //does not work as subnormals get in between the left side and 0.
+    if (!approximately_equal(midX, (dx23 * 3 / 2) + cubic[3].x)) {
+        return false;
+    }
+    float dy10 = cubic[1].y - cubic[0].y;
+    float dy23 = cubic[2].y - cubic[3].y;
+    float midY = cubic[0].y + dy10 * 3 / 2;
+    if (!approximately_equal(midY, (dy23 * 3 / 2) + cubic[3].y)) {
+        return false;
+    }
+    reduction[0] = cubic[0];
+    reduction[1].x = midX;
+    reduction[1].y = midY;
+    reduction[2] = cubic[3];
+    return true;
+}
+
+void STDMETHODCALLTYPE SkDWriteGeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) {
+    SkPoint lastPt;
+    fPath->getLastPt(&lastPt);
+    D2D1_POINT_2F prevPt = { SkScalarToFloat(lastPt.fX), SkScalarToFloat(lastPt.fY) };
+
+    for (const D2D1_BEZIER_SEGMENT *end = &beziers[beziersCount]; beziers < end; ++beziers) {
+        Cubic cubic = { { prevPt.x, prevPt.y },
+                        { beziers->point1.x, beziers->point1.y },
+                        { beziers->point2.x, beziers->point2.y },
+                        { beziers->point3.x, beziers->point3.y }, };
+        Quadratic quadratic;
+        if (check_quadratic(cubic, quadratic)) {
+            fPath->quadTo(SkFloatToScalar(quadratic[1].x), SkFloatToScalar(quadratic[1].y),
+                          SkFloatToScalar(quadratic[2].x), SkFloatToScalar(quadratic[2].y));
+        } else {
+            fPath->cubicTo(SkFloatToScalar(beziers->point1.x), SkFloatToScalar(beziers->point1.y),
+                           SkFloatToScalar(beziers->point2.x), SkFloatToScalar(beziers->point2.y),
+                           SkFloatToScalar(beziers->point3.x), SkFloatToScalar(beziers->point3.y));
+        }
+        prevPt = beziers->point3;
+    }
+}
+
+void STDMETHODCALLTYPE SkDWriteGeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) {
+    fPath->close();
+}
+
+HRESULT SkDWriteGeometrySink::Close() {
+    return S_OK;
+}
+
+HRESULT SkDWriteGeometrySink::Create(SkPath* path, IDWriteGeometrySink** geometryToPath) {
+    *geometryToPath = new SkDWriteGeometrySink(path);
+    return S_OK;
+}
diff --git a/src/utils/win/SkDWriteGeometrySink.h b/src/utils/win/SkDWriteGeometrySink.h
new file mode 100644
index 0000000..99a3262
--- /dev/null
+++ b/src/utils/win/SkDWriteGeometrySink.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDWriteToPath_DEFINED
+#define SkDWriteToPath_DEFINED
+
+#include "SkTypes.h"
+
+class SkPath;
+
+#include <dwrite.h>
+#include <d2d1.h>
+
+class SkDWriteGeometrySink : public IDWriteGeometrySink {
+private:
+    LONG fRefCount;
+    SkPath* fPath;
+
+    SkDWriteGeometrySink(const SkDWriteGeometrySink&);
+    SkDWriteGeometrySink& operator=(const SkDWriteGeometrySink&);
+
+protected:
+    explicit SkDWriteGeometrySink(SkPath* path);
+    virtual ~SkDWriteGeometrySink();
+
+public:
+    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object) SK_OVERRIDE;
+    virtual ULONG STDMETHODCALLTYPE AddRef(void) SK_OVERRIDE;
+    virtual ULONG STDMETHODCALLTYPE Release(void) SK_OVERRIDE;
+
+    virtual void STDMETHODCALLTYPE SetFillMode(D2D1_FILL_MODE fillMode) SK_OVERRIDE;
+    virtual void STDMETHODCALLTYPE SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) SK_OVERRIDE;
+    virtual void STDMETHODCALLTYPE BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) SK_OVERRIDE;
+    virtual void STDMETHODCALLTYPE AddLines(const D2D1_POINT_2F *points, UINT pointsCount) SK_OVERRIDE;
+    virtual void STDMETHODCALLTYPE AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) SK_OVERRIDE;
+    virtual void STDMETHODCALLTYPE EndFigure(D2D1_FIGURE_END figureEnd) SK_OVERRIDE;
+    virtual HRESULT STDMETHODCALLTYPE Close() SK_OVERRIDE;
+
+    static HRESULT Create(SkPath* path, IDWriteGeometrySink** geometryToPath);
+};
+
+#endif