mirror of
https://github.com/libretro/scummvm.git
synced 2024-11-28 03:40:36 +00:00
GUI: Handle ellipsis shortening of text when drawing u32 strings
This commit is contained in:
parent
5f2af6b93e
commit
ad78777bc6
@ -1115,7 +1115,7 @@ drawString(const Graphics::Font *font, const Common::U32String &text, const Comm
|
||||
|
||||
if (!drawArea.isEmpty()) {
|
||||
Surface textAreaSurface = _activeSurface->getSubArea(drawArea);
|
||||
font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax);
|
||||
font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,17 +334,23 @@ Common::Rect Font::getBoundingBox(const Common::String &input, int x, int y, con
|
||||
return getBoundingBoxImpl(*this, str, x, y, w, align, deltax);
|
||||
}
|
||||
|
||||
Common::Rect Font::getBoundingBox(const Common::U32String &str, int x, int y, const int w, TextAlign align) const {
|
||||
Common::Rect Font::getBoundingBox(const Common::U32String &input, int x, int y, const int w, TextAlign align, int deltax, bool useEllipsis) const {
|
||||
// In case no width was given we cannot any alignment apart from left
|
||||
// alignment.
|
||||
if (w == 0) {
|
||||
if (useEllipsis) {
|
||||
warning("Font::getBoundingBox: Requested ellipsis when no width was specified");
|
||||
}
|
||||
|
||||
if (align != kTextAlignLeft) {
|
||||
warning("Font::getBoundingBox: Requested text alignment when no width was specified");
|
||||
}
|
||||
|
||||
useEllipsis = false;
|
||||
align = kTextAlignLeft;
|
||||
}
|
||||
|
||||
const Common::U32String str = useEllipsis ? handleEllipsis(input, w) : input;
|
||||
return getBoundingBoxImpl(*this, str, x, y, w, align, 0);
|
||||
}
|
||||
|
||||
@ -369,8 +375,9 @@ void Font::drawString(Surface *dst, const Common::String &str, int x, int y, int
|
||||
drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax);
|
||||
}
|
||||
|
||||
void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax) const {
|
||||
drawStringImpl(*this, dst, str, x, y, w, color, align, deltax);
|
||||
void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
|
||||
Common::U32String renderStr = useEllipsis ? handleEllipsis(str, w) : str;
|
||||
drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax);
|
||||
}
|
||||
|
||||
void Font::drawString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
|
||||
@ -380,10 +387,10 @@ void Font::drawString(ManagedSurface *dst, const Common::String &str, int x, int
|
||||
}
|
||||
}
|
||||
|
||||
void Font::drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax) const {
|
||||
drawString(&dst->_innerSurface, str, x, y, w, color, align, deltax);
|
||||
void Font::drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
|
||||
drawString(&dst->_innerSurface, str, x, y, w, color, align, deltax, useEllipsis);
|
||||
if (w != 0) {
|
||||
dst->addDirtyRect(getBoundingBox(str, x, y, w, align));
|
||||
dst->addDirtyRect(getBoundingBox(str, x, y, w, align, useEllipsis));
|
||||
}
|
||||
}
|
||||
|
||||
@ -477,4 +484,81 @@ TextAlign convertTextAlignH(TextAlign alignH, bool rtl) {
|
||||
}
|
||||
}
|
||||
|
||||
Common::U32String Font::handleEllipsis(const Common::U32String &input, int w) const {
|
||||
Common::U32String s = input;
|
||||
int width = getStringWidth(s);
|
||||
bool hasEllipsisAtEnd = false;
|
||||
|
||||
if (s.size() > 3 && s[s.size() - 1] == '.' && s[s.size() - 2] == '.' && s[s.size() - 3] == '.') {
|
||||
hasEllipsisAtEnd = true;
|
||||
}
|
||||
|
||||
if (width > w && hasEllipsisAtEnd) {
|
||||
// String is too wide. Check whether it ends in an ellipsis
|
||||
// ("..."). If so, remove that and try again!
|
||||
s.deleteLastChar();
|
||||
s.deleteLastChar();
|
||||
s.deleteLastChar();
|
||||
width = getStringWidth(s);
|
||||
}
|
||||
|
||||
if (width > w) {
|
||||
Common::U32String str;
|
||||
Common::U32String ellipsis("...");
|
||||
|
||||
// String is too wide. So we shorten it "intelligently" by
|
||||
// replacing parts of the string by an ellipsis. There are
|
||||
// three possibilities for this: replace the start, the end, or
|
||||
// the middle of the string. What is best really depends on the
|
||||
// context; but unless we want to make this configurable,
|
||||
// replacing the middle seems to be a good compromise.
|
||||
|
||||
const int ellipsisWidth = getStringWidth(ellipsis);
|
||||
|
||||
// SLOW algorithm to remove enough of the middle. But it is good enough
|
||||
// for now.
|
||||
const int halfWidth = (w - ellipsisWidth) / 2;
|
||||
int w2 = 0;
|
||||
Common::String::unsigned_type last = 0;
|
||||
uint i = 0;
|
||||
|
||||
for (; i < s.size(); ++i) {
|
||||
const Common::String::unsigned_type cur = s[i];
|
||||
int charWidth = getCharWidth(cur) + getKerningOffset(last, cur);
|
||||
if (w2 + charWidth > halfWidth)
|
||||
break;
|
||||
last = cur;
|
||||
w2 += charWidth;
|
||||
str += cur;
|
||||
}
|
||||
|
||||
// At this point we know that the first 'i' chars are together 'w2'
|
||||
// pixels wide. We took the first i-1, and add "..." to them.
|
||||
str += ellipsis;
|
||||
last = '.';
|
||||
|
||||
// The original string is width wide. Of those we already skipped past
|
||||
// w2 pixels, which means (width - w2) remain.
|
||||
// The new str is (w2+ellipsisWidth) wide, so we can accommodate about
|
||||
// (w - (w2+ellipsisWidth)) more pixels.
|
||||
// Thus we skip ((width - w2) - (w - (w2+ellipsisWidth))) =
|
||||
// (width + ellipsisWidth - w)
|
||||
int skip = width + ellipsisWidth - w;
|
||||
for (; i < s.size() && skip > 0; ++i) {
|
||||
const Common::String::unsigned_type cur = s[i];
|
||||
skip -= getCharWidth(cur) + getKerningOffset(last, cur);
|
||||
last = cur;
|
||||
}
|
||||
|
||||
// Append the remaining chars, if any
|
||||
for (; i < s.size(); ++i) {
|
||||
str += s[i];
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
* @return The actual area where the string is drawn.
|
||||
*/
|
||||
Common::Rect getBoundingBox(const Common::String &str, int x = 0, int y = 0, const int w = 0, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = false) const;
|
||||
Common::Rect getBoundingBox(const Common::U32String &str, int x = 0, int _y = 0, const int w = 0, TextAlign align = kTextAlignLeft) const;
|
||||
Common::Rect getBoundingBox(const Common::U32String &str, int x = 0, int _y = 0, const int w = 0, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = false) const;
|
||||
|
||||
/**
|
||||
* Draw a character at a specific point on a surface.
|
||||
@ -155,9 +155,9 @@ public:
|
||||
|
||||
// TODO: Add doxygen comments to this
|
||||
void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
|
||||
void drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0) const;
|
||||
void drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
|
||||
void drawString(ManagedSurface *dst, const Common::String &str, int x, int _y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
|
||||
void drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0) const;
|
||||
void drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
|
||||
|
||||
/**
|
||||
* Compute and return the width the string str has when rendered using this font.
|
||||
@ -191,6 +191,7 @@ public:
|
||||
|
||||
private:
|
||||
Common::String handleEllipsis(const Common::String &str, int w) const;
|
||||
Common::U32String handleEllipsis(const Common::U32String &str, int w) const;
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
Loading…
Reference in New Issue
Block a user