summaryrefslogtreecommitdiff
path: root/Runtime/GUI/TextGenerator.h
blob: ef78eb600d6ea63bdd4edad10a56b6c68e050b9e (plain)
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);

}