1
0
forked from 0ad/0ad

Refactor text renderer

Replace unifont with CFont and CFontManager, since the h_mgr interface
was
needlessly inconvenient.

Load the font textures through CTextureManager, to support dynamic
reloading (e.g. when resetting GL state - see #741).

Add CFontMetrics as a convenient wrapper for code that just wants to
measure text.

Fixes #1117.

This was SVN commit r14016.
This commit is contained in:
Ykkrosh 2013-10-18 15:53:07 +00:00
parent 8799bd98b0
commit 5778484a77
25 changed files with 406 additions and 541 deletions

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Textures>
<File pattern="*" format="alpha" mipmap="false"/>
<File pattern="*-stroke-*.png" format="rgba"/>
</Textures>

57
source/graphics/Font.cpp Normal file
View File

@ -0,0 +1,57 @@
/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "Font.h"
#include "graphics/FontManager.h"
#include "ps/Filesystem.h"
#include "ps/CLogger.h"
#include "renderer/Renderer.h"
#include <map>
#include <string>
int CFont::GetCharacterWidth(wchar_t c) const
{
GlyphMap::const_iterator it = m_Glyphs.find(c);
if (it == m_Glyphs.end())
it = m_Glyphs.find(0xFFFD); // Use the missing glyph symbol
if (it == m_Glyphs.end())
return 0;
return it->second.xadvance;
}
void CFont::CalculateStringSize(const wchar_t* string, int& width, int& height) const
{
width = 0;
height = m_Height;
for (const wchar_t* c = string; *c != '\0'; c++)
{
GlyphMap::const_iterator it = m_Glyphs.find(*c);
if (it == m_Glyphs.end())
it = m_Glyphs.find(0xFFFD); // Use the missing glyph symbol
if (it != m_Glyphs.end())
width += it->second.xadvance; // Add the character's advance distance
}
}

61
source/graphics/Font.h Normal file
View File

@ -0,0 +1,61 @@
/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_FONT
#define INCLUDED_FONT
#include "graphics/Texture.h"
#include "lib/res/handle.h"
#include <map>
class CStrW;
struct UnifontGlyphData;
class CFont
{
friend class CFontManager;
public:
struct GlyphData
{
float u0, v0, u1, v1;
i16 x0, y0, x1, y1;
i16 xadvance;
};
typedef std::map<u16, GlyphData> GlyphMap;
bool HasRGB() const { return m_HasRGB; }
int GetLineSpacing() const { return m_LineSpacing; }
int GetHeight() const { return m_Height; }
int GetCharacterWidth(wchar_t c) const;
void CalculateStringSize(const wchar_t* string, int& w, int& h) const;
const GlyphMap& GetGlyphs() const { return m_Glyphs; }
CTexturePtr GetTexture() const { return m_Texture; }
private:
CTexturePtr m_Texture;
bool m_HasRGB; // true if RGBA, false if ALPHA
GlyphMap m_Glyphs;
int m_LineSpacing;
int m_Height; // height of a capital letter, roughly
};
#endif // INCLUDED_FONT

View File

@ -0,0 +1,122 @@
/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "FontManager.h"
#include "graphics/Font.h"
#include "graphics/TextureManager.h"
#include "ps/CLogger.h"
#include "ps/CStr.h"
#include "ps/Filesystem.h"
#include "renderer/Renderer.h"
shared_ptr<CFont> CFontManager::LoadFont(const CStrW& fontName)
{
FontsMap::iterator it = m_Fonts.find(fontName);
if (it != m_Fonts.end())
return it->second;
shared_ptr<CFont> font(new CFont());
if (!ReadFont(font.get(), fontName))
{
// Fall back to default font (unless this is the default font)
if (fontName == L"sans-10")
font.reset();
else
font = LoadFont(L"sans-10");
}
m_Fonts[fontName] = font;
return font;
}
bool CFontManager::ReadFont(CFont* font, const CStrW& fontName)
{
const VfsPath path(L"fonts/");
// Read font definition file into a stringstream
shared_ptr<u8> buf;
size_t size;
const VfsPath fntName(fontName + L".fnt");
if (g_VFS->LoadFile(path / fntName, buf, size) < 0)
{
LOGERROR(L"Failed to open font file %ls", (path / fntName).string().c_str());
return false;
}
std::istringstream FNTStream(std::string((const char*)buf.get(), size));
int Version;
FNTStream >> Version;
if (Version != 101) // Make sure this is from a recent version of the font builder
{
LOGERROR(L"Font %ls has invalid version", fontName.c_str());
return 0;
}
int TextureWidth, TextureHeight;
FNTStream >> TextureWidth >> TextureHeight;
std::string Format;
FNTStream >> Format;
if (Format == "rgba")
font->m_HasRGB = true;
else if (Format == "a")
font->m_HasRGB = false;
else
debug_warn(L"Invalid .fnt format string");
int NumGlyphs;
FNTStream >> NumGlyphs;
FNTStream >> font->m_LineSpacing;
FNTStream >> font->m_Height;
for (int i = 0; i < NumGlyphs; ++i)
{
int Codepoint, TextureX, TextureY, Width, Height, OffsetX, OffsetY, Advance;
FNTStream >> Codepoint>>TextureX>>TextureY>>Width>>Height>>OffsetX>>OffsetY>>Advance;
if (Codepoint < 0 || Codepoint > 0xFFFF)
{
LOGWARNING(L"Font %ls has invalid codepoint 0x%x", fontName.c_str(), Codepoint);
continue;
}
float u = (float)TextureX / (float)TextureWidth;
float v = (float)TextureY / (float)TextureHeight;
float w = (float)Width / (float)TextureWidth;
float h = (float)Height / (float)TextureHeight;
CFont::GlyphData g = { u, -v, u+w, -v+h, (i16)OffsetX, (i16)-OffsetY, (i16)(OffsetX+Width), (i16)(-OffsetY+Height), (i16)Advance };
font->m_Glyphs[(u16)Codepoint] = g;
}
ENSURE(font->m_Height); // Ensure the height has been found (which should always happen if the font includes an 'I')
// Load glyph texture
const VfsPath imgName(fontName + L".png");
CTextureProperties textureProps(path / imgName);
textureProps.SetFilter(GL_NEAREST);
if (!font->m_HasRGB)
textureProps.SetFormatOverride(GL_ALPHA);
font->m_Texture = g_Renderer.GetTextureManager().CreateTexture(textureProps);
return true;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2012 Wildfire Games.
/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -15,33 +15,27 @@
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_FONT
#define INCLUDED_FONT
#ifndef INCLUDED_FONTMANAGER
#define INCLUDED_FONTMANAGER
#include "lib/res/handle.h"
#include <map>
#include <boost/unordered_map.hpp>
class CFont;
class CStrW;
struct UnifontGlyphData;
class CFont
/**
* Font manager: loads and caches bitmap fonts.
*/
class CFontManager
{
public:
CFont(const CStrW& name);
~CFont();
bool HasRGB();
int GetLineSpacing();
int GetHeight();
int GetCharacterWidth(wchar_t c);
void CalculateStringSize(const wchar_t* string, int& w, int& h);
const std::map<u16, UnifontGlyphData>& GetGlyphs();
Handle GetTexture();
shared_ptr<CFont> LoadFont(const CStrW& fontName);
private:
Handle h;
bool ReadFont(CFont* font, const CStrW& fontName);
typedef boost::unordered_map<CStrW, shared_ptr<CFont> > FontsMap;
FontsMap m_Fonts;
};
#endif // INCLUDED_FONT
#endif // INCLUDED_FONTMANAGER

View File

@ -0,0 +1,61 @@
/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "FontMetrics.h"
#include "graphics/Font.h"
#include "graphics/FontManager.h"
#include "ps/Filesystem.h"
#include "ps/CLogger.h"
#include "renderer/Renderer.h"
CFontMetrics::CFontMetrics(const CStrW& font)
{
m_Font = g_Renderer.GetFontManager().LoadFont(font);
}
int CFontMetrics::GetLineSpacing() const
{
// Return some arbitrary default if the font failed to load, so that the
// user of CFontMetrics doesn't have to care about failures
if (!m_Font)
return 12;
return m_Font->GetLineSpacing();
}
int CFontMetrics::GetHeight() const
{
if (!m_Font)
return 6;
return m_Font->GetHeight();
}
int CFontMetrics::GetCharacterWidth(wchar_t c) const
{
if (!m_Font)
return 6;
return m_Font->GetCharacterWidth(c);
}
void CFontMetrics::CalculateStringSize(const wchar_t* string, int& w, int& h) const
{
if (!m_Font)
w = h = 0;
else
m_Font->CalculateStringSize(string, w, h);
}

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_FONTMETRICS
#define INCLUDED_FONTMETRICS
class CFont;
class CStrW;
/**
* Helper class for measuring sizes of text.
* This will load the font when necessary, and will return plausible values
* if loading fails (since misrendering is better than crashing).
*/
class CFontMetrics
{
public:
CFontMetrics(const CStrW& font);
int GetLineSpacing() const;
int GetHeight() const;
int GetCharacterWidth(wchar_t c) const;
void CalculateStringSize(const wchar_t* string, int& w, int& h) const;
private:
shared_ptr<CFont> m_Font;
};
#endif // INCLUDED_FONTMETRICS

View File

@ -19,10 +19,11 @@
#include "TextRenderer.h"
#include "graphics/Font.h"
#include "graphics/FontManager.h"
#include "lib/ogl.h"
#include "lib/res/graphics/unifont.h"
#include "ps/CStrIntern.h"
#include "ps/Font.h"
#include "renderer/Renderer.h"
extern int g_xres, g_yres;
@ -74,10 +75,7 @@ void CTextRenderer::Color(float r, float g, float b, float a)
void CTextRenderer::Font(const CStrW& font)
{
if (!m_Fonts[font])
m_Fonts[font] = shared_ptr<CFont>(new CFont(font));
m_Font = m_Fonts[font];
m_Font = g_Renderer.GetFontManager().LoadFont(font);
}
void CTextRenderer::PrintfAdvance(const wchar_t* fmt, ...)
@ -125,6 +123,9 @@ void CTextRenderer::Put(float x, float y, const wchar_t* buf)
if (buf[0] == 0)
return; // empty string; don't bother storing
if (!m_Font)
return; // invalid font; can't render
CMatrix3D translate;
translate.SetTranslation(x, y, 0.0f);
@ -155,7 +156,7 @@ void CTextRenderer::Render()
if (batch.text.empty()) // avoid zero-length arrays
continue;
const std::map<u16, UnifontGlyphData>& glyphs = batch.font->GetGlyphs();
const CFont::GlyphMap& glyphs = batch.font->GetGlyphs();
m_Shader->BindTexture(str_tex, batch.font->GetTexture());
@ -179,7 +180,7 @@ void CTextRenderer::Render()
i16 x = 0;
for (size_t i = 0; i < batch.text.size(); ++i)
{
std::map<u16, UnifontGlyphData>::const_iterator it = glyphs.find(batch.text[i]);
CFont::GlyphMap::const_iterator it = glyphs.find(batch.text[i]);
if (it == glyphs.end())
it = glyphs.find(0xFFFD); // Use the missing glyph symbol
@ -187,7 +188,7 @@ void CTextRenderer::Render()
if (it == glyphs.end()) // Missing the missing glyph symbol - give up
continue;
const UnifontGlyphData& g = it->second;
const CFont::GlyphData& g = it->second;
vertexes[i*4].u = g.u1;
vertexes[i*4].v = g.v0;

View File

@ -101,8 +101,6 @@ private:
CColor m_Color;
shared_ptr<CFont> m_Font;
std::map<CStrW, shared_ptr<CFont> > m_Fonts;
std::vector<SBatch> m_Batches;
};

View File

@ -24,7 +24,7 @@ CCheckBox
#include "CCheckBox.h"
#include "ps/CLogger.h"
#include "ps/Font.h"
#include "graphics/FontMetrics.h"
//-------------------------------------------------------------------
@ -130,7 +130,7 @@ void CCheckBox::Draw()
GUI<int>::GetSetting(this, "cell_id", cell_id);
// Get line height
CFont font (font_name);
CFontMetrics font (font_name);
float line_height = (float)font.GetHeight();
float bz = GetBufferedZ();

View File

@ -41,6 +41,7 @@ CGUI
#include "MiniMap.h"
#include "scripting/JSInterface_GUITypes.h"
#include "graphics/FontMetrics.h"
#include "graphics/ShaderManager.h"
#include "graphics/TextRenderer.h"
#include "lib/input.h"
@ -49,7 +50,6 @@ CGUI
#include "lib/sysdep/sysdep.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
#include "ps/Font.h"
#include "ps/Hotkey.h"
#include "ps/Globals.h"
#include "ps/Overlay.h"

View File

@ -24,6 +24,7 @@ CInput
#include "CInput.h"
#include "CGUIScrollBarVertical.h"
#include "graphics/FontMetrics.h"
#include "graphics/ShaderManager.h"
#include "graphics/TextRenderer.h"
#include "lib/ogl.h"
@ -31,7 +32,6 @@ CInput
#include "lib/timer.h"
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
#include "ps/Font.h"
#include "ps/Globals.h"
#include "ps/Hotkey.h"
#include "renderer/Renderer.h"
@ -1057,7 +1057,7 @@ void CInput::Draw()
scroll = GetScrollBar(0).GetPos();
}
CFont font(font_name);
CFontMetrics font(font_name);
// We'll have to setup clipping manually, since we're doing the rendering manually.
CRect cliparea(m_CachedActualSize);
@ -1406,7 +1406,7 @@ void CInput::UpdateText(int from, int to_before, int to_after)
if (to_before == -1)
to = (int)caption.length();
CFont font(font_name);
CFontMetrics font(font_name);
std::list<SRow>::iterator current_line;
@ -1782,7 +1782,7 @@ int CInput::GetMouseHoveringTextPosition()
// Now get the height of the font.
// TODO: Get the real font
CFont font(font_name);
CFontMetrics font(font_name);
float spacing = (float)font.GetLineSpacing();
//float height = (float)font.GetHeight(); // unused
@ -1930,7 +1930,7 @@ void CInput::UpdateAutoScroll()
// Now get the height of the font.
// TODO: Get the real font
CFont font(font_name);
CFontMetrics font(font_name);
float spacing = (float)font.GetLineSpacing();
//float height = font.GetHeight();

View File

@ -23,12 +23,11 @@ GUI text
#include "GUI.h"
#include "GUIManager.h"
#include "graphics/FontMetrics.h"
#include "ps/CLogger.h"
#include "ps/Parser.h"
#include <algorithm>
#include "ps/Font.h"
static const wchar_t TagStart = '[';
static const wchar_t TagEnd = ']';
@ -232,7 +231,7 @@ void CGUIString::GenerateTextCall(SFeedback &Feedback,
// Calculate the size of the font
CSize size;
int cx, cy;
CFont font (TextCall.m_Font);
CFontMetrics font (TextCall.m_Font);
font.CalculateStringSize(TextCall.m_String.c_str(), cx, cy);
// For anything other than the first line, the line spacing
// needs to be considered rather than just the height of the text

View File

@ -1,299 +0,0 @@
/* Copyright (c) 2012 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Unicode OpenGL texture font.
*/
#include "precompiled.h"
#include "unifont.h"
#include <stdio.h>
#include <string>
#include <sstream>
#include <map>
#include "ogl_tex.h"
#include "lib/res/h_mgr.h"
typedef std::map<u16, UnifontGlyphData> glyphmap;
struct UniFont
{
Handle ht; // Handle to font texture
bool HasRGB; // true if RGBA, false if ALPHA
glyphmap* glyphs;
int LineSpacing;
int Height; // of a capital letter, roughly
};
H_TYPE_DEFINE(UniFont);
static void UniFont_init(UniFont* UNUSED(f), va_list UNUSED(args))
{
}
static void UniFont_dtor(UniFont* f)
{
// these are all safe, no is_valid flags needed
(void)ogl_tex_free(f->ht);
SAFE_DELETE(f->glyphs);
}
// basename is e.g. "console"; the files are "fonts/console.fnt" and "fonts/console.png"
// [10..70ms]
static Status UniFont_reload(UniFont* f, const PIVFS& vfs, const VfsPath& basename, Handle UNUSED(h))
{
// already loaded
if(f->ht > 0)
return INFO::OK;
f->glyphs = new glyphmap();
const VfsPath path(L"fonts/");
// Read font definition file into a stringstream
shared_ptr<u8> buf; size_t size;
const VfsPath fntName(basename.ChangeExtension(L".fnt"));
RETURN_STATUS_IF_ERR(vfs->LoadFile(path / fntName, buf, size)); // [cumulative for 12: 36ms]
std::istringstream FNTStream(std::string((const char*)buf.get(), size));
int Version;
FNTStream >> Version;
if (Version < 100 || Version > 101) // Make sure this is from a recent version of the font builder
WARN_RETURN(ERR::FAIL);
int TextureWidth, TextureHeight;
FNTStream >> TextureWidth >> TextureHeight;
if (Version >= 101)
{
std::string Format;
FNTStream >> Format;
if (Format == "rgba")
f->HasRGB = true;
else if (Format == "a")
f->HasRGB = false;
else
debug_warn(L"Invalid .fnt format string");
}
int NumGlyphs;
FNTStream >> NumGlyphs;
FNTStream >> f->LineSpacing;
if (Version >= 101)
FNTStream >> f->Height;
else
f->Height = 0;
// [cumulative for 12: 256ms]
for (int i = 0; i < NumGlyphs; ++i)
{
int Codepoint, TextureX, TextureY, Width, Height, OffsetX, OffsetY, Advance;
FNTStream >> Codepoint>>TextureX>>TextureY>>Width>>Height>>OffsetX>>OffsetY>>Advance;
if (Codepoint < 0 || Codepoint > 0xFFFF)
{
DEBUG_WARN_ERR(ERR::LOGIC); // Invalid codepoint
continue;
}
if (Version < 101 && Codepoint == 'I')
{
f->Height = Height;
}
GLfloat u = (GLfloat)TextureX / (GLfloat)TextureWidth;
GLfloat v = (GLfloat)TextureY / (GLfloat)TextureHeight;
GLfloat w = (GLfloat)Width / (GLfloat)TextureWidth;
GLfloat h = (GLfloat)Height / (GLfloat)TextureHeight;
UnifontGlyphData g = { u, -v, u+w, -v+h, (i16)OffsetX, (i16)-OffsetY, (i16)(OffsetX+Width), (i16)(-OffsetY+Height), (i16)Advance };
(*f->glyphs)[(u16)Codepoint] = g;
}
ENSURE(f->Height); // Ensure the height has been found (which should always happen if the font includes an 'I')
// Load glyph texture
// [cumulative for 12: 20ms]
const VfsPath imgName(basename.ChangeExtension(L".png"));
Handle ht = ogl_tex_load(vfs, path / imgName);
RETURN_STATUS_IF_ERR(ht);
(void)ogl_tex_set_filter(ht, GL_NEAREST);
Status err;
if (f->HasRGB)
{
// use format auto-detection
err = ogl_tex_upload(ht);
}
else
{
// override is necessary because the GL format is chosen as LUMINANCE,
// but we want ALPHA. there is no way of knowing what format
// 8bpp textures are in - we could adopt a naming convention and
// add some TEX_ flags, but that's overkill.
err = ogl_tex_upload(ht, GL_ALPHA);
}
if(err < 0)
{
(void)ogl_tex_free(ht);
return err;
}
f->ht = ht;
return INFO::OK;
}
static Status UniFont_validate(const UniFont* f)
{
if(f->ht < 0)
WARN_RETURN(ERR::_1);
if(debug_IsPointerBogus(f->glyphs))
WARN_RETURN(ERR::_2);
// <LineSpacing> and <Height> are read directly from font file.
// negative values don't make sense, but that's all we can check.
if(f->LineSpacing < 0 || f->Height < 0)
WARN_RETURN(ERR::_3);
return INFO::OK;
}
static Status UniFont_to_string(const UniFont* f, wchar_t* buf)
{
if (f->ht) // not true if this is called after dtor (which it is)
{
const VfsPath& path = h_filename(f->ht);
swprintf_s(buf, H_STRING_LEN, L"Font %ls", path.string().c_str());
}
else
swprintf_s(buf, H_STRING_LEN, L"Font");
return INFO::OK;
}
Handle unifont_load(const PIVFS& vfs, const VfsPath& pathname, size_t flags)
{
return h_alloc(H_UniFont, vfs, pathname, flags);
}
Status unifont_unload(Handle& h)
{
H_DEREF(h, UniFont, f);
return h_free(h, H_UniFont);
}
int unifont_linespacing(const Handle h)
{
H_DEREF(h, UniFont, f);
return f->LineSpacing;
}
int unifont_height(const Handle h)
{
H_DEREF(h, UniFont, f);
return f->Height;
}
bool unifont_has_rgb(const Handle h)
{
UniFont* const f = H_USER_DATA(h, UniFont);
if(!f)
return false;
return f->HasRGB;
}
int unifont_character_width(const Handle h, wchar_t c)
{
H_DEREF(h, UniFont, f);
glyphmap::iterator it = f->glyphs->find(c);
if (it == f->glyphs->end())
it = f->glyphs->find(0xFFFD); // Use the missing glyph symbol
return it->second.xadvance;
}
Status unifont_stringsize(const Handle h, const wchar_t* text, int& width, int& height)
{
H_DEREF(h, UniFont, f);
width = 0;
height = f->Height;
size_t len = wcslen(text);
for (size_t i = 0; i < len; ++i)
{
glyphmap::iterator it = f->glyphs->find(text[i]);
if (it == f->glyphs->end())
it = f->glyphs->find(0xFFFD); // Use the missing glyph symbol
if (it == f->glyphs->end()) // Missing the missing glyph symbol - give up
{
DEBUG_WARN_ERR(ERR::LOGIC); // Missing the missing glyph in a unifont!
return INFO::OK;
}
width += it->second.xadvance; // Add the character's advance distance
}
return INFO::OK;
}
const glyphmap& unifont_get_glyphs(const Handle h)
{
UniFont* const f = H_USER_DATA(h, UniFont);
if(!f)
{
DEBUG_WARN_ERR(ERR::INVALID_HANDLE);
static glyphmap dummy;
return dummy;
}
return *f->glyphs;
}
Handle unifont_get_texture(const Handle h)
{
UniFont* const f = H_USER_DATA(h, UniFont);
if(!f)
{
DEBUG_WARN_ERR(ERR::INVALID_HANDLE);
return 0;
}
return f->ht;
}

View File

@ -1,105 +0,0 @@
/* Copyright (c) 2012 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Unicode OpenGL texture font.
*/
#ifndef INCLUDED_UNIFONT
#define INCLUDED_UNIFONT
#include <stdarg.h> // va_list
#include <map>
#include "lib/res/handle.h"
#include "lib/file/vfs/vfs.h"
/**
* Load a font.
*
* @param vfs
* @param pathname path and basename of the font definition file
* (.fnt) and its texture (.png)
* @param flags
**/
extern Handle unifont_load(const PIVFS& vfs, const VfsPath& pathname, size_t flags = 0);
/**
* Release a handle to a previously loaded font
* (subject to reference counting).
**/
extern Status unifont_unload(Handle& h);
/**
* Determine pixel extents of a string.
*
* @param h
* @param text string in question.
* @param width
* @param height is roughly the pixel height of a capital letter, for use
* when aligning text in an aesthetically pleasing way.
*
* note: This is intended for the GUI (hence Unicode).
**/
Status unifont_stringsize(const Handle h, const wchar_t* text, int& width, int& height);
/**
* @return whether the font is an RGBA texture, not an ALPHA texture.
**/
bool unifont_has_rgb(const Handle h);
/**
* @return height [pixels] of the font.
**/
int unifont_height(const Handle h);
/**
* @return width [pixels] of a certain character.
**/
int unifont_character_width(const Handle h, wchar_t c);
/**
* @return spacing in pixels from one line of text to the next.
**/
int unifont_linespacing(const Handle h);
// Raw access to font data (since it's convenient to move as much of the
// processing as possible to outside lib/):
struct UnifontGlyphData
{
float u0, v0, u1, v1;
i16 x0, y0, x1, y1;
i16 xadvance;
};
/**
* @return glyph data for all glyphs in this font.
*/
const std::map<u16, UnifontGlyphData>& unifont_get_glyphs(const Handle h);
/**
* @return texture handle for this font.
*/
Handle unifont_get_texture(const Handle h);
#endif // INCLUDED_UNIFONT

View File

@ -93,7 +93,9 @@ void CArchiveBuilder::Build(const OsPath& archive, bool compress)
ENSURE(ret == INFO::OK);
// Compress textures and store the new cached version instead of the original
if (boost::algorithm::starts_with(path.string(), L"art/textures/") &&
if ((boost::algorithm::starts_with(path.string(), L"art/textures/") ||
boost::algorithm::starts_with(path.string(), L"fonts/")
) &&
tex_is_known_extension(path) &&
// Skip some subdirectories where the engine doesn't use CTextureManager yet:
!boost::algorithm::starts_with(path.string(), L"art/textures/cursors/") &&

View File

@ -24,6 +24,7 @@
#include "CConsole.h"
#include "graphics/FontMetrics.h"
#include "graphics/ShaderManager.h"
#include "graphics/TextRenderer.h"
#include "gui/GUIutil.h"
@ -35,7 +36,6 @@
#include "network/NetServer.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
#include "ps/Font.h"
#include "ps/Globals.h"
#include "ps/Hotkey.h"
#include "ps/Pyrogenesis.h"

View File

@ -19,13 +19,13 @@
#include "CLogger.h"
#include "CConsole.h"
#include "graphics/FontMetrics.h"
#include "graphics/ShaderManager.h"
#include "graphics/TextRenderer.h"
#include "lib/ogl.h"
#include "lib/timer.h"
#include "lib/utf8.h"
#include "lib/sysdep/sysdep.h"
#include "ps/Font.h"
#include "ps/Profile.h"
#include "renderer/Renderer.h"
@ -281,7 +281,7 @@ void CLogger::Render()
CleanupRenderQueue();
CStrW font_name(L"mono-stroke-10");
CFont font(font_name);
CFontMetrics font(font_name);
int lineSpacing = font.GetLineSpacing();
CShaderTechniquePtr textTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);

View File

@ -1,83 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "Font.h"
#include "lib/res/graphics/unifont.h"
#include "ps/Filesystem.h"
#include "ps/CLogger.h"
#include <map>
#include <string>
const wchar_t* DefaultFont = L"sans-10";
CFont::CFont(const CStrW& name)
{
h = unifont_load(g_VFS, name);
// Found it
if (h > 0)
return;
// Not found as a font -- give up and use the default.
LOGERROR(L"Failed to find font '%ls'", name.c_str());
h = unifont_load(g_VFS, DefaultFont);
// Assume this worked
}
CFont::~CFont()
{
unifont_unload(h);
}
bool CFont::HasRGB()
{
return unifont_has_rgb(h);
}
int CFont::GetLineSpacing()
{
return unifont_linespacing(h);
}
int CFont::GetHeight()
{
return unifont_height(h);
}
int CFont::GetCharacterWidth(wchar_t c)
{
return unifont_character_width(h, c);
}
void CFont::CalculateStringSize(const wchar_t* string, int& width, int& height)
{
unifont_stringsize(h, string, width, height);
}
const std::map<u16, UnifontGlyphData>& CFont::GetGlyphs()
{
return unifont_get_glyphs(h);
}
Handle CFont::GetTexture()
{
return unifont_get_texture(h);
}

View File

@ -36,6 +36,7 @@
#endif
#include "graphics/CinemaTrack.h"
#include "graphics/FontMetrics.h"
#include "graphics/GameView.h"
#include "graphics/LightEnv.h"
#include "graphics/MapReader.h"
@ -55,7 +56,6 @@
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
#include "ps/Filesystem.h"
#include "ps/Font.h"
#include "ps/Game.h"
#include "ps/GameSetup/Atlas.h"
#include "ps/GameSetup/GameSetup.h"
@ -507,7 +507,7 @@ static void InitPs(bool setup_gui, const CStrW& gui_page, CScriptVal initData)
g_Console->UpdateScreenSize(g_xres, g_yres);
// Calculate and store the line spacing
CFont font(CONSOLE_FONT);
CFontMetrics font(CONSOLE_FONT);
g_Console->m_iFontHeight = font.GetLineSpacing();
g_Console->m_iFontWidth = font.GetCharacterWidth(L'C');
g_Console->m_charsPerPage = (size_t)(g_xres / g_Console->m_iFontWidth);

View File

@ -27,12 +27,12 @@
#include "ProfileViewer.h"
#include "graphics/FontMetrics.h"
#include "gui/GUIutil.h"
#include "graphics/ShaderManager.h"
#include "graphics/TextRenderer.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
#include "ps/Font.h"
#include "ps/Hotkey.h"
#include "ps/Profile.h"
#include "lib/external_libraries/libsdl.h"
@ -171,7 +171,7 @@ void CProfileViewer::RenderProfile()
size_t numrows = table->GetNumberRows();
CStrW font_name = L"mono-stroke-10";
CFont font(font_name);
CFontMetrics font(font_name);
int lineSpacing = font.GetLineSpacing();
// Render background

View File

@ -44,6 +44,7 @@
#include "ps/Loader.h"
#include "ps/ProfileViewer.h"
#include "graphics/Camera.h"
#include "graphics/FontManager.h"
#include "graphics/GameView.h"
#include "graphics/LightEnv.h"
#include "graphics/LOSTexture.h"
@ -281,6 +282,8 @@ public:
/// Postprocessing effect manager
CPostprocManager postprocManager;
CFontManager fontManager;
/// Various model renderers
struct Models
{
@ -2007,4 +2010,9 @@ CMaterialManager& CRenderer::GetMaterialManager()
CPostprocManager& CRenderer::GetPostprocManager()
{
return m->postprocManager;
}
}
CFontManager& CRenderer::GetFontManager()
{
return m->fontManager;
}

View File

@ -36,6 +36,7 @@
#include "scriptinterface/ScriptInterface.h"
// necessary declarations
class CFontManager;
class CLightEnv;
class CMaterial;
class CMaterialManager;
@ -304,6 +305,8 @@ public:
CMaterialManager& GetMaterialManager();
CFontManager& GetFontManager();
CShaderDefines GetSystemShaderDefines() { return m_SystemShaderDefines; }
CTimeManager& GetTimeManager();

View File

@ -39,7 +39,6 @@
#include "ps/Filesystem.h"
#include "ps/CLogger.h"
#include "ps/Font.h"
#include "ps/Game.h"
#include "ps/Profile.h"
#include "ps/World.h"

View File

@ -38,7 +38,6 @@
#include "graphics/Overlay.h"
#include "maths/MathUtil.h"
#include "ps/Filesystem.h"
#include "ps/Font.h"
#include "ps/CLogger.h"
#include "ps/GameSetup/Config.h"
#include "ps/ProfileViewer.h"