diff options
author | chai <chaifix@163.com> | 2021-11-01 12:19:36 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-11-01 12:19:36 +0800 |
commit | 4dead522e513ffd326101b790b2129595f72ff42 (patch) | |
tree | 9c1cbc8169f524a36e6dbb4a43af7728e15fefe7 | |
parent | 44d6c41e5e586572de08c72c358aed9100a30353 (diff) |
* TextGenerator -> Font
-rw-r--r-- | Editor/EditorMain.cpp | 7 | ||||
-rw-r--r-- | Projects/VisualStudio/Editor/Editor.vcxproj | 4 | ||||
-rw-r--r-- | Projects/VisualStudio/Editor/Editor.vcxproj.filters | 18 | ||||
-rw-r--r-- | Runtime/GUI/Font.cpp | 214 | ||||
-rw-r--r-- | Runtime/GUI/Font.h | 110 | ||||
-rw-r--r-- | Runtime/GUI/TextGenerator.cpp | 214 | ||||
-rw-r--r-- | Runtime/GUI/TextGenerator.h | 109 |
7 files changed, 334 insertions, 342 deletions
diff --git a/Editor/EditorMain.cpp b/Editor/EditorMain.cpp index 45ac81a..187df1c 100644 --- a/Editor/EditorMain.cpp +++ b/Editor/EditorMain.cpp @@ -9,7 +9,7 @@ #include "Editor/Win/Win.h"
#include "Runtime/Threading/Thread.h"
-#include "Runtime/GUI/TextGenerator.h"
+#include "Runtime/GUI/Font.h"
using namespace LuaBind;
@@ -25,10 +25,9 @@ void TestFont() setting.padding = 5;
setting.atlasSize = Internal::Vector2(512, 512);
- TextGenerator::Instance()->Setup(setting);
+ Font::Instance()->Setup(setting);
auto content = L"abcdf与电子计算机的区别 与电子计算机的最大区别在于: 只是简单的计算工具,有些机型具备函数计算功能,有些机型具备一定的贮存功能,但一般只能存储几组数据。计算机则具备复杂存贮功能、控制功能,更加";
- TextGenerator::Instance()->RenderCharacters((character::Codepoint*)content, wcslen(content), 14);
-
+ Font::Instance()->RenderCharacters((character::Codepoint*)content, wcslen(content), 14);
}
int BeforeMainLoop(lua_State* L)
diff --git a/Projects/VisualStudio/Editor/Editor.vcxproj b/Projects/VisualStudio/Editor/Editor.vcxproj index ffdf5ef..f732067 100644 --- a/Projects/VisualStudio/Editor/Editor.vcxproj +++ b/Projects/VisualStudio/Editor/Editor.vcxproj @@ -200,7 +200,6 @@ <ClCompile Include="..\..\..\Runtime\Graphics\VertexAttribute.cpp" />
<ClCompile Include="..\..\..\Runtime\Graphics\VertexBuffer.cpp" />
<ClCompile Include="..\..\..\Runtime\GUI\Font.cpp" />
- <ClCompile Include="..\..\..\Runtime\GUI\TextGenerator.cpp" />
<ClCompile Include="..\..\..\Runtime\Lua\LuaBind\LuaBindCFunctions.cpp" />
<ClCompile Include="..\..\..\Runtime\Lua\LuaBind\LuaBindClass.cpp" />
<ClCompile Include="..\..\..\Runtime\Lua\LuaBind\LuaBindEnum.cpp" />
@@ -284,9 +283,8 @@ <ClInclude Include="..\..\..\Runtime\Graphics\Texture.h" />
<ClInclude Include="..\..\..\Runtime\Graphics\VertexAttribute.h" />
<ClInclude Include="..\..\..\Runtime\Graphics\VertexBuffer.h" />
- <ClInclude Include="..\..\..\Runtime\GUI\Font.h" />
<ClInclude Include="..\..\..\Runtime\GUI\freetype.h" />
- <ClInclude Include="..\..\..\Runtime\GUI\TextGenerator.h" />
+ <ClInclude Include="..\..\..\Runtime\GUI\Font.h" />
<ClInclude Include="..\..\..\Runtime\Lua\LuaBind\LuaBind.h" />
<ClInclude Include="..\..\..\Runtime\Lua\LuaBind\LuaBindCFunctions.h" />
<ClInclude Include="..\..\..\Runtime\Lua\LuaBind\LuaBindClass.hpp" />
diff --git a/Projects/VisualStudio/Editor/Editor.vcxproj.filters b/Projects/VisualStudio/Editor/Editor.vcxproj.filters index 9fb8bf2..edda3e3 100644 --- a/Projects/VisualStudio/Editor/Editor.vcxproj.filters +++ b/Projects/VisualStudio/Editor/Editor.vcxproj.filters @@ -378,9 +378,6 @@ <ClCompile Include="..\..\..\Editor\FileSystem\FileWatcher.cpp">
<Filter>Editor\FileSystem</Filter>
</ClCompile>
- <ClCompile Include="..\..\..\Runtime\GUI\TextGenerator.cpp">
- <Filter>Runtime\GUI</Filter>
- </ClCompile>
<ClCompile Include="..\..\..\Runtime\Rendering\Quad.cpp">
<Filter>Runtime\Rendering</Filter>
</ClCompile>
@@ -390,12 +387,12 @@ <ClCompile Include="..\..\..\Runtime\Graphics\RenderCommands.cpp">
<Filter>Runtime\Graphics</Filter>
</ClCompile>
- <ClCompile Include="..\..\..\Runtime\GUI\Font.cpp">
- <Filter>Runtime\GUI</Filter>
- </ClCompile>
<ClCompile Include="..\..\..\Runtime\Graphics\DynamicVertexBuffer.cpp">
<Filter>Runtime\Graphics</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\Runtime\GUI\Font.cpp">
+ <Filter>Runtime\GUI</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\Editor\GUI\Dock.h">
@@ -659,9 +656,6 @@ <ClInclude Include="..\..\..\Editor\FileSystem\FileWatcher.h">
<Filter>Editor\FileSystem</Filter>
</ClInclude>
- <ClInclude Include="..\..\..\Runtime\GUI\TextGenerator.h">
- <Filter>Runtime\GUI</Filter>
- </ClInclude>
<ClInclude Include="..\..\..\Runtime\GUI\freetype.h">
<Filter>Runtime\GUI</Filter>
</ClInclude>
@@ -683,12 +677,12 @@ <ClInclude Include="..\..\..\Runtime\Graphics\RenderCommands.h">
<Filter>Runtime\Graphics</Filter>
</ClInclude>
- <ClInclude Include="..\..\..\Runtime\GUI\Font.h">
- <Filter>Runtime\GUI</Filter>
- </ClInclude>
<ClInclude Include="..\..\..\Runtime\Graphics\DynamicVertexBuffer.h">
<Filter>Runtime\Graphics</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\Runtime\GUI\Font.h">
+ <Filter>Runtime\GUI</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\Runtime\Lua\LuaBind\LuaBindClass.inc">
diff --git a/Runtime/GUI/Font.cpp b/Runtime/GUI/Font.cpp index e69de29..f00f33d 100644 --- a/Runtime/GUI/Font.cpp +++ b/Runtime/GUI/Font.cpp @@ -0,0 +1,214 @@ +#include "freetype.h" +#include "Font.h" +#include "../Math/Math.h" +#include "Runtime/Debug/Log.h" +#include "Runtime/Utilities/Assert.h" +#include "Runtime/Graphics/ImageData.h" + +using namespace character; + +//https://unicode-table.com/en/#cjk-unified-ideographs-extension-a +//https://learnopengl.com/In-Practice/Text-Rendering +//https://www.zhihu.com/question/294660079 +//https://baike.baidu.com/item/%E5%9F%BA%E6%9C%AC%E5%A4%9A%E6%96%87%E7%A7%8D%E5%B9%B3%E9%9D%A2/10788078 +//https://stackoverflow.com/questions/27331819/whats-the-difference-between-a-character-a-code-point-a-glyph-and-a-grapheme + +void Font::Setup(TextGeneratingSettings settings) +{ + m_AtlasMargin = settings.margin; + m_GlyphPadding = settings.padding; + m_AtlasSize = settings.atlasSize; + + if (FT_Init_FreeType(&m_FTLibrary)) + { + return; + } + + if (FT_New_Face(m_FTLibrary, "Resources/Font/Deng.ttf", 0, &m_FTFace)) + { + return; + } +} + +character::Hash Font::GetHash(Codepoint codepoint, int pixelSize) +{ + character::Hash hash; + hash.codepoint = codepoint; + hash.size = pixelSize; + return hash; +} + +const Character* Font::GetCharacter(character::Codepoint codepoint, int pixelSize) +{ + character::Hash hash = GetHash(codepoint, pixelSize); + auto iter = m_Characters.find(hash); + if (iter == m_Characters.end()) + { + RenderCharacter(codepoint, pixelSize); + iter = m_Characters.find(hash); + } + Assert(iter != m_Characters.end()); + return &iter->second; +} + +void Font::RenderCharacters(character::Codepoint* codepoint, int n, int pixelSize) +{ + for (int i = 0; i < n; ++i) + { + RenderCharacter(codepoint[i], pixelSize); + } +} + +void Font::RenderCharacter(character::Codepoint codepoint, int pixelSize) +{ + character::Hash hash = GetHash(codepoint, pixelSize); + if (m_Characters.count(hash) != 0) + return; + FT_Set_Pixel_Sizes(m_FTFace, 0, pixelSize); + if (FT_Load_Char(m_FTFace, codepoint, FT_LOAD_RENDER)) + { + return; + } + + int w = m_FTFace->glyph->bitmap.width; + int h = m_FTFace->glyph->bitmap.rows; + + //TextHelper::print_glyph(m_FTFace->glyph->bitmap.buffer, w, h); + + GlyphAtals* atlas = RequestAtlas(pixelSize, Internal::Vector2(w, h)); + Assert(atlas); + + Internal::Rect rect = GetRenderChartAndMove(atlas, Internal::Vector2(w, h)); + + try + { + atlas->altas->UpdateSubImage(rect, EPixelFormat::PixelFormat_R, EPixelElementType::PixelType_UNSIGNED_BYTE, m_FTFace->glyph->bitmap.buffer); + } + catch (TextureException& e) + { + std::string error = e.what(); + error = "Render Character Error: " + error; + log_error(e.what()); + return; + } + + Character character; + character.atlas = atlas->index; + character.position = rect; + character.bearing = Internal::Vector2(m_FTFace->glyph->bitmap_left, m_FTFace->glyph->bitmap_top); + character.advance = m_FTFace->glyph->advance.x * 1/64.f; + + m_Characters.insert(std::pair<character::Hash, Character>(hash, character)); +} + +const GlyphAtals* Font::GetGlyphAtlas(int index) +{ + if (index >= m_Atlases.size()) + return NULL; + return &m_Atlases[index]; +} + +Internal::Rect Font::GetRenderChartAndMove(GlyphAtals* atlas, Internal::Vector2 preferSize) +{ + Internal::Rect rect; + Internal::Vector2 space; + space.x = atlas->width - atlas->cursor.x - m_AtlasMargin; + space.y = atlas->height - atlas->cursor.y - m_AtlasMargin; + if (space.x > preferSize.x && space.y > preferSize.y) + { + rect.x = atlas->cursor.x; + rect.y = atlas->cursor.y; + rect.width = preferSize.x; + rect.height = preferSize.y; + atlas->cursor.x += rect.width + m_GlyphPadding; + atlas->rowHeight = max(atlas->rowHeight, preferSize.y); + } + else if (space.y - atlas->rowHeight - m_GlyphPadding - m_AtlasMargin > preferSize.y) + { + rect.x = m_AtlasMargin; + rect.y = atlas->cursor.y + m_GlyphPadding + atlas->rowHeight; + rect.width = preferSize.x; + rect.height = preferSize.y; + atlas->cursor.x = m_AtlasMargin; + atlas->cursor.y += atlas->rowHeight + m_GlyphPadding; + atlas->rowHeight = rect.height; + } + else + { + Assert(false); + } + return rect; +} + +GlyphAtals* Font::RequestAtlas(int pixelSize, Internal::Vector2 preferSize) +{ + GlyphAtals* atlas = NULL; + auto iter = m_AtlasCache.find(pixelSize); + if (iter == m_AtlasCache.end() || !HasEnoughSpace(iter->second, preferSize)) + { + Texture* tex = CreateAtlas(); + GlyphAtals newAtlas = GlyphAtals(); + newAtlas.altas = tex; + newAtlas.width = m_AtlasSize.x; + newAtlas.height = m_AtlasSize.y; + newAtlas.index = m_Atlases.size(); + newAtlas.cursor = Internal::Vector2(m_AtlasMargin, m_AtlasMargin); + + m_Atlases.push_back(newAtlas); + atlas = &m_Atlases[m_Atlases.size() - 1]; + + if (iter != m_AtlasCache.end()) + m_AtlasCache.erase(pixelSize); + m_AtlasCache.insert(std::pair<int, GlyphAtals*>(pixelSize, atlas)); + } + else + { + atlas = iter->second; + } + Assert(atlas); + return atlas; +} + +Texture* Font::CreateAtlas() +{ + TextureSetting setting; + setting.filterMode = ETextureFilterMode::Linear; + setting.wrapMode = ETextureWrapMode::Clamp; + setting.format = ETextureFormat::R8; + setting.type = ETextureType::TEX_2D; + setting.keepImageData = false; + Texture* tex = new Texture(setting, m_AtlasSize.x, m_AtlasSize.y); + return tex; +} + +bool Font::HasEnoughSpace(GlyphAtals* atlas, Internal::Vector2 preferSize) +{ + if (atlas == NULL) + return false; + Internal::Vector2 space; + space.x = atlas->width - atlas->cursor.x - m_AtlasMargin; + space.y = atlas->height - atlas->cursor.y - m_AtlasMargin; + if (space.x > preferSize.x && space.y > preferSize.y) + return true; + if (space.y - atlas->rowHeight - m_GlyphPadding - m_AtlasMargin > preferSize.y) + return true; + return false; +} + +Character GetCharacter(character::Codepoint Codepoint, int pixelSize) +{ + return Character(); +} + +void TextHelper::print_glyph(unsigned char* glyph, int width, int height) +{ + for (int r = 0; r < height; ++r) + { + for (int c = 0; c < width; ++c) + { + unsigned char ch = glyph[c + r * width]; + printf("%c", ch == 0 ? ' ' : '+'); + } + printf("\n"); + } +} diff --git a/Runtime/GUI/Font.h b/Runtime/GUI/Font.h index e69de29..da9ef55 100644 --- a/Runtime/GUI/Font.h +++ b/Runtime/GUI/Font.h @@ -0,0 +1,110 @@ +#pragma once + +#include "Runtime/Utilities/Singleton.h" +#include "Runtime/Graphics/Texture.h" +#include "freetype.h" +#include "Runtime/Lua/LuaHelper.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 Font : public Singleton<Font> +{ +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 (*Font::Instance()) + +namespace TextHelper +{ + + void print_glyph(unsigned char* glyph, int width, int height); + +} diff --git a/Runtime/GUI/TextGenerator.cpp b/Runtime/GUI/TextGenerator.cpp deleted file mode 100644 index d2cd20c..0000000 --- a/Runtime/GUI/TextGenerator.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include "freetype.h" -#include "TextGenerator.h" -#include "../Math/Math.h" -#include "Runtime/Debug/Log.h" -#include "Runtime/Utilities/Assert.h" -#include "Runtime/Graphics/ImageData.h" - -using namespace character; - -//https://unicode-table.com/en/#cjk-unified-ideographs-extension-a -//https://learnopengl.com/In-Practice/Text-Rendering -//https://www.zhihu.com/question/294660079 -//https://baike.baidu.com/item/%E5%9F%BA%E6%9C%AC%E5%A4%9A%E6%96%87%E7%A7%8D%E5%B9%B3%E9%9D%A2/10788078 -//https://stackoverflow.com/questions/27331819/whats-the-difference-between-a-character-a-code-point-a-glyph-and-a-grapheme - -void TextGenerator::Setup(TextGeneratingSettings settings) -{ - m_AtlasMargin = settings.margin; - m_GlyphPadding = settings.padding; - m_AtlasSize = settings.atlasSize; - - if (FT_Init_FreeType(&m_FTLibrary)) - { - return; - } - - if (FT_New_Face(m_FTLibrary, "Resources/Font/Deng.ttf", 0, &m_FTFace)) - { - return; - } -} - -character::Hash TextGenerator::GetHash(Codepoint codepoint, int pixelSize) -{ - character::Hash hash; - hash.codepoint = codepoint; - hash.size = pixelSize; - return hash; -} - -const Character* TextGenerator::GetCharacter(character::Codepoint codepoint, int pixelSize) -{ - character::Hash hash = GetHash(codepoint, pixelSize); - auto iter = m_Characters.find(hash); - if (iter == m_Characters.end()) - { - RenderCharacter(codepoint, pixelSize); - iter = m_Characters.find(hash); - } - Assert(iter != m_Characters.end()); - return &iter->second; -} - -void TextGenerator::RenderCharacters(character::Codepoint* codepoint, int n, int pixelSize) -{ - for (int i = 0; i < n; ++i) - { - RenderCharacter(codepoint[i], pixelSize); - } -} - -void TextGenerator::RenderCharacter(character::Codepoint codepoint, int pixelSize) -{ - character::Hash hash = GetHash(codepoint, pixelSize); - if (m_Characters.count(hash) != 0) - return; - FT_Set_Pixel_Sizes(m_FTFace, 0, pixelSize); - if (FT_Load_Char(m_FTFace, codepoint, FT_LOAD_RENDER)) - { - return; - } - - int w = m_FTFace->glyph->bitmap.width; - int h = m_FTFace->glyph->bitmap.rows; - - //TextHelper::print_glyph(m_FTFace->glyph->bitmap.buffer, w, h); - - GlyphAtals* atlas = RequestAtlas(pixelSize, Internal::Vector2(w, h)); - Assert(atlas); - - Internal::Rect rect = GetRenderChartAndMove(atlas, Internal::Vector2(w, h)); - - try - { - atlas->altas->UpdateSubImage(rect, EPixelFormat::PixelFormat_R, EPixelElementType::PixelType_UNSIGNED_BYTE, m_FTFace->glyph->bitmap.buffer); - } - catch (TextureException& e) - { - std::string error = e.what(); - error = "Render Character Error: " + error; - log_error(e.what()); - return; - } - - Character character; - character.atlas = atlas->index; - character.position = rect; - character.bearing = Internal::Vector2(m_FTFace->glyph->bitmap_left, m_FTFace->glyph->bitmap_top); - character.advance = m_FTFace->glyph->advance.x * 1/64.f; - - m_Characters.insert(std::pair<character::Hash, Character>(hash, character)); -} - -const GlyphAtals* TextGenerator::GetGlyphAtlas(int index) -{ - if (index >= m_Atlases.size()) - return NULL; - return &m_Atlases[index]; -} - -Internal::Rect TextGenerator::GetRenderChartAndMove(GlyphAtals* atlas, Internal::Vector2 preferSize) -{ - Internal::Rect rect; - Internal::Vector2 space; - space.x = atlas->width - atlas->cursor.x - m_AtlasMargin; - space.y = atlas->height - atlas->cursor.y - m_AtlasMargin; - if (space.x > preferSize.x && space.y > preferSize.y) - { - rect.x = atlas->cursor.x; - rect.y = atlas->cursor.y; - rect.width = preferSize.x; - rect.height = preferSize.y; - atlas->cursor.x += rect.width + m_GlyphPadding; - atlas->rowHeight = max(atlas->rowHeight, preferSize.y); - } - else if (space.y - atlas->rowHeight - m_GlyphPadding - m_AtlasMargin > preferSize.y) - { - rect.x = m_AtlasMargin; - rect.y = atlas->cursor.y + m_GlyphPadding + atlas->rowHeight; - rect.width = preferSize.x; - rect.height = preferSize.y; - atlas->cursor.x = m_AtlasMargin; - atlas->cursor.y += atlas->rowHeight + m_GlyphPadding; - atlas->rowHeight = rect.height; - } - else - { - Assert(false); - } - return rect; -} - -GlyphAtals* TextGenerator::RequestAtlas(int pixelSize, Internal::Vector2 preferSize) -{ - GlyphAtals* atlas = NULL; - auto iter = m_AtlasCache.find(pixelSize); - if (iter == m_AtlasCache.end() || !HasEnoughSpace(iter->second, preferSize)) - { - Texture* tex = CreateAtlas(); - GlyphAtals newAtlas = GlyphAtals(); - newAtlas.altas = tex; - newAtlas.width = m_AtlasSize.x; - newAtlas.height = m_AtlasSize.y; - newAtlas.index = m_Atlases.size(); - newAtlas.cursor = Internal::Vector2(m_AtlasMargin, m_AtlasMargin); - - m_Atlases.push_back(newAtlas); - atlas = &m_Atlases[m_Atlases.size() - 1]; - - if (iter != m_AtlasCache.end()) - m_AtlasCache.erase(pixelSize); - m_AtlasCache.insert(std::pair<int, GlyphAtals*>(pixelSize, atlas)); - } - else - { - atlas = iter->second; - } - Assert(atlas); - return atlas; -} - -Texture* TextGenerator::CreateAtlas() -{ - TextureSetting setting; - setting.filterMode = ETextureFilterMode::Linear; - setting.wrapMode = ETextureWrapMode::Clamp; - setting.format = ETextureFormat::R8; - setting.type = ETextureType::TEX_2D; - setting.keepImageData = false; - Texture* tex = new Texture(setting, m_AtlasSize.x, m_AtlasSize.y); - return tex; -} - -bool TextGenerator::HasEnoughSpace(GlyphAtals* atlas, Internal::Vector2 preferSize) -{ - if (atlas == NULL) - return false; - Internal::Vector2 space; - space.x = atlas->width - atlas->cursor.x - m_AtlasMargin; - space.y = atlas->height - atlas->cursor.y - m_AtlasMargin; - if (space.x > preferSize.x && space.y > preferSize.y) - return true; - if (space.y - atlas->rowHeight - m_GlyphPadding - m_AtlasMargin > preferSize.y) - return true; - return false; -} - -Character GetCharacter(character::Codepoint Codepoint, int pixelSize) -{ - return Character(); -} - -void TextHelper::print_glyph(unsigned char* glyph, int width, int height) -{ - for (int r = 0; r < height; ++r) - { - for (int c = 0; c < width; ++c) - { - unsigned char ch = glyph[c + r * width]; - printf("%c", ch == 0 ? ' ' : '+'); - } - printf("\n"); - } -} diff --git a/Runtime/GUI/TextGenerator.h b/Runtime/GUI/TextGenerator.h deleted file mode 100644 index ef78eb6..0000000 --- a/Runtime/GUI/TextGenerator.h +++ /dev/null @@ -1,109 +0,0 @@ -#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); - -} |