// NeL - MMORPG Framework // 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 . #include "std3d.h" #include //#include #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, bool embolden, bool oblique, IDriver *driver, CComputedString &output, bool keep800x600Ratio) { // static to avoid reallocation static ucstring ucs; ucs= s; computeString(ucs, fontGen, color, fontSize, embolden, oblique, driver, output, keep800x600Ratio); } // *************************************************************************** void CFontManager::computeString (const ucstring &s, CFontGenerator *fontGen, const NLMISC::CRGBA &color, uint32 fontSize, bool embolden, bool oblique, 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; k.Embolden = embolden; k.Oblique = oblique; 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, bool embolden, bool oblique, 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; k.Embolden = embolden; k.Oblique = oblique; 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