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 |