Use emoji segmenter to apply emoji fonts automatically
Colorful emojis in Unicode are not isolated to specific ranges of code points like other writing systems. Instead, there are a set of rules defining whether a sequence of characters should be displayed in color or black/white. http://www.unicode.org/reports/tr51/ For instance, appending a variation selector to a character can turn it into a color emoji, even if it is a code point that predates the invention of emojis. In addition, sequences of joined characters that are determined to be a color emoji sequence should be parsed by a single emoji font, so that it can apply things like skin color, etc. In general, users expect emojis and emoji sequences to be shown in the preferred color font of the system, even if a selected font has black/white characters for the symbols. This patch applies the emoji segmenter to strings to isolate sequences that should be in color. As an implementation hack, we mark this in the QScriptItems as a special "emoji" script. Note that this is not a real Unicode script and only exists internally for this reason, because the "emojiness" of the resulting glyph overrides the original script of the individual characters when selecting fonts. This way, we can use a lot of the same logic for itemizing the strings and looking up fonts, and we don't need to increase the size of the QScriptItem. (It is just an implementation detail and is not exposed to the user, so it can be replaced by other approaches later if we need to.) When matching an emoji sequence, we always try to apply a color font and ignore all others. The exception is if there is no color font at all on the system, then we will find a black and white font which supports the characters instead as a final failsafe. In addition, each platform will put its default emoji font at the top of the fallbacks list in order to make this the preference in case there are more than one. This patch also adds API to override this with an application-defined emoji font, since this is a common use case. Note: The font includes an environment variable to disable the feature as a fail safe. A flag to disable it per QFont will be added in a follow-up. Fixes: QTBUG-111801 Change-Id: I9431ec34d56772ab8688814963073b83b23002ae Reviewed-by: Lars Knoll <lars@knoll.priv.no> Reviewed-by: <carl@carlschwan.eu>
This commit is contained in:
parent
222cf3145e
commit
1685070930
@ -327,6 +327,7 @@ struct FontDescription {
|
|||||||
QFont::Stretch stretch;
|
QFont::Stretch stretch;
|
||||||
qreal pointSize;
|
qreal pointSize;
|
||||||
bool fixedPitch;
|
bool fixedPitch;
|
||||||
|
bool colorFont;
|
||||||
QSupportedWritingSystems writingSystems;
|
QSupportedWritingSystems writingSystems;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -359,6 +360,9 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
|
|||||||
fd->style = QFont::StyleNormal;
|
fd->style = QFont::StyleNormal;
|
||||||
fd->stretch = QFont::Unstretched;
|
fd->stretch = QFont::Unstretched;
|
||||||
fd->fixedPitch = false;
|
fd->fixedPitch = false;
|
||||||
|
fd->colorFont = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) {
|
if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) {
|
||||||
uint tag = QFont::Tag("OS/2").value();
|
uint tag = QFont::Tag("OS/2").value();
|
||||||
@ -393,6 +397,9 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
|
|||||||
if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) {
|
if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) {
|
||||||
int d;
|
int d;
|
||||||
if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) {
|
if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) {
|
||||||
|
if (d & kCTFontColorGlyphsTrait)
|
||||||
|
fd->colorFont = true;
|
||||||
|
|
||||||
if (d & kCTFontMonoSpaceTrait)
|
if (d & kCTFontMonoSpaceTrait)
|
||||||
fd->fixedPitch = true;
|
fd->fixedPitch = true;
|
||||||
if (d & kCTFontExpandedTrait)
|
if (d & kCTFontExpandedTrait)
|
||||||
@ -451,7 +458,7 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font, con
|
|||||||
CFRetain(font);
|
CFRetain(font);
|
||||||
QPlatformFontDatabase::registerFont(family, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch,
|
QPlatformFontDatabase::registerFont(family, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch,
|
||||||
true /* antialiased */, true /* scalable */, 0 /* pixelSize, ignored as font is scalable */,
|
true /* antialiased */, true /* scalable */, 0 /* pixelSize, ignored as font is scalable */,
|
||||||
fd.fixedPitch, fd.writingSystems, (void *)font);
|
fd.fixedPitch, fd.colorFont, fd.writingSystems, (void *)font);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString * const kQtFontDataAttribute = @"QtFontDataAttribute";
|
static NSString * const kQtFontDataAttribute = @"QtFontDataAttribute";
|
||||||
@ -629,7 +636,18 @@ CTFontDescriptorRef descriptorForStyle(QFont::StyleHint styleHint)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
QStringList QCoreTextFontDatabase::fallbacksForScript(QFontDatabasePrivate::ExtendedScript script) const
|
||||||
|
{
|
||||||
|
if (script == QFontDatabasePrivate::Script_Emoji)
|
||||||
|
return QStringList{} << QStringLiteral(".Apple Color Emoji UI");
|
||||||
|
else
|
||||||
|
return QStringList{};
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(style);
|
Q_UNUSED(style);
|
||||||
|
|
||||||
@ -639,7 +657,7 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
|
|||||||
|
|
||||||
QMacAutoReleasePool pool;
|
QMacAutoReleasePool pool;
|
||||||
|
|
||||||
QStringList fallbackList;
|
QStringList fallbackList = fallbacksForScript(script);
|
||||||
|
|
||||||
QCFType<CFArrayRef> fallbackFonts = fallbacksForFamily(family);
|
QCFType<CFArrayRef> fallbackFonts = fallbacksForFamily(family);
|
||||||
if (!fallbackFonts || !CFArrayGetCount(fallbackFonts)) {
|
if (!fallbackFonts || !CFArrayGetCount(fallbackFonts)) {
|
||||||
@ -702,32 +720,34 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
|
|||||||
fallbackList.append(QStringLiteral("Apple Symbols"));
|
fallbackList.append(QStringLiteral("Apple Symbols"));
|
||||||
// Some Noto* fonts are not automatically enumerated by system, despite being the main
|
// Some Noto* fonts are not automatically enumerated by system, despite being the main
|
||||||
// fonts for their writing system.
|
// fonts for their writing system.
|
||||||
QString hardcodedFont = m_hardcodedFallbackFonts.value(script);
|
if (script < int(QChar::ScriptCount)) {
|
||||||
if (!hardcodedFont.isEmpty() && !fallbackList.contains(hardcodedFont)) {
|
QString hardcodedFont = m_hardcodedFallbackFonts.value(QChar::Script(script));
|
||||||
if (!isFamilyPopulated(hardcodedFont)) {
|
if (!hardcodedFont.isEmpty() && !fallbackList.contains(hardcodedFont)) {
|
||||||
if (!m_privateFamilies.contains(hardcodedFont)) {
|
if (!isFamilyPopulated(hardcodedFont)) {
|
||||||
QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(hardcodedFont);
|
if (!m_privateFamilies.contains(hardcodedFont)) {
|
||||||
QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, nullptr);
|
QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(hardcodedFont);
|
||||||
if (matchingFonts) {
|
QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, nullptr);
|
||||||
const int numFonts = CFArrayGetCount(matchingFonts);
|
if (matchingFonts) {
|
||||||
for (int i = 0; i < numFonts; ++i)
|
const int numFonts = CFArrayGetCount(matchingFonts);
|
||||||
const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)),
|
for (int i = 0; i < numFonts; ++i)
|
||||||
hardcodedFont);
|
const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)),
|
||||||
|
hardcodedFont);
|
||||||
|
|
||||||
fallbackList.append(hardcodedFont);
|
fallbackList.append(hardcodedFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register as private family even if the font is not found, in order to avoid
|
||||||
|
// redoing the check later. In later calls, the font will then just be ignored.
|
||||||
|
m_privateFamilies.insert(hardcodedFont);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// Register as private family even if the font is not found, in order to avoid
|
fallbackList.append(hardcodedFont);
|
||||||
// redoing the check later. In later calls, the font will then just be ignored.
|
|
||||||
m_privateFamilies.insert(hardcodedFont);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
fallbackList.append(hardcodedFont);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &);
|
extern QStringList qt_sort_families_by_writing_system(QFontDatabasePrivate::ExtendedScript, const QStringList &);
|
||||||
fallbackList = qt_sort_families_by_writing_system(script, fallbackList);
|
fallbackList = qt_sort_families_by_writing_system(script, fallbackList);
|
||||||
|
|
||||||
qCDebug(lcQpaFonts).nospace() << "Fallback families ordered by script " << script << ": " << fallbackList;
|
qCDebug(lcQpaFonts).nospace() << "Fallback families ordered by script " << script << ": " << fallbackList;
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
void populateFamily(const QString &familyName) override;
|
void populateFamily(const QString &familyName) override;
|
||||||
void invalidate() override;
|
void invalidate() override;
|
||||||
|
|
||||||
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override;
|
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QFontDatabasePrivate::ExtendedScript script) const override;
|
||||||
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) override;
|
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) override;
|
||||||
void releaseHandle(void *handle) override;
|
void releaseHandle(void *handle) override;
|
||||||
bool isPrivateFontFamily(const QString &family) const override;
|
bool isPrivateFontFamily(const QString &family) const override;
|
||||||
@ -55,6 +55,7 @@ private:
|
|||||||
void populateThemeFonts();
|
void populateThemeFonts();
|
||||||
void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString(), QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr);
|
void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString(), QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr);
|
||||||
static CFArrayRef fallbacksForFamily(const QString &family);
|
static CFArrayRef fallbacksForFamily(const QString &family);
|
||||||
|
QStringList fallbacksForScript(QFontDatabasePrivate::ExtendedScript script) const;
|
||||||
|
|
||||||
QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
|
QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
|
||||||
QHash<QString, QList<QCFType<CTFontDescriptorRef>>> m_systemFontDescriptors;
|
QHash<QString, QList<QCFType<CTFontDescriptorRef>>> m_systemFontDescriptors;
|
||||||
|
@ -101,6 +101,7 @@ void QFreeTypeFontDatabase::addNamedInstancesForFace(void *face_,
|
|||||||
QFont::Stretch stretch,
|
QFont::Stretch stretch,
|
||||||
QFont::Style style,
|
QFont::Style style,
|
||||||
bool fixedPitch,
|
bool fixedPitch,
|
||||||
|
bool isColor,
|
||||||
const QSupportedWritingSystems &writingSystems,
|
const QSupportedWritingSystems &writingSystems,
|
||||||
const QByteArray &fileName,
|
const QByteArray &fileName,
|
||||||
const QByteArray &fontData)
|
const QByteArray &fontData)
|
||||||
@ -181,6 +182,7 @@ void QFreeTypeFontDatabase::addNamedInstancesForFace(void *face_,
|
|||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
fixedPitch,
|
fixedPitch,
|
||||||
|
isColor,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
variantFontFile);
|
variantFontFile);
|
||||||
}
|
}
|
||||||
@ -222,6 +224,12 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
|
|||||||
}
|
}
|
||||||
numFaces = face->num_faces;
|
numFaces = face->num_faces;
|
||||||
|
|
||||||
|
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 20501
|
||||||
|
bool isColor = FT_HAS_COLOR(face);
|
||||||
|
#else
|
||||||
|
bool isColor = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
QFont::Weight weight = QFont::Normal;
|
QFont::Weight weight = QFont::Normal;
|
||||||
|
|
||||||
QFont::Style style = QFont::StyleNormal;
|
QFont::Style style = QFont::StyleNormal;
|
||||||
@ -335,9 +343,9 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
|
|||||||
applicationFont->properties.append(properties);
|
applicationFont->properties.append(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerFont(family, styleName, QString(), weight, style, stretch, true, true, 0, fixedPitch, writingSystems, fontFile);
|
registerFont(family, styleName, QString(), weight, style, stretch, true, true, 0, fixedPitch, isColor, writingSystems, fontFile);
|
||||||
|
|
||||||
addNamedInstancesForFace(face, index, family, styleName, weight, stretch, style, fixedPitch, writingSystems, file, fontData);
|
addNamedInstancesForFace(face, index, family, styleName, weight, stretch, style, fixedPitch, isColor, writingSystems, file, fontData);
|
||||||
|
|
||||||
families.append(family);
|
families.append(family);
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
static void addNamedInstancesForFace(void *face, int faceIndex,
|
static void addNamedInstancesForFace(void *face, int faceIndex,
|
||||||
const QString &family, const QString &styleName,
|
const QString &family, const QString &styleName,
|
||||||
QFont::Weight weight, QFont::Stretch stretch,
|
QFont::Weight weight, QFont::Stretch stretch,
|
||||||
QFont::Style style, bool fixedPitch,
|
QFont::Style style, bool fixedPitch, bool isColor,
|
||||||
const QSupportedWritingSystems &writingSystems,
|
const QSupportedWritingSystems &writingSystems,
|
||||||
const QByteArray &fileName, const QByteArray &fontData);
|
const QByteArray &fileName, const QByteArray &fontData);
|
||||||
|
|
||||||
|
@ -383,13 +383,13 @@ void QFontPrivate::unsetFeature(QFont::Tag tag)
|
|||||||
QFontEngineData::QFontEngineData()
|
QFontEngineData::QFontEngineData()
|
||||||
: ref(0), fontCacheId(QFontCache::instance()->id())
|
: ref(0), fontCacheId(QFontCache::instance()->id())
|
||||||
{
|
{
|
||||||
memset(engines, 0, QChar::ScriptCount * sizeof(QFontEngine *));
|
memset(engines, 0, QFontDatabasePrivate::ScriptCount * sizeof(QFontEngine *));
|
||||||
}
|
}
|
||||||
|
|
||||||
QFontEngineData::~QFontEngineData()
|
QFontEngineData::~QFontEngineData()
|
||||||
{
|
{
|
||||||
Q_ASSERT(ref.loadRelaxed() == 0);
|
Q_ASSERT(ref.loadRelaxed() == 0);
|
||||||
for (int i = 0; i < QChar::ScriptCount; ++i) {
|
for (int i = 0; i < QFontDatabasePrivate::ScriptCount; ++i) {
|
||||||
if (engines[i]) {
|
if (engines[i]) {
|
||||||
if (!engines[i]->ref.deref())
|
if (!engines[i]->ref.deref())
|
||||||
delete engines[i];
|
delete engines[i];
|
||||||
@ -2681,8 +2681,10 @@ void QFont::clearFeatures()
|
|||||||
d->features.clear();
|
d->features.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
|
extern QStringList qt_fallbacksForFamily(const QString &family,
|
||||||
QFont::StyleHint styleHint, QChar::Script script);
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QString QFont::defaultFamily() const
|
\fn QString QFont::defaultFamily() const
|
||||||
@ -2694,8 +2696,10 @@ extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style sty
|
|||||||
*/
|
*/
|
||||||
QString QFont::defaultFamily() const
|
QString QFont::defaultFamily() const
|
||||||
{
|
{
|
||||||
const QStringList fallbacks = qt_fallbacksForFamily(QString(), QFont::StyleNormal
|
const QStringList fallbacks = qt_fallbacksForFamily(QString(),
|
||||||
, QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
|
QFont::StyleNormal,
|
||||||
|
QFont::StyleHint(d->request.styleHint),
|
||||||
|
QFontDatabasePrivate::Script_Common);
|
||||||
if (!fallbacks.isEmpty())
|
if (!fallbacks.isEmpty())
|
||||||
return fallbacks.first();
|
return fallbacks.first();
|
||||||
return QString();
|
return QString();
|
||||||
@ -3402,7 +3406,7 @@ void QFontCache::clear()
|
|||||||
end = engineDataCache.end();
|
end = engineDataCache.end();
|
||||||
while (it != end) {
|
while (it != end) {
|
||||||
QFontEngineData *data = it.value();
|
QFontEngineData *data = it.value();
|
||||||
for (int i = 0; i < QChar::ScriptCount; ++i) {
|
for (int i = 0; i < QFontDatabasePrivate::ScriptCount; ++i) {
|
||||||
if (data->engines[i]) {
|
if (data->engines[i]) {
|
||||||
if (!data->engines[i]->ref.deref()) {
|
if (!data->engines[i]->ref.deref()) {
|
||||||
Q_ASSERT(engineCacheCount.value(data->engines[i]) == 0);
|
Q_ASSERT(engineCacheCount.value(data->engines[i]) == 0);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "QtCore/qstringlist.h"
|
#include "QtCore/qstringlist.h"
|
||||||
#include <QtGui/qfontdatabase.h>
|
#include <QtGui/qfontdatabase.h>
|
||||||
#include "private/qfixed_p.h"
|
#include "private/qfixed_p.h"
|
||||||
|
#include "private/qfontdatabase_p.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -153,8 +154,7 @@ public:
|
|||||||
QAtomicInt ref;
|
QAtomicInt ref;
|
||||||
const int fontCacheId;
|
const int fontCacheId;
|
||||||
|
|
||||||
QFontEngine *engines[QChar::ScriptCount];
|
QFontEngine *engines[QFontDatabasePrivate::ScriptCount];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY_MOVE(QFontEngineData)
|
Q_DISABLE_COPY_MOVE(QFontEngineData)
|
||||||
};
|
};
|
||||||
|
@ -413,6 +413,8 @@ static bool familySupportsWritingSystem(QtFontFamily *family, size_t writingSyst
|
|||||||
|
|
||||||
Q_GUI_EXPORT QFontDatabase::WritingSystem qt_writing_system_for_script(int script)
|
Q_GUI_EXPORT QFontDatabase::WritingSystem qt_writing_system_for_script(int script)
|
||||||
{
|
{
|
||||||
|
if (script >= QChar::ScriptCount)
|
||||||
|
return QFontDatabase::Any;
|
||||||
return QFontDatabase::WritingSystem(std::find(scriptForWritingSystem,
|
return QFontDatabase::WritingSystem(std::find(scriptForWritingSystem,
|
||||||
scriptForWritingSystem + QFontDatabase::WritingSystemsCount,
|
scriptForWritingSystem + QFontDatabase::WritingSystemsCount,
|
||||||
script) - scriptForWritingSystem);
|
script) - scriptForWritingSystem);
|
||||||
@ -537,7 +539,7 @@ QFontDatabasePrivate *QFontDatabasePrivate::instance()
|
|||||||
void qt_registerFont(const QString &familyName, const QString &stylename,
|
void qt_registerFont(const QString &familyName, const QString &stylename,
|
||||||
const QString &foundryname, int weight,
|
const QString &foundryname, int weight,
|
||||||
QFont::Style style, int stretch, bool antialiased,
|
QFont::Style style, int stretch, bool antialiased,
|
||||||
bool scalable, int pixelSize, bool fixedPitch,
|
bool scalable, int pixelSize, bool fixedPitch, bool colorFont,
|
||||||
const QSupportedWritingSystems &writingSystems, void *handle)
|
const QSupportedWritingSystems &writingSystems, void *handle)
|
||||||
{
|
{
|
||||||
auto *d = QFontDatabasePrivate::instance();
|
auto *d = QFontDatabasePrivate::instance();
|
||||||
@ -549,6 +551,7 @@ void qt_registerFont(const QString &familyName, const QString &stylename,
|
|||||||
styleKey.stretch = stretch;
|
styleKey.stretch = stretch;
|
||||||
QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::EnsureCreated);
|
QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::EnsureCreated);
|
||||||
f->fixedPitch = fixedPitch;
|
f->fixedPitch = fixedPitch;
|
||||||
|
f->colorFont = colorFont;
|
||||||
|
|
||||||
for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
|
for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
|
||||||
if (writingSystems.supported(QFontDatabase::WritingSystem(i)))
|
if (writingSystems.supported(QFontDatabase::WritingSystem(i)))
|
||||||
@ -620,7 +623,10 @@ bool qt_isFontFamilyPopulated(const QString &familyName)
|
|||||||
Default implementation returns a list of fonts for which \a style and \a script support
|
Default implementation returns a list of fonts for which \a style and \a script support
|
||||||
has been reported during the font database population.
|
has been reported during the font database population.
|
||||||
*/
|
*/
|
||||||
QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(family);
|
Q_UNUSED(family);
|
||||||
Q_UNUSED(styleHint);
|
Q_UNUSED(styleHint);
|
||||||
@ -659,7 +665,10 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
|
|||||||
return preferredFallbacks + otherFallbacks;
|
return preferredFallbacks + otherFallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
|
static QStringList fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(fontDatabaseMutex());
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
auto *db = QFontDatabasePrivate::ensureFontDatabase();
|
auto *db = QFontDatabasePrivate::ensureFontDatabase();
|
||||||
@ -670,7 +679,7 @@ static QStringList fallbacksForFamily(const QString &family, QFont::Style style,
|
|||||||
return *fallbacks;
|
return *fallbacks;
|
||||||
|
|
||||||
// make sure that the db has all fallback families
|
// make sure that the db has all fallback families
|
||||||
QStringList userFallbacks = db->applicationFallbackFontFamilies.value(script == QChar::Script_Latin ? QChar::Script_Common : script);
|
QStringList userFallbacks = db->applicationFallbackFontFamilies(script == QFontDatabasePrivate::Script_Latin ? QFontDatabasePrivate::Script_Common : script);
|
||||||
QStringList retList = userFallbacks + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
|
QStringList retList = userFallbacks + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
|
||||||
|
|
||||||
QStringList::iterator i;
|
QStringList::iterator i;
|
||||||
@ -693,7 +702,7 @@ static QStringList fallbacksForFamily(const QString &family, QFont::Style style,
|
|||||||
return retList;
|
return retList;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
|
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QFontDatabasePrivate::ExtendedScript script)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(fontDatabaseMutex());
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
return fallbacksForFamily(family, style, styleHint, script);
|
return fallbacksForFamily(family, style, styleHint, script);
|
||||||
@ -722,10 +731,10 @@ QFontEngine *QFontDatabasePrivate::loadSingleEngine(int script,
|
|||||||
QFontCache::Key key(def,script);
|
QFontCache::Key key(def,script);
|
||||||
QFontEngine *engine = fontCache->findEngine(key);
|
QFontEngine *engine = fontCache->findEngine(key);
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
const bool cacheForCommonScript = script != QChar::Script_Common
|
const bool cacheForCommonScript = script != QFontDatabasePrivate::Script_Common
|
||||||
&& (family->writingSystems[QFontDatabase::Latin] & QtFontFamily::Supported) != 0;
|
&& (family->writingSystems[QFontDatabase::Latin] & QtFontFamily::Supported) != 0;
|
||||||
|
|
||||||
if (Q_LIKELY(cacheForCommonScript)) {
|
if (Q_LIKELY(cacheForCommonScript) && script < QChar::ScriptCount) {
|
||||||
// fast path: check if engine was loaded for another script
|
// fast path: check if engine was loaded for another script
|
||||||
key.script = QChar::Script_Common;
|
key.script = QChar::Script_Common;
|
||||||
engine = fontCache->findEngine(key);
|
engine = fontCache->findEngine(key);
|
||||||
@ -757,7 +766,7 @@ QFontEngine *QFontDatabasePrivate::loadSingleEngine(int script,
|
|||||||
engine = pfdb->fontEngine(def, size->handle);
|
engine = pfdb->fontEngine(def, size->handle);
|
||||||
if (engine) {
|
if (engine) {
|
||||||
// Also check for OpenType tables when using complex scripts
|
// Also check for OpenType tables when using complex scripts
|
||||||
if (!engine->supportsScript(QChar::Script(script))) {
|
if (script < QChar::ScriptCount && !engine->supportsScript(QChar::Script(script))) {
|
||||||
qCInfo(lcFontDb, "OpenType support missing for \"%ls\", script %d",
|
qCInfo(lcFontDb, "OpenType support missing for \"%ls\", script %d",
|
||||||
qUtf16Printable(def.families.constFirst()), script);
|
qUtf16Printable(def.families.constFirst()), script);
|
||||||
if (engine->ref.loadRelaxed() == 0)
|
if (engine->ref.loadRelaxed() == 0)
|
||||||
@ -789,7 +798,8 @@ QFontEngine *QFontDatabasePrivate::loadEngine(int script, const QFontDef &reques
|
|||||||
Q_TRACE(QFontDatabase_loadEngine, request.families.join(QLatin1Char(';')), request.pointSize);
|
Q_TRACE(QFontDatabase_loadEngine, request.families.join(QLatin1Char(';')), request.pointSize);
|
||||||
|
|
||||||
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
|
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
|
||||||
QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script));
|
QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine,
|
||||||
|
QFontDatabasePrivate::ExtendedScript(script));
|
||||||
if (!request.fallBackFamilies.isEmpty()) {
|
if (!request.fallBackFamilies.isEmpty()) {
|
||||||
QStringList fallbacks = request.fallBackFamilies;
|
QStringList fallbacks = request.fallBackFamilies;
|
||||||
|
|
||||||
@ -797,7 +807,10 @@ QFontEngine *QFontDatabasePrivate::loadEngine(int script, const QFontDef &reques
|
|||||||
if (styleHint == QFont::AnyStyle && request.fixedPitch)
|
if (styleHint == QFont::AnyStyle && request.fixedPitch)
|
||||||
styleHint = QFont::TypeWriter;
|
styleHint = QFont::TypeWriter;
|
||||||
|
|
||||||
fallbacks += fallbacksForFamily(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script));
|
fallbacks += fallbacksForFamily(family->name,
|
||||||
|
QFont::Style(style->key.style),
|
||||||
|
styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript(script));
|
||||||
|
|
||||||
pfMultiEngine->setFallbackFamiliesList(fallbacks);
|
pfMultiEngine->setFallbackFamiliesList(fallbacks);
|
||||||
}
|
}
|
||||||
@ -877,8 +890,10 @@ unsigned int QFontDatabasePrivate::bestFoundry(int script, unsigned int score, i
|
|||||||
desc->style = nullptr;
|
desc->style = nullptr;
|
||||||
desc->size = nullptr;
|
desc->size = nullptr;
|
||||||
|
|
||||||
|
qCDebug(lcFontMatch, " REMARK: looking for best foundry for family '%s'%s [%d]",
|
||||||
qCDebug(lcFontMatch, " REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
|
family->name.toLatin1().constData(),
|
||||||
|
family->colorFont ? " (color font)" : "",
|
||||||
|
family->count);
|
||||||
|
|
||||||
for (int x = 0; x < family->count; ++x) {
|
for (int x = 0; x < family->count; ++x) {
|
||||||
QtFontFoundry *foundry = family->foundries[x];
|
QtFontFoundry *foundry = family->foundries[x];
|
||||||
@ -1068,6 +1083,10 @@ int QFontDatabasePrivate::match(int script, const QFontDef &request, const QStri
|
|||||||
if (writingSystem != QFontDatabase::Any && !familySupportsWritingSystem(test.family, writingSystem))
|
if (writingSystem != QFontDatabase::Any && !familySupportsWritingSystem(test.family, writingSystem))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Check if we require a color font and check for match
|
||||||
|
if (script == QFontDatabasePrivate::Script_Emoji && !test.family->colorFont)
|
||||||
|
continue;
|
||||||
|
|
||||||
// as we know the script is supported, we can be sure
|
// as we know the script is supported, we can be sure
|
||||||
// to find a matching font here.
|
// to find a matching font here.
|
||||||
unsigned int newscore =
|
unsigned int newscore =
|
||||||
@ -2202,6 +2221,48 @@ bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QFontDatabasePrivate::setApplicationFallbackFontFamilies(ExtendedScript script, const QStringList &familyNames)
|
||||||
|
{
|
||||||
|
applicationFallbackFontFamiliesHash[script] = familyNames;
|
||||||
|
|
||||||
|
QFontCache::instance()->clear();
|
||||||
|
fallbacksCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList QFontDatabasePrivate::applicationFallbackFontFamilies(ExtendedScript script)
|
||||||
|
{
|
||||||
|
return applicationFallbackFontFamiliesHash.value(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFontDatabasePrivate::removeApplicationFallbackFontFamily(ExtendedScript script, const QString &familyName)
|
||||||
|
{
|
||||||
|
auto it = applicationFallbackFontFamiliesHash.find(script);
|
||||||
|
if (it != applicationFallbackFontFamiliesHash.end()) {
|
||||||
|
if (it->removeAll(familyName) > 0) {
|
||||||
|
if (it->isEmpty())
|
||||||
|
it = applicationFallbackFontFamiliesHash.erase(it);
|
||||||
|
QFontCache::instance()->clear();
|
||||||
|
fallbacksCache.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QFontDatabasePrivate::addApplicationFallbackFontFamily(ExtendedScript script, const QString &familyName)
|
||||||
|
{
|
||||||
|
auto it = applicationFallbackFontFamiliesHash.find(script);
|
||||||
|
if (it == applicationFallbackFontFamiliesHash.end())
|
||||||
|
it = applicationFallbackFontFamiliesHash.insert(script, QStringList{});
|
||||||
|
|
||||||
|
it->prepend(familyName);
|
||||||
|
|
||||||
|
QFontCache::instance()->clear();
|
||||||
|
fallbacksCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\since 4.2
|
\since 4.2
|
||||||
|
|
||||||
@ -2398,7 +2459,7 @@ void QFontDatabase::addApplicationFallbackFontFamily(QChar::Script script, const
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(fontDatabaseMutex());
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
|
|
||||||
if (script < QChar::Script_Common) {
|
if (script < QChar::Script_Common || script >= QChar::ScriptCount) {
|
||||||
qCWarning(lcFontDb) << "Invalid script passed to addApplicationFallbackFontFamily:" << script;
|
qCWarning(lcFontDb) << "Invalid script passed to addApplicationFallbackFontFamily:" << script;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2407,14 +2468,7 @@ void QFontDatabase::addApplicationFallbackFontFamily(QChar::Script script, const
|
|||||||
script = QChar::Script_Common;
|
script = QChar::Script_Common;
|
||||||
|
|
||||||
auto *db = QFontDatabasePrivate::instance();
|
auto *db = QFontDatabasePrivate::instance();
|
||||||
auto it = db->applicationFallbackFontFamilies.find(script);
|
db->addApplicationFallbackFontFamily(QFontDatabasePrivate::ExtendedScript(script), familyName);
|
||||||
if (it == db->applicationFallbackFontFamilies.end())
|
|
||||||
it = db->applicationFallbackFontFamilies.insert(script, QStringList{});
|
|
||||||
|
|
||||||
it->prepend(familyName);
|
|
||||||
|
|
||||||
QFontCache::instance()->clear();
|
|
||||||
db->fallbacksCache.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2431,7 +2485,7 @@ bool QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script script, co
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(fontDatabaseMutex());
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
|
|
||||||
if (script < QChar::Script_Common) {
|
if (script < QChar::Script_Common || script >= QChar::ScriptCount) {
|
||||||
qCWarning(lcFontDb) << "Invalid script passed to removeApplicationFallbackFontFamily:" << script;
|
qCWarning(lcFontDb) << "Invalid script passed to removeApplicationFallbackFontFamily:" << script;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2440,18 +2494,8 @@ bool QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script script, co
|
|||||||
script = QChar::Script_Common;
|
script = QChar::Script_Common;
|
||||||
|
|
||||||
auto *db = QFontDatabasePrivate::instance();
|
auto *db = QFontDatabasePrivate::instance();
|
||||||
auto it = db->applicationFallbackFontFamilies.find(script);
|
return db->removeApplicationFallbackFontFamily(QFontDatabasePrivate::ExtendedScript(script),
|
||||||
if (it != db->applicationFallbackFontFamilies.end()) {
|
familyName);
|
||||||
if (it->removeAll(familyName) > 0) {
|
|
||||||
if (it->isEmpty())
|
|
||||||
it = db->applicationFallbackFontFamilies.erase(it);
|
|
||||||
QFontCache::instance()->clear();
|
|
||||||
db->fallbacksCache.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2471,7 +2515,7 @@ void QFontDatabase::setApplicationFallbackFontFamilies(QChar::Script script, con
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(fontDatabaseMutex());
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
|
|
||||||
if (script < QChar::Script_Common) {
|
if (script < QChar::Script_Common || script >= QChar::ScriptCount) {
|
||||||
qCWarning(lcFontDb) << "Invalid script passed to setApplicationFallbackFontFamilies:" << script;
|
qCWarning(lcFontDb) << "Invalid script passed to setApplicationFallbackFontFamilies:" << script;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2480,10 +2524,8 @@ void QFontDatabase::setApplicationFallbackFontFamilies(QChar::Script script, con
|
|||||||
script = QChar::Script_Common;
|
script = QChar::Script_Common;
|
||||||
|
|
||||||
auto *db = QFontDatabasePrivate::instance();
|
auto *db = QFontDatabasePrivate::instance();
|
||||||
db->applicationFallbackFontFamilies[script] = familyNames;
|
db->setApplicationFallbackFontFamilies(QFontDatabasePrivate::ExtendedScript(script),
|
||||||
|
familyNames);
|
||||||
QFontCache::instance()->clear();
|
|
||||||
db->fallbacksCache.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2498,11 +2540,81 @@ QStringList QFontDatabase::applicationFallbackFontFamilies(QChar::Script script)
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(fontDatabaseMutex());
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
|
|
||||||
|
if (script >= QChar::ScriptCount) {
|
||||||
|
qCWarning(lcFontDb) << "Invalid script passed to applicationFallbackFontFamilies:" << script;
|
||||||
|
return QStringList{};
|
||||||
|
}
|
||||||
|
|
||||||
if (script == QChar::Script_Latin)
|
if (script == QChar::Script_Latin)
|
||||||
script = QChar::Script_Common;
|
script = QChar::Script_Common;
|
||||||
|
|
||||||
auto *db = QFontDatabasePrivate::instance();
|
auto *db = QFontDatabasePrivate::instance();
|
||||||
return db->applicationFallbackFontFamilies.value(script);
|
return db->applicationFallbackFontFamilies(QFontDatabasePrivate::ExtendedScript(script));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.9
|
||||||
|
|
||||||
|
Adds \a familyName as an application-defined emoji font.
|
||||||
|
|
||||||
|
For displaying multi-color emojis or emoji sequences, Qt will by default prefer the system
|
||||||
|
default emoji font. Sometimes the application may want to override the default, either to
|
||||||
|
achieve a specific visual style or to show emojis that are not supported by the system.
|
||||||
|
|
||||||
|
\sa removeApplicationEmojiFontFamily, setApplicationEmojiFontFamilies(), applicationEmojiFontFamilies(), addApplicationFallbackFontFamily()
|
||||||
|
*/
|
||||||
|
void QFontDatabase::addApplicationEmojiFontFamily(const QString &familyName)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
|
auto *db = QFontDatabasePrivate::instance();
|
||||||
|
db->addApplicationFallbackFontFamily(QFontDatabasePrivate::Script_Emoji, familyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.9
|
||||||
|
|
||||||
|
Removes \a familyName from the list of application-defined emoji fonts,
|
||||||
|
provided that it has previously been added with \l{addApplicationEmojiFontFamily()}.
|
||||||
|
|
||||||
|
Returns true if the family name was in the list and false if it was not.
|
||||||
|
|
||||||
|
\sa addApplicationEmojiFontFamily(), setApplicationEmojiFontFamilies(), applicationEmojiFontFamilies(), removeApplicationFallbackFontFamily()
|
||||||
|
*/
|
||||||
|
bool QFontDatabase::removeApplicationEmojiFontFamily(const QString &familyName)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
|
auto *db = QFontDatabasePrivate::instance();
|
||||||
|
return db->removeApplicationFallbackFontFamily(QFontDatabasePrivate::Script_Emoji,
|
||||||
|
familyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.9
|
||||||
|
|
||||||
|
Sets the list of application-defined emoji fonts to \a familyNames.
|
||||||
|
|
||||||
|
\sa addApplicationEmojiFontFamily(), removeApplicationEmojiFontFamily(), applicationEmojiFontFamilies(), setApplicationFallbackFontFamilies()
|
||||||
|
*/
|
||||||
|
void QFontDatabase::setApplicationEmojiFontFamilies(const QStringList &familyNames)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
|
auto *db = QFontDatabasePrivate::instance();
|
||||||
|
db->setApplicationFallbackFontFamilies(QFontDatabasePrivate::Script_Emoji,
|
||||||
|
familyNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.9
|
||||||
|
|
||||||
|
Returns the list of application-defined emoji font families.
|
||||||
|
|
||||||
|
\sa addApplicationEmojiFontFamily(), removeApplicationEmojiFontFamily(), setApplicationEmojiFontFamilies(), applicationFallbackFontFamilies()
|
||||||
|
*/
|
||||||
|
QStringList QFontDatabase::applicationEmojiFontFamilies()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(fontDatabaseMutex());
|
||||||
|
auto *db = QFontDatabasePrivate::instance();
|
||||||
|
return db->applicationFallbackFontFamilies(QFontDatabasePrivate::Script_Emoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2559,12 +2671,27 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
|
|||||||
QtFontDesc desc;
|
QtFontDesc desc;
|
||||||
QList<int> blackListed;
|
QList<int> blackListed;
|
||||||
unsigned int score = UINT_MAX;
|
unsigned int score = UINT_MAX;
|
||||||
int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed, &score);
|
|
||||||
|
// 1.
|
||||||
|
// We start by looking up the family name and finding the best style/foundry. For multi fonts
|
||||||
|
// we always want the requested font to be on top, even if it does not support the selected
|
||||||
|
// script, since the fallback mechanism will handle this later. For NoFontMerging fonts, we pass
|
||||||
|
// in the script in order to prefer foundries that support the script. If none is found, we will
|
||||||
|
// retry with Script_Common later. Note that Script_Emoji is special. This means the Unicode
|
||||||
|
// algorithm has determined that we should use a color font. If the selected font is not
|
||||||
|
// a color font, we use the fall back mechanism to find one, since we want to prefer *any* color
|
||||||
|
// font over a non-color font in this case.
|
||||||
|
int index = match(multi && script != QFontDatabasePrivate::Script_Emoji ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed, &score);
|
||||||
|
|
||||||
|
// 2.
|
||||||
|
// If no font was found or it was not a perfect match, we let the database populate family
|
||||||
|
// aliases and try again.
|
||||||
if (score > 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases(family_name)) {
|
if (score > 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases(family_name)) {
|
||||||
// We populated family aliases (e.g. localized families), so try again
|
// We populated family aliases (e.g. localized families), so try again
|
||||||
index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed);
|
index = match(multi && script != QFontDatabasePrivate::Script_Emoji ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3.
|
||||||
// If we do not find a match and NoFontMerging is set, use the requested font even if it does
|
// If we do not find a match and NoFontMerging is set, use the requested font even if it does
|
||||||
// not support the script.
|
// not support the script.
|
||||||
//
|
//
|
||||||
@ -2589,6 +2716,10 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
|
|||||||
qCDebug(lcFontMatch, " NO MATCH FOUND\n");
|
qCDebug(lcFontMatch, " NO MATCH FOUND\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4.
|
||||||
|
// If no font matching the script + family exists, we go via the fallback mechanism. This
|
||||||
|
// happens when the family does not exist or if we want a color font and the requested font
|
||||||
|
// is not.
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
if (!requestFamily.isEmpty()) {
|
if (!requestFamily.isEmpty()) {
|
||||||
QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
|
QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
|
||||||
@ -2599,32 +2730,49 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
|
|||||||
+ fallbacksForFamily(requestFamily,
|
+ fallbacksForFamily(requestFamily,
|
||||||
QFont::Style(request.style),
|
QFont::Style(request.style),
|
||||||
styleHint,
|
styleHint,
|
||||||
QChar::Script(script));
|
QFontDatabasePrivate::ExtendedScript(script));
|
||||||
if (script > QChar::Script_Common)
|
if (script > QChar::Script_Common)
|
||||||
fallbacks += QString(); // Find the first font matching the specified script.
|
fallbacks += QString(); // Find the first font matching the specified script.
|
||||||
|
|
||||||
for (int i = 0; !engine && i < fallbacks.size(); i++) {
|
auto findMatchingFallback = [&](int xscript) {
|
||||||
QFontDef def = request;
|
for (int i = 0; !engine && i < fallbacks.size(); i++) {
|
||||||
def.families = QStringList(fallbacks.at(i));
|
QFontDef def = request;
|
||||||
QFontCache::Key key(def, script, multi ? 1 : 0);
|
|
||||||
engine = fontCache->findEngine(key);
|
def.families = QStringList(fallbacks.at(i));
|
||||||
if (!engine) {
|
QFontCache::Key key(def, xscript, multi ? 1 : 0);
|
||||||
QtFontDesc desc;
|
engine = fontCache->findEngine(key);
|
||||||
do {
|
if (!engine) {
|
||||||
index = match(multi ? QChar::Script_Common : script, def, def.families.constFirst(), ""_L1, &desc, blackListed);
|
QtFontDesc desc;
|
||||||
if (index >= 0) {
|
do {
|
||||||
QFontDef loadDef = def;
|
index = match(xscript,
|
||||||
if (loadDef.families.isEmpty())
|
def,
|
||||||
loadDef.families = QStringList(desc.family->name);
|
def.families.constFirst(),
|
||||||
engine = loadEngine(script, loadDef, desc.family, desc.foundry, desc.style, desc.size);
|
""_L1,
|
||||||
if (engine)
|
&desc,
|
||||||
initFontDef(desc, loadDef, &engine->fontDef, multi);
|
blackListed);
|
||||||
else
|
|
||||||
blackListed.append(index);
|
if (index >= 0) {
|
||||||
}
|
QFontDef loadDef = def;
|
||||||
} while (index >= 0 && !engine);
|
if (loadDef.families.isEmpty())
|
||||||
|
loadDef.families = QStringList(desc.family->name);
|
||||||
|
engine = loadEngine(xscript, loadDef, desc.family, desc.foundry, desc.style, desc.size);
|
||||||
|
if (engine)
|
||||||
|
initFontDef(desc, loadDef, &engine->fontDef, multi);
|
||||||
|
else
|
||||||
|
blackListed.append(index);
|
||||||
|
}
|
||||||
|
} while (index >= 0 && !engine);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
findMatchingFallback(multi && script != QFontDatabasePrivate::Script_Emoji ? QChar::Script_Common: script);
|
||||||
|
|
||||||
|
// If we are looking for a color font and there are no color fonts on the system,
|
||||||
|
// we will end up here, for one final pass. This is a rare occurrence so we accept
|
||||||
|
// and extra pass on the fallbacks for this.
|
||||||
|
if (!engine && script == QFontDatabasePrivate::Script_Emoji)
|
||||||
|
findMatchingFallback(QChar::Script_Common);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
@ -2721,7 +2869,7 @@ void QFontDatabasePrivate::load(const QFontPrivate *d, int script)
|
|||||||
|
|
||||||
Q_ASSERT(fe);
|
Q_ASSERT(fe);
|
||||||
if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
|
if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
|
||||||
for (int i = 0; i < QChar::ScriptCount; ++i) {
|
for (int i = 0; i < QFontDatabasePrivate::ScriptCount; ++i) {
|
||||||
if (!d->engineData->engines[i]) {
|
if (!d->engineData->engines[i]) {
|
||||||
d->engineData->engines[i] = fe;
|
d->engineData->engines[i] = fe;
|
||||||
fe->ref.ref();
|
fe->ref.ref();
|
||||||
@ -2738,11 +2886,13 @@ QString QFontDatabasePrivate::resolveFontFamilyAlias(const QString &family)
|
|||||||
return QGuiApplicationPrivate::platformIntegration()->fontDatabase()->resolveFontFamilyAlias(family);
|
return QGuiApplicationPrivate::platformIntegration()->fontDatabase()->resolveFontFamilyAlias(family);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script, const QStringList &families)
|
Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QFontDatabasePrivate::ExtendedScript script,
|
||||||
|
const QStringList &families)
|
||||||
{
|
{
|
||||||
size_t writingSystem = qt_writing_system_for_script(script);
|
size_t writingSystem = qt_writing_system_for_script(script);
|
||||||
if (writingSystem == QFontDatabase::Any
|
if (script != QFontDatabasePrivate::Script_Emoji
|
||||||
|| writingSystem >= QFontDatabase::WritingSystemsCount) {
|
&& (writingSystem == QFontDatabase::Any
|
||||||
|
|| writingSystem >= QFontDatabase::WritingSystemsCount)) {
|
||||||
return families;
|
return families;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2762,7 +2912,8 @@ Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script
|
|||||||
|
|
||||||
uint order = i;
|
uint order = i;
|
||||||
if (testFamily == nullptr
|
if (testFamily == nullptr
|
||||||
|| !familySupportsWritingSystem(testFamily, writingSystem)) {
|
|| (script == QFontDatabasePrivate::Script_Emoji && !testFamily->colorFont)
|
||||||
|
|| (script != QFontDatabasePrivate::Script_Emoji && !familySupportsWritingSystem(testFamily, writingSystem))) {
|
||||||
order |= 1u << 31;
|
order |= 1u << 31;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +117,11 @@ public:
|
|||||||
static void setApplicationFallbackFontFamilies(QChar::Script, const QStringList &familyNames);
|
static void setApplicationFallbackFontFamilies(QChar::Script, const QStringList &familyNames);
|
||||||
static QStringList applicationFallbackFontFamilies(QChar::Script script);
|
static QStringList applicationFallbackFontFamilies(QChar::Script script);
|
||||||
|
|
||||||
|
static void addApplicationEmojiFontFamily(const QString &familyName);
|
||||||
|
static bool removeApplicationEmojiFontFamily(const QString &familyName);
|
||||||
|
static void setApplicationEmojiFontFamilies(const QStringList &familyNames);
|
||||||
|
static QStringList applicationEmojiFontFamilies();
|
||||||
|
|
||||||
static QFont systemFont(SystemFont type);
|
static QFont systemFont(SystemFont type);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ struct QtFontFallbacksCacheKey
|
|||||||
QString family;
|
QString family;
|
||||||
QFont::Style style;
|
QFont::Style style;
|
||||||
QFont::StyleHint styleHint;
|
QFont::StyleHint styleHint;
|
||||||
QChar::Script script;
|
int script;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const QtFontFallbacksCacheKey &lhs, const QtFontFallbacksCacheKey &rhs) noexcept
|
inline bool operator==(const QtFontFallbacksCacheKey &lhs, const QtFontFallbacksCacheKey &rhs) noexcept
|
||||||
@ -155,6 +155,7 @@ struct Q_GUI_EXPORT QtFontFamily
|
|||||||
:
|
:
|
||||||
populated(false),
|
populated(false),
|
||||||
fixedPitch(false),
|
fixedPitch(false),
|
||||||
|
colorFont(false),
|
||||||
name(n), count(0), foundries(nullptr)
|
name(n), count(0), foundries(nullptr)
|
||||||
{
|
{
|
||||||
memset(writingSystems, 0, sizeof(writingSystems));
|
memset(writingSystems, 0, sizeof(writingSystems));
|
||||||
@ -167,6 +168,7 @@ struct Q_GUI_EXPORT QtFontFamily
|
|||||||
|
|
||||||
bool populated : 1;
|
bool populated : 1;
|
||||||
bool fixedPitch : 1;
|
bool fixedPitch : 1;
|
||||||
|
bool colorFont : 1;
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
QStringList aliases;
|
QStringList aliases;
|
||||||
@ -202,13 +204,21 @@ public:
|
|||||||
EnsurePopulated
|
EnsurePopulated
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Expands QChar::Script by adding a special "script" for emoji sequences
|
||||||
|
enum ExtendedScript {
|
||||||
|
Script_Common = QChar::Script_Common,
|
||||||
|
Script_Latin = QChar::Script_Latin,
|
||||||
|
Script_Emoji = QChar::ScriptCount,
|
||||||
|
ScriptCount
|
||||||
|
};
|
||||||
|
|
||||||
QtFontFamily *family(const QString &f, FamilyRequestFlags flags = EnsurePopulated);
|
QtFontFamily *family(const QString &f, FamilyRequestFlags flags = EnsurePopulated);
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
QtFontFamily **families;
|
QtFontFamily **families;
|
||||||
bool populated = false;
|
bool populated = false;
|
||||||
|
|
||||||
QHash<QChar::Script, QStringList> applicationFallbackFontFamilies;
|
QHash<ExtendedScript, QStringList> applicationFallbackFontFamiliesHash;
|
||||||
|
|
||||||
QCache<QtFontFallbacksCacheKey, QStringList> fallbacksCache;
|
QCache<QtFontFallbacksCacheKey, QStringList> fallbacksCache;
|
||||||
struct ApplicationFont {
|
struct ApplicationFont {
|
||||||
@ -236,21 +246,30 @@ public:
|
|||||||
int addAppFont(const QByteArray &fontData, const QString &fileName);
|
int addAppFont(const QByteArray &fontData, const QString &fileName);
|
||||||
bool isApplicationFont(const QString &fileName);
|
bool isApplicationFont(const QString &fileName);
|
||||||
|
|
||||||
|
void setApplicationFallbackFontFamilies(ExtendedScript script, const QStringList &familyNames);
|
||||||
|
QStringList applicationFallbackFontFamilies(ExtendedScript script);
|
||||||
|
bool removeApplicationFallbackFontFamily(ExtendedScript script, const QString &familyName);
|
||||||
|
void addApplicationFallbackFontFamily(ExtendedScript script, const QString &familyName);
|
||||||
|
|
||||||
static QFontDatabasePrivate *instance();
|
static QFontDatabasePrivate *instance();
|
||||||
|
|
||||||
static void parseFontName(const QString &name, QString &foundry, QString &family);
|
static void parseFontName(const QString &name, QString &foundry, QString &family);
|
||||||
static QString resolveFontFamilyAlias(const QString &family);
|
static QString resolveFontFamilyAlias(const QString &family);
|
||||||
static QFontEngine *findFont(const QFontDef &request,
|
static QFontEngine *findFont(const QFontDef &request,
|
||||||
int script /* QChar::Script */,
|
int script /* QFontDatabasePrivate::ExtendedScript */,
|
||||||
bool preferScriptOverFamily = false);
|
bool preferScriptOverFamily = false);
|
||||||
static void load(const QFontPrivate *d, int script /* QChar::Script */);
|
static void load(const QFontPrivate *d, int script /* QFontDatabasePrivate::ExtendedScript */);
|
||||||
static QFontDatabasePrivate *ensureFontDatabase();
|
static QFontDatabasePrivate *ensureFontDatabase();
|
||||||
|
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int match(int script, const QFontDef &request, const QString &family_name,
|
static int match(int script,
|
||||||
const QString &foundry_name, QtFontDesc *desc, const QList<int> &blacklistedFamilies,
|
const QFontDef &request,
|
||||||
|
const QString &family_name,
|
||||||
|
const QString &foundry_name,
|
||||||
|
QtFontDesc *desc,
|
||||||
|
const QList<int> &blacklistedFamilies,
|
||||||
unsigned int *resultingScore = nullptr);
|
unsigned int *resultingScore = nullptr);
|
||||||
|
|
||||||
static unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
|
static unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
|
||||||
|
@ -1747,7 +1747,7 @@ QFontEngineMulti::~QFontEngineMulti()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script);
|
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QFontDatabasePrivate::ExtendedScript script);
|
||||||
|
|
||||||
void QFontEngineMulti::ensureFallbackFamiliesQueried()
|
void QFontEngineMulti::ensureFallbackFamiliesQueried()
|
||||||
{
|
{
|
||||||
@ -1757,7 +1757,7 @@ void QFontEngineMulti::ensureFallbackFamiliesQueried()
|
|||||||
|
|
||||||
setFallbackFamiliesList(qt_fallbacksForFamily(fontDef.families.constFirst(),
|
setFallbackFamiliesList(qt_fallbacksForFamily(fontDef.families.constFirst(),
|
||||||
QFont::Style(fontDef.style), styleHint,
|
QFont::Style(fontDef.style), styleHint,
|
||||||
QChar::Script(m_script)));
|
QFontDatabasePrivate::ExtendedScript(m_script)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QFontEngineMulti::setFallbackFamiliesList(const QStringList &fallbackFamilies)
|
void QFontEngineMulti::setFallbackFamiliesList(const QStringList &fallbackFamilies)
|
||||||
@ -1805,7 +1805,7 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
|
|||||||
// info about the actual script of the characters may have been discarded,
|
// info about the actual script of the characters may have been discarded,
|
||||||
// so we do not check for writing system support, but instead just load
|
// so we do not check for writing system support, but instead just load
|
||||||
// the family indiscriminately.
|
// the family indiscriminately.
|
||||||
if (QFontEngine *engine = QFontDatabasePrivate::findFont(request, QChar::Script_Common)) {
|
if (QFontEngine *engine = QFontDatabasePrivate::findFont(request, QFontDatabasePrivate::Script_Common)) {
|
||||||
engine->fontDef.weight = request.weight;
|
engine->fontDef.weight = request.weight;
|
||||||
if (request.style > QFont::StyleNormal)
|
if (request.style > QFont::StyleNormal)
|
||||||
engine->fontDef.style = request.style;
|
engine->fontDef.style = request.style;
|
||||||
@ -2381,7 +2381,7 @@ QFontEngine *QFontEngineMulti::createMultiFontEngine(QFontEngine *fe, int script
|
|||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script));
|
engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QFontDatabasePrivate::ExtendedScript(script));
|
||||||
fc->insertEngine(key, engine, /* insertMulti */ !faceIsLocal);
|
fc->insertEngine(key, engine, /* insertMulti */ !faceIsLocal);
|
||||||
}
|
}
|
||||||
Q_ASSERT(engine);
|
Q_ASSERT(engine);
|
||||||
|
@ -24,7 +24,7 @@ Q_LOGGING_CATEGORY(lcQpaFonts, "qt.qpa.fonts")
|
|||||||
void qt_registerFont(const QString &familyname, const QString &stylename,
|
void qt_registerFont(const QString &familyname, const QString &stylename,
|
||||||
const QString &foundryname, int weight,
|
const QString &foundryname, int weight,
|
||||||
QFont::Style style, int stretch, bool antialiased,
|
QFont::Style style, int stretch, bool antialiased,
|
||||||
bool scalable, int pixelSize, bool fixedPitch,
|
bool scalable, int pixelSize, bool fixedPitch, bool colorFont,
|
||||||
const QSupportedWritingSystems &writingSystems, void *hanlde);
|
const QSupportedWritingSystems &writingSystems, void *hanlde);
|
||||||
|
|
||||||
void qt_registerFontFamily(const QString &familyName);
|
void qt_registerFontFamily(const QString &familyName);
|
||||||
@ -55,7 +55,7 @@ bool qt_isFontFamilyPopulated(const QString &familyName);
|
|||||||
void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &stylename,
|
void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &stylename,
|
||||||
const QString &foundryname, QFont::Weight weight,
|
const QString &foundryname, QFont::Weight weight,
|
||||||
QFont::Style style, QFont::Stretch stretch, bool antialiased,
|
QFont::Style style, QFont::Stretch stretch, bool antialiased,
|
||||||
bool scalable, int pixelSize, bool fixedPitch,
|
bool scalable, int pixelSize, bool fixedPitch, bool colorFont,
|
||||||
const QSupportedWritingSystems &writingSystems, void *usrPtr)
|
const QSupportedWritingSystems &writingSystems, void *usrPtr)
|
||||||
{
|
{
|
||||||
if (scalable)
|
if (scalable)
|
||||||
@ -63,7 +63,7 @@ void QPlatformFontDatabase::registerFont(const QString &familyname, const QStrin
|
|||||||
|
|
||||||
qt_registerFont(familyname, stylename, foundryname, weight, style,
|
qt_registerFont(familyname, stylename, foundryname, weight, style,
|
||||||
stretch, antialiased, scalable, pixelSize,
|
stretch, antialiased, scalable, pixelSize,
|
||||||
fixedPitch, writingSystems, usrPtr);
|
fixedPitch, colorFont, writingSystems, usrPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -271,7 +271,8 @@ void QPlatformFontDatabase::invalidate()
|
|||||||
option to fall back to the fonts given by \a fallbacks if \a fontEngine does not support
|
option to fall back to the fonts given by \a fallbacks if \a fontEngine does not support
|
||||||
a certain character.
|
a certain character.
|
||||||
*/
|
*/
|
||||||
QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
|
QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script)
|
||||||
{
|
{
|
||||||
return new QFontEngineMulti(fontEngine, script);
|
return new QFontEngineMulti(fontEngine, script);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <QtCore/QList>
|
#include <QtCore/QList>
|
||||||
#include <QtGui/QFontDatabase>
|
#include <QtGui/QFontDatabase>
|
||||||
#include <QtGui/private/qfontengine_p.h>
|
#include <QtGui/private/qfontengine_p.h>
|
||||||
#include <QtGui/private/qfont_p.h>
|
|
||||||
#include <QtGui/private/qfontdatabase_p.h>
|
#include <QtGui/private/qfontdatabase_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -72,12 +71,12 @@ public:
|
|||||||
virtual void populateFamily(const QString &familyName);
|
virtual void populateFamily(const QString &familyName);
|
||||||
virtual void invalidate();
|
virtual void invalidate();
|
||||||
|
|
||||||
virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
|
virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QFontDatabasePrivate::ExtendedScript script) const;
|
||||||
virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *font = nullptr);
|
virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *font = nullptr);
|
||||||
|
|
||||||
virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
|
virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
|
||||||
virtual QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
|
virtual QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
|
||||||
virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script);
|
virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QFontDatabasePrivate::ExtendedScript script);
|
||||||
virtual void releaseHandle(void *handle);
|
virtual void releaseHandle(void *handle);
|
||||||
|
|
||||||
virtual QString fontDir() const;
|
virtual QString fontDir() const;
|
||||||
@ -99,7 +98,7 @@ public:
|
|||||||
static void registerFont(const QString &familyname, const QString &stylename,
|
static void registerFont(const QString &familyname, const QString &stylename,
|
||||||
const QString &foundryname, QFont::Weight weight,
|
const QString &foundryname, QFont::Weight weight,
|
||||||
QFont::Style style, QFont::Stretch stretch, bool antialiased,
|
QFont::Style style, QFont::Stretch stretch, bool antialiased,
|
||||||
bool scalable, int pixelSize, bool fixedPitch,
|
bool scalable, int pixelSize, bool fixedPitch, bool colorFont,
|
||||||
const QSupportedWritingSystems &writingSystems, void *handle);
|
const QSupportedWritingSystems &writingSystems, void *handle);
|
||||||
|
|
||||||
static void registerFontFamily(const QString &familyName);
|
static void registerFontFamily(const QString &familyName);
|
||||||
|
@ -1409,8 +1409,8 @@ void QTextEngine::shapeText(int item) const
|
|||||||
QFont font = f.font();
|
QFont font = f.font();
|
||||||
# if QT_CONFIG(harfbuzz)
|
# if QT_CONFIG(harfbuzz)
|
||||||
kerningEnabled = font.kerning();
|
kerningEnabled = font.kerning();
|
||||||
shapingEnabled = QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script))
|
shapingEnabled = (si.analysis.script < QChar::ScriptCount && QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script)))
|
||||||
|| (font.styleStrategy() & QFont::PreferNoShaping) == 0;
|
|| (font.styleStrategy() & QFont::PreferNoShaping) == 0;
|
||||||
# endif
|
# endif
|
||||||
wordSpacing = QFixed::fromReal(font.wordSpacing());
|
wordSpacing = QFixed::fromReal(font.wordSpacing());
|
||||||
letterSpacing = QFixed::fromReal(font.letterSpacing());
|
letterSpacing = QFixed::fromReal(font.letterSpacing());
|
||||||
@ -1422,8 +1422,8 @@ void QTextEngine::shapeText(int item) const
|
|||||||
QFont font = this->font(si);
|
QFont font = this->font(si);
|
||||||
#if QT_CONFIG(harfbuzz)
|
#if QT_CONFIG(harfbuzz)
|
||||||
kerningEnabled = font.d->kerning;
|
kerningEnabled = font.d->kerning;
|
||||||
shapingEnabled = QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script))
|
shapingEnabled = (si.analysis.script < QChar::ScriptCount && QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script)))
|
||||||
|| (font.d->request.styleStrategy & QFont::PreferNoShaping) == 0;
|
|| (font.d->request.styleStrategy & QFont::PreferNoShaping) == 0;
|
||||||
#endif
|
#endif
|
||||||
letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;
|
letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;
|
||||||
letterSpacing = font.d->letterSpacing;
|
letterSpacing = font.d->letterSpacing;
|
||||||
@ -1619,7 +1619,9 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
|
|||||||
|
|
||||||
hb_segment_properties_t props = HB_SEGMENT_PROPERTIES_DEFAULT;
|
hb_segment_properties_t props = HB_SEGMENT_PROPERTIES_DEFAULT;
|
||||||
props.direction = si.analysis.bidiLevel % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR;
|
props.direction = si.analysis.bidiLevel % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR;
|
||||||
QChar::Script script = QChar::Script(si.analysis.script);
|
QChar::Script script = si.analysis.script < QChar::ScriptCount
|
||||||
|
? QChar::Script(si.analysis.script)
|
||||||
|
: QChar::Script_Common;
|
||||||
props.script = hb_qt_script_to_script(script);
|
props.script = hb_qt_script_to_script(script);
|
||||||
// ### TODO get_default_for_script?
|
// ### TODO get_default_for_script?
|
||||||
props.language = hb_language_get_default(); // use default language from locale
|
props.language = hb_language_get_default(); // use default language from locale
|
||||||
@ -1923,8 +1925,38 @@ void QTextEngine::validate() const
|
|||||||
layoutData->string.insert(specialData->preeditPosition, specialData->preeditText);
|
layoutData->string.insert(specialData->preeditPosition, specialData->preeditText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(QT_NO_EMOJISEGMENTER)
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
enum CharacterCategory {
|
||||||
|
EMOJI = 0,
|
||||||
|
EMOJI_TEXT_PRESENTATION = 1,
|
||||||
|
EMOJI_EMOJI_PRESENTATION = 2,
|
||||||
|
EMOJI_MODIFIER_BASE = 3,
|
||||||
|
EMOJI_MODIFIER = 4,
|
||||||
|
EMOJI_VS_BASE = 5,
|
||||||
|
REGIONAL_INDICATOR = 6,
|
||||||
|
KEYCAP_BASE = 7,
|
||||||
|
COMBINING_ENCLOSING_KEYCAP = 8,
|
||||||
|
COMBINING_ENCLOSING_CIRCLE_BACKSLASH = 9,
|
||||||
|
ZWJ = 10,
|
||||||
|
VS15 = 11,
|
||||||
|
VS16 = 12,
|
||||||
|
TAG_BASE = 13,
|
||||||
|
TAG_SEQUENCE = 14,
|
||||||
|
TAG_TERM = 15,
|
||||||
|
OTHER = 16
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef CharacterCategory *emoji_text_iter_t;
|
||||||
|
|
||||||
|
#include "../../3rdparty/emoji-segmenter/emoji_presentation_scanner.c"
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void QTextEngine::itemize() const
|
void QTextEngine::itemize() const
|
||||||
{
|
{
|
||||||
|
static bool disableEmojiSegmenter = qEnvironmentVariableIntValue("QT_DISABLE_EMOJI_SEGMENTER") > 0;
|
||||||
validate();
|
validate();
|
||||||
if (layoutData->items.size())
|
if (layoutData->items.size())
|
||||||
return;
|
return;
|
||||||
@ -1954,9 +1986,76 @@ void QTextEngine::itemize() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(QT_NO_EMOJISEGMENTER)
|
||||||
|
QVarLengthArray<CharacterCategory> categorizedString;
|
||||||
|
if (!disableEmojiSegmenter) {
|
||||||
|
// Parse emoji sequences
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
const QChar &c = string[i];
|
||||||
|
const bool isSurrogate = c.isHighSurrogate() && i < length - 1;
|
||||||
|
const char32_t ucs4 = isSurrogate
|
||||||
|
? QChar::surrogateToUcs4(c, string[++i])
|
||||||
|
: c.unicode();
|
||||||
|
const QUnicodeTables::Properties *p = QUnicodeTables::properties(ucs4);
|
||||||
|
|
||||||
|
if (ucs4 == 0x20E3)
|
||||||
|
categorizedString.append(CharacterCategory::COMBINING_ENCLOSING_KEYCAP);
|
||||||
|
else if (ucs4 == 0x20E0)
|
||||||
|
categorizedString.append(CharacterCategory::COMBINING_ENCLOSING_CIRCLE_BACKSLASH);
|
||||||
|
else if (ucs4 == 0xFE0E)
|
||||||
|
categorizedString.append(CharacterCategory::VS15);
|
||||||
|
else if (ucs4 == 0xFE0F)
|
||||||
|
categorizedString.append(CharacterCategory::VS16);
|
||||||
|
else if (ucs4 == 0x200D)
|
||||||
|
categorizedString.append(CharacterCategory::ZWJ);
|
||||||
|
else if (ucs4 == 0x1F3F4)
|
||||||
|
categorizedString.append(CharacterCategory::TAG_BASE);
|
||||||
|
else if (ucs4 == 0xE007F)
|
||||||
|
categorizedString.append(CharacterCategory::TAG_TERM);
|
||||||
|
else if ((ucs4 >= 0xE0030 && ucs4 <= 0xE0039) || (ucs4 >= 0xE0061 && ucs4 <= 0xE007A))
|
||||||
|
categorizedString.append(CharacterCategory::TAG_SEQUENCE);
|
||||||
|
else if (ucs4 >= 0x1F1E6 && ucs4 <= 0x1F1FF)
|
||||||
|
categorizedString.append(CharacterCategory::REGIONAL_INDICATOR);
|
||||||
|
// emoji_keycap_sequence = [0-9#*] \x{FE0F 20E3}
|
||||||
|
else if ((ucs4 >= 0x0030 && ucs4 <= 0x0039) || ucs4 == 0x0023 || ucs4 == 0x002A)
|
||||||
|
categorizedString.append(CharacterCategory::KEYCAP_BASE);
|
||||||
|
else if (p->emojiFlags & uchar(QUnicodeTables::EmojiFlags::Emoji_Modifier_Base))
|
||||||
|
categorizedString.append(CharacterCategory::EMOJI_MODIFIER_BASE);
|
||||||
|
else if (p->emojiFlags & uchar(QUnicodeTables::EmojiFlags::Emoji_Modifier))
|
||||||
|
categorizedString.append(CharacterCategory::EMOJI_MODIFIER);
|
||||||
|
else if (p->emojiFlags & uchar(QUnicodeTables::EmojiFlags::Emoji_Presentation))
|
||||||
|
categorizedString.append(CharacterCategory::EMOJI_EMOJI_PRESENTATION);
|
||||||
|
// If it's in the emoji list and doesn't have the emoji presentation, it is text
|
||||||
|
// presentation.
|
||||||
|
else if (p->emojiFlags & uchar(QUnicodeTables::EmojiFlags::Emoji))
|
||||||
|
categorizedString.append(CharacterCategory::EMOJI_TEXT_PRESENTATION);
|
||||||
|
else
|
||||||
|
categorizedString.append(CharacterCategory::OTHER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const ushort *uc = string;
|
const ushort *uc = string;
|
||||||
const ushort *e = uc + length;
|
const ushort *e = uc + length;
|
||||||
|
|
||||||
|
#if !defined(QT_NO_EMOJISEGMENTER)
|
||||||
|
const emoji_text_iter_t categoriesStart = categorizedString.data();
|
||||||
|
const emoji_text_iter_t categoriesEnd = categoriesStart + categorizedString.size();
|
||||||
|
|
||||||
|
emoji_text_iter_t categoryIt = categoriesStart;
|
||||||
|
|
||||||
|
bool isEmoji = false;
|
||||||
|
bool hasVs = false;
|
||||||
|
emoji_text_iter_t nextIt = categoryIt;
|
||||||
|
#endif
|
||||||
|
|
||||||
while (uc < e) {
|
while (uc < e) {
|
||||||
|
#if !defined(QT_NO_EMOJISEGMENTER)
|
||||||
|
// Find next emoji sequence
|
||||||
|
if (!disableEmojiSegmenter && categoryIt == nextIt)
|
||||||
|
nextIt = scan_emoji_presentation(categoryIt, categoriesEnd, &isEmoji, &hasVs);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (*uc) {
|
switch (*uc) {
|
||||||
case QChar::ObjectReplacementCharacter:
|
case QChar::ObjectReplacementCharacter:
|
||||||
{
|
{
|
||||||
@ -1996,7 +2095,27 @@ void QTextEngine::itemize() const
|
|||||||
default:
|
default:
|
||||||
analysis->flags = QScriptAnalysis::None;
|
analysis->flags = QScriptAnalysis::None;
|
||||||
break;
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(QT_NO_EMOJISEGMENTER)
|
||||||
|
if (!disableEmojiSegmenter) {
|
||||||
|
if (isEmoji) {
|
||||||
|
static_assert(QChar::ScriptCount < USHRT_MAX);
|
||||||
|
analysis->script = QFontDatabasePrivate::Script_Emoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QChar::isHighSurrogate(*uc) && (uc + 1) < e && QChar::isLowSurrogate(*(uc + 1))) {
|
||||||
|
if (isEmoji)
|
||||||
|
(analysis + 1)->script = QFontDatabasePrivate::Script_Emoji;
|
||||||
|
|
||||||
|
++uc;
|
||||||
|
++analysis;
|
||||||
|
}
|
||||||
|
|
||||||
|
++categoryIt;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
++uc;
|
++uc;
|
||||||
++analysis;
|
++analysis;
|
||||||
}
|
}
|
||||||
|
@ -475,6 +475,12 @@ static void populateFromPattern(FcPattern *pattern,
|
|||||||
FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);
|
FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);
|
||||||
|
|
||||||
bool fixedPitch = spacing_value >= FC_MONO;
|
bool fixedPitch = spacing_value >= FC_MONO;
|
||||||
|
|
||||||
|
FcBool colorFont = false;
|
||||||
|
#ifdef FC_COLOR
|
||||||
|
FcPatternGetBool(pattern, FC_COLOR, 1, &colorFont);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Note: stretch should really be an int but registerFont incorrectly uses an enum
|
// Note: stretch should really be an int but registerFont incorrectly uses an enum
|
||||||
QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
|
QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
|
||||||
QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
|
QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
|
||||||
@ -490,7 +496,7 @@ static void populateFromPattern(FcPattern *pattern,
|
|||||||
applicationFont->properties.append(properties);
|
applicationFont->properties.append(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1StringView((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
|
QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1StringView((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,colorFont,writingSystems,fontFile);
|
||||||
if (applicationFont != nullptr && face != nullptr && db != nullptr) {
|
if (applicationFont != nullptr && face != nullptr && db != nullptr) {
|
||||||
db->addNamedInstancesForFace(face,
|
db->addNamedInstancesForFace(face,
|
||||||
indexValue,
|
indexValue,
|
||||||
@ -500,6 +506,7 @@ static void populateFromPattern(FcPattern *pattern,
|
|||||||
stretch,
|
stretch,
|
||||||
style,
|
style,
|
||||||
fixedPitch,
|
fixedPitch,
|
||||||
|
colorFont,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
QByteArray((const char*)file_value),
|
QByteArray((const char*)file_value),
|
||||||
applicationFont->data);
|
applicationFont->data);
|
||||||
@ -536,7 +543,7 @@ static void populateFromPattern(FcPattern *pattern,
|
|||||||
applicationFont->properties.append(properties);
|
applicationFont->properties.append(properties);
|
||||||
}
|
}
|
||||||
FontFile *altFontFile = new FontFile(*fontFile);
|
FontFile *altFontFile = new FontFile(*fontFile);
|
||||||
QPlatformFontDatabase::registerFont(altFamilyName, altStyleName, QLatin1StringView((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,altFontFile);
|
QPlatformFontDatabase::registerFont(altFamilyName, altStyleName, QLatin1StringView((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,colorFont,writingSystems,altFontFile);
|
||||||
} else {
|
} else {
|
||||||
QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName);
|
QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName);
|
||||||
}
|
}
|
||||||
@ -613,9 +620,9 @@ void QFontconfigDatabase::populateFontDatabase()
|
|||||||
|
|
||||||
while (f->qtname) {
|
while (f->qtname) {
|
||||||
QString familyQtName = QString::fromLatin1(f->qtname);
|
QString familyQtName = QString::fromLatin1(f->qtname);
|
||||||
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,f->fixed,ws,nullptr);
|
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,false,0,f->fixed,ws,nullptr);
|
||||||
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,f->fixed,ws,nullptr);
|
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,false,0,f->fixed,ws,nullptr);
|
||||||
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,f->fixed,ws,nullptr);
|
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,false,0,f->fixed,ws,nullptr);
|
||||||
++f;
|
++f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,7 +641,7 @@ void QFontconfigDatabase::invalidate()
|
|||||||
FcConfigAppFontClear(nullptr);
|
FcConfigAppFontClear(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
|
QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QFontDatabasePrivate::ExtendedScript script)
|
||||||
{
|
{
|
||||||
return new QFontEngineMultiFontConfig(fontEngine, script);
|
return new QFontEngineMultiFontConfig(fontEngine, script);
|
||||||
}
|
}
|
||||||
@ -758,7 +765,10 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal p
|
|||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) const
|
||||||
{
|
{
|
||||||
QStringList fallbackFamilies;
|
QStringList fallbackFamilies;
|
||||||
FcPattern *pattern = FcPatternCreate();
|
FcPattern *pattern = FcPatternCreate();
|
||||||
@ -771,6 +781,14 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont
|
|||||||
value.u.s = (const FcChar8 *)cs.data();
|
value.u.s = (const FcChar8 *)cs.data();
|
||||||
FcPatternAdd(pattern,FC_FAMILY,value,true);
|
FcPatternAdd(pattern,FC_FAMILY,value,true);
|
||||||
|
|
||||||
|
#ifdef FC_COLOR
|
||||||
|
if (script == QFontDatabasePrivate::Script_Emoji) {
|
||||||
|
FcPatternAddBool(pattern, FC_COLOR, true);
|
||||||
|
value.u.s = (const FcChar8 *)"emoji";
|
||||||
|
FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int slant_value = FC_SLANT_ROMAN;
|
int slant_value = FC_SLANT_ROMAN;
|
||||||
if (style == QFont::StyleItalic)
|
if (style == QFont::StyleItalic)
|
||||||
slant_value = FC_SLANT_ITALIC;
|
slant_value = FC_SLANT_ITALIC;
|
||||||
@ -778,8 +796,8 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont
|
|||||||
slant_value = FC_SLANT_OBLIQUE;
|
slant_value = FC_SLANT_OBLIQUE;
|
||||||
FcPatternAddInteger(pattern, FC_SLANT, slant_value);
|
FcPatternAddInteger(pattern, FC_SLANT, slant_value);
|
||||||
|
|
||||||
Q_ASSERT(uint(script) < QChar::ScriptCount);
|
Q_ASSERT(uint(script) < QFontDatabasePrivate::ScriptCount);
|
||||||
if (*specialLanguages[script] != '\0') {
|
if (uint(script) < QChar::ScriptCount && *specialLanguages[script] != '\0') {
|
||||||
FcLangSet *ls = FcLangSetCreate();
|
FcLangSet *ls = FcLangSetCreate();
|
||||||
FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
|
FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
|
||||||
FcPatternAddLangSet(pattern, FC_LANG, ls);
|
FcPatternAddLangSet(pattern, FC_LANG, ls);
|
||||||
|
@ -29,10 +29,14 @@ public:
|
|||||||
void populateFontDatabase() override;
|
void populateFontDatabase() override;
|
||||||
void invalidate() override;
|
void invalidate() override;
|
||||||
bool supportsVariableApplicationFonts() const override;
|
bool supportsVariableApplicationFonts() const override;
|
||||||
QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) override;
|
QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) override;
|
||||||
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
|
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
|
||||||
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
|
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
|
||||||
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override;
|
QStringList fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) const override;
|
||||||
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) override;
|
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) override;
|
||||||
QString resolveFontFamilyAlias(const QString &family) const override;
|
QString resolveFontFamilyAlias(const QString &family) const override;
|
||||||
QFont defaultFont() const override;
|
QFont defaultFont() const override;
|
||||||
|
@ -138,9 +138,9 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
|
|||||||
for (uint j = 0; j < matchingFonts->GetFontCount(); ++j) {
|
for (uint j = 0; j < matchingFonts->GetFontCount(); ++j) {
|
||||||
DirectWriteScope<IDWriteFont> font;
|
DirectWriteScope<IDWriteFont> font;
|
||||||
if (SUCCEEDED(matchingFonts->GetFont(j, &font))) {
|
if (SUCCEEDED(matchingFonts->GetFont(j, &font))) {
|
||||||
DirectWriteScope<IDWriteFont1> font1;
|
DirectWriteScope<IDWriteFont2> font2;
|
||||||
if (!SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont1),
|
if (!SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont2),
|
||||||
reinterpret_cast<void **>(&font1)))) {
|
reinterpret_cast<void **>(&font2)))) {
|
||||||
qCWarning(lcQpaFonts) << "COM object does not support IDWriteFont1";
|
qCWarning(lcQpaFonts) << "COM object does not support IDWriteFont1";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
|
|||||||
QString englishLocaleFamilyName;
|
QString englishLocaleFamilyName;
|
||||||
|
|
||||||
DirectWriteScope<IDWriteFontFamily> fontFamily2;
|
DirectWriteScope<IDWriteFontFamily> fontFamily2;
|
||||||
if (SUCCEEDED(font1->GetFontFamily(&fontFamily2))) {
|
if (SUCCEEDED(font2->GetFontFamily(&fontFamily2))) {
|
||||||
DirectWriteScope<IDWriteLocalizedStrings> names;
|
DirectWriteScope<IDWriteLocalizedStrings> names;
|
||||||
if (SUCCEEDED(fontFamily2->GetFamilyNames(&names))) {
|
if (SUCCEEDED(fontFamily2->GetFamilyNames(&names))) {
|
||||||
defaultLocaleFamilyName = hasDefaultLocale ? localeString(*names, defaultLocale) : QString();
|
defaultLocaleFamilyName = hasDefaultLocale ? localeString(*names, defaultLocale) : QString();
|
||||||
@ -162,14 +162,15 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
|
|||||||
|
|
||||||
{
|
{
|
||||||
DirectWriteScope<IDWriteLocalizedStrings> names;
|
DirectWriteScope<IDWriteLocalizedStrings> names;
|
||||||
if (SUCCEEDED(font1->GetFaceNames(&names))) {
|
if (SUCCEEDED(font2->GetFaceNames(&names))) {
|
||||||
QString defaultLocaleStyleName = hasDefaultLocale ? localeString(*names, defaultLocale) : QString();
|
QString defaultLocaleStyleName = hasDefaultLocale ? localeString(*names, defaultLocale) : QString();
|
||||||
QString englishLocaleStyleName = localeString(*names, englishLocale);
|
QString englishLocaleStyleName = localeString(*names, englishLocale);
|
||||||
|
|
||||||
QFont::Stretch stretch = fromDirectWriteStretch(font1->GetStretch());
|
QFont::Stretch stretch = fromDirectWriteStretch(font2->GetStretch());
|
||||||
QFont::Style style = fromDirectWriteStyle(font1->GetStyle());
|
QFont::Style style = fromDirectWriteStyle(font2->GetStyle());
|
||||||
QFont::Weight weight = fromDirectWriteWeight(font1->GetWeight());
|
QFont::Weight weight = fromDirectWriteWeight(font2->GetWeight());
|
||||||
bool fixed = font1->IsMonospacedFont();
|
bool fixed = font2->IsMonospacedFont();
|
||||||
|
bool color = font2->IsColorFont();
|
||||||
|
|
||||||
qCDebug(lcQpaFonts) << "Family" << familyName << "has english variant" << englishLocaleStyleName << ", in default locale:" << defaultLocaleStyleName << stretch << style << weight << fixed;
|
qCDebug(lcQpaFonts) << "Family" << familyName << "has english variant" << englishLocaleStyleName << ", in default locale:" << defaultLocaleStyleName << stretch << style << weight << fixed;
|
||||||
|
|
||||||
@ -190,6 +191,7 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
|
|||||||
scalable,
|
scalable,
|
||||||
size,
|
size,
|
||||||
fixed,
|
fixed,
|
||||||
|
color,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(*face, englishLocaleFamilyName));
|
new FontHandle(*face, englishLocaleFamilyName));
|
||||||
}
|
}
|
||||||
@ -205,6 +207,7 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
|
|||||||
scalable,
|
scalable,
|
||||||
size,
|
size,
|
||||||
fixed,
|
fixed,
|
||||||
|
color,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(*face, defaultLocaleFamilyName));
|
new FontHandle(*face, defaultLocaleFamilyName));
|
||||||
}
|
}
|
||||||
@ -290,18 +293,20 @@ bool QWindowsDirectWriteFontDatabase::populateFamilyAliases(const QString &missi
|
|||||||
DirectWriteScope<IDWriteFont> font;
|
DirectWriteScope<IDWriteFont> font;
|
||||||
if (SUCCEEDED(fontCollection->GetFontFromFontFace(*directWriteFontFace, &font))) {
|
if (SUCCEEDED(fontCollection->GetFontFromFontFace(*directWriteFontFace, &font))) {
|
||||||
|
|
||||||
DirectWriteScope<IDWriteFont1> font1;
|
DirectWriteScope<IDWriteFont2> font2;
|
||||||
if (SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont1),
|
if (SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont2),
|
||||||
reinterpret_cast<void **>(&font1)))) {
|
reinterpret_cast<void **>(&font2)))) {
|
||||||
DirectWriteScope<IDWriteLocalizedStrings> names;
|
DirectWriteScope<IDWriteLocalizedStrings> names;
|
||||||
if (SUCCEEDED(font1->GetFaceNames(&names))) {
|
if (SUCCEEDED(font2->GetFaceNames(&names))) {
|
||||||
wchar_t englishLocale[] = L"en-us";
|
wchar_t englishLocale[] = L"en-us";
|
||||||
QString englishLocaleStyleName = localeString(*names, englishLocale);
|
QString englishLocaleStyleName = localeString(*names, englishLocale);
|
||||||
|
|
||||||
QFont::Stretch stretch = fromDirectWriteStretch(font1->GetStretch());
|
QFont::Stretch stretch = fromDirectWriteStretch(font2->GetStretch());
|
||||||
QFont::Style style = fromDirectWriteStyle(font1->GetStyle());
|
QFont::Style style = fromDirectWriteStyle(font2->GetStyle());
|
||||||
QFont::Weight weight = fromDirectWriteWeight(font1->GetWeight());
|
QFont::Weight weight = fromDirectWriteWeight(font2->GetWeight());
|
||||||
bool fixed = font1->IsMonospacedFont();
|
bool fixed = font2->IsMonospacedFont();
|
||||||
|
bool isColorFont = font2->IsColorFont();
|
||||||
|
|
||||||
|
|
||||||
QSupportedWritingSystems writingSystems = supportedWritingSystems(*directWriteFontFace);
|
QSupportedWritingSystems writingSystems = supportedWritingSystems(*directWriteFontFace);
|
||||||
|
|
||||||
@ -316,6 +321,7 @@ bool QWindowsDirectWriteFontDatabase::populateFamilyAliases(const QString &missi
|
|||||||
true,
|
true,
|
||||||
0xffff,
|
0xffff,
|
||||||
fixed,
|
fixed,
|
||||||
|
isColorFont,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(*directWriteFontFace, missingFamily));
|
new FontHandle(*directWriteFontFace, missingFamily));
|
||||||
|
|
||||||
@ -407,9 +413,13 @@ QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(const QFontDef &fontDef
|
|||||||
return fontEngine;
|
return fontEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList QWindowsDirectWriteFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
QStringList QWindowsDirectWriteFontDatabase::fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) const
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
result.append(QWindowsFontDatabaseBase::familiesForScript(script));
|
||||||
result.append(familyForStyleHint(styleHint));
|
result.append(familyForStyleHint(styleHint));
|
||||||
result.append(extraTryFontsForFamily(family));
|
result.append(extraTryFontsForFamily(family));
|
||||||
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||||
@ -516,6 +526,7 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray
|
|||||||
QFont::Style style = fromDirectWriteStyle(face3->GetStyle());
|
QFont::Style style = fromDirectWriteStyle(face3->GetStyle());
|
||||||
QFont::Weight weight = fromDirectWriteWeight(face3->GetWeight());
|
QFont::Weight weight = fromDirectWriteWeight(face3->GetWeight());
|
||||||
bool fixed = face3->IsMonospacedFont();
|
bool fixed = face3->IsMonospacedFont();
|
||||||
|
bool color = face3->IsColorFont();
|
||||||
|
|
||||||
qCDebug(lcQpaFonts) << "\tFont names:" << englishLocaleFamilyName << ", " << defaultLocaleFamilyName
|
qCDebug(lcQpaFonts) << "\tFont names:" << englishLocaleFamilyName << ", " << defaultLocaleFamilyName
|
||||||
<< ", style names:" << englishLocaleStyleName << ", " << defaultLocaleStyleName
|
<< ", style names:" << englishLocaleStyleName << ", " << defaultLocaleStyleName
|
||||||
@ -545,6 +556,7 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray
|
|||||||
scalable,
|
scalable,
|
||||||
size,
|
size,
|
||||||
fixed,
|
fixed,
|
||||||
|
color,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(face, englishLocaleFamilyName));
|
new FontHandle(face, englishLocaleFamilyName));
|
||||||
}
|
}
|
||||||
@ -570,6 +582,7 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray
|
|||||||
scalable,
|
scalable,
|
||||||
size,
|
size,
|
||||||
fixed,
|
fixed,
|
||||||
|
color,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(face, defaultLocaleFamilyName));
|
new FontHandle(face, defaultLocaleFamilyName));
|
||||||
}
|
}
|
||||||
@ -595,6 +608,7 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray
|
|||||||
scalable,
|
scalable,
|
||||||
size,
|
size,
|
||||||
fixed,
|
fixed,
|
||||||
|
color,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(face, englishLocaleGdiCompatibleFamilyName));
|
new FontHandle(face, englishLocaleGdiCompatibleFamilyName));
|
||||||
}
|
}
|
||||||
@ -620,6 +634,7 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray
|
|||||||
scalable,
|
scalable,
|
||||||
size,
|
size,
|
||||||
fixed,
|
fixed,
|
||||||
|
color,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(face, defaultLocaleGdiCompatibleFamilyName));
|
new FontHandle(face, defaultLocaleGdiCompatibleFamilyName));
|
||||||
}
|
}
|
||||||
@ -645,6 +660,7 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray
|
|||||||
scalable,
|
scalable,
|
||||||
size,
|
size,
|
||||||
fixed,
|
fixed,
|
||||||
|
color,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(face, englishLocaleTypographicFamilyName));
|
new FontHandle(face, englishLocaleTypographicFamilyName));
|
||||||
}
|
}
|
||||||
@ -670,6 +686,7 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray
|
|||||||
scalable,
|
scalable,
|
||||||
size,
|
size,
|
||||||
fixed,
|
fixed,
|
||||||
|
color,
|
||||||
writingSystems,
|
writingSystems,
|
||||||
new FontHandle(face, defaultLocaleTypographicFamilyName));
|
new FontHandle(face, defaultLocaleTypographicFamilyName));
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,10 @@ public:
|
|||||||
bool populateFamilyAliases(const QString &missingFamily) override;
|
bool populateFamilyAliases(const QString &missingFamily) override;
|
||||||
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
|
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
|
||||||
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
|
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
|
||||||
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override;
|
QStringList fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) const override;
|
||||||
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *font = nullptr) override;
|
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *font = nullptr) override;
|
||||||
|
|
||||||
bool isPrivateFontFamily(const QString &family) const override;
|
bool isPrivateFontFamily(const QString &family) const override;
|
||||||
|
@ -541,19 +541,19 @@ static bool addFontToDatabase(QString familyName,
|
|||||||
|
|
||||||
const bool wasPopulated = QPlatformFontDatabase::isFamilyPopulated(familyName);
|
const bool wasPopulated = QPlatformFontDatabase::isFamilyPopulated(familyName);
|
||||||
QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight,
|
QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight,
|
||||||
style, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
style, stretch, antialias, scalable, size, fixed, false, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
||||||
|
|
||||||
|
|
||||||
// add fonts windows can generate for us:
|
// add fonts windows can generate for us:
|
||||||
if (weight <= QFont::DemiBold && styleName.isEmpty())
|
if (weight <= QFont::DemiBold && styleName.isEmpty())
|
||||||
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
|
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
|
||||||
style, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
style, stretch, antialias, scalable, size, fixed, false, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
||||||
if (style != QFont::StyleItalic && styleName.isEmpty())
|
if (style != QFont::StyleItalic && styleName.isEmpty())
|
||||||
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight,
|
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight,
|
||||||
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, false, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
||||||
if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
|
if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
|
||||||
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
|
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
|
||||||
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
QFont::StyleItalic, stretch, antialias, scalable, size, fixed, false, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
||||||
|
|
||||||
// We came here from populating a different font family, so we have
|
// We came here from populating a different font family, so we have
|
||||||
// to ensure the entire typographic family is populated before we
|
// to ensure the entire typographic family is populated before we
|
||||||
@ -567,7 +567,7 @@ static bool addFontToDatabase(QString familyName,
|
|||||||
|
|
||||||
if (!subFamilyName.isEmpty() && familyName != subFamilyName) {
|
if (!subFamilyName.isEmpty() && familyName != subFamilyName) {
|
||||||
QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight,
|
QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight,
|
||||||
style, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
style, stretch, antialias, scalable, size, fixed, false, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!englishName.isEmpty() && englishName != familyName)
|
if (!englishName.isEmpty() && englishName != familyName)
|
||||||
@ -1162,9 +1162,13 @@ void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont)
|
|||||||
++it->refCount;
|
++it->refCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) const
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
result.append(QWindowsFontDatabaseBase::familiesForScript(script));
|
||||||
result.append(familyForStyleHint(styleHint));
|
result.append(familyForStyleHint(styleHint));
|
||||||
result.append(m_eudcFonts);
|
result.append(m_eudcFonts);
|
||||||
result.append(extraTryFontsForFamily(family));
|
result.append(extraTryFontsForFamily(family));
|
||||||
|
@ -243,24 +243,24 @@ static bool addFontToDatabase(QString familyName,
|
|||||||
value.prepend(QFile::decodeName(qgetenv("windir") + "\\Fonts\\"));
|
value.prepend(QFile::decodeName(qgetenv("windir") + "\\Fonts\\"));
|
||||||
|
|
||||||
QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch,
|
QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch,
|
||||||
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
|
antialias, scalable, size, fixed, false, writingSystems, createFontFile(value, index));
|
||||||
|
|
||||||
// add fonts windows can generate for us:
|
// add fonts windows can generate for us:
|
||||||
if (weight <= QFont::DemiBold && styleName.isEmpty())
|
if (weight <= QFont::DemiBold && styleName.isEmpty())
|
||||||
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, style, stretch,
|
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, style, stretch,
|
||||||
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
|
antialias, scalable, size, fixed, false, writingSystems, createFontFile(value, index));
|
||||||
|
|
||||||
if (style != QFont::StyleItalic && styleName.isEmpty())
|
if (style != QFont::StyleItalic && styleName.isEmpty())
|
||||||
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight, QFont::StyleItalic, stretch,
|
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight, QFont::StyleItalic, stretch,
|
||||||
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
|
antialias, scalable, size, fixed, false, writingSystems, createFontFile(value, index));
|
||||||
|
|
||||||
if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
|
if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
|
||||||
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, QFont::StyleItalic, stretch,
|
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, QFont::StyleItalic, stretch,
|
||||||
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
|
antialias, scalable, size, fixed, false, writingSystems, createFontFile(value, index));
|
||||||
|
|
||||||
if (!subFamilyName.isEmpty() && familyName != subFamilyName) {
|
if (!subFamilyName.isEmpty() && familyName != subFamilyName) {
|
||||||
QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight,
|
QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight,
|
||||||
style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
|
style, stretch, antialias, scalable, size, fixed, false, writingSystems, createFontFile(value, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!englishName.isEmpty() && englishName != familyName)
|
if (!englishName.isEmpty() && englishName != familyName)
|
||||||
@ -397,9 +397,13 @@ QFontEngine *QWindowsFontDatabaseFT::fontEngine(const QByteArray &fontData, qrea
|
|||||||
return fe;
|
return fe;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family,
|
||||||
|
QFont::Style style,
|
||||||
|
QFont::StyleHint styleHint,
|
||||||
|
QFontDatabasePrivate::ExtendedScript script) const
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
result.append(QWindowsFontDatabaseBase::familiesForScript(script));
|
||||||
result.append(QWindowsFontDatabaseBase::familyForStyleHint(styleHint));
|
result.append(QWindowsFontDatabaseBase::familyForStyleHint(styleHint));
|
||||||
result.append(QWindowsFontDatabaseBase::extraTryFontsForFamily(family));
|
result.append(QWindowsFontDatabaseBase::extraTryFontsForFamily(family));
|
||||||
result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
|
|
||||||
QStringList fallbacksForFamily(const QString &family, QFont::Style style,
|
QStringList fallbacksForFamily(const QString &family, QFont::Style style,
|
||||||
QFont::StyleHint styleHint,
|
QFont::StyleHint styleHint,
|
||||||
QChar::Script script) const override;
|
QFontDatabasePrivate::ExtendedScript script) const override;
|
||||||
|
|
||||||
QString fontDir() const override;
|
QString fontDir() const override;
|
||||||
QFont defaultFont() const override;
|
QFont defaultFont() const override;
|
||||||
|
@ -51,7 +51,7 @@ public:
|
|||||||
bool populateFamilyAliases(const QString &missingFamily) override;
|
bool populateFamilyAliases(const QString &missingFamily) override;
|
||||||
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
|
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
|
||||||
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
|
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
|
||||||
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override;
|
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QFontDatabasePrivate::ExtendedScript script) const override;
|
||||||
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) override;
|
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) override;
|
||||||
void releaseHandle(void *handle) override;
|
void releaseHandle(void *handle) override;
|
||||||
QString fontDir() const override;
|
QString fontDir() const override;
|
||||||
|
@ -873,6 +873,14 @@ QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qr
|
|||||||
return fontEngine;
|
return fontEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList QWindowsFontDatabaseBase::familiesForScript(QFontDatabasePrivate::ExtendedScript script)
|
||||||
|
{
|
||||||
|
if (script == QFontDatabasePrivate::Script_Emoji)
|
||||||
|
return QStringList{} << QStringLiteral("Segoe UI Emoji");
|
||||||
|
else
|
||||||
|
return QStringList{};
|
||||||
|
}
|
||||||
|
|
||||||
QString QWindowsFontDatabaseBase::familyForStyleHint(QFont::StyleHint styleHint)
|
QString QWindowsFontDatabaseBase::familyForStyleHint(QFont::StyleHint styleHint)
|
||||||
{
|
{
|
||||||
switch (styleHint) {
|
switch (styleHint) {
|
||||||
|
@ -75,6 +75,7 @@ public:
|
|||||||
|
|
||||||
static QString familyForStyleHint(QFont::StyleHint styleHint);
|
static QString familyForStyleHint(QFont::StyleHint styleHint);
|
||||||
static QStringList extraTryFontsForFamily(const QString &family);
|
static QStringList extraTryFontsForFamily(const QString &family);
|
||||||
|
static QStringList familiesForScript(QFontDatabasePrivate::ExtendedScript script);
|
||||||
|
|
||||||
class FontTable{};
|
class FontTable{};
|
||||||
class EmbeddedFont
|
class EmbeddedFont
|
||||||
|
@ -45,10 +45,15 @@ void QAndroidPlatformFontDatabase::populateFontDatabase()
|
|||||||
QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &family,
|
QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &family,
|
||||||
QFont::Style style,
|
QFont::Style style,
|
||||||
QFont::StyleHint styleHint,
|
QFont::StyleHint styleHint,
|
||||||
QChar::Script script) const
|
QFontDatabasePrivate::ExtendedScript script) const
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
|
||||||
|
if (script == QFontDatabasePrivate::Script_Emoji) {
|
||||||
|
result.append(QStringLiteral("Noto Color Emoji"));
|
||||||
|
result.append(QStringLiteral("Noto Color Emoji Flags"));
|
||||||
|
}
|
||||||
|
|
||||||
// Prepend CJK fonts by the locale.
|
// Prepend CJK fonts by the locale.
|
||||||
QLocale locale = QLocale::system();
|
QLocale locale = QLocale::system();
|
||||||
switch (locale.language()) {
|
switch (locale.language()) {
|
||||||
|
@ -17,7 +17,7 @@ public:
|
|||||||
QStringList fallbacksForFamily(const QString &family,
|
QStringList fallbacksForFamily(const QString &family,
|
||||||
QFont::Style style,
|
QFont::Style style,
|
||||||
QFont::StyleHint styleHint,
|
QFont::StyleHint styleHint,
|
||||||
QChar::Script script) const override;
|
QFontDatabasePrivate::ExtendedScript script) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -319,7 +319,7 @@ QFontEngine *QWasmFontDatabase::fontEngine(const QFontDef &fontDef, void *handle
|
|||||||
|
|
||||||
QStringList QWasmFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style,
|
QStringList QWasmFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style,
|
||||||
QFont::StyleHint styleHint,
|
QFont::StyleHint styleHint,
|
||||||
QChar::Script script) const
|
QFontDatabasePrivate::ExtendedScript script) const
|
||||||
{
|
{
|
||||||
QStringList fallbacks
|
QStringList fallbacks
|
||||||
= QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script);
|
= QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script);
|
||||||
|
@ -20,7 +20,7 @@ public:
|
|||||||
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
|
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
|
||||||
QStringList fallbacksForFamily(const QString &family, QFont::Style style,
|
QStringList fallbacksForFamily(const QString &family, QFont::Style style,
|
||||||
QFont::StyleHint styleHint,
|
QFont::StyleHint styleHint,
|
||||||
QChar::Script script) const override;
|
QFontDatabasePrivate::ExtendedScript script) const override;
|
||||||
void releaseHandle(void *handle) override;
|
void releaseHandle(void *handle) override;
|
||||||
QFont defaultFont() const override;
|
QFont defaultFont() const override;
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ set(testdata_resource_files
|
|||||||
"LED_REAL.TTF"
|
"LED_REAL.TTF"
|
||||||
"QtTestLimitedFont-Regular.ttf"
|
"QtTestLimitedFont-Regular.ttf"
|
||||||
"QtTestFallbackFont-Regular.ttf"
|
"QtTestFallbackFont-Regular.ttf"
|
||||||
|
"QtEmojiTestFont-Regular.ttf"
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_add_resource(tst_qfontdatabase "testdata"
|
qt_internal_add_resource(tst_qfontdatabase "testdata"
|
||||||
|
BIN
tests/auto/gui/text/qfontdatabase/QtEmojiTestFont-Regular.ttf
Normal file
BIN
tests/auto/gui/text/qfontdatabase/QtEmojiTestFont-Regular.ttf
Normal file
Binary file not shown.
@ -71,6 +71,7 @@ private slots:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void addApplicationFontFallback();
|
void addApplicationFontFallback();
|
||||||
|
void addApplicationEmojiFontFamily();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_ledFont;
|
QString m_ledFont;
|
||||||
@ -80,6 +81,7 @@ private:
|
|||||||
QString m_testFontVariable;
|
QString m_testFontVariable;
|
||||||
QString m_limitedFont;
|
QString m_limitedFont;
|
||||||
QString m_fallbackFont;
|
QString m_fallbackFont;
|
||||||
|
QString m_emojiFont;
|
||||||
};
|
};
|
||||||
|
|
||||||
tst_QFontDatabase::tst_QFontDatabase()
|
tst_QFontDatabase::tst_QFontDatabase()
|
||||||
@ -95,6 +97,7 @@ void tst_QFontDatabase::initTestCase()
|
|||||||
m_testFontVariable = QFINDTESTDATA("testfont_variable.ttf");
|
m_testFontVariable = QFINDTESTDATA("testfont_variable.ttf");
|
||||||
m_limitedFont = QFINDTESTDATA("QtTestLimitedFont-Regular.ttf");
|
m_limitedFont = QFINDTESTDATA("QtTestLimitedFont-Regular.ttf");
|
||||||
m_fallbackFont = QFINDTESTDATA("QtTestFallbackFont-Regular.ttf");
|
m_fallbackFont = QFINDTESTDATA("QtTestFallbackFont-Regular.ttf");
|
||||||
|
m_emojiFont = QFINDTESTDATA("QtEmojiTestFont-Regular.ttf");
|
||||||
QVERIFY(!m_ledFont.isEmpty());
|
QVERIFY(!m_ledFont.isEmpty());
|
||||||
QVERIFY(!m_testFont.isEmpty());
|
QVERIFY(!m_testFont.isEmpty());
|
||||||
QVERIFY(!m_testFontCondensed.isEmpty());
|
QVERIFY(!m_testFontCondensed.isEmpty());
|
||||||
@ -102,6 +105,7 @@ void tst_QFontDatabase::initTestCase()
|
|||||||
QVERIFY(!m_testFontVariable.isEmpty());
|
QVERIFY(!m_testFontVariable.isEmpty());
|
||||||
QVERIFY(!m_limitedFont.isEmpty());
|
QVERIFY(!m_limitedFont.isEmpty());
|
||||||
QVERIFY(!m_fallbackFont.isEmpty());
|
QVERIFY(!m_fallbackFont.isEmpty());
|
||||||
|
QVERIFY(!m_emojiFont.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QFontDatabase::styles_data()
|
void tst_QFontDatabase::styles_data()
|
||||||
@ -763,5 +767,65 @@ void tst_QFontDatabase::addApplicationFontFallback()
|
|||||||
QVERIFY(QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script_Latin, u"QtTestFallbackFont"_s));
|
QVERIFY(QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script_Latin, u"QtTestFallbackFont"_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QFontDatabase::addApplicationEmojiFontFamily()
|
||||||
|
{
|
||||||
|
int id = -1;
|
||||||
|
auto cleanup = qScopeGuard([&id] {
|
||||||
|
if (id >= 0)
|
||||||
|
QFontDatabase::removeApplicationFont(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
id = QFontDatabase::addApplicationFont(m_emojiFont);
|
||||||
|
QVERIFY(id >= 0);
|
||||||
|
|
||||||
|
QStringList families = QFontDatabase::applicationFontFamilies(id);
|
||||||
|
QVERIFY(families.size() > 0);
|
||||||
|
|
||||||
|
const QChar airplane(0x2708);
|
||||||
|
const QChar vs16(0xfe0f);
|
||||||
|
|
||||||
|
QFontDatabase::addApplicationEmojiFontFamily(families.first());
|
||||||
|
|
||||||
|
// Get emoji version of regular airplane symbol
|
||||||
|
{
|
||||||
|
QTextLayout layout;
|
||||||
|
layout.setText(QString(airplane) + vs16);
|
||||||
|
layout.beginLayout();
|
||||||
|
layout.createLine();
|
||||||
|
layout.endLayout();
|
||||||
|
|
||||||
|
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
|
||||||
|
QCOMPARE(glyphRuns.size(), 1);
|
||||||
|
|
||||||
|
QGlyphRun glyphRun = glyphRuns.first();
|
||||||
|
QList<quint32> glyphIndexes = glyphRun.glyphIndexes();
|
||||||
|
|
||||||
|
QCOMPARE(glyphIndexes.size(), 1);
|
||||||
|
QCOMPARE(glyphIndexes.at(0), 237);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QChar asterisk('*');
|
||||||
|
const QChar enclosingKeyCap(0x20e3);
|
||||||
|
|
||||||
|
// Get emoji keycap ligature (vs16 should be ignored when evaluating ligature substitution)
|
||||||
|
{
|
||||||
|
QTextLayout layout;
|
||||||
|
layout.setText(QString(asterisk) + vs16 + enclosingKeyCap);
|
||||||
|
layout.beginLayout();
|
||||||
|
layout.createLine();
|
||||||
|
layout.endLayout();
|
||||||
|
|
||||||
|
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
|
||||||
|
QCOMPARE(glyphRuns.size(), 1);
|
||||||
|
|
||||||
|
QGlyphRun glyphRun = glyphRuns.first();
|
||||||
|
QList<quint32> glyphIndexes = glyphRun.glyphIndexes();
|
||||||
|
|
||||||
|
QCOMPARE(glyphIndexes.size(), 1);
|
||||||
|
QCOMPARE(glyphIndexes.at(0), 238);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QFontDatabase)
|
QTEST_MAIN(tst_QFontDatabase)
|
||||||
#include "tst_qfontdatabase.moc"
|
#include "tst_qfontdatabase.moc"
|
||||||
|
34
tests/manual/emojisequences/CMakeLists.txt
Normal file
34
tests/manual/emojisequences/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
project(emojisequences LANGUAGES CXX)
|
||||||
|
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||||
|
find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
|
||||||
|
|
||||||
|
qt_standard_project_setup()
|
||||||
|
|
||||||
|
qt_internal_add_manual_test(emojisequences
|
||||||
|
GUI
|
||||||
|
SOURCES
|
||||||
|
main.cpp
|
||||||
|
mainwindow.h mainwindow.cpp
|
||||||
|
mainwindow.ui
|
||||||
|
LIBRARIES
|
||||||
|
Qt::Gui
|
||||||
|
Qt::Widgets
|
||||||
|
ENABLE_AUTOGEN_TOOLS
|
||||||
|
uic
|
||||||
|
)
|
||||||
|
|
||||||
|
set(emojisequences_resource_files
|
||||||
|
"emoji-test.txt"
|
||||||
|
)
|
||||||
|
|
||||||
|
qt_internal_add_resource(emojisequences "emojisequences"
|
||||||
|
PREFIX
|
||||||
|
"/"
|
||||||
|
FILES
|
||||||
|
${emojisequences_resource_files}
|
||||||
|
)
|
3768
tests/manual/emojisequences/emoji-test.txt
Normal file
3768
tests/manual/emojisequences/emoji-test.txt
Normal file
File diff suppressed because it is too large
Load Diff
18
tests/manual/emojisequences/main.cpp
Normal file
18
tests/manual/emojisequences/main.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QtWidgets>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
|
MainWindow w;
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
|
|
95
tests/manual/emojisequences/mainwindow.cpp
Normal file
95
tests/manual/emojisequences/mainwindow.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QtWidgets>
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
|
: QMainWindow(parent)
|
||||||
|
, ui(new Ui::MainWindow)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
connect(ui->toolButton, &QToolButton::clicked, this, &MainWindow::loadCustomFont);
|
||||||
|
|
||||||
|
populateEmojiTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::populateEmojiTest()
|
||||||
|
{
|
||||||
|
QFile file(":/emoji-test.txt");
|
||||||
|
|
||||||
|
ui->tableWidget->clear();
|
||||||
|
ui->tableWidget->setColumnCount(8);
|
||||||
|
|
||||||
|
QList<QPair<QString, QString> > strings;
|
||||||
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
|
while (!file.atEnd()) {
|
||||||
|
QString l = file.readLine();
|
||||||
|
|
||||||
|
QStringList toolTip;
|
||||||
|
QString testString;
|
||||||
|
QStringList tokens = l.split(QLatin1Char(' '), Qt::SkipEmptyParts);
|
||||||
|
for (int i = 0; i < tokens.size(); ++i) {
|
||||||
|
if (tokens.at(i) == QLatin1Char(';'))
|
||||||
|
break;
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
char32_t ucs4 = tokens.at(i).toUInt(&ok, 16);
|
||||||
|
if (!ok)
|
||||||
|
break;
|
||||||
|
|
||||||
|
testString += QString::fromUcs4(&ucs4, 1);
|
||||||
|
toolTip << QString::number(ucs4, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!toolTip.isEmpty()) {
|
||||||
|
strings.append(qMakePair(testString, toolTip.join(',')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->tableWidget->setRowCount(strings.count() / 8);
|
||||||
|
for (int i = 0; i < strings.count(); ++i) {
|
||||||
|
int row = i / 8;
|
||||||
|
int column = i % 8;
|
||||||
|
QString testString = strings.at(i).first;
|
||||||
|
QString toolTip = strings.at(i).second;
|
||||||
|
|
||||||
|
QTableWidgetItem *it = new QTableWidgetItem(testString);
|
||||||
|
ui->tableWidget->setItem(row, column, it);
|
||||||
|
it->setText(testString);
|
||||||
|
it->setToolTip(toolTip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::loadCustomFont()
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||||
|
ui->tableWidget->clear();
|
||||||
|
QFontDatabase::removeAllApplicationFonts();
|
||||||
|
|
||||||
|
QString fileName = QFileDialog::getOpenFileName(this, tr("Open font file"), QString(), tr("Fonts (*.ttf *.otf);All files (*)"));
|
||||||
|
if (!fileName.isEmpty()) {
|
||||||
|
int id = QFontDatabase::addApplicationFont(fileName);
|
||||||
|
if (id >= 0) {
|
||||||
|
QStringList families = QFontDatabase::applicationFontFamilies(id);
|
||||||
|
QString family = families.size() > 0 ? families.first() : QString();
|
||||||
|
if (!family.isEmpty()) {
|
||||||
|
QFontDatabase::setApplicationEmojiFontFamilies(QStringList() << family);
|
||||||
|
populateEmojiTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
31
tests/manual/emojisequences/mainwindow.h
Normal file
31
tests/manual/emojisequences/mainwindow.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void loadCustomFont();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void populateEmojiTest();
|
||||||
|
|
||||||
|
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINWINDOW_H
|
50
tests/manual/emojisequences/mainwindow.ui
Normal file
50
tests/manual/emojisequences/mainwindow.ui
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1245</width>
|
||||||
|
<height>972</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="tableWidget">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>20</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="toolButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Load custom font...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1245</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
x
Reference in New Issue
Block a user