summaryrefslogtreecommitdiff
path: root/Runtime/GUI/UITextMesh.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-11-04 12:48:01 +0800
committerchai <chaifix@163.com>2021-11-04 12:48:01 +0800
commit94a9a28de16badb75e66a60efca3b01d31cc0fc6 (patch)
treea37e09236da2b7cda11a451d6fed4fe37afb065c /Runtime/GUI/UITextMesh.cpp
parentb215d811a1981e20f35bb31df4e6cd2a74146193 (diff)
* text anchor
Diffstat (limited to 'Runtime/GUI/UITextMesh.cpp')
-rw-r--r--Runtime/GUI/UITextMesh.cpp67
1 files changed, 61 insertions, 6 deletions
diff --git a/Runtime/GUI/UITextMesh.cpp b/Runtime/GUI/UITextMesh.cpp
index abb5231..94e61c4 100644
--- a/Runtime/GUI/UITextMesh.cpp
+++ b/Runtime/GUI/UITextMesh.cpp
@@ -29,6 +29,7 @@ static unsigned int s_IndicesPerText;
struct TextInfo {
const Character* ch;
float offset;
+ int line; // 从0开始
};
static unordered_map<unsigned int, vector<TextInfo>> s_TextInfos;
@@ -59,27 +60,56 @@ InitializeStaticVariables([]() {
// * 换行
// * 颜色
-UITextMesh::UITextMesh(const UnicodeString& str, Font* font,int pixelSize, ETextAnchor anchor, ETextAlignment alignment)
+// lineheight 用来处理换行、锚点
+// wordwrap 自动换行
+// preferredSize 自动换行区域大小
+UITextMesh::UITextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, ETextAnchor anchor, ETextAlignment alignment, bool wordwrap, float preferred)
{
m_Font = font;
s_TextInfos.clear();
const Vector2 atlasSize = font->GetAtlasSize();
+ Vector2 textRegion;
// 按照不同的atlas分类到s_TextInfos
float offset = 0;
+ int line = 0;
for (int i = 0; i < str.length; ++i)
{
character::Unicode c = str.str[i];
const Character* ch = font->GetCharacter(c, pixelSize);
if (ch == NULL)
continue;
+
+ if (wordwrap) // 自动换行
+ {
+ if (offset + ch->bearing.x + ch->position.width > preferred)
+ {
+ ++line;
+ offset = 0;
+ }
+ }
+
unsigned int atlasIndex = ch->atlas;
-
if (atlasIndex != FONT_NOT_IN_ATLAS_PLACEHOLDER) //非空格
{
+
+// 换行符Unix'\n', Windows'\r\n', MacOS '\r'
+#define CHECK_BREAKS() \
+ if (c == '\n' || c == '\r') \
+ { \
+ ++line; \
+ offset = 0; \
+ if (c == '\r' && ((i + 1) < str.length && str.str[i + 1] == '\n')) /*skip\n*/ \
+ ++i; \
+ continue; \
+ }
+
+ CHECK_BREAKS();
+
TextInfo info;
info.ch = ch;
info.offset = offset;
+ info.line = line;
auto list = s_TextInfos.find(atlasIndex);
if (list == s_TextInfos.end())
@@ -88,13 +118,37 @@ UITextMesh::UITextMesh(const UnicodeString& str, Font* font,int pixelSize, EText
vector<TextInfo>& v = s_TextInfos[atlasIndex];
v.push_back(info);
}
+ else
+ {
+ // 有些字体换行没有字形,所以也需要在这里处理
+ CHECK_BREAKS();
+ }
offset += ch->advance;
+
+ textRegion.x = max(offset, textRegion.x);
}
+ textRegion.y = (line + 1) * lineHeight;
+
if (s_TextInfos.size() == 0)
return;
+ Vector2i textOffset;
+ Vector2 halfRegion = Vector2(textRegion.x/ 2.f, textRegion.y / 2.f);
+ switch (anchor)
+ {
+ case TextAnchor_UpperLeft: textOffset.Set(0, 0); break;
+ case TextAnchor_UpperCenter: textOffset.Set(-halfRegion.x, 0); break;
+ case TextAnchor_UpperRight: textOffset.Set(-textRegion.x, 0); break;
+ case TextAnchor_MiddleLeft: textOffset.Set(0, -halfRegion.y); break;
+ case TextAnchor_MiddleCenter: textOffset.Set(-halfRegion.x, -halfRegion.y); break;
+ case TextAnchor_MiddleRight: textOffset.Set(-textRegion.x, -halfRegion.y); break;
+ case TextAnchor_LowerLeft: textOffset.Set(0, -textRegion.y); break;
+ case TextAnchor_LowerCenter: textOffset.Set(-halfRegion.x, -textRegion.y); break;
+ case TextAnchor_LowerRight: textOffset.Set(-textRegion.x, -textRegion.y); break;
+ }
+
// 填充VBO和IBO
for (auto iter : s_TextInfos) {
unsigned int atlasIndex = iter.first; // atlas atlasIndex
@@ -113,12 +167,13 @@ UITextMesh::UITextMesh(const UnicodeString& str, Font* font,int pixelSize, EText
TextInfo& text = texts[i];
int vOff = i * s_VertexPerText;
+ int lineOff = text.line * lineHeight;
// 左上角是原点
float pos[] = {
- text.offset + text.ch->bearing.x, pixelSize - text.ch->bearing.y + text.ch->position.height, // bottom-left
- text.offset + text.ch->bearing.x + text.ch->position.width, pixelSize - text.ch->bearing.y + text.ch->position.height, // bottom-right
- text.offset + text.ch->bearing.x + text.ch->position.width, pixelSize - text.ch->bearing.y, // top-right
- text.offset + text.ch->bearing.x, pixelSize - text.ch->bearing.y, // top-left
+ textOffset.x + text.offset + text.ch->bearing.x, textOffset.y + lineOff + pixelSize - text.ch->bearing.y + text.ch->position.height, // bottom-left
+ textOffset.x + text.offset + text.ch->bearing.x + text.ch->position.width, textOffset.y + lineOff + pixelSize - text.ch->bearing.y + text.ch->position.height, // bottom-right
+ textOffset.x + text.offset + text.ch->bearing.x + text.ch->position.width, textOffset.y + lineOff + pixelSize - text.ch->bearing.y, // top-right
+ textOffset.x + text.offset + text.ch->bearing.x, textOffset.y + lineOff + pixelSize - text.ch->bearing.y, // top-left
};
Vector4 uvQuad = Vector4(text.ch->position.x / atlasSize.x, text.ch->position.y / atlasSize.y, text.ch->position.width / atlasSize.x, text.ch->position.height / atlasSize.y);
float uv[] = {