diff options
author | chai <chaifix@163.com> | 2021-11-04 12:48:01 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-11-04 12:48:01 +0800 |
commit | 94a9a28de16badb75e66a60efca3b01d31cc0fc6 (patch) | |
tree | a37e09236da2b7cda11a451d6fed4fe37afb065c /Runtime/GUI/UITextMesh.cpp | |
parent | b215d811a1981e20f35bb31df4e6cd2a74146193 (diff) |
* text anchor
Diffstat (limited to 'Runtime/GUI/UITextMesh.cpp')
-rw-r--r-- | Runtime/GUI/UITextMesh.cpp | 67 |
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[] = { |