From c6e63f37d3ba7781963c225273d7466bb0b7496a Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Mon, 6 Jan 2003 23:49:43 +0000 Subject: [PATCH] add font alignment --- stepmania/src/Font.cpp | 36 ++++++++++++++++++++++--- stepmania/src/Font.h | 27 +++++++++++++++++-- stepmania/src/FontManager.cpp | 49 +++++++++++++++++++++-------------- 3 files changed, 87 insertions(+), 25 deletions(-) diff --git a/stepmania/src/Font.cpp b/stepmania/src/Font.cpp index 364276a2e1..58475ed927 100644 --- a/stepmania/src/Font.cpp +++ b/stepmania/src/Font.cpp @@ -37,6 +37,25 @@ void FontPage::Load( const CString &TexturePath, const FontPageSettings &cfg ) m_pTexture = TEXTUREMAN->LoadTexture( m_sTexturePath ); ASSERT( m_pTexture != NULL ); + /* All characters on a page have the same vertical spacing, baseline + * and center. */ + baseline = cfg.Baseline; + if(baseline == -1) + { + /* The default baseline is 75% down the frame; this is where it + * tends to be. */ + baseline = int(m_pTexture->GetTextureFrameHeight() * .75f); + } + + center = cfg.Center; + if(center == -1) + { + /* We don't know the center, so assume it's the center of the frame. */ + center = m_pTexture->GetSourceFrameHeight()/2; + } + + kanji = cfg.Kanji; + // load character widths vector FrameWidths; int i; @@ -66,7 +85,6 @@ void FontPage::Load( const CString &TexturePath, const FontPageSettings &cfg ) m_iCharToGlyphNo = cfg.CharToGlyphNo; - /* All characters on a page have the same vertical spacing. */ int LineSpacing = cfg.LineSpacing; if(LineSpacing == -1) LineSpacing = m_pTexture->GetSourceFrameHeight(); @@ -81,6 +99,8 @@ void FontPage::SetTextureCoords(const vector &widths, int LineSpacing) { glyph g; + g.fp = this; + /* 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);; @@ -92,10 +112,11 @@ void FontPage::SetTextureCoords(const vector &widths, int LineSpacing) /* By default, advance one pixel more than the width. (This could be * an option.) */ g.hadvance = int(g.width + 1); + g.vadvance = LineSpacing; /* 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; + g.vshift = -(m_pTexture->GetSourceFrameHeight() - g.vadvance)/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. */ @@ -115,7 +136,6 @@ void FontPage::SetTextureCoords(const vector &widths, int LineSpacing) g.rect.right -= fTexCoordsToChopOff/2; } - g.vadvance = LineSpacing; g.Texture = m_pTexture; glyphs.push_back(g); @@ -158,7 +178,6 @@ FontPage::~FontPage() TEXTUREMAN->UnloadTexture( m_pTexture ); } - int Font::GetLineWidthInSourcePixels( const lstring &szLine ) const { int LineWidth = 0; @@ -261,3 +280,12 @@ void Font::CapsOnly() m_iCharToGlyph[(char) tolower(c)] = it->second; } } + +void Font::SetDefaultGlyph(FontPage *fp) +{ + ASSERT(fp); + ASSERT(!fp->glyphs.empty()); + def = fp; +} + + diff --git a/stepmania/src/Font.h b/stepmania/src/Font.h index c2d4677f1b..7a5a264bc8 100644 --- a/stepmania/src/Font.h +++ b/stepmania/src/Font.h @@ -15,7 +15,10 @@ #include "RageUtil.h" #include "IniFile.h" +class FontPage; + struct glyph { + FontPage *fp; RageTexture *Texture; /* Number of pixels to advance horizontally after drawing this character. */ @@ -35,8 +38,11 @@ struct FontPageSettings { int DrawExtraPixelsLeft, DrawExtraPixelsRight, AddToAllWidths, - LineSpacing; + LineSpacing, + Baseline, + Center; float ScaleAllWidthsBy; + bool Kanji; map CharToGlyphNo; /* If a value is missing, the width of the texture frame is used. */ @@ -46,7 +52,10 @@ struct FontPageSettings { DrawExtraPixelsLeft(0), DrawExtraPixelsRight(0), AddToAllWidths(0), LineSpacing(-1), - ScaleAllWidthsBy(1) + ScaleAllWidthsBy(1), + Baseline(-1), + Center(-1), + Kanji(false) { } }; @@ -67,6 +76,10 @@ public: void Load( const CString &sASCIITexturePath, const FontPageSettings &cfg ); + /* Page-global properties. */ + int baseline, center; + bool kanji; + private: void SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight); void SetTextureCoords(const vector &widths, int LineSpacing); @@ -97,12 +110,22 @@ public: /* Load font-wide settings. */ void CapsOnly(); + int GetBaseline() const { return def->baseline; } + bool IsKanjiFont() const { return def->kanji; } + int GetCenter() const { return def->center; } + + void SetDefaultGlyph(FontPage *fp); + static const longchar DEFAULT_GLYPH; private: /* List of pages and fonts that we're responsible for freeing. */ vector pages; vector merged_fonts; + + /* This is the primary fontpage of this font; font-wide baseline, ascender, + * etc. is pulled from it. */ + FontPage *def; }; #endif diff --git a/stepmania/src/FontManager.cpp b/stepmania/src/FontManager.cpp index 0a179914af..33b8958212 100644 --- a/stepmania/src/FontManager.cpp +++ b/stepmania/src/FontManager.cpp @@ -83,6 +83,9 @@ void FontManager::LoadFontPageSettings(FontPageSettings &cfg, IniFile &ini, cons ini.GetValueI( PageName, "AddToAllWidths", cfg.AddToAllWidths ); ini.GetValueF( PageName, "ScaleAllWidthsBy", cfg.ScaleAllWidthsBy ); ini.GetValueI( PageName, "LineSpacing", cfg.LineSpacing ); + ini.GetValueI( PageName, "Baseline", cfg.Baseline ); + ini.GetValueI( PageName, "Center", cfg.Center ); + ini.GetValueB( PageName, "Kanji", cfg.Kanji ); /* Iterate over all keys. */ const IniFile::key *k = ini.GetKey(PageName); @@ -264,9 +267,11 @@ Font *FontManager::LoadFontInt(const CString &sFontOrTextureFilePath, CString sC } LoadStack.push_back(sFontOrTextureFilePath); } + /* The font is not already loaded. Figure out what we have. */ // LOG->Trace( "FontManager::LoadFont(%s).", sFontFilePath.GetString() ); + /* Get the filenames associated with this font. */ CStringArray TexturePaths; CString IniPath; GetFontPaths(sFontOrTextureFilePath, TexturePaths, IniPath); @@ -276,6 +281,7 @@ Font *FontManager::LoadFontInt(const CString &sFontOrTextureFilePath, CString sC bool CapitalsOnly = false; + /* If we have an INI, load it. */ IniFile ini; if( !IniPath.empty() ) { @@ -288,7 +294,7 @@ Font *FontManager::LoadFontInt(const CString &sFontOrTextureFilePath, CString sC { /* Check to see if we need to import any other fonts. Do this * before loading this font, so any characters in this font - * override those imported. */ + * override imported characters. */ CString imports; ini.GetValue( "main", "import", imports ); CStringArray ImportList; @@ -304,6 +310,7 @@ Font *FontManager::LoadFontInt(const CString &sFontOrTextureFilePath, CString sC LoadingDefaultFont = false; } + /* Load imports. */ for(unsigned i = 0; i < ImportList.size(); ++i) { CString path = THEME->GetPathTo("Fonts", ImportList[i]); @@ -312,42 +319,44 @@ Font *FontManager::LoadFontInt(const CString &sFontOrTextureFilePath, CString sC } /* Load each font page. */ - int expect = -1; for(unsigned i = 0; i < TexturePaths.size(); ++i) { FontPage *fp = new FontPage; - int frames; - { - int wide, high; - RageTexture::GetFrameDimensionsFromFileName(TexturePaths[i], &wide, &high ); - frames = wide*high; - } + + int frames = RageTexture::GetFrameCountFromFileName(TexturePaths[i]); /* Grab the page name, eg "foo" from "Normal [foo].png". */ CString pagename = GetPageNameFromFileName(TexturePaths[i]); + /* Load settings for this page from the INI. */ FontPageSettings cfg; - if( !sChars.empty() ) + + /* If we have any characters to map, add them. */ + for( unsigned n=0; nLoad(TexturePaths[i], cfg); - if( expect != -1 && fp->m_pTexture->GetNumFrames() < expect ) + + /* Expect at least as many frames as we have premapped characters. */ + if( unsigned(fp->m_pTexture->GetNumFrames()) < sChars.size() ) RageException::Throw( "The font '%s' has %d frames; expected at least %i frames.", - fp->m_pTexture->GetNumFrames(), expect ); + fp->m_pTexture->GetNumFrames(), sChars.size() ); LOG->Trace("Adding page %s (%s) to %s; %i glyphs", TexturePaths[i].GetString(), pagename.GetString(), sFontOrTextureFilePath.GetString(), fp->m_iCharToGlyphNo.size()); pFont->AddPage(fp); + + /* If this is the first font loaded, or it's called "main", this page's + * properties become the font's properties. */ + if(i == 0 || pagename == "main") + pFont->SetDefaultGlyph(fp); } if(CapitalsOnly) @@ -453,7 +462,7 @@ void FontManager::InitCharAliases() if(!CharAliases.empty()) return; /* XXX; these should be in a data file somewhere (theme metrics?) - * (The comments here are UTF-8; they won't show up in VC6.) */ + * (The comments here are UTF-8; they won't show up in VC6.) */ CharAliases["default"] = Font::DEFAULT_GLYPH; /* ? */ CharAliases["kakumei1"] = 0x9769; /* 革 */ CharAliases["kakumei2"] = 0x547D; /* 命 */ @@ -464,7 +473,9 @@ void FontManager::InitCharAliases() CharAliases["omega"] = 0x03a9; /* Ω */ CharAliases["whiteheart"] = 0x2661; /* ♡ */ CharAliases["blackstar"] = 0x2605; /* ★ */ + CharAliases["whitestar"] = 0x2606; /* ☆ */ + /* These are internal-use glyphs; they don't have real Unicode codepoints. */ CharAliases["up"] = 0x100000; CharAliases["down"] = 0x100001; CharAliases["left"] = 0x100002;