Gfx: Improve D2D local font support

This commit is contained in:
Birunthan Mohanathas 2013-04-12 19:41:47 +03:00
parent 3a70f91d15
commit d04bb46009
3 changed files with 136 additions and 35 deletions

View File

@ -93,15 +93,20 @@ void TextFormatD2D::SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection)
{
auto fontCollectionD2D = (FontCollectionD2D*)fontCollection;
Dispose();
WCHAR dwriteFamilyName[LF_FACESIZE];
DWRITE_FONT_WEIGHT dwriteFontWeight =
bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR;
DWRITE_FONT_STYLE dwriteFontStyle =
italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
DWRITE_FONT_STRETCH dwriteFontStretch = DWRITE_FONT_STRETCH_NORMAL;
// |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font
// using the GDI family name and then create a text format using the DirectWrite family name
// obtained from it.
WCHAR dwriteFamilyName[LF_FACESIZE];
DWRITE_FONT_WEIGHT dwriteFontWeight;
DWRITE_FONT_STYLE dwriteFontStyle;
DWRITE_FONT_STRETCH dwriteFontStretch;
HRESULT hr = Util::GetDWritePropertiesFromGDIProperties(
CanvasD2D::c_DWFactory, fontFamily, bold, italic, dwriteFontWeight, dwriteFontStyle,
dwriteFontStretch, dwriteFamilyName, _countof(dwriteFamilyName));
@ -121,15 +126,28 @@ void TextFormatD2D::SetProperties(
if (FAILED(hr))
{
IDWriteFontCollection* dwriteFontCollection = nullptr;
auto fontCollectionD2D = (FontCollectionD2D*)fontCollection;
// If |fontFamily| is not in the system collection, use the font collection from
// |fontCollectionD2D| if possible.
//
// TODO: Need to check GDI family names of the collection in |fontCollectionD2D|.
if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory, fontFamily) &&
(fontCollectionD2D && fontCollectionD2D->InitializeCollection()))
{
IDWriteFont* dwriteFont = Util::FindDWriteFontInFontCollectionByGDIFamilyName(
fontCollectionD2D->m_Collection, fontFamily);
if (dwriteFont)
{
hr = Util::GetFamilyNameFromDWriteFont(
dwriteFont, dwriteFamilyName, _countof(dwriteFamilyName));
{
fontFamily = dwriteFamilyName;
Util::GetPropertiesFromDWriteFont(
dwriteFont, bold, italic, &dwriteFontWeight, &dwriteFontStyle,
&dwriteFontStretch);
}
dwriteFont->Release();
}
dwriteFontCollection = fontCollectionD2D->m_Collection;
}
@ -137,9 +155,9 @@ void TextFormatD2D::SetProperties(
hr = CanvasD2D::c_DWFactory->CreateTextFormat(
fontFamily,
dwriteFontCollection,
bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR,
italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
dwriteFontWeight,
dwriteFontStyle,
dwriteFontStretch,
size * (4.0f / 3.0f),
L"",
&m_TextFormat);

View File

@ -32,31 +32,8 @@ HRESULT GetDWritePropertiesFromGDIProperties(
{
if (GetFamilyNameFromDWriteFont(dwriteFont, dwriteFamilyName, dwriteFamilyNameSize))
{
dwriteFontWeight = dwriteFont->GetWeight();
if (gdiBold)
{
if (dwriteFontWeight == DWRITE_FONT_WEIGHT_NORMAL)
{
dwriteFontWeight = DWRITE_FONT_WEIGHT_BOLD;
}
else if (dwriteFontWeight < DWRITE_FONT_WEIGHT_ULTRA_BOLD)
{
// If 'gdiFamilyName' was e.g. 'Segoe UI Light', |dwFontWeight| wil be equal to
// DWRITE_FONT_WEIGHT_LIGHT. If |gdiBold| is true in that case, we need to
// increase the weight a little more for similar results with GDI+.
// TODO: Is +100 enough?
dwriteFontWeight = (DWRITE_FONT_WEIGHT)(dwriteFontWeight + 100);
}
}
dwriteFontStyle = dwriteFont->GetStyle();
if (gdiItalic && dwriteFontStyle == DWRITE_FONT_STYLE_NORMAL)
{
dwriteFontStyle = DWRITE_FONT_STYLE_ITALIC;
}
dwriteFontStretch = dwriteFont->GetStretch();
GetPropertiesFromDWriteFont(
dwriteFont, gdiBold, gdiItalic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch);
hr = S_OK;
}
@ -66,6 +43,37 @@ HRESULT GetDWritePropertiesFromGDIProperties(
return hr;
}
void GetPropertiesFromDWriteFont(
IDWriteFont* dwriteFont, const bool bold, const bool italic,
DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
DWRITE_FONT_STRETCH* dwriteFontStretch)
{
*dwriteFontWeight = dwriteFont->GetWeight();
if (bold)
{
if (*dwriteFontWeight == DWRITE_FONT_WEIGHT_NORMAL)
{
*dwriteFontWeight = DWRITE_FONT_WEIGHT_BOLD;
}
else if (*dwriteFontWeight < DWRITE_FONT_WEIGHT_ULTRA_BOLD)
{
// If 'gdiFamilyName' was e.g. 'Segoe UI Light', |dwFontWeight| wil be equal to
// DWRITE_FONT_WEIGHT_LIGHT. If |gdiBold| is true in that case, we need to
// increase the weight a little more for similar results with GDI+.
// TODO: Is +100 enough?
*dwriteFontWeight = (DWRITE_FONT_WEIGHT)(*dwriteFontWeight + 100);
}
}
*dwriteFontStyle = dwriteFont->GetStyle();
if (italic && *dwriteFontStyle == DWRITE_FONT_STYLE_NORMAL)
{
*dwriteFontStyle = DWRITE_FONT_STYLE_ITALIC;
}
*dwriteFontStretch = dwriteFont->GetStretch();
}
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName)
{
IDWriteGdiInterop* dwGdiInterop;
@ -145,5 +153,72 @@ bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* family
return result;
}
HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize)
{
bool result = false;
IDWriteLocalizedStrings* strings;
BOOL stringsExist;
HRESULT hr = font->GetInformationalStrings(
DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &stringsExist);
if (SUCCEEDED(hr) && stringsExist)
{
hr = strings->GetString(0, buffer, bufferSize);
if (SUCCEEDED(hr))
{
result = true;
}
}
return result;
}
IDWriteFont* FindDWriteFontInFontFamilyByGDIFamilyName(
IDWriteFontFamily* fontFamily, const WCHAR* gdiFamilyName)
{
const UINT32 fontFamilyFontCount = fontFamily->GetFontCount();
for (UINT32 j = 0; j < fontFamilyFontCount; ++j)
{
IDWriteFont* font;
HRESULT hr = fontFamily->GetFont(j, &font);
if (SUCCEEDED(hr))
{
WCHAR buffer[LF_FACESIZE];
if (GetGDIFamilyNameFromDWriteFont(font, buffer, _countof(buffer)) &&
_wcsicmp(gdiFamilyName, buffer) == 0)
{
return font;
}
font->Release();
}
}
return nullptr;
}
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName)
{
const UINT32 fontCollectionFamilyCount = fontCollection->GetFontFamilyCount();
for (UINT32 i = 0; i < fontCollectionFamilyCount; ++i)
{
IDWriteFontFamily* fontFamily;
HRESULT hr = fontCollection->GetFontFamily(i, &fontFamily);
if (SUCCEEDED(hr))
{
IDWriteFont* font = FindDWriteFontInFontFamilyByGDIFamilyName(
fontFamily, gdiFamilyName);
fontFamily->Release();
if (font)
{
return font;
}
}
}
return nullptr;
}
} // namespace Util
} // namespace Gfx

View File

@ -31,6 +31,11 @@ HRESULT GetDWritePropertiesFromGDIProperties(
DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize);
void GetPropertiesFromDWriteFont(
IDWriteFont* dwriteFont, const bool bold, const bool italic,
DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
DWRITE_FONT_STRETCH* dwriteFontStretch);
// Creates a IDWriteFont using the GDI family name instead of the DirectWrite family name. For
// example, 'Segoe UI' and 'Segoe UI Semibold' are separate family names with GDI whereas
// DirectWrite uses the family name 'Segoe UI' for both and differentiates them by the font
@ -44,6 +49,9 @@ HRESULT GetFamilyNameFromDWriteFontFamily(
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName);
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName);
} // namespace Util
} // namespace Gfx