ROOT logo
// @(#)root/graf:$Id$
// Author: Olivier Couet     01/10/02

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TTF                                                                  //
//                                                                      //
// Interface to the freetype 2 library.                                 //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

// RConfigure.h is needed for TTFFONTDIR
#include "RConfigure.h"

#include "TTF.h"
#include "TSystem.h"
#include "TEnv.h"
#include "TMath.h"
#include "TError.h"


// to scale fonts to the same size as the old TT version
const Float_t kScale = 0.93376068;

TTF gCleanupTTF; // Allows to call "Cleanup" at the end of the session

Bool_t      TTF::fgInit           = kFALSE;
Bool_t      TTF::fgSmoothing      = kTRUE;
Bool_t      TTF::fgKerning        = kTRUE;
Bool_t      TTF::fgHinting        = kFALSE;
Int_t       TTF::fgTBlankW        = 0;
Int_t       TTF::fgWidth          = 0;
Int_t       TTF::fgAscent         = 0;
Int_t       TTF::fgCurFontIdx     = -1;
Int_t       TTF::fgSymbItaFontIdx = -1;
Int_t       TTF::fgFontCount      = 0;
Int_t       TTF::fgNumGlyphs      = 0;
char       *TTF::fgFontName[kTTMaxFonts];
FT_Matrix  *TTF::fgRotMatrix;
FT_Library  TTF::fgLibrary;
FT_BBox     TTF::fgCBox;
FT_Face     TTF::fgFace[kTTMaxFonts];
FT_CharMap  TTF::fgCharMap[kTTMaxFonts];
TTGlyph     TTF::fgGlyphs[kMaxGlyphs];


ClassImp(TTF)

//______________________________________________________________________________
TTF::~TTF()
{
   // Cleanup TTF environment.

   Cleanup();
}

//______________________________________________________________________________
void TTF::Init()
{
   // Initialise the TrueType fonts interface.

   fgInit = kTRUE;

   // initialize FTF library
   if (FT_Init_FreeType(&fgLibrary)) {
      Error("TTF::Init", "error initializing FreeType");
      return;
   }

   // load default font (arialbd)
   SetTextFont(62);
}

//______________________________________________________________________________
void TTF::Cleanup()
{
   // Cleanup. Is called by the gCleanupTTF destructor.

   if (!fgInit) return;

   for (int i = 0; i < fgFontCount; i++) {
      delete [] fgFontName[i];
      FT_Done_Face(fgFace[i]);
   }
   if (fgRotMatrix) delete fgRotMatrix;
   FT_Done_FreeType(fgLibrary);

   fgInit = kFALSE;
}

//______________________________________________________________________________
Short_t TTF::CharToUnicode(UInt_t code)
{
   // Map char to unicode. Returns 0 in case no mapping exists.

   if (!fgCharMap[fgCurFontIdx]) {
      UShort_t i, platform, encoding;
      FT_CharMap  charmap;

      if (!fgFace[fgCurFontIdx]) return 0;
      Int_t n = fgFace[fgCurFontIdx]->num_charmaps;
      for (i = 0; i < n; i++) {
         if (!fgFace[fgCurFontIdx]) continue;
         charmap  = fgFace[fgCurFontIdx]->charmaps[i];
         platform = charmap->platform_id;
         encoding = charmap->encoding_id;
         if ((platform == 3 && encoding == 1) ||
             (platform == 0 && encoding == 0) ||
             (platform == 1 && encoding == 0 &&
              !strcmp(fgFontName[fgCurFontIdx], "wingding.ttf")) ||
             (platform == 1 && encoding == 0 &&
              !strcmp(fgFontName[fgCurFontIdx], "symbol.ttf")))
         {
            fgCharMap[fgCurFontIdx] = charmap;
            if (FT_Set_Charmap(fgFace[fgCurFontIdx], fgCharMap[fgCurFontIdx]))
                Error("TTF::CharToUnicode", "error in FT_Set_CharMap");
            return FT_Get_Char_Index(fgFace[fgCurFontIdx], (FT_ULong)code);
         }
      }
   }
   return FT_Get_Char_Index(fgFace[fgCurFontIdx], (FT_ULong)code);
}

//______________________________________________________________________________
void TTF::GetTextExtent(UInt_t &w, UInt_t &h, char *text)
{
   // Get width (w) and height (h) when text is horizontal.

   if (!fgInit) Init();

   SetRotationMatrix(0);
   PrepareString(text);
   LayoutGlyphs();
   Int_t Xoff = 0; if (fgCBox.xMin < 0) Xoff = -fgCBox.xMin;
   Int_t Yoff = 0; if (fgCBox.yMin < 0) Yoff = -fgCBox.yMin;
   w = fgCBox.xMax + Xoff + fgTBlankW;
   h = fgCBox.yMax + Yoff;
}

//______________________________________________________________________________
void TTF::GetTextAdvance(UInt_t &a, char *text)
{
   // Get advance (a) when text is horizontal.

   if (!fgInit) Init();

   SetRotationMatrix(0);
   PrepareString(text);
   LayoutGlyphs();
   a = GetWidth()>>6;
}

//______________________________________________________________________________
void TTF::GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *text)
{
   // Get width (w) and height (h) when text is horizontal.

   if (!fgInit) Init();

   SetRotationMatrix(0);
   PrepareString(text);
   LayoutGlyphs();
   Int_t Xoff = 0; if (fgCBox.xMin < 0) Xoff = -fgCBox.xMin;
   Int_t Yoff = 0; if (fgCBox.yMin < 0) Yoff = -fgCBox.yMin;
   w = fgCBox.xMax + Xoff + fgTBlankW;
   h = fgCBox.yMax + Yoff;
}

//______________________________________________________________________________
void TTF::LayoutGlyphs()
{
   // Compute the glyps positions, fgAscent and fgWidth (needed for alignment).
   // Perform the Glyphs transformation.
   // Compute the string control box.
   // If required take the "kerning" into account.
   // SetRotation and PrepareString should have been called before.

   TTGlyph*  glyph = fgGlyphs;
   FT_Vector origin;
   FT_UInt   load_flags;
   FT_UInt   prev_index = 0;

   fgAscent = 0;
   fgWidth  = 0;

   load_flags = FT_LOAD_DEFAULT;
   if (!fgHinting) load_flags |= FT_LOAD_NO_HINTING;

   fgCBox.xMin = fgCBox.yMin =  32000;
   fgCBox.xMax = fgCBox.yMax = -32000;

   for (int n = 0; n < fgNumGlyphs; n++, glyph++) {

      // compute glyph origin
      if (fgKerning) {
         if (prev_index) {
            FT_Vector  kern;
            FT_Get_Kerning(fgFace[fgCurFontIdx], prev_index, glyph->fIndex,
                           fgHinting ? ft_kerning_default : ft_kerning_unfitted,
                           &kern);
            fgWidth += kern.x;
         }
         prev_index = glyph->fIndex;
      }

      origin.x = fgWidth;
      origin.y = 0;

      // clear existing image if there is one
      if (glyph->fImage) FT_Done_Glyph(glyph->fImage);

      // load the glyph image (in its native format)
      if (FT_Load_Glyph(fgFace[fgCurFontIdx], glyph->fIndex, load_flags))
         continue;

      // extract the glyph image
      if (FT_Get_Glyph (fgFace[fgCurFontIdx]->glyph, &glyph->fImage))
         continue;

      glyph->fPos = origin;
      fgWidth    += fgFace[fgCurFontIdx]->glyph->advance.x;
      fgAscent    = TMath::Max((Int_t)(fgFace[fgCurFontIdx]->glyph->metrics.horiBearingY), fgAscent);

      // transform the glyphs
      FT_Vector_Transform(&glyph->fPos, fgRotMatrix);
      if (FT_Glyph_Transform(glyph->fImage, fgRotMatrix, &glyph->fPos))
         continue;

      // compute the string control box
      FT_BBox  bbox;
      FT_Glyph_Get_CBox(glyph->fImage, ft_glyph_bbox_pixels, &bbox);
      if (bbox.xMin < fgCBox.xMin) fgCBox.xMin = bbox.xMin;
      if (bbox.yMin < fgCBox.yMin) fgCBox.yMin = bbox.yMin;
      if (bbox.xMax > fgCBox.xMax) fgCBox.xMax = bbox.xMax;
      if (bbox.yMax > fgCBox.yMax) fgCBox.yMax = bbox.yMax;
   }
}

//______________________________________________________________________________
void TTF::PrepareString(const char *string)
{
   // Put the characters in "string" in the "glyphs" array.

   const unsigned char *p = (const unsigned char*) string;
   TTGlyph *glyph = fgGlyphs;
   UInt_t index;       // Unicode value
   Int_t NbTBlank = 0; // number of trailing blanks

   fgTBlankW   = 0;
   fgNumGlyphs = 0;
   while (*p) {
      index = CharToUnicode((FT_ULong)*p);
      if (index != 0) {
         glyph->fIndex = index;
         glyph++;
         fgNumGlyphs++;
      }
      if (*p == ' ') {
         NbTBlank++;
      } else {
         NbTBlank = 0;
      }
      if (fgNumGlyphs >= kMaxGlyphs) break;
      p++;
   }

   // compute the trailing blanks width. It is use to compute the text
   // width in GetTextExtent
   if (NbTBlank) {
      FT_UInt load_flags = FT_LOAD_DEFAULT;
      if (!fgHinting) load_flags |= FT_LOAD_NO_HINTING;
      if (FT_Load_Glyph(fgFace[fgCurFontIdx], 3, load_flags)) return;
      fgTBlankW = (Int_t)((fgFace[fgCurFontIdx]->glyph->advance.x)>>6)*NbTBlank;
   }
}

//______________________________________________________________________________
void TTF::PrepareString(const wchar_t *string)
{
   // Put the characters in "string" in the "glyphs" array.

   const wchar_t *p = string;
   TTGlyph *glyph = fgGlyphs;
   UInt_t index;       // Unicode value
   Int_t NbTBlank = 0; // number of trailing blanks

   fgTBlankW   = 0;
   fgNumGlyphs = 0;
   while (*p) {
      index = FT_Get_Char_Index(fgFace[fgCurFontIdx], (FT_ULong)*p);
      if (index != 0) {
         glyph->fIndex = index;
         glyph++;
         fgNumGlyphs++;
      }
      if (*p == ' ') {
         NbTBlank++;
      } else {
         NbTBlank = 0;
      }
      if (fgNumGlyphs >= kMaxGlyphs) break;
      p++;
   }

   // compute the trailing blanks width. It is use to compute the text
   // width in GetTextExtent
   if (NbTBlank) {
      FT_UInt load_flags = FT_LOAD_DEFAULT;
      if (!fgHinting) load_flags |= FT_LOAD_NO_HINTING;
      if (FT_Load_Glyph(fgFace[fgCurFontIdx], 3, load_flags)) return;
      fgTBlankW = (Int_t)((fgFace[fgCurFontIdx]->glyph->advance.x)>>6)*NbTBlank;
   }
}

//______________________________________________________________________________
void TTF::SetHinting(Bool_t state)
{
   // Set hinting flag.

   fgHinting = state;
}

//______________________________________________________________________________
void TTF::SetKerning(Bool_t state)
{
   // Set kerning flag.

   fgKerning = state;
}

//______________________________________________________________________________
void TTF::SetRotationMatrix(Float_t angle)
{
   // Set the rotation matrix used to rotate the font outlines.

   Float_t rangle = Float_t(angle * TMath::Pi() / 180.); // Angle in radian
#if defined(FREETYPE_PATCH) && \
    (FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 1) && (FREETYPE_PATCH == 2)
   Float_t sin    = TMath::Sin(rangle);
   Float_t cos    = TMath::Cos(rangle);
#else
   Float_t sin    = TMath::Sin(-rangle);
   Float_t cos    = TMath::Cos(-rangle);
#endif

   if (!fgRotMatrix) fgRotMatrix = new FT_Matrix;

   fgRotMatrix->xx = (FT_Fixed) (cos * (1<<16));
   fgRotMatrix->xy = (FT_Fixed) (sin * (1<<16));
   fgRotMatrix->yx = -fgRotMatrix->xy;
   fgRotMatrix->yy =  fgRotMatrix->xx;
}

//______________________________________________________________________________
void TTF::SetSmoothing(Bool_t state)
{
   // Set smoothing (anti-aliasing) flag.

   fgSmoothing = state;
}

//______________________________________________________________________________
Int_t TTF::SetTextFont(const char *fontname, Int_t italic)
{
   // Set text font to specified name.
   // font       : font name
   // italic     : the fonts should be slanted. Used for symbol font.
   //
   // Set text font to specified name. This function returns 0 if
   // the specified font is found, 1 if not.

   if (!fgInit) Init();

   if (!fontname || !fontname[0]) {
      Warning("TTF::SetTextFont",
              "no font name specified, using default font %s", fgFontName[0]);
      fgCurFontIdx = 0;
      return 0;
   }
   const char *basename = gSystem->BaseName(fontname);

   // check if font is in cache
   int i;
   for (i = 0; i < fgFontCount; i++) {
      if (!strcmp(fgFontName[i], basename)) {
         if (italic) {
            if (i==fgSymbItaFontIdx) {
               fgCurFontIdx = i;
               return 0;
            }
         } else {
            if (i!=fgSymbItaFontIdx) {
               fgCurFontIdx = i;
               return 0;
            }
         }
      }
   }

   // enough space in cache to load font?
   if (fgFontCount >= kTTMaxFonts) {
      Error("TTF::SetTextFont", "too many fonts opened (increase kTTMaxFont = %d)",
            kTTMaxFonts);
      Warning("TTF::SetTextFont", "using default font %s", fgFontName[0]);
      fgCurFontIdx = 0;    // use font 0 (default font, set in ctor)
      return 0;
   }

   // try to load font (font must be in Root.TTFontPath resource)
   const char *ttpath = gEnv->GetValue("Root.TTFontPath",
# ifdef TTFFONTDIR
                                       TTFFONTDIR
# else
                                       "$(ROOTSYS)/fonts"
# endif
                                      );

   char *ttfont = gSystem->Which(ttpath, fontname, kReadPermission);

   if (!ttfont) {
      Error("TTF::SetTextFont", "font file %s not found in path", fontname);
      if (fgFontCount) {
         Warning("TTF::SetTextFont", "using default font %s", fgFontName[0]);
         fgCurFontIdx = 0;    // use font 0 (default font, set in ctor)
         return 0;
      } else {
         return 1;
      }
   }

   FT_Face  tface = 0;

   if (FT_New_Face(fgLibrary, ttfont, 0, &tface)) {
      Error("TTF::SetTextFont", "error loading font %s", ttfont);
      delete [] ttfont;
      if (tface) FT_Done_Face(tface);
      if (fgFontCount) {
         Warning("TTF::SetTextFont", "using default font %s", fgFontName[0]);
         fgCurFontIdx = 0;
         return 0;
      } else {
         return 1;
      }
   }

   delete [] ttfont;

   fgFontName[fgFontCount] = StrDup(basename);
   fgCurFontIdx            = fgFontCount;
   fgFace[fgCurFontIdx]    = tface;
   fgCharMap[fgCurFontIdx] = 0;
   fgFontCount++;

   if (italic) {
      fgSymbItaFontIdx = fgCurFontIdx;
      FT_Matrix slantMat;
      slantMat.xx = (1 << 16);
      slantMat.xy = ((1 << 16) >> 2);
      slantMat.yx = 0;
      slantMat.yy = (1 << 16);
      FT_Set_Transform( fgFace[fgSymbItaFontIdx], &slantMat, NULL );
   }

   return 0;
}

//______________________________________________________________________________
void TTF::SetTextFont(Font_t fontnumber)
{
   // Set specified font.
   // List of the currently supported fonts (screen and PostScript)
   // =============================================================
   //   Font ID       X11                        TTF
   //        1 : times-medium-i-normal       timesi.ttf
   //        2 : times-bold-r-normal         timesbd.ttf
   //        3 : times-bold-i-normal         timesi.ttf
   //        4 : helvetica-medium-r-normal   arial.ttf
   //        5 : helvetica-medium-o-normal   ariali.ttf
   //        6 : helvetica-bold-r-normal     arialbd.ttf
   //        7 : helvetica-bold-o-normal     arialbi.ttf
   //        8 : courier-medium-r-normal     cour.ttf
   //        9 : courier-medium-o-normal     couri.ttf
   //       10 : courier-bold-r-normal       courbd.ttf
   //       11 : courier-bold-o-normal       courbi.ttf
   //       12 : symbol-medium-r-normal      symbol.ttf
   //       13 : times-medium-r-normal       times.ttf
   //       14 :                             wingding.ttf
   //       15 : symbol oblique is emulated from symbol.ttf

   // Added by cholm for use of DFSG - fonts - based on Kevins fix.
   // Table of Microsoft and (for non-MSFT operating systems) backup
   // FreeFont TTF fonts.
   static const char *fonttable[][2] = {
     { "Root.TTFont.0", "FreeSansBold.otf" },
     { "Root.TTFont.1", "FreeSerifItalic.otf" },
     { "Root.TTFont.2", "FreeSerifBold.otf" },
     { "Root.TTFont.3", "FreeSerifBoldItalic.otf" },
     { "Root.TTFont.4", "FreeSans.otf" },
     { "Root.TTFont.5", "FreeSansOblique.otf" },
     { "Root.TTFont.6", "FreeSansBold.otf" },
     { "Root.TTFont.7", "FreeSansBoldOblique.otf" },
     { "Root.TTFont.8", "FreeMono.otf" },
     { "Root.TTFont.9", "FreeMonoOblique.otf" },
     { "Root.TTFont.10", "FreeMonoBold.otf" },
     { "Root.TTFont.11", "FreeMonoBoldOblique.otf" },
     { "Root.TTFont.12", "symbol.ttf" },
     { "Root.TTFont.13", "FreeSerif.otf" },
     { "Root.TTFont.14", "wingding.ttf" },
     { "Root.TTFont.15", "symbol.ttf" },
     { "Root.TTFont.STIXGen", "STIXGeneral.otf" },
     { "Root.TTFont.STIXGenIt", "STIXGeneralItalic.otf" },
     { "Root.TTFont.STIXGenBd", "STIXGeneralBol.otf" },
     { "Root.TTFont.STIXGenBdIt", "STIXGeneralBolIta.otf" },
     { "Root.TTFont.STIXSiz1Sym", "STIXSiz1Sym.otf" },
     { "Root.TTFont.STIXSiz1SymBd", "STIXSiz1SymBol.otf" },
     { "Root.TTFont.STIXSiz2Sym", "STIXSiz2Sym.otf" },
     { "Root.TTFont.STIXSiz2SymBd", "STIXSiz2SymBol.otf" },
     { "Root.TTFont.STIXSiz3Sym", "STIXSiz3Sym.otf" },
     { "Root.TTFont.STIXSiz3SymBd", "STIXSiz3SymBol.otf" },
     { "Root.TTFont.STIXSiz4Sym", "STIXSiz4Sym.otf" },
     { "Root.TTFont.STIXSiz4SymBd", "STIXSiz4SymBol.otf" },
     { "Root.TTFont.STIXSiz5Sym", "STIXSiz5Sym.otf" },
     { "Root.TTFont.ME", "DroidSansFallback.ttf" },
     { "Root.TTFont.CJKMing", "DroidSansFallback.ttf" },
     { "Root.TTFont.CJKGothic", "DroidSansFallback.ttf" }
   };

   static int fontset = -1;
   int        thisset = fontset;

   int fontid = fontnumber / 10;
   if (fontid < 0 || fontid > 31) fontid = 0;

   if (thisset == -1) {
      // try to load font (font must be in Root.TTFontPath resource)
      // to see which fontset we have available
      const char *ttpath = gEnv->GetValue("Root.TTFontPath",
#ifdef TTFFONTDIR
                                          TTFFONTDIR
#else
                                          "$(ROOTSYS)/fonts"
#endif
                                         );
      char *ttfont = gSystem->Which(ttpath, gEnv->GetValue(fonttable[fontid][0], fonttable[fontid][1]), kReadPermission);
      if (ttfont) {
         delete [] ttfont;
         thisset = 0;
      } else {
         // try backup free font
         thisset = 1;
      }
   }
   Int_t italic = 0;
   if (fontid==15) italic = 1;
   int ret = SetTextFont(gEnv->GetValue(fonttable[fontid][thisset], fonttable[fontid][1]), italic);
   // Do not define font set is we're loading the symbol.ttf - it's
   // the same in both cases.
   if (ret == 0 && fontid != 12) fontset = thisset;
}

//______________________________________________________________________________
void TTF::SetTextSize(Float_t textsize)
{
   // Set current text size.

   if (!fgInit) Init();
   if (textsize < 0) return;

   if (fgCurFontIdx < 0 || fgFontCount <= fgCurFontIdx) {
      Error("TTF::SetTextSize", "current font index out of bounds");
      fgCurFontIdx = 0;
      return;
   }

   Int_t tsize = (Int_t)(textsize*kScale+0.5) << 6;
   if (FT_Set_Char_Size(fgFace[fgCurFontIdx], tsize, tsize, 72, 72))
      Error("TTF::SetTextSize", "error in FT_Set_Char_Size");
}

//______________________________________________________________________________
void TTF::Version(Int_t &major, Int_t &minor, Int_t &patch)
{
   FT_Library_Version(fgLibrary, &major, &minor, &patch);
}

//______________________________________________________________________________
Bool_t TTF::GetHinting()
{
    return fgHinting;
}

//______________________________________________________________________________
Bool_t TTF::GetKerning()
{
    return fgKerning;
}

//______________________________________________________________________________
Bool_t TTF::GetSmoothing()
{
    return fgSmoothing;
}

//______________________________________________________________________________
Bool_t TTF::IsInitialized()
{
    return fgInit;
}

//______________________________________________________________________________
Int_t  TTF::GetWidth()
{
    return fgWidth;
}

//______________________________________________________________________________
Int_t  TTF::GetAscent()
{
    return fgAscent;
}

//______________________________________________________________________________
Int_t  TTF::GetNumGlyphs()
{
    return fgNumGlyphs;
}

//______________________________________________________________________________
FT_Matrix *TTF::GetRotMatrix()
{
    return fgRotMatrix;
}

//______________________________________________________________________________
const FT_BBox &TTF::GetBox()
{
    return fgCBox;
}

//______________________________________________________________________________
TTGlyph *TTF::GetGlyphs()
{
    return fgGlyphs;
}
 TTF.cxx:1
 TTF.cxx:2
 TTF.cxx:3
 TTF.cxx:4
 TTF.cxx:5
 TTF.cxx:6
 TTF.cxx:7
 TTF.cxx:8
 TTF.cxx:9
 TTF.cxx:10
 TTF.cxx:11
 TTF.cxx:12
 TTF.cxx:13
 TTF.cxx:14
 TTF.cxx:15
 TTF.cxx:16
 TTF.cxx:17
 TTF.cxx:18
 TTF.cxx:19
 TTF.cxx:20
 TTF.cxx:21
 TTF.cxx:22
 TTF.cxx:23
 TTF.cxx:24
 TTF.cxx:25
 TTF.cxx:26
 TTF.cxx:27
 TTF.cxx:28
 TTF.cxx:29
 TTF.cxx:30
 TTF.cxx:31
 TTF.cxx:32
 TTF.cxx:33
 TTF.cxx:34
 TTF.cxx:35
 TTF.cxx:36
 TTF.cxx:37
 TTF.cxx:38
 TTF.cxx:39
 TTF.cxx:40
 TTF.cxx:41
 TTF.cxx:42
 TTF.cxx:43
 TTF.cxx:44
 TTF.cxx:45
 TTF.cxx:46
 TTF.cxx:47
 TTF.cxx:48
 TTF.cxx:49
 TTF.cxx:50
 TTF.cxx:51
 TTF.cxx:52
 TTF.cxx:53
 TTF.cxx:54
 TTF.cxx:55
 TTF.cxx:56
 TTF.cxx:57
 TTF.cxx:58
 TTF.cxx:59
 TTF.cxx:60
 TTF.cxx:61
 TTF.cxx:62
 TTF.cxx:63
 TTF.cxx:64
 TTF.cxx:65
 TTF.cxx:66
 TTF.cxx:67
 TTF.cxx:68
 TTF.cxx:69
 TTF.cxx:70
 TTF.cxx:71
 TTF.cxx:72
 TTF.cxx:73
 TTF.cxx:74
 TTF.cxx:75
 TTF.cxx:76
 TTF.cxx:77
 TTF.cxx:78
 TTF.cxx:79
 TTF.cxx:80
 TTF.cxx:81
 TTF.cxx:82
 TTF.cxx:83
 TTF.cxx:84
 TTF.cxx:85
 TTF.cxx:86
 TTF.cxx:87
 TTF.cxx:88
 TTF.cxx:89
 TTF.cxx:90
 TTF.cxx:91
 TTF.cxx:92
 TTF.cxx:93
 TTF.cxx:94
 TTF.cxx:95
 TTF.cxx:96
 TTF.cxx:97
 TTF.cxx:98
 TTF.cxx:99
 TTF.cxx:100
 TTF.cxx:101
 TTF.cxx:102
 TTF.cxx:103
 TTF.cxx:104
 TTF.cxx:105
 TTF.cxx:106
 TTF.cxx:107
 TTF.cxx:108
 TTF.cxx:109
 TTF.cxx:110
 TTF.cxx:111
 TTF.cxx:112
 TTF.cxx:113
 TTF.cxx:114
 TTF.cxx:115
 TTF.cxx:116
 TTF.cxx:117
 TTF.cxx:118
 TTF.cxx:119
 TTF.cxx:120
 TTF.cxx:121
 TTF.cxx:122
 TTF.cxx:123
 TTF.cxx:124
 TTF.cxx:125
 TTF.cxx:126
 TTF.cxx:127
 TTF.cxx:128
 TTF.cxx:129
 TTF.cxx:130
 TTF.cxx:131
 TTF.cxx:132
 TTF.cxx:133
 TTF.cxx:134
 TTF.cxx:135
 TTF.cxx:136
 TTF.cxx:137
 TTF.cxx:138
 TTF.cxx:139
 TTF.cxx:140
 TTF.cxx:141
 TTF.cxx:142
 TTF.cxx:143
 TTF.cxx:144
 TTF.cxx:145
 TTF.cxx:146
 TTF.cxx:147
 TTF.cxx:148
 TTF.cxx:149
 TTF.cxx:150
 TTF.cxx:151
 TTF.cxx:152
 TTF.cxx:153
 TTF.cxx:154
 TTF.cxx:155
 TTF.cxx:156
 TTF.cxx:157
 TTF.cxx:158
 TTF.cxx:159
 TTF.cxx:160
 TTF.cxx:161
 TTF.cxx:162
 TTF.cxx:163
 TTF.cxx:164
 TTF.cxx:165
 TTF.cxx:166
 TTF.cxx:167
 TTF.cxx:168
 TTF.cxx:169
 TTF.cxx:170
 TTF.cxx:171
 TTF.cxx:172
 TTF.cxx:173
 TTF.cxx:174
 TTF.cxx:175
 TTF.cxx:176
 TTF.cxx:177
 TTF.cxx:178
 TTF.cxx:179
 TTF.cxx:180
 TTF.cxx:181
 TTF.cxx:182
 TTF.cxx:183
 TTF.cxx:184
 TTF.cxx:185
 TTF.cxx:186
 TTF.cxx:187
 TTF.cxx:188
 TTF.cxx:189
 TTF.cxx:190
 TTF.cxx:191
 TTF.cxx:192
 TTF.cxx:193
 TTF.cxx:194
 TTF.cxx:195
 TTF.cxx:196
 TTF.cxx:197
 TTF.cxx:198
 TTF.cxx:199
 TTF.cxx:200
 TTF.cxx:201
 TTF.cxx:202
 TTF.cxx:203
 TTF.cxx:204
 TTF.cxx:205
 TTF.cxx:206
 TTF.cxx:207
 TTF.cxx:208
 TTF.cxx:209
 TTF.cxx:210
 TTF.cxx:211
 TTF.cxx:212
 TTF.cxx:213
 TTF.cxx:214
 TTF.cxx:215
 TTF.cxx:216
 TTF.cxx:217
 TTF.cxx:218
 TTF.cxx:219
 TTF.cxx:220
 TTF.cxx:221
 TTF.cxx:222
 TTF.cxx:223
 TTF.cxx:224
 TTF.cxx:225
 TTF.cxx:226
 TTF.cxx:227
 TTF.cxx:228
 TTF.cxx:229
 TTF.cxx:230
 TTF.cxx:231
 TTF.cxx:232
 TTF.cxx:233
 TTF.cxx:234
 TTF.cxx:235
 TTF.cxx:236
 TTF.cxx:237
 TTF.cxx:238
 TTF.cxx:239
 TTF.cxx:240
 TTF.cxx:241
 TTF.cxx:242
 TTF.cxx:243
 TTF.cxx:244
 TTF.cxx:245
 TTF.cxx:246
 TTF.cxx:247
 TTF.cxx:248
 TTF.cxx:249
 TTF.cxx:250
 TTF.cxx:251
 TTF.cxx:252
 TTF.cxx:253
 TTF.cxx:254
 TTF.cxx:255
 TTF.cxx:256
 TTF.cxx:257
 TTF.cxx:258
 TTF.cxx:259
 TTF.cxx:260
 TTF.cxx:261
 TTF.cxx:262
 TTF.cxx:263
 TTF.cxx:264
 TTF.cxx:265
 TTF.cxx:266
 TTF.cxx:267
 TTF.cxx:268
 TTF.cxx:269
 TTF.cxx:270
 TTF.cxx:271
 TTF.cxx:272
 TTF.cxx:273
 TTF.cxx:274
 TTF.cxx:275
 TTF.cxx:276
 TTF.cxx:277
 TTF.cxx:278
 TTF.cxx:279
 TTF.cxx:280
 TTF.cxx:281
 TTF.cxx:282
 TTF.cxx:283
 TTF.cxx:284
 TTF.cxx:285
 TTF.cxx:286
 TTF.cxx:287
 TTF.cxx:288
 TTF.cxx:289
 TTF.cxx:290
 TTF.cxx:291
 TTF.cxx:292
 TTF.cxx:293
 TTF.cxx:294
 TTF.cxx:295
 TTF.cxx:296
 TTF.cxx:297
 TTF.cxx:298
 TTF.cxx:299
 TTF.cxx:300
 TTF.cxx:301
 TTF.cxx:302
 TTF.cxx:303
 TTF.cxx:304
 TTF.cxx:305
 TTF.cxx:306
 TTF.cxx:307
 TTF.cxx:308
 TTF.cxx:309
 TTF.cxx:310
 TTF.cxx:311
 TTF.cxx:312
 TTF.cxx:313
 TTF.cxx:314
 TTF.cxx:315
 TTF.cxx:316
 TTF.cxx:317
 TTF.cxx:318
 TTF.cxx:319
 TTF.cxx:320
 TTF.cxx:321
 TTF.cxx:322
 TTF.cxx:323
 TTF.cxx:324
 TTF.cxx:325
 TTF.cxx:326
 TTF.cxx:327
 TTF.cxx:328
 TTF.cxx:329
 TTF.cxx:330
 TTF.cxx:331
 TTF.cxx:332
 TTF.cxx:333
 TTF.cxx:334
 TTF.cxx:335
 TTF.cxx:336
 TTF.cxx:337
 TTF.cxx:338
 TTF.cxx:339
 TTF.cxx:340
 TTF.cxx:341
 TTF.cxx:342
 TTF.cxx:343
 TTF.cxx:344
 TTF.cxx:345
 TTF.cxx:346
 TTF.cxx:347
 TTF.cxx:348
 TTF.cxx:349
 TTF.cxx:350
 TTF.cxx:351
 TTF.cxx:352
 TTF.cxx:353
 TTF.cxx:354
 TTF.cxx:355
 TTF.cxx:356
 TTF.cxx:357
 TTF.cxx:358
 TTF.cxx:359
 TTF.cxx:360
 TTF.cxx:361
 TTF.cxx:362
 TTF.cxx:363
 TTF.cxx:364
 TTF.cxx:365
 TTF.cxx:366
 TTF.cxx:367
 TTF.cxx:368
 TTF.cxx:369
 TTF.cxx:370
 TTF.cxx:371
 TTF.cxx:372
 TTF.cxx:373
 TTF.cxx:374
 TTF.cxx:375
 TTF.cxx:376
 TTF.cxx:377
 TTF.cxx:378
 TTF.cxx:379
 TTF.cxx:380
 TTF.cxx:381
 TTF.cxx:382
 TTF.cxx:383
 TTF.cxx:384
 TTF.cxx:385
 TTF.cxx:386
 TTF.cxx:387
 TTF.cxx:388
 TTF.cxx:389
 TTF.cxx:390
 TTF.cxx:391
 TTF.cxx:392
 TTF.cxx:393
 TTF.cxx:394
 TTF.cxx:395
 TTF.cxx:396
 TTF.cxx:397
 TTF.cxx:398
 TTF.cxx:399
 TTF.cxx:400
 TTF.cxx:401
 TTF.cxx:402
 TTF.cxx:403
 TTF.cxx:404
 TTF.cxx:405
 TTF.cxx:406
 TTF.cxx:407
 TTF.cxx:408
 TTF.cxx:409
 TTF.cxx:410
 TTF.cxx:411
 TTF.cxx:412
 TTF.cxx:413
 TTF.cxx:414
 TTF.cxx:415
 TTF.cxx:416
 TTF.cxx:417
 TTF.cxx:418
 TTF.cxx:419
 TTF.cxx:420
 TTF.cxx:421
 TTF.cxx:422
 TTF.cxx:423
 TTF.cxx:424
 TTF.cxx:425
 TTF.cxx:426
 TTF.cxx:427
 TTF.cxx:428
 TTF.cxx:429
 TTF.cxx:430
 TTF.cxx:431
 TTF.cxx:432
 TTF.cxx:433
 TTF.cxx:434
 TTF.cxx:435
 TTF.cxx:436
 TTF.cxx:437
 TTF.cxx:438
 TTF.cxx:439
 TTF.cxx:440
 TTF.cxx:441
 TTF.cxx:442
 TTF.cxx:443
 TTF.cxx:444
 TTF.cxx:445
 TTF.cxx:446
 TTF.cxx:447
 TTF.cxx:448
 TTF.cxx:449
 TTF.cxx:450
 TTF.cxx:451
 TTF.cxx:452
 TTF.cxx:453
 TTF.cxx:454
 TTF.cxx:455
 TTF.cxx:456
 TTF.cxx:457
 TTF.cxx:458
 TTF.cxx:459
 TTF.cxx:460
 TTF.cxx:461
 TTF.cxx:462
 TTF.cxx:463
 TTF.cxx:464
 TTF.cxx:465
 TTF.cxx:466
 TTF.cxx:467
 TTF.cxx:468
 TTF.cxx:469
 TTF.cxx:470
 TTF.cxx:471
 TTF.cxx:472
 TTF.cxx:473
 TTF.cxx:474
 TTF.cxx:475
 TTF.cxx:476
 TTF.cxx:477
 TTF.cxx:478
 TTF.cxx:479
 TTF.cxx:480
 TTF.cxx:481
 TTF.cxx:482
 TTF.cxx:483
 TTF.cxx:484
 TTF.cxx:485
 TTF.cxx:486
 TTF.cxx:487
 TTF.cxx:488
 TTF.cxx:489
 TTF.cxx:490
 TTF.cxx:491
 TTF.cxx:492
 TTF.cxx:493
 TTF.cxx:494
 TTF.cxx:495
 TTF.cxx:496
 TTF.cxx:497
 TTF.cxx:498
 TTF.cxx:499
 TTF.cxx:500
 TTF.cxx:501
 TTF.cxx:502
 TTF.cxx:503
 TTF.cxx:504
 TTF.cxx:505
 TTF.cxx:506
 TTF.cxx:507
 TTF.cxx:508
 TTF.cxx:509
 TTF.cxx:510
 TTF.cxx:511
 TTF.cxx:512
 TTF.cxx:513
 TTF.cxx:514
 TTF.cxx:515
 TTF.cxx:516
 TTF.cxx:517
 TTF.cxx:518
 TTF.cxx:519
 TTF.cxx:520
 TTF.cxx:521
 TTF.cxx:522
 TTF.cxx:523
 TTF.cxx:524
 TTF.cxx:525
 TTF.cxx:526
 TTF.cxx:527
 TTF.cxx:528
 TTF.cxx:529
 TTF.cxx:530
 TTF.cxx:531
 TTF.cxx:532
 TTF.cxx:533
 TTF.cxx:534
 TTF.cxx:535
 TTF.cxx:536
 TTF.cxx:537
 TTF.cxx:538
 TTF.cxx:539
 TTF.cxx:540
 TTF.cxx:541
 TTF.cxx:542
 TTF.cxx:543
 TTF.cxx:544
 TTF.cxx:545
 TTF.cxx:546
 TTF.cxx:547
 TTF.cxx:548
 TTF.cxx:549
 TTF.cxx:550
 TTF.cxx:551
 TTF.cxx:552
 TTF.cxx:553
 TTF.cxx:554
 TTF.cxx:555
 TTF.cxx:556
 TTF.cxx:557
 TTF.cxx:558
 TTF.cxx:559
 TTF.cxx:560
 TTF.cxx:561
 TTF.cxx:562
 TTF.cxx:563
 TTF.cxx:564
 TTF.cxx:565
 TTF.cxx:566
 TTF.cxx:567
 TTF.cxx:568
 TTF.cxx:569
 TTF.cxx:570
 TTF.cxx:571
 TTF.cxx:572
 TTF.cxx:573
 TTF.cxx:574
 TTF.cxx:575
 TTF.cxx:576
 TTF.cxx:577
 TTF.cxx:578
 TTF.cxx:579
 TTF.cxx:580
 TTF.cxx:581
 TTF.cxx:582
 TTF.cxx:583
 TTF.cxx:584
 TTF.cxx:585
 TTF.cxx:586
 TTF.cxx:587
 TTF.cxx:588
 TTF.cxx:589
 TTF.cxx:590
 TTF.cxx:591
 TTF.cxx:592
 TTF.cxx:593
 TTF.cxx:594
 TTF.cxx:595
 TTF.cxx:596
 TTF.cxx:597
 TTF.cxx:598
 TTF.cxx:599
 TTF.cxx:600
 TTF.cxx:601
 TTF.cxx:602
 TTF.cxx:603
 TTF.cxx:604
 TTF.cxx:605
 TTF.cxx:606
 TTF.cxx:607
 TTF.cxx:608
 TTF.cxx:609
 TTF.cxx:610
 TTF.cxx:611
 TTF.cxx:612
 TTF.cxx:613
 TTF.cxx:614
 TTF.cxx:615
 TTF.cxx:616
 TTF.cxx:617
 TTF.cxx:618
 TTF.cxx:619
 TTF.cxx:620
 TTF.cxx:621
 TTF.cxx:622
 TTF.cxx:623
 TTF.cxx:624
 TTF.cxx:625
 TTF.cxx:626
 TTF.cxx:627
 TTF.cxx:628
 TTF.cxx:629
 TTF.cxx:630
 TTF.cxx:631
 TTF.cxx:632
 TTF.cxx:633
 TTF.cxx:634
 TTF.cxx:635
 TTF.cxx:636
 TTF.cxx:637
 TTF.cxx:638
 TTF.cxx:639
 TTF.cxx:640
 TTF.cxx:641
 TTF.cxx:642
 TTF.cxx:643
 TTF.cxx:644
 TTF.cxx:645
 TTF.cxx:646
 TTF.cxx:647
 TTF.cxx:648
 TTF.cxx:649
 TTF.cxx:650
 TTF.cxx:651
 TTF.cxx:652