#include "RConfigure.h"
#include "TGLFontManager.h"
#include "TSystem.h"
#include "TEnv.h"
#include "TObjString.h"
#include "TGLUtil.h"
#include "TGLIncludes.h"
#ifndef BUILTIN_FTGL
# include <FTGL/ftgl.h>
#else
# include "FTFont.h"
# include "FTGLExtrdFont.h"
# include "FTGLOutlineFont.h"
# include "FTGLPolygonFont.h"
# include "FTGLTextureFont.h"
# include "FTGLPixmapFont.h"
# include "FTGLBitmapFont.h"
#endif
ClassImp(TGLFont);
TGLFont::TGLFont():
fFont(0), fManager(0), fDepth(0),
fSize(0), fFile(0), fMode(kUndef),
fTrashCount(0)
{
}
TGLFont::TGLFont(Int_t size, Int_t font, EMode mode, FTFont* f, TGLFontManager* mng):
fFont(f), fManager(mng), fDepth(0),
fSize(size), fFile(font), fMode(mode),
fTrashCount(0)
{
}
TGLFont::TGLFont(const TGLFont &o):
fFont(0), fManager(0), fDepth(0), fTrashCount(0)
{
fFont = (FTFont*)o.GetFont();
fSize = o.fSize;
fFile = o.fFile;
fMode = o.fMode;
fTrashCount = o.fTrashCount;
}
TGLFont::~TGLFont()
{
if (fManager) fManager->ReleaseFont(*this);
}
void TGLFont::CopyAttributes(const TGLFont &o)
{
SetFont(o.fFont);
SetManager(o.fManager);
SetDepth(o.fDepth);
fSize = o.fSize;
fFile = o.fFile;
fMode = o.fMode;
fTrashCount = o.fTrashCount;
}
void TGLFont::BBox(const char* txt, Float_t& llx, Float_t& lly, Float_t& llz, Float_t& urx, Float_t& ury, Float_t& urz) const
{
const_cast<FTFont*>(fFont)->BBox(txt, llx, lly, llz, urx, ury, urz);
}
void TGLFont::Render(const char* txt) const
{
Bool_t scaleDepth = (fMode == kExtrude && fDepth != 1.0f);
if (scaleDepth) {
glPushMatrix();
glTranslatef(0.0f, 0.0f, 0.5f*fDepth * 0.2f*fSize);
glScalef(1.0f, 1.0f, fDepth);
}
const_cast<FTFont*>(fFont)->Render(txt);
if (scaleDepth) {
glPopMatrix();
}
}
void TGLFont::RenderBitmap(const char* txt, Float_t xs, Float_t ys, Float_t zs, ETextAlign_e align) const
{
glPushMatrix();
glTranslatef(xs, ys, zs);
Float_t llx, lly, llz, urx, ury, urz;
BBox(txt, llx, lly, llz, urx, ury, urz);
if (txt[0] == '-')
urx += (urx-llx)/strlen(txt);
Float_t x=0, y=0;
switch (align)
{
case kCenterUp:
x = -urx*0.5; y = -ury;
break;
case kCenterDown:
x = -urx*0.5; y = 0;
break;
case kRight:
x = -urx; y =(lly -ury)*0.5;
break;
case kLeft:
x = 0; y = -ury*0.5;
break;
default:
break;
};
glRasterPos2i(0, 0);
glBitmap(0, 0, 0, 0, x, y, 0);
Render(txt);
glPopMatrix();
}
void TGLFont::PreRender(Bool_t autoLight, Bool_t lightOn) const
{
switch (fMode)
{
case kBitmap:
case kPixmap:
glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
glEnable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glAlphaFunc(GL_GEQUAL, 0.0625);
break;
case kTexture:
glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE);
glEnable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glAlphaFunc(GL_GEQUAL, 0.0625);
break;
case kOutline:
case kPolygon:
case kExtrude:
glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT);
glEnable(GL_NORMALIZE);
glDisable(GL_CULL_FACE);
break;
default:
Warning("TGLFont::PreRender", "Font mode undefined.");
glPushAttrib(GL_LIGHTING_BIT);
break;
}
if ((autoLight && fMode > TGLFont::kOutline) || (!autoLight && lightOn))
glEnable(GL_LIGHTING);
else
glDisable(GL_LIGHTING);
}
void TGLFont::PostRender() const
{
glPopAttrib();
}
ClassImp(TGLFontManager);
TObjArray TGLFontManager::fgFontFileArray;
TGLFontManager::FontSizeVec_t TGLFontManager::fgFontSizeArray;
Bool_t TGLFontManager::fgStaticInitDone = kFALSE;
TGLFontManager::~TGLFontManager()
{
FontMap_i it = fFontMap.begin();
while (it != fFontMap.end()) {
delete it->first.GetFont();
it++;
}
fFontMap.clear();
}
void TGLFontManager::RegisterFont(Int_t size, Int_t fileID, TGLFont::EMode mode, TGLFont &out)
{
if (fgStaticInitDone == kFALSE) InitStatics();
FontMap_i it = fFontMap.find(TGLFont(size, fileID, mode));
if (it == fFontMap.end())
{
TString ttpath;
# ifdef TTFFONTDIR
ttpath = gEnv->GetValue("Root.TTGLFontPath", TTFFONTDIR );
# else
ttpath = gEnv->GetValue("Root.TTGLFontPath", "$(ROOTSYS)/fonts");
# endif
TObjString* name = (TObjString*)fgFontFileArray[fileID];
const char *file = gSystem->Which(ttpath.Data(), Form("%s.ttf", name->GetString().Data()));
FTFont* ftfont = 0;
switch (mode)
{
case TGLFont::kBitmap:
ftfont = new FTGLBitmapFont(file);
break;
case TGLFont::kPixmap:
ftfont = new FTGLPixmapFont(file);
break;
case TGLFont::kOutline:
ftfont = new FTGLOutlineFont(file);
break;
case TGLFont::kPolygon:
ftfont = new FTGLPolygonFont(file);
break;
case TGLFont::kExtrude:
ftfont = new FTGLExtrdFont(file);
ftfont->Depth(0.2*size);
break;
case TGLFont::kTexture:
ftfont = new FTGLTextureFont(file);
break;
default:
Error("TGLFontManager::GetFont", "invalid FTGL type");
break;
}
delete [] file;
ftfont->FaceSize(size);
const TGLFont &mf = fFontMap.insert(std::make_pair(TGLFont(size, fileID, mode, ftfont, 0), 1)).first->first;
out.CopyAttributes(mf);
}
else
{
if (it->first.GetTrashCount() > 0) {
fFontTrash.remove(&(it->first));
it->first.SetTrashCount(0);
}
++(it->second);
out.CopyAttributes(it->first);
}
out.SetManager(this);
}
void TGLFontManager::RegisterFont(Int_t size, const Text_t* name, TGLFont::EMode mode, TGLFont &out)
{
TObjArray* farr = GetFontFileArray();
TIter next(farr);
TObjString* os;
Int_t cnt = 0;
while ((os = (TObjString*) next()) != 0)
{
if (os->GetString() == name)
break;
cnt++;
}
if (cnt < farr->GetSize())
RegisterFont(size, cnt, mode, out);
else
Error("TGLFontManager::GetFont", "unknown font name %s", name);
}
void TGLFontManager::ReleaseFont(TGLFont& font)
{
FontMap_i it = fFontMap.find(font);
if (it != fFontMap.end())
{
--(it->second);
if (it->second == 0)
{
assert(it->first.GetTrashCount() == 0);
it->first.IncTrashCount();
fFontTrash.push_back(&it->first);
}
}
}
TObjArray* TGLFontManager::GetFontFileArray()
{
if (fgStaticInitDone == kFALSE) InitStatics();
return &fgFontFileArray;
}
TGLFontManager::FontSizeVec_t* TGLFontManager::GetFontSizeArray()
{
if (fgStaticInitDone == kFALSE) InitStatics();
return &fgFontSizeArray;
}
Int_t TGLFontManager::GetFontSize(Float_t ds, Int_t min, Int_t max)
{
if (fgStaticInitDone == kFALSE) InitStatics();
Int_t nums = fgFontSizeArray.size();
Int_t i = 0;
while (i<nums)
{
if (ds<=fgFontSizeArray[i]) break;
i++;
}
Int_t fs = fgFontSizeArray[i];
if (min>0 && fs<min)
fs = min;
if (max>0 && fs>max)
fs = max;
return fs;
}
const char* TGLFontManager::GetFontNameFromId(Int_t id)
{
static const char *fonttable[] = {
"arialbd",
"timesi",
"timesbd",
"timesbi",
"arial",
"ariali",
"arialbd",
"arialbi",
"cour",
"couri",
"courbd",
"courbi",
"symbol",
"times",
"wingding"
};
return fonttable[id / 10];
}
void TGLFontManager::InitStatics()
{
const char *ttpath = gEnv->GetValue("Root.TTFontPath",
# ifdef TTFFONTDIR
TTFFONTDIR);
# else
"$(ROOTSYS)/fonts");
# endif
void *dir = gSystem->OpenDirectory(ttpath);
const char* name = 0;
TString s;
while ((name = gSystem->GetDirEntry(dir))) {
s = name;
if (s.EndsWith(".ttf")) {
s.Resize(s.Sizeof() -5);
fgFontFileArray.Add(new TObjString(s.Data()));
}
}
fgFontFileArray.Sort();
gSystem->FreeDirectory(dir);
for (Int_t i = 8; i <= 20; i+=2)
fgFontSizeArray.push_back(i);
for (Int_t i = 24; i <= 64; i+=4)
fgFontSizeArray.push_back(i);
for (Int_t i = 72; i <= 120; i+=8)
fgFontSizeArray.push_back(i);
fgStaticInitDone = kTRUE;
}
void TGLFontManager::ClearFontTrash()
{
FontList_i it = fFontTrash.begin();
while (it != fFontTrash.end())
{
if ((*it)->IncTrashCount() > 10000)
{
FontMap_i mi = fFontMap.find(**it);
assert(mi != fFontMap.end());
fFontMap.erase(mi);
delete (*it)->GetFont();
FontList_i li = it++;
fFontTrash.erase(li);
}
else
{
++it;
}
}
}
Last change: Wed Dec 10 08:21:33 2008
Last generated: 2008-12-10 08:21
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.