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