more bitmap font work
This commit is contained in:
@@ -55,7 +55,7 @@ BitmapText::BitmapText()
|
|||||||
BitmapText::~BitmapText()
|
BitmapText::~BitmapText()
|
||||||
{
|
{
|
||||||
if( m_pFont )
|
if( m_pFont )
|
||||||
FONT->UnloadFont( m_pFont->m_sTexturePath );
|
FONT->UnloadFont( m_pFont );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitmapText::LoadFromFont( CString sFontFilePath )
|
bool BitmapText::LoadFromFont( CString sFontFilePath )
|
||||||
@@ -63,7 +63,7 @@ bool BitmapText::LoadFromFont( CString sFontFilePath )
|
|||||||
LOG->Trace( "BitmapText::LoadFromFontName(%s)", sFontFilePath.GetString() );
|
LOG->Trace( "BitmapText::LoadFromFontName(%s)", sFontFilePath.GetString() );
|
||||||
|
|
||||||
if( m_pFont ) {
|
if( m_pFont ) {
|
||||||
FONT->UnloadFont( m_pFont->m_sTexturePath );
|
FONT->UnloadFont( m_pFont );
|
||||||
m_pFont = NULL;
|
m_pFont = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ bool BitmapText::LoadFromTextureAndChars( CString sTexturePath, CString sChars )
|
|||||||
LOG->Trace( "BitmapText::LoadFromTextureAndChars(%s)", sTexturePath.GetString() );
|
LOG->Trace( "BitmapText::LoadFromTextureAndChars(%s)", sTexturePath.GetString() );
|
||||||
|
|
||||||
if( m_pFont ) {
|
if( m_pFont ) {
|
||||||
FONT->UnloadFont( m_pFont->m_sTexturePath );
|
FONT->UnloadFont( m_pFont );
|
||||||
m_pFont = NULL;
|
m_pFont = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,9 +96,6 @@ void BitmapText::SetText( CString sText )
|
|||||||
{
|
{
|
||||||
ASSERT( m_pFont );
|
ASSERT( m_pFont );
|
||||||
|
|
||||||
if( m_pFont->m_bCapitalsOnly )
|
|
||||||
sText.MakeUpper();
|
|
||||||
|
|
||||||
m_szText = sText;
|
m_szText = sText;
|
||||||
|
|
||||||
/* Break the string into lines. */
|
/* Break the string into lines. */
|
||||||
@@ -139,7 +136,8 @@ void BitmapText::DrawPrimitives()
|
|||||||
if( m_szTextLines.empty() )
|
if( m_szTextLines.empty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RageTexture* pTexture = m_pFont->m_pTexture;
|
/* XXX */
|
||||||
|
RageTexture* pTexture = m_pFont->GetGlyph('0').Texture;
|
||||||
|
|
||||||
static RageVertex *v = NULL;
|
static RageVertex *v = NULL;
|
||||||
static int vcnt = 0;
|
static int vcnt = 0;
|
||||||
@@ -189,13 +187,7 @@ void BitmapText::DrawPrimitives()
|
|||||||
|
|
||||||
for( unsigned j=0; j<szLine.size(); j++ ) // for each character in the line
|
for( unsigned j=0; j<szLine.size(); j++ ) // for each character in the line
|
||||||
{
|
{
|
||||||
const char c = szLine[j];
|
const glyph &g = m_pFont->GetGlyph(szLine[j]);
|
||||||
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 */
|
/* 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, 0 ); // top left
|
||||||
@@ -204,7 +196,7 @@ void BitmapText::DrawPrimitives()
|
|||||||
v[iNumV++].p = RageVector3( (float)iX+g.hshift+g.width, iY+g.vshift, 0 ); // top right
|
v[iNumV++].p = RageVector3( (float)iX+g.hshift+g.width, iY+g.vshift, 0 ); // top right
|
||||||
|
|
||||||
/* Advance the cursor. */
|
/* Advance the cursor. */
|
||||||
iX += g.advance;
|
iX += g.hadvance;
|
||||||
|
|
||||||
/* set texture coordinates */
|
/* set texture coordinates */
|
||||||
iNumV -= 4;
|
iNumV -= 4;
|
||||||
|
|||||||
+91
-77
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
||||||
Chris Danford
|
Chris Danford
|
||||||
|
Glenn Maynard
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -18,16 +19,12 @@
|
|||||||
#include "RageLog.h"
|
#include "RageLog.h"
|
||||||
#include "RageException.h"
|
#include "RageException.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
FontPage::FontPage()
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
void Font::Init()
|
|
||||||
{
|
{
|
||||||
m_bCapitalsOnly = false;
|
m_pTexture = NULL;
|
||||||
m_iRefCount = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::Load( const CString &TexturePath, IniFile &ini )
|
void FontPage::Load( const CString &TexturePath, IniFile &ini )
|
||||||
{
|
{
|
||||||
m_sTexturePath = TexturePath;
|
m_sTexturePath = TexturePath;
|
||||||
|
|
||||||
@@ -36,13 +33,11 @@ void Font::Load( const CString &TexturePath, IniFile &ini )
|
|||||||
m_pTexture = TEXTUREMAN->LoadTexture( m_sTexturePath );
|
m_pTexture = TEXTUREMAN->LoadTexture( m_sTexturePath );
|
||||||
ASSERT( m_pTexture != NULL );
|
ASSERT( m_pTexture != NULL );
|
||||||
|
|
||||||
m_iLineSpacing = m_pTexture->GetSourceFrameHeight();
|
|
||||||
|
|
||||||
// load character widths
|
// load character widths
|
||||||
vector<int> FrameWidths;
|
vector<int> FrameWidths;
|
||||||
int i;
|
int i;
|
||||||
// Assume each character is the width of the frame by default.
|
// Assume each character is the width of the frame by default.
|
||||||
for( i=0; i<256; i++ )
|
for( i=0; i<m_pTexture->GetNumFrames(); i++ )
|
||||||
FrameWidths.push_back(m_pTexture->GetSourceFrameWidth());
|
FrameWidths.push_back(m_pTexture->GetSourceFrameWidth());
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -80,13 +75,12 @@ void Font::Load( const CString &TexturePath, IniFile &ini )
|
|||||||
RageException::Throw( "The font '%s' has an invalid INI value '%s'.",
|
RageException::Throw( "The font '%s' has an invalid INI value '%s'.",
|
||||||
m_sTexturePath.GetString(), val.GetString() );
|
m_sTexturePath.GetString(), val.GetString() );
|
||||||
|
|
||||||
m_iCharToFrameNo[i] = atoi(data);
|
m_iCharToGlyphNo[i] = atoi(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ini.GetValueB( "main", "CapitalsOnly", m_bCapitalsOnly );
|
|
||||||
int DrawExtraPixelsLeft = 0, DrawExtraPixelsRight = 0;
|
int DrawExtraPixelsLeft = 0, DrawExtraPixelsRight = 0;
|
||||||
|
|
||||||
ini.GetValueI( "main", "DrawExtraPixelsLeft", DrawExtraPixelsLeft );
|
ini.GetValueI( "main", "DrawExtraPixelsLeft", DrawExtraPixelsLeft );
|
||||||
@@ -106,62 +100,15 @@ void Font::Load( const CString &TexturePath, IniFile &ini )
|
|||||||
FrameWidths[i] = int(roundf( FrameWidths[i] * fScaleAllWidthsBy ));
|
FrameWidths[i] = int(roundf( FrameWidths[i] * fScaleAllWidthsBy ));
|
||||||
}
|
}
|
||||||
|
|
||||||
ini.GetValueI( "main", "LineSpacing", m_iLineSpacing );
|
/* All characters on a page have the same vertical spacing. */
|
||||||
|
int LineSpacing = m_pTexture->GetSourceFrameHeight();
|
||||||
|
ini.GetValueI( "main", "LineSpacing", LineSpacing );
|
||||||
|
|
||||||
SetTextureCoords(FrameWidths);
|
SetTextureCoords(FrameWidths, LineSpacing);
|
||||||
SetExtraPixels(DrawExtraPixelsLeft, DrawExtraPixelsRight);
|
SetExtraPixels(DrawExtraPixelsLeft, DrawExtraPixelsRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::Font( const CString &sASCIITexturePath )
|
void FontPage::SetTextureCoords(const vector<int> &widths, int LineSpacing)
|
||||||
{
|
|
||||||
//LOG->Trace( "Font::LoadFromFontName(%s)", sASCIITexturePath.GetString() );
|
|
||||||
|
|
||||||
Init();
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
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() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Font::Font( const CString &sTexturePath, const CString& sCharacters )
|
|
||||||
{
|
|
||||||
//LOG->Trace( "Font::LoadFromFontName(%s)", sFontFilePath.GetString() );
|
|
||||||
|
|
||||||
Init();
|
|
||||||
|
|
||||||
/* Map characters to frames; we don't actually have an INI. */
|
|
||||||
for( int i=0; i<sCharacters.GetLength(); i++ )
|
|
||||||
{
|
|
||||||
char c = sCharacters[i];
|
|
||||||
m_iCharToFrameNo[c] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load texture */
|
|
||||||
IniFile ini;
|
|
||||||
Load(sTexturePath, ini);
|
|
||||||
|
|
||||||
// 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() );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Font::SetTextureCoords(const vector<int> &widths)
|
|
||||||
{
|
{
|
||||||
for(int i = 0; i < m_pTexture->GetNumFrames(); ++i)
|
for(int i = 0; i < m_pTexture->GetNumFrames(); ++i)
|
||||||
{
|
{
|
||||||
@@ -177,7 +124,7 @@ void Font::SetTextureCoords(const vector<int> &widths)
|
|||||||
|
|
||||||
/* Shift the character up so the top of the rendered quad is at the top
|
/* Shift the character up so the top of the rendered quad is at the top
|
||||||
* of the character. */
|
* of the character. */
|
||||||
g.vshift = -(m_pTexture->GetSourceFrameHeight() - m_iLineSpacing)/2.0f;
|
g.vshift = -(m_pTexture->GetSourceFrameHeight() - LineSpacing)/2.0f;
|
||||||
|
|
||||||
/* Do the same thing with X. Do this by changing the actual rendered
|
/* 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. */
|
* rect, instead of shifting it, so we don't render more than we need to. */
|
||||||
@@ -192,7 +139,8 @@ void Font::SetTextureCoords(const vector<int> &widths)
|
|||||||
|
|
||||||
/* By default, advance one pixel more than the width. (This could be
|
/* By default, advance one pixel more than the width. (This could be
|
||||||
* an option.) */
|
* an option.) */
|
||||||
g.advance = g.width + 1;
|
g.hadvance = g.width + 1;
|
||||||
|
g.vadvance = float(LineSpacing);
|
||||||
glyphs.push_back(g);
|
glyphs.push_back(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,13 +152,18 @@ void Font::SetTextureCoords(const vector<int> &widths)
|
|||||||
// glyphs[i].width++;
|
// glyphs[i].width++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight)
|
void FontPage::SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight)
|
||||||
{
|
{
|
||||||
|
/* Hack: do one more than we were asked to; I think a lot of fonts are one
|
||||||
|
* too low. */
|
||||||
|
DrawExtraPixelsRight++;
|
||||||
|
DrawExtraPixelsLeft++;
|
||||||
|
|
||||||
/* Adjust for DrawExtraPixelsLeft and DrawExtraPixelsRight. */
|
/* Adjust for DrawExtraPixelsLeft and DrawExtraPixelsRight. */
|
||||||
for(unsigned i = 0; i < glyphs.size(); ++i)
|
for(unsigned i = 0; i < glyphs.size(); ++i)
|
||||||
{
|
{
|
||||||
int iFrameWidth = m_pTexture->GetSourceFrameWidth();
|
int iFrameWidth = m_pTexture->GetSourceFrameWidth();
|
||||||
float iCharWidth = glyphs[i].advance;
|
float iCharWidth = glyphs[i].hadvance;
|
||||||
|
|
||||||
/* Extra pixels to draw to the left and right. */
|
/* Extra pixels to draw to the left and right. */
|
||||||
float ExtraLeft = min( float(DrawExtraPixelsLeft), (iFrameWidth-iCharWidth)/2.0f );
|
float ExtraLeft = min( float(DrawExtraPixelsLeft), (iFrameWidth-iCharWidth)/2.0f );
|
||||||
@@ -221,11 +174,12 @@ void Font::SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight)
|
|||||||
glyphs[i].rect.right += ExtraRight / m_pTexture->GetSourceWidth();
|
glyphs[i].rect.right += ExtraRight / m_pTexture->GetSourceWidth();
|
||||||
glyphs[i].hshift -= ExtraLeft;
|
glyphs[i].hshift -= ExtraLeft;
|
||||||
glyphs[i].width += ExtraLeft + ExtraRight;
|
glyphs[i].width += ExtraLeft + ExtraRight;
|
||||||
// glyphs[i].advance += ExtraLeft + ExtraRight;
|
|
||||||
|
glyphs[i].Texture = m_pTexture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::~Font()
|
FontPage::~FontPage()
|
||||||
{
|
{
|
||||||
if( m_pTexture != NULL )
|
if( m_pTexture != NULL )
|
||||||
TEXTUREMAN->UnloadTexture( m_pTexture );
|
TEXTUREMAN->UnloadTexture( m_pTexture );
|
||||||
@@ -238,12 +192,8 @@ int Font::GetLineWidthInSourcePixels( const CString &szLine )
|
|||||||
|
|
||||||
for( unsigned i=0; i<szLine.size(); i++ )
|
for( unsigned i=0; i<szLine.size(); i++ )
|
||||||
{
|
{
|
||||||
const char c = szLine[i];
|
const glyph &g = GetGlyph(szLine[i]);
|
||||||
if(m_iCharToFrameNo.find(c) == m_iCharToFrameNo.end())
|
LineWidth += g.hadvance;
|
||||||
RageException::Throw( "The font '%s' does not implement the character '%c'", m_sTexturePath.GetString(), c );
|
|
||||||
|
|
||||||
const int iFrameNo = m_iCharToFrameNo[ (unsigned char)c ];
|
|
||||||
LineWidth += glyphs[iFrameNo].advance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return int(LineWidth);
|
return int(LineWidth);
|
||||||
@@ -251,6 +201,70 @@ int Font::GetLineWidthInSourcePixels( const CString &szLine )
|
|||||||
|
|
||||||
int Font::GetLineHeightInSourcePixels( const CString &szLine )
|
int Font::GetLineHeightInSourcePixels( const CString &szLine )
|
||||||
{
|
{
|
||||||
return m_iLineSpacing;
|
float iLineSpacing = 0;
|
||||||
|
|
||||||
|
for( unsigned i=0; i<szLine.size(); i++ )
|
||||||
|
{
|
||||||
|
const glyph &g = GetGlyph(szLine[i]);
|
||||||
|
|
||||||
|
iLineSpacing = max(iLineSpacing, g.vadvance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return int(iLineSpacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Font::Font()
|
||||||
|
{
|
||||||
|
//LOG->Trace( "Font::LoadFromFontName(%s)", sASCIITexturePath.GetString() );
|
||||||
|
|
||||||
|
m_iRefCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Font::~Font()
|
||||||
|
{
|
||||||
|
for(unsigned i = 0; i < pages.size(); ++i)
|
||||||
|
delete pages[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::AddPage(FontPage *fp)
|
||||||
|
{
|
||||||
|
pages.push_back(fp);
|
||||||
|
|
||||||
|
for(map<int,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
|
||||||
|
{
|
||||||
|
map<int,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 );
|
||||||
|
|
||||||
|
return *it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load font-global settings. */
|
||||||
|
void Font::LoadINI(IniFile &ini)
|
||||||
|
{
|
||||||
|
bool CapitalsOnly = false;
|
||||||
|
ini.GetValueB( "main", "CapitalsOnly", CapitalsOnly );
|
||||||
|
if(CapitalsOnly)
|
||||||
|
{
|
||||||
|
/* For each uppercase character that we have a mapping for, add
|
||||||
|
* a lowercase one. */
|
||||||
|
for(char c = 'A'; c <= 'Z'; ++c)
|
||||||
|
{
|
||||||
|
map<int,glyph*>::const_iterator it = m_iCharToGlyph.find(c);
|
||||||
|
|
||||||
|
if(it == m_iCharToGlyph.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_iCharToGlyph[tolower(c)] = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user