diff --git a/Common/Gfx/Util/DWriteHelpers.cpp b/Common/Gfx/Util/DWriteHelpers.cpp new file mode 100644 index 00000000..96e3d642 --- /dev/null +++ b/Common/Gfx/Util/DWriteHelpers.cpp @@ -0,0 +1,153 @@ +/* + 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" + +namespace Gfx { +namespace Util { + +bool GetDWritePropertiesFromGDIProperties( + 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) +{ + bool result = false; + IDWriteFont* dwriteFont = CreateDWriteFontFromGDIFamilyName(factory, gdiFamilyName); + if (dwriteFont) + { + 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(); + + result = true; + } + + dwriteFont->Release(); + } + + return result; +} + +IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName) +{ + IDWriteGdiInterop* dwGdiInterop; + HRESULT hr = factory->GetGdiInterop(&dwGdiInterop); + 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; + } + + dwGdiInterop->Release(); + } + + return nullptr; +} + +bool GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize) +{ + IDWriteFontFamily* dwriteFontFamily; + HRESULT hr = font->GetFontFamily(&dwriteFontFamily); + if (SUCCEEDED(hr)) + { + GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize); + dwriteFontFamily->Release(); + return true; + } + + return false; +} + +bool GetFamilyNameFromDWriteFontFamily( + IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize) +{ + bool result = false; + IDWriteLocalizedStrings* dwFamilyNames; + HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames); + if (SUCCEEDED(hr)) + { + // TODO: Determine the best index? + hr = dwFamilyNames->GetString(0, buffer, bufferSize); + result = SUCCEEDED(hr); + dwFamilyNames->Release(); + } + + return result; +} + +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) + { + result = true; + } + + systemFontCollection->Release(); + } + + return result; +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/DWriteHelpers.h b/Common/Gfx/Util/DWriteHelpers.h new file mode 100644 index 00000000..7c21d827 --- /dev/null +++ b/Common/Gfx/Util/DWriteHelpers.h @@ -0,0 +1,50 @@ +/* + 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. +*/ + +#ifndef RM_GFX_UTIL_DWRITEHELPERS_H_ +#define RM_GFX_UTIL_DWRITEHELPERS_H_ + +#include + +namespace Gfx { +namespace Util { + +// Maps the GDI family name and italic/bold flags to the DirectWrite family name, weight, style, +// and stretch. +bool GetDWritePropertiesFromGDIProperties( + 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); + +// 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. +IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* fontFamily); + +bool GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize); + +bool GetFamilyNameFromDWriteFontFamily( + IDWriteFontFamily* fontFamily, WCHAR* buffer, UINT bufferSize); + +bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName); + +} // namespace Util +} // namespace Gfx + +#endif \ No newline at end of file