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