Qt5: support for variable fonts (#11621)

* Qt5: support for variable fonts

* qthaikuplugins: bump version
This commit is contained in:
Máximo Castañeda
2025-04-26 21:34:39 +02:00
committed by GitHub
parent 28a4457746
commit 88df714922
3 changed files with 659 additions and 24 deletions

View File

@@ -1,4 +1,4 @@
From 162eebac0d16049549b138401c9ba2a76bf3dd79 Mon Sep 17 00:00:00 2001
From 7e6551df2576d0ad18d4dffee19c14eca4c80f77 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= <revol@free.fr>
Date: Mon, 11 Feb 2019 15:53:49 +1000
Subject: Make sure libs are searched in the develop/ dir by CMake
@@ -23,7 +23,7 @@ index 64639f1..42ad698 100644
2.45.2
From 83f98bb3eeb34cca31d33a971dd3c5d8660c8481 Mon Sep 17 00:00:00 2001
From 050fd9d8f0b42a1bbea702aba4eb9c6a9ce86733 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Mon, 11 Feb 2019 15:55:08 +1000
Subject: Disable built-in haiku QPA plugin
@@ -48,7 +48,7 @@ index 23f838a..8ef1812 100644
2.45.2
From fae20ebc004c913a5a99411715b89acffbab748a Mon Sep 17 00:00:00 2001
From ed94085d15b55d33760d439b8ce37f72fe588461 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Mon, 11 Feb 2019 15:56:12 +1000
Subject: Fix QStandartPaths for Haiku
@@ -111,7 +111,7 @@ index 044d69f..1f255a9 100644
2.45.2
From eef708ff70cf863c17938ab0c034fa4ea4b4410f Mon Sep 17 00:00:00 2001
From 23ef7e631daeca831cd42b60a830fa063a5c2609 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Mon, 11 Feb 2019 15:56:39 +1000
Subject: QSslSocketPrivate::unixRootCertDirectories(): add ssl path for Haiku.
@@ -133,14 +133,14 @@ index 2a0b3a4..e0a1d6f 100644
2.45.2
From 56a4693f5855f2967256c8246e492c63dc7329c2 Mon Sep 17 00:00:00 2001
From f90f3c207147152ea4421c7f2368f97b7ab059f2 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Mon, 11 Feb 2019 15:56:59 +1000
Subject: Fix build for Haiku platform
diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf
index 0c505fc..38fbe4f 100644
index c70f279..15e5ad5 100644
--- a/mkspecs/features/toolchain.prf
+++ b/mkspecs/features/toolchain.prf
@@ -263,7 +263,7 @@ isEmpty($${target_prefix}.INCDIRS) {
@@ -156,7 +156,7 @@ index 0c505fc..38fbe4f 100644
2.45.2
From caa7088f601f85ccf9657c6a4e76d18552cabff2 Mon Sep 17 00:00:00 2001
From 347cbf52d1f6b3f730b24a25693043c7be415b40 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Mon, 11 Feb 2019 15:57:54 +1000
Subject: Fix endian detection
@@ -183,7 +183,7 @@ index 9bb306e..9f0ea58 100644
2.45.2
From 42d5ca1bb1bf9a8ac6af68855f4b3e73b8306dac Mon Sep 17 00:00:00 2001
From a106f9e82c6675a326f17926affa5e98b730df86 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sat, 27 Apr 2019 17:47:23 +1000
Subject: Add dnslookup query function for Haiku
@@ -271,7 +271,7 @@ index 0000000..0b387df
2.45.2
From b12bf7f7635d6d19e5ab3c8702d5de8ad6e29a42 Mon Sep 17 00:00:00 2001
From d7412e7ed6c3fe5e7724a1318f1232d321826d26 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Wed, 27 May 2020 19:54:30 +1000
Subject: Disable LibResolv for Haiku
@@ -294,7 +294,7 @@ index 73679c9..73ce64c 100644
2.45.2
From a5369dfc5f06af29695bfceaec19d38688a40259 Mon Sep 17 00:00:00 2001
From fc735f0e89c28fb13e605345c78b8b3b9c0c183d Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sun, 8 Sep 2019 00:17:19 +1000
Subject: Don't use ifaddrs for Haiku
@@ -317,7 +317,7 @@ index e7889b6..1036ead 100644
2.45.2
From 263eb1866affb5d20dff84da8127678cc08887f7 Mon Sep 17 00:00:00 2001
From 53679486a79d43ecd5921c661463a25b2b26b86e Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sun, 8 Sep 2019 18:32:05 +1000
Subject: Add platform plugins installer
@@ -383,7 +383,7 @@ index c7ff2a6..4d83bdc 100644
2.45.2
From d29dcbdeff35fb4bbf7b4098dd974b5298799738 Mon Sep 17 00:00:00 2001
From 502881f3ee60c5d396a8ccb19b320553701a5bc0 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Wed, 27 May 2020 19:54:58 +1000
Subject: Disable sharedmemory feature for bootstrap
@@ -407,7 +407,7 @@ index 24862a0..0d6df52 100644
2.45.2
From 6f413c134e7cd49c37bedafaba19b275ff6c10b2 Mon Sep 17 00:00:00 2001
From cb38eeef587d95ca1ec83aeeacfcb4c363814e0b Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sun, 29 Dec 2019 18:13:19 +1000
Subject: Fix build for x86_gcc2
@@ -430,7 +430,7 @@ index b663b8a..5ad2b12 100644
2.45.2
From bf11f042898f8e98d74ace015d8f18859dbf0f2b Mon Sep 17 00:00:00 2001
From b1b25397ddd0322ca3b720d9180dc093f2503551 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Thu, 4 Jun 2020 23:11:17 +1000
Subject: Implement QFilesystemWatcher for Haiku
@@ -826,7 +826,7 @@ index 0000000..8a8d75a
2.45.2
From 3609bcacf7af5d7f0f15f9a29999b2188deb2865 Mon Sep 17 00:00:00 2001
From 2da1bcd3c3c8ae1d81c63982b27f61b021416664 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Tue, 16 Jun 2020 18:06:57 +1000
Subject: Don't use AF_INET6 for new sockets
@@ -853,7 +853,7 @@ index feb102b..07b65cc 100644
2.45.2
From 52ddd48661bf19773ebb1a43d9696cc32ca21c60 Mon Sep 17 00:00:00 2001
From fb28a35125704dde2f9d39baca82b48a36485b43 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Mon, 5 Oct 2020 19:40:40 +1000
Subject: Disable Haswell CPU feature for plugins
@@ -876,7 +876,7 @@ index 5cd21b6..2de224d 100644
2.45.2
From dfb96d82878f846fed5d90448122fe5a55fde6fc Mon Sep 17 00:00:00 2001
From 5ed247c0afbb169a6b372b02d1090e518b059bec Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sat, 9 Oct 2021 18:33:27 +1000
Subject: QSharedMemory implementation for Haiku
@@ -1166,7 +1166,7 @@ index 0c13375..172ca95 100644
2.45.2
From 17e4477201bf92163c76078a0f999eaf155872cd Mon Sep 17 00:00:00 2001
From 71e858b38a5fa2855e3a98ad467638bb957fd9d7 Mon Sep 17 00:00:00 2001
From: PulkoMandy <pulkomandy@pulkomandy.tk>
Date: Sat, 10 Aug 2024 17:05:17 +0200
Subject: Fix build on Haiku R1/beta5
@@ -1203,7 +1203,7 @@ index 0159636..7ca58a4 100644
2.45.2
From 15e10a741f4254fa99ab6861edd3d3f627fce2a8 Mon Sep 17 00:00:00 2001
From fc67058ddb32f07b95e76fb84ade05e29173e6be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A1ximo=20Casta=C3=B1eda?= <antiswen@yahoo.es>
Date: Fri, 23 Aug 2024 20:30:08 +0200
Subject: SSL: try opening with OPENSSL_SHLIB_VERSION version number
@@ -1236,3 +1236,637 @@ index 6a9a3ef..6a24bfc 100644
--
2.45.2
From 5a9bcfd0481521a31ff298092d84da9dcdf5a534 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A1ximo=20Casta=C3=B1eda?= <antiswen@yahoo.es>
Date: Wed, 28 Aug 2024 19:05:51 +0200
Subject: Font db: improve support outside RBI space
Searching may use a previous font with a style name and change another
property. If we select on style name coincidence, we get the old one.
Using the style name just like any other property allows to use, say,
all different weights of Noto Sans in Calligra Words, instead of just
their projection on Regular/Bold/Italic space.
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 7aa6228..0b7f021 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -1060,12 +1060,6 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st
for ( int i = 0; i < foundry->count; i++ ) {
QtFontStyle *style = foundry->styles[i];
- if (!styleName.isEmpty() && styleName == style->styleName) {
- dist = 0;
- best = i;
- break;
- }
-
int d = qAbs( styleKey.weight - style->key.weight );
if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
@@ -1080,9 +1074,16 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st
d += 0x1000;
}
+ d *= 2;
+ if (!styleName.isEmpty() && styleName != style->styleName) {
+ d += 0x0001;
+ }
+
if ( d < dist ) {
best = i;
dist = d;
+ if ( d == 0 )
+ break;
}
}
--
2.45.2
From 1d2624892474544ebe8514b15e38cb14cfc15396 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A1ximo=20Casta=C3=B1eda?= <antiswen@yahoo.es>
Date: Thu, 3 Oct 2024 16:33:09 +0200
Subject: Font db: improve weight detection from style name
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 0b7f021..151c386 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -115,14 +115,22 @@ static int getFontWeight(const QString &weightString)
// Next up, let's see if contains() matches: slightly more expensive, but
// still fast enough.
if (s.contains(QLatin1String("bold"))) {
- if (s.contains(QLatin1String("demi")))
+ if (s.contains(QLatin1String("semibold")) || s.contains(QLatin1String("semi bold"))
+ || s.contains(QLatin1String("demibold")) || s.contains(QLatin1String("demi bold")))
return QFont::DemiBold;
+ if (s.contains(QLatin1String("extrabold")) || s.contains(QLatin1String("extra bold"))
+ || s.contains(QLatin1String("ultrabold")) || s.contains(QLatin1String("ultra bold")))
+ return QFont::ExtraBold;
return QFont::Bold;
}
if (s.contains(QLatin1String("thin")))
return QFont::Thin;
- if (s.contains(QLatin1String("light")))
+ if (s.contains(QLatin1String("light"))) {
+ if (s.contains(QLatin1String("extralight")) || s.contains(QLatin1String("extra light"))
+ || s.contains(QLatin1String("ultralight")) || s.contains(QLatin1String("ultra light")))
+ return QFont::ExtraLight;
return QFont::Light;
+ }
if (s.contains(QLatin1String("black")))
return QFont::Black;
--
2.45.2
From 06aed265773ab24fd7e9c5a6ff611c613833ea51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A1ximo=20Casta=C3=B1eda?= <antiswen@yahoo.es>
Date: Thu, 3 Oct 2024 16:40:13 +0200
Subject: Font db: include best style score in foundry's one
Instead of always assigning the same StyleMismatch penalty
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 151c386..ab87fb6 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -1060,15 +1060,15 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
}
static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey,
- const QString &styleName = QString())
+ const QString &styleName = QString(), unsigned int* score = nullptr)
{
int best = 0;
- int dist = 0xffff;
+ unsigned int dist = 0xffff;
for ( int i = 0; i < foundry->count; i++ ) {
QtFontStyle *style = foundry->styles[i];
- int d = qAbs( styleKey.weight - style->key.weight );
+ unsigned int d = qAbs( styleKey.weight - style->key.weight );
if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
d += qAbs( styleKey.stretch - style->key.stretch );
@@ -1079,7 +1079,7 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st
// one is italic, the other oblique
d += 0x0001;
else
- d += 0x1000;
+ d += 0x0100;
}
d *= 2;
@@ -1095,6 +1095,9 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st
}
}
+ if (score != nullptr)
+ *score = dist;
+
qCDebug(lcFontMatch, " best style has distance 0x%x", dist );
return foundry->styles[best];
}
@@ -1124,7 +1127,8 @@ unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
qCDebug(lcFontMatch, " looking for matching style in foundry '%s' %d",
foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
- QtFontStyle *style = bestStyle(foundry, styleKey, styleName);
+ unsigned int this_score = 0x0000;
+ QtFontStyle *style = bestStyle(foundry, styleKey, styleName, &this_score);
if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
qCDebug(lcFontMatch, " ForceOutline set, but not smoothly scalable");
@@ -1201,7 +1205,6 @@ unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
}
- unsigned int this_score = 0x0000;
enum {
PitchMismatch = 0x4000,
StyleMismatch = 0x2000,
@@ -1212,8 +1215,6 @@ unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
|| (pitch == 'p' && family->fixedPitch))
this_score += PitchMismatch;
}
- if (styleKey != style->key)
- this_score += StyleMismatch;
if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled
this_score += BitmapScaledPenalty;
if (px != pixelSize) // close, but not exact, size match
--
2.45.2
From 85910a62f15af32e9df0deb7e94da3b50b5cbf09 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A1ximo=20Casta=C3=B1eda?= <antiswen@yahoo.es>
Date: Thu, 3 Oct 2024 16:50:04 +0200
Subject: FT Font db: load named styles of variable fonts
As the system doesn't seem to consider anything out of the weight/slant
space, we are abusing the foundry property (empty at least for the
FreeType backend) to classify styles with other axis.
Width seems to need to be unstretched to correctly draw different width
variations, so that is also included in the fake foundry.
diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
index 56dcc61..0505da0 100644
--- a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
@@ -45,13 +45,18 @@
#include <QtCore/QFile>
#include <QtCore/QLibraryInfo>
#include <QtCore/QDir>
+#include <QtCore/QDataStream>
+#include <QtCore/QTextCodec>
#include <QtCore/QtEndian>
#undef QT_NO_FREETYPE
#include <QtFontDatabaseSupport/private/qfontengine_ft_p.h>
#include <ft2build.h>
+#include FT_TRUETYPE_IDS_H
#include FT_TRUETYPE_TABLES_H
+#include FT_MULTIPLE_MASTERS_H
+#include FT_SFNT_NAMES_H
#include FT_ERRORS_H
QT_BEGIN_NAMESPACE
@@ -111,6 +116,306 @@ void QFreeTypeFontDatabase::releaseHandle(void *handle)
extern FT_Library qt_getFreetype();
+static FT_Error loadFace(FT_Library library, const QByteArray &fontData, const QByteArray &file, int index, FT_Face *face)
+{
+ FT_Error error;
+
+ if (!fontData.isEmpty()) {
+ error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, face);
+ } else {
+ error = FT_New_Face(library, file.constData(), index, face);
+ }
+
+ if (error != FT_Err_Ok) {
+ qDebug() << "FT_New_Face failed with index" << index << ':' << Qt::hex << error;
+ }
+ return error;
+}
+
+static float fixedToFloat(FT_Fixed value)
+{
+ return value / (float) 0x10000;
+}
+
+static QString getSfntName(FT_Face face, FT_UInt id)
+{
+ FT_Byte* buffer;
+ FT_UInt length = 0;
+ FT_UInt count = FT_Get_Sfnt_Name_Count(face);
+
+ for (FT_UInt i = 0; i < count; i++) {
+ FT_SfntName name;
+
+ if (FT_Get_Sfnt_Name(face, i, &name) != FT_Err_Ok || name.name_id != id
+ || name.platform_id != TT_PLATFORM_MICROSOFT
+ || name.encoding_id != TT_MS_ID_UNICODE_CS)
+ continue;
+
+ if (length == 0 || name.language_id == TT_MS_LANGID_ENGLISH_UNITED_STATES) {
+ buffer = name.string;
+ length = name.string_len;
+ }
+
+ if (name.language_id == TT_MS_LANGID_ENGLISH_UNITED_STATES)
+ break;
+ }
+
+ if (length > 0) {
+ QTextCodec* decoder = QTextCodec::codecForName("UTF-16BE");
+ return decoder->toUnicode((char*)buffer, length);
+ }
+
+ return QString();
+}
+
+struct STAT_Header
+{
+ STAT_Header(const char* src)
+ {
+ QByteArray ba = QByteArray::fromRawData(src, sizeof(STAT_Header));
+ QDataStream ds(ba);
+ ds.setByteOrder(QDataStream::BigEndian);
+ ds >> majorVersion;
+ if (majorVersion != 1)
+ return;
+ ds
+ >> minorVersion
+ >> designAxisSize
+ >> designAxisCount
+ >> designAxesOffset
+ >> axisValueCount
+ >> axisValueOffsetsOffset;
+ if (minorVersion >= 1)
+ ds >> elidedFallbackNameID;
+ else
+ elidedFallbackNameID = 0xffff;
+ }
+
+ quint16 majorVersion;
+ quint16 minorVersion;
+ quint16 designAxisSize;
+ quint16 designAxisCount;
+ quint32 designAxesOffset;
+ quint16 axisValueCount;
+ quint32 axisValueOffsetsOffset;
+ quint16 elidedFallbackNameID;
+};
+
+struct STAT_Value
+{
+ STAT_Value(const char* src)
+ {
+ QByteArray ba = QByteArray::fromRawData(src, sizeof(STAT_Value));
+ QDataStream ds(ba);
+ ds.setByteOrder(QDataStream::BigEndian);
+ ds >> format;
+ if (format > 3)
+ return;
+ ds
+ >> index
+ >> flags
+ >> nameID
+ >> value;
+ if (format == 2) {
+ ds >> min >> max;
+ } else {
+ min = max = value;
+ }
+ }
+
+ quint16 format;
+ quint16 index;
+ quint16 flags;
+ quint16 nameID;
+ qint32 value;
+ qint32 min;
+ qint32 max;
+};
+
+class AxisData
+{
+
+ struct Span
+ {
+ qint32 min;
+ qint32 max;
+ QString name;
+ };
+
+ class Axis
+ {
+ public:
+ Axis() : tag(0) {};
+
+ void Insert(const STAT_Value& value, QString name)
+ {
+ if (value.format > 3)
+ return;
+
+ if (value.flags & 0x0002)
+ def = value.value;
+
+ Span current;
+ current.min = value.min;
+ current.max = value.max;
+ current.name = name;
+ span.push_back(current);
+ }
+
+ QString Name(FT_Fixed value)
+ {
+ if (tag != 'wdth' && (value == def || min == max))
+ return QString();
+
+
+ for (unsigned int i = 0; i < span.size(); i++) {
+ if (span[i].min <= value && span[i].max >= value)
+ return span[i].name;
+ }
+
+ float pct;
+ if (tag == 'wdth')
+ pct = fixedToFloat(value);
+ else
+ pct = 100 * (fixedToFloat(value) - min) / (max - min);
+ QString name = axisName + QLatin1String(": ")
+ + QString::number((int)pct)
+ + QLatin1String("%");
+ return name;
+ }
+
+ public:
+ QString axisName;
+ quint32 tag;
+ FT_Fixed def;
+ float min;
+ float max;
+ std::vector<Span> span;
+ };
+
+public:
+ AxisData(FT_Face face) : count(0), axis(nullptr), fake(false)
+ {
+ FT_MM_Var* mm;
+ if (FT_Get_MM_Var(face, &mm) != 0)
+ return;
+
+ count = mm->num_axis;
+ if (count == 0) {
+ FT_Done_MM_Var(qt_getFreetype(), mm);
+ return;
+ }
+ axis = new Axis[count];
+
+ for (FT_UInt i = 0; i < count; i++) {
+ FT_Var_Axis* mm_axis = mm->axis + i;
+ axis[i].tag = mm_axis->tag;
+ axis[i].def = mm_axis->def;
+ axis[i].min = fixedToFloat(mm_axis->minimum);
+ axis[i].max = fixedToFloat(mm_axis->maximum);
+ axis[i].axisName = getSfntName(face, mm_axis->strid);
+ if (mm_axis->tag != tagWeight
+ && mm_axis->tag != tagItalics && mm_axis->tag != tagSlant){
+ fake = true;
+ }
+ }
+
+ FT_Done_MM_Var(qt_getFreetype(), mm);
+
+ FT_ULong length = 0;
+ if (FT_Load_Sfnt_Table(face, 'STAT', 0, (FT_Byte*)NULL, &length) != FT_Err_Ok)
+ return;
+
+ char* buffer = (char*)malloc(length);
+ if (buffer == NULL)
+ return;
+ if (FT_Load_Sfnt_Table(face, 'STAT', 0, (FT_Byte*)buffer, &length) != FT_Err_Ok) {
+ free(buffer);
+ return;
+ }
+
+ STAT_Header header{buffer};
+ if (header.majorVersion != 1 || header.designAxisCount == 0 || header.axisValueCount == 0) {
+ free(buffer);
+ return;
+ }
+
+ unsigned int map[(unsigned int)header.designAxisCount];
+
+ for (unsigned int i = 0; i < header.designAxisCount; i++) {
+ quint32 tag = qFromBigEndian(*(quint32*)(buffer + header.designAxesOffset + i * header.designAxisSize));
+ unsigned int j;
+ for (j = 0; j < count; j++) {
+ if (axis[j].tag == tag) {
+ map[i] = j;
+ break;
+ }
+ }
+ }
+
+ quint16_be* offsets = (quint16_be*)(buffer + header.axisValueOffsetsOffset);
+ for (int i = 0; i < header.axisValueCount; i++) {
+ int offset = header.axisValueOffsetsOffset + offsets[i];
+ STAT_Value value{buffer + offset};
+ if (value.format > 3 || value.index >= count)
+ continue;
+ axis[map[value.index]].Insert(value, getSfntName(face, value.nameID));
+ }
+
+ regularName = getSfntName(face, header.elidedFallbackNameID);
+ if (regularName.isEmpty())
+ regularName = QString::fromLatin1("Regular");
+
+ free(buffer);
+ }
+
+ ~AxisData() {
+ delete[] axis;
+ }
+
+ QString Coordinates(FT_Face face, QFont::Weight& weight, QFont::Style& style) {
+ QString fakeFoundry;
+ if (count == 0)
+ return fakeFoundry;
+
+ FT_Fixed coords[count];
+ FT_Get_Var_Design_Coordinates(face, count, coords);
+ for (unsigned int i = 0; i < count; i++) {
+ if (axis[i].tag == tagWeight) {
+ weight = QPlatformFontDatabase::weightFromInteger(coords[i] >> 16);
+ } else if (axis[i].tag == tagItalics) {
+ if (coords[i] > 0x8000)
+ style = QFont::StyleItalic;
+ else
+ style = QFont::StyleNormal;
+ } else if (axis[i].tag == tagSlant) {
+ if (coords[i] == 0)
+ style = QFont::StyleNormal;
+ else
+ style = QFont::StyleOblique;
+ } else {
+ if (!fakeFoundry.isEmpty())
+ fakeFoundry += QChar::fromLatin1(' ');
+ fakeFoundry += axis[i].Name(coords[i]);
+ }
+ }
+
+ if (fake && fakeFoundry.isEmpty())
+ fakeFoundry = regularName;
+ return fakeFoundry;
+ }
+
+public:
+ static const int tagWeight = 'wght';
+ static const int tagItalics = 'ital';
+ static const int tagSlant = 'slnt';
+
+ unsigned int count;
+ Axis* axis;
+ bool fake;
+ QString regularName;
+};
+
QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file)
{
FT_Library library = qt_getFreetype();
@@ -118,19 +423,29 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
int index = 0;
int numFaces = 0;
QStringList families;
+
+ FT_Face face;
+ if (loadFace(library, fontData, file, -1, &face) != FT_Err_Ok) {
+ return families;
+ }
+ numFaces = face->num_faces;
+ FT_Done_Face(face);
+
do {
- FT_Face face;
- FT_Error error;
- if (!fontData.isEmpty()) {
- error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
- } else {
- error = FT_New_Face(library, file.constData(), index, &face);
- }
- if (error != FT_Err_Ok) {
- qDebug() << "FT_New_Face failed with index" << index << ':' << Qt::hex << error;
+ if (loadFace(library, fontData, file, index, &face) != FT_Err_Ok) {
+ break;
+ }
+
+ AxisData variableData(face);
+ int variableCount = (face->style_flags & 0x7fff0000) >> 16;
+ FT_Done_Face(face);
+
+ int namedStyle = variableCount == 0 ? 0 : 1;
+ do {
+ int faceIndex = index | (namedStyle << 16);
+ if (loadFace(library, fontData, file, faceIndex, &face) != FT_Err_Ok) {
break;
}
- numFaces = face->num_faces;
QFont::Weight weight = QFont::Normal;
@@ -153,7 +468,6 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
}
}
- QFont::Stretch stretch = QFont::Unstretched;
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
if (os2) {
quint32 unicodeRange[4] = {
@@ -192,50 +506,55 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
else if (w <= 10)
weight = QFont::Black;
}
+ }
+ QString family = QString::fromLatin1(face->family_name);
+ QString fakeFoundry;
+ if (namedStyle > 0) {
+ fakeFoundry = variableData.Coordinates(face, weight, style);
+ } else if (os2) {
switch (os2->usWidthClass) {
case 1:
- stretch = QFont::UltraCondensed;
+ fakeFoundry = QString::fromLatin1("UltraCondensed");
break;
case 2:
- stretch = QFont::ExtraCondensed;
+ fakeFoundry = QString::fromLatin1("ExtraCondensed");
break;
case 3:
- stretch = QFont::Condensed;
+ fakeFoundry = QString::fromLatin1("Condensed");
break;
case 4:
- stretch = QFont::SemiCondensed;
- break;
- case 5:
- stretch = QFont::Unstretched;
+ fakeFoundry = QString::fromLatin1("SemiCondensed");
break;
case 6:
- stretch = QFont::SemiExpanded;
+ fakeFoundry = QString::fromLatin1("SemiExpanded");
break;
case 7:
- stretch = QFont::Expanded;
+ fakeFoundry = QString::fromLatin1("Expanded");
break;
case 8:
- stretch = QFont::ExtraExpanded;
+ fakeFoundry = QString::fromLatin1("ExtraExpanded");
break;
case 9:
- stretch = QFont::UltraExpanded;
+ fakeFoundry = QString::fromLatin1("UltraExpanded");
break;
+ default:
+ fakeFoundry = QString::fromLatin1("Medium");
}
}
-
- QString family = QString::fromLatin1(face->family_name);
FontFile *fontFile = new FontFile;
fontFile->fileName = QFile::decodeName(file);
- fontFile->indexValue = index;
+ fontFile->indexValue = faceIndex;
- registerFont(family,QString::fromLatin1(face->style_name),QString(),weight,style,stretch,true,true,0,fixedPitch,writingSystems,fontFile);
+ registerFont(family,QString::fromLatin1(face->style_name),fakeFoundry,weight,style,QFont::Unstretched,true,true,0,fixedPitch,writingSystems,fontFile);
families.append(family);
FT_Done_Face(face);
- ++index;
+ ++namedStyle;
+ } while (namedStyle <= variableCount);
+ ++index;
} while (index < numFaces);
return families;
}
--
2.45.2

View File

@@ -8,7 +8,7 @@ COPYRIGHT="2015-2020 The Qt Company Ltd."
LICENSE="GNU LGPL v2.1
GNU LGPL v3
FDL"
REVISION="1"
REVISION="2"
#baseURL="https://download.qt.io/official_releases/qt/${portVersion%.*}/$portVersion/submodules"
baseURL="http://qt-mirror.dannhauer.de/official_releases/qt/${portVersion%.*}/$portVersion/submodules/"
SOURCE_URI="https://github.com/qt/qt5/archive/v$portVersion-lts-lgpl.tar.gz"

View File

@@ -11,10 +11,11 @@ HOMEPAGE="https://github.com/threedeyes/qthaikuplugins/"
COPYRIGHT="2017-2023 Gerasim Troeglazov"
LICENSE="GNU LGPL v2.1
GNU LGPL v3"
REVISION="2"
SOURCE_URI="$HOMEPAGE/archive/$portVersion.tar.gz"
CHECKSUM_SHA256="8392ad9b1995da8ac2bb2c74da759c7276cdf75d6ad324e5575f44edbc6a4bca"
SOURCE_DIR="qthaikuplugins-$portVersion"
REVISION="1"
srcGitRev=af09b4f18b74621601f5bf9b593be0dc12de892a
SOURCE_URI="$HOMEPAGE/archive/${srcGitRev}.tar.gz"
CHECKSUM_SHA256="896d39b703fa8ce71aee7f4776d453ac4a85cafa022e6a408a2e95d660baaa5b"
SOURCE_DIR="qthaikuplugins-${srcGitRev}"
ARCHITECTURES="all !x86_gcc2"
SECONDARY_ARCHITECTURES="x86"