From ede1a8476acd54941c20b809455ba62b30302a4e Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 7 Nov 2022 01:01:28 +0100 Subject: Add option to limit number of lines of text drawn in Text class --- src/Body.cpp | 2 ++ src/BodyItem.cpp | 2 ++ src/Text.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++---- src/plugins/Fourchan.cpp | 13 +--------- src/plugins/Matrix.cpp | 2 ++ 5 files changed, 65 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/Body.cpp b/src/Body.cpp index 32d5dd5..5bc4f2a 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -872,6 +872,7 @@ namespace QuickMedia { body_item->title_text = std::make_unique(body_item->get_title(), false, std::floor(get_config().body.title_font_size * get_config().scale * get_config().font_scale), width, title_mark_urls); } body_item->title_text->set_color(body_item->get_title_color()); + body_item->title_text->set_max_lines(body_item->title_max_lines); body_item->title_text->updateGeometry(); } @@ -884,6 +885,7 @@ namespace QuickMedia { body_item->description_text = std::make_unique(body_item->get_description(), false, std::floor(get_config().body.description_font_size * get_config().scale * get_config().font_scale), width, true); } body_item->description_text->set_color(body_item->get_description_color(), body_item->force_description_color); + body_item->description_text->set_max_lines(body_item->description_max_lines); body_item->description_text->updateGeometry(); } diff --git a/src/BodyItem.cpp b/src/BodyItem.cpp index 64d18d4..d62efea 100644 --- a/src/BodyItem.cpp +++ b/src/BodyItem.cpp @@ -30,6 +30,8 @@ namespace QuickMedia { BodyItem& BodyItem::operator=(const BodyItem &other) { url = other.url; thumbnail_url = other.thumbnail_url; + title_max_lines = other.title_max_lines; + description_max_lines = other.description_max_lines; visible = other.visible; dirty = !other.title.empty(); dirty_description = !other.description.empty(); diff --git a/src/Text.cpp b/src/Text.cpp index e6fe90c..e67d879 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -18,6 +18,8 @@ #include // TODO: text editing should take into consideration FORMATTED_TEXT_START/FORMATTED_TEXT_END. +// TODO: Add elipses at end when using max_lines. Also allow choosing where the text is cut. +// Right now the text is always cut at the end but it should be possible to cut in the middle and start too. namespace QuickMedia { @@ -154,6 +156,17 @@ namespace QuickMedia dirtyText = true; } + void Text::set_max_lines(int max_lines) { + if(max_lines < 0) + max_lines = 0; + + if(max_lines != this->max_lines) { + this->max_lines = max_lines; + dirty = true; + dirtyText = true; + } + } + // static std::string Text::to_printable_string(const std::string &str) { std::string result; @@ -906,9 +919,11 @@ namespace QuickMedia float text_offset_y = 0.0f; int last_space_index = -1; num_lines = 1; + bool cut_lines = false; // TODO: Binary search? - for(int i = 0; i < (int)vertices_linear.size(); ++i) { - VertexRef &vertex_ref = vertices_linear[i]; + int vertices_linear_index = 0; + for(vertices_linear_index = 0; vertices_linear_index < (int)vertices_linear.size(); ++vertices_linear_index) { + VertexRef &vertex_ref = vertices_linear[vertices_linear_index]; mgl::Vertex *vertex = &vertices[vertex_ref.vertices_index][vertex_ref.index]; for(int v = 0; v < 6; ++v) { @@ -920,12 +935,17 @@ namespace QuickMedia switch(vertex_ref.codepoint) { case ' ': case '\t': - last_space_index = i; + last_space_index = vertices_linear_index; break; case '\n': text_wrap_offset = 0.0f; last_space_index = -1; ++num_lines; + if(max_lines != 0 && num_lines > max_lines) { + --num_lines; + cut_lines = true; + goto vertices_linear_done; + } break; default: break; @@ -934,10 +954,16 @@ namespace QuickMedia float vertex_right_side = get_text_quad_right_side(vertex_ref); if(vertex_right_side > maxWidth && maxWidth > WORD_WRAP_MIN_SIZE) { ++num_lines; + if(max_lines != 0 && num_lines > max_lines) { + --num_lines; + cut_lines = true; + goto vertices_linear_done; + } + // TODO: Ignore line wrap on space - if(last_space_index != -1 && last_space_index != i) { + if(last_space_index != -1 && last_space_index != vertices_linear_index) { float vertex_left_side = get_text_quad_left_side(vertices_linear[last_space_index + 1]); - for(int j = last_space_index + 1; j <= i; ++j) { + for(int j = last_space_index + 1; j <= vertices_linear_index; ++j) { VertexRef &vertex_ref_wrap = vertices_linear[j]; mgl::Vertex *vertex = &vertices[vertex_ref_wrap.vertices_index][vertex_ref_wrap.index]; for(int v = 0; v < 6; ++v) { @@ -961,6 +987,7 @@ namespace QuickMedia text_offset_y += line_height; } } + vertices_linear_done:; // TODO: Optimize for(TextElement &textElement : textElements) { @@ -971,6 +998,23 @@ namespace QuickMedia } } + std::array resized_vertices; + for(size_t i = 0; i < resized_vertices.size(); ++i) { + resized_vertices[i] = false; + } + + if(cut_lines) { + for(int i = vertices_linear_index; i < (int)vertices_linear.size(); ++i) { + VertexRef &vertex_ref = vertices_linear[i]; + if(resized_vertices[vertex_ref.vertices_index]) + continue; + + vertices[vertex_ref.vertices_index].resize(vertex_ref.index); + resized_vertices[vertex_ref.vertices_index] = true; + } + vertices_linear.resize(vertices_linear_index); + } + boundingBox.size.x = 0.0f; for(VertexRef &vertex_ref : vertices_linear) { boundingBox.size.x = std::max(boundingBox.size.x, get_text_quad_right_side(vertex_ref)); @@ -1190,6 +1234,9 @@ namespace QuickMedia { if(!editable) return; + if(caretIndex > (int)vertices_linear.size()) + caretIndex = vertices_linear.size(); + bool caretAtEnd = caretIndex == (int)vertices_linear.size(); if(event.type == mgl::Event::KeyPressed) @@ -1374,6 +1421,9 @@ namespace QuickMedia for(const TextElement &textElement : textElements) { if(textElement.text_type == TextElement::TextType::EMOJI) { + if(textElement.pos.to_vec2f().y + vspace > boundingBox.size.y) + continue; + auto emoji_data = AsyncImageLoader::get_instance().get_thumbnail(textElement.url, textElement.local, { (int)vspace, (int)vspace }); if(emoji_data->loading_state == LoadingState::FINISHED_LOADING) { if(!emoji_data->texture.load_from_image(*emoji_data->image)) @@ -1408,6 +1458,9 @@ namespace QuickMedia } if(thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE) { + if(textElement.pos.to_vec2f().y + thumbnail_data->texture->get_size().y > boundingBox.size.y) + continue; + sprite.set_texture(&thumbnail_data->texture); sprite.set_position(pos + textElement.pos.to_vec2f()); sprite.set_size(textElement.size.to_vec2f()); diff --git a/src/plugins/Fourchan.cpp b/src/plugins/Fourchan.cpp index 051acc3..4cfaeaa 100644 --- a/src/plugins/Fourchan.cpp +++ b/src/plugins/Fourchan.cpp @@ -527,20 +527,9 @@ namespace QuickMedia { title_text.back() = ' '; std::string comment_text = html_to_text(comment_begin, comment_end - comment_begin, comment_by_postno, result_items, 0); - // TODO: Do the same when wrapping is implemented - // TODO: Remove this - int num_lines = 0; - for(size_t i = 0; i < comment_text.size(); ++i) { - if(comment_text[i] == '\n') { - ++num_lines; - if(num_lines == 6) { - comment_text = comment_text.substr(0, i) + " (...)"; - break; - } - } - } auto body_item = BodyItem::create(std::move(comment_text)); + body_item->set_title_max_lines(6); body_item->set_author(std::move(title_text)); body_item->url = std::to_string(thread_num.asInt64()); diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index e4a7bd1..14a5bbe 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -678,6 +678,7 @@ namespace QuickMedia { room->body_item->set_description_color(get_theme().faded_text_color); } room->body_item->set_description(std::move(room_desc)); + room->body_item->set_description_max_lines(3); if(set_room_as_unread) room->body_item->set_title_color(get_theme().attention_alert_text_color, true); room->last_message_read = false; @@ -687,6 +688,7 @@ namespace QuickMedia { } else if(last_new_message) { room->body_item->set_description(extract_first_line_remove_newline_elipses(matrix->message_get_author_displayname(last_new_message.get()), AUTHOR_MAX_LENGTH) + ": " + message_to_room_description_text(last_new_message.get())); room->body_item->set_description_color(get_theme().faded_text_color); + room->body_item->set_description_max_lines(3); rooms_page->move_room_to_top(room); room_tags_page->move_room_to_top(room); -- cgit v1.2.3