mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
Get the Qt plugins building with Qt6
This commit is contained in:
parent
28e6d251da
commit
e3d0259d70
@ -458,7 +458,7 @@ class Build(Command):
|
|||||||
from setup.parallel_build import cpu_count
|
from setup.parallel_build import cpu_count
|
||||||
if iswindows or ishaiku:
|
if iswindows or ishaiku:
|
||||||
return # Dont have headless operation on these platforms
|
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)
|
self.info('\n####### Building headless QPA plugin', '#'*7)
|
||||||
a = absolutize
|
a = absolutize
|
||||||
headers = a([
|
headers = a([
|
||||||
@ -470,50 +470,25 @@ class Build(Command):
|
|||||||
'calibre/headless/headless_backingstore.cpp',
|
'calibre/headless/headless_backingstore.cpp',
|
||||||
'calibre/headless/headless_integration.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'])
|
others = a(['calibre/headless/headless.json'])
|
||||||
target = self.dest('headless')
|
target = self.dest('headless')
|
||||||
|
if not ismacos:
|
||||||
|
target = target.replace('headless', 'libheadless')
|
||||||
if not self.newer(target, headers + sources + others):
|
if not self.newer(target, headers + sources + others):
|
||||||
return
|
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')
|
bdir = self.j(self.build_dir, 'headless')
|
||||||
if not os.path.exists(bdir):
|
if os.path.exists(bdir):
|
||||||
os.makedirs(bdir)
|
shutil.rmtree(bdir)
|
||||||
pf = self.j(bdir, 'headless.pro')
|
os.makedirs(bdir)
|
||||||
open(self.j(bdir, '.qmake.conf'), 'wb').close()
|
|
||||||
with open(pf, 'wb') as f:
|
|
||||||
f.write(pro.encode('utf-8'))
|
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.chdir(bdir)
|
os.chdir(bdir)
|
||||||
try:
|
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)])
|
self.check_call([self.env.make] + ['-j%d'%(cpu_count or 1)])
|
||||||
finally:
|
finally:
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
if ismacos:
|
os.rename(self.j(bdir, 'libheadless.' + ('dylib' if ismacos else 'so')), target)
|
||||||
os.rename(self.j(self.d(target), 'libheadless.dylib'), self.j(self.d(target), 'headless.so'))
|
|
||||||
|
|
||||||
def create_sip_build_skeleton(self, src_dir, ext):
|
def create_sip_build_skeleton(self, src_dir, ext):
|
||||||
from setup.build_environment import pyqt_sip_abi_version
|
from setup.build_environment import pyqt_sip_abi_version
|
||||||
|
@ -60,6 +60,8 @@ for x in ('qmake6', 'qmake-qt6', 'qt6-qmake', 'qmake'):
|
|||||||
QMAKE = os.environ.get('QMAKE', QMAKE)
|
QMAKE = os.environ.get('QMAKE', QMAKE)
|
||||||
if iswindows and not QMAKE.lower().endswith('.exe'):
|
if iswindows and not QMAKE.lower().endswith('.exe'):
|
||||||
QMAKE += '.exe'
|
QMAKE += '.exe'
|
||||||
|
CMAKE = 'cmake'
|
||||||
|
CMAKE = os.environ.get('CMAKE', CMAKE)
|
||||||
|
|
||||||
PKGCONFIG = shutil.which('pkg-config')
|
PKGCONFIG = shutil.which('pkg-config')
|
||||||
PKGCONFIG = os.environ.get('PKG_CONFIG', PKGCONFIG)
|
PKGCONFIG = os.environ.get('PKG_CONFIG', PKGCONFIG)
|
||||||
|
8
src/calibre/headless/CMakeLists.txt
Normal file
8
src/calibre/headless/CMakeLists.txt
Normal file
@ -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)
|
@ -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 <QtGlobal>
|
|
||||||
|
|
||||||
#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 <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h>
|
|
||||||
#include <QtFontDatabaseSupport/private/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 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
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* fontconfig.h
|
|
||||||
* Copyright (C) 2015 Kovid Goyal <kovid at kovidgoyal.net>
|
|
||||||
*
|
|
||||||
* Distributed under terms of the GPL3 license.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <qpa/qplatformfontdatabase.h>
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
|
||||||
#include <QtFontDatabaseSupport/private/qfreetypefontdatabase_p.h>
|
|
||||||
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
|
|
||||||
#include <QtFontDatabaseSupport/private/qbasicfontdatabase_p.h>
|
|
||||||
#define QFreeTypeFontDatabase QBasicFontDatabase
|
|
||||||
#else
|
|
||||||
#include <QtPlatformSupport/private/qbasicfontdatabase_p.h>
|
|
||||||
#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
|
|
@ -2,18 +2,18 @@
|
|||||||
#include "headless_integration.h"
|
#include "headless_integration.h"
|
||||||
#include "headless_backingstore.h"
|
#include "headless_backingstore.h"
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h>
|
#include <QtGui/private/qcoretextfontdatabase_p.h>
|
||||||
class QCoreTextFontEngine;
|
class QCoreTextFontEngine;
|
||||||
#include <qpa/qplatformservices.h>
|
#include <qpa/qplatformservices.h>
|
||||||
#include <QtCore/private/qeventdispatcher_unix_p.h>
|
#include <QtCore/private/qeventdispatcher_unix_p.h>
|
||||||
#else
|
#else
|
||||||
#include "fontconfig_database.h"
|
#include <QtGui/private/qfontconfigdatabase_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <QtCore/private/qeventdispatcher_win_p.h>
|
#include <QtCore/private/qeventdispatcher_win_p.h>
|
||||||
#else
|
#else
|
||||||
#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
|
#include <QtGui/private/qgenericunixeventdispatcher_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QtGui/private/qpixmap_raster_p.h>
|
#include <QtGui/private/qpixmap_raster_p.h>
|
||||||
|
@ -3,11 +3,7 @@
|
|||||||
#include <qpa/qplatformintegration.h>
|
#include <qpa/qplatformintegration.h>
|
||||||
#include <qpa/qplatformscreen.h>
|
#include <qpa/qplatformscreen.h>
|
||||||
#include <qpa/qplatformservices.h>
|
#include <qpa/qplatformservices.h>
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
|
#include <QtGui/private/qgenericunixservices_p.h>
|
||||||
#include <QtServiceSupport/private/qgenericunixservices_p.h>
|
|
||||||
#else
|
|
||||||
#include <QtPlatformSupport/private/qgenericunixservices_p.h>
|
|
||||||
#endif
|
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
@ -319,7 +319,7 @@ class BuildTest(unittest.TestCase):
|
|||||||
display_env_var = os.environ.pop('DISPLAY', None)
|
display_env_var = os.environ.pop('DISPLAY', None)
|
||||||
try:
|
try:
|
||||||
ensure_app()
|
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
|
from calibre.ebooks.covers import create_cover
|
||||||
create_cover('xxx', ['yyy'])
|
create_cover('xxx', ['yyy'])
|
||||||
na = QNetworkAccessManager()
|
na = QNetworkAccessManager()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user