SFML community forums

Help => Graphics => Topic started by: JollyRoger on December 12, 2009, 04:40:51 am

Title: Load Font from Memory
Post by: JollyRoger on December 12, 2009, 04:40:51 am
Hi, I'm trying to load a font from memory, because I plan to use a custom font file type in the future already used in my engine.

Right now, though, I'm just trying to load a file into a std::string, and then use font.LoadFromFile( ) to get the font.

This is the code I'm using:
Code: [Select]

std::string& OpenFile( std::string filename )
{
    int length;
    char* buffer;
    std::string* encrypted;

    std::ifstream file;
    file.open( filename.c_str( ), std::ios::binary | std::ios::ate );

    file.seekg( 0, std::ios::end );
    length = file.tellg( );
    file.seekg( 0, std::ios::beg );

    buffer = new char[ length ];

    file.read( buffer, length );
    file.close( );

    *encrypted = buffer;

    delete( buffer );

    return( *encrypted );
}


And this is the code I use to load the font:
Code: [Select]

sf::Font font;

std::string file = OpenFile( "Arial.ttf" );
font.LoadFromMemory( file.c_str( ), file.length( ) );


The file is valid, and the error I get from SFML is an invalid stream operation.

Any help is appreciated.
Title: Load Font from Memory
Post by: Laurent on December 12, 2009, 09:58:54 am
Code: [Select]
std::string* encrypted;
...
*encrypted = buffer;

encrypted is not allocated. Why do you use a pointer here?
Title: Load Font from Memory
Post by: JollyRoger on December 12, 2009, 06:53:02 pm
Thanks.  I was working with two similar functions, I allocated the string in one, but not the other.

I figured out that one reason it wasn't working was because I was deleting the buffer, so it was trying to access memory that wasn't there.  I ended up just having the function return the buffer instead of a std::string.

Thanks for the help.
Title: Load Font from Memory
Post by: Nexus on December 13, 2009, 04:59:57 pm
Quote from: "JollyRoger"
I figured out that one reason it wasn't working was because I was deleting the buffer, so it was trying to access memory that wasn't there.
No, your pointer to std::string wasn't initialized, as Laurent said.

Quote from: "JollyRoger"
I ended up just having the function return the buffer instead of a std::string.
I think, that's a bad idea because the invoker is now responsible for the memory. Why don't you use std::string? C-String char arrays have got a lot of problems.

Some improvement suggestions:
Code: [Select]
// return a std::string copy (not reference) and pass a const-reference
std::string OpenFile( const std::string& filename )
{
    // use constructor
    std::ifstream file( filename.c_str( ), std::ios::binary | std::ios::ate );

    file.seekg( 0, std::ios::end );
    length = file.tellg( );
    file.seekg( 0, std::ios::beg );

    // don't declare variables far before they are used
    int length; // initialize length
    char* buffer = new char[ length ];

    file.read( buffer, length );
    file.close( );

    // don't declare variables far before they are used, again
    std::string encrypted = buffer;

    // use delete[] for arrays!
    delete buffer;

    // return copy (parentheses aren't required)
    return encrypted;
}
Title: Load Font from Memory
Post by: JollyRoger on December 13, 2009, 08:41:05 pm
Thank you for taking the time to post those improvements.
Title: Load Font from Memory
Post by: Nexus on December 13, 2009, 09:13:51 pm
Quote from: "JollyRoger"
Thank you for taking the time to post those improvements.
No problem, I like to help (especially if people don't just ignore my advice). :)

P.S.: I hope, you saw that some of the code is still wrong, for example the use of delete instead of delete[]. However, the errors should be described in comments.