Jump to content
  • Advertisement
Sign in to follow this  
cozzie

C++ AddFontResourceA and debugging

Recommended Posts

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;
}

 

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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

Edited by cozzie

Share this post


Link to post
Share on other sites

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).

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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 :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!