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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/ports/SkFontHost_win_dw.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1931 @@
     1.4 +/*
     1.5 + * Copyright 2011 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#include "SkTypes.h"
    1.12 +#undef GetGlyphIndices
    1.13 +
    1.14 +#include "SkAdvancedTypefaceMetrics.h"
    1.15 +#include "SkColorFilter.h"
    1.16 +#include "SkDWriteFontFileStream.h"
    1.17 +#include "SkDWriteGeometrySink.h"
    1.18 +#include "SkDescriptor.h"
    1.19 +#include "SkEndian.h"
    1.20 +#include "SkFontDescriptor.h"
    1.21 +#include "SkFontHost.h"
    1.22 +#include "SkFontMgr.h"
    1.23 +#include "SkFontStream.h"
    1.24 +#include "SkGlyph.h"
    1.25 +#include "SkHRESULT.h"
    1.26 +#include "SkMaskGamma.h"
    1.27 +#include "SkOnce.h"
    1.28 +#include "SkOTTable_head.h"
    1.29 +#include "SkOTTable_hhea.h"
    1.30 +#include "SkOTTable_OS_2.h"
    1.31 +#include "SkOTTable_post.h"
    1.32 +#include "SkPath.h"
    1.33 +#include "SkStream.h"
    1.34 +#include "SkString.h"
    1.35 +#include "SkTScopedComPtr.h"
    1.36 +#include "SkThread.h"
    1.37 +#include "SkTypeface_win.h"
    1.38 +#include "SkTypefaceCache.h"
    1.39 +#include "SkUtils.h"
    1.40 +
    1.41 +#include <dwrite.h>
    1.42 +
    1.43 +static bool isLCD(const SkScalerContext::Rec& rec) {
    1.44 +    return SkMask::kLCD16_Format == rec.fMaskFormat ||
    1.45 +           SkMask::kLCD32_Format == rec.fMaskFormat;
    1.46 +}
    1.47 +
    1.48 +/** Prefer to use this type to prevent template proliferation. */
    1.49 +typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
    1.50 +
    1.51 +/** Converts a utf8 string to a WCHAR string. */
    1.52 +static HRESULT cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) {
    1.53 +    int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0);
    1.54 +    if (0 == wlen) {
    1.55 +        HRM(HRESULT_FROM_WIN32(GetLastError()),
    1.56 +            "Could not get length for wchar to utf-8 conversion.");
    1.57 +    }
    1.58 +    name->reset(wlen);
    1.59 +    wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen);
    1.60 +    if (0 == wlen) {
    1.61 +        HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8.");
    1.62 +    }
    1.63 +    return S_OK;
    1.64 +}
    1.65 +
    1.66 +/** Converts a WCHAR string to a utf8 string. */
    1.67 +static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) {
    1.68 +    int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
    1.69 +    if (0 == len) {
    1.70 +        HRM(HRESULT_FROM_WIN32(GetLastError()),
    1.71 +            "Could not get length for utf-8 to wchar conversion.");
    1.72 +    }
    1.73 +    skname->resize(len - 1);
    1.74 +
    1.75 +    // TODO: remove after https://code.google.com/p/skia/issues/detail?id=1989 is fixed.
    1.76 +    // If we resize to 0 then the skname points to gEmptyRec (the unique empty SkString::Rec).
    1.77 +    // gEmptyRec is static const and on Windows this means the value is in a read only page.
    1.78 +    // Writing to it in the following call to WideCharToMultiByte will cause an access violation.
    1.79 +    if (1 == len) {
    1.80 +        return S_OK;
    1.81 +    }
    1.82 +
    1.83 +    len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
    1.84 +    if (0 == len) {
    1.85 +        HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
    1.86 +    }
    1.87 +    return S_OK;
    1.88 +}
    1.89 +
    1.90 +///////////////////////////////////////////////////////////////////////////////
    1.91 +
    1.92 +static void create_dwrite_factory(IDWriteFactory** factory) {
    1.93 +    typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
    1.94 +    DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>(
    1.95 +        GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
    1.96 +
    1.97 +    if (!dWriteCreateFactoryProc) {
    1.98 +        HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
    1.99 +        if (!IS_ERROR(hr)) {
   1.100 +            hr = ERROR_PROC_NOT_FOUND;
   1.101 +        }
   1.102 +        HRVM(hr, "Could not get DWriteCreateFactory proc.");
   1.103 +    }
   1.104 +
   1.105 +    HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
   1.106 +                                 __uuidof(IDWriteFactory),
   1.107 +                                 reinterpret_cast<IUnknown**>(factory)),
   1.108 +         "Could not create DirectWrite factory.");
   1.109 +}
   1.110 +
   1.111 +static IDWriteFactory* get_dwrite_factory() {
   1.112 +    static IDWriteFactory* gDWriteFactory = NULL;
   1.113 +    SK_DECLARE_STATIC_ONCE(once);
   1.114 +    SkOnce(&once, create_dwrite_factory, &gDWriteFactory);
   1.115 +
   1.116 +    return gDWriteFactory;
   1.117 +}
   1.118 +
   1.119 +///////////////////////////////////////////////////////////////////////////////
   1.120 +
   1.121 +class StreamFontFileLoader;
   1.122 +
   1.123 +class SkFontMgr_DirectWrite : public SkFontMgr {
   1.124 +public:
   1.125 +    /** localeNameLength must include the null terminator. */
   1.126 +    SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
   1.127 +                          WCHAR* localeName, int localeNameLength)
   1.128 +        : fFontCollection(SkRefComPtr(fontCollection))
   1.129 +        , fLocaleName(localeNameLength)
   1.130 +    {
   1.131 +        memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
   1.132 +    }
   1.133 +
   1.134 +    SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
   1.135 +                                             IDWriteFont* font,
   1.136 +                                             IDWriteFontFamily* fontFamily,
   1.137 +                                             StreamFontFileLoader* = NULL,
   1.138 +                                             IDWriteFontCollectionLoader* = NULL) const;
   1.139 +
   1.140 +protected:
   1.141 +    virtual int onCountFamilies() const SK_OVERRIDE;
   1.142 +    virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE;
   1.143 +    virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE;
   1.144 +    virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE;
   1.145 +    virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
   1.146 +                                           const SkFontStyle& fontstyle) const SK_OVERRIDE;
   1.147 +    virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
   1.148 +                                         const SkFontStyle& fontstyle) const SK_OVERRIDE;
   1.149 +    virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE;
   1.150 +    virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE;
   1.151 +    virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE;
   1.152 +    virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
   1.153 +                                               unsigned styleBits) const SK_OVERRIDE;
   1.154 +
   1.155 +private:
   1.156 +    HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
   1.157 +    HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const;
   1.158 +
   1.159 +    void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) const {
   1.160 +        SkAutoMutexAcquire ama(fTFCacheMutex);
   1.161 +        fTFCache.add(face, requestedStyle, strong);
   1.162 +    }
   1.163 +
   1.164 +    SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) const {
   1.165 +        SkAutoMutexAcquire ama(fTFCacheMutex);
   1.166 +        SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx);
   1.167 +        return typeface;
   1.168 +    }
   1.169 +
   1.170 +    SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
   1.171 +    SkSMallocWCHAR fLocaleName;
   1.172 +    mutable SkMutex fTFCacheMutex;
   1.173 +    mutable SkTypefaceCache fTFCache;
   1.174 +
   1.175 +    friend class SkFontStyleSet_DirectWrite;
   1.176 +};
   1.177 +
   1.178 +class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
   1.179 +public:
   1.180 +    SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
   1.181 +                               IDWriteFontFamily* fontFamily)
   1.182 +        : fFontMgr(SkRef(fontMgr))
   1.183 +        , fFontFamily(SkRefComPtr(fontFamily))
   1.184 +    { }
   1.185 +
   1.186 +    virtual int count() SK_OVERRIDE;
   1.187 +    virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
   1.188 +    virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
   1.189 +    virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
   1.190 +
   1.191 +private:
   1.192 +    SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
   1.193 +    SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
   1.194 +};
   1.195 +
   1.196 +///////////////////////////////////////////////////////////////////////////////
   1.197 +
   1.198 +class DWriteOffscreen {
   1.199 +public:
   1.200 +    DWriteOffscreen() : fWidth(0), fHeight(0) {
   1.201 +    }
   1.202 +
   1.203 +    void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
   1.204 +        fFontFace = fontFace;
   1.205 +        fFontSize = fontSize;
   1.206 +        fXform = xform;
   1.207 +    }
   1.208 +
   1.209 +    const void* draw(const SkGlyph&, bool isBW);
   1.210 +
   1.211 +private:
   1.212 +    uint16_t fWidth;
   1.213 +    uint16_t fHeight;
   1.214 +    IDWriteFontFace* fFontFace;
   1.215 +    FLOAT fFontSize;
   1.216 +    DWRITE_MATRIX fXform;
   1.217 +    SkTDArray<uint8_t> fBits;
   1.218 +};
   1.219 +
   1.220 +const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
   1.221 +    IDWriteFactory* factory = get_dwrite_factory();
   1.222 +    SkASSERT(factory != NULL);
   1.223 +
   1.224 +    if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
   1.225 +        fWidth = SkMax32(fWidth, glyph.fWidth);
   1.226 +        fHeight = SkMax32(fHeight, glyph.fHeight);
   1.227 +
   1.228 +        if (isBW) {
   1.229 +            fBits.setCount(fWidth * fHeight);
   1.230 +        } else {
   1.231 +            fBits.setCount(fWidth * fHeight * 3);
   1.232 +        }
   1.233 +    }
   1.234 +
   1.235 +    // erase
   1.236 +    memset(fBits.begin(), 0, fBits.count());
   1.237 +
   1.238 +    fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
   1.239 +    fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
   1.240 +
   1.241 +    FLOAT advance = 0.0f;
   1.242 +
   1.243 +    UINT16 index = glyph.getGlyphID();
   1.244 +
   1.245 +    DWRITE_GLYPH_OFFSET offset;
   1.246 +    offset.advanceOffset = 0.0f;
   1.247 +    offset.ascenderOffset = 0.0f;
   1.248 +
   1.249 +    DWRITE_GLYPH_RUN run;
   1.250 +    run.glyphCount = 1;
   1.251 +    run.glyphAdvances = &advance;
   1.252 +    run.fontFace = fFontFace;
   1.253 +    run.fontEmSize = fFontSize;
   1.254 +    run.bidiLevel = 0;
   1.255 +    run.glyphIndices = &index;
   1.256 +    run.isSideways = FALSE;
   1.257 +    run.glyphOffsets = &offset;
   1.258 +
   1.259 +    DWRITE_RENDERING_MODE renderingMode;
   1.260 +    DWRITE_TEXTURE_TYPE textureType;
   1.261 +    if (isBW) {
   1.262 +        renderingMode = DWRITE_RENDERING_MODE_ALIASED;
   1.263 +        textureType = DWRITE_TEXTURE_ALIASED_1x1;
   1.264 +    } else {
   1.265 +        renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
   1.266 +        textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
   1.267 +    }
   1.268 +    SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
   1.269 +    HRNM(factory->CreateGlyphRunAnalysis(&run,
   1.270 +                                         1.0f, // pixelsPerDip,
   1.271 +                                         &fXform,
   1.272 +                                         renderingMode,
   1.273 +                                         DWRITE_MEASURING_MODE_NATURAL,
   1.274 +                                         0.0f, // baselineOriginX,
   1.275 +                                         0.0f, // baselineOriginY,
   1.276 +                                         &glyphRunAnalysis),
   1.277 +         "Could not create glyph run analysis.");
   1.278 +
   1.279 +    //NOTE: this assumes that the glyph has already been measured
   1.280 +    //with an exact same glyph run analysis.
   1.281 +    RECT bbox;
   1.282 +    bbox.left = glyph.fLeft;
   1.283 +    bbox.top = glyph.fTop;
   1.284 +    bbox.right = glyph.fLeft + glyph.fWidth;
   1.285 +    bbox.bottom = glyph.fTop + glyph.fHeight;
   1.286 +    HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
   1.287 +                                              &bbox,
   1.288 +                                              fBits.begin(),
   1.289 +                                              fBits.count()),
   1.290 +         "Could not draw mask.");
   1.291 +    return fBits.begin();
   1.292 +}
   1.293 +
   1.294 +///////////////////////////////////////////////////////////////////////////////
   1.295 +
   1.296 +class StreamFontFileLoader : public IDWriteFontFileLoader {
   1.297 +public:
   1.298 +    // IUnknown methods
   1.299 +    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
   1.300 +    virtual ULONG STDMETHODCALLTYPE AddRef();
   1.301 +    virtual ULONG STDMETHODCALLTYPE Release();
   1.302 +
   1.303 +    // IDWriteFontFileLoader methods
   1.304 +    virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
   1.305 +        void const* fontFileReferenceKey,
   1.306 +        UINT32 fontFileReferenceKeySize,
   1.307 +        IDWriteFontFileStream** fontFileStream);
   1.308 +
   1.309 +    static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
   1.310 +        *streamFontFileLoader = new StreamFontFileLoader(stream);
   1.311 +        if (NULL == streamFontFileLoader) {
   1.312 +            return E_OUTOFMEMORY;
   1.313 +        }
   1.314 +        return S_OK;
   1.315 +    }
   1.316 +
   1.317 +    SkAutoTUnref<SkStream> fStream;
   1.318 +
   1.319 +private:
   1.320 +    StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
   1.321 +
   1.322 +    ULONG fRefCount;
   1.323 +};
   1.324 +
   1.325 +HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
   1.326 +    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
   1.327 +        *ppvObject = this;
   1.328 +        AddRef();
   1.329 +        return S_OK;
   1.330 +    } else {
   1.331 +        *ppvObject = NULL;
   1.332 +        return E_NOINTERFACE;
   1.333 +    }
   1.334 +}
   1.335 +
   1.336 +ULONG StreamFontFileLoader::AddRef() {
   1.337 +    return InterlockedIncrement(&fRefCount);
   1.338 +}
   1.339 +
   1.340 +ULONG StreamFontFileLoader::Release() {
   1.341 +    ULONG newCount = InterlockedDecrement(&fRefCount);
   1.342 +    if (0 == newCount) {
   1.343 +        delete this;
   1.344 +    }
   1.345 +    return newCount;
   1.346 +}
   1.347 +
   1.348 +HRESULT StreamFontFileLoader::CreateStreamFromKey(
   1.349 +    void const* fontFileReferenceKey,
   1.350 +    UINT32 fontFileReferenceKeySize,
   1.351 +    IDWriteFontFileStream** fontFileStream)
   1.352 +{
   1.353 +    SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
   1.354 +    HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
   1.355 +    *fontFileStream = stream.release();
   1.356 +    return S_OK;
   1.357 +}
   1.358 +
   1.359 +class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
   1.360 +public:
   1.361 +    // IUnknown methods
   1.362 +    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
   1.363 +    virtual ULONG STDMETHODCALLTYPE AddRef();
   1.364 +    virtual ULONG STDMETHODCALLTYPE Release();
   1.365 +
   1.366 +    // IDWriteFontFileEnumerator methods
   1.367 +    virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
   1.368 +    virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
   1.369 +
   1.370 +    static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
   1.371 +                          StreamFontFileEnumerator** streamFontFileEnumerator) {
   1.372 +        *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
   1.373 +        if (NULL == streamFontFileEnumerator) {
   1.374 +            return E_OUTOFMEMORY;
   1.375 +        }
   1.376 +        return S_OK;
   1.377 +    }
   1.378 +private:
   1.379 +    StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
   1.380 +    ULONG fRefCount;
   1.381 +
   1.382 +    SkTScopedComPtr<IDWriteFactory> fFactory;
   1.383 +    SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
   1.384 +    SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
   1.385 +    bool fHasNext;
   1.386 +};
   1.387 +
   1.388 +StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
   1.389 +                                                   IDWriteFontFileLoader* fontFileLoader)
   1.390 +    : fRefCount(1)
   1.391 +    , fFactory(SkRefComPtr(factory))
   1.392 +    , fCurrentFile()
   1.393 +    , fFontFileLoader(SkRefComPtr(fontFileLoader))
   1.394 +    , fHasNext(true)
   1.395 +{ }
   1.396 +
   1.397 +HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
   1.398 +    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
   1.399 +        *ppvObject = this;
   1.400 +        AddRef();
   1.401 +        return S_OK;
   1.402 +    } else {
   1.403 +        *ppvObject = NULL;
   1.404 +        return E_NOINTERFACE;
   1.405 +    }
   1.406 +}
   1.407 +
   1.408 +ULONG StreamFontFileEnumerator::AddRef() {
   1.409 +    return InterlockedIncrement(&fRefCount);
   1.410 +}
   1.411 +
   1.412 +ULONG StreamFontFileEnumerator::Release() {
   1.413 +    ULONG newCount = InterlockedDecrement(&fRefCount);
   1.414 +    if (0 == newCount) {
   1.415 +        delete this;
   1.416 +    }
   1.417 +    return newCount;
   1.418 +}
   1.419 +
   1.420 +HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
   1.421 +    *hasCurrentFile = FALSE;
   1.422 +
   1.423 +    if (!fHasNext) {
   1.424 +        return S_OK;
   1.425 +    }
   1.426 +    fHasNext = false;
   1.427 +
   1.428 +    UINT32 dummy = 0;
   1.429 +    HR(fFactory->CreateCustomFontFileReference(
   1.430 +            &dummy, //cannot be NULL
   1.431 +            sizeof(dummy), //even if this is 0
   1.432 +            fFontFileLoader.get(),
   1.433 +            &fCurrentFile));
   1.434 +
   1.435 +    *hasCurrentFile = TRUE;
   1.436 +    return S_OK;
   1.437 +}
   1.438 +
   1.439 +HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
   1.440 +    if (fCurrentFile.get() == NULL) {
   1.441 +        *fontFile = NULL;
   1.442 +        return E_FAIL;
   1.443 +    }
   1.444 +
   1.445 +    *fontFile = SkRefComPtr(fCurrentFile.get());
   1.446 +    return  S_OK;
   1.447 +}
   1.448 +
   1.449 +class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
   1.450 +public:
   1.451 +    // IUnknown methods
   1.452 +    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
   1.453 +    virtual ULONG STDMETHODCALLTYPE AddRef();
   1.454 +    virtual ULONG STDMETHODCALLTYPE Release();
   1.455 +
   1.456 +    // IDWriteFontCollectionLoader methods
   1.457 +    virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
   1.458 +        IDWriteFactory* factory,
   1.459 +        void const* collectionKey,
   1.460 +        UINT32 collectionKeySize,
   1.461 +        IDWriteFontFileEnumerator** fontFileEnumerator);
   1.462 +
   1.463 +    static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
   1.464 +                          StreamFontCollectionLoader** streamFontCollectionLoader) {
   1.465 +        *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
   1.466 +        if (NULL == streamFontCollectionLoader) {
   1.467 +            return E_OUTOFMEMORY;
   1.468 +        }
   1.469 +        return S_OK;
   1.470 +    }
   1.471 +private:
   1.472 +    StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
   1.473 +        : fRefCount(1)
   1.474 +        , fFontFileLoader(SkRefComPtr(fontFileLoader))
   1.475 +    { }
   1.476 +
   1.477 +    ULONG fRefCount;
   1.478 +    SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
   1.479 +};
   1.480 +
   1.481 +HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
   1.482 +    if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
   1.483 +        *ppvObject = this;
   1.484 +        AddRef();
   1.485 +        return S_OK;
   1.486 +    } else {
   1.487 +        *ppvObject = NULL;
   1.488 +        return E_NOINTERFACE;
   1.489 +    }
   1.490 +}
   1.491 +
   1.492 +ULONG StreamFontCollectionLoader::AddRef() {
   1.493 +    return InterlockedIncrement(&fRefCount);
   1.494 +}
   1.495 +
   1.496 +ULONG StreamFontCollectionLoader::Release() {
   1.497 +    ULONG newCount = InterlockedDecrement(&fRefCount);
   1.498 +    if (0 == newCount) {
   1.499 +        delete this;
   1.500 +    }
   1.501 +    return newCount;
   1.502 +}
   1.503 +
   1.504 +HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
   1.505 +    IDWriteFactory* factory,
   1.506 +    void const* collectionKey,
   1.507 +    UINT32 collectionKeySize,
   1.508 +    IDWriteFontFileEnumerator** fontFileEnumerator)
   1.509 +{
   1.510 +    SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
   1.511 +    HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
   1.512 +    *fontFileEnumerator = enumerator.release();
   1.513 +    return S_OK;
   1.514 +}
   1.515 +
   1.516 +///////////////////////////////////////////////////////////////////////////////
   1.517 +
   1.518 +static SkTypeface::Style get_style(IDWriteFont* font) {
   1.519 +    int style = SkTypeface::kNormal;
   1.520 +    DWRITE_FONT_WEIGHT weight = font->GetWeight();
   1.521 +    if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
   1.522 +        style |= SkTypeface::kBold;
   1.523 +    }
   1.524 +    DWRITE_FONT_STYLE angle = font->GetStyle();
   1.525 +    if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
   1.526 +        style |= SkTypeface::kItalic;
   1.527 +    }
   1.528 +    return static_cast<SkTypeface::Style>(style);
   1.529 +}
   1.530 +
   1.531 +class DWriteFontTypeface : public SkTypeface {
   1.532 +private:
   1.533 +    DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
   1.534 +                       IDWriteFontFace* fontFace,
   1.535 +                       IDWriteFont* font,
   1.536 +                       IDWriteFontFamily* fontFamily,
   1.537 +                       StreamFontFileLoader* fontFileLoader = NULL,
   1.538 +                       IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
   1.539 +        : SkTypeface(style, fontID, false)
   1.540 +        , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
   1.541 +        , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
   1.542 +        , fDWriteFontFamily(SkRefComPtr(fontFamily))
   1.543 +        , fDWriteFont(SkRefComPtr(font))
   1.544 +        , fDWriteFontFace(SkRefComPtr(fontFace))
   1.545 +    { }
   1.546 +
   1.547 +public:
   1.548 +    SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
   1.549 +    SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
   1.550 +    SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
   1.551 +    SkTScopedComPtr<IDWriteFont> fDWriteFont;
   1.552 +    SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
   1.553 +
   1.554 +    static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
   1.555 +                                      IDWriteFont* font,
   1.556 +                                      IDWriteFontFamily* fontFamily,
   1.557 +                                      StreamFontFileLoader* fontFileLoader = NULL,
   1.558 +                                      IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
   1.559 +        SkTypeface::Style style = get_style(font);
   1.560 +        SkFontID fontID = SkTypefaceCache::NewFontID();
   1.561 +        return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
   1.562 +                                               fontFace, font, fontFamily,
   1.563 +                                               fontFileLoader, fontCollectionLoader));
   1.564 +    }
   1.565 +
   1.566 +    ~DWriteFontTypeface() {
   1.567 +        if (fDWriteFontCollectionLoader.get() == NULL) return;
   1.568 +
   1.569 +        IDWriteFactory* factory = get_dwrite_factory();
   1.570 +        SkASSERT(factory != NULL);
   1.571 +        HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
   1.572 +        HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
   1.573 +    }
   1.574 +
   1.575 +protected:
   1.576 +    virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
   1.577 +    virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
   1.578 +    virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
   1.579 +    virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
   1.580 +                                SkAdvancedTypefaceMetrics::PerGlyphInfo,
   1.581 +                                const uint32_t*, uint32_t) const SK_OVERRIDE;
   1.582 +    virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
   1.583 +    virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
   1.584 +                                uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
   1.585 +    virtual int onCountGlyphs() const SK_OVERRIDE;
   1.586 +    virtual int onGetUPEM() const SK_OVERRIDE;
   1.587 +    virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
   1.588 +    virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
   1.589 +    virtual size_t onGetTableData(SkFontTableTag, size_t offset,
   1.590 +                                  size_t length, void* data) const SK_OVERRIDE;
   1.591 +};
   1.592 +
   1.593 +class SkScalerContext_DW : public SkScalerContext {
   1.594 +public:
   1.595 +    SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
   1.596 +    virtual ~SkScalerContext_DW();
   1.597 +
   1.598 +protected:
   1.599 +    virtual unsigned generateGlyphCount() SK_OVERRIDE;
   1.600 +    virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
   1.601 +    virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
   1.602 +    virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
   1.603 +    virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
   1.604 +    virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
   1.605 +    virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
   1.606 +                                     SkPaint::FontMetrics* mY) SK_OVERRIDE;
   1.607 +
   1.608 +private:
   1.609 +    DWriteOffscreen fOffscreen;
   1.610 +    DWRITE_MATRIX fXform;
   1.611 +    SkAutoTUnref<DWriteFontTypeface> fTypeface;
   1.612 +    int fGlyphCount;
   1.613 +};
   1.614 +
   1.615 +static bool are_same(IUnknown* a, IUnknown* b) {
   1.616 +    SkTScopedComPtr<IUnknown> iunkA;
   1.617 +    if (FAILED(a->QueryInterface(&iunkA))) {
   1.618 +        return false;
   1.619 +    }
   1.620 +
   1.621 +    SkTScopedComPtr<IUnknown> iunkB;
   1.622 +    if (FAILED(b->QueryInterface(&iunkB))) {
   1.623 +        return false;
   1.624 +    }
   1.625 +
   1.626 +    return iunkA.get() == iunkB.get();
   1.627 +}
   1.628 +static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
   1.629 +    //Check to see if the two fonts are identical.
   1.630 +    DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
   1.631 +    IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
   1.632 +    if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
   1.633 +        return true;
   1.634 +    }
   1.635 +
   1.636 +    //Check if the two fonts share the same loader and have the same key.
   1.637 +    SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
   1.638 +    SkTScopedComPtr<IDWriteFontFace> dwFontFace;
   1.639 +    HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
   1.640 +    HRB(dwFont->CreateFontFace(&dwFontFace));
   1.641 +    if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
   1.642 +        return true;
   1.643 +    }
   1.644 +
   1.645 +    UINT32 dwFaceNumFiles;
   1.646 +    UINT32 dwNumFiles;
   1.647 +    HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
   1.648 +    HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
   1.649 +    if (dwFaceNumFiles != dwNumFiles) {
   1.650 +        return false;
   1.651 +    }
   1.652 +
   1.653 +    SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
   1.654 +    SkTScopedComPtr<IDWriteFontFile> dwFontFile;
   1.655 +    HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
   1.656 +    HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
   1.657 +
   1.658 +    //for (each file) { //we currently only admit fonts from one file.
   1.659 +    SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
   1.660 +    SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
   1.661 +    HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
   1.662 +    HRB(dwFontFile->GetLoader(&dwFontFileLoader));
   1.663 +    if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
   1.664 +        return false;
   1.665 +    }
   1.666 +    //}
   1.667 +
   1.668 +    const void* dwFaceFontRefKey;
   1.669 +    UINT32 dwFaceFontRefKeySize;
   1.670 +    const void* dwFontRefKey;
   1.671 +    UINT32 dwFontRefKeySize;
   1.672 +    HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
   1.673 +    HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
   1.674 +    if (dwFaceFontRefKeySize != dwFontRefKeySize) {
   1.675 +        return false;
   1.676 +    }
   1.677 +    if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
   1.678 +        return false;
   1.679 +    }
   1.680 +
   1.681 +    //TODO: better means than comparing name strings?
   1.682 +    //NOTE: .tfc and fake bold/italic will end up here.
   1.683 +    SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
   1.684 +    SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
   1.685 +    HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
   1.686 +    HRB(dwFont->GetFontFamily(&dwFontFamily));
   1.687 +
   1.688 +    SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
   1.689 +    SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
   1.690 +    HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
   1.691 +    HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
   1.692 +
   1.693 +    SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
   1.694 +    SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
   1.695 +    HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
   1.696 +    HRB(dwFont->GetFaceNames(&dwFontNames));
   1.697 +
   1.698 +    UINT32 dwFaceFontFamilyNameLength;
   1.699 +    UINT32 dwFaceFontNameLength;
   1.700 +    HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
   1.701 +    HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
   1.702 +
   1.703 +    UINT32 dwFontFamilyNameLength;
   1.704 +    UINT32 dwFontNameLength;
   1.705 +    HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
   1.706 +    HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
   1.707 +
   1.708 +    if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
   1.709 +        dwFaceFontNameLength != dwFontNameLength)
   1.710 +    {
   1.711 +        return false;
   1.712 +    }
   1.713 +
   1.714 +    SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
   1.715 +    SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
   1.716 +    HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
   1.717 +    HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
   1.718 +
   1.719 +    SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
   1.720 +    SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
   1.721 +    HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
   1.722 +    HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
   1.723 +
   1.724 +    return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
   1.725 +           wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
   1.726 +}
   1.727 +
   1.728 +SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
   1.729 +                                                 const SkDescriptor* desc)
   1.730 +        : SkScalerContext(typeface, desc)
   1.731 +        , fTypeface(SkRef(typeface))
   1.732 +        , fGlyphCount(-1) {
   1.733 +
   1.734 +    fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
   1.735 +    fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
   1.736 +    fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
   1.737 +    fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
   1.738 +    fXform.dx = 0;
   1.739 +    fXform.dy = 0;
   1.740 +
   1.741 +    fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
   1.742 +}
   1.743 +
   1.744 +SkScalerContext_DW::~SkScalerContext_DW() {
   1.745 +}
   1.746 +
   1.747 +unsigned SkScalerContext_DW::generateGlyphCount() {
   1.748 +    if (fGlyphCount < 0) {
   1.749 +        fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
   1.750 +    }
   1.751 +    return fGlyphCount;
   1.752 +}
   1.753 +
   1.754 +uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
   1.755 +    uint16_t index = 0;
   1.756 +    fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
   1.757 +    return index;
   1.758 +}
   1.759 +
   1.760 +void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
   1.761 +    //Delta is the difference between the right/left side bearing metric
   1.762 +    //and where the right/left side bearing ends up after hinting.
   1.763 +    //DirectWrite does not provide this information.
   1.764 +    glyph->fRsbDelta = 0;
   1.765 +    glyph->fLsbDelta = 0;
   1.766 +
   1.767 +    glyph->fAdvanceX = 0;
   1.768 +    glyph->fAdvanceY = 0;
   1.769 +
   1.770 +    uint16_t glyphId = glyph->getGlyphID();
   1.771 +    DWRITE_GLYPH_METRICS gm;
   1.772 +    HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
   1.773 +         "Could not get design metrics.");
   1.774 +
   1.775 +    DWRITE_FONT_METRICS dwfm;
   1.776 +    fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
   1.777 +
   1.778 +    SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
   1.779 +                                       SkIntToScalar(gm.advanceWidth),
   1.780 +                                       SkIntToScalar(dwfm.designUnitsPerEm));
   1.781 +
   1.782 +    if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
   1.783 +        advanceX = SkScalarRoundToScalar(advanceX);
   1.784 +    }
   1.785 +
   1.786 +    SkVector vecs[1] = { { advanceX, 0 } };
   1.787 +    SkMatrix mat;
   1.788 +    fRec.getMatrixFrom2x2(&mat);
   1.789 +    mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
   1.790 +
   1.791 +    glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
   1.792 +    glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
   1.793 +}
   1.794 +
   1.795 +void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
   1.796 +    glyph->fWidth = 0;
   1.797 +
   1.798 +    this->generateAdvance(glyph);
   1.799 +
   1.800 +    //Measure raster size.
   1.801 +    fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
   1.802 +    fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
   1.803 +
   1.804 +    FLOAT advance = 0;
   1.805 +
   1.806 +    UINT16 glyphId = glyph->getGlyphID();
   1.807 +
   1.808 +    DWRITE_GLYPH_OFFSET offset;
   1.809 +    offset.advanceOffset = 0.0f;
   1.810 +    offset.ascenderOffset = 0.0f;
   1.811 +
   1.812 +    DWRITE_GLYPH_RUN run;
   1.813 +    run.glyphCount = 1;
   1.814 +    run.glyphAdvances = &advance;
   1.815 +    run.fontFace = fTypeface->fDWriteFontFace.get();
   1.816 +    run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
   1.817 +    run.bidiLevel = 0;
   1.818 +    run.glyphIndices = &glyphId;
   1.819 +    run.isSideways = FALSE;
   1.820 +    run.glyphOffsets = &offset;
   1.821 +
   1.822 +    IDWriteFactory* factory = get_dwrite_factory();
   1.823 +    SkASSERT(factory != NULL);
   1.824 +
   1.825 +    const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
   1.826 +    DWRITE_RENDERING_MODE renderingMode;
   1.827 +    DWRITE_TEXTURE_TYPE textureType;
   1.828 +    if (isBW) {
   1.829 +        renderingMode = DWRITE_RENDERING_MODE_ALIASED;
   1.830 +        textureType = DWRITE_TEXTURE_ALIASED_1x1;
   1.831 +    } else {
   1.832 +        renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
   1.833 +        textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
   1.834 +    }
   1.835 +
   1.836 +    SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
   1.837 +    HRVM(factory->CreateGlyphRunAnalysis(&run,
   1.838 +                                         1.0f, // pixelsPerDip,
   1.839 +                                         &fXform,
   1.840 +                                         renderingMode,
   1.841 +                                         DWRITE_MEASURING_MODE_NATURAL,
   1.842 +                                         0.0f, // baselineOriginX,
   1.843 +                                         0.0f, // baselineOriginY,
   1.844 +                                         &glyphRunAnalysis),
   1.845 +         "Could not create glyph run analysis.");
   1.846 +
   1.847 +    RECT bbox;
   1.848 +    HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
   1.849 +         "Could not get texture bounds.");
   1.850 +
   1.851 +    glyph->fWidth = SkToU16(bbox.right - bbox.left);
   1.852 +    glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
   1.853 +    glyph->fLeft = SkToS16(bbox.left);
   1.854 +    glyph->fTop = SkToS16(bbox.top);
   1.855 +}
   1.856 +
   1.857 +void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
   1.858 +                                                  SkPaint::FontMetrics* my) {
   1.859 +    if (!(mx || my))
   1.860 +      return;
   1.861 +
   1.862 +    if (mx) {
   1.863 +        sk_bzero(mx, sizeof(*mx));
   1.864 +    }
   1.865 +    if (my) {
   1.866 +        sk_bzero(my, sizeof(*my));
   1.867 +    }
   1.868 +
   1.869 +    DWRITE_FONT_METRICS dwfm;
   1.870 +    fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
   1.871 +
   1.872 +    SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
   1.873 +    if (mx) {
   1.874 +        mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
   1.875 +        mx->fAscent = mx->fTop;
   1.876 +        mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
   1.877 +        mx->fBottom = mx->fDescent;
   1.878 +        mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
   1.879 +        mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
   1.880 +        mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
   1.881 +        mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
   1.882 +
   1.883 +        mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
   1.884 +        mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   1.885 +    }
   1.886 +
   1.887 +    if (my) {
   1.888 +        my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
   1.889 +        my->fAscent = my->fTop;
   1.890 +        my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
   1.891 +        my->fBottom = my->fDescent;
   1.892 +        my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
   1.893 +        my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
   1.894 +        my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
   1.895 +        my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
   1.896 +
   1.897 +        my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
   1.898 +        my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   1.899 +    }
   1.900 +}
   1.901 +
   1.902 +///////////////////////////////////////////////////////////////////////////////
   1.903 +
   1.904 +#include "SkColorPriv.h"
   1.905 +
   1.906 +static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
   1.907 +    const int width = glyph.fWidth;
   1.908 +    const size_t dstRB = (width + 7) >> 3;
   1.909 +    uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
   1.910 +
   1.911 +    int byteCount = width >> 3;
   1.912 +    int bitCount = width & 7;
   1.913 +
   1.914 +    for (int y = 0; y < glyph.fHeight; ++y) {
   1.915 +        if (byteCount > 0) {
   1.916 +            for (int i = 0; i < byteCount; ++i) {
   1.917 +                unsigned byte = 0;
   1.918 +                byte |= src[0] & (1 << 7);
   1.919 +                byte |= src[1] & (1 << 6);
   1.920 +                byte |= src[2] & (1 << 5);
   1.921 +                byte |= src[3] & (1 << 4);
   1.922 +                byte |= src[4] & (1 << 3);
   1.923 +                byte |= src[5] & (1 << 2);
   1.924 +                byte |= src[6] & (1 << 1);
   1.925 +                byte |= src[7] & (1 << 0);
   1.926 +                dst[i] = byte;
   1.927 +                src += 8;
   1.928 +            }
   1.929 +        }
   1.930 +        if (bitCount > 0) {
   1.931 +            unsigned byte = 0;
   1.932 +            unsigned mask = 0x80;
   1.933 +            for (int i = 0; i < bitCount; i++) {
   1.934 +                byte |= (src[i]) & mask;
   1.935 +                mask >>= 1;
   1.936 +            }
   1.937 +            dst[byteCount] = byte;
   1.938 +        }
   1.939 +        src += bitCount;
   1.940 +        dst += dstRB;
   1.941 +    }
   1.942 +}
   1.943 +
   1.944 +template<bool APPLY_PREBLEND>
   1.945 +static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
   1.946 +    const size_t dstRB = glyph.rowBytes();
   1.947 +    const U16CPU width = glyph.fWidth;
   1.948 +    uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
   1.949 +
   1.950 +    for (U16CPU y = 0; y < glyph.fHeight; y++) {
   1.951 +        for (U16CPU i = 0; i < width; i++) {
   1.952 +            U8CPU r = *(src++);
   1.953 +            U8CPU g = *(src++);
   1.954 +            U8CPU b = *(src++);
   1.955 +            dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
   1.956 +        }
   1.957 +        dst = (uint8_t*)((char*)dst + dstRB);
   1.958 +    }
   1.959 +}
   1.960 +
   1.961 +template<bool APPLY_PREBLEND>
   1.962 +static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
   1.963 +                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1.964 +    const size_t dstRB = glyph.rowBytes();
   1.965 +    const U16CPU width = glyph.fWidth;
   1.966 +    uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
   1.967 +
   1.968 +    for (U16CPU y = 0; y < glyph.fHeight; y++) {
   1.969 +        for (U16CPU i = 0; i < width; i++) {
   1.970 +            U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
   1.971 +            U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
   1.972 +            U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
   1.973 +            dst[i] = SkPack888ToRGB16(r, g, b);
   1.974 +        }
   1.975 +        dst = (uint16_t*)((char*)dst + dstRB);
   1.976 +    }
   1.977 +}
   1.978 +
   1.979 +template<bool APPLY_PREBLEND>
   1.980 +static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
   1.981 +                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1.982 +    const size_t dstRB = glyph.rowBytes();
   1.983 +    const U16CPU width = glyph.fWidth;
   1.984 +    SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
   1.985 +
   1.986 +    for (U16CPU y = 0; y < glyph.fHeight; y++) {
   1.987 +        for (U16CPU i = 0; i < width; i++) {
   1.988 +            U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
   1.989 +            U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
   1.990 +            U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
   1.991 +            dst[i] = SkPackARGB32(0xFF, r, g, b);
   1.992 +        }
   1.993 +        dst = (SkPMColor*)((char*)dst + dstRB);
   1.994 +    }
   1.995 +}
   1.996 +
   1.997 +void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
   1.998 +    const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
   1.999 +    const bool isAA = !isLCD(fRec);
  1.1000 +
  1.1001 +    //Create the mask.
  1.1002 +    const void* bits = fOffscreen.draw(glyph, isBW);
  1.1003 +    if (!bits) {
  1.1004 +        sk_bzero(glyph.fImage, glyph.computeImageSize());
  1.1005 +        return;
  1.1006 +    }
  1.1007 +
  1.1008 +    //Copy the mask into the glyph.
  1.1009 +    const uint8_t* src = (const uint8_t*)bits;
  1.1010 +    if (isBW) {
  1.1011 +        bilevel_to_bw(src, glyph);
  1.1012 +    } else if (isAA) {
  1.1013 +        if (fPreBlend.isApplicable()) {
  1.1014 +            rgb_to_a8<true>(src, glyph, fPreBlend.fG);
  1.1015 +        } else {
  1.1016 +            rgb_to_a8<false>(src, glyph, fPreBlend.fG);
  1.1017 +        }
  1.1018 +    } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
  1.1019 +        if (fPreBlend.isApplicable()) {
  1.1020 +            rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1.1021 +        } else {
  1.1022 +            rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1.1023 +        }
  1.1024 +    } else {
  1.1025 +        SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
  1.1026 +        if (fPreBlend.isApplicable()) {
  1.1027 +            rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1.1028 +        } else {
  1.1029 +            rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1.1030 +        }
  1.1031 +    }
  1.1032 +}
  1.1033 +
  1.1034 +void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
  1.1035 +    SkASSERT(&glyph && path);
  1.1036 +
  1.1037 +    path->reset();
  1.1038 +
  1.1039 +    SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
  1.1040 +    HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
  1.1041 +         "Could not create geometry to path converter.");
  1.1042 +    uint16_t glyphId = glyph.getGlyphID();
  1.1043 +    //TODO: convert to<->from DIUs? This would make a difference if hinting.
  1.1044 +    //It may not be needed, it appears that DirectWrite only hints at em size.
  1.1045 +    HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
  1.1046 +                                       &glyphId,
  1.1047 +                                       NULL, //advances
  1.1048 +                                       NULL, //offsets
  1.1049 +                                       1, //num glyphs
  1.1050 +                                       FALSE, //sideways
  1.1051 +                                       FALSE, //rtl
  1.1052 +                                       geometryToPath.get()),
  1.1053 +         "Could not create glyph outline.");
  1.1054 +
  1.1055 +    SkMatrix mat;
  1.1056 +    fRec.getMatrixFrom2x2(&mat);
  1.1057 +    path->transform(mat);
  1.1058 +}
  1.1059 +
  1.1060 +void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
  1.1061 +                                             bool* isLocalStream) const {
  1.1062 +    // Get the family name.
  1.1063 +    SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
  1.1064 +    HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
  1.1065 +
  1.1066 +    UINT32 dwFamilyNamesLength;
  1.1067 +    HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
  1.1068 +
  1.1069 +    SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
  1.1070 +    HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
  1.1071 +
  1.1072 +    SkString utf8FamilyName;
  1.1073 +    HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
  1.1074 +
  1.1075 +    desc->setFamilyName(utf8FamilyName.c_str());
  1.1076 +    *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
  1.1077 +}
  1.1078 +
  1.1079 +static SkUnichar next_utf8(const void** chars) {
  1.1080 +    return SkUTF8_NextUnichar((const char**)chars);
  1.1081 +}
  1.1082 +
  1.1083 +static SkUnichar next_utf16(const void** chars) {
  1.1084 +    return SkUTF16_NextUnichar((const uint16_t**)chars);
  1.1085 +}
  1.1086 +
  1.1087 +static SkUnichar next_utf32(const void** chars) {
  1.1088 +    const SkUnichar** uniChars = (const SkUnichar**)chars;
  1.1089 +    SkUnichar uni = **uniChars;
  1.1090 +    *uniChars += 1;
  1.1091 +    return uni;
  1.1092 +}
  1.1093 +
  1.1094 +typedef SkUnichar (*EncodingProc)(const void**);
  1.1095 +
  1.1096 +static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
  1.1097 +    static const EncodingProc gProcs[] = {
  1.1098 +        next_utf8, next_utf16, next_utf32
  1.1099 +    };
  1.1100 +    SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
  1.1101 +    return gProcs[enc];
  1.1102 +}
  1.1103 +
  1.1104 +int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
  1.1105 +                                        uint16_t glyphs[], int glyphCount) const
  1.1106 +{
  1.1107 +    if (NULL == glyphs) {
  1.1108 +        EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
  1.1109 +        for (int i = 0; i < glyphCount; ++i) {
  1.1110 +            const SkUnichar c = next_ucs4_proc(&chars);
  1.1111 +            BOOL exists;
  1.1112 +            fDWriteFont->HasCharacter(c, &exists);
  1.1113 +            if (!exists) {
  1.1114 +                return i;
  1.1115 +            }
  1.1116 +        }
  1.1117 +        return glyphCount;
  1.1118 +    }
  1.1119 +
  1.1120 +    switch (encoding) {
  1.1121 +    case SkTypeface::kUTF8_Encoding:
  1.1122 +    case SkTypeface::kUTF16_Encoding: {
  1.1123 +        static const int scratchCount = 256;
  1.1124 +        UINT32 scratch[scratchCount];
  1.1125 +        EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
  1.1126 +        for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
  1.1127 +            int glyphsLeft = glyphCount - baseGlyph;
  1.1128 +            int limit = SkTMin(glyphsLeft, scratchCount);
  1.1129 +            for (int i = 0; i < limit; ++i) {
  1.1130 +                scratch[i] = next_ucs4_proc(&chars);
  1.1131 +            }
  1.1132 +            fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
  1.1133 +        }
  1.1134 +        break;
  1.1135 +    }
  1.1136 +    case SkTypeface::kUTF32_Encoding: {
  1.1137 +        const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
  1.1138 +        fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
  1.1139 +        break;
  1.1140 +    }
  1.1141 +    default:
  1.1142 +        SK_CRASH();
  1.1143 +    }
  1.1144 +
  1.1145 +    for (int i = 0; i < glyphCount; ++i) {
  1.1146 +        if (0 == glyphs[i]) {
  1.1147 +            return i;
  1.1148 +        }
  1.1149 +    }
  1.1150 +    return glyphCount;
  1.1151 +}
  1.1152 +
  1.1153 +int DWriteFontTypeface::onCountGlyphs() const {
  1.1154 +    return fDWriteFontFace->GetGlyphCount();
  1.1155 +}
  1.1156 +
  1.1157 +int DWriteFontTypeface::onGetUPEM() const {
  1.1158 +    DWRITE_FONT_METRICS metrics;
  1.1159 +    fDWriteFontFace->GetMetrics(&metrics);
  1.1160 +    return metrics.designUnitsPerEm;
  1.1161 +}
  1.1162 +
  1.1163 +class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
  1.1164 +public:
  1.1165 +    /** Takes ownership of the IDWriteLocalizedStrings. */
  1.1166 +    explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
  1.1167 +        : fIndex(0), fStrings(strings)
  1.1168 +    { }
  1.1169 +
  1.1170 +    virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
  1.1171 +        if (fIndex >= fStrings->GetCount()) {
  1.1172 +            return false;
  1.1173 +        }
  1.1174 +
  1.1175 +        // String
  1.1176 +        UINT32 stringLength;
  1.1177 +        HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
  1.1178 +        stringLength += 1;
  1.1179 +
  1.1180 +        SkSMallocWCHAR wString(stringLength);
  1.1181 +        HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
  1.1182 +
  1.1183 +        HRB(wchar_to_skstring(wString.get(), &localizedString->fString));
  1.1184 +
  1.1185 +        // Locale
  1.1186 +        UINT32 localeLength;
  1.1187 +        HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
  1.1188 +        localeLength += 1;
  1.1189 +
  1.1190 +        SkSMallocWCHAR wLocale(localeLength);
  1.1191 +        HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
  1.1192 +
  1.1193 +        HRB(wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
  1.1194 +
  1.1195 +        ++fIndex;
  1.1196 +        return true;
  1.1197 +    }
  1.1198 +
  1.1199 +private:
  1.1200 +    UINT32 fIndex;
  1.1201 +    SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
  1.1202 +};
  1.1203 +
  1.1204 +SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
  1.1205 +    SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
  1.1206 +    HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
  1.1207 +
  1.1208 +    return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
  1.1209 +}
  1.1210 +
  1.1211 +int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
  1.1212 +    DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
  1.1213 +    if (type != DWRITE_FONT_FACE_TYPE_CFF &&
  1.1214 +        type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
  1.1215 +        type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
  1.1216 +    {
  1.1217 +        return 0;
  1.1218 +    }
  1.1219 +
  1.1220 +    int ttcIndex;
  1.1221 +    SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
  1.1222 +    return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
  1.1223 +}
  1.1224 +
  1.1225 +class AutoDWriteTable {
  1.1226 +public:
  1.1227 +    AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
  1.1228 +        // Any errors are ignored, user must check fExists anyway.
  1.1229 +        fontFace->TryGetFontTable(beTag,
  1.1230 +            reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
  1.1231 +    }
  1.1232 +    ~AutoDWriteTable() {
  1.1233 +        if (fExists) {
  1.1234 +            fFontFace->ReleaseFontTable(fLock);
  1.1235 +        }
  1.1236 +    }
  1.1237 +
  1.1238 +    const uint8_t* fData;
  1.1239 +    UINT32 fSize;
  1.1240 +    BOOL fExists;
  1.1241 +private:
  1.1242 +    // Borrowed reference, the user must ensure the fontFace stays alive.
  1.1243 +    IDWriteFontFace* fFontFace;
  1.1244 +    void* fLock;
  1.1245 +};
  1.1246 +
  1.1247 +size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
  1.1248 +                                          size_t length, void* data) const
  1.1249 +{
  1.1250 +    AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
  1.1251 +    if (!table.fExists) {
  1.1252 +        return 0;
  1.1253 +    }
  1.1254 +
  1.1255 +    if (offset > table.fSize) {
  1.1256 +        return 0;
  1.1257 +    }
  1.1258 +    size_t size = SkTMin(length, table.fSize - offset);
  1.1259 +    if (NULL != data) {
  1.1260 +        memcpy(data, table.fData + offset, size);
  1.1261 +    }
  1.1262 +
  1.1263 +    return size;
  1.1264 +}
  1.1265 +
  1.1266 +template <typename T> class SkAutoIDWriteUnregister {
  1.1267 +public:
  1.1268 +    SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
  1.1269 +        : fFactory(factory), fUnregister(unregister)
  1.1270 +    { }
  1.1271 +
  1.1272 +    ~SkAutoIDWriteUnregister() {
  1.1273 +        if (fUnregister) {
  1.1274 +            unregister(fFactory, fUnregister);
  1.1275 +        }
  1.1276 +    }
  1.1277 +
  1.1278 +    T* detatch() {
  1.1279 +        T* old = fUnregister;
  1.1280 +        fUnregister = NULL;
  1.1281 +        return old;
  1.1282 +    }
  1.1283 +
  1.1284 +private:
  1.1285 +    HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
  1.1286 +        return factory->UnregisterFontFileLoader(unregister);
  1.1287 +    }
  1.1288 +
  1.1289 +    HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
  1.1290 +        return factory->UnregisterFontCollectionLoader(unregister);
  1.1291 +    }
  1.1292 +
  1.1293 +    IDWriteFactory* fFactory;
  1.1294 +    T* fUnregister;
  1.1295 +};
  1.1296 +
  1.1297 +static SkTypeface* create_from_stream(SkStream* stream, int ttcIndex) {
  1.1298 +    IDWriteFactory* factory = get_dwrite_factory();
  1.1299 +    if (NULL == factory) {
  1.1300 +        return NULL;
  1.1301 +    }
  1.1302 +
  1.1303 +    SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
  1.1304 +    HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
  1.1305 +    HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
  1.1306 +    SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
  1.1307 +        factory, fontFileLoader.get());
  1.1308 +
  1.1309 +    SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
  1.1310 +    HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
  1.1311 +    HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
  1.1312 +    SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
  1.1313 +        factory, fontCollectionLoader.get());
  1.1314 +
  1.1315 +    SkTScopedComPtr<IDWriteFontCollection> fontCollection;
  1.1316 +    HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
  1.1317 +
  1.1318 +    // Find the first non-simulated font which has the given ttc index.
  1.1319 +    UINT32 familyCount = fontCollection->GetFontFamilyCount();
  1.1320 +    for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
  1.1321 +        SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  1.1322 +        HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
  1.1323 +
  1.1324 +        UINT32 fontCount = fontFamily->GetFontCount();
  1.1325 +        for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
  1.1326 +            SkTScopedComPtr<IDWriteFont> font;
  1.1327 +            HRN(fontFamily->GetFont(fontIndex, &font));
  1.1328 +            if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
  1.1329 +                continue;
  1.1330 +            }
  1.1331 +
  1.1332 +            SkTScopedComPtr<IDWriteFontFace> fontFace;
  1.1333 +            HRN(font->CreateFontFace(&fontFace));
  1.1334 +
  1.1335 +            UINT32 faceIndex = fontFace->GetIndex();
  1.1336 +            if (faceIndex == ttcIndex) {
  1.1337 +                return DWriteFontTypeface::Create(fontFace.get(), font.get(), fontFamily.get(),
  1.1338 +                                                  autoUnregisterFontFileLoader.detatch(),
  1.1339 +                                                  autoUnregisterFontCollectionLoader.detatch());
  1.1340 +            }
  1.1341 +        }
  1.1342 +    }
  1.1343 +
  1.1344 +    return NULL;
  1.1345 +}
  1.1346 +
  1.1347 +SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
  1.1348 +    *ttcIndex = fDWriteFontFace->GetIndex();
  1.1349 +
  1.1350 +    UINT32 numFiles;
  1.1351 +    HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
  1.1352 +         "Could not get number of font files.");
  1.1353 +    if (numFiles != 1) {
  1.1354 +        return NULL;
  1.1355 +    }
  1.1356 +
  1.1357 +    SkTScopedComPtr<IDWriteFontFile> fontFile;
  1.1358 +    HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
  1.1359 +
  1.1360 +    const void* fontFileKey;
  1.1361 +    UINT32 fontFileKeySize;
  1.1362 +    HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
  1.1363 +         "Could not get font file reference key.");
  1.1364 +
  1.1365 +    SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
  1.1366 +    HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
  1.1367 +
  1.1368 +    SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
  1.1369 +    HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
  1.1370 +                                             &fontFileStream),
  1.1371 +         "Could not create font file stream.");
  1.1372 +
  1.1373 +    return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
  1.1374 +}
  1.1375 +
  1.1376 +SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
  1.1377 +    return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
  1.1378 +}
  1.1379 +
  1.1380 +void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
  1.1381 +    if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
  1.1382 +        rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
  1.1383 +    {
  1.1384 +        rec->fMaskFormat = SkMask::kA8_Format;
  1.1385 +    }
  1.1386 +
  1.1387 +    unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
  1.1388 +                                  SkScalerContext::kForceAutohinting_Flag |
  1.1389 +                                  SkScalerContext::kEmbeddedBitmapText_Flag |
  1.1390 +                                  SkScalerContext::kEmbolden_Flag |
  1.1391 +                                  SkScalerContext::kLCD_BGROrder_Flag |
  1.1392 +                                  SkScalerContext::kLCD_Vertical_Flag;
  1.1393 +    rec->fFlags &= ~flagsWeDontSupport;
  1.1394 +
  1.1395 +    SkPaint::Hinting h = rec->getHinting();
  1.1396 +    // DirectWrite does not provide for hinting hints.
  1.1397 +    h = SkPaint::kSlight_Hinting;
  1.1398 +    rec->setHinting(h);
  1.1399 +
  1.1400 +#if SK_FONT_HOST_USE_SYSTEM_SETTINGS
  1.1401 +    IDWriteFactory* factory = get_dwrite_factory();
  1.1402 +    if (factory != NULL) {
  1.1403 +        SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
  1.1404 +        if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
  1.1405 +            float gamma = defaultRenderingParams->GetGamma();
  1.1406 +            rec->setDeviceGamma(gamma);
  1.1407 +            rec->setPaintGamma(gamma);
  1.1408 +
  1.1409 +            rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
  1.1410 +        }
  1.1411 +    }
  1.1412 +#endif
  1.1413 +}
  1.1414 +
  1.1415 +///////////////////////////////////////////////////////////////////////////////
  1.1416 +//PDF Support
  1.1417 +
  1.1418 +using namespace skia_advanced_typeface_metrics_utils;
  1.1419 +
  1.1420 +// Construct Glyph to Unicode table.
  1.1421 +// Unicode code points that require conjugate pairs in utf16 are not
  1.1422 +// supported.
  1.1423 +// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
  1.1424 +// require parsing the TTF cmap table (platform 4, encoding 12) directly instead
  1.1425 +// of calling GetFontUnicodeRange().
  1.1426 +// TODO(bungeman): This never does what anyone wants.
  1.1427 +// What is really wanted is the text to glyphs mapping
  1.1428 +static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
  1.1429 +                                      const unsigned glyphCount,
  1.1430 +                                      SkTDArray<SkUnichar>* glyphToUnicode) {
  1.1431 +    HRESULT hr = S_OK;
  1.1432 +
  1.1433 +    //Do this like free type instead
  1.1434 +    UINT32 count = 0;
  1.1435 +    for (UINT32 c = 0; c < 0x10FFFF; ++c) {
  1.1436 +        UINT16 glyph;
  1.1437 +        hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
  1.1438 +        if (glyph > 0) {
  1.1439 +            ++count;
  1.1440 +        }
  1.1441 +    }
  1.1442 +
  1.1443 +    SkAutoTArray<UINT32> chars(count);
  1.1444 +    count = 0;
  1.1445 +    for (UINT32 c = 0; c < 0x10FFFF; ++c) {
  1.1446 +        UINT16 glyph;
  1.1447 +        hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
  1.1448 +        if (glyph > 0) {
  1.1449 +            chars[count] = c;
  1.1450 +            ++count;
  1.1451 +        }
  1.1452 +    }
  1.1453 +
  1.1454 +    SkAutoTArray<UINT16> glyph(count);
  1.1455 +    fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
  1.1456 +
  1.1457 +    USHORT maxGlyph = 0;
  1.1458 +    for (USHORT j = 0; j < count; ++j) {
  1.1459 +        if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
  1.1460 +    }
  1.1461 +
  1.1462 +    glyphToUnicode->setCount(maxGlyph+1);
  1.1463 +    for (USHORT j = 0; j < maxGlyph+1u; ++j) {
  1.1464 +        (*glyphToUnicode)[j] = 0;
  1.1465 +    }
  1.1466 +
  1.1467 +    //'invert'
  1.1468 +    for (USHORT j = 0; j < count; ++j) {
  1.1469 +        if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
  1.1470 +            (*glyphToUnicode)[glyph[j]] = chars[j];
  1.1471 +        }
  1.1472 +    }
  1.1473 +}
  1.1474 +
  1.1475 +static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
  1.1476 +    SkASSERT(advance);
  1.1477 +
  1.1478 +    UINT16 glyphId = gId;
  1.1479 +    DWRITE_GLYPH_METRICS gm;
  1.1480 +    HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
  1.1481 +
  1.1482 +    if (FAILED(hr)) {
  1.1483 +        *advance = 0;
  1.1484 +        return false;
  1.1485 +    }
  1.1486 +
  1.1487 +    *advance = gm.advanceWidth;
  1.1488 +    return true;
  1.1489 +}
  1.1490 +
  1.1491 +template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
  1.1492 +public:
  1.1493 +    static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
  1.1494 +    AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
  1.1495 +
  1.1496 +    const T* operator->() const { return reinterpret_cast<const T*>(fData); }
  1.1497 +};
  1.1498 +
  1.1499 +SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
  1.1500 +        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
  1.1501 +        const uint32_t* glyphIDs,
  1.1502 +        uint32_t glyphIDsCount) const {
  1.1503 +
  1.1504 +    SkAdvancedTypefaceMetrics* info = NULL;
  1.1505 +
  1.1506 +    HRESULT hr = S_OK;
  1.1507 +
  1.1508 +    const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
  1.1509 +
  1.1510 +    DWRITE_FONT_METRICS dwfm;
  1.1511 +    fDWriteFontFace->GetMetrics(&dwfm);
  1.1512 +
  1.1513 +    info = new SkAdvancedTypefaceMetrics;
  1.1514 +    info->fEmSize = dwfm.designUnitsPerEm;
  1.1515 +    info->fMultiMaster = false;
  1.1516 +    info->fLastGlyphID = SkToU16(glyphCount - 1);
  1.1517 +    info->fStyle = 0;
  1.1518 +
  1.1519 +
  1.1520 +    SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
  1.1521 +    SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
  1.1522 +    hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
  1.1523 +    hr = fDWriteFont->GetFaceNames(&faceNames);
  1.1524 +
  1.1525 +    UINT32 familyNameLength;
  1.1526 +    hr = familyNames->GetStringLength(0, &familyNameLength);
  1.1527 +
  1.1528 +    UINT32 faceNameLength;
  1.1529 +    hr = faceNames->GetStringLength(0, &faceNameLength);
  1.1530 +
  1.1531 +    UINT32 size = familyNameLength+1+faceNameLength+1;
  1.1532 +    SkSMallocWCHAR wFamilyName(size);
  1.1533 +    hr = familyNames->GetString(0, wFamilyName.get(), size);
  1.1534 +    wFamilyName[familyNameLength] = L' ';
  1.1535 +    hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
  1.1536 +
  1.1537 +    hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName);
  1.1538 +
  1.1539 +    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
  1.1540 +        populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
  1.1541 +    }
  1.1542 +
  1.1543 +    DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
  1.1544 +    if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
  1.1545 +        fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
  1.1546 +        info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
  1.1547 +    } else {
  1.1548 +        info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
  1.1549 +        info->fItalicAngle = 0;
  1.1550 +        info->fAscent = dwfm.ascent;;
  1.1551 +        info->fDescent = dwfm.descent;
  1.1552 +        info->fStemV = 0;
  1.1553 +        info->fCapHeight = dwfm.capHeight;
  1.1554 +        info->fBBox = SkIRect::MakeEmpty();
  1.1555 +        return info;
  1.1556 +    }
  1.1557 +
  1.1558 +    AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
  1.1559 +    AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
  1.1560 +    AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
  1.1561 +    AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
  1.1562 +    if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
  1.1563 +        info->fItalicAngle = 0;
  1.1564 +        info->fAscent = dwfm.ascent;;
  1.1565 +        info->fDescent = dwfm.descent;
  1.1566 +        info->fStemV = 0;
  1.1567 +        info->fCapHeight = dwfm.capHeight;
  1.1568 +        info->fBBox = SkIRect::MakeEmpty();
  1.1569 +        return info;
  1.1570 +    }
  1.1571 +
  1.1572 +    //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
  1.1573 +    //but have full width, latin half-width, and half-width kana.
  1.1574 +    bool fixedWidth = (postTable->isFixedPitch &&
  1.1575 +                      (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
  1.1576 +    //Monospace
  1.1577 +    if (fixedWidth) {
  1.1578 +        info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
  1.1579 +    }
  1.1580 +    //Italic
  1.1581 +    if (os2Table->version.v0.fsSelection.field.Italic) {
  1.1582 +        info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
  1.1583 +    }
  1.1584 +    //Script
  1.1585 +    if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
  1.1586 +        info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
  1.1587 +    //Serif
  1.1588 +    } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
  1.1589 +               SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
  1.1590 +               SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
  1.1591 +        info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
  1.1592 +    }
  1.1593 +
  1.1594 +    info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
  1.1595 +
  1.1596 +    info->fAscent = SkToS16(dwfm.ascent);
  1.1597 +    info->fDescent = SkToS16(dwfm.descent);
  1.1598 +    info->fCapHeight = SkToS16(dwfm.capHeight);
  1.1599 +
  1.1600 +    info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
  1.1601 +                                    (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
  1.1602 +                                    (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
  1.1603 +                                    (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
  1.1604 +
  1.1605 +    //TODO: is this even desired? It seems PDF only wants this value for Type1
  1.1606 +    //fonts, and we only get here for TrueType fonts.
  1.1607 +    info->fStemV = 0;
  1.1608 +    /*
  1.1609 +    // Figure out a good guess for StemV - Min width of i, I, !, 1.
  1.1610 +    // This probably isn't very good with an italic font.
  1.1611 +    int16_t min_width = SHRT_MAX;
  1.1612 +    info->fStemV = 0;
  1.1613 +    char stem_chars[] = {'i', 'I', '!', '1'};
  1.1614 +    for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
  1.1615 +        ABC abcWidths;
  1.1616 +        if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
  1.1617 +            int16_t width = abcWidths.abcB;
  1.1618 +            if (width > 0 && width < min_width) {
  1.1619 +                min_width = width;
  1.1620 +                info->fStemV = min_width;
  1.1621 +            }
  1.1622 +        }
  1.1623 +    }
  1.1624 +    */
  1.1625 +
  1.1626 +    // If Restricted, the font may not be embedded in a document.
  1.1627 +    // If not Restricted, the font can be embedded.
  1.1628 +    // If PreviewPrint, the embedding is read-only.
  1.1629 +    if (os2Table->version.v0.fsType.field.Restricted) {
  1.1630 +        info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
  1.1631 +    } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
  1.1632 +        if (fixedWidth) {
  1.1633 +            appendRange(&info->fGlyphWidths, 0);
  1.1634 +            int16_t advance;
  1.1635 +            getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
  1.1636 +            info->fGlyphWidths->fAdvance.append(1, &advance);
  1.1637 +            finishRange(info->fGlyphWidths.get(), 0,
  1.1638 +                        SkAdvancedTypefaceMetrics::WidthRange::kDefault);
  1.1639 +        } else {
  1.1640 +            info->fGlyphWidths.reset(
  1.1641 +                getAdvanceData(fDWriteFontFace.get(),
  1.1642 +                               glyphCount,
  1.1643 +                               glyphIDs,
  1.1644 +                               glyphIDsCount,
  1.1645 +                               getWidthAdvance));
  1.1646 +        }
  1.1647 +    }
  1.1648 +
  1.1649 +    return info;
  1.1650 +}
  1.1651 +
  1.1652 +///////////////////////////////////////////////////////////////////////////////
  1.1653 +
  1.1654 +static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
  1.1655 +                              SkString* skname) {
  1.1656 +    UINT32 nameIndex = 0;
  1.1657 +    if (preferedLocale) {
  1.1658 +        // Ignore any errors and continue with index 0 if there is a problem.
  1.1659 +        BOOL nameExists;
  1.1660 +        names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
  1.1661 +        if (!nameExists) {
  1.1662 +            nameIndex = 0;
  1.1663 +        }
  1.1664 +    }
  1.1665 +
  1.1666 +    UINT32 nameLength;
  1.1667 +    HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
  1.1668 +    nameLength += 1;
  1.1669 +
  1.1670 +    SkSMallocWCHAR name(nameLength);
  1.1671 +    HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
  1.1672 +
  1.1673 +    HRV(wchar_to_skstring(name.get(), skname));
  1.1674 +}
  1.1675 +
  1.1676 +SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
  1.1677 +        IDWriteFontFace* fontFace,
  1.1678 +        IDWriteFont* font,
  1.1679 +        IDWriteFontFamily* fontFamily,
  1.1680 +        StreamFontFileLoader* fontFileLoader,
  1.1681 +        IDWriteFontCollectionLoader* fontCollectionLoader) const {
  1.1682 +    SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font);
  1.1683 +    if (NULL == face) {
  1.1684 +        face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
  1.1685 +                                          fontFileLoader, fontCollectionLoader);
  1.1686 +        if (face) {
  1.1687 +            Add(face, get_style(font), fontCollectionLoader != NULL);
  1.1688 +        }
  1.1689 +    }
  1.1690 +    return face;
  1.1691 +}
  1.1692 +
  1.1693 +int SkFontMgr_DirectWrite::onCountFamilies() const {
  1.1694 +    return fFontCollection->GetFontFamilyCount();
  1.1695 +}
  1.1696 +
  1.1697 +void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
  1.1698 +    SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  1.1699 +    HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
  1.1700 +
  1.1701 +    SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
  1.1702 +    HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
  1.1703 +
  1.1704 +    get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
  1.1705 +}
  1.1706 +
  1.1707 +SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
  1.1708 +    SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  1.1709 +    HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
  1.1710 +
  1.1711 +    return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
  1.1712 +}
  1.1713 +
  1.1714 +SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
  1.1715 +    SkSMallocWCHAR dwFamilyName;
  1.1716 +    HRN(cstring_to_wchar(familyName, &dwFamilyName));
  1.1717 +
  1.1718 +    UINT32 index;
  1.1719 +    BOOL exists;
  1.1720 +    HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
  1.1721 +            "Failed while finding family by name.");
  1.1722 +    if (!exists) {
  1.1723 +        return NULL;
  1.1724 +    }
  1.1725 +
  1.1726 +    return this->onCreateStyleSet(index);
  1.1727 +}
  1.1728 +
  1.1729 +SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
  1.1730 +                                                      const SkFontStyle& fontstyle) const {
  1.1731 +    SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
  1.1732 +    return sset->matchStyle(fontstyle);
  1.1733 +}
  1.1734 +
  1.1735 +SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
  1.1736 +                                                    const SkFontStyle& fontstyle) const {
  1.1737 +    SkString familyName;
  1.1738 +    SkFontStyleSet_DirectWrite sset(
  1.1739 +        this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
  1.1740 +    );
  1.1741 +    return sset.matchStyle(fontstyle);
  1.1742 +}
  1.1743 +
  1.1744 +SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const {
  1.1745 +    return create_from_stream(stream, ttcIndex);
  1.1746 +}
  1.1747 +
  1.1748 +SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
  1.1749 +    SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
  1.1750 +    return this->createFromStream(stream, ttcIndex);
  1.1751 +}
  1.1752 +
  1.1753 +SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
  1.1754 +    SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
  1.1755 +    return this->createFromStream(stream, ttcIndex);
  1.1756 +}
  1.1757 +
  1.1758 +HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
  1.1759 +                                               IDWriteFontFamily** fontFamily) const {
  1.1760 +    UINT32 index;
  1.1761 +    BOOL exists;
  1.1762 +    HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
  1.1763 +
  1.1764 +    if (exists) {
  1.1765 +        HR(fFontCollection->GetFontFamily(index, fontFamily));
  1.1766 +        return S_OK;
  1.1767 +    }
  1.1768 +    return S_FALSE;
  1.1769 +}
  1.1770 +
  1.1771 +HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const {
  1.1772 +    NONCLIENTMETRICSW metrics;
  1.1773 +    metrics.cbSize = sizeof(metrics);
  1.1774 +    if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
  1.1775 +                                   sizeof(metrics),
  1.1776 +                                   &metrics,
  1.1777 +                                   0)) {
  1.1778 +        return E_UNEXPECTED;
  1.1779 +    }
  1.1780 +    HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
  1.1781 +        "Could not create DWrite font family from LOGFONT.");
  1.1782 +
  1.1783 +    return S_OK;
  1.1784 +}
  1.1785 +
  1.1786 +SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
  1.1787 +                                                          unsigned styleBits) const {
  1.1788 +    SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  1.1789 +    if (familyName) {
  1.1790 +        SkSMallocWCHAR wideFamilyName;
  1.1791 +        if (SUCCEEDED(cstring_to_wchar(familyName, &wideFamilyName))) {
  1.1792 +            this->getByFamilyName(wideFamilyName, &fontFamily);
  1.1793 +        }
  1.1794 +    }
  1.1795 +
  1.1796 +    if (NULL == fontFamily.get()) {
  1.1797 +        // No family with given name, try default.
  1.1798 +        HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
  1.1799 +    }
  1.1800 +
  1.1801 +    SkTScopedComPtr<IDWriteFont> font;
  1.1802 +    DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
  1.1803 +                              ? DWRITE_FONT_WEIGHT_BOLD
  1.1804 +                              : DWRITE_FONT_WEIGHT_NORMAL;
  1.1805 +    DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
  1.1806 +    DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
  1.1807 +                             ? DWRITE_FONT_STYLE_ITALIC
  1.1808 +                             : DWRITE_FONT_STYLE_NORMAL;
  1.1809 +    HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
  1.1810 +         "Could not get matching font.");
  1.1811 +
  1.1812 +    SkTScopedComPtr<IDWriteFontFace> fontFace;
  1.1813 +    HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  1.1814 +
  1.1815 +    return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
  1.1816 +}
  1.1817 +
  1.1818 +///////////////////////////////////////////////////////////////////////////////
  1.1819 +
  1.1820 +int SkFontStyleSet_DirectWrite::count() {
  1.1821 +    return fFontFamily->GetFontCount();
  1.1822 +}
  1.1823 +
  1.1824 +SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
  1.1825 +    SkTScopedComPtr<IDWriteFont> font;
  1.1826 +    HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
  1.1827 +
  1.1828 +    SkTScopedComPtr<IDWriteFontFace> fontFace;
  1.1829 +    HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  1.1830 +
  1.1831 +    return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
  1.1832 +}
  1.1833 +
  1.1834 +void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
  1.1835 +    SkTScopedComPtr<IDWriteFont> font;
  1.1836 +    HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
  1.1837 +
  1.1838 +    SkFontStyle::Slant slant;
  1.1839 +    switch (font->GetStyle()) {
  1.1840 +    case DWRITE_FONT_STYLE_NORMAL:
  1.1841 +        slant = SkFontStyle::kUpright_Slant;
  1.1842 +        break;
  1.1843 +    case DWRITE_FONT_STYLE_OBLIQUE:
  1.1844 +    case DWRITE_FONT_STYLE_ITALIC:
  1.1845 +        slant = SkFontStyle::kItalic_Slant;
  1.1846 +        break;
  1.1847 +    default:
  1.1848 +        SkASSERT(false);
  1.1849 +    }
  1.1850 +
  1.1851 +    int weight = font->GetWeight();
  1.1852 +    int width = font->GetStretch();
  1.1853 +
  1.1854 +    *fs = SkFontStyle(weight, width, slant);
  1.1855 +
  1.1856 +    SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
  1.1857 +    if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
  1.1858 +        get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
  1.1859 +    }
  1.1860 +}
  1.1861 +
  1.1862 +SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
  1.1863 +    DWRITE_FONT_STYLE slant;
  1.1864 +    switch (pattern.slant()) {
  1.1865 +    case SkFontStyle::kUpright_Slant:
  1.1866 +        slant = DWRITE_FONT_STYLE_NORMAL;
  1.1867 +        break;
  1.1868 +    case SkFontStyle::kItalic_Slant:
  1.1869 +        slant = DWRITE_FONT_STYLE_ITALIC;
  1.1870 +        break;
  1.1871 +    default:
  1.1872 +        SkASSERT(false);
  1.1873 +    }
  1.1874 +
  1.1875 +    DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
  1.1876 +    DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
  1.1877 +
  1.1878 +    SkTScopedComPtr<IDWriteFont> font;
  1.1879 +    // TODO: perhaps use GetMatchingFonts and get the least simulated?
  1.1880 +    HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
  1.1881 +            "Could not match font in family.");
  1.1882 +
  1.1883 +    SkTScopedComPtr<IDWriteFontFace> fontFace;
  1.1884 +    HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  1.1885 +
  1.1886 +    return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
  1.1887 +                                                  fFontFamily.get());
  1.1888 +}
  1.1889 +
  1.1890 +///////////////////////////////////////////////////////////////////////////////
  1.1891 +
  1.1892 +typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameProc;
  1.1893 +static HRESULT GetGetUserDefaultLocaleNameProc(GetUserDefaultLocaleNameProc* proc) {
  1.1894 +    *proc = reinterpret_cast<GetUserDefaultLocaleNameProc>(
  1.1895 +        GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName")
  1.1896 +    );
  1.1897 +    if (!*proc) {
  1.1898 +        HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1.1899 +        if (!IS_ERROR(hr)) {
  1.1900 +            hr = ERROR_PROC_NOT_FOUND;
  1.1901 +        }
  1.1902 +        return hr;
  1.1903 +    }
  1.1904 +    return S_OK;
  1.1905 +}
  1.1906 +
  1.1907 +SkFontMgr* SkFontMgr_New_DirectWrite() {
  1.1908 +    IDWriteFactory* factory = get_dwrite_factory();
  1.1909 +    if (NULL == factory) {
  1.1910 +        return NULL;
  1.1911 +    }
  1.1912 +
  1.1913 +    SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
  1.1914 +    HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
  1.1915 +         "Could not get system font collection.");
  1.1916 +
  1.1917 +    WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
  1.1918 +    WCHAR* localeName = NULL;
  1.1919 +    int localeNameLen = 0;
  1.1920 +
  1.1921 +    // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
  1.1922 +    GetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
  1.1923 +    HRESULT hr = GetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
  1.1924 +    if (NULL == getUserDefaultLocaleNameProc) {
  1.1925 +        SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
  1.1926 +    } else {
  1.1927 +        localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
  1.1928 +        if (localeNameLen) {
  1.1929 +            localeName = localeNameStorage;
  1.1930 +        };
  1.1931 +    }
  1.1932 +
  1.1933 +    return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));
  1.1934 +}

mercurial