Gfx: Make D2D font family name handling more consistent with GDI+

This commit is contained in:
Birunthan Mohanathas 2013-04-07 14:30:50 +03:00
parent e1b39f62b1
commit 2f8f67e2cf
4 changed files with 108 additions and 9 deletions

View File

@ -55,6 +55,7 @@ namespace Gfx {
UINT CanvasD2D::c_Instances = 0; UINT CanvasD2D::c_Instances = 0;
ID2D1Factory* CanvasD2D::c_D2D = nullptr; ID2D1Factory* CanvasD2D::c_D2D = nullptr;
IDWriteFactory* CanvasD2D::c_DW = nullptr; IDWriteFactory* CanvasD2D::c_DW = nullptr;
IDWriteGdiInterop* CanvasD2D::c_DWGDIInterop = nullptr;
IWICImagingFactory* CanvasD2D::c_WIC = nullptr; IWICImagingFactory* CanvasD2D::c_WIC = nullptr;
CanvasD2D::CanvasD2D() : Canvas(), CanvasD2D::CanvasD2D() : Canvas(),
@ -102,6 +103,9 @@ bool CanvasD2D::Initialize()
__uuidof(IDWriteFactory), __uuidof(IDWriteFactory),
(IUnknown**)&c_DW); (IUnknown**)&c_DW);
if (FAILED(hr)) return false; if (FAILED(hr)) return false;
hr = c_DW->GetGdiInterop(&c_DWGDIInterop);
if (FAILED(hr)) return false;
} }
return true; return true;
@ -114,6 +118,7 @@ void CanvasD2D::Finalize()
{ {
SafeRelease(&c_D2D); SafeRelease(&c_D2D);
SafeRelease(&c_WIC); SafeRelease(&c_WIC);
SafeRelease(&c_DWGDIInterop);
SafeRelease(&c_DW); SafeRelease(&c_DW);
} }
} }

View File

@ -98,6 +98,7 @@ private:
static UINT c_Instances; static UINT c_Instances;
static ID2D1Factory* c_D2D; static ID2D1Factory* c_D2D;
static IDWriteFactory* c_DW; static IDWriteFactory* c_DW;
static IDWriteGdiInterop* c_DWGDIInterop;
static IWICImagingFactory* c_WIC; static IWICImagingFactory* c_WIC;
}; };

View File

@ -92,7 +92,37 @@ void TextFormatD2D::SetProperties(const WCHAR* fontFamily, int size, bool bold,
{ {
Dispose(); Dispose();
HRESULT hr = CanvasD2D::c_DW->CreateTextFormat( HRESULT hr = E_FAIL;
// |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.
IDWriteFont* dwFont = CreateDWFontFromGDIFamilyName(fontFamily, bold, italic);
if (dwFont)
{
WCHAR buffer[LF_FACESIZE];
if (GetDWFontFamilyName(dwFont, buffer, _countof(buffer)))
{
// TODO: If |fontFamily| is e.g. 'Segoe UI Semibold' and |bold| is true, we might want
// to make the weight heaver to match GDI+.
hr = CanvasD2D::c_DW->CreateTextFormat(
buffer,
nullptr,
dwFont->GetWeight(),
dwFont->GetStyle(),
DWRITE_FONT_STRETCH_NORMAL,
size * (4.0f / 3.0f),
L"",
&m_TextFormat);
}
dwFont->Release();
}
if (FAILED(hr))
{
// Fallback in case above fails.
hr = CanvasD2D::c_DW->CreateTextFormat(
fontFamily, fontFamily,
nullptr, nullptr,
bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR, bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR,
@ -101,6 +131,7 @@ void TextFormatD2D::SetProperties(const WCHAR* fontFamily, int size, bool bold,
size * (4.0f / 3.0f), size * (4.0f / 3.0f),
L"", L"",
&m_TextFormat); &m_TextFormat);
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -160,4 +191,58 @@ void TextFormatD2D::SetVerticalAlignment(VerticalAlignment alignment)
} }
} }
IDWriteFont* TextFormatD2D::CreateDWFontFromGDIFamilyName(const WCHAR* fontFamily, bool bold, bool italic)
{
IDWriteGdiInterop* dwGdiInterop;
HRESULT hr = CanvasD2D::c_DW->GetGdiInterop(&dwGdiInterop);
if (SUCCEEDED(hr))
{
LOGFONT lf = {};
wcscpy_s(lf.lfFaceName, fontFamily);
lf.lfWidth = 12;
lf.lfHeight = 12;
lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
lf.lfItalic = (BYTE)italic;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = ANTIALIASED_QUALITY;
lf.lfPitchAndFamily = VARIABLE_PITCH;
IDWriteFont* dwFont;
hr = dwGdiInterop->CreateFontFromLOGFONT(&lf, &dwFont);
if (SUCCEEDED(hr))
{
return dwFont;
}
dwGdiInterop->Release();
}
return nullptr;
}
bool TextFormatD2D::GetDWFontFamilyName(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize)
{
bool result = false;
IDWriteFontFamily* dwFontFamily;
HRESULT hr = font->GetFontFamily(&dwFontFamily);
if (SUCCEEDED(hr))
{
IDWriteLocalizedStrings* dwFamilyNames;
hr = dwFontFamily->GetFamilyNames(&dwFamilyNames);
if (SUCCEEDED(hr))
{
// TODO: Determine the best index?
hr = dwFamilyNames->GetString(0, buffer, bufferSize);
result = SUCCEEDED(hr);
dwFamilyNames->Release();
}
dwFontFamily->Release();
}
return result;
}
} // namespace Gfx } // namespace Gfx

View File

@ -50,6 +50,14 @@ private:
// changes. // changes.
void CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH); void CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH);
// 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
// style.
static IDWriteFont* CreateDWFontFromGDIFamilyName(const WCHAR* fontFamily, bool bold, bool italic);
static bool GetDWFontFamilyName(IDWriteFont* font, WCHAR* buffer, UINT bufferSize);
IDWriteTextFormat* m_TextFormat; IDWriteTextFormat* m_TextFormat;
IDWriteTextLayout* m_TextLayout; IDWriteTextLayout* m_TextLayout;
IDWriteInlineObject* m_InlineEllipsis; IDWriteInlineObject* m_InlineEllipsis;