diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-04-04 15:19:04 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-04-04 15:19:04 +0200 |
commit | 4533539e8a1bed378527b50f11e0fb197b223466 (patch) | |
tree | 2b9094c10aa71dcf5f985d8b4aded1d96af89992 | |
parent | ce7341be876b59ae2bd9a0c47542b496d8e8bee5 (diff) | |
download | serenity-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.cpp | 13 | ||||
-rw-r--r-- | SharedGraphics/Font.h | 1 | ||||
-rw-r--r-- | SharedGraphics/Painter.cpp | 41 | ||||
-rw-r--r-- | SharedGraphics/Painter.h | 9 | ||||
-rw-r--r-- | SharedGraphics/TextElision.h | 7 |
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, +}; + |