Logo ROOT   6.18/05
Reference Guide
FontCache.mm
Go to the documentation of this file.
1// @(#)root/graf2d:$Id$
2// Author: Timur Pocheptsov 19/03/2012
3
4/*************************************************************************
5 * Copyright (C) 1995-2012, 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//#define NDEBUG
13
14#include <stdexcept>
15#include <sstream>
16#include <cassert>
17#include <string>
18#include <cmath>
19
20#include "CocoaUtils.h"
21#include "QuartzText.h"
22#include "FontCache.h"
23#include "TSystem.h"
24#include "TError.h"
25#include "TEnv.h"
26#include "TROOT.h"
27
28namespace ROOT {
29namespace MacOSX {
30namespace Details {
31
32namespace {
33
34//ROOT uses indices for fonts. Indices are in the range [1 .. 15],
35//12 is a symbol font (quite special thing, see the code below,
36//15 is a "symbol italic" font - shear transformation is applied.
37
38//TODO: actually, it's not good to assume I have these fonts for sure,
39//find a better way to check the available fonts and search for the best
40//match.
41
42const CFStringRef fixedFontNames[FontCache::nPadFonts] =
43 {
44 CFSTR("TimesNewRomanPS-ItalicMT"),
45 CFSTR("TimesNewRomanPS-BoldMT"),
46 CFSTR("TimesNewRomanPS-BoldItalicMT"),
47 CFSTR("Helvetica"),
48 CFSTR("Helvetica-Oblique"),
49 CFSTR("Helvetica-Bold"),
50 CFSTR("Helvetica-BoldOblique"),
51 CFSTR("Courier"),
52 CFSTR("Courier-Oblique"),
53 CFSTR("Courier-Bold"),
54 CFSTR("Courier-BoldOblique"),
55 CFSTR("Symbol"),
56 CFSTR("TimesNewRomanPSMT"),
57 CFSTR("Wingdings"),
58 CFSTR("Symbol-Italic")
59 };
60
61//______________________________________________________________________________
62CTFontCollectionRef CreateFontCollection(const X11::XLFDName &/*xlfd*/)
63{
64 CTFontCollectionRef ctCollection = CTFontCollectionCreateFromAvailableFonts(0);
65 if (!ctCollection)
66 ::Error("CreateFontCollection", "CTFontCollectionCreateFromAvailableFonts failed");
67
68 return ctCollection;
69/* CTFontCollectionRef ctCollection = 0;
70 if (xlfd.fFamilyName == "*")
71 ctCollection = CTFontCollectionCreateFromAvailableFonts(0);//Select all available fonts.
72 else {
73 //Create collection, using font descriptor?
74 const Util::CFScopeGuard<CFStringRef> fontName(CFStringCreateWithCString(kCFAllocatorDefault, xlfd.fFamilyName.c_str(), kCFStringEncodingMacRoman));
75 if (!fontName.Get()) {
76 ::Error("CreateFontCollection", "CFStringCreateWithCString failed");
77 return 0;
78 }
79
80 const Util::CFScopeGuard<CTFontDescriptorRef> fontDescriptor(CTFontDescriptorCreateWithNameAndSize(fontName.Get(), 0.));
81 if (!fontDescriptor.Get()) {
82 ::Error("CreateFontCollection", "CTFontDescriptorCreateWithNameAndSize failed");
83 return 0;
84 }
85
86 Util::CFScopeGuard<CFMutableArrayRef> descriptors(CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
87 if (!descriptors.Get()) {
88 ::Error("CreateFontCollection", "CFArrayCreateMutable failed");
89 return 0;
90 }
91
92 CFArrayAppendValue(descriptors.Get(), fontDescriptor.Get());
93 ctCollection = CTFontCollectionCreateWithFontDescriptors(descriptors.Get(), 0);//Oh mama, so many code just to do this :(((
94 }
95
96 if (!ctCollection) {
97 ::Error("CreateFontCollection", "No fonts are available for family %s", xlfd.fFamilyName.c_str());//WTF???
98 return 0;
99 }
100
101
102 return ctCollection;*/
103}
104
105//______________________________________________________________________________
106bool GetFamilyName(CTFontDescriptorRef fontDescriptor, std::vector<char> &name)
107{
108 //If success, this function returns a null-terminated string in a vector.
109 assert(fontDescriptor != 0 && "GetFamilyName, parameter 'fontDescriptor' is null");
110
111 name.clear();
112
113 Util::CFScopeGuard<CFStringRef> cfFamilyName((CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute));
114 if (const CFIndex cfLen = CFStringGetLength(cfFamilyName.Get())) {
115 name.resize(cfLen + 1);//+ 1 for '\0'.
116 if (CFStringGetCString(cfFamilyName.Get(), &name[0], name.size(), kCFStringEncodingMacRoman))
117 return true;
118 }
119
120 return false;
121}
122
123#ifdef MAC_OS_X_VERSION_10_9
124
125//______________________________________________________________________________
126bool GetPostscriptName(CTFontDescriptorRef fontDescriptor, std::vector<char> &name)
127{
128 //If success, this function returns a null-terminated string in a vector.
129 assert(fontDescriptor != 0 && "GetPostscriptName, parameter 'fontDescriptor' is null");
130
131 name.clear();
132
133 Util::CFScopeGuard<CFStringRef> cfFamilyName((CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontNameAttribute));
134
135 if (const CFIndex cfLen = CFStringGetLength(cfFamilyName.Get())) {
136 name.resize(cfLen + 1);//+ 1 for '\0'.
137 if (CFStringGetCString(cfFamilyName.Get(), &name[0], name.size(), kCFStringEncodingMacRoman))
138 return true;
139 }
140
141 return false;
142}
143
144#endif
145
146//______________________________________________________________________________
147void GetWeightAndSlant(CTFontDescriptorRef fontDescriptor, X11::XLFDName &newXLFD)
148{
149 //Let's ask for a weight and pixel size.
150 const Util::CFScopeGuard<CFDictionaryRef> traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute));
151 if (traits.Get()) {
152 if (CFNumberRef symbolTraits = (CFNumberRef)CFDictionaryGetValue(traits.Get(), kCTFontSymbolicTrait)) {
153 uint32_t val = 0;
154 CFNumberGetValue(symbolTraits, kCFNumberIntType, &val);
155 if (val & kCTFontItalicTrait)
156 newXLFD.fSlant = X11::kFSItalic;
157 else
158 newXLFD.fSlant = X11::kFSRegular;
159
160 if (val & kCTFontBoldTrait)
161 newXLFD.fWeight = X11::kFWBold;
162 else
163 newXLFD.fWeight = X11::kFWMedium;
164 }
165
166 /*
167 //The code below is wrong - using it, I can not identify bold or italic and always have
168 //only medium/regular.
169 if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(traits.Get(), kCTFontWeightTrait)) {
170 double val = 0.;
171 if (CFNumberGetValue(weight, kCFNumberDoubleType, &val))
172 newXLFD.fWeight = val > 0. ? X11::kFWBold : X11::kFWMedium;
173 }
174
175 if(CFNumberRef slant = (CFNumberRef)CFDictionaryGetValue(traits.Get(), kCTFontSlantTrait)) {
176 double val = 0.;
177 if (CFNumberGetValue(slant, kCFNumberDoubleType, &val))
178 newXLFD.fSlant = val > 0. ? X11::kFSItalic : X11::kFSRegular;
179 }
180 */
181 }
182}
183
184//______________________________________________________________________________
185void GetPixelSize(CTFontDescriptorRef fontDescriptor, X11::XLFDName &newXLFD)
186{
187 const Util::CFScopeGuard<CFNumberRef> size((CFNumberRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontSizeAttribute));
188 if (size.Get()) {
189 int pixelSize = 0;
190 if(CFNumberIsFloatType(size.Get())) {
191 double val = 0;
192 CFNumberGetValue(size.Get(), kCFNumberDoubleType, &val);
193 pixelSize = val;
194 } else
195 CFNumberGetValue(size.Get(), kCFNumberIntType, &pixelSize);
196
197 if(pixelSize)
198 newXLFD.fPixelSize = pixelSize;
199 }
200}
201
202//_________________________________________________________________
203void CreateXLFDString(const X11::XLFDName &xlfd, std::string &xlfdString)
204{
205 xlfdString = "-CoreText-"; //Fake foundry.
206 xlfdString += xlfd.fFamilyName;
207
208 if (xlfd.fWeight == X11::kFWBold)
209 xlfdString += "-bold";
210 else
211 xlfdString += "-normal";
212
213 if (xlfd.fSlant == X11::kFSItalic)
214 xlfdString += "-i";
215 else
216 xlfdString += "-r";
217
218 xlfdString += "-*-*"; //width, addstyle
219
220 if (xlfd.fPixelSize) {
221 std::ostringstream out;
222 out<<xlfd.fPixelSize;
223 xlfdString += "-";
224 xlfdString += out.str();
225 } else
226 xlfdString += "-*";
227
228 xlfdString += "-*-*-*-*-*-*-*-";
229}
230
231}
232
233//_________________________________________________________________
235 : fSymbolFontRegistered(false)
236{
237 //XLFD name is not exactly PS name thus generating a warning with a new Core Text.
238 fXLFDtoPostscriptNames["helvetica"] = "Helvetica";
239 fXLFDtoPostscriptNames["courier"] = "Courier";
240 fXLFDtoPostscriptNames["times"] = "Times-Roman";
241}
242
243//______________________________________________________________________________
245{
246 using Util::CFScopeGuard;
248
249#ifdef MAC_OS_X_VERSION_10_9
250 PSNameMap_t::const_iterator nameIt = fXLFDtoPostscriptNames.find(xlfd.fFamilyName);
251 const std::string &psName = nameIt == fXLFDtoPostscriptNames.end() ? xlfd.fFamilyName : nameIt->second;
252 const CFScopeGuard<CFStringRef> fontName(CFStringCreateWithCString(kCFAllocatorDefault, psName.c_str(), kCFStringEncodingMacRoman));
253#else
254 const CFScopeGuard<CFStringRef> fontName(CFStringCreateWithCString(kCFAllocatorDefault, xlfd.fFamilyName.c_str(), kCFStringEncodingMacRoman));
255#endif
256
257 const CFStrongReference<CTFontRef> baseFont(CTFontCreateWithName(fontName.Get(), xlfd.fPixelSize, 0), false);//false == do not retain
258
259 if (!baseFont.Get()) {
260 ::Error("FontCache::LoadFont", "CTFontCreateWithName failed for %s", xlfd.fFamilyName.c_str());
261 return FontStruct_t();//Haha! Die ROOT, die!
262 }
263
264 CTFontSymbolicTraits symbolicTraits = CTFontSymbolicTraits();
265
266 if (xlfd.fWeight == X11::kFWBold)
267 symbolicTraits |= kCTFontBoldTrait;
268 if (xlfd.fSlant == X11::kFSItalic)
269 symbolicTraits |= kCTFontItalicTrait;
270
271 if (symbolicTraits) {
272 const CFStrongReference<CTFontRef> font(CTFontCreateCopyWithSymbolicTraits(baseFont.Get(), xlfd.fPixelSize, 0, symbolicTraits, symbolicTraits), false);//false == do not retain.
273 if (font.Get()) {
274 if (fLoadedFonts.find(font.Get()) == fLoadedFonts.end())
275 fLoadedFonts[font.Get()] = font;
276
277 return reinterpret_cast<FontStruct_t>(font.Get());
278 }
279 }
280
281 if (fLoadedFonts.find(baseFont.Get()) == fLoadedFonts.end())
282 fLoadedFonts[baseFont.Get()] = baseFont;
283
284 return reinterpret_cast<FontStruct_t>(baseFont.Get());
285}
286
287//______________________________________________________________________________
289{
290 CTFontRef fontRef = (CTFontRef)font;
291 font_iterator fontIter = fLoadedFonts.find(fontRef);
292
293 assert(fontIter != fLoadedFonts.end() && "Attempt to unload font, not created by font manager");
294
295 fLoadedFonts.erase(fontIter);
296}
297
298//______________________________________________________________________________
299char **FontCache::ListFonts(const X11::XLFDName &xlfd, int maxNames, int &count)
300{
301 typedef std::vector<char>::size_type size_type;
302
303 count = 0;
304
305 //Ugly, ugly code. I should "think different"!!!
306 //To extract font names, I have to: create CFString, create font descriptor, create
307 //CFArray, create CTFontCollection, that's a mess!!!
308 //It's good I have my small and ugly RAII classes, otherwise the code will be
309 //total trash and sodomy because of all possible cleanup actions.
310
311 //First, create a font collection.
312 const Util::CFScopeGuard<CTFontCollectionRef> collectionGuard(CreateFontCollection(xlfd));
313 if (!collectionGuard.Get())
314 return 0;
315
316 Util::CFScopeGuard<CFArrayRef> fonts(CTFontCollectionCreateMatchingFontDescriptors(collectionGuard.Get()));
317 if (!fonts.Get()) {
318 ::Error("FontCache::ListFonts", "CTFontCollectionCreateMatchingFontDescriptors failed %s", xlfd.fFamilyName.c_str());
319 return 0;
320 }
321
322 std::vector<char> xlfdData;
323 //familyName is actually a null-terminated string.
324 std::vector<char> familyName;
325 X11::XLFDName newXLFD;
326 std::string xlfdString;
327
328 const CFIndex nFonts = CFArrayGetCount(fonts.Get());
329 for (CFIndex i = 0; i < nFonts && count < maxNames; ++i) {
330 CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts.Get(), i);
331
332 if (!GetFamilyName(font, familyName))
333 continue;
334
335 if (xlfd.fFamilyName != "*" && xlfd.fFamilyName != &familyName[0])
336 continue;
337
338 newXLFD.fFamilyName = &familyName[0];
339
340 //If family name has '-', ROOT's GUI can not parse it correctly -
341 //'-' is a separator in XLFD. Just skip this font (anyway, it wan not requested by GUI, only
342 //listed by FontCache.
343 if (newXLFD.fFamilyName.find('-') != std::string::npos)
344 continue;
345
346 GetWeightAndSlant(font, newXLFD);
347
348 //Check weight and slant.
349 if (xlfd.fWeight != X11::kFWAny && newXLFD.fWeight != xlfd.fWeight)
350 continue;
351 if (xlfd.fSlant != X11::kFSAny && newXLFD.fSlant != xlfd.fSlant)
352 continue;
353
354 if (xlfd.fPixelSize) {//Size was requested.
355 GetPixelSize(font, newXLFD);
356 //Core Text supports different font sizes.
357 if (!newXLFD.fPixelSize)
358 newXLFD.fPixelSize = xlfd.fPixelSize;
359 }
360
361#ifdef MAC_OS_X_VERSION_10_9
362 //To avoid a warning from Core Text, save a mapping from a name seen by ROOT (family)
363 //to a right postscript name (required by Core Text).
364
365 //It's a null-terminated string:
366 std::vector<char> postscriptName;
367 if (GetPostscriptName(font, postscriptName)) {
368 if (fXLFDtoPostscriptNames.find(&familyName[0]) == fXLFDtoPostscriptNames.end())
369 fXLFDtoPostscriptNames[&familyName[0]] = &postscriptName[0];
370 }
371#endif
372
373
374 //Ok, now lets create XLFD name, and place into list.
375 CreateXLFDString(newXLFD, xlfdString);
376 //
377 xlfdData.insert(xlfdData.end(), xlfdString.begin(), xlfdString.end());
378 xlfdData.push_back(0);//terminal 0.
379 ++count;
380 }
381
382 //Setup array with string addresses.
383 if (xlfdData.size()) {
384 fFontLists.push_back(fDummyList);
385 fFontLists.back().fStringData.swap(xlfdData);
386
387 std::vector<char> &data = fFontLists.back().fStringData;
388 std::vector<char *> &list = fFontLists.back().fList;
389
390 list.push_back(&data[0]);
391 for (size_type i = 1, e = data.size(); i < e; ++i) {
392 if (!data[i] && i + 1 < e)
393 list.push_back(&data[i + 1]);
394 }
395
396 return &list[0];
397 } else
398 return 0;
399}
400
401//______________________________________________________________________________
402void FontCache::FreeFontNames(char **fontList)
403{
404 if (!fontList)
405 return;
406
407 for (std::list<FontList>::iterator it = fFontLists.begin(), eIt = fFontLists.end(); it != eIt; ++it) {
408 if (fontList == &it->fList[0]) {
409 fFontLists.erase(it);
410 return;
411 }
412 }
413
414 assert(0 && "FreeFontNames, unknown fontList");
415}
416
417//______________________________________________________________________________
418unsigned FontCache::GetTextWidth(FontStruct_t font, const char *text, int nChars)
419{
420 typedef std::vector<CGSize>::size_type size_type;
421 //
422 CTFontRef fontRef = (CTFontRef)font;
423 assert(fLoadedFonts.find(fontRef) != fLoadedFonts.end() && "Font was not created by font manager");
424
425 //nChars is either positive, or negative (take all string).
426 if (nChars < 0)
427 nChars = std::strlen(text);
428
429 std::vector<UniChar> unichars(text, text + nChars);
430
431 //Extract glyphs for a text.
432 std::vector<CGGlyph> glyphs(unichars.size());
433 CTFontGetGlyphsForCharacters(fontRef, &unichars[0], &glyphs[0], unichars.size());
434
435 //Glyps' advances for a text.
436 std::vector<CGSize> glyphAdvances(glyphs.size());
437 CTFontGetAdvancesForGlyphs(fontRef, Quartz::horizontalFontOrientation, &glyphs[0], &glyphAdvances[0], glyphs.size());
438
439 CGFloat textWidth = 0.;
440 for (size_type i = 0, e = glyphAdvances.size(); i < e; ++i)
441 textWidth += std::ceil(glyphAdvances[i].width);
442
443 return textWidth;
444}
445
446
447//_________________________________________________________________
448void FontCache::GetFontProperties(FontStruct_t font, int &maxAscent, int &maxDescent)
449{
450 CTFontRef fontRef = (CTFontRef)font;
451
452 assert(fLoadedFonts.find(fontRef) != fLoadedFonts.end() && "Font was not created by font manager");
453
454 try {
455 maxAscent = int(CTFontGetAscent(fontRef) + 0.5) + 2;
456 maxDescent = int(CTFontGetDescent(fontRef) + 0.5);
457 } catch (const std::exception &) {
458 throw;
459 }
460}
461
462
463//_________________________________________________________________
464CTFontRef FontCache::SelectFont(Font_t fontIndex, Float_t fontSize)
465{
466 fontIndex /= 10;
467
468 if (fontIndex > nPadFonts || !fontIndex) {
469 ::Warning("FontCache::SelectFont", "Font with index %d was requested", fontIndex);
470 fontIndex = 3;//Select the Helvetica as default.
471 } else
472 fontIndex -= 1;
473
474 if (fontIndex == 11 || fontIndex == 14)//Special case, our own symbol.ttf file.
475 return SelectSymbolFont(fontSize, fontIndex);
476
477 const UInt_t fixedSize = UInt_t(fontSize);
478 font_map_iterator it = fFonts[fontIndex].find(fixedSize);
479
480 if (it == fFonts[fontIndex].end()) {
481 //Insert the new font.
482 try {
483 const CTFontGuard_t font(CTFontCreateWithName(fixedFontNames[fontIndex], fixedSize, 0), false);
484 if (!font.Get()) {//With Apple's lame documentation it's not clear, if function can return 0.
485 ::Error("FontCache::SelectFont", "CTFontCreateWithName failed for font %d", fontIndex);
486 return 0;
487 }
488
489 fFonts[fontIndex][fixedSize] = font;//Insetion can throw.
490 return fSelectedFont = font.Get();
491 } catch (const std::exception &) {//Bad alloc.
492 return 0;
493 }
494 }
495
496 return fSelectedFont = it->second.Get();
497}
498
499//_________________________________________________________________
500CTFontRef FontCache::SelectSymbolFont(Float_t fontSize, unsigned fontIndex)
501{
502 assert(fontIndex == 11 || fontIndex == 14 && "SelectSymbolFont, parameter fontIndex has invalid value");
503
504 const UInt_t fixedSize = UInt_t(fontSize);
505 font_map_iterator it = fFonts[fontIndex].find(fixedSize);//In ROOT, 11 is a font from symbol.ttf.
506
507 if (it == fFonts[fontIndex].end()) {
508 //This GetValue
509 const char * const fontDirectoryPath = gEnv->GetValue("Root.TTFontPath",TROOT::GetTTFFontDir());
510 char * const fontFileName = gSystem->Which(fontDirectoryPath, "symbol.ttf", kReadPermission);//This must be deleted.
511
512 const Util::ScopedArray<char> arrayGuard(fontFileName);
513
514 if (!fontFileName || fontFileName[0] == 0) {
515 ::Error("FontCache::SelectSymbolFont", "symbol.ttf file not found");
516 return 0;
517 }
518
519 try {
520 const Util::CFScopeGuard<CFStringRef> path(CFStringCreateWithCString(kCFAllocatorDefault, fontFileName, kCFURLPOSIXPathStyle));
521 if (!path.Get()) {
522 ::Error("FontCache::SelectSymbolFont", "CFStringCreateWithCString failed");
523 return 0;
524 }
525
526 const Util::CFScopeGuard<CFURLRef> fontURL(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.Get(), kCFURLPOSIXPathStyle, false));
527 if (!fontURL.Get()) {
528 ::Error("FontCache::SelectSymbolFont", "CFURLCreateWithFileSystemPath failed");
529 return 0;
530 }
531
532 //Try to register this font.
534 CFErrorRef err = 0;
535 fSymbolFontRegistered = CTFontManagerRegisterFontsForURL(fontURL.Get(), kCTFontManagerScopeProcess, &err);
537 ::Error("FontCache::SelectSymbolFont", "CTFontManagerRegisterFontsForURL failed");
538 if (err)
539 CFRelease(err);
540 return 0;
541 }
542 }
543
544 const Util::CFScopeGuard<CFArrayRef> arr(CTFontManagerCreateFontDescriptorsFromURL(fontURL.Get()));
545 if (!arr.Get()) {
546 ::Error("FontCache::SelectSymbolFont", "CTFontManagerCreateFontDescriptorsFromURL failed");
547 return 0;
548 }
549
550 CTFontDescriptorRef fontDesc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(arr.Get(), 0);
551
552 const CGAffineTransform shearMatrix = {1., 0., 0.26794, 1., 0., 0.};//Yes, these are hardcoded values, taken from TPDF class.
553 const CTFontGuard_t font(CTFontCreateWithFontDescriptorAndOptions(fontDesc, fixedSize,
554 fontIndex == 11 ? &CGAffineTransformIdentity :
555 &shearMatrix, kCTFontOptionsDefault), false);
556 if (!font.Get()) {
557 ::Error("FontCache::SelectSymbolFont", "CTFontCreateWithFontDescriptor failed");
558 return 0;
559 }
560
561 fFonts[fontIndex][fixedSize] = font;//This can throw.
562 return fSelectedFont = font.Get();
563 } catch (const std::exception &) {//Bad alloc.
564 //RAII destructors should do their work.
565 return 0;
566 }
567 }
568
569 return fSelectedFont = it->second.Get();
570}
571
572//_________________________________________________________________
573void FontCache::GetTextBounds(UInt_t &w, UInt_t &h, const char *text)const
574{
575 assert(fSelectedFont != 0 && "GetTextBounds: no font was selected");
576
577 try {
578 const Quartz::TextLine ctLine(text, fSelectedFont);
579 ctLine.GetBounds(w, h);
580 h += 2;
581 } catch (const std::exception &) {
582 throw;
583 }
584}
585
586//_________________________________________________________________
587void FontCache::GetTextBounds(UInt_t &w, UInt_t &h, const std::vector<UniChar> &unichars)const
588{
589 assert(fSelectedFont != 0 && "GetTextBounds: no font was selected");
590
591 try {
592 const Quartz::TextLine ctLine(unichars, fSelectedFont);
593 ctLine.GetBounds(w, h);
594 h += 2;
595 } catch (const std::exception &) {
596 throw;
597 }
598}
599
600//_________________________________________________________________
602{
603 assert(fSelectedFont != 0 && "GetAscent, no font was selected");
604 return CTFontGetAscent(fSelectedFont) + 1;
605}
606
607//_________________________________________________________________
608double FontCache::GetAscent(const char *text)const
609{
610 assert(text != 0 && "GetAscent, parameter 'text' is null");
611 assert(fSelectedFont != 0 && "GetAscent, no font was selected");
612
613 try {
614 const Quartz::TextLine ctLine(text, fSelectedFont);
615 Int_t ascent = 0, descent = 0;
616 ctLine.GetAscentDescent(ascent, descent);
617 return ascent;
618 } catch (const std::exception &) {
619 throw;
620 }
621}
622
623//_________________________________________________________________
624double FontCache::GetAscent(const std::vector<UniChar> &unichars)const
625{
626 assert(fSelectedFont != 0 && "GetAscent, no font was selected");
627
628 try {
629 const Quartz::TextLine ctLine(unichars, fSelectedFont);
630 Int_t ascent = 0, descent = 0;
631 ctLine.GetAscentDescent(ascent, descent);
632 return ascent;
633 } catch (const std::exception &) {
634 throw;
635 }
636}
637
638//_________________________________________________________________
640{
641 assert(fSelectedFont != 0 && "GetDescent, no font was selected");
642 return CTFontGetDescent(fSelectedFont) + 1;
643}
644
645//_________________________________________________________________
646double FontCache::GetDescent(const char *text)const
647{
648 assert(text != 0 && "GetDescent, parameter 'text' is null");
649 assert(fSelectedFont != 0 && "GetDescent, no font was selected");
650
651 try {
652 const Quartz::TextLine ctLine(text, fSelectedFont);
653 Int_t ascent = 0, descent = 0;
654 ctLine.GetAscentDescent(ascent, descent);
655 return descent;
656 } catch (const std::exception &) {
657 throw;
658 }
659}
660
661//_________________________________________________________________
662double FontCache::GetDescent(const std::vector<UniChar> &unichars)const
663{
664 assert(fSelectedFont != 0 && "GetDescent, no font was selected");
665
666 try {
667 const Quartz::TextLine ctLine(unichars, fSelectedFont);
668 Int_t ascent = 0, descent = 0;
669 ctLine.GetAscentDescent(ascent, descent);
670 return descent;
671 } catch (const std::exception &) {
672 throw;
673 }
674}
675
676//_________________________________________________________________
678{
679 assert(fSelectedFont != 0 && "GetLeading, no font was selected");
680 return CTFontGetLeading(fSelectedFont);
681}
682
683
684}//Details
685}//MacOSX
686}//ROOT
Handle_t FontStruct_t
Definition: GuiTypes.h:38
#define h(i)
Definition: RSha256.hxx:106
#define e(i)
Definition: RSha256.hxx:103
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
short Font_t
Definition: RtypesCore.h:75
float Float_t
Definition: RtypesCore.h:53
include TDocParser_001 C image html pict1_TDocParser_001 png width
Definition: TDocParser.cxx:121
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
char name[80]
Definition: TGX11.cxx:109
double ceil(double)
@ kReadPermission
Definition: TSystem.h:48
R__EXTERN TSystem * gSystem
Definition: TSystem.h:560
void FreeFontNames(char **fontList)
Definition: FontCache.mm:402
void GetFontProperties(FontStruct_t font, int &maxAscent, int &maxDescent)
Definition: FontCache.mm:448
std::map< CTFontRef, CTFontGuard_t >::iterator font_iterator
Definition: FontCache.h:82
char ** ListFonts(const X11::XLFDName &xlfd, int maxNames, int &count)
Definition: FontCache.mm:299
unsigned GetTextWidth(FontStruct_t font, const char *text, int nChars)
Definition: FontCache.mm:418
CTFontRef SelectSymbolFont(Float_t fontSize, unsigned fontIndex)
Definition: FontCache.mm:500
std::list< FontList > fFontLists
Definition: FontCache.h:107
void GetTextBounds(UInt_t &w, UInt_t &h, const char *text) const
Definition: FontCache.mm:573
std::map< CTFontRef, CTFontGuard_t > fLoadedFonts
Definition: FontCache.h:81
FontStruct_t LoadFont(const X11::XLFDName &xlfd)
Definition: FontCache.mm:244
void UnloadFont(FontStruct_t font)
Definition: FontCache.mm:288
CTFontRef SelectFont(Font_t fontIndex, Float_t fontSize)
Definition: FontCache.mm:464
FontMap_t::iterator font_map_iterator
Definition: FontCache.h:87
FontMap_t fFonts[nPadFonts]
Definition: FontCache.h:90
void GetBounds(UInt_t &w, UInt_t &h) const
Definition: QuartzText.mm:179
void GetAscentDescent(Int_t &asc, Int_t &desc) const
Definition: QuartzText.mm:189
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
static const TString & GetTTFFontDir()
Get the fonts directory in the installation. Static utility function.
Definition: TROOT.cxx:3176
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1536
TText * text
TCanvas * fonts()
Definition: fonts.C:10
const CTFontOrientation horizontalFontOrientation
Definition: QuartzText.mm:39
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21