Cast LOGFONT to DWRITE_FONT_WEIGHT

I have font class which is a wrapper around API's that create HFONT.

Relevant excerpt from class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Font
{
    // ...
    HFONT mhFont;
};

bool Font::GetLogFont(LOGFONT& LogFont) const noexcept
{
	if (GetObjectW(mhFont, sizeof(LOGFONT), &LogFont) != 0)
		return true;

	return false;
}

DWRITE_FONT_WEIGHT Font::GetDWriteCompatibleWeight() const noexcept
{
	LOGFONT LogFont{ };
        if (GetLogFont(LogFont))
	{
	        return static_cast<DWRITE_FONT_WEIGHT>(LogFont.lfWeight);
	}

        // If failed return normal weight
        return DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL;
}


DWRITE_FONT_WEIGHT is an enum defined as shown on the link below
https://learn.microsoft.com/en-us/windows/win32/api/dwrite/ne-dwrite-dwrite_font_weight

LOGFONG lfWeight consists of same range of values, 0-1000, however not every value is defined for DWRITE_FONT_WEIGHT.
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createfontw

Therefore my GetDWriteCompatibleWeight function may return a value that in fact does not exist in the DWRITE_FONT_WEIGHT enum.

However it works!
I've tried with font weight 350 which isn't defined in the enum, the return value was 350 and a function that expect the enum succeeded:

Sample code which call the converter method
1
2
3
4
5
6
7
8
9
10
11
12
13
Font mFont = /* ... */

hr = pWriteFactory->CreateTextFormat(
	DEFAULT_FONT_TYPEFACE,	// The default font constant
	NULL,
	// This succeeds with value of 350 or any other that is not in DWRITE_FONT_WEIGHT 
	mFont.GetDWriteCompatibleWeight(),

	DWRITE_FONT_STYLE::DWRITE_FONT_STYLE_NORMAL,
	DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_NORMAL,
	static_cast<float>(DialogBase.cy),
	L"en-us",
	&mpCaptionFormat);


My question is, why does it succeed and would it be better method to use if else to convert HFONT.lfWeight to closest match instead of casting the value directly?

For example, is it better to:

1
2
3
4
5
6
if (lfWeight <= 100)
      return DWRITE_FONT_WEIGHT_THIN;
else if (lfWeight <= 200)
      return DWRITE_FONT_WEIGHT_EXTRA_LIGHT;

// etc.. a bunch of if else statements follow for each enum 


Is there a better method?
Last edited on
In the meantime I've found a better method with IDWriteGdiInterop::CreateFontFromLOGFONT:
https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritegdiinterop-createfontfromlogfont

Once the IDWriteFont is created call IDWriteFont::GetWeight
https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritefont-getweight
Registered users can post here. Sign in or register to post.