From c36dc137bada0c217a921ff96c7c2f0f859f3e31 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 30 Jul 2019 10:52:24 +0200 Subject: [PATCH] - made adjustments to the text placement on the summary screen. With extended fonts much of the old code did not work anymore, this needed more precise checks for the sources of the printed texts. --- src/gamedata/fonts/font.cpp | 47 +++++++++++ src/gamedata/fonts/v_font.h | 3 + src/scripting/vmthunks.cpp | 13 +++ wadsrc/static/zscript/base.zs | 1 + .../zscript/ui/statscreen/statscreen.zs | 83 +++++++++++++------ 5 files changed, 123 insertions(+), 24 deletions(-) diff --git a/src/gamedata/fonts/font.cpp b/src/gamedata/fonts/font.cpp index 480b9a4c4..b3de95197 100644 --- a/src/gamedata/fonts/font.cpp +++ b/src/gamedata/fonts/font.cpp @@ -1107,6 +1107,53 @@ int FFont::StringWidth(const uint8_t *string) const return MAX(maxw, w); } +//========================================================================== +// +// Get the largest ascender in the first line of this text. +// +//========================================================================== + +int FFont::GetMaxAscender(const uint8_t* string) const +{ + int retval = 0; + + while (*string) + { + auto chr = GetCharFromString(string); + if (chr == TEXTCOLOR_ESCAPE) + { + // We do not need to check for UTF-8 in here. + if (*string == '[') + { + while (*string != '\0' && *string != ']') + { + ++string; + } + } + if (*string != '\0') + { + ++string; + } + continue; + } + else if (chr == '\n') + { + break; + } + else + { + auto ctex = GetChar(chr, CR_UNTRANSLATED, nullptr); + if (ctex) + { + auto offs = int(ctex->GetScaledTopOffset(0)); + if (offs > retval) retval = offs; + } + } + } + + return retval; +} + //========================================================================== // // FFont :: LoadTranslations diff --git a/src/gamedata/fonts/v_font.h b/src/gamedata/fonts/v_font.h index 6eff7e009..2c9d1aeb6 100644 --- a/src/gamedata/fonts/v_font.h +++ b/src/gamedata/fonts/v_font.h @@ -103,6 +103,9 @@ public: int GetSpaceWidth () const { return SpaceWidth; } int GetHeight () const { return FontHeight; } int GetDefaultKerning () const { return GlobalKerning; } + int GetMaxAscender(const uint8_t* text) const; + int GetMaxAscender(const char* text) const { return GetMaxAscender((uint8_t*)text); } + int GetMaxAscender(const FString &text) const { return GetMaxAscender((uint8_t*)text.GetChars()); } virtual void LoadTranslations(); FName GetName() const { return FontName; } diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index d2ffc0c73..fbf412890 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -2032,6 +2032,19 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, StringWidth, StringWidth) ACTION_RETURN_INT(StringWidth(self, str)); } +static int GetMaxAscender(FFont* font, const FString& str) +{ + const char* txt = str[0] == '$' ? GStrings(&str[1]) : str.GetChars(); + return font->GetMaxAscender(txt); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetMaxAscender, GetMaxAscender) +{ + PARAM_SELF_STRUCT_PROLOGUE(FFont); + PARAM_STRING(str); + ACTION_RETURN_INT(GetMaxAscender(self, str)); +} + static int CanPrint(FFont *font, const FString &str) { const char *txt = str[0] == '$' ? GStrings(&str[1]) : str.GetChars(); diff --git a/wadsrc/static/zscript/base.zs b/wadsrc/static/zscript/base.zs index 3d343e896..3b52b2730 100644 --- a/wadsrc/static/zscript/base.zs +++ b/wadsrc/static/zscript/base.zs @@ -320,6 +320,7 @@ struct Font native native int GetCharWidth(int code); native int StringWidth(String code); + native int GetMaxAscender(String code); native bool CanPrint(String code); native int GetHeight(); native int GetDisplacement(); diff --git a/wadsrc/static/zscript/ui/statscreen/statscreen.zs b/wadsrc/static/zscript/ui/statscreen/statscreen.zs index 699790308..10160efc2 100644 --- a/wadsrc/static/zscript/ui/statscreen/statscreen.zs +++ b/wadsrc/static/zscript/ui/statscreen/statscreen.zs @@ -149,7 +149,7 @@ class StatusScreen abstract play version("2.5") // //==================================================================== - int, int DrawName(int y, TextureID tex, String levelname) + int DrawName(int y, TextureID tex, String levelname) { // draw if (tex.isValid()) @@ -161,7 +161,7 @@ class StatusScreen abstract play version("2.5") // patches with vast amounts of empty space at the bottom. size.Y = TexMan.CheckRealHeight(tex); } - return y + int(Size.Y), (BigFont.GetHeight() - BigFont.GetDisplacement()) * CleanYfac / 4; + return y + int(Size.Y) * CleanYfac; } else if (levelname.Length() > 0) { @@ -176,9 +176,9 @@ class StatusScreen abstract play version("2.5") screen.DrawText(mapname.mFont, mapname.mColor, (screen.GetWidth() - lines.StringWidth(i) * CleanXfac) / 2, y + h, lines.StringAt(i), DTA_CleanNoMove, true); h += lumph; } - return y + h, (mapname.mFont.GetHeight() - mapname.mFont.GetDisplacement())/4; + return y + h; } - return 0, 0; + return 0; } //==================================================================== @@ -232,17 +232,35 @@ class StatusScreen abstract play version("2.5") virtual int drawLF () { - int y = TITLEY * CleanYfac; + bool ispatch = wbs.LName0.isValid(); + int oldy = TITLEY * CleanYfac; int h; + + if (!ispatch) + { + let asc = mapname.mFont.GetMaxAscender(lnametexts[1]); + if (asc > TITLEY - 2) + { + oldy = (asc+2) * CleanYfac; + } + } + + int y = DrawName(oldy, wbs.LName0, lnametexts[0]); - [y, h] = DrawName(y, wbs.LName0, lnametexts[0]); - - // Adjustment for different font sizes for map name and 'finished'. - let fontspace1 = finished.mFont.GetDisplacement(); - let fontspace2 = ((h + (finished.mFont.GetHeight() - fontspace1)/4)) / 2; - - y += max(0, fontspace2 - fontspace1) * CleanYFac; - + // If the displayed info is made of patches we need some additional offsetting here. + if (ispatch) + { + int h1 = BigFont.GetHeight() - BigFont.GetDisplacement(); + int h2 = (y - oldy) / CleanYfac / 4; + let disp = min(h1, h2); + // The offset getting applied here must at least be as tall as the largest ascender in the following text to avoid overlaps. + if (!TexMan.OkForLocalization(finishedPatch, "$WI_FINISHED")) + { + disp += finished.mFont.GetMaxAscender("$WI_FINISHED"); + } + y += disp * CleanYfac; + } + // draw "Finished!" int statsy = multiplayer? NG_STATSY : SP_STATSY * CleanYFac; @@ -266,19 +284,36 @@ class StatusScreen abstract play version("2.5") virtual void drawEL () { - int y = TITLEY * CleanYfac; + bool ispatch = TexMan.OkForLocalization(enteringPatch, "$WI_ENTERING"); + int oldy = TITLEY * CleanYfac; - y = DrawPatchOrText(y, entering, enteringPatch, "$WI_ENTERING"); - let h = (entering.mFont.GetHeight() - entering.mFont.GetDisplacement()) / 4; - - if (!wbs.LName1.isValid()) + if (!ispatch) { - // Factor out the font's displacement here. - let fontspace1 = mapname.mFont.GetDisplacement(); - let fontspace2 = ((h + (mapname.mFont.GetHeight() - fontspace1)/4)) / 2; - h = max(0, fontspace2 - fontspace1) * CleanYFac; - } - y += h * CleanYFac; + let asc = entering.mFont.GetMaxAscender("$WI_ENTERING"); + if (asc > TITLEY - 2) + { + oldy = (asc+2) * CleanYfac; + } + } + + int y = DrawPatchOrText(oldy, entering, enteringPatch, "$WI_ENTERING"); + + // If the displayed info is made of patches we need some additional offsetting here. + + if (ispatch) + { + int h1 = BigFont.GetHeight() - BigFont.GetDisplacement(); + let size = TexMan.GetScaledSize(enteringPatch); + int h2 = int(size.Y); + let disp = min(h1, h2) / 4; + // The offset getting applied here must at least be as tall as the largest ascender in the following text to avoid overlaps. + if (!wbs.LName1.isValid()) + { + disp += mapname.mFont.GetMaxAscender(lnametexts[1]); + } + y += disp * CleanYfac; + } + DrawName(y, wbs.LName1, lnametexts[1]); }