diff --git a/desktop_version/src/Editor.cpp b/desktop_version/src/Editor.cpp index 4fa8a59c..41bd1038 100644 --- a/desktop_version/src/Editor.cpp +++ b/desktop_version/src/Editor.cpp @@ -1076,9 +1076,9 @@ void editorrender(void) if(ed.dmtileeditor>0 && t2<=30) { - short labellen = 2 + graphics.len(loc::gettext("Tile:")); - graphics.bprint(2, 45-t2, loc::gettext("Tile:"), 196, 196, 255 - help.glow, false); - graphics.bprint(labellen+16, 45-t2, help.String(ed.dmtile), 196, 196, 255 - help.glow, false); + short labellen = 2 + font::len(0, loc::gettext("Tile:")); + font::print(PR_BOR, 2, 45-t2, loc::gettext("Tile:"), 196, 196, 255 - help.glow); + font::print(PR_BOR, labellen+16, 45-t2, help.String(ed.dmtile), 196, 196, 255 - help.glow); graphics.fill_rect(labellen+2,44-t2,10,10, graphics.getRGB(255 - help.glow, 196, 196)); graphics.fill_rect(labellen+3,45-t2,8,8, graphics.getRGB(0,0,0)); @@ -1093,11 +1093,13 @@ void editorrender(void) } else { - short labellen = 2 + graphics.len(loc::gettext("Tile:")); - graphics.bprint(2, 12, loc::gettext("Tile:"), 196, 196, 255 - help.glow, false); - graphics.bprint(labellen+16, 12, help.String(ed.dmtile), 196, 196, 255 - help.glow, false); - graphics.fill_rect(labellen+2,11,10,10, graphics.getRGB(255 - help.glow, 196, 196)); - graphics.fill_rect(labellen+3,12,8,8, graphics.getRGB(0,0,0)); + short labellen = 2 + font::len(0, loc::gettext("Tile:")); + int y = 2 + font::height(0); + y = SDL_max(y, 12); + font::print(PR_BOR, 2, y, loc::gettext("Tile:"), 196, 196, 255 - help.glow); + font::print(PR_BOR, labellen+16, y, help.String(ed.dmtile), 196, 196, 255 - help.glow); + graphics.fill_rect(labellen+2, y-1, 10,10, graphics.getRGB(255 - help.glow, 196, 196)); + graphics.fill_rect(labellen+3, y, 8,8, graphics.getRGB(0,0,0)); if(room->tileset==0) { @@ -1459,15 +1461,18 @@ void editorrender(void) toolname = "???"; break; } - int toolnamelen = graphics.len(toolname); - graphics.fill_rect(0,197,toolnamelen+8,11, graphics.getRGB(32,32,32)); - graphics.fill_rect(0,198,toolnamelen+7,10, graphics.getRGB(0,0,0)); - graphics.bprint(2,199, toolname, 196, 196, 255 - help.glow); - - graphics.fill_rect(260,197,80,11, graphics.getRGB(32,32,32)); - graphics.fill_rect(261,198,80,10, graphics.getRGB(0,0,0)); - font::print(PR_BOR | PR_CJK_HIGH | PR_RIGHT, 316, 199, "("+help.String(ed.levx+1)+","+help.String(ed.levy+1)+")", 196, 196, 255 - help.glow); + int bgheight = 2 + font::height(0); + int toolnamelen = font::len(0, toolname); + graphics.fill_rect(0,207-bgheight,toolnamelen+8,bgheight+1, graphics.getRGB(32,32,32)); + graphics.fill_rect(0,208-bgheight,toolnamelen+7,bgheight, graphics.getRGB(0,0,0)); + font::print(PR_BOR | PR_CJK_HIGH, 2,199, toolname, 196, 196, 255 - help.glow); + char coords[8]; + SDL_snprintf(coords, sizeof(coords), "(%d,%d)", ed.levx+1, ed.levy+1); + int coordslen = font::len(0, coords); + graphics.fill_rect(319-coordslen-8,207-bgheight,coordslen+8,bgheight+1, graphics.getRGB(32,32,32)); + graphics.fill_rect(320-coordslen-8,208-bgheight,coordslen+8,bgheight, graphics.getRGB(0,0,0)); + font::print(PR_BOR | PR_CJK_HIGH | PR_RIGHT, 316, 199, coords, 196, 196, 255 - help.glow); } else { @@ -1510,20 +1515,24 @@ void editorrender(void) int menuwidth = 0; for (size_t i = 0; i < SDL_arraysize(shiftmenuoptions); i++) { - int len = graphics.len(shiftmenuoptions[i]); + int len = font::len(0, shiftmenuoptions[i]); if (len > menuwidth) menuwidth = len; } - fillboxabs(0, 117,menuwidth+17,140,graphics.getRGB(64,64,64)); - graphics.fill_rect(0,118,menuwidth+16,140, graphics.getRGB(0,0,0)); + int lineheight = font::height(0); + lineheight = SDL_max(10, lineheight); + int left_y = 230-SDL_arraysize(shiftmenuoptions)*lineheight; + + fillboxabs(0, left_y-3, menuwidth+17, 240,graphics.getRGB(64,64,64)); + graphics.fill_rect(0,left_y-2,menuwidth+16,240, graphics.getRGB(0,0,0)); for (size_t i = 0; i < SDL_arraysize(shiftmenuoptions); i++) - graphics.Print(4, 120+i*10, shiftmenuoptions[i], 164,164,164,false); + graphics.Print(4, left_y+i*lineheight, shiftmenuoptions[i], 164,164,164,false); fillboxabs(220, 207,100,60,graphics.getRGB(64,64,64)); graphics.fill_rect(221,208,160,60, graphics.getRGB(0,0,0)); graphics.Print(224, 210, loc::gettext("S: Save Map"),164,164,164,false); - graphics.Print(224, 220, loc::gettext("L: Load Map"),164,164,164,false); + graphics.Print(224, 210+lineheight, loc::gettext("L: Load Map"),164,164,164,false); } } diff --git a/desktop_version/src/Font.cpp b/desktop_version/src/Font.cpp index 3c4347dd..4c29705e 100644 --- a/desktop_version/src/Font.cpp +++ b/desktop_version/src/Font.cpp @@ -465,6 +465,7 @@ void destroy(void) unload_font_container(&fonts_main); } +static Font* container_get(FontContainer* container, uint8_t idx); // TODO TEMP TEMP TEMP static bool next_wrap( size_t* start, @@ -493,7 +494,7 @@ static bool next_wrap( goto next; } - linewidth += get_advance(&fonts_main.fonts[font_idx_8x8], str[idx]); // TODO get font via argument! + linewidth += get_advance(container_get(&fonts_main, loc::get_langmeta()->font_idx), str[idx]); // TODO get font via argument! switch (str[idx]) { diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index fc4eb30a..27328464 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -2833,7 +2833,7 @@ void Game::updatestate(void) "gamecomplete_n_trinkets:int", trinkets() ); - graphics.createtextboxflipme(label, 168-graphics.len(label), 84, 0,0,0); + graphics.createtextboxflipme(label, 168-font::len(PR_FONT_INTERFACE, label), 84, 0,0,0); graphics.textboxprintflags(PR_FONT_INTERFACE); graphics.createtextboxflipme(buffer, 180, 84, 0, 0, 0); graphics.textboxprintflags(PR_FONT_INTERFACE); @@ -2846,7 +2846,7 @@ void Game::updatestate(void) const char* label = loc::gettext("Game Time:"); std::string tempstring = savetime; - graphics.createtextboxflipme(label, 168-graphics.len(label), 96, 0,0,0); + graphics.createtextboxflipme(label, 168-font::len(PR_FONT_INTERFACE, label), 96, 0,0,0); graphics.textboxprintflags(PR_FONT_INTERFACE); graphics.createtextboxflipme(tempstring, 180, 96, 0, 0, 0); graphics.textboxprintflags(PR_FONT_INTERFACE); @@ -2858,7 +2858,7 @@ void Game::updatestate(void) setstatedelay(45); const char* label = loc::gettext("Total Flips:"); - graphics.createtextboxflipme(label, 168-graphics.len(label), 123, 0,0,0); + graphics.createtextboxflipme(label, 168-font::len(PR_FONT_INTERFACE, label), 123, 0,0,0); graphics.textboxprintflags(PR_FONT_INTERFACE); graphics.createtextboxflipme(help.String(totalflips), 180, 123, 0, 0, 0); graphics.textboxprintflags(PR_FONT_INTERFACE); @@ -2870,7 +2870,7 @@ void Game::updatestate(void) setstatedelay(45+15); const char* label = loc::gettext("Total Deaths:"); - graphics.createtextboxflipme(label, 168-graphics.len(label), 135, 0,0,0); + graphics.createtextboxflipme(label, 168-font::len(PR_FONT_INTERFACE, label), 135, 0,0,0); graphics.textboxprintflags(PR_FONT_INTERFACE); graphics.createtextboxflipme(help.String(deathcounts), 180, 135, 0, 0, 0); graphics.textboxprintflags(PR_FONT_INTERFACE); @@ -6888,7 +6888,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) menuwidth = 0; for (size_t i = 0; i < menuoptions.size(); i++) { - int width = i*menuspacing + graphics.len(menuoptions[i].text); + int width = i*menuspacing + font::len(menuoptions[i].print_flags, menuoptions[i].text); if (width > menuwidth) menuwidth = width; } diff --git a/desktop_version/src/LocalizationStorage.cpp b/desktop_version/src/LocalizationStorage.cpp index 0edaf9dd..f741a935 100644 --- a/desktop_version/src/LocalizationStorage.cpp +++ b/desktop_version/src/LocalizationStorage.cpp @@ -299,26 +299,33 @@ static bool max_check_string(const char* str, const char* max) max_h = 2; } + uint8_t font_idx = get_langmeta()->font_idx; + uint32_t print_flags = PR_FONT_IDX(font_idx) | PR_CJK_LOW; uint8_t font_w = 8; uint8_t font_h = 8; - font::glyph_dimensions_main(get_langmeta()->font_idx, &font_w, &font_h); + font::glyph_dimensions_main(font_idx, &font_w, &font_h); - unsigned short max_w_px = max_w * font_w; - unsigned short max_h_px = max_h * SDL_max(10, font_h); + unsigned short max_w_px = max_w * 8; + unsigned short max_h_px = max_h * 10; bool does_overflow = false; if (max_h == 1) { - does_overflow = graphics.len(str) > (int) max_w_px; + max_h_px = font_h; + does_overflow = font::len(print_flags, str) > (int) max_w_px; } else { short lines; - font::string_wordwrap(str, max_w_px, &lines); - does_overflow = lines > (short) max_h; + font::string_wordwrap(str, max_w_px, &lines); // TODO: needs to be passed the font! + does_overflow = lines*SDL_max(10, font_h) > (short) max_h_px; } + // Convert max_w and max_h from 8x8 into local + max_w = max_w_px / font_w; + max_h = max_h_px / SDL_max(10, font_h); + if (does_overflow) { TextOverflow overflow; @@ -329,6 +336,7 @@ static bool max_check_string(const char* str, const char* max) overflow.max_w_px = max_w_px; overflow.max_h_px = max_h_px; overflow.multiline = max_h > 1; + overflow.flags = print_flags; text_overflows.push_back(overflow); diff --git a/desktop_version/src/LocalizationStorage.h b/desktop_version/src/LocalizationStorage.h index 8b53f8f2..5263e1de 100644 --- a/desktop_version/src/LocalizationStorage.h +++ b/desktop_version/src/LocalizationStorage.h @@ -50,6 +50,7 @@ struct TextOverflow unsigned short max_w, max_h; unsigned short max_w_px, max_h_px; bool multiline; + uint32_t flags; }; extern std::vector text_overflows; diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 9fe53c51..fe5a59c9 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -57,48 +57,63 @@ static inline void drawslowdowntext(const int y) } } +static void slider_get(char* buffer, size_t buffer_len, int position, int n_positions, int target_width) +{ + /* Print a slider to the buffer for target_width in pixels. + * + * <--target w--> + * []............ + * ......[]...... + * ............[] + * ^^^^^^ dots_per_position=6 + * ^^^^^^^^^^^^^^ max_chars=14 + */ + + if (n_positions < 2 || position < 0 || position >= n_positions) + { + buffer[0] = '\0'; + return; + } + + int max_chars = ((target_width - font::len(0, "[]")) / font::len(0, ".")) + 2; + max_chars = SDL_min(max_chars, buffer_len-1); + + int dots_per_position = (max_chars-2) / (n_positions-1); + max_chars = dots_per_position * (n_positions-1) + 2; + + VVV_fillstring(buffer, max_chars+1, '.'); + if (dots_per_position<1) + { + return; + } + + int handle_idx = position*dots_per_position; + buffer[handle_idx] = '['; + buffer[handle_idx+1] = ']'; +} + static void volumesliderrender(void) { - char buffer[SCREEN_WIDTH_CHARS + 1]; - - char slider[20 + 1]; - int slider_length; - - const char symbol[] = "[]"; - int symbol_length; - - int offset; - int num_positions; - - const int* volume_ptr; + int volume_max_position = USER_VOLUME_MAX / USER_VOLUME_STEP; + int volume; switch (game.currentmenuoption) { case 0: - volume_ptr = &music.user_music_volume; + volume = music.user_music_volume; break; case 1: - volume_ptr = &music.user_sound_volume; + volume = music.user_sound_volume; break; default: SDL_assert(0 && "Unhandled volume slider menu option!"); return; } - VVV_fillstring(slider, sizeof(slider), '.'); - slider_length = sizeof(slider) - 1; + char slider[40 + 1]; + slider_get(slider, sizeof(slider), volume_max_position*volume/USER_VOLUME_MAX, volume_max_position+1, 240); - symbol_length = sizeof(symbol) - 1; - - num_positions = slider_length - symbol_length + 1; - - offset = num_positions * (*volume_ptr) / USER_VOLUME_MAX; - offset = SDL_clamp(offset, 0, slider_length - symbol_length); - - /* SDL_strlcpy null-terminates, which would end the string in the middle of - * it, which we don't want! - */ - SDL_memcpy(&slider[offset], symbol, symbol_length); + char buffer[SCREEN_WIDTH_CHARS + 1]; if (game.slidermode == SLIDER_NONE) { @@ -110,7 +125,7 @@ static void volumesliderrender(void) vformat_buf(buffer, sizeof(buffer), loc::get_langmeta()->menu_select.c_str(), "label:str", slider); } - graphics.Print(-1, 95, buffer, tr, tg, tb, true); + font::print(PR_CEN, -1, 95, buffer, tr, tg, tb); } static void inline drawglitchrunnertext(const int y) @@ -155,8 +170,7 @@ static void menurender(void) graphics.draw_sprite((160 - 96) + 4 * 32, temp, 23, tr, tg, tb); graphics.draw_sprite((160 - 96) + 5 * 32, temp, 23, tr, tg, tb); #if defined(MAKEANDPLAY) - const char* editionlabel = loc::gettext("MAKE AND PLAY EDITION"); - graphics.Print(264-graphics.len(editionlabel),temp+35,editionlabel,tr, tg, tb); + font::print(PR_RIGHT, 264, temp+35, loc::gettext("MAKE AND PLAY EDITION"), tr, tg, tb); #endif #ifdef INTERIM_VERSION_EXISTS graphics.Print( 310 - (10*8), 200, COMMIT_DATE, tr/2, tg/2, tb/2); @@ -563,30 +577,15 @@ static void menurender(void) switch (game.currentmenuoption) { case 0: - graphics.Print(32, 75, loc::gettext("Low"), tr, tg, tb); - graphics.Print(-1, 75, loc::gettext("Medium"), tr, tg, tb, true); - #define HIGHLABEL loc::gettext("High") - graphics.Print(288-graphics.len(HIGHLABEL), 75, HIGHLABEL, tr, tg, tb); - #undef HIGHLABEL - switch(key.sensitivity) - { - case 0: - graphics.Print( -1, 85, "[]..........................", tr, tg, tb, true); - break; - case 1: - graphics.Print( -1, 85, ".......[]...................", tr, tg, tb, true); - break; - case 2: - graphics.Print( -1, 85, ".............[].............", tr, tg, tb, true); - break; - case 3: - graphics.Print( -1, 85, "...................[].......", tr, tg, tb, true); - break; - case 4: - graphics.Print( -1, 85, "..........................[]", tr, tg, tb, true); - break; - } + { + font::print(0, 32, 75, loc::gettext("Low"), tr, tg, tb); + font::print(PR_CEN, -1, 75, loc::gettext("Medium"), tr, tg, tb); + font::print(PR_RIGHT, 288, 75, loc::gettext("High"), tr, tg, tb); + char slider[SCREEN_WIDTH_CHARS + 1]; + slider_get(slider, sizeof(slider), key.sensitivity, 5, 240); + font::print(PR_CEN, -1, 85, slider, tr, tg, tb); break; + } case 1: case 2: case 3: @@ -710,14 +709,10 @@ static void menurender(void) overflow.max_w_px, overflow.max_h_px, overflow.lang.c_str() ); - graphics.Print(10, 10, buffer, tr/2, tg/2, tb/2); - - uint8_t font_h = 8; - font::glyph_dimensions_main(loc::get_langmeta()->font_idx, NULL, &font_h); + font::print(PR_FONT_8X8, 10, 10, buffer, tr/2, tg/2, tb/2); int box_x = SDL_min(10, (320-overflow.max_w_px)/2); - int box_h = overflow.max_h_px - SDL_max(0, 10-font_h); - graphics.fill_rect(box_x-1, 30-1, overflow.max_w_px+2, box_h+2, tr/3, tg/3, tb/3); + graphics.fill_rect(box_x-1, 30-1, overflow.max_w_px+2, overflow.max_h_px+2, tr/3, tg/3, tb/3); int wraplimit; if (overflow.multiline) @@ -731,7 +726,7 @@ static void menurender(void) if (overflow.text != NULL) { - graphics.PrintWrap(box_x, 30, overflow.text, tr, tg, tb, false, -1, wraplimit); + font::print_wrap(overflow.flags, box_x, 30, overflow.text, tr, tg, tb, -1, wraplimit); } } break; @@ -1616,8 +1611,7 @@ void titlerender(void) graphics.draw_sprite((160 - 96) + 4 * 32, temp, 23, tr, tg, tb); graphics.draw_sprite((160 - 96) + 5 * 32, temp, 23, tr, tg, tb); #if defined(MAKEANDPLAY) - const char* editionlabel = loc::gettext("MAKE AND PLAY EDITION"); - graphics.Print(264-graphics.len(editionlabel),temp+35,editionlabel,tr, tg, tb); + font::print(PR_RIGHT, 264, temp+35, loc::gettext("MAKE AND PLAY EDITION"), tr, tg, tb); #endif graphics.PrintWrap(5, 175, loc::gettext("[ Press ACTION to Start ]"), tr, tg, tb, true); @@ -2018,11 +2012,11 @@ void gamerender(void) { std::string tempstring = help.timestring(game.swntimer); graphics.bprint( 10, 10, loc::gettext("Current Time"), 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), false); - graphics.bigbprint( 25, 24, tempstring, 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), false, 2); + font::print(PR_2X | PR_BOR | PR_FONT_8X8, 25, 24, tempstring, 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2)); tempstring = help.timestring(game.swnrecord); const char* besttimelabel = loc::gettext("Best Time"); graphics.bprint( 320-graphics.len(besttimelabel)-8, 10, besttimelabel, 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), false); - graphics.bigbrprint( 300, 24, tempstring, 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), false, 2); + font::print(PR_2X | PR_BOR | PR_FONT_8X8 | PR_RIGHT, 300, 24, tempstring, 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2)); switch(game.swnbestrank) { diff --git a/desktop_version/src/main.cpp b/desktop_version/src/main.cpp index 9d044e42..6f32d029 100644 --- a/desktop_version/src/main.cpp +++ b/desktop_version/src/main.cpp @@ -891,6 +891,8 @@ static void unfocused_run(void) { graphics.fill_rect(0, 0, 0); #define FLIP(YPOS) graphics.flipmode ? 232 - YPOS : YPOS + /* The pause screen can also appear on the language screen, where highlighting + * a language changes the used language metadata but not the loaded strings... */ uint32_t flags = PR_CEN | PR_BOR | PR_FONT_IDX(loc::langmeta.font_idx); font::print(flags | PR_CJK_HIGH, -1, FLIP(110), loc::gettext("Game paused"), 196 - help.glow, 255 - help.glow, 196 - help.glow); font::print(flags | PR_CJK_LOW, -1, FLIP(120), loc::gettext("[click to resume]"), 196 - help.glow, 255 - help.glow, 196 - help.glow); diff --git a/desktop_version/src/preloader.cpp b/desktop_version/src/preloader.cpp index 621370dd..c3098282 100644 --- a/desktop_version/src/preloader.cpp +++ b/desktop_version/src/preloader.cpp @@ -1,5 +1,6 @@ #include "Constants.h" #include "Enums.h" +#include "Font.h" #include "Game.h" #include "Graphics.h" #include "GraphicsUtil.h" @@ -134,8 +135,7 @@ void preloaderrender(void) pre_fakepercent ); - int percentage_len = graphics.len(buffer); - graphics.Print(282-percentage_len, 204, buffer, 124, 112, 218, false); + font::print(PR_RIGHT | PR_CJK_HIGH, 282, 204, buffer, 124, 112, 218); } graphics.drawfade();