00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00026
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
00042
00043
00044
00045
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
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
00066 }
00067
00068
00069 TGLFont::TGLFont(const TGLFont &o):
00070 fFont(0), fManager(0), fDepth(0), fTrashCount(0)
00071 {
00072
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
00086
00087 if (fManager) fManager->ReleaseFont(*this);
00088 }
00089
00090
00091 void TGLFont::CopyAttributes(const TGLFont &o)
00092 {
00093
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
00113
00114 return fFont->Ascender();
00115 }
00116
00117
00118 Float_t TGLFont::GetDescent() const
00119 {
00120
00121
00122 return -fFont->Descender();
00123 }
00124
00125
00126 Float_t TGLFont::GetLineHeight() const
00127 {
00128
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
00138
00139
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
00154
00155
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 ) const
00161 {
00162
00163
00164 glPushMatrix();
00165
00166
00167
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
00173
00174
00175
00176
00177
00178
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
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
00234
00235 Bool_t scaleDepth = (fMode == kExtrude && fDepth != 1.0f);
00236
00237 if (scaleDepth) {
00238 glPushMatrix();
00239
00240 glTranslatef(0.0f, 0.0f, 0.5f*fDepth * 0.2f*fSize);
00241 glScalef(1.0f, 1.0f, fDepth);
00242 }
00243
00244
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
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
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
00349
00350 glPopAttrib();
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
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
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
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
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
00475
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
00495
00496 if (fgStaticInitDone == kFALSE) InitStatics();
00497 return &fgFontFileArray;
00498 }
00499
00500
00501 TGLFontManager::FontSizeVec_t* TGLFontManager::GetFontSizeArray()
00502 {
00503
00504
00505 if (fgStaticInitDone == kFALSE) InitStatics();
00506 return &fgFontSizeArray;
00507 }
00508
00509
00510 Int_t TGLFontManager::GetFontSize(Int_t ds)
00511 {
00512
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
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
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
00547
00548 fgFontFileArray.Add(new TObjString("arialbd"));
00549
00550 fgFontFileArray.Add(new TObjString("timesi"));
00551 fgFontFileArray.Add(new TObjString("timesbd"));
00552 fgFontFileArray.Add(new TObjString("timesbi"));
00553
00554 fgFontFileArray.Add(new TObjString("arial"));
00555 fgFontFileArray.Add(new TObjString("ariali"));
00556 fgFontFileArray.Add(new TObjString("arialbd"));
00557 fgFontFileArray.Add(new TObjString("arialbi"));
00558
00559 fgFontFileArray.Add(new TObjString("cour"));
00560 fgFontFileArray.Add(new TObjString("couri"));
00561 fgFontFileArray.Add(new TObjString("courbd"));
00562 fgFontFileArray.Add(new TObjString("courbi"));
00563
00564 fgFontFileArray.Add(new TObjString("symbol"));
00565 fgFontFileArray.Add(new TObjString("times"));
00566 fgFontFileArray.Add(new TObjString("wingding"));
00567
00568
00569
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
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 }