summaryrefslogtreecommitdiff
path: root/Runtime/GUI
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-11-05 12:14:59 +0800
committerchai <chaifix@163.com>2021-11-05 12:14:59 +0800
commit6d5787d8da9ad1685864668dd4c3d6aa73a563db (patch)
treef4d28a553b13b369a580c482e187bcc4b42f39de /Runtime/GUI
parentbe9870f5c1ba4f6ae8cd9764f1a8ed56ee81ddd5 (diff)
TextMeshGenerator
Diffstat (limited to 'Runtime/GUI')
-rw-r--r--Runtime/GUI/Font.h3
-rw-r--r--Runtime/GUI/TextMeshGenerator.cpp89
-rw-r--r--Runtime/GUI/TextMeshGenerator.h14
-rw-r--r--Runtime/GUI/UITextMesh.cpp25
-rw-r--r--Runtime/GUI/UITextMesh.h33
5 files changed, 143 insertions, 21 deletions
diff --git a/Runtime/GUI/Font.h b/Runtime/GUI/Font.h
index cd546af..565fafc 100644
--- a/Runtime/GUI/Font.h
+++ b/Runtime/GUI/Font.h
@@ -31,10 +31,13 @@ namespace character
union Hash {
unsigned int hashCode;
+#pragma pack(1)
struct {
Unicode codepoint;
unsigned short size;//字体大小
};
+#pragma pack()
+
bool operator==(const Hash &other) const
{
return codepoint == other.codepoint && size == other.size;
diff --git a/Runtime/GUI/TextMeshGenerator.cpp b/Runtime/GUI/TextMeshGenerator.cpp
index 98d3b09..b4c8c4d 100644
--- a/Runtime/GUI/TextMeshGenerator.cpp
+++ b/Runtime/GUI/TextMeshGenerator.cpp
@@ -1,10 +1,89 @@
#include "TextMeshGenerator.h"
-UITextMesh* TextMeshGenerator::GetTextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 col32, ETextAnchor anchor, ETextAlignment alignment, bool wordwrap, float preferred)
+// 计算一个哈希值
+static uint32_t GetStrHash(const UnicodeString& str)
{
- for (int i = 0; i < m_TextMeshes.size(); ++i)
- {
- UITextMesh* tm = m_TextMeshes[i];
+ if (str.length == 0)
+ return 0;
- }
+ int len = str.length;
+ uint32_t hash = (uint32_t)len; // seed
+ size_t step = (len >> 5) + 1;
+ for (int l = len; l >= step; l -= step)
+ {
+ unsigned short unicode = str.str[l - 1];
+ unsigned char hicode = *((unsigned char*)&unicode);
+ unsigned char locode = *(((unsigned char*)&unicode) + 1);
+ hash = hash ^ ((hash << 5) + (hash >> 2) + hicode + locode);
+ }
+ return hash;
+}
+
+const UITextMesh* TextMeshGenerator::GetTextMesh(
+ const UnicodeString& str
+ , Font* font
+ , int pixelSize
+ , int lineHeight
+ , Color32 col32
+ , ETextAnchor anchor
+ , ETextAlignment alignment
+ , bool wordwrap
+ , float preferred
+){
+ uint32_t hash = GetStrHash(str);
+ UITextMeshList* tm = NULL;
+ bool hasHash = m_TextMeshes.count(hash);
+ if (hasHash)
+ {
+ tm = m_TextMeshes[hash];
+ while (tm)
+ {
+ UITextMesh* mesh = tm->mesh;
+ if (mesh->GetFont() != font
+ || mesh->GetPixelSize() != pixelSize
+ || mesh->GetLineHeight() != lineHeight
+ || mesh->GetAnchor() != anchor
+ || mesh->GetAlignment() != alignment
+ || mesh->GetWordwrap() != wordwrap
+ || mesh->GetPreferred() != preferred
+ || mesh->GetColor() != col32
+ ){
+ tm = tm->next;
+ continue;
+ }
+ const UnicodeString& content = mesh->GetContent();
+ if (content.length != str.length)
+ {
+ tm = tm->next;
+ continue;
+ }
+ if (memcmp(str.str, content.str, sizeof(character::Unicode) * str.length) == 0)
+ {
+ return tm->mesh;
+ }
+ tm = tm->next;
+ }
+ }
+ tm = new UITextMeshList();
+ try {
+ tm->mesh = new UITextMesh(str, font, pixelSize, lineHeight, col32, anchor, alignment, wordwrap, preferred);
+ log_info("Text", "New UITextMesh");
+ }
+ catch(TextMeshException& e)
+ {
+ delete tm;
+ throw;
+ }
+ if (hasHash)
+ {
+ UITextMeshList* list = m_TextMeshes[hash];
+ tm->next = list;
+ m_TextMeshes[hash] = tm;
+ }
+ else
+ {
+ tm->next = NULL;
+ m_TextMeshes.insert(std::pair<uint32_t, UITextMeshList*>(hash, tm));
+ }
+ return tm->mesh;
}
diff --git a/Runtime/GUI/TextMeshGenerator.h b/Runtime/GUI/TextMeshGenerator.h
index dd4f1d9..815f4c4 100644
--- a/Runtime/GUI/TextMeshGenerator.h
+++ b/Runtime/GUI/TextMeshGenerator.h
@@ -3,9 +3,11 @@
#include "UITextMesh.h"
#include "Runtime/Utilities/IIncrementalTask.h"
#include "Font.h"
+#include "Runtime/Debug/Log.h"
#include <vector>
+#include <unordered_map>
-// collect unused text mesh gradually
+// 逐步回收长期没用到的textmesh
class GraduallyReleaseTextMesh : public IIncrementalTask
{
public:
@@ -21,14 +23,18 @@ public:
};
+struct UITextMeshList {
+ UITextMesh* mesh;
+ UITextMeshList* next;
+};
+
class TextMeshGenerator : public Singleton<TextMeshGenerator>
{
public:
- UITextMesh* GetTextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 col32, ETextAnchor anchor, ETextAlignment alignment, bool wordwrap, float preferred);
+ const UITextMesh* GetTextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 col32, ETextAnchor anchor, ETextAlignment alignment, bool wordwrap, float preferred);
private:
- std::vector<UITextMesh*> m_TextMeshes;
-
+ std::unordered_map<uint32_t, UITextMeshList*> m_TextMeshes;
};
#define g_TextMeshGenerator (*TextMeshGenerator::Instance()) \ No newline at end of file
diff --git a/Runtime/GUI/UITextMesh.cpp b/Runtime/GUI/UITextMesh.cpp
index 24aff47..23c0a9c 100644
--- a/Runtime/GUI/UITextMesh.cpp
+++ b/Runtime/GUI/UITextMesh.cpp
@@ -33,7 +33,6 @@ struct TextInfo {
int line; // 从0开始
};
-static unordered_map<unsigned int, vector<TextInfo>> s_TextInfos;
InitializeStaticVariables([]() {
VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(TextMeshVBOLayout));
@@ -63,6 +62,20 @@ UITextMesh::UITextMesh(
, bool wordwrap // 自动换行
, float preferred // 自动换行区域大小
){
+ m_Font = font;
+ m_PixelSize = pixelSize;
+ m_LineHeight = lineHeight;
+ m_Color = color32;
+ m_Alignment = alignment;
+ m_Anchor = anchor;
+ m_Wordwrap = wordwrap;
+ m_Preferred = preferred;
+ m_Content.length = str.length;
+ m_Content.str = (character::Unicode*)malloc(str.length * sizeof(character::Unicode));
+ memcpy(m_Content.str, str.str, str.length * sizeof(character::Unicode));
+
+ // 记录文本按atlas分类
+ static unordered_map<unsigned int, vector<TextInfo>> s_TextInfos;
s_TextInfos.clear();
// 记录文本每行的长度
@@ -76,9 +89,9 @@ UITextMesh::UITextMesh(
InvokeWhenLeave([]() {
s_LineWidths.clear();
s_LineOffsets.clear();
+ s_TextInfos.clear();
});
- m_Font = font;
const Vector2 atlasSize = font->GetAtlasSize();
//-----------------------------------------------------------------
@@ -149,8 +162,10 @@ UITextMesh::UITextMesh(
textRegion.y = (line + 1) * lineHeight;
- if (s_TextInfos.size() == 0)
- return;
+ if (s_TextInfos.size() == 0)
+ {
+ return;
+ }
Vector2i textOffset;
Vector2 halfRegion = Vector2(textRegion.x/ 2.f, textRegion.y / 2.f);
@@ -240,7 +255,7 @@ UITextMesh::UITextMesh(
WipeGLError();
}
-void UITextMesh::Draw()
+void UITextMesh::Draw() const
{
for (auto subText : m_VBOs)
{
diff --git a/Runtime/GUI/UITextMesh.h b/Runtime/GUI/UITextMesh.h
index c298cb0..505b390 100644
--- a/Runtime/GUI/UITextMesh.h
+++ b/Runtime/GUI/UITextMesh.h
@@ -34,15 +34,34 @@ namespace TextHelper
class UITextMesh
{
public:
- UITextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 color32 = Color32::white, ETextAnchor anchor = TextAnchor_UpperLeft, ETextAlignment alignment = TextAlignment_Left, bool wordwrap = false, float preferred = 0)/*throw TextMeshException*/;
+ void Draw() const;
- ~UITextMesh();
+ GET(const Font*, Font, m_Font);
+ GET(int, PixelSize, m_PixelSize);
+ GET(int, LineHeight, m_LineHeight);
+ GET(Color32, Color, m_Color);
+ GET(ETextAlignment, Alignment, m_Alignment);
+ GET(ETextAnchor, Anchor, m_Anchor);
+ GET(bool, Wordwrap, m_Wordwrap);
+ GET(float, Preferred, m_Preferred);
+ GET(const UnicodeString&, Content, m_Content);
- void Draw();
+private:
+ friend class TextMeshGenerator;
-private:
- unsigned long long m_NotUniqueHash;
- Font* m_Font;
- std::unordered_map<int/*IndexOfAtlas*/, VertexBuffer*> m_VBOs;
+ UITextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 color32 = Color32::white, ETextAnchor anchor = TextAnchor_UpperLeft, ETextAlignment alignment = TextAlignment_Left, bool wordwrap = false, float preferred = 0)/*throw TextMeshException*/;
+ ~UITextMesh();
+
+ std::unordered_map<int, VertexBuffer*> m_VBOs;
+
+ Font* m_Font;
+ UnicodeString m_Content;
+ int m_PixelSize;
+ int m_LineHeight;
+ Color32 m_Color;
+ ETextAlignment m_Alignment;
+ ETextAnchor m_Anchor;
+ bool m_Wordwrap;
+ float m_Preferred;
}; \ No newline at end of file