From 63b19022a39241b18fa4f3822f8861d6b4e9a1f1 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov <Timur.Pocheptsov@cern.ch> Date: Mon, 7 May 2012 09:00:42 +0000 Subject: [PATCH] Implement ListFonts. Disabled at the moment - got sudden crash in stressGUI. git-svn-id: http://root.cern.ch/svn/root/trunk@44150 27541ba8-7e3a-0410-8455-c3a389f83636 --- graf2d/cocoa/inc/FontCache.h | 7 +- graf2d/cocoa/src/FontCache.mm | 206 ++++++++++++++++++++++------------ graf2d/cocoa/src/TGCocoa.mm | 13 ++- 3 files changed, 150 insertions(+), 76 deletions(-) diff --git a/graf2d/cocoa/inc/FontCache.h b/graf2d/cocoa/inc/FontCache.h index 065522379f0..31793b199b3 100644 --- a/graf2d/cocoa/inc/FontCache.h +++ b/graf2d/cocoa/inc/FontCache.h @@ -49,8 +49,10 @@ public: FontCache(); FontStruct_t LoadFont(const X11::XLFDName &xlfd); - char **ListFonts(const X11::XLFDName &xlfd, int maxNames, int &count); void UnloadFont(FontStruct_t font); + + char **ListFonts(const X11::XLFDName &xlfd, int maxNames, int &count); + void FreeFontNames(char **fontList); unsigned GetTextWidth(FontStruct_t font, const char *text, int nChars); void GetFontProperties(FontStruct_t font, int &maxAscent, int &maxDescent); @@ -99,7 +101,8 @@ private: std::vector<char> fStringData; }; - std::list<FontList> fFontLists;//list of "list" of fonts :) + std::list<FontList> fFontLists;//list of "lists" of fonts :) + FontList fDummyList; FontCache(const FontCache &rhs); FontCache &operator = (const FontCache &rhs); diff --git a/graf2d/cocoa/src/FontCache.mm b/graf2d/cocoa/src/FontCache.mm index 44138a0a5b6..62154524f62 100644 --- a/graf2d/cocoa/src/FontCache.mm +++ b/graf2d/cocoa/src/FontCache.mm @@ -12,7 +12,9 @@ //#define NDEBUG #include <stdexcept> +#include <sstream> #include <cassert> +#include <string> #include <cmath> #include "CocoaUtils.h" @@ -52,52 +54,6 @@ const CFStringRef fixedFontNames[FontCache::nPadFonts] = }; -} - -//_________________________________________________________________ -FontCache::FontCache() -{ -} - -//______________________________________________________________________________ -FontStruct_t FontCache::LoadFont(const X11::XLFDName &xlfd) -{ - using Util::CFScopeGuard; - using Util::CFStrongReference; - - const CFScopeGuard<CFStringRef> fontName(CFStringCreateWithCString(kCFAllocatorDefault, xlfd.fFamilyName.c_str(), kCFStringEncodingMacRoman)); - const CFStrongReference<CTFontRef> baseFont(CTFontCreateWithName(fontName.Get(), xlfd.fPixelSize, 0), false);//false == do not retain - - if (!baseFont.Get()) { - ::Error("FontCache::LoadFont", "CTFontCreateWithName failed for %s", xlfd.fFamilyName.c_str()); - return FontStruct_t();//Haha! Die ROOT, die! - } - - CTFontSymbolicTraits symbolicTraits = CTFontSymbolicTraits(); - - if (xlfd.fWeight == X11::kFWBold) - symbolicTraits |= kCTFontBoldTrait; - if (xlfd.fSlant == X11::kFSItalic) - symbolicTraits |= kCTFontItalicTrait; - - if (symbolicTraits) { - const CFStrongReference<CTFontRef> font(CTFontCreateCopyWithSymbolicTraits(baseFont.Get(), xlfd.fPixelSize, 0, symbolicTraits, symbolicTraits), false);//false == do not retain. - if (font.Get()) { - if (fLoadedFonts.find(font.Get()) == fLoadedFonts.end()) - fLoadedFonts[font.Get()] = font; - - return reinterpret_cast<FontStruct_t>(font.Get()); - } - } - - if (fLoadedFonts.find(baseFont.Get()) == fLoadedFonts.end()) - fLoadedFonts[baseFont.Get()] = baseFont; - - return reinterpret_cast<FontStruct_t>(baseFont.Get()); -} - -namespace { - //______________________________________________________________________________ CTFontCollectionRef CreateFontCollection(const X11::XLFDName &xlfd) { @@ -111,7 +67,7 @@ CTFontCollectionRef CreateFontCollection(const X11::XLFDName &xlfd) ::Error("CreateFontCollection", "CFStringCreateWithCString failed"); return 0; } - + const Util::CFScopeGuard<CTFontDescriptorRef> fontDescriptor(CTFontDescriptorCreateWithNameAndSize(fontName.Get(), 0.)); if (!fontDescriptor.Get()) { ::Error("CreateFontCollection", "CTFontDescriptorCreateWithNameAndSize failed"); @@ -123,11 +79,11 @@ CTFontCollectionRef CreateFontCollection(const X11::XLFDName &xlfd) ::Error("CreateFontCollection", "CFArrayCreateMutable failed"); return 0; } - - CFArrayAppendValue(descriptors.Get(), fontDescriptor.Get()); + + CFArrayAppendValue(descriptors.Get(), fontDescriptor.Get()); ctCollection = CTFontCollectionCreateWithFontDescriptors(descriptors.Get(), 0);//Oh mama, so many code just to do this :((( } - + if (!ctCollection) { ::Error("CreateFontCollection", "No fonts are available for family %s", xlfd.fFamilyName.c_str());//WTF??? return 0; @@ -141,12 +97,12 @@ CTFontCollectionRef CreateFontCollection(const X11::XLFDName &xlfd) bool GetFamilyName(CTFontDescriptorRef fontDescriptor, std::vector<char> &name) { assert(fontDescriptor != 0 && "GetFamilyName, fontDescriptor parameter is null"); - + name.clear(); - + Util::CFScopeGuard<CFStringRef> cfFamilyName((CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute)); const CFIndex cfLen = CFStringGetLength(cfFamilyName.Get()); - name.resize(cfLen + 1);//+ 1 for '0'. + name.resize(cfLen + 1);//+ 1 for '\0'. if (CFStringGetCString(cfFamilyName.Get(), &name[0], name.size(), kCFStringEncodingMacRoman)) return true; @@ -188,14 +144,98 @@ void GetPixelSize(CTFontDescriptorRef fontDescriptor, X11::XLFDName &newXLFD) if(pixelSize) newXLFD.fPixelSize = pixelSize; - } + } +} + +//_________________________________________________________________ +void CreateXLFDString(const X11::XLFDName &xlfd, std::string &xlfdString) +{ + xlfdString = "-*-"; //skip the foundry. + xlfdString += xlfd.fFamilyName; + + if (xlfd.fWeight == X11::kFWBold) + xlfdString += "-bold"; + else + xlfdString += "-*"; + + if (xlfd.fSlant == X11::kFSItalic) + xlfdString += "-i"; + else + xlfdString += "-r"; + + xlfdString += "-*-*"; //width, addstyle + + if (xlfd.fPixelSize) { + std::ostringstream out; + out<<xlfd.fPixelSize; + xlfdString += "-"; + xlfdString += out.str(); + } else + xlfdString += "-*"; + + xlfdString += "-*-*-*-*-*-*-*-";//TODO: something more reasonable? +} + } +//_________________________________________________________________ +FontCache::FontCache() +{ +} + +//______________________________________________________________________________ +FontStruct_t FontCache::LoadFont(const X11::XLFDName &xlfd) +{ + using Util::CFScopeGuard; + using Util::CFStrongReference; + + const CFScopeGuard<CFStringRef> fontName(CFStringCreateWithCString(kCFAllocatorDefault, xlfd.fFamilyName.c_str(), kCFStringEncodingMacRoman)); + const CFStrongReference<CTFontRef> baseFont(CTFontCreateWithName(fontName.Get(), xlfd.fPixelSize, 0), false);//false == do not retain + + if (!baseFont.Get()) { + ::Error("FontCache::LoadFont", "CTFontCreateWithName failed for %s", xlfd.fFamilyName.c_str()); + return FontStruct_t();//Haha! Die ROOT, die! + } + + CTFontSymbolicTraits symbolicTraits = CTFontSymbolicTraits(); + + if (xlfd.fWeight == X11::kFWBold) + symbolicTraits |= kCTFontBoldTrait; + if (xlfd.fSlant == X11::kFSItalic) + symbolicTraits |= kCTFontItalicTrait; + + if (symbolicTraits) { + const CFStrongReference<CTFontRef> font(CTFontCreateCopyWithSymbolicTraits(baseFont.Get(), xlfd.fPixelSize, 0, symbolicTraits, symbolicTraits), false);//false == do not retain. + if (font.Get()) { + if (fLoadedFonts.find(font.Get()) == fLoadedFonts.end()) + fLoadedFonts[font.Get()] = font; + + return reinterpret_cast<FontStruct_t>(font.Get()); + } + } + + if (fLoadedFonts.find(baseFont.Get()) == fLoadedFonts.end()) + fLoadedFonts[baseFont.Get()] = baseFont; + + return reinterpret_cast<FontStruct_t>(baseFont.Get()); +} + +//______________________________________________________________________________ +void FontCache::UnloadFont(FontStruct_t font) +{ + CTFontRef fontRef = (CTFontRef)font; + font_iterator fontIter = fLoadedFonts.find(fontRef); + + assert(fontIter != fLoadedFonts.end() && "Attempt to unload font, not created by font manager"); + + fLoadedFonts.erase(fontIter); } //______________________________________________________________________________ char **FontCache::ListFonts(const X11::XLFDName &xlfd, int maxNames, int &count) { + typedef std::vector<char>::size_type size_type; + count = 0; //Ugly, ugly code. I should "think different"!!! @@ -215,13 +255,13 @@ char **FontCache::ListFonts(const X11::XLFDName &xlfd, int maxNames, int &count) return 0; } - int added = 0; - FontList newFontList; + std::vector<char> xlfdData; std::vector<char> familyName; X11::XLFDName newXLFD = {}; + std::string xlfdString; const CFIndex nFonts = CFArrayGetCount(fonts.Get()); - for (CFIndex i = 0; i < nFonts && added < maxNames; ++i) { + for (CFIndex i = 0; i < nFonts && count < maxNames; ++i) { CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts.Get(), i); if (!GetFamilyName(font, familyName)) @@ -236,32 +276,58 @@ char **FontCache::ListFonts(const X11::XLFDName &xlfd, int maxNames, int &count) continue; if (newXLFD.fSlant != xlfd.fSlant) continue; - if (xlfd.fPixelSize) {//Size was requested. - GetPixelSize(font, newXLFD); - if (xlfd.fPixelSize != newXLFD.fPixelSize)//??? do I need this check actually? - continue; + GetPixelSize(font, newXLFD); + //I do not think, that font has a pixel size. + //But Core Text supports different font sizes. + if (!newXLFD.fPixelSize) + newXLFD.fPixelSize = xlfd.fPixelSize; } //Ok, now lets create XLFD name, and place into list. + CreateXLFDString(newXLFD, xlfdString); + // + xlfdData.insert(xlfdData.end(), xlfdString.begin(), xlfdString.end()); + xlfdData.push_back(0);//terminal 0. + ++count; } - return 0; + //Setup array with string addresses. + if (xlfdData.size()) { + fFontLists.push_back(fDummyList); + fFontLists.back().fStringData.swap(xlfdData); + + std::vector<char> &data = fFontLists.back().fStringData; + std::vector<char *> &list = fFontLists.back().fList; + + list.push_back(&data[0]); + for (size_type i = 1, e = data.size(); i < e; ++i) { + if (!data[i] && i + 1 < e) + list.push_back(&data[i + 1]); + } + + return &list[0]; + } else + return 0; } //______________________________________________________________________________ -void FontCache::UnloadFont(FontStruct_t font) +void FontCache::FreeFontNames(char **fontList) { - CTFontRef fontRef = (CTFontRef)font; - font_iterator fontIter = fLoadedFonts.find(fontRef); - - assert(fontIter != fLoadedFonts.end() && "Attempt to unload font, not created by font manager"); - - fLoadedFonts.erase(fontIter); + if (!fontList) + return; + + for (std::list<FontList>::iterator it = fFontLists.begin(), eIt = fFontLists.end(); it != eIt; ++it) { + if (fontList == &it->fList[0]) { + fFontLists.erase(it); + return; + } + } + + assert(0 && "FreeFontNames, unknown fontList"); } - //______________________________________________________________________________ unsigned FontCache::GetTextWidth(FontStruct_t font, const char *text, int nChars) { diff --git a/graf2d/cocoa/src/TGCocoa.mm b/graf2d/cocoa/src/TGCocoa.mm index 28270141f9b..faa7fb2a46e 100644 --- a/graf2d/cocoa/src/TGCocoa.mm +++ b/graf2d/cocoa/src/TGCocoa.mm @@ -2139,20 +2139,25 @@ void TGCocoa::FreeFontStruct(FontStruct_t /*fs*/) char **TGCocoa::ListFonts(const char * /*fontName*/, Int_t /*maxNames*/, Int_t &count) { count = 0; -/* - if (fontName && fontName[0]) { + + /* if (fontName && fontName[0]) { X11::XLFDName xlfd = {}; if (X11::ParseXLFDName(fontName, xlfd)) return fPimpl->fFontManager.ListFonts(xlfd, maxNames, count); - }*/ + } + */ return 0; } //______________________________________________________________________________ -void TGCocoa::FreeFontNames(char ** /*fontlist*/) +void TGCocoa::FreeFontNames(char **fontList) { // Frees the specified the array of strings "fontlist". + if (!fontList) + return; + + fPimpl->fFontManager.FreeFontNames(fontList); } //Color management. -- GitLab