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