1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-23 01:59:43 +01:00

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.
This commit is contained in:
Dav999-v 2023-01-21 02:31:44 +01:00 committed by Misa Elizabeth Kai
parent 0eaceed0a2
commit 25feb9dbb5
7 changed files with 119 additions and 109 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;