AddFontResourceA and debugging

Started by
6 comments, last by cozzie 4 years, 8 months ago

Hi all,

I've been struggling with using AddFontResource(A) to add a font to my application session.
When I executet the code without breakpoints, the font doesn't show up, but when I add a breakpoint after the call to AddFontResourceA, it does work as expected.

I checked the return code in both working/ not working cases, always 1, which is as expected.
Also tried to call SendMessage like MSDN describes (HWND_BROADCAST, WM_FONTCHANGE), but without luck.

The only thing I can think of, is that the breakpoint makes the window loose focus and continuing 'refreshes' things.
But so far I havent been able to reproduce this (with sending WM_ACTIVATE for example).

Any thoughts on what might be happening here?


bool DX11FontRenderer::AddCurrFontToSystem()
{
	if(!mCurrFont->IsLoaded())
	{
		std::string fullFileName = std::string(IO_FOLDER_FONTS) + mCurrFont->GetFilename().c_str();
		
		int result = AddFontResourceA(fullFileName.c_str());
		if(result == 0)
		{
			CLOG(ERROR, "DX11RENDERER") << error_loadfont.c_str() << mCurrFont->GetFilename();
			return false;
		}
		CLOG(DEBUG, "DX11RENDERER") << debug_font_added.c_str() << mCurrFont->GetFontName();

		CLOG(DEBUG, "DX11RENDERER") << "FONTS ADDED, RESULT: " << result;
		mCurrFont->SetLoaded(true);
		mAddedSystemFonts.push_back(fullFileName);
	}
	return true;
}

 

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

It sounds like some kind of update and/or caching problem. Your code continues running but the message hasn't been processed by your window/application so far and the system table for that window hasn't updated yet. With the breakpoint, the message seems to be put on the queue for your process to be processed right now

Thanks @Shaarigan. Do you know of there’s a way to validate if it’s done? Like a check if the font exist in the system font table. If that’s possible I could wait till that returns positive.

On the other hand, it might not be a timing issue, because i tried adding a 10 sec sleep after adding the font, without expected result. So it feels like something with a message not arriving at the hwnd or something

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Update; did some more testing, when I add a sleep directly after the addfontresourcea call, the results are as expected. So I guess I need to find a way to validate if adding the font to the system fonts finished. Which is not the case when the function returns 1 in this case (1 font added).

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

It seems that you have to send a message and need to listen to the message to be sure processing is done. An alternative would be to use the AddFontResourceEx function that seems to work more stable

I tried to call the SendMessage after adding the font, but that didn’t resolve it. Because probably in the background the font still isn’t “Really” added to the system fonts.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

OK, for now I resolved it.

Created a function that checks if a certain font exists within the system fonts (using DWrite), so only usable for the DX11 fontrenderer. Added the function on base class, so I can create a different implementation for non-windows platforms.

It seems that using AddFontResourceEx(A), doesn't add a font to the system fonts in windows (Tried that because read online that it would be faster, might be; but there's no way to validate if it's done).

So for now I just run a while loop until the added found is found in the systemfonts, and then proceed. Will make a cleaner implementation with a timeout, to prevent crashing ?


		bool fontAdded = false;

		while(!fontAdded)
		{
			std::vector<std::wstring> fontNames;

			IDWriteFontCollection* pFontCollection = NULL;
			if(FAILED(mDirectWriteFactory->GetSystemFontCollection(&pFontCollection)))
			{
				MessageBox(nullptr, L"Error", L"Bla", MB_OK);
			}

			UINT32 familyCount = 0;
			familyCount = pFontCollection->GetFontFamilyCount();

			for (UINT32 i = 0; i < familyCount; ++i)
			{
				IDWriteFontFamily* pFontFamily = NULL;
				pFontCollection->GetFontFamily(i, &pFontFamily);

				IDWriteLocalizedStrings* pFamilyNames = NULL;
				pFontFamily->GetFamilyNames(&pFamilyNames);

				wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
				int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH);

				BOOL exists = false;
				UINT32 index = 0;

				if(defaultLocaleSuccess)
				{
					pFamilyNames->FindLocaleName(localeName, &index, &exists);
				}

				if(!exists)
				{
					pFamilyNames->FindLocaleName(L"en-us", &index, &exists);
				}

				if(!exists)
					index = 0;
				else
				{
					UINT32 length = 0;
					pFamilyNames->GetStringLength(index, &length);
					wchar_t* name = new (std::nothrow) wchar_t[length+1];
					pFamilyNames->GetString(index, name, length+1);

					fontNames.push_back(name);
				}
			}

			// compare font
			for(size_t i=0;i<fontNames.size();++i)
			{
				std::wstring fontName = std::wstring(mCurrFont->GetFontName().begin(), mCurrFont->GetFontName().end());

				if(fontName.compare(fontNames.at(i)) == 0)
				{
					CLOG(DEBUG, "RENDERER") << "FONT FOUND AFTER ADDING!";
					fontAdded = true;
				}
			}
			if(!fontAdded) CLOG(DEBUG, "RENDERER") << "FONT NOT FOUND YET!";
		}

Disclaimer: this is the test implementation, not properly/ cleaned up yet :)

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

This topic is closed to new replies.

Advertisement