summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-04-04 15:19:04 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-04-04 15:19:04 +0200
commit4533539e8a1bed378527b50f11e0fb197b223466 (patch)
tree2b9094c10aa71dcf5f985d8b4aded1d96af89992
parentce7341be876b59ae2bd9a0c47542b496d8e8bee5 (diff)
downloadserenity-4533539e8a1bed378527b50f11e0fb197b223466.zip
Painter: Add text elision support (only right-hand side supported.)
Some window titles didn't fit on the taskbar buttons, so I needed a way to collapse the remaining part of the text into "..."
-rw-r--r--SharedGraphics/Font.cpp13
-rw-r--r--SharedGraphics/Font.h1
-rw-r--r--SharedGraphics/Painter.cpp41
-rw-r--r--SharedGraphics/Painter.h9
-rw-r--r--SharedGraphics/TextElision.h7
5 files changed, 56 insertions, 15 deletions
diff --git a/SharedGraphics/Font.cpp b/SharedGraphics/Font.cpp
index a7748a930a..615677aa13 100644
--- a/SharedGraphics/Font.cpp
+++ b/SharedGraphics/Font.cpp
@@ -160,15 +160,20 @@ bool Font::write_to_file(const String& path)
int Font::width(const String& string) const
{
- if (string.is_empty())
+ return width(string.characters(), string.length());
+}
+
+int Font::width(const char* characters, int length) const
+{
+ if (!length)
return 0;
if (m_fixed_width)
- return string.length() * m_glyph_width;
+ return length * m_glyph_width;
int width = 0;
- for (int i = 0; i < string.length(); ++i)
- width += glyph_width(string[i]) + 1;
+ for (int i = 0; i < length; ++i)
+ width += glyph_width(characters[i]) + 1;
return width - 1;
}
diff --git a/SharedGraphics/Font.h b/SharedGraphics/Font.h
index 5919bbebe7..60ecd32ba4 100644
--- a/SharedGraphics/Font.h
+++ b/SharedGraphics/Font.h
@@ -61,6 +61,7 @@ public:
byte max_glyph_width() const { return m_max_glyph_width; }
byte glyph_spacing() const { return m_fixed_width ? 0 : 1; }
int width(const String& string) const;
+ int width(const char*, int) const;
String name() const { return m_name; }
void set_name(const String& name) { m_name = name; }
diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp
index 955ad2a52a..c42c14be30 100644
--- a/SharedGraphics/Painter.cpp
+++ b/SharedGraphics/Painter.cpp
@@ -4,6 +4,7 @@
#include <SharedGraphics/CharacterBitmap.h>
#include <AK/Assertions.h>
#include <AK/StdLibExtras.h>
+#include <AK/StringBuilder.h>
#include <unistd.h>
Painter::Painter(GraphicsBitmap& bitmap)
@@ -343,8 +344,34 @@ void Painter::draw_scaled_bitmap(const Rect& a_dst_rect, const GraphicsBitmap& s
draw_bitmap(point, font.glyph_bitmap(ch), color);
}
-void Painter::draw_text(const Rect& rect, const char* text, int length, const Font& font, TextAlignment alignment, Color color)
+void Painter::draw_text(const Rect& rect, const char* text, int length, const Font& font, TextAlignment alignment, Color color, TextElision elision)
{
+ String elided_text;
+ if (elision == TextElision::Right) {
+ if (font.width(text, length) > rect.width()) {
+ int glyph_spacing = font.glyph_spacing();
+ int new_length = 0;
+ int new_width = font.width("...");
+ for (int i = 0; i < length; ++i) {
+ int glyph_width = font.glyph_width(text[i]);
+ // NOTE: Glyph spacing should not be added after the last glyph on the line,
+ // but since we are here because the last glyph does not actually fit on the line,
+ // we don't have to worry about spacing.
+ int width_with_this_glyph_included = new_width + glyph_width + glyph_spacing;
+ if (width_with_this_glyph_included > rect.width())
+ break;
+ ++new_length;
+ new_width += glyph_width + glyph_spacing;
+ }
+ StringBuilder builder;
+ builder.append(text, new_length);
+ builder.append("...");
+ elided_text = builder.to_string();
+ text = elided_text.characters();
+ length = elided_text.length();
+ }
+ }
+
Point point;
if (alignment == TextAlignment::TopLeft) {
@@ -374,19 +401,19 @@ void Painter::draw_text(const Rect& rect, const char* text, int length, const Fo
}
}
-void Painter::draw_text(const Rect& rect, const String& text, TextAlignment alignment, Color color)
+void Painter::draw_text(const Rect& rect, const String& text, TextAlignment alignment, Color color, TextElision elision)
{
- draw_text(rect, text.characters(), text.length(), alignment, color);
+ draw_text(rect, text.characters(), text.length(), alignment, color, elision);
}
-void Painter::draw_text(const Rect& rect, const String& text, const Font& font, TextAlignment alignment, Color color)
+void Painter::draw_text(const Rect& rect, const String& text, const Font& font, TextAlignment alignment, Color color, TextElision elision)
{
- draw_text(rect, text.characters(), text.length(), font, alignment, color);
+ draw_text(rect, text.characters(), text.length(), font, alignment, color, elision);
}
-void Painter::draw_text(const Rect& rect, const char* text, int length, TextAlignment alignment, Color color)
+void Painter::draw_text(const Rect& rect, const char* text, int length, TextAlignment alignment, Color color, TextElision elision)
{
- draw_text(rect, text, length, font(), alignment, color);
+ draw_text(rect, text, length, font(), alignment, color, elision);
}
void Painter::set_pixel(const Point& p, Color color)
diff --git a/SharedGraphics/Painter.h b/SharedGraphics/Painter.h
index d1533938b4..07ab4283b9 100644
--- a/SharedGraphics/Painter.h
+++ b/SharedGraphics/Painter.h
@@ -5,6 +5,7 @@
#include "Rect.h"
#include "Size.h"
#include <SharedGraphics/TextAlignment.h>
+#include <SharedGraphics/TextElision.h>
#include <AK/AKString.h>
class CharacterBitmap;
@@ -28,10 +29,10 @@ public:
void blit(const Point&, const GraphicsBitmap&, const Rect& src_rect);
void blit_with_opacity(const Point&, const GraphicsBitmap&, const Rect& src_rect, float opacity);
- void draw_text(const Rect&, const char* text, int length, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black);
- void draw_text(const Rect&, const char* text, int length, TextAlignment = TextAlignment::TopLeft, Color = Color::Black);
- void draw_text(const Rect&, const String&, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black);
- void draw_text(const Rect&, const String&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black);
+ void draw_text(const Rect&, const char* text, int length, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None);
+ void draw_text(const Rect&, const char* text, int length, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None);
+ void draw_text(const Rect&, const String&, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None);
+ void draw_text(const Rect&, const String&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None);
void draw_glyph(const Point&, char, Color);
void draw_glyph(const Point&, char, const Font&, Color);
diff --git a/SharedGraphics/TextElision.h b/SharedGraphics/TextElision.h
new file mode 100644
index 0000000000..ecd97cd452
--- /dev/null
+++ b/SharedGraphics/TextElision.h
@@ -0,0 +1,7 @@
+#pragma once
+
+enum class TextElision {
+ None,
+ Right,
+};
+