khanat-opennel-code/code/nel/src/3d/font_manager.cpp
2013-06-17 16:03:24 +02:00

315 lines
8 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "std3d.h"
#include <string>
//#include <sstream>
#include "nel/3d/font_manager.h"
#include "nel/3d/font_generator.h"
#include "nel/3d/texture_font.h"
#include "nel/3d/computed_string.h"
#include "nel/3d/index_buffer.h"
#include "nel/3d/material.h"
#include "nel/misc/smart_ptr.h"
#include "nel/misc/debug.h"
#include "nel/misc/file.h"
using namespace std;
namespace NL3D {
// ***************************************************************************
CMaterial* CFontManager::getFontMaterial()
{
if (_TexFont == NULL)
{
_TexFont = new CTextureFont;
}
if (_MatFont == NULL)
{
_MatFont= new CMaterial;
_MatFont->initUnlit();
_MatFont->setSrcBlend(CMaterial::srcalpha);
_MatFont->setDstBlend(CMaterial::invsrcalpha);
_MatFont->setBlend(true);
_MatFont->setTexture(0, _TexFont);
_MatFont->texEnvOpRGB(0, CMaterial::Replace);
_MatFont->texEnvArg0RGB(0, CMaterial::Diffuse, CMaterial::SrcColor);
}
return _MatFont;
}
// ***************************************************************************
void CFontManager::computeString (const std::string &s,
CFontGenerator *fontGen,
const NLMISC::CRGBA &color,
uint32 fontSize,
IDriver *driver,
CComputedString &output,
bool keep800x600Ratio)
{
// static to avoid reallocation
static ucstring ucs;
ucs= s;
computeString(ucs, fontGen, color, fontSize, driver, output, keep800x600Ratio);
}
// ***************************************************************************
void CFontManager::computeString (const ucstring &s,
CFontGenerator *fontGen,
const NLMISC::CRGBA &color,
uint32 fontSize,
IDriver *driver,
CComputedString &output,
bool keep800x600Ratio)
{
output.Color = color;
// resize fontSize if window not of 800x600.
if (keep800x600Ratio)
{
uint32 width, height;
driver->getWindowSize (width, height);
if ((height == 0) || (width == 0))
return;
// keep the 800*600 ratio
fontSize = (uint32)floor(fontSize*height/600.f);
fontSize = max(fontSize, (uint32)2);
}
// Setting vertices format
output.Vertices.setNumVertices (4 * (uint32)s.size());
// 1 character <-> 1 quad
sint32 penx = 0, dx;
sint32 penz = 0, dz;
float x1, z1, x2, z2;
float u1, v1, u2, v2;
CMaterial *pMatFont = getFontMaterial();
CTextureFont *pTexFont = (CTextureFont*)(pMatFont->getTexture (0));
float TexRatioW = 1.0f / pTexFont->getWidth();
float TexRatioH = 1.0f / pTexFont->getHeight();
/*float hlfPixTexW = 0.5f * TexRatioW;
float hlfPixTexH = 0.5f * TexRatioH;
float hlfPixScrW = 0.5f;
float hlfPixScrH = 0.5f;*/
// Yoyo: Do not need Half Pixel/Texel displacement!!
float hlfPixTexW = 0;
float hlfPixTexH = 0;
float hlfPixScrW = 0;
float hlfPixScrH = 0;
CTextureFont::SLetterKey k;
// string bound.
output.XMin= FLT_MAX;
output.XMax= -FLT_MAX;
output.ZMin= FLT_MAX;
output.ZMax= -FLT_MAX;
// string info.
sint32 nMaxZ = -1000000, nMinZ = 1000000;
output.StringHeight = 0;
uint j = 0;
{
CVertexBufferReadWrite vba;
output.Vertices.lock (vba);
// For all chars
for (uint i = 0; i < s.size(); i++)
{
// Creating font
k.Char = s[i];
k.FontGenerator = fontGen;
k.Size = fontSize;
CTextureFont::SLetterInfo *pLI = pTexFont->getLetterInfo (k);
if(pLI != NULL)
{
if ((pLI->CharWidth > 0) && (pLI->CharHeight > 0))
{
// Creating vertices
dx = pLI->Left;
dz = -((sint32)pLI->CharHeight-(sint32)(pLI->Top));
u1 = pLI->U - hlfPixTexW;
v1 = pLI->V - hlfPixTexH;
u2 = pLI->U + ((float)pLI->CharWidth) * TexRatioW + hlfPixTexW;
v2 = pLI->V + ((float)pLI->CharHeight) * TexRatioH + hlfPixTexH;
x1 = (penx + dx) - hlfPixScrW;
z1 = (penz + dz) - hlfPixScrH;
x2 = (penx + dx + (sint32)pLI->CharWidth) + hlfPixScrW;
z2 = (penz + dz + (sint32)pLI->CharHeight) + hlfPixScrH;
vba.setVertexCoord (j, x1, 0, z1);
vba.setTexCoord (j, 0, u1, v2);
++j;
vba.setVertexCoord (j, x2, 0, z1);
vba.setTexCoord (j, 0, u2, v2);
++j;
vba.setVertexCoord (j, x2, 0, z2);
vba.setTexCoord (j, 0, u2, v1);
++j;
vba.setVertexCoord (j, x1, 0, z2);
vba.setTexCoord (j, 0, u1, v1);
++j;
// String Bound
output.XMin= min(output.XMin, x1);
output.XMin= min(output.XMin, x2);
output.XMax= max(output.XMax, x1);
output.XMax= max(output.XMax, x2);
output.ZMin= min(output.ZMin, z1);
output.ZMin= min(output.ZMin, z2);
output.ZMax= max(output.ZMax, z1);
output.ZMax= max(output.ZMax, z2);
// String info
sint32 nZ1 = (sint32)pLI->Top-(sint32)pLI->CharHeight;
sint32 nZ2 = pLI->Top;
if (nZ1 < nMinZ) nMinZ = nZ1;
if (nZ2 > nMaxZ) nMaxZ = nZ2;
}
penx += pLI->AdvX;
}
// Building Material
output.Material = pMatFont;
}
}
output.Vertices.setNumVertices (j);
// compile string info
output.StringWidth = (float)penx;
if(nMaxZ>nMinZ)
{
output.StringHeight = (float)(nMaxZ - nMinZ);
output.StringLine = -(float)nMinZ;
}
else
{
output.StringHeight = 0;
output.StringLine = 0;
}
}
// ***************************************************************************
void CFontManager::computeStringInfo ( const ucstring &s,
CFontGenerator *fontGen,
const NLMISC::CRGBA &color,
uint32 fontSize,
IDriver *driver,
CComputedString &output,
bool keep800x600Ratio )
{
output.Color = color;
// resize fontSize if window not of 800x600.
if (keep800x600Ratio)
{
uint32 width, height;
driver->getWindowSize (width, height);
if ((height == 0) || (width == 0))
return;
// keep the 800*600 ratio
fontSize = (uint32)floor(fontSize*height/600.f);
fontSize = max(fontSize, (uint32)2);
}
sint32 penx = 0;
sint32 nMaxZ = -1000000, nMinZ = 1000000;
CMaterial *pMatFont = getFontMaterial();
CTextureFont *pTexFont = (CTextureFont*)(pMatFont->getTexture (0));
CTextureFont::SLetterKey k;
CTextureFont::SLetterInfo *pLI;
for (uint i = 0; i < s.size(); i++)
{
// Creating font
k.Char = s[i];
k.FontGenerator = fontGen;
k.Size = fontSize;
pLI = pTexFont->getLetterInfo (k);
if(pLI != NULL)
{
if ((pLI->CharWidth > 0) && (pLI->CharHeight > 0))
{
// String info
sint32 nZ1 = (sint32)pLI->Top-(sint32)pLI->CharHeight;
sint32 nZ2 = pLI->Top;
if (nZ1 < nMinZ) nMinZ = nZ1;
if (nZ2 > nMaxZ) nMaxZ = nZ2;
}
penx += pLI->AdvX;
}
}
// compile string info
output.StringWidth = (float)penx;
if(nMaxZ>nMinZ)
{
output.StringHeight = (float)(nMaxZ - nMinZ);
output.StringLine = -(float)nMinZ;
}
else
{
output.StringHeight = 0;
output.StringLine = 0;
}
}
// ***************************************************************************
string CFontManager::getCacheInformation() const
{
// stringstream ss;
// ss << "MaxMemory: " << (uint) _MaxMemory << " MemSize: " << (uint) _MemSize << " NbChar: " << (uint) _NbChar;
// return ss.str();
string str;
str = "MaxMemory: " + NLMISC::toString(_MaxMemory) + " MemSize: " + NLMISC::toString(_MemSize) + " NbChar: " + NLMISC::toString(_NbChar);
return str;
}
// ***************************************************************************
void CFontManager::invalidate()
{
if (_TexFont)
_TexFont = NULL;
_TexFont = new CTextureFont;
}
} // NL3D