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