Skip to content

Commit

Permalink
WidgetLabel: Ensure that buffer height is large enough for text
Browse files Browse the repository at this point in the history
The result of TTF_FontLineSkip() is not always larger than
TTF_SizeUTF8(), so we should use the larger value when possible to
prevent the top/bottom edges of labels from being cut off.

FontEngine changes:
- renamed calc_size -> calcSizeWrapped
- renamed calc_width -> calcSize (returns both dimensions now as
  a Point)
  • Loading branch information
dorkster committed Jan 27, 2025
1 parent 4904a10 commit eb7fc85
Show file tree
Hide file tree
Showing 13 changed files with 40 additions and 37 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Engine fixes:
* Errors in saved fog-of-war data no longer causes a forced exit & mod reset.
* Primary stat upgrade buttons are now hidden in the Character menu if the cooresponding label is hidden.
* Fixed crash in action bar when less than 12 slots were defined.
* Fixed single-line text having the top/bottom "cut off" with certain fonts.
* Android: Fix 'Flare' directory not being automatically created.
* Android: Added a dialog to direct the player to the wiki page for installing if no game data is found.

Expand Down
28 changes: 14 additions & 14 deletions src/FontEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,16 @@ size_t FontEngine::stringToFontColor(const std::string& val) {
/**
* Using the given wrap width, calculate the width and height necessary to display this text
*/
Point FontEngine::calc_size(const std::string& text_with_newlines, int width) {
Point FontEngine::calcSizeWrapped(const std::string& text_with_newlines, int width) {
char newline = 10;

std::string text = text_with_newlines;

// if this contains newlines, recurse
size_t check_newline = text.find_first_of(newline);
if (check_newline != std::string::npos) {
Point p1 = calc_size(text.substr(0, check_newline), width);
Point p2 = calc_size(text.substr(check_newline+1, text.length()), width);
Point p1 = calcSizeWrapped(text.substr(0, check_newline), width);
Point p2 = calcSizeWrapped(text.substr(check_newline+1, text.length()), width);
Point p3;

if (p1.x > p2.x) p3.x = p1.x;
Expand Down Expand Up @@ -147,13 +147,13 @@ Point FontEngine::calc_size(const std::string& text_with_newlines, int width) {

builder += next_word;

if (calc_width(builder) > width) {
if (calcSize(builder).x > width) {

// this word can't fit on this line, so word wrap
if (!builder_prev.empty()) {
height += getLineHeight();
if (calc_width(builder_prev) > max_width) {
max_width = calc_width(builder_prev);
if (calcSize(builder_prev).x > max_width) {
max_width = calcSize(builder_prev).x;
}
}

Expand All @@ -163,8 +163,8 @@ Point FontEngine::calc_size(const std::string& text_with_newlines, int width) {

if (!long_token.empty()) {
while (!long_token.empty()) {
if (calc_width(next_word) > max_width) {
max_width = calc_width(next_word);
if (calcSize(next_word).x > max_width) {
max_width = calcSize(next_word).x;
}
height += getLineHeight();

Expand Down Expand Up @@ -194,8 +194,8 @@ Point FontEngine::calc_size(const std::string& text_with_newlines, int width) {
builder = Parse::trim(builder); //removes whitespace that shouldn't be included in the size
if (!builder.empty())
height += getLineHeight();
if (calc_width(builder) > max_width)
max_width = calc_width(builder);
if (calcSize(builder).x > max_width)
max_width = calcSize(builder).x;

// handle blank lines
if (text_with_newlines == " ")
Expand All @@ -216,11 +216,11 @@ Rect FontEngine::position(const std::string& text, int x, int y, int justify) {
dest_rect.y = y;
}
else if (justify == JUSTIFY_RIGHT) {
dest_rect.x = x - calc_width(text);
dest_rect.x = x - calcSize(text).x;
dest_rect.y = y;
}
else if (justify == JUSTIFY_CENTER) {
dest_rect.x = x - calc_width(text)/2;
dest_rect.x = x - (calcSize(text).x / 2);
dest_rect.y = y;
}
else {
Expand Down Expand Up @@ -260,7 +260,7 @@ void FontEngine::render(const std::string& text, int x, int y, int justify, Imag

builder += next_word;

if (calc_width(builder) > width) {
if (calcSize(builder).x > width) {
if (!builder_prev.empty()) {
renderInternal(builder_prev, x, cursor_y, justify, target, color);
cursor_y += getLineHeight();
Expand Down Expand Up @@ -319,7 +319,7 @@ std::string FontEngine::popTokenByWidth(std::string& text, int width) {
if (i < text.length() && (text[i] & 0xc0) == 0x80)
continue;

if (calc_width(text.substr(0, i)) > width)
if (calcSize(text.substr(0, i)).x > width)
break;

new_length = i;
Expand Down
4 changes: 2 additions & 2 deletions src/FontEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class FontEngine {

Color getColor(size_t _color);

Point calc_size(const std::string& text_with_newlines, int width);
Point calcSizeWrapped(const std::string& text_with_newlines, int width);

void render(const std::string& text, int x, int y, int justify, Image *target, int width, const Color& color);
void renderShadowed(const std::string& text, int x, int y, int justify, Image *target, int width, const Color& color);
Expand All @@ -87,7 +87,7 @@ class FontEngine {
virtual int getFontHeight() = 0;

virtual void setFont(const std::string& _font) = 0;
virtual int calc_width(const std::string& text) = 0;
virtual Point calcSize(const std::string& text) = 0;
virtual std::string trimTextToWidth(const std::string& text, const int width, const bool use_ellipsis, size_t left_pos) = 0;

int cursor_y;
Expand Down
2 changes: 1 addition & 1 deletion src/GameStateCutscene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ void Scene::refreshWidgets() {
int caption_width = settings->view_w - static_cast<int>(settings->view_w * (cutscene_settings.caption_margins.x * 2.0f));
font->setFont("font_captions");
int padding = font->getLineHeight()/4;
Point caption_size = font->calc_size(caption, caption_width);
Point caption_size = font->calcSizeWrapped(caption, caption_width);
Point caption_size_padded(caption_size.x + padding*2, caption_size.y + padding*2);

if (!caption_box) {
Expand Down
2 changes: 1 addition & 1 deletion src/MenuBook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ void MenuBook::refreshText() {

// render text to surface
font->setFont(text[i].font);
Point pSize = font->calc_size(text[i].text, text[i].size.w);
Point pSize = font->calcSizeWrapped(text[i].text, text[i].size.w);
Image *graphics = NULL;
if (text[i].shadow) {
graphics = render_device->createImage(text[i].size.w + 1, pSize.y + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/MenuHUDLog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ void MenuHUDLog::add(const std::string& s, int type) {

// render the log entry and store it in a buffer
font->setFont("font_regular");
Point size = font->calc_size(log_msg.back(), window_area.w - (paragraph_spacing*2));
Point size = font->calcSizeWrapped(log_msg.back(), window_area.w - (paragraph_spacing*2));
Image *graphics = render_device->createImage(size.x, size.y);
font->renderShadowed(log_msg.back(), 0, 0, FontEngine::JUSTIFY_LEFT, graphics, window_area.w - (paragraph_spacing*2), font->getColor(FontEngine::COLOR_MENU_NORMAL));
msg_buffer.push_back(graphics->createSprite());
Expand Down
2 changes: 1 addition & 1 deletion src/MenuTalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void MenuTalker::createBuffer() {
line = Utils::substituteVarsInString(npc->dialog[dialog_node][event_cursor].s, pc);

// render dialog text to the scrollbox buffer
Point line_size = font->calc_size(line,textbox->pos.w-(text_offset.x*2));
Point line_size = font->calcSizeWrapped(line,textbox->pos.w-(text_offset.x*2));
textbox->resize(textbox->pos.w, line_size.y + button_height);
font->setFont(font_dialog);
font->render(
Expand Down
16 changes: 8 additions & 8 deletions src/SDLFontEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,14 @@ int SDLFontEngine::getFontHeight() {
/**
* For single-line text, just calculate the width
*/
int SDLFontEngine::calc_width(const std::string& text) {
Point SDLFontEngine::calcSize(const std::string& text) {
if (!isActiveFontValid())
return 1;
return Point(1, 1);

int w, h;
TTF_SizeUTF8(active_font->ttfont, text.c_str(), &w, &h);

return w;
return Point(w, h);
}

/**
Expand All @@ -149,28 +149,28 @@ int SDLFontEngine::calc_width(const std::string& text) {
* It ensures that this character is visible, chopping the end of the string if needed.
*/
std::string SDLFontEngine::trimTextToWidth(const std::string& text, const int width, const bool use_ellipsis, size_t left_pos) {
if (width >= calc_width(text))
if (width >= calcSize(text).x)
return text;

size_t text_length = text.length();
size_t ret_length = text_length;
int total_width = (use_ellipsis ? width - calc_width("...") : width);
int total_width = (use_ellipsis ? width - calcSize("...").x : width);

for (size_t i=text_length; i>0; i--) {
if (use_ellipsis) {
if (total_width < calc_width(text.substr(0,ret_length)))
if (total_width < calcSize(text.substr(0,ret_length)).x)
ret_length = i;
else
break;
}
else if (left_pos < text_length - ret_length) {
if (total_width < calc_width(text.substr(left_pos,ret_length)))
if (total_width < calcSize(text.substr(left_pos,ret_length)).x)
ret_length = i;
else
break;
}
else {
if (total_width < calc_width(text.substr(text_length-ret_length)))
if (total_width < calcSize(text.substr(text_length-ret_length)).x)
ret_length = i;
else
break;
Expand Down
2 changes: 1 addition & 1 deletion src/SDLFontEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class SDLFontEngine : public FontEngine {

void setFont(const std::string& _font);

int calc_width(const std::string& text);
Point calcSize(const std::string& text);
std::string trimTextToWidth(const std::string& text, const int width, const bool use_ellipsis, size_t left_pos);
};

Expand Down
2 changes: 1 addition & 1 deletion src/Version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ FLARE. If not, see http://www.gnu.org/licenses/

#include <SDL.h>

Version VersionInfo::ENGINE(1, 14, 98);
Version VersionInfo::ENGINE(1, 14, 99);
Version VersionInfo::MIN(0, 0, 0);
Version VersionInfo::MAX(USHRT_MAX, USHRT_MAX, USHRT_MAX);

Expand Down
10 changes: 6 additions & 4 deletions src/WidgetLabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,16 @@ void WidgetLabel::recacheTextSprite() {
std::string temp_text = text;

font->setFont(font_style);
bounds.w = font->calc_width(temp_text);
bounds.h = font->getFontHeight();

if (max_width > 0 && bounds.w > max_width) {
Point p = font->calcSize(temp_text);
if (max_width > 0 && p.x > max_width) {
temp_text = font->trimTextToWidth(text, max_width, FontEngine::USE_ELLIPSIS, 0);
bounds.w = font->calc_width(temp_text);
p = font->calcSize(temp_text);
}

bounds.w = p.x;
bounds.h = std::max(p.y, font->getFontHeight());

image = render_device->createImage(bounds.w, bounds.h);
if (!image) return;

Expand Down
4 changes: 2 additions & 2 deletions src/WidgetLog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void WidgetLog::refresh() {
// Resize the scrollbox content area first
for (size_t i=0; i<messages.size(); i++) {
setFont(styles[i]);
Point size = font->calc_size(messages[i], content_width);
Point size = font->calcSizeWrapped(messages[i], content_width);
y += size.y+paragraph_spacing;

if (separators[i])
Expand All @@ -97,7 +97,7 @@ void WidgetLog::refresh() {
// Render messages into the scrollbox area
for (size_t i = messages.size(); i > 0; i--) {
setFont(styles[i-1]);
Point size = font->calc_size(messages[i-1], content_width);
Point size = font->calcSizeWrapped(messages[i-1], content_width);
Image* render_target = scroll_box->contents->getGraphics();

if (!separators.empty() && separators[i-1]) {
Expand Down
2 changes: 1 addition & 1 deletion src/WidgetTooltip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ bool WidgetTooltip::createBuffer(TooltipData &tip) {
font->setFont("font_regular");

// calculate the full size to display a multi-line tooltip
Point size = font->calc_size(fulltext, eset->tooltips.width - (eset->tooltips.margin*2));
Point size = font->calcSizeWrapped(fulltext, eset->tooltips.width - (eset->tooltips.margin*2));

// WARNING: dynamic memory allocation. Be careful of memory leaks.
if (sprite_buf) {
Expand Down

0 comments on commit eb7fc85

Please sign in to comment.