we do a minuscule amount of refactoring
This commit is contained in:
parent
ea61fcd2bf
commit
12d861d295
@ -31,7 +31,11 @@
|
|||||||
john@suckerfreegames.com
|
john@suckerfreegames.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <freetype/freetype.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <optional>
|
||||||
|
#include "irr_ptr.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -45,29 +49,79 @@ namespace irr
|
|||||||
namespace gui
|
namespace gui
|
||||||
{
|
{
|
||||||
|
|
||||||
// Manages the FT_Face cache.
|
std::map<io::path, SGUITTFace*> SGUITTFace::faces;
|
||||||
struct SGUITTFace : public irr::IReferenceCounted
|
std::optional<FT_Library> SGUITTFace::freetype_library;
|
||||||
|
|
||||||
|
std::optional<FT_Library> SGUITTFace::getFreeTypeLibrary()
|
||||||
|
{
|
||||||
|
if (freetype_library) return *freetype_library;
|
||||||
|
FT_Library ft;
|
||||||
|
if (FT_Init_FreeType(&ft))
|
||||||
|
return std::nullopt; // TODO can't we just bail out entirely if this fails?
|
||||||
|
return freetype_library = ft;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGUITTFace::SGUITTFace(std::string &&buffer) : face_buffer(std::move(buffer))
|
||||||
{
|
{
|
||||||
SGUITTFace()
|
|
||||||
{
|
|
||||||
memset((void*)&face, 0, sizeof(FT_Face));
|
memset((void*)&face, 0, sizeof(FT_Face));
|
||||||
}
|
}
|
||||||
|
|
||||||
~SGUITTFace()
|
SGUITTFace::~SGUITTFace()
|
||||||
{
|
{
|
||||||
FT_Done_Face(face);
|
FT_Done_Face(face);
|
||||||
|
}
|
||||||
|
|
||||||
|
SGUITTFace* SGUITTFace::createFace(std::string &&buffer)
|
||||||
|
{
|
||||||
|
irr_ptr<SGUITTFace> face(new SGUITTFace(std::move(buffer)));
|
||||||
|
auto ft = getFreeTypeLibrary();
|
||||||
|
if (!ft) return nullptr;
|
||||||
|
return (FT_New_Memory_Face(*ft,
|
||||||
|
reinterpret_cast<const FT_Byte*>(face->face_buffer.data()),
|
||||||
|
face->face_buffer.size(), 0, &face->face))
|
||||||
|
? nullptr : face.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
SGUITTFace* SGUITTFace::loadFace(const io::path &filename)
|
||||||
|
{
|
||||||
|
auto it = faces.find(filename);
|
||||||
|
if (it != faces.end()) {
|
||||||
|
it->second->grab();
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Face face;
|
std::string buffer;
|
||||||
std::string face_buffer;
|
if (!fs::ReadFile(filename.c_str(), buffer, true)) {
|
||||||
};
|
errorstream << "CGUITTFont: Reading file " << filename.c_str() << " failed." << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Static variables.
|
auto *face = SGUITTFace::createFace(std::move(buffer));
|
||||||
FT_Library CGUITTFont::c_library;
|
if (!face) {
|
||||||
std::map<io::path, SGUITTFace*> CGUITTFont::c_faces;
|
errorstream << "CGUITTFont: FT_New_Memory_Face failed." << std::endl;
|
||||||
bool CGUITTFont::c_libraryLoaded = false;
|
return nullptr;
|
||||||
|
}
|
||||||
|
faces.emplace(filename, face);
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
void SGUITTFace::dropFilename(const io::path &filename)
|
||||||
|
{
|
||||||
|
auto it = faces.find(filename);
|
||||||
|
if (it == faces.end()) return;
|
||||||
|
|
||||||
|
SGUITTFace* f = it->second;
|
||||||
|
// Drop our face. If this was the last face, the destructor will clean up.
|
||||||
|
if (f->drop())
|
||||||
|
faces.erase(filename);
|
||||||
|
|
||||||
|
// If there are no more faces referenced by FreeType, clean up.
|
||||||
|
if (faces.empty()) {
|
||||||
|
assert(freetype_library);
|
||||||
|
FT_Done_FreeType(*freetype_library);
|
||||||
|
freetype_library = std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const
|
video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const
|
||||||
{
|
{
|
||||||
@ -203,15 +257,12 @@ void SGUITTGlyph::unload()
|
|||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
|
|
||||||
CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency, const u32 shadow, const u32 shadow_alpha)
|
// TODO constructor which takes bogus filename and data
|
||||||
{
|
|
||||||
if (!c_libraryLoaded)
|
|
||||||
{
|
|
||||||
if (FT_Init_FreeType(&c_library))
|
|
||||||
return 0;
|
|
||||||
c_libraryLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env,
|
||||||
|
const io::path& filename, u32 size, bool antialias,
|
||||||
|
bool transparency, u32 shadow, u32 shadow_alpha)
|
||||||
|
{
|
||||||
CGUITTFont* font = new CGUITTFont(env);
|
CGUITTFont* font = new CGUITTFont(env);
|
||||||
bool ret = font->load(filename, size, antialias, transparency);
|
bool ret = font->load(filename, size, antialias, transparency);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
@ -266,32 +317,9 @@ bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antia
|
|||||||
<< (transparency ? "+transparency" : "-transparency") << std::endl;
|
<< (transparency ? "+transparency" : "-transparency") << std::endl;
|
||||||
|
|
||||||
// Grab the face.
|
// Grab the face.
|
||||||
SGUITTFace* face = nullptr;
|
auto *face = SGUITTFace::loadFace(filename);
|
||||||
auto node = c_faces.find(filename);
|
if (!face)
|
||||||
if (node == c_faces.end()) {
|
|
||||||
face = new SGUITTFace();
|
|
||||||
|
|
||||||
if (!fs::ReadFile(filename.c_str(), face->face_buffer, true)) {
|
|
||||||
delete face;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Create the face.
|
|
||||||
if (FT_New_Memory_Face(c_library,
|
|
||||||
reinterpret_cast<const FT_Byte*>(face->face_buffer.data()),
|
|
||||||
face->face_buffer.size(), 0, &face->face))
|
|
||||||
{
|
|
||||||
errorstream << "CGUITTFont: FT_New_Memory_Face failed." << std::endl;
|
|
||||||
delete face;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
c_faces.emplace(filename, face);
|
|
||||||
} else {
|
|
||||||
// Using another instance of this face.
|
|
||||||
face = node->second;
|
|
||||||
face->grab();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store our face.
|
// Store our face.
|
||||||
tt_face = face->face;
|
tt_face = face->face;
|
||||||
@ -323,22 +351,7 @@ CGUITTFont::~CGUITTFont()
|
|||||||
Glyphs.clear();
|
Glyphs.clear();
|
||||||
|
|
||||||
// We aren't using this face anymore.
|
// We aren't using this face anymore.
|
||||||
auto n = c_faces.find(filename);
|
SGUITTFace::dropFilename(filename);
|
||||||
if (n != c_faces.end())
|
|
||||||
{
|
|
||||||
SGUITTFace* f = n->second;
|
|
||||||
|
|
||||||
// Drop our face. If this was the last face, the destructor will clean up.
|
|
||||||
if (f->drop())
|
|
||||||
c_faces.erase(filename);
|
|
||||||
|
|
||||||
// If there are no more faces referenced by FreeType, clean up.
|
|
||||||
if (c_faces.empty())
|
|
||||||
{
|
|
||||||
FT_Done_FreeType(c_library);
|
|
||||||
c_libraryLoaded = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drop our driver now.
|
// Drop our driver now.
|
||||||
if (Driver)
|
if (Driver)
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
@ -44,11 +45,42 @@
|
|||||||
#include "util/enriched_string.h"
|
#include "util/enriched_string.h"
|
||||||
#include "util/basic_macros.h"
|
#include "util/basic_macros.h"
|
||||||
|
|
||||||
|
// TODO these should be in the C++ when the struct is properly split into C++ & header
|
||||||
|
#include <optional>
|
||||||
|
#include "irr_ptr.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "filesys.h"
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
namespace gui
|
namespace gui
|
||||||
{
|
{
|
||||||
struct SGUITTFace;
|
// Manages the FT_Face cache.
|
||||||
|
struct SGUITTFace : public irr::IReferenceCounted
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
static std::map<io::path, SGUITTFace*> faces;
|
||||||
|
static std::optional<FT_Library> freetype_library;
|
||||||
|
|
||||||
|
static std::optional<FT_Library> getFreeTypeLibrary();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SGUITTFace(std::string &&buffer);
|
||||||
|
|
||||||
|
~SGUITTFace();
|
||||||
|
|
||||||
|
FT_Face face;
|
||||||
|
/// Must not be deallocated until we are done with the face!
|
||||||
|
std::string face_buffer;
|
||||||
|
|
||||||
|
static SGUITTFace* createFace(std::string &&buffer);
|
||||||
|
|
||||||
|
static SGUITTFace* loadFace(const io::path &filename);
|
||||||
|
|
||||||
|
static void dropFilename(const io::path &filename);
|
||||||
|
};
|
||||||
class CGUITTFont;
|
class CGUITTFont;
|
||||||
|
|
||||||
//! Structure representing a single TrueType glyph.
|
//! Structure representing a single TrueType glyph.
|
||||||
@ -220,7 +252,9 @@ namespace gui
|
|||||||
//! \param antialias set the use_monochrome (opposite to antialias) flag
|
//! \param antialias set the use_monochrome (opposite to antialias) flag
|
||||||
//! \param transparency set the use_transparency flag
|
//! \param transparency set the use_transparency flag
|
||||||
//! \return Returns a pointer to a CGUITTFont. Will return 0 if the font failed to load.
|
//! \return Returns a pointer to a CGUITTFont. Will return 0 if the font failed to load.
|
||||||
static CGUITTFont* createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true, const u32 shadow = 0, const u32 shadow_alpha = 255);
|
static CGUITTFont* createTTFont(IGUIEnvironment *env,
|
||||||
|
const io::path& filename, u32 size, bool antialias = true,
|
||||||
|
bool transparency = true, u32 shadow = 0, u32 shadow_alpha = 255);
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
virtual ~CGUITTFont();
|
virtual ~CGUITTFont();
|
||||||
@ -329,11 +363,6 @@ namespace gui
|
|||||||
core::dimension2du max_page_texture_size;
|
core::dimension2du max_page_texture_size;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Manages the FreeType library.
|
|
||||||
static FT_Library c_library;
|
|
||||||
static std::map<io::path, SGUITTFace*> c_faces;
|
|
||||||
static bool c_libraryLoaded;
|
|
||||||
|
|
||||||
// Helper functions for the same-named public member functions above
|
// Helper functions for the same-named public member functions above
|
||||||
// (Since std::u32string is nicer to work with than wchar_t *)
|
// (Since std::u32string is nicer to work with than wchar_t *)
|
||||||
core::dimension2d<u32> getDimension(const std::u32string& text) const;
|
core::dimension2d<u32> getDimension(const std::u32string& text) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user