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