make a Font charmap for numbers fonts

This commit is contained in:
Chris Danford
2004-05-31 00:11:34 +00:00
parent 3cadf4c5d5
commit 93e274b3ac
3 changed files with 151 additions and 145 deletions
-8
View File
@@ -88,13 +88,6 @@ bool BitmapText::LoadFromFont( CString sFontFilePath )
{
CHECKPOINT_M( ssprintf("BitmapText::LoadFromFont(%s)", sFontFilePath.c_str()) );
// if we're called with a non-ini file, then we're trying to load a 5x3 numbers graphic
bool bIsNumbers = GetExtension(sFontFilePath).CompareNoCase("ini")!=0;
if( bIsNumbers )
{
return LoadFromTextureAndChars( sFontFilePath, "0123456789%. :x" );
}
if( m_pFont ) {
FONT->UnloadFont( m_pFont );
m_pFont = NULL;
@@ -117,7 +110,6 @@ bool BitmapText::LoadFromTextureAndChars( CString sTexturePath, CString sChars )
m_pFont = NULL;
}
// load font
m_pFont = FONT->LoadFont( sTexturePath, sChars );
BuildChars();
+141 -137
View File
@@ -491,162 +491,162 @@ void Font::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, const CStri
/* Iterate over all keys. */
const IniFile::key *k = ini.GetKey(PageName);
if(k == NULL)
return;
for(IniFile::key::const_iterator key = k->begin(); key != k->end(); ++key)
if( k )
{
CString val = key->first;
CString data = key->second;
val.MakeUpper();
/* If val is an integer, it's a width, eg. "10=27". */
if(IsAnInt(val))
for(IniFile::key::const_iterator key = k->begin(); key != k->end(); ++key)
{
cfg.GlyphWidths[atoi(val)] = atoi(data);
continue;
}
CString val = key->first;
CString data = key->second;
/* "map codepoint=frame" maps a char to a frame. */
if(val.substr(0, 4) == "MAP ")
{
/* map CODEPOINT=frame. CODEPOINT can be
* 1. U+hexval
* 2. an alias ("oq")
* 3. a game type followed by a game alias, eg "pump menuleft"
* 4. a character in quotes ("X")
*
* map 1=2 is the same as
* range unicode #1-1=2
*/
CString codepoint = val.substr(4); /* "CODEPOINT" */
Game game = GAME_INVALID;
val.MakeUpper();
if(codepoint.find_first_of(' ') != codepoint.npos)
/* If val is an integer, it's a width, eg. "10=27". */
if(IsAnInt(val))
{
/* There's a space; the first word should be a game type. Split it. */
unsigned pos = codepoint.find_first_of(' ');
CString gamename = codepoint.substr(0, pos);
codepoint = codepoint.substr(pos+1);
game = GameManager::StringToGameType(gamename);
if(game == GAME_INVALID)
{
LOG->Warn( "Font definition '%s' uses unknown game type '%s'",
ini.GetPath().c_str(), gamename.c_str() );
continue;
}
}
wchar_t c;
if(codepoint.substr(0, 2) == "U+" && IsHexVal(codepoint.substr(2)))
sscanf(codepoint.substr(2).c_str(), "%x", &c);
else if(codepoint.size() > 0 &&
utf8_get_char_len(codepoint[0]) == int(codepoint.size()))
{
c = utf8_get_char(codepoint.c_str());
if(c == wchar_t(-1))
LOG->Warn("Font definition '%s' has an invalid value '%s'.",
ini.GetPath().c_str(), val.c_str() );
}
else if(!FontCharAliases::GetChar(codepoint, c))
{
LOG->Warn("Font definition '%s' has an invalid value '%s'.",
ini.GetPath().c_str(), val.c_str() );
cfg.GlyphWidths[atoi(val)] = atoi(data);
continue;
}
if(game != GAME_INVALID)
/* "map codepoint=frame" maps a char to a frame. */
if(val.substr(0, 4) == "MAP ")
{
longchar lc = FontManager::MakeGameGlyph(c, game);
cfg.CharToGlyphNo[lc] = atoi(data);
} else {
cfg.CharToGlyphNo[c] = atoi(data);
/* map CODEPOINT=frame. CODEPOINT can be
* 1. U+hexval
* 2. an alias ("oq")
* 3. a game type followed by a game alias, eg "pump menuleft"
* 4. a character in quotes ("X")
*
* map 1=2 is the same as
* range unicode #1-1=2
*/
CString codepoint = val.substr(4); /* "CODEPOINT" */
Game game = GAME_INVALID;
if(codepoint.find_first_of(' ') != codepoint.npos)
{
/* There's a space; the first word should be a game type. Split it. */
unsigned pos = codepoint.find_first_of(' ');
CString gamename = codepoint.substr(0, pos);
codepoint = codepoint.substr(pos+1);
game = GameManager::StringToGameType(gamename);
if(game == GAME_INVALID)
{
LOG->Warn( "Font definition '%s' uses unknown game type '%s'",
ini.GetPath().c_str(), gamename.c_str() );
continue;
}
}
wchar_t c;
if(codepoint.substr(0, 2) == "U+" && IsHexVal(codepoint.substr(2)))
sscanf(codepoint.substr(2).c_str(), "%x", &c);
else if(codepoint.size() > 0 &&
utf8_get_char_len(codepoint[0]) == int(codepoint.size()))
{
c = utf8_get_char(codepoint.c_str());
if(c == wchar_t(-1))
LOG->Warn("Font definition '%s' has an invalid value '%s'.",
ini.GetPath().c_str(), val.c_str() );
}
else if(!FontCharAliases::GetChar(codepoint, c))
{
LOG->Warn("Font definition '%s' has an invalid value '%s'.",
ini.GetPath().c_str(), val.c_str() );
continue;
}
if(game != GAME_INVALID)
{
longchar lc = FontManager::MakeGameGlyph(c, game);
cfg.CharToGlyphNo[lc] = atoi(data);
} else {
cfg.CharToGlyphNo[c] = atoi(data);
}
continue;
}
continue;
}
if(val.substr(0, 6) == "RANGE ")
{
/* range CODESET=first_frame or
* range CODESET #start-end=first_frame
* eg
* range CP1252=0 (default for 256-frame fonts)
* range ASCII=0 (default for 128-frame fonts)
*
* (Start and end are in hex.)
*
* Map two high-bit portions of ISO-8859- to one font:
* range ISO-8859-2 #80-FF=0
* range ISO-8859-3 #80-FF=128
*
* Map hiragana to 0-84:
* range Unicode #3041-3094=0
*/
vector<CString> matches;
static Regex parse("^RANGE ([A-Z\\-]+)( ?#([0-9A-F]+)-([0-9A-F]+))?$");
bool match = parse.Compare(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().c_str(), val.c_str() );
/* We must have either 1 match (just the codeset) or 4 (the whole thing). */
int cnt = -1;
int first = 0;
if(!matches[2].empty())
if(val.substr(0, 6) == "RANGE ")
{
sscanf(matches[2].c_str(), "%x", &first);
int last;
sscanf(matches[3].c_str(), "%x", &last);
if(last < first)
RageException::Throw("Font definition '%s' has an invalid range '%s': %i < %i.",
ini.GetPath().c_str(), val.c_str(), last < first );
/* range CODESET=first_frame or
* range CODESET #start-end=first_frame
* eg
* range CP1252=0 (default for 256-frame fonts)
* range ASCII=0 (default for 128-frame fonts)
*
* (Start and end are in hex.)
*
* Map two high-bit portions of ISO-8859- to one font:
* range ISO-8859-2 #80-FF=0
* range ISO-8859-3 #80-FF=128
*
* Map hiragana to 0-84:
* range Unicode #3041-3094=0
*/
vector<CString> matches;
static Regex parse("^RANGE ([A-Z\\-]+)( ?#([0-9A-F]+)-([0-9A-F]+))?$");
bool match = parse.Compare(val, matches);
ASSERT(matches.size() == 4); /* 4 parens */
cnt = last-first+1;
if(!match || matches[0].empty())
RageException::Throw("Font definition '%s' has an invalid range '%s': parse error",
ini.GetPath().c_str(), val.c_str() );
/* 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].c_str(), "%x", &first);
int last;
sscanf(matches[3].c_str(), "%x", &last);
if(last < first)
RageException::Throw("Font definition '%s' has an invalid range '%s': %i < %i.",
ini.GetPath().c_str(), val.c_str(), 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().c_str(), val.c_str(), ret.c_str() );
continue;
}
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().c_str(), val.c_str(), ret.c_str() );
if(val.substr(0, 5) == "LINE ")
{
/* line ROW=CHAR1CHAR2CHAR3CHAR4
* eg.
* line 0=ABCDEFGH
*
* This lets us assign characters very compactly and readably. */
continue;
}
CString row_str = val.substr(5);
ASSERT(IsAnInt(row_str));
const int row = atoi(row_str.c_str());
const int first_frame = row * NumFramesWide;
if(val.substr(0, 5) == "LINE ")
{
/* line ROW=CHAR1CHAR2CHAR3CHAR4
* eg.
* line 0=ABCDEFGH
*
* This lets us assign characters very compactly and readably. */
if(row > NumFramesHigh)
RageException::Throw("The font definition \"%s\" tries to assign line %i, but the font is only %i characters high",
ini.GetPath().c_str(), first_frame, NumFramesHigh);
CString row_str = val.substr(5);
ASSERT(IsAnInt(row_str));
const int row = atoi(row_str.c_str());
const int first_frame = row * NumFramesWide;
/* Decode the string. */
const wstring wdata(CStringToWstring(data));
if(row > NumFramesHigh)
RageException::Throw("The font definition \"%s\" tries to assign line %i, but the font is only %i characters high",
ini.GetPath().c_str(), first_frame, NumFramesHigh);
if(int(wdata.size()) > NumFramesWide)
RageException::Throw("The font definition \"%s\" assigns %i characters to row %i (\"%ls\"), but the font only has %i characters wide",
ini.GetPath().c_str(), wdata.size(), row, wdata.c_str(), NumFramesWide);
/* Decode the string. */
const wstring wdata(CStringToWstring(data));
if(int(wdata.size()) > NumFramesWide)
RageException::Throw("The font definition \"%s\" assigns %i characters to row %i (\"%ls\"), but the font only has %i characters wide",
ini.GetPath().c_str(), wdata.size(), row, wdata.c_str(), NumFramesWide);
for(unsigned i = 0; i < wdata.size(); ++i)
cfg.CharToGlyphNo[wdata[i]] = first_frame+i;
for(unsigned i = 0; i < wdata.size(); ++i)
cfg.CharToGlyphNo[wdata[i]] = first_frame+i;
}
}
}
@@ -658,6 +658,8 @@ void Font::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, const CStri
cfg.MapRange("ascii", 0, 0, -1);
else if(cfg.CharToGlyphNo.empty() && NumFrames == 256)
cfg.MapRange("cp1252", 0, 0, -1);
else if(cfg.CharToGlyphNo.empty() && NumFrames == 15)
cfg.MapRange("numbers", 0, 0, -1);
/* If ' ' is set and nbsp is not, set nbsp. */
if( cfg.CharToGlyphNo.find(' ') != cfg.CharToGlyphNo.end() )
@@ -818,10 +820,12 @@ void Font::Load(const CString &sFontOrTextureFilePath, CString sChars)
/* Load each font page. */
for(unsigned i = 0; i < TexturePaths.size(); ++i)
{
const CString sTexturePath = TexturePaths[i];
FontPage *fp = new FontPage;
/* Grab the page name, eg "foo" from "Normal [foo].png". */
CString pagename = GetPageNameFromFileName(TexturePaths[i]);
CString pagename = GetPageNameFromFileName(sTexturePath);
/* Load settings for this page from the INI. */
FontPageSettings cfg;
+10
View File
@@ -136,6 +136,15 @@ static const wchar_t map_korean_jamo[] =
0
};
/* Numbers. "0123456789%. :x" */
static const wchar_t map_numbers[] = {
0x0030, 0x0031, 0x0032, 0x0033, 0x0034,
0x0035, 0x0036, 0x0037, 0x0038, 0x0039,
0x0025, 0x002E, 0x0020, 0x003A, 0x0078,
0
};
static void Init()
{
if(!charmaps.empty())
@@ -147,6 +156,7 @@ static void Init()
charmaps["cp1252"] = map_cp1252;
charmaps["iso-8859-2"] = map_iso_8859_2;
charmaps["korean-jamo"] = map_korean_jamo;
charmaps["numbers"] = map_numbers;
}
const wchar_t *FontCharmaps::get_char_map(CString name)