diff options
Diffstat (limited to 'src/Text.cpp')
-rw-r--r-- | src/Text.cpp | 157 |
1 files changed, 131 insertions, 26 deletions
diff --git a/src/Text.cpp b/src/Text.cpp index 02ea6fa..c433ddc 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -11,11 +11,14 @@ namespace dchat const float EMOJI_SCALE_WITH_TEXT = 1.7f; const float EMOJI_SCALE_STANDALONE = 5.0f; + const sf::Color URL_COLOR(15, 192, 252); + Text::Text(const sf::Font *_font) : font(_font), characterSize(0), maxWidth(0.0f), color(sf::Color::White), + urlColor(URL_COLOR), dirty(false), plainText(false), totalHeight(0.0f) @@ -29,6 +32,7 @@ namespace dchat vertices(sf::PrimitiveType::Quads), maxWidth(_maxWidth), color(sf::Color::White), + urlColor(URL_COLOR), dirty(true), plainText(_plainText), totalHeight(0.0f), @@ -109,43 +113,142 @@ namespace dchat return totalHeight; } + size_t stringSplitUrl(const StringViewUtf32 textElementStr, const sf::String &urlStr, size_t offset, std::vector<TextElement> &newTextElements) + { + size_t stringStart = offset; + size_t urlStart = textElementStr.find(StringViewUtf32(urlStr.getData(), urlStr.getSize()), offset); + if(urlStart != -1) + { + offset = urlStart + urlStr.getSize(); + while(offset < textElementStr.size) + { + if(isspace(textElementStr[offset])) + break; + ++offset; + } + + StringViewUtf32 beforeUrlStr(textElementStr.data + stringStart, urlStart - stringStart); + newTextElements.push_back({ beforeUrlStr, TextElement::Type::TEXT }); + + StringViewUtf32 url(textElementStr.data + urlStart, offset - urlStart); + newTextElements.push_back({ url, TextElement::Type::URL }); + return offset; + } + return -1; + } + void Text::stringSplitElements(sf::String &stringToSplit, usize startIndex) { + StringViewUtf32 wholeStr(&stringToSplit[startIndex], stringToSplit.getSize() - startIndex); + textElements.push_back({ wholeStr, TextElement::Type::TEXT }); if(plainText) - { - StringViewUtf32 wholeStr(&stringToSplit[startIndex], stringToSplit.getSize() - startIndex); - textElements.push_back({ wholeStr, TextElement::Type::TEXT }); return; + + const char *httpStrRaw = "http://"; + const sf::String httpStr = sf::String::fromUtf8(httpStrRaw, httpStrRaw + 7); + + const char *httpsStrRaw = "https://"; + const sf::String httpsStr = sf::String::fromUtf8(httpsStrRaw, httpsStrRaw + 8); + + const char *emojiStrRaw = "[emoji]("; + const sf::String emojiStr = sf::String::fromUtf8(emojiStrRaw, emojiStrRaw + 8); + + const char *parentheseStrRaw = ")"; + const sf::String parentheseStr = sf::String::fromUtf8(parentheseStrRaw, parentheseStrRaw + 1); + static_assert(sizeof(*parentheseStr.getData()) == sizeof(u32), "sf::String size has changed..."); + + std::vector<TextElement> newTextElements; + for(size_t i = 0; i < textElements.size(); ++i) + { + TextElement textElement = textElements[i]; + if(textElement.type != TextElement::Type::TEXT) + { + newTextElements.push_back(textElement); + continue; + } + + size_t offset = 0; + while(offset < textElement.text.size) + { + size_t stringStart = offset; + size_t foundStartIndex = textElement.text.find(StringViewUtf32(emojiStr.getData(), emojiStr.getSize()), offset); + size_t foundEndIndex = -1; + if(foundStartIndex != -1) + { + offset = foundStartIndex + 8; + foundEndIndex = textElement.text.find(StringViewUtf32(parentheseStr.getData(), parentheseStr.getSize()), offset); + } + + if(foundEndIndex != -1) + { + StringViewUtf32 beforeEmojiStr(textElement.text.data + stringStart, foundStartIndex - stringStart); + newTextElements.push_back({ beforeEmojiStr, TextElement::Type::TEXT }); + + StringViewUtf32 url(textElement.text.data + offset, foundEndIndex - offset); + newTextElements.push_back({ url, TextElement::Type::EMOJI }); + offset = foundEndIndex + 1; + } + else + { + StringViewUtf32 strToEnd(textElement.text.data + stringStart, textElement.text.size - stringStart); + newTextElements.push_back({ strToEnd, TextElement::Type::TEXT }); + offset = textElement.text.size; + } + } } + textElements = newTextElements; - size_t offset = startIndex; - while(offset < stringToSplit.getSize()) + newTextElements.clear(); + for(size_t i = 0; i < textElements.size(); ++i) { - size_t stringStart = offset; - size_t foundStartIndex = stringToSplit.find("[emoji](", offset); - size_t foundEndIndex = -1; - if(foundStartIndex != -1) + TextElement textElement = textElements[i]; + if(textElement.type != TextElement::Type::TEXT) { - offset += (foundStartIndex + 8); - foundEndIndex = stringToSplit.find(")", offset); + newTextElements.push_back(textElement); + continue; } - if(foundEndIndex != -1) + size_t offset = 0; + while(offset < textElement.text.size) { - StringViewUtf32 beforeEmojiStr(&stringToSplit[stringStart], foundStartIndex - stringStart); - textElements.push_back({ beforeEmojiStr, TextElement::Type::TEXT }); - - StringViewUtf32 url(&stringToSplit[offset], foundEndIndex - offset); - textElements.push_back({ url, TextElement::Type::EMOJI }); - offset = foundEndIndex + 1; + size_t urlEnd = stringSplitUrl(textElement.text, httpStr, offset, newTextElements); + if(urlEnd == -1) + { + StringViewUtf32 strToEnd(textElement.text.data + offset, textElement.text.size - offset); + newTextElements.push_back({ strToEnd, TextElement::Type::TEXT }); + offset = textElement.text.size; + } + else + offset = urlEnd; } - else + } + textElements = newTextElements; + + newTextElements.clear(); + for(size_t i = 0; i < textElements.size(); ++i) + { + TextElement textElement = textElements[i]; + if(textElement.type != TextElement::Type::TEXT) + { + newTextElements.push_back(textElement); + continue; + } + + size_t offset = 0; + while(offset < textElement.text.size) { - StringViewUtf32 strToEnd(&stringToSplit[stringStart], stringToSplit.getSize() - stringStart); - textElements.push_back({ strToEnd, TextElement::Type::TEXT }); - offset = stringToSplit.getSize(); + size_t urlEnd = stringSplitUrl(textElement.text, httpsStr, offset, newTextElements); + if(urlEnd == -1) + { + StringViewUtf32 strToEnd(textElement.text.data + offset, textElement.text.size - offset); + newTextElements.push_back({ strToEnd, TextElement::Type::TEXT }); + offset = textElement.text.size; + } + else + offset = urlEnd; } } + textElements = newTextElements; for(std::vector<TextElement>::iterator it = textElements.begin(); it != textElements.end();) { @@ -302,10 +405,12 @@ namespace dchat sf::Vector2f textureBottomLeft(glyph.textureRect.left, glyph.textureRect.top + glyph.textureRect.height); sf::Vector2f textureBottomRight(glyph.textureRect.left + glyph.textureRect.width, glyph.textureRect.top + glyph.textureRect.height); - vertices[vertexOffset + i * 4 + 0] = { vertexTopLeft, color, textureTopLeft }; - vertices[vertexOffset + i * 4 + 1] = { vertexTopRight, color, textureTopRight }; - vertices[vertexOffset + i * 4 + 2] = { vertexBottomRight, color, textureBottomRight }; - vertices[vertexOffset + i * 4 + 3] = { vertexBottomLeft, color, textureBottomLeft }; + sf::Color fontColor = (textElement.type == TextElement::Type::TEXT ? color : urlColor); + + vertices[vertexOffset + i * 4 + 0] = { vertexTopLeft, fontColor, textureTopLeft }; + vertices[vertexOffset + i * 4 + 1] = { vertexTopRight, fontColor, textureTopRight }; + vertices[vertexOffset + i * 4 + 2] = { vertexBottomRight, fontColor, textureBottomRight }; + vertices[vertexOffset + i * 4 + 3] = { vertexBottomLeft, fontColor, textureBottomLeft }; glyphPos.x += glyph.advance; } |