Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qfreetypefontdatabase.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtGui/private/qguiapplication_p.h>
7#include <qpa/qplatformscreen.h>
8
9#include <QtCore/QFile>
10#include <QtCore/QLibraryInfo>
11#include <QtCore/QDir>
12#include <QtCore/QtEndian>
13#include <QtCore/QLoggingCategory>
14#include <QtCore/QUuid>
15
16#undef QT_NO_FREETYPE
17#include "qfontengine_ft_p.h"
18
19#include <ft2build.h>
20#include FT_TRUETYPE_TABLES_H
21#include FT_ERRORS_H
22
23#include FT_MULTIPLE_MASTERS_H
24#include FT_SFNT_NAMES_H
25#include FT_TRUETYPE_IDS_H
26
28
30
31using namespace Qt::StringLiterals;
32
34{
35 QString fontpath = fontDir();
36 QDir dir(fontpath);
37
38 if (!dir.exists()) {
39 qWarning("QFontDatabase: Cannot find font directory %s.\n"
40 "Note that Qt no longer ships fonts. Deploy some (from https://dejavu-fonts.github.io/ for example) or switch to fontconfig.",
41 qPrintable(fontpath));
42 return;
43 }
44
45 static const QString nameFilters[] = {
46 u"*.ttf"_s,
47 u"*.pfa"_s,
48 u"*.pfb"_s,
49 u"*.otf"_s,
50 };
51
52 const auto fis = dir.entryInfoList(QStringList::fromReadOnlyData(nameFilters), QDir::Files);
53 for (const QFileInfo &fi : fis) {
54 const QByteArray file = QFile::encodeName(fi.absoluteFilePath());
56 }
57}
58
60{
61 FontFile *fontfile = static_cast<FontFile *>(usrPtr);
63 faceId.filename = QFile::encodeName(fontfile->fileName);
64 faceId.index = fontfile->indexValue;
65 faceId.instanceIndex = fontfile->instanceIndex;
66 faceId.variableAxes = fontDef.variableAxisValues;
67
68 // Make sure the FaceId compares uniquely in cases where a
69 // file name is not provided.
70 if (faceId.filename.isEmpty()) {
72 memcpy(&id, &usrPtr, sizeof(usrPtr));
73 faceId.uuid = QUuid(id).toByteArray();
74 }
75
76 return QFontEngineFT::create(fontDef, faceId, fontfile->data);
77}
78
80 QFont::HintingPreference hintingPreference)
81{
82 return QFontEngineFT::create(fontData, pixelSize, hintingPreference, {});
83}
84
89
91{
92 FontFile *file = static_cast<FontFile *>(handle);
93 delete file;
94}
95
96extern FT_Library qt_getFreetype();
97
99 int faceIndex,
100 const QString &family,
101 const QString &styleName,
103 QFont::Stretch stretch,
104 QFont::Style style,
105 bool fixedPitch,
106 const QSupportedWritingSystems &writingSystems,
107 const QByteArray &fileName,
108 const QByteArray &fontData)
109{
110 FT_Face face = reinterpret_cast<FT_Face>(face_);
111
112 // Note: The following does not actually depend on API from 2.9, but the
113 // FT_Set_Named_Instance() was added in 2.9, so to avoid populating the database with
114 // named instances that cannot be selected, we disable the feature on older Freetype
115 // versions.
116#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 20900
117 FT_MM_Var *var = nullptr;
118 FT_Get_MM_Var(face, &var);
119 if (var != nullptr) {
120 std::unique_ptr<FT_MM_Var, void(*)(FT_MM_Var*)> varGuard(var, [](FT_MM_Var *res) {
121 FT_Done_MM_Var(qt_getFreetype(), res);
122 });
123
124 for (FT_UInt i = 0; i < var->num_namedstyles; ++i) {
125 FT_UInt id = var->namedstyle[i].strid;
126
127 QFont::Weight instanceWeight = weight;
128 QFont::Stretch instanceStretch = stretch;
129 QFont::Style instanceStyle = style;
130 for (FT_UInt axis = 0; axis < var->num_axis; ++axis) {
131 if (var->axis[axis].tag == QFont::Tag("wght").value()) {
132 instanceWeight = QFont::Weight(var->namedstyle[i].coords[axis] >> 16);
133 } else if (var->axis[axis].tag == QFont::Tag("wdth").value()) {
134 instanceStretch = QFont::Stretch(var->namedstyle[i].coords[axis] >> 16);
135 } else if (var->axis[axis].tag == QFont::Tag("ital").value()) {
136 FT_UInt ital = var->namedstyle[i].coords[axis] >> 16;
137 if (ital == 1)
138 instanceStyle = QFont::StyleItalic;
139 else
140 instanceStyle = QFont::StyleNormal;
141 }
142 }
143
144 FT_UInt count = FT_Get_Sfnt_Name_Count(face);
145 for (FT_UInt j = 0; j < count; ++j) {
146 FT_SfntName name;
147 if (FT_Get_Sfnt_Name(face, j, &name))
148 continue;
149
150 if (name.name_id != id)
151 continue;
152
153 // Only support Unicode for now
154 if (name.encoding_id != TT_MS_ID_UNICODE_CS)
155 continue;
156
157 // Sfnt names stored as UTF-16BE
158 QString instanceName;
159 for (FT_UInt k = 0; k < name.string_len; k += 2)
160 instanceName += QChar((name.string[k] << 8) + name.string[k + 1]);
161 if (instanceName != styleName) {
162 FontFile *variantFontFile = new FontFile{
164 faceIndex,
165 int(i),
167 };
168
169 qCDebug(lcFontDb) << "Registering named instance" << i
170 << ":" << instanceName
171 << "for font family" << family
172 << "with weight" << instanceWeight
173 << ", style" << instanceStyle
174 << ", stretch" << instanceStretch;
175
176 registerFont(family,
177 instanceName,
178 QString(),
179 instanceWeight,
180 instanceStyle,
181 instanceStretch,
182 true,
183 true,
184 0,
185 fixedPitch,
186 writingSystems,
187 variantFontFile);
188 }
189 }
190 }
191 }
192#else
193 Q_UNUSED(face);
194 Q_UNUSED(family);
195 Q_UNUSED(styleName);
197 Q_UNUSED(stretch);
198 Q_UNUSED(style);
199 Q_UNUSED(fixedPitch);
200 Q_UNUSED(writingSystems);
202#endif
203
204}
205
207{
208 FT_Library library = qt_getFreetype();
209
210 int index = 0;
211 int numFaces = 0;
212 QStringList families;
213 do {
214 FT_Face face;
215 FT_Error error;
216 if (!fontData.isEmpty()) {
217 error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
218 } else {
219 error = FT_New_Face(library, file.constData(), index, &face);
220 }
221 if (error != FT_Err_Ok) {
222 qDebug() << "FT_New_Face failed with index" << index << ':' << Qt::hex << error;
223 break;
224 }
225 numFaces = face->num_faces;
226
228
230 if (face->style_flags & FT_STYLE_FLAG_ITALIC)
231 style = QFont::StyleItalic;
232
233 if (face->style_flags & FT_STYLE_FLAG_BOLD)
235
236 bool fixedPitch = (face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);
237 QSupportedWritingSystems writingSystems;
238 // detect symbol fonts
239 for (int i = 0; i < face->num_charmaps; ++i) {
240 FT_CharMap cm = face->charmaps[i];
241 if (cm->encoding == FT_ENCODING_ADOBE_CUSTOM
242 || cm->encoding == FT_ENCODING_MS_SYMBOL) {
243 writingSystems.setSupported(QFontDatabase::Symbol);
244 break;
245 }
246 }
247
249 TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
250 if (os2) {
251 quint32 unicodeRange[4] = {
252 quint32(os2->ulUnicodeRange1),
253 quint32(os2->ulUnicodeRange2),
254 quint32(os2->ulUnicodeRange3),
255 quint32(os2->ulUnicodeRange4)
256 };
257 quint32 codePageRange[2] = {
258 quint32(os2->ulCodePageRange1),
259 quint32(os2->ulCodePageRange2)
260 };
261
262 writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
263
264 if (os2->usWeightClass) {
265 weight = static_cast<QFont::Weight>(os2->usWeightClass);
266 } else if (os2->panose[2]) {
267 int w = os2->panose[2];
268 if (w <= 1)
270 else if (w <= 2)
272 else if (w <= 3)
274 else if (w <= 5)
276 else if (w <= 6)
278 else if (w <= 7)
280 else if (w <= 8)
282 else if (w <= 9)
284 else if (w <= 10)
286 }
287
288 switch (os2->usWidthClass) {
289 case 1:
290 stretch = QFont::UltraCondensed;
291 break;
292 case 2:
293 stretch = QFont::ExtraCondensed;
294 break;
295 case 3:
296 stretch = QFont::Condensed;
297 break;
298 case 4:
299 stretch = QFont::SemiCondensed;
300 break;
301 case 5:
302 stretch = QFont::Unstretched;
303 break;
304 case 6:
305 stretch = QFont::SemiExpanded;
306 break;
307 case 7:
308 stretch = QFont::Expanded;
309 break;
310 case 8:
311 stretch = QFont::ExtraExpanded;
312 break;
313 case 9:
314 stretch = QFont::UltraExpanded;
315 break;
316 }
317 }
318
319 QString family = QString::fromLatin1(face->family_name);
320 FontFile *fontFile = new FontFile{
322 index,
323 -1,
325 };
326
327 QString styleName = QString::fromLatin1(face->style_name);
328
329 if (applicationFont != nullptr) {
331 properties.familyName = family;
332 properties.styleName = styleName;
333 properties.weight = weight;
334 properties.stretch = stretch;
335 properties.style = style;
336
337 applicationFont->properties.append(properties);
338 }
339
340 registerFont(family, styleName, QString(), weight, style, stretch, true, true, 0, fixedPitch, writingSystems, fontFile);
341
342 addNamedInstancesForFace(face, index, family, styleName, weight, stretch, style, fixedPitch, writingSystems, file, fontData);
343
344 families.append(family);
345
346 FT_Done_Face(face);
347 ++index;
348 } while (index < numFaces);
349 return families;
350}
351
353{
354#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 20900
355 return true;
356#else
357 return false;
358#endif
359}
360
\inmodule QtCore
Definition qbytearray.h:57
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
\inmodule QtCore
\inmodule QtCore
Definition qdir.h:20
@ Files
Definition qdir.h:23
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
static QFontEngineFT * create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData=QByteArray())
HintingPreference
Definition qfont.h:55
Stretch
Predefined stretch values that follow the CSS naming convention.
Definition qfont.h:83
@ ExtraCondensed
Definition qfont.h:86
@ Expanded
Definition qfont.h:91
@ Unstretched
Definition qfont.h:89
@ SemiCondensed
Definition qfont.h:88
@ SemiExpanded
Definition qfont.h:90
@ UltraCondensed
Definition qfont.h:85
@ ExtraExpanded
Definition qfont.h:92
@ Condensed
Definition qfont.h:87
@ UltraExpanded
Definition qfont.h:93
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:63
@ DemiBold
Definition qfont.h:69
@ Thin
Definition qfont.h:64
@ ExtraBold
Definition qfont.h:71
@ Black
Definition qfont.h:72
@ Bold
Definition qfont.h:70
@ ExtraLight
Definition qfont.h:65
@ Normal
Definition qfont.h:67
@ Light
Definition qfont.h:66
@ Medium
Definition qfont.h:68
Style
This enum describes the different styles of glyphs that are used to display text.
Definition qfont.h:76
@ StyleItalic
Definition qfont.h:78
@ StyleNormal
Definition qfont.h:77
static void addNamedInstancesForFace(void *face, int faceIndex, const QString &family, const QString &styleName, QFont::Weight weight, QFont::Stretch stretch, QFont::Style style, bool fixedPitch, const QSupportedWritingSystems &writingSystems, const QByteArray &fileName, const QByteArray &fontData)
bool supportsVariableApplicationFonts() const override
Returns true if this font database supports loading named instances from variable application fonts.
QFontEngine * fontEngine(const QFontDef &fontDef, void *handle) override
Returns the font engine that can be used to render the font described by the font definition,...
void populateFontDatabase() override
This function is called once at startup by Qt's internal font database.
static QStringList addTTFile(const QByteArray &fontData, const QByteArray &file, QFontDatabasePrivate::ApplicationFont *applicationFont=nullptr)
void releaseHandle(void *handle) override
Releases the specified font handle.
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont=nullptr) override
Adds an application font described by the font contained supplied fontData or using the font containe...
static QList< QString > fromReadOnlyData(const QString(&t)[N]) noexcept
Definition qlist.h:729
virtual QString fontDir() const
Returns the directory containing the fonts used by the database.
static QSupportedWritingSystems writingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2])
Helper function that determines the writing systems support by a given unicodeRange and codePageRange...
static void registerFont(const QString &familyname, const QString &stylename, const QString &foundryname, QFont::Weight weight, QFont::Style style, QFont::Stretch stretch, bool antialiased, bool scalable, int pixelSize, bool fixedPitch, const QSupportedWritingSystems &writingSystems, void *handle)
Registers a font with the given set of attributes describing the font's foundry, family name,...
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
The QSupportedWritingSystems class is used when registering fonts with the internal Qt fontdatabase.
void setSupported(QFontDatabase::WritingSystem, bool supported=true)
Sets or clears support for the specified writingSystem based on the value given by support.
\inmodule QtCore
Definition quuid.h:31
QByteArray toByteArray(StringFormat mode=WithBraces) const
Definition quuid.cpp:691
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
FT_Library qt_getFreetype()
FT_Library qt_getFreetype()
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLenum GLsizeiptr const void GLsizei faceIndex
GLuint64 GLenum void * handle
GLfloat GLfloat GLfloat w
[0]
GLuint index
[2]
GLenum GLenum GLsizei count
GLenum face
GLuint GLuint GLfloat weight
GLuint name
GLenum GLsizeiptr const void * fontData
GLuint res
#define qPrintable(string)
Definition qstring.h:1531
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
double qreal
Definition qtypes.h:187
QFile file
[0]
QString dir
[11]
QMap< QFont::Tag, float > variableAxisValues
Definition qfont_p.h:58
QMap< QFont::Tag, float > variableAxes
The QFont::Tag type provides access to advanced font features.
Definition qfont.h:215
constexpr quint32 value() const noexcept
Returns the numerical value of this tag.
Definition qfont.h:227
\inmodule QtCore
Definition quuid.h:58