diff --git a/desktop_version/src/Font.cpp b/desktop_version/src/Font.cpp index 8b58252c..1f1f387d 100644 --- a/desktop_version/src/Font.cpp +++ b/desktop_version/src/Font.cpp @@ -4,6 +4,7 @@ #include #include "Alloc.h" +#include "Constants.h" #include "FileSystemUtils.h" #include "Graphics.h" #include "UtilityClass.h" @@ -313,21 +314,22 @@ int get_advance(const Font* f, const uint32_t codepoint) return glyph->advance; } -int print_char( +static int print_char( const Font* f, const uint32_t codepoint, const int x, const int y, const int scale, - const uint8_t r, - const uint8_t g, - const uint8_t b, - const uint8_t a + uint8_t r, + uint8_t g, + uint8_t b, + const uint8_t a, + const uint8_t colorglyph_bri ) { /* Draws the glyph for a codepoint at x,y. * Returns the amount of pixels to advance the cursor. */ - GlyphInfo* glyph = find_glyphinfo(f, codepoint);; + GlyphInfo* glyph = find_glyphinfo(f, codepoint); if (glyph == NULL) { return f->glyph_w * scale; @@ -335,14 +337,109 @@ int print_char( if (glyph->flags & GLYPH_COLOR && (r | g | b) != 0) { - graphics.draw_grid_tile(f->image, glyph->image_idx, x, y, f->glyph_w, f->glyph_h, 255, 255, 255, 255, scale, scale * (graphics.flipmode ? -1 : 1)); - } - else - { - graphics.draw_grid_tile(f->image, glyph->image_idx, x, y, f->glyph_w, f->glyph_h, r, g, b, a, scale, scale * (graphics.flipmode ? -1 : 1)); + r = g = b = colorglyph_bri; } + graphics.draw_grid_tile(f->image, glyph->image_idx, x, y, f->glyph_w, f->glyph_h, r, g, b, a, scale, scale * (graphics.flipmode ? -1 : 1)); + return glyph->advance * scale; } +#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 = 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 + +void print( + const uint32_t flags, + int x, + int y, + const std::string& text, + const uint8_t r, + const uint8_t g, + const uint8_t b +) +{ + PrintFlags pf = decode_print_flags(flags); + + // TODO pf.font_sel + + if (pf.align_cen || pf.align_right) + { + const int textlen = graphics.len(text) * pf.scale; + + if (pf.align_cen) + { + if (x == -1) + { + x = SCREEN_WIDTH_PIXELS / 2; + } + x = SDL_max(x - textlen/2, 0); + } + else + { + x -= textlen; + } + } + // TODO cjk_low/cjk_high + + if (pf.border && !graphics.notextoutline) + { + static const int offsets[4][2] = {{0,-1}, {-1,0}, {1,0}, {0,1}}; + + for (int offset = 0; offset < 4; offset++) + { + print( + flags & ~PR_BOR & ~PR_CEN & ~PR_RIGHT, + x + offsets[offset][0]*pf.scale, + y + offsets[offset][1]*pf.scale, + text, + 0, 0, 0 + ); + } + } + + int position = 0; + std::string::const_iterator iter = text.begin(); + while (iter != text.end()) + { + const uint32_t character = utf8::unchecked::next(iter); + position += font::print_char( + &font::temp_bfont, + character, + x + position, + y, + pf.scale, + r, + g, + b, + pf.alpha, + pf.colorglyph_bri + ); + } +} + } // namespace font diff --git a/desktop_version/src/Font.h b/desktop_version/src/Font.h index c460cc03..c9e91a93 100644 --- a/desktop_version/src/Font.h +++ b/desktop_version/src/Font.h @@ -1,8 +1,34 @@ +/* + * == SOME TEXT PRINTING EXAMPLES == + * + * Standard print + * font::print(0, 50, 50, "Hello world!", 255, 255, 255); + * + * Centered text + * font::print(PR_CEN, -1, 50, "Hello world!", 255, 255, 255); + * (set X to -1, unless you want to center *around* X) + * + * 2x scale + * font::print(PR_2X, 50, 50, "V", 255, 255, 255); + * + * Centered 2x scale + * font::print(PR_CEN | PR_2X, -1, 50, "V", 255, 255, 255); + * + * Right-aligned 3x scale with a border around it + * font::print(PR_RIGHT | PR_3X | PR_BOR, 320, 50, "V", 255, 255, 255); + * + * Wordwrapped centered text + * font::print_wrap(PR_CEN, -1, 50, "Hello world, this will wordwrap to the screen width", 255, 255, 255); + * + */ + + #ifndef FONT_H #define FONT_H #include #include +#include #include "GraphicsUtil.h" @@ -34,6 +60,43 @@ struct Font GlyphInfo* glyph_page[FONT_N_PAGES]; }; +struct PrintFlags +{ + uint8_t scale; + uint8_t font_sel; + uint8_t alpha; + uint8_t colorglyph_bri; + bool border; + bool align_cen; + bool align_right; + bool cjk_low; + bool cjk_high; +}; + +#define PR_1X (0 << 0) /* default, 1x scale */ +#define PR_2X (1 << 0) /* 2x scale */ +#define PR_3X (2 << 0) /* etc */ +#define PR_4X (3 << 0) +#define PR_5X (4 << 0) +#define PR_6X (5 << 0) +#define PR_7X (6 << 0) +#define PR_8X (7 << 0) +#define PR_FONT_INTERFACE (0 << 3) /* default, use interface font */ +#define PR_FONT_LEVEL (1 << 3) /* use level-specific font (room names, cutscene dialogue, etc) */ +#define PR_FONT_8X8 (2 << 3) /* use 8x8 font no matter what */ +#define PR_AB_IS_BRI (1 << 16) +#define PR_ALPHA(value) /* use this alpha value 0-255 (incompatible with PR_COLORGLYPH_BRI) */\ + ((~SDL_clamp((int)(value), 0, 255) & 0xff) << 8) +#define PR_COLORGLYPH_BRI(value) /* use this brightness 0-255 for colored glyphs (button icons) */\ + (((~SDL_clamp((int)(value), 0, 255) & 0xff) << 8) | PR_AB_IS_BRI) +#define PR_BOR (1 << 17) /* draw a black border around the text (was bprint/bigbprint) */ +#define PR_LEFT (0 << 18) /* default, left-align text/place at x coordinate */ +#define PR_CEN (1 << 18) /* center-align text relative to X (X is center) or to screen if X == -1 */ +#define PR_RIGHT (2 << 18) /* right-align text to X (X is now the right border, not left border) */ +#define PR_CJK_CEN (0 << 20) /* default, larger fonts should stick out on top and bottom compared to 8x8 font */ +#define PR_CJK_LOW (1 << 20) /* larger fonts should stick out fully on the bottom (draw at Y) */ +#define PR_CJK_HIGH (2 << 20) /* larger fonts should stick out fully on the top */ + extern Font temp_bfont; void load_main(void); @@ -42,7 +105,8 @@ void unload_custom(void); void destroy(void); int get_advance(const Font* f, uint32_t codepoint); // TODO de-api -int print_char(const Font* f, uint32_t codepoint, int x, int y, int scale, uint8_t r, uint8_t g, uint8_t b, uint8_t a); // TODO de-api + +void print(uint32_t flags, int x, int y, const std::string& text, uint8_t r, uint8_t g, uint8_t b); } // namespace font diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 8aa0c5fb..58282ca6 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -337,43 +337,21 @@ void Graphics::map_option(int opt, int num_opts, const std::string& text, bool s } } -void Graphics::do_print( - const int x, - const int y, - const std::string& text, - int r, - int g, - int b, - int a, - const int scale -) { - // TODO do something with flipmode - - int position = 0; - std::string::const_iterator iter = text.begin(); - - r = SDL_clamp(r, 0, 255); - g = SDL_clamp(g, 0, 255); - b = SDL_clamp(b, 0, 255); - a = SDL_clamp(a, 0, 255); - - while (iter != text.end()) - { - const uint32_t character = utf8::unchecked::next(iter); - position += font::print_char(&font::temp_bfont, character, x + position, y, scale, r, g, b, a); - } -} - -void Graphics::Print( int _x, int _y, const std::string& _s, int r, int g, int b, bool cen /*= false*/ ) { - return PrintAlpha(_x,_y,_s,r,g,b,255,cen); -} - -void Graphics::PrintAlpha( int _x, int _y, const std::string& _s, int r, int g, int b, int a, bool cen /*= false*/ ) -{ +void Graphics::Print( int x, int y, const std::string& text, int r, int g, int b, bool cen /*= false*/ ) { + // DEPRECATED if (cen) - _x = ((160 ) - ((len(_s)) / 2)); + font::print(PR_CEN, -1, y, text, r, g, b); + else + font::print(0, x, y, text, r, g, b); +} - return do_print(_x, _y, _s, r, g, b, a, 1); +void Graphics::PrintAlpha( int x, int y, const std::string& text, int r, int g, int b, int a, bool cen /*= false*/ ) +{ + // DEPRECATED + if (cen) + font::print(PR_ALPHA(a) | PR_CEN, -1, y, text, r, g, b); + else + font::print(PR_ALPHA(a), x, y, text, r, g, b); } bool Graphics::next_wrap( @@ -520,38 +498,24 @@ int Graphics::PrintWrap( } -void Graphics::bigprint( int _x, int _y, const std::string& _s, int r, int g, int b, bool cen, int sc ) +void Graphics::bigprint( int x, int y, const std::string& text, int r, int g, int b, bool cen, int sc ) { + // DEPRECATED. Also, use PR_2X/PR_3X/etc directly + int PR_scX = (sc-1); if (cen) - { - const int len_ = len(_s); - _x = SDL_max(160 - (int((len_/ 2.0)*sc)), 0 ); - } - - return do_print(_x, _y, _s, r, g, b, 255, sc); + font::print(PR_scX | PR_CEN, -1, y, text, r, g, b); + else + font::print(PR_scX, x, y, text, r, g, b); } -void Graphics::bigbprint(int x, int y, const std::string& s, int r, int g, int b, bool cen, int sc) +void Graphics::bigbprint(int x, int y, const std::string& text, int r, int g, int b, bool cen, int sc) { - if (!notextoutline) - { - bigprint(x, y - sc, s, 0, 0, 0, cen, sc); - if (cen) - { - const int len_ = len(s); - int x_cen = SDL_max(160 - (len_ / 2) * sc, 0); - bigprint(x_cen - sc, y, s, 0, 0, 0, false, sc); - bigprint(x_cen + sc, y, s, 0, 0, 0, false, sc); - } - else - { - bigprint(x - sc, y, s, 0, 0, 0, cen, sc); - bigprint(x + sc, y, s, 0, 0, 0, cen, sc); - } - bigprint(x, y + sc, s, 0, 0, 0, cen, sc); - } - - bigprint(x, y, s, r, g, b, cen, sc); + // DEPRECATED. Also, use PR_2X/PR_3X/etc directly + int PR_scX = (sc-1); + if (cen) + font::print(PR_scX | PR_CEN | PR_BOR, -1, y, text, r, g, b); + else + font::print(PR_scX | PR_BOR, x, y, text, r, g, b); } int Graphics::len(const std::string& t) @@ -694,30 +658,21 @@ std::string Graphics::string_unwordwrap(const std::string& s) return result; } -void Graphics::bprint( int x, int y, const std::string& t, int r, int g, int b, bool cen /*= false*/ ) { - bprintalpha(x,y,t,r,g,b,255,cen); +void Graphics::bprint( int x, int y, const std::string& text, int r, int g, int b, bool cen /*= false*/ ) { + // DEPRECATED + if (cen) + font::print(PR_CEN | PR_BOR, -1, y, text, r, g, b); + else + font::print(PR_BOR, x, y, text, r, g, b); } -void Graphics::bprintalpha( int x, int y, const std::string& t, int r, int g, int b, int a, bool cen /*= false*/ ) +void Graphics::bprintalpha( int x, int y, const std::string& text, int r, int g, int b, int a, bool cen /*= false*/ ) { - if (!notextoutline) - { - PrintAlpha(x, y - 1, t, 0, 0, 0, a, cen); - if (cen) - { - const int x_cen = 160 - len(t)/2; - PrintAlpha(x_cen - 1, y, t, 0, 0, 0, a, false); - PrintAlpha(x_cen + 1, y, t, 0, 0, 0, a, false); - } - else - { - PrintAlpha(x -1, y, t, 0, 0, 0, a, cen); - PrintAlpha(x +1, y, t, 0, 0, 0, a, cen); - } - PrintAlpha(x, y+1, t, 0, 0, 0, a, cen); - } - - PrintAlpha(x, y, t, r, g, b, a, cen); + // DEPRECATED + if (cen) + font::print(PR_ALPHA(a) | PR_CEN | PR_BOR, -1, y, text, r, g, b); + else + font::print(PR_ALPHA(a) | PR_BOR, x, y, text, r, g, b); } void Graphics::printcrewname( int x, int y, int t ) @@ -1181,7 +1136,7 @@ void Graphics::drawgui(void) for (j = 0; j < textboxes[i].lines.size(); j++) { - Print(textboxes[i].xp + 8, yp + text_yoff + text_sign * (j * 8), textboxes[i].lines[j], r, g, b); + font::print(PR_COLORGLYPH_BRI(tl_lerp*255), textboxes[i].xp + 8, yp + text_yoff + text_sign * (j * 8), textboxes[i].lines[j], r, g, b); } } @@ -2043,6 +1998,7 @@ void Graphics::drawgravityline( int t ) void Graphics::drawtrophytext(void) { int temp, temp2, temp3; + int brightness; if (obj.trophytext < 15) { @@ -2050,12 +2006,14 @@ void Graphics::drawtrophytext(void) temp = (196 * usethismult) / 15; temp2 = (196 * usethismult) / 15; temp3 = ((255 - help.glow) * usethismult) / 15; + brightness = (usethismult/15.0)*255; } else { temp = 196; temp2 = 196; temp3 = 255 - help.glow; + brightness = 255; } /* These were originally all at the top of the screen, but might be too tight for localization. @@ -2135,6 +2093,7 @@ void Graphics::drawtrophytext(void) } /* These were `bprint` before */ + // TODO: add PR_COLORGLYPH_BRI(brightness) | PR_BOR short lines; if (top_text != NULL) { @@ -3589,49 +3548,24 @@ void Graphics::renderfixedpost(void) } } -void Graphics::bigrprint(int x, int y, const std::string& t, int r, int g, int b, bool cen, float sc) +void Graphics::bigrprint(int x, int y, const std::string& text, int r, int g, int b, bool cen, int sc) { - const int len_ = len(t); - - x = x / (sc); - - x -= len_; - + // DEPRECATED. Also, use PR_2X/PR_3X/etc directly + int PR_scX = (sc-1); if (cen) - { - x = SDL_max(160 - (int((len_/ 2.0)*sc)), 0 ); - } + font::print(PR_scX | PR_CEN, -1, y, text, r, g, b); else - { - x *= (sc); - } - - return do_print(x, y, t, r, g, b, 255, sc); + font::print(PR_scX | PR_RIGHT, x, y, text, r, g, b); } -void Graphics::bigbrprint(int x, int y, const std::string& s, int r, int g, int b, bool cen, float sc) +void Graphics::bigbrprint(int x, int y, const std::string& text, int r, int g, int b, bool cen, int sc) { - if (!notextoutline) - { - const int len_ = len(s); - int x_o = x / sc - len_; - bigrprint(x, y - sc, s, 0, 0, 0, cen, sc); - if (cen) - { - x_o = SDL_max(160 - (len_ / 2) * sc, 0); - bigprint(x_o - sc, y, s, 0, 0, 0, false, sc); - bigprint(x_o + sc, y, s, 0, 0, 0, false, sc); - } - else - { - x_o *= sc; - bigprint(x_o - sc, y, s, 0, 0, 0, false, sc); - bigprint(x_o + sc, y, s, 0, 0, 0, false, sc); - } - bigrprint(x, y + sc, s, 0, 0, 0, cen, sc); - } - - bigrprint(x, y, s, r, g, b, cen, sc); + // DEPRECATED. Also, use PR_2X/PR_3X/etc directly + int PR_scX = (sc-1); + if (cen) + font::print(PR_scX | PR_CEN | PR_BOR, -1, y, text, r, g, b); + else + font::print(PR_scX | PR_RIGHT | PR_BOR, x, y, text, r, g, b); } void Graphics::drawtele(int x, int y, int t, const SDL_Color color) diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index ce32c136..af35e906 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -202,8 +202,6 @@ public: void map_option(int opt, int num_opts, const std::string& text, bool selected = false); - void do_print(int x, int y, const std::string& text, int r, int g, int b, int a, int scale); - void Print(int _x, int _y, const std::string& _s, int r, int g, int b, bool cen = false); void PrintAlpha(int _x, int _y, const std::string& _s, int r, int g, int b, int a, bool cen = false); @@ -248,8 +246,8 @@ public: void drawtrophytext(void); - void bigrprint(int x, int y, const std::string& t, int r, int g, int b, bool cen = false, float sc = 2); - void bigbrprint(int x, int y, const std::string& t, int r, int g, int b, bool cen = false, float sc = 2); + void bigrprint(int x, int y, const std::string& t, int r, int g, int b, bool cen = false, int sc = 2); + void bigbrprint(int x, int y, const std::string& t, int r, int g, int b, bool cen = false, int sc = 2); void drawtele(int x, int y, int t, SDL_Color c); diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index a147e720..b193ecb0 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -6,6 +6,7 @@ #include "Editor.h" #include "Entity.h" #include "FileSystemUtils.h" +#include "Font.h" #include "GlitchrunnerMode.h" #include "Graphics.h" #include "GraphicsUtil.h" @@ -1984,7 +1985,15 @@ void gamerender(void) ); int alpha = graphics.lerp(game.oldreadytotele, game.readytotele); - graphics.bprint(5, graphics.flipmode ? 20 : 210, final_string, alpha - 20 - (help.glow / 2), alpha - 20 - (help.glow / 2), alpha, true); + font::print( + PR_COLORGLYPH_BRI(alpha) | PR_CEN | PR_BOR, + -1, + graphics.flipmode ? 20 : 210, + final_string, + alpha - 20 - (help.glow / 2), + alpha - 20 - (help.glow / 2), + alpha + ); } if (game.swnmode) @@ -2202,12 +2211,36 @@ void gamerender(void) if (game.activity_r == 0 && game.activity_g == 0 && game.activity_b == 0) { - graphics.bprint(centered_x + game.activity_x, game.activity_y + 12, final_string, 196*act_alpha, 196*act_alpha, (255 - help.glow)*act_alpha); + font::print( + PR_COLORGLYPH_BRI(act_alpha*255), + centered_x + game.activity_x, + game.activity_y + 12, + final_string, + 196*act_alpha, + 196*act_alpha, + (255 - help.glow)*act_alpha + ); } else { - graphics.drawtextbox(game.activity_x + 4, game.activity_y + 4, 39, 3, game.activity_r*act_alpha, game.activity_g*act_alpha, game.activity_b*act_alpha); - graphics.Print(centered_x + game.activity_x, game.activity_y + 12, final_string, game.activity_r*act_alpha, game.activity_g*act_alpha, game.activity_b*act_alpha); + graphics.drawtextbox( + game.activity_x + 4, + game.activity_y + 4, + 39, + 3, + game.activity_r*act_alpha, + game.activity_g*act_alpha, + game.activity_b*act_alpha + ); + font::print( + PR_COLORGLYPH_BRI(act_alpha*255), + centered_x + game.activity_x, + game.activity_y + 12, + final_string, + game.activity_r*act_alpha, + game.activity_g*act_alpha, + game.activity_b*act_alpha + ); } }