diff --git a/stepmania/src/BitmapText.cpp b/stepmania/src/BitmapText.cpp index dca1fa7d44..d81cd148de 100644 --- a/stepmania/src/BitmapText.cpp +++ b/stepmania/src/BitmapText.cpp @@ -70,6 +70,8 @@ bool BitmapText::LoadFromFont( CString sFontFilePath ) // load font m_pFont = FONT->LoadFont( sFontFilePath ); + BuildChars(); + return true; } @@ -86,15 +88,95 @@ bool BitmapText::LoadFromTextureAndChars( CString sTexturePath, CString sChars ) // load font m_pFont = FONT->LoadFont( sTexturePath, sChars ); + BuildChars(); + return true; } +void BitmapText::BuildChars() +{ + /* If we don't have a font yet, we'll do this when it loads. */ + if(m_pFont == NULL) + return; + verts.clear(); + tex.clear(); + + int TotalHeight = 0; + unsigned i; + for(i = 0; i < m_szTextLines.size(); ++i) + TotalHeight += m_iLineHeights[i]; + int iY; // the top position of the first row of characters + switch( m_VertAlign ) + { + case align_top: iY = 0; break; + case align_middle: iY = -TotalHeight/2; break; + case align_bottom: iY = -TotalHeight; break; + default: ASSERT( false ); return; + } + + for( i=0; iGetGlyph(szLine[j]); + + /* set vertex positions */ + v[0].p = RageVector3( iX+g.hshift, iY+g.vshift, 0 ); // top left + v[1].p = RageVector3( iX+g.hshift, iY+g.vshift+g.height, 0 ); // bottom left + v[2].p = RageVector3( iX+g.hshift+g.width, iY+g.vshift+g.height, 0 ); // bottom right + v[3].p = RageVector3( iX+g.hshift+g.width, iY+g.vshift, 0 ); // top right + + /* Advance the cursor. */ + iX += g.hadvance; + + /* set texture coordinates */ + v[0].t = RageVector2( g.rect.left, g.rect.top ); + v[1].t = RageVector2( g.rect.left, g.rect.bottom ); + v[2].t = RageVector2( g.rect.right, g.rect.bottom ); + v[3].t = RageVector2( g.rect.right, g.rect.top ); + + verts.insert(verts.end(), &v[0], &v[4]); + tex.push_back(m_pFont->GetGlyphTexture(szLine[j])); + } + + iY += m_iLineHeights[i]; + } +} + +void BitmapText::DrawChars() +{ + for(unsigned start = 0; start < tex.size(); ++start) + { + unsigned end = start; + while(end < tex.size() && tex[end] == tex[start]) + end++; + DISPLAY->SetTexture( tex[start] ); + DISPLAY->DrawQuads( &verts[start*4], (end-start)*4 ); + + start = end+1; + } +} void BitmapText::SetText( CString sText ) { ASSERT( m_pFont ); + if(m_szText == sText) + return; m_szText = sText; @@ -114,6 +196,8 @@ void BitmapText::SetText( CString sText ) m_iLineHeights.push_back(m_pFont->GetLineHeightInSourcePixels( m_szTextLines[l] )); m_iWidestLineWidth = max(m_iWidestLineWidth, m_iLineWidths.back()); } + + BuildChars(); } void BitmapText::CropToWidth( int iMaxWidthInSourcePixels ) @@ -136,82 +220,6 @@ void BitmapText::DrawPrimitives() if( m_szTextLines.empty() ) return; - /* XXX */ - RageTexture* pTexture = m_pFont->GetGlyph('0').Texture; - - static RageVertex *v = NULL; - static int vcnt = 0; - { - int charcnt = 0; - for( unsigned i=0; i vcnt) - { - vcnt = charcnt; - delete [] v; - v = new RageVertex[vcnt]; - } - } - - int iNumV = 0; // the current vertex number - - float TotalHeight = 0; - unsigned i; - for(i = 0; i < m_szTextLines.size(); ++i) - TotalHeight += m_iLineHeights[i]; - - float iY; // the top position of the first row of characters - switch( m_VertAlign ) - { - case align_top: iY = 0; break; - case align_middle: iY = -TotalHeight/2.0f; break; - case align_bottom: iY = -TotalHeight; break; - default: ASSERT( false ); return; - } - - for( i=0; iGetGlyph(szLine[j]); - - /* set vertex positions */ - v[iNumV++].p = RageVector3( (float)iX+g.hshift, iY+g.vshift, 0 ); // top left - v[iNumV++].p = RageVector3( (float)iX+g.hshift, iY+g.vshift+g.height, 0 ); // bottom left - v[iNumV++].p = RageVector3( (float)iX+g.hshift+g.width, iY+g.vshift+g.height, 0 ); // bottom right - v[iNumV++].p = RageVector3( (float)iX+g.hshift+g.width, iY+g.vshift, 0 ); // top right - - /* Advance the cursor. */ - iX += g.hadvance; - - /* set texture coordinates */ - iNumV -= 4; - - v[iNumV++].t = RageVector2( g.rect.left, g.rect.top ); - v[iNumV++].t = RageVector2( g.rect.left, g.rect.bottom ); - v[iNumV++].t = RageVector2( g.rect.right, g.rect.bottom ); - v[iNumV++].t = RageVector2( g.rect.right, g.rect.top ); - } - - iY += m_iLineHeights[i]; - } - - - DISPLAY->SetTexture( pTexture ); DISPLAY->SetTextureModeModulate(); if( m_bBlendAdd ) DISPLAY->SetBlendModeAdd(); @@ -232,9 +240,9 @@ void BitmapText::DrawPrimitives() RageColor dim(0,0,0,0.5f*m_temp.diffuse[0].a); // semi-transparent black - for( int i=0; iDrawQuads( v, iNumV ); + for( unsigned i=0; iPopMatrix(); } @@ -245,27 +253,27 @@ void BitmapText::DrawPrimitives() if( m_bRainbow ) { int color_index = int(RageTimer::GetTimeSinceStart() / 0.200) % NUM_RAINBOW_COLORS; - for( int i=0; iDrawQuads( v, iNumV ); + DrawChars(); } /* render the glow pass */ @@ -273,9 +281,23 @@ void BitmapText::DrawPrimitives() { DISPLAY->SetTextureModeGlow(); - int i; - for( i=0; iDrawQuads( v, iNumV ); + for( unsigned i=0; i verts; +// int num_vertices; + vector tex; +// vector vec_cnt; + +// vector chars; +// static bool sort_chars(const one_char &a, const one_char &b); + void BuildChars(); + void DrawChars(); }; diff --git a/stepmania/src/Font.cpp b/stepmania/src/Font.cpp index 1df24c819f..4992ff0e66 100644 --- a/stepmania/src/Font.cpp +++ b/stepmania/src/Font.cpp @@ -122,6 +122,10 @@ void FontPage::SetTextureCoords(const vector &widths, int LineSpacing) g.width = float(widths[i]); g.height = float(m_pTexture->GetSourceFrameHeight()); + /* By default, advance one pixel more than the width. (This could be + * an option.) */ + g.hadvance = int(g.width + 1); + /* Shift the character up so the top of the rendered quad is at the top * of the character. */ g.vshift = -(m_pTexture->GetSourceFrameHeight() - LineSpacing)/2.0f; @@ -131,25 +135,24 @@ void FontPage::SetTextureCoords(const vector &widths, int LineSpacing) g.hshift = 0; { int iPixelsToChopOff = m_pTexture->GetSourceFrameWidth() - widths[i]; + if((iPixelsToChopOff % 2) == 1) + { + /* We don't want to chop off an odd number of pixels, since that'll + * put our texture coordinates between texels and make things blurrier. */ + iPixelsToChopOff--; + g.width++; + } float fTexCoordsToChopOff = float(iPixelsToChopOff) / m_pTexture->GetSourceWidth(); - + g.rect.left += fTexCoordsToChopOff/2; g.rect.right -= fTexCoordsToChopOff/2; } - /* By default, advance one pixel more than the width. (This could be - * an option.) */ - g.hadvance = g.width + 1; - g.vadvance = float(LineSpacing); + g.vadvance = LineSpacing; + g.Texture = m_pTexture; + glyphs.push_back(g); } - - // force widths to even number - // Why do this? It seems to just artificially widen some characters a little and - // make it look a little worse in 640x480 ... -// for( i=0; iGetSourceFrameWidth(); - float iCharWidth = glyphs[i].hadvance; + float iCharWidth = glyphs[i].width; - /* Extra pixels to draw to the left and right. */ + /* Extra pixels to draw to the left and right. We don't have to + * worry about alignment here; CharWidth is always even (by + * SetTextureCoords) and iFrameWidth are almost always even. */ float ExtraLeft = min( float(DrawExtraPixelsLeft), (iFrameWidth-iCharWidth)/2.0f ); float ExtraRight = min( float(DrawExtraPixelsRight), (iFrameWidth-iCharWidth)/2.0f ); @@ -174,8 +182,6 @@ void FontPage::SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight) glyphs[i].rect.right += ExtraRight / m_pTexture->GetSourceWidth(); glyphs[i].hshift -= ExtraLeft; glyphs[i].width += ExtraLeft + ExtraRight; - - glyphs[i].Texture = m_pTexture; } } @@ -186,31 +192,25 @@ FontPage::~FontPage() } -int Font::GetLineWidthInSourcePixels( const CString &szLine ) +int Font::GetLineWidthInSourcePixels( const CString &szLine ) const { - float LineWidth = 0; + int LineWidth = 0; for( unsigned i=0; isecond; } +RageTexture *Font::GetGlyphTexture( int c ) +{ + map::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 ); + + return it->second->Texture; +} + /* Load font-global settings. */ void Font::LoadINI(IniFile &ini) { diff --git a/stepmania/src/Font.h b/stepmania/src/Font.h index c9aafdd844..d8a9c02910 100644 --- a/stepmania/src/Font.h +++ b/stepmania/src/Font.h @@ -18,7 +18,7 @@ struct glyph { RageTexture *Texture; /* Number of pixels to advance horizontally after drawing this character. */ - float hadvance, vadvance; + int hadvance, vadvance; /* Size of the actual rendered character. */ float width, height; @@ -67,8 +67,8 @@ public: RageTexture *GetGlyphTexture( int c ); const glyph &GetGlyph( int c ) const; - int GetLineWidthInSourcePixels( const CString &szLine ); - int GetLineHeightInSourcePixels( const CString &szLine ); + int GetLineWidthInSourcePixels( const CString &szLine ) const; + int GetLineHeightInSourcePixels( const CString &szLine ) const; /* Add a FontPage to this font. */ void AddPage(FontPage *fp); @@ -78,7 +78,6 @@ public: private: vector pages; - }; #endif diff --git a/stepmania/src/FontManager.cpp b/stepmania/src/FontManager.cpp index 17bfe302a1..2b81a964d6 100644 --- a/stepmania/src/FontManager.cpp +++ b/stepmania/src/FontManager.cpp @@ -3,16 +3,15 @@ ----------------------------------------------------------------------------- Class: FontManager - Desc: Interface for loading and releasing textures. + Desc: Interface for loading and releasing fonts. - Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved. + Chris Danford + Glenn Maynard ----------------------------------------------------------------------------- */ -//----------------------------------------------------------------------------- -// Includes -//----------------------------------------------------------------------------- #include "FontManager.h" #include "Font.h" #include "RageUtil.h" @@ -23,9 +22,6 @@ FontManager* FONT = NULL; -//----------------------------------------------------------------------------- -// constructor/destructor -//----------------------------------------------------------------------------- FontManager::FontManager() { } @@ -42,9 +38,6 @@ FontManager::~FontManager() } -//----------------------------------------------------------------------------- -// Load/Unload textures from disk -//----------------------------------------------------------------------------- Font* FontManager::LoadFont( CString sFontOrTextureFilePath, CString sChars ) { sFontOrTextureFilePath.MakeLower(); @@ -143,3 +136,14 @@ void FontManager::UnloadFont( Font *fp ) RageException::Throw( "Unloaded an unknown font (%p)", fp ); } + +CString FontManager::GetPageNameFromFileName(const CString &fn) +{ + unsigned begin = fn.find_first_of('['); + if(begin == fn.npos) return "main"; + unsigned end = fn.find_first_of(']', begin); + if(end == fn.npos) return "main"; + begin++; end--; + if(end == begin) return "main"; + return fn.substr(begin+1, end-begin+1); +} diff --git a/stepmania/src/FontManager.h b/stepmania/src/FontManager.h index 2169abf669..93cef8fa7c 100644 --- a/stepmania/src/FontManager.h +++ b/stepmania/src/FontManager.h @@ -30,6 +30,7 @@ public: protected: // map from file name to a texture holder map m_mapPathToFont; + static CString FontManager::GetPageNameFromFileName(const CString &fn); }; extern FontManager* FONT; // global and accessable from anywhere in our program