Logo ROOT   6.12/07
Reference Guide
TGFont.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Fons Rademakers 20/5/2003
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2003, 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 
13  This source is based on Xclass95, a Win95-looking GUI toolkit.
14  Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
15 
16  Xclass95 is free software; you can redistribute it and/or
17  modify it under the terms of the GNU Library General Public
18  License as published by the Free Software Foundation; either
19  version 2 of the License, or (at your option) any later version.
20 
21 **************************************************************************/
22 
23 
24 //////////////////////////////////////////////////////////////////////////
25 // //
26 // TGFont and TGFontPool //
27 // //
28 // Encapsulate fonts used in the GUI system. //
29 // TGFontPool provides a pool of fonts. //
30 // TGTextLayout is used to keep track of string measurement //
31 // information when using the text layout facilities. //
32 // It can be displayed with respect to any origin. //
33 // //
34 //////////////////////////////////////////////////////////////////////////
35 
36 #include "TGFont.h"
37 #include "TGClient.h"
38 #include "THashTable.h"
39 #include "TVirtualX.h"
40 #include "TObjString.h"
41 #include "TGWidget.h"
42 #include <errno.h>
43 #include <stdlib.h>
44 #include <limits.h>
45 
46 #include "Riostream.h"
47 #include "TROOT.h"
48 #include "TError.h"
49 #include "TMath.h"
50 
51 
55 
56 #define FONT_FAMILY 0
57 #define FONT_SIZE 1
58 #define FONT_WEIGHT 2
59 #define FONT_SLANT 3
60 #define FONT_UNDERLINE 4
61 #define FONT_OVERSTRIKE 5
62 #define FONT_NUMFIELDS 6
63 
64 // The following defines specify the meaning of the fields in a fully
65 // qualified XLFD.
66 
67 #define XLFD_FOUNDRY 0
68 #define XLFD_FAMILY 1
69 #define XLFD_WEIGHT 2
70 #define XLFD_SLANT 3
71 #define XLFD_SETWIDTH 4
72 #define XLFD_ADD_STYLE 5
73 #define XLFD_PIXEL_SIZE 6
74 #define XLFD_POINT_SIZE 7
75 #define XLFD_RESOLUTION_X 8
76 #define XLFD_RESOLUTION_Y 9
77 #define XLFD_SPACING 10
78 #define XLFD_AVERAGE_WIDTH 11
79 #define XLFD_REGISTRY 12
80 #define XLFD_ENCODING 13
81 #define XLFD_NUMFIELDS 14 // Number of fields in XLFD.
82 
83 
84 // A LayoutChunk_t represents a contiguous range of text that can be measured
85 // and displayed by low-level text calls. In general, chunks will be
86 // delimited by newlines and tabs. Low-level, platform-specific things
87 // like kerning and non-integer character widths may occur between the
88 // characters in a single chunk, but not between characters in different
89 // chunks.
90 
91 struct LayoutChunk_t {
92 
93  const char *fStart; // Pointer to simple string to be displayed.
94  // This is a pointer into the TGTextLayout's
95  // string.
96  Int_t fNumChars; // The number of characters in this chunk.
97  Int_t fNumDisplayChars; // The number of characters to display when
98  // this chunk is displayed. Can be less than
99  // numChars if extra space characters were
100  // absorbed by the end of the chunk. This
101  // will be < 0 if this is a chunk that is
102  // holding a tab or newline.
103  Int_t fX; // The x origin and
104  Int_t fY; // the y origin of the first character in this
105  // chunk with respect to the upper-left hand
106  // corner of the TGTextLayout.
107  Int_t fTotalWidth; // Width in pixels of this chunk. Used
108  // when hit testing the invisible spaces at
109  // the end of a chunk.
110  Int_t fDisplayWidth; // Width in pixels of the displayable
111  // characters in this chunk. Can be less than
112  // width if extra space characters were
113  // absorbed by the end of the chunk.
114 };
115 
116 
117 // The following structure is used to return attributes when parsing an
118 // XLFD. The extra information is used to find the closest matching font.
119 
120 struct XLFDAttributes_t {
121  FontAttributes_t fFA; // Standard set of font attributes.
122  const char *fFoundry; // The foundry of the font.
123  Int_t fSlant; // The tristate value for the slant
124  Int_t fSetwidth; // The proportionate width
125  Int_t fCharset; // The character set encoding (the glyph family).
126  Int_t fEncoding; // Variations within a charset for the glyphs above character 127.
127 
128  XLFDAttributes_t() : // default constructor
129  fFA(),
130  fFoundry(0),
131  fSlant(0),
132  fSetwidth(0),
133  fCharset(0),
134  fEncoding(0) { }
135 };
136 
137 
138 // The following data structure is used to keep track of the font attributes
139 // for each named font that has been defined. The named font is only deleted
140 // when the last reference to it goes away.
141 
142 class TNamedFont : public TObjString, public TRefCnt {
143 public:
144  Int_t fDeletePending; // Non-zero if font should be deleted when last reference goes away.
145  FontAttributes_t fFA; // Desired attributes for named font.
146 };
147 
148 // enums
153 
158 
162 
163 
164 // Possible values for entries in the "types" field in a TGFont structure,
165 // which classifies the types of all characters in the given font. This
166 // information is used when measuring and displaying characters.
167 //
168 // kCharNormal: Standard character.
169 // kCharReplace: This character doesn't print: instead of displaying
170 // character, display a replacement sequence like "\n"
171 // (for those characters where ANSI C defines such a
172 // sequence) or a sequence of the form "\xdd" where dd
173 // is the hex equivalent of the character.
174 // kCharSkip: Don't display anything for this character. This is
175 // only used where the font doesn't contain all the
176 // characters needed to generate replacement sequences.
178 
179 
180 // The following structures are used as two-way maps between the values for
181 // the fields in the FontAttributes_t structure and the strings used when
182 // parsing both option-value format and style-list format font name strings.
183 
184 struct FontStateMap_t { Int_t fNumKey; const char *fStrKey; };
185 
186 static const FontStateMap_t gWeightMap[] = {
187  { kFontWeightNormal, "normal" },
188  { kFontWeightBold, "bold" },
189  { kFontWeightUnknown, 0 }
190 };
191 
192 static const FontStateMap_t gSlantMap[] = {
193  { kFontSlantRoman, "roman" },
194  { kFontSlantItalic, "italic" },
195  { kFontSlantUnknown, 0 }
196 };
197 
198 static const FontStateMap_t gUnderlineMap[] = {
199  { 1, "underline" },
200  { 0, 0 }
201 };
202 
203 static const FontStateMap_t gOverstrikeMap[] = {
204  { 1, "overstrike" },
205  { 0, 0 }
206 };
207 
208 // The following structures are used when parsing XLFD's into a set of
209 // FontAttributes_t.
210 
211 static const FontStateMap_t gXlfdgWeightMap[] = {
212  { kFontWeightNormal, "normal" },
213  { kFontWeightNormal, "medium" },
214  { kFontWeightNormal, "book" },
215  { kFontWeightNormal, "light" },
216  { kFontWeightBold, "bold" },
217  { kFontWeightBold, "demi" },
218  { kFontWeightBold, "demibold" },
219  { kFontWeightNormal, 0 } // Assume anything else is "normal".
220 };
221 
222 static const FontStateMap_t gXlfdSlantMap[] = {
223  { kFontSlantRoman, "r" },
224  { kFontSlantItalic, "i" },
225  { kFontSlantOblique, "o" },
226  { kFontSlantRoman, 0 } // Assume anything else is "roman".
227 };
228 
229 static const FontStateMap_t gXlfdSetwidthMap[] = {
230  { kFontSWNormal, "normal" },
231  { kFontSWCondence, "narrow" },
232  { kFontSWCondence, "semicondensed" },
233  { kFontSWCondence, "condensed" },
234  { kFontSWUnknown, 0 }
235 };
236 
237 static const FontStateMap_t gXlfdCharsetMap[] = {
238  { kFontCSNormal, "iso8859" },
239  { kFontCSSymbol, "adobe" },
240  { kFontCSSymbol, "sun" },
241  { kFontCSOther, 0 }
242 };
243 
244 
245 // Characters used when displaying control sequences.
246 
247 static char gHexChars[] = "0123456789abcdefxtnvr\\";
248 
249 
250 // The following table maps some control characters to sequences like '\n'
251 // rather than '\x10'. A zero entry in the table means no such mapping
252 // exists, and the table only maps characters less than 0x10.
253 
254 static char gMapChars[] = {
255  0, 0, 0, 0, 0, 0, 0, 'a', 'b', 't', 'n', 'v', 'f', 'r', 0
256 };
257 
258 static int GetControlCharSubst(int c, char buf[4]);
259 
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Delete font.
263 
265 {
266  if (fFontStruct) {
267  gVirtualX->DeleteFont(fFontStruct);
268  }
269 }
270 
271 ////////////////////////////////////////////////////////////////////////////////
272 /// Get font metrics.
273 
275 {
276  if (!m) {
277  Error("GetFontMetrics", "argument may not be 0");
278  return;
279  }
280 
281  *m = fFM;
282  m->fLinespace = fFM.fAscent + fFM.fDescent;
283 }
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 /// Not inline due to a bug in g++ 2.96 20000731 (Red Hat Linux 7.0)
287 
289 {
290  return fFontStruct;
291 }
292 
293 ////////////////////////////////////////////////////////////////////////////////
294 /// Print font info.
295 
296 void TGFont::Print(Option_t *option) const
297 {
298  TString opt = option;
299 
300  if ((opt == "full") && fNamedHash) {
301  Printf("TGFont: %s, %s, ref cnt = %u",
302  fNamedHash->GetName(),
303  fFM.fFixed ? "fixed" : "prop", References());
304  } else {
305  Printf("TGFont: %s, %s, ref cnt = %u", fName.Data(),
306  fFM.fFixed ? "fixed" : "prop", References());
307  }
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// Return the name of the corresponding Postscript font for this TGFont.
312 ///
313 /// The return value is the pointsize of the TGFont. The name of the
314 /// Postscript font is appended to ds.
315 ///
316 /// If the font does not exist on the printer, the print job will fail at
317 /// print time. Given a "reasonable" Postscript printer, the following
318 /// TGFont font families should print correctly:
319 ///
320 /// Avant Garde, Arial, Bookman, Courier, Courier New, Geneva,
321 /// Helvetica, Monaco, New Century Schoolbook, New York,
322 /// Palatino, Symbol, Times, Times New Roman, Zapf Chancery,
323 /// and Zapf Dingbats.
324 ///
325 /// Any other TGFont font families may not print correctly because the
326 /// computed Postscript font name may be incorrect.
327 ///
328 /// dst -- Pointer to an initialized TString object to which the name of the
329 /// Postscript font that corresponds to the font will be appended.
330 
332 {
333  const char *family;
334  TString weightString;
335  TString slantString;
336  char *src, *dest;
337  Int_t upper, len;
338 
339  len = dst->Length();
340 
341  // Convert the case-insensitive TGFont family name to the
342  // case-sensitive Postscript family name. Take out any spaces and
343  // capitalize the first letter of each word.
344 
345  family = fFA.fFamily;
346  if (strncasecmp(family, "itc ", 4) == 0) {
347  family = family + 4;
348  }
349  if ((strcasecmp(family, "Arial") == 0)
350  || (strcasecmp(family, "Geneva") == 0)) {
351  family = "Helvetica";
352  } else if ((strcasecmp(family, "Times New Roman") == 0)
353  || (strcasecmp(family, "New York") == 0)) {
354  family = "Times";
355  } else if ((strcasecmp(family, "Courier New") == 0)
356  || (strcasecmp(family, "Monaco") == 0)) {
357  family = "Courier";
358  } else if (strcasecmp(family, "AvantGarde") == 0) {
359  family = "AvantGarde";
360  } else if (strcasecmp(family, "ZapfChancery") == 0) {
361  family = "ZapfChancery";
362  } else if (strcasecmp(family, "ZapfDingbats") == 0) {
363  family = "ZapfDingbats";
364  } else {
365 
366  // Inline, capitalize the first letter of each word, lowercase the
367  // rest of the letters in each word, and then take out the spaces
368  // between the words. This may make the TString shorter, which is
369  // safe to do.
370 
371  dst->Append(family);
372 
373  src = dest = (char*)dst->Data() + len;
374  upper = 1;
375  for (; *src != '\0'; src++, dest++) {
376  while (isspace(UChar_t(*src))) {
377  src++;
378  upper = 1;
379  }
380  *dest = *src;
381  if ((upper != 0) && (islower(UChar_t(*src)))) {
382  *dest = toupper(UChar_t(*src));
383  }
384  upper = 0;
385  }
386  *dest = '\0';
387  //dst->SetLength(dest - dst->GetString()); // dst->ResetLength(); may be better
388  family = (char *) dst->Data() + len;
389  }
390  if (family != (char *) dst->Data() + len) {
391  dst->Append(family);
392  family = (char *) dst->Data() + len;
393  }
394  if (strcasecmp(family, "NewCenturySchoolbook") == 0) {
395 // dst->SetLength(len);
396  dst->Append("NewCenturySchlbk");
397  family = (char *) dst->Data() + len;
398  }
399 
400  // Get the string to use for the weight.
401 
402  weightString = "";
403  if (fFA.fWeight == kFontWeightNormal) {
404  if (strcmp(family, "Bookman") == 0) {
405  weightString = "Light";
406  } else if (strcmp(family, "AvantGarde") == 0) {
407  weightString = "Book";
408  } else if (strcmp(family, "ZapfChancery") == 0) {
409  weightString = "Medium";
410  }
411  } else {
412  if ((strcmp(family, "Bookman") == 0)
413  || (strcmp(family, "AvantGarde") == 0)) {
414  weightString = "Demi";
415  } else {
416  weightString = "Bold";
417  }
418  }
419 
420  // Get the string to use for the slant.
421 
422  slantString = "";
423  if (fFA.fSlant == kFontSlantRoman) {
424  ;
425  } else {
426  if ((strcmp(family, "Helvetica") == 0)
427  || (strcmp(family, "Courier") == 0)
428  || (strcmp(family, "AvantGarde") == 0)) {
429  slantString = "Oblique";
430  } else {
431  slantString = "Italic";
432  }
433  }
434 
435  // The string "Roman" needs to be added to some fonts that are not bold
436  // and not italic.
437 
438  if ((slantString.IsNull()) && (weightString.IsNull())) {
439  if ((strcmp(family, "Times") == 0)
440  || (strcmp(family, "NewCenturySchlbk") == 0)
441  || (strcmp(family, "Palatino") == 0)) {
442  dst->Append("-Roman");
443  }
444  } else {
445  dst->Append("-");
446  if (!weightString.IsNull()) dst->Append(weightString);
447  if (!slantString.IsNull()) dst->Append(slantString);
448  }
449 
450  return fFA.fPointsize;
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////
454 /// Determine the number of characters from the string that will fit in the
455 /// given horizontal span. The measurement is done under the assumption that
456 /// DrawChars() will be used to actually display the characters.
457 ///
458 /// The return value is the number of characters from source that fit into
459 /// the span that extends from 0 to maxLength. *length is filled with the
460 /// x-coordinate of the right edge of the last character that did fit.
461 ///
462 /// source -- Characters to be displayed. Need not be '\0' terminated.
463 /// numChars -- Maximum number of characters to consider from source string.
464 /// maxLength -- If > 0, maxLength specifies the longest permissible line
465 /// length; don't consider any character that would cross this
466 /// x-position. If <= 0, then line length is unbounded and the
467 /// flags argument is ignored.
468 /// flags -- Various flag bits OR-ed together:
469 /// TEXT_PARTIAL_OK means include the last char which only
470 /// partially fit on this line.
471 /// TEXT_WHOLE_WORDS means stop on a word boundary, if possible.
472 /// TEXT_AT_LEAST_ONE means return at least one character even
473 /// if no characters fit.
474 /// *length -- Filled with x-location just after the terminating character.
475 
476 Int_t TGFont::MeasureChars(const char *source, Int_t numChars, Int_t maxLength,
477  Int_t flags, Int_t *length) const
478 {
479  const char *p; // Current character.
480  const char *term; // Pointer to most recent character that may legally be a terminating character.
481  Int_t termX; // X-position just after term.
482  Int_t curX; // X-position corresponding to p.
483  Int_t newX; // X-position corresponding to p+1.
484  Int_t c, sawNonSpace;
485 
486  if (!numChars) {
487  *length = 0;
488  return 0;
489  }
490  if (maxLength <= 0) {
491  maxLength = INT_MAX;
492  }
493  newX = curX = termX = 0;
494  p = term = source;
495  sawNonSpace = !isspace(UChar_t(*p));
496 
497  // Scan the input string one character at a time, calculating width.
498 
499  for (c = UChar_t(*p);;) {
500  newX += fWidths[c];
501  if (newX > maxLength) {
502  break;
503  }
504  curX = newX;
505  numChars--;
506  p++;
507  if (!numChars) {
508  term = p;
509  termX = curX;
510  break;
511  }
512  c = UChar_t(*p);
513  if (isspace(c)) {
514  if (sawNonSpace) {
515  term = p;
516  termX = curX;
517  sawNonSpace = 0;
518  }
519  } else {
520  sawNonSpace = 1;
521  }
522  }
523 
524  // P points to the first character that doesn't fit in the desired
525  // span. Use the flags to figure out what to return.
526 
527  if ((flags & kTextPartialOK) && (numChars > 0) && (curX < maxLength)) {
528 
529  // Include the first character that didn't quite fit in the desired
530  // span. The width returned will include the width of that extra
531  // character.
532 
533  numChars--;
534  curX = newX;
535  p++;
536  }
537  if ((flags & kTextAtLeastOne) && (term == source) && (numChars > 0)) {
538  term = p;
539  termX = curX;
540  if (term == source) {
541  term++;
542  termX = newX;
543  }
544  } else if ((numChars == 0) || !(flags & kTextWholeWords)) {
545  term = p;
546  termX = curX;
547  }
548  *length = termX;
549 
550  return term - source;
551 }
552 
553 ////////////////////////////////////////////////////////////////////////////////
554 /// A wrapper function for the more complicated interface of MeasureChars.
555 /// Computes how much space the given simple string needs.
556 ///
557 /// The return value is the width (in pixels) of the given string.
558 ///
559 /// string -- String whose width will be computed.
560 /// numChars -- Number of characters to consider from string, or < 0 for
561 /// strlen().
562 
563 Int_t TGFont::TextWidth(const char *string, Int_t numChars) const
564 {
565  Int_t width;
566 
567  if (numChars < 0) {
568  numChars = strlen(string);
569  }
570  MeasureChars(string, numChars, 0, 0, &width);
571 
572  return width;
573 }
574 
575 ////////////////////////////////////////////////////////////////////////////////
576 /// Return text widht in pixels
577 
578 Int_t TGFont::XTextWidth(const char *string, Int_t numChars) const
579 {
580  int width;
581 
582  if (numChars < 0) {
583  numChars = strlen(string);
584  }
585  width = gVirtualX->TextWidth(fFontStruct, string, numChars);
586 
587  return width;
588 }
589 
590 ////////////////////////////////////////////////////////////////////////////////
591 /// This procedure draws an underline for a given range of characters in a
592 /// given string. It doesn't draw the characters (which are assumed to have
593 /// been displayed previously); it just draws the underline. This procedure
594 /// would mainly be used to quickly underline a few characters without having
595 /// to construct an underlined font. To produce properly underlined text, the
596 /// appropriate underlined font should be constructed and used.
597 ///
598 /// dst -- Window or pixmap in which to draw.
599 /// gc -- Graphics context for actually drawing line.
600 /// string -- String containing characters to be underlined or overstruck.
601 /// x, y -- Coordinates at which first character of string is drawn.
602 /// firstChar -- Index of first character.
603 /// lastChar -- Index of one after the last character.
604 
606  const char *string, Int_t x, Int_t y,
607  Int_t firstChar, Int_t lastChar) const
608 {
609  Int_t startX, endX;
610 
611  MeasureChars(string, firstChar, 0, 0, &startX);
612  MeasureChars(string, lastChar, 0, 0, &endX);
613 
614  gVirtualX->FillRectangle(dst, gc, x + startX, y + fUnderlinePos,
615  (UInt_t) (endX - startX),
616  (UInt_t) fUnderlineHeight);
617 }
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 /// Computes the amount of screen space needed to display a multi-line,
621 /// justified string of text. Records all the measurements that were done
622 /// to determine to size and positioning of the individual lines of text;
623 /// this information can be used by the TGTextLayout::DrawText() procedure
624 /// to display the text quickly (without remeasuring it).
625 ///
626 /// This procedure is useful for simple widgets that want to display
627 /// single-font, multi-line text and want TGFont to handle the details.
628 ///
629 /// The return value is a TGTextLayout token that holds the measurement
630 /// information for the given string. The token is only valid for the given
631 /// string. If the string is freed, the token is no longer valid and must
632 /// also be deleted.
633 ///
634 /// The dimensions of the screen area needed to display the text are stored
635 /// in *width and *height.
636 ///
637 /// string -- String whose dimensions are to be computed.
638 /// numChars -- Number of characters to consider from string, or < 0 for
639 /// strlen().
640 /// wrapLength -- Longest permissible line length, in pixels. <= 0 means no
641 /// automatic wrapping: just let lines get as long as needed.
642 /// justify -- How to justify lines.
643 /// flags -- Flag bits OR-ed together. kTextIgnoreTabs means that tab
644 /// characters should not be expanded. kTextIgnoreNewlines
645 /// means that newline characters should not cause a line break.
646 /// width -- Filled with width of string.
647 /// height -- Filled with height of string.
648 
649 TGTextLayout *TGFont::ComputeTextLayout(const char *string, Int_t numChars,
650  Int_t wrapLength, Int_t justify, Int_t flags,
651  UInt_t *width, UInt_t *height) const
652 {
653  const char *start, *end, *special;
654  Int_t n, y=0, charsThisChunk, maxChunks;
655  Int_t baseline, h, curX, newX, maxWidth;
656  TGTextLayout *layout;
657  LayoutChunk_t *chunk;
658 
659 #define MAX_LINES 50
660  Int_t staticLineLengths[MAX_LINES];
661  Int_t *lineLengths;
662  Int_t maxLines, curLine, layoutHeight;
663 
664  lineLengths = staticLineLengths;
665  maxLines = MAX_LINES;
666 
667  h = fFM.fAscent + fFM.fDescent;
668 
669  if (numChars < 0) {
670  numChars = strlen(string);
671  }
672  maxChunks = 0;
673 
674  layout = new TGTextLayout;
675  layout->fFont = this;
676  layout->fString = string;
677  layout->fNumChunks = 0;
678  layout->fChunks = 0;
679 
680  baseline = fFM.fAscent;
681  maxWidth = 0;
682 
683  // Divide the string up into simple strings and measure each string.
684 
685  curX = 0;
686 
687  end = string + numChars;
688  special = string;
689 
691  flags |= kTextWholeWords | kTextAtLeastOne;
692  curLine = 0;
693 
694  for (start = string; start < end;) {
695  if (start >= special) {
696  // Find the next special character in the string.
697 
698  for (special = start; special < end; special++) {
699  if (!(flags & kTextIgnoreNewlines)) {
700  if ((*special == '\n') || (*special == '\r')) {
701  break;
702  }
703  }
704  if (!(flags & kTextIgnoreTabs)) {
705  if (*special == '\t') {
706  break;
707  }
708  }
709  }
710  }
711 
712  // Special points at the next special character (or the end of the
713  // string). Process characters between start and special.
714 
715  chunk = 0;
716  if (start < special) {
717  charsThisChunk = MeasureChars(start, special - start,
718  wrapLength - curX, flags, &newX);
719  newX += curX;
720  flags &= ~kTextAtLeastOne;
721  if (charsThisChunk > 0) {
722  chunk = NewChunk(layout, &maxChunks, start,
723  charsThisChunk, curX, newX, baseline);
724 
725  start += charsThisChunk;
726  curX = newX;
727  }
728  }
729  if ((start == special) && (special < end)) {
730  // Handle the special character.
731  LayoutChunk_t *newchunk = 0;
732 
733  chunk = 0;
734  if (*special == '\t') {
735  newX = curX + fTabWidth;
736  newX -= newX % fTabWidth;
737  newchunk = NewChunk(layout, &maxChunks, start, 1, curX, newX, baseline);
738  if (newchunk) newchunk->fNumDisplayChars = -1;
739  start++;
740  if ((start < end) && ((wrapLength <= 0) || (newX <= wrapLength))) {
741 
742  // More chars can still fit on this line.
743 
744  curX = newX;
745  flags &= ~kTextAtLeastOne;
746  continue;
747  }
748  } else {
749  newchunk = NewChunk(layout, &maxChunks, start, 1, curX, 1000000000, baseline);
750  if (newchunk) newchunk->fNumDisplayChars = -1;
751  start++;
752  goto wrapLine;
753  }
754  }
755 
756  // No more characters are going to go on this line, either because
757  // no more characters can fit or there are no more characters left.
758  // Consume all extra spaces at end of line.
759 
760  while ((start < end) && isspace(UChar_t(*start))) {
761  if (!(flags & kTextIgnoreNewlines)) {
762  if ((*start == '\n') || (*start == '\r')) {
763  break;
764  }
765  }
766  if (!(flags & kTextIgnoreTabs)) {
767  if (*start == '\t') {
768  break;
769  }
770  }
771  start++;
772  }
773  if (chunk) {
774  // Append all the extra spaces on this line to the end of the
775  // last text chunk.
776 
777  charsThisChunk = start - (chunk->fStart + chunk->fNumChars);
778  if (charsThisChunk > 0) {
779  chunk->fNumChars += MeasureChars(chunk->fStart + chunk->fNumChars,
780  charsThisChunk, 0, 0, &chunk->fTotalWidth);
781  chunk->fTotalWidth += curX;
782  }
783  }
784 wrapLine:
785  flags |= kTextAtLeastOne;
786 
787  // Save current line length, then move current position to start of
788  // next line.
789 
790  if (curX > maxWidth) {
791  maxWidth = curX;
792  }
793 
794  // Remember width of this line, so that all chunks on this line
795  // can be centered or right justified, if necessary.
796 
797  if (curLine >= maxLines) {
798  int *newLengths;
799 
800  newLengths = new int[2 * maxLines];
801  memcpy((void *) newLengths, lineLengths, maxLines * sizeof (int));
802 
803  if (lineLengths != staticLineLengths) {
804  delete[] lineLengths;
805  }
806  lineLengths = newLengths;
807  maxLines *= 2;
808  }
809  lineLengths[curLine] = curX;
810  curLine++;
811 
812  curX = 0;
813  baseline += h;
814  }
815 
816  // If last line ends with a newline, then we need to make a 0 width
817  // chunk on the next line. Otherwise "Hello" and "Hello\n" are the
818  // same height.
819 
820  if ((layout->fNumChunks > 0) && ((flags & kTextIgnoreNewlines) == 0)) {
821  if (layout->fChunks[layout->fNumChunks - 1].fStart[0] == '\n') {
822  chunk = NewChunk(layout, &maxChunks, start, 0, curX, 1000000000, baseline);
823  chunk->fNumDisplayChars = -1;
824  baseline += h;
825  }
826  }
827 
828  // Using maximum line length, shift all the chunks so that the lines are
829  // all justified correctly.
830 
831  curLine = 0;
832  chunk = layout->fChunks;
833  if (chunk) y = chunk->fY;
834  for (n = 0; n < layout->fNumChunks; n++) {
835  int extra;
836 
837  if (chunk->fY != y) {
838  curLine++;
839  y = chunk->fY;
840  }
841  extra = maxWidth - lineLengths[curLine];
842  if (justify == kTextCenterX) {
843  chunk->fX += extra / 2;
844  } else if (justify == kTextRight) {
845  chunk->fX += extra;
846  }
847  ++chunk;
848  }
849 
850  layout->fWidth = maxWidth;
851  layoutHeight = baseline - fFM.fAscent;
852  if (layout->fNumChunks == 0) {
853  layoutHeight = h;
854 
855  // This fake chunk is used by the other procedures so that they can
856  // pretend that there is a chunk with no chars in it, which makes
857  // the coding simpler.
858 
859  layout->fNumChunks = 1;
860  layout->fChunks = new LayoutChunk_t[1];
861  layout->fChunks[0].fStart = string;
862  layout->fChunks[0].fNumChars = 0;
863  layout->fChunks[0].fNumDisplayChars = -1;
864  layout->fChunks[0].fX = 0;
865  layout->fChunks[0].fY = fFM.fAscent;
866  layout->fChunks[0].fTotalWidth = 0;
867  layout->fChunks[0].fDisplayWidth = 0;
868  }
869  if (width) {
870  *width = layout->fWidth;
871  }
872  if (height) {
873  *height = layoutHeight;
874  }
875  if (lineLengths != staticLineLengths) {
876  delete[] lineLengths;
877  }
878 
879  return layout;
880 }
881 
882 ////////////////////////////////////////////////////////////////////////////////
883 /// destructor
884 
886 {
887  if (fChunks) {
888  delete[] fChunks;
889  }
890 }
891 
892 ////////////////////////////////////////////////////////////////////////////////
893 /// Use the information in the TGTextLayout object to display a multi-line,
894 /// justified string of text.
895 ///
896 /// This procedure is useful for simple widgets that need to display
897 /// single-font, multi-line text and want TGFont to handle the details.
898 ///
899 /// dst -- Window or pixmap in which to draw.
900 /// gc -- Graphics context to use for drawing text.
901 /// x, y -- Upper-left hand corner of rectangle in which to draw
902 /// (pixels).
903 /// firstChar -- The index of the first character to draw from the given
904 /// text item. 0 specfies the beginning.
905 /// lastChar -- The index just after the last character to draw from the
906 /// given text item. A number < 0 means to draw all characters.
907 
909  Int_t x, Int_t y, Int_t firstChar, Int_t lastChar) const
910 {
911  Int_t i, numDisplayChars, drawX;
912  LayoutChunk_t *chunk;
913 
914  if (lastChar < 0) lastChar = 100000000;
915  chunk = fChunks;
916 
917  for (i = 0; i < fNumChunks; i++) {
918  numDisplayChars = chunk->fNumDisplayChars;
919  if ((numDisplayChars > 0) && (firstChar < numDisplayChars)) {
920  if (firstChar <= 0) {
921  drawX = 0;
922  firstChar = 0;
923  } else {
924  fFont->MeasureChars(chunk->fStart, firstChar, 0, 0, &drawX);
925  }
926  if (lastChar < numDisplayChars) numDisplayChars = lastChar;
927  fFont->DrawChars(dst, gc, chunk->fStart + firstChar, numDisplayChars - firstChar,
928  x + chunk->fX + drawX, y + chunk->fY);
929  }
930  firstChar -= chunk->fNumChars;
931  lastChar -= chunk->fNumChars;
932 
933  if (lastChar <= 0) break;
934  chunk++;
935  }
936 }
937 
938 ////////////////////////////////////////////////////////////////////////////////
939 /// Use the information in the TGTextLayout object to display an underline
940 /// below an individual character. This procedure does not draw the text,
941 /// just the underline.
942 ///
943 /// This procedure is useful for simple widgets that need to display
944 /// single-font, multi-line text with an individual character underlined
945 /// and want TGFont to handle the details. To display larger amounts of
946 /// underlined text, construct and use an underlined font.
947 ///
948 /// dst -- Window or pixmap in which to draw.
949 /// gc -- Graphics context to use for drawing text.
950 /// x, y -- Upper-left hand corner of rectangle in which to draw
951 /// (pixels).
952 /// underline -- Index of the single character to underline, or -1 for
953 /// no underline.
954 
956  Int_t x, Int_t y, Int_t underline) const
957 {
958  int xx, yy, width, height;
959 
960  if ((CharBbox(underline, &xx, &yy, &width, &height) != 0)
961  && (width != 0)) {
962  gVirtualX->FillRectangle(dst, gc, x + xx,
963  y + yy + fFont->fFM.fAscent + fFont->fUnderlinePos,
964  (UInt_t) width, (UInt_t) fFont->fUnderlineHeight);
965  }
966 }
967 
968 ////////////////////////////////////////////////////////////////////////////////
969 /// Use the information in the TGTextLayout token to determine the character
970 /// closest to the given point. The point must be specified with respect to
971 /// the upper-left hand corner of the text layout, which is considered to be
972 /// located at (0, 0).
973 ///
974 /// Any point whose y-value is less that 0 will be considered closest to the
975 /// first character in the text layout; any point whose y-value is greater
976 /// than the height of the text layout will be considered closest to the last
977 /// character in the text layout.
978 ///
979 /// Any point whose x-value is less than 0 will be considered closest to the
980 /// first character on that line; any point whose x-value is greater than the
981 /// width of the text layout will be considered closest to the last character
982 /// on that line.
983 ///
984 /// The return value is the index of the character that was closest to the
985 /// point. Given a text layout with no characters, the value 0 will always
986 /// be returned, referring to a hypothetical zero-width placeholder character.
987 
989 {
990  LayoutChunk_t *chunk, *last;
991  Int_t i, n, dummy, baseline, pos;
992 
993  if (y < 0) {
994  // Point lies above any line in this layout. Return the index of
995  // the first char.
996 
997  return 0;
998  }
999 
1000  // Find which line contains the point.
1001 
1002  last = chunk = fChunks;
1003  for (i = 0; i < fNumChunks; i++) {
1004  baseline = chunk->fY;
1005  if (y < baseline + fFont->fFM.fDescent) {
1006  if (x < chunk->fX) {
1007  // Point is to the left of all chunks on this line. Return
1008  // the index of the first character on this line.
1009 
1010  return (chunk->fStart - fString);
1011  }
1012  if (x >= fWidth) {
1013 
1014  // If point lies off right side of the text layout, return
1015  // the last char in the last chunk on this line. Without
1016  // this, it might return the index of the first char that
1017  // was located outside of the text layout.
1018 
1019  x = INT_MAX;
1020  }
1021 
1022  // Examine all chunks on this line to see which one contains
1023  // the specified point.
1024 
1025  last = chunk;
1026  while ((i < fNumChunks) && (chunk->fY == baseline)) {
1027  if (x < chunk->fX + chunk->fTotalWidth) {
1028 
1029  // Point falls on one of the characters in this chunk.
1030 
1031  if (chunk->fNumDisplayChars < 0) {
1032 
1033  // This is a special chunk that encapsulates a single
1034  // tab or newline char.
1035 
1036  return (chunk->fStart - fString);
1037  }
1038  n = fFont->MeasureChars(chunk->fStart, chunk->fNumChars,
1039  x + 1 - chunk->fX, kTextPartialOK, &dummy);
1040  return ((chunk->fStart + n - 1) - fString);
1041  }
1042  last = chunk;
1043  chunk++;
1044  i++;
1045  }
1046 
1047  // Point is to the right of all chars in all the chunks on this
1048  // line. Return the index just past the last char in the last
1049  // chunk on this line.
1050 
1051  pos = (last->fStart + last->fNumChars) - fString;
1052  if (i < fNumChunks) pos--;
1053  return pos;
1054  }
1055  last = chunk;
1056  chunk++;
1057  }
1058 
1059  // Point lies below any line in this text layout. Return the index
1060  // just past the last char.
1061 
1062  return ((last->fStart + last->fNumChars) - fString);
1063 }
1064 
1065 ////////////////////////////////////////////////////////////////////////////////
1066 /// Use the information in the TGTextLayout token to return the bounding box
1067 /// for the character specified by index.
1068 ///
1069 /// The width of the bounding box is the advance width of the character, and
1070 /// does not include and left- or right-bearing. Any character that extends
1071 /// partially outside of the text layout is considered to be truncated at the
1072 /// edge. Any character which is located completely outside of the text
1073 /// layout is considered to be zero-width and pegged against the edge.
1074 ///
1075 /// The height of the bounding box is the line height for this font,
1076 /// extending from the top of the ascent to the bottom of the descent.
1077 /// Information about the actual height of the individual letter is not
1078 /// available.
1079 ///
1080 /// A text layout that contains no characters is considered to contain a
1081 /// single zero-width placeholder character.
1082 ///
1083 /// The return value is 0 if the index did not specify a character in the
1084 /// text layout, or non-zero otherwise. In that case, *bbox is filled with
1085 /// the bounding box of the character.
1086 ///
1087 /// layout -- Layout information, from a previous call to ComputeTextLayout().
1088 /// index -- The index of the character whose bbox is desired.
1089 /// x, y -- Filled with the upper-left hand corner, in pixels, of the
1090 /// bounding box for the character specified by index, if non-NULL.
1091 /// w, h -- Filled with the width and height of the bounding box for the
1092 /// character specified by index, if non-NULL.
1093 
1095 {
1096  LayoutChunk_t *chunk;
1097  Int_t i, xx = 0, ww = 0;
1098 
1099  if (index < 0) {
1100  return 0;
1101  }
1102 
1103  chunk = fChunks;
1104 
1105  for (i = 0; i < fNumChunks; i++) {
1106  if (chunk->fNumDisplayChars < 0) {
1107  if (!index) {
1108  xx = chunk->fX;
1109  ww = chunk->fTotalWidth;
1110  goto check;
1111  }
1112  } else if (index < chunk->fNumChars) {
1113  if (x) {
1114  fFont->MeasureChars(chunk->fStart, index, 0, 0, &xx);
1115  xx += chunk->fX;
1116  }
1117  if (w) {
1118  fFont->MeasureChars(chunk->fStart + index, 1, 0, 0, &ww);
1119  }
1120  goto check;
1121  }
1122  index -= chunk->fNumChars;
1123  chunk++;
1124  }
1125  if (!index) {
1126 
1127  // Special case to get location just past last char in layout.
1128 
1129  chunk--;
1130  xx = chunk->fX + chunk->fTotalWidth;
1131  ww = 0;
1132  } else {
1133  return 0;
1134  }
1135 
1136  // Ensure that the bbox lies within the text layout. This forces all
1137  // chars that extend off the right edge of the text layout to have
1138  // truncated widths, and all chars that are completely off the right
1139  // edge of the text layout to peg to the edge and have 0 width.
1140 
1141 check:
1142  if (y) {
1143  *y = chunk->fY - fFont->fFM.fAscent;
1144  }
1145  if (h) {
1146  *h = fFont->fFM.fAscent + fFont->fFM.fDescent;
1147  }
1148  if (xx > fWidth) {
1149  xx = fWidth;
1150  }
1151  if (x) {
1152  *x = xx;
1153  }
1154  if (w) {
1155  if (xx + ww > fWidth) {
1156  ww = fWidth - xx;
1157  }
1158  *w = ww;
1159  }
1160  return 1;
1161 }
1162 
1163 ////////////////////////////////////////////////////////////////////////////////
1164 /// Computes the distance in pixels from the given point to the given
1165 /// text layout. Non-displaying space characters that occur at the end of
1166 /// individual lines in the text layout are ignored for hit detection
1167 /// purposes.
1168 ///
1169 /// The return value is 0 if the point (x, y) is inside the text layout.
1170 /// If the point isn't inside the text layout then the return value is the
1171 /// distance in pixels from the point to the text item.
1172 ///
1173 /// x, y -- Coordinates of point to check, with respect to the upper-left
1174 /// corner of the text layout (in pixels).
1175 
1177 {
1178  Int_t i, x1, x2, y1, y2, xDiff, yDiff, dist, minDist, ascent, descent;
1179  LayoutChunk_t *chunk;
1180 
1181  ascent = fFont->fFM.fAscent;
1182  descent = fFont->fFM.fDescent;
1183 
1184  minDist = 0;
1185  chunk = fChunks;
1186  for (i = 0; i < fNumChunks; i++) {
1187  if (chunk->fStart[0] == '\n') {
1188 
1189  // Newline characters are not counted when computing distance
1190  // (but tab characters would still be considered).
1191 
1192  chunk++;
1193  continue;
1194  }
1195  x1 = chunk->fX;
1196  y1 = chunk->fY - ascent;
1197  x2 = chunk->fX + chunk->fDisplayWidth;
1198  y2 = chunk->fY + descent;
1199 
1200  if (x < x1) {
1201  xDiff = x1 - x;
1202  } else if (x >= x2) {
1203  xDiff = x - x2 + 1;
1204  } else {
1205  xDiff = 0;
1206  }
1207 
1208  if (y < y1) {
1209  yDiff = y1 - y;
1210  } else if (y >= y2) {
1211  yDiff = y - y2 + 1;
1212  } else {
1213  yDiff = 0;
1214  }
1215  if ((xDiff == 0) && (yDiff == 0)) {
1216  return 0;
1217  }
1218  dist = (int) TMath::Hypot((Double_t) xDiff, (Double_t) yDiff);
1219  if ((dist < minDist) || !minDist) {
1220  minDist = dist;
1221  }
1222  chunk++;
1223  }
1224  return minDist;
1225 }
1226 
1227 ////////////////////////////////////////////////////////////////////////////////
1228 /// Determines whether a text layout lies entirely inside, entirely outside,
1229 /// or overlaps a given rectangle. Non-displaying space characters that occur
1230 /// at the end of individual lines in the text layout are ignored for
1231 /// intersection calculations.
1232 ///
1233 /// The return value is -1 if the text layout is entirely outside of the
1234 /// rectangle, 0 if it overlaps, and 1 if it is entirely inside of the
1235 /// rectangle.
1236 ///
1237 /// x, y -- Upper-left hand corner, in pixels, of rectangular area to compare
1238 /// with text layout. Coordinates are with respect to the upper-left
1239 /// hand corner of the text layout itself.
1240 /// w, h -- The width and height of the above rectangular area, in pixels.
1241 
1243 {
1244  Int_t result, i, x1, y1, x2, y2;
1245  LayoutChunk_t *chunk;
1246  Int_t left, top, right, bottom;
1247 
1248  // Scan the chunks one at a time, seeing whether each is entirely in,
1249  // entirely out, or overlapping the rectangle. If an overlap is
1250  // detected, return immediately; otherwise wait until all chunks have
1251  // been processed and see if they were all inside or all outside.
1252 
1253  chunk = fChunks;
1254 
1255  left = x;
1256  top = y;
1257  right = x + w;
1258  bottom = y + h;
1259 
1260  result = 0;
1261  for (i = 0; i < fNumChunks; i++) {
1262  if (chunk->fStart[0] == '\n') {
1263 
1264  // Newline characters are not counted when computing area
1265  // intersection (but tab characters would still be considered).
1266 
1267  chunk++;
1268  continue;
1269  }
1270  x1 = chunk->fX;
1271  y1 = chunk->fY - fFont->fFM.fAscent;
1272  x2 = chunk->fX + chunk->fDisplayWidth;
1273  y2 = chunk->fY + fFont->fFM.fDescent;
1274 
1275  if ((right < x1) || (left >= x2) || (bottom < y1) || (top >= y2)) {
1276  if (result == 1) {
1277  return 0;
1278  }
1279  result = -1;
1280  } else if ((x1 < left) || (x2 >= right) || (y1 < top) || (y2 >= bottom)) {
1281  return 0;
1282  } else if (result == -1) {
1283  return 0;
1284  } else {
1285  result = 1;
1286  }
1287  chunk++;
1288  }
1289  return result;
1290 }
1291 
1292 ////////////////////////////////////////////////////////////////////////////////
1293 /// Outputs the contents of a text layout in Postscript format. The set of
1294 /// lines in the text layout will be rendered by the user supplied Postscript
1295 /// function. The function should be of the form:
1296 ///
1297 /// justify x y string function --
1298 ///
1299 /// Justify is -1, 0, or 1, depending on whether the following string should
1300 /// be left, center, or right justified, x and y is the location for the
1301 /// origin of the string, string is the sequence of characters to be printed,
1302 /// and function is the name of the caller-provided function; the function
1303 /// should leave nothing on the stack.
1304 ///
1305 /// The meaning of the origin of the string (x and y) depends on the
1306 /// justification. For left justification, x is where the left edge of the
1307 /// string should appear. For center justification, x is where the center of
1308 /// the string should appear. And for right justification, x is where the
1309 /// right edge of the string should appear. This behavior is necessary
1310 /// because, for example, right justified text on the screen is justified
1311 /// with screen metrics. The same string needs to be justified with printer
1312 /// metrics on the printer to appear in the correct place with respect to
1313 /// other similarly justified strings. In all circumstances, y is the
1314 /// location of the baseline for the string.
1315 ///
1316 /// result is modified to hold the Postscript code that will render the text
1317 /// layout.
1318 
1320 {
1321 #define MAXUSE 128
1322  char buf[MAXUSE + 10];
1323  LayoutChunk_t *chunk;
1324  Int_t i, j, used, c, baseline;
1325 
1326  chunk = fChunks;
1327  baseline = chunk->fY;
1328  used = 0;
1329  buf[used++] = '(';
1330 
1331  for (i = 0; i < fNumChunks; i++) {
1332  if (baseline != chunk->fY) {
1333  buf[used++] = ')';
1334  buf[used++] = '\n';
1335  buf[used++] = '(';
1336  baseline = chunk->fY;
1337  }
1338  if (chunk->fNumDisplayChars <= 0) {
1339  if (chunk->fStart[0] == '\t') {
1340  buf[used++] = '\\';
1341  buf[used++] = 't';
1342  }
1343  } else {
1344  for (j = 0; j < chunk->fNumDisplayChars; j++) {
1345  c = UChar_t(chunk->fStart[j]);
1346  if ((c == '(') || (c == ')') || (c == '\\') || (c < 0x20) || (c >= UChar_t(0x7f))) {
1347 
1348  // Tricky point: the "03" is necessary in the sprintf
1349  // below, so that a full three digits of octal are
1350  // always generated. Without the "03", a number
1351  // following this sequence could be interpreted by
1352  // Postscript as part of this sequence.
1353 
1354  // coverity[secure_coding]
1355  sprintf(buf + used, "\\%03o", c);
1356  used += 4;
1357  } else {
1358  buf[used++] = c;
1359  }
1360  if (used >= MAXUSE) {
1361  buf[used] = '\0';
1362  result->Append(buf);
1363  used = 0;
1364  }
1365  }
1366  }
1367  if (used >= MAXUSE) {
1368  // If there are a whole bunch of returns or tabs in a row,
1369  // then buf[] could get filled up.
1370 
1371  buf[used] = '\0';
1372  result->Append(buf);
1373  used = 0;
1374  }
1375  chunk++;
1376  }
1377  buf[used++] = ')';
1378  buf[used++] = '\n';
1379  buf[used] = '\0';
1380 
1381  result->Append(buf);
1382 }
1383 
1384 ////////////////////////////////////////////////////////////////////////////////
1385 /// Helper function for ComputeTextLayout(). Encapsulates a measured set of
1386 /// characters in a chunk that can be quickly drawn.
1387 ///
1388 /// Returns a pointer to the new chunk in the text layout. The text layout is
1389 /// reallocated to hold more chunks as necessary.
1390 ///
1391 /// Currently, ComputeTextLayout() stores contiguous ranges of "normal"
1392 /// characters in a chunk, along with individual tab and newline chars in
1393 /// their own chunks. All characters in the text layout are accounted for.
1394 
1395 LayoutChunk_t *TGFont::NewChunk(TGTextLayout *layout, Int_t *maxPtr,
1396  const char *start, Int_t numChars,
1397  Int_t curX, Int_t newX, Int_t y) const
1398 {
1399  LayoutChunk_t *chunk;
1400  Int_t i, maxChunks;
1401 
1402  maxChunks = *maxPtr;
1403  if (layout->fNumChunks == maxChunks) {
1404  if (maxChunks == 0) {
1405  maxChunks = 1;
1406  } else {
1407  maxChunks *= 2;
1408  }
1409  chunk = new LayoutChunk_t[maxChunks];
1410 
1411  if (layout->fNumChunks > 0) {
1412  for (i=0; i<layout->fNumChunks; ++i) chunk[i] = layout->fChunks[i];
1413  delete[] layout->fChunks;
1414  }
1415  layout->fChunks = chunk;
1416  *maxPtr = maxChunks;
1417  }
1418 
1419  chunk = &layout->fChunks[layout->fNumChunks];
1420  chunk->fStart = start;
1421  chunk->fNumChars = numChars;
1422  chunk->fNumDisplayChars = numChars;
1423  chunk->fX = curX;
1424  chunk->fY = y;
1425  chunk->fTotalWidth = newX - curX;
1426  chunk->fDisplayWidth = newX - curX;
1427  layout->fNumChunks++;
1428 
1429  return chunk;
1430 }
1431 
1432 ////////////////////////////////////////////////////////////////////////////////
1433 /// Draw a string of characters on the screen. DrawCharsExp() expands
1434 /// control characters that occur in the string to \X or \xXX sequences.
1435 /// DrawChars() just draws the strings.
1436 ///
1437 /// dst -- Window or pixmap in which to draw.
1438 /// gc -- Graphics context for drawing characters.
1439 /// source -- Characters to be displayed. Need not be'\0' terminated.
1440 /// For DrawChars(), all meta-characters (tabs, control
1441 /// characters, and newlines) should be stripped out of the
1442 /// string that is passed to this function. If they are not
1443 /// stripped out, they will be displayed as regular printing
1444 /// characters.
1445 /// numChars -- Number of characters in string.
1446 /// x, y -- Coordinates at which to place origin of string when drawing.
1447 
1449  const char *source, Int_t numChars,
1450  Int_t x, Int_t y) const
1451 {
1452  const char *p;
1453  Int_t i, type;
1454  char buf[4];
1455 
1456  p = source;
1457  for (i = 0; i < numChars; i++) {
1458  type = fTypes[UChar_t(*p)];
1459  if (type != kCharNormal) {
1460  DrawChars(dst, gc, source, p - source, x, y);
1461  x += gVirtualX->TextWidth(fFontStruct, source, p - source);
1462  if (type == kCharReplace) {
1463  DrawChars(dst, gc, buf, GetControlCharSubst(UChar_t(*p), buf), x, y);
1464  x += fWidths[UChar_t(*p)];
1465  }
1466  source = p + 1;
1467  }
1468  p++;
1469  }
1470 
1471  DrawChars(dst, gc, source, p - source, x, y);
1472 }
1473 
1474 ////////////////////////////////////////////////////////////////////////////////
1475 /// Perform a quick sanity check to ensure we won't overflow the X
1476 /// coordinate space.
1477 
1479  const char *source, Int_t numChars,
1480  Int_t x, Int_t y) const
1481 {
1482  Int_t max_width = gVirtualX->TextWidth(fFontStruct, "@", 1);
1483 
1484  if ((x + (max_width * numChars) > 0x7fff)) {
1485  int length;
1486 
1487  // The string we are being asked to draw is too big and would overflow
1488  // the X coordinate space. Unfortunatley X servers aren't too bright
1489  // and so they won't deal with this case cleanly. We need to truncate
1490  // the string before sending it to X.
1491 
1492  numChars = MeasureChars(source, numChars, 0x7fff - x, 0, &length);
1493  }
1494 
1495  gVirtualX->DrawString(dst, gc, x, y, source, numChars);
1496 
1497  if (fFA.fUnderline != 0) {
1498  gVirtualX->FillRectangle(dst, gc, x, y + fUnderlinePos,
1499  (UInt_t) gVirtualX->TextWidth(fFontStruct, source, numChars),
1500  (UInt_t) fBarHeight);
1501  }
1502  if (fFA.fOverstrike != 0) {
1503  y -= fFM.fDescent + fFM.fAscent / 10;
1504  gVirtualX->FillRectangle(dst, gc, x, y,
1505  (UInt_t) gVirtualX->TextWidth(fFontStruct, source, numChars),
1506  (UInt_t) fBarHeight);
1507  }
1508 }
1509 
1510 ////////////////////////////////////////////////////////////////////////////////
1511 /// Create a font pool.
1512 
1514 {
1515  fClient = client;
1516  fList = new THashTable(50);
1517  fList->SetOwner();
1518 
1519  fNamedTable = new THashTable(50);
1520  fNamedTable->SetOwner();
1521 
1522  fUidTable = new THashTable(50);
1523  fUidTable->SetOwner();
1524 }
1525 
1526 ////////////////////////////////////////////////////////////////////////////////
1527 /// Cleanup font pool.
1528 
1530 {
1531  delete fList;
1532 }
1533 
1534 ////////////////////////////////////////////////////////////////////////////////
1535 /// Get the specified font.
1536 /// The font can be one of the following forms:
1537 /// XLFD (see X documentation)
1538 /// "Family [size [style] [style ...]]"
1539 /// Returns 0 if error or no font can be found.
1540 /// If fixedDefault is false the "fixed" font will not be substituted
1541 /// as fallback when the asked for font does not exist.
1542 
1543 TGFont *TGFontPool::GetFont(const char *font, Bool_t fixedDefault)
1544 {
1545  if (!font || !*font) {
1546  Error("GetFont", "argument may not be 0 or empty");
1547  return 0;
1548  }
1549 
1550  TGFont *f = (TGFont*)fList->FindObject(font);
1551 
1552  if (f) {
1553  f->AddReference();
1554  return f;
1555  }
1556 
1557  TNamedFont *nf = (TNamedFont*)fNamedTable->FindObject(font);
1558 
1559  if (nf) {
1560  // Construct a font based on a named font.
1561  nf->AddReference();
1562  f = GetFontFromAttributes(&nf->fFA, 0);
1563 
1564  } else {
1565 
1566  // Native font (aka string in XLFD format)?
1567  Int_t errsav = gErrorIgnoreLevel;
1569 
1570  f = GetNativeFont(font, fixedDefault);
1571  gErrorIgnoreLevel = errsav;
1572 
1573  if (!f) {
1574  FontAttributes_t fa;
1575 
1576  if (!ParseFontName(font, &fa)) {
1577  //fontCache.DeleteHashEntry(cacheHash);
1578 
1579  return 0;
1580  }
1581 
1582  // String contained the attributes inline.
1583  f = GetFontFromAttributes(&fa, 0);
1584  }
1585  }
1586 
1587  if (!f) return 0;
1588 
1589  fList->Add(f);
1590 
1591  f->SetRefCount(1);
1592  //f->cacheHash = cacheHash;
1593  f->fNamedHash = nf;
1594 
1595  f->MeasureChars("0", 1, 0, 0, &f->fTabWidth);
1596 
1597  if (!f->fTabWidth) {
1598  f->fTabWidth = f->fFM.fMaxWidth;
1599  }
1600  f->fTabWidth *= 8;
1601 
1602  // Make sure the tab width isn't zero (some fonts may not have enough
1603  // information to set a reasonable tab width).
1604 
1605  if (!f->fTabWidth) {
1606  f->fTabWidth = 1;
1607  }
1608 
1609  // Get information used for drawing underlines in generic code on a
1610  // non-underlined font.
1611 
1612  Int_t descent = f->fFM.fDescent;
1613  f->fUnderlinePos = descent/2; // ==!== could be set by MakeFont()
1614  f->fUnderlineHeight = f->fFA.fPointsize/10;
1615 
1616  if (!f->fUnderlineHeight) {
1617  f->fUnderlineHeight = 1;
1618  }
1619  if (f->fUnderlinePos + f->fUnderlineHeight > descent) {
1620 
1621  // If this set of values would cause the bottom of the underline
1622  // bar to stick below the descent of the font, jack the underline
1623  // up a bit higher.
1624 
1625  f->fUnderlineHeight = descent - f->fUnderlinePos;
1626 
1627  if (!f->fUnderlineHeight) {
1628  f->fUnderlinePos--;
1629  f->fUnderlineHeight = 1;
1630  }
1631  }
1632 
1633  return f;
1634 }
1635 
1636 ////////////////////////////////////////////////////////////////////////////////
1637 /// Use font, i.e. increases ref count of specified font. Returns 0
1638 /// if font is not found.
1639 
1641 {
1642  TGFont *f = (TGFont*)fList->FindObject(font);
1643 
1644  if (f) {
1645  f->AddReference();
1646  return f;
1647  }
1648 
1649  return 0;
1650 }
1651 
1652 ////////////////////////////////////////////////////////////////////////////////
1653 /// Use font, i.e. increases ref count of specified font.
1654 
1656 {
1657  TGFont *f = FindFont(fs);
1658 
1659  if (f) {
1660  f->AddReference();
1661  return f;
1662  }
1663 
1664  static int i = 0;
1665  f = MakeFont(0, fs, TString::Format("unknown-%d", i));
1666  fList->Add(f);
1667  i++;
1668 
1669  return f;
1670 }
1671 
1672 ////////////////////////////////////////////////////////////////////////////////
1673 /// Returns font specified bay family, pixel/point size, weight and slant
1674 /// negative value of ptsize means size in pixels
1675 /// positive value of ptsize means size in points
1676 ///
1677 /// For example:
1678 /// TGFont *font = fpool->GetFont("helvetica", -9, kFontWeightNormal, kFontSlantRoman);
1679 /// font->Print();
1680 
1681 TGFont *TGFontPool::GetFont(const char *family, Int_t ptsize, Int_t weight, Int_t slant)
1682 {
1683  const char *s;
1684  TString tmp;
1685 
1686  tmp = TString::Format("%s %d", family, ptsize);
1687  s = FindStateString(gWeightMap, weight);
1688  if (s) {
1689  tmp += " ";
1690  tmp + s;
1691  }
1692  s = FindStateString(gSlantMap, slant);
1693  if (s) {
1694  tmp += " ";
1695  tmp += s;
1696  }
1697  return GetFont(tmp.Data());
1698 }
1699 
1700 ////////////////////////////////////////////////////////////////////////////////
1701 /// Free font. If ref count is 0 delete font.
1702 
1703 void TGFontPool::FreeFont(const TGFont *font)
1704 {
1705  TGFont *f = (TGFont*) fList->FindObject(font);
1706  if (f) {
1707  if (f->RemoveReference() == 0) {
1708  if (font->fNamedHash) {
1709 
1710  // The font is being deleted. Determine if the associated named
1711  // font definition should and/or can be deleted too.
1712 
1713  TNamedFont *nf = (TNamedFont *) font->fNamedHash;
1714 
1715  if ((nf->RemoveReference() == 0) && (nf->fDeletePending != 0)) {
1716  fNamedTable->Remove(nf);
1717  delete nf;
1718  }
1719  }
1720  fList->Remove(f);
1721  delete font;
1722  }
1723  }
1724 }
1725 
1726 ////////////////////////////////////////////////////////////////////////////////
1727 /// Find font based on its font struct. Returns 0 if font is not found.
1728 
1730 {
1731  TIter next(fList);
1732  TGFont *f = 0;
1733 
1734  while ((f = (TGFont*) next())) {
1735  if (f->fFontStruct == font) {
1736  return f;
1737  }
1738  }
1739 
1740  return 0;
1741 }
1742 
1743 ////////////////////////////////////////////////////////////////////////////////
1744 /// Find font based on its font handle. Returns 0 if font is not found.
1745 
1747 {
1748  TIter next(fList);
1749  TGFont *f = 0;
1750 
1751  while ((f = (TGFont*) next())) {
1752  if (f->fFontH == font) {
1753  return f;
1754  }
1755  }
1756 
1757  return 0;
1758 }
1759 
1760 ////////////////////////////////////////////////////////////////////////////////
1761 /// Given a string, this procedure returns a unique identifier for the string.
1762 ///
1763 /// This procedure returns a pointer to a new char string corresponding to
1764 /// the "string" argument. The new string has a value identical to string
1765 /// (strcmp will return 0), but it's guaranteed that any other calls to this
1766 /// procedure with a string equal to "string" will return exactly the same
1767 /// result (i.e. can compare pointer *values* directly, without having to
1768 /// call strcmp on what they point to).
1769 
1770 const char *TGFontPool::GetUid(const char *string)
1771 {
1772  TObjString *obj = 0;
1773  obj = (TObjString*)fUidTable->FindObject(string);
1774 
1775  if (!obj) {
1776  obj = new TObjString(string);
1777  fUidTable->Add(obj);
1778  }
1779 
1780  return (const char *)obj->GetName();
1781 }
1782 
1783 ////////////////////////////////////////////////////////////////////////////////
1784 /// Return information about the font attributes as an array of strings.
1785 ///
1786 /// An array of FONT_NUMFIELDS strings is returned holding the value of the
1787 /// font attributes in the following order:
1788 /// family size weight slant underline overstrike
1789 
1791 {
1792  Int_t i, num;
1793  const char *str = 0;
1794 
1795  char **result = new char*[FONT_NUMFIELDS];
1796 
1797  for (i = 0; i < FONT_NUMFIELDS; ++i) {
1798  str = 0;
1799  num = 0;
1800 
1801  switch (i) {
1802  case FONT_FAMILY:
1803  str = fa->fFamily;
1804  if (!str) str = "";
1805  break;
1806 
1807  case FONT_SIZE:
1808  num = fa->fPointsize;
1809  break;
1810 
1811  case FONT_WEIGHT:
1812  str = FindStateString(gWeightMap, fa->fWeight);
1813  break;
1814 
1815  case FONT_SLANT:
1816  str = FindStateString(gSlantMap, fa->fSlant);
1817  break;
1818 
1819  case FONT_UNDERLINE:
1820  num = fa->fUnderline;
1821  break;
1822 
1823  case FONT_OVERSTRIKE:
1824  num = fa->fOverstrike;
1825  break;
1826  }
1827 
1828  if (str) {
1829  int len = strlen(str)+1;
1830  result[i] = new char[len];
1831  strlcpy(result[i], str, len);
1832  } else {
1833  result[i] = new char[20];
1834  snprintf(result[i], 20, "%d", num);
1835  }
1836  }
1837 
1838  return result;
1839 }
1840 
1841 ////////////////////////////////////////////////////////////////////////////////
1842 /// Free attributes info.
1843 
1845 {
1846  Int_t i;
1847 
1848  if (info) {
1849  for (i = 0; i < FONT_NUMFIELDS; ++i) {
1850  if (info[i]) {
1851  delete[] info[i];
1852  }
1853  }
1854  delete[] info;
1855  }
1856 }
1857 
1858 ////////////////////////////////////////////////////////////////////////////////
1859 /// List all fonts in the pool.
1860 
1861 void TGFontPool::Print(Option_t *opt) const
1862 {
1863  fList->Print(opt);
1864 }
1865 
1866 ////////////////////////////////////////////////////////////////////////////////
1867 /// Save the used font as a C++ statement(s) on output stream out.
1868 
1869 void TGFont::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
1870 {
1871  char quote = '"';
1872 
1873  if (gROOT->ClassSaved(TGFont::Class())) {
1874  out << std::endl;
1875  } else {
1876  // declare a font object to reflect required user changes
1877  out << std::endl;
1878  out << " TGFont *ufont; // will reflect user font changes" << std::endl;
1879  }
1880  out << " ufont = gClient->GetFont(" << quote << GetName() << quote << ");" << std::endl;
1881 }
1882 
1883 ////////////////////////////////////////////////////////////////////////////////
1884 
1885 static char *GetToken(char *str)
1886 {
1887  static char *p = 0;
1888  char *retp;
1889 
1890  if (str) p = str;
1891 
1892  if (!p) {
1893  return 0;
1894  }
1895  if (!*p) {
1896  return 0;
1897  }
1898 
1899  while (*p && ((*p == ' ') || (*p == '\t'))) { // skip spaces
1900  ++p;
1901  }
1902 
1903  if (!*p) {
1904  return 0;
1905  }
1906 
1907  if (*p == '"') { // quoted string
1908  retp = ++p;
1909 
1910  if (!*p) {
1911  return 0;
1912  }
1913 
1914  while (*p && (*p != '"')) {
1915  ++p;
1916  }
1917 
1918  if (*p == '"') {
1919  *p++ = '\0';
1920  }
1921  } else {
1922  retp = p;
1923  while (*p && (*p != ' ') && (*p != '\t')) {
1924  ++p;
1925  }
1926  if (*p) {
1927  *p++ = '\0';
1928  }
1929  }
1930 
1931  return retp;
1932 }
1933 
1934 ////////////////////////////////////////////////////////////////////////////////
1935 /// Converts a string into a set of font attributes that can be used to
1936 /// construct a font.
1937 ///
1938 /// The string can be one of the following forms:
1939 /// XLFD (see X documentation)
1940 /// "Family [size [style] [style ...]]"
1941 ///
1942 /// The return value is kFALSE if the object was syntactically
1943 /// invalid. Otherwise, fills the font attribute buffer with the values
1944 /// parsed from the string and returns kTRUE. The structure must already be
1945 /// properly initialized.
1946 
1948 {
1949  char *s;
1950  int n, result;
1951 
1952  XLFDAttributes_t xa;
1953 
1954  int len = strlen(string)+1;
1955  char *str = new char[len];
1956  strlcpy(str, string, len);
1957 
1958  if (*str == '-' || *str == '*') {
1959 
1960  // This appears to be an XLFD.
1961 
1962  xa.fFA = *fa;
1963  result = ParseXLFD(str, &xa);
1964  if (result) {
1965  *fa = xa.fFA;
1966  delete[] str;
1967  return kTRUE; //OK
1968  }
1969  }
1970 
1971  // Wasn't an XLFD or "-option value" string. Try it as a
1972  // "font size style" list.
1973 
1974  s = GetToken(str);
1975  if (!s) {
1976  delete[] str;
1977  return kFALSE;
1978  }
1979  fa->fFamily = GetUid(s);
1980 
1981  s = GetToken(0);
1982 
1983  if (s) {
1984  char *end;
1985 
1986  fa->fPointsize = strtol(s, &end, 0);
1987  if ((errno == ERANGE) || (end == s)) {
1988  return kFALSE;
1989  }
1990  }
1991 
1992  while ((s = GetToken(0))) {
1993  n = FindStateNum(gWeightMap, s);
1994  if ((EFontWeight)n != kFontWeightUnknown) {
1995  fa->fWeight = n;
1996  continue;
1997  }
1998  n = FindStateNum(gSlantMap, s);
1999  // tell coverity that n is an integer value, and not an enum, even if
2000  // we compare it with an enum value (which is -1 in both case anyway)
2001  // coverity[mixed_enums]
2002  if ((EFontSlant)n != kFontSlantUnknown) {
2003  fa->fSlant = n;
2004  continue;
2005  }
2006  n = FindStateNum(gUnderlineMap, s);
2007  if (n) {
2008  fa->fUnderline = n;
2009  continue;
2010  }
2011  n = FindStateNum(gOverstrikeMap, s);
2012  if (n) {
2013  fa->fOverstrike = n;
2014  continue;
2015  }
2016 
2017  // Unknown style.
2018 
2019  delete[] str;
2020  return kFALSE;
2021  }
2022 
2023  delete[] str;
2024  return kTRUE;
2025 }
2026 
2027 ////////////////////////////////////////////////////////////////////////////////
2028 /// Break up a fully specified XLFD into a set of font attributes.
2029 ///
2030 /// Return value is kFALSE if string was not a fully specified XLFD.
2031 /// Otherwise, fills font attribute buffer with the values parsed from
2032 /// the XLFD and returns kTRUE.
2033 ///
2034 /// string -- Parseable font description string.
2035 /// xa -- XLFD attributes structure whose fields are to be modified.
2036 /// Structure must already be properly initialized.
2037 
2038 Bool_t TGFontPool::ParseXLFD(const char *string, XLFDAttributes_t *xa)
2039 {
2040  char *src;
2041  const char *str;
2042  int i, j;
2043  char *field[XLFD_NUMFIELDS + 2];
2044  TString ds("");
2045 
2046  memset(field, '\0', sizeof (field));
2047 
2048  str = string;
2049  if (*str == '-') str++;
2050 
2051  ds.Append((char *) str);
2052  src = (char*)ds.Data();
2053 
2054  field[0] = src;
2055  for (i = 0; *src != '\0'; src++) {
2056  if (isupper(UChar_t(*src))) {
2057  *src = tolower(UChar_t(*src));
2058  }
2059  if (*src == '-') {
2060  i++;
2061  if (i > XLFD_NUMFIELDS) {
2062  break;
2063  }
2064  *src = '\0';
2065  field[i] = src + 1;
2066  }
2067  }
2068 
2069  // An XLFD of the form -adobe-times-medium-r-*-12-*-* is pretty common,
2070  // but it is (strictly) malformed, because the first * is eliding both
2071  // the Setwidth and the Addstyle fields. If the Addstyle field is a
2072  // number, then assume the above incorrect form was used and shift all
2073  // the rest of the fields up by one, so the number gets interpreted
2074  // as a pixelsize.
2075 
2076  if ((i > XLFD_ADD_STYLE) && (FieldSpecified(field[XLFD_ADD_STYLE]))) {
2077  if (atoi(field[XLFD_ADD_STYLE]) != 0) {
2078  for (j = XLFD_NUMFIELDS - 1; j >= XLFD_ADD_STYLE; j--) {
2079  field[j + 1] = field[j];
2080  }
2081  field[XLFD_ADD_STYLE] = 0;
2082  i++;
2083  }
2084  }
2085 
2086  // Bail if we don't have enough of the fields (up to pointsize).
2087 
2088  if (i < XLFD_FAMILY) {
2089  return kFALSE;
2090  }
2091  if (FieldSpecified(field[XLFD_FOUNDRY])) {
2092  xa->fFoundry = GetUid(field[XLFD_FOUNDRY]);
2093  }
2094  if (FieldSpecified(field[XLFD_FAMILY])) {
2095  xa->fFA.fFamily = GetUid(field[XLFD_FAMILY]);
2096  }
2097  if (FieldSpecified(field[XLFD_WEIGHT])) {
2098  xa->fFA.fWeight = FindStateNum(gXlfdgWeightMap, field[XLFD_WEIGHT]);
2099  }
2100  if (FieldSpecified(field[XLFD_SLANT])) {
2101  xa->fSlant = FindStateNum(gXlfdSlantMap, field[XLFD_SLANT]);
2102  if (xa->fSlant == kFontSlantRoman) {
2103  xa->fFA.fSlant = kFontSlantRoman;
2104  } else {
2105  xa->fFA.fSlant = kFontSlantItalic;
2106  }
2107  }
2108  if (FieldSpecified(field[XLFD_SETWIDTH])) {
2109  xa->fSetwidth = FindStateNum(gXlfdSetwidthMap, field[XLFD_SETWIDTH]);
2110  }
2111  // XLFD_ADD_STYLE ignored.
2112 
2113  // Pointsize in tenths of a point, but treat it as tenths of a pixel.
2114 
2115  if (FieldSpecified(field[XLFD_POINT_SIZE])) {
2116  if (field[XLFD_POINT_SIZE][0] == '[') {
2117 
2118  // Some X fonts have the point size specified as follows:
2119  //
2120  // [ N1 N2 N3 N4 ]
2121  //
2122  // where N1 is the point size (in points, not decipoints!), and
2123  // N2, N3, and N4 are some additional numbers that I don't know
2124  // the purpose of, so I ignore them.
2125 
2126  xa->fFA.fPointsize = atoi(field[XLFD_POINT_SIZE] + 1);
2127  } else {
2128  char *end;
2129 
2130  xa->fFA.fPointsize = strtol(field[XLFD_POINT_SIZE], &end, 0);
2131  if (errno == ERANGE || end == field[XLFD_POINT_SIZE]) {
2132  return kFALSE;
2133  }
2134  xa->fFA.fPointsize /= 10;
2135  }
2136  }
2137 
2138  // Pixel height of font. If specified, overrides pointsize.
2139 
2140  if (FieldSpecified(field[XLFD_PIXEL_SIZE])) {
2141  if (field[XLFD_PIXEL_SIZE][0] == '[') {
2142 
2143  // Some X fonts have the pixel size specified as follows:
2144  //
2145  // [ N1 N2 N3 N4 ]
2146  //
2147  // where N1 is the pixel size, and where N2, N3, and N4
2148  // are some additional numbers that I don't know
2149  // the purpose of, so I ignore them.
2150 
2151  xa->fFA.fPointsize = atoi(field[XLFD_PIXEL_SIZE] + 1);
2152  } else {
2153  char *end;
2154 
2155  xa->fFA.fPointsize = strtol(field[XLFD_PIXEL_SIZE], &end, 0);
2156  if (errno == ERANGE || end == field[XLFD_PIXEL_SIZE]) {
2157  return kFALSE;
2158  }
2159  }
2160  }
2161  xa->fFA.fPointsize = -xa->fFA.fPointsize;
2162 
2163  // XLFD_RESOLUTION_X ignored.
2164 
2165  // XLFD_RESOLUTION_Y ignored.
2166 
2167  // XLFD_SPACING ignored.
2168 
2169  // XLFD_AVERAGE_WIDTH ignored.
2170 
2171  if (FieldSpecified(field[XLFD_REGISTRY])) {
2172  xa->fCharset = FindStateNum(gXlfdCharsetMap, field[XLFD_REGISTRY]);
2173  }
2174  if (FieldSpecified(field[XLFD_ENCODING])) {
2175  xa->fEncoding = atoi(field[XLFD_ENCODING]);
2176  }
2177 
2178  return kTRUE;
2179 }
2180 
2181 ////////////////////////////////////////////////////////////////////////////////
2182 /// Given a lookup table, map a string to a number in the table.
2183 ///
2184 /// If strKey was equal to the string keys of one of the elements in the
2185 /// table, returns the numeric key of that element. Returns the numKey
2186 /// associated with the last element (the NULL string one) in the table
2187 /// if strKey was not equal to any of the string keys in the table.
2188 
2189 Int_t TGFontPool::FindStateNum(const FontStateMap_t *map, const char *strKey)
2190 {
2191  const FontStateMap_t *m;
2192 
2193  if (!map->fStrKey) {
2194  return 0;
2195  }
2196 
2197  for (m = map; m->fStrKey != 0; m++) {
2198  if (strcasecmp(strKey, m->fStrKey) == 0) {
2199  return m->fNumKey;
2200  }
2201  }
2202  return m->fNumKey;
2203 }
2204 
2205 ////////////////////////////////////////////////////////////////////////////////
2206 /// Given a lookup table, map a number to a string in the table.
2207 ///
2208 /// If numKey was equal to the numeric key of one of the elements in the
2209 /// table, returns the string key of that element. Returns NULL if numKey
2210 /// was not equal to any of the numeric keys in the table
2211 
2212 const char *TGFontPool::FindStateString(const FontStateMap_t *map, Int_t numKey)
2213 {
2214  for ( ; map->fStrKey != 0; map++) {
2215  if (numKey == map->fNumKey) return map->fStrKey;
2216  }
2217  return 0;
2218 }
2219 
2220 ////////////////////////////////////////////////////////////////////////////////
2221 /// Helper function for ParseXLFD(). Determines if a field in the XLFD was
2222 /// set to a non-null, non-don't-care value.
2223 ///
2224 /// The return value is kFALSE if the field in the XLFD was not set and
2225 /// should be ignored, kTRUE otherwise.
2226 ///
2227 /// field -- The field of the XLFD to check. Strictly speaking, only when
2228 /// the string is "*" does it mean don't-care. However, an
2229 /// unspecified or question mark is also interpreted as don't-care.
2230 
2232 {
2233  char ch;
2234 
2235  if (!field) {
2236  return kFALSE;
2237  }
2238  ch = field[0];
2239 
2240  return (ch != '*' && ch != '?');
2241 }
2242 
2243 ////////////////////////////////////////////////////////////////////////////////
2244 /// Given a font, return a textual string identifying it.
2245 
2246 const char *TGFontPool::NameOfFont(TGFont *font)
2247 {
2248  return font->GetName();
2249 }
2250 
2251 ////////////////////////////////////////////////////////////////////////////////
2252 /// Return information about the font families that are available on the
2253 /// current display.
2254 ///
2255 /// An array of strings is returned holding a list of all the available font
2256 /// families. The array is terminated with a NULL pointer.
2257 
2259 {
2260  Int_t i, numNames;
2261  char *family, *end, *p;
2262 
2263  THashTable familyTable(100);
2264  familyTable.SetOwner();
2265 
2266  char **nameList;
2267  char **dst;
2268 
2269  // coverity[returned_null]
2270  // coverity[dereference]
2271  nameList = gVirtualX->ListFonts("*", 10000, numNames);
2272 
2273  for (i = 0; i < numNames; i++) {
2274  if (nameList[i][0] != '-') {
2275  continue;
2276  }
2277  family = strchr(nameList[i] + 1, '-');
2278  if (!family) {
2279  continue;
2280  }
2281  family++;
2282  end = strchr(family, '-');
2283  if (!end) {
2284  continue;
2285  }
2286  *end = '\0';
2287  for (p = family; *p != '\0'; p++) {
2288  if (isupper(UChar_t(*p))) {
2289  *p = tolower(UChar_t(*p));
2290  }
2291  }
2292  if (!familyTable.FindObject(family)) {
2293  familyTable.Add(new TObjString(family));
2294  }
2295  }
2296 
2297  UInt_t entries = familyTable.GetEntries();
2298  dst = new char*[entries+1];
2299 
2300  TIter next(&familyTable);
2301  i = 0;
2302  TObject *obj;
2303 
2304  while ((obj = next())) {
2305  dst[i] = StrDup(obj->GetName());
2306  i++;
2307  }
2308  dst[i] = 0;
2309 
2310  gVirtualX->FreeFontNames(nameList);
2311  return dst;
2312 }
2313 
2314 ////////////////////////////////////////////////////////////////////////////////
2315 /// Delete an array of families allocated GetFontFamilies() method
2316 
2318 {
2319  Int_t i;
2320 
2321  if (!f) return;
2322 
2323  for (i = 0; f[i] != 0; ++i) {
2324  delete[] f[i];
2325  }
2326  delete[] f;
2327 }
2328 
2329 ////////////////////////////////////////////////////////////////////////////////
2330 /// Given a desired set of attributes for a font, find a font with the
2331 /// closest matching attributes and create a new TGFont object.
2332 /// The return value is a pointer to a TGFont object that represents the
2333 /// font with the desired attributes. If a font with the desired attributes
2334 /// could not be constructed, some other font will be substituted
2335 /// automatically.
2336 ///
2337 /// Every call to this procedure returns a new TGFont object, even if the
2338 /// specified attributes have already been seen before.
2339 
2341 {
2342  Int_t numNames, score, i, scaleable, pixelsize, xaPixelsize;
2343  Int_t bestIdx, bestScore, bestScaleableIdx, bestScaleableScore;
2344  XLFDAttributes_t xa;
2345  TString buf;
2346  char **nameList;
2347  TGFont *font;
2348  FontStruct_t fontStruct;
2349  const char *fmt, *family;
2350 
2351  family = fa->fFamily;
2352  if (!family) {
2353  family = "*";
2354  }
2355  pixelsize = -fa->fPointsize;
2356 
2357  if (pixelsize < 0) {
2358  double d;
2359  d = -pixelsize * 25.4/72;
2360  Int_t xx; Int_t yy; UInt_t ww; UInt_t hh;
2361  gVirtualX->GetWindowSize(gVirtualX->GetDefaultRootWindow(), xx, yy, ww, hh);
2362  d *= ww;
2363 
2364  d /= gVirtualX->ScreenWidthMM();
2365  d += 0.5;
2366  pixelsize = (int) d;
2367  }
2368 
2369  fontStruct = 0;
2370 
2371  // Couldn't find exact match. Now fall back to other available physical fonts.
2372 
2373  fmt = "-*-%.240s-*-*-*-*-*-*-*-*-*-*-*-*";
2374  buf = TString::Format(fmt, family);
2375  nameList = gVirtualX->ListFonts(buf.Data(), 32768, numNames);
2376  if (!numNames) {
2377  // Try getting some system font.
2378 
2379  buf = TString::Format(fmt, "fixed");
2380  // coverity[returned_null]
2381  // coverity[dereference]
2382  nameList = gVirtualX->ListFonts(buf.Data(), 32768, numNames);
2383 
2384  if (!numNames) {
2385 
2386 getsystem:
2387  fontStruct = gVirtualX->LoadQueryFont("fixed");
2388 
2389  if (!fontStruct) {
2390  fontStruct = gVirtualX->LoadQueryFont("*");
2391  if (!fontStruct) {
2392  return 0;
2393  }
2394  }
2395  goto end;
2396  }
2397  }
2398 
2399  // Inspect each of the XLFDs and pick the one that most closely
2400  // matches the desired attributes.
2401 
2402  bestIdx = 0;
2403  bestScore = kMaxInt;
2404  bestScaleableIdx = 0;
2405  bestScaleableScore = kMaxInt;
2406 
2407  for (i = 0; i < numNames; i++) {
2408  score = 0;
2409  scaleable = 0;
2410  if (!ParseXLFD(nameList[i], &xa)) {
2411  continue;
2412  }
2413  xaPixelsize = -xa.fFA.fPointsize;
2414 
2415  // Since most people used to use -adobe-* in their XLFDs,
2416  // preserve the preference for "adobe" foundry. Otherwise
2417  // some applications looks may change slightly if another foundry
2418  // is chosen.
2419 
2420  if (xa.fFoundry && (strcasecmp(xa.fFoundry, "adobe") != 0)) {
2421  score += 3000;
2422  }
2423  if (!xa.fFA.fPointsize) {
2424 
2425  // A scaleable font is almost always acceptable, but the
2426  // corresponding bitmapped font would be better.
2427 
2428  score += 10;
2429  scaleable = 1;
2430  } else {
2431 
2432  // A font that is too small is better than one that is too big.
2433 
2434  if (xaPixelsize > pixelsize) {
2435  score += (xaPixelsize - pixelsize) * 120;
2436  } else {
2437  score += (pixelsize - xaPixelsize) * 100;
2438  }
2439  }
2440 
2441  score += TMath::Abs(xa.fFA.fWeight - fa->fWeight) * 30;
2442  score += TMath::Abs(xa.fFA.fSlant - fa->fSlant) * 25;
2443 
2444  if (xa.fSlant == kFontSlantOblique) {
2445 
2446  // Italic fonts are preferred over oblique.
2447 
2448  //score += 4;
2449  }
2450  if (xa.fSetwidth != kFontSWNormal) {
2451 
2452  // The normal setwidth is highly preferred.
2453 
2454  score += 2000;
2455  }
2456  if (xa.fCharset == kFontCSOther) {
2457 
2458  // The standard character set is highly preferred over
2459  // foreign languages charsets (because we don't support
2460  // other languages yet).
2461 
2462  score += 11000;
2463  }
2464  if ((xa.fCharset == kFontCSNormal) && (xa.fEncoding != 1)) {
2465 
2466  // The '1' encoding for the characters above 0x7f is highly
2467  // preferred over the other encodings.
2468 
2469  score += 8000;
2470  }
2471  if (scaleable) {
2472  if (score < bestScaleableScore) {
2473  bestScaleableIdx = i;
2474  bestScaleableScore = score;
2475  }
2476  } else {
2477  if (score < bestScore) {
2478  bestIdx = i;
2479  bestScore = score;
2480  }
2481  }
2482  if (!score) {
2483  break;
2484  }
2485  }
2486 
2487  // Now we know which is the closest matching scaleable font and the
2488  // closest matching bitmapped font. If the scaleable font was a
2489  // better match, try getting the scaleable font; however, if the
2490  // scalable font was not actually available in the desired pointsize,
2491  // fall back to the closest bitmapped font.
2492 
2493  fontStruct = 0;
2494 
2495  if (bestScaleableScore < bestScore) {
2496  char *str, *rest;
2497 
2498  // Fill in the desired pointsize info for this font.
2499 
2500 tryscale:
2501  str = nameList[bestScaleableIdx];
2502  for (i = 0; i < XLFD_PIXEL_SIZE - 1; i++) {
2503  str = strchr(str + 1, '-');
2504  }
2505  rest = str;
2506  for (i = XLFD_PIXEL_SIZE - 1; i < XLFD_REGISTRY; i++) {
2507  rest = strchr(rest + 1, '-');
2508  }
2509  *str = '\0';
2510  buf = TString::Format("%.240s-*-%d-*-*-*-*-*%s", nameList[bestScaleableIdx], pixelsize, rest);
2511  *str = '-';
2512  fontStruct = gVirtualX->LoadQueryFont(buf.Data());
2513  bestScaleableScore = kMaxInt;
2514  }
2515  if (!fontStruct) {
2516  buf = nameList[bestIdx];
2517  fontStruct = gVirtualX->LoadQueryFont(buf.Data());
2518 
2519  if (!fontStruct) {
2520 
2521  // This shouldn't happen because the font name is one of the
2522  // names that X gave us to use, but it does anyhow.
2523 
2524  if (bestScaleableScore < kMaxInt) {
2525  goto tryscale;
2526  } else {
2527  gVirtualX->FreeFontNames(nameList);
2528  goto getsystem;
2529  }
2530  }
2531  }
2532  gVirtualX->FreeFontNames(nameList);
2533 
2534 end:
2535  font = MakeFont(fontPtr, fontStruct, buf);
2536  font->fFA.fUnderline = fa->fUnderline;
2537  font->fFA.fOverstrike = fa->fOverstrike;
2538 
2539  return font;
2540 }
2541 
2542 ////////////////////////////////////////////////////////////////////////////////
2543 /// The return value is a pointer to an TGFont object that represents the
2544 /// native font. If a native font by the given name could not be found,
2545 /// the return value is NULL.
2546 ///
2547 /// Every call to this procedure returns a new TGFont object, even if the
2548 /// name has already been seen before. The caller should call FreeFont
2549 /// when the font is no longer needed.
2550 
2551 TGFont *TGFontPool::GetNativeFont(const char *name, Bool_t fixedDefault)
2552 {
2553  FontStruct_t fontStruct;
2554  fixedDefault = fixedDefault && ((*name == '-') || (*name == '*'));
2555  fontStruct = fClient->GetFontByName(name, fixedDefault);
2556 
2557  if (!fontStruct) {
2558  return 0;
2559  }
2560 
2561  return MakeFont(0, fontStruct, name);
2562 }
2563 
2564 ////////////////////////////////////////////////////////////////////////////////
2565 /// Helper for GetNativeFont() and GetFontFromAttributes(). Creates and
2566 /// intializes a new TGFont object.
2567 ///
2568 /// font -- If non-NULL, store the information in this existing TGFont
2569 /// object, rather than creating a new one; the existing
2570 /// contents of the font will be released. If NULL, a new
2571 /// TGFont object is created.
2572 /// fontStruct -- information about font.
2573 /// fontName -- The string passed to TVirtualX::LoadQueryFont() to construct the
2574 /// fontStruct.
2575 
2577  const char *fontName)
2578 {
2579  TGFont *newFont;
2580 
2581  Int_t i, width, firstChar, lastChar, n, replaceOK;
2582  char *p;
2583  char buf[4];
2584  XLFDAttributes_t xa;
2585 
2586  if (font) {
2587  gVirtualX->FreeFontStruct(font->fFontStruct);
2588  newFont = font;
2589  } else {
2590  newFont = new TGFont(fontName);
2591  }
2592 
2593  if (!ParseXLFD(fontName, &xa)) {
2594  newFont->fFA.fFamily = GetUid(fontName);
2595  } else {
2596  newFont->fFA = xa.fFA;
2597  }
2598 
2599  if (newFont->fFA.fPointsize < 0) {
2600  double d;
2601  Int_t xx; Int_t yy; UInt_t ww; UInt_t hh;
2602  gVirtualX->GetWindowSize(gVirtualX->GetDefaultRootWindow(), xx, yy, ww, hh);
2603  d = -newFont->fFA.fPointsize * 72/25.4;
2604  d *= gVirtualX->ScreenWidthMM();
2605  d /= ww;
2606  d += 0.5;
2607  newFont->fFA.fPointsize = (int) d;
2608  }
2609 
2610  Int_t ascent;
2611  Int_t descent;
2612  gVirtualX->GetFontProperties(fontStruct, ascent, descent);
2613 
2614  newFont->fFM.fAscent = ascent;
2615  newFont->fFM.fDescent = descent;
2616  newFont->fFM.fLinespace = ascent + descent;
2617  newFont->fFM.fMaxWidth = gVirtualX->TextWidth(fontStruct, "@", 1);
2618  newFont->fFM.fFixed = kTRUE;
2619  newFont->fFontStruct = fontStruct;
2620  newFont->fFontH = gVirtualX->GetFontHandle(fontStruct);
2621 
2622  // Classify the characters.
2623 
2624  firstChar = 0x20; //fontStruct->min_char_or_byte2;
2625  lastChar = 0xff; //fontStruct->max_char_or_byte2;
2626 
2627  for (i = 0; i < 256; i++) {
2628  if ((i == 160) || (i == 173) || (i == 177) ||
2629  (i < firstChar) || (i > lastChar)) {
2630  newFont->fTypes[i] = kCharReplace;
2631  } else {
2632  newFont->fTypes[i] = kCharNormal;
2633  }
2634  }
2635 
2636  // Compute the widths for all the normal characters. Any other
2637  // characters are given an initial width of 0. Also, this determines
2638  // if this is a fixed or variable width font, by comparing the widths
2639  // of all the normal characters.
2640 
2641  char ch[2] = {0, 0};
2642  width = 0;
2643  for (i = 0; i < 256; i++) {
2644  if (newFont->fTypes[i] != kCharNormal) {
2645  n = 0;
2646  } else {
2647  ch[0] = i;
2648  n = gVirtualX->TextWidth(fontStruct, ch, 1);
2649  }
2650  newFont->fWidths[i] = n;
2651  if (n) {
2652  if (!width) {
2653  width = n;
2654  } else if (width != n) {
2655  newFont->fFM.fFixed = kFALSE;
2656  }
2657  }
2658  }
2659 
2660  // Compute the widths of the characters that should be replaced with
2661  // control character expansions. If the appropriate chars are not
2662  // available in this font, then control character expansions will not
2663  // be used; control chars will be invisible & zero-width.
2664 
2665  replaceOK = kTRUE;
2666  for (p = gHexChars; *p != '\0'; p++) {
2667  if ((UChar_t(*p) < firstChar) || (UChar_t(*p) > lastChar)) {
2668  replaceOK = kFALSE;
2669  break;
2670  }
2671  }
2672  for (i = 0; i < 256; i++) {
2673  if (newFont->fTypes[i] == kCharReplace) {
2674  if (replaceOK) {
2675  n = GetControlCharSubst(i, buf);
2676  for (; --n >= 0;) {
2677  newFont->fWidths[i] += newFont->fWidths[UChar_t(buf[n])];
2678  }
2679  } else {
2680  newFont->fTypes[i] = kCharSkip;
2681  }
2682  }
2683  }
2684 
2685  newFont->fUnderlinePos = descent >> 1;
2686  newFont->fBarHeight = newFont->fWidths[(int)'I']/3;
2687 
2688  if (newFont->fBarHeight == 0) {
2689  newFont->fBarHeight = 1;
2690  }
2691 
2692  if (newFont->fUnderlinePos + newFont->fBarHeight > descent) {
2693 
2694  // If this set of cobbled together values would cause the bottom of
2695  // the underline bar to stick below the descent of the font, jack
2696  // the underline up a bit higher.
2697 
2698  newFont->fBarHeight = descent - newFont->fUnderlinePos;
2699 
2700  if (!newFont->fBarHeight) {
2701  newFont->fUnderlinePos--;
2702  newFont->fBarHeight = 1;
2703  }
2704  }
2705 
2706  return newFont;
2707 }
2708 
2709 ////////////////////////////////////////////////////////////////////////////////
2710 /// When displaying text in a widget, a backslashed escape sequence is
2711 /// substituted for control characters that occur in the text. Given a
2712 /// control character, fill in a buffer with the replacement string that
2713 /// should be displayed.
2714 ///
2715 /// The return value is the length of the substitute string, buf is
2716 /// filled with the substitute string; it is not '\0' terminated.
2717 ///
2718 /// c -- The control character to be replaced.
2719 /// buf -- Buffer that gets replacement string. It only needs to be
2720 /// 4 characters long.
2721 
2722 static Int_t GetControlCharSubst(Int_t c, char buf[4])
2723 {
2724  buf[0] = '\\';
2725 
2726  if (((UInt_t)c < sizeof(gMapChars)) && (gMapChars[c] != 0)) {
2727  buf[1] = gMapChars[c];
2728  return 2;
2729  } else {
2730  buf[1] = 'x';
2731  buf[2] = gHexChars[(c >> 4) & 0xf];
2732  buf[3] = gHexChars[c & 0xf];
2733  return 4;
2734  }
2735 }
void ToPostscript(TString *dst) const
Outputs the contents of a text layout in Postscript format.
Definition: TGFont.cxx:1319
Int_t CharBbox(Int_t index, Int_t *x, Int_t *y, Int_t *w, Int_t *h) const
Use the information in the TGTextLayout token to return the bounding box for the character specified ...
Definition: TGFont.cxx:1094
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:145
Handle_t FontStruct_t
Definition: GuiTypes.h:38
ECharType
Definition: TGFont.cxx:177
#define MAXUSE
void DrawChars(Drawable_t dst, GContext_t gc, const char *source, Int_t numChars, Int_t x, Int_t y) const
Perform a quick sanity check to ensure we won&#39;t overflow the X coordinate space.
Definition: TGFont.cxx:1478
char ** GetFontFamilies()
Return information about the font families that are available on the current display.
Definition: TGFont.cxx:2258
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
#define XLFD_NUMFIELDS
Definition: TGFont.cxx:81
void Print(Option_t *option="") const
List all fonts in the pool.
Definition: TGFont.cxx:1861
FontAttributes_t fFA
Definition: TGFont.h:158
Int_t fOverstrike
Definition: TGFont.h:77
Int_t PostscriptFontName(TString *dst) const
Return the name of the corresponding Postscript font for this TGFont.
Definition: TGFont.cxx:331
static const FontStateMap_t gXlfdgWeightMap[]
Definition: TGFont.cxx:211
void FreeFontFamilies(char **f)
Delete an array of families allocated GetFontFamilies() method.
Definition: TGFont.cxx:2317
Int_t XTextWidth(const char *string, Int_t numChars=-1) const
Return text widht in pixels.
Definition: TGFont.cxx:578
TGFont * FindFont(FontStruct_t font) const
Find font based on its font struct. Returns 0 if font is not found.
Definition: TGFont.cxx:1729
virtual ~TGTextLayout()
destructor
Definition: TGFont.cxx:885
#define XLFD_PIXEL_SIZE
Definition: TGFont.cxx:73
#define FONT_SIZE
Definition: TGFont.cxx:57
auto * m
Definition: textangle.C:8
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:105
void DrawCharsExp(Drawable_t dst, GContext_t gc, const char *source, Int_t numChars, Int_t x, Int_t y) const
Draw a string of characters on the screen.
Definition: TGFont.cxx:1448
Collectable string class.
Definition: TObjString.h:28
const char Option_t
Definition: RtypesCore.h:62
#define XLFD_POINT_SIZE
Definition: TGFont.cxx:74
static char gHexChars[]
Definition: TGFont.cxx:247
const char * NameOfFont(TGFont *font)
Given a font, return a textual string identifying it.
Definition: TGFont.cxx:2246
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Int_t fWeight
Definition: TGFont.h:74
TH1 * h
Definition: legend2.C:5
EFontSlant
Definition: TGFont.h:53
TGFont * MakeFont(TGFont *font, FontStruct_t fontStruct, const char *fontName)
Helper for GetNativeFont() and GetFontFromAttributes().
Definition: TGFont.cxx:2576
Definitions for TRefCnt, base class for reference counted objects.
Definition: TRefCnt.h:27
Int_t fPointsize
Definition: TGFont.h:73
virtual Int_t GetEntries() const
Definition: TCollection.h:177
#define FONT_SLANT
Definition: TGFont.cxx:59
#define FONT_UNDERLINE
Definition: TGFont.cxx:60
#define XLFD_FOUNDRY
Definition: TGFont.cxx:67
#define gROOT
Definition: TROOT.h:402
Handle_t GContext_t
Definition: GuiTypes.h:37
Int_t fBarHeight
Definition: TGFont.h:168
Basic string class.
Definition: TString.h:125
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
void DrawText(Drawable_t dst, GContext_t gc, Int_t x, Int_t y, Int_t firstChar, Int_t lastChar) const
Use the information in the TGTextLayout object to display a multi-line, justified string of text...
Definition: TGFont.cxx:908
Handle_t Drawable_t
Definition: GuiTypes.h:30
EFontSpacing
Definition: TGFont.cxx:149
Int_t PointToChar(Int_t x, Int_t y) const
Use the information in the TGTextLayout token to determine the character closest to the given point...
Definition: TGFont.cxx:988
static const FontStateMap_t gSlantMap[]
Definition: TGFont.cxx:192
const char * fString
Definition: TGFont.h:121
char ** GetAttributeInfo(const FontAttributes_t *fa)
Return information about the font attributes as an array of strings.
Definition: TGFont.cxx:1790
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
int FindStateNum(const FontStateMap_t *map, const char *strKey)
Given a lookup table, map a string to a number in the table.
Definition: TGFont.cxx:2189
virtual void SavePrimitive(std::ostream &out, Option_t *="")
Save the used font as a C++ statement(s) on output stream out.
Definition: TGFont.cxx:1869
#define XLFD_WEIGHT
Definition: TGFont.cxx:69
void FreeAttributeInfo(char **info)
Free attributes info.
Definition: TGFont.cxx:1844
TObjString * fNamedHash
Definition: TGFont.h:159
Handle_t FontH_t
Definition: GuiTypes.h:34
TGFont * GetFontFromAttributes(FontAttributes_t *fa, TGFont *fontPtr)
Given a desired set of attributes for a font, find a font with the closest matching attributes and cr...
Definition: TGFont.cxx:2340
TGFont * GetNativeFont(const char *name, Bool_t fixedDefault=kTRUE)
The return value is a pointer to an TGFont object that represents the native font.
Definition: TGFont.cxx:2551
static const double x2[5]
THashTable implements a hash table to store TObject&#39;s.
Definition: THashTable.h:35
Double_t x[n]
Definition: legend1.C:17
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2365
#define XLFD_REGISTRY
Definition: TGFont.cxx:79
void Class()
Definition: Class.C:29
#define FONT_NUMFIELDS
Definition: TGFont.cxx:62
const Int_t kFatal
Definition: TError.h:42
Int_t TextWidth(const char *string, Int_t numChars=-1) const
A wrapper function for the more complicated interface of MeasureChars.
Definition: TGFont.cxx:563
static const FontStateMap_t gXlfdCharsetMap[]
Definition: TGFont.cxx:237
TString & Append(const char *cs)
Definition: TString.h:495
static const FontStateMap_t gXlfdSlantMap[]
Definition: TGFont.cxx:222
Int_t DistanceToText(Int_t x, Int_t y) const
Computes the distance in pixels from the given point to the given text layout.
Definition: TGFont.cxx:1176
#define XLFD_ADD_STYLE
Definition: TGFont.cxx:72
Bool_t FieldSpecified(const char *field)
Helper function for ParseXLFD().
Definition: TGFont.cxx:2231
virtual ~TGFont()
Delete font.
Definition: TGFont.cxx:264
void Error(const char *location, const char *msgfmt,...)
Int_t IntersectText(Int_t x, Int_t y, Int_t w, Int_t h) const
Determines whether a text layout lies entirely inside, entirely outside, or overlaps a given rectangl...
Definition: TGFont.cxx:1242
void UnderlineChar(Drawable_t dst, GContext_t gc, Int_t x, Int_t y, Int_t underline) const
Use the information in the TGTextLayout object to display an underline below an individual character...
Definition: TGFont.cxx:955
const char * GetName() const
Returns name of object.
Definition: TObjString.h:39
Int_t fLinespace
Definition: TGFont.h:64
Int_t fNumChunks
Definition: TGFont.h:123
static char gMapChars[]
Definition: TGFont.cxx:254
#define XLFD_SETWIDTH
Definition: TGFont.cxx:71
#define FONT_WEIGHT
Definition: TGFont.cxx:58
void SetRefCount(UInt_t r)
Definition: TRefCnt.h:39
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:321
void FreeFont(const TGFont *font)
Free font. If ref count is 0 delete font.
Definition: TGFont.cxx:1703
FontMetrics_t fFM
Definition: TGFont.h:157
EFontSetWidth
Definition: TGFont.cxx:154
virtual ~TGFontPool()
Cleanup font pool.
Definition: TGFont.cxx:1529
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t fWidth
Definition: TGFont.h:122
Ssiz_t Length() const
Definition: TString.h:386
static const FontStateMap_t gXlfdSetwidthMap[]
Definition: TGFont.cxx:229
Int_t fWidths[256]
Definition: TGFont.h:167
#define XLFD_SLANT
Definition: TGFont.cxx:70
TGFontPool(const TGFontPool &fp)
#define FONT_FAMILY
Definition: TGFont.cxx:56
#define XLFD_ENCODING
Definition: TGFont.cxx:80
static const FontStateMap_t gUnderlineMap[]
Definition: TGFont.cxx:198
#define gVirtualX
Definition: TVirtualX.h:350
#define Printf
Definition: TGeoToOCC.h:18
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2544
const Bool_t kFALSE
Definition: RtypesCore.h:88
Bool_t ParseFontName(const char *string, FontAttributes_t *fa)
Converts a string into a set of font attributes that can be used to construct a font.
Definition: TGFont.cxx:1947
Bool_t ParseXLFD(const char *string, XLFDAttributes_t *xa)
Break up a fully specified XLFD into a set of font attributes.
Definition: TGFont.cxx:2038
void Print(Option_t *option="") const
Print font info.
Definition: TGFont.cxx:296
Bool_t fFixed
Definition: TGFont.h:66
TGFont * GetFont(const char *font, Bool_t fixedDefault=kTRUE)
Get the specified font.
Definition: TGFont.cxx:1543
static const FontStateMap_t gWeightMap[]
Definition: TGFont.cxx:186
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashTable.cxx:227
static const double x1[5]
#define ClassImp(name)
Definition: Rtypes.h:359
double Double_t
Definition: RtypesCore.h:55
UInt_t RemoveReference()
Definition: TRefCnt.h:41
static char * GetToken(char *str)
Definition: TGFont.cxx:1885
int type
Definition: TGX11.cxx:120
Definition: TGFont.h:149
static RooMathCoreReg dummy
TGTextLayout * ComputeTextLayout(const char *string, Int_t numChars, Int_t wrapLength, Int_t justify, Int_t flags, UInt_t *width, UInt_t *height) const
Computes the amount of screen space needed to display a multi-line, justified string of text...
Definition: TGFont.cxx:649
Double_t y[n]
Definition: legend1.C:17
void Add(TObject *obj)
Add object to the hash table.
Definition: THashTable.cxx:77
static constexpr double s
Int_t fUnderlinePos
Definition: TGFont.h:161
Double_t Hypot(Double_t x, Double_t y)
Definition: TMath.cxx:60
Int_t fSlant
Definition: TGFont.h:75
Bool_t IsNull() const
Definition: TString.h:383
#define XLFD_FAMILY
Definition: TGFont.cxx:68
Int_t fUnderline
Definition: TGFont.h:76
Mother of all ROOT objects.
Definition: TObject.h:37
FontStruct_t fFontStruct
Definition: TGFont.h:155
Int_t MeasureChars(const char *source, Int_t numChars, Int_t maxLength, Int_t flags, Int_t *length) const
Determine the number of characters from the string that will fit in the given horizontal span...
Definition: TGFont.cxx:476
TGFont * FindFontByHandle(FontH_t font) const
Find font based on its font handle. Returns 0 if font is not found.
Definition: TGFont.cxx:1746
static int GetControlCharSubst(int c, char buf[4])
When displaying text in a widget, a backslashed escape sequence is substituted for control characters...
Definition: TGFont.cxx:2722
const char * fFamily
Definition: TGFont.h:72
const char * FindStateString(const FontStateMap_t *map, int numKey)
Given a lookup table, map a number to a string in the table.
Definition: TGFont.cxx:2212
Int_t fTabWidth
Definition: TGFont.h:160
EFontWeight
Definition: TGFont.h:43
FontH_t fFontH
Definition: TGFont.h:156
void AddReference()
Definition: TRefCnt.h:40
#define dest(otri, vertexptr)
Definition: triangle.c:1040
const TGFont * fFont
Definition: TGFont.h:120
const Int_t kMaxInt
Definition: RtypesCore.h:99
#define snprintf
Definition: civetweb.c:822
Int_t fAscent
Definition: TGFont.h:62
#define MAX_LINES
FontStruct_t operator()() const
Not inline due to a bug in g++ 2.96 20000731 (Red Hat Linux 7.0)
Definition: TGFont.cxx:288
Int_t fDescent
Definition: TGFont.h:63
#define FONT_OVERSTRIKE
Definition: TGFont.cxx:61
EFontCharset
Definition: TGFont.cxx:159
void GetFontMetrics(FontMetrics_t *m) const
Get font metrics.
Definition: TGFont.cxx:274
unsigned char UChar_t
Definition: RtypesCore.h:34
void UnderlineChars(Drawable_t dst, GContext_t gc, const char *string, Int_t x, Int_t y, Int_t firstChar, Int_t lastChar) const
This procedure draws an underline for a given range of characters in a given string.
Definition: TGFont.cxx:605
static const FontStateMap_t gOverstrikeMap[]
Definition: TGFont.cxx:203
LayoutChunk_t * fChunks
Definition: TGFont.h:124
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
const Bool_t kTRUE
Definition: RtypesCore.h:87
const Int_t n
Definition: legend1.C:16
Int_t fMaxWidth
Definition: TGFont.h:65
char fTypes[256]
Definition: TGFont.h:165
Int_t fUnderlineHeight
Definition: TGFont.h:163
char name[80]
Definition: TGX11.cxx:109
const char * GetUid(const char *string)
Given a string, this procedure returns a unique identifier for the string.
Definition: TGFont.cxx:1770
LayoutChunk_t * NewChunk(TGTextLayout *layout, int *maxPtr, const char *start, int numChars, int curX, int newX, int y) const
Helper function for ComputeTextLayout().
Definition: TGFont.cxx:1395
const char * Data() const
Definition: TString.h:345