diff options
author | chai <chaifix@163.com> | 2021-12-13 00:07:19 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-12-13 00:07:19 +0800 |
commit | 60cbbdec07ab7a5636eac5b3c024ae44e937f4d4 (patch) | |
tree | b2c7b0a868f18159dbc43d8954e1bd7668549a88 /Client/Source/GUI/Font.h |
+init
Diffstat (limited to 'Client/Source/GUI/Font.h')
-rw-r--r-- | Client/Source/GUI/Font.h | 149 |
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); + +} |