Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Font LoadFromMemory issue.  (Read 811 times)

0 Members and 1 Guest are viewing this topic.

skylinx

  • Newbie
  • *
  • Posts: 2
    • View Profile
Font LoadFromMemory issue.
« on: August 08, 2022, 01:27:58 am »
Hey guys. I cannot seem to load a font from memory properly even though it works perfectly with images and gives no errors. I pack images into a bin file and load them perfectly, yet when I try the same with any font file it fails to render. LoadFromMemory() returns no errors and seemingly loads the font perfectly. (I've breakpointed and it shows the font face and everything) But when rendering the font using this method it just doesn't work.
It does work if I load from file. I am not sure what I'm doing wrong. I will post the relevant code.

This method packs the font into the bin file. I use this method with images and it works beautifully.
void osb::AssetPacker::PackFileToBin(string path, ofstream* dataStream)
{
        // open the file as binary
        ifstream loaded_file{ path, ifstream::binary };

        if (!loaded_file)
        {
                Logger::LogMessage("~Packing Failed! Could not open file: " + path);
                return;
        }

        // create the buffer to store the texture data
        vector<char> buffer;

        // get end size of texture
        loaded_file.seekg(0, loaded_file.end);

        // gives conversion warnings, static cast removes them
        // const auto length = texture_file.tellg()
        streampos sLength = loaded_file.tellg();

        // make sure stream length is not negative, or possible memory overflow
        if (sLength < 0) { return; }

        const auto length = static_cast<size_t>(sLength);
        if (!length)
        {
                Logger::LogMessage("~Packing Failed~ Cannot load zero byte file: " + path);
                return;
        }

        // resize buffer to the length of the texture
        buffer.resize(length);

        // seek to start of texture
        loaded_file.seekg(0, loaded_file.beg);

        // read texture from start to end into buffer vector
        auto start = &*buffer.begin();
        loaded_file.read(start, length);
        loaded_file.close();

        // append each character in buffer to file

        for (size_t i = 0; i < buffer.size(); i++)
        {
                *dataStream << buffer[i];
        }

        Logger::LogMessage("~Pack Success! Packed file: " + path + " ~ Buffer Size: " + to_string(buffer.size()));
}

 

The method below loads the font from the bin into a Font variable in the class.
Uncommenting the last line allows the font to render, it's loading from memory which just causes it to be dots.

void osb::AssetPacker::LoadFontFromBin()
{
        std::ifstream dataIn;

        // open the data file
        dataIn.open("fontdata.bin", std::ifstream::binary | std::ifstream::in);

        // begin reading binary data file
        char c;
        std::vector<char> buffer;
        if (dataIn.is_open())
        {
                // read all characters in data file; not skipping white space
                while (dataIn >> std::noskipws >> c)
                {
                        // push the character into the buffer
                        buffer.push_back(c);
                }

                Logger::LogMessage("Final Font Buffer Size: " + std::to_string(buffer.size()));
                dataIn.close();
        }

        if (!standard_font.loadFromMemory(&buffer[0], buffer.size()))
        {
// this never happens yet the font does not render,
                Logger::LogMessage("Font Load Failed | Buffer Size : " + buffer.size());
                return;
        }
       
        // standard_font.loadFromFile("assets/FiveByFive.ttf");
}
 

I'm really not sure why it's broken considering this works with images. Any guidance would be appreciated.
This is what it looks like when loading from memory.



Works perfectly fine when uncommenting the last line which leads me to believe it's how I'm loading from memory rather than some reference problem.
standard_font.loadFromFile("assets/FiveByFive.ttf");


« Last Edit: August 08, 2022, 01:54:23 am by skylinx »

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Font LoadFromMemory issue.
« Reply #1 on: August 08, 2022, 07:16:49 pm »
Hello, when your osb::AssetPacker::LoadFontFromBin function returns, the std::vector<char> buffer; is destroyed. For Fonts this is wrong, as documentation can tell you: https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Font.php#abf2f8d6de31eb4e1db02e061c323e346

This is unique to Font and Music objects, IIRC, you are right that other resources like Texture and Image don't have this problem (they don't need buffer to be alive).

You should make that buffer part of same class/object as the font, so they have same lifetime. Your code to load data from file could use some improvement too (load more than 1 byte at a time).
Back to C++ gamedev with SFML in May 2023

skylinx

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Font LoadFromMemory issue.
« Reply #2 on: August 08, 2022, 10:09:09 pm »
Hello, when your osb::AssetPacker::LoadFontFromBin function returns, the std::vector<char> buffer; is destroyed. For Fonts this is wrong, as documentation can tell you: https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Font.php#abf2f8d6de31eb4e1db02e061c323e346

This is unique to Font and Music objects, IIRC, you are right that other resources like Texture and Image don't have this problem (they don't need buffer to be alive).

You should make that buffer part of same class/object as the font, so they have same lifetime. Your code to load data from file could use some improvement too (load more than 1 byte at a time).

Thank you so much. I knew I was making a mistake somewhere. I had read this when going through the docs but for some reason I had misinterpreted what it meant. The code indeed could use some improvements. Iterating each byte is not ideal but it works right now :) I will get to that as soon as I fix the fonts. Appreciate your insight.