1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qplatformfontdatabase.h"
41#include <QtGui/private/qfontengine_p.h>
42#include <QtGui/private/qfontengine_qpf2_p.h>
43#include <QtGui/QGuiApplication>
44#include <QtGui/QScreen>
45#include <qpa/qplatformscreen.h>
46#include <QtCore/QLibraryInfo>
47#include <QtCore/QDir>
48#include <QtCore/QMetaEnum>
49
50#include <algorithm>
51#include <iterator>
52
53QT_BEGIN_NAMESPACE
54
55void qt_registerFont(const QString &familyname, const QString &stylename,
56 const QString &foundryname, int weight,
57 QFont::Style style, int stretch, bool antialiased,
58 bool scalable, int pixelSize, bool fixedPitch,
59 const QSupportedWritingSystems &writingSystems, void *hanlde);
60
61void qt_registerFontFamily(const QString &familyName);
62void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
63bool qt_isFontFamilyPopulated(const QString &familyName);
64
65/*!
66 Registers the pre-rendered QPF2 font contained in the given \a dataArray.
67
68 \sa registerFont()
69*/
70void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle)
71{
72 if (dataArray.size() == 0)
73 return;
74
75 const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData());
76 if (QFontEngineQPF2::verifyHeader(data, dataArray.size())) {
77 QString fontName = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_FontName).toString();
78 int pixelSize = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_PixelSize).toInt();
79 QVariant weight = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Weight);
80 QVariant style = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Style);
81 QByteArray writingSystemBits = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_WritingSystems).toByteArray();
82
83 if (!fontName.isEmpty() && pixelSize) {
84 QFont::Weight fontWeight = QFont::Normal;
85 if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt)
86 fontWeight = QFont::Weight(weight.toInt());
87
88 QFont::Style fontStyle = static_cast<QFont::Style>(style.toInt());
89
90 QSupportedWritingSystems writingSystems;
91 for (int i = 0; i < writingSystemBits.count(); ++i) {
92 uchar currentByte = writingSystemBits.at(i);
93 for (int j = 0; j < 8; ++j) {
94 if (currentByte & 1)
95 writingSystems.setSupported(QFontDatabase::WritingSystem(i * 8 + j));
96 currentByte >>= 1;
97 }
98 }
99 QFont::Stretch stretch = QFont::Unstretched;
100 registerFont(fontName,QString(),QString(),fontWeight,fontStyle,stretch,true,false,pixelSize,false,writingSystems,handle);
101 }
102 } else {
103 qDebug("header verification of QPF2 font failed. maybe it is corrupt?");
104 }
105}
106
107/*!
108 Registers a font with the given set of attributes describing the font's
109 foundry, family name, style and stretch information, pixel size, and
110 supported writing systems. Additional information about whether the font
111 can be scaled and antialiased can also be provided.
112
113 The foundry name and font family are described by \a foundryName and
114 \a familyName. The font weight (light, normal, bold, etc.), style (normal,
115 oblique, italic) and stretch information (condensed, expanded, unstretched,
116 etc.) are specified by \a weight, \a style and \a stretch.
117
118 Some fonts can be antialiased and scaled; \a scalable and \a antialiased
119 can be set to true for fonts with these attributes. The intended pixel
120 size of non-scalable fonts is specified by \a pixelSize; this value will be
121 ignored for scalable fonts.
122
123 The writing systems supported by the font are specified by the
124 \a writingSystems argument.
125
126 \sa registerQPF2Font(), registerFontFamily()
127*/
128void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &stylename,
129 const QString &foundryname, QFont::Weight weight,
130 QFont::Style style, QFont::Stretch stretch, bool antialiased,
131 bool scalable, int pixelSize, bool fixedPitch,
132 const QSupportedWritingSystems &writingSystems, void *usrPtr)
133{
134 if (scalable)
135 pixelSize = 0;
136
137 qt_registerFont(familyname, stylename, foundryname, weight, style,
138 stretch, antialiased, scalable, pixelSize,
139 fixedPitch, writingSystems, usrPtr);
140}
141
142/*!
143 Registers a font family with the font database. The font will be
144 lazily populated by a callback to populateFamily() when the font
145 database determines that the family needs population.
146
147 \sa populateFamily(), registerFont()
148*/
149void QPlatformFontDatabase::registerFontFamily(const QString &familyName)
150{
151 qt_registerFontFamily(familyName);
152}
153
154class QWritingSystemsPrivate
155{
156public:
157 QWritingSystemsPrivate()
158 : ref(1)
159 , vector(QFontDatabase::WritingSystemsCount,false)
160 {
161 }
162
163 QWritingSystemsPrivate(const QWritingSystemsPrivate *other)
164 : ref(1)
165 , vector(other->vector)
166 {
167 }
168
169 QAtomicInt ref;
170 QVector<bool> vector;
171};
172
173/*!
174 Constructs a new object to handle supported writing systems.
175*/
176QSupportedWritingSystems::QSupportedWritingSystems()
177{
178 d = new QWritingSystemsPrivate;
179}
180
181/*!
182 Constructs a copy of the \a other writing systems object.
183*/
184QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other)
185{
186 d = other.d;
187 d->ref.ref();
188}
189
190/*!
191 Constructs a copy of the \a other writing systems object.
192*/
193QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other)
194{
195 if (d != other.d) {
196 other.d->ref.ref();
197 if (!d->ref.deref())
198 delete d;
199 d = other.d;
200 }
201 return *this;
202}
203
204#ifndef QT_NO_DEBUG_STREAM
205QDebug operator<<(QDebug debug, const QSupportedWritingSystems &sws)
206{
207 QMetaObject mo = QFontDatabase::staticMetaObject;
208 QMetaEnum me = mo.enumerator(mo.indexOfEnumerator("WritingSystem"));
209
210 QDebugStateSaver saver(debug);
211 debug.nospace() << "QSupportedWritingSystems(";
212 int i = sws.d->vector.indexOf(true);
213 while (i > 0) {
214 debug << me.valueToKey(i);
215 i = sws.d->vector.indexOf(true, i + 1);
216 if (i > 0)
217 debug << ", ";
218 }
219 debug << ")";
220 return debug;
221}
222#endif
223
224/*!
225 Destroys the supported writing systems object.
226*/
227QSupportedWritingSystems::~QSupportedWritingSystems()
228{
229 if (!d->ref.deref())
230 delete d;
231}
232
233/*!
234 \internal
235*/
236void QSupportedWritingSystems::detach()
237{
238 if (d->ref.loadRelaxed() != 1) {
239 QWritingSystemsPrivate *newd = new QWritingSystemsPrivate(d);
240 if (!d->ref.deref())
241 delete d;
242 d = newd;
243 }
244}
245
246/*!
247 Sets or clears support for the specified \a writingSystem based on the
248 value given by \a support.
249*/
250void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support)
251{
252 detach();
253 d->vector[writingSystem] = support;
254}
255
256/*!
257 Returns \c true if the writing system specified by \a writingSystem is
258 supported; otherwise returns \c false.
259*/
260bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const
261{
262 return d->vector.at(writingSystem);
263}
264
265/*!
266 \class QSupportedWritingSystems
267 \brief The QSupportedWritingSystems class is used when registering fonts with the internal Qt
268 fontdatabase.
269 \ingroup painting
270 \inmodule QtGui
271
272 Its to provide an easy to use interface for indicating what writing systems a specific font
273 supports.
274
275*/
276
277/*!
278 \internal
279 */
280QPlatformFontDatabase::~QPlatformFontDatabase()
281{
282}
283
284/*!
285 This function is called once at startup by Qt's internal font database.
286 Reimplement this function in a subclass for a convenient place to initialize
287 the internal font database.
288
289 You may lazily populate the database by calling registerFontFamily() instead
290 of registerFont(), in which case you'll get a callback to populateFamily()
291 when the required family needs population. You then call registerFont() to
292 finish population of the family.
293
294 The default implementation looks in the fontDir() location and registers all
295 QPF2 fonts.
296*/
297void QPlatformFontDatabase::populateFontDatabase()
298{
299 QString fontpath = fontDir();
300 if(!QFile::exists(fontpath)) {
301 qWarning("QFontDatabase: Cannot find font directory '%s' - is Qt installed correctly?",
302 qPrintable(QDir::toNativeSeparators(fontpath)));
303 return;
304 }
305
306 QDir dir(fontpath);
307 dir.setNameFilters(QStringList() << QLatin1String("*.qpf2"));
308 dir.refresh();
309 for (int i = 0; i < int(dir.count()); ++i) {
310 const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i]));
311 QFile file(QString::fromLocal8Bit(fileName));
312 if (file.open(QFile::ReadOnly)) {
313 const QByteArray fileData = file.readAll();
314 QByteArray *fileDataPtr = new QByteArray(fileData);
315 registerQPF2Font(fileData, fileDataPtr);
316 }
317 }
318}
319
320/*!
321 This function is called whenever a lazily populated family, populated
322 through registerFontFamily(), needs full population.
323
324 You are expected to fully populate the family by calling registerFont()
325 for each font that matches the family name.
326*/
327void QPlatformFontDatabase::populateFamily(const QString &familyName)
328{
329 Q_UNUSED(familyName);
330}
331
332/*!
333 This function is called whenever the font database is invalidated.
334
335 Reimplement this function to clear any internal data structures that
336 will need to be rebuilt at the next call to populateFontDatabase().
337*/
338void QPlatformFontDatabase::invalidate()
339{
340}
341
342/*!
343 Returns a multi font engine in the specified \a script to encapsulate \a fontEngine with the
344 option to fall back to the fonts given by \a fallbacks if \a fontEngine does not support
345 a certain character.
346*/
347QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
348{
349 return new QFontEngineMulti(fontEngine, script);
350}
351
352/*!
353 Returns the font engine that can be used to render the font described by
354 the font definition, \a fontDef, in the specified \a script.
355*/
356QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
357{
358 QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
359 QFontEngineQPF2 *engine = new QFontEngineQPF2(fontDef,*fileDataPtr);
360 //qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family;
361 return engine;
362}
363
364QFontEngine *QPlatformFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize,
365 QFont::HintingPreference hintingPreference)
366{
367 Q_UNUSED(fontData);
368 Q_UNUSED(pixelSize);
369 Q_UNUSED(hintingPreference);
370 qWarning("This plugin does not support font engines created directly from font data");
371 return 0;
372}
373
374/*!
375 Adds an application font described by the font contained supplied \a fontData
376 or using the font contained in the file referenced by \a fileName. Returns
377 a list of family names, or an empty list if the font could not be added.
378
379 \note The default implementation of this function does not add an application
380 font. Subclasses should reimplement this function to perform the necessary
381 loading and registration of fonts.
382*/
383QStringList QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
384{
385 Q_UNUSED(fontData);
386 Q_UNUSED(fileName);
387
388 qWarning("This plugin does not support application fonts");
389 return QStringList();
390}
391
392/*!
393 Releases the specified font \a handle.
394*/
395void QPlatformFontDatabase::releaseHandle(void *handle)
396{
397 QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
398 delete fileDataPtr;
399}
400
401/*!
402 Returns the directory containing the fonts used by the database.
403*/
404QString QPlatformFontDatabase::fontDir() const
405{
406 QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QPA_FONTDIR"));
407 if (fontpath.isEmpty())
408 fontpath = QLibraryInfo::location(QLibraryInfo::LibrariesPath) + QLatin1String("/fonts");
409
410 return fontpath;
411}
412
413/*!
414 Returns true if the font family is private. For any given family name,
415 the result is platform dependent.
416*/
417bool QPlatformFontDatabase::isPrivateFontFamily(const QString &family) const
418{
419 Q_UNUSED(family);
420 return false;
421}
422
423/*!
424 Returns the default system font.
425
426 \sa QGuiApplication::font()
427 \since 5.0
428*/
429
430QFont QPlatformFontDatabase::defaultFont() const
431{
432 return QFont(QLatin1String("Helvetica"));
433}
434
435
436QString qt_resolveFontFamilyAlias(const QString &alias);
437
438/*!
439 Resolve alias to actual font family names.
440
441 \since 5.0
442 */
443QString QPlatformFontDatabase::resolveFontFamilyAlias(const QString &family) const
444{
445 return qt_resolveFontFamilyAlias(family);
446}
447
448/*!
449 Return true if all fonts are considered scalable when using this font database.
450 Defaults to false.
451
452 \since 5.0
453 */
454
455bool QPlatformFontDatabase::fontsAlwaysScalable() const
456{
457 return false;
458}
459
460/*!
461 Return list of standard font sizes when using this font database.
462
463 \since 5.0
464 */
465
466 QList<int> QPlatformFontDatabase::standardSizes() const
467{
468 QList<int> ret;
469 static const quint8 standard[] =
470 { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 };
471 static const int num_standards = int(sizeof standard / sizeof *standard);
472 ret.reserve(num_standards);
473 std::copy(standard, standard + num_standards, std::back_inserter(ret));
474 return ret;
475}
476
477// ### copied to tools/makeqpf/qpf2.cpp
478
479// see the Unicode subset bitfields in the MSDN docs
480static const quint8 requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
481 { 127, 127 }, // Any
482 { 0, 127 }, // Latin
483 { 7, 127 }, // Greek
484 { 9, 127 }, // Cyrillic
485 { 10, 127 }, // Armenian
486 { 11, 127 }, // Hebrew
487 { 13, 127 }, // Arabic
488 { 71, 127 }, // Syriac
489 { 72, 127 }, // Thaana
490 { 15, 127 }, // Devanagari
491 { 16, 127 }, // Bengali
492 { 17, 127 }, // Gurmukhi
493 { 18, 127 }, // Gujarati
494 { 19, 127 }, // Oriya
495 { 20, 127 }, // Tamil
496 { 21, 127 }, // Telugu
497 { 22, 127 }, // Kannada
498 { 23, 127 }, // Malayalam
499 { 73, 127 }, // Sinhala
500 { 24, 127 }, // Thai
501 { 25, 127 }, // Lao
502 { 70, 127 }, // Tibetan
503 { 74, 127 }, // Myanmar
504 { 26, 127 }, // Georgian
505 { 80, 127 }, // Khmer
506 { 126, 127 }, // SimplifiedChinese
507 { 126, 127 }, // TraditionalChinese
508 { 126, 127 }, // Japanese
509 { 56, 127 }, // Korean
510 { 0, 127 }, // Vietnamese (same as latin1)
511 { 126, 127 }, // Other
512 { 78, 127 }, // Ogham
513 { 79, 127 }, // Runic
514 { 14, 127 }, // Nko
515};
516
517enum CsbBits {
518 Latin1CsbBit = 0,
519 CentralEuropeCsbBit = 1,
520 TurkishCsbBit = 4,
521 BalticCsbBit = 7,
522 CyrillicCsbBit = 2,
523 GreekCsbBit = 3,
524 HebrewCsbBit = 5,
525 ArabicCsbBit = 6,
526 VietnameseCsbBit = 8,
527 SimplifiedChineseCsbBit = 18,
528 TraditionalChineseCsbBit = 20,
529 ThaiCsbBit = 16,
530 JapaneseCsbBit = 17,
531 KoreanCsbBit = 19,
532 KoreanJohabCsbBit = 21,
533 SymbolCsbBit = 31
534};
535
536/*!
537 Helper function that determines the writing systems support by a given
538 \a unicodeRange and \a codePageRange.
539
540 \since 5.1
541*/
542QSupportedWritingSystems QPlatformFontDatabase::writingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2])
543{
544 QSupportedWritingSystems writingSystems;
545
546 bool hasScript = false;
547 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
548 int bit = requiredUnicodeBits[i][0];
549 int index = bit/32;
550 int flag = 1 << (bit&31);
551 if (bit != 126 && (unicodeRange[index] & flag)) {
552 bit = requiredUnicodeBits[i][1];
553 index = bit/32;
554
555 flag = 1 << (bit&31);
556 if (bit == 127 || (unicodeRange[index] & flag)) {
557 writingSystems.setSupported(QFontDatabase::WritingSystem(i));
558 hasScript = true;
559 // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i);
560 }
561 }
562 }
563 if (codePageRange[0] & ((1 << Latin1CsbBit) | (1 << CentralEuropeCsbBit) | (1 << TurkishCsbBit) | (1 << BalticCsbBit))) {
564 writingSystems.setSupported(QFontDatabase::Latin);
565 hasScript = true;
566 //qDebug("font %s supports Latin", familyName.latin1());
567 }
568 if (codePageRange[0] & (1 << CyrillicCsbBit)) {
569 writingSystems.setSupported(QFontDatabase::Cyrillic);
570 hasScript = true;
571 //qDebug("font %s supports Cyrillic", familyName.latin1());
572 }
573 if (codePageRange[0] & (1 << GreekCsbBit)) {
574 writingSystems.setSupported(QFontDatabase::Greek);
575 hasScript = true;
576 //qDebug("font %s supports Greek", familyName.latin1());
577 }
578 if (codePageRange[0] & (1 << HebrewCsbBit)) {
579 writingSystems.setSupported(QFontDatabase::Hebrew);
580 hasScript = true;
581 //qDebug("font %s supports Hebrew", familyName.latin1());
582 }
583 if (codePageRange[0] & (1 << ArabicCsbBit)) {
584 writingSystems.setSupported(QFontDatabase::Arabic);
585 hasScript = true;
586 //qDebug("font %s supports Arabic", familyName.latin1());
587 }
588 if (codePageRange[0] & (1 << ThaiCsbBit)) {
589 writingSystems.setSupported(QFontDatabase::Thai);
590 hasScript = true;
591 //qDebug("font %s supports Thai", familyName.latin1());
592 }
593 if (codePageRange[0] & (1 << VietnameseCsbBit)) {
594 writingSystems.setSupported(QFontDatabase::Vietnamese);
595 hasScript = true;
596 //qDebug("font %s supports Vietnamese", familyName.latin1());
597 }
598 if (codePageRange[0] & (1 << SimplifiedChineseCsbBit)) {
599 writingSystems.setSupported(QFontDatabase::SimplifiedChinese);
600 hasScript = true;
601 //qDebug("font %s supports Simplified Chinese", familyName.latin1());
602 }
603 if (codePageRange[0] & (1 << TraditionalChineseCsbBit)) {
604 writingSystems.setSupported(QFontDatabase::TraditionalChinese);
605 hasScript = true;
606 //qDebug("font %s supports Traditional Chinese", familyName.latin1());
607 }
608 if (codePageRange[0] & (1 << JapaneseCsbBit)) {
609 writingSystems.setSupported(QFontDatabase::Japanese);
610 hasScript = true;
611 //qDebug("font %s supports Japanese", familyName.latin1());
612 }
613 if (codePageRange[0] & ((1 << KoreanCsbBit) | (1 << KoreanJohabCsbBit))) {
614 writingSystems.setSupported(QFontDatabase::Korean);
615 hasScript = true;
616 //qDebug("font %s supports Korean", familyName.latin1());
617 }
618 if (codePageRange[0] & (1U << SymbolCsbBit)) {
619 writingSystems = QSupportedWritingSystems();
620 hasScript = false;
621 }
622
623 if (!hasScript)
624 writingSystems.setSupported(QFontDatabase::Symbol);
625
626 return writingSystems;
627}
628
629/*!
630 Helper function that returns the Qt font weight matching
631 a given opentype integer value. Converts the integer
632 \a weight (0 ~ 1000) to QFont::Weight and returns it.
633
634 \since 5.5
635*/
636
637QFont::Weight QPlatformFontDatabase::weightFromInteger(int weight)
638{
639 if (weight < 150)
640 return QFont::Thin;
641 if (weight < 250)
642 return QFont::ExtraLight;
643 if (weight < 350)
644 return QFont::Light;
645 if (weight < 450)
646 return QFont::Normal;
647 if (weight < 550)
648 return QFont::Medium;
649 if (weight < 650)
650 return QFont::DemiBold;
651 if (weight < 750)
652 return QFont::Bold;
653 if (weight < 850)
654 return QFont::ExtraBold;
655 return QFont::Black;
656}
657
658/*!
659 Helper function that register the \a alias for the \a familyName.
660
661 \since 5.2
662*/
663
664void QPlatformFontDatabase::registerAliasToFontFamily(const QString &familyName, const QString &alias)
665{
666 qt_registerAliasToFontFamily(familyName, alias);
667}
668
669/*!
670 Helper function that returns true if the font family has already been registered and populated.
671
672 \since 5.14
673*/
674bool QPlatformFontDatabase::isFamilyPopulated(const QString &familyName)
675{
676 return qt_isFontFamilyPopulated(familyName);
677}
678
679/*!
680 \class QPlatformFontDatabase
681 \since 5.0
682 \internal
683 \preliminary
684 \ingroup qpa
685 \ingroup painting
686
687 \brief The QPlatformFontDatabase class makes it possible to customize how fonts
688 are discovered and how they are rendered
689
690 QPlatformFontDatabase is the superclass which is intended to let platform implementations use
691 native font handling.
692
693 Qt has its internal font database which it uses to discover available fonts on the
694 user's system. To be able to populate this database subclass this class, and
695 reimplement populateFontDatabase().
696
697 Use the function registerFont() to populate the internal font database.
698
699 Sometimes a specified font does not have the required glyphs; in such a case, the
700 fallbackForFamily() function is called automatically to find alternative font
701 families that can supply alternatives to the missing glyphs.
702
703 \sa QSupportedWritingSystems
704*/
705QT_END_NAMESPACE
706