Hello forum people.
I'm trying to implement text rendering for my game engine and I've been running into a particular problem.
I have a resource manager whose job is to load and store the resources needed for the game. When a new map loads, the manager parses the map and loads any fonts needed. The part of the function that does the font loading is this (using PhysicsFS):
[spoiler]
// Consider this the "loading" function.
BPhysFSFilePtr File(Path);
PHYSFS_sint64 FontFileSize = MPhysFSManager::Instance().fileLength(File);
std::vector<PHYSFS_sint64> FontData(FontFileSize);
MPhysFSManager::Instance().read<PHYSFS_sint64>(File, FontData, 1, FontFileSize);
RWopsPtr RWops(SDL_RWFromMem(FontData.data(), FontFileSize), SDL_FreeRW);
Fonts.emplace(ID, BTTFFont(std::unique_ptr<TTF_Font, decltype(&TTF_CloseFont)>(TTF_OpenFontRW(RWops.get(), 0, Size), TTF_CloseFont), ID, Size));
[/spoiler]
BTTFFont is a wrapper class that overloads operator TTF_Font* and RWopsPtr is an alias for std::unique_ptr<SDL_RWops, decltype(&SDL_FreeRW)>.
The loaded fonts are then used to create various OpenGL textures using different texts. The function that does that is this one:
[spoiler]
// Consider this the "texturing" function.
using SurfacePtr = std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)>;
auto& Font = MResourceManager::Instance().RequestFont(FontID);
const auto& FontData = MResourceManager::Instance().RequestFontData(ID);
SurfacePtr Surface(nullptr, nullptr);
if (FontData.Rendering == EFontRendering::Solid)
{
Surface = SurfacePtr(TTF_RenderUTF8_Solid(Font, Text.c_str(), FontData.Color), SDL_FreeSurface);
}
else if (FontData.Rendering == EFontRendering::Blended)
{
Surface = SurfacePtr(TTF_RenderUTF8_Blended_Wrapped(Font, Text.c_str(), FontData.Color, WrapLength), SDL_FreeSurface);
}
MResourceManager::Instance().CreateTextureFromSurface(ID, Surface.get());
[/spoiler]
The problem is that I'm getting an access violation exception as soon as either TTF_Render function is called. TTF_Init has been successfully called.
What I've checked for:
- Text.c_str() is null, it's not
- Font is null, it's not
- Call TTF_GetStyle and TTF_SetStyle using Font, they both work just fine
- Call TTF_SizeUTF8 using Font and Text.c_str(), access violation
- Call TTF_SizeUTF8 using Font and a hardcoded const char* passed directly as argument, access violation
- Call TTF_SizeUTF8 using Font and a const char* variable with some text, access violation
I then added these lines to the font loading function:
using SurfacePtr = std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)>;
auto Surface = SurfacePtr(TTF_RenderUTF8_Blended(Fonts.at(ID), "Use the Arrow keys to move", SDL_Color()), SDL_FreeSurface);
This worked for the first call of the texturing function but throws an access violation on the second call (I currently only have 2 text boxes that call this). If I add this line
Surface = SurfacePtr(TTF_RenderUTF8_Blended(Fonts.at(ID), "Press and hold the Space bar to jump", SDL_Color()), SDL_FreeSurface);
then the game plays as it should and texts are rendered fine.
If, however, I change the text in the loading function, then it may throw an access violation. By "may" I mean that if I completely change it, it throws. If I write "Use the Arrow keyssssssss to move" instead of "Use the Arrow keys to move", it works fine. I don't know how much I need to change the text in order to cause an exception. I've also noticed that if I use Solid instead of Blended rendering in the loading function, it causes an access violation as well (the particular text boxes I have use Blended rendering).
Any ideas on what the problem might be?
Thank you.