diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/text/qfontdatabase.cpp | 91 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase.cpp | 32 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase.h | 2 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm | 49 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h | 1 |
5 files changed, 136 insertions, 39 deletions
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 02b9e6d25c..ae7b6c1c0d 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -317,6 +317,7 @@ struct QtFontFamily QtFontFamily(const QString &n) : + populated(false), fixedPitch(false), name(n), count(0), foundries(0) , bogusWritingSystems(false) @@ -330,6 +331,7 @@ struct QtFontFamily free(foundries); } + bool populated : 1; bool fixedPitch : 1; QString name; @@ -344,6 +346,8 @@ struct QtFontFamily bool matchesFamilyName(const QString &familyName) const; QtFontFoundry *foundry(const QString &f, bool = false); + + void ensurePopulated(); }; QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) @@ -375,6 +379,14 @@ bool QtFontFamily::matchesFamilyName(const QString &familyName) const return name.compare(familyName, Qt::CaseInsensitive) == 0 || aliases.contains(familyName, Qt::CaseInsensitive); } +void QtFontFamily::ensurePopulated() +{ + if (populated) + return; + + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamily(name); + Q_ASSERT(populated); +} class QFontDatabasePrivate { @@ -386,7 +398,14 @@ public: ~QFontDatabasePrivate() { free(); } - QtFontFamily *family(const QString &f, bool = false); + + enum FamilyRequestFlags { + RequestFamily = 0, + EnsureCreated, + EnsurePopulated + }; + + QtFontFamily *family(const QString &f, FamilyRequestFlags flags = EnsurePopulated); void free() { while (count--) delete families[count]; @@ -424,8 +443,10 @@ void QFontDatabasePrivate::invalidate() emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged(); } -QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) +QtFontFamily *QFontDatabasePrivate::family(const QString &f, FamilyRequestFlags flags) { + QtFontFamily *fam = 0; + int low = 0; int high = count; int pos = count / 2; @@ -439,28 +460,34 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) pos = (high + low) / 2; } if (!res) - return families[pos]; + fam = families[pos]; } - if (!create) - return 0; - if (res < 0) - pos++; + if (!fam && (flags & EnsureCreated)) { + if (res < 0) + pos++; + + // qDebug() << "adding family " << f.toLatin1() << " at " << pos << " total=" << count; + if (!(count % 8)) { + QtFontFamily **newFamilies = (QtFontFamily **) + realloc(families, + (((count+8) >> 3) << 3) * sizeof(QtFontFamily *)); + Q_CHECK_PTR(newFamilies); + families = newFamilies; + } + + QtFontFamily *family = new QtFontFamily(f); + memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *)); + families[pos] = family; + count++; - // qDebug() << "adding family " << f.toLatin1() << " at " << pos << " total=" << count; - if (!(count % 8)) { - QtFontFamily **newFamilies = (QtFontFamily **) - realloc(families, - (((count+8) >> 3) << 3) * sizeof(QtFontFamily *)); - Q_CHECK_PTR(newFamilies); - families = newFamilies; + fam = families[pos]; } - QtFontFamily *family = new QtFontFamily(f); - memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *)); - families[pos] = family; - count++; - return families[pos]; + if (fam && (flags & EnsurePopulated)) + fam->ensurePopulated(); + + return fam; } @@ -670,7 +697,7 @@ void qt_registerFont(const QString &familyName, const QString &stylename, styleKey.style = style; styleKey.weight = weight; styleKey.stretch = stretch; - QtFontFamily *f = d->family(familyName, true); + QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::EnsureCreated); f->fixedPitch = fixedPitch; for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { @@ -689,6 +716,13 @@ void qt_registerFont(const QString &familyName, const QString &stylename, integration->fontDatabase()->releaseHandle(size->handle); } size->handle = handle; + f->populated = true; +} + +void qt_registerFontFamily(const QString &familyName) +{ + // Create uninitialized/unpopulated family + privateDb()->family(familyName, QFontDatabasePrivate::EnsureCreated); } void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias) @@ -697,7 +731,7 @@ void qt_registerAliasToFontFamily(const QString &familyName, const QString &alia return; QFontDatabasePrivate *d = privateDb(); - QtFontFamily *f = d->family(familyName, false); + QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::RequestFamily); if (!f) return; @@ -1092,6 +1126,8 @@ static int match(int script, const QFontDef &request, if (!matchFamilyName(family_name, test.family)) continue; + test.family->ensurePopulated(); + if (family_name.isEmpty()) load(test.family->name, script); @@ -1304,6 +1340,8 @@ QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const QList<WritingSystem> list; for (int i = 0; i < d->count; ++i) { QtFontFamily *family = d->families[i]; + family->ensurePopulated(); + if (family->count == 0) continue; for (int x = Latin; x < WritingSystemsCount; ++x) { @@ -1367,11 +1405,14 @@ QStringList QFontDatabase::families(WritingSystem writingSystem) const QStringList flist; for (int i = 0; i < d->count; i++) { QtFontFamily *f = d->families[i]; - if (f->count == 0) + if (f->populated && f->count == 0) continue; - if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported)) - continue; - if (f->count == 1) { + if (writingSystem != Any) { + f->ensurePopulated(); + if (f->writingSystems[writingSystem] != QtFontFamily::Supported) + continue; + } + if (!f->populated || f->count == 1) { flist.append(f->name); } else { for (int j = 0; j < f->count; j++) { diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index 5f277c878a..33301005c6 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -53,6 +53,7 @@ void qt_registerFont(const QString &familyname, const QString &stylename, bool scalable, int pixelSize, bool fixedPitch, const QSupportedWritingSystems &writingSystems, void *hanlde); +void qt_registerFontFamily(const QString &familyName); void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias); /*! @@ -118,7 +119,7 @@ void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void * The writing systems supported by the font are specified by the \a writingSystems argument. - \sa registerQPF2Font() + \sa registerQPF2Font(), registerFontFamily() */ void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &stylename, const QString &foundryname, QFont::Weight weight, @@ -134,6 +135,18 @@ void QPlatformFontDatabase::registerFont(const QString &familyname, const QStrin fixedPitch, writingSystems, usrPtr); } +/*! + Registers a font family with the font database. The font will be + lazily populated by a callback to populateFamily() when the font + database determines that the family needs population. + + \sa populateFamily(), registerFont() +*/ +void QPlatformFontDatabase::registerFontFamily(const QString &familyName) +{ + qt_registerFontFamily(familyName); +} + class QWritingSystemsPrivate { public: @@ -249,6 +262,11 @@ QPlatformFontDatabase::~QPlatformFontDatabase() Reimplement this function in a subclass for a convenient place to initialize the internal font database. + You may lazily populate the database by calling registerFontFamily() instead + of registerFont(), in which case you'll get a callback to populateFamily() + when the required family needs population. You then call registerFont() to + finish population of the family. + The default implementation looks in the fontDir() location and registers all QPF2 fonts. */ @@ -276,6 +294,18 @@ void QPlatformFontDatabase::populateFontDatabase() } /*! + This function is called whenever a lazily populated family, populated + through registerFontFamily(), needs full population. + + You are expected to fully populate the family by calling registerFont() + for each font that matches the family name. +*/ +void QPlatformFontDatabase::populateFamily(const QString &familyName) +{ + Q_UNUSED(familyName); +} + +/*! This function is called whenever the font database is invalidated. Reimplement this function to clear any internal data structures that diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h index 870480809b..b200cf0e58 100644 --- a/src/gui/text/qplatformfontdatabase.h +++ b/src/gui/text/qplatformfontdatabase.h @@ -96,6 +96,7 @@ class Q_GUI_EXPORT QPlatformFontDatabase public: virtual ~QPlatformFontDatabase(); virtual void populateFontDatabase(); + virtual void populateFamily(const QString &familyName); virtual void invalidate(); virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script); @@ -125,6 +126,7 @@ public: bool scalable, int pixelSize, bool fixedPitch, const QSupportedWritingSystems &writingSystems, void *handle); + static void registerFontFamily(const QString &familyName); static void registerAliasToFontFamily(const QString &familyName, const QString &alias); }; diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index afee68ebed..1c0e888758 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -41,9 +41,11 @@ #include "qglobal.h" -#ifdef Q_OS_MACX +#if defined(Q_OS_MACX) #import <Cocoa/Cocoa.h> #import <IOKit/graphics/IOGraphicsLib.h> +#elif defined(Q_OS_IOS) +#import <UIKit/UIFont.h> #endif #include "qcoretextfontdatabase_p.h" @@ -176,29 +178,50 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase() { } +static CFArrayRef availableFamilyNames() +{ +#if defined(Q_OS_OSX) + return CTFontManagerCopyAvailableFontFamilyNames(); +#elif defined(Q_OS_IOS) + return (CFArrayRef) [[UIFont familyNames] retain]; +#endif +} + void QCoreTextFontDatabase::populateFontDatabase() { // The caller (QFontDB) expects the db to be populate only with system fonts, so we need // to make sure that any previously registered app fonts become invisible. removeApplicationFonts(); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + QCFType<CFArrayRef> familyNames = availableFamilyNames(); + const int numberOfFamilies = CFArrayGetCount(familyNames); + for (int i = 0; i < numberOfFamilies; ++i) { + QString familyName = QCFString::toQString((CFStringRef) CFArrayGetValueAtIndex(familyNames, i)); - QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0); - if (! collection) - return; + // Don't populate internal fonts + if (familyName.startsWith(QLatin1Char('.')) || familyName == QStringLiteral("LastResort")) + continue; - QCFType<CFArrayRef> fonts = CTFontCollectionCreateMatchingFontDescriptors(collection); - if (! fonts) - return; + QPlatformFontDatabase::registerFontFamily(familyName); + } +} - const int numFonts = CFArrayGetCount(fonts); - for (int i = 0; i < numFonts; ++i) { - CTFontDescriptorRef font = (CTFontDescriptorRef) CFArrayGetValueAtIndex(fonts, i); - populateFromDescriptor(font); +void QCoreTextFontDatabase::populateFamily(const QString &familyName) +{ + CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(familyName)); + CTFontDescriptorRef nameOnlyDescriptor = CTFontDescriptorCreateWithAttributes(attributes); + + // A single family might match several different fonts with different styles eg. + QCFType<CFArrayRef> matchingFonts = (CFArrayRef) CTFontDescriptorCreateMatchingFontDescriptors(nameOnlyDescriptor, 0); + if (!matchingFonts) { + qWarning() << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName; + return; } - [pool release]; + const int numFonts = CFArrayGetCount(matchingFonts); + for (int i = 0; i < numFonts; ++i) + populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i))); } void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index c6fc791503..c73f4a32ca 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -72,6 +72,7 @@ public: QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase(); + void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); |