1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#pragma once
#include "Runtime/Utilities/Singleton.h"
#include "Runtime/Graphics/Texture.h"
#include "freetype.h"
#include <string>
#include <unordered_map>
#include <vector>
//https://learnopengl.com/In-Practice/Text-Rendering
struct Character {
unsigned int atlas; // atlas索引
Internal::Rect position; // 在altas里的位置
Internal::Vector2 bearing; // 左上角相对于原点的偏移
unsigned int advance; // 总宽,算上了间隔
};
namespace character
{
typedef unsigned short Codepoint; // unicode Codepoint(BMP,U+0000至U+FFFF)
union Hash {
unsigned int hashCode;
struct {
Codepoint codepoint;
unsigned short size;//字体大小
};
bool operator==(const Hash &other) const
{
return codepoint == other.codepoint && size == other.size;
}
};
}
namespace std
{
template <>
struct hash<character::Hash>
{
std::size_t operator()(const character::Hash& k) const
{
return k.hashCode;
}
};
}
struct GlyphAtals
{
int index;
Texture* altas; // 贴图
int width, height; // 尺寸
Internal::Vector2 cursor; // 游标,从左上角(0,0)开始
int rowHeight; // 当前行的高度
};
struct TextGeneratingSettings
{
Internal::Vector2 atlasSize; // atlas的尺寸
int margin; // atlas的边界
int padding; // glyph相互之间的间距,防止采样的时候越界
};
class TextGenerator : public Singleton<TextGenerator>
{
public:
void Setup(TextGeneratingSettings settings);
const Character* GetCharacter(character::Codepoint codepoint, int pixelSize);
const GlyphAtals* GetGlyphAtlas(int index);
// pre-bake
void RenderCharacter(character::Codepoint codepoint, int pixelSize);
void RenderCharacters(character::Codepoint* codepoint, int n, int pixelSize);
private:
Texture* CreateAtlas();
GlyphAtals* RequestAtlas(int pixelSize, Internal::Vector2 preferSize);
Internal::Rect GetRenderChartAndMove(GlyphAtals* atlas, Internal::Vector2 preferSize);
bool HasEnoughSpace(GlyphAtals* atlas, Internal::Vector2 preferSize);
character::Hash GetHash(character::Codepoint Codepoint, int pixelSize);
std::unordered_map<character::Hash, Character> m_Characters; // 渲染完的文字
std::vector<GlyphAtals> m_Atlases; // 当前所有的atlas
std::unordered_map<int, GlyphAtals*> m_AtlasCache; // 快速找到可用的atlas
int m_AtlasMargin;
int m_GlyphPadding;
Internal::Vector2 m_AtlasSize;
FT_Library m_FTLibrary;
FT_Face m_FTFace;
};
#define g_TextGenerator (*TextGenerator::Instance())
namespace TextHelper
{
void print_glyph(unsigned char* glyph, int width, int height);
}
|