Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/ports/SkFontMgr_win_dw.cpp

Issue 942083004: Use IDWriteFontFallback when available. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Cache the query. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/utils/win/SkDWrite.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | src/utils/win/SkDWrite.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698