diff --git a/stepmania/src/BitmapText.cpp b/stepmania/src/BitmapText.cpp index 09aa37a4c1..380d17f623 100644 --- a/stepmania/src/BitmapText.cpp +++ b/stepmania/src/BitmapText.cpp @@ -187,28 +187,29 @@ void BitmapText::DrawPrimitives() for( unsigned j=0; jm_iCharToFrameNo[ (unsigned char)c ]; - if( iFrameNo == -1 ) // this font doesn't impelemnt this character + if(m_pFont->m_iCharToFrameNo.find(c) == m_pFont->m_iCharToFrameNo.end()) RageException::Throw( "The font '%s' does not implement the character '%c'", m_sFontFilePath.GetString(), c ); + const int iFrameNo = m_pFont->m_iCharToFrameNo[ (unsigned char)c ]; + + const glyph &g = m_pFont->GetGlyph(iFrameNo); + /* set vertex positions */ - v[iNumV++].p = RageVector3( (float)iX-m_pFont->m_Left[iFrameNo], iY-iHeight/2.0f, 0 ); // top left - v[iNumV++].p = RageVector3( (float)iX-m_pFont->m_Left[iFrameNo], iY+iHeight/2.0f, 0 ); // bottom left - v[iNumV++].p = RageVector3( (float)iX+m_pFont->m_Right[iFrameNo], iY+iHeight/2.0f, 0 ); // bottom right - v[iNumV++].p = RageVector3( (float)iX+m_pFont->m_Right[iFrameNo], iY-iHeight/2.0f, 0 ); // top right + v[iNumV++].p = RageVector3( (float)iX-g.left, iY-iHeight/2.0f, 0 ); // top left + v[iNumV++].p = RageVector3( (float)iX-g.left, iY+iHeight/2.0f, 0 ); // bottom left + v[iNumV++].p = RageVector3( (float)iX+g.right, iY+iHeight/2.0f, 0 ); // bottom right + v[iNumV++].p = RageVector3( (float)iX+g.right, iY-iHeight/2.0f, 0 ); // top right /* Advance the cursor. */ - iX += m_pFont->m_iFrameNoToWidth[iFrameNo]; + iX += g.width; /* set texture coordinates */ iNumV -= 4; - RectF frectTexCoords = m_pFont->GetTextureCoordRect( iFrameNo ); - - v[iNumV++].t = RageVector2( frectTexCoords.left, frectTexCoords.top ); // top left - v[iNumV++].t = RageVector2( frectTexCoords.left, frectTexCoords.bottom ); // bottom left - v[iNumV++].t = RageVector2( frectTexCoords.right, frectTexCoords.bottom ); // bottom right - v[iNumV++].t = RageVector2( frectTexCoords.right, frectTexCoords.top ); // top right + v[iNumV++].t = RageVector2( g.rect.left, g.rect.top ); // top left + v[iNumV++].t = RageVector2( g.rect.left, g.rect.bottom ); // bottom left + v[iNumV++].t = RageVector2( g.rect.right, g.rect.bottom ); // bottom right + v[iNumV++].t = RageVector2( g.rect.right, g.rect.top ); // top right } iY += iLineSpacing; diff --git a/stepmania/src/Font.cpp b/stepmania/src/Font.cpp index 076d3076f1..78cc791cc4 100644 --- a/stepmania/src/Font.cpp +++ b/stepmania/src/Font.cpp @@ -23,17 +23,74 @@ void Font::Init() { + m_bCapitalsOnly = false; + m_iRefCount = 1; +} + +void Font::Load( const CString &TexturePath, IniFile &ini ) +{ + m_sTexturePath = TexturePath; + + // load texture + m_sTexturePath.MakeLower(); + m_pTexture = TEXTUREMAN->LoadTexture( m_sTexturePath ); + ASSERT( m_pTexture != NULL ); + + m_iLineSpacing = m_pTexture->GetSourceFrameHeight(); + + // load character widths + vector FrameWidths; int i; + // Assume each character is the width of the frame by default. + for( i=0; i<256; i++ ) + FrameWidths.push_back(m_pTexture->GetSourceFrameWidth()); - for( i=0; ibegin(); key != k->end(); ++key) + { + 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)) + { + FrameWidths[atoi(val)] = atoi(data); + continue; + } + } + } } - m_bCapitalsOnly = false; + ini.GetValueB( "main", "CapitalsOnly", m_bCapitalsOnly ); + int DrawExtraPixelsLeft = 0, DrawExtraPixelsRight = 0; - m_iRefCount = 1; + ini.GetValueI( "main", "DrawExtraPixelsLeft", DrawExtraPixelsLeft ); + ini.GetValueI( "main", "DrawExtraPixelsRight", DrawExtraPixelsRight ); + + int iAddToAllWidths = 0; + if( ini.GetValueI( "main", "AddToAllWidths", iAddToAllWidths ) ) + { + for( int i=0; i<256; i++ ) + FrameWidths[i] += iAddToAllWidths; + } + + float fScaleAllWidthsBy = 0; + if( ini.GetValueF( "main", "ScaleAllWidthsBy", fScaleAllWidthsBy ) ) + { + for( int i=0; i<256; i++ ) + FrameWidths[i] = int(roundf( FrameWidths[i] * fScaleAllWidthsBy )); + } + + ini.GetValueI( "main", "LineSpacing", m_iLineSpacing ); + + SetTextureCoords(FrameWidths); + SetExtraPixels(DrawExtraPixelsLeft, DrawExtraPixelsRight); } Font::Font( const CString &sASCIITexturePath ) @@ -42,56 +99,23 @@ Font::Font( const CString &sASCIITexturePath ) Init(); - // load texture - m_sTexturePath = sASCIITexturePath; - m_sTexturePath.MakeLower(); - m_pTexture = TEXTUREMAN->LoadTexture( m_sTexturePath ); - ASSERT( m_pTexture != NULL ); - if( m_pTexture->GetNumFrames() != 16*16 ) - RageException::Throw( "The font '%s' has only %d frames. All fonts must have 16*16 frames.", m_sTexturePath.GetString() ); - - int i; - for( i=0; i<256; i++ ) + /* Default to 0..255. */ + for( int i=0; i<256; i++ ) m_iCharToFrameNo[i] = i; // Find .ini widths path from texture path CString sDir, sFileName, sExtension; splitrelpath( sASCIITexturePath, sDir, sFileName, sExtension ); const CString sIniPath = sDir + sFileName + ".ini"; + IniFile ini; ini.SetPath( sIniPath ); ini.ReadFile(); + ini.RenameKey("Char Widths", "main"); + Load(sASCIITexturePath, ini); - // load character widths - for( i=0; i<256; i++ ) - if( !ini.GetValueI( "Char Widths", ssprintf("%d",i), m_iFrameNoToWidth[i] ) ) - RageException::Throw( "Error reading width value '%d' from '%s'.", i, sIniPath.GetString() ); - - ini.GetValueB( "Char Widths", "CapitalsOnly", m_bCapitalsOnly ); - int DrawExtraPixelsLeft = 0, DrawExtraPixelsRight = 0; - - ini.GetValueI( "Char Widths", "DrawExtraPixelsLeft", DrawExtraPixelsLeft ); - ini.GetValueI( "Char Widths", "DrawExtraPixelsRight", DrawExtraPixelsRight ); - - int iAddToAllWidths = 0; - if( ini.GetValueI( "Char Widths", "AddToAllWidths", iAddToAllWidths ) ) - { - for( int i=0; i<256; i++ ) - m_iFrameNoToWidth[i] += iAddToAllWidths; - } - - float fScaleAllWidthsBy = 0; - if( ini.GetValueF( "Char Widths", "ScaleAllWidthsBy", fScaleAllWidthsBy ) ) - { - for( int i=0; i<256; i++ ) - m_iFrameNoToWidth[i] = int(roundf( m_iFrameNoToWidth[i] * fScaleAllWidthsBy )); - } - - m_iLineSpacing = m_pTexture->GetSourceFrameHeight(); - ini.GetValueI( "Char Widths", "LineSpacing", m_iLineSpacing ); - - SetTextureCoords(); - SetExtraPixels(DrawExtraPixelsLeft, DrawExtraPixelsRight); + if( m_pTexture->GetNumFrames() != 16*16 ) + RageException::Throw( "The font '%s' has only %d frames. All fonts must have 16*16 frames.", m_sTexturePath.GetString() ); } @@ -101,42 +125,24 @@ Font::Font( const CString &sTexturePath, const CString& sCharacters ) Init(); - // - // load texture - // - m_sTexturePath = sTexturePath; // save - m_sTexturePath.MakeLower(); + /* Map characters to frames; we don't actually have an INI. */ + for( int i=0; iLoadTexture( m_sTexturePath ); - ASSERT( m_pTexture != NULL ); - m_iLineSpacing = m_pTexture->GetSourceFrameHeight(); + /* load texture */ + IniFile ini; + Load(sTexturePath, ini); - // - // find out what characters are in this font - // // sanity check if( sCharacters.GetLength() != m_pTexture->GetNumFrames() ) RageException::Throw( "The image '%s' doesn't have the correct number of frames. It has %d frames but should have %d frames.", m_sTexturePath.GetString(), m_pTexture->GetNumFrames(), sCharacters.GetLength() ); - - // set the char to frame number map - int i; - for( i=0; iGetNumFrames(); i++ ) - m_iFrameNoToWidth[i] = m_pTexture->GetSourceFrameWidth(); - - SetTextureCoords(); } -void Font::SetTextureCoords() +void Font::SetTextureCoords(const vector &widths) { // force widths to even number // Why do this? It seems to just artificially widen some characters a little and @@ -148,47 +154,51 @@ void Font::SetTextureCoords() for(int i = 0; i < m_pTexture->GetNumFrames(); ++i) { + glyph g; + g.left = g.right = 0; + /* Make a copy of each texture rect, reducing each to the actual dimensions * of the character (most characters don't take a full block). */ - RectF r = *m_pTexture->GetTextureCoordRect(i);; + g.rect = *m_pTexture->GetTextureCoordRect(i);; - float fPixelsToChopOff = m_pTexture->GetSourceFrameWidth() - (float)m_iFrameNoToWidth[i]; + float fPixelsToChopOff = m_pTexture->GetSourceFrameWidth() - (float)widths[i]; float fTexCoordsToChopOff = fPixelsToChopOff / m_pTexture->GetSourceWidth(); - r.left += fTexCoordsToChopOff/2; - r.right -= fTexCoordsToChopOff/2; - m_TextureCoordRects.push_back(r); + g.rect.left += fTexCoordsToChopOff/2; + g.rect.right -= fTexCoordsToChopOff/2; /* Add normal widths. */ - m_Left.push_back(0); - m_Right.push_back(m_iFrameNoToWidth[i]); + g.left = 0; + g.right = g.width = widths[i]; + + glyphs.push_back(g); } } void Font::SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight) { /* Adjust for DrawExtraPixelsLeft and DrawExtraPixelsRight. */ - for(unsigned i = 0; i < m_TextureCoordRects.size(); ++i) + for(unsigned i = 0; i < glyphs.size(); ++i) { int iFrameWidth = m_pTexture->GetSourceFrameWidth(); - int iCharWidth = m_iFrameNoToWidth[i]; + int iCharWidth = glyphs[i].width; /* Extra pixels to draw to the left and right. */ int ExtraLeft = min( DrawExtraPixelsLeft, (iFrameWidth-iCharWidth)/2 ); int ExtraRight = min( DrawExtraPixelsRight, (iFrameWidth-iCharWidth)/2 ) + ExtraLeft; /* Move left and expand right. */ - m_TextureCoordRects[i].left -= float(ExtraLeft) / m_pTexture->GetSourceWidth(); - m_TextureCoordRects[i].right += float(ExtraRight) / m_pTexture->GetSourceWidth(); - m_Left[i] += ExtraLeft; - m_Right[i] += ExtraRight; + glyphs[i].rect.left -= float(ExtraLeft) / m_pTexture->GetSourceWidth(); + glyphs[i].rect.right += float(ExtraRight) / m_pTexture->GetSourceWidth(); + glyphs[i].left += ExtraLeft; + glyphs[i].right += ExtraRight; } } Font::~Font() { if( m_pTexture != NULL ) - TEXTUREMAN->UnloadTexture( m_sTexturePath ); + TEXTUREMAN->UnloadTexture( m_pTexture ); } @@ -203,7 +213,7 @@ int Font::GetLineWidthInSourcePixels( const CString &szLine ) if( iFrameNo == -1 ) // this font doesn't impelemnt this character RageException::Throw( "The font '%s' does not implement the character '%c'", m_sTexturePath.GetString(), c ); - iLineWidth += m_iFrameNoToWidth[iFrameNo]; + iLineWidth += glyphs[iFrameNo].width; } return iLineWidth; diff --git a/stepmania/src/Font.h b/stepmania/src/Font.h index 09573c6436..3509260184 100644 --- a/stepmania/src/Font.h +++ b/stepmania/src/Font.h @@ -12,9 +12,16 @@ */ #include "RageTexture.h" +#include "IniFile.h" -const int MAX_FONT_CHARS = 256; // only low ASCII chars are supported +struct glyph { + int width; + /* X coordinates to be rendered for this character are X-left and X+right. */ + int left, right; + /* Texture coordinate rect. */ + RectF rect; +}; class Font { @@ -30,24 +37,20 @@ public: CString m_sTexturePath; + vector glyphs; + RageTexture* m_pTexture; bool m_bCapitalsOnly; int m_iLineSpacing; - int m_iCharToFrameNo[MAX_FONT_CHARS]; - int m_iFrameNoToWidth[MAX_FONT_CHARS]; // in soure coordinate space + map m_iCharToFrameNo; - const RectF &GetTextureCoordRect( int frameNo ) const { return m_TextureCoordRects[frameNo]; } - - /* Source pixels to print to the left and right of each character. - * m_Left[] is usually 0. */ - vector m_Left, m_Right; + const glyph &GetGlyph( int frameNo ) const { return glyphs[frameNo]; } private: - vector m_TextureCoordRects; void SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight); - void SetTextureCoords(); - + void SetTextureCoords(const vector &widths); + void Load( const CString &sASCIITexturePath, IniFile &ini ); }; #endif