Qt 4.8
Functions
qfontdatabase_mac.cpp File Reference
#include <private/qt_mac_p.h>
#include "qfontengine_p.h"
#include <qfile.h>
#include <qabstractfileengine.h>
#include <stdlib.h>
#include <qendian.h>
#include <private/qfontengine_coretext_p.h>
#include <private/qfontengine_mac_p.h>

Go to the source code of this file.

Functions

static void initializeDb ()
 
static void initWritingSystems (QtFontFamily *family, ATSFontRef atsFont)
 
static void load (const QString &=QString(), int=-1)
 
static QFontEngineloadFromDatabase (QFontDef &req, const QFontPrivate *d)
 
int qt_mac_pixelsize (const QFontDef &def, int dpi)
 
int qt_mac_pointsize (const QFontDef &def, int dpi)
 
static void registerFont (QFontDatabasePrivate::ApplicationFont *fnt)
 
static const char * styleHint (const QFontDef &request)
 
static float weightToFloat (unsigned int weight)
 

Function Documentation

◆ initializeDb()

static void initializeDb ( )
static

Definition at line 129 of file qfontdatabase_mac.cpp.

Referenced by QFontDatabase::createDatabase(), load(), and loadFromDatabase().

130 {
131  QFontDatabasePrivate *db = privateDb();
132  if(!db || db->count)
133  return;
134 
135 #if defined(QT_MAC_USE_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
137  QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0);
138  if(!collection)
139  return;
140  QCFType<CFArrayRef> fonts = CTFontCollectionCreateMatchingFontDescriptors(collection);
141  if(!fonts)
142  return;
143  QString foundry_name = "CoreText";
144  const int numFonts = CFArrayGetCount(fonts);
145  for(int i = 0; i < numFonts; ++i) {
146  CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i);
147  QCFString family_name = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL);
148  QCFString style_name = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL);
149  QtFontFamily *family = db->family(family_name, true);
150 
151  if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) {
152  CFIndex length = CFArrayGetCount(languages);
153  for (int i = 1; i < LanguageCount; ++i) {
154  if (!languageForWritingSystem[i])
155  continue;
156  QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII);
157  if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang))
159  }
160  }
161 
162  QtFontFoundry *foundry = family->foundry(foundry_name, true);
163 
164  QtFontStyle::Key styleKey;
165  QString styleName = style_name;
166  if(QCFType<CFDictionaryRef> styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) {
167  if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
168  Q_ASSERT(CFNumberIsFloatType(weight));
169  double d;
170  if(CFNumberGetValue(weight, kCFNumberDoubleType, &d)) {
171  //qDebug() << "BOLD" << (QString)family_name << d;
172  styleKey.weight = (d > 0.0) ? QFont::Bold : QFont::Normal;
173  }
174  }
175  if(CFNumberRef italic = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
176  Q_ASSERT(CFNumberIsFloatType(italic));
177  double d;
178  if(CFNumberGetValue(italic, kCFNumberDoubleType, &d)) {
179  //qDebug() << "ITALIC" << (QString)family_name << d;
180  if (d > 0.0)
181  styleKey.style = QFont::StyleItalic;
182  }
183  }
184  }
185 
186  QtFontStyle *style = foundry->style(styleKey, styleName, true);
187  style->smoothScalable = true;
188  if(QCFType<CFNumberRef> size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
189  //qDebug() << "WHEE";
190  int pixel_size=0;
191  if(CFNumberIsFloatType(size)) {
192  double d;
193  CFNumberGetValue(size, kCFNumberDoubleType, &d);
194  pixel_size = d;
195  } else {
196  CFNumberGetValue(size, kCFNumberIntType, &pixel_size);
197  }
198  //qDebug() << "SIZE" << (QString)family_name << pixel_size;
199  if(pixel_size)
200  style->pixelSize(pixel_size, true);
201  } else {
202  //qDebug() << "WTF?";
203  }
204  }
205 } else
206 #endif
207  {
208 #ifndef QT_MAC_USE_COCOA
209  FMFontIterator it;
210  if (!FMCreateFontIterator(0, 0, kFMUseGlobalScopeOption, &it)) {
211  while (true) {
212  FMFont fmFont;
213  if (FMGetNextFont(&it, &fmFont) != noErr)
214  break;
215 
216  FMFontFamily fmFamily;
217  FMFontStyle fmStyle;
218  QString familyName;
219 
220  QtFontStyle::Key styleKey;
221 
222  ATSFontRef atsFont = FMGetATSFontRefFromFont(fmFont);
223 
224  if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) {
225  { //sanity check the font, and see if we can use it at all! --Sam
226  ATSUFontID fontID;
227  if(ATSUFONDtoFontID(fmFamily, 0, &fontID) != noErr)
228  continue;
229  }
230 
231  if (fmStyle & ::italic)
232  styleKey.style = QFont::StyleItalic;
233  if (fmStyle & ::bold)
234  styleKey.weight = QFont::Bold;
235 
236  ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily);
237  QCFString cfFamilyName;;
238  ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName);
239  familyName = cfFamilyName;
240  } else {
241  QCFString cfFontName;
242  ATSFontGetName(atsFont, kATSOptionFlagsDefault, &cfFontName);
243  familyName = cfFontName;
244  quint16 macStyle = 0;
245  {
246  uchar data[4];
247  ByteCount len = 4;
248  if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 44, 4, &data, &len) == noErr)
249  macStyle = qFromBigEndian<quint16>(data);
250  }
251  if (macStyle & 1)
252  styleKey.weight = QFont::Bold;
253  if (macStyle & 2)
254  styleKey.style = QFont::StyleItalic;
255  }
256 
257  QtFontFamily *family = db->family(familyName, true);
258  QtFontFoundry *foundry = family->foundry(QString(), true);
259  QtFontStyle *style = foundry->style(styleKey, QString(), true);
260  style->pixelSize(0, true);
261  style->smoothScalable = true;
262 
263  initWritingSystems(family, atsFont);
264  }
265  FMDisposeFontIterator(&it);
266  }
267 #endif
268  }
269 
270 }
double d
Definition: qnumeric_p.h:62
const struct __CFString * CFStringRef
QtFontStyle * style(const QtFontStyle::Key &, const QString &=QString(), bool=false)
#define it(className, varName)
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static const char * languageForWritingSystem[]
#define MAKE_TAG(ch1, ch2, ch3, ch4)
unsigned char uchar
Definition: qglobal.h:994
static void initWritingSystems(QtFontFamily *family, ATSFontRef atsFont)
unsigned short quint16
Definition: qglobal.h:936
static const char * data(const QByteArray &arr)
QtFontFamily * family(const QString &f, bool=false)
quint16 qFromBigEndian< quint16 >(const uchar *src)
Definition: qendian.h:249
unsigned char writingSystems[QFontDatabase::WritingSystemsCount]
QtFontSize * pixelSize(unsigned short size, bool=false)
static const MacVersion MacintoshVersion
the version of the Macintosh operating system on which the application is run (Mac only)...
Definition: qglobal.h:1646
QtFontFoundry * foundry(const QString &f, bool=false)
const struct __CFArray * CFArrayRef

◆ initWritingSystems()

static void initWritingSystems ( QtFontFamily family,
ATSFontRef  atsFont 
)
static

Definition at line 57 of file qfontdatabase_mac.cpp.

Referenced by initializeDb().

58 {
59  ByteCount length = 0;
60  if (ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 0, 0, 0, &length) != noErr)
61  return;
62  QVarLengthArray<uchar> os2Table(length);
63  if (length < 86
64  || ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 0, length, os2Table.data(), &length) != noErr)
65  return;
66 
67  // See also qfontdatabase_win.cpp, offsets taken from OS/2 table in the TrueType spec
68  quint32 unicodeRange[4] = {
69  qFromBigEndian<quint32>(os2Table.data() + 42),
70  qFromBigEndian<quint32>(os2Table.data() + 46),
71  qFromBigEndian<quint32>(os2Table.data() + 50),
72  qFromBigEndian<quint32>(os2Table.data() + 54)
73  };
74  quint32 codePageRange[2] = { qFromBigEndian<quint32>(os2Table.data() + 78), qFromBigEndian<quint32>(os2Table.data() + 82) };
76 #if 0
78  ATSFontGetName(atsFont, kATSOptionFlagsDefault, &name);
79  qDebug() << systems.count() << "writing systems for" << QString(name);
80 qDebug() << "first char" << hex << unicodeRange[0];
81  for (int i = 0; i < systems.count(); ++i)
82  qDebug() << QFontDatabase::writingSystemName(systems.at(i));
83 #endif
84  for (int i = 0; i < systems.count(); ++i)
85  family->writingSystems[systems.at(i)] = QtFontFamily::Supported;
86 }
quint32 qFromBigEndian< quint32 >(const uchar *src)
Definition: qendian.h:239
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define MAKE_TAG(ch1, ch2, ch3, ch4)
Q_CORE_EXPORT void qDebug(const char *,...)
const char * name
unsigned char writingSystems[QFontDatabase::WritingSystemsCount]
unsigned int quint32
Definition: qglobal.h:938
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
static QString writingSystemName(WritingSystem writingSystem)
Returns the names the writingSystem (e.g.
QList< QFontDatabase::WritingSystem > qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2])

◆ load()

static void load ( const QString = QString(),
int  = -1 
)
inlinestatic

Definition at line 272 of file qfontdatabase_mac.cpp.

273 {
274  initializeDb();
275 }
static void initializeDb()

◆ loadFromDatabase()

static QFontEngine* loadFromDatabase ( QFontDef req,
const QFontPrivate d 
)
static

Definition at line 303 of file qfontdatabase_mac.cpp.

Referenced by QFontDatabase::load().

304 {
305 #if defined(QT_MAC_USE_COCOA)
306  QCFString fontName = NULL;
307 #else
308  ATSFontFamilyRef familyRef = 0;
309  ATSFontRef fontRef = 0;
310 #endif
311 
312  QStringList family_list = familyList(req);
313 
314  const char *stylehint = styleHint(req);
315  if (stylehint)
316  family_list << QLatin1String(stylehint);
317 
318  // add QFont::defaultFamily() to the list, for compatibility with previous versions
319  family_list << QApplication::font().defaultFamily();
320 
321  QMutexLocker locker(fontDatabaseMutex());
322  QFontDatabasePrivate *db = privateDb();
323  if (!db->count)
324  initializeDb();
325  for (int i = 0; i < family_list.size(); ++i) {
326  for (int k = 0; k < db->count; ++k) {
327  if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) {
328 #if defined(QT_MAC_USE_COCOA)
329  CFStringRef familyName = QCFString::toCFStringRef(db->families[k]->name);
330  QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(
331  QCFType<CFDictionaryRef>(CFDictionaryCreate(kCFAllocatorDefault,
332  (const void**)&kCTFontFamilyNameAttribute,
333  (const void**)&familyName, 1,
334  &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)));
335  CFRelease(familyName);
336  QCFType<CTFontRef> ctFont = CTFontCreateWithFontDescriptor(descriptor, 0, NULL);
337  if (ctFont) {
338  fontName = CTFontCopyFullName(ctFont);
339  goto found;
340  }
341 #else
342  familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
343  if (familyRef) {
344  fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
345  goto found;
346  }
347 #endif
348  }
349  }
350  }
351 found:
352 #ifdef QT_MAC_USE_COCOA
353  if (fontName)
354  return new QCoreTextFontEngineMulti(fontName, req, d->kerning);
355 #else
356  if (familyRef) {
357  QCFString actualName;
358  if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
359  req.family = actualName;
360  return new QFontEngineMacMulti(familyRef, fontRef, req, d->kerning);
361  }
362 #endif
363  return NULL;
364 }
const struct __CFString * CFStringRef
static const char * styleHint(const QFontDef &request)
static CFStringRef toCFStringRef(const QString &str)
Definition: qcore_mac.cpp:69
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static QFont font()
Returns the default application font.
static QStringList familyList(const QFontDef &req)
QtFontFamily ** families
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static void initializeDb()
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
int compare(const QString &s) const
Definition: qstring.cpp:5037
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QString defaultFamily() const
Returns the family name that corresponds to the current style hint.
Definition: qfont_mac.cpp:134
uint kerning
Definition: qfont_p.h:191
QString family
Definition: qfont_p.h:82

◆ qt_mac_pixelsize()

int qt_mac_pixelsize ( const QFontDef def,
int  dpi 
)

Definition at line 64 of file qfont_mac.cpp.

Referenced by QFontDatabase::load().

65 {
66  float ret;
67  if(def.pixelSize == -1)
68  ret = def.pointSize * dpi / qt_mac_defaultDpi_x();
69  else
70  ret = def.pixelSize;
71  return qRound(ret);
72 }
qreal pointSize
Definition: qfont_p.h:89
float qt_mac_defaultDpi_x()
qreal pixelSize
Definition: qfont_p.h:90
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203

◆ qt_mac_pointsize()

int qt_mac_pointsize ( const QFontDef def,
int  dpi 
)

Definition at line 73 of file qfont_mac.cpp.

Referenced by QFontDatabase::load().

74 {
75  float ret;
76  if(def.pointSize < 0)
77  ret = def.pixelSize * qt_mac_defaultDpi_x() / float(dpi);
78  else
79  ret = def.pointSize;
80  return qRound(ret);
81 }
qreal pointSize
Definition: qfont_p.h:89
float qt_mac_defaultDpi_x()
qreal pixelSize
Definition: qfont_p.h:90
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203

◆ registerFont()

static void registerFont ( QFontDatabasePrivate::ApplicationFont fnt)
static

Definition at line 440 of file qfontdatabase_mac.cpp.

Referenced by QFontDatabasePrivate::addAppFont().

441 {
442  ATSFontContainerRef handle;
443  OSStatus e = noErr;
444 
445  if(fnt->data.isEmpty()) {
446 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
448  FSRef ref;
449  if(qt_mac_create_fsref(fnt->fileName, &ref) != noErr)
450  return;
451 
452  ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle);
453  } else
454 #endif
455  {
456 #ifndef Q_WS_MAC64
457  FSSpec spec;
458  if(qt_mac_create_fsspec(fnt->fileName, &spec) != noErr)
459  return;
460 
461  e = ATSFontActivateFromFileSpecification(&spec, kATSFontContextLocal, kATSFontFormatUnspecified,
462  0, kATSOptionFlagsDefault, &handle);
463 #endif
464  }
465  } else {
466  e = ATSFontActivateFromMemory((void *)fnt->data.constData(), fnt->data.size(), kATSFontContextLocal,
467  kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle);
468 
469  fnt->data = QByteArray();
470  }
471 
472  if(e != noErr)
473  return;
474 
475  ItemCount fontCount = 0;
476  e = ATSFontFindFromContainer(handle, kATSOptionFlagsDefault, 0, 0, &fontCount);
477  if(e != noErr)
478  return;
479 
480  QVarLengthArray<ATSFontRef> containedFonts(fontCount);
481  e = ATSFontFindFromContainer(handle, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount);
482  if(e != noErr)
483  return;
484 
485  fnt->families.clear();
486 #if defined(QT_MAC_USE_COCOA)
487  // Make sure that the family name set on the font matches what
488  // kCTFontFamilyNameAttribute returns in initializeDb().
489  // So far the best solution seems find the installed font
490  // using CoreText and get the family name from it.
491  // (ATSFontFamilyGetName appears to be the correct API, but also
492  // returns the font display name.)
493  for(int i = 0; i < containedFonts.size(); ++i) {
494  QCFString fontPostScriptName;
495  ATSFontGetPostScriptName(containedFonts[i], kATSOptionFlagsDefault, &fontPostScriptName);
496  QCFType<CTFontDescriptorRef> font = CTFontDescriptorCreateWithNameAndSize(fontPostScriptName, 14);
497  QCFString familyName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
498  fnt->families.append(familyName);
499  }
500 #else
501  for(int i = 0; i < containedFonts.size(); ++i) {
502  QCFString family;
503  ATSFontGetName(containedFonts[i], kATSOptionFlagsDefault, &family);
504  fnt->families.append(family);
505  }
506 #endif
507 
508  fnt->handle = handle;
509 }
const struct __CFString * CFStringRef
OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec)
Definition: qcore_mac.cpp:131
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref)
Definition: qcore_mac.cpp:125
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
void clear()
Removes all items from the list.
Definition: qlist.h:764
signed long OSStatus
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
static const MacVersion MacintoshVersion
the version of the Macintosh operating system on which the application is run (Mac only)...
Definition: qglobal.h:1646
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421

◆ styleHint()

static const char* styleHint ( const QFontDef request)
static

Definition at line 277 of file qfontdatabase_mac.cpp.

Referenced by loadFromDatabase().

278 {
279  const char *stylehint = 0;
280  switch (request.styleHint) {
281  case QFont::SansSerif:
282  stylehint = "Arial";
283  break;
284  case QFont::Serif:
285  stylehint = "Times New Roman";
286  break;
287  case QFont::TypeWriter:
288  stylehint = "Courier New";
289  break;
290  default:
291  if (request.fixedPitch)
292  stylehint = "Courier New";
293  break;
294  }
295  return stylehint;
296 }
uint fixedPitch
Definition: qfont_p.h:96
uint styleHint
Definition: qfont_p.h:93

◆ weightToFloat()

static float weightToFloat ( unsigned int  weight)
inlinestatic

Definition at line 298 of file qfontdatabase_mac.cpp.

299 {
300  return (weight - 50) / 100.0;
301 }