From 4bb452404cb1ce228295893f94d329c2cd91bf7d Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Sat, 4 Jan 2003 01:47:01 +0000 Subject: [PATCH] more bitmap font work --- stepmania/src/BitmapText.cpp | 49 ++++++++++--------- stepmania/src/BitmapText.h | 1 + stepmania/src/Font.cpp | 92 ++++++++++++++++++++++++------------ stepmania/src/Font.h | 12 +++-- 4 files changed, 99 insertions(+), 55 deletions(-) diff --git a/stepmania/src/BitmapText.cpp b/stepmania/src/BitmapText.cpp index 380d17f623..4cfcd79bce 100644 --- a/stepmania/src/BitmapText.cpp +++ b/stepmania/src/BitmapText.cpp @@ -104,6 +104,7 @@ void BitmapText::SetText( CString sText ) /* Break the string into lines. */ m_szTextLines.clear(); m_iLineWidths.clear(); + m_iLineHeights.clear(); split(m_szText, "\n", m_szTextLines, false); @@ -113,6 +114,7 @@ void BitmapText::SetText( CString sText ) for( unsigned l=0; lGetLineWidthInSourcePixels( m_szTextLines[l] )); + m_iLineHeights.push_back(m_pFont->GetLineHeightInSourcePixels( m_szTextLines[l] )); m_iWidestLineWidth = max(m_iWidestLineWidth, m_iLineWidths.back()); } } @@ -157,30 +159,31 @@ void BitmapText::DrawPrimitives() int iNumV = 0; // the current vertex number - // make the object in logical units centered at the origin - const int iHeight = pTexture->GetSourceFrameHeight(); // height of a character - const int iLineSpacing = m_pFont->m_iLineSpacing; // spacing between lines + float TotalHeight = 0; + unsigned i; + for(i = 0; i < m_szTextLines.size(); ++i) + TotalHeight += m_iLineHeights[i]; - int iY; // the center position of the first row of characters + float iY; // the top position of the first row of characters switch( m_VertAlign ) { - case align_bottom: iY = -(int(m_szTextLines.size())) * iLineSpacing + iLineSpacing/2; break; - case align_middle: iY = -(int(m_szTextLines.size())-1) * iLineSpacing/2; break; - case align_top: iY = + iLineSpacing/2; break; - default: ASSERT( false ); return; + 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( unsigned i=0; iGetGlyph(iFrameNo); /* set vertex positions */ - 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 + 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.width; + iX += g.advance; /* set texture coordinates */ iNumV -= 4; - 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 + 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 += iLineSpacing; + iY += m_iLineHeights[i]; } diff --git a/stepmania/src/BitmapText.h b/stepmania/src/BitmapText.h index bab3472347..e8b7f5f5bb 100644 --- a/stepmania/src/BitmapText.h +++ b/stepmania/src/BitmapText.h @@ -46,6 +46,7 @@ protected: CString m_szText; vector m_szTextLines; vector m_iLineWidths; // in source pixels + vector m_iLineHeights; // in source pixels int m_iWidestLineWidth; // in source pixels bool m_bRainbow; diff --git a/stepmania/src/Font.cpp b/stepmania/src/Font.cpp index 78cc791cc4..f88ce4e926 100644 --- a/stepmania/src/Font.cpp +++ b/stepmania/src/Font.cpp @@ -63,6 +63,25 @@ void Font::Load( const CString &TexturePath, IniFile &ini ) FrameWidths[atoi(val)] = atoi(data); continue; } + + /* "map XXXX=frame" maps a char to a frame. */ + if(val.substr(0, 4) == "map ") + { + val = val.substr(4); /* "XXXX" */ + + /* XXXX can be "U+HEX". */ + + int c = -1; + + if(val.substr(0, 2) == "U+" && IsHexVal(val.substr(2))) + sscanf(val.substr(2).c_str(), "%x", &c); + + if(c == -1) + RageException::Throw( "The font '%s' has an invalid INI value '%s'.", + m_sTexturePath.GetString(), val.GetString() ); + + m_iCharToFrameNo[i] = atoi(data); + } } } } @@ -144,35 +163,45 @@ Font::Font( const CString &sTexturePath, const CString& sCharacters ) 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 - // make it look a little worse in 640x480 ... -/* for( i=0; i<256; i++ ) - if( m_iFrameNoToWidth[i]%2 == 1 ) - m_iFrameNoToWidth[i]++; -*/ - 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). */ g.rect = *m_pTexture->GetTextureCoordRect(i);; - float fPixelsToChopOff = m_pTexture->GetSourceFrameWidth() - (float)widths[i]; - float fTexCoordsToChopOff = fPixelsToChopOff / m_pTexture->GetSourceWidth(); - - g.rect.left += fTexCoordsToChopOff/2; - g.rect.right -= fTexCoordsToChopOff/2; + /* Set the width and height to the width and line spacing, respectively. */ + g.width = float(widths[i]); + g.height = float(m_pTexture->GetSourceFrameHeight()); - /* Add normal widths. */ - g.left = 0; - g.right = g.width = widths[i]; + /* Shift the character up so the top of the rendered quad is at the top + * of the character. */ + g.vshift = -(m_pTexture->GetSourceFrameHeight() - m_iLineSpacing)/2.0f; + /* Do the same thing with X. Do this by changing the actual rendered + * rect, instead of shifting it, so we don't render more than we need to. */ + g.hshift = 0; + { + int iPixelsToChopOff = m_pTexture->GetSourceFrameWidth() - widths[i]; + 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.advance = g.width + 1; 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(); - int iCharWidth = glyphs[i].width; + float iCharWidth = glyphs[i].advance; /* Extra pixels to draw to the left and right. */ - int ExtraLeft = min( DrawExtraPixelsLeft, (iFrameWidth-iCharWidth)/2 ); - int ExtraRight = min( DrawExtraPixelsRight, (iFrameWidth-iCharWidth)/2 ) + ExtraLeft; + float ExtraLeft = min( float(DrawExtraPixelsLeft), (iFrameWidth-iCharWidth)/2.0f ); + float ExtraRight = min( float(DrawExtraPixelsRight), (iFrameWidth-iCharWidth)/2.0f ); /* Move left and expand right. */ - 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; + glyphs[i].rect.left -= ExtraLeft / m_pTexture->GetSourceWidth(); + glyphs[i].rect.right += ExtraRight / m_pTexture->GetSourceWidth(); + glyphs[i].hshift -= ExtraLeft; + glyphs[i].width += ExtraLeft + ExtraRight; +// glyphs[i].advance += ExtraLeft + ExtraRight; } } @@ -204,19 +234,23 @@ Font::~Font() int Font::GetLineWidthInSourcePixels( const CString &szLine ) { - int iLineWidth = 0; + float LineWidth = 0; for( unsigned i=0; i