SkFontMgr_win_dw.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227
  1. /*
  2. * Copyright 2014 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/utils/win/SkDWriteNTDDI_VERSION.h"
  8. #include "include/core/SkTypes.h"
  9. #if defined(SK_BUILD_FOR_WIN)
  10. #include "include/core/SkFontMgr.h"
  11. #include "include/core/SkStream.h"
  12. #include "include/core/SkTypeface.h"
  13. #include "include/core/SkTypes.h"
  14. #include "include/private/SkMutex.h"
  15. #include "src/core/SkEndian.h"
  16. #include "src/core/SkMakeUnique.h"
  17. #include "src/core/SkTypefaceCache.h"
  18. #include "src/ports/SkTypeface_win_dw.h"
  19. #include "src/utils/SkUTF.h"
  20. #include "src/utils/win/SkDWrite.h"
  21. #include "src/utils/win/SkDWriteFontFileStream.h"
  22. #include "src/utils/win/SkHRESULT.h"
  23. #include "src/utils/win/SkTScopedComPtr.h"
  24. #include <dwrite.h>
  25. #include <dwrite_2.h>
  26. #include <dwrite_3.h>
  27. ////////////////////////////////////////////////////////////////////////////////
  28. class StreamFontFileLoader : public IDWriteFontFileLoader {
  29. public:
  30. // IUnknown methods
  31. virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
  32. virtual ULONG STDMETHODCALLTYPE AddRef();
  33. virtual ULONG STDMETHODCALLTYPE Release();
  34. // IDWriteFontFileLoader methods
  35. virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
  36. void const* fontFileReferenceKey,
  37. UINT32 fontFileReferenceKeySize,
  38. IDWriteFontFileStream** fontFileStream);
  39. // Takes ownership of stream.
  40. static HRESULT Create(std::unique_ptr<SkStreamAsset> stream,
  41. StreamFontFileLoader** streamFontFileLoader) {
  42. *streamFontFileLoader = new StreamFontFileLoader(std::move(stream));
  43. if (nullptr == *streamFontFileLoader) {
  44. return E_OUTOFMEMORY;
  45. }
  46. return S_OK;
  47. }
  48. std::unique_ptr<SkStreamAsset> fStream;
  49. private:
  50. StreamFontFileLoader(std::unique_ptr<SkStreamAsset> stream)
  51. : fStream(std::move(stream)), fRefCount(1)
  52. {}
  53. virtual ~StreamFontFileLoader() { }
  54. ULONG fRefCount;
  55. };
  56. HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
  57. if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
  58. *ppvObject = this;
  59. AddRef();
  60. return S_OK;
  61. } else {
  62. *ppvObject = nullptr;
  63. return E_NOINTERFACE;
  64. }
  65. }
  66. ULONG StreamFontFileLoader::AddRef() {
  67. return InterlockedIncrement(&fRefCount);
  68. }
  69. ULONG StreamFontFileLoader::Release() {
  70. ULONG newCount = InterlockedDecrement(&fRefCount);
  71. if (0 == newCount) {
  72. delete this;
  73. }
  74. return newCount;
  75. }
  76. HRESULT StreamFontFileLoader::CreateStreamFromKey(
  77. void const* fontFileReferenceKey,
  78. UINT32 fontFileReferenceKeySize,
  79. IDWriteFontFileStream** fontFileStream)
  80. {
  81. SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
  82. HR(SkDWriteFontFileStreamWrapper::Create(fStream->duplicate().release(), &stream));
  83. *fontFileStream = stream.release();
  84. return S_OK;
  85. }
  86. ////////////////////////////////////////////////////////////////////////////////
  87. class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
  88. public:
  89. // IUnknown methods
  90. virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
  91. virtual ULONG STDMETHODCALLTYPE AddRef();
  92. virtual ULONG STDMETHODCALLTYPE Release();
  93. // IDWriteFontFileEnumerator methods
  94. virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
  95. virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
  96. static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
  97. StreamFontFileEnumerator** streamFontFileEnumerator) {
  98. *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
  99. if (nullptr == *streamFontFileEnumerator) {
  100. return E_OUTOFMEMORY;
  101. }
  102. return S_OK;
  103. }
  104. private:
  105. StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
  106. virtual ~StreamFontFileEnumerator() { }
  107. ULONG fRefCount;
  108. SkTScopedComPtr<IDWriteFactory> fFactory;
  109. SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
  110. SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
  111. bool fHasNext;
  112. };
  113. StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
  114. IDWriteFontFileLoader* fontFileLoader)
  115. : fRefCount(1)
  116. , fFactory(SkRefComPtr(factory))
  117. , fCurrentFile()
  118. , fFontFileLoader(SkRefComPtr(fontFileLoader))
  119. , fHasNext(true)
  120. { }
  121. HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
  122. if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
  123. *ppvObject = this;
  124. AddRef();
  125. return S_OK;
  126. } else {
  127. *ppvObject = nullptr;
  128. return E_NOINTERFACE;
  129. }
  130. }
  131. ULONG StreamFontFileEnumerator::AddRef() {
  132. return InterlockedIncrement(&fRefCount);
  133. }
  134. ULONG StreamFontFileEnumerator::Release() {
  135. ULONG newCount = InterlockedDecrement(&fRefCount);
  136. if (0 == newCount) {
  137. delete this;
  138. }
  139. return newCount;
  140. }
  141. HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
  142. *hasCurrentFile = FALSE;
  143. if (!fHasNext) {
  144. return S_OK;
  145. }
  146. fHasNext = false;
  147. UINT32 dummy = 0;
  148. HR(fFactory->CreateCustomFontFileReference(
  149. &dummy, //cannot be nullptr
  150. sizeof(dummy), //even if this is 0
  151. fFontFileLoader.get(),
  152. &fCurrentFile));
  153. *hasCurrentFile = TRUE;
  154. return S_OK;
  155. }
  156. HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
  157. if (fCurrentFile.get() == nullptr) {
  158. *fontFile = nullptr;
  159. return E_FAIL;
  160. }
  161. *fontFile = SkRefComPtr(fCurrentFile.get());
  162. return S_OK;
  163. }
  164. ////////////////////////////////////////////////////////////////////////////////
  165. class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
  166. public:
  167. // IUnknown methods
  168. virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
  169. virtual ULONG STDMETHODCALLTYPE AddRef();
  170. virtual ULONG STDMETHODCALLTYPE Release();
  171. // IDWriteFontCollectionLoader methods
  172. virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
  173. IDWriteFactory* factory,
  174. void const* collectionKey,
  175. UINT32 collectionKeySize,
  176. IDWriteFontFileEnumerator** fontFileEnumerator);
  177. static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
  178. StreamFontCollectionLoader** streamFontCollectionLoader) {
  179. *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
  180. if (nullptr == *streamFontCollectionLoader) {
  181. return E_OUTOFMEMORY;
  182. }
  183. return S_OK;
  184. }
  185. private:
  186. StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
  187. : fRefCount(1)
  188. , fFontFileLoader(SkRefComPtr(fontFileLoader))
  189. { }
  190. virtual ~StreamFontCollectionLoader() { }
  191. ULONG fRefCount;
  192. SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
  193. };
  194. HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
  195. if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
  196. *ppvObject = this;
  197. AddRef();
  198. return S_OK;
  199. } else {
  200. *ppvObject = nullptr;
  201. return E_NOINTERFACE;
  202. }
  203. }
  204. ULONG StreamFontCollectionLoader::AddRef() {
  205. return InterlockedIncrement(&fRefCount);
  206. }
  207. ULONG StreamFontCollectionLoader::Release() {
  208. ULONG newCount = InterlockedDecrement(&fRefCount);
  209. if (0 == newCount) {
  210. delete this;
  211. }
  212. return newCount;
  213. }
  214. HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
  215. IDWriteFactory* factory,
  216. void const* collectionKey,
  217. UINT32 collectionKeySize,
  218. IDWriteFontFileEnumerator** fontFileEnumerator)
  219. {
  220. SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
  221. HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
  222. *fontFileEnumerator = enumerator.release();
  223. return S_OK;
  224. }
  225. ////////////////////////////////////////////////////////////////////////////////
  226. class SkFontMgr_DirectWrite : public SkFontMgr {
  227. public:
  228. /** localeNameLength and defaultFamilyNameLength must include the null terminator. */
  229. SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection,
  230. IDWriteFontFallback* fallback,
  231. const WCHAR* localeName, int localeNameLength,
  232. const WCHAR* defaultFamilyName, int defaultFamilyNameLength)
  233. : fFactory(SkRefComPtr(factory))
  234. , fFontFallback(SkSafeRefComPtr(fallback))
  235. , fFontCollection(SkRefComPtr(fontCollection))
  236. , fLocaleName(localeNameLength)
  237. , fDefaultFamilyName(defaultFamilyNameLength)
  238. {
  239. memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
  240. memcpy(fDefaultFamilyName.get(), defaultFamilyName, defaultFamilyNameLength*sizeof(WCHAR));
  241. }
  242. protected:
  243. int onCountFamilies() const override;
  244. void onGetFamilyName(int index, SkString* familyName) const override;
  245. SkFontStyleSet* onCreateStyleSet(int index) const override;
  246. SkFontStyleSet* onMatchFamily(const char familyName[]) const override;
  247. SkTypeface* onMatchFamilyStyle(const char familyName[],
  248. const SkFontStyle& fontstyle) const override;
  249. SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
  250. const char* bcp47[], int bcp47Count,
  251. SkUnichar character) const override;
  252. SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
  253. const SkFontStyle& fontstyle) const override;
  254. sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>, int ttcIndex) const override;
  255. sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>, const SkFontArguments&) const override;
  256. sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override;
  257. sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override;
  258. sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override;
  259. private:
  260. HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
  261. sk_sp<SkTypeface> fallback(const WCHAR* dwFamilyName, DWriteStyle,
  262. const WCHAR* dwBcp47, UINT32 character) const;
  263. sk_sp<SkTypeface> layoutFallback(const WCHAR* dwFamilyName, DWriteStyle,
  264. const WCHAR* dwBcp47, UINT32 character) const;
  265. /** Creates a typeface using a typeface cache. */
  266. sk_sp<SkTypeface> makeTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
  267. IDWriteFont* font,
  268. IDWriteFontFamily* fontFamily) const;
  269. SkTScopedComPtr<IDWriteFactory> fFactory;
  270. SkTScopedComPtr<IDWriteFontFallback> fFontFallback;
  271. SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
  272. SkSMallocWCHAR fLocaleName;
  273. SkSMallocWCHAR fDefaultFamilyName;
  274. mutable SkMutex fTFCacheMutex;
  275. mutable SkTypefaceCache fTFCache;
  276. friend class SkFontStyleSet_DirectWrite;
  277. friend class FontFallbackRenderer;
  278. };
  279. class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
  280. public:
  281. SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
  282. IDWriteFontFamily* fontFamily)
  283. : fFontMgr(SkRef(fontMgr))
  284. , fFontFamily(SkRefComPtr(fontFamily))
  285. { }
  286. int count() override;
  287. void getStyle(int index, SkFontStyle* fs, SkString* styleName) override;
  288. SkTypeface* createTypeface(int index) override;
  289. SkTypeface* matchStyle(const SkFontStyle& pattern) override;
  290. private:
  291. sk_sp<const SkFontMgr_DirectWrite> fFontMgr;
  292. SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
  293. };
  294. static HRESULT are_same(IUnknown* a, IUnknown* b, bool& same) {
  295. SkTScopedComPtr<IUnknown> iunkA;
  296. HRM(a->QueryInterface(&iunkA), "Failed to QI<IUnknown> for a.");
  297. SkTScopedComPtr<IUnknown> iunkB;
  298. HRM(b->QueryInterface(&iunkB), "Failed to QI<IUnknown> for b.");
  299. same = (iunkA.get() == iunkB.get());
  300. return S_OK;
  301. }
  302. struct ProtoDWriteTypeface {
  303. IDWriteFontFace* fDWriteFontFace;
  304. IDWriteFont* fDWriteFont;
  305. IDWriteFontFamily* fDWriteFontFamily;
  306. };
  307. static bool FindByDWriteFont(SkTypeface* cached, void* ctx) {
  308. DWriteFontTypeface* cshFace = reinterpret_cast<DWriteFontTypeface*>(cached);
  309. ProtoDWriteTypeface* ctxFace = reinterpret_cast<ProtoDWriteTypeface*>(ctx);
  310. bool same;
  311. //Check to see if the two fonts are identical.
  312. HRB(are_same(cshFace->fDWriteFont.get(), ctxFace->fDWriteFont, same));
  313. if (same) {
  314. return true;
  315. }
  316. HRB(are_same(cshFace->fDWriteFontFace.get(), ctxFace->fDWriteFontFace, same));
  317. if (same) {
  318. return true;
  319. }
  320. //Check if the two fonts share the same loader and have the same key.
  321. UINT32 cshNumFiles;
  322. UINT32 ctxNumFiles;
  323. HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, nullptr));
  324. HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, nullptr));
  325. if (cshNumFiles != ctxNumFiles) {
  326. return false;
  327. }
  328. SkTScopedComPtr<IDWriteFontFile> cshFontFile;
  329. SkTScopedComPtr<IDWriteFontFile> ctxFontFile;
  330. HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, &cshFontFile));
  331. HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, &ctxFontFile));
  332. //for (each file) { //we currently only admit fonts from one file.
  333. SkTScopedComPtr<IDWriteFontFileLoader> cshFontFileLoader;
  334. SkTScopedComPtr<IDWriteFontFileLoader> ctxFontFileLoader;
  335. HRB(cshFontFile->GetLoader(&cshFontFileLoader));
  336. HRB(ctxFontFile->GetLoader(&ctxFontFileLoader));
  337. HRB(are_same(cshFontFileLoader.get(), ctxFontFileLoader.get(), same));
  338. if (!same) {
  339. return false;
  340. }
  341. //}
  342. const void* cshRefKey;
  343. UINT32 cshRefKeySize;
  344. const void* ctxRefKey;
  345. UINT32 ctxRefKeySize;
  346. HRB(cshFontFile->GetReferenceKey(&cshRefKey, &cshRefKeySize));
  347. HRB(ctxFontFile->GetReferenceKey(&ctxRefKey, &ctxRefKeySize));
  348. if (cshRefKeySize != ctxRefKeySize) {
  349. return false;
  350. }
  351. if (0 != memcmp(cshRefKey, ctxRefKey, ctxRefKeySize)) {
  352. return false;
  353. }
  354. //TODO: better means than comparing name strings?
  355. //NOTE: .ttc and fake bold/italic will end up here.
  356. SkTScopedComPtr<IDWriteLocalizedStrings> cshFamilyNames;
  357. SkTScopedComPtr<IDWriteLocalizedStrings> cshFaceNames;
  358. HRB(cshFace->fDWriteFontFamily->GetFamilyNames(&cshFamilyNames));
  359. HRB(cshFace->fDWriteFont->GetFaceNames(&cshFaceNames));
  360. UINT32 cshFamilyNameLength;
  361. UINT32 cshFaceNameLength;
  362. HRB(cshFamilyNames->GetStringLength(0, &cshFamilyNameLength));
  363. HRB(cshFaceNames->GetStringLength(0, &cshFaceNameLength));
  364. SkTScopedComPtr<IDWriteLocalizedStrings> ctxFamilyNames;
  365. SkTScopedComPtr<IDWriteLocalizedStrings> ctxFaceNames;
  366. HRB(ctxFace->fDWriteFontFamily->GetFamilyNames(&ctxFamilyNames));
  367. HRB(ctxFace->fDWriteFont->GetFaceNames(&ctxFaceNames));
  368. UINT32 ctxFamilyNameLength;
  369. UINT32 ctxFaceNameLength;
  370. HRB(ctxFamilyNames->GetStringLength(0, &ctxFamilyNameLength));
  371. HRB(ctxFaceNames->GetStringLength(0, &ctxFaceNameLength));
  372. if (cshFamilyNameLength != ctxFamilyNameLength ||
  373. cshFaceNameLength != ctxFaceNameLength)
  374. {
  375. return false;
  376. }
  377. SkSMallocWCHAR cshFamilyName(cshFamilyNameLength+1);
  378. SkSMallocWCHAR cshFaceName(cshFaceNameLength+1);
  379. HRB(cshFamilyNames->GetString(0, cshFamilyName.get(), cshFamilyNameLength+1));
  380. HRB(cshFaceNames->GetString(0, cshFaceName.get(), cshFaceNameLength+1));
  381. SkSMallocWCHAR ctxFamilyName(ctxFamilyNameLength+1);
  382. SkSMallocWCHAR ctxFaceName(ctxFaceNameLength+1);
  383. HRB(ctxFamilyNames->GetString(0, ctxFamilyName.get(), ctxFamilyNameLength+1));
  384. HRB(ctxFaceNames->GetString(0, ctxFaceName.get(), ctxFaceNameLength+1));
  385. return wcscmp(cshFamilyName.get(), ctxFamilyName.get()) == 0 &&
  386. wcscmp(cshFaceName.get(), ctxFaceName.get()) == 0;
  387. }
  388. sk_sp<SkTypeface> SkFontMgr_DirectWrite::makeTypefaceFromDWriteFont(
  389. IDWriteFontFace* fontFace,
  390. IDWriteFont* font,
  391. IDWriteFontFamily* fontFamily) const {
  392. SkAutoMutexExclusive ama(fTFCacheMutex);
  393. ProtoDWriteTypeface spec = { fontFace, font, fontFamily };
  394. sk_sp<SkTypeface> face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec);
  395. if (nullptr == face) {
  396. face = DWriteFontTypeface::Make(fFactory.get(), fontFace, font, fontFamily);
  397. if (face) {
  398. fTFCache.add(face);
  399. }
  400. }
  401. return face;
  402. }
  403. int SkFontMgr_DirectWrite::onCountFamilies() const {
  404. return fFontCollection->GetFontFamilyCount();
  405. }
  406. void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
  407. SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  408. HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
  409. SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
  410. HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
  411. sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
  412. }
  413. SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
  414. SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  415. HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
  416. return new SkFontStyleSet_DirectWrite(this, fontFamily.get());
  417. }
  418. SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
  419. if (!familyName) {
  420. return nullptr;
  421. }
  422. SkSMallocWCHAR dwFamilyName;
  423. HRN(sk_cstring_to_wchar(familyName, &dwFamilyName));
  424. UINT32 index;
  425. BOOL exists;
  426. HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
  427. "Failed while finding family by name.");
  428. if (!exists) {
  429. return nullptr;
  430. }
  431. return this->onCreateStyleSet(index);
  432. }
  433. SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
  434. const SkFontStyle& fontstyle) const {
  435. sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
  436. return sset->matchStyle(fontstyle);
  437. }
  438. class FontFallbackRenderer : public IDWriteTextRenderer {
  439. public:
  440. FontFallbackRenderer(const SkFontMgr_DirectWrite* outer, UINT32 character)
  441. : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character), fResolvedTypeface(nullptr) {
  442. }
  443. virtual ~FontFallbackRenderer() { }
  444. // IDWriteTextRenderer methods
  445. virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
  446. void* clientDrawingContext,
  447. FLOAT baselineOriginX,
  448. FLOAT baselineOriginY,
  449. DWRITE_MEASURING_MODE measuringMode,
  450. DWRITE_GLYPH_RUN const* glyphRun,
  451. DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
  452. IUnknown* clientDrawingEffect) override
  453. {
  454. if (!glyphRun->fontFace) {
  455. HRM(E_INVALIDARG, "Glyph run without font face.");
  456. }
  457. SkTScopedComPtr<IDWriteFont> font;
  458. HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
  459. "Could not get font from font face.");
  460. // It is possible that the font passed does not actually have the requested character,
  461. // due to no font being found and getting the fallback font.
  462. // Check that the font actually contains the requested character.
  463. BOOL exists;
  464. HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
  465. if (exists) {
  466. SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  467. HRM(font->GetFontFamily(&fontFamily), "Could not get family.");
  468. fResolvedTypeface = fOuter->makeTypefaceFromDWriteFont(glyphRun->fontFace,
  469. font.get(),
  470. fontFamily.get());
  471. }
  472. return S_OK;
  473. }
  474. virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
  475. void* clientDrawingContext,
  476. FLOAT baselineOriginX,
  477. FLOAT baselineOriginY,
  478. DWRITE_UNDERLINE const* underline,
  479. IUnknown* clientDrawingEffect) override
  480. { return E_NOTIMPL; }
  481. virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
  482. void* clientDrawingContext,
  483. FLOAT baselineOriginX,
  484. FLOAT baselineOriginY,
  485. DWRITE_STRIKETHROUGH const* strikethrough,
  486. IUnknown* clientDrawingEffect) override
  487. { return E_NOTIMPL; }
  488. virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
  489. void* clientDrawingContext,
  490. FLOAT originX,
  491. FLOAT originY,
  492. IDWriteInlineObject* inlineObject,
  493. BOOL isSideways,
  494. BOOL isRightToLeft,
  495. IUnknown* clientDrawingEffect) override
  496. { return E_NOTIMPL; }
  497. // IDWritePixelSnapping methods
  498. virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
  499. void* clientDrawingContext,
  500. BOOL* isDisabled) override
  501. {
  502. *isDisabled = FALSE;
  503. return S_OK;
  504. }
  505. virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
  506. void* clientDrawingContext,
  507. DWRITE_MATRIX* transform) override
  508. {
  509. const DWRITE_MATRIX ident = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
  510. *transform = ident;
  511. return S_OK;
  512. }
  513. virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
  514. void* clientDrawingContext,
  515. FLOAT* pixelsPerDip) override
  516. {
  517. *pixelsPerDip = 1.0f;
  518. return S_OK;
  519. }
  520. // IUnknown methods
  521. ULONG STDMETHODCALLTYPE AddRef() override {
  522. return InterlockedIncrement(&fRefCount);
  523. }
  524. ULONG STDMETHODCALLTYPE Release() override {
  525. ULONG newCount = InterlockedDecrement(&fRefCount);
  526. if (0 == newCount) {
  527. delete this;
  528. }
  529. return newCount;
  530. }
  531. virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) override{
  532. if (__uuidof(IUnknown) == riid ||
  533. __uuidof(IDWritePixelSnapping) == riid ||
  534. __uuidof(IDWriteTextRenderer) == riid)
  535. {
  536. *ppvObject = this;
  537. this->AddRef();
  538. return S_OK;
  539. }
  540. *ppvObject = nullptr;
  541. return E_FAIL;
  542. }
  543. sk_sp<SkTypeface> ConsumeFallbackTypeface() { return std::move(fResolvedTypeface); }
  544. protected:
  545. ULONG fRefCount;
  546. sk_sp<const SkFontMgr_DirectWrite> fOuter;
  547. UINT32 fCharacter;
  548. sk_sp<SkTypeface> fResolvedTypeface;
  549. };
  550. class FontFallbackSource : public IDWriteTextAnalysisSource {
  551. public:
  552. FontFallbackSource(const WCHAR* string, UINT32 length, const WCHAR* locale,
  553. IDWriteNumberSubstitution* numberSubstitution)
  554. : fRefCount(1)
  555. , fString(string)
  556. , fLength(length)
  557. , fLocale(locale)
  558. , fNumberSubstitution(numberSubstitution)
  559. { }
  560. virtual ~FontFallbackSource() { }
  561. // IDWriteTextAnalysisSource methods
  562. virtual HRESULT STDMETHODCALLTYPE GetTextAtPosition(
  563. UINT32 textPosition,
  564. WCHAR const** textString,
  565. UINT32* textLength) override
  566. {
  567. if (fLength <= textPosition) {
  568. *textString = nullptr;
  569. *textLength = 0;
  570. return S_OK;
  571. }
  572. *textString = fString + textPosition;
  573. *textLength = fLength - textPosition;
  574. return S_OK;
  575. }
  576. virtual HRESULT STDMETHODCALLTYPE GetTextBeforePosition(
  577. UINT32 textPosition,
  578. WCHAR const** textString,
  579. UINT32* textLength) override
  580. {
  581. if (textPosition < 1 || fLength <= textPosition) {
  582. *textString = nullptr;
  583. *textLength = 0;
  584. return S_OK;
  585. }
  586. *textString = fString;
  587. *textLength = textPosition;
  588. return S_OK;
  589. }
  590. virtual DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirection() override {
  591. // TODO: this is also interesting.
  592. return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
  593. }
  594. virtual HRESULT STDMETHODCALLTYPE GetLocaleName(
  595. UINT32 textPosition,
  596. UINT32* textLength,
  597. WCHAR const** localeName) override
  598. {
  599. *localeName = fLocale;
  600. return S_OK;
  601. }
  602. virtual HRESULT STDMETHODCALLTYPE GetNumberSubstitution(
  603. UINT32 textPosition,
  604. UINT32* textLength,
  605. IDWriteNumberSubstitution** numberSubstitution) override
  606. {
  607. *numberSubstitution = fNumberSubstitution;
  608. return S_OK;
  609. }
  610. // IUnknown methods
  611. ULONG STDMETHODCALLTYPE AddRef() override {
  612. return InterlockedIncrement(&fRefCount);
  613. }
  614. ULONG STDMETHODCALLTYPE Release() override {
  615. ULONG newCount = InterlockedDecrement(&fRefCount);
  616. if (0 == newCount) {
  617. delete this;
  618. }
  619. return newCount;
  620. }
  621. virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) override{
  622. if (__uuidof(IUnknown) == riid ||
  623. __uuidof(IDWriteTextAnalysisSource) == riid)
  624. {
  625. *ppvObject = this;
  626. this->AddRef();
  627. return S_OK;
  628. }
  629. *ppvObject = nullptr;
  630. return E_FAIL;
  631. }
  632. protected:
  633. ULONG fRefCount;
  634. const WCHAR* fString;
  635. UINT32 fLength;
  636. const WCHAR* fLocale;
  637. IDWriteNumberSubstitution* fNumberSubstitution;
  638. };
  639. SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char familyName[],
  640. const SkFontStyle& style,
  641. const char* bcp47[], int bcp47Count,
  642. SkUnichar character) const
  643. {
  644. const DWriteStyle dwStyle(style);
  645. const WCHAR* dwFamilyName = nullptr;
  646. SkSMallocWCHAR dwFamilyNameLocal;
  647. if (familyName) {
  648. HRN(sk_cstring_to_wchar(familyName, &dwFamilyNameLocal));
  649. dwFamilyName = dwFamilyNameLocal;
  650. }
  651. const SkSMallocWCHAR* dwBcp47;
  652. SkSMallocWCHAR dwBcp47Local;
  653. if (bcp47Count < 1) {
  654. dwBcp47 = &fLocaleName;
  655. } else {
  656. // TODO: support fallback stack.
  657. // TODO: DirectWrite supports 'zh-CN' or 'zh-Hans', but 'zh' misses completely
  658. // and may produce a Japanese font.
  659. HRN(sk_cstring_to_wchar(bcp47[bcp47Count - 1], &dwBcp47Local));
  660. dwBcp47 = &dwBcp47Local;
  661. }
  662. if (fFontFallback) {
  663. return this->fallback(dwFamilyName, dwStyle, dwBcp47->get(), character).release();
  664. }
  665. // LayoutFallback may use the system font collection for fallback.
  666. return this->layoutFallback(dwFamilyName, dwStyle, dwBcp47->get(), character).release();
  667. }
  668. sk_sp<SkTypeface> SkFontMgr_DirectWrite::fallback(const WCHAR* dwFamilyName,
  669. DWriteStyle dwStyle,
  670. const WCHAR* dwBcp47,
  671. UINT32 character) const
  672. {
  673. WCHAR str[16];
  674. UINT32 strLen = SkTo<UINT32>(SkUTF::ToUTF16(character, reinterpret_cast<uint16_t*>(str)));
  675. if (!fFontFallback) {
  676. return nullptr;
  677. }
  678. SkTScopedComPtr<IDWriteNumberSubstitution> numberSubstitution;
  679. HRNM(fFactory->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, dwBcp47,
  680. TRUE, &numberSubstitution),
  681. "Could not create number substitution.");
  682. SkTScopedComPtr<FontFallbackSource> fontFallbackSource(
  683. new FontFallbackSource(str, strLen, dwBcp47, numberSubstitution.get()));
  684. UINT32 mappedLength;
  685. SkTScopedComPtr<IDWriteFont> font;
  686. FLOAT scale;
  687. HRNM(fFontFallback->MapCharacters(fontFallbackSource.get(),
  688. 0, // textPosition,
  689. strLen,
  690. fFontCollection.get(),
  691. dwFamilyName,
  692. dwStyle.fWeight,
  693. dwStyle.fSlant,
  694. dwStyle.fWidth,
  695. &mappedLength,
  696. &font,
  697. &scale),
  698. "Could not map characters");
  699. if (!font.get()) {
  700. return nullptr;
  701. }
  702. SkTScopedComPtr<IDWriteFontFace> fontFace;
  703. HRNM(font->CreateFontFace(&fontFace), "Could not get font face from font.");
  704. SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  705. HRNM(font->GetFontFamily(&fontFamily), "Could not get family from font.");
  706. return this->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
  707. }
  708. sk_sp<SkTypeface> SkFontMgr_DirectWrite::layoutFallback(const WCHAR* dwFamilyName,
  709. DWriteStyle dwStyle,
  710. const WCHAR* dwBcp47,
  711. UINT32 character) const
  712. {
  713. WCHAR str[16];
  714. UINT32 strLen = SkTo<UINT32>(SkUTF::ToUTF16(character, reinterpret_cast<uint16_t*>(str)));
  715. SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
  716. HRNM(fFactory->CreateTextFormat(dwFamilyName ? dwFamilyName : L"",
  717. fFontCollection.get(),
  718. dwStyle.fWeight,
  719. dwStyle.fSlant,
  720. dwStyle.fWidth,
  721. 72.0f,
  722. dwBcp47,
  723. &fallbackFormat),
  724. "Could not create text format.");
  725. // No matter how the font collection is set on this IDWriteTextLayout, it is not possible to
  726. // disable use of the system font collection in fallback.
  727. SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
  728. HRNM(fFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
  729. 200.0f, 200.0f,
  730. &fallbackLayout),
  731. "Could not create text layout.");
  732. SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
  733. new FontFallbackRenderer(this, character));
  734. HRNM(fallbackLayout->SetFontCollection(fFontCollection.get(), { 0, strLen }),
  735. "Could not set layout font collection.");
  736. HRNM(fallbackLayout->Draw(nullptr, fontFallbackRenderer.get(), 50.0f, 50.0f),
  737. "Could not draw layout with renderer.");
  738. return fontFallbackRenderer->ConsumeFallbackTypeface();
  739. }
  740. SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
  741. const SkFontStyle& fontstyle) const {
  742. SkString familyName;
  743. SkFontStyleSet_DirectWrite sset(
  744. this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
  745. );
  746. return sset.matchStyle(fontstyle);
  747. }
  748. template <typename T> class SkAutoIDWriteUnregister {
  749. public:
  750. SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
  751. : fFactory(factory), fUnregister(unregister)
  752. { }
  753. ~SkAutoIDWriteUnregister() {
  754. if (fUnregister) {
  755. unregister(fFactory, fUnregister);
  756. }
  757. }
  758. T* detatch() {
  759. T* old = fUnregister;
  760. fUnregister = nullptr;
  761. return old;
  762. }
  763. private:
  764. HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
  765. return factory->UnregisterFontFileLoader(unregister);
  766. }
  767. HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
  768. return factory->UnregisterFontCollectionLoader(unregister);
  769. }
  770. IDWriteFactory* fFactory;
  771. T* fUnregister;
  772. };
  773. sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
  774. int ttcIndex) const {
  775. SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
  776. // This transfers ownership of stream to the new object.
  777. HRN(StreamFontFileLoader::Create(std::move(stream), &fontFileLoader));
  778. HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get()));
  779. SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
  780. fFactory.get(), fontFileLoader.get());
  781. SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
  782. HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
  783. HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
  784. SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
  785. fFactory.get(), fontCollectionLoader.get());
  786. SkTScopedComPtr<IDWriteFontCollection> fontCollection;
  787. HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), nullptr, 0, &fontCollection));
  788. // Find the first non-simulated font which has the given ttc index.
  789. UINT32 familyCount = fontCollection->GetFontFamilyCount();
  790. for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
  791. SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  792. HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
  793. UINT32 fontCount = fontFamily->GetFontCount();
  794. for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
  795. SkTScopedComPtr<IDWriteFont> font;
  796. HRN(fontFamily->GetFont(fontIndex, &font));
  797. if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
  798. continue;
  799. }
  800. SkTScopedComPtr<IDWriteFontFace> fontFace;
  801. HRN(font->CreateFontFace(&fontFace));
  802. int faceIndex = fontFace->GetIndex();
  803. if (faceIndex == ttcIndex) {
  804. return DWriteFontTypeface::Make(fFactory.get(),
  805. fontFace.get(), font.get(), fontFamily.get(),
  806. autoUnregisterFontFileLoader.detatch(),
  807. autoUnregisterFontCollectionLoader.detatch());
  808. }
  809. }
  810. }
  811. return nullptr;
  812. }
  813. sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
  814. const SkFontArguments& args) const {
  815. SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
  816. // This transfers ownership of stream to the new object.
  817. HRN(StreamFontFileLoader::Create(std::move(stream), &fontFileLoader));
  818. HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get()));
  819. SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
  820. fFactory.get(), fontFileLoader.get());
  821. SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
  822. HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
  823. HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
  824. SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
  825. fFactory.get(), fontCollectionLoader.get());
  826. SkTScopedComPtr<IDWriteFontCollection> fontCollection;
  827. HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), nullptr, 0,
  828. &fontCollection));
  829. // Find the first non-simulated font which has the given ttc index.
  830. UINT32 familyCount = fontCollection->GetFontFamilyCount();
  831. for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
  832. SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  833. HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
  834. UINT32 fontCount = fontFamily->GetFontCount();
  835. for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
  836. SkTScopedComPtr<IDWriteFont> font;
  837. HRN(fontFamily->GetFont(fontIndex, &font));
  838. // Skip if the current font is simulated
  839. if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
  840. continue;
  841. }
  842. SkTScopedComPtr<IDWriteFontFace> fontFace;
  843. HRN(font->CreateFontFace(&fontFace));
  844. int faceIndex = fontFace->GetIndex();
  845. int ttcIndex = args.getCollectionIndex();
  846. // Skip if the current face index does not match the ttcIndex
  847. if (faceIndex != ttcIndex) {
  848. continue;
  849. }
  850. #if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
  851. SkTScopedComPtr<IDWriteFontFace5> fontFace5;
  852. if (SUCCEEDED(fontFace->QueryInterface(&fontFace5)) && fontFace5->HasVariations()) {
  853. UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
  854. UINT32 argsCoordCount = args.getVariationDesignPosition().coordinateCount;
  855. SkAutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisValues(fontAxisCount);
  856. SkTScopedComPtr<IDWriteFontResource> fontResource;
  857. HRN(fontFace5->GetFontResource(&fontResource));
  858. // Set all axes by default values
  859. HRN(fontResource->GetDefaultFontAxisValues(fontAxisValues, fontAxisCount));
  860. for (UINT32 fontIndex = 0; fontIndex < fontAxisCount; ++fontIndex) {
  861. for (UINT32 argsIndex = 0; argsIndex < argsCoordCount; ++argsIndex) {
  862. if (SkEndian_SwapBE32(fontAxisValues[fontIndex].axisTag) ==
  863. args.getVariationDesignPosition().coordinates[argsIndex].axis) {
  864. fontAxisValues[fontIndex].value =
  865. args.getVariationDesignPosition().coordinates[argsIndex].value;
  866. }
  867. }
  868. }
  869. SkTScopedComPtr<IDWriteFontFace5> fontFace5_Out;
  870. HRN(fontResource->CreateFontFace(DWRITE_FONT_SIMULATIONS_NONE,
  871. fontAxisValues.get(),
  872. fontAxisCount,
  873. &fontFace5_Out));
  874. fontFace.reset();
  875. HRN(fontFace5_Out->QueryInterface(&fontFace));
  876. }
  877. #endif
  878. return DWriteFontTypeface::Make(
  879. fFactory.get(), fontFace.get(), font.get(), fontFamily.get(),
  880. autoUnregisterFontFileLoader.detatch(),
  881. autoUnregisterFontCollectionLoader.detatch());
  882. }
  883. }
  884. return nullptr;
  885. }
  886. sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const {
  887. return this->makeFromStream(skstd::make_unique<SkMemoryStream>(std::move(data)), ttcIndex);
  888. }
  889. sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromFile(const char path[], int ttcIndex) const {
  890. return this->makeFromStream(SkStream::MakeFromFile(path), ttcIndex);
  891. }
  892. HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
  893. IDWriteFontFamily** fontFamily) const {
  894. UINT32 index;
  895. BOOL exists;
  896. HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
  897. if (exists) {
  898. HR(fFontCollection->GetFontFamily(index, fontFamily));
  899. }
  900. return S_OK;
  901. }
  902. sk_sp<SkTypeface> SkFontMgr_DirectWrite::onLegacyMakeTypeface(const char familyName[],
  903. SkFontStyle style) const {
  904. SkTScopedComPtr<IDWriteFontFamily> fontFamily;
  905. const DWriteStyle dwStyle(style);
  906. if (familyName) {
  907. SkSMallocWCHAR dwFamilyName;
  908. if (SUCCEEDED(sk_cstring_to_wchar(familyName, &dwFamilyName))) {
  909. this->getByFamilyName(dwFamilyName, &fontFamily);
  910. if (!fontFamily && fFontFallback) {
  911. return this->fallback(dwFamilyName, dwStyle, fLocaleName.get(), 32);
  912. }
  913. }
  914. }
  915. if (!fontFamily) {
  916. if (fFontFallback) {
  917. return this->fallback(nullptr, dwStyle, fLocaleName.get(), 32);
  918. }
  919. // SPI_GETNONCLIENTMETRICS lfMessageFont can fail in Win8. (DisallowWin32kSystemCalls)
  920. // layoutFallback causes DCHECK in Chromium. (Uses system font collection.)
  921. HRNM(this->getByFamilyName(fDefaultFamilyName, &fontFamily),
  922. "Could not create DWrite font family from LOGFONT.");
  923. }
  924. if (!fontFamily) {
  925. // Could not obtain the default font.
  926. HRNM(fFontCollection->GetFontFamily(0, &fontFamily),
  927. "Could not get default-default font family.");
  928. }
  929. SkTScopedComPtr<IDWriteFont> font;
  930. HRNM(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &font),
  931. "Could not get matching font.");
  932. SkTScopedComPtr<IDWriteFontFace> fontFace;
  933. HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  934. return this->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
  935. }
  936. ///////////////////////////////////////////////////////////////////////////////
  937. int SkFontStyleSet_DirectWrite::count() {
  938. return fFontFamily->GetFontCount();
  939. }
  940. SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
  941. SkTScopedComPtr<IDWriteFont> font;
  942. HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
  943. SkTScopedComPtr<IDWriteFontFace> fontFace;
  944. HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  945. return fFontMgr->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()).release();
  946. }
  947. void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
  948. SkTScopedComPtr<IDWriteFont> font;
  949. HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
  950. if (fs) {
  951. *fs = get_style(font.get());
  952. }
  953. if (styleName) {
  954. SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
  955. if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
  956. sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
  957. }
  958. }
  959. }
  960. SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
  961. SkTScopedComPtr<IDWriteFont> font;
  962. DWriteStyle dwStyle(pattern);
  963. // TODO: perhaps use GetMatchingFonts and get the least simulated?
  964. HRNM(fFontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &font),
  965. "Could not match font in family.");
  966. SkTScopedComPtr<IDWriteFontFace> fontFace;
  967. HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
  968. return fFontMgr->makeTypefaceFromDWriteFont(fontFace.get(), font.get(),
  969. fFontFamily.get()).release();
  970. }
  971. ////////////////////////////////////////////////////////////////////////////////
  972. #include "include/ports/SkTypeface_win.h"
  973. SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory,
  974. IDWriteFontCollection* collection) {
  975. return SkFontMgr_New_DirectWrite(factory, collection, nullptr);
  976. }
  977. SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory,
  978. IDWriteFontCollection* collection,
  979. IDWriteFontFallback* fallback) {
  980. if (nullptr == factory) {
  981. factory = sk_get_dwrite_factory();
  982. if (nullptr == factory) {
  983. return nullptr;
  984. }
  985. }
  986. SkTScopedComPtr<IDWriteFontCollection> systemFontCollection;
  987. if (nullptr == collection) {
  988. HRNM(factory->GetSystemFontCollection(&systemFontCollection, FALSE),
  989. "Could not get system font collection.");
  990. collection = systemFontCollection.get();
  991. }
  992. // It is possible to have been provided a font fallback when factory2 is not available.
  993. SkTScopedComPtr<IDWriteFontFallback> systemFontFallback;
  994. if (nullptr == fallback) {
  995. SkTScopedComPtr<IDWriteFactory2> factory2;
  996. if (!SUCCEEDED(factory->QueryInterface(&factory2))) {
  997. // IUnknown::QueryInterface states that if it fails, punk will be set to nullptr.
  998. // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
  999. SkASSERT_RELEASE(nullptr == factory2.get());
  1000. } else {
  1001. HRNM(factory2->GetSystemFontFallback(&systemFontFallback),
  1002. "Could not get system fallback.");
  1003. fallback = systemFontFallback.get();
  1004. }
  1005. }
  1006. const WCHAR* defaultFamilyName = L"";
  1007. int defaultFamilyNameLen = 1;
  1008. NONCLIENTMETRICSW metrics;
  1009. metrics.cbSize = sizeof(metrics);
  1010. if (nullptr == fallback) {
  1011. if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) {
  1012. defaultFamilyName = metrics.lfMessageFont.lfFaceName;
  1013. defaultFamilyNameLen = LF_FACESIZE;
  1014. }
  1015. }
  1016. WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
  1017. const WCHAR* localeName = L"";
  1018. int localeNameLen = 1;
  1019. // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
  1020. SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = nullptr;
  1021. HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
  1022. if (nullptr == getUserDefaultLocaleNameProc) {
  1023. SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
  1024. } else {
  1025. int size = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
  1026. if (size) {
  1027. localeName = localeNameStorage;
  1028. localeNameLen = size;
  1029. }
  1030. }
  1031. return sk_make_sp<SkFontMgr_DirectWrite>(factory, collection, fallback,
  1032. localeName, localeNameLen,
  1033. defaultFamilyName, defaultFamilyNameLen);
  1034. }
  1035. #include "include/ports/SkFontMgr_indirect.h"
  1036. SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWriteRenderer(sk_sp<SkRemotableFontMgr> proxy) {
  1037. sk_sp<SkFontMgr> impl(SkFontMgr_New_DirectWrite());
  1038. if (!impl) {
  1039. return nullptr;
  1040. }
  1041. return sk_make_sp<SkFontMgr_Indirect>(std::move(impl), std::move(proxy));
  1042. }
  1043. #endif//defined(SK_BUILD_FOR_WIN)