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