SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const { SkTScopedComPtr<IDWriteFontFamily> fontFamily; if (familyName) { SkSMallocWCHAR wideFamilyName; if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) { this->getByFamilyName(wideFamilyName, &fontFamily); } } if (nullptr == fontFamily.get()) { // No family with given name, try default. this->getDefaultFontFamily(&fontFamily); } if (nullptr == fontFamily.get()) { // Could not obtain the default font. HRNM(fFontCollection->GetFontFamily(0, &fontFamily), "Could not get default-default font family."); } SkTScopedComPtr<IDWriteFont> font; DWriteStyle dwStyle(style); HRNM(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &font), "Could not get matching font."); SkTScopedComPtr<IDWriteFontFace> fontFace; HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get()); }
SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) { DWRITE_FONT_STYLE slant; switch (pattern.slant()) { case SkFontStyle::kUpright_Slant: slant = DWRITE_FONT_STYLE_NORMAL; break; case SkFontStyle::kItalic_Slant: slant = DWRITE_FONT_STYLE_ITALIC; break; default: SkASSERT(false); } DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight(); DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width(); SkTScopedComPtr<IDWriteFont> font; // TODO: perhaps use GetMatchingFonts and get the least simulated? HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font), "Could not match font in family."); SkTScopedComPtr<IDWriteFontFace> fontFace; HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()); }
SkStreamAsset* DWriteFontTypeface::onOpenStream(int* ttcIndex) const { *ttcIndex = fDWriteFontFace->GetIndex(); UINT32 numFiles; HRNM(fDWriteFontFace->GetFiles(&numFiles, nullptr), "Could not get number of font files."); if (numFiles != 1) { return nullptr; } SkTScopedComPtr<IDWriteFontFile> fontFile; HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files."); const void* fontFileKey; UINT32 fontFileKeySize; HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize), "Could not get font file reference key."); SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader; HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader."); SkTScopedComPtr<IDWriteFontFileStream> fontFileStream; HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize, &fontFileStream), "Could not create font file stream."); return new SkDWriteFontFileStream(fontFileStream.get()); }
SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) { SkTScopedComPtr<IDWriteFont> font; HRNM(fFontFamily->GetFont(index, &font), "Could not get font."); SkTScopedComPtr<IDWriteFontFace> fontFace; HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()); }
const void* SkDWriteFontFileStream::getMemoryBase() { if (fLockedMemory) { return fLockedMemory; } UINT64 fileSize; HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size"); HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock), "Could not lock file fragment."); return fLockedMemory; }
SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) { SkTScopedComPtr<IDWriteFont> font; DWriteStyle dwStyle(pattern); // TODO: perhaps use GetMatchingFonts and get the least simulated? HRNM(fFontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &font), "Could not match font in family."); SkTScopedComPtr<IDWriteFontFace> fontFace; HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()); }
SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* collection, IDWriteFontFallback* fallback) { if (nullptr == factory) { factory = sk_get_dwrite_factory(); if (nullptr == factory) { return nullptr; } } SkTScopedComPtr<IDWriteFontCollection> systemFontCollection; if (nullptr == collection) { HRNM(factory->GetSystemFontCollection(&systemFontCollection, FALSE), "Could not get system font collection."); collection = systemFontCollection.get(); } WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH]; WCHAR* localeName = nullptr; int localeNameLen = 0; // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP. SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = nullptr; HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc); if (nullptr == getUserDefaultLocaleNameProc) { SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName."); } else { localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH); if (localeNameLen) { localeName = localeNameStorage; }; } return new SkFontMgr_DirectWrite(factory, collection, fallback, localeName, localeNameLen); }
SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) { if (NULL == factory) { factory = sk_get_dwrite_factory(); if (NULL == factory) { return NULL; } } SkTScopedComPtr<IDWriteFontCollection> sysFontCollection; HRNM(SkFontMgr_GetFontCollectionToUse(&sysFontCollection, factory), "Could not get system font collection."); WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH]; WCHAR* localeName = NULL; int localeNameLen = 0; // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP. SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL; HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc); if (NULL == getUserDefaultLocaleNameProc) { SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName."); } else { localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH); if (localeNameLen) { localeName = localeNameStorage; }; } return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(), localeName, localeNameLen)); }
SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const { SkTypeface::LocalizedStrings* nameIter = SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); if (nullptr == nameIter) { SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names."); nameIter = new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release()); } return nameIter; }
SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const { SkSMallocWCHAR dwFamilyName; HRN(sk_cstring_to_wchar(familyName, &dwFamilyName)); UINT32 index; BOOL exists; HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists), "Failed while finding family by name."); if (!exists) { return nullptr; } return this->onCreateStyleSet(index); }
SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[], unsigned styleBits) const { SkTScopedComPtr<IDWriteFontFamily> fontFamily; if (familyName) { SkSMallocWCHAR wideFamilyName; if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) { this->getByFamilyName(wideFamilyName, &fontFamily); } } if (NULL == fontFamily.get()) { // No family with given name, try default. HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family."); } if (NULL == fontFamily.get()) { // Could not obtain the default font. HRNM(fFontCollection->GetFontFamily(0, &fontFamily), "Could not get default-default font family."); } SkTScopedComPtr<IDWriteFont> font; DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold) ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL; DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic) ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font), "Could not get matching font."); SkTScopedComPtr<IDWriteFontFace> fontFace; HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get()); }
SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style, const char* bcp47[], int bcp47Count, SkUnichar character) const { const DWriteStyle dwStyle(style); const WCHAR* dwFamilyName = nullptr; SkSMallocWCHAR dwFamilyNameLocal; if (familyName) { HRN(sk_cstring_to_wchar(familyName, &dwFamilyNameLocal)); dwFamilyName = dwFamilyNameLocal; } WCHAR str[16]; UINT32 strLen = static_cast<UINT32>( SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str))); const SkSMallocWCHAR* dwBcp47; SkSMallocWCHAR dwBcp47Local; if (bcp47Count < 1) { dwBcp47 = &fLocaleName; } else { // TODO: support fallback stack. // TODO: DirectWrite supports 'zh-CN' or 'zh-Hans', but 'zh' misses completely // and may produce a Japanese font. HRN(sk_cstring_to_wchar(bcp47[bcp47Count - 1], &dwBcp47Local)); dwBcp47 = &dwBcp47Local; } if (fFactory2.get()) { SkTScopedComPtr<IDWriteFontFallback> systemFontFallback; IDWriteFontFallback* fontFallback = fFontFallback.get(); if (!fontFallback) { HRNM(fFactory2->GetSystemFontFallback(&systemFontFallback), "Could not get system fallback."); fontFallback = systemFontFallback.get(); } SkTScopedComPtr<IDWriteNumberSubstitution> numberSubstitution; HRNM(fFactory2->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, nullptr, TRUE, &numberSubstitution), "Could not create number substitution."); SkTScopedComPtr<FontFallbackSource> fontFallbackSource( new FontFallbackSource(str, strLen, *dwBcp47, numberSubstitution.get())); UINT32 mappedLength; SkTScopedComPtr<IDWriteFont> font; FLOAT scale; HRNM(fontFallback->MapCharacters(fontFallbackSource.get(), 0, // textPosition, strLen, fFontCollection.get(), dwFamilyName, dwStyle.fWeight, dwStyle.fSlant, dwStyle.fWidth, &mappedLength, &font, &scale), "Could not map characters"); if (!font.get()) { return nullptr; } SkTScopedComPtr<IDWriteFontFace> fontFace; HRNM(font->CreateFontFace(&fontFace), "Could not get font face from font."); SkTScopedComPtr<IDWriteFontFamily> fontFamily; HRNM(font->GetFontFamily(&fontFamily), "Could not get family from font."); return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get()); } SkTScopedComPtr<IDWriteTextFormat> fallbackFormat; HRNM(fFactory->CreateTextFormat(dwFamilyName ? dwFamilyName : L"", fFontCollection.get(), dwStyle.fWeight, dwStyle.fSlant, dwStyle.fWidth, 72.0f, *dwBcp47, &fallbackFormat), "Could not create text format."); SkTScopedComPtr<IDWriteTextLayout> fallbackLayout; HRNM(fFactory->CreateTextLayout(str, strLen, fallbackFormat.get(), 200.0f, 200.0f, &fallbackLayout), "Could not create text layout."); SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer( new FontFallbackRenderer(this, character)); HRNM(fallbackLayout->Draw(nullptr, fontFallbackRenderer.get(), 50.0f, 50.0f), "Could not draw layout with renderer."); return fontFallbackRenderer->FallbackTypeface(); }
SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const { SkTScopedComPtr<IDWriteFontFamily> fontFamily; HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); return new SkFontStyleSet_DirectWrite(this, fontFamily.get()); }