summaryrefslogtreecommitdiff
path: root/Client/Source/GUI/Font.h
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-12-13 00:07:19 +0800
committerchai <chaifix@163.com>2021-12-13 00:07:19 +0800
commit60cbbdec07ab7a5636eac5b3c024ae44e937f4d4 (patch)
treeb2c7b0a868f18159dbc43d8954e1bd7668549a88 /Client/Source/GUI/Font.h
+init
Diffstat (limited to 'Client/Source/GUI/Font.h')
-rw-r--r--Client/Source/GUI/Font.h149
1 files changed, 149 insertions, 0 deletions
diff --git a/Client/Source/GUI/Font.h b/Client/Source/GUI/Font.h
new file mode 100644
index 0000000..6fd3c19
--- /dev/null
+++ b/Client/Source/GUI/Font.h
@@ -0,0 +1,149 @@
+#pragma once
+
+#include "../Utilities/Singleton.h"
+#include "../Graphics/Texture.h"
+#include "../Common/DataBuffer.h"
+#include "../Math/Math.h"
+
+#include "freetype.h"
+
+#include <string>
+#include <unordered_map>
+#include <exception>
+#include <vector>
+
+//https://github.com/kaienfr/Font
+
+struct Character {
+ unsigned int atlas; // atlas索引
+ Rect position; // 在altas里的位置,以左上角为原点的,和GL的Y镜像
+ Vector2f bearing; // 左上角相对于原点的偏移
+ unsigned int advance; // 总宽,算上了间隔
+};
+
+namespace character
+{
+#if GAMELAB_WIN
+ typedef unsigned short Unicode; // unicode codepoint(BMP,U+0000至U+FFFF)
+#else
+ typedef unsigned int Unicode; // unicode codepoint(BMP,U+0000至U+FFFF)
+#endif
+
+#pragma pack(1)
+ union Hash {
+ unsigned int hashCode;
+ struct {
+ Unicode codepoint;
+ unsigned short size;//字体大小
+ };
+#pragma pack(pop)
+
+ bool operator==(const Hash &other) const
+ {
+ return codepoint == other.codepoint && size == other.size;
+ }
+ };
+}
+
+struct UnicodeString
+{
+ character::Unicode* str;
+ int length;
+};
+
+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; // 尺寸
+
+ Vector2f cursor; // 游标,从左上角(0,0)开始
+ int rowHeight; // 当前行的高度
+};
+
+struct TextGeneratingSettings
+{
+ Vector2f atlasSize; // atlas的尺寸
+ int margin; // atlas的边界
+ int padding; // glyph相互之间的间距,防止采样的时候越界
+};
+
+class FontException : public std::exception
+{
+public:
+ FontException(const char* what)
+ : std::exception(what)
+ {
+ }
+};
+
+enum EEncoding
+{
+ Encoding_ASCII,
+ Encoding_UTF8,
+ Encoding_UTF16,
+};
+
+// 没有字形,但是有advance的文字,比如space和tab
+#define FONT_NOT_IN_ATLAS_PLACEHOLDER (INT_MAX)
+
+// 单个字体
+class Font
+{
+public:
+ Font(std::string path, TextGeneratingSettings setting)/*throw FontException*/;
+ Font(DataBuffer* db, TextGeneratingSettings setting)/*throw FontException*/;
+
+ const Character* GetCharacter(character::Unicode codepoint, int pixelSize);
+ const GlyphAtals* GetGlyphAtlas(int index);
+
+ // pre-bake
+ bool RenderCharacter(character::Unicode codepoint, int pixelSize);
+ void RenderCharacters(character::Unicode* codepoint, int n, int pixelSize);
+ void RenderCharacters(std::vector<character::Unicode>& codepoint, int pixelSize);
+
+ GET(Vector2f, AtlasSize, m_AtlasSize);
+
+private:
+ Texture* CreateAtlas();
+ GlyphAtals* RequestAtlas(int pixelSize, Vector2f preferSize);
+ Rect GetRenderChartAndMove(GlyphAtals* atlas, Vector2f preferSize);
+ bool HasEnoughSpace(GlyphAtals* atlas, Vector2f preferSize);
+ character::Hash GetHash(character::Unicode Unicode, int pixelSize);
+
+ //-------------------------------------------------------------------------
+
+ std::unordered_map<unsigned int , Character> m_Characters; // 渲染完的文字
+
+ std::vector<GlyphAtals> m_Atlases; // 当前所有的atlas,由font完全拥有所有权,所以是lightuserdata
+ std::unordered_map<int/*pixelSize*/, GlyphAtals*> m_AtlasCache; // 快速找到可用的atlas
+
+ bool m_IsEnabled;
+
+ Vector2f m_AtlasSize;
+ int m_AtlasMargin;
+ int m_GlyphPadding;
+
+ FT_Library m_FTLibrary;
+ FT_Face m_FTFace;
+
+};
+
+namespace TextHelper
+{
+
+ void print_glyph(unsigned char* glyph, int width, int height);
+
+}