utf-8 support is working

This commit is contained in:
Glenn Maynard
2003-01-05 05:13:45 +00:00
parent 28a4abd876
commit 16052ecd3d
6 changed files with 126 additions and 37 deletions
+84 -2
View File
@@ -22,6 +22,86 @@
#include "GameConstantsAndTypes.h" #include "GameConstantsAndTypes.h"
#include "Font.h" #include "Font.h"
char *g_utf8_find_next_char (const char *p,
const char *end)
{
if (*p) {
if (end)
for (++p; p < end && (*p & 0xc0) == 0x80; ++p)
;
else
for (++p; (*p & 0xc0) == 0x80; ++p)
;
}
return (p == end) ? NULL : (char *)p;
}
#define UTF8_GET \
wchar_t
g_utf8_get_char (const char *p)
{
int i, mask = 0, len;
wchar_t result;
unsigned char c = (unsigned char) *p;
if (c < 128) {
len = 1;
mask = 0x7f;
} else if ((c & 0xe0) == 0xc0) {
len = 2;
mask = 0x1f;
} else if ((c & 0xf0) == 0xe0) {
len = 3;
mask = 0x0f;
} else if ((c & 0xf8) == 0xf0) {
len = 4;
mask = 0x07;
} else if ((c & 0xfc) == 0xf8) {
len = 5;
mask = 0x03;
} else if ((c & 0xfe) == 0xfc) {
len = 6;
mask = 0x01;
} else
return (wchar_t)-1;
result = wchar_t(p[0] & mask);
for (i = 1; i < len; ++i) {
if ((p[i] & 0xc0) != 0x80)
return (wchar_t) -1;
result <<= 6;
result |= p[i] & 0x3f;
}
return result;
}
wstring CStringToWstring(const CString &str)
{
const char *ptr = str.c_str(), *end = str.c_str()+str.size();
wstring ret;
while(ptr)
{
wchar_t c = g_utf8_get_char (ptr);
if(c != wchar_t(-1))
ret.push_back(c);
ptr = g_utf8_find_next_char (ptr, end);
}
return ret;
}
#define RAINBOW_COLOR(n) THEME->GetMetricC("BitmapText",ssprintf("RainbowColor%i", n+1)) #define RAINBOW_COLOR(n) THEME->GetMetricC("BitmapText",ssprintf("RainbowColor%i", n+1))
@@ -118,7 +198,7 @@ void BitmapText::BuildChars()
for( i=0; i<m_szTextLines.size(); i++ ) // foreach line for( i=0; i<m_szTextLines.size(); i++ ) // foreach line
{ {
const CString &szLine = m_szTextLines[i]; const wstring &szLine = m_szTextLines[i];
const int iLineWidth = m_iLineWidths[i]; const int iLineWidth = m_iLineWidths[i];
int iX; int iX;
@@ -172,6 +252,8 @@ void BitmapText::DrawChars()
} }
} }
/* sText is UTF-8. */
void BitmapText::SetText( CString sText ) void BitmapText::SetText( CString sText )
{ {
ASSERT( m_pFont ); ASSERT( m_pFont );
@@ -185,7 +267,7 @@ void BitmapText::SetText( CString sText )
m_iLineWidths.clear(); m_iLineWidths.clear();
m_iLineHeights.clear(); m_iLineHeights.clear();
split(m_szText, "\n", m_szTextLines, false); split(CStringToWstring(sText), L"\n", m_szTextLines, false);
/* calculate line lengths and widths */ /* calculate line lengths and widths */
m_iWidestLineWidth = 0; m_iWidestLineWidth = 0;
+2 -2
View File
@@ -46,8 +46,8 @@ public:
protected: protected:
// recalculate the items below on SetText() // recalculate the items below on SetText()
CString m_szText; CString m_szText;
vector<CString> m_szTextLines; vector<wstring> m_szTextLines;
vector<int> m_iLineWidths; // in source pixels vector<int> m_iLineWidths; // in source pixels
vector<int> m_iLineHeights; // in source pixels vector<int> m_iLineHeights; // in source pixels
int m_iWidestLineWidth; // in source pixels int m_iWidestLineWidth; // in source pixels
+10 -10
View File
@@ -34,7 +34,7 @@ void FontPage::Load( const CString &TexturePath, const FontPageSettings &cfg )
ASSERT( m_pTexture != NULL ); ASSERT( m_pTexture != NULL );
// load character widths // load character widths
vector<int> FrameWidths; // = cfg.GlyphWidths; vector<int> FrameWidths;
int i; int i;
// Assume each character is the width of the frame by default. // Assume each character is the width of the frame by default.
for( i=0; i<m_pTexture->GetNumFrames(); i++ ) for( i=0; i<m_pTexture->GetNumFrames(); i++ )
@@ -155,7 +155,7 @@ FontPage::~FontPage()
} }
int Font::GetLineWidthInSourcePixels( const CString &szLine ) const int Font::GetLineWidthInSourcePixels( const wstring &szLine ) const
{ {
int LineWidth = 0; int LineWidth = 0;
@@ -165,7 +165,7 @@ int Font::GetLineWidthInSourcePixels( const CString &szLine ) const
return LineWidth; return LineWidth;
} }
int Font::GetLineHeightInSourcePixels( const CString &szLine ) const int Font::GetLineHeightInSourcePixels( const wstring &szLine ) const
{ {
int iLineSpacing = 0; int iLineSpacing = 0;
@@ -194,16 +194,16 @@ void Font::AddPage(FontPage *fp)
{ {
pages.push_back(fp); pages.push_back(fp);
for(map<int,int>::const_iterator it = fp->m_iCharToGlyphNo.begin(); for(map<wchar_t,int>::const_iterator it = fp->m_iCharToGlyphNo.begin();
it != fp->m_iCharToGlyphNo.end(); ++it) it != fp->m_iCharToGlyphNo.end(); ++it)
{ {
m_iCharToGlyph[it->first] = &fp->glyphs[it->second]; m_iCharToGlyph[it->first] = &fp->glyphs[it->second];
} }
} }
const glyph &Font::GetGlyph( int c ) const const glyph &Font::GetGlyph( wchar_t c ) const
{ {
map<int,glyph*>::const_iterator it = m_iCharToGlyph.find(c); map<wchar_t,glyph*>::const_iterator it = m_iCharToGlyph.find(c);
if(it == m_iCharToGlyph.end()) if(it == m_iCharToGlyph.end())
RageException::Throw( "The font '%s' does not implement the character '%c'", path.GetString(), c ); RageException::Throw( "The font '%s' does not implement the character '%c'", path.GetString(), c );
@@ -211,9 +211,9 @@ const glyph &Font::GetGlyph( int c ) const
return *it->second; return *it->second;
} }
RageTexture *Font::GetGlyphTexture( int c ) RageTexture *Font::GetGlyphTexture( wchar_t c )
{ {
map<int,glyph*>::iterator it = m_iCharToGlyph.find(c); map<wchar_t,glyph*>::iterator it = m_iCharToGlyph.find(c);
if(it == m_iCharToGlyph.end()) if(it == m_iCharToGlyph.end())
RageException::Throw( "The font '%s' does not implement the character '%c'", path.GetString(), c ); RageException::Throw( "The font '%s' does not implement the character '%c'", path.GetString(), c );
@@ -227,11 +227,11 @@ void Font::CapsOnly()
* a lowercase one. */ * a lowercase one. */
for(char c = 'A'; c <= 'Z'; ++c) for(char c = 'A'; c <= 'Z'; ++c)
{ {
map<int,glyph*>::const_iterator it = m_iCharToGlyph.find(c); map<wchar_t,glyph*>::const_iterator it = m_iCharToGlyph.find(c);
if(it == m_iCharToGlyph.end()) if(it == m_iCharToGlyph.end())
continue; continue;
m_iCharToGlyph[tolower(c)] = it->second; m_iCharToGlyph[(char) tolower(c)] = it->second;
} }
} }
+8 -10
View File
@@ -37,7 +37,7 @@ struct FontPageSettings {
LineSpacing; LineSpacing;
float ScaleAllWidthsBy; float ScaleAllWidthsBy;
map<int,int> CharToGlyphNo; map<wchar_t,int> CharToGlyphNo;
/* If a value is missing, the width of the texture frame is used. */ /* If a value is missing, the width of the texture frame is used. */
map<int,int> GlyphWidths; map<int,int> GlyphWidths;
@@ -49,6 +49,7 @@ struct FontPageSettings {
{ } { }
}; };
// typedef basic_string<wchar_t> wstring;
class FontPage class FontPage
{ {
@@ -60,14 +61,11 @@ public:
/* All glyphs in this list will point to m_pTexture. */ /* All glyphs in this list will point to m_pTexture. */
vector<glyph> glyphs; vector<glyph> glyphs;
map<int,int> m_iCharToGlyphNo; map<wchar_t,int> m_iCharToGlyphNo;
FontPage(); FontPage();
~FontPage(); ~FontPage();
int GetLineWidthInSourcePixels( const CString &szLine );
int GetLineHeightInSourcePixels( const CString &szLine );
void Load( const CString &sASCIITexturePath, const FontPageSettings &cfg ); void Load( const CString &sASCIITexturePath, const FontPageSettings &cfg );
private: private:
@@ -80,16 +78,16 @@ class Font
public: public:
int m_iRefCount; int m_iRefCount;
CString path; CString path;
map<int,glyph*> m_iCharToGlyph; map<wchar_t,glyph*> m_iCharToGlyph;
Font(); Font();
~Font(); ~Font();
RageTexture *GetGlyphTexture( int c ); RageTexture *GetGlyphTexture( wchar_t c );
const glyph &GetGlyph( int c ) const; const glyph &GetGlyph( wchar_t c ) const;
int GetLineWidthInSourcePixels( const CString &szLine ) const; int GetLineWidthInSourcePixels( const wstring &szLine ) const;
int GetLineHeightInSourcePixels( const CString &szLine ) const; int GetLineHeightInSourcePixels( const wstring &szLine ) const;
/* Add a FontPage to this font. */ /* Add a FontPage to this font. */
void AddPage(FontPage *fp); void AddPage(FontPage *fp);
+4 -5
View File
@@ -19,7 +19,7 @@
#include "RageException.h" #include "RageException.h"
#include "RageTimer.h" #include "RageTimer.h"
static map <CString, int, StdStringLessNoCase> CharAliases; static map <CString, wchar_t, StdStringLessNoCase> CharAliases;
FontManager* FONT = NULL; FontManager* FONT = NULL;
@@ -53,7 +53,7 @@ void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, cons
else if(NumFrames == 256) else if(NumFrames == 256)
cfg.MapRange("ISO-8859-1", 0, 255, 0); cfg.MapRange("ISO-8859-1", 0, 255, 0);
*/ */
for( int i=0; i<NumFrames; i++ ) for( wchar_t i=0; i<NumFrames; i++ )
cfg.CharToGlyphNo[i] = i; cfg.CharToGlyphNo[i] = i;
} }
ini.RenameKey("Char Widths", "main"); ini.RenameKey("Char Widths", "main");
@@ -93,14 +93,13 @@ void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, cons
*/ */
CString codepoint = val.substr(4); /* "XXXX" */ CString codepoint = val.substr(4); /* "XXXX" */
int c = -1; wchar_t c;
if(codepoint.substr(0, 2) == "U+" && IsHexVal(codepoint.substr(2))) if(codepoint.substr(0, 2) == "U+" && IsHexVal(codepoint.substr(2)))
sscanf(codepoint.substr(2).c_str(), "%x", &c); sscanf(codepoint.substr(2).c_str(), "%x", &c);
else if(CharAliases.find(codepoint) != CharAliases.end()) else if(CharAliases.find(codepoint) != CharAliases.end())
c = CharAliases[codepoint]; c = CharAliases[codepoint];
else
if(c == -1)
RageException::Throw( "Font definition '%s' has an invalid value '%s'.", RageException::Throw( "Font definition '%s' has an invalid value '%s'.",
ini.GetPath().GetString(), val.GetString() ); ini.GetPath().GetString(), val.GetString() );
+18 -8
View File
@@ -116,10 +116,7 @@ CString ThemeManager::GetThemeDirFromName( CString sThemeName )
CString ThemeManager::GetPathTo( CString sAssetCategory, CString sFileName ) CString ThemeManager::GetPathTo( CString sAssetCategory, CString sFileName )
{ {
#ifdef _DEBUG
try_element_again: try_element_again:
#endif
sAssetCategory.MakeLower(); sAssetCategory.MakeLower();
sFileName.MakeLower(); sFileName.MakeLower();
@@ -139,6 +136,7 @@ try_element_again:
static const char *font_masks[] = { " 16x16.png", ".redir", NULL }; static const char *font_masks[] = { " 16x16.png", ".redir", NULL };
static const char *numbers_masks[] = { " 5x3.png", ".redir", NULL }; static const char *numbers_masks[] = { " 5x3.png", ".redir", NULL };
static const char *bganimations_masks[] = { ".", ".redir", NULL }; static const char *bganimations_masks[] = { ".", ".redir", NULL };
static const char *blank_mask[] = { "", NULL };
const char **asset_masks = NULL; const char **asset_masks = NULL;
if( sAssetCategory == "graphics" ) asset_masks = graphic_masks; if( sAssetCategory == "graphics" ) asset_masks = graphic_masks;
else if( sAssetCategory == "sounds" ) asset_masks = sound_masks; else if( sAssetCategory == "sounds" ) asset_masks = sound_masks;
@@ -146,8 +144,15 @@ try_element_again:
else if( sAssetCategory == "numbers" ) asset_masks = numbers_masks; else if( sAssetCategory == "numbers" ) asset_masks = numbers_masks;
else if( sAssetCategory == "bganimations" ) asset_masks = bganimations_masks; else if( sAssetCategory == "bganimations" ) asset_masks = bganimations_masks;
else ASSERT(0); // Unknown theme asset category else ASSERT(0); // Unknown theme asset category
/* If the theme asset name has an extension, don't add
* a mask. This should only happen with redirs. */
if(sFileName.find_last_of('.') != sFileName.npos)
asset_masks = blank_mask;
int i; int i;
CString path; CString path;
for(i = 0; asset_masks[i]; ++i) for(i = 0; asset_masks[i]; ++i)
{ {
path = sCurrentThemeDir; path = sCurrentThemeDir;
@@ -204,11 +209,8 @@ try_element_again:
/* backwards-compatibility hack */ /* backwards-compatibility hack */
if( sAssetCategory == "fonts" ) if( sAssetCategory == "fonts" )
sNewFilePath.Replace(" 16x16.png", ""); sNewFilePath.Replace(" 16x16.png", "");
return sNewFilePath;
} }
else if( !DoesFileExist(sNewFilePath) )
if( !DoesFileExist(sNewFilePath) )
{ {
CString message = ssprintf( CString message = ssprintf(
"The redirect '%s' points to the file '%s', which does not exist." "The redirect '%s' points to the file '%s', which does not exist."
@@ -222,8 +224,16 @@ try_element_again:
RageException::Throw( "%s", message.GetString() ); RageException::Throw( "%s", message.GetString() );
} }
/* Search again. For example, themes/default/Fonts/foo might redir
* to "Hello"; but "Hello" might be overridden in themes/hot pink/Fonts/Hello. */
return sNewFilePath; /* Strip off the path. */
unsigned pos = sNewFilePath.find_last_of("/\\");
if(pos != sNewFilePath.npos) sNewFilePath = sNewFilePath.substr(pos+1);
sFileName = sNewFilePath;
/* XXX check for loops */
goto try_element_again;
} }
/* If we're searching for a font, the return value should be the file /* If we're searching for a font, the return value should be the file