TGLFontManager.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLFontManager.cxx 35051 2010-08-27 15:19:55Z matevz $
00002 // Author: Alja Mrak-Tadel 2008
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "Riostream.h"
00013 #include "RConfigure.h"
00014 #include "TGLFontManager.h"
00015 
00016 
00017 #include "TVirtualX.h"
00018 #include "TMath.h"
00019 #include "TSystem.h"
00020 #include "TEnv.h"
00021 #include "TObjString.h"
00022 #include "TGLUtil.h"
00023 #include "TGLIncludes.h"
00024 
00025 // Direct inclussion of FTGL headers is deprecated in ftgl-2.1.3 while
00026 // ftgl-2.1.2 shipped with ROOT requires manual inclusion.
00027 #ifndef BUILTIN_FTGL
00028 # include <FTGL/ftgl.h>
00029 #else
00030 # include "FTFont.h"
00031 # include "FTGLExtrdFont.h"
00032 # include "FTGLOutlineFont.h"
00033 # include "FTGLPolygonFont.h"
00034 # include "FTGLTextureFont.h"
00035 # include "FTGLPixmapFont.h"
00036 # include "FTGLBitmapFont.h"
00037 #endif
00038 
00039 
00040 //______________________________________________________________________________
00041 // TGLFont
00042 //
00043 // A wrapper class for FTFont.
00044 // Holds pointer to FTFont object and its description: face size, font file
00045 // and class ID. It  wraps Render and BBox functions.
00046 //
00047 
00048 ClassImp(TGLFont);
00049 
00050 //______________________________________________________________________________
00051 TGLFont::TGLFont():
00052    fFont(0), fManager(0), fDepth(0),
00053    fSize(0), fFile(0), fMode(kUndef),
00054    fTrashCount(0)
00055 {
00056    // Constructor.
00057 }
00058 
00059 //______________________________________________________________________________
00060 TGLFont::TGLFont(Int_t size, Int_t font, EMode mode, FTFont* f, TGLFontManager* mng):
00061    fFont(f), fManager(mng), fDepth(0),
00062    fSize(size), fFile(font), fMode(mode),
00063    fTrashCount(0)
00064 {
00065    // Constructor.
00066 }
00067 
00068 //______________________________________________________________________________
00069 TGLFont::TGLFont(const TGLFont &o):
00070    fFont(0), fManager(0), fDepth(0), fTrashCount(0)
00071 {
00072    // Assignment operator.
00073    fFont = (FTFont*)o.GetFont();
00074 
00075    fSize  = o.fSize;
00076    fFile  = o.fFile;
00077    fMode  = o.fMode;
00078 
00079    fTrashCount = o.fTrashCount;
00080 }
00081 
00082 //______________________________________________________________________________
00083 TGLFont::~TGLFont()
00084 {
00085    //Destructor
00086 
00087    if (fManager) fManager->ReleaseFont(*this);
00088 }
00089 
00090 //______________________________________________________________________________
00091 void TGLFont::CopyAttributes(const TGLFont &o)
00092 {
00093    // Assignment operator.
00094    SetFont(o.fFont);
00095    SetManager(o.fManager);
00096 
00097    SetDepth(o.fDepth);
00098 
00099    fSize  = o.fSize;
00100    fFile  = o.fFile;
00101    fMode  = o.fMode;
00102 
00103    fTrashCount = o.fTrashCount;
00104 }
00105 
00106 
00107 /******************************************************************************/
00108 
00109 //______________________________________________________________________________
00110 Float_t TGLFont::GetAscent() const
00111 {
00112    // Get font's ascent.
00113 
00114    return fFont->Ascender();
00115 }
00116 
00117 //______________________________________________________________________________
00118 Float_t TGLFont::GetDescent() const
00119 {
00120    // Get font's descent. The returned value is positive.
00121 
00122    return -fFont->Descender();
00123 }
00124 
00125 //______________________________________________________________________________
00126 Float_t TGLFont::GetLineHeight() const
00127 {
00128    // Get font's line-height.
00129 
00130    return fFont->LineHeight();
00131 }
00132 
00133 //______________________________________________________________________________
00134 void TGLFont::MeasureBaseLineParams(Float_t& ascent, Float_t& descent, Float_t& line_height,
00135                                     const char* txt) const
00136 {
00137    // Measure font's base-line parameters from the passed text.
00138    // Note that the measured parameters are not the same as the ones
00139    // returned by get-functions - those were set by the font designer.
00140 
00141    Float_t dum, lly, ury;
00142    const_cast<FTFont*>(fFont)->BBox(txt, dum, lly, dum, dum, ury, dum);
00143    ascent      =  ury;
00144    descent     = -lly;
00145    line_height =  ury - lly;
00146 }
00147 
00148 //______________________________________________________________________________
00149 void TGLFont::BBox(const char* txt,
00150                    Float_t& llx, Float_t& lly, Float_t& llz,
00151                    Float_t& urx, Float_t& ury, Float_t& urz) const
00152 {
00153    // Get bounding box.
00154 
00155    // FTGL is not const correct.
00156    const_cast<FTFont*>(fFont)->BBox(txt, llx, lly, llz, urx, ury, urz);
00157 }
00158 
00159 //______________________________________________________________________________
00160 void TGLFont::Render(const char* txt, Double_t x, Double_t y, Double_t angle, Double_t /*mgn*/) const
00161 {
00162    //mgn is simply ignored, because ROOT's TVirtualX TGX11 are complete mess with
00163    //painting attributes.
00164    glPushMatrix();
00165    //glLoadIdentity();
00166    
00167    // FTGL is not const correct.
00168    Float_t llx = 0.f, lly = 0.f, llz = 0.f, urx = 0.f, ury = 0.f, urz = 0.f;
00169    BBox(txt, llx, lly, llz, urx, ury, urz);
00170    
00171    /*
00172     V\H   | left | center | right
00173    _______________________________
00174    bottom |  7   |   8    |   9
00175    _______________________________
00176    center |  4   |   5    |   6
00177    _______________________________
00178     top   |  1   |   2    |   3
00179    */
00180    const Double_t dx = urx - llx, dy = ury - lly;
00181    Double_t xc = 0., yc = 0.;
00182    const UInt_t align = gVirtualX->GetTextAlign();
00183 
00184    switch (align) {
00185    case 7:
00186       xc += 0.5 * dx;
00187       yc += 0.5 * dy;
00188       break;
00189    case 8:
00190       yc += 0.5 * dy;
00191       break;
00192    case 9:
00193       xc -= 0.5 * dx;
00194       yc += 0.5 * dy;
00195       break;
00196    case 4:
00197       xc += 0.5 * dx;
00198       break;
00199    case 5:
00200       break;
00201    case 6:
00202       xc = -0.5 * dx;
00203       break;
00204    case 1:
00205       xc += 0.5 * dx;
00206       yc -= 0.5 * dy;
00207       break;
00208    case 2:
00209       yc -= 0.5 * dy;
00210       break;
00211    case 3:
00212       xc -= 0.5 * dx;
00213       yc -= 0.5 * dy;
00214       break;
00215    }
00216    
00217    glTranslated(x, y, 0.);
00218    glRotated(angle, 0., 0., 1.);
00219    glTranslated(xc, yc, 0.);
00220    glTranslated(-0.5 * dx, -0.5 * dy, 0.);
00221    //glScaled(mgn, mgn, 1.);
00222       
00223    const_cast<FTFont*>(fFont)->Render(txt);
00224    
00225    glPopMatrix();
00226    
00227    
00228 }
00229 
00230 //______________________________________________________________________________
00231 void TGLFont::Render(const TString &txt) const
00232 {
00233    // Render text.
00234 
00235    Bool_t scaleDepth = (fMode == kExtrude && fDepth != 1.0f);
00236 
00237    if (scaleDepth) {
00238       glPushMatrix();
00239       // !!! 0.2*fSize is hard-coded in TGLFontManager::GetFont(), too.
00240       glTranslatef(0.0f, 0.0f, 0.5f*fDepth * 0.2f*fSize);
00241       glScalef(1.0f, 1.0f, fDepth);
00242    }
00243 
00244    // FTGL is not const correct.
00245    const_cast<FTFont*>(fFont)->Render(txt);
00246 
00247    if (scaleDepth) {
00248       glPopMatrix();
00249    }
00250 }
00251 
00252 //______________________________________________________________________________
00253 void  TGLFont:: Render(const TString &txt, Float_t x, Float_t y, Float_t z,
00254              ETextAlignH_e alignH, ETextAlignV_e alignV) const
00255 {
00256    // Render text with given alignmentrepl and at given position.
00257 
00258    glPushMatrix();
00259 
00260    glTranslatef(x, y, z);
00261 
00262    x=0, y=0;
00263    Float_t llx, lly, llz, urx, ury, urz;
00264    BBox(txt, llx, lly, llz, urx, ury, urz);
00265 
00266    switch (alignH)
00267    {
00268       case TGLFont::kRight:
00269          x = -urx;
00270          break;
00271 
00272       case  TGLFont::kCenterH:
00273          x = -urx*0.5;
00274          break;
00275       default:
00276          break;
00277    };
00278 
00279    switch (alignV)
00280    {
00281       case TGLFont::kBottom:
00282          y = -ury;
00283          break;
00284       case  TGLFont::kCenterV:
00285          y = -ury*0.5;
00286          break;
00287       default:
00288          break;
00289    };
00290 
00291    if (fMode == TGLFont::kPixmap || fMode ==  TGLFont::kBitmap)
00292    {
00293       glRasterPos2i(0, 0);
00294       glBitmap(0, 0, 0, 0, x, y, 0);
00295    }
00296    else
00297    {
00298       glTranslatef(x, y, 0);
00299    }
00300    Render(txt);
00301    glPopMatrix();
00302 }
00303 
00304 //______________________________________________________________________________
00305 void TGLFont::PreRender(Bool_t autoLight, Bool_t lightOn) const
00306 {
00307    // Set-up GL state before FTFont rendering.
00308 
00309    switch (fMode)
00310    {
00311       case kBitmap:
00312       case kPixmap:
00313          glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
00314          glEnable(GL_ALPHA_TEST);
00315          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00316          glAlphaFunc(GL_GEQUAL, 0.0625);
00317          break;
00318       case kTexture:
00319          glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT);
00320          glEnable(GL_TEXTURE_2D);
00321          glDisable(GL_CULL_FACE);
00322          glEnable(GL_ALPHA_TEST);
00323          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00324          glAlphaFunc(GL_GEQUAL, 0.0625);
00325          break;
00326       case kOutline:
00327       case kPolygon:
00328       case kExtrude:
00329          glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT);
00330          glEnable(GL_NORMALIZE);
00331          glDisable(GL_CULL_FACE);
00332          break;
00333       default:
00334          Warning("TGLFont::PreRender", "Font mode undefined.");
00335          glPushAttrib(GL_LIGHTING_BIT);
00336          break;
00337    }
00338 
00339    if ((autoLight && fMode > TGLFont::kOutline) || (!autoLight && lightOn))
00340       glEnable(GL_LIGHTING);
00341    else
00342       glDisable(GL_LIGHTING);
00343 }
00344 
00345 //______________________________________________________________________________
00346 void TGLFont::PostRender() const
00347 {
00348    // Reset GL state after FTFont rendering.
00349 
00350    glPopAttrib();
00351 }
00352 
00353 
00354 //______________________________________________________________________________
00355 //
00356 // A FreeType GL font manager.
00357 //
00358 // Each GL rendering context has an instance of FTGLManager.
00359 // This enables FTGL fonts to be shared same way as textures and display lists.
00360 
00361 ClassImp(TGLFontManager);
00362 
00363 TObjArray   TGLFontManager::fgFontFileArray;
00364 TGLFontManager::FontSizeVec_t TGLFontManager::fgFontSizeArray;
00365 Bool_t  TGLFontManager::fgStaticInitDone = kFALSE;
00366 
00367 //______________________________________________________________________________
00368 TGLFontManager::~TGLFontManager()
00369 {
00370    // Destructor.
00371 
00372    FontMap_i it = fFontMap.begin();
00373    while (it != fFontMap.end()) {
00374       delete it->first.GetFont();
00375       it++;
00376    }
00377    fFontMap.clear();
00378 }
00379 
00380 //______________________________________________________________________________
00381 void TGLFontManager::RegisterFont(Int_t sizeIn, Int_t fileID, TGLFont::EMode mode, TGLFont &out)
00382 {
00383    // Provide font with given size, file and FTGL class.
00384 
00385    if (fgStaticInitDone == kFALSE) InitStatics();
00386 
00387    Int_t  size = GetFontSize(sizeIn);
00388    if (mode == out.GetMode() && fileID == out.GetFile() && size == out.GetSize())
00389       return;
00390 
00391    FontMap_i it = fFontMap.find(TGLFont(size, fileID, mode));
00392    if (it == fFontMap.end())
00393    {
00394       TString ttpath, file;
00395 # ifdef TTFFONTDIR
00396       ttpath = gEnv->GetValue("Root.TTGLFontPath", TTFFONTDIR );
00397 # else
00398       ttpath = gEnv->GetValue("Root.TTGLFontPath", "$(ROOTSYS)/fonts");
00399 # endif
00400       {
00401          char *fp = gSystem->Which(ttpath, ((TObjString*)fgFontFileArray[fileID])->String() + ".ttf");
00402          file = fp;
00403          delete [] fp;
00404       }
00405 
00406       FTFont* ftfont = 0;
00407       switch (mode)
00408       {
00409          case TGLFont::kBitmap:
00410             ftfont = new FTGLBitmapFont(file);
00411             break;
00412          case TGLFont::kPixmap:
00413             ftfont = new FTGLPixmapFont(file);
00414             break;
00415          case TGLFont::kOutline:
00416             ftfont = new FTGLOutlineFont(file);
00417             break;
00418          case TGLFont::kPolygon:
00419             ftfont = new FTGLPolygonFont(file);
00420             break;
00421          case TGLFont::kExtrude:
00422             ftfont = new FTGLExtrdFont(file);
00423             ftfont->Depth(0.2*size);
00424             break;
00425          case TGLFont::kTexture:
00426             ftfont = new FTGLTextureFont(file);
00427             break;
00428          default:
00429             Error("TGLFontManager::GetFont", "invalid FTGL type");
00430             return;
00431             break;
00432       }
00433       ftfont->FaceSize(size);
00434       const TGLFont &mf = fFontMap.insert(std::make_pair(TGLFont(size, fileID, mode, ftfont, 0), 1)).first->first;
00435       out.CopyAttributes(mf);
00436    }
00437    else
00438    {
00439       if (it->first.GetTrashCount() > 0) {
00440          fFontTrash.remove(&(it->first));
00441          it->first.SetTrashCount(0);
00442       }
00443       ++(it->second);
00444       out.CopyAttributes(it->first);
00445    }
00446    out.SetManager(this);
00447 }
00448 
00449 //______________________________________________________________________________
00450 void TGLFontManager::RegisterFont(Int_t size, const char* name, TGLFont::EMode mode, TGLFont &out)
00451 {
00452    // Get mapping from ttf id to font names. Table taken from TTF.cxx.
00453 
00454    TObjArray* farr = GetFontFileArray();
00455    TIter next(farr);
00456    TObjString* os;
00457    Int_t cnt = 0;
00458    while ((os = (TObjString*) next()) != 0)
00459    {
00460       if (os->GetString() == name)
00461          break;
00462       cnt++;
00463    }
00464 
00465    if (cnt < farr->GetSize())
00466       RegisterFont(size, cnt, mode, out);
00467    else
00468       Error("TGLFontManager::GetFont", "unknown font name %s", name);
00469 }
00470 
00471 //______________________________________________________________________________
00472 void TGLFontManager::ReleaseFont(TGLFont& font)
00473 {
00474    // Release font with given attributes. Returns false if font has
00475    // not been found in the managers font set.
00476 
00477    FontMap_i it = fFontMap.find(font);
00478 
00479    if (it != fFontMap.end())
00480    {
00481       --(it->second);
00482       if (it->second == 0)
00483       {
00484          assert(it->first.GetTrashCount() == 0);
00485          it->first.IncTrashCount();
00486          fFontTrash.push_back(&it->first);
00487       }
00488    }
00489 }
00490 
00491 //______________________________________________________________________________
00492 TObjArray* TGLFontManager::GetFontFileArray()
00493 {
00494    // Get id to file name map.
00495 
00496    if (fgStaticInitDone == kFALSE) InitStatics();
00497    return &fgFontFileArray;
00498 }
00499 
00500 //______________________________________________________________________________
00501 TGLFontManager::FontSizeVec_t* TGLFontManager::GetFontSizeArray()
00502 {
00503    // Get valid font size vector.
00504 
00505    if (fgStaticInitDone == kFALSE) InitStatics();
00506    return &fgFontSizeArray;
00507 }
00508 
00509 //______________________________________________________________________________
00510 Int_t TGLFontManager::GetFontSize(Int_t ds)
00511 {
00512    // Get availabe font size.
00513 
00514    if (fgStaticInitDone == kFALSE) InitStatics();
00515 
00516    Int_t idx = TMath::BinarySearch(fgFontSizeArray.size(), &fgFontSizeArray[0],
00517                                    TMath::CeilNint(ds));
00518    if (idx < 0) idx = 0;
00519    return fgFontSizeArray[idx];
00520 }
00521 
00522 //______________________________________________________________________________
00523 Int_t TGLFontManager::GetFontSize(Int_t ds, Int_t min, Int_t max)
00524 {
00525    // Get availabe font size.
00526 
00527    if (ds < min) ds = min;
00528    if (ds > max) ds = max;
00529    return GetFontSize(ds);
00530 }
00531 
00532 //______________________________________________________________________________
00533 const char* TGLFontManager::GetFontNameFromId(Int_t id)
00534 {
00535    // Get font name from TAttAxis font id.
00536 
00537    if (fgStaticInitDone == kFALSE) InitStatics();
00538 
00539    TObjString* os = (TObjString*)fgFontFileArray[id / 10];
00540    return os->GetString().Data();
00541 }
00542 
00543 //______________________________________________________________________________
00544 void TGLFontManager::InitStatics()
00545 {
00546    // Create a list of available font files and allowed font sizes.
00547 
00548    fgFontFileArray.Add(new TObjString("arialbd"));  //   0
00549 
00550    fgFontFileArray.Add(new TObjString("timesi"));   //  10
00551    fgFontFileArray.Add(new TObjString("timesbd"));  //  20
00552    fgFontFileArray.Add(new TObjString("timesbi"));  //  30
00553 
00554    fgFontFileArray.Add(new TObjString("arial"));    //  40
00555    fgFontFileArray.Add(new TObjString("ariali"));   //  50
00556    fgFontFileArray.Add(new TObjString("arialbd"));  //  60
00557    fgFontFileArray.Add(new TObjString("arialbi"));  //  70
00558 
00559    fgFontFileArray.Add(new TObjString("cour"));     //  80
00560    fgFontFileArray.Add(new TObjString("couri"));    //  90
00561    fgFontFileArray.Add(new TObjString("courbd"));   // 100
00562    fgFontFileArray.Add(new TObjString("courbi"));   // 110
00563 
00564    fgFontFileArray.Add(new TObjString("symbol"));   // 120
00565    fgFontFileArray.Add(new TObjString("times"));    // 130
00566    fgFontFileArray.Add(new TObjString("wingding")); // 140
00567 
00568 
00569    // font sizes
00570    for (Int_t i = 8; i <= 20; i+=2)
00571       fgFontSizeArray.push_back(i);
00572    for (Int_t i = 24; i <= 64; i+=4)
00573       fgFontSizeArray.push_back(i);
00574    for (Int_t i = 72; i <= 128; i+=8)
00575       fgFontSizeArray.push_back(i);
00576 
00577    fgStaticInitDone = kTRUE;
00578 }
00579 
00580 //______________________________________________________________________________
00581 void TGLFontManager::ClearFontTrash()
00582 {
00583    // Delete FTFFont objects registered for destruction.
00584 
00585    FontList_i it = fFontTrash.begin();
00586    while (it != fFontTrash.end())
00587    {
00588       if ((*it)->IncTrashCount() > 10000)
00589       {
00590          FontMap_i mi = fFontMap.find(**it);
00591          assert(mi != fFontMap.end());
00592          fFontMap.erase(mi);
00593          delete (*it)->GetFont();
00594 
00595          FontList_i li = it++;
00596          fFontTrash.erase(li);
00597       }
00598       else
00599       {
00600          ++it;
00601       }
00602    }
00603 }

Generated on Tue Jul 5 14:18:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1