iPlug2 - C++ Audio Plug-in Framework
IGraphicsCoreText.mm
1 /*
2  ==============================================================================
3 
4  This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5 
6  See LICENSE.txt for more info.
7 
8  ==============================================================================
9 */
10 
11 #include "IGraphicsCoreText.h"
12 #include "IPlugPaths.h"
13 
14 using namespace iplug;
15 using namespace igraphics;
16 
17 IFontDataPtr CoreTextFont::GetFontData()
18 {
19  CFLocal<CFDataRef> rawData(CGDataProviderCopyData(mProvider));
20  const UInt8* bytes = CFDataGetBytePtr(rawData.Get());
21  int faceIdx = 0;
22 
23  if (mStyleString.GetLength())
24  faceIdx = GetFaceIdx(bytes, static_cast<int>(CFDataGetLength(rawData.Get())), mStyleString.Get());
25 
26  IFontDataPtr fontData(new IFontData(bytes, static_cast<int>(CFDataGetLength(rawData.Get())), faceIdx));
27 
28  return fontData;
29 }
30 
31 CoreTextFont::~CoreTextFont()
32 {
33  CGDataProviderRelease(mProvider);
34  if (mDescriptor)
35  CFRelease(mDescriptor);
36 };
37 
38 PlatformFontPtr CoreTextHelpers::LoadPlatformFont(const char* fontID, const char* fileNameOrResID, const char* bundleID, const char* sharedResourceSubPath)
39 {
40  WDL_String fullPath;
41  const EResourceLocation fontLocation = LocateResource(fileNameOrResID, "ttf", fullPath, bundleID, nullptr, sharedResourceSubPath);
42 
43  if (fontLocation == kNotFound)
44  return nullptr;
45 
46  CFLocal<CFStringRef> path(CFStringCreateWithCString(NULL, fullPath.Get(), kCFStringEncodingUTF8));
47  CFLocal<CFURLRef> url(CFURLCreateWithFileSystemPath(NULL, path.Get(), kCFURLPOSIXPathStyle, false));
48  CFLocal<CGDataProviderRef> provider(url.Get() ? CGDataProviderCreateWithURL(url.Get()) : nullptr); // CGDataProviderCreateWithURL will fail in macOS sandbox!
49 
50  if (!provider.Get())
51  return nullptr;
52 
53  CFLocal<CGFontRef> cgFont(CGFontCreateWithDataProvider(provider.Get()));
54  CFLocal<CTFontRef> ctFont(CTFontCreateWithGraphicsFont(cgFont.Get(), 0.f, NULL, NULL));
55  CFLocal<CTFontDescriptorRef> descriptor(CTFontCopyFontDescriptor(ctFont.Get()));
56 
57  if (!descriptor.Get())
58  return nullptr;
59 
60  return PlatformFontPtr(new CoreTextFont(descriptor.Release(), provider.Release(), "", false));
61 }
62 
63 PlatformFontPtr CoreTextHelpers::LoadPlatformFont(const char* fontID, const char* fontName, ETextStyle style)
64 {
65  CFLocal<CFStringRef> fontStr(CFStringCreateWithCString(NULL, fontName, kCFStringEncodingUTF8));
66  CFLocal<CFStringRef> styleStr(CFStringCreateWithCString(NULL, TextStyleString(style), kCFStringEncodingUTF8));
67 
68  CFStringRef keys[] = { kCTFontFamilyNameAttribute, kCTFontStyleNameAttribute };
69  CFTypeRef values[] = { fontStr.Get(), styleStr.Get() };
70 
71  CFLocal<CFDictionaryRef> dictionary(CFDictionaryCreate(NULL, (const void**)&keys, (const void**)&values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
72  CFLocal<CTFontDescriptorRef> descriptor(CTFontDescriptorCreateWithAttributes(dictionary.Get()));
73  CFLocal<CFURLRef> url((CFURLRef) CTFontDescriptorCopyAttribute(descriptor.Get(), kCTFontURLAttribute));
74  CFLocal<CGDataProviderRef> provider(url.Get() ? CGDataProviderCreateWithURL(url.Get()) : nullptr);
75 
76  if (!provider.Get())
77  return nullptr;
78 
79  return PlatformFontPtr(new CoreTextFont(descriptor.Release(), provider.Release(), TextStyleString(style), true));
80 }
81 
82 void releaseFontData(void* info, const void* data, size_t size)
83 {
84  uint8_t* pData = (uint8_t*)data;
85  delete[] pData;
86 }
87 
88 PlatformFontPtr CoreTextHelpers::LoadPlatformFont(const char* fontID, void* pData, int dataSize)
89 {
90  uint8_t* dataCopy = new uint8_t[dataSize];
91  memcpy((void*)dataCopy, pData, dataSize);
92 
93  CFLocal<CGDataProviderRef> provider(CGDataProviderCreateWithData(nullptr, dataCopy, (size_t)dataSize, &releaseFontData));
94 
95  if (!provider.Get())
96  return nullptr;
97 
98  CFLocal<CGFontRef> cgFont(CGFontCreateWithDataProvider(provider.Get()));
99  CFLocal<CTFontRef> ctFont(CTFontCreateWithGraphicsFont(cgFont.Get(), 0.f, NULL, NULL));
100  CFLocal<CTFontDescriptorRef> descriptor(CTFontCopyFontDescriptor(ctFont.Get()));
101 
102  if (!descriptor.Get())
103  return nullptr;
104 
105  return PlatformFontPtr(new CoreTextFont(descriptor.Release(), provider.Release(), "", false));
106 }
107 
108 void CoreTextHelpers::CachePlatformFont(const char* fontID, const PlatformFontPtr& font, StaticStorage<CoreTextFontDescriptor>& cache)
109 {
110  StaticStorage<CoreTextFontDescriptor>::Accessor storage(cache);
111 
112  CTFontDescriptorRef descriptor = font->GetDescriptor();
113  IFontDataPtr data = font->GetFontData();
114 
115  if (!storage.Find(fontID))
116  storage.Add(new CoreTextFontDescriptor(descriptor, data->GetHeightEMRatio()), fontID);
117 }
118 
119 CoreTextFontDescriptor* CoreTextHelpers::GetCTFontDescriptor(const IText& text, StaticStorage<CoreTextFontDescriptor>& cache)
120 {
121  StaticStorage<CoreTextFontDescriptor>::Accessor storage(cache);
122 
123  CoreTextFontDescriptor* cachedFont = storage.Find(text.mFont);
124 
125  assert(cachedFont && "font not found - did you forget to load it?");
126 
127  return cachedFont;
128 }
129 
Common paths useful for plug-ins.
IText is used to manage font and text/text entry style for a piece of text on the UI...
EResourceLocation LocateResource(const char *fileNameOrResID, const char *type, WDL_String &result, const char *bundleID, void *pHInstance, const char *sharedResourcesSubPath)
Find the absolute path of a resource based on it&#39;s file name (e.g.
static const char * TextStyleString(ETextStyle style)
Helper to get a CString based on ETextStyle.