OXYGENHUB
◆ main openmsx / src / imgui / freetype_utils.hh
2.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef FREETYPE_UTILS_HH
2
#define FREETYPE_UTILS_HH
3
4
#include "FileOperations.hh"
5
#include "MSXException.hh"
6
7
#include <cstdint>
8
#include <span>
9
#include <string>
10
11
#include <ft2build.h>
12
#include FT_FREETYPE_H
13
14
namespace openmsx {
15
16
/* Example usage:
17
 *   FreeTypeLibrary library;
18
 *   std::vector<std::string> result;
19
 *   auto fontData = File(fontFilename).mmap<uint8_t>();
20
 *   for (auto i : xrange(getNumFaces(library, fontData))) {
21
 *       result.push_back(getFontDisplayName(library, fontData, i, fontFilename));
22
 *   }
23
 *   return result;
24
 */
25
26
struct FreeTypeLibrary
27
{
28
	FreeTypeLibrary(const FreeTypeLibrary&) = delete;
29
	FreeTypeLibrary(FreeTypeLibrary&&) = delete;
30
	FreeTypeLibrary& operator=(const FreeTypeLibrary&) = delete;
31
	FreeTypeLibrary& operator=(FreeTypeLibrary&&) = delete;
32
33
	FreeTypeLibrary()
34
	{
35
		if (FT_Init_FreeType(&library)) {
36
			throw MSXException("Could not initialize FreeType library");
37
		}
38
	}
39
40
	~FreeTypeLibrary()
41
	{
42
		FT_Done_FreeType(library);
43
	}
44
45
	FT_Library library;
46
};
47
48
struct FreeTypeFace
49
{
50
	FreeTypeFace(const FreeTypeFace&) = delete;
51
	FreeTypeFace(FreeTypeFace&&) = delete;
52
	FreeTypeFace& operator=(const FreeTypeFace&) = delete;
53
	FreeTypeFace& operator=(FreeTypeFace&&) = delete;
54
55
	FreeTypeFace(FreeTypeLibrary& library, std::span<const uint8_t> fontData, long faceIndex)
56
	{
57
		if (FT_New_Memory_Face(library.library, fontData.data(), fontData.size(), faceIndex, &face)) {
58
			throw MSXException("Could not parse font");
59
		}
60
	}
61
62
	~FreeTypeFace()
63
	{
64
		FT_Done_Face(face);
65
	}
66
67
	FT_Face face;
68
};
69
70
[[nodiscard]] inline long getNumFaces(FreeTypeLibrary& library, std::span<const uint8_t> fontData)
71
{
72
	FreeTypeFace face(library, fontData, -1);
73
	return face.face->num_faces;
74
}
75
76
[[nodiscard]] inline std::string getFontDisplayName(
77
	FreeTypeLibrary& library, const std::span<const uint8_t>& fontData, long faceIndex,
78
	std::string_view fontFile)
79
{
80
	FreeTypeFace face(library, fontData, faceIndex);
81
	auto toSV = [](const char* s) { return std::string_view(s ? s : ""); };
82
	auto family = toSV(face.face->family_name);
83
	auto style = toSV(face.face->style_name);
84
85
	auto name = !family.empty()
86
	          ? std::string(family)
87
	          : std::string(FileOperations::stem(fontFile));
88
	if (!style.empty() && (!family.empty() || style != family)) {
89
		strAppend(name, " - ", style);
90
	}
91
	return name;
92
}
93
94
} // namespace openmsx
95
96
#endif // FREETYPE_UTILS_HH