From 25feb9dbb597be0bce309641983c44181abf6450 Mon Sep 17 00:00:00 2001 From: Dav999-v Date: Sat, 21 Jan 2023 02:31:44 +0100 Subject: [PATCH] Make wordwrapping functions take font arguments They need to know how wide the text is going to be in a particular font, so font::string_wordwrap and font::string_wordwrap_balanced now take a flags argument like all the printing and dimensions-getting functions. next_wrap and next_wrap_s take a Font* now, they're internal to Font.cpp so they can take a Font and avoid double flag-parsing. But if any non-Font.cpp code needs next_wrap/next_wrap_s in the future, I'd just make a public wrapper that takes a uint32_t flags and passes the Font* to the internal functions. --- desktop_version/src/Editor.cpp | 6 +- desktop_version/src/Font.cpp | 202 ++++++++++---------- desktop_version/src/Font.h | 4 +- desktop_version/src/Game.cpp | 2 +- desktop_version/src/Graphics.cpp | 10 +- desktop_version/src/LocalizationStorage.cpp | 2 +- desktop_version/src/Script.cpp | 2 +- 7 files changed, 119 insertions(+), 109 deletions(-) diff --git a/desktop_version/src/Editor.cpp b/desktop_version/src/Editor.cpp index 488e9c1d..3f3a3e43 100644 --- a/desktop_version/src/Editor.cpp +++ b/desktop_version/src/Editor.cpp @@ -1161,7 +1161,7 @@ void editorrender(void) } short lines; - message = font::string_wordwrap(message, 312, &lines); + message = font::string_wordwrap(0, message, 312, &lines); short textheight = font::height(0)*lines; graphics.fill_rect(0,238-textheight,320,240, graphics.getRGB(32,32,32)); @@ -1264,7 +1264,7 @@ void editorrender(void) else if (ed.textmod) { short lines; - std::string wrapped = font::string_wordwrap(ed.textdesc, 312, &lines); + std::string wrapped = font::string_wordwrap(0, ed.textdesc, 312, &lines); short textheight = font::height(0)*lines+font::height(PR_FONT_LEVEL); graphics.fill_rect(0, 238-textheight, 320, 240, graphics.getRGB(32, 32, 32)); @@ -1604,7 +1604,7 @@ void editorrender(void) if(ed.notedelay>0 || ed.oldnotedelay>0) { short lines; - std::string wrapped = font::string_wordwrap(ed.note, 304, &lines); + std::string wrapped = font::string_wordwrap(0, ed.note, 304, &lines); short textheight = 8+(lines-1)*SDL_max(10, font::height(0)); short banner_y = 120 - textheight/2 - 5; diff --git a/desktop_version/src/Font.cpp b/desktop_version/src/Font.cpp index b1f6a049..664e0364 100644 --- a/desktop_version/src/Font.cpp +++ b/desktop_version/src/Font.cpp @@ -518,9 +518,95 @@ void destroy(void) unload_font_container(&fonts_main); } -static Font* container_get(FontContainer* container, uint8_t idx); // TODO TEMP TEMP TEMP +static Font* container_get(FontContainer* container, uint8_t idx) +{ + /* Get a certain font from the given container (with bounds checking). + * Does its best to return at least something, + * but if there are no fonts whatsoever, can return NULL. */ + + if (idx < container->count) + { + return &container->fonts[idx]; + } + if (font_idx_8x8 < fonts_main.count) + { + return &fonts_main.fonts[font_idx_8x8]; + } + if (fonts_main.count > 0) + { + return &fonts_main.fonts[0]; + } + if (fonts_custom.count > 0) + { + return &fonts_custom.fonts[0]; + } + return NULL; +} + +static Font* fontsel_to_font(int sel) +{ + /* Take font selection integer (0-31) and turn it into the correct Font + * 0: PR_FONT_INTERFACE - use interface font + * 1: PR_FONT_LEVEL - use level font + * 2: PR_FONT_8X8 - use 8x8 font no matter what + * 3-31: - use (main) font index 0-28 */ + + if (sel < 0) + { + // Shouldn't happen but better safe than sorry... + return NULL; + } + + switch (sel) + { + case 0: + return container_get(&fonts_main, loc::get_langmeta()->font_idx); + case 1: + if (font_idx_custom_is_custom) + { + return container_get(&fonts_custom, font_idx_custom); + } + else + { + return container_get(&fonts_main, font_idx_custom); + } + case 2: + return container_get(&fonts_main, font_idx_8x8); + } + + return container_get(&fonts_main, sel-3); +} + +#define FLAG_PART(start, count) ((flags >> start) % (1 << count)) +static PrintFlags decode_print_flags(uint32_t flags) +{ + PrintFlags pf; + pf.scale = FLAG_PART(0, 3) + 1; + pf.font_sel = fontsel_to_font(FLAG_PART(3, 5)); + + if (flags & PR_AB_IS_BRI) + { + pf.alpha = 255; + pf.colorglyph_bri = ~FLAG_PART(8, 8) & 0xff; + } + else + { + pf.alpha = ~FLAG_PART(8, 8) & 0xff; + pf.colorglyph_bri = 255; + } + + pf.border = flags & PR_BOR; + pf.align_cen = flags & PR_CEN; + pf.align_right = flags & PR_RIGHT; + pf.cjk_low = flags & PR_CJK_LOW; + pf.cjk_high = flags & PR_CJK_HIGH; + + return pf; +} +#undef FLAG_PART static bool next_wrap( + Font* f, size_t* start, size_t* len, const char* str, @@ -547,7 +633,7 @@ static bool next_wrap( goto next; } - linewidth += get_advance(container_get(&fonts_main, loc::get_langmeta()->font_idx), str[idx]); // TODO get font via argument! + linewidth += get_advance(f, str[idx]); switch (str[idx]) { @@ -584,6 +670,7 @@ next: } static bool next_wrap_s( + Font* f, char buffer[], const size_t buffer_size, size_t* start, @@ -593,7 +680,7 @@ static bool next_wrap_s( size_t len = 0; const size_t prev_start = *start; - const bool retval = next_wrap(start, &len, &str[*start], maxwidth); + const bool retval = next_wrap(f, start, &len, &str[*start], maxwidth); if (retval) { @@ -606,7 +693,7 @@ static bool next_wrap_s( return retval; } -std::string string_wordwrap(const std::string& s, int maxwidth, short *lines /*= NULL*/) +std::string string_wordwrap(const uint32_t flags, const std::string& s, int maxwidth, short *lines /*= NULL*/) { /* Return a string wordwrapped to a maximum limit by adding newlines. * CJK will need to have autowordwrap disabled and have manually inserted newlines. */ @@ -616,6 +703,12 @@ std::string string_wordwrap(const std::string& s, int maxwidth, short *lines /*= *lines = 1; } + PrintFlags pf = decode_print_flags(flags); + if (pf.font_sel == NULL) + { + return s; + } + const char* orig = s.c_str(); std::string result; @@ -627,7 +720,7 @@ std::string string_wordwrap(const std::string& s, int maxwidth, short *lines /*= size_t len = 0; const char* part = &orig[start]; - const bool retval = next_wrap(&start, &len, part, maxwidth); + const bool retval = next_wrap(pf.font_sel, &start, &len, part, maxwidth); if (!retval) { @@ -651,7 +744,7 @@ std::string string_wordwrap(const std::string& s, int maxwidth, short *lines /*= } } -std::string string_wordwrap_balanced(const std::string& s, int maxwidth) +std::string string_wordwrap_balanced(const uint32_t flags, const std::string& s, int maxwidth) { /* Return a string wordwrapped to a limit of maxwidth by adding newlines. * Try to fill the lines as far as possible, and return result where lines are most filled. @@ -664,7 +757,7 @@ std::string string_wordwrap_balanced(const std::string& s, int maxwidth) } short lines; - string_wordwrap(s, maxwidth, &lines); + string_wordwrap(flags, s, maxwidth, &lines); int bestwidth = maxwidth; if (lines > 1) @@ -672,7 +765,7 @@ std::string string_wordwrap_balanced(const std::string& s, int maxwidth) for (int curlimit = maxwidth; curlimit > 1; curlimit -= 8) { short try_lines; - string_wordwrap(s, curlimit, &try_lines); + string_wordwrap(flags, s, curlimit, &try_lines); if (try_lines > lines) { @@ -682,7 +775,7 @@ std::string string_wordwrap_balanced(const std::string& s, int maxwidth) } } - return string_wordwrap(s, bestwidth); + return string_wordwrap(flags, s, bestwidth); } std::string string_unwordwrap(const std::string& s) @@ -766,31 +859,6 @@ static int print_char( return glyph->advance * scale; } -static Font* container_get(FontContainer* container, uint8_t idx) -{ - /* Get a certain font from the given container (with bounds checking). - * Does its best to return at least something, - * but if there are no fonts whatsoever, can return NULL. */ - - if (idx < container->count) - { - return &container->fonts[idx]; - } - if (font_idx_8x8 < fonts_main.count) - { - return &fonts_main.fonts[font_idx_8x8]; - } - if (fonts_main.count > 0) - { - return &fonts_main.fonts[0]; - } - if (fonts_custom.count > 0) - { - return &fonts_custom.fonts[0]; - } - return NULL; -} - const char* get_main_font_name(uint8_t idx) { Font* f = container_get(&fonts_main, idx); @@ -801,68 +869,6 @@ const char* get_main_font_name(uint8_t idx) return f->name; } -static Font* fontsel_to_font(int sel) -{ - /* Take font selection integer (0-31) and turn it into the correct Font - * 0: PR_FONT_INTERFACE - use interface font - * 1: PR_FONT_LEVEL - use level font - * 2: PR_FONT_8X8 - use 8x8 font no matter what - * 3-31: - use (main) font index 0-28 */ - - if (sel < 0) - { - /* Shouldn't happen but better safe than sorry... */ - return NULL; - } - - switch (sel) - { - case 0: - return container_get(&fonts_main, loc::get_langmeta()->font_idx); - case 1: - if (font_idx_custom_is_custom) - { - return container_get(&fonts_custom, font_idx_custom); - } - else - { - return container_get(&fonts_main, font_idx_custom); - } - case 2: - return container_get(&fonts_main, font_idx_8x8); - } - - return container_get(&fonts_main, sel-3); -} - -#define FLAG_PART(start, count) ((flags >> start) % (1 << count)) -static PrintFlags decode_print_flags(uint32_t flags) -{ - PrintFlags pf; - pf.scale = FLAG_PART(0, 3) + 1; - pf.font_sel = fontsel_to_font(FLAG_PART(3, 5)); - - if (flags & PR_AB_IS_BRI) - { - pf.alpha = 255; - pf.colorglyph_bri = ~FLAG_PART(8, 8) & 0xff; - } - else - { - pf.alpha = ~FLAG_PART(8, 8) & 0xff; - pf.colorglyph_bri = 255; - } - - pf.border = flags & PR_BOR; - pf.align_cen = flags & PR_CEN; - pf.align_right = flags & PR_RIGHT; - pf.cjk_low = flags & PR_CJK_LOW; - pf.cjk_high = flags & PR_CJK_HIGH; - - return pf; -} -#undef FLAG_PART - bool glyph_dimensions(uint32_t flags, uint8_t* glyph_w, uint8_t* glyph_h) { /* Gets the dimensions (glyph_w and glyph_h) of a certain font. @@ -1040,7 +1046,7 @@ int print_wrap( { // Correct for the height of the resulting print. size_t len = 0; - while (next_wrap(&start, &len, &str[start], maxwidth)) + while (next_wrap(pf.font_sel, &start, &len, &str[start], maxwidth)) { y += linespacing; } @@ -1048,7 +1054,7 @@ int print_wrap( start = 0; } - while (next_wrap_s(buffer, sizeof(buffer), &start, str, maxwidth)) + while (next_wrap_s(pf.font_sel, buffer, sizeof(buffer), &start, str, maxwidth)) { print(flags, x, y, buffer, r, g, b); diff --git a/desktop_version/src/Font.h b/desktop_version/src/Font.h index 72072dd4..c56caf92 100644 --- a/desktop_version/src/Font.h +++ b/desktop_version/src/Font.h @@ -70,8 +70,8 @@ void load_custom(const char* name); void unload_custom(void); void destroy(void); -std::string string_wordwrap(const std::string& s, int maxwidth, short *lines = NULL); -std::string string_wordwrap_balanced(const std::string& s, int maxwidth); +std::string string_wordwrap(uint32_t flags, const std::string& s, int maxwidth, short *lines = NULL); +std::string string_wordwrap_balanced(uint32_t flags, const std::string& s, int maxwidth); std::string string_unwordwrap(const std::string& s); bool glyph_dimensions(uint32_t flags, uint8_t* glyph_w, uint8_t* glyph_h); diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index fca7b922..6f909f0a 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -673,7 +673,7 @@ void Game::crewmate_textbox(const int r, const int g, const int b) /* This is a special case for wrapping, we MUST have two lines. * So just make sure it can't fit in one line. */ const char* text = loc::gettext("You have rescued a crew member!"); - std::string wrapped = font::string_wordwrap_balanced(text, font::len(PR_FONT_INTERFACE, text)-1); + std::string wrapped = font::string_wordwrap_balanced(PR_FONT_INTERFACE, text, font::len(PR_FONT_INTERFACE, text)-1); size_t startline = 0; size_t newline; diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 1bf42dbf..7a9b80ca 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -1770,12 +1770,12 @@ void Graphics::drawtrophytext(void) short lines; if (top_text != NULL) { - font::string_wordwrap(top_text, 304, &lines); + font::string_wordwrap(0, top_text, 304, &lines); font::print_wrap(PR_CEN | PR_COLORGLYPH_BRI(brightness) | PR_BOR, -1, 11-(lines-1)*5, top_text, temp, temp2, temp3); } if (bottom_text != NULL) { - font::string_wordwrap(bottom_text, 304, &lines); + font::string_wordwrap(0, bottom_text, 304, &lines); font::print_wrap(PR_CEN | PR_COLORGLYPH_BRI(brightness) | PR_BOR, -1, 221-(lines-1)*5, bottom_text, temp, temp2, temp3); } } @@ -3049,7 +3049,11 @@ int Graphics::textboxwrap(int pad) vlog_error("textboxwrap() has no first line!"); return 16; } - std::string wrapped = font::string_wordwrap_balanced(textboxes[m].lines[0], 36*8 - pad*8); + std::string wrapped = font::string_wordwrap_balanced( + textboxes[m].print_flags, + textboxes[m].lines[0], + 36*8 - pad*8 + ); textboxes[m].lines.clear(); size_t startline = 0; diff --git a/desktop_version/src/LocalizationStorage.cpp b/desktop_version/src/LocalizationStorage.cpp index 79d696b8..1a7d5df8 100644 --- a/desktop_version/src/LocalizationStorage.cpp +++ b/desktop_version/src/LocalizationStorage.cpp @@ -318,7 +318,7 @@ static bool max_check_string(const char* str, const char* max) else { short lines; - font::string_wordwrap(str, max_w_px, &lines); // TODO: needs to be passed the font! + font::string_wordwrap(print_flags, str, max_w_px, &lines); does_overflow = lines*SDL_max(10, font_h) > (short) max_h_px; } diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 51ec3c89..78929bca 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -2507,7 +2507,7 @@ void scriptclass::translate_dialogue(void) } else { - tra = font::string_wordwrap_balanced(format->text, format->wraplimit); + tra = font::string_wordwrap_balanced(PR_FONT_LEVEL, format->text, format->wraplimit); } textcentertext = format->centertext;