khanat-opennel-code/code/nel/include/nel/3d/text_context.h
Nimetu c760b1e3d9 Add embolden, oblique font styles (NL3D)
--HG--
branch : develop
2015-03-29 17:28:33 +03:00

444 lines
14 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/>.
#ifndef NL_TEXT_CONTEXT_H
#define NL_TEXT_CONTEXT_H
#include "nel/3d/font_manager.h"
#include "nel/3d/computed_string.h"
namespace NL3D {
class CFontGenerator;
/**
* CTextContext
*
* \author Stephane Coutelas
* \author Nevrax France
* \date 2000
*/
class CTextContext
{
public:
/**
* Constructor
* defaults : fontsize=12, color=(0,0,0,255), hotspot=bottomleft, scale=1, shaded=false, shadeExtent=0.001f
* shadecolor=(0,0,0,255), 800x600ratio=true
*/
CTextContext ();
/// Destructor
~CTextContext();
/**
* Inits
*/
/// set the driver.
void init (IDriver *drv, CFontManager *fmg)
{
nlassert(drv && fmg);
_Driver= drv;
_FontManager= fmg;
}
// get the fontManager
CFontManager *getFontManager() const {return _FontManager;}
/// Must be called before any print
void setFontGenerator (const std::string &fontFileName, const std::string &fontExFileName = "");
NL3D::CFontGenerator *getFontGenerator () { return _FontGen; }
/**
* Accessors SET
*/
void setColor (NLMISC::CRGBA color) { _Color = color; }
void setFontSize (uint32 fontSize) { _FontSize = fontSize; }
void setEmbolden (bool b) { _Embolden = b; }
void setOblique (bool b) { _Oblique = b; }
void setHotSpot (CComputedString::THotSpot hotSpot) { _HotSpot = hotSpot; }
void setScaleX (float scaleX) { _ScaleX = scaleX; }
void setScaleZ (float scaleZ) { _ScaleZ = scaleZ; }
void setShaded (bool b) { _Shaded = b; }
void setShadeOutline (bool b) { _ShadeOutline = b; }
void setShadeExtent (float shext) { _ShadeExtent = shext; }
/// The alpha of the shade is multiplied at each draw with the alpha of the color. Default: (0,0,0,255)
void setShadeColor (NLMISC::CRGBA color) { _ShadeColor = color; }
/// If true the CFontManager look at Driver window size, and resize fontSize to keep the same
/// size than if it was in 800x600...
void setKeep800x600Ratio (bool keep) { _Keep800x600Ratio = keep; }
/**
* Accessors GET
*/
NLMISC::CRGBA getColor () const { return _Color; }
uint32 getFontSize () const { return _FontSize; }
bool getEmbolden () const { return _Embolden; }
bool getOblique () const { return _Oblique; }
CComputedString::THotSpot getHotSpot() const { return _HotSpot; }
float getScaleX() const { return _ScaleX; }
float getScaleZ() const { return _ScaleZ; }
bool getShaded() const { return _Shaded; }
bool getShadeOutline() const { return _ShadeOutline; }
bool getKeep800x600Ratio() const {return _Keep800x600Ratio;}
NLMISC::CRGBA getShadeColor () const { return _ShadeColor; }
/**
* Cache methods
*/
/// compute and add a string to the cache (return the index)
uint32 textPush (const char *format, ...);
/// computes an ucstring and adds the result to the cache (return the index)
uint32 textPush (const ucstring &str);
/// remove a string from the cache
void erase (uint32 index);
/// Clear the cache
void clear();
/**
* Printing methods
*/
/** Print a string that is in the cache from its index (it leaves the string in the cache)
* z : if the hotspot is bottom z is the position of the line of the string, not the bottom of the string bounding box !
*/
void printAt (float x, float z, uint32 index)
{
nlassert (index < _CacheStrings.size());
CComputedString &rCS = _CacheStrings[index];
if (_Shaded)
{
CRGBA bkup = rCS.Color;
rCS.Color = _ShadeColor;
rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8);
if (_ShadeOutline)
{
float rext = _ShadeExtent * 0.7071f;
rCS.render2D(*_Driver, x+rext, z-rext, _HotSpot, _ScaleX, _ScaleZ);
rCS.render2D(*_Driver, x-rext, z-rext, _HotSpot, _ScaleX, _ScaleZ);
rCS.render2D(*_Driver, x-rext, z+rext, _HotSpot, _ScaleX, _ScaleZ);
rCS.render2D(*_Driver, x+rext, z+rext, _HotSpot, _ScaleX, _ScaleZ);
rCS.render2D(*_Driver, x+_ShadeExtent, z, _HotSpot, _ScaleX, _ScaleZ);
rCS.render2D(*_Driver, x-_ShadeExtent, z, _HotSpot, _ScaleX, _ScaleZ);
rCS.render2D(*_Driver, x, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ);
rCS.render2D(*_Driver, x, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ);
}
else
{
rCS.render2D(*_Driver, x+_ShadeExtent, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ);
}
rCS.Color= bkup;
}
rCS.render2D(*_Driver, x, z, _HotSpot, _ScaleX, _ScaleZ);
}
/** Clip and print a string that is in the cache (it leaves the string in the cache)
* z : if the hotspot is bottom z is the position of the line of the string, not the bottom of the string bounding box !
*/
void printClipAt (CRenderStringBuffer &rdrBuffer, float x, float z, uint32 index, float xmin, float ymin, float xmax, float ymax)
{
nlassert (index < _CacheStrings.size());
CComputedString &rCS = _CacheStrings[index];
if(_Shaded)
{
CRGBA bkup = rCS.Color;
rCS.Color= _ShadeColor;
rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8);
if (_ShadeOutline)
{
float rext = _ShadeExtent * 0.7071f;
rCS.render2DClip(*_Driver, rdrBuffer, x+rext, z-rext, xmin, ymin, xmax, ymax);
rCS.render2DClip(*_Driver, rdrBuffer, x-rext, z-rext, xmin, ymin, xmax, ymax);
rCS.render2DClip(*_Driver, rdrBuffer, x-rext, z+rext, xmin, ymin, xmax, ymax);
rCS.render2DClip(*_Driver, rdrBuffer, x+rext, z+rext, xmin, ymin, xmax, ymax);
rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z, xmin, ymin, xmax, ymax);
rCS.render2DClip(*_Driver, rdrBuffer, x-_ShadeExtent, z, xmin, ymin, xmax, ymax);
rCS.render2DClip(*_Driver, rdrBuffer, x, z+_ShadeExtent, xmin, ymin, xmax, ymax);
rCS.render2DClip(*_Driver, rdrBuffer, x, z-_ShadeExtent, xmin, ymin, xmax, ymax);
}
else
{
rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z-_ShadeExtent, xmin, ymin, xmax, ymax);
}
rCS.Color= bkup;
}
rCS.render2DClip (*_Driver, rdrBuffer, x, z, xmin, ymin, xmax, ymax);
}
/** Clip and print a string that is in the cache (it leaves the string in the cache)
* z : if the hotspot is bottom z is the position of the line of the string, not the bottom of the string bounding box !
*/
void printClipAtUnProjected (CRenderStringBuffer &renderBuffer, class NL3D::CFrustum &frustum, const NLMISC::CMatrix &scaleMatrix, float x, float y, float depth, uint32 index, float xmin, float ymin, float xmax, float ymax)
{
nlassert (index < _CacheStrings.size());
CComputedString &rCS = _CacheStrings[index];
if (_Shaded)
{
CRGBA bkup = rCS.Color;
rCS.Color= _ShadeColor;
rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8);
if (_ShadeOutline)
{
float rext = _ShadeExtent * 0.7071f;
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rext, y-rext, depth, xmin, ymin, xmax, ymax);
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rext, y-rext, depth, xmin, ymin, xmax, ymax);
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rext, y+rext, depth, xmin, ymin, xmax, ymax);
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rext, y+rext, depth, xmin, ymin, xmax, ymax);
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y, depth, xmin, ymin, xmax, ymax);
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-_ShadeExtent, y, depth, xmin, ymin, xmax, ymax);
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y+_ShadeExtent, depth, xmin, ymin, xmax, ymax);
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax);
}
else
{
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax);
}
rCS.Color= bkup;
}
rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y, depth, xmin, ymin, xmax, ymax);
}
/// Directly print a string
void printAt (float x, float z, const ucstring &ucstr)
{
nlassert(_FontGen);
// compute the string just one time
_FontManager->computeString (ucstr, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, _TempString, _Keep800x600Ratio);
// draw shaded
if (_Shaded)
{
CRGBA bkup = _TempString.Color;
_TempString.Color = _ShadeColor;
_TempString.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8);
if (_ShadeOutline)
{
float rext = _ShadeExtent * 0.7071f;
_TempString.render2D(*_Driver,x+rext,z-rext,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x-rext,z-rext,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x-rext,z+rext,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x+rext,z+rext,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x+_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x-_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ);
}
else
{
_TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ);
}
_TempString.Color = bkup;
}
// draw
_TempString.render2D(*_Driver, x, z, _HotSpot, _ScaleX, _ScaleZ);
}
/// Directly print a string
void printfAt (float x, float z, const char * format, ...)
{
nlassert(_FontGen);
// compute the string just one time
char *str;
NLMISC_CONVERT_VARGS (str, format, NLMISC::MaxCStringSize);
_FontManager->computeString (str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, _TempString, _Keep800x600Ratio);
// draw shaded
if (_Shaded)
{
CRGBA bkup = _TempString.Color;
_TempString.Color = _ShadeColor;
_TempString.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8);
if (_ShadeOutline)
{
float rext = _ShadeExtent * 0.7071f;
_TempString.render2D(*_Driver,x+rext,z-rext,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x-rext,z-rext,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x-rext,z+rext,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x+rext,z+rext,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x+_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x-_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ);
_TempString.render2D(*_Driver,x,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ);
}
else
{
_TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ);
}
_TempString.Color = bkup;
}
// draw
_TempString.render2D(*_Driver, x, z, _HotSpot, _ScaleX, _ScaleZ);
}
/// Get computed string from index
CComputedString& operator[](uint32 index)
{
nlassert (index < _CacheStrings.size());
return _CacheStrings[index];
}
CComputedString* getComputedString (uint32 index)
{
if (index < _CacheStrings.size())
return &_CacheStrings[index];
else
return NULL;
}
/**
* Compute a string as primitive blocks using the
* font manager's method computeString
* \param a string
* \param the computed string
*/
void computeString (const std::string& s, CComputedString& output)
{
_FontManager->computeString (s, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, output, _Keep800x600Ratio);
}
/**
* Compute a ucstring as primitive blocks using the
* font manager's method computeString
* \param an ucstring
* \param the computed string
*/
void computeString (const ucstring& s, CComputedString& output)
{
_FontManager->computeString (s, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, output, _Keep800x600Ratio);
}
void computeStringInfo (const ucstring& s, CComputedString& output)
{
_FontManager->computeStringInfo (s, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, output, _Keep800x600Ratio);
}
/// Debug : write to the disk the texture cache
void dumpCache (const char *filename)
{
_FontManager->dumpCache (filename);
}
/// In single line mode you can assign several color to letters
void setLetterColors(CLetterColors * letterColors, uint index);
bool isSameLetterColors(CLetterColors * letterColors, uint index);
private:
/// Driver
IDriver *_Driver;
/// Font manager
NL3D::CFontManager *_FontManager;
/// Font generator
NL3D::CFontGenerator * _FontGen;
/**
* Text Style properties
*/
/// Font size;
uint32 _FontSize;
bool _Embolden;
bool _Oblique;
/// Current text color
NLMISC::CRGBA _Color;
/// Hotspot
CComputedString::THotSpot _HotSpot;
/// X scale
float _ScaleX;
/// Z scale
float _ScaleZ;
/// true if text is shaded
bool _Shaded;
/// true if shade appears as an outline
bool _ShadeOutline;
/// shade's extent (shadow size)
float _ShadeExtent;
/// Shade color (default is black)
NLMISC::CRGBA _ShadeColor;
/// resize the font to keep the same aspect ratio than in 800x600
bool _Keep800x600Ratio;
/**
* Strings Caches
*/
/// Cache to manipulate strings with indexes
std::vector<CComputedString> _CacheStrings;
std::vector<uint32> _CacheFreePlaces;
uint32 _CacheNbFreePlaces;
/// Cache for for printAt() and printfAt().
/// This prevents from creating VBdrvinfos each time they are called (N*each frame!!).
CComputedString _TempString;
};
} // NL3D
#endif // NL_TEXT_CONTEXT_H
/* End of text_context.h */