4
votes

I am trying to load a font from my resources. This is the call I use, which currently returns NULL and therefore fails:

HRSRC rsrcData = FindResource(NULL, MAKEINTRESOURCE(IDF_ROBOTBLACK), L"FONT");

I added the font resource to my Resource.rc file, which now lists the following:

/////////////////////////////////////////////////////////////////////////////
//
// Font
//

IDF_ROBOTBLACK          FONT                    "Resources\\Fonts\\Roboto\\Roboto-Black.ttf"

Additionally, this is what my Resource.h looks like:

#define IDF_ROBOTBLACK                  108

As far as I can tell, this should be all there is to the whole process.

I already successfully managed to load another resource format, "PNG", which was added as a new, custom resource type as well, following the same procedure while only replacing "FONT" with "PNG" where it is due.

However, compared to my "PNG" loading approach, the "FONT" is never found. FindResource returns NULL, no matter what happens.

The error code returend by GetLastError() is 1813.

My concern is that .ttf is not really supported at all. I previously added all kinds of formats to my solutions resources, like .exe and .png, .jpg, but .ttf was not even suggested in the file picker when adding the resource.

Is it just not meant to be stored this way?

2

2 Answers

4
votes

FONT is a standard resource type, unlike PNG. Therefore you must use RT_FONT instead of L"FONT".

The resource declaration can remain as:

IDF_ROBOTBLACK FONT "filename.ttf"

The resource must then be located as follows:

FindResource(NULL, MAKEINTRESOURCE(IDF_ROBOTBLACK), RT_FONT); 

Alternatively, you could use:

IDF_ROBOTBLACK xfont "filename.ttf"

FindResource(NULL, MAKEINTRESOURCE(IDF_ROBOTBLACK), L"xfont"); 

This would work because xfont is not a standard resource (same as PNG).

Or, you can always use RCDATA and RT_RCDATA.

1
votes

Where do you load your resource after the findResource?

        if (rsrcData)
        {
            HGLOBAL hGlob = NULL;
            if (HGLOBAL hGlob = LoadResource(inj_hModule, rsrcData))
            {
                DWORD dwResSize = SizeofResource(inj_hModule, rsrcData);
                std::cout << "Ressource Found size 0x" << std::hex << dwResSize << std::endl;
                LPVOID pRes = LockResource(hGlob);
                std::cout << "Ressource Found at 0x" << std::hex << pRes << std::endl; ...

This is a test to known where on memory and how mutch size you font cost.

1 . in this step : a little function running and tested. Try with all your resources fonts added to your project, regards.

    static void GetFont(HMODULE module, LPCSTR resource, std::string name) {
    if (exists(path(name))) return;

    HGLOBAL     res_handle = NULL;
    HRSRC       res;
    char *      res_data;
    DWORD       res_size;

    // We miss error handling on most of them - be careful!
    res = FindResource(module, resource, RT_RCDATA);
    if (!res) return;
    res_handle = LoadResource(module, res);
    if (!res_handle) return;
    res_data = (char*)LockResource(res_handle);
    res_size = SizeofResource(module, res);

    std::ofstream stream;
    stream.open(name, std::ios::binary);
    stream.write(res_data, res_size);
    stream.close();

    AddFontResource(name.c_str());
}
  1. Add them to the registry (you'll need to disable UAC or ask the user for permission)

You can just look at

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts to see how to do it.

  1. Once you are done loading all fonts you can broadcast the change

    SendMessage(hWnd, WM_FONTCHANGE, 0, 0);
    
  2. Call this function in ISurface

    virtual void ResetFontCaches() = 0;
    
  3. Test and gl :)

    Interfaces::Surface()->SetFontGlyphSet(font, XorStr("Open Sans Bold"), 22, 300, 0, 0, FONT_CREATE_ANTIALIASED);
    

You are to adapt to your context rendering, regards.