Logo ROOT   6.12/06
Reference Guide
TTF.cxx
Go to the documentation of this file.
1 // @(#)root/graf:$Id$
2 // Author: Olivier Couet 01/10/02
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TTF
13 \ingroup BasicGraphics
14 
15 Interface to the freetype 2 library.
16 */
17 
18 # include <ft2build.h>
19 # include FT_FREETYPE_H
20 # include FT_GLYPH_H
21 #include "TROOT.h"
22 #include "TTF.h"
23 #include "TSystem.h"
24 #include "TEnv.h"
25 #include "TMath.h"
26 #include "TError.h"
27 
28 #include <fontconfig/fontconfig.h>
29 
30 // to scale fonts to the same size as the old TT version
31 const Float_t kScale = 0.93376068;
32 
33 TTF gCleanupTTF; // Allows to call "Cleanup" at the end of the session
34 
45 Int_t TTF::fgFontID[kTTMaxFonts];
46 FT_Matrix *TTF::fgRotMatrix;
47 FT_Library TTF::fgLibrary;
48 FT_BBox TTF::fgCBox;
49 FT_Face TTF::fgFace[kTTMaxFonts];
50 FT_CharMap TTF::fgCharMap[kTTMaxFonts];
51 TTF::TTGlyph TTF::fgGlyphs[kMaxGlyphs];
52 
53 ClassImp(TTF);
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 /// Cleanup TTF environment.
57 
59 {
60  Cleanup();
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 /// Initialise the TrueType fonts interface.
65 
66 void TTF::Init()
67 {
68  fgInit = kTRUE;
69 
70  // initialize FTF library
71  if (FT_Init_FreeType(&fgLibrary)) {
72  Error("TTF::Init", "error initializing FreeType");
73  return;
74  }
75 
76  // Add root's font directory
77  const char *ttpath = gEnv->GetValue("Root.TTFontPath",
79  FcConfigAppFontAddDir (NULL, (const FcChar8*)ttpath);
80 
81  // load default font (arialbd)
82  SetTextFont(62);
83 }
84 
85 ////////////////////////////////////////////////////////////////////////////////
86 /// Cleanup. Is called by the gCleanupTTF destructor.
87 
89 {
90  if (!fgInit) return;
91 
92  for (int i = 0; i < fgFontCount; i++) {
93  FT_Done_Face(fgFace[i]);
94  }
95  if (fgRotMatrix) delete fgRotMatrix;
96  FT_Done_FreeType(fgLibrary);
97 
98  fgInit = kFALSE;
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Map char to unicode. Returns 0 in case no mapping exists.
103 
105 {
106  if (!fgCharMap[fgCurFontIdx]) {
107  UShort_t i, platform, encoding;
108  FT_CharMap charmap;
109 
110  if (!fgFace[fgCurFontIdx]) return 0;
111  Int_t n = fgFace[fgCurFontIdx]->num_charmaps;
112  for (i = 0; i < n; i++) {
113  if (!fgFace[fgCurFontIdx]) continue;
114  charmap = fgFace[fgCurFontIdx]->charmaps[i];
115  platform = charmap->platform_id;
116  encoding = charmap->encoding_id;
117  if ((platform == 3 && encoding == 1 &&
118  (fgFontID[fgCurFontIdx] != 12 &&
119  fgFontID[fgCurFontIdx] != 14 &&
120  fgFontID[fgCurFontIdx] != 15)) ||
121  (platform == 0 && encoding == 0) ||
122  (platform == 7 && encoding == 2 &&
123  (fgFontID[fgCurFontIdx] == 12 ||
124  fgFontID[fgCurFontIdx] == 14 ||
125  fgFontID[fgCurFontIdx] == 15)) ||
126  (platform == 1 && encoding == 0 &&
127  (fgFontID[fgCurFontIdx] == 12 ||
128  fgFontID[fgCurFontIdx] == 14 ||
129  fgFontID[fgCurFontIdx] == 15)) ||
130  // Horrible hack for broken charmaps in StandardSymbolsPS.otf
131  // Hopefully temporary...
132  (platform == 0 && encoding == 3 &&
133  (fgFontID[fgCurFontIdx] == 12 ||
134  fgFontID[fgCurFontIdx] == 15)))
135  {
136  fgCharMap[fgCurFontIdx] = charmap;
137  if (FT_Set_Charmap(fgFace[fgCurFontIdx], fgCharMap[fgCurFontIdx]))
138  Error("TTF::CharToUnicode", "error in FT_Set_CharMap");
139  return FT_Get_Char_Index(fgFace[fgCurFontIdx], (FT_ULong)code);
140  }
141  }
142  }
143  return FT_Get_Char_Index(fgFace[fgCurFontIdx], (FT_ULong)code);
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// Get width (w) and height (h) when text is horizontal.
148 
150 {
151  if (!fgInit) Init();
152 
155  LayoutGlyphs();
156  Int_t Xoff = 0; if (fgCBox.xMin < 0) Xoff = -fgCBox.xMin;
157  Int_t Yoff = 0; if (fgCBox.yMin < 0) Yoff = -fgCBox.yMin;
158  w = fgCBox.xMax + Xoff + fgTBlankW;
159  h = fgCBox.yMax + Yoff;
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Get advance (a) when text is horizontal.
164 
166 {
167  if (!fgInit) Init();
168 
171  LayoutGlyphs();
172  a = GetWidth()>>6;
173 }
174 
175 ////////////////////////////////////////////////////////////////////////////////
176 /// Get width (w) and height (h) when text is horizontal.
177 
178 void TTF::GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *text)
179 {
180  if (!fgInit) Init();
181 
184  LayoutGlyphs();
185  Int_t Xoff = 0; if (fgCBox.xMin < 0) Xoff = -fgCBox.xMin;
186  Int_t Yoff = 0; if (fgCBox.yMin < 0) Yoff = -fgCBox.yMin;
187  w = fgCBox.xMax + Xoff + fgTBlankW;
188  h = fgCBox.yMax + Yoff;
189 }
190 
191 ////////////////////////////////////////////////////////////////////////////////
192 /// Compute the glyphs positions, fgAscent and fgWidth (needed for alignment).
193 /// Perform the Glyphs transformation.
194 /// Compute the string control box.
195 /// If required take the "kerning" into account.
196 /// SetRotation and PrepareString should have been called before.
197 
199 {
200  TTGlyph* glyph = fgGlyphs;
201  FT_Vector origin;
202  FT_UInt load_flags;
203  FT_UInt prev_index = 0;
204 
205  fgAscent = 0;
206  fgWidth = 0;
207 
208  load_flags = FT_LOAD_DEFAULT;
209  if (!fgHinting) load_flags |= FT_LOAD_NO_HINTING;
210 
211  fgCBox.xMin = fgCBox.yMin = 32000;
212  fgCBox.xMax = fgCBox.yMax = -32000;
213 
214  for (int n = 0; n < fgNumGlyphs; n++, glyph++) {
215 
216  // compute glyph origin
217  if (fgKerning) {
218  if (prev_index) {
219  FT_Vector kern;
220  FT_Get_Kerning(fgFace[fgCurFontIdx], prev_index, glyph->fIndex,
221  fgHinting ? ft_kerning_default : ft_kerning_unfitted,
222  &kern);
223  fgWidth += kern.x;
224  }
225  prev_index = glyph->fIndex;
226  }
227 
228  origin.x = fgWidth;
229  origin.y = 0;
230 
231  // clear existing image if there is one
232  if (glyph->fImage) FT_Done_Glyph(glyph->fImage);
233 
234  // load the glyph image (in its native format)
235  if (FT_Load_Glyph(fgFace[fgCurFontIdx], glyph->fIndex, load_flags))
236  continue;
237 
238  // extract the glyph image
239  if (FT_Get_Glyph (fgFace[fgCurFontIdx]->glyph, &glyph->fImage))
240  continue;
241 
242  glyph->fPos = origin;
243  fgWidth += fgFace[fgCurFontIdx]->glyph->advance.x;
244  fgAscent = TMath::Max((Int_t)(fgFace[fgCurFontIdx]->glyph->metrics.horiBearingY), fgAscent);
245 
246  // transform the glyphs
247  FT_Vector_Transform(&glyph->fPos, fgRotMatrix);
248  if (FT_Glyph_Transform(glyph->fImage, fgRotMatrix, &glyph->fPos))
249  continue;
250 
251  // compute the string control box
252  FT_BBox bbox;
253  FT_Glyph_Get_CBox(glyph->fImage, ft_glyph_bbox_pixels, &bbox);
254  if (bbox.xMin < fgCBox.xMin) fgCBox.xMin = bbox.xMin;
255  if (bbox.yMin < fgCBox.yMin) fgCBox.yMin = bbox.yMin;
256  if (bbox.xMax > fgCBox.xMax) fgCBox.xMax = bbox.xMax;
257  if (bbox.yMax > fgCBox.yMax) fgCBox.yMax = bbox.yMax;
258  }
259 }
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Put the characters in "string" in the "glyphs" array.
263 
264 void TTF::PrepareString(const char *string)
265 {
266  const unsigned char *p = (const unsigned char*) string;
267  TTGlyph *glyph = fgGlyphs;
268  UInt_t index; // Unicode value
269  Int_t NbTBlank = 0; // number of trailing blanks
270 
271  fgTBlankW = 0;
272  fgNumGlyphs = 0;
273  while (*p) {
274  index = CharToUnicode((FT_ULong)*p);
275  if (index != 0) {
276  glyph->fIndex = index;
277  glyph++;
278  fgNumGlyphs++;
279  }
280  if (*p == ' ') {
281  NbTBlank++;
282  } else {
283  NbTBlank = 0;
284  }
285  if (fgNumGlyphs >= kMaxGlyphs) break;
286  p++;
287  }
288 
289  // compute the trailing blanks width. It is use to compute the text
290  // width in GetTextExtent
291  if (NbTBlank) {
292  FT_UInt load_flags = FT_LOAD_DEFAULT;
293  if (!fgHinting) load_flags |= FT_LOAD_NO_HINTING;
294  if (FT_Load_Glyph(fgFace[fgCurFontIdx], 3, load_flags)) return;
295  fgTBlankW = (Int_t)((fgFace[fgCurFontIdx]->glyph->advance.x)>>6)*NbTBlank;
296  }
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// Put the characters in "string" in the "glyphs" array.
301 
302 void TTF::PrepareString(const wchar_t *string)
303 {
304  const wchar_t *p = string;
305  TTGlyph *glyph = fgGlyphs;
306  UInt_t index; // Unicode value
307  Int_t NbTBlank = 0; // number of trailing blanks
308 
309  fgTBlankW = 0;
310  fgNumGlyphs = 0;
311  while (*p) {
312  index = FT_Get_Char_Index(fgFace[fgCurFontIdx], (FT_ULong)*p);
313  if (index != 0) {
314  glyph->fIndex = index;
315  glyph++;
316  fgNumGlyphs++;
317  }
318  if (*p == ' ') {
319  NbTBlank++;
320  } else {
321  NbTBlank = 0;
322  }
323  if (fgNumGlyphs >= kMaxGlyphs) break;
324  p++;
325  }
326 
327  // compute the trailing blanks width. It is use to compute the text
328  // width in GetTextExtent
329  if (NbTBlank) {
330  FT_UInt load_flags = FT_LOAD_DEFAULT;
331  if (!fgHinting) load_flags |= FT_LOAD_NO_HINTING;
332  if (FT_Load_Glyph(fgFace[fgCurFontIdx], 3, load_flags)) return;
333  fgTBlankW = (Int_t)((fgFace[fgCurFontIdx]->glyph->advance.x)>>6)*NbTBlank;
334  }
335 }
336 
337 ////////////////////////////////////////////////////////////////////////////////
338 /// Set hinting flag.
339 
341 {
342  fgHinting = state;
343 }
344 
345 ////////////////////////////////////////////////////////////////////////////////
346 /// Set kerning flag.
347 
349 {
350  fgKerning = state;
351 }
352 
353 ////////////////////////////////////////////////////////////////////////////////
354 /// Set the rotation matrix used to rotate the font outlines.
355 
357 {
358  Float_t rangle = Float_t(angle * TMath::Pi() / 180.); // Angle in radian
359 #if defined(FREETYPE_PATCH) && \
360  (FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 1) && (FREETYPE_PATCH == 2)
361  Float_t sin = TMath::Sin(rangle);
362  Float_t cos = TMath::Cos(rangle);
363 #else
364  Float_t sin = TMath::Sin(-rangle);
365  Float_t cos = TMath::Cos(-rangle);
366 #endif
367 
368  if (!fgRotMatrix) fgRotMatrix = new FT_Matrix;
369 
370  fgRotMatrix->xx = (FT_Fixed) (cos * (1<<16));
371  fgRotMatrix->xy = (FT_Fixed) (sin * (1<<16));
372  fgRotMatrix->yx = -fgRotMatrix->xy;
373  fgRotMatrix->yy = fgRotMatrix->xx;
374 }
375 
376 ////////////////////////////////////////////////////////////////////////////////
377 /// Set smoothing (anti-aliasing) flag.
378 
380 {
381  fgSmoothing = state;
382 }
383 
384 ////////////////////////////////////////////////////////////////////////////////
385 /// Set text font to specified name.
386 /// - font : font name
387 /// - italic : the fonts should be slanted. Used for symbol font.
388 ///
389 /// Set text font to specified name. This function returns 0 if
390 /// the specified font is found, 1 if not.
391 
392 Int_t TTF::SetTextFont(const char *fontname, Int_t italic)
393 {
394  if (!fgInit) Init();
395 
396  if (!fontname || !fontname[0]) {
397  Warning("TTF::SetTextFont",
398  "no font name specified, using default font");
399  fgCurFontIdx = 0;
400  return 0;
401  }
402  const char *basename = gSystem->BaseName(fontname);
403 
404  if (strcmp(basename, "timesi.ttf") == 0 ||
405  strcmp(basename, "FreeSerifItalic.otf") == 0) {
406  SetTextFont(12);
407  }
408  else if (strcmp(basename, "timesbd.ttf") == 0 ||
409  strcmp(basename, "FreeSerifBold.otf") == 0) {
410  SetTextFont(22);
411  }
412  else if (strcmp(basename, "timesbi.ttf") == 0 ||
413  strcmp(basename, "FreeSerifBoldItalic.otf") == 0) {
414  SetTextFont(32);
415  }
416  else if (strcmp(basename, "arial.ttf") == 0 ||
417  strcmp(basename, "FreeSans.otf") == 0) {
418  SetTextFont(42);
419  }
420  else if (strcmp(basename, "ariali.ttf") == 0 ||
421  strcmp(basename, "FreeSansOblique.otf") == 0) {
422  SetTextFont(52);
423  }
424  else if (strcmp(basename, "arialbd.ttf") == 0 ||
425  strcmp(basename, "FreeSansBold.otf") == 0) {
426  SetTextFont(62);
427  }
428  else if (strcmp(basename, "arialbi.ttf") == 0 ||
429  strcmp(basename, "FreeSansBoldOblique.otf") == 0) {
430  SetTextFont(72);
431  }
432  else if (strcmp(basename, "cour.ttf") == 0 ||
433  strcmp(basename, "FreeMono.otf") == 0) {
434  SetTextFont(82);
435  }
436  else if (strcmp(basename, "couri.ttf") == 0 ||
437  strcmp(basename, "FreeMonoOblique.otf") == 0) {
438  SetTextFont(92);
439  }
440  else if (strcmp(basename, "courbd.ttf") == 0 ||
441  strcmp(basename, "FreeMonoBold.otf") == 0) {
442  SetTextFont(102);
443  }
444  else if (strcmp(basename, "courbi.ttf") == 0 ||
445  strcmp(basename, "FreeMonoBoldOblique.otf") == 0) {
446  SetTextFont(112);
447  }
448  else if (strcmp(basename, "symbol.ttf") == 0) {
449  if (italic)
450  SetTextFont(152);
451  else
452  SetTextFont(122);
453  }
454  else if (strcmp(basename, "times.ttf") == 0 ||
455  strcmp(basename, "FreeSerif.otf") == 0) {
456  SetTextFont(132);
457  }
458  else if (strcmp(basename, "wingding.ttf") == 0) {
459  SetTextFont(142);
460  }
461  else if (strcmp(basename, "STIXGeneral.otf") == 0) {
462  SetTextFont(162);
463  }
464  else if (strcmp(basename, "STIXGeneralItalic.otf") == 0) {
465  SetTextFont(172);
466  }
467  else if (strcmp(basename, "STIXGeneralBol.otf") == 0) {
468  SetTextFont(182);
469  }
470  else if (strcmp(basename, "STIXGeneralBolIta.otf") == 0) {
471  SetTextFont(192);
472  }
473  else if (strcmp(basename, "STIXSiz1Sym.otf") == 0) {
474  SetTextFont(202);
475  }
476  else if (strcmp(basename, "STIXSiz1SymBol.otf") == 0) {
477  SetTextFont(212);
478  }
479  else if (strcmp(basename, "STIXSiz2Sym.otf") == 0) {
480  SetTextFont(222);
481  }
482  else if (strcmp(basename, "STIXSiz2SymBol.otf") == 0) {
483  SetTextFont(232);
484  }
485  else if (strcmp(basename, "STIXSiz3Sym.otf") == 0) {
486  SetTextFont(242);
487  }
488  else if (strcmp(basename, "STIXSiz3SymBol.otf") == 0) {
489  SetTextFont(252);
490  }
491  else if (strcmp(basename, "STIXSiz4Sym.otf") == 0) {
492  SetTextFont(262);
493  }
494  else if (strcmp(basename, "STIXSiz4SymBol.otf") == 0) {
495  SetTextFont(272);
496  }
497  else if (strcmp(basename, "STIXSiz5Sym.otf") == 0) {
498  SetTextFont(282);
499  }
500  else if (strcmp(basename, "DroidSansFallback.ttf") == 0) {
501  SetTextFont(292);
502  }
503  else {
504  Error("TTF::SetTextFont", "font %s not known to ROOT", basename);
505  if (fgFontCount) {
506  Warning("TTF::SetTextFont", "using default font");
507  fgCurFontIdx = 0; // use font 0 (default font, set in ctor)
508  return 0;
509  } else {
510  return 1;
511  }
512  }
513 
514  return 0;
515 }
516 
517 //______________________________________________________________________________
518 void TTF::SetTextFont(Font_t fontnumber)
519 {
520  int fontid = fontnumber / 10;
521  if (fontid < 0 || fontid > 31) fontid = 0;
522 
523  Int_t italic = 0;
524  if (fontid==15) italic = 1;
525 
526  if (!fgInit) Init();
527 
528  if (fontid == 0) {
529  fgCurFontIdx = 0; // use font 0 (default font, set in ctor)
530  return;
531  }
532 
533  // check if font is in cache
534  int i;
535  for (i = 0; i < fgFontCount; i++) {
536  if (fgFontID[i] == fontid) {
537  fgCurFontIdx = i;
538  return;
539  }
540  }
541 
542  // enough space in cache to load font?
543  if (fgFontCount >= kTTMaxFonts) {
544  Error("TTF::SetTextFont", "too many fonts opened (increase kTTMaxFont = %d)",
545  kTTMaxFonts);
546  Warning("TTF::SetTextFont", "using default font");
547  fgCurFontIdx = 0; // use font 0 (default font, set in ctor)
548  return;
549  }
550 
551  char *ttfont = NULL;
552  int ttindex = 0;
553 
554  FcPattern *pat, *match;
555  FcCharSet *set = NULL;
556  FcResult result;
557 
558  pat = FcPatternCreate ();
559 
560  switch (fontid) {
561  case 1:
562  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freeserif");
563  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
564  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
565  break;
566  case 2:
567  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freeserif");
568  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
569  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
570  break;
571  case 3:
572  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freeserif");
573  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
574  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
575  break;
576  case 4:
577  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freesans");
578  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
579  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
580  break;
581  case 5:
582  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freesans");
583  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
584  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
585  break;
586  case 6:
587  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freesans");
588  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
589  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
590  break;
591  case 7:
592  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freesans");
593  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
594  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
595  break;
596  case 8:
597  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freemono");
598  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
599  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
600  break;
601  case 9:
602  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freemono");
603  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
604  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
605  break;
606  case 10:
607  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freemono");
608  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
609  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
610  break;
611  case 11:
612  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freemono");
613  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
614  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
615  break;
616  case 12:
617  case 15:
618  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"symbol");
619  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
620  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
621  break;
622  case 13:
623  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freeserif");
624  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
625  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
626  break;
627  case 14:
628  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"dingbats");
629  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
630  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
631  break;
632  case 16:
633  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixgeneral");
634  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
635  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
636  break;
637  case 17:
638  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixgeneral");
639  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
640  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
641  break;
642  case 18:
643  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixgeneral");
644  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
645  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
646  break;
647  case 19:
648  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixgeneral");
649  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
650  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
651  break;
652  case 20:
653  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize1");
654  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
655  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
656  break;
657  case 21:
658  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize1");
659  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
660  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
661  break;
662  case 22:
663  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize2");
664  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
665  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
666  break;
667  case 23:
668  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize2");
669  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
670  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
671  break;
672  case 24:
673  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize3");
674  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
675  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
676  break;
677  case 25:
678  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize3");
679  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
680  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
681  break;
682  case 26:
683  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize4");
684  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
685  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
686  break;
687  case 27:
688  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize4");
689  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
690  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
691  break;
692  case 28:
693  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize5");
694  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
695  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
696  break;
697  case 29:
698  case 30:
699  case 31:
700  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"droidsansfallback");
701  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
702  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
703  set = FcCharSetCreate ();
704  FcCharSetAddChar (set, 0x0410); // Cyrillic
705  FcCharSetAddChar (set, 0x4e00); // CJK
706  FcPatternAddCharSet (pat, FC_CHARSET, set);
707  break;
708  default:
709  Error("TTF::SetTextFont", "font %i not known to ROOT", fontid);
710  FcPatternDestroy (pat);
711  Warning("TTF::SetTextFont", "using default font");
712  fgCurFontIdx = 0; // use font 0 (default font, set in ctor)
713  return;
714  break;
715  }
716 
717  FcConfigSubstitute (NULL, pat, FcMatchPattern);
718  FcDefaultSubstitute (pat);
719  match = FcFontMatch (NULL, pat, &result);
720  char *ttfnt;
721  FcPatternGetString (match, FC_FILE, 0, (FcChar8**)&ttfnt);
722  ttfont = StrDup (ttfnt);
723  FcPatternGetInteger (match, FC_INDEX, 0, &ttindex);
724  FcPatternDestroy (match);
725  FcPatternDestroy (pat);
726  if (set) FcCharSetDestroy (set);
727 
728  FT_Face tface = 0;
729 
730  if (FT_New_Face(fgLibrary, ttfont, ttindex, &tface)) {
731  Error("TTF::SetTextFont", "error loading font %s", ttfont);
732  delete [] ttfont;
733  if (tface) FT_Done_Face(tface);
734  Warning("TTF::SetTextFont", "using default font");
735  fgCurFontIdx = 0;
736  return;
737  }
738 
739  delete [] ttfont;
740 
741  fgFontID[fgFontCount] = fontid;
743  fgFace[fgCurFontIdx] = tface;
744  fgCharMap[fgCurFontIdx] = 0;
745  fgFontCount++;
746 
747  if (italic) {
748  FT_Matrix slantMat;
749  slantMat.xx = (1 << 16);
750  slantMat.xy = ((1 << 16) >> 2);
751  slantMat.yx = 0;
752  slantMat.yy = (1 << 16);
753  FT_Set_Transform( fgFace[fgCurFontIdx], &slantMat, NULL );
754  }
755 }
756 
757 ////////////////////////////////////////////////////////////////////////////////
758 /// Set current text size.
759 
760 void TTF::SetTextSize(Float_t textsize)
761 {
762  if (!fgInit) Init();
763  if (textsize < 0) return;
764 
765  if (fgCurFontIdx < 0 || fgFontCount <= fgCurFontIdx) {
766  Error("TTF::SetTextSize", "current font index out of bounds");
767  fgCurFontIdx = 0;
768  return;
769  }
770 
771  Int_t tsize = (Int_t)(textsize*kScale+0.5) << 6;
772  if (FT_Set_Char_Size(fgFace[fgCurFontIdx], tsize, tsize, 72, 72))
773  Error("TTF::SetTextSize", "error in FT_Set_Char_Size");
774 }
775 
776 ////////////////////////////////////////////////////////////////////////////////
777 
778 void TTF::Version(Int_t &major, Int_t &minor, Int_t &patch)
779 {
780  FT_Library_Version(fgLibrary, &major, &minor, &patch);
781 }
782 
783 ////////////////////////////////////////////////////////////////////////////////
784 
786 {
787  return fgHinting;
788 }
789 
790 ////////////////////////////////////////////////////////////////////////////////
791 
793 {
794  return fgKerning;
795 }
796 
797 ////////////////////////////////////////////////////////////////////////////////
798 
800 {
801  return fgSmoothing;
802 }
803 
804 ////////////////////////////////////////////////////////////////////////////////
805 
807 {
808  return fgInit;
809 }
810 
811 ////////////////////////////////////////////////////////////////////////////////
812 
814 {
815  return fgWidth;
816 }
817 
818 ////////////////////////////////////////////////////////////////////////////////
819 
821 {
822  return fgAscent;
823 }
824 
825 ////////////////////////////////////////////////////////////////////////////////
826 
828 {
829  return fgNumGlyphs;
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 
834 FT_Matrix *TTF::GetRotMatrix()
835 {
836  return fgRotMatrix;
837 }
838 
839 ////////////////////////////////////////////////////////////////////////////////
840 
841 const FT_BBox &TTF::GetBox()
842 {
843  return fgCBox;
844 }
845 
846 ////////////////////////////////////////////////////////////////////////////////
847 
849 {
850  return fgGlyphs;
851 }
virtual ~TTF()
Cleanup TTF environment.
Definition: TTF.cxx:58
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:932
static void Init()
Initialise the TrueType fonts interface.
Definition: TTF.cxx:66
static const TString & GetTTFFontDir()
Get the fonts directory in the installation. Static utility function.
Definition: TROOT.cxx:3042
FT_Vector fPos
position of glyph origin
Definition: TTF.h:68
static FT_Matrix * fgRotMatrix
rotation matrix
Definition: TTF.h:88
float Float_t
Definition: RtypesCore.h:53
static Int_t fgFontCount
number of fonts loaded
Definition: TTF.h:79
static Bool_t IsInitialized()
Definition: TTF.cxx:806
FT_Glyph fImage
glyph image
Definition: TTF.h:69
unsigned short UShort_t
Definition: RtypesCore.h:36
TH1 * h
Definition: legend2.C:5
const Float_t kScale
Definition: TTF.cxx:31
static void Cleanup()
Cleanup. Is called by the gCleanupTTF destructor.
Definition: TTF.cxx:88
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Interface to the freetype 2 library.
Definition: TTF.h:53
static void Version(Int_t &major, Int_t &minor, Int_t &patch)
Definition: TTF.cxx:778
UInt_t fIndex
glyph index in face
Definition: TTF.h:67
short Font_t
Definition: RtypesCore.h:75
static FT_CharMap fgCharMap[kTTMaxFonts]
font character map
Definition: TTF.h:77
double cos(double)
static Int_t fgAscent
string ascent, used to compute Y alignment
Definition: TTF.h:75
static TTF::TTGlyph fgGlyphs[kMaxGlyphs]
glyphs
Definition: TTF.h:82
static void LayoutGlyphs()
Compute the glyphs positions, fgAscent and fgWidth (needed for alignment).
Definition: TTF.cxx:198
static Bool_t GetHinting()
Definition: TTF.cxx:785
static void SetTextFont(Font_t fontnumber)
Definition: TTF.cxx:518
static void GetTextExtent(UInt_t &w, UInt_t &h, char *text)
Get width (w) and height (h) when text is horizontal.
Definition: TTF.cxx:149
static void PrepareString(const char *string)
Put the characters in "string" in the "glyphs" array.
Definition: TTF.cxx:264
static FT_BBox fgCBox
string control box
Definition: TTF.h:76
static void GetTextAdvance(UInt_t &a, char *text)
Get advance (a) when text is horizontal.
Definition: TTF.cxx:165
static TTGlyph * GetGlyphs()
Definition: TTF.cxx:848
constexpr Double_t Pi()
Definition: TMath.h:40
double sin(double)
void Error(const char *location, const char *msgfmt,...)
static Int_t fgTBlankW
trailing blanks width
Definition: TTF.h:90
static void SetSmoothing(Bool_t state)
Set smoothing (anti-aliasing) flag.
Definition: TTF.cxx:379
static Int_t fgCurFontIdx
current font index
Definition: TTF.h:78
static Int_t GetWidth()
Definition: TTF.cxx:813
static FT_Library fgLibrary
FreeType font library.
Definition: TTF.h:86
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
auto * a
Definition: textangle.C:12
static Bool_t GetKerning()
Definition: TTF.cxx:792
static Int_t fgFontID[kTTMaxFonts]
font ID
Definition: TTF.h:80
static Bool_t fgKerning
use kerning (true by default)
Definition: TTF.h:85
static Bool_t fgInit
true if the Init has been called
Definition: TTF.h:84
static FT_Matrix * GetRotMatrix()
Definition: TTF.cxx:834
unsigned int UInt_t
Definition: RtypesCore.h:42
TTF helper class containing glyphs description.
Definition: TTF.h:65
short Short_t
Definition: RtypesCore.h:35
static void SetHinting(Bool_t state)
Set hinting flag.
Definition: TTF.cxx:340
void Warning(const char *location, const char *msgfmt,...)
static void SetKerning(Bool_t state)
Set kerning flag.
Definition: TTF.cxx:348
Double_t Cos(Double_t)
Definition: TMath.h:550
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2544
const Bool_t kFALSE
Definition: RtypesCore.h:88
static Bool_t fgHinting
use hinting (true by default)
Definition: TTF.h:83
#define ClassImp(name)
Definition: Rtypes.h:359
static Int_t GetAscent()
Definition: TTF.cxx:820
TText * text
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
TTF gCleanupTTF
Definition: TTF.cxx:33
static Bool_t fgSmoothing
use anti-aliasing (true when >8 planes, false otherwise)
Definition: TTF.h:89
static void SetRotationMatrix(Float_t angle)
Set the rotation matrix used to rotate the font outlines.
Definition: TTF.cxx:356
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
Double_t Sin(Double_t)
Definition: TMath.h:547
static FT_Face fgFace[kTTMaxFonts]
font face
Definition: TTF.h:81
static Int_t fgNumGlyphs
number of glyphs in the string
Definition: TTF.h:87
static void SetTextSize(Float_t textsize)
Set current text size.
Definition: TTF.cxx:760
static Short_t CharToUnicode(UInt_t code)
Map char to unicode. Returns 0 in case no mapping exists.
Definition: TTF.cxx:104
static Int_t GetNumGlyphs()
Definition: TTF.cxx:827
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
const Bool_t kTRUE
Definition: RtypesCore.h:87
const Int_t n
Definition: legend1.C:16
static Int_t fgWidth
string width, used to compute X alignment
Definition: TTF.h:91
static const FT_BBox & GetBox()
Definition: TTF.cxx:841
static Bool_t GetSmoothing()
Definition: TTF.cxx:799