Qt 4.8
qcoretextfontdatabase.mm
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qcoretextfontdatabase.h"
43 
44 #include <CoreText/CoreText.h>
45 #include <Foundation/Foundation.h>
46 
47 #include <private/qcore_mac_p.h>
48 #include <private/qfontengine_coretext_p.h>
49 
51 
53  const QFont::Style &style,
55  const QUnicodeTables::Script &script) const
56 {
57  Q_UNUSED(family);
58  Q_UNUSED(style);
59  Q_UNUSED(script);
60  if (fallbackLists.isEmpty())
61  const_cast<QCoreTextFontDatabase *>(this)->populateFontDatabase();
62 
63  return fallbackLists[styleHint];
64 }
65 
66 static QFont::StyleHint styleHintFromNSString(NSString *style)
67 {
68  if ([style isEqual: @"sans-serif"])
69  return QFont::SansSerif;
70  else if ([style isEqual: @"monospace"])
71  return QFont::Monospace;
72  else if ([style isEqual: @"cursive"])
73  return QFont::Cursive;
74  else if ([style isEqual: @"serif"])
75  return QFont::Serif;
76  else if ([style isEqual: @"fantasy"])
77  return QFont::Fantasy;
78  else
79  return QFont::AnyStyle;
80 }
81 
82 static NSInteger languageMapSort(id obj1, id obj2, void *context)
83 {
84  NSArray *map1 = (NSArray *) obj1;
85  NSArray *map2 = (NSArray *) obj2;
86  NSArray *languages = (NSArray *) context;
87 
88  NSString *lang1 = [map1 objectAtIndex: 0];
89  NSString *lang2 = [map2 objectAtIndex: 0];
90 
91  return [languages indexOfObject: lang1] - [languages indexOfObject: lang2];
92 }
93 
95  NSString *psName)
96 {
98  if (psNameToFamily->contains(name)) {
99  return psNameToFamily->value(name);
100  } else {
101  QCFType<CTFontRef> font = CTFontCreateWithName((CFStringRef) psName, 12.0, NULL);
102  if (font) {
103  QCFString family = CTFontCopyFamilyName(font);
104  (*psNameToFamily)[name] = family;
105  return family;
106  }
107  }
108 
109  return name;
110 }
111 
113 {
114  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
115 
116  QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0);
117  if (!collection)
118  return;
119  QCFType<CFArrayRef> fonts = CTFontCollectionCreateMatchingFontDescriptors(collection);
120  if (!fonts)
121  return;
122  QSupportedWritingSystems supportedWritingSystems;
123  for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i)
124  supportedWritingSystems.setSupported((QFontDatabase::WritingSystem)i, true);
125  QString foundry_name = "CoreText";
126  const int numFonts = CFArrayGetCount(fonts);
127  QHash<QString, QString> psNameToFamily;
128  for (int i = 0; i < numFonts; ++i) {
129  CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i);
130 
131  QCFString family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
132 // QCFString style_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute);
133 
134  QFont::Weight fontWeight = QFont::Normal;
135  QFont::Style fontStyle = QFont::StyleNormal;
136  if (QCFType<CFDictionaryRef> styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) {
137  if (CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
138  Q_ASSERT(CFNumberIsFloatType(weight));
139  double d;
140  if (CFNumberGetValue(weight, kCFNumberDoubleType, &d)) {
141  if (d > 0.0)
142  fontWeight = QFont::Bold;
143  }
144  }
145  if (CFNumberRef italic = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
146  Q_ASSERT(CFNumberIsFloatType(italic));
147  double d;
148  if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) {
149  if (d > 0.0)
150  fontStyle = QFont::StyleItalic;
151  }
152  }
153  }
154 
155  int pixelSize = 0;
156  if (QCFType<CFNumberRef> size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
157  if (CFNumberIsFloatType(size)) {
158  double d;
159  CFNumberGetValue(size, kCFNumberDoubleType, &d);
160  pixelSize = d;
161  } else {
162  CFNumberGetValue(size, kCFNumberIntType, &pixelSize);
163  }
164  }
165  QString familyName = QCFString::toQString(family_name);
166  registerFont(familyName,
167  foundry_name,
168  fontWeight,
169  fontStyle,
171  true,
172  true,
173  pixelSize,
174  supportedWritingSystems,
175  0);
176 
177  CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(font,
178  kCTFontNameAttribute);
179  psNameToFamily[QCFString::toQString(psName)] = familyName;
180  CFRelease(psName);
181  }
182 
183  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
184  NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"];
185 
186  NSDictionary *fallbackDict = [NSDictionary dictionaryWithContentsOfFile: @"/System/Library/Frameworks/CoreText.framework/DefaultFontFallbacks.plist"];
187  for (NSString *style in [fallbackDict allKeys]) {
188  NSArray *list = [fallbackDict valueForKey: style];
190  QStringList fallbackList;
191  for (id item in list) {
192  if ([item isKindOfClass: [NSArray class]]) {
193  NSArray *langs = [(NSArray *) item sortedArrayUsingFunction: languageMapSort
194  context: languages];
195  for (NSArray *map in langs)
196  fallbackList.append(familyNameFromPostScriptName(&psNameToFamily, [map objectAtIndex: 1]));
197  } else if ([item isKindOfClass: [NSString class]]) {
198  fallbackList.append(familyNameFromPostScriptName(&psNameToFamily, item));
199  }
200  }
201 
202  fallbackLists[styleHint] = fallbackList;
203  }
204 
205  [pool release];
206 }
207 
209 {
210  Q_UNUSED(script)
211  Q_UNUSED(handle)
212  CTFontSymbolicTraits symbolicTraits = 0;
213  if (fontDef.weight >= QFont::Bold)
214  symbolicTraits |= kCTFontBoldTrait;
215  switch (fontDef.style) {
216  case QFont::StyleNormal:
217  break;
218  case QFont::StyleItalic:
219  case QFont::StyleOblique:
220  symbolicTraits |= kCTFontItalicTrait;
221  break;
222  }
223 
224  CGAffineTransform transform = CGAffineTransformIdentity;
225  if (fontDef.stretch != 100) {
226  transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
227  }
228 
229  QCFType<CTFontRef> baseFont = CTFontCreateWithName(QCFString(fontDef.family), fontDef.pixelSize, &transform);
230  QCFType<CTFontRef> ctFont = NULL;
231  // There is a side effect in Core Text: if we apply 0 as symbolic traits to a font in normal weight,
232  // we will get the light version of that font (while the way supposed to work doesn't:
233  // setting kCTFontWeightTrait to some value between -1.0 to 0.0 has no effect on font selection)
234  if (fontDef.weight != QFont::Normal || symbolicTraits)
235  ctFont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, &transform, symbolicTraits, symbolicTraits);
236 
237  // CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does
238  // not exist for the given font. (for example italic)
239  if (ctFont == 0) {
240  ctFont = baseFont;
241  }
242 
243  if (ctFont)
244  return new QCoreTextFontEngine(ctFont, fontDef);
245  return 0;
246 }
247 
static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result)
double d
Definition: qnumeric_p.h:62
void setSupported(QFontDatabase::WritingSystem, bool supported=true)
Sets the supported state of the writing system given by writingSystem to the value specified by suppo...
const struct __CFString * CFStringRef
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static NSInteger languageMapSort(id obj1, id obj2, void *context)
static QString toQString(CFStringRef cfstr)
Definition: qcore_mac.cpp:47
Weight
Qt uses a weighting scale from 0 to 99 similar to, but not the same as, the scales used in Windows or...
Definition: qfont.h:103
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
void populateFontDatabase()
This function is called once at startup by Qts internal fontdatabase.
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static float pixelSize(const QFontDef &request, int dpi)
Definition: qfont_win.cpp:80
static bool init
const char * name
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
The QSupportedWritingSystems class is used when registering fonts with the internal Qt fontdatabase...
bool isEmpty() const
Returns true if the hash contains no items; otherwise returns false.
Definition: qhash.h:297
const char * styleHint(const QFontDef &request)
uint weight
Definition: qfont_p.h:95
Style
This enum describes the different styles of glyphs that are used to display text. ...
Definition: qfont.h:111
Q_CORE_EXPORT int QT_FASTCALL script(uint ucs4)
qreal pixelSize
Definition: qfont_p.h:90
static QString familyNameFromPostScriptName(QHash< QString, QString > *psNameToFamily, NSString *psName)
StyleHint
Style hints are used by the font matching algorithm to find an appropriate default family if a select...
Definition: qfont.h:69
static void registerFont(const QString &familyname, const QString &foundryname, QFont::Weight weight, QFont::Style style, QFont::Stretch stretch, bool antialiased, bool scalable, int pixelSize, const QSupportedWritingSystems &writingSystems, void *handle)
Registers a font with the given set of attributes describing the font&#39;s foundry, family name...
QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const
Returns a list of alternative fonts for the specified family and style and script using the styleHint...
uint style
Definition: qfont_p.h:97
QHash< QFont::StyleHint, QStringList > fallbackLists
uint stretch
Definition: qfont_p.h:98
QFontEngine * fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle)
Returns the font engine that can be used to render the font described by the font definition...
QString family
Definition: qfont_p.h:82
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QFont::StyleHint styleHintFromNSString(NSString *style)