OLD | NEW |
(Empty) | |
| 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 |
| 8 #include "SkDWrite.h" |
| 9 #include "SkDWriteFontFileStream.h" |
| 10 #include "SkFontMgr.h" |
| 11 #include "SkHRESULT.h" |
| 12 #include "SkStream.h" |
| 13 #include "SkTScopedComPtr.h" |
| 14 #include "SkThread.h" |
| 15 #include "SkTypeface.h" |
| 16 #include "SkTypefaceCache.h" |
| 17 #include "SkTypeface_win_dw.h" |
| 18 #include "SkTypes.h" |
| 19 |
| 20 #include <dwrite.h> |
| 21 |
| 22 //////////////////////////////////////////////////////////////////////////////// |
| 23 |
| 24 class StreamFontFileLoader : public IDWriteFontFileLoader { |
| 25 public: |
| 26 // IUnknown methods |
| 27 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObjec
t); |
| 28 virtual ULONG STDMETHODCALLTYPE AddRef(); |
| 29 virtual ULONG STDMETHODCALLTYPE Release(); |
| 30 |
| 31 // IDWriteFontFileLoader methods |
| 32 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey( |
| 33 void const* fontFileReferenceKey, |
| 34 UINT32 fontFileReferenceKeySize, |
| 35 IDWriteFontFileStream** fontFileStream); |
| 36 |
| 37 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFil
eLoader) { |
| 38 *streamFontFileLoader = new StreamFontFileLoader(stream); |
| 39 if (NULL == streamFontFileLoader) { |
| 40 return E_OUTOFMEMORY; |
| 41 } |
| 42 return S_OK; |
| 43 } |
| 44 |
| 45 SkAutoTUnref<SkStream> fStream; |
| 46 |
| 47 private: |
| 48 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)
) { } |
| 49 |
| 50 ULONG fRefCount; |
| 51 }; |
| 52 |
| 53 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) { |
| 54 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { |
| 55 *ppvObject = this; |
| 56 AddRef(); |
| 57 return S_OK; |
| 58 } else { |
| 59 *ppvObject = NULL; |
| 60 return E_NOINTERFACE; |
| 61 } |
| 62 } |
| 63 |
| 64 ULONG StreamFontFileLoader::AddRef() { |
| 65 return InterlockedIncrement(&fRefCount); |
| 66 } |
| 67 |
| 68 ULONG StreamFontFileLoader::Release() { |
| 69 ULONG newCount = InterlockedDecrement(&fRefCount); |
| 70 if (0 == newCount) { |
| 71 delete this; |
| 72 } |
| 73 return newCount; |
| 74 } |
| 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, &stream)); |
| 83 *fontFileStream = stream.release(); |
| 84 return S_OK; |
| 85 } |
| 86 |
| 87 //////////////////////////////////////////////////////////////////////////////// |
| 88 |
| 89 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator { |
| 90 public: |
| 91 // IUnknown methods |
| 92 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObjec
t); |
| 93 virtual ULONG STDMETHODCALLTYPE AddRef(); |
| 94 virtual ULONG STDMETHODCALLTYPE Release(); |
| 95 |
| 96 // IDWriteFontFileEnumerator methods |
| 97 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile); |
| 98 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontF
ile); |
| 99 |
| 100 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFi
leLoader, |
| 101 StreamFontFileEnumerator** streamFontFileEnumerator) { |
| 102 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFi
leLoader); |
| 103 if (NULL == streamFontFileEnumerator) { |
| 104 return E_OUTOFMEMORY; |
| 105 } |
| 106 return S_OK; |
| 107 } |
| 108 private: |
| 109 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fon
tFileLoader); |
| 110 ULONG fRefCount; |
| 111 |
| 112 SkTScopedComPtr<IDWriteFactory> fFactory; |
| 113 SkTScopedComPtr<IDWriteFontFile> fCurrentFile; |
| 114 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; |
| 115 bool fHasNext; |
| 116 }; |
| 117 |
| 118 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory, |
| 119 IDWriteFontFileLoader* fontFi
leLoader) |
| 120 : fRefCount(1) |
| 121 , fFactory(SkRefComPtr(factory)) |
| 122 , fCurrentFile() |
| 123 , fFontFileLoader(SkRefComPtr(fontFileLoader)) |
| 124 , fHasNext(true) |
| 125 { } |
| 126 |
| 127 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) { |
| 128 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) { |
| 129 *ppvObject = this; |
| 130 AddRef(); |
| 131 return S_OK; |
| 132 } else { |
| 133 *ppvObject = NULL; |
| 134 return E_NOINTERFACE; |
| 135 } |
| 136 } |
| 137 |
| 138 ULONG StreamFontFileEnumerator::AddRef() { |
| 139 return InterlockedIncrement(&fRefCount); |
| 140 } |
| 141 |
| 142 ULONG StreamFontFileEnumerator::Release() { |
| 143 ULONG newCount = InterlockedDecrement(&fRefCount); |
| 144 if (0 == newCount) { |
| 145 delete this; |
| 146 } |
| 147 return newCount; |
| 148 } |
| 149 |
| 150 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) { |
| 151 *hasCurrentFile = FALSE; |
| 152 |
| 153 if (!fHasNext) { |
| 154 return S_OK; |
| 155 } |
| 156 fHasNext = false; |
| 157 |
| 158 UINT32 dummy = 0; |
| 159 HR(fFactory->CreateCustomFontFileReference( |
| 160 &dummy, //cannot be NULL |
| 161 sizeof(dummy), //even if this is 0 |
| 162 fFontFileLoader.get(), |
| 163 &fCurrentFile)); |
| 164 |
| 165 *hasCurrentFile = TRUE; |
| 166 return S_OK; |
| 167 } |
| 168 |
| 169 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile)
{ |
| 170 if (fCurrentFile.get() == NULL) { |
| 171 *fontFile = NULL; |
| 172 return E_FAIL; |
| 173 } |
| 174 |
| 175 *fontFile = SkRefComPtr(fCurrentFile.get()); |
| 176 return S_OK; |
| 177 } |
| 178 |
| 179 //////////////////////////////////////////////////////////////////////////////// |
| 180 |
| 181 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader { |
| 182 public: |
| 183 // IUnknown methods |
| 184 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObjec
t); |
| 185 virtual ULONG STDMETHODCALLTYPE AddRef(); |
| 186 virtual ULONG STDMETHODCALLTYPE Release(); |
| 187 |
| 188 // IDWriteFontCollectionLoader methods |
| 189 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( |
| 190 IDWriteFactory* factory, |
| 191 void const* collectionKey, |
| 192 UINT32 collectionKeySize, |
| 193 IDWriteFontFileEnumerator** fontFileEnumerator); |
| 194 |
| 195 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader, |
| 196 StreamFontCollectionLoader** streamFontCollectionLoade
r) { |
| 197 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoa
der); |
| 198 if (NULL == streamFontCollectionLoader) { |
| 199 return E_OUTOFMEMORY; |
| 200 } |
| 201 return S_OK; |
| 202 } |
| 203 private: |
| 204 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader) |
| 205 : fRefCount(1) |
| 206 , fFontFileLoader(SkRefComPtr(fontFileLoader)) |
| 207 { } |
| 208 |
| 209 ULONG fRefCount; |
| 210 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; |
| 211 }; |
| 212 |
| 213 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject)
{ |
| 214 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) { |
| 215 *ppvObject = this; |
| 216 AddRef(); |
| 217 return S_OK; |
| 218 } else { |
| 219 *ppvObject = NULL; |
| 220 return E_NOINTERFACE; |
| 221 } |
| 222 } |
| 223 |
| 224 ULONG StreamFontCollectionLoader::AddRef() { |
| 225 return InterlockedIncrement(&fRefCount); |
| 226 } |
| 227 |
| 228 ULONG StreamFontCollectionLoader::Release() { |
| 229 ULONG newCount = InterlockedDecrement(&fRefCount); |
| 230 if (0 == newCount) { |
| 231 delete this; |
| 232 } |
| 233 return newCount; |
| 234 } |
| 235 |
| 236 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey( |
| 237 IDWriteFactory* factory, |
| 238 void const* collectionKey, |
| 239 UINT32 collectionKeySize, |
| 240 IDWriteFontFileEnumerator** fontFileEnumerator) |
| 241 { |
| 242 SkTScopedComPtr<StreamFontFileEnumerator> enumerator; |
| 243 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumera
tor)); |
| 244 *fontFileEnumerator = enumerator.release(); |
| 245 return S_OK; |
| 246 } |
| 247 |
| 248 //////////////////////////////////////////////////////////////////////////////// |
| 249 |
| 250 class SkFontMgr_DirectWrite : public SkFontMgr { |
| 251 public: |
| 252 /** localeNameLength must include the null terminator. */ |
| 253 SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCo
llection, |
| 254 WCHAR* localeName, int localeNameLength) |
| 255 : fFactory(SkRefComPtr(factory)) |
| 256 , fFontCollection(SkRefComPtr(fontCollection)) |
| 257 , fLocaleName(localeNameLength) |
| 258 { |
| 259 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR)); |
| 260 } |
| 261 |
| 262 /** Creates a typeface using a typeface cache. */ |
| 263 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace, |
| 264 IDWriteFont* font, |
| 265 IDWriteFontFamily* fontFamily) cons
t; |
| 266 |
| 267 protected: |
| 268 virtual int onCountFamilies() const SK_OVERRIDE; |
| 269 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERR
IDE; |
| 270 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE; |
| 271 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER
RIDE; |
| 272 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], |
| 273 const SkFontStyle& fontstyle) const S
K_OVERRIDE; |
| 274 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, |
| 275 const SkFontStyle& fontstyle) const SK_
OVERRIDE; |
| 276 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const
SK_OVERRIDE; |
| 277 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV
ERRIDE; |
| 278 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const
SK_OVERRIDE; |
| 279 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
| 280 unsigned styleBits) const SK_OVER
RIDE; |
| 281 |
| 282 private: |
| 283 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFa
mily) const; |
| 284 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const; |
| 285 |
| 286 void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) co
nst { |
| 287 SkAutoMutexAcquire ama(fTFCacheMutex); |
| 288 fTFCache.add(face, requestedStyle, strong); |
| 289 } |
| 290 |
| 291 SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) cons
t { |
| 292 SkAutoMutexAcquire ama(fTFCacheMutex); |
| 293 SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx); |
| 294 return typeface; |
| 295 } |
| 296 |
| 297 SkTScopedComPtr<IDWriteFactory> fFactory; |
| 298 SkTScopedComPtr<IDWriteFontCollection> fFontCollection; |
| 299 SkSMallocWCHAR fLocaleName; |
| 300 mutable SkMutex fTFCacheMutex; |
| 301 mutable SkTypefaceCache fTFCache; |
| 302 |
| 303 friend class SkFontStyleSet_DirectWrite; |
| 304 }; |
| 305 |
| 306 class SkFontStyleSet_DirectWrite : public SkFontStyleSet { |
| 307 public: |
| 308 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr, |
| 309 IDWriteFontFamily* fontFamily) |
| 310 : fFontMgr(SkRef(fontMgr)) |
| 311 , fFontFamily(SkRefComPtr(fontFamily)) |
| 312 { } |
| 313 |
| 314 virtual int count() SK_OVERRIDE; |
| 315 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OV
ERRIDE; |
| 316 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE; |
| 317 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE; |
| 318 |
| 319 private: |
| 320 SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr; |
| 321 SkTScopedComPtr<IDWriteFontFamily> fFontFamily; |
| 322 }; |
| 323 |
| 324 static bool are_same(IUnknown* a, IUnknown* b) { |
| 325 SkTScopedComPtr<IUnknown> iunkA; |
| 326 if (FAILED(a->QueryInterface(&iunkA))) { |
| 327 return false; |
| 328 } |
| 329 |
| 330 SkTScopedComPtr<IUnknown> iunkB; |
| 331 if (FAILED(b->QueryInterface(&iunkB))) { |
| 332 return false; |
| 333 } |
| 334 |
| 335 return iunkA.get() == iunkB.get(); |
| 336 } |
| 337 |
| 338 static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style, void* ctx) { |
| 339 //Check to see if the two fonts are identical. |
| 340 DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face); |
| 341 IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx); |
| 342 if (are_same(dwFace->fDWriteFont.get(), dwFont)) { |
| 343 return true; |
| 344 } |
| 345 |
| 346 //Check if the two fonts share the same loader and have the same key. |
| 347 SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace; |
| 348 SkTScopedComPtr<IDWriteFontFace> dwFontFace; |
| 349 HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace)); |
| 350 HRB(dwFont->CreateFontFace(&dwFontFace)); |
| 351 if (are_same(dwFaceFontFace.get(), dwFontFace.get())) { |
| 352 return true; |
| 353 } |
| 354 |
| 355 UINT32 dwFaceNumFiles; |
| 356 UINT32 dwNumFiles; |
| 357 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL)); |
| 358 HRB(dwFontFace->GetFiles(&dwNumFiles, NULL)); |
| 359 if (dwFaceNumFiles != dwNumFiles) { |
| 360 return false; |
| 361 } |
| 362 |
| 363 SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile; |
| 364 SkTScopedComPtr<IDWriteFontFile> dwFontFile; |
| 365 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile)); |
| 366 HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile)); |
| 367 |
| 368 //for (each file) { //we currently only admit fonts from one file. |
| 369 SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader; |
| 370 SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader; |
| 371 HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader)); |
| 372 HRB(dwFontFile->GetLoader(&dwFontFileLoader)); |
| 373 if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) { |
| 374 return false; |
| 375 } |
| 376 //} |
| 377 |
| 378 const void* dwFaceFontRefKey; |
| 379 UINT32 dwFaceFontRefKeySize; |
| 380 const void* dwFontRefKey; |
| 381 UINT32 dwFontRefKeySize; |
| 382 HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize
)); |
| 383 HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize)); |
| 384 if (dwFaceFontRefKeySize != dwFontRefKeySize) { |
| 385 return false; |
| 386 } |
| 387 if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) { |
| 388 return false; |
| 389 } |
| 390 |
| 391 //TODO: better means than comparing name strings? |
| 392 //NOTE: .tfc and fake bold/italic will end up here. |
| 393 SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily; |
| 394 SkTScopedComPtr<IDWriteFontFamily> dwFontFamily; |
| 395 HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily)); |
| 396 HRB(dwFont->GetFontFamily(&dwFontFamily)); |
| 397 |
| 398 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames; |
| 399 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames; |
| 400 HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames)); |
| 401 HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames)); |
| 402 |
| 403 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames; |
| 404 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames; |
| 405 HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames)); |
| 406 HRB(dwFont->GetFaceNames(&dwFontNames)); |
| 407 |
| 408 UINT32 dwFaceFontFamilyNameLength; |
| 409 UINT32 dwFaceFontNameLength; |
| 410 HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength)); |
| 411 HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength)); |
| 412 |
| 413 UINT32 dwFontFamilyNameLength; |
| 414 UINT32 dwFontNameLength; |
| 415 HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength)); |
| 416 HRB(dwFontNames->GetStringLength(0, &dwFontNameLength)); |
| 417 |
| 418 if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength || |
| 419 dwFaceFontNameLength != dwFontNameLength) |
| 420 { |
| 421 return false; |
| 422 } |
| 423 |
| 424 SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1); |
| 425 SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1); |
| 426 HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFa
ceFontFamilyNameLength+1)); |
| 427 HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLe
ngth+1)); |
| 428 |
| 429 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1); |
| 430 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1); |
| 431 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamily
NameLength+1)); |
| 432 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1)); |
| 433 |
| 434 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) ==
0 && |
| 435 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0; |
| 436 } |
| 437 |
| 438 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont( |
| 439 IDWriteFontFace* fontFace, |
| 440 IDWriteFont* font, |
| 441 IDWriteFontFamily* fontFamily) const { |
| 442 SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font); |
| 443 if (NULL == face) { |
| 444 face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFa
mily); |
| 445 if (face) { |
| 446 Add(face, get_style(font), true); |
| 447 } |
| 448 } |
| 449 return face; |
| 450 } |
| 451 |
| 452 int SkFontMgr_DirectWrite::onCountFamilies() const { |
| 453 return fFontCollection->GetFontFamilyCount(); |
| 454 } |
| 455 |
| 456 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) con
st { |
| 457 SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
| 458 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requ
ested family."); |
| 459 |
| 460 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; |
| 461 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names."
); |
| 462 |
| 463 sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName); |
| 464 } |
| 465 |
| 466 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const { |
| 467 SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
| 468 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requ
ested family."); |
| 469 |
| 470 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get())); |
| 471 } |
| 472 |
| 473 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) co
nst { |
| 474 SkSMallocWCHAR dwFamilyName; |
| 475 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName)); |
| 476 |
| 477 UINT32 index; |
| 478 BOOL exists; |
| 479 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists), |
| 480 "Failed while finding family by name."); |
| 481 if (!exists) { |
| 482 return NULL; |
| 483 } |
| 484 |
| 485 return this->onCreateStyleSet(index); |
| 486 } |
| 487 |
| 488 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[], |
| 489 const SkFontStyle& fontsty
le) const { |
| 490 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); |
| 491 return sset->matchStyle(fontstyle); |
| 492 } |
| 493 |
| 494 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMemb
er, |
| 495 const SkFontStyle& fontstyle
) const { |
| 496 SkString familyName; |
| 497 SkFontStyleSet_DirectWrite sset( |
| 498 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get() |
| 499 ); |
| 500 return sset.matchStyle(fontstyle); |
| 501 } |
| 502 |
| 503 template <typename T> class SkAutoIDWriteUnregister { |
| 504 public: |
| 505 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister) |
| 506 : fFactory(factory), fUnregister(unregister) |
| 507 { } |
| 508 |
| 509 ~SkAutoIDWriteUnregister() { |
| 510 if (fUnregister) { |
| 511 unregister(fFactory, fUnregister); |
| 512 } |
| 513 } |
| 514 |
| 515 T* detatch() { |
| 516 T* old = fUnregister; |
| 517 fUnregister = NULL; |
| 518 return old; |
| 519 } |
| 520 |
| 521 private: |
| 522 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregiste
r) { |
| 523 return factory->UnregisterFontFileLoader(unregister); |
| 524 } |
| 525 |
| 526 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unr
egister) { |
| 527 return factory->UnregisterFontCollectionLoader(unregister); |
| 528 } |
| 529 |
| 530 IDWriteFactory* fFactory; |
| 531 T* fUnregister; |
| 532 }; |
| 533 |
| 534 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcI
ndex) const { |
| 535 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader; |
| 536 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader)); |
| 537 HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get())); |
| 538 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader( |
| 539 fFactory.get(), fontFileLoader.get()); |
| 540 |
| 541 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader; |
| 542 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollection
Loader)); |
| 543 HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get())); |
| 544 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollec
tionLoader( |
| 545 fFactory.get(), fontCollectionLoader.get()); |
| 546 |
| 547 SkTScopedComPtr<IDWriteFontCollection> fontCollection; |
| 548 HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0
, &fontCollection)); |
| 549 |
| 550 // Find the first non-simulated font which has the given ttc index. |
| 551 UINT32 familyCount = fontCollection->GetFontFamilyCount(); |
| 552 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) { |
| 553 SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
| 554 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily)); |
| 555 |
| 556 UINT32 fontCount = fontFamily->GetFontCount(); |
| 557 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) { |
| 558 SkTScopedComPtr<IDWriteFont> font; |
| 559 HRN(fontFamily->GetFont(fontIndex, &font)); |
| 560 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { |
| 561 continue; |
| 562 } |
| 563 |
| 564 SkTScopedComPtr<IDWriteFontFace> fontFace; |
| 565 HRN(font->CreateFontFace(&fontFace)); |
| 566 |
| 567 UINT32 faceIndex = fontFace->GetIndex(); |
| 568 if (faceIndex == ttcIndex) { |
| 569 return DWriteFontTypeface::Create(fFactory.get(), |
| 570 fontFace.get(), font.get(), fo
ntFamily.get(), |
| 571 autoUnregisterFontFileLoader.d
etatch(), |
| 572 autoUnregisterFontCollectionLo
ader.detatch()); |
| 573 } |
| 574 } |
| 575 } |
| 576 |
| 577 return NULL; |
| 578 } |
| 579 |
| 580 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex)
const { |
| 581 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data))); |
| 582 return this->createFromStream(stream, ttcIndex); |
| 583 } |
| 584 |
| 585 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIn
dex) const { |
| 586 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
| 587 return this->createFromStream(stream, ttcIndex); |
| 588 } |
| 589 |
| 590 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[], |
| 591 IDWriteFontFamily** fontFamily) c
onst { |
| 592 UINT32 index; |
| 593 BOOL exists; |
| 594 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists)); |
| 595 |
| 596 if (exists) { |
| 597 HR(fFontCollection->GetFontFamily(index, fontFamily)); |
| 598 } |
| 599 return S_OK; |
| 600 } |
| 601 |
| 602 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFami
ly) const { |
| 603 NONCLIENTMETRICSW metrics; |
| 604 metrics.cbSize = sizeof(metrics); |
| 605 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, |
| 606 sizeof(metrics), |
| 607 &metrics, |
| 608 0)) { |
| 609 return E_UNEXPECTED; |
| 610 } |
| 611 HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily), |
| 612 "Could not create DWrite font family from LOGFONT."); |
| 613 return S_OK; |
| 614 } |
| 615 |
| 616 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[
], |
| 617 unsigned styleBits) co
nst { |
| 618 SkTScopedComPtr<IDWriteFontFamily> fontFamily; |
| 619 if (familyName) { |
| 620 SkSMallocWCHAR wideFamilyName; |
| 621 if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) { |
| 622 this->getByFamilyName(wideFamilyName, &fontFamily); |
| 623 } |
| 624 } |
| 625 |
| 626 if (NULL == fontFamily.get()) { |
| 627 // No family with given name, try default. |
| 628 HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default fon
t family."); |
| 629 } |
| 630 |
| 631 if (NULL == fontFamily.get()) { |
| 632 // Could not obtain the default font. |
| 633 HRNM(fFontCollection->GetFontFamily(0, &fontFamily), |
| 634 "Could not get default-default font family."); |
| 635 } |
| 636 |
| 637 SkTScopedComPtr<IDWriteFont> font; |
| 638 DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold) |
| 639 ? DWRITE_FONT_WEIGHT_BOLD |
| 640 : DWRITE_FONT_WEIGHT_NORMAL; |
| 641 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; |
| 642 DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic) |
| 643 ? DWRITE_FONT_STYLE_ITALIC |
| 644 : DWRITE_FONT_STYLE_NORMAL; |
| 645 HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font), |
| 646 "Could not get matching font."); |
| 647 |
| 648 SkTScopedComPtr<IDWriteFontFace> fontFace; |
| 649 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); |
| 650 |
| 651 return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFa
mily.get()); |
| 652 } |
| 653 |
| 654 /////////////////////////////////////////////////////////////////////////////// |
| 655 |
| 656 int SkFontStyleSet_DirectWrite::count() { |
| 657 return fFontFamily->GetFontCount(); |
| 658 } |
| 659 |
| 660 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) { |
| 661 SkTScopedComPtr<IDWriteFont> font; |
| 662 HRNM(fFontFamily->GetFont(index, &font), "Could not get font."); |
| 663 |
| 664 SkTScopedComPtr<IDWriteFontFace> fontFace; |
| 665 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); |
| 666 |
| 667 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fF
ontFamily.get()); |
| 668 } |
| 669 |
| 670 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString*
styleName) { |
| 671 SkTScopedComPtr<IDWriteFont> font; |
| 672 HRVM(fFontFamily->GetFont(index, &font), "Could not get font."); |
| 673 |
| 674 if (fs) { |
| 675 SkFontStyle::Slant slant; |
| 676 switch (font->GetStyle()) { |
| 677 case DWRITE_FONT_STYLE_NORMAL: |
| 678 slant = SkFontStyle::kUpright_Slant; |
| 679 break; |
| 680 case DWRITE_FONT_STYLE_OBLIQUE: |
| 681 case DWRITE_FONT_STYLE_ITALIC: |
| 682 slant = SkFontStyle::kItalic_Slant; |
| 683 break; |
| 684 default: |
| 685 SkASSERT(false); |
| 686 } |
| 687 |
| 688 int weight = font->GetWeight(); |
| 689 int width = font->GetStretch(); |
| 690 |
| 691 *fs = SkFontStyle(weight, width, slant); |
| 692 } |
| 693 |
| 694 if (styleName) { |
| 695 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; |
| 696 if (SUCCEEDED(font->GetFaceNames(&faceNames))) { |
| 697 sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), s
tyleName); |
| 698 } |
| 699 } |
| 700 } |
| 701 |
| 702 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) { |
| 703 DWRITE_FONT_STYLE slant; |
| 704 switch (pattern.slant()) { |
| 705 case SkFontStyle::kUpright_Slant: |
| 706 slant = DWRITE_FONT_STYLE_NORMAL; |
| 707 break; |
| 708 case SkFontStyle::kItalic_Slant: |
| 709 slant = DWRITE_FONT_STYLE_ITALIC; |
| 710 break; |
| 711 default: |
| 712 SkASSERT(false); |
| 713 } |
| 714 |
| 715 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight(); |
| 716 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width(); |
| 717 |
| 718 SkTScopedComPtr<IDWriteFont> font; |
| 719 // TODO: perhaps use GetMatchingFonts and get the least simulated? |
| 720 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font), |
| 721 "Could not match font in family."); |
| 722 |
| 723 SkTScopedComPtr<IDWriteFontFace> fontFace; |
| 724 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); |
| 725 |
| 726 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), |
| 727 fFontFamily.get()); |
| 728 } |
| 729 |
| 730 //////////////////////////////////////////////////////////////////////////////// |
| 731 |
| 732 SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) { |
| 733 if (NULL == factory) { |
| 734 factory = sk_get_dwrite_factory(); |
| 735 if (NULL == factory) { |
| 736 return NULL; |
| 737 } |
| 738 } |
| 739 |
| 740 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection; |
| 741 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE), |
| 742 "Could not get system font collection."); |
| 743 |
| 744 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH]; |
| 745 WCHAR* localeName = NULL; |
| 746 int localeNameLen = 0; |
| 747 |
| 748 // Dynamically load GetUserDefaultLocaleName function, as it is not availabl
e on XP. |
| 749 SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL; |
| 750 HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc
); |
| 751 if (NULL == getUserDefaultLocaleNameProc) { |
| 752 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName."); |
| 753 } else { |
| 754 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_N
AME_MAX_LENGTH); |
| 755 if (localeNameLen) { |
| 756 localeName = localeNameStorage; |
| 757 }; |
| 758 } |
| 759 |
| 760 return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(), |
| 761 localeName, localeNameLen)); |
| 762 } |
| 763 |
| 764 //////////////////////////////////////////////////////////////////////////////// |
| 765 |
| 766 #include "SkFontMgr_indirect.h" |
| 767 #include "SkTypeface_win.h" |
| 768 SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) { |
| 769 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); |
| 770 if (impl.get() == NULL) { |
| 771 return NULL; |
| 772 } |
| 773 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy)); |
| 774 } |
OLD | NEW |