gfx/skia/trunk/src/ports/SkFontHost_win_dw.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright 2011 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkTypes.h"
     9 #undef GetGlyphIndices
    11 #include "SkAdvancedTypefaceMetrics.h"
    12 #include "SkColorFilter.h"
    13 #include "SkDWriteFontFileStream.h"
    14 #include "SkDWriteGeometrySink.h"
    15 #include "SkDescriptor.h"
    16 #include "SkEndian.h"
    17 #include "SkFontDescriptor.h"
    18 #include "SkFontHost.h"
    19 #include "SkFontMgr.h"
    20 #include "SkFontStream.h"
    21 #include "SkGlyph.h"
    22 #include "SkHRESULT.h"
    23 #include "SkMaskGamma.h"
    24 #include "SkOnce.h"
    25 #include "SkOTTable_head.h"
    26 #include "SkOTTable_hhea.h"
    27 #include "SkOTTable_OS_2.h"
    28 #include "SkOTTable_post.h"
    29 #include "SkPath.h"
    30 #include "SkStream.h"
    31 #include "SkString.h"
    32 #include "SkTScopedComPtr.h"
    33 #include "SkThread.h"
    34 #include "SkTypeface_win.h"
    35 #include "SkTypefaceCache.h"
    36 #include "SkUtils.h"
    38 #include <dwrite.h>
    40 static bool isLCD(const SkScalerContext::Rec& rec) {
    41     return SkMask::kLCD16_Format == rec.fMaskFormat ||
    42            SkMask::kLCD32_Format == rec.fMaskFormat;
    43 }
    45 /** Prefer to use this type to prevent template proliferation. */
    46 typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
    48 /** Converts a utf8 string to a WCHAR string. */
    49 static HRESULT cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) {
    50     int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0);
    51     if (0 == wlen) {
    52         HRM(HRESULT_FROM_WIN32(GetLastError()),
    53             "Could not get length for wchar to utf-8 conversion.");
    54     }
    55     name->reset(wlen);
    56     wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen);
    57     if (0 == wlen) {
    58         HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8.");
    59     }
    60     return S_OK;
    61 }
    63 /** Converts a WCHAR string to a utf8 string. */
    64 static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) {
    65     int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
    66     if (0 == len) {
    67         HRM(HRESULT_FROM_WIN32(GetLastError()),
    68             "Could not get length for utf-8 to wchar conversion.");
    69     }
    70     skname->resize(len - 1);
    72     // TODO: remove after https://code.google.com/p/skia/issues/detail?id=1989 is fixed.
    73     // If we resize to 0 then the skname points to gEmptyRec (the unique empty SkString::Rec).
    74     // gEmptyRec is static const and on Windows this means the value is in a read only page.
    75     // Writing to it in the following call to WideCharToMultiByte will cause an access violation.
    76     if (1 == len) {
    77         return S_OK;
    78     }
    80     len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
    81     if (0 == len) {
    82         HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
    83     }
    84     return S_OK;
    85 }
    87 ///////////////////////////////////////////////////////////////////////////////
    89 static void create_dwrite_factory(IDWriteFactory** factory) {
    90     typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
    91     DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>(
    92         GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
    94     if (!dWriteCreateFactoryProc) {
    95         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
    96         if (!IS_ERROR(hr)) {
    97             hr = ERROR_PROC_NOT_FOUND;
    98         }
    99         HRVM(hr, "Could not get DWriteCreateFactory proc.");
   100     }
   102     HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
   103                                  __uuidof(IDWriteFactory),
   104                                  reinterpret_cast<IUnknown**>(factory)),
   105          "Could not create DirectWrite factory.");
   106 }
   108 static IDWriteFactory* get_dwrite_factory() {
   109     static IDWriteFactory* gDWriteFactory = NULL;
   110     SK_DECLARE_STATIC_ONCE(once);
   111     SkOnce(&once, create_dwrite_factory, &gDWriteFactory);
   113     return gDWriteFactory;
   114 }
   116 ///////////////////////////////////////////////////////////////////////////////
   118 class StreamFontFileLoader;
   120 class SkFontMgr_DirectWrite : public SkFontMgr {
   121 public:
   122     /** localeNameLength must include the null terminator. */
   123     SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
   124                           WCHAR* localeName, int localeNameLength)
   125         : fFontCollection(SkRefComPtr(fontCollection))
   126         , fLocaleName(localeNameLength)
   127     {
   128         memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
   129     }
   131     SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
   132                                              IDWriteFont* font,
   133                                              IDWriteFontFamily* fontFamily,
   134                                              StreamFontFileLoader* = NULL,
   135                                              IDWriteFontCollectionLoader* = NULL) const;
   137 protected:
   138     virtual int onCountFamilies() const SK_OVERRIDE;
   139     virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE;
   140     virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE;
   141     virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE;
   142     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
   143                                            const SkFontStyle& fontstyle) const SK_OVERRIDE;
   144     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
   145                                          const SkFontStyle& fontstyle) const SK_OVERRIDE;
   146     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE;
   147     virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE;
   148     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE;
   149     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
   150                                                unsigned styleBits) const SK_OVERRIDE;
   152 private:
   153     HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
   154     HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const;
   156     void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) const {
   157         SkAutoMutexAcquire ama(fTFCacheMutex);
   158         fTFCache.add(face, requestedStyle, strong);
   159     }
   161     SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) const {
   162         SkAutoMutexAcquire ama(fTFCacheMutex);
   163         SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx);
   164         return typeface;
   165     }
   167     SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
   168     SkSMallocWCHAR fLocaleName;
   169     mutable SkMutex fTFCacheMutex;
   170     mutable SkTypefaceCache fTFCache;
   172     friend class SkFontStyleSet_DirectWrite;
   173 };
   175 class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
   176 public:
   177     SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
   178                                IDWriteFontFamily* fontFamily)
   179         : fFontMgr(SkRef(fontMgr))
   180         , fFontFamily(SkRefComPtr(fontFamily))
   181     { }
   183     virtual int count() SK_OVERRIDE;
   184     virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
   185     virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
   186     virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
   188 private:
   189     SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
   190     SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
   191 };
   193 ///////////////////////////////////////////////////////////////////////////////
   195 class DWriteOffscreen {
   196 public:
   197     DWriteOffscreen() : fWidth(0), fHeight(0) {
   198     }
   200     void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
   201         fFontFace = fontFace;
   202         fFontSize = fontSize;
   203         fXform = xform;
   204     }
   206     const void* draw(const SkGlyph&, bool isBW);
   208 private:
   209     uint16_t fWidth;
   210     uint16_t fHeight;
   211     IDWriteFontFace* fFontFace;
   212     FLOAT fFontSize;
   213     DWRITE_MATRIX fXform;
   214     SkTDArray<uint8_t> fBits;
   215 };
   217 const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
   218     IDWriteFactory* factory = get_dwrite_factory();
   219     SkASSERT(factory != NULL);
   221     if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
   222         fWidth = SkMax32(fWidth, glyph.fWidth);
   223         fHeight = SkMax32(fHeight, glyph.fHeight);
   225         if (isBW) {
   226             fBits.setCount(fWidth * fHeight);
   227         } else {
   228             fBits.setCount(fWidth * fHeight * 3);
   229         }
   230     }
   232     // erase
   233     memset(fBits.begin(), 0, fBits.count());
   235     fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
   236     fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
   238     FLOAT advance = 0.0f;
   240     UINT16 index = glyph.getGlyphID();
   242     DWRITE_GLYPH_OFFSET offset;
   243     offset.advanceOffset = 0.0f;
   244     offset.ascenderOffset = 0.0f;
   246     DWRITE_GLYPH_RUN run;
   247     run.glyphCount = 1;
   248     run.glyphAdvances = &advance;
   249     run.fontFace = fFontFace;
   250     run.fontEmSize = fFontSize;
   251     run.bidiLevel = 0;
   252     run.glyphIndices = &index;
   253     run.isSideways = FALSE;
   254     run.glyphOffsets = &offset;
   256     DWRITE_RENDERING_MODE renderingMode;
   257     DWRITE_TEXTURE_TYPE textureType;
   258     if (isBW) {
   259         renderingMode = DWRITE_RENDERING_MODE_ALIASED;
   260         textureType = DWRITE_TEXTURE_ALIASED_1x1;
   261     } else {
   262         renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
   263         textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
   264     }
   265     SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
   266     HRNM(factory->CreateGlyphRunAnalysis(&run,
   267                                          1.0f, // pixelsPerDip,
   268                                          &fXform,
   269                                          renderingMode,
   270                                          DWRITE_MEASURING_MODE_NATURAL,
   271                                          0.0f, // baselineOriginX,
   272                                          0.0f, // baselineOriginY,
   273                                          &glyphRunAnalysis),
   274          "Could not create glyph run analysis.");
   276     //NOTE: this assumes that the glyph has already been measured
   277     //with an exact same glyph run analysis.
   278     RECT bbox;
   279     bbox.left = glyph.fLeft;
   280     bbox.top = glyph.fTop;
   281     bbox.right = glyph.fLeft + glyph.fWidth;
   282     bbox.bottom = glyph.fTop + glyph.fHeight;
   283     HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
   284                                               &bbox,
   285                                               fBits.begin(),
   286                                               fBits.count()),
   287          "Could not draw mask.");
   288     return fBits.begin();
   289 }
   291 ///////////////////////////////////////////////////////////////////////////////
   293 class StreamFontFileLoader : public IDWriteFontFileLoader {
   294 public:
   295     // IUnknown methods
   296     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
   297     virtual ULONG STDMETHODCALLTYPE AddRef();
   298     virtual ULONG STDMETHODCALLTYPE Release();
   300     // IDWriteFontFileLoader methods
   301     virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
   302         void const* fontFileReferenceKey,
   303         UINT32 fontFileReferenceKeySize,
   304         IDWriteFontFileStream** fontFileStream);
   306     static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
   307         *streamFontFileLoader = new StreamFontFileLoader(stream);
   308         if (NULL == streamFontFileLoader) {
   309             return E_OUTOFMEMORY;
   310         }
   311         return S_OK;
   312     }
   314     SkAutoTUnref<SkStream> fStream;
   316 private:
   317     StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
   319     ULONG fRefCount;
   320 };
   322 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
   323     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
   324         *ppvObject = this;
   325         AddRef();
   326         return S_OK;
   327     } else {
   328         *ppvObject = NULL;
   329         return E_NOINTERFACE;
   330     }
   331 }
   333 ULONG StreamFontFileLoader::AddRef() {
   334     return InterlockedIncrement(&fRefCount);
   335 }
   337 ULONG StreamFontFileLoader::Release() {
   338     ULONG newCount = InterlockedDecrement(&fRefCount);
   339     if (0 == newCount) {
   340         delete this;
   341     }
   342     return newCount;
   343 }
   345 HRESULT StreamFontFileLoader::CreateStreamFromKey(
   346     void const* fontFileReferenceKey,
   347     UINT32 fontFileReferenceKeySize,
   348     IDWriteFontFileStream** fontFileStream)
   349 {
   350     SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
   351     HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
   352     *fontFileStream = stream.release();
   353     return S_OK;
   354 }
   356 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
   357 public:
   358     // IUnknown methods
   359     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
   360     virtual ULONG STDMETHODCALLTYPE AddRef();
   361     virtual ULONG STDMETHODCALLTYPE Release();
   363     // IDWriteFontFileEnumerator methods
   364     virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
   365     virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
   367     static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
   368                           StreamFontFileEnumerator** streamFontFileEnumerator) {
   369         *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
   370         if (NULL == streamFontFileEnumerator) {
   371             return E_OUTOFMEMORY;
   372         }
   373         return S_OK;
   374     }
   375 private:
   376     StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
   377     ULONG fRefCount;
   379     SkTScopedComPtr<IDWriteFactory> fFactory;
   380     SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
   381     SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
   382     bool fHasNext;
   383 };
   385 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
   386                                                    IDWriteFontFileLoader* fontFileLoader)
   387     : fRefCount(1)
   388     , fFactory(SkRefComPtr(factory))
   389     , fCurrentFile()
   390     , fFontFileLoader(SkRefComPtr(fontFileLoader))
   391     , fHasNext(true)
   392 { }
   394 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
   395     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
   396         *ppvObject = this;
   397         AddRef();
   398         return S_OK;
   399     } else {
   400         *ppvObject = NULL;
   401         return E_NOINTERFACE;
   402     }
   403 }
   405 ULONG StreamFontFileEnumerator::AddRef() {
   406     return InterlockedIncrement(&fRefCount);
   407 }
   409 ULONG StreamFontFileEnumerator::Release() {
   410     ULONG newCount = InterlockedDecrement(&fRefCount);
   411     if (0 == newCount) {
   412         delete this;
   413     }
   414     return newCount;
   415 }
   417 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
   418     *hasCurrentFile = FALSE;
   420     if (!fHasNext) {
   421         return S_OK;
   422     }
   423     fHasNext = false;
   425     UINT32 dummy = 0;
   426     HR(fFactory->CreateCustomFontFileReference(
   427             &dummy, //cannot be NULL
   428             sizeof(dummy), //even if this is 0
   429             fFontFileLoader.get(),
   430             &fCurrentFile));
   432     *hasCurrentFile = TRUE;
   433     return S_OK;
   434 }
   436 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
   437     if (fCurrentFile.get() == NULL) {
   438         *fontFile = NULL;
   439         return E_FAIL;
   440     }
   442     *fontFile = SkRefComPtr(fCurrentFile.get());
   443     return  S_OK;
   444 }
   446 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
   447 public:
   448     // IUnknown methods
   449     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
   450     virtual ULONG STDMETHODCALLTYPE AddRef();
   451     virtual ULONG STDMETHODCALLTYPE Release();
   453     // IDWriteFontCollectionLoader methods
   454     virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
   455         IDWriteFactory* factory,
   456         void const* collectionKey,
   457         UINT32 collectionKeySize,
   458         IDWriteFontFileEnumerator** fontFileEnumerator);
   460     static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
   461                           StreamFontCollectionLoader** streamFontCollectionLoader) {
   462         *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
   463         if (NULL == streamFontCollectionLoader) {
   464             return E_OUTOFMEMORY;
   465         }
   466         return S_OK;
   467     }
   468 private:
   469     StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
   470         : fRefCount(1)
   471         , fFontFileLoader(SkRefComPtr(fontFileLoader))
   472     { }
   474     ULONG fRefCount;
   475     SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
   476 };
   478 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
   479     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
   480         *ppvObject = this;
   481         AddRef();
   482         return S_OK;
   483     } else {
   484         *ppvObject = NULL;
   485         return E_NOINTERFACE;
   486     }
   487 }
   489 ULONG StreamFontCollectionLoader::AddRef() {
   490     return InterlockedIncrement(&fRefCount);
   491 }
   493 ULONG StreamFontCollectionLoader::Release() {
   494     ULONG newCount = InterlockedDecrement(&fRefCount);
   495     if (0 == newCount) {
   496         delete this;
   497     }
   498     return newCount;
   499 }
   501 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
   502     IDWriteFactory* factory,
   503     void const* collectionKey,
   504     UINT32 collectionKeySize,
   505     IDWriteFontFileEnumerator** fontFileEnumerator)
   506 {
   507     SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
   508     HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
   509     *fontFileEnumerator = enumerator.release();
   510     return S_OK;
   511 }
   513 ///////////////////////////////////////////////////////////////////////////////
   515 static SkTypeface::Style get_style(IDWriteFont* font) {
   516     int style = SkTypeface::kNormal;
   517     DWRITE_FONT_WEIGHT weight = font->GetWeight();
   518     if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
   519         style |= SkTypeface::kBold;
   520     }
   521     DWRITE_FONT_STYLE angle = font->GetStyle();
   522     if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
   523         style |= SkTypeface::kItalic;
   524     }
   525     return static_cast<SkTypeface::Style>(style);
   526 }
   528 class DWriteFontTypeface : public SkTypeface {
   529 private:
   530     DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
   531                        IDWriteFontFace* fontFace,
   532                        IDWriteFont* font,
   533                        IDWriteFontFamily* fontFamily,
   534                        StreamFontFileLoader* fontFileLoader = NULL,
   535                        IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
   536         : SkTypeface(style, fontID, false)
   537         , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
   538         , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
   539         , fDWriteFontFamily(SkRefComPtr(fontFamily))
   540         , fDWriteFont(SkRefComPtr(font))
   541         , fDWriteFontFace(SkRefComPtr(fontFace))
   542     { }
   544 public:
   545     SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
   546     SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
   547     SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
   548     SkTScopedComPtr<IDWriteFont> fDWriteFont;
   549     SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
   551     static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
   552                                       IDWriteFont* font,
   553                                       IDWriteFontFamily* fontFamily,
   554                                       StreamFontFileLoader* fontFileLoader = NULL,
   555                                       IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
   556         SkTypeface::Style style = get_style(font);
   557         SkFontID fontID = SkTypefaceCache::NewFontID();
   558         return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
   559                                                fontFace, font, fontFamily,
   560                                                fontFileLoader, fontCollectionLoader));
   561     }
   563     ~DWriteFontTypeface() {
   564         if (fDWriteFontCollectionLoader.get() == NULL) return;
   566         IDWriteFactory* factory = get_dwrite_factory();
   567         SkASSERT(factory != NULL);
   568         HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
   569         HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
   570     }
   572 protected:
   573     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
   574     virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
   575     virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
   576     virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
   577                                 SkAdvancedTypefaceMetrics::PerGlyphInfo,
   578                                 const uint32_t*, uint32_t) const SK_OVERRIDE;
   579     virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
   580     virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
   581                                 uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
   582     virtual int onCountGlyphs() const SK_OVERRIDE;
   583     virtual int onGetUPEM() const SK_OVERRIDE;
   584     virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
   585     virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
   586     virtual size_t onGetTableData(SkFontTableTag, size_t offset,
   587                                   size_t length, void* data) const SK_OVERRIDE;
   588 };
   590 class SkScalerContext_DW : public SkScalerContext {
   591 public:
   592     SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
   593     virtual ~SkScalerContext_DW();
   595 protected:
   596     virtual unsigned generateGlyphCount() SK_OVERRIDE;
   597     virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
   598     virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
   599     virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
   600     virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
   601     virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
   602     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
   603                                      SkPaint::FontMetrics* mY) SK_OVERRIDE;
   605 private:
   606     DWriteOffscreen fOffscreen;
   607     DWRITE_MATRIX fXform;
   608     SkAutoTUnref<DWriteFontTypeface> fTypeface;
   609     int fGlyphCount;
   610 };
   612 static bool are_same(IUnknown* a, IUnknown* b) {
   613     SkTScopedComPtr<IUnknown> iunkA;
   614     if (FAILED(a->QueryInterface(&iunkA))) {
   615         return false;
   616     }
   618     SkTScopedComPtr<IUnknown> iunkB;
   619     if (FAILED(b->QueryInterface(&iunkB))) {
   620         return false;
   621     }
   623     return iunkA.get() == iunkB.get();
   624 }
   625 static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
   626     //Check to see if the two fonts are identical.
   627     DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
   628     IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
   629     if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
   630         return true;
   631     }
   633     //Check if the two fonts share the same loader and have the same key.
   634     SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
   635     SkTScopedComPtr<IDWriteFontFace> dwFontFace;
   636     HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
   637     HRB(dwFont->CreateFontFace(&dwFontFace));
   638     if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
   639         return true;
   640     }
   642     UINT32 dwFaceNumFiles;
   643     UINT32 dwNumFiles;
   644     HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
   645     HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
   646     if (dwFaceNumFiles != dwNumFiles) {
   647         return false;
   648     }
   650     SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
   651     SkTScopedComPtr<IDWriteFontFile> dwFontFile;
   652     HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
   653     HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
   655     //for (each file) { //we currently only admit fonts from one file.
   656     SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
   657     SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
   658     HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
   659     HRB(dwFontFile->GetLoader(&dwFontFileLoader));
   660     if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
   661         return false;
   662     }
   663     //}
   665     const void* dwFaceFontRefKey;
   666     UINT32 dwFaceFontRefKeySize;
   667     const void* dwFontRefKey;
   668     UINT32 dwFontRefKeySize;
   669     HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
   670     HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
   671     if (dwFaceFontRefKeySize != dwFontRefKeySize) {
   672         return false;
   673     }
   674     if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
   675         return false;
   676     }
   678     //TODO: better means than comparing name strings?
   679     //NOTE: .tfc and fake bold/italic will end up here.
   680     SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
   681     SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
   682     HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
   683     HRB(dwFont->GetFontFamily(&dwFontFamily));
   685     SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
   686     SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
   687     HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
   688     HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
   690     SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
   691     SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
   692     HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
   693     HRB(dwFont->GetFaceNames(&dwFontNames));
   695     UINT32 dwFaceFontFamilyNameLength;
   696     UINT32 dwFaceFontNameLength;
   697     HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
   698     HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
   700     UINT32 dwFontFamilyNameLength;
   701     UINT32 dwFontNameLength;
   702     HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
   703     HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
   705     if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
   706         dwFaceFontNameLength != dwFontNameLength)
   707     {
   708         return false;
   709     }
   711     SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
   712     SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
   713     HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
   714     HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
   716     SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
   717     SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
   718     HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
   719     HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
   721     return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
   722            wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
   723 }
   725 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
   726                                                  const SkDescriptor* desc)
   727         : SkScalerContext(typeface, desc)
   728         , fTypeface(SkRef(typeface))
   729         , fGlyphCount(-1) {
   731     fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
   732     fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
   733     fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
   734     fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
   735     fXform.dx = 0;
   736     fXform.dy = 0;
   738     fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
   739 }
   741 SkScalerContext_DW::~SkScalerContext_DW() {
   742 }
   744 unsigned SkScalerContext_DW::generateGlyphCount() {
   745     if (fGlyphCount < 0) {
   746         fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
   747     }
   748     return fGlyphCount;
   749 }
   751 uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
   752     uint16_t index = 0;
   753     fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
   754     return index;
   755 }
   757 void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
   758     //Delta is the difference between the right/left side bearing metric
   759     //and where the right/left side bearing ends up after hinting.
   760     //DirectWrite does not provide this information.
   761     glyph->fRsbDelta = 0;
   762     glyph->fLsbDelta = 0;
   764     glyph->fAdvanceX = 0;
   765     glyph->fAdvanceY = 0;
   767     uint16_t glyphId = glyph->getGlyphID();
   768     DWRITE_GLYPH_METRICS gm;
   769     HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
   770          "Could not get design metrics.");
   772     DWRITE_FONT_METRICS dwfm;
   773     fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
   775     SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
   776                                        SkIntToScalar(gm.advanceWidth),
   777                                        SkIntToScalar(dwfm.designUnitsPerEm));
   779     if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
   780         advanceX = SkScalarRoundToScalar(advanceX);
   781     }
   783     SkVector vecs[1] = { { advanceX, 0 } };
   784     SkMatrix mat;
   785     fRec.getMatrixFrom2x2(&mat);
   786     mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
   788     glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
   789     glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
   790 }
   792 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
   793     glyph->fWidth = 0;
   795     this->generateAdvance(glyph);
   797     //Measure raster size.
   798     fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
   799     fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
   801     FLOAT advance = 0;
   803     UINT16 glyphId = glyph->getGlyphID();
   805     DWRITE_GLYPH_OFFSET offset;
   806     offset.advanceOffset = 0.0f;
   807     offset.ascenderOffset = 0.0f;
   809     DWRITE_GLYPH_RUN run;
   810     run.glyphCount = 1;
   811     run.glyphAdvances = &advance;
   812     run.fontFace = fTypeface->fDWriteFontFace.get();
   813     run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
   814     run.bidiLevel = 0;
   815     run.glyphIndices = &glyphId;
   816     run.isSideways = FALSE;
   817     run.glyphOffsets = &offset;
   819     IDWriteFactory* factory = get_dwrite_factory();
   820     SkASSERT(factory != NULL);
   822     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
   823     DWRITE_RENDERING_MODE renderingMode;
   824     DWRITE_TEXTURE_TYPE textureType;
   825     if (isBW) {
   826         renderingMode = DWRITE_RENDERING_MODE_ALIASED;
   827         textureType = DWRITE_TEXTURE_ALIASED_1x1;
   828     } else {
   829         renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
   830         textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
   831     }
   833     SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
   834     HRVM(factory->CreateGlyphRunAnalysis(&run,
   835                                          1.0f, // pixelsPerDip,
   836                                          &fXform,
   837                                          renderingMode,
   838                                          DWRITE_MEASURING_MODE_NATURAL,
   839                                          0.0f, // baselineOriginX,
   840                                          0.0f, // baselineOriginY,
   841                                          &glyphRunAnalysis),
   842          "Could not create glyph run analysis.");
   844     RECT bbox;
   845     HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
   846          "Could not get texture bounds.");
   848     glyph->fWidth = SkToU16(bbox.right - bbox.left);
   849     glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
   850     glyph->fLeft = SkToS16(bbox.left);
   851     glyph->fTop = SkToS16(bbox.top);
   852 }
   854 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
   855                                                   SkPaint::FontMetrics* my) {
   856     if (!(mx || my))
   857       return;
   859     if (mx) {
   860         sk_bzero(mx, sizeof(*mx));
   861     }
   862     if (my) {
   863         sk_bzero(my, sizeof(*my));
   864     }
   866     DWRITE_FONT_METRICS dwfm;
   867     fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
   869     SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
   870     if (mx) {
   871         mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
   872         mx->fAscent = mx->fTop;
   873         mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
   874         mx->fBottom = mx->fDescent;
   875         mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
   876         mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
   877         mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
   878         mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
   880         mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
   881         mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   882     }
   884     if (my) {
   885         my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
   886         my->fAscent = my->fTop;
   887         my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
   888         my->fBottom = my->fDescent;
   889         my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
   890         my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
   891         my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
   892         my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
   894         my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
   895         my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   896     }
   897 }
   899 ///////////////////////////////////////////////////////////////////////////////
   901 #include "SkColorPriv.h"
   903 static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
   904     const int width = glyph.fWidth;
   905     const size_t dstRB = (width + 7) >> 3;
   906     uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
   908     int byteCount = width >> 3;
   909     int bitCount = width & 7;
   911     for (int y = 0; y < glyph.fHeight; ++y) {
   912         if (byteCount > 0) {
   913             for (int i = 0; i < byteCount; ++i) {
   914                 unsigned byte = 0;
   915                 byte |= src[0] & (1 << 7);
   916                 byte |= src[1] & (1 << 6);
   917                 byte |= src[2] & (1 << 5);
   918                 byte |= src[3] & (1 << 4);
   919                 byte |= src[4] & (1 << 3);
   920                 byte |= src[5] & (1 << 2);
   921                 byte |= src[6] & (1 << 1);
   922                 byte |= src[7] & (1 << 0);
   923                 dst[i] = byte;
   924                 src += 8;
   925             }
   926         }
   927         if (bitCount > 0) {
   928             unsigned byte = 0;
   929             unsigned mask = 0x80;
   930             for (int i = 0; i < bitCount; i++) {
   931                 byte |= (src[i]) & mask;
   932                 mask >>= 1;
   933             }
   934             dst[byteCount] = byte;
   935         }
   936         src += bitCount;
   937         dst += dstRB;
   938     }
   939 }
   941 template<bool APPLY_PREBLEND>
   942 static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
   943     const size_t dstRB = glyph.rowBytes();
   944     const U16CPU width = glyph.fWidth;
   945     uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
   947     for (U16CPU y = 0; y < glyph.fHeight; y++) {
   948         for (U16CPU i = 0; i < width; i++) {
   949             U8CPU r = *(src++);
   950             U8CPU g = *(src++);
   951             U8CPU b = *(src++);
   952             dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
   953         }
   954         dst = (uint8_t*)((char*)dst + dstRB);
   955     }
   956 }
   958 template<bool APPLY_PREBLEND>
   959 static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
   960                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   961     const size_t dstRB = glyph.rowBytes();
   962     const U16CPU width = glyph.fWidth;
   963     uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
   965     for (U16CPU y = 0; y < glyph.fHeight; y++) {
   966         for (U16CPU i = 0; i < width; i++) {
   967             U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
   968             U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
   969             U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
   970             dst[i] = SkPack888ToRGB16(r, g, b);
   971         }
   972         dst = (uint16_t*)((char*)dst + dstRB);
   973     }
   974 }
   976 template<bool APPLY_PREBLEND>
   977 static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
   978                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   979     const size_t dstRB = glyph.rowBytes();
   980     const U16CPU width = glyph.fWidth;
   981     SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
   983     for (U16CPU y = 0; y < glyph.fHeight; y++) {
   984         for (U16CPU i = 0; i < width; i++) {
   985             U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
   986             U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
   987             U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
   988             dst[i] = SkPackARGB32(0xFF, r, g, b);
   989         }
   990         dst = (SkPMColor*)((char*)dst + dstRB);
   991     }
   992 }
   994 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
   995     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
   996     const bool isAA = !isLCD(fRec);
   998     //Create the mask.
   999     const void* bits = fOffscreen.draw(glyph, isBW);
  1000     if (!bits) {
  1001         sk_bzero(glyph.fImage, glyph.computeImageSize());
  1002         return;
  1005     //Copy the mask into the glyph.
  1006     const uint8_t* src = (const uint8_t*)bits;
  1007     if (isBW) {
  1008         bilevel_to_bw(src, glyph);
  1009     } else if (isAA) {
  1010         if (fPreBlend.isApplicable()) {
  1011             rgb_to_a8<true>(src, glyph, fPreBlend.fG);
  1012         } else {
  1013             rgb_to_a8<false>(src, glyph, fPreBlend.fG);
  1015     } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
  1016         if (fPreBlend.isApplicable()) {
  1017             rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1018         } else {
  1019             rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1021     } else {
  1022         SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
  1023         if (fPreBlend.isApplicable()) {
  1024             rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1025         } else {
  1026             rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1031 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
  1032     SkASSERT(&glyph && path);
  1034     path->reset();
  1036     SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
  1037     HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
  1038          "Could not create geometry to path converter.");
  1039     uint16_t glyphId = glyph.getGlyphID();
  1040     //TODO: convert to<->from DIUs? This would make a difference if hinting.
  1041     //It may not be needed, it appears that DirectWrite only hints at em size.
  1042     HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
  1043                                        &glyphId,
  1044                                        NULL, //advances
  1045                                        NULL, //offsets
  1046                                        1, //num glyphs
  1047                                        FALSE, //sideways
  1048                                        FALSE, //rtl
  1049                                        geometryToPath.get()),
  1050          "Could not create glyph outline.");
  1052     SkMatrix mat;
  1053     fRec.getMatrixFrom2x2(&mat);
  1054     path->transform(mat);
  1057 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
  1058                                              bool* isLocalStream) const {
  1059     // Get the family name.
  1060     SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
  1061     HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
  1063     UINT32 dwFamilyNamesLength;
  1064     HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
  1066     SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
  1067     HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
  1069     SkString utf8FamilyName;
  1070     HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
  1072     desc->setFamilyName(utf8FamilyName.c_str());
  1073     *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
  1076 static SkUnichar next_utf8(const void** chars) {
  1077     return SkUTF8_NextUnichar((const char**)chars);
  1080 static SkUnichar next_utf16(const void** chars) {
  1081     return SkUTF16_NextUnichar((const uint16_t**)chars);
  1084 static SkUnichar next_utf32(const void** chars) {
  1085     const SkUnichar** uniChars = (const SkUnichar**)chars;
  1086     SkUnichar uni = **uniChars;
  1087     *uniChars += 1;
  1088     return uni;
  1091 typedef SkUnichar (*EncodingProc)(const void**);
  1093 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
  1094     static const EncodingProc gProcs[] = {
  1095         next_utf8, next_utf16, next_utf32
  1096     };
  1097     SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
  1098     return gProcs[enc];
  1101 int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
  1102                                         uint16_t glyphs[], int glyphCount) const
  1104     if (NULL == glyphs) {
  1105         EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
  1106         for (int i = 0; i < glyphCount; ++i) {
  1107             const SkUnichar c = next_ucs4_proc(&chars);
  1108             BOOL exists;
  1109             fDWriteFont->HasCharacter(c, &exists);
  1110             if (!exists) {
  1111                 return i;
  1114         return glyphCount;
  1117     switch (encoding) {
  1118     case SkTypeface::kUTF8_Encoding:
  1119     case SkTypeface::kUTF16_Encoding: {
  1120         static const int scratchCount = 256;
  1121         UINT32 scratch[scratchCount];
  1122         EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
  1123         for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
  1124             int glyphsLeft = glyphCount - baseGlyph;
  1125             int limit = SkTMin(glyphsLeft, scratchCount);
  1126             for (int i = 0; i < limit; ++i) {
  1127                 scratch[i] = next_ucs4_proc(&chars);
  1129             fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
  1131         break;
  1133     case SkTypeface::kUTF32_Encoding: {
  1134         const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
  1135         fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
  1136         break;
  1138     default:
  1139         SK_CRASH();
  1142     for (int i = 0; i < glyphCount; ++i) {
  1143         if (0 == glyphs[i]) {
  1144             return i;
  1147     return glyphCount;
  1150 int DWriteFontTypeface::onCountGlyphs() const {
  1151     return fDWriteFontFace->GetGlyphCount();
  1154 int DWriteFontTypeface::onGetUPEM() const {
  1155     DWRITE_FONT_METRICS metrics;
  1156     fDWriteFontFace->GetMetrics(&metrics);
  1157     return metrics.designUnitsPerEm;
  1160 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
  1161 public:
  1162     /** Takes ownership of the IDWriteLocalizedStrings. */
  1163     explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
  1164         : fIndex(0), fStrings(strings)
  1165     { }
  1167     virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
  1168         if (fIndex >= fStrings->GetCount()) {
  1169             return false;
  1172         // String
  1173         UINT32 stringLength;
  1174         HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
  1175         stringLength += 1;
  1177         SkSMallocWCHAR wString(stringLength);
  1178         HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
  1180         HRB(wchar_to_skstring(wString.get(), &localizedString->fString));
  1182         // Locale
  1183         UINT32 localeLength;
  1184         HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
  1185         localeLength += 1;
  1187         SkSMallocWCHAR wLocale(localeLength);
  1188         HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
  1190         HRB(wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
  1192         ++fIndex;
  1193         return true;
  1196 private:
  1197     UINT32 fIndex;
  1198     SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
  1199 };
  1201 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
  1202     SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
  1203     HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
  1205     return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
  1208 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
  1209     DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
  1210     if (type != DWRITE_FONT_FACE_TYPE_CFF &&
  1211         type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
  1212         type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
  1214         return 0;
  1217     int ttcIndex;
  1218     SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
  1219     return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
  1222 class AutoDWriteTable {
  1223 public:
  1224     AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
  1225         // Any errors are ignored, user must check fExists anyway.
  1226         fontFace->TryGetFontTable(beTag,
  1227             reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
  1229     ~AutoDWriteTable() {
  1230         if (fExists) {
  1231             fFontFace->ReleaseFontTable(fLock);
  1235     const uint8_t* fData;
  1236     UINT32 fSize;
  1237     BOOL fExists;
  1238 private:
  1239     // Borrowed reference, the user must ensure the fontFace stays alive.
  1240     IDWriteFontFace* fFontFace;
  1241     void* fLock;
  1242 };
  1244 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
  1245                                           size_t length, void* data) const
  1247     AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
  1248     if (!table.fExists) {
  1249         return 0;
  1252     if (offset > table.fSize) {
  1253         return 0;
  1255     size_t size = SkTMin(length, table.fSize - offset);
  1256     if (NULL != data) {
  1257         memcpy(data, table.fData + offset, size);
  1260     return size;
  1263 template <typename T> class SkAutoIDWriteUnregister {
  1264 public:
  1265     SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
  1266         : fFactory(factory), fUnregister(unregister)
  1267     { }
  1269     ~SkAutoIDWriteUnregister() {
  1270         if (fUnregister) {
  1271             unregister(fFactory, fUnregister);
  1275     T* detatch() {
  1276         T* old = fUnregister;
  1277         fUnregister = NULL;
  1278         return old;
  1281 private:
  1282     HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
  1283         return factory->UnregisterFontFileLoader(unregister);
  1286     HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
  1287         return factory->UnregisterFontCollectionLoader(unregister);
  1290     IDWriteFactory* fFactory;
  1291     T* fUnregister;
  1292 };
  1294 static SkTypeface* create_from_stream(SkStream* stream, int ttcIndex) {
  1295     IDWriteFactory* factory = get_dwrite_factory();
  1296     if (NULL == factory) {
  1297         return NULL;
  1300     SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
  1301     HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
  1302     HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
  1303     SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
  1304         factory, fontFileLoader.get());
  1306     SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
  1307     HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
  1308     HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
  1309     SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
  1310         factory, fontCollectionLoader.get());
  1312     SkTScopedComPtr<IDWriteFontCollection> fontCollection;
  1313     HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
  1315     // Find the first non-simulated font which has the given ttc index.
  1316     UINT32 familyCount = fontCollection->GetFontFamilyCount();
  1317     for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
  1318         SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  1319         HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
  1321         UINT32 fontCount = fontFamily->GetFontCount();
  1322         for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
  1323             SkTScopedComPtr<IDWriteFont> font;
  1324             HRN(fontFamily->GetFont(fontIndex, &font));
  1325             if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
  1326                 continue;
  1329             SkTScopedComPtr<IDWriteFontFace> fontFace;
  1330             HRN(font->CreateFontFace(&fontFace));
  1332             UINT32 faceIndex = fontFace->GetIndex();
  1333             if (faceIndex == ttcIndex) {
  1334                 return DWriteFontTypeface::Create(fontFace.get(), font.get(), fontFamily.get(),
  1335                                                   autoUnregisterFontFileLoader.detatch(),
  1336                                                   autoUnregisterFontCollectionLoader.detatch());
  1341     return NULL;
  1344 SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
  1345     *ttcIndex = fDWriteFontFace->GetIndex();
  1347     UINT32 numFiles;
  1348     HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
  1349          "Could not get number of font files.");
  1350     if (numFiles != 1) {
  1351         return NULL;
  1354     SkTScopedComPtr<IDWriteFontFile> fontFile;
  1355     HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
  1357     const void* fontFileKey;
  1358     UINT32 fontFileKeySize;
  1359     HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
  1360          "Could not get font file reference key.");
  1362     SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
  1363     HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
  1365     SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
  1366     HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
  1367                                              &fontFileStream),
  1368          "Could not create font file stream.");
  1370     return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
  1373 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
  1374     return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
  1377 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
  1378     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
  1379         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
  1381         rec->fMaskFormat = SkMask::kA8_Format;
  1384     unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
  1385                                   SkScalerContext::kForceAutohinting_Flag |
  1386                                   SkScalerContext::kEmbeddedBitmapText_Flag |
  1387                                   SkScalerContext::kEmbolden_Flag |
  1388                                   SkScalerContext::kLCD_BGROrder_Flag |
  1389                                   SkScalerContext::kLCD_Vertical_Flag;
  1390     rec->fFlags &= ~flagsWeDontSupport;
  1392     SkPaint::Hinting h = rec->getHinting();
  1393     // DirectWrite does not provide for hinting hints.
  1394     h = SkPaint::kSlight_Hinting;
  1395     rec->setHinting(h);
  1397 #if SK_FONT_HOST_USE_SYSTEM_SETTINGS
  1398     IDWriteFactory* factory = get_dwrite_factory();
  1399     if (factory != NULL) {
  1400         SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
  1401         if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
  1402             float gamma = defaultRenderingParams->GetGamma();
  1403             rec->setDeviceGamma(gamma);
  1404             rec->setPaintGamma(gamma);
  1406             rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
  1409 #endif
  1412 ///////////////////////////////////////////////////////////////////////////////
  1413 //PDF Support
  1415 using namespace skia_advanced_typeface_metrics_utils;
  1417 // Construct Glyph to Unicode table.
  1418 // Unicode code points that require conjugate pairs in utf16 are not
  1419 // supported.
  1420 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
  1421 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
  1422 // of calling GetFontUnicodeRange().
  1423 // TODO(bungeman): This never does what anyone wants.
  1424 // What is really wanted is the text to glyphs mapping
  1425 static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
  1426                                       const unsigned glyphCount,
  1427                                       SkTDArray<SkUnichar>* glyphToUnicode) {
  1428     HRESULT hr = S_OK;
  1430     //Do this like free type instead
  1431     UINT32 count = 0;
  1432     for (UINT32 c = 0; c < 0x10FFFF; ++c) {
  1433         UINT16 glyph;
  1434         hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
  1435         if (glyph > 0) {
  1436             ++count;
  1440     SkAutoTArray<UINT32> chars(count);
  1441     count = 0;
  1442     for (UINT32 c = 0; c < 0x10FFFF; ++c) {
  1443         UINT16 glyph;
  1444         hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
  1445         if (glyph > 0) {
  1446             chars[count] = c;
  1447             ++count;
  1451     SkAutoTArray<UINT16> glyph(count);
  1452     fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
  1454     USHORT maxGlyph = 0;
  1455     for (USHORT j = 0; j < count; ++j) {
  1456         if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
  1459     glyphToUnicode->setCount(maxGlyph+1);
  1460     for (USHORT j = 0; j < maxGlyph+1u; ++j) {
  1461         (*glyphToUnicode)[j] = 0;
  1464     //'invert'
  1465     for (USHORT j = 0; j < count; ++j) {
  1466         if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
  1467             (*glyphToUnicode)[glyph[j]] = chars[j];
  1472 static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
  1473     SkASSERT(advance);
  1475     UINT16 glyphId = gId;
  1476     DWRITE_GLYPH_METRICS gm;
  1477     HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
  1479     if (FAILED(hr)) {
  1480         *advance = 0;
  1481         return false;
  1484     *advance = gm.advanceWidth;
  1485     return true;
  1488 template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
  1489 public:
  1490     static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
  1491     AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
  1493     const T* operator->() const { return reinterpret_cast<const T*>(fData); }
  1494 };
  1496 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
  1497         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
  1498         const uint32_t* glyphIDs,
  1499         uint32_t glyphIDsCount) const {
  1501     SkAdvancedTypefaceMetrics* info = NULL;
  1503     HRESULT hr = S_OK;
  1505     const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
  1507     DWRITE_FONT_METRICS dwfm;
  1508     fDWriteFontFace->GetMetrics(&dwfm);
  1510     info = new SkAdvancedTypefaceMetrics;
  1511     info->fEmSize = dwfm.designUnitsPerEm;
  1512     info->fMultiMaster = false;
  1513     info->fLastGlyphID = SkToU16(glyphCount - 1);
  1514     info->fStyle = 0;
  1517     SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
  1518     SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
  1519     hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
  1520     hr = fDWriteFont->GetFaceNames(&faceNames);
  1522     UINT32 familyNameLength;
  1523     hr = familyNames->GetStringLength(0, &familyNameLength);
  1525     UINT32 faceNameLength;
  1526     hr = faceNames->GetStringLength(0, &faceNameLength);
  1528     UINT32 size = familyNameLength+1+faceNameLength+1;
  1529     SkSMallocWCHAR wFamilyName(size);
  1530     hr = familyNames->GetString(0, wFamilyName.get(), size);
  1531     wFamilyName[familyNameLength] = L' ';
  1532     hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
  1534     hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName);
  1536     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
  1537         populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
  1540     DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
  1541     if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
  1542         fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
  1543         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
  1544     } else {
  1545         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
  1546         info->fItalicAngle = 0;
  1547         info->fAscent = dwfm.ascent;;
  1548         info->fDescent = dwfm.descent;
  1549         info->fStemV = 0;
  1550         info->fCapHeight = dwfm.capHeight;
  1551         info->fBBox = SkIRect::MakeEmpty();
  1552         return info;
  1555     AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
  1556     AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
  1557     AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
  1558     AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
  1559     if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
  1560         info->fItalicAngle = 0;
  1561         info->fAscent = dwfm.ascent;;
  1562         info->fDescent = dwfm.descent;
  1563         info->fStemV = 0;
  1564         info->fCapHeight = dwfm.capHeight;
  1565         info->fBBox = SkIRect::MakeEmpty();
  1566         return info;
  1569     //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
  1570     //but have full width, latin half-width, and half-width kana.
  1571     bool fixedWidth = (postTable->isFixedPitch &&
  1572                       (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
  1573     //Monospace
  1574     if (fixedWidth) {
  1575         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
  1577     //Italic
  1578     if (os2Table->version.v0.fsSelection.field.Italic) {
  1579         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
  1581     //Script
  1582     if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
  1583         info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
  1584     //Serif
  1585     } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
  1586                SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
  1587                SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
  1588         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
  1591     info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
  1593     info->fAscent = SkToS16(dwfm.ascent);
  1594     info->fDescent = SkToS16(dwfm.descent);
  1595     info->fCapHeight = SkToS16(dwfm.capHeight);
  1597     info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
  1598                                     (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
  1599                                     (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
  1600                                     (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
  1602     //TODO: is this even desired? It seems PDF only wants this value for Type1
  1603     //fonts, and we only get here for TrueType fonts.
  1604     info->fStemV = 0;
  1605     /*
  1606     // Figure out a good guess for StemV - Min width of i, I, !, 1.
  1607     // This probably isn't very good with an italic font.
  1608     int16_t min_width = SHRT_MAX;
  1609     info->fStemV = 0;
  1610     char stem_chars[] = {'i', 'I', '!', '1'};
  1611     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
  1612         ABC abcWidths;
  1613         if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
  1614             int16_t width = abcWidths.abcB;
  1615             if (width > 0 && width < min_width) {
  1616                 min_width = width;
  1617                 info->fStemV = min_width;
  1621     */
  1623     // If Restricted, the font may not be embedded in a document.
  1624     // If not Restricted, the font can be embedded.
  1625     // If PreviewPrint, the embedding is read-only.
  1626     if (os2Table->version.v0.fsType.field.Restricted) {
  1627         info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
  1628     } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
  1629         if (fixedWidth) {
  1630             appendRange(&info->fGlyphWidths, 0);
  1631             int16_t advance;
  1632             getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
  1633             info->fGlyphWidths->fAdvance.append(1, &advance);
  1634             finishRange(info->fGlyphWidths.get(), 0,
  1635                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
  1636         } else {
  1637             info->fGlyphWidths.reset(
  1638                 getAdvanceData(fDWriteFontFace.get(),
  1639                                glyphCount,
  1640                                glyphIDs,
  1641                                glyphIDsCount,
  1642                                getWidthAdvance));
  1646     return info;
  1649 ///////////////////////////////////////////////////////////////////////////////
  1651 static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
  1652                               SkString* skname) {
  1653     UINT32 nameIndex = 0;
  1654     if (preferedLocale) {
  1655         // Ignore any errors and continue with index 0 if there is a problem.
  1656         BOOL nameExists;
  1657         names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
  1658         if (!nameExists) {
  1659             nameIndex = 0;
  1663     UINT32 nameLength;
  1664     HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
  1665     nameLength += 1;
  1667     SkSMallocWCHAR name(nameLength);
  1668     HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
  1670     HRV(wchar_to_skstring(name.get(), skname));
  1673 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
  1674         IDWriteFontFace* fontFace,
  1675         IDWriteFont* font,
  1676         IDWriteFontFamily* fontFamily,
  1677         StreamFontFileLoader* fontFileLoader,
  1678         IDWriteFontCollectionLoader* fontCollectionLoader) const {
  1679     SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font);
  1680     if (NULL == face) {
  1681         face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
  1682                                           fontFileLoader, fontCollectionLoader);
  1683         if (face) {
  1684             Add(face, get_style(font), fontCollectionLoader != NULL);
  1687     return face;
  1690 int SkFontMgr_DirectWrite::onCountFamilies() const {
  1691     return fFontCollection->GetFontFamilyCount();
  1694 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
  1695     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  1696     HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
  1698     SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
  1699     HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
  1701     get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
  1704 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
  1705     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  1706     HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
  1708     return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
  1711 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
  1712     SkSMallocWCHAR dwFamilyName;
  1713     HRN(cstring_to_wchar(familyName, &dwFamilyName));
  1715     UINT32 index;
  1716     BOOL exists;
  1717     HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
  1718             "Failed while finding family by name.");
  1719     if (!exists) {
  1720         return NULL;
  1723     return this->onCreateStyleSet(index);
  1726 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
  1727                                                       const SkFontStyle& fontstyle) const {
  1728     SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
  1729     return sset->matchStyle(fontstyle);
  1732 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
  1733                                                     const SkFontStyle& fontstyle) const {
  1734     SkString familyName;
  1735     SkFontStyleSet_DirectWrite sset(
  1736         this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
  1737     );
  1738     return sset.matchStyle(fontstyle);
  1741 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const {
  1742     return create_from_stream(stream, ttcIndex);
  1745 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
  1746     SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
  1747     return this->createFromStream(stream, ttcIndex);
  1750 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
  1751     SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
  1752     return this->createFromStream(stream, ttcIndex);
  1755 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
  1756                                                IDWriteFontFamily** fontFamily) const {
  1757     UINT32 index;
  1758     BOOL exists;
  1759     HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
  1761     if (exists) {
  1762         HR(fFontCollection->GetFontFamily(index, fontFamily));
  1763         return S_OK;
  1765     return S_FALSE;
  1768 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const {
  1769     NONCLIENTMETRICSW metrics;
  1770     metrics.cbSize = sizeof(metrics);
  1771     if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
  1772                                    sizeof(metrics),
  1773                                    &metrics,
  1774                                    0)) {
  1775         return E_UNEXPECTED;
  1777     HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
  1778         "Could not create DWrite font family from LOGFONT.");
  1780     return S_OK;
  1783 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
  1784                                                           unsigned styleBits) const {
  1785     SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  1786     if (familyName) {
  1787         SkSMallocWCHAR wideFamilyName;
  1788         if (SUCCEEDED(cstring_to_wchar(familyName, &wideFamilyName))) {
  1789             this->getByFamilyName(wideFamilyName, &fontFamily);
  1793     if (NULL == fontFamily.get()) {
  1794         // No family with given name, try default.
  1795         HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
  1798     SkTScopedComPtr<IDWriteFont> font;
  1799     DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
  1800                               ? DWRITE_FONT_WEIGHT_BOLD
  1801                               : DWRITE_FONT_WEIGHT_NORMAL;
  1802     DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
  1803     DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
  1804                              ? DWRITE_FONT_STYLE_ITALIC
  1805                              : DWRITE_FONT_STYLE_NORMAL;
  1806     HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
  1807          "Could not get matching font.");
  1809     SkTScopedComPtr<IDWriteFontFace> fontFace;
  1810     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  1812     return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
  1815 ///////////////////////////////////////////////////////////////////////////////
  1817 int SkFontStyleSet_DirectWrite::count() {
  1818     return fFontFamily->GetFontCount();
  1821 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
  1822     SkTScopedComPtr<IDWriteFont> font;
  1823     HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
  1825     SkTScopedComPtr<IDWriteFontFace> fontFace;
  1826     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  1828     return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
  1831 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
  1832     SkTScopedComPtr<IDWriteFont> font;
  1833     HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
  1835     SkFontStyle::Slant slant;
  1836     switch (font->GetStyle()) {
  1837     case DWRITE_FONT_STYLE_NORMAL:
  1838         slant = SkFontStyle::kUpright_Slant;
  1839         break;
  1840     case DWRITE_FONT_STYLE_OBLIQUE:
  1841     case DWRITE_FONT_STYLE_ITALIC:
  1842         slant = SkFontStyle::kItalic_Slant;
  1843         break;
  1844     default:
  1845         SkASSERT(false);
  1848     int weight = font->GetWeight();
  1849     int width = font->GetStretch();
  1851     *fs = SkFontStyle(weight, width, slant);
  1853     SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
  1854     if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
  1855         get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
  1859 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
  1860     DWRITE_FONT_STYLE slant;
  1861     switch (pattern.slant()) {
  1862     case SkFontStyle::kUpright_Slant:
  1863         slant = DWRITE_FONT_STYLE_NORMAL;
  1864         break;
  1865     case SkFontStyle::kItalic_Slant:
  1866         slant = DWRITE_FONT_STYLE_ITALIC;
  1867         break;
  1868     default:
  1869         SkASSERT(false);
  1872     DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
  1873     DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
  1875     SkTScopedComPtr<IDWriteFont> font;
  1876     // TODO: perhaps use GetMatchingFonts and get the least simulated?
  1877     HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
  1878             "Could not match font in family.");
  1880     SkTScopedComPtr<IDWriteFontFace> fontFace;
  1881     HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  1883     return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
  1884                                                   fFontFamily.get());
  1887 ///////////////////////////////////////////////////////////////////////////////
  1889 typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameProc;
  1890 static HRESULT GetGetUserDefaultLocaleNameProc(GetUserDefaultLocaleNameProc* proc) {
  1891     *proc = reinterpret_cast<GetUserDefaultLocaleNameProc>(
  1892         GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName")
  1893     );
  1894     if (!*proc) {
  1895         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1896         if (!IS_ERROR(hr)) {
  1897             hr = ERROR_PROC_NOT_FOUND;
  1899         return hr;
  1901     return S_OK;
  1904 SkFontMgr* SkFontMgr_New_DirectWrite() {
  1905     IDWriteFactory* factory = get_dwrite_factory();
  1906     if (NULL == factory) {
  1907         return NULL;
  1910     SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
  1911     HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
  1912          "Could not get system font collection.");
  1914     WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
  1915     WCHAR* localeName = NULL;
  1916     int localeNameLen = 0;
  1918     // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
  1919     GetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
  1920     HRESULT hr = GetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
  1921     if (NULL == getUserDefaultLocaleNameProc) {
  1922         SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
  1923     } else {
  1924         localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
  1925         if (localeNameLen) {
  1926             localeName = localeNameStorage;
  1927         };
  1930     return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));

mercurial