diff options
Diffstat (limited to 'src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm')
-rw-r--r-- | src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm | 797 |
1 files changed, 0 insertions, 797 deletions
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm deleted file mode 100644 index 894919a1c8..0000000000 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ /dev/null @@ -1,797 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobal.h" - -#include <sys/param.h> - -#if defined(Q_OS_OSX) -#import <AppKit/AppKit.h> -#import <IOKit/graphics/IOGraphicsLib.h> -#elif defined(QT_PLATFORM_UIKIT) -#import <UIKit/UIFont.h> -#endif - -#include <QtCore/qelapsedtimer.h> - -#include "qcoretextfontdatabase_p.h" -#include "qfontengine_coretext_p.h" -#if QT_CONFIG(settings) -#include <QtCore/QSettings> -#endif -#include <QtCore/QtEndian> -#ifndef QT_NO_FREETYPE -#include <QtFontDatabaseSupport/private/qfontengine_ft_p.h> -#endif - -QT_BEGIN_NAMESPACE - -// this could become a list of all languages used for each writing -// system, instead of using the single most common language. -static const char *languageForWritingSystem[] = { - 0, // Any - "en", // Latin - "el", // Greek - "ru", // Cyrillic - "hy", // Armenian - "he", // Hebrew - "ar", // Arabic - "syr", // Syriac - "div", // Thaana - "hi", // Devanagari - "bn", // Bengali - "pa", // Gurmukhi - "gu", // Gujarati - "or", // Oriya - "ta", // Tamil - "te", // Telugu - "kn", // Kannada - "ml", // Malayalam - "si", // Sinhala - "th", // Thai - "lo", // Lao - "bo", // Tibetan - "my", // Myanmar - "ka", // Georgian - "km", // Khmer - "zh-Hans", // SimplifiedChinese - "zh-Hant", // TraditionalChinese - "ja", // Japanese - "ko", // Korean - "vi", // Vietnamese - 0, // Symbol - "sga", // Ogham - "non", // Runic - "man" // N'Ko -}; -enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; - -QCoreTextFontDatabase::QCoreTextFontDatabase() - : m_hasPopulatedAliases(false) -{ -} - -QCoreTextFontDatabase::~QCoreTextFontDatabase() -{ - for (CTFontDescriptorRef ref : qAsConst(m_systemFontDescriptors)) - CFRelease(ref); -} - -void QCoreTextFontDatabase::populateFontDatabase() -{ - qCDebug(lcQpaFonts) << "Populating font database..."; - QElapsedTimer elapsed; - if (lcQpaFonts().isDebugEnabled()) - elapsed.start(); - - QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames(); - for (NSString *familyName in familyNames.as<const NSArray *>()) - QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName)); - - qCDebug(lcQpaFonts) << "Populating available families took" << elapsed.restart() << "ms"; - - // Force creating the theme fonts to get the descriptors in m_systemFontDescriptors - if (m_themeFonts.isEmpty()) - (void)themeFonts(); - - qCDebug(lcQpaFonts) << "Resolving theme fonts took" << elapsed.restart() << "ms"; - - Q_FOREACH (CTFontDescriptorRef fontDesc, m_systemFontDescriptors) - populateFromDescriptor(fontDesc); - - qCDebug(lcQpaFonts) << "Populating system descriptors took" << elapsed.restart() << "ms"; - - Q_ASSERT(!m_hasPopulatedAliases); -} - -bool QCoreTextFontDatabase::populateFamilyAliases(const QString &missingFamily) -{ -#if defined(Q_OS_MACOS) - if (m_hasPopulatedAliases) - return false; - - // There's no API to go from a localized family name to its non-localized - // name, so we have to resort to enumerating all the available fonts and - // doing a reverse lookup. - - qCDebug(lcQpaFonts) << "Populating family aliases..."; - QElapsedTimer elapsed; - elapsed.start(); - - QString nonLocalizedMatch; - QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames(); - NSFontManager *fontManager = NSFontManager.sharedFontManager; - for (NSString *familyName in familyNames.as<const NSArray *>()) { - NSString *localizedFamilyName = [fontManager localizedNameForFamily:familyName face:nil]; - if (![localizedFamilyName isEqual:familyName]) { - QString nonLocalizedFamily = QString::fromNSString(familyName); - QString localizedFamily = QString::fromNSString(localizedFamilyName); - QPlatformFontDatabase::registerAliasToFontFamily(nonLocalizedFamily, localizedFamily); - if (localizedFamily == missingFamily) - nonLocalizedMatch = nonLocalizedFamily; - } - } - m_hasPopulatedAliases = true; - - if (lcQpaFonts().isWarningEnabled()) { - QString warningMessage; - QDebug msg(&warningMessage); - - msg << "Populating font family aliases took" << elapsed.restart() << "ms."; - if (!nonLocalizedMatch.isNull()) - msg << "Replace uses of" << missingFamily << "with its non-localized name" << nonLocalizedMatch; - else - msg << "Replace uses of missing font family" << missingFamily << "with one that exists"; - msg << "to avoid this cost."; - - qCWarning(lcQpaFonts) << qPrintable(warningMessage); - } - - return true; -#else - Q_UNUSED(missingFamily); - return false; -#endif -} - -void QCoreTextFontDatabase::populateFamily(const QString &familyName) -{ - QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(familyName)); - QCFType<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) { - qCWarning(lcQpaFonts) << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName; - return; - } - - const int numFonts = CFArrayGetCount(matchingFonts); - for (int i = 0; i < numFonts; ++i) - populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)), familyName); -} - -void QCoreTextFontDatabase::invalidate() -{ - m_hasPopulatedAliases = false; -} - -struct FontDescription { - QCFString familyName; - QCFString styleName; - QString foundryName; - QFont::Weight weight; - QFont::Style style; - QFont::Stretch stretch; - qreal pointSize; - bool fixedPitch; - QSupportedWritingSystems writingSystems; -}; - -#ifndef QT_NO_DEBUG_STREAM -Q_DECL_UNUSED static inline QDebug operator<<(QDebug debug, const FontDescription &fd) -{ - QDebugStateSaver saver(debug); - return debug.nospace() << "FontDescription(" - << "familyName=" << QString(fd.familyName) - << ", styleName=" << QString(fd.styleName) - << ", foundry=" << fd.foundryName - << ", weight=" << fd.weight - << ", style=" << fd.style - << ", stretch=" << fd.stretch - << ", pointSize=" << fd.pointSize - << ", fixedPitch=" << fd.fixedPitch - << ", writingSystems=" << fd.writingSystems - << ")"; -} -#endif - -static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd) -{ - QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute); - - fd->foundryName = QStringLiteral("CoreText"); - fd->familyName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); - fd->styleName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute); - fd->weight = QFont::Normal; - fd->style = QFont::StyleNormal; - fd->stretch = QFont::Unstretched; - fd->fixedPitch = false; - - if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) { - uint tag = MAKE_TAG('O', 'S', '/', '2'); - CTFontRef tempFontRef = tempFont; - void *userData = reinterpret_cast<void *>(&tempFontRef); - uint length = 128; - QVarLengthArray<uchar, 128> os2Table(length); - if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length) && length >= 86) { - if (length > uint(os2Table.length())) { - os2Table.resize(length); - if (!QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length)) - Q_UNREACHABLE(); - Q_ASSERT(length >= 86); - } - quint32 unicodeRange[4] = { - qFromBigEndian<quint32>(os2Table.data() + 42), - qFromBigEndian<quint32>(os2Table.data() + 46), - qFromBigEndian<quint32>(os2Table.data() + 50), - qFromBigEndian<quint32>(os2Table.data() + 54) - }; - quint32 codePageRange[2] = { - qFromBigEndian<quint32>(os2Table.data() + 78), - qFromBigEndian<quint32>(os2Table.data() + 82) - }; - fd->writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); - } - } - - if (styles) { - if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) { - double normalizedWeight; - if (CFNumberGetValue(weightValue, kCFNumberFloat64Type, &normalizedWeight)) - fd->weight = QCoreTextFontEngine::qtWeightFromCFWeight(float(normalizedWeight)); - } - if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) { - double d; - if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) { - if (d > 0.0) - fd->style = QFont::StyleItalic; - } - } - if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) { - int d; - if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) { - if (d & kCTFontMonoSpaceTrait) - fd->fixedPitch = true; - if (d & kCTFontExpandedTrait) - fd->stretch = QFont::Expanded; - else if (d & kCTFontCondensedTrait) - fd->stretch = QFont::Condensed; - } - } - } - - if (QCFType<CFNumberRef> size = (CFNumberRef) CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) { - if (CFNumberIsFloatType(size)) { - double d; - CFNumberGetValue(size, kCFNumberDoubleType, &d); - fd->pointSize = d; - } else { - int i; - CFNumberGetValue(size, kCFNumberIntType, &i); - fd->pointSize = i; - } - } - - if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) { - CFIndex length = CFArrayGetCount(languages); - for (int i = 1; i < LanguageCount; ++i) { - if (!languageForWritingSystem[i]) - continue; - QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII); - if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang)) - fd->writingSystems.setSupported(QFontDatabase::WritingSystem(i)); - } - } -} - -void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName) -{ - FontDescription fd; - getFontDescription(font, &fd); - - // Note: The familyName we are registering, and the family name of the font descriptor, may not - // match, as CTFontDescriptorCreateMatchingFontDescriptors will return descriptors for replacement - // fonts if a font family does not have any fonts available on the system. - QString family = !familyName.isNull() ? familyName : static_cast<QString>(fd.familyName); - - CFRetain(font); - QPlatformFontDatabase::registerFont(family, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch, - true /* antialiased */, true /* scalable */, 0 /* pixelSize, ignored as font is scalable */, - fd.fixedPitch, fd.writingSystems, (void *)font); -} - -static NSString * const kQtFontDataAttribute = @"QtFontDataAttribute"; - -template <typename T> -T *descriptorAttribute(CTFontDescriptorRef descriptor, CFStringRef name) -{ - return [static_cast<T *>(CTFontDescriptorCopyAttribute(descriptor, name)) autorelease]; -} - -void QCoreTextFontDatabase::releaseHandle(void *handle) -{ - CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(handle); - if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) { - QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue); - delete fontData; - } - CFRelease(descriptor); -} - -extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); - -template <> -QFontEngine *QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>::fontEngine(const QFontDef &fontDef, void *usrPtr) -{ - QCFType<CTFontDescriptorRef> descriptor = QCFType<CTFontDescriptorRef>::constructFromGet( - static_cast<CTFontDescriptorRef>(usrPtr)); - - // Since we do not pass in the destination DPI to CoreText when making - // the font, we need to pass in a point size which is scaled to include - // the DPI. The default DPI for the screen is 72, thus the scale factor - // is destinationDpi / 72, but since pixelSize = pointSize / 72 * dpi, - // the pixelSize is actually the scaled point size for the destination - // DPI, and we can use that directly. - qreal scaledPointSize = fontDef.pixelSize; - - CGAffineTransform matrix = qt_transform_from_fontdef(fontDef); - if (QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix)) - return new QCoreTextFontEngine(font, fontDef); - - return nullptr; -} - -#ifndef QT_NO_FREETYPE -template <> -QFontEngine *QCoreTextFontDatabaseEngineFactory<QFontEngineFT>::fontEngine(const QFontDef &fontDef, void *usrPtr) -{ - CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(usrPtr); - - if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) { - QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue); - return QFontEngineFT::create(*fontData, fontDef.pixelSize, - static_cast<QFont::HintingPreference>(fontDef.hintingPreference)); - } else if (NSURL *url = descriptorAttribute<NSURL>(descriptor, kCTFontURLAttribute)) { - Q_ASSERT(url.fileURL); - QFontEngine::FaceId faceId; - faceId.filename = QString::fromNSString(url.path).toUtf8(); - return QFontEngineFT::create(fontDef, faceId); - } - Q_UNREACHABLE(); -} -#endif - -template <class T> -QFontEngine *QCoreTextFontDatabaseEngineFactory<T>::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) -{ - return T::create(fontData, pixelSize, hintingPreference); -} - -// Explicitly instantiate so that we don't need the plugin to involve FreeType -template class QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>; -#ifndef QT_NO_FREETYPE -template class QCoreTextFontDatabaseEngineFactory<QFontEngineFT>; -#endif - -CTFontDescriptorRef descriptorForFamily(const QString &familyName) -{ - return CTFontDescriptorCreateWithAttributes(CFDictionaryRef(@{ - (id)kCTFontFamilyNameAttribute: familyName.toNSString() - })); -} - -CTFontDescriptorRef descriptorForFamily(const char *familyName) -{ - return descriptorForFamily(QString::fromLatin1(familyName)); -} - -CFArrayRef fallbacksForDescriptor(CTFontDescriptorRef descriptor) -{ - QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, nullptr); - if (!font) { - qCWarning(lcQpaFonts) << "Failed to create fallback font for" << descriptor; - return nullptr; - } - - CFArrayRef cascadeList = CFArrayRef(CTFontCopyDefaultCascadeListForLanguages(font, - (CFArrayRef)[NSUserDefaults.standardUserDefaults stringArrayForKey:@"AppleLanguages"])); - - if (!cascadeList) { - qCWarning(lcQpaFonts) << "Failed to create fallback cascade list for" << descriptor; - return nullptr; - } - - return cascadeList; -} - -CFArrayRef QCoreTextFontDatabase::fallbacksForFamily(const QString &family) -{ - if (family.isEmpty()) - return nullptr; - - QCFType<CTFontDescriptorRef> fontDescriptor = descriptorForFamily(family); - if (!fontDescriptor) { - qCWarning(lcQpaFonts) << "Failed to create fallback font descriptor for" << family; - return nullptr; - } - - // If the font is not available we want to fall back to the style hint. - // By creating a matching font descriptor we can verify whether the font - // is available or not, and avoid CTFontCreateWithFontDescriptor picking - // a default font for us based on incomplete information. - fontDescriptor = CTFontDescriptorCreateMatchingFontDescriptor(fontDescriptor, 0); - if (!fontDescriptor) - return nullptr; - - return fallbacksForDescriptor(fontDescriptor); -} - -CTFontDescriptorRef descriptorForFontType(CTFontUIFontType uiType) -{ - static const CGFloat kDefaultSizeForRequestedUIType = 0.0; - QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage( - uiType, kDefaultSizeForRequestedUIType, nullptr); - return CTFontCopyFontDescriptor(ctFont); -} - -CTFontDescriptorRef descriptorForStyle(QFont::StyleHint styleHint) -{ - switch (styleHint) { - case QFont::SansSerif: return descriptorForFamily("Helvetica"); - case QFont::Serif: return descriptorForFamily("Times New Roman"); - case QFont::Monospace: return descriptorForFamily("Menlo"); -#ifdef Q_OS_MACOS - case QFont::Cursive: return descriptorForFamily("Apple Chancery"); -#endif - case QFont::Fantasy: return descriptorForFamily("Zapfino"); - case QFont::TypeWriter: return descriptorForFamily("American Typewriter"); - case QFont::AnyStyle: Q_FALLTHROUGH(); - case QFont::System: return descriptorForFontType(kCTFontUIFontSystem); - default: return nullptr; // No matching font on this platform - } -} - -QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const -{ - Q_UNUSED(style); - - qCDebug(lcQpaFonts).nospace() << "Resolving fallbacks families for" - << (!family.isEmpty() ? qPrintable(QLatin1String(" family '%1' with").arg(family)) : "") - << " style hint " << styleHint; - - QMacAutoReleasePool pool; - - QStringList fallbackList; - - QCFType<CFArrayRef> fallbackFonts = fallbacksForFamily(family); - if (!fallbackFonts || !CFArrayGetCount(fallbackFonts)) { - // We were not able to find a fallback for the specific family, - // or the family was empty, so we fall back to the style hint. - if (!family.isEmpty()) - qCDebug(lcQpaFonts) << "No fallbacks found. Using style hint instead"; - - if (QCFType<CTFontDescriptorRef> styleDescriptor = descriptorForStyle(styleHint)) { - CFMutableArrayRef tmp = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(tmp, styleDescriptor); - QCFType<CFArrayRef> styleFallbacks = fallbacksForDescriptor(styleDescriptor); - CFArrayAppendArray(tmp, styleFallbacks, CFRangeMake(0, CFArrayGetCount(styleFallbacks))); - fallbackFonts = tmp; - } - } - - if (!fallbackFonts) - return fallbackList; - - const int numberOfFallbacks = CFArrayGetCount(fallbackFonts); - for (int i = 0; i < numberOfFallbacks; ++i) { - auto fallbackDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fallbackFonts, i)); - auto fallbackFamilyName = QCFString(CTFontDescriptorCopyAttribute(fallbackDescriptor, kCTFontFamilyNameAttribute)); - - if (!isFamilyPopulated(fallbackFamilyName)) { - // We need to populate, or at least register the fallback fonts, - // otherwise the Qt font database may not know they exist. - if (isPrivateFontFamily(fallbackFamilyName)) - const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(fallbackDescriptor); - else - registerFontFamily(fallbackFamilyName); - } - - fallbackList.append(fallbackFamilyName); - } - - // Some fallback fonts will have have an order in the list returned - // by Core Text that would indicate they should be preferred for e.g. - // Arabic, or Emoji, while in reality only supporting a tiny subset - // of the required glyphs, or representing them by question marks. - // Move these to the end, so that the proper fonts are preferred. - for (const char *family : { ".Apple Symbols Fallback", ".Noto Sans Universal" }) { - int index = fallbackList.indexOf(QLatin1String(family)); - if (index >= 0) - fallbackList.move(index, fallbackList.size() - 1); - } - -#if defined(Q_OS_MACOS) - // Since we are only returning a list of default fonts for the current language, we do not - // cover all Unicode completely. This was especially an issue for some of the common script - // symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk - // of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most - // of Unicode 2.1. - if (!fallbackList.contains(QStringLiteral("Arial Unicode MS"))) - fallbackList.append(QStringLiteral("Arial Unicode MS")); - // Since some symbols (specifically Braille) are not in Arial Unicode MS, we - // add Apple Symbols to cover those too. - if (!fallbackList.contains(QStringLiteral("Apple Symbols"))) - fallbackList.append(QStringLiteral("Apple Symbols")); -#endif - - extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &); - fallbackList = qt_sort_families_by_writing_system(script, fallbackList); - - qCDebug(lcQpaFonts).nospace() << "Fallback families ordered by script " << script << ": " << fallbackList; - - return fallbackList; -} - -QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) -{ - QCFType<CFArrayRef> fonts; - - if (!fontData.isEmpty()) { - QCFType<CFDataRef> fontDataReference = fontData.toRawCFData(); - if (QCFType<CTFontDescriptorRef> descriptor = CTFontManagerCreateFontDescriptorFromData(fontDataReference)) { - // There's no way to get the data back out of a font descriptor created with - // CTFontManagerCreateFontDescriptorFromData, so we attach the data manually. - NSDictionary *attributes = @{ kQtFontDataAttribute : [NSValue valueWithPointer:new QByteArray(fontData)] }; - descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, (CFDictionaryRef)attributes); - CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(array, descriptor); - fonts = array; - } - } else { - QCFType<CFURLRef> fontURL = QUrl::fromLocalFile(fileName).toCFURL(); - fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL); - } - - if (!fonts) - return QStringList(); - - QStringList families; - const int numFonts = CFArrayGetCount(fonts); - for (int i = 0; i < numFonts; ++i) { - CTFontDescriptorRef fontDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fonts, i)); - populateFromDescriptor(fontDescriptor); - QCFType<CFStringRef> familyName = CFStringRef(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute)); - families.append(QString::fromCFString(familyName)); - } - - // Note: We don't do font matching via CoreText for application fonts, so we don't - // need to enable font matching for them via CTFontManagerEnableFontDescriptors. - - return families; -} - -bool QCoreTextFontDatabase::isPrivateFontFamily(const QString &family) const -{ - if (family.startsWith(QLatin1Char('.')) || family == QLatin1String("LastResort")) - return true; - - return QPlatformFontDatabase::isPrivateFontFamily(family); -} - -static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f) -{ - switch (f) { - case QPlatformTheme::SystemFont: - return kCTFontUIFontSystem; - - case QPlatformTheme::MenuFont: - case QPlatformTheme::MenuBarFont: - case QPlatformTheme::MenuItemFont: - return kCTFontUIFontMenuItem; - - case QPlatformTheme::MessageBoxFont: - return kCTFontUIFontEmphasizedSystem; - - case QPlatformTheme::LabelFont: - return kCTFontUIFontSystem; - - case QPlatformTheme::TipLabelFont: - return kCTFontUIFontToolTip; - - case QPlatformTheme::StatusBarFont: - return kCTFontUIFontSystem; - - case QPlatformTheme::TitleBarFont: - return kCTFontUIFontWindowTitle; - - case QPlatformTheme::MdiSubWindowTitleFont: - return kCTFontUIFontSystem; - - case QPlatformTheme::DockWidgetTitleFont: - return kCTFontUIFontSmallSystem; - - case QPlatformTheme::PushButtonFont: - return kCTFontUIFontPushButton; - - case QPlatformTheme::CheckBoxFont: - case QPlatformTheme::RadioButtonFont: - return kCTFontUIFontSystem; - - case QPlatformTheme::ToolButtonFont: - return kCTFontUIFontSmallToolbar; - - case QPlatformTheme::ItemViewFont: - return kCTFontUIFontSystem; - - case QPlatformTheme::ListViewFont: - return kCTFontUIFontViews; - - case QPlatformTheme::HeaderViewFont: - return kCTFontUIFontSmallSystem; - - case QPlatformTheme::ListBoxFont: - return kCTFontUIFontViews; - - case QPlatformTheme::ComboMenuItemFont: - return kCTFontUIFontSystem; - - case QPlatformTheme::ComboLineEditFont: - return kCTFontUIFontViews; - - case QPlatformTheme::SmallFont: - return kCTFontUIFontSmallSystem; - - case QPlatformTheme::MiniFont: - return kCTFontUIFontMiniSystem; - - case QPlatformTheme::FixedFont: - return kCTFontUIFontUserFixedPitch; - - default: - return kCTFontUIFontSystem; - } -} - -static CTFontDescriptorRef fontDescriptorFromTheme(QPlatformTheme::Font f) -{ -#if defined(QT_PLATFORM_UIKIT) - // Use Dynamic Type to resolve theme fonts if possible, to get - // correct font sizes and style based on user configuration. - NSString *textStyle = 0; - switch (f) { - case QPlatformTheme::TitleBarFont: - case QPlatformTheme::HeaderViewFont: - textStyle = UIFontTextStyleHeadline; - break; - case QPlatformTheme::MdiSubWindowTitleFont: - textStyle = UIFontTextStyleSubheadline; - break; - case QPlatformTheme::TipLabelFont: - case QPlatformTheme::SmallFont: - textStyle = UIFontTextStyleFootnote; - break; - case QPlatformTheme::MiniFont: - textStyle = UIFontTextStyleCaption2; - break; - case QPlatformTheme::FixedFont: - // Fall back to regular code path, as iOS doesn't provide - // an appropriate text style for this theme font. - break; - default: - textStyle = UIFontTextStyleBody; - break; - } - - if (textStyle) { - UIFontDescriptor *desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle]; - return static_cast<CTFontDescriptorRef>(CFBridgingRetain(desc)); - } -#endif // Q_OS_IOS, Q_OS_TVOS, Q_OS_WATCHOS - - // macOS default case and iOS fallback case - return descriptorForFontType(fontTypeFromTheme(f)); -} - -const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts() const -{ - if (m_themeFonts.isEmpty()) { - for (long f = QPlatformTheme::SystemFont; f < QPlatformTheme::NFonts; f++) { - QPlatformTheme::Font ft = static_cast<QPlatformTheme::Font>(f); - m_themeFonts.insert(ft, themeFont(ft)); - } - } - - return m_themeFonts; -} - -QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const -{ - CTFontDescriptorRef fontDesc = fontDescriptorFromTheme(f); - FontDescription fd; - getFontDescription(fontDesc, &fd); - - if (!m_systemFontDescriptors.contains(fontDesc)) - m_systemFontDescriptors.insert(fontDesc); - else - CFRelease(fontDesc); - - QFont *font = new QFont(fd.familyName, fd.pointSize, fd.weight, fd.style == QFont::StyleItalic); - return font; -} - -QFont QCoreTextFontDatabase::defaultFont() const -{ - if (defaultFontName.isEmpty()) { - QCFType<CTFontDescriptorRef> systemFont = descriptorForFontType(kCTFontUIFontSystem); - defaultFontName = QCFString(CTFontDescriptorCopyAttribute(systemFont, kCTFontFamilyNameAttribute)); - } - - return QFont(defaultFontName); -} - -bool QCoreTextFontDatabase::fontsAlwaysScalable() const -{ - return true; -} - -QList<int> QCoreTextFontDatabase::standardSizes() const -{ - QList<int> ret; - static const unsigned short standard[] = - { 9, 10, 11, 12, 13, 14, 18, 24, 36, 48, 64, 72, 96, 144, 288, 0 }; - ret.reserve(int(sizeof(standard) / sizeof(standard[0]))); - const unsigned short *sizes = standard; - while (*sizes) ret << *sizes++; - return ret; -} - -QT_END_NAMESPACE - |