- added a CanPrint function to FFont and used that to handle the statistics display on the automap HUD to only replace the font when actually needed, not based on the language.

This commit is contained in:
Christoph Oelckers 2019-04-22 09:08:43 +02:00
parent 68c33a6e43
commit e0a0be4f7b
8 changed files with 119 additions and 29 deletions

View file

@ -140,20 +140,7 @@ bool CheckFontComplete(FFont *font)
{ {
// Also check if the SmallFont contains all characters this language needs. // Also check if the SmallFont contains all characters this language needs.
// If not, switch back to the original one. // If not, switch back to the original one.
const uint8_t* checkstr = (const uint8_t*)GStrings["REQUIRED_CHARACTERS"]; return font->CanPrint(GStrings["REQUIRED_CHARACTERS"]);
bool incomplete = false;
if (!checkstr) return true;
while (int c = GetCharFromString(checkstr))
{
bool redirected;
int cc = font->GetCharCode(c, true);
if (c != cc && (c != 0x1e9e || cc != 0xdf))
{
return false;
}
}
return true;
} }
void UpdateGenericUI(bool cvar) void UpdateGenericUI(bool cvar)

View file

@ -597,6 +597,7 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight)
{ {
auto scale = GetUIScale(hud_scale); auto scale = GetUIScale(hud_scale);
auto font = generic_ui ? NewSmallFont : SmallFont; auto font = generic_ui ? NewSmallFont : SmallFont;
auto font2 = font;
auto vwidth = screen->GetWidth() / scale; auto vwidth = screen->GetWidth() / scale;
auto vheight = screen->GetHeight() / scale; auto vheight = screen->GetHeight() / scale;
auto fheight = font->GetHeight(); auto fheight = font->GetHeight();
@ -606,6 +607,11 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight)
int textdist = 4; int textdist = 4;
int zerowidth = font->GetCharWidth('0'); int zerowidth = font->GetCharWidth('0');
if (!generic_ui)
{
if (!font->CanPrint(GStrings("AM_MONSTERS")) || !font->CanPrint(GStrings("AM_SECRETS")) || !font->CanPrint(GStrings("AM_ITEMS"))) font2 = OriginalSmallFont;
}
if (am_showtime) if (am_showtime)
{ {
sec = Tics2Seconds(primaryLevel->time); sec = Tics2Seconds(primaryLevel->time);
@ -629,14 +635,14 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight)
if (am_showmonsters) if (am_showmonsters)
{ {
textbuffer.Format("%s\34%c %d/%d", GStrings("AM_MONSTERS"), crdefault + 65, primaryLevel->killed_monsters, primaryLevel->total_monsters); textbuffer.Format("%s\34%c %d/%d", GStrings("AM_MONSTERS"), crdefault + 65, primaryLevel->killed_monsters, primaryLevel->total_monsters);
screen->DrawText(font, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); screen->DrawText(font2, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE);
y += fheight; y += fheight;
} }
if (am_showsecrets) if (am_showsecrets)
{ {
textbuffer.Format("%s\34%c %d/%d", GStrings("AM_SECRETS"), crdefault + 65, primaryLevel->found_secrets, primaryLevel->total_secrets); textbuffer.Format("%s\34%c %d/%d", GStrings("AM_SECRETS"), crdefault + 65, primaryLevel->found_secrets, primaryLevel->total_secrets);
screen->DrawText(font, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); screen->DrawText(font2, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE);
y += fheight; y += fheight;
} }
@ -644,7 +650,7 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight)
if (am_showitems) if (am_showitems)
{ {
textbuffer.Format("%s\34%c %d/%d", GStrings("AM_ITEMS"), crdefault + 65, primaryLevel->found_items, primaryLevel->total_items); textbuffer.Format("%s\34%c %d/%d", GStrings("AM_ITEMS"), crdefault + 65, primaryLevel->found_items, primaryLevel->total_items);
screen->DrawText(font, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); screen->DrawText(font2, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE);
y += fheight; y += fheight;
} }

View file

@ -482,6 +482,51 @@ FFont::~FFont ()
} }
} }
//==========================================================================
//
// FFont :: CheckCase
//
//==========================================================================
void FFont::CheckCase()
{
int lowercount = 0, uppercount = 0;
for (unsigned i = 0; i < Chars.Size(); i++)
{
unsigned chr = i + FirstChar;
if (lowerforupper[chr] == chr && upperforlower[chr] == chr)
{
continue; // not a letter;
}
if (myislower(chr))
{
if (Chars[i].TranslatedPic != nullptr) lowercount++;
}
else
{
if (Chars[i].TranslatedPic != nullptr) uppercount++;
}
}
if (lowercount == 0) return; // This is an uppercase-only font and we are done.
// The ß needs special treatment because it is far more likely to be supplied lowercase only, even in an uppercase font.
if (Chars[0xdf - FirstChar].TranslatedPic != nullptr)
{
if (LastChar < 0x1e9e)
{
Chars.Resize(0x1e9f - FirstChar);
LastChar = 0x1e9e;
}
if (Chars[0x1e9e - FirstChar].TranslatedPic == nullptr)
{
std::swap(Chars[0xdf - FirstChar], Chars[0x1e9e - FirstChar]);
lowercount--;
uppercount++;
if (lowercount == 0) return;
}
}
}
//========================================================================== //==========================================================================
// //
// FFont :: FindFont // FFont :: FindFont
@ -834,15 +879,6 @@ int FFont::GetCharCode(int code, bool needpic) const
return code; return code;
} }
// Special handling for the ß which may only exist as lowercase, so for this we need an additional upper -> lower check for all fonts aside from the generic substitution logic.
if (code == 0x1e9e)
{
if (LastChar <= 0xdf && (!needpic || Chars[0xdf - FirstChar].TranslatedPic != nullptr))
{
return 0xdf;
}
}
// Use different substitution logic based on the fonts content: // Use different substitution logic based on the fonts content:
// In a font which has both upper and lower case, prefer unaccented small characters over capital ones. // In a font which has both upper and lower case, prefer unaccented small characters over capital ones.
// In a pure upper-case font, do not check for lower case replacements. // In a pure upper-case font, do not check for lower case replacements.
@ -975,6 +1011,47 @@ double GetBottomAlignOffset(FFont *font, int c)
return offset; return offset;
} }
//==========================================================================
//
// Checks if the font contains proper glyphs for all characters in the string
//
//==========================================================================
bool FFont::CanPrint(const uint8_t *string) const
{
while (*string)
{
auto chr = GetCharFromString(string);
if (!MixedCase) chr = upperforlower[chr]; // For uppercase-only fonts we shouldn't check lowercase characters.
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')
{
int cc = GetCharCode(chr, true);
if (chr != cc)
{
return false;
}
}
}
return true;
}
//========================================================================== //==========================================================================
// //
// Find string width using this font // Find string width using this font

View file

@ -849,7 +849,7 @@ int stripaccent(int code)
else if (code == 0x171) code = 0xfc; else if (code == 0x171) code = 0xfc;
else else
{ {
static const char accentless[] = "AaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnnNnOoOoOoOoRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZz "; static const char accentless[] = "AaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnnNnOoOoOoOoRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZzs";
return accentless[code - 0x100]; return accentless[code - 0x100];
} }
} }
@ -908,7 +908,7 @@ int stripaccent(int code)
} }
// skip the rest of Latin characters because none of them are relevant for modern languages. // skip the rest of Latin characters because none of them are relevant for modern languages, except Vietnamese which cannot be represented with the tiny bitmap fonts anyway.
return code; return code;
} }

View file

@ -113,6 +113,11 @@ public:
inline int StringWidth (const char *str) const { return StringWidth ((const uint8_t *)str); } inline int StringWidth (const char *str) const { return StringWidth ((const uint8_t *)str); }
inline int StringWidth (const FString &str) const { return StringWidth ((const uint8_t *)str.GetChars()); } inline int StringWidth (const FString &str) const { return StringWidth ((const uint8_t *)str.GetChars()); }
// Checks if the font contains all characters to print this text.
bool CanPrint(const uint8_t *str) const;
inline bool CanPrint(const char *str) const { return CanPrint((const uint8_t *)str); }
inline bool CanPrint(const FString &str) const { return CanPrint((const uint8_t *)str.GetChars()); }
int GetCharCode(int code, bool needpic) const; int GetCharCode(int code, bool needpic) const;
char GetCursor() const { return Cursor; } char GetCursor() const { return Cursor; }
void SetCursor(char c) { Cursor = c; } void SetCursor(char c) { Cursor = c; }
@ -120,6 +125,7 @@ public:
bool NoTranslate() const { return noTranslate; } bool NoTranslate() const { return noTranslate; }
void RecordAllTextureColors(uint32_t *usedcolors); void RecordAllTextureColors(uint32_t *usedcolors);
virtual void SetDefaultTranslation(uint32_t *colors); virtual void SetDefaultTranslation(uint32_t *colors);
void CheckCase();
protected: protected:
FFont (int lump); FFont (int lump);

View file

@ -2021,6 +2021,19 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, StringWidth, StringWidth)
ACTION_RETURN_INT(StringWidth(self, str)); ACTION_RETURN_INT(StringWidth(self, str));
} }
static int CanPrint(FFont *font, const FString &str)
{
const char *txt = str[0] == '$' ? GStrings(&str[1]) : str.GetChars();
return font->CanPrint(txt);
}
DEFINE_ACTION_FUNCTION_NATIVE(FFont, CanPrint, CanPrint)
{
PARAM_SELF_STRUCT_PROLOGUE(FFont);
PARAM_STRING(str);
ACTION_RETURN_INT(CanPrint(self, str));
}
static int FindFontColor(int name) static int FindFontColor(int name)
{ {
return V_FindFontColor(ENamedName(name)); return V_FindFontColor(ENamedName(name));

View file

@ -308,6 +308,7 @@ struct Font native
native int GetCharWidth(int code); native int GetCharWidth(int code);
native int StringWidth(String code); native int StringWidth(String code);
native bool CanPrint(String code);
native int GetHeight(); native int GetHeight();
native String GetCursor(); native String GetCursor();

View file

@ -828,7 +828,7 @@ class BaseStatusBar native ui
// automap HUD common drawer // automap HUD common drawer
// This is not called directly to give a status bar the opportunity to // This is not called directly to give a status bar the opportunity to
// change the text colors. If you want to do something different, // change the text colors. If you want to do something different,
// override DrawAutomap directly. // override DrawAutomapHUD directly.
// //
//============================================================================ //============================================================================