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

Author Topic: Access Violation issue when drawing sf::Text  (Read 2520 times)

0 Members and 1 Guest are viewing this topic.

SleepyRhino

  • Newbie
  • *
  • Posts: 2
    • View Profile
    • Email
Access Violation issue when drawing sf::Text
« on: July 27, 2014, 09:09:00 pm »

As per the title I can create a sf::Text object and use set font and everything work up until I want to draw the text.

I have added the code below for the class which handles the loading ad storing of Fonts, I have also copied all the loading and getting code into the same class as where I initialise the sf::Text object and it work fine however when I use the FontCache class it doesn't.

The Font is being loaded and retrieved fine.

At the bottom is where the exception is thrown.

Any help on this would be great been trying to fix it for like 12 hours of work time.

FontCache.h
#pragma once

#include <SFML/Graphics/Font.hpp>

#include <unordered_map>
#include <memory>
#include <string>

class FontCache
{
public:
        typedef std::shared_ptr<sf::Font> FontPtr;
        typedef std::unordered_map<std::string, FontPtr> FontMap;
        typedef FontMap::iterator FontMapIterator;

public:
        FontCache(unsigned int size = 10);
        ~FontCache();
        bool add(std::string name, std::string file);
        void remove(std::string name);
        sf::Font& get(std::string name);
        void unload();

private:
        FontMap resources_;
};
 

FontCache.cpp

#include "StandardInc.h"
#include "FontCache.h"
#include "PhysFsStream.h"

FontCache::FontCache(unsigned size)
: resources_(size)
{
       
}

FontCache::~FontCache()
{
        unload();
}

bool FontCache::add(std::string name, std::string file)
{
        FontMapIterator it = resources_.find(name);

        if(it != resources_.end())
        {
                return true;
        }

        PhysFsStream stream;
        stream.open(file.c_str());

        FontPtr newFont = std::make_shared<sf::Font>();
        if (!newFont->loadFromStream(stream))
        {
                printf("Error: Unable to load %s\n", file.c_str());
                return false;
        }

        resources_[name] = std::move(newFont);
        printf("Added Font: %s\n", file.c_str());
        return true;
}

void FontCache::remove(std::string name)
{
        FontMapIterator it = resources_.find(name);

        if(it != resources_.end())
        {
                resources_.erase(it);
        }
}

sf::Font& FontCache::get(std::string name)
{
        FontMapIterator it = resources_.find(name);
        if(it == resources_.end())
                add(name, name);

        return *resources_[name];
}

void FontCache::unload()
{
        resources_.clear();
}
 

Part of GameScene.hpp

sf::Text buildDetails_ = new sf::Text();
    buildDetails_->setFont(fonts_.get("fonts/PTM55FT.ttf"));
    buildDetails_->setString("Build 0.0.0");
    buildDetails_->setPosition(10, 10);
 


In the sf::Font::loadGlyph method is where the trouble starts

    // Load the glyph corresponding to the code point
    if (FT_Load_Char(face, codePoint, FT_LOAD_TARGET_NORMAL | FT_LOAD_FORCE_AUTOHINT) != 0)
        return glyph;
 

In the line
 if (static_cast<unsigned long>(stream->seek(offset)) == offset)  
is where the Access Violation exception is thrown.

    // FreeType callbacks that operate on a sf::InputStream
    unsigned long read(FT_Stream rec, unsigned long offset, unsigned char* buffer, unsigned long count)
    {
        sf::InputStream* stream = static_cast<sf::InputStream*>(rec->descriptor.pointer);
        if (static_cast<unsigned long>(stream->seek(offset)) == offset)
        {
            if (count > 0)
                return static_cast<unsigned long>(stream->read(reinterpret_cast<char*>(buffer), count));
            else
                return 0;
        }
        else
            return count > 0 ? 0 : 1; // error code is 0 if we're reading, or nonzero if we're seeking
    }
 

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: Access Violation issue when drawing sf::Text
« Reply #1 on: July 27, 2014, 10:55:21 pm »
If I understand what you want to do do, you can use Thor resources in the meantime. It's ridiculously easy to use  :)
« Last Edit: July 27, 2014, 10:57:45 pm by Strelok »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Access Violation issue when drawing sf::Text
« Reply #2 on: July 27, 2014, 11:03:13 pm »
When the font wants to load more glyphs dynamically, it tries to read from its source stream, which doesn't exist anymore since it was local to your function.

As stated in the documentation of sf::Font::loadFromStream:
Quote
Warning: SFML cannot preload all the font data in this function, so the contents of stream have to remain valid as long as the font is used.

The solution is to store your PhysFsStream streams together with their sf::Font instance.
Laurent Gomila - SFML developer

SleepyRhino

  • Newbie
  • *
  • Posts: 2
    • View Profile
    • Email
Re: Access Violation issue when drawing sf::Text
« Reply #3 on: July 27, 2014, 11:36:40 pm »
When the font wants to load more glyphs dynamically, it tries to read from its source stream, which doesn't exist anymore since it was local to your function.

As stated in the documentation of sf::Font::loadFromStream:
Quote
Warning: SFML cannot preload all the font data in this function, so the contents of stream have to remain valid as long as the font is used.

The solution is to store your PhysFsStream streams together with their sf::Font instance.

Cheers Laurent worked perfectly, something I totally over looked.

 

anything