aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-11-08 19:07:13 +0100
committerdec05eba <dec05eba@protonmail.com>2022-11-08 19:07:13 +0100
commit840b87c42bb55ae6f47acc7576b3b40af4c6a68c (patch)
treed2c9f51f2ab84e88f2edcd8e3d3efcc1b4d38454
parentc2219fdf1f741a33f415124459de69054313de57 (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)
m---------depends/mglpp0
-rw-r--r--include/Text.hpp1
-rw-r--r--src/AsyncImageLoader.cpp2
-rw-r--r--src/QuickMedia.cpp8
-rw-r--r--src/Text.cpp97
5 files changed, 73 insertions, 35 deletions
diff --git a/depends/mglpp b/depends/mglpp
-Subproject d04c98708fd46524c0861baf65e9e4ff62d4879
+Subproject 0108af496da089dbee70ce80d778dfb5c238460
diff --git a/include/Text.hpp b/include/Text.hpp
index 601f1a2..daf0d46 100644
--- a/include/Text.hpp
+++ b/include/Text.hpp
@@ -172,6 +172,7 @@ namespace QuickMedia
float font_get_real_height(mgl::Font *font);
float get_text_quad_left_side(const VertexRef &vertex_ref) const;
float get_text_quad_right_side(const VertexRef &vertex_ref) const;
+ float get_text_quad_bottom_side(const VertexRef &vertex_ref) const;
// If the index is past the end, then the caret offset is the right side of the last character, rather than the left side
float get_caret_offset_by_caret_index(int index) const;
VertexRef& get_vertex_ref_clamp(int index);
diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp
index d12f9af..4021c55 100644
--- a/src/AsyncImageLoader.cpp
+++ b/src/AsyncImageLoader.cpp
@@ -313,7 +313,7 @@ namespace QuickMedia {
std::shared_ptr<ThumbnailData> AsyncImageLoader::get_thumbnail(const std::string &url, bool local, mgl::vec2i resize_target_size) {
// TODO: Instead of generating a new hash everytime to access thumbnail, cache the hash of the thumbnail url
- auto &thumbnail_data = thumbnails[url];
+ auto &thumbnail_data = thumbnails[url + "_" + std::to_string(resize_target_size.x) + "x" + std::to_string(resize_target_size.y)];
if(!thumbnail_data)
thumbnail_data = std::make_shared<ThumbnailData>();
thumbnail_data->counter = counter;
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 1f5e775..72df6eb 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -6001,11 +6001,11 @@ namespace QuickMedia {
if(mention.visible) {
BodyItem *selected_mention_item = tabs[USERS_TAB_INDEX].body->get_selected();
if(selected_mention_item) {
- std::string str_to_append = selected_mention_item->get_description();
- if(!str_to_append.empty())
- str_to_append.erase(0, 1);
+ std::string str_to_append = Text::to_printable_string(selected_mention_item->get_description());
str_to_append += " ";
- chat_input.replace(chat_input.get_caret_index() - mention.filter.size(), mention.filter.size(), str_to_append);
+ const int filter_size = (int)mention.filter.size() + 1;
+ int start_index = chat_input.get_caret_index() - filter_size;
+ chat_input.replace(std::max(0, start_index), filter_size, str_to_append);
mention.hide();
}
return false;
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)