Coverage Report

Created: 2025-07-23 08:13

/src/qtbase/src/gui/text/qfont.cpp
Line
Count
Source (jump to first uncovered line)
1
/****************************************************************************
2
**
3
** Copyright (C) 2019 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 "qfont.h"
41
#include "qdebug.h"
42
#include "qpaintdevice.h"
43
#include "qfontdatabase.h"
44
#include "qfontmetrics.h"
45
#include "qfontinfo.h"
46
#include "qpainter.h"
47
#include "qhash.h"
48
#include "qdatastream.h"
49
#include "qguiapplication.h"
50
#include "qstringlist.h"
51
#include "qscreen.h"
52
53
#include "qthread.h"
54
#include "qthreadstorage.h"
55
56
#include "qfont_p.h"
57
#include <private/qfontengine_p.h>
58
#include <private/qpainter_p.h>
59
#include <private/qtextengine_p.h>
60
#include <limits.h>
61
62
#include <qpa/qplatformscreen.h>
63
#include <qpa/qplatformintegration.h>
64
#include <qpa/qplatformfontdatabase.h>
65
#include <QtGui/private/qguiapplication_p.h>
66
67
#include <QtCore/QMutexLocker>
68
#include <QtCore/QMutex>
69
70
// #define QFONTCACHE_DEBUG
71
#ifdef QFONTCACHE_DEBUG
72
#  define FC_DEBUG qDebug
73
#else
74
0
#  define FC_DEBUG if (false) qDebug
75
#endif
76
77
QT_BEGIN_NAMESPACE
78
79
#ifndef QFONTCACHE_DECREASE_TRIGGER_LIMIT
80
0
#  define QFONTCACHE_DECREASE_TRIGGER_LIMIT 256
81
#endif
82
83
bool QFontDef::exactMatch(const QFontDef &other) const
84
0
{
85
    /*
86
      QFontDef comparison is more complicated than just simple
87
      per-member comparisons.
88
89
      When comparing point/pixel sizes, either point or pixelsize
90
      could be -1.  in This case we have to compare the non negative
91
      size value.
92
93
      This test will fail if the point-sizes differ by 1/2 point or
94
      more or they do not round to the same value.  We have to do this
95
      since our API still uses 'int' point-sizes in the API, but store
96
      deci-point-sizes internally.
97
98
      To compare the family members, we need to parse the font names
99
      and compare the family/foundry strings separately.  This allows
100
      us to compare e.g. "Helvetica" and "Helvetica [Adobe]" with
101
      positive results.
102
    */
103
0
    if (pixelSize != -1 && other.pixelSize != -1) {
104
0
        if (pixelSize != other.pixelSize)
105
0
            return false;
106
0
    } else if (pointSize != -1 && other.pointSize != -1) {
107
0
        if (pointSize != other.pointSize)
108
0
            return false;
109
0
    } else {
110
0
        return false;
111
0
    }
112
113
0
    if (!ignorePitch && !other.ignorePitch && fixedPitch != other.fixedPitch)
114
0
        return false;
115
116
0
    if (stretch != 0 && other.stretch != 0 && stretch != other.stretch)
117
0
        return false;
118
119
    // If either families or other.families just has 1 entry and the other has 0 then
120
    // we will fall back to using the family in that case
121
0
    const int sizeDiff = qAbs(families.size() - other.families.size());
122
0
    if (sizeDiff > 1)
123
0
        return false;
124
0
    if (sizeDiff == 1 && (families.size() > 1 || other.families.size() > 1))
125
0
        return false;
126
127
0
    QStringList origFamilies = families;
128
0
    QStringList otherFamilies = other.families;
129
0
    if (sizeDiff != 0) {
130
0
        if (origFamilies.size() != 1)
131
0
            origFamilies << family;
132
0
        else
133
0
            otherFamilies << other.family;
134
0
    }
135
136
0
    QString this_family, this_foundry, other_family, other_foundry;
137
0
    for (int i = 0; i < origFamilies.size(); ++i) {
138
0
        QFontDatabase::parseFontName(origFamilies.at(i), this_foundry, this_family);
139
0
        QFontDatabase::parseFontName(otherFamilies.at(i), other_foundry, other_family);
140
0
        if (this_family != other_family || this_foundry != other_foundry)
141
0
            return false;
142
0
    }
143
144
    // Check family only if families is not set
145
0
    if (origFamilies.size() == 0) {
146
0
        QFontDatabase::parseFontName(family, this_foundry, this_family);
147
0
        QFontDatabase::parseFontName(other.family, other_foundry, other_family);
148
0
    }
149
150
0
    return (styleHint     == other.styleHint
151
0
            && styleStrategy == other.styleStrategy
152
0
            && weight        == other.weight
153
0
            && style        == other.style
154
0
            && this_family   == other_family
155
0
            && (styleName.isEmpty() || other.styleName.isEmpty() || styleName == other.styleName)
156
0
            && (this_foundry.isEmpty()
157
0
                || other_foundry.isEmpty()
158
0
                || this_foundry == other_foundry)
159
0
       );
160
0
}
161
162
extern bool qt_is_gui_used;
163
164
Q_GUI_EXPORT int qt_defaultDpiX()
165
62.7k
{
166
62.7k
    if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi))
167
0
        return 96;
168
169
62.7k
    if (!qt_is_gui_used)
170
0
        return 75;
171
172
62.7k
    if (const QScreen *screen = QGuiApplication::primaryScreen())
173
0
        return qRound(screen->logicalDotsPerInchX());
174
175
    //PI has not been initialised, or it is being initialised. Give a default dpi
176
62.7k
    return 100;
177
62.7k
}
178
179
Q_GUI_EXPORT int qt_defaultDpiY()
180
70.8k
{
181
70.8k
    if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi))
182
0
        return 96;
183
184
70.8k
    if (!qt_is_gui_used)
185
0
        return 75;
186
187
70.8k
    if (const QScreen *screen = QGuiApplication::primaryScreen())
188
0
        return qRound(screen->logicalDotsPerInchY());
189
190
    //PI has not been initialised, or it is being initialised. Give a default dpi
191
70.8k
    return 100;
192
70.8k
}
193
194
Q_GUI_EXPORT int qt_defaultDpi()
195
8.02k
{
196
8.02k
    return qt_defaultDpiY();
197
8.02k
}
198
199
QFontPrivate::QFontPrivate()
200
8.02k
    : engineData(nullptr), dpi(qt_defaultDpi()),
201
8.02k
      underline(false), overline(false), strikeOut(false), kerning(true),
202
8.02k
      capital(0), letterSpacingIsAbsolute(false), scFont(nullptr)
203
8.02k
{
204
8.02k
}
205
206
QFontPrivate::QFontPrivate(const QFontPrivate &other)
207
0
    : request(other.request), engineData(nullptr), dpi(other.dpi),
208
0
      underline(other.underline), overline(other.overline),
209
0
      strikeOut(other.strikeOut), kerning(other.kerning),
210
0
      capital(other.capital), letterSpacingIsAbsolute(other.letterSpacingIsAbsolute),
211
0
      letterSpacing(other.letterSpacing), wordSpacing(other.wordSpacing),
212
0
      scFont(other.scFont)
213
0
{
214
0
    if (scFont && scFont != this)
215
0
        scFont->ref.ref();
216
0
}
217
218
QFontPrivate::~QFontPrivate()
219
8.02k
{
220
8.02k
    if (engineData && !engineData->ref.deref())
221
0
        delete engineData;
222
8.02k
    engineData = nullptr;
223
8.02k
    if (scFont && scFont != this) {
224
0
        if (!scFont->ref.deref())
225
0
            delete scFont;
226
0
    }
227
8.02k
    scFont = nullptr;
228
8.02k
}
229
230
extern QRecursiveMutex *qt_fontdatabase_mutex();
231
232
0
#define QT_FONT_ENGINE_FROM_DATA(data, script) data->engines[script]
233
234
QFontEngine *QFontPrivate::engineForScript(int script) const
235
0
{
236
0
    QMutexLocker locker(qt_fontdatabase_mutex());
237
0
    if (script <= QChar::Script_Latin)
238
0
        script = QChar::Script_Common;
239
0
    if (engineData && engineData->fontCacheId != QFontCache::instance()->id()) {
240
        // throw out engineData that came from a different thread
241
0
        if (!engineData->ref.deref())
242
0
            delete engineData;
243
0
        engineData = nullptr;
244
0
    }
245
0
    if (!engineData || !QT_FONT_ENGINE_FROM_DATA(engineData, script))
246
0
        QFontDatabase::load(this, script);
247
0
    return QT_FONT_ENGINE_FROM_DATA(engineData, script);
248
0
}
249
250
0
void QFontPrivate::alterCharForCapitalization(QChar &c) const {
251
0
    switch (capital) {
252
0
    case QFont::AllUppercase:
253
0
    case QFont::SmallCaps:
254
0
        c = c.toUpper();
255
0
        break;
256
0
    case QFont::AllLowercase:
257
0
        c = c.toLower();
258
0
        break;
259
0
    case QFont::MixedCase:
260
0
        break;
261
0
    }
262
0
}
263
264
QFontPrivate *QFontPrivate::smallCapsFontPrivate() const
265
0
{
266
0
    if (scFont)
267
0
        return scFont;
268
0
    QFont font(const_cast<QFontPrivate *>(this));
269
0
    qreal pointSize = font.pointSizeF();
270
0
    if (pointSize > 0)
271
0
        font.setPointSizeF(pointSize * .7);
272
0
    else
273
0
        font.setPixelSize((font.pixelSize() * 7 + 5) / 10);
274
0
    scFont = font.d.data();
275
0
    if (scFont != this)
276
0
        scFont->ref.ref();
277
0
    return scFont;
278
0
}
279
280
281
void QFontPrivate::resolve(uint mask, const QFontPrivate *other)
282
0
{
283
0
    Q_ASSERT(other != nullptr);
284
285
0
    dpi = other->dpi;
286
287
0
    if ((mask & QFont::AllPropertiesResolved) == QFont::AllPropertiesResolved) return;
288
289
    // assign the unset-bits with the set-bits of the other font def
290
0
    if (! (mask & QFont::FamilyResolved))
291
0
        request.family = other->request.family;
292
293
0
    if (!(mask & QFont::FamiliesResolved)) {
294
0
        request.families = other->request.families;
295
        // Prepend the family explicitly set so it will be given
296
        // preference in this case
297
0
        if (mask & QFont::FamilyResolved)
298
0
            request.families.prepend(request.family);
299
0
    }
300
301
0
    if (! (mask & QFont::StyleNameResolved))
302
0
        request.styleName = other->request.styleName;
303
304
0
    if (! (mask & QFont::SizeResolved)) {
305
0
        request.pointSize = other->request.pointSize;
306
0
        request.pixelSize = other->request.pixelSize;
307
0
    }
308
309
0
    if (! (mask & QFont::StyleHintResolved))
310
0
        request.styleHint = other->request.styleHint;
311
312
0
    if (! (mask & QFont::StyleStrategyResolved))
313
0
        request.styleStrategy = other->request.styleStrategy;
314
315
0
    if (! (mask & QFont::WeightResolved))
316
0
        request.weight = other->request.weight;
317
318
0
    if (! (mask & QFont::StyleResolved))
319
0
        request.style = other->request.style;
320
321
0
    if (! (mask & QFont::FixedPitchResolved))
322
0
        request.fixedPitch = other->request.fixedPitch;
323
324
0
    if (! (mask & QFont::StretchResolved))
325
0
        request.stretch = other->request.stretch;
326
327
0
    if (! (mask & QFont::HintingPreferenceResolved))
328
0
        request.hintingPreference = other->request.hintingPreference;
329
330
0
    if (! (mask & QFont::UnderlineResolved))
331
0
        underline = other->underline;
332
333
0
    if (! (mask & QFont::OverlineResolved))
334
0
        overline = other->overline;
335
336
0
    if (! (mask & QFont::StrikeOutResolved))
337
0
        strikeOut = other->strikeOut;
338
339
0
    if (! (mask & QFont::KerningResolved))
340
0
        kerning = other->kerning;
341
342
0
    if (! (mask & QFont::LetterSpacingResolved)) {
343
0
        letterSpacing = other->letterSpacing;
344
0
        letterSpacingIsAbsolute = other->letterSpacingIsAbsolute;
345
0
    }
346
0
    if (! (mask & QFont::WordSpacingResolved))
347
0
        wordSpacing = other->wordSpacing;
348
0
    if (! (mask & QFont::CapitalizationResolved))
349
0
        capital = other->capital;
350
0
}
351
352
353
354
355
QFontEngineData::QFontEngineData()
356
0
    : ref(0), fontCacheId(QFontCache::instance()->id())
357
0
{
358
0
    memset(engines, 0, QChar::ScriptCount * sizeof(QFontEngine *));
359
0
}
360
361
QFontEngineData::~QFontEngineData()
362
0
{
363
0
    Q_ASSERT(ref.loadRelaxed() == 0);
364
0
    for (int i = 0; i < QChar::ScriptCount; ++i) {
365
0
        if (engines[i]) {
366
0
            if (!engines[i]->ref.deref())
367
0
                delete engines[i];
368
0
            engines[i] = nullptr;
369
0
        }
370
0
    }
371
0
}
372
373
374
375
376
/*!
377
    \class QFont
378
    \reentrant
379
380
    \brief The QFont class specifies a query for a font used for drawing text.
381
382
    \ingroup painting
383
    \ingroup appearance
384
    \ingroup shared
385
    \ingroup richtext-processing
386
    \inmodule QtGui
387
388
    QFont can be regarded as a query for one or more fonts on the system.
389
390
    When you create a QFont object you specify various attributes that
391
    you want the font to have. Qt will use the font with the specified
392
    attributes, or if no matching font exists, Qt will use the closest
393
    matching installed font. The attributes of the font that is
394
    actually used are retrievable from a QFontInfo object. If the
395
    window system provides an exact match exactMatch() returns \c true.
396
    Use QFontMetricsF to get measurements, e.g. the pixel length of a
397
    string using QFontMetrics::width().
398
399
    Attributes which are not specifically set will not affect the font
400
    selection algorithm, and default values will be preferred instead.
401
402
    To load a specific physical font, typically represented by a single file,
403
    use QRawFont instead.
404
405
    Note that a QGuiApplication instance must exist before a QFont can be
406
    used. You can set the application's default font with
407
    QGuiApplication::setFont().
408
409
    If a chosen font does not include all the characters that
410
    need to be displayed, QFont will try to find the characters in the
411
    nearest equivalent fonts. When a QPainter draws a character from a
412
    font the QFont will report whether or not it has the character; if
413
    it does not, QPainter will draw an unfilled square.
414
415
    Create QFonts like this:
416
417
    \snippet code/src_gui_text_qfont.cpp 0
418
419
    The attributes set in the constructor can also be set later, e.g.
420
    setFamily(), setPointSize(), setPointSizeF(), setWeight() and
421
    setItalic(). The remaining attributes must be set after
422
    contstruction, e.g. setBold(), setUnderline(), setOverline(),
423
    setStrikeOut() and setFixedPitch(). QFontInfo objects should be
424
    created \e after the font's attributes have been set. A QFontInfo
425
    object will not change, even if you change the font's
426
    attributes. The corresponding "get" functions, e.g. family(),
427
    pointSize(), etc., return the values that were set, even though
428
    the values used may differ. The actual values are available from a
429
    QFontInfo object.
430
431
    If the requested font family is unavailable you can influence the
432
    \l{#fontmatching}{font matching algorithm} by choosing a
433
    particular \l{QFont::StyleHint} and \l{QFont::StyleStrategy} with
434
    setStyleHint(). The default family (corresponding to the current
435
    style hint) is returned by defaultFamily().
436
437
    You can provide substitutions for font family names using
438
    insertSubstitution() and insertSubstitutions(). Substitutions can
439
    be removed with removeSubstitutions(). Use substitute() to retrieve
440
    a family's first substitute, or the family name itself if it has
441
    no substitutes. Use substitutes() to retrieve a list of a family's
442
    substitutes (which may be empty). After substituting a font, you must
443
    trigger the updating of the font by destroying and re-creating all
444
    QFont objects.
445
446
    Every QFont has a key() which you can use, for example, as the key
447
    in a cache or dictionary. If you want to store a user's font
448
    preferences you could use QSettings, writing the font information
449
    with toString() and reading it back with fromString(). The
450
    operator<<() and operator>>() functions are also available, but
451
    they work on a data stream.
452
453
    It is possible to set the height of characters shown on the screen
454
    to a specified number of pixels with setPixelSize(); however using
455
    setPointSize() has a similar effect and provides device
456
    independence.
457
458
    Loading fonts can be expensive, especially on X11. QFont contains
459
    extensive optimizations to make the copying of QFont objects fast,
460
    and to cache the results of the slow window system functions it
461
    depends upon.
462
463
    \target fontmatching
464
    The font matching algorithm works as follows:
465
    \list 1
466
    \li The specified font families (set by setFamilies()) are searched for.
467
    \li If not found, then if set the specified font family exists and can be used to represent
468
        the writing system in use, it will be selected.
469
    \li If not, a replacement font that supports the writing system is
470
        selected. The font matching algorithm will try to find the
471
        best match for all the properties set in the QFont. How this is
472
        done varies from platform to platform.
473
    \li If no font exists on the system that can support the text,
474
        then special "missing character" boxes will be shown in its place.
475
    \endlist
476
477
    \note If the selected font, though supporting the writing system in general,
478
    is missing glyphs for one or more specific characters, then Qt will try to
479
    find a fallback font for this or these particular characters. This feature
480
    can be disabled using QFont::NoFontMerging style strategy.
481
482
    In Windows a request for the "Courier" font is automatically changed to
483
    "Courier New", an improved version of Courier that allows for smooth scaling.
484
    The older "Courier" bitmap font can be selected by setting the PreferBitmap
485
    style strategy (see setStyleStrategy()).
486
487
    Once a font is found, the remaining attributes are matched in order of
488
    priority:
489
    \list 1
490
    \li fixedPitch()
491
    \li pointSize() (see below)
492
    \li weight()
493
    \li style()
494
    \endlist
495
496
    If you have a font which matches on family, even if none of the
497
    other attributes match, this font will be chosen in preference to
498
    a font which doesn't match on family but which does match on the
499
    other attributes. This is because font family is the dominant
500
    search criteria.
501
502
    The point size is defined to match if it is within 20% of the
503
    requested point size. When several fonts match and are only
504
    distinguished by point size, the font with the closest point size
505
    to the one requested will be chosen.
506
507
    The actual family, font size, weight and other font attributes
508
    used for drawing text will depend on what's available for the
509
    chosen family under the window system. A QFontInfo object can be
510
    used to determine the actual values used for drawing the text.
511
512
    Examples:
513
514
    \snippet code/src_gui_text_qfont.cpp 1
515
    If you had both an Adobe and a Cronyx Helvetica, you might get
516
    either.
517
518
    \snippet code/src_gui_text_qfont.cpp 2
519
520
    You can specify the foundry you want in the family name. The font f
521
    in the above example will be set to "Helvetica
522
    [Cronyx]".
523
524
    To determine the attributes of the font actually used in the window
525
    system, use a QFontInfo object, e.g.
526
527
    \snippet code/src_gui_text_qfont.cpp 3
528
529
    To find out font metrics use a QFontMetrics object, e.g.
530
531
    \snippet code/src_gui_text_qfont.cpp 4
532
533
    For more general information on fonts, see the
534
    \l{comp.fonts FAQ}{comp.fonts FAQ}.
535
    Information on encodings can be found from
536
    \l{Roman Czyborra's} page.
537
538
    \sa QFontMetrics, QFontInfo, QFontDatabase, {Character Map Example}
539
*/
540
541
/*!
542
    \internal
543
    \enum QFont::ResolveProperties
544
545
    This enum describes the properties of a QFont that can be set on a font
546
    individually and then considered resolved.
547
548
    \value FamilyResolved
549
    \value FamiliesResolved
550
    \value SizeResolved
551
    \value StyleHintResolved
552
    \value StyleStrategyResolved
553
    \value WeightResolved
554
    \value StyleResolved
555
    \value UnderlineResolved
556
    \value OverlineResolved
557
    \value StrikeOutResolved
558
    \value FixedPitchResolved
559
    \value StretchResolved
560
    \value KerningResolved
561
    \value CapitalizationResolved
562
    \value LetterSpacingResolved
563
    \value WordSpacingResolved
564
    \value CompletelyResolved
565
*/
566
567
/*!
568
    \enum QFont::Style
569
570
    This enum describes the different styles of glyphs that are used to
571
    display text.
572
573
    \value StyleNormal  Normal glyphs used in unstyled text.
574
    \value StyleItalic  Italic glyphs that are specifically designed for
575
                        the purpose of representing italicized text.
576
    \value StyleOblique Glyphs with an italic appearance that are typically
577
                        based on the unstyled glyphs, but are not fine-tuned
578
                        for the purpose of representing italicized text.
579
580
    \sa Weight
581
*/
582
583
/*!
584
    \fn QFont &QFont::operator=(QFont &&other)
585
586
    Move-assigns \a other to this QFont instance.
587
588
    \since 5.2
589
*/
590
591
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
592
/*!
593
  \obsolete
594
  Constructs a font from \a font for use on the paint device \a pd.
595
*/
596
QFont::QFont(const QFont &font, QPaintDevice *pd)
597
1.58k
    : QFont(font, static_cast<const QPaintDevice*>(pd))
598
1.58k
{}
599
#endif
600
601
/*!
602
  \since 5.13
603
  Constructs a font from \a font for use on the paint device \a pd.
604
*/
605
QFont::QFont(const QFont &font, const QPaintDevice *pd)
606
1.58k
    : resolve_mask(font.resolve_mask)
607
1.58k
{
608
1.58k
    Q_ASSERT(pd);
609
1.58k
    const int dpi = pd->logicalDpiY();
610
1.58k
    if (font.d->dpi != dpi) {
611
0
        d = new QFontPrivate(*font.d);
612
0
        d->dpi = dpi;
613
1.58k
    } else {
614
1.58k
        d = font.d;
615
1.58k
    }
616
1.58k
}
617
618
/*!
619
  \internal
620
*/
621
QFont::QFont(QFontPrivate *data)
622
0
    : d(data), resolve_mask(QFont::AllPropertiesResolved)
623
0
{
624
0
}
625
626
/*! \internal
627
    Detaches the font object from common font data.
628
*/
629
void QFont::detach()
630
0
{
631
0
    if (d->ref.loadRelaxed() == 1) {
632
0
        if (d->engineData && !d->engineData->ref.deref())
633
0
            delete d->engineData;
634
0
        d->engineData = nullptr;
635
0
        if (d->scFont && d->scFont != d.data()) {
636
0
            if (!d->scFont->ref.deref())
637
0
                delete d->scFont;
638
0
        }
639
0
        d->scFont = nullptr;
640
0
        return;
641
0
    }
642
643
0
    d.detach();
644
0
}
645
646
/*!
647
    \internal
648
    Detaches the font object from common font attributes data.
649
    Call this instead of QFont::detach() if the only font attributes data
650
    has been changed (underline, letterSpacing, kerning, etc.).
651
*/
652
void QFontPrivate::detachButKeepEngineData(QFont *font)
653
0
{
654
0
    if (font->d->ref.loadRelaxed() == 1)
655
0
        return;
656
657
0
    QFontEngineData *engineData = font->d->engineData;
658
0
    if (engineData)
659
0
        engineData->ref.ref();
660
0
    font->d.detach();
661
0
    font->d->engineData = engineData;
662
0
}
663
664
/*!
665
    Constructs a font object that uses the application's default font.
666
667
    \sa QGuiApplication::setFont(), QGuiApplication::font()
668
*/
669
QFont::QFont()
670
3.16k
    : d(QGuiApplicationPrivate::instance() ? QGuiApplication::font().d.data() : new QFontPrivate()), resolve_mask(0)
671
3.16k
{
672
3.16k
}
673
674
/*!
675
    Constructs a font object with the specified \a family, \a
676
    pointSize, \a weight and \a italic settings.
677
678
    If \a pointSize is zero or negative, the point size of the font
679
    is set to a system-dependent default value. Generally, this is
680
    12 points.
681
682
    The \a family name may optionally also include a foundry name,
683
    e.g. "Helvetica [Cronyx]". If the \a family is
684
    available from more than one foundry and the foundry isn't
685
    specified, an arbitrary foundry is chosen. If the family isn't
686
    available a family will be set using the \l{QFont}{font matching}
687
    algorithm.
688
689
    \sa Weight, setFamily(), setPointSize(), setWeight(), setItalic(),
690
    setStyleHint(), QGuiApplication::font()
691
*/
692
QFont::QFont(const QString &family, int pointSize, int weight, bool italic)
693
4.86k
    : d(new QFontPrivate()), resolve_mask(QFont::FamilyResolved)
694
4.86k
{
695
4.86k
    if (pointSize <= 0) {
696
0
        pointSize = 12;
697
4.86k
    } else {
698
4.86k
        resolve_mask |= QFont::SizeResolved;
699
4.86k
    }
700
701
4.86k
    if (weight < 0) {
702
4.86k
        weight = Normal;
703
4.86k
    } else {
704
0
        resolve_mask |= QFont::WeightResolved | QFont::StyleResolved;
705
0
    }
706
707
4.86k
    if (italic)
708
0
        resolve_mask |= QFont::StyleResolved;
709
710
4.86k
    d->request.family = family;
711
4.86k
    d->request.pointSize = qreal(pointSize);
712
4.86k
    d->request.pixelSize = -1;
713
4.86k
    d->request.weight = weight;
714
4.86k
    d->request.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
715
4.86k
}
716
717
/*!
718
    Constructs a font that is a copy of \a font.
719
*/
720
QFont::QFont(const QFont &font)
721
6.98k
    : d(font.d), resolve_mask(font.resolve_mask)
722
6.98k
{
723
6.98k
}
724
725
/*!
726
    Destroys the font object and frees all allocated resources.
727
*/
728
QFont::~QFont()
729
16.5k
{
730
16.5k
}
731
732
/*!
733
    Assigns \a font to this font and returns a reference to it.
734
*/
735
QFont &QFont::operator=(const QFont &font)
736
1.58k
{
737
1.58k
    d = font.d;
738
1.58k
    resolve_mask = font.resolve_mask;
739
1.58k
    return *this;
740
1.58k
}
741
742
/*!
743
    \fn void QFont::swap(QFont &other)
744
    \since 5.0
745
746
    Swaps this font instance with \a other. This function is very fast
747
    and never fails.
748
*/
749
750
/*!
751
    Returns the requested font family name, i.e. the name set in the
752
    constructor or the last setFont() call.
753
754
    \sa setFamily(), substitutes(), substitute()
755
*/
756
QString QFont::family() const
757
16.6k
{
758
16.6k
    return d->request.family;
759
16.6k
}
760
761
/*!
762
    Sets the family name of the font. The name is case insensitive and
763
    may include a foundry name.
764
765
    The \a family name may optionally also include a foundry name,
766
    e.g. "Helvetica [Cronyx]". If the \a family is
767
    available from more than one foundry and the foundry isn't
768
    specified, an arbitrary foundry is chosen. If the family isn't
769
    available a family will be set using the \l{QFont}{font matching}
770
    algorithm.
771
772
    \sa family(), setStyleHint(), QFontInfo
773
*/
774
void QFont::setFamily(const QString &family)
775
0
{
776
0
    if ((resolve_mask & QFont::FamilyResolved) && d->request.family == family)
777
0
        return;
778
779
0
    detach();
780
781
0
    d->request.family = family;
782
783
0
    resolve_mask |= QFont::FamilyResolved;
784
0
}
785
786
/*!
787
    \since 4.8
788
789
    Returns the requested font style name. This can be used to match the
790
    font with irregular styles (that can't be normalized in other style
791
    properties).
792
793
    \sa setFamily(), setStyle()
794
*/
795
QString QFont::styleName() const
796
16.6k
{
797
16.6k
    return d->request.styleName;
798
16.6k
}
799
800
/*!
801
    \since 4.8
802
803
    Sets the style name of the font to \a styleName. When set, other style properties
804
    like \l style() and \l weight() will be ignored for font matching, though they may be
805
    simulated afterwards if supported by the platform's font engine.
806
807
    Due to the lower quality of artificially simulated styles, and the lack of full cross
808
    platform support, it is not recommended to use matching by style name together with
809
    matching by style properties
810
811
    \sa styleName()
812
*/
813
void QFont::setStyleName(const QString &styleName)
814
0
{
815
0
    if ((resolve_mask & QFont::StyleNameResolved) && d->request.styleName == styleName)
816
0
        return;
817
818
0
    detach();
819
820
0
    d->request.styleName = styleName;
821
0
    resolve_mask |= QFont::StyleNameResolved;
822
0
}
823
824
/*!
825
    Returns the point size of the font. Returns -1 if the font size
826
    was specified in pixels.
827
828
    \sa setPointSize(), pointSizeF()
829
*/
830
int QFont::pointSize() const
831
0
{
832
0
    return qRound(d->request.pointSize);
833
0
}
834
835
/*!
836
    \since 4.8
837
838
    \enum QFont::HintingPreference
839
840
    This enum describes the different levels of hinting that can be applied
841
    to glyphs to improve legibility on displays where it might be warranted
842
    by the density of pixels.
843
844
    \value PreferDefaultHinting Use the default hinting level for the target platform.
845
    \value PreferNoHinting If possible, render text without hinting the outlines
846
           of the glyphs. The text layout will be typographically accurate and
847
           scalable, using the same metrics as are used e.g. when printing.
848
    \value PreferVerticalHinting If possible, render text with no horizontal hinting,
849
           but align glyphs to the pixel grid in the vertical direction. The text will appear
850
           crisper on displays where the density is too low to give an accurate rendering
851
           of the glyphs. But since the horizontal metrics of the glyphs are unhinted, the text's
852
           layout will be scalable to higher density devices (such as printers) without impacting
853
           details such as line breaks.
854
    \value PreferFullHinting If possible, render text with hinting in both horizontal and
855
           vertical directions. The text will be altered to optimize legibility on the target
856
           device, but since the metrics will depend on the target size of the text, the positions
857
           of glyphs, line breaks, and other typographical detail will not scale, meaning that a
858
           text layout may look different on devices with different pixel densities.
859
860
    Please note that this enum only describes a preference, as the full range of hinting levels
861
    are not supported on all of Qt's supported platforms. The following table details the effect
862
    of a given hinting preference on a selected set of target platforms.
863
864
    \table
865
    \header
866
    \li
867
    \li PreferDefaultHinting
868
    \li PreferNoHinting
869
    \li PreferVerticalHinting
870
    \li PreferFullHinting
871
    \row
872
    \li Windows Vista (w/o Platform Update) and earlier
873
    \li Full hinting
874
    \li Full hinting
875
    \li Full hinting
876
    \li Full hinting
877
    \row
878
    \li Windows 7 and Windows Vista (w/Platform Update) and DirectWrite enabled in Qt
879
    \li Full hinting
880
    \li Vertical hinting
881
    \li Vertical hinting
882
    \li Full hinting
883
    \row
884
    \li FreeType
885
    \li Operating System setting
886
    \li No hinting
887
    \li Vertical hinting (light)
888
    \li Full hinting
889
    \row
890
    \li Cocoa on \macos
891
    \li No hinting
892
    \li No hinting
893
    \li No hinting
894
    \li No hinting
895
    \endtable
896
897
    \note Please be aware that altering the hinting preference on Windows is available through
898
    the DirectWrite font engine. This is available on Windows Vista after installing the platform
899
    update, and on Windows 7. In order to use this extension, configure Qt using -directwrite.
900
    The target application will then depend on the availability of DirectWrite on the target
901
    system.
902
903
*/
904
905
/*!
906
    \since 4.8
907
908
    Set the preference for the hinting level of the glyphs to \a hintingPreference. This is a hint
909
    to the underlying font rendering system to use a certain level of hinting, and has varying
910
    support across platforms. See the table in the documentation for QFont::HintingPreference for
911
    more details.
912
913
    The default hinting preference is QFont::PreferDefaultHinting.
914
*/
915
void QFont::setHintingPreference(HintingPreference hintingPreference)
916
0
{
917
0
    if ((resolve_mask & QFont::HintingPreferenceResolved) && d->request.hintingPreference == hintingPreference)
918
0
        return;
919
920
0
    detach();
921
922
0
    d->request.hintingPreference = hintingPreference;
923
924
0
    resolve_mask |= QFont::HintingPreferenceResolved;
925
0
}
926
927
/*!
928
    \since 4.8
929
930
    Returns the currently preferred hinting level for glyphs rendered with this font.
931
*/
932
QFont::HintingPreference QFont::hintingPreference() const
933
0
{
934
0
    return QFont::HintingPreference(d->request.hintingPreference);
935
0
}
936
937
/*!
938
    Sets the point size to \a pointSize. The point size must be
939
    greater than zero.
940
941
    \sa pointSize(), setPointSizeF()
942
*/
943
void QFont::setPointSize(int pointSize)
944
0
{
945
0
    if (pointSize <= 0) {
946
0
        qWarning("QFont::setPointSize: Point size <= 0 (%d), must be greater than 0", pointSize);
947
0
        return;
948
0
    }
949
950
0
    if ((resolve_mask & QFont::SizeResolved) && d->request.pointSize == qreal(pointSize))
951
0
        return;
952
953
0
    detach();
954
955
0
    d->request.pointSize = qreal(pointSize);
956
0
    d->request.pixelSize = -1;
957
958
0
    resolve_mask |= QFont::SizeResolved;
959
0
}
960
961
/*!
962
    Sets the point size to \a pointSize. The point size must be
963
    greater than zero. The requested precision may not be achieved on
964
    all platforms.
965
966
    \sa pointSizeF(), setPointSize(), setPixelSize()
967
*/
968
void QFont::setPointSizeF(qreal pointSize)
969
0
{
970
0
    if (pointSize <= 0) {
971
0
        qWarning("QFont::setPointSizeF: Point size <= 0 (%f), must be greater than 0", pointSize);
972
0
        return;
973
0
    }
974
975
0
    if ((resolve_mask & QFont::SizeResolved) && d->request.pointSize == pointSize)
976
0
        return;
977
978
0
    detach();
979
980
0
    d->request.pointSize = pointSize;
981
0
    d->request.pixelSize = -1;
982
983
0
    resolve_mask |= QFont::SizeResolved;
984
0
}
985
986
/*!
987
    Returns the point size of the font. Returns -1 if the font size was
988
    specified in pixels.
989
990
    \sa pointSize(), setPointSizeF(), pixelSize(), QFontInfo::pointSize(), QFontInfo::pixelSize()
991
*/
992
qreal QFont::pointSizeF() const
993
20.9k
{
994
20.9k
    return d->request.pointSize;
995
20.9k
}
996
997
/*!
998
    Sets the font size to \a pixelSize pixels.
999
1000
    Using this function makes the font device dependent. Use
1001
    setPointSize() or setPointSizeF() to set the size of the font
1002
    in a device independent manner.
1003
1004
    \sa pixelSize()
1005
*/
1006
void QFont::setPixelSize(int pixelSize)
1007
0
{
1008
0
    if (pixelSize <= 0) {
1009
0
        qWarning("QFont::setPixelSize: Pixel size <= 0 (%d)", pixelSize);
1010
0
        return;
1011
0
    }
1012
1013
0
    if ((resolve_mask & QFont::SizeResolved) && d->request.pixelSize == qreal(pixelSize))
1014
0
        return;
1015
1016
0
    detach();
1017
1018
0
    d->request.pixelSize = pixelSize;
1019
0
    d->request.pointSize = -1;
1020
1021
0
    resolve_mask |= QFont::SizeResolved;
1022
0
}
1023
1024
/*!
1025
    Returns the pixel size of the font if it was set with
1026
    setPixelSize(). Returns -1 if the size was set with setPointSize()
1027
    or setPointSizeF().
1028
1029
    \sa setPixelSize(), pointSize(), QFontInfo::pointSize(), QFontInfo::pixelSize()
1030
*/
1031
int QFont::pixelSize() const
1032
0
{
1033
0
    return d->request.pixelSize;
1034
0
}
1035
1036
/*!
1037
  \fn bool QFont::italic() const
1038
1039
    Returns \c true if the style() of the font is not QFont::StyleNormal
1040
1041
    \sa setItalic(), style()
1042
*/
1043
1044
/*!
1045
  \fn void QFont::setItalic(bool enable)
1046
1047
  Sets the style() of the font to QFont::StyleItalic if \a enable is true;
1048
  otherwise the style is set to QFont::StyleNormal.
1049
1050
  \note If styleName() is set, this value may be ignored, or if supported
1051
  on the platform, the font may be rendered tilted instead of picking a
1052
  designed italic font-variant.
1053
1054
  \sa italic(), QFontInfo
1055
*/
1056
1057
/*!
1058
    Returns the style of the font.
1059
1060
    \sa setStyle()
1061
*/
1062
QFont::Style QFont::style() const
1063
0
{
1064
0
    return (QFont::Style)d->request.style;
1065
0
}
1066
1067
1068
/*!
1069
  Sets the style of the font to \a style.
1070
1071
  \sa italic(), QFontInfo
1072
*/
1073
void QFont::setStyle(Style style)
1074
0
{
1075
0
    if ((resolve_mask & QFont::StyleResolved) && d->request.style == style)
1076
0
        return;
1077
1078
0
    detach();
1079
1080
0
    d->request.style = style;
1081
0
    resolve_mask |= QFont::StyleResolved;
1082
0
}
1083
1084
/*!
1085
    Returns the weight of the font, using the same scale as the
1086
    \l{QFont::Weight} enumeration.
1087
1088
    \sa setWeight(), Weight, QFontInfo
1089
*/
1090
int QFont::weight() const
1091
0
{
1092
0
    return d->request.weight;
1093
0
}
1094
1095
/*!
1096
    \enum QFont::Weight
1097
1098
    Qt uses a weighting scale from 0 to 99 similar to, but not the
1099
    same as, the scales used in Windows or CSS. A weight of 0 will be
1100
    thin, whilst 99 will be extremely black.
1101
1102
    This enum contains the predefined font weights:
1103
1104
    \value Thin 0
1105
    \value ExtraLight 12
1106
    \value Light 25
1107
    \value Normal 50
1108
    \value Medium 57
1109
    \value DemiBold 63
1110
    \value Bold 75
1111
    \value ExtraBold 81
1112
    \value Black 87
1113
*/
1114
1115
/*!
1116
    Sets the weight of the font to \a weight, using the scale defined by
1117
    \l QFont::Weight enumeration.
1118
1119
    \note If styleName() is set, this value may be ignored for font selection.
1120
1121
    \sa weight(), QFontInfo
1122
*/
1123
void QFont::setWeight(int weight)
1124
0
{
1125
0
    Q_ASSERT_X(weight >= 0 && weight <= 99, "QFont::setWeight", "Weight must be between 0 and 99");
1126
1127
0
    if ((resolve_mask & QFont::WeightResolved) && d->request.weight == weight)
1128
0
        return;
1129
1130
0
    detach();
1131
1132
0
    d->request.weight = weight;
1133
0
    resolve_mask |= QFont::WeightResolved;
1134
0
}
1135
1136
/*!
1137
    \fn bool QFont::bold() const
1138
1139
    Returns \c true if weight() is a value greater than
1140
   \l{Weight}{QFont::Medium}; otherwise returns \c false.
1141
1142
    \sa weight(), setBold(), QFontInfo::bold()
1143
*/
1144
1145
/*!
1146
    \fn void QFont::setBold(bool enable)
1147
1148
    If \a enable is true sets the font's weight to
1149
    \l{Weight}{QFont::Bold};
1150
    otherwise sets the weight to \l{Weight}{QFont::Normal}.
1151
1152
    For finer boldness control use setWeight().
1153
1154
    \note If styleName() is set, this value may be ignored, or if supported
1155
    on the platform, the font artificially embolded.
1156
1157
    \sa bold(), setWeight()
1158
*/
1159
1160
/*!
1161
    Returns \c true if underline has been set; otherwise returns \c false.
1162
1163
    \sa setUnderline()
1164
*/
1165
bool QFont::underline() const
1166
0
{
1167
0
    return d->underline;
1168
0
}
1169
1170
/*!
1171
    If \a enable is true, sets underline on; otherwise sets underline
1172
    off.
1173
1174
    \sa underline(), QFontInfo
1175
*/
1176
void QFont::setUnderline(bool enable)
1177
0
{
1178
0
    if ((resolve_mask & QFont::UnderlineResolved) && d->underline == enable)
1179
0
        return;
1180
1181
0
    QFontPrivate::detachButKeepEngineData(this);
1182
1183
0
    d->underline = enable;
1184
0
    resolve_mask |= QFont::UnderlineResolved;
1185
0
}
1186
1187
/*!
1188
    Returns \c true if overline has been set; otherwise returns \c false.
1189
1190
    \sa setOverline()
1191
*/
1192
bool QFont::overline() const
1193
0
{
1194
0
    return d->overline;
1195
0
}
1196
1197
/*!
1198
  If \a enable is true, sets overline on; otherwise sets overline off.
1199
1200
  \sa overline(), QFontInfo
1201
*/
1202
void QFont::setOverline(bool enable)
1203
0
{
1204
0
    if ((resolve_mask & QFont::OverlineResolved) && d->overline == enable)
1205
0
        return;
1206
1207
0
    QFontPrivate::detachButKeepEngineData(this);
1208
1209
0
    d->overline = enable;
1210
0
    resolve_mask |= QFont::OverlineResolved;
1211
0
}
1212
1213
/*!
1214
    Returns \c true if strikeout has been set; otherwise returns \c false.
1215
1216
    \sa setStrikeOut()
1217
*/
1218
bool QFont::strikeOut() const
1219
0
{
1220
0
    return d->strikeOut;
1221
0
}
1222
1223
/*!
1224
    If \a enable is true, sets strikeout on; otherwise sets strikeout
1225
    off.
1226
1227
    \sa strikeOut(), QFontInfo
1228
*/
1229
void QFont::setStrikeOut(bool enable)
1230
0
{
1231
0
    if ((resolve_mask & QFont::StrikeOutResolved) && d->strikeOut == enable)
1232
0
        return;
1233
1234
0
    QFontPrivate::detachButKeepEngineData(this);
1235
1236
0
    d->strikeOut = enable;
1237
0
    resolve_mask |= QFont::StrikeOutResolved;
1238
0
}
1239
1240
/*!
1241
    Returns \c true if fixed pitch has been set; otherwise returns \c false.
1242
1243
    \sa setFixedPitch(), QFontInfo::fixedPitch()
1244
*/
1245
bool QFont::fixedPitch() const
1246
0
{
1247
0
    return d->request.fixedPitch;
1248
0
}
1249
1250
/*!
1251
    If \a enable is true, sets fixed pitch on; otherwise sets fixed
1252
    pitch off.
1253
1254
    \sa fixedPitch(), QFontInfo
1255
*/
1256
void QFont::setFixedPitch(bool enable)
1257
0
{
1258
0
    if ((resolve_mask & QFont::FixedPitchResolved) && d->request.fixedPitch == enable)
1259
0
        return;
1260
1261
0
    detach();
1262
1263
0
    d->request.fixedPitch = enable;
1264
0
    d->request.ignorePitch = false;
1265
0
    resolve_mask |= QFont::FixedPitchResolved;
1266
0
}
1267
1268
/*!
1269
  Returns \c true if kerning should be used when drawing text with this font.
1270
1271
  \sa setKerning()
1272
*/
1273
bool QFont::kerning() const
1274
0
{
1275
0
    return d->kerning;
1276
0
}
1277
1278
/*!
1279
    Enables kerning for this font if \a enable is true; otherwise
1280
    disables it. By default, kerning is enabled.
1281
1282
    When kerning is enabled, glyph metrics do not add up anymore,
1283
    even for Latin text. In other words, the assumption that
1284
    width('a') + width('b') is equal to width("ab") is not
1285
    necessarily true.
1286
1287
    \sa kerning(), QFontMetrics
1288
*/
1289
void QFont::setKerning(bool enable)
1290
0
{
1291
0
    if ((resolve_mask & QFont::KerningResolved) && d->kerning == enable)
1292
0
        return;
1293
1294
0
    QFontPrivate::detachButKeepEngineData(this);
1295
1296
0
    d->kerning = enable;
1297
0
    resolve_mask |= QFont::KerningResolved;
1298
0
}
1299
1300
/*!
1301
    Returns the StyleStrategy.
1302
1303
    The style strategy affects the \l{QFont}{font matching} algorithm.
1304
    See \l QFont::StyleStrategy for the list of available strategies.
1305
1306
    \sa setStyleHint(), QFont::StyleHint
1307
*/
1308
QFont::StyleStrategy QFont::styleStrategy() const
1309
0
{
1310
0
    return (StyleStrategy) d->request.styleStrategy;
1311
0
}
1312
1313
/*!
1314
    Returns the StyleHint.
1315
1316
    The style hint affects the \l{QFont#fontmatching}{font matching algorithm}.
1317
    See \l QFont::StyleHint for the list of available hints.
1318
1319
    \sa setStyleHint(), QFont::StyleStrategy, QFontInfo::styleHint()
1320
*/
1321
QFont::StyleHint QFont::styleHint() const
1322
0
{
1323
0
    return (StyleHint) d->request.styleHint;
1324
0
}
1325
1326
/*!
1327
    \enum QFont::StyleHint
1328
1329
    Style hints are used by the \l{QFont}{font matching} algorithm to
1330
    find an appropriate default family if a selected font family is
1331
    not available.
1332
1333
    \value AnyStyle leaves the font matching algorithm to choose the
1334
           family. This is the default.
1335
1336
    \value SansSerif the font matcher prefer sans serif fonts.
1337
    \value Helvetica is a synonym for \c SansSerif.
1338
1339
    \value Serif the font matcher prefers serif fonts.
1340
    \value Times is a synonym for \c Serif.
1341
1342
    \value TypeWriter the font matcher prefers fixed pitch fonts.
1343
    \value Courier a synonym for \c TypeWriter.
1344
1345
    \value OldEnglish the font matcher prefers decorative fonts.
1346
    \value Decorative is a synonym for \c OldEnglish.
1347
1348
    \value Monospace the font matcher prefers fonts that map to the
1349
    CSS generic font-family 'monospace'.
1350
1351
    \value Fantasy the font matcher prefers fonts that map to the
1352
    CSS generic font-family 'fantasy'.
1353
1354
    \value Cursive the font matcher prefers fonts that map to the
1355
    CSS generic font-family 'cursive'.
1356
1357
    \value System the font matcher prefers system fonts.
1358
*/
1359
1360
/*!
1361
    \enum QFont::StyleStrategy
1362
1363
    The style strategy tells the \l{QFont}{font matching} algorithm
1364
    what type of fonts should be used to find an appropriate default
1365
    family.
1366
1367
    The following strategies are available:
1368
1369
    \value PreferDefault the default style strategy. It does not prefer
1370
           any type of font.
1371
    \value PreferBitmap prefers bitmap fonts (as opposed to outline
1372
           fonts).
1373
    \value PreferDevice prefers device fonts.
1374
    \value PreferOutline prefers outline fonts (as opposed to bitmap fonts).
1375
    \value ForceOutline forces the use of outline fonts.
1376
    \value NoAntialias don't antialias the fonts.
1377
    \value NoSubpixelAntialias avoid subpixel antialiasing on the fonts if possible.
1378
    \value PreferAntialias antialias if possible.
1379
    \value OpenGLCompatible This style strategy has been deprecated since Qt 5.15.0. All
1380
           fonts are OpenGL-compatible by default.
1381
    \value NoFontMerging If the font selected for a certain writing system
1382
           does not contain a character requested to draw, then Qt automatically chooses a similar
1383
           looking font that contains the character. The NoFontMerging flag disables this feature.
1384
           Please note that enabling this flag will not prevent Qt from automatically picking a
1385
           suitable font when the selected font does not support the writing system of the text.
1386
    \value PreferNoShaping Sometimes, a font will apply complex rules to a set of characters in
1387
           order to display them correctly. In some writing systems, such as Brahmic scripts, this is
1388
           required in order for the text to be legible, but in e.g. Latin script, it is merely
1389
           a cosmetic feature. The PreferNoShaping flag will disable all such features when they
1390
           are not required, which will improve performance in most cases (since Qt 5.10).
1391
1392
    Any of these may be OR-ed with one of these flags:
1393
1394
    \value PreferMatch prefer an exact match. The font matcher will try to
1395
           use the exact font size that has been specified.
1396
    \value PreferQuality prefer the best quality font. The font matcher
1397
           will use the nearest standard point size that the font
1398
           supports.
1399
    \value ForceIntegerMetrics This style strategy has been deprecated since Qt 5.15.0. Use
1400
           \l QFontMetrics to retrieve rounded font metrics.
1401
*/
1402
1403
/*!
1404
    Sets the style hint and strategy to \a hint and \a strategy,
1405
    respectively.
1406
1407
    If these aren't set explicitly the style hint will default to
1408
    \c AnyStyle and the style strategy to \c PreferDefault.
1409
1410
    Qt does not support style hints on X11 since this information
1411
    is not provided by the window system.
1412
1413
    \sa StyleHint, styleHint(), StyleStrategy, styleStrategy(), QFontInfo
1414
*/
1415
void QFont::setStyleHint(StyleHint hint, StyleStrategy strategy)
1416
0
{
1417
0
    if ((resolve_mask & (QFont::StyleHintResolved | QFont::StyleStrategyResolved)) &&
1418
0
         (StyleHint) d->request.styleHint == hint &&
1419
0
         (StyleStrategy) d->request.styleStrategy == strategy)
1420
0
        return;
1421
1422
0
    detach();
1423
1424
0
    d->request.styleHint = hint;
1425
0
    d->request.styleStrategy = strategy;
1426
0
    resolve_mask |= QFont::StyleHintResolved;
1427
0
    resolve_mask |= QFont::StyleStrategyResolved;
1428
1429
0
}
1430
1431
/*!
1432
    Sets the style strategy for the font to \a s.
1433
1434
    \sa QFont::StyleStrategy
1435
*/
1436
void QFont::setStyleStrategy(StyleStrategy s)
1437
0
{
1438
0
    if ((resolve_mask & QFont::StyleStrategyResolved) &&
1439
0
         s == (StyleStrategy)d->request.styleStrategy)
1440
0
        return;
1441
1442
0
    detach();
1443
1444
0
    d->request.styleStrategy = s;
1445
0
    resolve_mask |= QFont::StyleStrategyResolved;
1446
0
}
1447
1448
1449
/*!
1450
    \enum QFont::Stretch
1451
1452
    Predefined stretch values that follow the CSS naming convention. The higher
1453
    the value, the more stretched the text is.
1454
1455
    \value AnyStretch 0 Accept any stretch matched using the other QFont properties (added in Qt 5.8)
1456
    \value UltraCondensed 50
1457
    \value ExtraCondensed 62
1458
    \value Condensed 75
1459
    \value SemiCondensed 87
1460
    \value Unstretched 100
1461
    \value SemiExpanded 112
1462
    \value Expanded 125
1463
    \value ExtraExpanded 150
1464
    \value UltraExpanded 200
1465
1466
    \sa setStretch(), stretch()
1467
*/
1468
1469
/*!
1470
    Returns the stretch factor for the font.
1471
1472
    \sa setStretch()
1473
 */
1474
int QFont::stretch() const
1475
0
{
1476
0
    return d->request.stretch;
1477
0
}
1478
1479
/*!
1480
    Sets the stretch factor for the font.
1481
1482
    The stretch factor matches a condensed or expanded version of the font or
1483
    applies a stretch transform that changes the width of all characters
1484
    in the font by \a factor percent.  For example, setting \a factor to 150
1485
    results in all characters in the font being 1.5 times (ie. 150%)
1486
    wider.  The minimum stretch factor is 1, and the maximum stretch factor
1487
    is 4000.  The default stretch factor is \c AnyStretch, which will accept
1488
    any stretch factor and not apply any transform on the font.
1489
1490
    The stretch factor is only applied to outline fonts.  The stretch
1491
    factor is ignored for bitmap fonts.
1492
1493
    \note When matching a font with a native non-default stretch factor,
1494
    requesting a stretch of 100 will stretch it back to a medium width font.
1495
1496
    \sa stretch(), QFont::Stretch
1497
*/
1498
void QFont::setStretch(int factor)
1499
0
{
1500
0
    if (factor < 0 || factor > 4000) {
1501
0
        qWarning("QFont::setStretch: Parameter '%d' out of range", factor);
1502
0
        return;
1503
0
    }
1504
1505
0
    if ((resolve_mask & QFont::StretchResolved) &&
1506
0
         d->request.stretch == (uint)factor)
1507
0
        return;
1508
1509
0
    detach();
1510
1511
0
    d->request.stretch = (uint)factor;
1512
0
    resolve_mask |= QFont::StretchResolved;
1513
0
}
1514
1515
/*!
1516
    \enum QFont::SpacingType
1517
    \since 4.4
1518
1519
    \value PercentageSpacing  A value of 100 will keep the spacing unchanged; a value of 200 will enlarge the
1520
                                                   spacing after a character by the width of the character itself.
1521
    \value AbsoluteSpacing      A positive value increases the letter spacing by the corresponding pixels; a negative
1522
                                                   value decreases the spacing.
1523
*/
1524
1525
/*!
1526
    \since 4.4
1527
    Returns the letter spacing for the font.
1528
1529
    \sa setLetterSpacing(), letterSpacingType(), setWordSpacing()
1530
 */
1531
qreal QFont::letterSpacing() const
1532
0
{
1533
0
    return d->letterSpacing.toReal();
1534
0
}
1535
1536
/*!
1537
    \since 4.4
1538
    Sets the letter spacing for the font to \a spacing and the type
1539
    of spacing to \a type.
1540
1541
    Letter spacing changes the default spacing between individual
1542
    letters in the font.  The spacing between the letters can be
1543
    made smaller as well as larger either in percentage of the
1544
    character width or in pixels, depending on the selected spacing type.
1545
1546
    \sa letterSpacing(), letterSpacingType(), setWordSpacing()
1547
*/
1548
void QFont::setLetterSpacing(SpacingType type, qreal spacing)
1549
0
{
1550
0
    const QFixed newSpacing = QFixed::fromReal(spacing);
1551
0
    const bool absoluteSpacing = type == AbsoluteSpacing;
1552
0
    if ((resolve_mask & QFont::LetterSpacingResolved) &&
1553
0
        d->letterSpacingIsAbsolute == absoluteSpacing &&
1554
0
        d->letterSpacing == newSpacing)
1555
0
        return;
1556
1557
0
    QFontPrivate::detachButKeepEngineData(this);
1558
1559
0
    d->letterSpacing = newSpacing;
1560
0
    d->letterSpacingIsAbsolute = absoluteSpacing;
1561
0
    resolve_mask |= QFont::LetterSpacingResolved;
1562
0
}
1563
1564
/*!
1565
    \since 4.4
1566
    Returns the spacing type used for letter spacing.
1567
1568
    \sa letterSpacing(), setLetterSpacing(), setWordSpacing()
1569
*/
1570
QFont::SpacingType QFont::letterSpacingType() const
1571
0
{
1572
0
    return d->letterSpacingIsAbsolute ? AbsoluteSpacing : PercentageSpacing;
1573
0
}
1574
1575
/*!
1576
    \since 4.4
1577
    Returns the word spacing for the font.
1578
1579
    \sa setWordSpacing(), setLetterSpacing()
1580
 */
1581
qreal QFont::wordSpacing() const
1582
0
{
1583
0
    return d->wordSpacing.toReal();
1584
0
}
1585
1586
/*!
1587
    \since 4.4
1588
    Sets the word spacing for the font to \a spacing.
1589
1590
    Word spacing changes the default spacing between individual
1591
    words. A positive value increases the word spacing
1592
    by a corresponding amount of pixels, while a negative value
1593
    decreases the inter-word spacing accordingly.
1594
1595
    Word spacing will not apply to writing systems, where indiviaul
1596
    words are not separated by white space.
1597
1598
    \sa wordSpacing(), setLetterSpacing()
1599
*/
1600
void QFont::setWordSpacing(qreal spacing)
1601
0
{
1602
0
    const QFixed newSpacing = QFixed::fromReal(spacing);
1603
0
    if ((resolve_mask & QFont::WordSpacingResolved) &&
1604
0
        d->wordSpacing == newSpacing)
1605
0
        return;
1606
1607
0
    QFontPrivate::detachButKeepEngineData(this);
1608
1609
0
    d->wordSpacing = newSpacing;
1610
0
    resolve_mask |= QFont::WordSpacingResolved;
1611
0
}
1612
1613
/*!
1614
    \enum QFont::Capitalization
1615
    \since 4.4
1616
1617
    Rendering option for text this font applies to.
1618
1619
1620
    \value MixedCase    This is the normal text rendering option where no capitalization change is applied.
1621
    \value AllUppercase This alters the text to be rendered in all uppercase type.
1622
    \value AllLowercase This alters the text to be rendered in all lowercase type.
1623
    \value SmallCaps    This alters the text to be rendered in small-caps type.
1624
    \value Capitalize   This alters the text to be rendered with the first character of each word as an uppercase character.
1625
*/
1626
1627
/*!
1628
    \since 4.4
1629
    Sets the capitalization of the text in this font to \a caps.
1630
1631
    A font's capitalization makes the text appear in the selected capitalization mode.
1632
1633
    \sa capitalization()
1634
*/
1635
void QFont::setCapitalization(Capitalization caps)
1636
0
{
1637
0
    if ((resolve_mask & QFont::CapitalizationResolved) &&
1638
0
        capitalization() == caps)
1639
0
        return;
1640
1641
0
    QFontPrivate::detachButKeepEngineData(this);
1642
1643
0
    d->capital = caps;
1644
0
    resolve_mask |= QFont::CapitalizationResolved;
1645
0
}
1646
1647
/*!
1648
    \since 4.4
1649
    Returns the current capitalization type of the font.
1650
1651
    \sa setCapitalization()
1652
*/
1653
QFont::Capitalization QFont::capitalization() const
1654
0
{
1655
0
    return static_cast<QFont::Capitalization> (d->capital);
1656
0
}
1657
1658
#if QT_DEPRECATED_SINCE(5, 5)
1659
/*!
1660
    \fn void QFont::setRawMode(bool enable)
1661
    \deprecated
1662
1663
    If \a enable is true, turns raw mode on; otherwise turns raw mode
1664
    off. This function only has an effect under X11.
1665
1666
    If raw mode is enabled, Qt will search for an X font with a
1667
    complete font name matching the family name, ignoring all other
1668
    values set for the QFont. If the font name matches several fonts,
1669
    Qt will use the first font returned by X. QFontInfo \e cannot be
1670
    used to fetch information about a QFont using raw mode (it will
1671
    return the values set in the QFont for all parameters, including
1672
    the family name).
1673
1674
    \warning Enabling raw mode has no effect since Qt 5.0.
1675
1676
    \sa rawMode()
1677
*/
1678
void QFont::setRawMode(bool)
1679
0
{
1680
0
}
1681
#endif
1682
1683
/*!
1684
    Returns \c true if a window system font exactly matching the settings
1685
    of this font is available.
1686
1687
    \sa QFontInfo
1688
*/
1689
bool QFont::exactMatch() const
1690
0
{
1691
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
1692
0
    Q_ASSERT(engine != nullptr);
1693
0
    return d->request.exactMatch(engine->fontDef);
1694
0
}
1695
1696
/*!
1697
    Returns \c true if this font is equal to \a f; otherwise returns
1698
    false.
1699
1700
    Two QFonts are considered equal if their font attributes are
1701
    equal.
1702
1703
    \sa operator!=(), isCopyOf()
1704
*/
1705
bool QFont::operator==(const QFont &f) const
1706
0
{
1707
0
    return (f.d == d
1708
0
            || (f.d->request   == d->request
1709
0
                && f.d->request.pointSize == d->request.pointSize
1710
0
                && f.d->underline == d->underline
1711
0
                && f.d->overline  == d->overline
1712
0
                && f.d->strikeOut == d->strikeOut
1713
0
                && f.d->kerning == d->kerning
1714
0
                && f.d->capital == d->capital
1715
0
                && f.d->letterSpacingIsAbsolute == d->letterSpacingIsAbsolute
1716
0
                && f.d->letterSpacing == d->letterSpacing
1717
0
                && f.d->wordSpacing == d->wordSpacing
1718
0
            ));
1719
0
}
1720
1721
1722
/*!
1723
    Provides an arbitrary comparison of this font and font \a f.
1724
    All that is guaranteed is that the operator returns \c false if both
1725
    fonts are equal and that (f1 \< f2) == !(f2 \< f1) if the fonts
1726
    are not equal.
1727
1728
    This function is useful in some circumstances, for example if you
1729
    want to use QFont objects as keys in a QMap.
1730
1731
    \sa operator==(), operator!=(), isCopyOf()
1732
*/
1733
bool QFont::operator<(const QFont &f) const
1734
0
{
1735
0
    if (f.d == d) return false;
1736
    // the < operator for fontdefs ignores point sizes.
1737
0
    const QFontDef &r1 = f.d->request;
1738
0
    const QFontDef &r2 = d->request;
1739
0
    if (r1.pointSize != r2.pointSize) return r1.pointSize < r2.pointSize;
1740
0
    if (r1.pixelSize != r2.pixelSize) return r1.pixelSize < r2.pixelSize;
1741
0
    if (r1.weight != r2.weight) return r1.weight < r2.weight;
1742
0
    if (r1.style != r2.style) return r1.style < r2.style;
1743
0
    if (r1.stretch != r2.stretch) return r1.stretch < r2.stretch;
1744
0
    if (r1.styleHint != r2.styleHint) return r1.styleHint < r2.styleHint;
1745
0
    if (r1.styleStrategy != r2.styleStrategy) return r1.styleStrategy < r2.styleStrategy;
1746
0
    if (r1.families != r2.families) return r1.families < r2.families;
1747
0
    if (r1.family != r2.family) return r1.family < r2.family;
1748
0
    if (f.d->capital != d->capital) return f.d->capital < d->capital;
1749
1750
0
    if (f.d->letterSpacingIsAbsolute != d->letterSpacingIsAbsolute) return f.d->letterSpacingIsAbsolute < d->letterSpacingIsAbsolute;
1751
0
    if (f.d->letterSpacing != d->letterSpacing) return f.d->letterSpacing < d->letterSpacing;
1752
0
    if (f.d->wordSpacing != d->wordSpacing) return f.d->wordSpacing < d->wordSpacing;
1753
1754
0
    int f1attrs = (f.d->underline << 3) + (f.d->overline << 2) + (f.d->strikeOut<<1) + f.d->kerning;
1755
0
    int f2attrs = (d->underline << 3) + (d->overline << 2) + (d->strikeOut<<1) + d->kerning;
1756
0
    return f1attrs < f2attrs;
1757
0
}
1758
1759
1760
/*!
1761
    Returns \c true if this font is different from \a f; otherwise
1762
    returns \c false.
1763
1764
    Two QFonts are considered to be different if their font attributes
1765
    are different.
1766
1767
    \sa operator==()
1768
*/
1769
bool QFont::operator!=(const QFont &f) const
1770
0
{
1771
0
    return !(operator==(f));
1772
0
}
1773
1774
/*!
1775
   Returns the font as a QVariant
1776
*/
1777
QFont::operator QVariant() const
1778
0
{
1779
0
    return QVariant(QMetaType::QFont, this);
1780
0
}
1781
1782
/*!
1783
    Returns \c true if this font and \a f are copies of each other, i.e.
1784
    one of them was created as a copy of the other and neither has
1785
    been modified since. This is much stricter than equality.
1786
1787
    \sa operator=(), operator==()
1788
*/
1789
bool QFont::isCopyOf(const QFont & f) const
1790
0
{
1791
0
    return d == f.d;
1792
0
}
1793
1794
#if QT_DEPRECATED_SINCE(5, 5)
1795
/*!
1796
    \deprecated
1797
1798
    Returns \c true if raw mode is used for font name matching; otherwise
1799
    returns \c false.
1800
1801
    \sa setRawMode()
1802
*/
1803
bool QFont::rawMode() const
1804
0
{
1805
0
    return false;
1806
0
}
1807
#endif
1808
1809
/*!
1810
    Returns a new QFont that has attributes copied from \a other that
1811
    have not been previously set on this font.
1812
*/
1813
QFont QFont::resolve(const QFont &other) const
1814
0
{
1815
0
    if (resolve_mask == 0 || (resolve_mask == other.resolve_mask && *this == other)) {
1816
0
        QFont o(other);
1817
0
        o.resolve_mask = resolve_mask;
1818
0
        return o;
1819
0
    }
1820
1821
0
    QFont font(*this);
1822
0
    font.detach();
1823
0
    font.d->resolve(resolve_mask, other.d.data());
1824
1825
0
    return font;
1826
0
}
1827
1828
/*!
1829
    \fn uint QFont::resolve() const
1830
    \internal
1831
*/
1832
1833
/*!
1834
    \fn void QFont::resolve(uint mask)
1835
    \internal
1836
*/
1837
1838
1839
/*****************************************************************************
1840
  QFont substitution management
1841
 *****************************************************************************/
1842
1843
typedef QHash<QString, QStringList> QFontSubst;
1844
Q_GLOBAL_STATIC(QFontSubst, globalFontSubst)
1845
1846
/*!
1847
    Returns the first family name to be used whenever \a familyName is
1848
    specified. The lookup is case insensitive.
1849
1850
    If there is no substitution for \a familyName, \a familyName is
1851
    returned.
1852
1853
    To obtain a list of substitutions use substitutes().
1854
1855
    \sa setFamily(), insertSubstitutions(), insertSubstitution(), removeSubstitutions()
1856
*/
1857
QString QFont::substitute(const QString &familyName)
1858
0
{
1859
0
    QFontSubst *fontSubst = globalFontSubst();
1860
0
    Q_ASSERT(fontSubst != nullptr);
1861
0
    QFontSubst::ConstIterator it = fontSubst->constFind(familyName.toLower());
1862
0
    if (it != fontSubst->constEnd() && !(*it).isEmpty())
1863
0
        return (*it).first();
1864
1865
0
    return familyName;
1866
0
}
1867
1868
1869
/*!
1870
    Returns a list of family names to be used whenever \a familyName
1871
    is specified. The lookup is case insensitive.
1872
1873
    If there is no substitution for \a familyName, an empty list is
1874
    returned.
1875
1876
    \sa substitute(), insertSubstitutions(), insertSubstitution(), removeSubstitutions()
1877
 */
1878
QStringList QFont::substitutes(const QString &familyName)
1879
0
{
1880
0
    QFontSubst *fontSubst = globalFontSubst();
1881
0
    Q_ASSERT(fontSubst != nullptr);
1882
0
    return fontSubst->value(familyName.toLower(), QStringList());
1883
0
}
1884
1885
1886
/*!
1887
    Inserts \a substituteName into the substitution
1888
    table for the family \a familyName.
1889
1890
    After substituting a font, trigger the updating of the font by destroying
1891
    and re-creating all QFont objects.
1892
1893
    \sa insertSubstitutions(), removeSubstitutions(), substitutions(), substitute(), substitutes()
1894
*/
1895
void QFont::insertSubstitution(const QString &familyName,
1896
                               const QString &substituteName)
1897
0
{
1898
0
    QFontSubst *fontSubst = globalFontSubst();
1899
0
    Q_ASSERT(fontSubst != nullptr);
1900
0
    QStringList &list = (*fontSubst)[familyName.toLower()];
1901
0
    QString s = substituteName.toLower();
1902
0
    if (!list.contains(s))
1903
0
        list.append(s);
1904
0
}
1905
1906
1907
/*!
1908
    Inserts the list of families \a substituteNames into the
1909
    substitution list for \a familyName.
1910
1911
    After substituting a font, trigger the updating of the font by destroying
1912
    and re-creating all QFont objects.
1913
1914
1915
    \sa insertSubstitution(), removeSubstitutions(), substitutions(), substitute()
1916
*/
1917
void QFont::insertSubstitutions(const QString &familyName,
1918
                                const QStringList &substituteNames)
1919
0
{
1920
0
    QFontSubst *fontSubst = globalFontSubst();
1921
0
    Q_ASSERT(fontSubst != nullptr);
1922
0
    QStringList &list = (*fontSubst)[familyName.toLower()];
1923
0
    for (const QString &substituteName : substituteNames) {
1924
0
        const QString lowerSubstituteName = substituteName.toLower();
1925
0
        if (!list.contains(lowerSubstituteName))
1926
0
            list.append(lowerSubstituteName);
1927
0
    }
1928
0
}
1929
1930
/*!
1931
    Removes all the substitutions for \a familyName.
1932
1933
    \sa insertSubstitutions(), insertSubstitution(), substitutions(), substitute()
1934
    \since 5.0
1935
*/
1936
void QFont::removeSubstitutions(const QString &familyName)
1937
0
{
1938
0
    QFontSubst *fontSubst = globalFontSubst();
1939
0
    Q_ASSERT(fontSubst != nullptr);
1940
0
    fontSubst->remove(familyName.toLower());
1941
0
}
1942
1943
/*!
1944
    \fn void QFont::removeSubstitution(const QString &familyName)
1945
1946
    \obsolete
1947
1948
    This function is deprecated. Use removeSubstitutions() instead.
1949
*/
1950
1951
/*!
1952
    Returns a sorted list of substituted family names.
1953
1954
    \sa insertSubstitution(), removeSubstitution(), substitute()
1955
*/
1956
QStringList QFont::substitutions()
1957
0
{
1958
0
    QFontSubst *fontSubst = globalFontSubst();
1959
0
    Q_ASSERT(fontSubst != nullptr);
1960
0
    QStringList ret = fontSubst->keys();
1961
1962
0
    ret.sort();
1963
0
    return ret;
1964
0
}
1965
1966
#ifndef QT_NO_DATASTREAM
1967
/*  \internal
1968
    Internal function. Converts boolean font settings to an unsigned
1969
    8-bit number. Used for serialization etc.
1970
*/
1971
static quint8 get_font_bits(int version, const QFontPrivate *f)
1972
0
{
1973
0
    Q_ASSERT(f != nullptr);
1974
0
    quint8 bits = 0;
1975
0
    if (f->request.style)
1976
0
        bits |= 0x01;
1977
0
    if (f->underline)
1978
0
        bits |= 0x02;
1979
0
    if (f->overline)
1980
0
        bits |= 0x40;
1981
0
    if (f->strikeOut)
1982
0
        bits |= 0x04;
1983
0
    if (f->request.fixedPitch)
1984
0
        bits |= 0x08;
1985
    // if (f.hintSetByUser)
1986
    // bits |= 0x10;
1987
0
    if (version >= QDataStream::Qt_4_0) {
1988
0
        if (f->kerning)
1989
0
            bits |= 0x10;
1990
0
    }
1991
0
    if (f->request.style == QFont::StyleOblique)
1992
0
        bits |= 0x80;
1993
0
    return bits;
1994
0
}
1995
1996
static quint8 get_extended_font_bits(const QFontPrivate *f)
1997
0
{
1998
0
    Q_ASSERT(f != nullptr);
1999
0
    quint8 bits = 0;
2000
0
    if (f->request.ignorePitch)
2001
0
        bits |= 0x01;
2002
0
    if (f->letterSpacingIsAbsolute)
2003
0
        bits |= 0x02;
2004
0
    return bits;
2005
0
}
2006
2007
/*  \internal
2008
    Internal function. Sets boolean font settings from an unsigned
2009
    8-bit number. Used for serialization etc.
2010
*/
2011
static void set_font_bits(int version, quint8 bits, QFontPrivate *f)
2012
0
{
2013
0
    Q_ASSERT(f != nullptr);
2014
0
    f->request.style         = (bits & 0x01) != 0 ? QFont::StyleItalic : QFont::StyleNormal;
2015
0
    f->underline             = (bits & 0x02) != 0;
2016
0
    f->overline              = (bits & 0x40) != 0;
2017
0
    f->strikeOut             = (bits & 0x04) != 0;
2018
0
    f->request.fixedPitch    = (bits & 0x08) != 0;
2019
    // f->hintSetByUser      = (bits & 0x10) != 0;
2020
0
    if (version >= QDataStream::Qt_4_0)
2021
0
        f->kerning               = (bits & 0x10) != 0;
2022
0
    if ((bits & 0x80) != 0)
2023
0
        f->request.style         = QFont::StyleOblique;
2024
0
}
2025
2026
static void set_extended_font_bits(quint8 bits, QFontPrivate *f)
2027
0
{
2028
0
    Q_ASSERT(f != nullptr);
2029
0
    f->request.ignorePitch = (bits & 0x01) != 0;
2030
0
    f->letterSpacingIsAbsolute = (bits & 0x02) != 0;
2031
0
}
2032
#endif
2033
2034
#if QT_DEPRECATED_SINCE(5, 3)
2035
/*!
2036
    \fn QString QFont::rawName() const
2037
    \deprecated
2038
2039
    Returns the name of the font within the underlying window system.
2040
2041
    On X11, this function will return an empty string.
2042
2043
    Using the return value of this function is usually \e not \e
2044
    portable.
2045
2046
    \sa setRawName()
2047
*/
2048
QString QFont::rawName() const
2049
0
{
2050
0
    return QLatin1String("unknown");
2051
0
}
2052
2053
/*!
2054
    \fn void QFont::setRawName(const QString &name)
2055
    \deprecated
2056
2057
    Sets a font by its system specific name.
2058
2059
    A font set with setRawName() is still a full-featured QFont. It can
2060
    be queried (for example with italic()) or modified (for example with
2061
    setItalic()) and is therefore also suitable for rendering rich text.
2062
2063
    If Qt's internal font database cannot resolve the raw name, the
2064
    font becomes a raw font with \a name as its family.
2065
2066
    \sa rawName(), setFamily()
2067
*/
2068
void QFont::setRawName(const QString &)
2069
0
{
2070
0
}
2071
#endif
2072
2073
/*!
2074
    Returns the font's key, a textual representation of a font. It is
2075
    typically used as the key for a cache or dictionary of fonts.
2076
2077
    \sa QMap
2078
*/
2079
QString QFont::key() const
2080
0
{
2081
0
    return toString();
2082
0
}
2083
2084
/*!
2085
    Returns a description of the font. The description is a
2086
    comma-separated list of the attributes, perfectly suited for use
2087
    in QSettings, and consists of the following:
2088
2089
    \list
2090
      \li Font family
2091
      \li Point size
2092
      \li Pixel size
2093
      \li Style hint
2094
      \li Font weight
2095
      \li Font style
2096
      \li Underline
2097
      \li Strike out
2098
      \li Fixed pitch
2099
      \li Always \e{0}
2100
      \li Capitalization
2101
      \li Letter spacing
2102
      \li Word spacing
2103
      \li Stretch
2104
      \li Style strategy
2105
      \li Font style (omitted when unavailable)
2106
    \endlist
2107
2108
    \sa fromString()
2109
 */
2110
QString QFont::toString() const
2111
0
{
2112
0
    const QChar comma(QLatin1Char(','));
2113
0
    QString fontDescription = family() + comma +
2114
0
        QString::number(     pointSizeF()) + comma +
2115
0
        QString::number(      pixelSize()) + comma +
2116
0
        QString::number((int) styleHint()) + comma +
2117
0
        QString::number(         weight()) + comma +
2118
0
        QString::number((int)     style()) + comma +
2119
0
        QString::number((int) underline()) + comma +
2120
0
        QString::number((int) strikeOut()) + comma +
2121
0
        QString::number((int)fixedPitch()) + comma +
2122
0
        QString::number((int)   false);
2123
2124
0
    QString fontStyle = styleName();
2125
0
    if (!fontStyle.isEmpty())
2126
0
        fontDescription += comma + fontStyle;
2127
2128
0
    return fontDescription;
2129
0
}
2130
2131
/*!
2132
    Returns the hash value for \a font. If specified, \a seed is used
2133
    to initialize the hash.
2134
2135
    \relates QFont
2136
    \since 5.3
2137
*/
2138
uint qHash(const QFont &font, uint seed) noexcept
2139
0
{
2140
0
    return qHash(QFontPrivate::get(font)->request, seed);
2141
0
}
2142
2143
2144
/*!
2145
    Sets this font to match the description \a descrip. The description
2146
    is a comma-separated list of the font attributes, as returned by
2147
    toString().
2148
2149
    \sa toString()
2150
 */
2151
bool QFont::fromString(const QString &descrip)
2152
0
{
2153
0
    const QStringRef sr = QStringRef(&descrip).trimmed();
2154
0
    const auto l = sr.split(QLatin1Char(','));
2155
0
    const int count = l.count();
2156
0
    if (!count || (count > 2 && count < 9) || count > 11 ||
2157
0
        l.first().isEmpty()) {
2158
0
        qWarning("QFont::fromString: Invalid description '%s'",
2159
0
                 descrip.isEmpty() ? "(empty)" : descrip.toLatin1().data());
2160
0
        return false;
2161
0
    }
2162
2163
0
    setFamily(l[0].toString());
2164
0
    if (count > 1 && l[1].toDouble() > 0.0)
2165
0
        setPointSizeF(l[1].toDouble());
2166
0
    if (count == 9) {
2167
0
        setStyleHint((StyleHint) l[2].toInt());
2168
0
        setWeight(qMax(qMin(99, l[3].toInt()), 0));
2169
0
        setItalic(l[4].toInt());
2170
0
        setUnderline(l[5].toInt());
2171
0
        setStrikeOut(l[6].toInt());
2172
0
        setFixedPitch(l[7].toInt());
2173
0
    } else if (count >= 10) {
2174
0
        if (l[2].toInt() > 0)
2175
0
            setPixelSize(l[2].toInt());
2176
0
        setStyleHint((StyleHint) l[3].toInt());
2177
0
        setWeight(qMax(qMin(99, l[4].toInt()), 0));
2178
0
        setStyle((QFont::Style)l[5].toInt());
2179
0
        setUnderline(l[6].toInt());
2180
0
        setStrikeOut(l[7].toInt());
2181
0
        setFixedPitch(l[8].toInt());
2182
0
        if (count == 11)
2183
0
            d->request.styleName = l[10].toString();
2184
0
        else
2185
0
            d->request.styleName.clear();
2186
0
    }
2187
2188
0
    if (count >= 9 && !d->request.fixedPitch) // assume 'false' fixedPitch equals default
2189
0
        d->request.ignorePitch = true;
2190
2191
0
    return true;
2192
0
}
2193
2194
/*! \fn void QFont::initialize()
2195
  \internal
2196
2197
  Internal function that initializes the font system.  The font cache
2198
  and font dict do not alloc the keys. The key is a QString which is
2199
  shared between QFontPrivate and QXFontName.
2200
*/
2201
void QFont::initialize()
2202
0
{
2203
0
}
2204
2205
/*! \fn void QFont::cleanup()
2206
  \internal
2207
2208
  Internal function that cleans up the font system.
2209
*/
2210
void QFont::cleanup()
2211
0
{
2212
0
    QFontCache::cleanup();
2213
0
}
2214
2215
/*! \internal
2216
2217
  Internal function that dumps font cache statistics.
2218
*/
2219
void QFont::cacheStatistics()
2220
0
{
2221
0
}
2222
2223
#if QT_DEPRECATED_SINCE(5, 13)
2224
/*!
2225
    \fn QString QFont::lastResortFamily() const
2226
2227
    \obsolete
2228
2229
    This function is deprecated and is not in use by the font
2230
    selection algorithm in Qt 5. It always returns "helvetica".
2231
2232
    \sa lastResortFont()
2233
*/
2234
QString QFont::lastResortFamily() const
2235
0
{
2236
0
    return QStringLiteral("helvetica");
2237
0
}
2238
#endif
2239
2240
extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
2241
                                         QFont::StyleHint styleHint, QChar::Script script);
2242
2243
/*!
2244
    \fn QString QFont::defaultFamily() const
2245
2246
    Returns the family name that corresponds to the current style
2247
    hint.
2248
2249
    \sa StyleHint, styleHint(), setStyleHint()
2250
*/
2251
QString QFont::defaultFamily() const
2252
0
{
2253
0
    const QStringList fallbacks = qt_fallbacksForFamily(QString(), QFont::StyleNormal
2254
0
                                      , QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
2255
0
    if (!fallbacks.isEmpty())
2256
0
        return fallbacks.first();
2257
0
    return QString();
2258
0
}
2259
2260
#if QT_DEPRECATED_SINCE(5, 13)
2261
/*!
2262
    \fn QString QFont::lastResortFont() const
2263
2264
    \obsolete
2265
2266
    Deprecated function. Since Qt 5.0, this is not used by the font selection algorithm. For
2267
    compatibility it remains in the API, but will always return the same value as lastResortFamily().
2268
*/
2269
QString QFont::lastResortFont() const
2270
0
{
2271
0
QT_WARNING_PUSH
2272
0
QT_WARNING_DISABLE_DEPRECATED
2273
0
    return lastResortFamily();
2274
0
QT_WARNING_POP
2275
0
}
2276
#endif
2277
2278
/*!
2279
    \since 5.13
2280
2281
    Returns the requested font family names, i.e. the names set in the last
2282
    setFamilies() call or via the constructor. Otherwise it returns an
2283
    empty list.
2284
2285
    \sa setFamily(), setFamilies(), family(), substitutes(), substitute()
2286
*/
2287
2288
QStringList QFont::families() const
2289
0
{
2290
0
    return d->request.families;
2291
0
}
2292
2293
/*!
2294
    \since 5.13
2295
2296
    Sets the list of family names for the font. The names are case
2297
    insensitive and may include a foundry name. The first family in
2298
    \a families will be set as the main family for the font.
2299
2300
    Each family name entry in \a families may optionally also include a
2301
    foundry name, e.g. "Helvetica [Cronyx]". If the family is
2302
    available from more than one foundry and the foundry isn't
2303
    specified, an arbitrary foundry is chosen. If the family isn't
2304
    available a family will be set using the \l{QFont}{font matching}
2305
    algorithm.
2306
2307
    \sa family(), families(), setFamily(), setStyleHint(), QFontInfo
2308
*/
2309
2310
void QFont::setFamilies(const QStringList &families)
2311
0
{
2312
0
    if ((resolve_mask & QFont::FamiliesResolved) && d->request.families == families)
2313
0
        return;
2314
0
    detach();
2315
0
    d->request.families = families;
2316
0
    resolve_mask |= QFont::FamiliesResolved;
2317
0
}
2318
2319
2320
/*****************************************************************************
2321
  QFont stream functions
2322
 *****************************************************************************/
2323
#ifndef QT_NO_DATASTREAM
2324
2325
/*!
2326
    \relates QFont
2327
2328
    Writes the font \a font to the data stream \a s. (toString()
2329
    writes to a text stream.)
2330
2331
    \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
2332
*/
2333
QDataStream &operator<<(QDataStream &s, const QFont &font)
2334
0
{
2335
0
    if (s.version() == 1) {
2336
0
        s << font.d->request.family.toLatin1();
2337
0
    } else {
2338
0
        s << font.d->request.family;
2339
0
        if (s.version() >= QDataStream::Qt_5_4)
2340
0
            s << font.d->request.styleName;
2341
0
    }
2342
2343
0
    if (s.version() >= QDataStream::Qt_4_0) {
2344
        // 4.0
2345
0
        double pointSize = font.d->request.pointSize;
2346
0
        qint32 pixelSize = font.d->request.pixelSize;
2347
0
        s << pointSize;
2348
0
        s << pixelSize;
2349
0
    } else if (s.version() <= 3) {
2350
0
        qint16 pointSize = (qint16) (font.d->request.pointSize * 10);
2351
0
        if (pointSize < 0) {
2352
0
            pointSize = (qint16)QFontInfo(font).pointSize() * 10;
2353
0
        }
2354
0
        s << pointSize;
2355
0
    } else {
2356
0
        s << (qint16) (font.d->request.pointSize * 10);
2357
0
        s << (qint16) font.d->request.pixelSize;
2358
0
    }
2359
2360
0
    s << (quint8) font.d->request.styleHint;
2361
0
    if (s.version() >= QDataStream::Qt_3_1) {
2362
        // Continue writing 8 bits for versions < 5.4 so that we don't write too much,
2363
        // even though we need 16 to store styleStrategy, so there is some data loss.
2364
0
        if (s.version() >= QDataStream::Qt_5_4)
2365
0
            s << (quint16) font.d->request.styleStrategy;
2366
0
        else
2367
0
            s << (quint8) font.d->request.styleStrategy;
2368
0
    }
2369
0
    s << (quint8) 0
2370
0
      << (quint8) font.d->request.weight
2371
0
      << get_font_bits(s.version(), font.d.data());
2372
0
    if (s.version() >= QDataStream::Qt_4_3)
2373
0
        s << (quint16)font.d->request.stretch;
2374
0
    if (s.version() >= QDataStream::Qt_4_4)
2375
0
        s << get_extended_font_bits(font.d.data());
2376
0
    if (s.version() >= QDataStream::Qt_4_5) {
2377
0
        s << font.d->letterSpacing.value();
2378
0
        s << font.d->wordSpacing.value();
2379
0
    }
2380
0
    if (s.version() >= QDataStream::Qt_5_4)
2381
0
        s << (quint8)font.d->request.hintingPreference;
2382
0
    if (s.version() >= QDataStream::Qt_5_6)
2383
0
        s << (quint8)font.d->capital;
2384
0
    if (s.version() >= QDataStream::Qt_5_13)
2385
0
        s << font.d->request.families;
2386
0
    return s;
2387
0
}
2388
2389
2390
/*!
2391
    \relates QFont
2392
2393
    Reads the font \a font from the data stream \a s. (fromString()
2394
    reads from a text stream.)
2395
2396
    \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
2397
*/
2398
QDataStream &operator>>(QDataStream &s, QFont &font)
2399
0
{
2400
0
    font.d = new QFontPrivate;
2401
0
    font.resolve_mask = QFont::AllPropertiesResolved;
2402
2403
0
    quint8 styleHint, charSet, weight, bits;
2404
0
    quint16 styleStrategy = QFont::PreferDefault;
2405
2406
0
    if (s.version() == 1) {
2407
0
        QByteArray fam;
2408
0
        s >> fam;
2409
0
        font.d->request.family = QString::fromLatin1(fam);
2410
0
    } else {
2411
0
        s >> font.d->request.family;
2412
0
        if (s.version() >= QDataStream::Qt_5_4)
2413
0
            s >> font.d->request.styleName;
2414
0
    }
2415
2416
0
    if (s.version() >= QDataStream::Qt_4_0) {
2417
        // 4.0
2418
0
        double pointSize;
2419
0
        qint32 pixelSize;
2420
0
        s >> pointSize;
2421
0
        s >> pixelSize;
2422
0
        font.d->request.pointSize = qreal(pointSize);
2423
0
        font.d->request.pixelSize = pixelSize;
2424
0
    } else {
2425
0
        qint16 pointSize, pixelSize = -1;
2426
0
        s >> pointSize;
2427
0
        if (s.version() >= 4)
2428
0
            s >> pixelSize;
2429
0
        font.d->request.pointSize = qreal(pointSize / 10.);
2430
0
        font.d->request.pixelSize = pixelSize;
2431
0
    }
2432
0
    s >> styleHint;
2433
0
    if (s.version() >= QDataStream::Qt_3_1) {
2434
0
        if (s.version() >= QDataStream::Qt_5_4) {
2435
0
            s >> styleStrategy;
2436
0
        } else {
2437
0
            quint8 tempStyleStrategy;
2438
0
            s >> tempStyleStrategy;
2439
0
            styleStrategy = tempStyleStrategy;
2440
0
        }
2441
0
    }
2442
2443
0
    s >> charSet;
2444
0
    s >> weight;
2445
0
    s >> bits;
2446
2447
0
    font.d->request.styleHint = styleHint;
2448
0
    font.d->request.styleStrategy = styleStrategy;
2449
0
    font.d->request.weight = weight;
2450
2451
0
    set_font_bits(s.version(), bits, font.d.data());
2452
2453
0
    if (s.version() >= QDataStream::Qt_4_3) {
2454
0
        quint16 stretch;
2455
0
        s >> stretch;
2456
0
        font.d->request.stretch = stretch;
2457
0
    }
2458
2459
0
    if (s.version() >= QDataStream::Qt_4_4) {
2460
0
        quint8 extendedBits;
2461
0
        s >> extendedBits;
2462
0
        set_extended_font_bits(extendedBits, font.d.data());
2463
0
    }
2464
0
    if (s.version() >= QDataStream::Qt_4_5) {
2465
0
        int value;
2466
0
        s >> value;
2467
0
        font.d->letterSpacing.setValue(value);
2468
0
        s >> value;
2469
0
        font.d->wordSpacing.setValue(value);
2470
0
    }
2471
0
    if (s.version() >= QDataStream::Qt_5_4) {
2472
0
        quint8 value;
2473
0
        s >> value;
2474
0
        font.d->request.hintingPreference = QFont::HintingPreference(value);
2475
0
    }
2476
0
    if (s.version() >= QDataStream::Qt_5_6) {
2477
0
        quint8 value;
2478
0
        s >> value;
2479
0
        font.d->capital = QFont::Capitalization(value);
2480
0
    }
2481
0
    if (s.version() >= QDataStream::Qt_5_13) {
2482
0
        QStringList value;
2483
0
        s >> value;
2484
0
        font.d->request.families = value;
2485
0
    }
2486
0
    return s;
2487
0
}
2488
2489
#endif // QT_NO_DATASTREAM
2490
2491
2492
/*****************************************************************************
2493
  QFontInfo member functions
2494
 *****************************************************************************/
2495
2496
/*!
2497
    \class QFontInfo
2498
    \reentrant
2499
2500
    \brief The QFontInfo class provides general information about fonts.
2501
    \inmodule QtGui
2502
2503
    \ingroup appearance
2504
    \ingroup shared
2505
2506
    The QFontInfo class provides the same access functions as QFont,
2507
    e.g. family(), pointSize(), italic(), weight(), fixedPitch(),
2508
    styleHint() etc. But whilst the QFont access functions return the
2509
    values that were set, a QFontInfo object returns the values that
2510
    apply to the font that will actually be used to draw the text.
2511
2512
    For example, when the program asks for a 25pt Courier font on a
2513
    machine that has a non-scalable 24pt Courier font, QFont will
2514
    (normally) use the 24pt Courier for rendering. In this case,
2515
    QFont::pointSize() returns 25 and QFontInfo::pointSize() returns
2516
    24.
2517
2518
    There are three ways to create a QFontInfo object.
2519
    \list 1
2520
    \li Calling the QFontInfo constructor with a QFont creates a font
2521
    info object for a screen-compatible font, i.e. the font cannot be
2522
    a printer font. If the font is changed later, the font
2523
    info object is \e not updated.
2524
2525
    (Note: If you use a printer font the values returned may be
2526
    inaccurate. Printer fonts are not always accessible so the nearest
2527
    screen font is used if a printer font is supplied.)
2528
2529
    \li QWidget::fontInfo() returns the font info for a widget's font.
2530
    This is equivalent to calling QFontInfo(widget->font()). If the
2531
    widget's font is changed later, the font info object is \e not
2532
    updated.
2533
2534
    \li QPainter::fontInfo() returns the font info for a painter's
2535
    current font. If the painter's font is changed later, the font
2536
    info object is \e not updated.
2537
    \endlist
2538
2539
    \sa QFont, QFontMetrics, QFontDatabase
2540
*/
2541
2542
/*!
2543
    Constructs a font info object for \a font.
2544
2545
    The font must be screen-compatible, i.e. a font you use when
2546
    drawing text in \l{QWidget}{widgets} or \l{QPixmap}{pixmaps}, not QPicture or QPrinter.
2547
2548
    The font info object holds the information for the font that is
2549
    passed in the constructor at the time it is created, and is not
2550
    updated if the font's attributes are changed later.
2551
2552
    Use QPainter::fontInfo() to get the font info when painting.
2553
    This will give correct results also when painting on paint device
2554
    that is not screen-compatible.
2555
*/
2556
QFontInfo::QFontInfo(const QFont &font)
2557
0
    : d(font.d)
2558
0
{
2559
0
}
2560
2561
/*!
2562
    Constructs a copy of \a fi.
2563
*/
2564
QFontInfo::QFontInfo(const QFontInfo &fi)
2565
0
    : d(fi.d)
2566
0
{
2567
0
}
2568
2569
/*!
2570
    Destroys the font info object.
2571
*/
2572
QFontInfo::~QFontInfo()
2573
0
{
2574
0
}
2575
2576
/*!
2577
    Assigns the font info in \a fi.
2578
*/
2579
QFontInfo &QFontInfo::operator=(const QFontInfo &fi)
2580
0
{
2581
0
    d = fi.d;
2582
0
    return *this;
2583
0
}
2584
2585
/*!
2586
    \fn void QFontInfo::swap(QFontInfo &other)
2587
    \since 5.0
2588
2589
    Swaps this font info instance with \a other. This function is very
2590
    fast and never fails.
2591
*/
2592
2593
/*!
2594
    Returns the family name of the matched window system font.
2595
2596
    \sa QFont::family()
2597
*/
2598
QString QFontInfo::family() const
2599
0
{
2600
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2601
0
    Q_ASSERT(engine != nullptr);
2602
0
    return engine->fontDef.family;
2603
0
}
2604
2605
/*!
2606
    \since 4.8
2607
2608
    Returns the style name of the matched window system font on
2609
    systems that support it.
2610
2611
    \sa QFont::styleName()
2612
*/
2613
QString QFontInfo::styleName() const
2614
0
{
2615
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2616
0
    Q_ASSERT(engine != nullptr);
2617
0
    return engine->fontDef.styleName;
2618
0
}
2619
2620
/*!
2621
    Returns the point size of the matched window system font.
2622
2623
    \sa pointSizeF(), QFont::pointSize()
2624
*/
2625
int QFontInfo::pointSize() const
2626
0
{
2627
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2628
0
    Q_ASSERT(engine != nullptr);
2629
0
    return qRound(engine->fontDef.pointSize);
2630
0
}
2631
2632
/*!
2633
    Returns the point size of the matched window system font.
2634
2635
    \sa QFont::pointSizeF()
2636
*/
2637
qreal QFontInfo::pointSizeF() const
2638
0
{
2639
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2640
0
    Q_ASSERT(engine != nullptr);
2641
0
    return engine->fontDef.pointSize;
2642
0
}
2643
2644
/*!
2645
    Returns the pixel size of the matched window system font.
2646
2647
    \sa QFont::pointSize()
2648
*/
2649
int QFontInfo::pixelSize() const
2650
0
{
2651
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2652
0
    Q_ASSERT(engine != nullptr);
2653
0
    return engine->fontDef.pixelSize;
2654
0
}
2655
2656
/*!
2657
    Returns the italic value of the matched window system font.
2658
2659
    \sa QFont::italic()
2660
*/
2661
bool QFontInfo::italic() const
2662
0
{
2663
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2664
0
    Q_ASSERT(engine != nullptr);
2665
0
    return engine->fontDef.style != QFont::StyleNormal;
2666
0
}
2667
2668
/*!
2669
    Returns the style value of the matched window system font.
2670
2671
    \sa QFont::style()
2672
*/
2673
QFont::Style QFontInfo::style() const
2674
0
{
2675
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2676
0
    Q_ASSERT(engine != nullptr);
2677
0
    return (QFont::Style)engine->fontDef.style;
2678
0
}
2679
2680
/*!
2681
    Returns the weight of the matched window system font.
2682
2683
    \sa QFont::weight(), bold()
2684
*/
2685
int QFontInfo::weight() const
2686
0
{
2687
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2688
0
    Q_ASSERT(engine != nullptr);
2689
0
    return engine->fontDef.weight;
2690
2691
0
}
2692
2693
/*!
2694
    \fn bool QFontInfo::bold() const
2695
2696
    Returns \c true if weight() would return a value greater than
2697
    QFont::Normal; otherwise returns \c false.
2698
2699
    \sa weight(), QFont::bold()
2700
*/
2701
2702
/*!
2703
    Returns the underline value of the matched window system font.
2704
2705
  \sa QFont::underline()
2706
2707
  \internal
2708
2709
  Here we read the underline flag directly from the QFont.
2710
  This is OK for X11 and for Windows because we always get what we want.
2711
*/
2712
bool QFontInfo::underline() const
2713
0
{
2714
0
    return d->underline;
2715
0
}
2716
2717
/*!
2718
    Returns the overline value of the matched window system font.
2719
2720
    \sa QFont::overline()
2721
2722
    \internal
2723
2724
    Here we read the overline flag directly from the QFont.
2725
    This is OK for X11 and for Windows because we always get what we want.
2726
*/
2727
bool QFontInfo::overline() const
2728
0
{
2729
0
    return d->overline;
2730
0
}
2731
2732
/*!
2733
    Returns the strikeout value of the matched window system font.
2734
2735
  \sa QFont::strikeOut()
2736
2737
  \internal Here we read the strikeOut flag directly from the QFont.
2738
  This is OK for X11 and for Windows because we always get what we want.
2739
*/
2740
bool QFontInfo::strikeOut() const
2741
0
{
2742
0
    return d->strikeOut;
2743
0
}
2744
2745
/*!
2746
    Returns the fixed pitch value of the matched window system font.
2747
2748
    \sa QFont::fixedPitch()
2749
*/
2750
bool QFontInfo::fixedPitch() const
2751
0
{
2752
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2753
0
    Q_ASSERT(engine != nullptr);
2754
#ifdef Q_OS_MAC
2755
    if (!engine->fontDef.fixedPitchComputed) {
2756
        QChar ch[2] = { QLatin1Char('i'), QLatin1Char('m') };
2757
        QGlyphLayoutArray<2> g;
2758
        int l = 2;
2759
        if (!engine->stringToCMap(ch, 2, &g, &l, {}))
2760
            Q_UNREACHABLE();
2761
        Q_ASSERT(l == 2);
2762
        engine->fontDef.fixedPitch = g.advances[0] == g.advances[1];
2763
        engine->fontDef.fixedPitchComputed = true;
2764
    }
2765
#endif
2766
0
    return engine->fontDef.fixedPitch;
2767
0
}
2768
2769
/*!
2770
    Returns the style of the matched window system font.
2771
2772
    Currently only returns the style hint set in QFont.
2773
2774
    \sa QFont::styleHint(), QFont::StyleHint
2775
*/
2776
QFont::StyleHint QFontInfo::styleHint() const
2777
0
{
2778
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2779
0
    Q_ASSERT(engine != nullptr);
2780
0
    return (QFont::StyleHint) engine->fontDef.styleHint;
2781
0
}
2782
2783
#if QT_DEPRECATED_SINCE(5, 5)
2784
/*!
2785
    \deprecated
2786
2787
    Returns \c true if the font is a raw mode font; otherwise returns
2788
    false.
2789
2790
    If it is a raw mode font, all other functions in QFontInfo will
2791
    return the same values set in the QFont, regardless of the font
2792
    actually used.
2793
2794
    \sa QFont::rawMode()
2795
*/
2796
bool QFontInfo::rawMode() const
2797
0
{
2798
0
    return false;
2799
0
}
2800
#endif
2801
2802
/*!
2803
    Returns \c true if the matched window system font is exactly the same
2804
    as the one specified by the font; otherwise returns \c false.
2805
2806
    \sa QFont::exactMatch()
2807
*/
2808
bool QFontInfo::exactMatch() const
2809
0
{
2810
0
    QFontEngine *engine = d->engineForScript(QChar::Script_Common);
2811
0
    Q_ASSERT(engine != nullptr);
2812
0
    return d->request.exactMatch(engine->fontDef);
2813
0
}
2814
2815
2816
2817
2818
// **********************************************************************
2819
// QFontCache
2820
// **********************************************************************
2821
2822
#ifdef QFONTCACHE_DEBUG
2823
// fast timeouts for debugging
2824
static const int fast_timeout =   1000;  // 1s
2825
static const int slow_timeout =   5000;  // 5s
2826
#else
2827
static const int fast_timeout =  10000; // 10s
2828
static const int slow_timeout = 300000; //  5m
2829
#endif // QFONTCACHE_DEBUG
2830
2831
#ifndef QFONTCACHE_MIN_COST
2832
#  define QFONTCACHE_MIN_COST 4*1024 // 4mb
2833
#endif
2834
const uint QFontCache::min_cost = QFONTCACHE_MIN_COST;
2835
Q_GLOBAL_STATIC(QThreadStorage<QFontCache *>, theFontCache)
2836
2837
QFontCache *QFontCache::instance()
2838
0
{
2839
0
    QFontCache *&fontCache = theFontCache()->localData();
2840
0
    if (!fontCache)
2841
0
        fontCache = new QFontCache;
2842
0
    return fontCache;
2843
0
}
2844
2845
void QFontCache::cleanup()
2846
0
{
2847
0
    QThreadStorage<QFontCache *> *cache = nullptr;
2848
0
    QT_TRY {
2849
0
        cache = theFontCache();
2850
0
    } QT_CATCH (const std::bad_alloc &) {
2851
        // no cache - just ignore
2852
0
    }
2853
0
    if (cache && cache->hasLocalData())
2854
0
        cache->setLocalData(0);
2855
0
}
2856
2857
static QBasicAtomicInt font_cache_id = Q_BASIC_ATOMIC_INITIALIZER(0);
2858
2859
QFontCache::QFontCache()
2860
0
    : QObject(), total_cost(0), max_cost(min_cost),
2861
0
      current_timestamp(0), fast(false), timer_id(-1),
2862
0
      m_id(font_cache_id.fetchAndAddRelaxed(1) + 1)
2863
0
{
2864
0
}
2865
2866
QFontCache::~QFontCache()
2867
0
{
2868
0
    clear();
2869
0
}
2870
2871
void QFontCache::clear()
2872
0
{
2873
0
    {
2874
0
        EngineDataCache::Iterator it = engineDataCache.begin(),
2875
0
                                 end = engineDataCache.end();
2876
0
        while (it != end) {
2877
0
            QFontEngineData *data = it.value();
2878
0
            for (int i = 0; i < QChar::ScriptCount; ++i) {
2879
0
                if (data->engines[i]) {
2880
0
                    if (!data->engines[i]->ref.deref()) {
2881
0
                        Q_ASSERT(engineCacheCount.value(data->engines[i]) == 0);
2882
0
                        delete data->engines[i];
2883
0
                    }
2884
0
                    data->engines[i] = nullptr;
2885
0
                }
2886
0
            }
2887
0
            if (!data->ref.deref()) {
2888
0
                delete data;
2889
0
            } else {
2890
0
                FC_DEBUG("QFontCache::clear: engineData %p still has refcount %d",
2891
0
                         data, data->ref.loadRelaxed());
2892
0
            }
2893
0
            ++it;
2894
0
        }
2895
0
    }
2896
2897
0
    engineDataCache.clear();
2898
2899
2900
0
    bool mightHaveEnginesLeftForCleanup;
2901
0
    do {
2902
0
        mightHaveEnginesLeftForCleanup = false;
2903
0
        for (EngineCache::Iterator it = engineCache.begin(), end = engineCache.end();
2904
0
             it != end; ++it) {
2905
0
            QFontEngine *engine = it.value().data;
2906
0
            if (engine) {
2907
0
                const int cacheCount = --engineCacheCount[engine];
2908
0
                Q_ASSERT(cacheCount >= 0);
2909
0
                if (!engine->ref.deref()) {
2910
0
                    Q_ASSERT(cacheCount == 0);
2911
0
                    mightHaveEnginesLeftForCleanup = engine->type() == QFontEngine::Multi;
2912
0
                    delete engine;
2913
0
                } else if (cacheCount == 0) {
2914
0
                    FC_DEBUG("QFontCache::clear: engine %p still has refcount %d",
2915
0
                             engine, engine->ref.loadRelaxed());
2916
0
                }
2917
0
                it.value().data = nullptr;
2918
0
            }
2919
0
        }
2920
0
    } while (mightHaveEnginesLeftForCleanup);
2921
2922
0
    engineCache.clear();
2923
0
    engineCacheCount.clear();
2924
2925
2926
0
    total_cost = 0;
2927
0
    max_cost = min_cost;
2928
0
}
2929
2930
2931
QFontEngineData *QFontCache::findEngineData(const QFontDef &def) const
2932
0
{
2933
0
    EngineDataCache::ConstIterator it = engineDataCache.constFind(def);
2934
0
    if (it == engineDataCache.constEnd())
2935
0
        return nullptr;
2936
2937
    // found
2938
0
    return it.value();
2939
0
}
2940
2941
void QFontCache::insertEngineData(const QFontDef &def, QFontEngineData *engineData)
2942
0
{
2943
#ifdef QFONTCACHE_DEBUG
2944
    FC_DEBUG("QFontCache: inserting new engine data %p", engineData);
2945
    if (engineDataCache.contains(def)) {
2946
        FC_DEBUG("   QFontCache already contains engine data %p for key=(%g %g %d %d %d)",
2947
                 engineDataCache.value(def), def.pointSize,
2948
                 def.pixelSize, def.weight, def.style, def.fixedPitch);
2949
    }
2950
#endif
2951
0
    Q_ASSERT(!engineDataCache.contains(def));
2952
2953
0
    engineData->ref.ref();
2954
    // Decrease now rather than waiting
2955
0
    if (total_cost > min_cost * 2 && engineDataCache.size() >= QFONTCACHE_DECREASE_TRIGGER_LIMIT)
2956
0
        decreaseCache();
2957
2958
0
    engineDataCache.insert(def, engineData);
2959
0
    increaseCost(sizeof(QFontEngineData));
2960
0
}
2961
2962
QFontEngine *QFontCache::findEngine(const Key &key)
2963
0
{
2964
0
    EngineCache::Iterator it = engineCache.find(key),
2965
0
                         end = engineCache.end();
2966
0
    if (it == end) return nullptr;
2967
2968
0
    Q_ASSERT(it.value().data != nullptr);
2969
0
    Q_ASSERT(key.multi == (it.value().data->type() == QFontEngine::Multi));
2970
2971
    // found... update the hitcount and timestamp
2972
0
    updateHitCountAndTimeStamp(it.value());
2973
2974
0
    return it.value().data;
2975
0
}
2976
2977
void QFontCache::updateHitCountAndTimeStamp(Engine &value)
2978
0
{
2979
0
    value.hits++;
2980
0
    value.timestamp = ++current_timestamp;
2981
2982
0
    FC_DEBUG("QFontCache: found font engine\n"
2983
0
             "  %p: timestamp %4u hits %3u ref %2d/%2d, type %d",
2984
0
             value.data, value.timestamp, value.hits,
2985
0
             value.data->ref.loadRelaxed(), engineCacheCount.value(value.data),
2986
0
             value.data->type());
2987
0
}
2988
2989
void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMulti)
2990
0
{
2991
0
    Q_ASSERT(engine != nullptr);
2992
0
    Q_ASSERT(key.multi == (engine->type() == QFontEngine::Multi));
2993
2994
#ifdef QFONTCACHE_DEBUG
2995
    FC_DEBUG("QFontCache: inserting new engine %p, refcount %d", engine, engine->ref.loadRelaxed());
2996
    if (!insertMulti && engineCache.contains(key)) {
2997
        FC_DEBUG("   QFontCache already contains engine %p for key=(%g %g %d %d %d)",
2998
                 engineCache.value(key).data, key.def.pointSize,
2999
                 key.def.pixelSize, key.def.weight, key.def.style, key.def.fixedPitch);
3000
    }
3001
#endif
3002
0
    engine->ref.ref();
3003
    // Decrease now rather than waiting
3004
0
    if (total_cost > min_cost * 2 && engineCache.size() >= QFONTCACHE_DECREASE_TRIGGER_LIMIT)
3005
0
        decreaseCache();
3006
3007
0
    Engine data(engine);
3008
0
    data.timestamp = ++current_timestamp;
3009
3010
0
    if (insertMulti)
3011
0
        engineCache.insert(key, data);
3012
0
    else
3013
0
        engineCache.replace(key, data);
3014
    // only increase the cost if this is the first time we insert the engine
3015
0
    if (++engineCacheCount[engine] == 1)
3016
0
        increaseCost(engine->cache_cost);
3017
0
}
3018
3019
void QFontCache::increaseCost(uint cost)
3020
0
{
3021
0
    cost = (cost + 512) / 1024; // store cost in kb
3022
0
    cost = cost > 0 ? cost : 1;
3023
0
    total_cost += cost;
3024
3025
0
    FC_DEBUG("  COST: increased %u kb, total_cost %u kb, max_cost %u kb",
3026
0
            cost, total_cost, max_cost);
3027
3028
0
    if (total_cost > max_cost) {
3029
0
        max_cost = total_cost;
3030
3031
0
        if (timer_id == -1 || ! fast) {
3032
0
            FC_DEBUG("  TIMER: starting fast timer (%d ms)", fast_timeout);
3033
3034
0
            if (timer_id != -1) killTimer(timer_id);
3035
0
            timer_id = startTimer(fast_timeout);
3036
0
            fast = true;
3037
0
        }
3038
0
    }
3039
0
}
3040
3041
void QFontCache::decreaseCost(uint cost)
3042
0
{
3043
0
    cost = (cost + 512) / 1024; // cost is stored in kb
3044
0
    cost = cost > 0 ? cost : 1;
3045
0
    Q_ASSERT(cost <= total_cost);
3046
0
    total_cost -= cost;
3047
3048
0
    FC_DEBUG("  COST: decreased %u kb, total_cost %u kb, max_cost %u kb",
3049
0
            cost, total_cost, max_cost);
3050
0
}
3051
3052
void QFontCache::timerEvent(QTimerEvent *)
3053
0
{
3054
0
    FC_DEBUG("QFontCache::timerEvent: performing cache maintenance (timestamp %u)",
3055
0
              current_timestamp);
3056
3057
0
    if (total_cost <= max_cost && max_cost <= min_cost) {
3058
0
        FC_DEBUG("  cache redused sufficiently, stopping timer");
3059
3060
0
        killTimer(timer_id);
3061
0
        timer_id = -1;
3062
0
        fast = false;
3063
3064
0
        return;
3065
0
    }
3066
0
    decreaseCache();
3067
0
}
3068
3069
void QFontCache::decreaseCache()
3070
0
{
3071
    // go through the cache and count up everything in use
3072
0
    uint in_use_cost = 0;
3073
3074
0
    {
3075
0
        FC_DEBUG("  SWEEP engine data:");
3076
3077
        // make sure the cost of each engine data is at least 1kb
3078
0
        const uint engine_data_cost =
3079
0
            sizeof(QFontEngineData) > 1024 ? sizeof(QFontEngineData) : 1024;
3080
3081
0
        EngineDataCache::ConstIterator it = engineDataCache.constBegin(),
3082
0
                                      end = engineDataCache.constEnd();
3083
0
        for (; it != end; ++it) {
3084
0
            FC_DEBUG("    %p: ref %2d", it.value(), int(it.value()->ref.loadRelaxed()));
3085
3086
0
            if (it.value()->ref.loadRelaxed() != 1)
3087
0
                in_use_cost += engine_data_cost;
3088
0
        }
3089
0
    }
3090
3091
0
    {
3092
0
        FC_DEBUG("  SWEEP engine:");
3093
3094
0
        EngineCache::ConstIterator it = engineCache.constBegin(),
3095
0
                                  end = engineCache.constEnd();
3096
0
        for (; it != end; ++it) {
3097
0
            FC_DEBUG("    %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes",
3098
0
                     it.value().data, it.value().timestamp, it.value().hits,
3099
0
                     it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
3100
0
                     it.value().data->cache_cost);
3101
3102
0
            if (it.value().data->ref.loadRelaxed() > engineCacheCount.value(it.value().data))
3103
0
                in_use_cost += it.value().data->cache_cost / engineCacheCount.value(it.value().data);
3104
0
        }
3105
3106
        // attempt to make up for rounding errors
3107
0
        in_use_cost += engineCache.size();
3108
0
    }
3109
3110
0
    in_use_cost = (in_use_cost + 512) / 1024; // cost is stored in kb
3111
3112
    /*
3113
      calculate the new maximum cost for the cache
3114
3115
      NOTE: in_use_cost is *not* correct due to rounding errors in the
3116
      above algorithm.  instead of worrying about getting the
3117
      calculation correct, we are more interested in speed, and use
3118
      in_use_cost as a floor for new_max_cost
3119
    */
3120
0
    uint new_max_cost = qMax(qMax(max_cost / 2, in_use_cost), min_cost);
3121
3122
0
    FC_DEBUG("  after sweep, in use %u kb, total %u kb, max %u kb, new max %u kb",
3123
0
              in_use_cost, total_cost, max_cost, new_max_cost);
3124
3125
0
    if (new_max_cost == max_cost) {
3126
0
        if (fast) {
3127
0
            FC_DEBUG("  cannot shrink cache, slowing timer");
3128
3129
0
            killTimer(timer_id);
3130
0
            timer_id = startTimer(slow_timeout);
3131
0
            fast = false;
3132
0
        }
3133
3134
0
        return;
3135
0
    } else if (! fast) {
3136
0
        FC_DEBUG("  dropping into passing gear");
3137
3138
0
        killTimer(timer_id);
3139
0
        timer_id = startTimer(fast_timeout);
3140
0
        fast = true;
3141
0
    }
3142
3143
0
    max_cost = new_max_cost;
3144
3145
0
    {
3146
0
        FC_DEBUG("  CLEAN engine data:");
3147
3148
        // clean out all unused engine data
3149
0
        EngineDataCache::Iterator it = engineDataCache.begin();
3150
0
        while (it != engineDataCache.end()) {
3151
0
            if (it.value()->ref.loadRelaxed() == 1) {
3152
0
                FC_DEBUG("    %p", it.value());
3153
0
                decreaseCost(sizeof(QFontEngineData));
3154
0
                it.value()->ref.deref();
3155
0
                delete it.value();
3156
0
                it = engineDataCache.erase(it);
3157
0
            } else {
3158
0
                ++it;
3159
0
            }
3160
0
        }
3161
0
    }
3162
3163
0
    FC_DEBUG("  CLEAN engine:");
3164
3165
    // clean out the engine cache just enough to get below our new max cost
3166
0
    bool cost_decreased;
3167
0
    do {
3168
0
        cost_decreased = false;
3169
3170
0
        EngineCache::Iterator it = engineCache.begin(),
3171
0
                             end = engineCache.end();
3172
        // determine the oldest and least popular of the unused engines
3173
0
        uint oldest = ~0u;
3174
0
        uint least_popular = ~0u;
3175
3176
0
        EngineCache::Iterator jt = end;
3177
3178
0
        for ( ; it != end; ++it) {
3179
0
            if (it.value().data->ref.loadRelaxed() != engineCacheCount.value(it.value().data))
3180
0
                continue;
3181
3182
0
            if (it.value().timestamp < oldest && it.value().hits <= least_popular) {
3183
0
                oldest = it.value().timestamp;
3184
0
                least_popular = it.value().hits;
3185
0
                jt = it;
3186
0
            }
3187
0
        }
3188
3189
0
        it = jt;
3190
0
        if (it != end) {
3191
0
            FC_DEBUG("    %p: timestamp %4u hits %2u ref %2d/%2d, type %d",
3192
0
                     it.value().data, it.value().timestamp, it.value().hits,
3193
0
                     it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
3194
0
                     it.value().data->type());
3195
3196
0
            QFontEngine *fontEngine = it.value().data;
3197
            // get rid of all occurrences
3198
0
            it = engineCache.begin();
3199
0
            while (it != engineCache.end()) {
3200
0
                if (it.value().data == fontEngine) {
3201
0
                    fontEngine->ref.deref();
3202
0
                    it = engineCache.erase(it);
3203
0
                } else {
3204
0
                    ++it;
3205
0
                }
3206
0
            }
3207
            // and delete the last occurrence
3208
0
            Q_ASSERT(fontEngine->ref.loadRelaxed() == 0);
3209
0
            decreaseCost(fontEngine->cache_cost);
3210
0
            delete fontEngine;
3211
0
            engineCacheCount.remove(fontEngine);
3212
3213
0
            cost_decreased = true;
3214
0
        }
3215
0
    } while (cost_decreased && total_cost > max_cost);
3216
0
}
3217
3218
3219
#ifndef QT_NO_DEBUG_STREAM
3220
QDebug operator<<(QDebug stream, const QFont &font)
3221
0
{
3222
0
    QDebugStateSaver saver(stream);
3223
0
    stream.nospace().noquote();
3224
0
    stream << "QFont(";
3225
3226
0
    if (stream.verbosity() == QDebug::DefaultVerbosity) {
3227
0
        stream << font.toString() << ")";
3228
0
        return stream;
3229
0
    }
3230
3231
0
    QString fontDescription;
3232
0
    QDebug debug(&fontDescription);
3233
0
    debug.nospace();
3234
3235
0
    const QFont defaultFont(new QFontPrivate);
3236
3237
0
    for (int property = QFont::FamilyResolved; property < QFont::AllPropertiesResolved; property <<= 1) {
3238
0
        const bool resolved = (font.resolve_mask & property) != 0;
3239
0
        if (!resolved && stream.verbosity() == QDebug::MinimumVerbosity)
3240
0
            continue;
3241
3242
0
        #define QFONT_DEBUG_SKIP_DEFAULT(prop) \
3243
0
            if ((font.prop() == defaultFont.prop()) && stream.verbosity() == 1) \
3244
0
                continue;
3245
3246
0
        QDebugStateSaver saver(debug);
3247
3248
0
        switch (property) {
3249
0
        case QFont::FamilyResolved:
3250
0
            debug << font.family(); break;
3251
0
        case QFont::SizeResolved:
3252
0
            if (font.pointSizeF() >= 0)
3253
0
                debug << font.pointSizeF() << "pt";
3254
0
            else if (font.pixelSize() >= 0)
3255
0
                debug << font.pixelSize() << "px";
3256
0
            else
3257
0
                Q_UNREACHABLE();
3258
0
            break;
3259
0
        case QFont::StyleHintResolved:
3260
0
            QFONT_DEBUG_SKIP_DEFAULT(styleHint);
3261
0
            debug.verbosity(1) << font.styleHint(); break;
3262
0
        case QFont::StyleStrategyResolved:
3263
0
            QFONT_DEBUG_SKIP_DEFAULT(styleStrategy);
3264
0
            debug.verbosity(1) << font.styleStrategy(); break;
3265
0
        case QFont::WeightResolved:
3266
0
            debug.verbosity(1) << QFont::Weight(font.weight()); break;
3267
0
        case QFont::StyleResolved:
3268
0
            QFONT_DEBUG_SKIP_DEFAULT(style);
3269
0
            debug.verbosity(0) << font.style(); break;
3270
0
        case QFont::UnderlineResolved:
3271
0
            QFONT_DEBUG_SKIP_DEFAULT(underline);
3272
0
            debug << "underline=" << font.underline(); break;
3273
0
        case QFont::OverlineResolved:
3274
0
            QFONT_DEBUG_SKIP_DEFAULT(overline);
3275
0
            debug << "overline=" << font.overline(); break;
3276
0
        case QFont::StrikeOutResolved:
3277
0
            QFONT_DEBUG_SKIP_DEFAULT(strikeOut);
3278
0
            debug << "strikeOut=" << font.strikeOut(); break;
3279
0
        case QFont::FixedPitchResolved:
3280
0
            QFONT_DEBUG_SKIP_DEFAULT(fixedPitch);
3281
0
            debug << "fixedPitch=" << font.fixedPitch(); break;
3282
0
        case QFont::StretchResolved:
3283
0
            QFONT_DEBUG_SKIP_DEFAULT(stretch);
3284
0
            debug.verbosity(0) << QFont::Stretch(font.stretch()); break;
3285
0
        case QFont::KerningResolved:
3286
0
            QFONT_DEBUG_SKIP_DEFAULT(kerning);
3287
0
            debug << "kerning=" << font.kerning(); break;
3288
0
        case QFont::CapitalizationResolved:
3289
0
            QFONT_DEBUG_SKIP_DEFAULT(capitalization);
3290
0
            debug.verbosity(0) << font.capitalization(); break;
3291
0
        case QFont::LetterSpacingResolved:
3292
0
            QFONT_DEBUG_SKIP_DEFAULT(letterSpacing);
3293
0
            debug << "letterSpacing=" << font.letterSpacing();
3294
0
            debug.verbosity(0) << " (" << font.letterSpacingType() << ")";
3295
0
            break;
3296
0
        case QFont::HintingPreferenceResolved:
3297
0
            QFONT_DEBUG_SKIP_DEFAULT(hintingPreference);
3298
0
            debug.verbosity(0) << font.hintingPreference(); break;
3299
0
        case QFont::StyleNameResolved:
3300
0
            QFONT_DEBUG_SKIP_DEFAULT(styleName);
3301
0
            debug << "styleName=" << font.styleName(); break;
3302
0
        default:
3303
0
            continue;
3304
0
        };
3305
3306
0
        #undef QFONT_DEBUG_SKIP_DEFAULT
3307
3308
0
        debug << ", ";
3309
0
    }
3310
3311
0
    if (stream.verbosity() > QDebug::MinimumVerbosity)
3312
0
        debug.verbosity(0) << "resolveMask=" << QFlags<QFont::ResolveProperties>(font.resolve_mask);
3313
0
    else
3314
0
        fontDescription.chop(2); // Last ', '
3315
3316
0
    stream << fontDescription << ')';
3317
3318
0
    return stream;
3319
0
}
3320
#endif
3321
3322
QT_END_NAMESPACE
3323
3324
#include "moc_qfont.cpp"