rainmeter-studio/Common/Gfx/Util/DWriteHelpers.cpp

243 lines
6.8 KiB
C++
Raw Normal View History

2013-04-12 15:06:51 +00:00
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "DWriteHelpers.h"
2013-05-05 14:34:22 +00:00
#include <wrl/client.h>
#include <cmath>
2013-04-12 15:06:51 +00:00
namespace Gfx {
namespace Util {
DWRITE_TEXT_METRICS GetAdjustedDWriteTextLayoutMetrics(
IDWriteTextLayout* textLayout, bool gdiEmulation, bool containsNewLine)
{
DWRITE_TEXT_METRICS metrics;
textLayout->GetMetrics(&metrics);
if (gdiEmulation)
{
float size = 0.0f;
textLayout->GetFontSize(0, &size);
2013-08-02 20:35:08 +00:00
metrics.width = floor(metrics.width + ((size / 3.0f) * 2.0f) + ((size * 3.0f / 4.0f) / 17.5f) + 0.255f);
if (containsNewLine)
{
metrics.width -= ((size * 3.0f / 4.0f) / 4.0f);
}
metrics.height = floor(metrics.height + (size / 9.25f) + 0.3f);
}
return metrics;
}
2013-04-12 16:18:56 +00:00
HRESULT GetDWritePropertiesFromGDIProperties(
2013-04-12 15:06:51 +00:00
IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize)
{
2013-04-12 16:18:56 +00:00
HRESULT hr = E_FAIL;
2013-04-12 15:06:51 +00:00
IDWriteFont* dwriteFont = CreateDWriteFontFromGDIFamilyName(factory, gdiFamilyName);
if (dwriteFont)
{
2013-04-13 15:58:24 +00:00
hr = GetFamilyNameFromDWriteFont(dwriteFont, dwriteFamilyName, dwriteFamilyNameSize);
if (SUCCEEDED(hr))
2013-04-12 15:06:51 +00:00
{
2013-04-12 16:41:47 +00:00
GetPropertiesFromDWriteFont(
dwriteFont, gdiBold, gdiItalic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch);
2013-04-12 15:06:51 +00:00
}
dwriteFont->Release();
}
2013-04-12 16:18:56 +00:00
return hr;
2013-04-12 15:06:51 +00:00
}
2013-04-12 16:41:47 +00:00
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();
}
2013-04-12 15:06:51 +00:00
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName)
{
2013-05-05 14:34:22 +00:00
Microsoft::WRL::ComPtr<IDWriteGdiInterop> dwGdiInterop;
HRESULT hr = factory->GetGdiInterop(dwGdiInterop.GetAddressOf());
2013-04-12 15:06:51 +00:00
if (SUCCEEDED(hr))
{
LOGFONT lf = {};
wcscpy_s(lf.lfFaceName, gdiFamilyName);
lf.lfHeight = -12;
lf.lfWeight = FW_DONTCARE;
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;
}
}
return nullptr;
}
2013-04-12 16:18:56 +00:00
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize)
2013-04-12 15:06:51 +00:00
{
IDWriteFontFamily* dwriteFontFamily;
HRESULT hr = font->GetFontFamily(&dwriteFontFamily);
if (SUCCEEDED(hr))
{
2013-04-13 15:58:24 +00:00
hr = GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize);
2013-04-12 15:06:51 +00:00
dwriteFontFamily->Release();
}
2013-04-12 16:18:56 +00:00
return hr;
2013-04-12 15:06:51 +00:00
}
2013-04-12 16:18:56 +00:00
HRESULT GetFamilyNameFromDWriteFontFamily(
2013-04-12 15:06:51 +00:00
IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize)
{
IDWriteLocalizedStrings* dwFamilyNames;
HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames);
if (SUCCEEDED(hr))
{
// TODO: Determine the best index?
hr = dwFamilyNames->GetString(0, buffer, bufferSize);
dwFamilyNames->Release();
}
2013-04-12 16:18:56 +00:00
return hr;
2013-04-12 15:06:51 +00:00
}
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName)
{
bool result = false;
IDWriteFontCollection* systemFontCollection;
HRESULT hr = factory->GetSystemFontCollection(&systemFontCollection);
if (SUCCEEDED(hr))
{
UINT32 familyNameIndex;
BOOL familyNameFound;
HRESULT hr = systemFontCollection->FindFamilyName(
familyName, &familyNameIndex, &familyNameFound);
if (SUCCEEDED(hr) && familyNameFound)
2013-04-12 15:06:51 +00:00
{
result = true;
}
systemFontCollection->Release();
}
return result;
}
2013-04-12 16:41:47 +00:00
HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize)
{
2013-05-05 14:34:22 +00:00
Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> strings;
2013-04-12 16:41:47 +00:00
BOOL stringsExist;
2013-05-05 14:34:22 +00:00
font->GetInformationalStrings(
DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, strings.GetAddressOf(), &stringsExist);
if (strings && stringsExist)
2013-04-12 16:41:47 +00:00
{
2013-05-05 14:34:22 +00:00
return strings->GetString(0, buffer, bufferSize);
2013-04-12 16:41:47 +00:00
}
2013-05-05 14:34:22 +00:00
return E_FAIL;
2013-04-12 16:41:47 +00:00
}
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];
2013-04-13 15:58:24 +00:00
hr = GetGDIFamilyNameFromDWriteFont(font, buffer, _countof(buffer));
if (SUCCEEDED(hr) && _wcsicmp(gdiFamilyName, buffer) == 0)
2013-04-12 16:41:47 +00:00
{
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;
}
2013-04-12 15:06:51 +00:00
} // namespace Util
} // namespace Gfx