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

Author Topic: Change the font loadFromFile() function to loadFromMemory() in my resource class  (Read 2400 times)

0 Members and 1 Guest are viewing this topic.

smguyk

  • Jr. Member
  • **
  • Posts: 79
    • View Profile
Hey,

I have this resource class that holds my resources (just fonts) for me. I call initialise() to load the resources, then I do the normal program flow and before I exit the program I call cleanUp(). This is all working perfectly.

This is the code for the class. resources.h:

#ifndef __RESOURCES_H__
#define __RESOURCES_H__

#include <SFML\Graphics.hpp>

class Resources {
 public:
  Resources();
  bool initialise();
  void cleanUp();
  bool loadAllFonts();
  bool loadFont(std::string filename);
  sf::Font &getFont(std::string filename);

  const std::string myFont_;
  const std::string myOtherFont_;

 private:
  const std::string fontPath_;
  std::map<std::string, sf::Font*> fonts_;

};

#endif

resources.cpp

#include "resources.h"

Resources::Resources() :
  myFont_("./data/myFont.ttf"),
  myOtherFont_("./data/myOtherFont.ttf")
{
}

bool Resources::initialise() {
  if (loadAllFonts()) { return true; }
  return false;
}

void Resources::cleanUp() {
  std::map<std::string, sf::Font*>::iterator font_it;
  for (font_it = fonts_.begin(); font_it != fonts_.end(); font_it++) {
    delete font_it->second;
    font_it->second = NULL;
  }
  fonts_.clear();
}

bool Resources::loadAllFonts() {
  if (!loadFont(myFont_)) { return false; }
  if (!loadFont(myOtherFont_)) { return false; }
  return true;
}

bool Resources::loadFont(std::string filename) {
  if (fonts_.find(filename) != fonts_.end()) {
    return false;
  }
  sf::Font *font = new sf::Font();
  sf::err().rdbuf(NULL);
  if (!font->loadFromFile(filename)) {
    delete font;
    font = NULL;
    return false;
  }
  const_cast<sf::Texture&>(font->getTexture(8)).setSmooth(false);
  const_cast<sf::Texture&>(font->getTexture(12)).setSmooth(false);
  const_cast<sf::Texture&>(font->getTexture(16)).setSmooth(false);
  const_cast<sf::Texture&>(font->getTexture(24)).setSmooth(false);
  fonts_.insert(std::pair<std::string, sf::Font*>(filename, font));
  return true;
}

sf::Font &Resources::getFont(std::string filename) {
  return *(fonts_.find(filename)->second);
}

This was simple enough and went without problems. I just use the class like this:

int main() {
  //...

  Resources resources_;
  resources_.initialise();

  sf::Text testText("test text", resources_.getFont(resources_.myFont_), 25);

  // ... (program loop)

  resources_.cleanUp();

  return 0;
}

Now, what I want to do is the following:

In Resources::loadFont(), instead of loading a font from a file with loadFromFile(filename), I want to load it from memory.

I know how loading a font from memory works. I simply convert a font file and fill an unsigned char array with the font data:

unsigned char myFontChar[] = {0x00,0x01,0x00, .......... ,0x00,0x30,0x00,0x03,0x00,0xc0,0x4f,0x53,0x2f};

Then I load the font like this:

sf::Font font;
if (!font.loadFromMemory(myFontChar, sizeof(myFontChar))) { return -1; }

This is working when I do it as demonstrated above, but I have no idea how I would go about adjusting the Resources::loadFont() function so that instead of loading the specified font from a file it loads it from memory (the unsigned char array).

Could you please help me and point me in the right direction?

I am not a pro, so this is hard for me, but I have some vague idea how to do it (in theory). I would apply the same principle that I currently have: Use an "identifier", so the std::map could be used.

Instead of std::map<std::string, sf::Font*> I would have to use something that replaces the second parameter sf::Font*, but I don't know what that would be and how the Resources::loadFont() function would then look like.

I hope I explained it well enough and really really hope someone can help me.

Thanks!
« Last Edit: May 20, 2014, 03:52:48 pm by smguyk »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
I believe you simply open the file in binary mode with standard iostreams and read it into memory.

smguyk

  • Jr. Member
  • **
  • Posts: 79
    • View Profile
I actually solved it, but it won't let me remove this thread.

Now I have the fonts as class members and load them from memory in the constructor, and the getFont() function just returns the font based on the name that is passed.

I also got rid of the map!

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
but it won't let me remove this thread.
Removing is a bad idea. Others may benefit in the future, or there may be people writing an answer.

Or people like me who give feedback unrelated to the actual question :p
  • __RESOURCES_H__ is a reserved identifier, using it in C++ programs is strictly speaking not allowed. Avoid double underscores or leading underscores followed by capital letters.
  • if (xy) return true; return false; can be written as return xy;
  • Pass strings by const-reference
  • Avoid new/delete, use RAII
  • Don't expose member variables in public section
  • You can use std::make_pair to infer the types
  • Setting local variables like font to NULL before returning is pointless; but this won't be necessary with RAII anyway
  • getFont() crashes when a wrong filename is specified. Maybe assertion or exception would be appropriate
  • Instead of a public initialise() function that must be called in order to work correctly, use the constructor for initialization (American English :P)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

smguyk

  • Jr. Member
  • **
  • Posts: 79
    • View Profile

Thanks, I took some of those suggestions to heart and improved my code!

 

anything