| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkDWrite.h" | 8 #include "SkDWrite.h" |
| 9 #include "SkDWriteFontFileStream.h" | 9 #include "SkDWriteFontFileStream.h" |
| 10 #include "SkFontMgr.h" | 10 #include "SkFontMgr.h" |
| 11 #include "SkHRESULT.h" | 11 #include "SkHRESULT.h" |
| 12 #include "SkStream.h" | 12 #include "SkStream.h" |
| 13 #include "SkTScopedComPtr.h" | 13 #include "SkTScopedComPtr.h" |
| 14 #include "SkThread.h" | 14 #include "SkThread.h" |
| 15 #include "SkTypeface.h" | 15 #include "SkTypeface.h" |
| 16 #include "SkTypefaceCache.h" | 16 #include "SkTypefaceCache.h" |
| 17 #include "SkTypeface_win_dw.h" | 17 #include "SkTypeface_win_dw.h" |
| 18 #include "SkTypes.h" | 18 #include "SkTypes.h" |
| 19 #include "SkUtils.h" | 19 #include "SkUtils.h" |
| 20 | 20 |
| 21 #include <dwrite.h> | 21 #include <dwrite.h> |
| 22 | 22 |
| 23 #if SK_HAS_DWRITE_2_H |
| 24 #include <dwrite_2.h> |
| 25 #endif |
| 26 |
| 23 //////////////////////////////////////////////////////////////////////////////// | 27 //////////////////////////////////////////////////////////////////////////////// |
| 24 | 28 |
| 25 class StreamFontFileLoader : public IDWriteFontFileLoader { | 29 class StreamFontFileLoader : public IDWriteFontFileLoader { |
| 26 public: | 30 public: |
| 27 // IUnknown methods | 31 // IUnknown methods |
| 28 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObjec
t); | 32 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObjec
t); |
| 29 virtual ULONG STDMETHODCALLTYPE AddRef(); | 33 virtual ULONG STDMETHODCALLTYPE AddRef(); |
| 30 virtual ULONG STDMETHODCALLTYPE Release(); | 34 virtual ULONG STDMETHODCALLTYPE Release(); |
| 31 | 35 |
| 32 // IDWriteFontFileLoader methods | 36 // IDWriteFontFileLoader methods |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 | 259 |
| 256 class SkFontMgr_DirectWrite : public SkFontMgr { | 260 class SkFontMgr_DirectWrite : public SkFontMgr { |
| 257 public: | 261 public: |
| 258 /** localeNameLength must include the null terminator. */ | 262 /** localeNameLength must include the null terminator. */ |
| 259 SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCo
llection, | 263 SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCo
llection, |
| 260 WCHAR* localeName, int localeNameLength) | 264 WCHAR* localeName, int localeNameLength) |
| 261 : fFactory(SkRefComPtr(factory)) | 265 : fFactory(SkRefComPtr(factory)) |
| 262 , fFontCollection(SkRefComPtr(fontCollection)) | 266 , fFontCollection(SkRefComPtr(fontCollection)) |
| 263 , fLocaleName(localeNameLength) | 267 , fLocaleName(localeNameLength) |
| 264 { | 268 { |
| 269 #ifdef SK_HAS_DWRITE_2_H |
| 270 if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) { |
| 271 // IUnknown::QueryInterface states that if it fails, punk will be se
t to NULL. |
| 272 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx |
| 273 SK_ALWAYSBREAK(NULL == fFactory2.get()); |
| 274 } |
| 275 #endif |
| 265 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR)); | 276 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR)); |
| 266 } | 277 } |
| 267 | 278 |
| 268 protected: | 279 protected: |
| 269 int onCountFamilies() const SK_OVERRIDE; | 280 int onCountFamilies() const SK_OVERRIDE; |
| 270 void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE; | 281 void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE; |
| 271 SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE; | 282 SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE; |
| 272 SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE; | 283 SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE; |
| 273 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], | 284 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], |
| 274 const SkFontStyle& fontstyle) const S
K_OVERRIDE; | 285 const SkFontStyle& fontstyle) const S
K_OVERRIDE; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 286 private: | 297 private: |
| 287 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFa
mily) const; | 298 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFa
mily) const; |
| 288 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const; | 299 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const; |
| 289 | 300 |
| 290 /** Creates a typeface using a typeface cache. */ | 301 /** Creates a typeface using a typeface cache. */ |
| 291 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace, | 302 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace, |
| 292 IDWriteFont* font, | 303 IDWriteFont* font, |
| 293 IDWriteFontFamily* fontFamily) cons
t; | 304 IDWriteFontFamily* fontFamily) cons
t; |
| 294 | 305 |
| 295 SkTScopedComPtr<IDWriteFactory> fFactory; | 306 SkTScopedComPtr<IDWriteFactory> fFactory; |
| 307 #ifdef SK_HAS_DWRITE_2_H |
| 308 SkTScopedComPtr<IDWriteFactory2> fFactory2; |
| 309 #endif |
| 296 SkTScopedComPtr<IDWriteFontCollection> fFontCollection; | 310 SkTScopedComPtr<IDWriteFontCollection> fFontCollection; |
| 297 SkSMallocWCHAR fLocaleName; | 311 SkSMallocWCHAR fLocaleName; |
| 298 mutable SkMutex fTFCacheMutex; | 312 mutable SkMutex fTFCacheMutex; |
| 299 mutable SkTypefaceCache fTFCache; | 313 mutable SkTypefaceCache fTFCache; |
| 300 | 314 |
| 301 friend class SkFontStyleSet_DirectWrite; | 315 friend class SkFontStyleSet_DirectWrite; |
| 302 friend class FontFallbackRenderer; | 316 friend class FontFallbackRenderer; |
| 303 }; | 317 }; |
| 304 | 318 |
| 305 class SkFontStyleSet_DirectWrite : public SkFontStyleSet { | 319 class SkFontStyleSet_DirectWrite : public SkFontStyleSet { |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 } | 600 } |
| 587 | 601 |
| 588 ULONG STDMETHODCALLTYPE Release() SK_OVERRIDE { | 602 ULONG STDMETHODCALLTYPE Release() SK_OVERRIDE { |
| 589 ULONG newCount = InterlockedDecrement(&fRefCount); | 603 ULONG newCount = InterlockedDecrement(&fRefCount); |
| 590 if (0 == newCount) { | 604 if (0 == newCount) { |
| 591 delete this; | 605 delete this; |
| 592 } | 606 } |
| 593 return newCount; | 607 return newCount; |
| 594 } | 608 } |
| 595 | 609 |
| 596 virtual HRESULT STDMETHODCALLTYPE QueryInterface( | 610 virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppv
Object) SK_OVERRIDE{ |
| 597 IID const& riid, void** ppvObject) SK_OVERRIDE | |
| 598 { | |
| 599 if (__uuidof(IUnknown) == riid || | 611 if (__uuidof(IUnknown) == riid || |
| 600 __uuidof(IDWritePixelSnapping) == riid || | 612 __uuidof(IDWritePixelSnapping) == riid || |
| 601 __uuidof(IDWriteTextRenderer) == riid) | 613 __uuidof(IDWriteTextRenderer) == riid) |
| 602 { | 614 { |
| 603 *ppvObject = this; | 615 *ppvObject = this; |
| 604 this->AddRef(); | 616 this->AddRef(); |
| 605 return S_OK; | 617 return S_OK; |
| 606 } | 618 } |
| 607 *ppvObject = NULL; | 619 *ppvObject = NULL; |
| 608 return E_FAIL; | 620 return E_FAIL; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 625 } | 637 } |
| 626 | 638 |
| 627 size_t len = wcsnlen_s(metrics.lfMessageFont.lfFaceName, LF_FACESIZE) + 1; | 639 size_t len = wcsnlen_s(metrics.lfMessageFont.lfFaceName, LF_FACESIZE) + 1; |
| 628 if (0 != wcsncpy_s(name->reset(len), len, metrics.lfMessageFont.lfFaceName,
_TRUNCATE)) { | 640 if (0 != wcsncpy_s(name->reset(len), len, metrics.lfMessageFont.lfFaceName,
_TRUNCATE)) { |
| 629 return E_UNEXPECTED; | 641 return E_UNEXPECTED; |
| 630 } | 642 } |
| 631 | 643 |
| 632 return S_OK; | 644 return S_OK; |
| 633 } | 645 } |
| 634 | 646 |
| 647 class FontFallbackSource : public IDWriteTextAnalysisSource { |
| 648 public: |
| 649 FontFallbackSource(const WCHAR* string, UINT32 length, const WCHAR* locale, |
| 650 IDWriteNumberSubstitution* numberSubstitution) |
| 651 : fString(string) |
| 652 , fLength(length) |
| 653 , fLocale(locale) |
| 654 , fNumberSubstitution(numberSubstitution) |
| 655 { } |
| 656 |
| 657 virtual ~FontFallbackSource() { } |
| 658 |
| 659 // IDWriteTextAnalysisSource methods |
| 660 virtual HRESULT STDMETHODCALLTYPE GetTextAtPosition( |
| 661 UINT32 textPosition, |
| 662 WCHAR const** textString, |
| 663 UINT32* textLength) SK_OVERRIDE |
| 664 { |
| 665 if (fLength <= textPosition) { |
| 666 *textString = NULL; |
| 667 *textLength = 0; |
| 668 return S_OK; |
| 669 } |
| 670 *textString = fString + textPosition; |
| 671 *textLength = fLength - textPosition; |
| 672 return S_OK; |
| 673 } |
| 674 |
| 675 virtual HRESULT STDMETHODCALLTYPE GetTextBeforePosition( |
| 676 UINT32 textPosition, |
| 677 WCHAR const** textString, |
| 678 UINT32* textLength) SK_OVERRIDE |
| 679 { |
| 680 if (textPosition < 1 || fLength <= textPosition) { |
| 681 *textString = NULL; |
| 682 *textLength = 0; |
| 683 return S_OK; |
| 684 } |
| 685 *textString = fString; |
| 686 *textLength = textPosition; |
| 687 return S_OK; |
| 688 } |
| 689 |
| 690 virtual DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirect
ion() SK_OVERRIDE { |
| 691 // TODO: this is also interesting. |
| 692 return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT; |
| 693 } |
| 694 |
| 695 virtual HRESULT STDMETHODCALLTYPE GetLocaleName( |
| 696 UINT32 textPosition, |
| 697 UINT32* textLength, |
| 698 WCHAR const** localeName) SK_OVERRIDE |
| 699 { |
| 700 *localeName = fLocale; |
| 701 return S_OK; |
| 702 } |
| 703 |
| 704 virtual HRESULT STDMETHODCALLTYPE GetNumberSubstitution( |
| 705 UINT32 textPosition, |
| 706 UINT32* textLength, |
| 707 IDWriteNumberSubstitution** numberSubstitution) SK_OVERRIDE |
| 708 { |
| 709 *numberSubstitution = fNumberSubstitution; |
| 710 return S_OK; |
| 711 } |
| 712 |
| 713 // IUnknown methods |
| 714 ULONG STDMETHODCALLTYPE AddRef() SK_OVERRIDE { |
| 715 return InterlockedIncrement(&fRefCount); |
| 716 } |
| 717 |
| 718 ULONG STDMETHODCALLTYPE Release() SK_OVERRIDE { |
| 719 ULONG newCount = InterlockedDecrement(&fRefCount); |
| 720 if (0 == newCount) { |
| 721 delete this; |
| 722 } |
| 723 return newCount; |
| 724 } |
| 725 |
| 726 virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppv
Object) SK_OVERRIDE{ |
| 727 if (__uuidof(IUnknown) == riid || |
| 728 __uuidof(IDWriteTextAnalysisSource) == riid) |
| 729 { |
| 730 *ppvObject = this; |
| 731 this->AddRef(); |
| 732 return S_OK; |
| 733 } |
| 734 *ppvObject = NULL; |
| 735 return E_FAIL; |
| 736 } |
| 737 |
| 738 protected: |
| 739 ULONG fRefCount; |
| 740 const WCHAR* fString; |
| 741 UINT32 fLength; |
| 742 const WCHAR* fLocale; |
| 743 IDWriteNumberSubstitution* fNumberSubstitution; |
| 744 }; |
| 745 |
| 635 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char family
Name[], | 746 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char family
Name[], |
| 636 const SkFontStyle
& style, | 747 const SkFontStyle
& style, |
| 637 const char* bcp47
[], int bcp47Count, | 748 const char* bcp47
[], int bcp47Count, |
| 638 SkUnichar charact
er) const | 749 SkUnichar charact
er) const |
| 639 { | 750 { |
| 640 // TODO: use IDWriteFactory2::GetSystemFontFallback when available. | |
| 641 | |
| 642 const DWriteStyle dwStyle(style); | 751 const DWriteStyle dwStyle(style); |
| 643 | 752 |
| 644 SkSMallocWCHAR dwFamilyName; | 753 SkSMallocWCHAR dwFamilyName; |
| 645 if (NULL == familyName) { | 754 if (NULL == familyName) { |
| 646 HRN(getDefaultFontFamilyName(&dwFamilyName)); | 755 HRN(getDefaultFontFamilyName(&dwFamilyName)); |
| 647 } else { | 756 } else { |
| 648 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName)); | 757 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName)); |
| 649 } | 758 } |
| 650 | 759 |
| 760 WCHAR str[16]; |
| 761 UINT32 strLen = static_cast<UINT32>( |
| 762 SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str))); |
| 763 |
| 651 const SkSMallocWCHAR* dwBcp47; | 764 const SkSMallocWCHAR* dwBcp47; |
| 652 SkSMallocWCHAR dwBcp47Local; | 765 SkSMallocWCHAR dwBcp47Local; |
| 653 if (bcp47Count < 1) { | 766 if (bcp47Count < 1) { |
| 654 dwBcp47 = &fLocaleName; | 767 dwBcp47 = &fLocaleName; |
| 655 } else { | 768 } else { |
| 656 // TODO: support fallback stack. | 769 // TODO: support fallback stack. |
| 657 // TODO: DirectWrite supports 'zh-CN' or 'zh-Hans', but 'zh' misses comp
letely | 770 // TODO: DirectWrite supports 'zh-CN' or 'zh-Hans', but 'zh' misses comp
letely |
| 658 // and may produce a Japanese font. | 771 // and may produce a Japanese font. |
| 659 HRN(sk_cstring_to_wchar(bcp47[bcp47Count - 1], &dwBcp47Local)); | 772 HRN(sk_cstring_to_wchar(bcp47[bcp47Count - 1], &dwBcp47Local)); |
| 660 dwBcp47 = &dwBcp47Local; | 773 dwBcp47 = &dwBcp47Local; |
| 661 } | 774 } |
| 662 | 775 |
| 776 #if SK_HAS_DWRITE_2_H |
| 777 if (fFactory2.get()) { |
| 778 SkTScopedComPtr<IDWriteFontFallback> fontFallback; |
| 779 HRNM(fFactory2->GetSystemFontFallback(&fontFallback), "Could not get sys
tem fallback."); |
| 780 |
| 781 SkTScopedComPtr<IDWriteNumberSubstitution> numberSubstitution; |
| 782 HRNM(fFactory2->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METH
OD_NONE, NULL, TRUE, |
| 783 &numberSubstitution), |
| 784 "Could not create number substitution."); |
| 785 SkTScopedComPtr<FontFallbackSource> fontFallbackSource( |
| 786 new FontFallbackSource(str, strLen, *dwBcp47, numberSubstitution.get
())); |
| 787 |
| 788 UINT32 mappedLength; |
| 789 SkTScopedComPtr<IDWriteFont> font; |
| 790 FLOAT scale; |
| 791 HRNM(fontFallback->MapCharacters(fontFallbackSource.get(), |
| 792 0, // textPosition, |
| 793 strLen, |
| 794 fFontCollection.get(), |
| 795 dwFamilyName, |
| 796 dwStyle.fWeight, |
| 797 dwStyle.fSlant, |
| 798 dwStyle.fWidth, |
| 799 &mappedLength, |
| 800 &font, |
| 801 &scale), |
| 802 "Could not map characters"); |
| 803 if (!font.get()) { |
| 804 return NULL; |
| 805 } |
| 806 |
| 807 SkTScopedComPtr<IDWriteFontFace> fontFace; |
| 808 HRNM(font->CreateFontFace(&fontFace), "Could not get font face from font
."); |
| 809 |
| 810 SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
| 811 HRNM(font->GetFontFamily(&fontFamily), "Could not get family from font."
); |
| 812 return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fo
ntFamily.get()); |
| 813 } |
| 814 #else |
| 815 # pragma message("No dwrite_2.h is available, font fallback may be affected.") |
| 816 #endif |
| 817 |
| 663 SkTScopedComPtr<IDWriteTextFormat> fallbackFormat; | 818 SkTScopedComPtr<IDWriteTextFormat> fallbackFormat; |
| 664 HRNM(fFactory->CreateTextFormat(dwFamilyName, | 819 HRNM(fFactory->CreateTextFormat(dwFamilyName, |
| 665 fFontCollection.get(), | 820 fFontCollection.get(), |
| 666 dwStyle.fWeight, | 821 dwStyle.fWeight, |
| 667 dwStyle.fSlant, | 822 dwStyle.fSlant, |
| 668 dwStyle.fWidth, | 823 dwStyle.fWidth, |
| 669 72.0f, | 824 72.0f, |
| 670 *dwBcp47, | 825 *dwBcp47, |
| 671 &fallbackFormat), | 826 &fallbackFormat), |
| 672 "Could not create text format."); | 827 "Could not create text format."); |
| 673 | 828 |
| 674 WCHAR str[16]; | |
| 675 UINT32 strLen = static_cast<UINT32>( | |
| 676 SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str))); | |
| 677 SkTScopedComPtr<IDWriteTextLayout> fallbackLayout; | 829 SkTScopedComPtr<IDWriteTextLayout> fallbackLayout; |
| 678 HRNM(fFactory->CreateTextLayout(str, strLen, fallbackFormat.get(), | 830 HRNM(fFactory->CreateTextLayout(str, strLen, fallbackFormat.get(), |
| 679 200.0f, 200.0f, | 831 200.0f, 200.0f, |
| 680 &fallbackLayout), | 832 &fallbackLayout), |
| 681 "Could not create text layout."); | 833 "Could not create text layout."); |
| 682 | 834 |
| 683 SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer( | 835 SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer( |
| 684 new FontFallbackRenderer(this, character)); | 836 new FontFallbackRenderer(this, character)); |
| 685 | 837 |
| 686 HRNM(fallbackLayout->Draw(NULL, fontFallbackRenderer.get(), 50.0f, 50.0f), | 838 HRNM(fallbackLayout->Draw(NULL, fontFallbackRenderer.get(), 50.0f, 50.0f), |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 } | 1112 } |
| 961 | 1113 |
| 962 #include "SkFontMgr_indirect.h" | 1114 #include "SkFontMgr_indirect.h" |
| 963 SK_API SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) { | 1115 SK_API SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) { |
| 964 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); | 1116 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); |
| 965 if (impl.get() == NULL) { | 1117 if (impl.get() == NULL) { |
| 966 return NULL; | 1118 return NULL; |
| 967 } | 1119 } |
| 968 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy)); | 1120 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy)); |
| 969 } | 1121 } |
| OLD | NEW |