Reputation: 25
I am trying to get all the available fonts of windows through IDWriteFactory::GetSystemFontCollection in c++. I followed all the Microsoft MSDN steps. Now I can successfully get all the major fonts, but it won't provide any "variants" fonts.
Eg, I get "Arial" but no "Arial Black" and "Arial Narrow", "Yu Gothic" but no "Yu Gothic Medium" and "Yu Gothic Light". Any one knows how to get all these fonts in C++? Thank you!
Below is my program:
void wmain()
{
IDWriteFactory* pDWriteFactory = NULL;
HRESULT hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&pDWriteFactory)
);
IDWriteFontCollection* pFontCollection = NULL;
// Get the system font collection.
if (SUCCEEDED(hr))
{
hr = pDWriteFactory->GetSystemFontCollection(&pFontCollection);
}
UINT32 familyCount = 0;
// Get the number of font families in the collection.
if (SUCCEEDED(hr))
{
familyCount = pFontCollection->GetFontFamilyCount();
}
for (UINT32 i = 0; i < familyCount; ++i)
{
IDWriteFontFamily* pFontFamily = NULL;
// Get the font family.
if (SUCCEEDED(hr))
{
hr = pFontCollection->GetFontFamily(i, &pFontFamily);
}
IDWriteLocalizedStrings* pFamilyNames = NULL;
// Get a list of localized strings for the family name.
if (SUCCEEDED(hr))
{
hr = pFontFamily->GetFamilyNames(&pFamilyNames);
}
UINT32 index = 0;
BOOL exists = false;
wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
if (SUCCEEDED(hr))
{
// Get the default locale for this user.
int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH);
// If the default locale is returned, find that locale name, otherwise use "en-us".
if (defaultLocaleSuccess)
{
hr = pFamilyNames->FindLocaleName(localeName, &index, &exists);
}
if (SUCCEEDED(hr) && !exists) // if the above find did not find a match, retry with US English
{
hr = pFamilyNames->FindLocaleName(L"en-us", &index, &exists);
}
}
// If the specified locale doesn't exist, select the first on the list.
if (!exists)
index = 0;
UINT32 length = 0;
// Get the string length.
if (SUCCEEDED(hr))
{
hr = pFamilyNames->GetStringLength(index, &length);
}
// Allocate a string big enough to hold the name.
wchar_t* name = new (std::nothrow) wchar_t[length+1];
if (name == NULL)
{
hr = E_OUTOFMEMORY;
}
// Get the family name.
if (SUCCEEDED(hr))
{
hr = pFamilyNames->GetString(index, name, length+1);
}
if (SUCCEEDED(hr))
{
// Print out the family name.
wprintf(L"%s\n", name);
}
}
}
Upvotes: 1
Views: 452
Reputation: 11588
GDI had a limitation of four variants per distinct font family. Therefore, Arial Black and Arial Narrow had to be treated as separate font families, even though in reality they're just different variants of Arial.
DirectWrite does not have that limitation, so now there is just Arial, and Arial Black and Arial Narrow come up as variants of Arial. Try it: call GetFonts()
on the IDWriteFontFamily for Arial and print the GetFaceNames()
s of all the resultant IDWriteFonts.
Of course, this may be counterintuitive to someone working with a program that uses GDI font enumeration, or expects that the family name of Arial Black is Arial Black
instead of Arial
(for instance, in a file format). I'm not sure what the solution to that problem is...
Upvotes: 3