aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
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)
Diffstat (limited to 'src')
-rw-r--r--src/AsyncImageLoader.cpp2
-rw-r--r--src/QuickMedia.cpp8
-rw-r--r--src/Text.cpp97
3 files changed, 72 insertions, 35 deletions
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)