aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-11-07 01:01:28 +0100
committerdec05eba <dec05eba@protonmail.com>2022-11-07 14:24:32 +0100
commitede1a8476acd54941c20b809455ba62b30302a4e (patch)
tree82160da56025e47484c23e8496f1d59b8ddc084f
parent8025d1075db0779bde635148f6e38303eb29d6c8 (diff)
Add option to limit number of lines of text drawn in Text class
-rw-r--r--include/BodyItem.hpp17
-rw-r--r--include/Text.hpp7
-rw-r--r--src/Body.cpp2
-rw-r--r--src/BodyItem.cpp2
-rw-r--r--src/Text.cpp63
-rw-r--r--src/plugins/Fourchan.cpp13
-rw-r--r--src/plugins/Matrix.cpp2
7 files changed, 86 insertions, 20 deletions
diff --git a/include/BodyItem.hpp b/include/BodyItem.hpp
index b7dc48a..647d344 100644
--- a/include/BodyItem.hpp
+++ b/include/BodyItem.hpp
@@ -104,6 +104,14 @@ namespace QuickMedia {
force_title_color = new_force_color;
}
+ // Set to 0 to disable max lines
+ void set_title_max_lines(int max_lines) {
+ if(max_lines == title_max_lines)
+ return;
+ title_max_lines = max_lines;
+ dirty = true;
+ }
+
void set_description_color(mgl::Color new_color, bool new_force_color = false) {
if(new_color == description_color && new_force_color == force_description_color)
return;
@@ -112,6 +120,13 @@ namespace QuickMedia {
force_description_color = new_force_color;
}
+ void set_description_max_lines(int max_lines) {
+ if(max_lines == description_max_lines)
+ return;
+ description_max_lines = max_lines;
+ dirty_description = true;
+ }
+
void set_author_color(mgl::Color new_color, bool new_force_color = false) {
if(new_color == author_color && new_force_color == force_description_color)
return;
@@ -153,6 +168,8 @@ namespace QuickMedia {
// TODO: Use a list of strings instead, not all plugins need all of these fields
std::string url;
std::string thumbnail_url;
+ int title_max_lines = 0;
+ int description_max_lines = 0;
bool visible; // TODO: Make private and when set by user, set a |visible_force| variable to true or false which makes the item invisible even after filtering
bool dirty;
bool dirty_description;
diff --git a/include/Text.hpp b/include/Text.hpp
index 73dd565..601f1a2 100644
--- a/include/Text.hpp
+++ b/include/Text.hpp
@@ -100,6 +100,8 @@ namespace QuickMedia
// text_flags is bit-or of FormattedTextFlag
static std::string formatted_text(const std::string &text, mgl::Color color, uint8_t text_flags);
void insert_text_at_caret_position(const std::string &str);
+ // Set to 0 to disable max lines
+ void set_max_lines(int max_lines);
static std::string to_printable_string(const std::string &str);
@@ -186,7 +188,7 @@ namespace QuickMedia
float maxWidth;
mgl::vec2f position;
mgl::Color color;
- bool force_color;
+ bool force_color = false;
bool dirty;
bool dirtyText;
bool dirtyCaret;
@@ -202,10 +204,9 @@ namespace QuickMedia
int caretIndex;
float caret_offset_x;
mgl::vec2f caretPosition;
- mgl::vec2u renderTarget_size;
+ int max_lines = 0;
std::vector<VertexRef> vertices_linear; // TODO: Use textElements instead
-
std::vector<Range> url_ranges;
};
}
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<Text>(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<Text>(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 <sstream>
// 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<bool, FONT_ARRAY_SIZE> 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);