c++ - 在我的资源类中将通过 loadFromFile() 加载字体的函数更改为 loadFromMemory()

标签 c++ memory resources sfml

我有这个资源类,它为我保存我的资源(只是字体)。我调用 initialise() 来加载资源,然后我做 正常的程序流程,在我退出程序之前调用 cleanUp()。这一切都很完美。

这是类的代码。资源.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

资源.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);
}

这很简单,没有任何问题。我只是像这样使用类:

int main() {
  //...

  Resources resources_;
  resources_.initialise();

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

  // ... (program loop)

  resources_.cleanUp();

  return 0;
}

现在,我要做的是:

Resources::loadFont() , 而不是使用 loadFromFile(filename) 从文件加载字体, 我想从内存中加载它。

我知道如何从内存加载字体。我只是转换一个字体文件并用字体数据填充一个无符号字符数组:

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

然后我像这样加载字体:

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

当我按照上面的说明这样做时,这是有效的,但我不知道我将如何调整 Resources::loadFont()函数,而不是从文件加载指定的字体,而是从内存(unsigned char 数组)加载它。

你能帮我指出正确的方向吗?

我不是专业人士,所以这对我来说很难,但我对如何去做(理论上)有一些模糊的想法。我将应用我目前拥有的相同原则:使用“标识符”以便可以使用 std::map。 而不是 std::map<std::string, sf::Font*>我将不得不使用一些东西来代替第二个参数 sf::Font* ,但我不知道那会是什么以及如何 Resources::loadFont()函数看起来像。

我希望我解释得足够好,真的希望有人能帮助我。

谢谢!

最佳答案

我不会这样做。它使事情变得不那么可配置和不灵活。大多数用户不会触及程序所在的目录。另一方面,如果有人真的非常想更改字体,他们仍然可以覆盖可执行文件中包含该字体的内存部分。不过,假设您确实有充分的理由这样做,这里有一些想法。

一种方法是在你的构造函数中简单地初始化 std::map,将你想要的任何字符串分配给你的字体:

bool Resources::loadAllFonts() {
  sf::Font *tempfont;

  tempfont = new sf::Font();
  if (!(tempfont->loadFromMemory(myFontMem)) { return false; }
  fonts_["myfont"] = tempfont;

  tempfont = new sf::Font();
  if (!(tempfont->loadFromMemory(myOtherFontMem)) { return false; }
  fonts_["myotherfont"] = tempfont;

  return true;
}

稍后,您需要记住分配的字符串。

但是,如果您只有几种字体,我的做法是将它们作为单独的成员存储在 Resources 中,然后只转换 getFont() 函数进入 if/else block :

#include <SFML\Graphics.hpp>

class Resources {
 public:
    //...

 private:
  const std::string fontPath_;
  // Load these fonts in the constructor
  sf::Font myFont;
  sf::Font myOtherFont;

};

// ...

sf::Font &Resources::getFont(std::string fontname) {
   if(fontname == "myfont") {
       return myFont;
   } else if(fontname == "myotherfont") {
       return myOtherFont;
   } else {
       // Error somehow
   }
}

关于c++ - 在我的资源类中将通过 loadFromFile() 加载字体的函数更改为 loadFromMemory(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23761514/

相关文章:

python - 字符串操作像python中的多个字母

c - 没有堆栈的 Linux 线程

c++ - 如何访问html资源文件?

java - 无法使用文件的 URL

android - 表示室内地图的数据结构

java - 如何在 servlet 中获取消息资源对象?

C++:用户输入产生不需要的行为

c++ - 如何在 C++ 中计算 10 位小数精度的 double 变量

c++ - 桌面集成应用程序(类似桌面小部件)

C++释放内存传递给函数中的参数或将其留给调用者