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> mappedFont; | |
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 &mappedFont, | |
801 &scale), | |
802 "Could not map characters"); | |
803 if (!mappedFont.get()) { | |
804 return NULL; | |
805 } | |
806 | |
807 SkTScopedComPtr<IDWriteFontFace> fontFace; | |
808 HRNM(mappedFont->CreateFontFace(&fontFace), "Could not get font face fro m font."); | |
809 | |
810 SkTScopedComPtr<IDWriteFontFamily> fontFamily; | |
811 HRNM(mappedFont->GetFontFamily(&fontFamily), "Could not get family."); | |
812 return createTypefaceFromDWriteFont(fontFace.get(), mappedFont.get(), fo ntFamily.get()); | |
mtklein
2015/02/23 17:11:21
this->
bungeman-skia
2015/02/23 17:30:52
Done.
| |
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 |