| Index: src/ports/SkFontMgr_win_dw.cpp
|
| diff --git a/src/ports/SkFontMgr_win_dw.cpp b/src/ports/SkFontMgr_win_dw.cpp
|
| index 96acd170ae73071371386b8bc611e02eb3721a01..669a95b2d594b30d5e4e2c887cec32acd0d5f3e6 100644
|
| --- a/src/ports/SkFontMgr_win_dw.cpp
|
| +++ b/src/ports/SkFontMgr_win_dw.cpp
|
| @@ -20,6 +20,10 @@
|
|
|
| #include <dwrite.h>
|
|
|
| +#if SK_HAS_DWRITE_2_H
|
| +#include <dwrite_2.h>
|
| +#endif
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|
| class StreamFontFileLoader : public IDWriteFontFileLoader {
|
| @@ -262,6 +266,13 @@ public:
|
| , fFontCollection(SkRefComPtr(fontCollection))
|
| , fLocaleName(localeNameLength)
|
| {
|
| +#ifdef SK_HAS_DWRITE_2_H
|
| + if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) {
|
| + // IUnknown::QueryInterface states that if it fails, punk will be set to NULL.
|
| + // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
|
| + SK_ALWAYSBREAK(NULL == fFactory2.get());
|
| + }
|
| +#endif
|
| memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
|
| }
|
|
|
| @@ -293,6 +304,9 @@ private:
|
| IDWriteFontFamily* fontFamily) const;
|
|
|
| SkTScopedComPtr<IDWriteFactory> fFactory;
|
| +#ifdef SK_HAS_DWRITE_2_H
|
| + SkTScopedComPtr<IDWriteFactory2> fFactory2;
|
| +#endif
|
| SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
|
| SkSMallocWCHAR fLocaleName;
|
| mutable SkMutex fTFCacheMutex;
|
| @@ -593,9 +607,7 @@ public:
|
| return newCount;
|
| }
|
|
|
| - virtual HRESULT STDMETHODCALLTYPE QueryInterface(
|
| - IID const& riid, void** ppvObject) SK_OVERRIDE
|
| - {
|
| + virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) SK_OVERRIDE{
|
| if (__uuidof(IUnknown) == riid ||
|
| __uuidof(IDWritePixelSnapping) == riid ||
|
| __uuidof(IDWriteTextRenderer) == riid)
|
| @@ -632,13 +644,110 @@ static HRESULT getDefaultFontFamilyName(SkSMallocWCHAR* name) {
|
| return S_OK;
|
| }
|
|
|
| +class FontFallbackSource : public IDWriteTextAnalysisSource {
|
| +public:
|
| + FontFallbackSource(const WCHAR* string, UINT32 length, const WCHAR* locale,
|
| + IDWriteNumberSubstitution* numberSubstitution)
|
| + : fString(string)
|
| + , fLength(length)
|
| + , fLocale(locale)
|
| + , fNumberSubstitution(numberSubstitution)
|
| + { }
|
| +
|
| + virtual ~FontFallbackSource() { }
|
| +
|
| + // IDWriteTextAnalysisSource methods
|
| + virtual HRESULT STDMETHODCALLTYPE GetTextAtPosition(
|
| + UINT32 textPosition,
|
| + WCHAR const** textString,
|
| + UINT32* textLength) SK_OVERRIDE
|
| + {
|
| + if (fLength <= textPosition) {
|
| + *textString = NULL;
|
| + *textLength = 0;
|
| + return S_OK;
|
| + }
|
| + *textString = fString + textPosition;
|
| + *textLength = fLength - textPosition;
|
| + return S_OK;
|
| + }
|
| +
|
| + virtual HRESULT STDMETHODCALLTYPE GetTextBeforePosition(
|
| + UINT32 textPosition,
|
| + WCHAR const** textString,
|
| + UINT32* textLength) SK_OVERRIDE
|
| + {
|
| + if (textPosition < 1 || fLength <= textPosition) {
|
| + *textString = NULL;
|
| + *textLength = 0;
|
| + return S_OK;
|
| + }
|
| + *textString = fString;
|
| + *textLength = textPosition;
|
| + return S_OK;
|
| + }
|
| +
|
| + virtual DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirection() SK_OVERRIDE {
|
| + // TODO: this is also interesting.
|
| + return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
|
| + }
|
| +
|
| + virtual HRESULT STDMETHODCALLTYPE GetLocaleName(
|
| + UINT32 textPosition,
|
| + UINT32* textLength,
|
| + WCHAR const** localeName) SK_OVERRIDE
|
| + {
|
| + *localeName = fLocale;
|
| + return S_OK;
|
| + }
|
| +
|
| + virtual HRESULT STDMETHODCALLTYPE GetNumberSubstitution(
|
| + UINT32 textPosition,
|
| + UINT32* textLength,
|
| + IDWriteNumberSubstitution** numberSubstitution) SK_OVERRIDE
|
| + {
|
| + *numberSubstitution = fNumberSubstitution;
|
| + return S_OK;
|
| + }
|
| +
|
| + // IUnknown methods
|
| + ULONG STDMETHODCALLTYPE AddRef() SK_OVERRIDE {
|
| + return InterlockedIncrement(&fRefCount);
|
| + }
|
| +
|
| + ULONG STDMETHODCALLTYPE Release() SK_OVERRIDE {
|
| + ULONG newCount = InterlockedDecrement(&fRefCount);
|
| + if (0 == newCount) {
|
| + delete this;
|
| + }
|
| + return newCount;
|
| + }
|
| +
|
| + virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) SK_OVERRIDE{
|
| + if (__uuidof(IUnknown) == riid ||
|
| + __uuidof(IDWriteTextAnalysisSource) == riid)
|
| + {
|
| + *ppvObject = this;
|
| + this->AddRef();
|
| + return S_OK;
|
| + }
|
| + *ppvObject = NULL;
|
| + return E_FAIL;
|
| + }
|
| +
|
| +protected:
|
| + ULONG fRefCount;
|
| + const WCHAR* fString;
|
| + UINT32 fLength;
|
| + const WCHAR* fLocale;
|
| + IDWriteNumberSubstitution* fNumberSubstitution;
|
| +};
|
| +
|
| SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char familyName[],
|
| const SkFontStyle& style,
|
| const char* bcp47[], int bcp47Count,
|
| SkUnichar character) const
|
| {
|
| - // TODO: use IDWriteFactory2::GetSystemFontFallback when available.
|
| -
|
| const DWriteStyle dwStyle(style);
|
|
|
| SkSMallocWCHAR dwFamilyName;
|
| @@ -648,6 +757,10 @@ SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char family
|
| HRN(sk_cstring_to_wchar(familyName, &dwFamilyName));
|
| }
|
|
|
| + WCHAR str[16];
|
| + UINT32 strLen = static_cast<UINT32>(
|
| + SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str)));
|
| +
|
| const SkSMallocWCHAR* dwBcp47;
|
| SkSMallocWCHAR dwBcp47Local;
|
| if (bcp47Count < 1) {
|
| @@ -660,6 +773,48 @@ SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char family
|
| dwBcp47 = &dwBcp47Local;
|
| }
|
|
|
| +#if SK_HAS_DWRITE_2_H
|
| + if (fFactory2.get()) {
|
| + SkTScopedComPtr<IDWriteFontFallback> fontFallback;
|
| + HRNM(fFactory2->GetSystemFontFallback(&fontFallback), "Could not get system fallback.");
|
| +
|
| + SkTScopedComPtr<IDWriteNumberSubstitution> numberSubstitution;
|
| + HRNM(fFactory2->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, NULL, TRUE,
|
| + &numberSubstitution),
|
| + "Could not create number substitution.");
|
| + SkTScopedComPtr<FontFallbackSource> fontFallbackSource(
|
| + new FontFallbackSource(str, strLen, *dwBcp47, numberSubstitution.get()));
|
| +
|
| + UINT32 mappedLength;
|
| + SkTScopedComPtr<IDWriteFont> font;
|
| + FLOAT scale;
|
| + HRNM(fontFallback->MapCharacters(fontFallbackSource.get(),
|
| + 0, // textPosition,
|
| + strLen,
|
| + fFontCollection.get(),
|
| + dwFamilyName,
|
| + dwStyle.fWeight,
|
| + dwStyle.fSlant,
|
| + dwStyle.fWidth,
|
| + &mappedLength,
|
| + &font,
|
| + &scale),
|
| + "Could not map characters");
|
| + if (!font.get()) {
|
| + return NULL;
|
| + }
|
| +
|
| + SkTScopedComPtr<IDWriteFontFace> fontFace;
|
| + HRNM(font->CreateFontFace(&fontFace), "Could not get font face from font.");
|
| +
|
| + SkTScopedComPtr<IDWriteFontFamily> fontFamily;
|
| + HRNM(font->GetFontFamily(&fontFamily), "Could not get family from font.");
|
| + return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
|
| + }
|
| +#else
|
| +# pragma message("No dwrite_2.h is available, font fallback may be affected.")
|
| +#endif
|
| +
|
| SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
|
| HRNM(fFactory->CreateTextFormat(dwFamilyName,
|
| fFontCollection.get(),
|
| @@ -671,9 +826,6 @@ SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char family
|
| &fallbackFormat),
|
| "Could not create text format.");
|
|
|
| - WCHAR str[16];
|
| - UINT32 strLen = static_cast<UINT32>(
|
| - SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str)));
|
| SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
|
| HRNM(fFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
|
| 200.0f, 200.0f,
|
|
|