mirror of
https://github.com/libretro/scummvm.git
synced 2024-11-28 11:50:46 +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()) {
|
if (!drawArea.isEmpty()) {
|
||||||
Surface textAreaSurface = _activeSurface->getSubArea(drawArea);
|
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);
|
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
|
// In case no width was given we cannot any alignment apart from left
|
||||||
// alignment.
|
// alignment.
|
||||||
if (w == 0) {
|
if (w == 0) {
|
||||||
|
if (useEllipsis) {
|
||||||
|
warning("Font::getBoundingBox: Requested ellipsis when no width was specified");
|
||||||
|
}
|
||||||
|
|
||||||
if (align != kTextAlignLeft) {
|
if (align != kTextAlignLeft) {
|
||||||
warning("Font::getBoundingBox: Requested text alignment when no width was specified");
|
warning("Font::getBoundingBox: Requested text alignment when no width was specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEllipsis = false;
|
||||||
align = kTextAlignLeft;
|
align = kTextAlignLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Common::U32String str = useEllipsis ? handleEllipsis(input, w) : input;
|
||||||
return getBoundingBoxImpl(*this, str, x, y, w, align, 0);
|
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);
|
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 {
|
void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
|
||||||
drawStringImpl(*this, dst, str, x, y, w, color, align, deltax);
|
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 {
|
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 {
|
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);
|
drawString(&dst->_innerSurface, str, x, y, w, color, align, deltax, useEllipsis);
|
||||||
if (w != 0) {
|
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
|
} // End of namespace Graphics
|
||||||
|
@ -128,7 +128,7 @@ public:
|
|||||||
* @return The actual area where the string is drawn.
|
* @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::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.
|
* Draw a character at a specific point on a surface.
|
||||||
@ -155,9 +155,9 @@ public:
|
|||||||
|
|
||||||
// TODO: Add doxygen comments to this
|
// 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::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::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.
|
* Compute and return the width the string str has when rendered using this font.
|
||||||
@ -191,6 +191,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Common::String handleEllipsis(const Common::String &str, int w) const;
|
Common::String handleEllipsis(const Common::String &str, int w) const;
|
||||||
|
Common::U32String handleEllipsis(const Common::U32String &str, int w) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Graphics
|
} // End of namespace Graphics
|
||||||
|
Loading…
Reference in New Issue
Block a user