refactoring for SK_FONTHOST_USES_FONTMGR option

BUG=
R=bungeman@google.com

Review URL: https://codereview.chromium.org/21149008

git-svn-id: http://skia.googlecode.com/svn/trunk@10440 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
index 4c5013f..e847b76 100644
--- a/include/core/SkFontHost.h
+++ b/include/core/SkFontHost.h
@@ -12,6 +12,8 @@
 
 #include "SkTypeface.h"
 
+//#define SK_FONTHOST_USES_FONTMGR
+
 class SkDescriptor;
 class SkScalerContext;
 struct SkScalerContextRec;
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index 429a24b..fccbe1f 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -240,6 +240,17 @@
     SkStream* openStream(int* ttcIndex) const;
 
     /**
+     *  Search within this typeface's family for a best match to the
+     *  specified style, and return a ref to that typeface. Note: the
+     *  returned object could be this, if it is the best match, or it
+     *  could be a different typeface. Either way, the caller must balance
+     *  this call with unref() on the returned object.
+     *
+     *  Will never return NULL.
+     */
+    SkTypeface* refMatchingStyle(Style) const;
+
+    /**
      *  Return a scalercontext for the given descriptor. If this fails, then
      *  if allowFailure is true, this returns NULL, else it returns a
      *  dummy scalercontext that will not crash, but will draw nothing.
@@ -287,6 +298,13 @@
     virtual size_t onGetTableData(SkFontTableTag, size_t offset,
                                   size_t length, void* data) const;
 
+    // TODO: make this pure-virtual when all ports have overridden it
+    virtual SkTypeface* onRefMatchingStyle(Style styleBits) const {
+        SkASSERT(!"unimplemented");
+        this->ref();
+        return const_cast<SkTypeface*>(this);
+    }
+
 private:
     SkFontID    fUniqueID;
     Style       fStyle;
diff --git a/include/ports/SkFontMgr.h b/include/ports/SkFontMgr.h
index 09df51e..d243825 100644
--- a/include/ports/SkFontMgr.h
+++ b/include/ports/SkFontMgr.h
@@ -31,6 +31,8 @@
     typedef SkRefCnt INHERITED;
 };
 
+class SkTypeface;
+
 class SK_API SkFontMgr : public SkRefCnt {
 public:
     SK_DECLARE_INST_COUNT(SkFontMgr)
@@ -73,6 +75,9 @@
      */
     SkTypeface* createFromFile(const char path[], int ttcIndex = 0);
 
+    SkTypeface* legacyCreateTypeface(const char familyName[],
+                                     unsigned typefaceStyleBits);
+
     /**
      *  Return a ref to the default fontmgr. The caller must call unref() on
      *  the returned object.
@@ -95,6 +100,9 @@
     virtual SkTypeface* onCreateFromStream(SkStream*, int ttcIndex) = 0;
     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) = 0;
 
+    // TODO: make this pure-virtual once all ports know about it
+    virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
+                                               unsigned styleBits);
 private:
     static SkFontMgr* Factory();    // implemented by porting layer
 
diff --git a/src/core/SkFontHost.cpp b/src/core/SkFontHost.cpp
index 734b3aa..11f6813 100644
--- a/src/core/SkFontHost.cpp
+++ b/src/core/SkFontHost.cpp
@@ -68,7 +68,6 @@
 
 #include "SkFontMgr.h"
 
-
 SK_DEFINE_INST_COUNT(SkFontStyleSet)
 
 class SkEmptyFontStyleSet : public SkFontStyleSet {
@@ -174,6 +173,17 @@
     return this->onCreateFromFile(path, ttcIndex);
 }
 
+SkTypeface* SkFontMgr::legacyCreateTypeface(const char familyName[],
+                                            unsigned styleBits) {
+    return this->onLegacyCreateTypeface(familyName, styleBits);
+}
+
+SkTypeface* SkFontMgr::onLegacyCreateTypeface(const char familyName[],
+                                              unsigned styleBits) {
+    SkASSERT(!"unimplemented");
+    return NULL;
+}
+
 SkFontMgr* SkFontMgr::RefDefault() {
     static SkFontMgr* gFM;
     if (NULL == gFM) {
@@ -185,3 +195,43 @@
     }
     return SkRef(gFM);
 }
+
+//////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_FONTHOST_USES_FONTMGR
+
+#if 0
+static SkFontStyle TypefaceStyleBitsToFontStyle(SkTypeface::Style styleBits) {
+    SkFontStyle::Weight weight = (styleBits & SkTypeface::kBold) ?
+                                     SkFontStyle::kBold_Weight :
+                                     SkFontStyle::kNormal_Weight;
+    SkFontStyle::Width width = SkFontStyle::kNormal_Width;
+    SkFontStyle::Slant slant = (styleBits & SkTypeface::kItalic) ?
+                                     SkFontStyle::kUpright_Slant :
+                                     SkFontStyle::kItalic_Slant;
+    return SkFontStyle(weight, width, slant);
+}
+#endif
+
+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
+                                       const char familyName[],
+                                       SkTypeface::Style style) {
+    if (familyFace) {
+        return familyFace->refMatchingStyle(style);
+    } else {
+        SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+        return fm->legacyCreateTypeface(familyName, style);
+    }
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
+    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    return fm->createFromFile(path);
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
+    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    return fm->createFromStream(stream);
+}
+
+#endif
diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp
index bea7985..915b0e3 100644
--- a/src/core/SkTypeface.cpp
+++ b/src/core/SkTypeface.cpp
@@ -209,6 +209,10 @@
     return this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
 }
 
+SkTypeface* SkTypeface::refMatchingStyle(Style style) const {
+    return this->onRefMatchingStyle(style);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 2586dfd..381c20a 100755
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -250,6 +250,7 @@
     virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
     virtual int onCountGlyphs() const SK_OVERRIDE;
     virtual int onGetUPEM() const SK_OVERRIDE;
+    virtual SkTypeface* onRefMatchingStyle(Style) const SK_OVERRIDE;
 };
 
 class FontMemResourceTypeface : public LogFontTypeface {
@@ -522,10 +523,10 @@
 //////////////////////////////////////////////////////////////////////////////
 #define BUFFERSIZE (1 << 13)
 
-class SkScalerContext_Windows : public SkScalerContext {
+class SkScalerContext_GDI : public SkScalerContext {
 public:
-    SkScalerContext_Windows(SkTypeface*, const SkDescriptor* desc);
-    virtual ~SkScalerContext_Windows();
+    SkScalerContext_GDI(SkTypeface*, const SkDescriptor* desc);
+    virtual ~SkScalerContext_GDI();
 
     // Returns true if the constructor was able to complete all of its
     // initializations (which may include calling GDI).
@@ -592,7 +593,7 @@
     }
 }
 
-SkScalerContext_Windows::SkScalerContext_Windows(SkTypeface* rawTypeface,
+SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
                                                  const SkDescriptor* desc)
         : SkScalerContext(rawTypeface, desc)
         , fDDC(0)
@@ -707,7 +708,7 @@
     if (fTM.tmPitchAndFamily & TMPF_VECTOR) {
         // Truetype or PostScript.
         // Stroked FON also gets here (TMPF_VECTOR), but we don't handle it.
-        fType = SkScalerContext_Windows::kTrueType_Type;
+        fType = SkScalerContext_GDI::kTrueType_Type;
 
         // fPost2x2 is column-major, left handed (y down).
         // XFORM 2x2 is row-major, left handed (y down).
@@ -753,7 +754,7 @@
 
     } else {
         // Assume bitmap
-        fType = SkScalerContext_Windows::kBitmap_Type;
+        fType = SkScalerContext_GDI::kBitmap_Type;
 
         xform.eM11 = 1.0f;
         xform.eM12 = 0.0f;
@@ -773,7 +774,7 @@
     fOffscreen.init(fFont, xform);
 }
 
-SkScalerContext_Windows::~SkScalerContext_Windows() {
+SkScalerContext_GDI::~SkScalerContext_GDI() {
     if (fDDC) {
         ::SelectObject(fDDC, fSavefont);
         ::DeleteDC(fDDC);
@@ -786,11 +787,11 @@
     }
 }
 
-bool SkScalerContext_Windows::isValid() const {
+bool SkScalerContext_GDI::isValid() const {
     return fDDC && fFont;
 }
 
-unsigned SkScalerContext_Windows::generateGlyphCount() {
+unsigned SkScalerContext_GDI::generateGlyphCount() {
     if (fGlyphCount < 0) {
         fGlyphCount = calculateGlyphCount(
                           fDDC, static_cast<const LogFontTypeface*>(this->getTypeface())->fLogFont);
@@ -798,7 +799,7 @@
     return fGlyphCount;
 }
 
-uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
+uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar uni) {
     uint16_t index = 0;
     WCHAR c[2];
     // TODO(ctguil): Support characters that generate more than one glyph.
@@ -823,14 +824,14 @@
     return index;
 }
 
-void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
+void SkScalerContext_GDI::generateAdvance(SkGlyph* glyph) {
     this->generateMetrics(glyph);
 }
 
-void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
+void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
     SkASSERT(fDDC);
 
-    if (fType == SkScalerContext_Windows::kBitmap_Type) {
+    if (fType == SkScalerContext_GDI::kBitmap_Type) {
         SIZE size;
         WORD glyphs = glyph->getGlyphID(0);
         if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
@@ -918,7 +919,7 @@
 }
 
 static const MAT2 gMat2Identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
-void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
+void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
     if (!(mx || my)) {
       return;
     }
@@ -933,7 +934,7 @@
     SkASSERT(fDDC);
 
 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
-    if (fType == SkScalerContext_Windows::kBitmap_Type) {
+    if (fType == SkScalerContext_GDI::kBitmap_Type) {
 #endif
         if (mx) {
             mx->fTop = SkIntToScalar(-fTM.tmAscent);
@@ -1252,7 +1253,7 @@
     return x - (x >> 8);
 }
 
-void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
+void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) {
     SkASSERT(fDDC);
 
     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
@@ -1602,7 +1603,7 @@
     }
 }
 
-DWORD SkScalerContext_Windows::getGDIGlyphPath(const SkGlyph& glyph, UINT flags,
+DWORD SkScalerContext_GDI::getGDIGlyphPath(const SkGlyph& glyph, UINT flags,
                                                SkAutoSTMalloc<BUFFERSIZE, uint8_t>* glyphbuf)
 {
     GLYPHMETRICS gm;
@@ -1639,7 +1640,7 @@
     return total_size;
 }
 
-void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
+void SkScalerContext_GDI::generatePath(const SkGlyph& glyph, SkPath* path) {
     SkASSERT(&glyph && path);
     SkASSERT(fDDC);
 
@@ -1984,10 +1985,6 @@
     return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference);
 }
 
-SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
-    return create_from_stream(stream);
-}
-
 SkStream* LogFontTypeface::onOpenStream(int* ttcIndex) const {
     *ttcIndex = 0;
 
@@ -2054,7 +2051,7 @@
 }
 
 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
-    SkScalerContext_Windows* ctx = SkNEW_ARGS(SkScalerContext_Windows,
+    SkScalerContext_GDI* ctx = SkNEW_ARGS(SkScalerContext_GDI,
                                                 (const_cast<LogFontTypeface*>(this), desc));
     if (!ctx->isValid()) {
         SkDELETE(ctx);
@@ -2063,36 +2060,6 @@
     return ctx;
 }
 
-/** 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) {
-    LOGFONT lf;
-    if (NULL == familyFace && NULL == familyName) {
-        lf = get_default_font();
-    } else if (familyFace) {
-        LogFontTypeface* face = (LogFontTypeface*)familyFace;
-        lf = face->fLogFont;
-    } else {
-        logfont_for_name(familyName, &lf);
-    }
-    setStyle(&lf, style);
-    return SkCreateTypefaceFromLOGFONT(lf);
-}
-
-SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
-    SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
-    return stream.get() ? CreateTypefaceFromStream(stream) : NULL;
-}
-
 void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
@@ -2147,6 +2114,26 @@
     }
 }
 
+static SkTypeface* create_typeface(const SkTypeface* familyFace,
+                                   const char familyName[],
+                                   unsigned styleBits) {
+    LOGFONT lf;
+    if (NULL == familyFace && NULL == familyName) {
+        lf = get_default_font();
+    } else if (familyFace) {
+        LogFontTypeface* face = (LogFontTypeface*)familyFace;
+        lf = face->fLogFont;
+    } else {
+        logfont_for_name(familyName, &lf);
+    }
+    setStyle(&lf, (SkTypeface::Style)styleBits);
+    return SkCreateTypefaceFromLOGFONT(lf);
+}
+
+SkTypeface* LogFontTypeface::onRefMatchingStyle(Style style) const {
+    return create_typeface(this, NULL, style);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkFontMgr.h"
@@ -2314,10 +2301,36 @@
         return this->createFromStream(stream);
     }
 
+    virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
+                                               unsigned styleBits) SK_OVERRIDE {
+        return create_typeface(NULL, familyName, styleBits);
+    }
+
 private:
     SkTDArray<ENUMLOGFONTEX> fLogFontArray;
 };
 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SK_FONTHOST_USES_FONTMGR
+
+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
+                                       const char familyName[],
+                                       SkTypeface::Style styleBits) {
+    return create_typeface(familyFace, familyName, styleBits);
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
+    SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
+    return stream.get() ? CreateTypefaceFromStream(stream) : NULL;
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
+    return create_from_stream(stream);
+}
+
+#endif
+
 SkFontMgr* SkFontMgr::Factory() {
     return SkNEW(SkFontMgrGDI);
 }
diff --git a/src/ports/SkFontHost_win_dw.cpp b/src/ports/SkFontHost_win_dw.cpp
index 3772a09..96bad37 100644
--- a/src/ports/SkFontHost_win_dw.cpp
+++ b/src/ports/SkFontHost_win_dw.cpp
@@ -494,12 +494,13 @@
     virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
     virtual int onCountGlyphs() const SK_OVERRIDE;
     virtual int onGetUPEM() const SK_OVERRIDE;
+    virtual SkTypeface* onRefMatchingStyle(Style) const SK_OVERRIDE;
 };
 
-class SkScalerContext_Windows : public SkScalerContext {
+class SkScalerContext_DW : public SkScalerContext {
 public:
-    SkScalerContext_Windows(DWriteFontTypeface*, const SkDescriptor* desc);
-    virtual ~SkScalerContext_Windows();
+    SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
+    virtual ~SkScalerContext_DW();
 
 protected:
     virtual unsigned generateGlyphCount() SK_OVERRIDE;
@@ -723,7 +724,7 @@
     return static_cast<DWriteFontTypeface*>(SkTypefaceCache::FindByID(fontID));
 }
 
-SkScalerContext_Windows::SkScalerContext_Windows(DWriteFontTypeface* typeface,
+SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
                                                  const SkDescriptor* desc)
         : SkScalerContext(typeface, desc)
         , fTypeface(SkRef(typeface))
@@ -740,23 +741,23 @@
     fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
 }
 
-SkScalerContext_Windows::~SkScalerContext_Windows() {
+SkScalerContext_DW::~SkScalerContext_DW() {
 }
 
-unsigned SkScalerContext_Windows::generateGlyphCount() {
+unsigned SkScalerContext_DW::generateGlyphCount() {
     if (fGlyphCount < 0) {
         fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
     }
     return fGlyphCount;
 }
 
-uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
+uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
     uint16_t index = 0;
     fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
     return index;
 }
 
-void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
+void SkScalerContext_DW::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.
@@ -791,7 +792,7 @@
     glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
 }
 
-void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
+void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
     glyph->fWidth = 0;
 
     this->generateAdvance(glyph);
@@ -853,7 +854,7 @@
     glyph->fTop = SkToS16(bbox.top);
 }
 
-void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx,
+void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
                                                   SkPaint::FontMetrics* my) {
     if (!(mx || my))
       return;
@@ -987,7 +988,7 @@
     }
 }
 
-void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
+void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
     SkAutoMutexAcquire ac(gFTMutex);
 
     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
@@ -1026,7 +1027,7 @@
     }
 }
 
-void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
+void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
     SkAutoMutexAcquire ac(gFTMutex);
 
     SkASSERT(&glyph && path);
@@ -1162,10 +1163,6 @@
     return NULL;
 }
 
-SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
-    return create_from_stream(stream, 0);
-}
-
 SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
     *ttcIndex = fDWriteFontFace->GetIndex();
 
@@ -1196,7 +1193,7 @@
 }
 
 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
-    return SkNEW_ARGS(SkScalerContext_Windows, (const_cast<DWriteFontTypeface*>(this), desc));
+    return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
 }
 
 static HRESULT get_by_family_name(const char familyName[], IDWriteFontFamily** fontFamily) {
@@ -1220,55 +1217,6 @@
     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;
-    if (familyFace) {
-        const DWriteFontTypeface* face = static_cast<const DWriteFontTypeface*>(familyFace);
-        *(&fontFamily) = SkRefComPtr(face->fDWriteFontFamily.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());
-}
-
-SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
-    printf("SkFontHost::CreateTypefaceFromFile unimplemented");
-    return NULL;
-}
-
 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
@@ -1564,6 +1512,46 @@
     return info;
 }
 
+static SkTypeface* create_typeface(const SkTypeface* familyFace,
+                                   const char familyName[],
+                                   unsigned style) {
+    HRESULT hr;
+    SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+    if (familyFace) {
+        const DWriteFontTypeface* face = static_cast<const DWriteFontTypeface*>(familyFace);
+        *(&fontFamily) = SkRefComPtr(face->fDWriteFontFamily.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());
+}
+
+SkTypeface* DWriteFontTypeface::onRefMatchingStyle(Style style) const {
+    return create_typeface(this, NULL, style);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkFontMgr.h"
@@ -1720,6 +1708,11 @@
         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
         return this->createFromStream(stream, ttcIndex);
     }
+
+    virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
+                                               unsigned styleBits) SK_OVERRIDE {
+        return create_typeface(NULL, familyName, styleBits);
+    }
 };
 
 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
@@ -1750,6 +1743,27 @@
     }
 }
 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SK_FONTHOST_USES_FONTMGR
+
+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
+                                       const char familyName[],
+                                       SkTypeface::Style style) {
+    return create_typeface(familyFace, familyName, style);
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
+    printf("SkFontHost::CreateTypefaceFromFile unimplemented");
+    return NULL;
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
+    return create_from_stream(stream, 0);
+}
+
+#endif
+
 SkFontMgr* SkFontMgr::Factory() {
     IDWriteFactory* factory;
     HRNM(get_dwrite_factory(&factory), "Could not get factory.");