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 "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))
@@ -118,7 +198,7 @@ void BitmapText::BuildChars()
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];
int iX;
@@ -172,6 +252,8 @@ void BitmapText::DrawChars()
}
}
/* sText is UTF-8. */
void BitmapText::SetText( CString sText )
{
ASSERT( m_pFont );
@@ -185,7 +267,7 @@ void BitmapText::SetText( CString sText )
m_iLineWidths.clear();
m_iLineHeights.clear();
split(m_szText, "\n", m_szTextLines, false);
split(CStringToWstring(sText), L"\n", m_szTextLines, false);
/* calculate line lengths and widths */
m_iWidestLineWidth = 0;
+2 -2
View File
@@ -46,8 +46,8 @@ public:
protected:
// recalculate the items below on SetText()
CString m_szText;
vector<CString> m_szTextLines;
CString m_szText;
vector<wstring> m_szTextLines;
vector<int> m_iLineWidths; // in source pixels
vector<int> m_iLineHeights; // 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 );
// load character widths
vector<int> FrameWidths; // = cfg.GlyphWidths;
vector<int> FrameWidths;
int i;
// Assume each character is the width of the frame by default.
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;
@@ -165,7 +165,7 @@ int Font::GetLineWidthInSourcePixels( const CString &szLine ) const
return LineWidth;
}
int Font::GetLineHeightInSourcePixels( const CString &szLine ) const
int Font::GetLineHeightInSourcePixels( const wstring &szLine ) const
{
int iLineSpacing = 0;
@@ -194,16 +194,16 @@ void Font::AddPage(FontPage *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)
{
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())
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;
}
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())
RageException::Throw( "The font '%s' does not implement the character '%c'", path.GetString(), c );
@@ -227,11 +227,11 @@ void Font::CapsOnly()
* a lowercase one. */
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())
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;
float ScaleAllWidthsBy;
map<int,int> CharToGlyphNo;
map<wchar_t,int> CharToGlyphNo;
/* If a value is missing, the width of the texture frame is used. */
map<int,int> GlyphWidths;
@@ -49,6 +49,7 @@ struct FontPageSettings {
{ }
};
// typedef basic_string<wchar_t> wstring;
class FontPage
{
@@ -60,14 +61,11 @@ public:
/* All glyphs in this list will point to m_pTexture. */
vector<glyph> glyphs;
map<int,int> m_iCharToGlyphNo;
map<wchar_t,int> m_iCharToGlyphNo;
FontPage();
~FontPage();
int GetLineWidthInSourcePixels( const CString &szLine );
int GetLineHeightInSourcePixels( const CString &szLine );
void Load( const CString &sASCIITexturePath, const FontPageSettings &cfg );
private:
@@ -80,16 +78,16 @@ class Font
public:
int m_iRefCount;
CString path;
map<int,glyph*> m_iCharToGlyph;
map<wchar_t,glyph*> m_iCharToGlyph;
Font();
~Font();
RageTexture *GetGlyphTexture( int c );
const glyph &GetGlyph( int c ) const;
RageTexture *GetGlyphTexture( wchar_t c );
const glyph &GetGlyph( wchar_t c ) const;
int GetLineWidthInSourcePixels( const CString &szLine ) const;
int GetLineHeightInSourcePixels( const CString &szLine ) const;
int GetLineWidthInSourcePixels( const wstring &szLine ) const;
int GetLineHeightInSourcePixels( const wstring &szLine ) const;
/* Add a FontPage to this font. */
void AddPage(FontPage *fp);
+4 -5
View File
@@ -19,7 +19,7 @@
#include "RageException.h"
#include "RageTimer.h"
static map <CString, int, StdStringLessNoCase> CharAliases;
static map <CString, wchar_t, StdStringLessNoCase> CharAliases;
FontManager* FONT = NULL;
@@ -53,7 +53,7 @@ void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, cons
else if(NumFrames == 256)
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;
}
ini.RenameKey("Char Widths", "main");
@@ -93,14 +93,13 @@ void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, cons
*/
CString codepoint = val.substr(4); /* "XXXX" */
int c = -1;
wchar_t c;
if(codepoint.substr(0, 2) == "U+" && IsHexVal(codepoint.substr(2)))
sscanf(codepoint.substr(2).c_str(), "%x", &c);
else if(CharAliases.find(codepoint) != CharAliases.end())
c = CharAliases[codepoint];
if(c == -1)
else
RageException::Throw( "Font definition '%s' has an invalid value '%s'.",
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 )
{
#ifdef _DEBUG
try_element_again:
#endif
sAssetCategory.MakeLower();
sFileName.MakeLower();
@@ -139,6 +136,7 @@ try_element_again:
static const char *font_masks[] = { " 16x16.png", ".redir", NULL };
static const char *numbers_masks[] = { " 5x3.png", ".redir", NULL };
static const char *bganimations_masks[] = { ".", ".redir", NULL };
static const char *blank_mask[] = { "", NULL };
const char **asset_masks = NULL;
if( sAssetCategory == "graphics" ) asset_masks = graphic_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 == "bganimations" ) asset_masks = bganimations_masks;
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;
CString path;
for(i = 0; asset_masks[i]; ++i)
{
path = sCurrentThemeDir;
@@ -204,11 +209,8 @@ try_element_again:
/* backwards-compatibility hack */
if( sAssetCategory == "fonts" )
sNewFilePath.Replace(" 16x16.png", "");
return sNewFilePath;
}
if( !DoesFileExist(sNewFilePath) )
else if( !DoesFileExist(sNewFilePath) )
{
CString message = ssprintf(
"The redirect '%s' points to the file '%s', which does not exist."
@@ -222,8 +224,16 @@ try_element_again:
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