diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | images/troonjak.png | bin | 11574 -> 0 bytes | |||
-rw-r--r-- | src/Text.cpp | 44 |
3 files changed, 31 insertions, 16 deletions
@@ -243,4 +243,5 @@ The formatting of replying to a message with an image in matrix is a bit weird. Add ctrl+h to go back to the front page. Async load textures (not just images). This can be done efficiently by using different opengl contexts in different threads and making the context current right before a heavy opengl operation. All threads need to set their opengl context often. Downloading files should take into account the remove mime type if available. Fallback to file extension. -Text images atlas.
\ No newline at end of file +Text images atlas. +Do not render invalid unicode.
\ No newline at end of file diff --git a/images/troonjak.png b/images/troonjak.png Binary files differdeleted file mode 100644 index 75c33f5..0000000 --- a/images/troonjak.png +++ /dev/null diff --git a/src/Text.cpp b/src/Text.cpp index 192061f..0b6347d 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -510,21 +510,11 @@ namespace QuickMedia if(emoji_codepoint_combined == "1f441-fe0f-200d-1f5e8-fe0f") emoji_codepoint_combined = "1f441-200d-1f5e8"; - std::string image_url; - bool image_local = false; - if(emoji_codepoint_combined != "1f3f3-fe0f-200d-26a7-fe0f") { - image_url = "/usr/share/quickmedia/emoji/" + emoji_codepoint_combined + ".png"; - image_local = true; - } else { - image_url = "/usr/share/quickmedia/images/troonjak.png"; - image_local = true; - } - text_element.create_text("E"); text_element.text_type = TextElement::TextType::EMOJI; text_element.text = "E"; - text_element.url = std::move(image_url); - text_element.local = image_local; + text_element.url = "/usr/share/quickmedia/emoji/" + emoji_codepoint_combined + ".png"; + text_element.local = true; text_element.size = { (int)vspace, (int)vspace }; text_element.text_num_bytes = emoji_byte_length; text_elements.push_back(std::move(text_element)); @@ -602,6 +592,23 @@ namespace QuickMedia static mgl::vec2f vec2f_floor(mgl::vec2f value) { return mgl::vec2f((int)value.x, (int)value.y); } + + static size_t utf8_get_num_codepoints(const char *str, size_t size) { + size_t codepoint_index = 0; + for(size_t i = 0; i < size;) { + unsigned char *cp = (unsigned char*)&str[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, size - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + i += clen; + ++codepoint_index; + } + return codepoint_index; + } void Text::updateGeometry(bool update_even_if_not_dirty) { if(dirtyText) { @@ -1183,6 +1190,9 @@ namespace QuickMedia } else if(event.key.code == mgl::Keyboard::Backspace && caretIndex > 0) { + if(caretIndex < 0 || caretIndex > (int)vertices_linear.size()) + return; + const size_t str_index = get_string_index_from_caret_index(caretIndex); if(str_index > 0 && str_index <= str.size()) { const size_t codepoint_start = str_index - vertices_linear[caretIndex - 1].text_num_bytes; @@ -1195,6 +1205,9 @@ namespace QuickMedia } else if(event.key.code == mgl::Keyboard::Delete && !caretAtEnd) { + if(caretIndex < 0 || caretIndex >= (int)vertices_linear.size()) + return; + const size_t str_index = get_string_index_from_caret_index(caretIndex); const size_t codepoint_end = str_index + vertices_linear[caretIndex].text_num_bytes; if(str_index < str.size() && codepoint_end <= str.size()) { @@ -1266,10 +1279,11 @@ namespace QuickMedia std::vector<TextElement> new_text_elements; split_text_by_type(new_text_elements, stringToAdd); for(auto &text_element : new_text_elements) { - if(text_element.type == TextElement::Type::IMAGE || text_element.text_type == TextElement::TextType::EMOJI) + if(text_element.type == TextElement::Type::IMAGE || text_element.text_type == TextElement::TextType::EMOJI) { caretIndex += 1; - else - caretIndex += text_element.text_num_bytes; + } else { + caretIndex += utf8_get_num_codepoints(text_element.text.data(), text_element.text.size()); + } } dirty = true; dirtyText = true; |