diff options
author | dec05eba <dec05eba@protonmail.com> | 2022-11-08 19:07:13 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2022-11-08 19:07:13 +0100 |
commit | 840b87c42bb55ae6f47acc7576b3b40af4c6a68c (patch) | |
tree | d2c9f51f2ab84e88f2edcd8e3d3efcc1b4d38454 /src/Text.cpp | |
parent | c2219fdf1f741a33f415124459de69054313de57 (diff) |
Fix emoji drawn outside border when max lines set, username autocomplete caret not moving to end of text, multiple images on the same page with different sizes (downscaled)
Diffstat (limited to 'src/Text.cpp')
-rw-r--r-- | src/Text.cpp | 97 |
1 files changed, 67 insertions, 30 deletions
diff --git a/src/Text.cpp b/src/Text.cpp index 6bc777d..44bf73c 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -228,13 +228,42 @@ namespace QuickMedia return characterSize; } + 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::replace(size_t start_index, size_t length, const std::string &insert_str) { - int string_diff = (int)insert_str.size() - (int)length; + const bool at_end = start_index == str.size(); str.replace(start_index, length, insert_str); dirty = true; dirtyText = true; - if(caretIndex >= (int)start_index) { - caretIndex += string_diff; + if(!at_end) { + std::vector<TextElement> new_text_elements; + Text::split_text_by_type(new_text_elements, insert_str, 0.0f); + int caret_advance = 0; + for(auto &text_element : new_text_elements) { + if(text_element.type == TextElement::Type::IMAGE || text_element.text_type == TextElement::TextType::EMOJI) { + caret_advance += 1; + } else { + caret_advance += utf8_get_num_codepoints(text_element.text.data(), text_element.text.size()); + } + } + + fprintf(stderr, "old caret index: %d, advance: %d\n", caretIndex, caret_advance); + caretIndex += caret_advance; dirtyCaret = true; } } @@ -556,6 +585,10 @@ namespace QuickMedia return vertices[vertex_ref.vertices_index][vertex_ref.index + 5].position.x; } + float Text::get_text_quad_bottom_side(const VertexRef &vertex_ref) const { + return vertices[vertex_ref.vertices_index][vertex_ref.index + 4].position.y; + } + float Text::get_caret_offset_by_caret_index(int index) const { const int num_vertices = vertices_linear.size(); if(num_vertices == 0) @@ -603,23 +636,6 @@ 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) { @@ -652,9 +668,10 @@ namespace QuickMedia latin_font = FontLoader::get_font(FontLoader::FontType::LATIN, characterSize); const float latin_font_width = latin_font->get_glyph(' ').advance; - const float hspace = latin_font_width + characterSpacing; + const float hspace_latin = latin_font_width + characterSpacing; const float vspace = font_get_real_height(latin_font); const float emoji_spacing = 2.0f; + int hspace_monospace = 0; const mgl::Color url_color = get_theme().url_text_color; size_t url_range_index = 0; @@ -792,6 +809,8 @@ namespace QuickMedia clen = 1; } + float hspace = hspace_latin; + // TODO: CJK monospace if(is_symbol_codepoint(codepoint)) { ff = FontLoader::get_font(FontLoader::FontType::SYMBOLS, characterSize); @@ -802,6 +821,9 @@ namespace QuickMedia } else if(monospace) { ff = FontLoader::get_font(FontLoader::FontType::LATIN_MONOSPACE, characterSize); vertices_index = FONT_INDEX_MONOSPACE; + if(hspace_monospace == 0) + hspace_monospace = ff->get_glyph(' ').advance + characterSpacing; + hspace = hspace_monospace; } else { ff = latin_font; vertices_index = FONT_INDEX_LATIN; @@ -1003,6 +1025,9 @@ namespace QuickMedia const VertexRef &vertex_ref = vertices_linear[textElement.vertex_ref_index]; const mgl::vec2f top_left_vertex_pos = vertices[vertex_ref.vertices_index][vertex_ref.index + 1].position; textElement.pos = { (int)top_left_vertex_pos.x, (int)top_left_vertex_pos.y }; + // Hide images by drawing them far away if we should cut them... + if(cut_lines && textElement.vertex_ref_index >= vertices_linear_index) + textElement.pos.y = 9999.0f; } } @@ -1024,10 +1049,22 @@ namespace QuickMedia } boundingBox.size.x = 0.0f; + boundingBox.size.y = 0.0f; for(VertexRef &vertex_ref : vertices_linear) { boundingBox.size.x = std::max(boundingBox.size.x, get_text_quad_right_side(vertex_ref)); + //boundingBox.size.y = std::max(boundingBox.size.y, get_text_quad_bottom_side(vertex_ref)); } + boundingBox.size.y = num_lines * line_height; + //boundingBox.size.y = text_offset_y; + + // TODO: + + //if(vertices_linear.empty()) + // boundingBox.size.y = line_height; + + //if(editable) + // boundingBox.size.y = num_lines * line_height; // TODO: Clear |vertices| somehow even with editable text for(size_t i = 0; i < FONT_ARRAY_SIZE; ++i) { @@ -1241,6 +1278,15 @@ namespace QuickMedia void Text::processEvent(mgl::Window &window, const mgl::Event &event) { if(!editable) return; + + // TODO: Dont do this here! it's slow, but it's needed to process the change before the next event + updateGeometry(); + + if(dirtyCaret || caretMoveDirection != CaretMoveDirection::NONE) { + updateCaret(); + dirtyCaret = false; + caretMoveDirection = CaretMoveDirection::NONE; + } if(caretIndex > (int)vertices_linear.size()) caretIndex = vertices_linear.size(); @@ -1366,15 +1412,6 @@ namespace QuickMedia dirtyText = true; dirtyCaret = true; } - - // TODO: Dont do this here! it's slow, but it's needed to process the change before the next event - updateGeometry(); - - if(dirtyCaret || caretMoveDirection != CaretMoveDirection::NONE) { - updateCaret(); - dirtyCaret = false; - caretMoveDirection = CaretMoveDirection::NONE; - } } bool Text::draw(mgl::Window &target) |