diff --git a/stepmania/src/BitmapText.cpp b/stepmania/src/BitmapText.cpp index 24d3434fa0..c4f22f85ad 100644 --- a/stepmania/src/BitmapText.cpp +++ b/stepmania/src/BitmapText.cpp @@ -21,6 +21,7 @@ #include "ThemeManager.h" #include "GameConstantsAndTypes.h" #include "Font.h" +#include "FontCharAliases.h" /* XXX: * We need some kind of font modifier string for metrics. For example, @@ -214,7 +215,7 @@ void BitmapText::SetText( CString sText, bool DoSubst ) ASSERT( m_pFont ); if(DoSubst) - FontManager::ReplaceMarkers(sText); + FontCharAliases::ReplaceMarkers(sText); if(m_szText == sText) return; diff --git a/stepmania/src/Font.cpp b/stepmania/src/Font.cpp index 21db9fb833..b15d3a49c8 100644 --- a/stepmania/src/Font.cpp +++ b/stepmania/src/Font.cpp @@ -22,6 +22,8 @@ #include "GameState.h" #include "ThemeManager.h" #include "GameManager.h" +#include "FontCharmaps.h" +#include "FontCharAliases.h" const longchar Font::DEFAULT_GLYPH = 0xFFFFFF; @@ -45,6 +47,11 @@ void FontPage::Load( const FontPageSettings &cfg ) // load character widths vector FrameWidths; int i; + + int default_width = m_pTexture->GetSourceFrameWidth(); + if(cfg.DefaultWidth != -1) + default_width = cfg.DefaultWidth; + // Assume each character is the width of the frame by default. for( i=0; iGetNumFrames(); i++ ) { @@ -53,19 +60,19 @@ void FontPage::Load( const FontPageSettings &cfg ) { FrameWidths.push_back(it->second); } else { - FrameWidths.push_back(m_pTexture->GetSourceFrameWidth()); + FrameWidths.push_back(default_width); } } if( cfg.AddToAllWidths ) { - for( int i=0; i<256; i++ ) + for( int i=0; iGetNumFrames(); i++ ) FrameWidths[i] += cfg.AddToAllWidths; } if( cfg.ScaleAllWidthsBy != 1 ) { - for( int i=0; i<256; i++ ) + for( int i=0; iGetNumFrames(); i++ ) FrameWidths[i] = int(roundf( FrameWidths[i] * cfg.ScaleAllWidthsBy )); } @@ -411,21 +418,6 @@ void Font::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, const CStri cfg.CharToGlyphNo[c] = n; } int NumFrames = RageTexture::GetFrameCountFromFileName(TexturePath); - if(NumFrames == 128 || NumFrames == 256) - { - /* If it's 128 or 256 frames, default to ASCII or ISO-8859-1, - * respectively. If it's anything else, we don't know what it - * is, so don't make any default mappings (the INI needs to do - * it itself). */ - /* - if(NumFrames == 128) - cfg.MapRange("ASCII", 0, 127, 0); - else if(NumFrames == 256) - cfg.MapRange("ISO-8859-1", 0, 255, 0); - */ - for( longchar i=0; i matches; + bool match = regex("^RANGE ([A-Z\\-]+)( ?#([0-9A-F]+)-([0-9A-F]+))?$" , val, matches); + + ASSERT(matches.size() == 4); /* 4 parens */ + if(!match || matches[0].empty()) + RageException::Throw("Font definition '%s' has an invalid range '%s': parse error", + ini.GetPath().GetString(), val.GetString() ); + + /* We must have either 1 match (just the codeset) or 4 (the whole thing). */ + + int cnt = -1; + int first = 0; + if(!matches[2].empty()) + { + sscanf(matches[2].GetString(), "%x", &first); + int last; + sscanf(matches[3].GetString(), "%x", &last); + if(last < first) + RageException::Throw("Font definition '%s' has an invalid range '%s': %i < %i.", + ini.GetPath().GetString(), val.GetString(), last < first ); + + cnt = last-first+1; } - + CString ret = cfg.MapRange(matches[0], first, atoi(data), cnt); + if(!ret.empty()) + RageException::Throw("Font definition '%s' has an invalid range '%s': %s.", + ini.GetPath().GetString(), val.GetString(), ret.GetString() ); continue; } -#endif } + + /* If it's 128 or 256 frames, default to ASCII or CP1252, + * respectively. If it's anything else, we don't know what it + * is, so don't make any default mappings (the INI needs to do + * it itself). */ + if(cfg.CharToGlyphNo.empty() && NumFrames == 128) + cfg.MapRange("ascii", 0, 0, -1); + else if(cfg.CharToGlyphNo.empty() && NumFrames == 256) + cfg.MapRange("cp1252", 0, 0, -1); +} + +CString FontPageSettings::MapRange(CString Mapping, int map_offset, int glyphno, int cnt) +{ + if(!Mapping.CompareNoCase("Unicode")) + { + /* Special case. */ + if(cnt == -1) + return "Can't map all of Unicode to one font page"; /* don't do that */ + + /* What's a practical limit? A 2048x2048 texture could contain 16x16 characters, + * which is 16384 glyphs. (Use a grayscale map and that's only 4 megs.) Let's use + * that as a cap. (We don't want to go crazy if someone says "range Unicode + * #0-FFFFFFFF".) */ + if(cnt > 16384) + return ssprintf("Can't map %i glyphs to one font page", cnt); + + while(cnt) + { + CharToGlyphNo[map_offset] = glyphno; + map_offset++; + glyphno++; + cnt--; + } + + return ""; + } + + const wchar_t *mapping = FontCharmaps::get_char_map(Mapping); + if(mapping == NULL) + return "Unknown mapping"; + + while(*mapping != 0 && map_offset) { mapping++; map_offset--; } + if(map_offset) + return "Map overflow"; /* there aren't enough characters in the map */ + + /* If cnt is -1, set it to the number of characters in the map. */ + if(cnt == -1) + for(cnt = 0; mapping[cnt] != 0; ++cnt) ; + + while(*mapping != 0) + { + if(*mapping != FontCharmaps::M_SKIP) + CharToGlyphNo[*mapping] = glyphno; + mapping++; + glyphno++; + cnt--; + } + + if(cnt) + return "Map overflow"; /* there aren't enough characters in the map */ + + return ""; } static CStringArray LoadStack; diff --git a/stepmania/src/Font.h b/stepmania/src/Font.h index 1cbebb72e4..69729f8091 100644 --- a/stepmania/src/Font.h +++ b/stepmania/src/Font.h @@ -43,7 +43,8 @@ struct FontPageSettings AddToAllWidths, LineSpacing, Top, - Baseline; + Baseline, + DefaultWidth; float ScaleAllWidthsBy; map CharToGlyphNo; @@ -56,8 +57,13 @@ struct FontPageSettings LineSpacing(-1), ScaleAllWidthsBy(1), Top(-1), - Baseline(-1) + Baseline(-1), + DefaultWidth(-1) { } + + /* Map a range from a character map to glyphs. If cnt is -1, map the + * whole map. Returns "" or an error message. */ + CString MapRange(CString Mapping, int map_offset, int glyph_offset, int cnt); }; class FontPage diff --git a/stepmania/src/FontManager.cpp b/stepmania/src/FontManager.cpp index c5a5863d5b..d5241b7428 100644 --- a/stepmania/src/FontManager.cpp +++ b/stepmania/src/FontManager.cpp @@ -19,9 +19,6 @@ #include "RageException.h" #include "RageTimer.h" -FontManager::aliasmap FontManager::CharAliases; -map FontManager::CharAliasRepl; - FontManager* FONT = NULL; FontManager::FontManager() @@ -68,8 +65,6 @@ void FontManager::ReloadFonts() Font* FontManager::LoadFont( const CString &sFontOrTextureFilePath, CString sChars ) { - InitCharAliases(); - // Convert the path to lowercase so that we don't load duplicates. // Really, this does not solve the duplicate problem. We could have two copies // of the same bitmap if there are equivalent but different paths @@ -116,56 +111,3 @@ void FontManager::UnloadFont( Font *fp ) RageException::Throw( "Unloaded an unknown font (%p)", fp ); } - - -void FontManager::InitCharAliases() -{ - if(!CharAliases.empty()) - return; - /* XXX; these should be in a data file somewhere (theme metrics?) - * (The comments here are UTF-8; they won't show up in VC6.) */ - CharAliases["default"] = Font::DEFAULT_GLYPH; /* ? */ - CharAliases["kakumei1"] = 0x9769; /* 革 */ - CharAliases["kakumei2"] = 0x547D; /* 命 */ - CharAliases["matsuri"] = 0x796D; /* 祭 */ - CharAliases["oni"] = 0x9B3C; /* 鬼 */ - CharAliases["michi"] = 0x9053; /* 道 */ - CharAliases["futatsu"] = 0x5F10; /* 弐 */ - CharAliases["omega"] = 0x03a9; /* Ω */ - CharAliases["whiteheart"] = 0x2661; /* ♡ */ - CharAliases["blackstar"] = 0x2605; /* ★ */ - CharAliases["whitestar"] = 0x2606; /* ☆ */ - CharAliases["flipped-a"] = 0x2200; /* ∀ */ - - /* These are internal-use glyphs; they don't have real Unicode codepoints. */ - CharAliases["up"] = 0xE000; - CharAliases["down"] = 0xE001; - CharAliases["left"] = 0xE002; - CharAliases["right"] = 0xE003; - CharAliases["menuup"] = 0xE004; - CharAliases["menudown"] = 0xE005; - CharAliases["menuleft"] = 0xE006; - CharAliases["menuright"] = 0xE007; - CharAliases["start"] = 0xE008; - - CharAliases["invalid"] = INVALID_CHAR; /* 0xFFFF */ - - for(aliasmap::const_iterator i = CharAliases.begin(); i != CharAliases.end(); ++i) - { - CString from = ssprintf("&%s;", i->first.GetString()); - CString to = LcharToUTF8(i->second); - from.MakeUpper(); - CharAliasRepl[from] = to; - LOG->Trace("from '%s' to '%s'", from.GetString(), to.GetString()); - } -} - -/* Replace all &markers; and &#NNNN;s with UTF-8. I'm not really - * sure where to put this; this is used elsewhere, too. */ -void FontManager::ReplaceMarkers( CString &sText ) -{ - InitCharAliases(); - ReplaceText(sText, FontManager::CharAliasRepl); - Replace_Unicode_Markers(sText); -} - diff --git a/stepmania/src/FontManager.h b/stepmania/src/FontManager.h index f9ff266a94..f1ab88630f 100644 --- a/stepmania/src/FontManager.h +++ b/stepmania/src/FontManager.h @@ -42,16 +42,9 @@ public: static longchar MakeGameGlyph(longchar c, Game g); static bool ExtractGameGlyph(longchar ch, int &c, Game &g); - typedef map aliasmap; - static aliasmap CharAliases; - static map CharAliasRepl; - - static void ReplaceMarkers( CString &sText ); - protected: // map from file name to a texture holder map m_mapPathToFont; - static void InitCharAliases(); }; extern FontManager* FONT; // global and accessable from anywhere in our program diff --git a/stepmania/src/ScreenTextEntry.cpp b/stepmania/src/ScreenTextEntry.cpp index 45447568fe..e72ba0067d 100644 --- a/stepmania/src/ScreenTextEntry.cpp +++ b/stepmania/src/ScreenTextEntry.cpp @@ -18,7 +18,7 @@ #include "GameConstantsAndTypes.h" #include "PrefsManager.h" #include "ThemeManager.h" -#include "FontManager.h" +#include "FontCharAliases.h" const float QUESTION_X = CENTER_X; const float QUESTION_Y = CENTER_Y - 60; @@ -199,7 +199,7 @@ void ScreenTextEntry::MenuStart( PlayerNumber pn ) if( m_pOnOK ) { CString ret = LStringToCString(m_sAnswer); - FontManager::ReplaceMarkers(ret); + FontCharAliases::ReplaceMarkers(ret); m_pOnOK( ret ); } }