add loading of font stroke texture

This commit is contained in:
Chris Danford
2008-02-15 09:41:19 +00:00
parent 7d1cff4639
commit 4be68e9930
2 changed files with 76 additions and 36 deletions
+61 -33
View File
@@ -13,7 +13,6 @@
FontPage::FontPage() FontPage::FontPage()
{ {
m_pTexture = NULL;
m_iDrawExtraPixelsLeft = m_iDrawExtraPixelsRight = 0; m_iDrawExtraPixelsLeft = m_iDrawExtraPixelsRight = 0;
} }
@@ -22,24 +21,40 @@ void FontPage::Load( const FontPageSettings &cfg )
m_sTexturePath = cfg.m_sTexturePath; m_sTexturePath = cfg.m_sTexturePath;
// load texture // load texture
RageTextureID ID( m_sTexturePath ); RageTextureID ID1( m_sTexturePath );
if( cfg.m_sTextureHints != "default" ) if( cfg.m_sTextureHints != "default" )
ID.AdditionalTextureHints = cfg.m_sTextureHints; ID1.AdditionalTextureHints = cfg.m_sTextureHints;
else
ID.AdditionalTextureHints = "16bpp";
m_pTexture = TEXTUREMAN->LoadTexture( ID ); m_FontPageTextures.m_pTextureMain = TEXTUREMAN->LoadTexture( ID1 );
ASSERT( m_pTexture != NULL ); ASSERT( m_FontPageTextures.m_pTextureMain != NULL );
RageTextureID ID2 = ID1;
{
/* "arial 20 16x16.png" => "arial 20 16x16 (stroke).png" */
size_t pos = ID2.filename.find_last_of( '.' );
if( pos == RString::npos )
ID2.filename += " (stroke)";
else
ID2.filename.insert( pos, " (stroke)" );
}
if( IsAFile(ID2.filename) )
{
m_FontPageTextures.m_pTextureStroke = TEXTUREMAN->LoadTexture( ID2 );
ASSERT( m_FontPageTextures.m_pTextureStroke != NULL );
ASSERT_M( m_FontPageTextures.m_pTextureMain->GetSourceFrameWidth() == m_FontPageTextures.m_pTextureStroke->GetSourceFrameWidth(), ssprintf("'%s' and '%s' must have the same frame widths", ID1.filename.c_str(), ID2.filename.c_str()) );
ASSERT_M( m_FontPageTextures.m_pTextureMain->GetNumFrames() == m_FontPageTextures.m_pTextureStroke->GetNumFrames(), ssprintf("'%s' and '%s' must have the same frame dimensions", ID1.filename.c_str(), ID2.filename.c_str()) );
}
// load character widths // load character widths
vector<int> aiFrameWidths; vector<int> aiFrameWidths;
int default_width = m_pTexture->GetSourceFrameWidth(); int default_width = m_FontPageTextures.m_pTextureMain->GetSourceFrameWidth();
if( cfg.m_iDefaultWidth != -1 ) if( cfg.m_iDefaultWidth != -1 )
default_width = cfg.m_iDefaultWidth; default_width = cfg.m_iDefaultWidth;
// Assume each character is the width of the frame by default. // Assume each character is the width of the frame by default.
for( int i=0; i<m_pTexture->GetNumFrames(); i++ ) for( int i=0; i<m_FontPageTextures.m_pTextureMain->GetNumFrames(); i++ )
{ {
map<int,int>::const_iterator it = cfg.m_mapGlyphWidths.find(i); map<int,int>::const_iterator it = cfg.m_mapGlyphWidths.find(i);
if( it != cfg.m_mapGlyphWidths.end() ) if( it != cfg.m_mapGlyphWidths.end() )
@@ -50,13 +65,13 @@ void FontPage::Load( const FontPageSettings &cfg )
if( cfg.m_iAddToAllWidths ) if( cfg.m_iAddToAllWidths )
{ {
for( int i=0; i<m_pTexture->GetNumFrames(); i++ ) for( int i=0; i<m_FontPageTextures.m_pTextureMain->GetNumFrames(); i++ )
aiFrameWidths[i] += cfg.m_iAddToAllWidths; aiFrameWidths[i] += cfg.m_iAddToAllWidths;
} }
if( cfg.m_fScaleAllWidthsBy != 1 ) if( cfg.m_fScaleAllWidthsBy != 1 )
{ {
for( int i=0; i<m_pTexture->GetNumFrames(); i++ ) for( int i=0; i<m_FontPageTextures.m_pTextureMain->GetNumFrames(); i++ )
aiFrameWidths[i] = lrintf( aiFrameWidths[i] * cfg.m_fScaleAllWidthsBy ); aiFrameWidths[i] = lrintf( aiFrameWidths[i] * cfg.m_fScaleAllWidthsBy );
} }
@@ -64,7 +79,7 @@ void FontPage::Load( const FontPageSettings &cfg )
m_iLineSpacing = cfg.m_iLineSpacing; m_iLineSpacing = cfg.m_iLineSpacing;
if( m_iLineSpacing == -1 ) if( m_iLineSpacing == -1 )
m_iLineSpacing = m_pTexture->GetSourceFrameHeight(); m_iLineSpacing = m_FontPageTextures.m_pTextureMain->GetSourceFrameHeight();
int iBaseline=0; int iBaseline=0;
/* If we don't have a top and/or baseline, assume we're centered in the /* If we don't have a top and/or baseline, assume we're centered in the
@@ -72,14 +87,14 @@ void FontPage::Load( const FontPageSettings &cfg )
iBaseline = cfg.m_iBaseline; iBaseline = cfg.m_iBaseline;
if( iBaseline == -1 ) if( iBaseline == -1 )
{ {
float center = m_pTexture->GetSourceFrameHeight()/2.0f; float center = m_FontPageTextures.m_pTextureMain->GetSourceFrameHeight()/2.0f;
iBaseline = int( center + m_iLineSpacing/2 ); iBaseline = int( center + m_iLineSpacing/2 );
} }
int iTop = cfg.m_iTop; int iTop = cfg.m_iTop;
if( iTop == -1 ) if( iTop == -1 )
{ {
float center = m_pTexture->GetSourceFrameHeight()/2.0f; float center = m_FontPageTextures.m_pTextureMain->GetSourceFrameHeight()/2.0f;
iTop = int( center - m_iLineSpacing/2 ); iTop = int( center - m_iLineSpacing/2 );
} }
m_iHeight = iBaseline - iTop; m_iHeight = iBaseline - iTop;
@@ -98,7 +113,7 @@ void FontPage::Load( const FontPageSettings &cfg )
void FontPage::SetTextureCoords( const vector<int> &widths, int iAdvanceExtraPixels ) void FontPage::SetTextureCoords( const vector<int> &widths, int iAdvanceExtraPixels )
{ {
for(int i = 0; i < m_pTexture->GetNumFrames(); ++i) for(int i = 0; i < m_FontPageTextures.m_pTextureMain->GetNumFrames(); ++i)
{ {
glyph g; glyph g;
@@ -106,11 +121,11 @@ void FontPage::SetTextureCoords( const vector<int> &widths, int iAdvanceExtraPix
/* Make a copy of each texture rect, reducing each to the actual dimensions /* Make a copy of each texture rect, reducing each to the actual dimensions
* of the character (most characters don't take a full block). */ * of the character (most characters don't take a full block). */
g.m_TexRect = *m_pTexture->GetTextureCoordRect(i); g.m_TexRect = *m_FontPageTextures.m_pTextureMain->GetTextureCoordRect(i);
/* Set the width and height to the width and line spacing, respectively. */ /* Set the width and height to the width and line spacing, respectively. */
g.m_fWidth = float( widths[i] ); g.m_fWidth = float( widths[i] );
g.m_fHeight = float(m_pTexture->GetSourceFrameHeight()); g.m_fHeight = float(m_FontPageTextures.m_pTextureMain->GetSourceFrameHeight());
g.m_iHadvance = int(g.m_fWidth) + iAdvanceExtraPixels; g.m_iHadvance = int(g.m_fWidth) + iAdvanceExtraPixels;
@@ -119,7 +134,7 @@ void FontPage::SetTextureCoords( const vector<int> &widths, int iAdvanceExtraPix
* need to. */ * need to. */
g.m_fHshift = 0; g.m_fHshift = 0;
{ {
int iSourcePixelsToChopOff = m_pTexture->GetSourceFrameWidth() - widths[i]; int iSourcePixelsToChopOff = m_FontPageTextures.m_pTextureMain->GetSourceFrameWidth() - widths[i];
if( (iSourcePixelsToChopOff % 2) == 1 ) if( (iSourcePixelsToChopOff % 2) == 1 )
{ {
/* We don't want to chop off an odd number of pixels, since that'll /* We don't want to chop off an odd number of pixels, since that'll
@@ -132,13 +147,13 @@ void FontPage::SetTextureCoords( const vector<int> &widths, int iAdvanceExtraPix
++g.m_fWidth; ++g.m_fWidth;
} }
const float fTexCoordsToChopOff = iSourcePixelsToChopOff * m_pTexture->GetSourceToTexCoordsRatioX(); const float fTexCoordsToChopOff = iSourcePixelsToChopOff * m_FontPageTextures.m_pTextureMain->GetSourceToTexCoordsRatioX();
g.m_TexRect.left += fTexCoordsToChopOff/2; g.m_TexRect.left += fTexCoordsToChopOff/2;
g.m_TexRect.right -= fTexCoordsToChopOff/2; g.m_TexRect.right -= fTexCoordsToChopOff/2;
} }
g.m_pTexture = m_pTexture; g.m_FontPageTextures = m_FontPageTextures;
m_aGlyphs.push_back(g); m_aGlyphs.push_back(g);
} }
@@ -157,7 +172,7 @@ void FontPage::SetExtraPixels( int iDrawExtraPixelsLeft, int iDrawExtraPixelsRig
/* Adjust for iDrawExtraPixelsLeft and iDrawExtraPixelsRight. */ /* Adjust for iDrawExtraPixelsLeft and iDrawExtraPixelsRight. */
for( unsigned i = 0; i < m_aGlyphs.size(); ++i ) for( unsigned i = 0; i < m_aGlyphs.size(); ++i )
{ {
int iFrameWidth = m_pTexture->GetSourceFrameWidth(); int iFrameWidth = m_FontPageTextures.m_pTextureMain->GetSourceFrameWidth();
float fCharWidth = m_aGlyphs[i].m_fWidth; float fCharWidth = m_aGlyphs[i].m_fWidth;
/* Extra pixels to draw to the left and right. We don't have to /* Extra pixels to draw to the left and right. We don't have to
@@ -167,8 +182,8 @@ void FontPage::SetExtraPixels( int iDrawExtraPixelsLeft, int iDrawExtraPixelsRig
float fExtraRight = min( float(iDrawExtraPixelsRight), (iFrameWidth-fCharWidth)/2.0f ); float fExtraRight = min( float(iDrawExtraPixelsRight), (iFrameWidth-fCharWidth)/2.0f );
/* Move left and expand right. */ /* Move left and expand right. */
m_aGlyphs[i].m_TexRect.left -= fExtraLeft * m_pTexture->GetSourceToTexCoordsRatioX(); m_aGlyphs[i].m_TexRect.left -= fExtraLeft * m_FontPageTextures.m_pTextureMain->GetSourceToTexCoordsRatioX();
m_aGlyphs[i].m_TexRect.right += fExtraRight * m_pTexture->GetSourceToTexCoordsRatioX(); m_aGlyphs[i].m_TexRect.right += fExtraRight * m_FontPageTextures.m_pTextureMain->GetSourceToTexCoordsRatioX();
m_aGlyphs[i].m_fHshift -= fExtraLeft; m_aGlyphs[i].m_fHshift -= fExtraLeft;
m_aGlyphs[i].m_fWidth += fExtraLeft + fExtraRight; m_aGlyphs[i].m_fWidth += fExtraLeft + fExtraRight;
} }
@@ -176,8 +191,16 @@ void FontPage::SetExtraPixels( int iDrawExtraPixelsLeft, int iDrawExtraPixelsRig
FontPage::~FontPage() FontPage::~FontPage()
{ {
if( m_pTexture != NULL ) if( m_FontPageTextures.m_pTextureMain != NULL )
TEXTUREMAN->UnloadTexture( m_pTexture ); {
TEXTUREMAN->UnloadTexture( m_FontPageTextures.m_pTextureMain );
m_FontPageTextures.m_pTextureMain = NULL;
}
if( m_FontPageTextures.m_pTextureStroke != NULL )
{
TEXTUREMAN->UnloadTexture( m_FontPageTextures.m_pTextureStroke );
m_FontPageTextures.m_pTextureStroke = NULL;
}
} }
int Font::GetLineWidthInSourcePixels( const wstring &szLine ) const int Font::GetLineWidthInSourcePixels( const wstring &szLine ) const
@@ -505,9 +528,7 @@ void Font::LoadFontPageSettings( FontPageSettings &cfg, IniFile &ini, const RStr
* This lets us assign characters very compactly and readably. */ * This lets us assign characters very compactly and readably. */
RString sRowStr = sName.substr(5); RString sRowStr = sName.substr(5);
TrimLeft( sRowStr );
ASSERT( IsAnInt(sRowStr) ); ASSERT( IsAnInt(sRowStr) );
const int iRow = atoi( sRowStr.c_str() ); const int iRow = atoi( sRowStr.c_str() );
const int iFirstFrame = iRow * iNumFramesWide; const int iFirstFrame = iRow * iNumFramesWide;
@@ -534,15 +555,22 @@ void Font::LoadFontPageSettings( FontPageSettings &cfg, IniFile &ini, const RStr
* it itself). */ * it itself). */
if( sPageName != "common" && cfg.CharToGlyphNo.empty() ) if( sPageName != "common" && cfg.CharToGlyphNo.empty() )
{ {
if( iNumFrames == 128 ) switch( iNumFrames )
{
case 128:
cfg.MapRange( "ascii", 0, 0, -1 ); cfg.MapRange( "ascii", 0, 0, -1 );
else if( iNumFrames == 256 ) break;
case 256:
cfg.MapRange( "cp1252", 0, 0, -1 ); cfg.MapRange( "cp1252", 0, 0, -1 );
else if( iNumFrames == 15 ) break;
case 15:
case 16:
cfg.MapRange( "numbers", 0, 0, -1 ); cfg.MapRange( "numbers", 0, 0, -1 );
else break;
default:
LOG->Trace( "Font page \"%s\" has no characters", sTexturePath.c_str() ); LOG->Trace( "Font page \"%s\" has no characters", sTexturePath.c_str() );
} }
}
/* If ' ' is set and nbsp is not, set nbsp. */ /* If ' ' is set and nbsp is not, set nbsp. */
if( cfg.CharToGlyphNo.find(' ') != cfg.CharToGlyphNo.end() ) if( cfg.CharToGlyphNo.find(' ') != cfg.CharToGlyphNo.end() )
@@ -727,10 +755,10 @@ void Font::Load( const RString &sIniPath, RString sChars )
for( map<wchar_t,int>::const_iterator it = pPage->m_iCharToGlyphNo.begin(); for( map<wchar_t,int>::const_iterator it = pPage->m_iCharToGlyphNo.begin();
it != pPage->m_iCharToGlyphNo.end(); ++it ) it != pPage->m_iCharToGlyphNo.end(); ++it )
{ {
if( it->second < pPage->m_pTexture->GetNumFrames() ) if( it->second < pPage->m_FontPageTextures.m_pTextureMain->GetNumFrames() )
continue; /* OK */ continue; /* OK */
RageException::Throw( "The font \"%s\" maps \"%s\" to frame %i, but the font only has %i frames.", RageException::Throw( "The font \"%s\" maps \"%s\" to frame %i, but the font only has %i frames.",
sTexturePath.c_str(), WcharDisplayText(wchar_t(it->first)).c_str(), it->second, pPage->m_pTexture->GetNumFrames() ); sTexturePath.c_str(), WcharDisplayText(wchar_t(it->first)).c_str(), it->second, pPage->m_FontPageTextures.m_pTextureMain->GetNumFrames() );
} }
// LOG->Trace( "Adding page %s (%s) to %s; %i glyphs", // LOG->Trace( "Adding page %s (%s) to %s; %i glyphs",
+15 -3
View File
@@ -12,11 +12,23 @@ class FontPage;
class RageTexture; class RageTexture;
class IniFile; class IniFile;
struct FontPageTextures
{
RageTexture *m_pTextureMain;
RageTexture *m_pTextureStroke; /* an optional texture drawn underneath Main that can help to acheive complicated layer styles */
FontPageTextures()
{
m_pTextureMain = NULL;
m_pTextureStroke = NULL;
}
};
struct glyph struct glyph
{ {
FontPage *m_pPage; FontPage *m_pPage;
RageTexture *m_pTexture; FontPageTextures m_FontPageTextures;
RageTexture *GetTexture() const { return const_cast<RageTexture *>(m_pTexture); } FontPageTextures *GetFontPageTextures() const { return const_cast<FontPageTextures *>(&m_FontPageTextures); }
/* Number of pixels to advance horizontally after drawing this character. */ /* Number of pixels to advance horizontally after drawing this character. */
int m_iHadvance; int m_iHadvance;
@@ -84,7 +96,7 @@ public:
/* Remember these only for GetLineWidthInSourcePixels. */ /* Remember these only for GetLineWidthInSourcePixels. */
int m_iDrawExtraPixelsLeft, m_iDrawExtraPixelsRight; int m_iDrawExtraPixelsLeft, m_iDrawExtraPixelsRight;
RageTexture* m_pTexture; FontPageTextures m_FontPageTextures;
// XXX remove? // XXX remove?
RString m_sTexturePath; RString m_sTexturePath;