2025-11-28 00:35:46 +09:00

354 lines
12 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//
//----------------------------------------------------------------------------
#include "ChooseFont.h"
#include "FontEnumeration.h"
/******************************************************************
* *
* GetLocalizedName *
* *
* Select a name from a list of localized names and use a simple *
* fallback scheme if the desired locale isn't supported. *
* *
******************************************************************/
HRESULT GetLocalizedName(IDWriteLocalizedStrings* names, const WCHAR* locale, OUT std::wstring& familyName)
{
HRESULT hr = S_OK;
UINT32 nameIndex;
BOOL nameExists;
UINT32 nameLength = 0;
try
{
hr = names->FindLocaleName(locale, &nameIndex, &nameExists);
// If there is no name with the desired locale fallback to US English.
if (SUCCEEDED(hr))
{
if (!nameExists)
hr = names->FindLocaleName(L"en-us", &nameIndex, &nameExists);
// If the name still doesn't exist just take the first one.
if (!nameExists)
nameIndex = 0;
}
if (SUCCEEDED(hr))
{
hr = names->GetStringLength(nameIndex, &nameLength);
}
if (SUCCEEDED(hr))
{
familyName.resize(nameLength + 1);
hr = names->GetString(nameIndex, &familyName[0], (UINT32) familyName.size());
}
}
catch (...)
{
hr = ExceptionToHResult();
}
return hr;
}
/******************************************************************
* *
* GetFontFamilyName *
* *
* Get the family name (e.g. "Arial" in "Arial Bold") for a font *
* family. *
* *
******************************************************************/
HRESULT GetFontFamilyName(IDWriteFontFamily* fontFamily, const WCHAR* locale, OUT std::wstring& familyName)
{
HRESULT hr = S_OK;
IDWriteLocalizedStrings* familyNames = NULL;
hr = fontFamily->GetFamilyNames(&familyNames);
if (SUCCEEDED(hr))
{
hr = GetLocalizedName(familyNames, locale, familyName);
}
SafeRelease(&familyNames);
return hr;
}
/******************************************************************
* *
* GetFontFaceName *
* *
* Get the face name (e.g. "Bold" in "Arial Bold") for a font. *
* *
******************************************************************/
HRESULT GetFontFaceName(IDWriteFont* font, const WCHAR* locale, OUT std::wstring& faceName)
{
HRESULT hr = S_OK;
IDWriteLocalizedStrings* faceNames = NULL;
hr = font->GetFaceNames(&faceNames);
if (SUCCEEDED(hr))
{
hr = GetLocalizedName(faceNames, locale, faceName);
}
SafeRelease(&faceNames);
return hr;
}
/******************************************************************
* *
* GetFontFamily *
* *
* Get the font family object given a family name. *
* *
******************************************************************/
HRESULT GetFontFamily(IDWriteFontCollection* fontCollection, const WCHAR* fontFamilyName, OUT IDWriteFontFamily** fontFamily)
{
HRESULT hr;
UINT32 familyIndex;
BOOL familyExists;
hr = fontCollection->FindFamilyName(fontFamilyName, &familyIndex, &familyExists);
if (!familyExists)
return DWRITE_E_NOFONT;
if (SUCCEEDED(hr))
{
hr = fontCollection->GetFontFamily(familyIndex, fontFamily);
}
return hr;
}
/******************************************************************
* *
* GetFonts *
* *
* Return all of the fonts (e.g. Arial Regular, Arial Bold, *
* Arial Narrow, etc.) in a font family (e.g. Arial) *
* *
******************************************************************/
HRESULT GetFonts(IDWriteFontCollection* fontCollection, const WCHAR* fontFamilyName, IN OUT std::vector<IDWriteFont*>& fonts)
{
HRESULT hr = S_OK;
IDWriteFontFamily* fontFamily = NULL;
IDWriteFont* font = NULL;
hr = GetFontFamily(fontCollection, fontFamilyName, &fontFamily);
if (SUCCEEDED(hr))
{
UINT32 fontCount = fontFamily->GetFontCount();
// Read font variant in the family.
try
{
for (UINT32 i = 0; i != fontCount; ++i)
{
hr = fontFamily->GetFont(i, &font);
if (FAILED(hr))
break;
fonts.push_back(font);
SafeDetach(&font);
}
}
catch (...)
{
hr = ExceptionToHResult();
}
}
SafeRelease(&font);
SafeRelease(&fontFamily);
return hr;
}
/******************************************************************
* *
* GetFontFaceInfo *
* *
* Get information about the font faces supported by a font family *
* *
******************************************************************/
HRESULT GetFontFaceInfo(const std::vector<IDWriteFont*>& fonts, const WCHAR* locale, IN OUT std::vector<FontFaceInfo>& info)
{
HRESULT hr = S_OK;
// If there are no fonts in this family just returned standard harcoded choices
try
{
if (fonts.empty())
{
info.push_back(FontFaceInfo(L"Regular", DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL));
info.push_back(FontFaceInfo(L"Bold", DWRITE_FONT_WEIGHT_BOLD, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL));
info.push_back(FontFaceInfo(L"Italic", DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_ITALIC, DWRITE_FONT_STRETCH_NORMAL));
info.push_back(FontFaceInfo(L"Bold Italic", DWRITE_FONT_WEIGHT_BOLD, DWRITE_FONT_STYLE_ITALIC, DWRITE_FONT_STRETCH_NORMAL));
return S_OK;
}
for (size_t i = 0; i != fonts.size(); ++i)
{
std::wstring faceName;
hr = GetFontFaceName(fonts[i], locale, faceName);
if (FAILED(hr))
break;
info.push_back(FontFaceInfo(
faceName.c_str(),
fonts[i]->GetWeight(),
fonts[i]->GetStyle(),
fonts[i]->GetStretch()));
}
}
catch (...)
{
hr = ExceptionToHResult();
}
return hr;
}
/******************************************************************
* *
* GetFontFamilies *
* *
* Get all the font families (e.g. Arial, Cambria, Tahoma, etc.) *
* in a font collection. *
* *
******************************************************************/
HRESULT GetFontFamilyNames(IDWriteFontCollection* fontCollection, const WCHAR* localeName, IN OUT std::vector< std::wstring >& fontFamilyNames)
{
HRESULT hr = S_OK;
std::wstring familyName;
UINT32 familyCount = fontCollection->GetFontFamilyCount();
try
{
for (UINT32 i = 0; i != familyCount; ++i)
{
IDWriteFontFamily* fontFamily = NULL;
hr = fontCollection->GetFontFamily(i, &fontFamily);
if (SUCCEEDED(hr))
{
hr = GetFontFamilyName(fontFamily, localeName, familyName);
}
SafeRelease(&fontFamily);
if (FAILED(hr))
break;
fontFamilyNames.push_back(familyName);
}
}
catch (...)
{
hr = ExceptionToHResult();
}
return hr;
}
/******************************************************************
* *
* GetFontFamilyNameFromFormat *
* *
* Return the font family name from an IDWriteTextFormat object. *
* *
******************************************************************/
HRESULT GetFontFamilyNameFromFormat(IDWriteTextFormat* textFormat, OUT std::wstring& fontFamilyName)
{
HRESULT hr = S_OK;
UINT32 familyNameLength = textFormat->GetFontFamilyNameLength() + 1;
try
{
fontFamilyName.resize(familyNameLength);
hr = textFormat->GetFontFamilyName(&fontFamilyName[0], familyNameLength);
}
catch (...)
{
hr = ExceptionToHResult();
}
return hr;
}
/******************************************************************
* *
* GetBestFontAttributes *
* *
* Find the font that best matches the desired font attributes *
* and return the actual attributes. *
* *
******************************************************************/
ULONG GetBestFontAttributes(IDWriteFontCollection* fontCollection, const WCHAR* fontFamilyName, const FontFaceInfo& desiredAttributes)
{
DWRITE_FONT_WEIGHT fontWeight = desiredAttributes.fontWeight;
DWRITE_FONT_STYLE fontStyle = desiredAttributes.fontStyle;
DWRITE_FONT_STRETCH fontStretch = desiredAttributes.fontStretch;
IDWriteFontFamily* fontFamily = NULL;
IDWriteFont* font = NULL;
if (SUCCEEDED(GetFontFamily(fontCollection, fontFamilyName, &fontFamily)))
{
if (SUCCEEDED(fontFamily->GetFirstMatchingFont(fontWeight, fontStretch, fontStyle, &font)))
{
fontWeight = font->GetWeight();
fontStyle = font->GetStyle();
fontStretch = font->GetStretch();
}
}
SafeRelease(&font);
SafeRelease(&fontFamily);
FontFaceInfo fontFaceInfo(L"", fontWeight, fontStyle, fontStretch);
return fontFaceInfo.PackedFontAttributes();
}