aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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)