diff --git a/setup/build.py b/setup/build.py index 25a9ca1ea3..e30654d2f1 100644 --- a/setup/build.py +++ b/setup/build.py @@ -458,7 +458,7 @@ class Build(Command): from setup.parallel_build import cpu_count if iswindows or ishaiku: return # Dont have headless operation on these platforms - from setup.build_environment import ft_inc_dirs, QMAKE + from setup.build_environment import CMAKE self.info('\n####### Building headless QPA plugin', '#'*7) a = absolutize headers = a([ @@ -470,50 +470,25 @@ class Build(Command): 'calibre/headless/headless_backingstore.cpp', 'calibre/headless/headless_integration.cpp', ]) - if ismacos: - sources.extend(a(['calibre/headless/coretext_fontdatabase.mm'])) - else: - headers.extend(a(['calibre/headless/fontconfig_database.h'])) - sources.extend(a(['calibre/headless/fontconfig_database.cpp'])) others = a(['calibre/headless/headless.json']) target = self.dest('headless') + if not ismacos: + target = target.replace('headless', 'libheadless') if not self.newer(target, headers + sources + others): return - pro = textwrap.dedent( - '''\ - TARGET = headless - PLUGIN_TYPE = platforms - PLUGIN_CLASS_NAME = HeadlessIntegrationPlugin - QT += core-private gui-private - TEMPLATE = lib - CONFIG += plugin - QT += fontdatabase_support_private service_support_private eventdispatcher_support_private - HEADERS = {headers} - SOURCES = {sources} - OTHER_FILES = {others} - INCLUDEPATH += {freetype} - DESTDIR = {destdir} - CONFIG -= create_cmake # Prevent qmake from generating a cmake build file which it puts in the calibre src directory - ''').format( - headers=' '.join(headers), sources=' '.join(sources), others=' '.join(others), destdir=self.d( - target), freetype=' '.join(ft_inc_dirs)) bdir = self.j(self.build_dir, 'headless') - if not os.path.exists(bdir): - os.makedirs(bdir) - pf = self.j(bdir, 'headless.pro') - open(self.j(bdir, '.qmake.conf'), 'wb').close() - with open(pf, 'wb') as f: - f.write(pro.encode('utf-8')) + if os.path.exists(bdir): + shutil.rmtree(bdir) + os.makedirs(bdir) cwd = os.getcwd() os.chdir(bdir) try: - self.check_call([QMAKE] + [self.b(pf)]) + self.check_call([CMAKE, '-S', os.path.dirname(sources[0])]) self.check_call([self.env.make] + ['-j%d'%(cpu_count or 1)]) finally: os.chdir(cwd) - if ismacos: - os.rename(self.j(self.d(target), 'libheadless.dylib'), self.j(self.d(target), 'headless.so')) + os.rename(self.j(bdir, 'libheadless.' + ('dylib' if ismacos else 'so')), target) def create_sip_build_skeleton(self, src_dir, ext): from setup.build_environment import pyqt_sip_abi_version diff --git a/setup/build_environment.py b/setup/build_environment.py index 70b497cd11..ab27bfb769 100644 --- a/setup/build_environment.py +++ b/setup/build_environment.py @@ -60,6 +60,8 @@ for x in ('qmake6', 'qmake-qt6', 'qt6-qmake', 'qmake'): QMAKE = os.environ.get('QMAKE', QMAKE) if iswindows and not QMAKE.lower().endswith('.exe'): QMAKE += '.exe' +CMAKE = 'cmake' +CMAKE = os.environ.get('CMAKE', CMAKE) PKGCONFIG = shutil.which('pkg-config') PKGCONFIG = os.environ.get('PKG_CONFIG', PKGCONFIG) diff --git a/src/calibre/headless/.qmake.conf b/src/calibre/headless/.qmake.conf deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/calibre/headless/CMakeLists.txt b/src/calibre/headless/CMakeLists.txt new file mode 100644 index 0000000000..9de5e10067 --- /dev/null +++ b/src/calibre/headless/CMakeLists.txt @@ -0,0 +1,8 @@ +project(headless) +cmake_minimum_required(VERSION 3.21) +set(CMAKE_AUTOMOC ON) +find_package(Qt6Gui REQUIRED) +add_library(headless MODULE main.cpp headless_backingstore.cpp headless_integration.cpp) +set_property(TARGET headless PROPERTY QT_PLUGIN_TYPE "platforms") +set_property(TARGET headless PROPERTY QT_PLUGIN_CLASS_NAME "HeadlessIntegrationPlugin") +target_link_libraries(headless PRIVATE Qt::Gui Qt::GuiPrivate Qt::Core Qt::CorePrivate) diff --git a/src/calibre/headless/coretext_fontdatabase.mm b/src/calibre/headless/coretext_fontdatabase.mm deleted file mode 100644 index b56a6e095e..0000000000 --- a/src/calibre/headless/coretext_fontdatabase.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 - -#include - -#if defined(Q_OS_OSX) -#import -#import -#elif defined(QT_PLATFORM_UIKIT) -#import -#endif - -#include - -#include -#include -#if QT_CONFIG(settings) -#include -#endif -#include -#ifndef QT_NO_FREETYPE -#include -#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 familyNames = CTFontManagerCopyAvailableFontFamilyNames(); - for (NSString *familyName in familyNames.as()) - 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 familyNames = CTFontManagerCopyAvailableFontFamilyNames(); - NSFontManager *fontManager = NSFontManager.sharedFontManager; - for (NSString *familyName in familyNames.as()) { - 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 attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(familyName)); - QCFType nameOnlyDescriptor = CTFontDescriptorCreateWithAttributes(attributes); - - // A single family might match several different fonts with different styles eg. - QCFType 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 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 tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) { - uint tag = MAKE_TAG('O', 'S', '/', '2'); - CTFontRef tempFontRef = tempFont; - void *userData = reinterpret_cast(&tempFontRef); - uint length = 128; - QVarLengthArray 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(os2Table.data() + 42), - qFromBigEndian(os2Table.data() + 46), - qFromBigEndian(os2Table.data() + 50), - qFromBigEndian(os2Table.data() + 54) - }; - quint32 codePageRange[2] = { - qFromBigEndian(os2Table.data() + 78), - qFromBigEndian(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 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 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(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 -T *descriptorAttribute(CTFontDescriptorRef descriptor, CFStringRef name) -{ - return [static_cast(CTFontDescriptorCopyAttribute(descriptor, name)) autorelease]; -} - -void QCoreTextFontDatabase::releaseHandle(void *handle) -{ - CTFontDescriptorRef descriptor = static_cast(handle); - if (NSValue *fontDataValue = descriptorAttribute(descriptor, (CFStringRef)kQtFontDataAttribute)) { - QByteArray *fontData = static_cast(fontDataValue.pointerValue); - delete fontData; - } - CFRelease(descriptor); -} - -extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); - -template <> -QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QFontDef &fontDef, void *usrPtr) -{ - QCFType descriptor = QCFType::constructFromGet( - static_cast(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 font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix)) - return new QCoreTextFontEngine(font, fontDef); - - return nullptr; -} - -#ifndef QT_NO_FREETYPE -template <> -QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QFontDef &fontDef, void *usrPtr) -{ - CTFontDescriptorRef descriptor = static_cast(usrPtr); - - if (NSValue *fontDataValue = descriptorAttribute(descriptor, (CFStringRef)kQtFontDataAttribute)) { - QByteArray *fontData = static_cast(fontDataValue.pointerValue); - return QFontEngineFT::create(*fontData, fontDef.pixelSize, - static_cast(fontDef.hintingPreference)); - } else if (NSURL *url = descriptorAttribute(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 -QFontEngine *QCoreTextFontDatabaseEngineFactory::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; -#ifndef QT_NO_FREETYPE -template class QCoreTextFontDatabaseEngineFactory; -#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 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 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 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 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 styleDescriptor = descriptorForStyle(styleHint)) { - CFMutableArrayRef tmp = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(tmp, styleDescriptor); - QCFType 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(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 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 fonts; - - if (!fontData.isEmpty()) { - QCFType fontDataReference = fontData.toRawCFData(); - if (QCFType 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 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 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(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 &QCoreTextFontDatabase::themeFonts() const -{ - if (m_themeFonts.isEmpty()) { - for (long f = QPlatformTheme::SystemFont; f < QPlatformTheme::NFonts; f++) { - QPlatformTheme::Font ft = static_cast(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 systemFont = descriptorForFontType(kCTFontUIFontSystem); - defaultFontName = QCFString(CTFontDescriptorCopyAttribute(systemFont, kCTFontFamilyNameAttribute)); - } - - return QFont(defaultFontName); -} - -bool QCoreTextFontDatabase::fontsAlwaysScalable() const -{ - return true; -} - -QList QCoreTextFontDatabase::standardSizes() const -{ - QList 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 - diff --git a/src/calibre/headless/fontconfig_database.cpp b/src/calibre/headless/fontconfig_database.cpp deleted file mode 100644 index 96a6365ba2..0000000000 --- a/src/calibre/headless/fontconfig_database.cpp +++ /dev/null @@ -1,1093 +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 "fontconfig_database.h" - -#include -#include - -#include -#include -#include -#include - -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) -#include -#else -#include -#endif -#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) -#include -#else -#include -#endif -#include -#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) -#include -#endif - -#include - -#include -#if FC_VERSION >= 20402 -#include -#endif - -QT_BEGIN_NAMESPACE - -#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) -static const int maxWeight = 99; - -static inline int mapToQtWeightForRange(int fcweight, int fcLower, int fcUpper, int qtLower, int qtUpper) -{ - return qtLower + ((fcweight - fcLower) * (qtUpper - qtLower)) / (fcUpper - fcLower); -} -#endif - -static inline int weightFromFcWeight(int fcweight) -{ - // Font Config uses weights from 0 to 215 (the highest enum value) while QFont ranges from - // 0 to 99. The spacing between the values for the enums are uneven so a linear mapping from - // Font Config values to Qt would give surprising results. So, we do a piecewise linear - // mapping. This ensures that where there is a corresponding enum on both sides (for example - // FC_WEIGHT_DEMIBOLD and QFont::DemiBold) we map one to the other but other values map - // to intermediate Qt weights. -#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) - if (fcweight <= FC_WEIGHT_THIN) - return QFont::Thin; - if (fcweight <= FC_WEIGHT_ULTRALIGHT) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_THIN, FC_WEIGHT_ULTRALIGHT, QFont::Thin, QFont::ExtraLight); - if (fcweight <= FC_WEIGHT_LIGHT) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRALIGHT, FC_WEIGHT_LIGHT, QFont::ExtraLight, QFont::Light); - if (fcweight <= FC_WEIGHT_NORMAL) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_LIGHT, FC_WEIGHT_NORMAL, QFont::Light, QFont::Normal); - if (fcweight <= FC_WEIGHT_MEDIUM) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_NORMAL, FC_WEIGHT_MEDIUM, QFont::Normal, QFont::Medium); - if (fcweight <= FC_WEIGHT_DEMIBOLD) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_MEDIUM, FC_WEIGHT_DEMIBOLD, QFont::Medium, QFont::DemiBold); - if (fcweight <= FC_WEIGHT_BOLD) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_DEMIBOLD, FC_WEIGHT_BOLD, QFont::DemiBold, QFont::Bold); - if (fcweight <= FC_WEIGHT_ULTRABOLD) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_BOLD, FC_WEIGHT_ULTRABOLD, QFont::Bold, QFont::ExtraBold); - if (fcweight <= FC_WEIGHT_BLACK) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRABOLD, FC_WEIGHT_BLACK, QFont::ExtraBold, QFont::Black); - if (fcweight <= FC_WEIGHT_ULTRABLACK) - return mapToQtWeightForRange(fcweight, FC_WEIGHT_BLACK, FC_WEIGHT_ULTRABLACK, QFont::Black, maxWeight); - return maxWeight; -#else - const int maxWeight = 99; - int qtweight; - if (fcweight < 0) - qtweight = 0; - else if (fcweight <= FC_WEIGHT_LIGHT) - qtweight = (fcweight * QFont::Light) / FC_WEIGHT_LIGHT; - else if (fcweight <= FC_WEIGHT_NORMAL) - qtweight = QFont::Light + ((fcweight - FC_WEIGHT_LIGHT) * (QFont::Normal - QFont::Light)) / (FC_WEIGHT_NORMAL - FC_WEIGHT_LIGHT); - else if (fcweight <= FC_WEIGHT_DEMIBOLD) - qtweight = QFont::Normal + ((fcweight - FC_WEIGHT_NORMAL) * (QFont::DemiBold - QFont::Normal)) / (FC_WEIGHT_DEMIBOLD - FC_WEIGHT_NORMAL); - else if (fcweight <= FC_WEIGHT_BOLD) - qtweight = QFont::DemiBold + ((fcweight - FC_WEIGHT_DEMIBOLD) * (QFont::Bold - QFont::DemiBold)) / (FC_WEIGHT_BOLD - FC_WEIGHT_DEMIBOLD); - else if (fcweight <= FC_WEIGHT_BLACK) - qtweight = QFont::Bold + ((fcweight - FC_WEIGHT_BOLD) * (QFont::Black - QFont::Bold)) / (FC_WEIGHT_BLACK - FC_WEIGHT_BOLD); - else if (fcweight <= FC_WEIGHT_ULTRABLACK) - qtweight = QFont::Black + ((fcweight - FC_WEIGHT_BLACK) * (maxWeight - QFont::Black)) / (FC_WEIGHT_ULTRABLACK - FC_WEIGHT_BLACK); - else - qtweight = maxWeight; - - return qtweight; -#endif -} - -static inline int stretchFromFcWidth(int fcwidth) -{ - // Font Config enums for width match pretty closely with those used by Qt so just use - // Font Config values directly while enforcing the same limits imposed by QFont. - const int maxStretch = 4000; - int qtstretch; - if (fcwidth < 1) - qtstretch = 1; - else if (fcwidth > maxStretch) - qtstretch = maxStretch; - else - qtstretch = fcwidth; - - return qtstretch; -} - -static const char specialLanguages[][6] = { - "", // Unknown - "", // Inherited - "", // Common - "en", // Latin - "el", // Greek - "ru", // Cyrillic - "hy", // Armenian - "he", // Hebrew - "ar", // Arabic - "syr", // Syriac - "dv", // 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 - "ko", // Hangul - "am", // Ethiopic - "chr", // Cherokee - "cr", // CanadianAboriginal - "sga", // Ogham - "non", // Runic - "km", // Khmer - "mn", // Mongolian - "ja", // Hiragana - "ja", // Katakana - "zh-TW", // Bopomofo - "", // Han - "ii", // Yi - "ett", // OldItalic - "got", // Gothic - "en", // Deseret - "fil", // Tagalog - "hnn", // Hanunoo - "bku", // Buhid - "tbw", // Tagbanwa - "cop", // Coptic - "lif", // Limbu - "tdd", // TaiLe - "grc", // LinearB - "uga", // Ugaritic - "en", // Shavian - "so", // Osmanya - "grc", // Cypriot - "", // Braille - "bug", // Buginese - "khb", // NewTaiLue - "cu", // Glagolitic - "shi", // Tifinagh - "syl", // SylotiNagri - "peo", // OldPersian - "pra", // Kharoshthi - "ban", // Balinese - "akk", // Cuneiform - "phn", // Phoenician - "lzh", // PhagsPa - "man", // Nko - "su", // Sundanese - "lep", // Lepcha - "sat", // OlChiki - "vai", // Vai - "saz", // Saurashtra - "eky", // KayahLi - "rej", // Rejang - "xlc", // Lycian - "xcr", // Carian - "xld", // Lydian - "cjm", // Cham - "nod", // TaiTham - "blt", // TaiViet - "ae", // Avestan - "egy", // EgyptianHieroglyphs - "smp", // Samaritan - "lis", // Lisu - "bax", // Bamum - "jv", // Javanese - "mni", // MeeteiMayek - "arc", // ImperialAramaic - "xsa", // OldSouthArabian - "xpr", // InscriptionalParthian - "pal", // InscriptionalPahlavi - "otk", // OldTurkic - "bh", // Kaithi - "bbc", // Batak - "pra", // Brahmi - "myz", // Mandaic - "ccp", // Chakma - "xmr", // MeroiticCursive - "xmr", // MeroiticHieroglyphs - "hmd", // Miao - "sa", // Sharada - "srb", // SoraSompeng -#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) - "doi", // Takri - "lez", // CaucasianAlbanian - "bsq", // BassaVah - "fr", // Duployan - "sq", // Elbasan - "sa", // Grantha - "hnj", // PahawhHmong - "sd", // Khojki - "lab", // LinearA - "hi", // Mahajani - "xmn", // Manichaean - "men", // MendeKikakui - "mr", // Modi - "mru", // Mro - "xna", // OldNorthArabian - "arc", // Nabataean - "arc", // Palmyrene - "ctd", // PauCinHau - "kv", // OldPermic - "pal", // PsalterPahlavi - "sa", // Siddham - "sd", // Khudawadi - "mai", // Tirhuta -#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) - "hoc", // WarangCiti - "", // Ahom - "", // AnatolianHieroglyphs - "", // Hatran - "", // Multani - "", // OldHungarian -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - "", // SignWriting - "", // Adlam - "", // Bhaiksuki - "", // Marchen - "", // Newa - "", // Osage - "", // Tangut - "", // MasaramGondi - "", // Nushu - "", // Soyombo -#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) - "", // ZanabazarSquare - "", // Dogra - "", // GunjalaGondi - "", // HanifiRohingya - "", // Makasar - "", // Medefaidrin - "", // OldSogdian - "", // Sogdian - "", // Elymaic - "", // Nandinagari - "", // NyiakengPuachueHmong - "", // Wancho - "", // Chorasmian - "", // DivesAkuru - "", // KhitanSmallScript - "" // Yezidi -#else - "" // ZanabazarSquare -#endif // Qt >= 5.15 -#else - "" // SignWriting -#endif // Qt >= 5.11 -#else - "hoc" // WarangCiti -#endif // Qt >= 5.6.0 -#else - "doi" // Takri -#endif // Qt >= 5.5.0 - -}; -Q_STATIC_ASSERT(sizeof specialLanguages / sizeof *specialLanguages == QChar::ScriptCount); - -// 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[][6] = { - "", // 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-cn", // SimplifiedChinese - "zh-tw", // TraditionalChinese - "ja", // Japanese - "ko", // Korean - "vi", // Vietnamese - "", // Symbol - "sga", // Ogham - "non", // Runic - "man" // N'Ko -}; -Q_STATIC_ASSERT(sizeof languageForWritingSystem / sizeof *languageForWritingSystem == QFontDatabase::WritingSystemsCount); - -#if FC_VERSION >= 20297 -// Newer FontConfig let's us sort out fonts that report certain scripts support, -// but no open type tables for handling them correctly. -// Check the reported script presence in the FC_CAPABILITY's "otlayout:" section. -static const char capabilityForWritingSystem[][5] = { - "", // Any - "", // Latin - "", // Greek - "", // Cyrillic - "", // Armenian - "", // Hebrew - "", // Arabic - "syrc", // Syriac - "thaa", // Thaana - "deva", // Devanagari - "beng", // Bengali - "guru", // Gurmukhi -#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) - "gujr", // Gujarati -#else - "gurj", // Gujarati -#endif - "orya", // Oriya - "taml", // Tamil - "telu", // Telugu - "knda", // Kannada - "mlym", // Malayalam - "sinh", // Sinhala - "", // Thai - "", // Lao - "tibt", // Tibetan - "mymr", // Myanmar - "", // Georgian - "khmr", // Khmer - "", // SimplifiedChinese - "", // TraditionalChinese - "", // Japanese - "", // Korean - "", // Vietnamese - "", // Symbol - "", // Ogham - "", // Runic - "nko " // N'Ko -}; -Q_STATIC_ASSERT(sizeof(capabilityForWritingSystem) / sizeof(*capabilityForWritingSystem) == QFontDatabase::WritingSystemsCount); -#endif - -static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) -{ - const char *stylehint = 0; - switch (style) { - case QFont::SansSerif: - stylehint = "sans-serif"; - break; - case QFont::Serif: - stylehint = "serif"; - break; - case QFont::TypeWriter: - case QFont::Monospace: - stylehint = "monospace"; - break; - case QFont::Cursive: - stylehint = "cursive"; - break; - case QFont::Fantasy: - stylehint = "fantasy"; - break; - default: - break; - } - return stylehint; -} - -static inline bool requiresOpenType(int writingSystem) -{ - return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) - || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); -} - -static void populateFromPattern(FcPattern *pattern) -{ - QString familyName; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - QString familyNameLang; -#endif - FcChar8 *value = 0; - int weight_value; - int slant_value; - int spacing_value; - int width_value; - FcChar8 *file_value; - int indexValue; - FcChar8 *foundry_value; - FcChar8 *style_value; - FcBool scalable; - FcBool antialias; - - if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch) - return; - - familyName = QString::fromUtf8((const char *)value); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - if (FcPatternGetString(pattern, FC_FAMILYLANG, 0, &value) == FcResultMatch) - familyNameLang = QString::fromUtf8((const char *)value); -#endif - slant_value = FC_SLANT_ROMAN; - weight_value = FC_WEIGHT_REGULAR; - spacing_value = FC_PROPORTIONAL; - file_value = 0; - indexValue = 0; - scalable = FcTrue; - - - if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch) - slant_value = FC_SLANT_ROMAN; - if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch) - weight_value = FC_WEIGHT_REGULAR; - if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch) - width_value = FC_WIDTH_NORMAL; - if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch) - spacing_value = FC_PROPORTIONAL; - if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch) - file_value = 0; - if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch) - indexValue = 0; - if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch) - scalable = FcTrue; - if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) - foundry_value = 0; - if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch) - style_value = 0; - if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch) - antialias = true; - - QSupportedWritingSystems writingSystems; - FcLangSet *langset = 0; - FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset); - if (res == FcResultMatch) { - bool hasLang = false; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) && FC_VERSION >= 20297 - FcChar8 *cap = Q_NULLPTR; - FcResult capRes = FcResultNoMatch; -#endif - for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { - const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; - if (lang) { - FcLangResult langRes = FcLangSetHasLang(langset, lang); - if (langRes != FcLangDifferentLang) { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) && FC_VERSION >= 20297 - if (*capabilityForWritingSystem[j] && requiresOpenType(j)) { - if (cap == Q_NULLPTR) - capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap); - if (capRes == FcResultMatch && strstr(reinterpret_cast(cap), capabilityForWritingSystem[j]) == 0) - continue; - } -#endif - writingSystems.setSupported(QFontDatabase::WritingSystem(j)); - hasLang = true; - } - } - } - if (!hasLang) - // none of our known languages, add it to the other set - writingSystems.setSupported(QFontDatabase::Other); - } else { - // we set Other to supported for symbol fonts. It makes no - // sense to merge these with other ones, as they are - // special in a way. - writingSystems.setSupported(QFontDatabase::Other); - } - -#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0)) && FC_VERSION >= 20297 - for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { - if (writingSystems.supported(QFontDatabase::WritingSystem(j)) - && requiresOpenType(j) && capabilityForWritingSystem[j]) { - FcChar8 *cap; - res = FcPatternGetString (pattern, FC_CAPABILITY, 0, &cap); - if (res != FcResultMatch || !strstr((const char *)cap, capabilityForWritingSystem[j])) - writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); - } - } -#endif - - FontFile *fontFile = new FontFile; - fontFile->fileName = QString::fromLocal8Bit((const char *)file_value); - fontFile->indexValue = indexValue; - - QFont::Style style = (slant_value == FC_SLANT_ITALIC) - ? QFont::StyleItalic - : ((slant_value == FC_SLANT_OBLIQUE) - ? QFont::StyleOblique - : QFont::StyleNormal); - // Note: weight should really be an int but registerFont incorrectly uses an enum - QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value)); - - double pixel_size = 0; - if (!scalable) - FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size); - - bool fixedPitch = spacing_value >= FC_MONO; - // Note: stretch should really be an int but registerFont incorrectly uses an enum - QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value)); - QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); - QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); -// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; - -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) { - const QString altFamilyName = QString::fromUtf8((const char *)value); - // Extra family names can be aliases or subfamilies. - // If it is a subfamily, register it as a separate font, so only members of the subfamily are - // matched when the subfamily is requested. - QString altStyleName; - if (FcPatternGetString(pattern, FC_STYLE, k, &value) == FcResultMatch) - altStyleName = QString::fromUtf8((const char *)value); - else - altStyleName = styleName; - - QString altFamilyNameLang; - if (FcPatternGetString(pattern, FC_FAMILYLANG, k, &value) == FcResultMatch) - altFamilyNameLang = QString::fromUtf8((const char *)value); - else - altFamilyNameLang = familyNameLang; - - if (familyNameLang == altFamilyNameLang && altStyleName != styleName) { - FontFile *altFontFile = new FontFile(*fontFile); - QPlatformFontDatabase::registerFont(altFamilyName, altStyleName, QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,altFontFile); - } else { - QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName); - } - } -#else - for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) - QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value)); -#endif - -} - -void QFontconfigDatabase::populateFontDatabase() -{ -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - FcInit(); -#else - FcInitReinitialize(); -#endif - FcFontSet *fonts; - - { - FcObjectSet *os = FcObjectSetCreate(); - FcPattern *pattern = FcPatternCreate(); - const char *properties [] = { - FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT, - FC_SPACING, FC_FILE, FC_INDEX, - FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, - FC_WIDTH, -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - FC_FAMILYLANG, -#endif -#if FC_VERSION >= 20297 - FC_CAPABILITY, -#endif - (const char *)0 - }; - const char **p = properties; - while (*p) { - FcObjectSetAdd(os, *p); - ++p; - } - fonts = FcFontList(0, pattern, os); - FcObjectSetDestroy(os); - FcPatternDestroy(pattern); - } - - for (int i = 0; i < fonts->nfont; i++) - populateFromPattern(fonts->fonts[i]); - - FcFontSetDestroy (fonts); - - struct FcDefaultFont { - const char *qtname; - const char *rawname; - bool fixed; - }; - const FcDefaultFont defaults[] = { - { "Serif", "serif", false }, - { "Sans Serif", "sans-serif", false }, - { "Monospace", "monospace", true }, - { 0, 0, false } - }; - const FcDefaultFont *f = defaults; - // aliases only make sense for 'common', not for any of the specials - QSupportedWritingSystems ws; - ws.setSupported(QFontDatabase::Latin); - - while (f->qtname) { - QString familyQtName = QString::fromLatin1(f->qtname); - registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,f->fixed,ws,0); - registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,f->fixed,ws,0); - registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,f->fixed,ws,0); - ++f; - } - - //Lighthouse has very lazy population of the font db. We want it to be initialized when - //QApplication is constructed, so that the population procedure can do something like this to - //set the default font -// const FcDefaultFont *s = defaults; -// QFont font("Sans Serif"); -// font.setPointSize(9); -// QApplication::setFont(font); -} - -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) -void QFontconfigDatabase::invalidate() -{ - // Clear app fonts. - FcConfigAppFontClear(0); -} -#endif - -QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) -{ - return new QFontEngineMultiFontConfig(fontEngine, script); -} - -namespace { -QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool useXftConf) -{ - switch (hintingPreference) { - case QFont::PreferNoHinting: - return QFontEngine::HintNone; - case QFont::PreferVerticalHinting: - return QFontEngine::HintLight; - case QFont::PreferFullHinting: - return QFontEngine::HintFull; - case QFont::PreferDefaultHinting: - break; - } - - // Removed by Kovid for headless QPA - -#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) - if (QHighDpiScaling::isActive()) - return QFontEngine::HintNone; -#endif - - if (useXftConf) { - void *hintStyleResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle", - QGuiApplication::primaryScreen()); - int hintStyle = int(reinterpret_cast(hintStyleResource)); - if (hintStyle > 0) - return QFontEngine::HintStyle(hintStyle - 1); - } - - int hint_style = 0; - if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) - hint_style = FC_HINT_FULL; - switch (hint_style) { - case FC_HINT_NONE: - return QFontEngine::HintNone; - case FC_HINT_SLIGHT: - return QFontEngine::HintLight; - case FC_HINT_MEDIUM: - return QFontEngine::HintMedium; - case FC_HINT_FULL: - return QFontEngine::HintFull; - default: - Q_UNREACHABLE(); - break; - } - return QFontEngine::HintFull; -} - -QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool useXftConf) -{ - if (useXftConf) { - void *subpixelTypeResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype", - QGuiApplication::primaryScreen()); - int subpixelType = int(reinterpret_cast(subpixelTypeResource)); - if (subpixelType > 0) - return QFontEngine::SubpixelAntialiasingType(subpixelType - 1); - } - - int subpixel = FC_RGBA_UNKNOWN; - FcPatternGetInteger(match, FC_RGBA, 0, &subpixel); - - switch (subpixel) { - case FC_RGBA_UNKNOWN: - case FC_RGBA_NONE: - return QFontEngine::Subpixel_None; - case FC_RGBA_RGB: - return QFontEngine::Subpixel_RGB; - case FC_RGBA_BGR: - return QFontEngine::Subpixel_BGR; - case FC_RGBA_VRGB: - return QFontEngine::Subpixel_VRGB; - case FC_RGBA_VBGR: - return QFontEngine::Subpixel_VBGR; - default: - Q_UNREACHABLE(); - break; - } - return QFontEngine::Subpixel_None; -} -} // namespace - -QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) -{ - if (!usrPtr) - return 0; - - FontFile *fontfile = static_cast (usrPtr); - QFontEngine::FaceId fid; - fid.filename = QFile::encodeName(fontfile->fileName); - fid.index = fontfile->indexValue; - - QFontEngineFT *engine = new QFontEngineFT(f); - engine->face_id = fid; - - setupFontEngine(engine, f); - - if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) { - delete engine; - engine = 0; - } - - return engine; -} - -QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) -{ - QFontEngineFT *engine = static_cast(QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference)); - if (engine == 0) - return 0; - - setupFontEngine(engine, engine->fontDef); - - return engine; -} - -QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const -{ - QStringList fallbackFamilies; - FcPattern *pattern = FcPatternCreate(); - if (!pattern) - return fallbackFamilies; - - FcValue value; - value.type = FcTypeString; - QByteArray cs = family.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAdd(pattern,FC_FAMILY,value,true); - - int slant_value = FC_SLANT_ROMAN; - if (style == QFont::StyleItalic) - slant_value = FC_SLANT_ITALIC; - else if (style == QFont::StyleOblique) - slant_value = FC_SLANT_OBLIQUE; - FcPatternAddInteger(pattern, FC_SLANT, slant_value); - - Q_ASSERT(uint(script) < QChar::ScriptCount); - if (*specialLanguages[script] != '\0') { - FcLangSet *ls = FcLangSetCreate(); - FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); - FcPatternAddLangSet(pattern, FC_LANG, ls); - FcLangSetDestroy(ls); - } else if (!family.isEmpty()) { - // If script is Common or Han, then it may include languages like CJK, - // we should attach system default language set to the pattern - // to obtain correct font fallback list (i.e. if LANG=zh_CN - // then we normally want to use a Chinese font for CJK text; - // while a Japanese font should be used for that if LANG=ja) - FcPattern *dummy = FcPatternCreate(); - FcDefaultSubstitute(dummy); - FcChar8 *lang = 0; - FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang); - if (res == FcResultMatch) - FcPatternAddString(pattern, FC_LANG, lang); - FcPatternDestroy(dummy); - } - - const char *stylehint = getFcFamilyForStyleHint(styleHint); - if (stylehint) { - value.u.s = (const FcChar8 *)stylehint; - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - } - - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - FcResult result = FcResultMatch; - FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); - FcPatternDestroy(pattern); - - if (fontSet) { - QSet duplicates; - duplicates.reserve(fontSet->nfont + 1); - duplicates.insert(family.toCaseFolded()); - for (int i = 0; i < fontSet->nfont; i++) { - FcChar8 *value = 0; - if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) - continue; - // capitalize(value); - const QString familyName = QString::fromUtf8((const char *)value); - const QString familyNameCF = familyName.toCaseFolded(); - if (!duplicates.contains(familyNameCF)) { - fallbackFamilies << familyName; - duplicates.insert(familyNameCF); - } - } - FcFontSetDestroy(fontSet); - } -// qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies; - - return fallbackFamilies; -} - -static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count) -{ -#if FC_VERSION < 20402 - Q_UNUSED(data) - return FcFreeTypeQuery(file, id, blanks, count); -#else - if (data.isEmpty()) - return FcFreeTypeQuery(file, id, blanks, count); - - FT_Library lib = qt_getFreetype(); - - FcPattern *pattern = 0; - - FT_Face face; - if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) { - *count = face->num_faces; - - pattern = FcFreeTypeQueryFace(face, file, id, blanks); - - FT_Done_Face(face); - } - - return pattern; -#endif -} - -QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) -{ - QStringList families; - - FcFontSet *set = FcConfigGetFonts(0, FcSetApplication); - if (!set) { - FcConfigAppFontAddFile(0, (const FcChar8 *)":/non-existent"); - set = FcConfigGetFonts(0, FcSetApplication); // try again - if (!set) - return families; - } - - int id = 0; - FcBlanks *blanks = FcConfigGetBlanks(0); - int count = 0; - - FcPattern *pattern; - do { - pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(), - fontData, id, blanks, &count); - if (!pattern) - return families; - - FcChar8 *fam = 0; - if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) { - QString family = QString::fromUtf8(reinterpret_cast(fam)); - families << family; - } - populateFromPattern(pattern); - - FcFontSetAdd(set, pattern); - - ++id; - } while (id < count); - - return families; -} - -QString QFontconfigDatabase::resolveFontFamilyAlias(const QString &family) const -{ - QString resolved = QFreeTypeFontDatabase::resolveFontFamilyAlias(family); - if (!resolved.isEmpty() && resolved != family) - return resolved; - FcPattern *pattern = FcPatternCreate(); - if (!pattern) - return family; - - if (!family.isEmpty()) { - QByteArray cs = family.toUtf8(); - FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) cs.constData()); - } - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - FcChar8 *familyAfterSubstitution = 0; - FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); - resolved = QString::fromUtf8((const char *) familyAfterSubstitution); - FcPatternDestroy(pattern); - - return resolved; -} - -QFont QFontconfigDatabase::defaultFont() const -{ - // Hack to get system default language until FcGetDefaultLangs() - // is exported (https://bugs.freedesktop.org/show_bug.cgi?id=32853) - // or https://bugs.freedesktop.org/show_bug.cgi?id=35482 is fixed - FcPattern *dummy = FcPatternCreate(); - FcDefaultSubstitute(dummy); - FcChar8 *lang = 0; - FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang); - - FcPattern *pattern = FcPatternCreate(); - if (res == FcResultMatch) { - // Make defaultFont pattern matching locale language aware, because - // certain FC_LANG based custom rules may happen in FcConfigSubstitute() - FcPatternAddString(pattern, FC_LANG, lang); - } - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - FcChar8 *familyAfterSubstitution = 0; - FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); - QString resolved = QString::fromUtf8((const char *) familyAfterSubstitution); - FcPatternDestroy(pattern); - FcPatternDestroy(dummy); - - return QFont(resolved); -} - -void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const -{ - bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - bool forcedAntialiasSetting = !antialias; - - // Changed by Kovid for headless QPA - bool useXftConf = false; - if (useXftConf) { - void *antialiasResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled", - QGuiApplication::primaryScreen()); - int antialiasingEnabled = int(reinterpret_cast(antialiasResource)); - if (antialiasingEnabled > 0) - antialias = antialiasingEnabled - 1; - } - - QFontEngine::GlyphFormat format; - // try and get the pattern - FcPattern *pattern = FcPatternCreate(); - - FcValue value; - value.type = FcTypeString; - QByteArray cs = fontDef.family.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAdd(pattern,FC_FAMILY,value,true); - - QFontEngine::FaceId fid = engine->faceId(); - - if (!fid.filename.isEmpty()) { - value.u.s = (const FcChar8 *)fid.filename.data(); - FcPatternAdd(pattern,FC_FILE,value,true); - - value.type = FcTypeInteger; - value.u.i = fid.index; - FcPatternAdd(pattern,FC_INDEX,value,true); - } - - if (fontDef.pixelSize > 0.1) - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize); - - FcResult result; - - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - FcPattern *match = FcFontMatch(0, pattern, &result); - if (match) { - engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); - - FcBool fc_autohint; - if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch) - engine->forceAutoHint = fc_autohint; - -#if defined(FT_LCD_FILTER_H) - int lcdFilter; - if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch) - engine->lcdFilterType = lcdFilter; -#endif - - if (!forcedAntialiasSetting) { - FcBool fc_antialias; - if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch) - antialias = fc_antialias; - } - - if (antialias) { - QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None; - if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) - subpixelType = subpixelTypeFromMatch(match, useXftConf); - engine->subpixelType = subpixelType; - - format = (subpixelType == QFontEngine::Subpixel_None) - ? QFontEngine::Format_A8 - : QFontEngine::Format_A32; - } else - format = QFontEngine::Format_Mono; - - FcPatternDestroy(match); - } else - format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono; - - FcPatternDestroy(pattern); - - engine->antialias = antialias; - engine->defaultFormat = format; - engine->glyphFormat = format; -} - -QT_END_NAMESPACE diff --git a/src/calibre/headless/fontconfig_database.h b/src/calibre/headless/fontconfig_database.h deleted file mode 100644 index 3c36558b6c..0000000000 --- a/src/calibre/headless/fontconfig_database.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * fontconfig.h - * Copyright (C) 2015 Kovid Goyal - * - * Distributed under terms of the GPL3 license. - */ -#pragma once - -#include -#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) -#include -#elif (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) -#include -#define QFreeTypeFontDatabase QBasicFontDatabase -#else -#include -#define QFreeTypeFontDatabase QBasicFontDatabase -#endif - -QT_BEGIN_NAMESPACE - -class QFontEngineFT; - -class QFontconfigDatabase : public QFreeTypeFontDatabase -{ -public: -#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) - void populateFontDatabase() Q_DECL_OVERRIDE; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - void invalidate() Q_DECL_OVERRIDE; -#endif - QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE; - QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE; - QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) Q_DECL_OVERRIDE; - QString resolveFontFamilyAlias(const QString &family) const Q_DECL_OVERRIDE; - QFont defaultFont() const Q_DECL_OVERRIDE; -#else - void populateFontDatabase(); - QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script); - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); - QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; - QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); - QString resolveFontFamilyAlias(const QString &family) const; - QFont defaultFont() const; -#endif - -private: - void setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const; -}; - -QT_END_NAMESPACE diff --git a/src/calibre/headless/headless_integration.cpp b/src/calibre/headless/headless_integration.cpp index bc8f6d3ea6..ff40feecdc 100644 --- a/src/calibre/headless/headless_integration.cpp +++ b/src/calibre/headless/headless_integration.cpp @@ -2,18 +2,18 @@ #include "headless_integration.h" #include "headless_backingstore.h" #ifdef __APPLE__ -#include +#include class QCoreTextFontEngine; #include #include #else -#include "fontconfig_database.h" +#include #endif #ifdef Q_OS_WIN #include #else -#include +#include #endif #include diff --git a/src/calibre/headless/headless_integration.h b/src/calibre/headless/headless_integration.h index 5c1316639b..e4771aaa40 100644 --- a/src/calibre/headless/headless_integration.h +++ b/src/calibre/headless/headless_integration.h @@ -3,11 +3,7 @@ #include #include #include -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) -#include -#else -#include -#endif +#include #include QT_BEGIN_NAMESPACE diff --git a/src/calibre/test_build.py b/src/calibre/test_build.py index 45c35a56ad..e1d3202c97 100644 --- a/src/calibre/test_build.py +++ b/src/calibre/test_build.py @@ -319,7 +319,7 @@ class BuildTest(unittest.TestCase): display_env_var = os.environ.pop('DISPLAY', None) try: ensure_app() - self.assertGreaterEqual(len(QFontDatabase().families()), 5, 'The QPA headless plugin is not able to locate enough system fonts via fontconfig') + self.assertGreaterEqual(len(QFontDatabase.families()), 5, 'The QPA headless plugin is not able to locate enough system fonts via fontconfig') from calibre.ebooks.covers import create_cover create_cover('xxx', ['yyy']) na = QNetworkAccessManager()