Fix uses of qRound on non-floating-point types.
[profile/ivi/qtbase.git] / src / gui / text / qfont.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 <QtCore/QMutexLocker>
84 #include <QtCore/QMutex>
85
86 // #define QFONTCACHE_DEBUG
87 #ifdef QFONTCACHE_DEBUG
88 #  define FC_DEBUG qDebug
89 #else
90 #  define FC_DEBUG if (false) qDebug
91 #endif
92
93 QT_BEGIN_NAMESPACE
94
95 #ifdef Q_WS_WIN
96 extern HDC shared_dc();
97 #endif
98
99 #ifdef Q_WS_X11
100 extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
101 #endif
102
103 bool QFontDef::exactMatch(const QFontDef &other) const
104 {
105     /*
106       QFontDef comparison is more complicated than just simple
107       per-member comparisons.
108
109       When comparing point/pixel sizes, either point or pixelsize
110       could be -1.  in This case we have to compare the non negative
111       size value.
112
113       This test will fail if the point-sizes differ by 1/2 point or
114       more or they do not round to the same value.  We have to do this
115       since our API still uses 'int' point-sizes in the API, but store
116       deci-point-sizes internally.
117
118       To compare the family members, we need to parse the font names
119       and compare the family/foundry strings separately.  This allows
120       us to compare e.g. "Helvetica" and "Helvetica [Adobe]" with
121       positive results.
122     */
123     if (pixelSize != -1 && other.pixelSize != -1) {
124         if (pixelSize != other.pixelSize)
125             return false;
126     } else if (pointSize != -1 && other.pointSize != -1) {
127         if (pointSize != other.pointSize)
128             return false;
129     } else {
130         return false;
131     }
132
133     if (!ignorePitch && !other.ignorePitch && fixedPitch != other.fixedPitch)
134         return false;
135
136     if (stretch != 0 && other.stretch != 0 && stretch != other.stretch)
137         return false;
138
139     QString this_family, this_foundry, other_family, other_foundry;
140     QFontDatabase::parseFontName(family, this_foundry, this_family);
141     QFontDatabase::parseFontName(other.family, other_foundry, other_family);
142
143     this_family = QFontDatabase::resolveFontFamilyAlias(this_family);
144     other_family = QFontDatabase::resolveFontFamilyAlias(other_family);
145
146     return (styleHint     == other.styleHint
147             && styleStrategy == other.styleStrategy
148             && weight        == other.weight
149             && style        == other.style
150             && this_family   == other_family
151             && (styleName.isEmpty() || other.styleName.isEmpty() || styleName == other.styleName)
152             && (this_foundry.isEmpty()
153                 || other_foundry.isEmpty()
154                 || this_foundry == other_foundry)
155 #ifdef Q_WS_X11
156             && addStyle == other.addStyle
157 #endif // Q_WS_X11
158        );
159 }
160
161 extern bool qt_is_gui_used;
162
163 Q_GUI_EXPORT int qt_defaultDpiX()
164 {
165     if (!qt_is_gui_used)
166         return 75;
167
168     int dpi;
169 #ifdef Q_WS_X11
170     dpi = QX11Info::appDpiX();
171 #elif defined(Q_WS_WIN)
172     dpi = GetDeviceCaps(shared_dc(),LOGPIXELSX);
173 #elif defined(Q_WS_MAC)
174     extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp
175     dpi = qt_mac_defaultDpi_x();
176 #elif defined(Q_WS_QWS)
177     if (!qt_screen)
178         return 72;
179     QScreen *screen = qt_screen;
180     const QList<QScreen*> subScreens = qt_screen->subScreens();
181     if (!subScreens.isEmpty())
182         screen = subScreens.at(0);
183     dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4)));
184 #elif defined(Q_WS_QPA)
185     QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
186     if (pi) {
187         QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0);
188         const QSize screenSize = screen->geometry().size();
189         const QSize physicalSize = screen->physicalSize();
190         dpi = qRound(screenSize.width() / (physicalSize.width() / qreal(25.4)));
191     } else {
192         //PI has not been initialised, or it is being initialised. Give a default dpi
193         dpi = 100;
194     }
195 #elif defined(Q_OS_SYMBIAN)
196     dpi = S60->defaultDpiX;
197 #endif // Q_WS_X11
198
199     return dpi;
200 }
201
202 Q_GUI_EXPORT int qt_defaultDpiY()
203 {
204     if (!qt_is_gui_used)
205         return 75;
206
207     int dpi;
208 #ifdef Q_WS_X11
209     dpi = QX11Info::appDpiY();
210 #elif defined(Q_WS_WIN)
211     dpi = GetDeviceCaps(shared_dc(),LOGPIXELSY);
212 #elif defined(Q_WS_MAC)
213     extern float qt_mac_defaultDpi_y(); //qpaintdevice_mac.cpp
214     dpi = qt_mac_defaultDpi_y();
215 #elif defined(Q_WS_QWS)
216     if (!qt_screen)
217         return 72;
218     QScreen *screen = qt_screen;
219     const QList<QScreen*> subScreens = qt_screen->subScreens();
220     if (!subScreens.isEmpty())
221         screen = subScreens.at(0);
222     dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4)));
223 #elif defined(Q_WS_QPA)
224     QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
225     if (pi) {
226         QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0);
227         const QSize screenSize = screen->geometry().size();
228         const QSize physicalSize = screen->physicalSize();
229         dpi = qRound(screenSize.height() / (physicalSize.height() / qreal(25.4)));
230     } else {
231         //PI has not been initialised, or it is being initialised. Give a default dpi
232         dpi = 100;
233     }
234 #elif defined(Q_OS_SYMBIAN)
235     dpi = S60->defaultDpiY;
236 #endif // Q_WS_X11
237
238     return dpi;
239 }
240
241 Q_GUI_EXPORT int qt_defaultDpi()
242 {
243     return qt_defaultDpiY();
244 }
245
246 QFontPrivate::QFontPrivate()
247     : engineData(0), dpi(qt_defaultDpi()), screen(0),
248       rawMode(false), underline(false), overline(false), strikeOut(false), kerning(true),
249       capital(0), letterSpacingIsAbsolute(false), scFont(0)
250 {
251 #ifdef Q_WS_X11
252     if (QX11Info::display())
253         screen = QX11Info::appScreen();
254     else
255         screen = 0;
256 #endif
257 #ifdef Q_WS_WIN
258     hdc = 0;
259 #endif
260 }
261
262 QFontPrivate::QFontPrivate(const QFontPrivate &other)
263     : request(other.request), engineData(0), dpi(other.dpi), screen(other.screen),
264       rawMode(other.rawMode), underline(other.underline), overline(other.overline),
265       strikeOut(other.strikeOut), kerning(other.kerning),
266       capital(other.capital), letterSpacingIsAbsolute(other.letterSpacingIsAbsolute),
267       letterSpacing(other.letterSpacing), wordSpacing(other.wordSpacing),
268       scFont(other.scFont)
269 {
270 #ifdef Q_WS_WIN
271     hdc = other.hdc;
272 #endif
273     if (scFont && scFont != this)
274         scFont->ref.ref();
275 }
276
277 QFontPrivate::~QFontPrivate()
278 {
279     if (engineData)
280         engineData->ref.deref();
281     engineData = 0;
282     if (scFont && scFont != this)
283         scFont->ref.deref();
284     scFont = 0;
285 }
286
287 extern QMutex *qt_fontdatabase_mutex();
288
289 #if !defined(Q_WS_MAC)
290 #define QT_FONT_ENGINE_FROM_DATA(data, script) data->engines[script]
291 #else
292 #define QT_FONT_ENGINE_FROM_DATA(data, script) data->engine
293 #endif
294
295 QFontEngine *QFontPrivate::engineForScript(int script) const
296 {
297     QMutexLocker locker(qt_fontdatabase_mutex());
298     if (script >= QUnicodeTables::Inherited)
299         script = QUnicodeTables::Common;
300     if (engineData && engineData->fontCache != QFontCache::instance()) {
301         // throw out engineData that came from a different thread
302         engineData->ref.deref();
303         engineData = 0;
304     }
305     if (!engineData || !QT_FONT_ENGINE_FROM_DATA(engineData, script))
306         QFontDatabase::load(this, script);
307     return QT_FONT_ENGINE_FROM_DATA(engineData, script);
308 }
309
310 void QFontPrivate::alterCharForCapitalization(QChar &c) const {
311     switch (capital) {
312     case QFont::AllUppercase:
313     case QFont::SmallCaps:
314         c = c.toUpper();
315         break;
316     case QFont::AllLowercase:
317         c = c.toLower();
318         break;
319     case QFont::MixedCase:
320         break;
321     }
322 }
323
324 QFontPrivate *QFontPrivate::smallCapsFontPrivate() const
325 {
326     if (scFont)
327         return scFont;
328     QFont font(const_cast<QFontPrivate *>(this));
329     qreal pointSize = font.pointSizeF();
330     if (pointSize > 0)
331         font.setPointSizeF(pointSize * .7);
332     else
333         font.setPixelSize((font.pixelSize() * 7 + 5) / 10);
334     scFont = font.d.data();
335     if (scFont != this)
336         scFont->ref.ref();
337     return scFont;
338 }
339
340
341 void QFontPrivate::resolve(uint mask, const QFontPrivate *other)
342 {
343     Q_ASSERT(other != 0);
344
345     dpi = other->dpi;
346
347     if ((mask & QFont::AllPropertiesResolved) == QFont::AllPropertiesResolved) return;
348
349     // assign the unset-bits with the set-bits of the other font def
350     if (! (mask & QFont::FamilyResolved))
351         request.family = other->request.family;
352
353     if (! (mask & QFont::StyleNameResolved))
354         request.styleName = other->request.styleName;
355
356     if (! (mask & QFont::SizeResolved)) {
357         request.pointSize = other->request.pointSize;
358         request.pixelSize = other->request.pixelSize;
359     }
360
361     if (! (mask & QFont::StyleHintResolved))
362         request.styleHint = other->request.styleHint;
363
364     if (! (mask & QFont::StyleStrategyResolved))
365         request.styleStrategy = other->request.styleStrategy;
366
367     if (! (mask & QFont::WeightResolved))
368         request.weight = other->request.weight;
369
370     if (! (mask & QFont::StyleResolved))
371         request.style = other->request.style;
372
373     if (! (mask & QFont::FixedPitchResolved))
374         request.fixedPitch = other->request.fixedPitch;
375
376     if (! (mask & QFont::StretchResolved))
377         request.stretch = other->request.stretch;
378
379     if (! (mask & QFont::HintingPreferenceResolved))
380         request.hintingPreference = other->request.hintingPreference;
381
382     if (! (mask & QFont::UnderlineResolved))
383         underline = other->underline;
384
385     if (! (mask & QFont::OverlineResolved))
386         overline = other->overline;
387
388     if (! (mask & QFont::StrikeOutResolved))
389         strikeOut = other->strikeOut;
390
391     if (! (mask & QFont::KerningResolved))
392         kerning = other->kerning;
393
394     if (! (mask & QFont::LetterSpacingResolved)) {
395         letterSpacing = other->letterSpacing;
396         letterSpacingIsAbsolute = other->letterSpacingIsAbsolute;
397     }
398     if (! (mask & QFont::WordSpacingResolved))
399         wordSpacing = other->wordSpacing;
400     if (! (mask & QFont::CapitalizationResolved))
401         capital = other->capital;
402 }
403
404
405
406
407 QFontEngineData::QFontEngineData()
408     : ref(1), fontCache(QFontCache::instance())
409 {
410 #if !defined(Q_WS_MAC)
411     memset(engines, 0, QUnicodeTables::ScriptCount * sizeof(QFontEngine *));
412 #else
413     engine = 0;
414 #endif
415 }
416
417 QFontEngineData::~QFontEngineData()
418 {
419 #if !defined(Q_WS_MAC)
420     for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
421         if (engines[i])
422             engines[i]->ref.deref();
423         engines[i] = 0;
424     }
425 #else
426     if (engine)
427         engine->ref.deref();
428     engine = 0;
429 #endif // Q_WS_X11 || Q_WS_WIN || Q_WS_MAC
430 }
431
432
433
434
435 /*!
436     \class QFont
437     \reentrant
438
439     \brief The QFont class specifies a font used for drawing text.
440
441     \ingroup painting
442     \ingroup appearance
443     \ingroup shared
444     \ingroup richtext-processing
445
446
447     When you create a QFont object you specify various attributes that
448     you want the font to have. Qt will use the font with the specified
449     attributes, or if no matching font exists, Qt will use the closest
450     matching installed font. The attributes of the font that is
451     actually used are retrievable from a QFontInfo object. If the
452     window system provides an exact match exactMatch() returns true.
453     Use QFontMetrics to get measurements, e.g. the pixel length of a
454     string using QFontMetrics::width().
455
456     Note that a QApplication instance must exist before a QFont can be
457     used. You can set the application's default font with
458     QApplication::setFont().
459
460     If a chosen font does not include all the characters that
461     need to be displayed, QFont will try to find the characters in the
462     nearest equivalent fonts. When a QPainter draws a character from a
463     font the QFont will report whether or not it has the character; if
464     it does not, QPainter will draw an unfilled square.
465
466     Create QFonts like this:
467
468     \snippet doc/src/snippets/code/src_gui_text_qfont.cpp 0
469
470     The attributes set in the constructor can also be set later, e.g.
471     setFamily(), setPointSize(), setPointSizeFloat(), setWeight() and
472     setItalic(). The remaining attributes must be set after
473     contstruction, e.g. setBold(), setUnderline(), setOverline(),
474     setStrikeOut() and setFixedPitch(). QFontInfo objects should be
475     created \e after the font's attributes have been set. A QFontInfo
476     object will not change, even if you change the font's
477     attributes. The corresponding "get" functions, e.g. family(),
478     pointSize(), etc., return the values that were set, even though
479     the values used may differ. The actual values are available from a
480     QFontInfo object.
481
482     If the requested font family is unavailable you can influence the
483     \link #fontmatching font matching algorithm\endlink by choosing a
484     particular \l{QFont::StyleHint} and \l{QFont::StyleStrategy} with
485     setStyleHint(). The default family (corresponding to the current
486     style hint) is returned by defaultFamily().
487
488     The font-matching algorithm has a lastResortFamily() and
489     lastResortFont() in cases where a suitable match cannot be found.
490     You can provide substitutions for font family names using
491     insertSubstitution() and insertSubstitutions(). Substitutions can
492     be removed with removeSubstitution(). Use substitute() to retrieve
493     a family's first substitute, or the family name itself if it has
494     no substitutes. Use substitutes() to retrieve a list of a family's
495     substitutes (which may be empty).
496
497     Every QFont has a key() which you can use, for example, as the key
498     in a cache or dictionary. If you want to store a user's font
499     preferences you could use QSettings, writing the font information
500     with toString() and reading it back with fromString(). The
501     operator<<() and operator>>() functions are also available, but
502     they work on a data stream.
503
504     It is possible to set the height of characters shown on the screen
505     to a specified number of pixels with setPixelSize(); however using
506     setPointSize() has a similar effect and provides device
507     independence.
508
509     In X11 you can set a font using its system
510     specific name with setRawName().
511
512     Loading fonts can be expensive, especially on X11. QFont contains
513     extensive optimizations to make the copying of QFont objects fast,
514     and to cache the results of the slow window system functions it
515     depends upon.
516
517     \target fontmatching
518     The font matching algorithm works as follows:
519     \list 1
520     \o The specified font family is searched for.
521     \o If not found, the styleHint() is used to select a replacement
522        family.
523     \o Each replacement font family is searched for.
524     \o If none of these are found or there was no styleHint(), "helvetica"
525        will be searched for.
526     \o If "helvetica" isn't found Qt will try the lastResortFamily().
527     \o If the lastResortFamily() isn't found Qt will try the
528        lastResortFont() which will always return a name of some kind.
529     \endlist
530
531     Note that the actual font matching algorithm varies from platform to platform.
532
533     In Windows a request for the "Courier" font is automatically changed to
534     "Courier New", an improved version of Courier that allows for smooth scaling.
535     The older "Courier" bitmap font can be selected by setting the PreferBitmap
536     style strategy (see setStyleStrategy()).
537
538     Once a font is found, the remaining attributes are matched in order of
539     priority:
540     \list 1
541     \o fixedPitch()
542     \o pointSize() (see below)
543     \o weight()
544     \o style()
545     \endlist
546
547     If you have a font which matches on family, even if none of the
548     other attributes match, this font will be chosen in preference to
549     a font which doesn't match on family but which does match on the
550     other attributes. This is because font family is the dominant
551     search criteria.
552
553     The point size is defined to match if it is within 20% of the
554     requested point size. When several fonts match and are only
555     distinguished by point size, the font with the closest point size
556     to the one requested will be chosen.
557
558     The actual family, font size, weight and other font attributes
559     used for drawing text will depend on what's available for the
560     chosen family under the window system. A QFontInfo object can be
561     used to determine the actual values used for drawing the text.
562
563     Examples:
564
565     \snippet doc/src/snippets/code/src_gui_text_qfont.cpp 1
566     If you had both an Adobe and a Cronyx Helvetica, you might get
567     either.
568
569     \snippet doc/src/snippets/code/src_gui_text_qfont.cpp 2
570
571     You can specify the foundry you want in the family name. The font f
572     in the above example will be set to "Helvetica
573     [Cronyx]".
574
575     To determine the attributes of the font actually used in the window
576     system, use a QFontInfo object, e.g.
577
578     \snippet doc/src/snippets/code/src_gui_text_qfont.cpp 3
579
580     To find out font metrics use a QFontMetrics object, e.g.
581
582     \snippet doc/src/snippets/code/src_gui_text_qfont.cpp 4
583
584     For more general information on fonts, see the
585     \link http://nwalsh.com/comp.fonts/FAQ/ comp.fonts FAQ.\endlink
586     Information on encodings can be found from
587     \link http://czyborra.com/ Roman Czyborra's\endlink page.
588
589     \sa QFontComboBox, QFontMetrics, QFontInfo, QFontDatabase, {Character Map Example}
590 */
591
592 /*!
593     \internal
594     \enum QFont::ResolveProperties
595
596     This enum describes the properties of a QFont that can be set on a font
597     individually and then considered resolved.
598
599     \value FamilyResolved
600     \value SizeResolved
601     \value StyleHintResolved
602     \value StyleStrategyResolved
603     \value WeightResolved
604     \value StyleResolved
605     \value UnderlineResolved
606     \value OverlineResolved
607     \value StrikeOutResolved
608     \value FixedPitchResolved
609     \value StretchResolved
610     \value KerningResolved
611     \value CapitalizationResolved
612     \value LetterSpacingResolved
613     \value WordSpacingResolved
614     \value CompletelyResolved
615 */
616
617 /*!
618     \enum QFont::Style
619
620     This enum describes the different styles of glyphs that are used to
621     display text.
622
623     \value StyleNormal  Normal glyphs used in unstyled text.
624     \value StyleItalic  Italic glyphs that are specifically designed for
625                         the purpose of representing italicized text.
626     \value StyleOblique Glyphs with an italic appearance that are typically
627                         based on the unstyled glyphs, but are not fine-tuned
628                         for the purpose of representing italicized text.
629
630     \sa Weight
631 */
632
633 /*!
634     \fn Qt::HANDLE QFont::handle() const
635
636     Returns the window system handle to the font, for low-level
637     access. Using this function is \e not portable.
638 */
639
640 /*!
641     \fn FT_Face QFont::freetypeFace() const
642
643     Returns the handle to the primary FreeType face of the font. If font merging is not disabled a
644     QFont can contain several physical fonts.
645
646     Returns 0 if the font does not contain a FreeType face.
647
648     \note This function is only available on platforms that provide the FreeType library;
649     i.e., X11 and some Embedded Linux platforms.
650 */
651
652 /*!
653     \fn QString QFont::rawName() const
654
655     Returns the name of the font within the underlying window system.
656
657     On X11, this function will return an empty string if Qt is built with
658     FontConfig support; otherwise the XLFD (X Logical Font Description) is
659     returned.
660
661     Using the return value of this function is usually \e not \e
662     portable.
663
664     \sa setRawName()
665 */
666
667 /*!
668     \fn void QFont::setRawName(const QString &name)
669
670     Sets a font by its system specific name. The function is
671     particularly useful under X, where system font settings (for
672     example X resources) are usually available in XLFD (X Logical Font
673     Description) form only. You can pass an XLFD as \a name to this
674     function.
675
676     A font set with setRawName() is still a full-featured QFont. It can
677     be queried (for example with italic()) or modified (for example with
678     setItalic()) and is therefore also suitable for rendering rich text.
679
680     If Qt's internal font database cannot resolve the raw name, the
681     font becomes a raw font with \a name as its family.
682
683     Note that the present implementation does not handle wildcards in
684     XLFDs well, and that font aliases (file \c fonts.alias in the font
685     directory on X11) are not supported.
686
687     \sa rawName(), setRawMode(), setFamily()
688 */
689
690 /*!
691     \fn QString QFont::lastResortFamily() const
692
693     Returns the "last resort" font family name.
694
695     The current implementation tries a wide variety of common fonts,
696     returning the first one it finds. Is is possible that no family is
697     found in which case an empty string is returned.
698
699     \sa lastResortFont()
700 */
701
702 /*!
703     \fn QString QFont::defaultFamily() const
704
705     Returns the family name that corresponds to the current style
706     hint.
707
708     \sa StyleHint styleHint() setStyleHint()
709 */
710
711 /*!
712     \fn QString QFont::lastResortFont() const
713
714     Returns a "last resort" font name for the font matching algorithm.
715     This is used if the last resort family is not available. It will
716     always return a name, if necessary returning something like
717     "fixed" or "system".
718
719     The current implementation tries a wide variety of common fonts,
720     returning the first one it finds. The implementation may change
721     at any time, but this function will always return a string
722     containing something.
723
724     It is theoretically possible that there really isn't a
725     lastResortFont() in which case Qt will abort with an error
726     message. We have not been able to identify a case where this
727     happens. Please \link bughowto.html report it as a bug\endlink if
728     it does, preferably with a list of the fonts you have installed.
729
730     \sa lastResortFamily() rawName()
731 */
732
733 /*!
734   Constructs a font from \a font for use on the paint device \a pd.
735 */
736 QFont::QFont(const QFont &font, QPaintDevice *pd)
737     : resolve_mask(font.resolve_mask)
738 {
739     Q_ASSERT(pd != 0);
740     int dpi = pd->logicalDpiY();
741 #ifdef Q_WS_X11
742     const QX11Info *info = qt_x11Info(pd);
743     int screen = info ? info->screen() : 0;
744 #else
745     const int screen = 0;
746 #endif
747     if (font.d->dpi != dpi || font.d->screen != screen ) {
748         d = new QFontPrivate(*font.d);
749         d->dpi = dpi;
750         d->screen = screen;
751     } else {
752         d = font.d.data();
753     }
754 #ifdef Q_WS_WIN
755     if (pd->devType() == QInternal::Printer && pd->getDC())
756         d->hdc = pd->getDC();
757 #endif
758 }
759
760 /*!
761   \internal
762 */
763 QFont::QFont(QFontPrivate *data)
764     : d(data), resolve_mask(QFont::AllPropertiesResolved)
765 {
766 }
767
768 /*! \internal
769     Detaches the font object from common font data.
770 */
771 void QFont::detach()
772 {
773     if (d->ref == 1) {
774         if (d->engineData)
775             d->engineData->ref.deref();
776         d->engineData = 0;
777         if (d->scFont && d->scFont != d.data())
778             d->scFont->ref.deref();
779         d->scFont = 0;
780         return;
781     }
782
783     d.detach();
784 }
785
786 /*!
787     Constructs a font object that uses the application's default font.
788
789     \sa QApplication::setFont(), QApplication::font()
790 */
791 QFont::QFont()
792     : d(QApplication::font().d.data()), resolve_mask(0)
793 {
794 }
795
796 /*!
797     Constructs a font object with the specified \a family, \a
798     pointSize, \a weight and \a italic settings.
799
800     If \a pointSize is zero or negative, the point size of the font
801     is set to a system-dependent default value. Generally, this is
802     12 points, except on Symbian where it is 7 points.
803
804     The \a family name may optionally also include a foundry name,
805     e.g. "Helvetica [Cronyx]". If the \a family is
806     available from more than one foundry and the foundry isn't
807     specified, an arbitrary foundry is chosen. If the family isn't
808     available a family will be set using the \l{QFont}{font matching}
809     algorithm.
810
811     \sa Weight, setFamily(), setPointSize(), setWeight(), setItalic(),
812     setStyleHint() QApplication::font()
813 */
814 QFont::QFont(const QString &family, int pointSize, int weight, bool italic)
815     : d(new QFontPrivate()), resolve_mask(QFont::FamilyResolved)
816 {
817     if (pointSize <= 0) {
818 #ifdef Q_OS_SYMBIAN
819         pointSize = 7;
820 #else
821         pointSize = 12;
822 #endif
823     } else {
824         resolve_mask |= QFont::SizeResolved;
825     }
826
827     if (weight < 0) {
828         weight = Normal;
829     } else {
830         resolve_mask |= QFont::WeightResolved | QFont::StyleResolved;
831     }
832
833     if (italic)
834         resolve_mask |= QFont::StyleResolved;
835
836     d->request.family = family;
837     d->request.pointSize = qreal(pointSize);
838     d->request.pixelSize = -1;
839     d->request.weight = weight;
840     d->request.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
841 }
842
843 /*!
844     Constructs a font that is a copy of \a font.
845 */
846 QFont::QFont(const QFont &font)
847     : d(font.d.data()), resolve_mask(font.resolve_mask)
848 {
849 }
850
851 /*!
852     Destroys the font object and frees all allocated resources.
853 */
854 QFont::~QFont()
855 {
856 }
857
858 /*!
859     Assigns \a font to this font and returns a reference to it.
860 */
861 QFont &QFont::operator=(const QFont &font)
862 {
863     d = font.d.data();
864     resolve_mask = font.resolve_mask;
865     return *this;
866 }
867
868 /*!
869     Returns the requested font family name, i.e. the name set in the
870     constructor or the last setFont() call.
871
872     \sa setFamily() substitutes() substitute()
873 */
874 QString QFont::family() const
875 {
876     return d->request.family;
877 }
878
879 /*!
880     Sets the family name of the font. The name is case insensitive and
881     may include a foundry name.
882
883     The \a family name may optionally also include a foundry name,
884     e.g. "Helvetica [Cronyx]". If the \a family is
885     available from more than one foundry and the foundry isn't
886     specified, an arbitrary foundry is chosen. If the family isn't
887     available a family will be set using the \l{QFont}{font matching}
888     algorithm.
889
890     \sa family(), setStyleHint(), QFontInfo
891 */
892 void QFont::setFamily(const QString &family)
893 {
894     detach();
895
896     d->request.family = family;
897 #if defined(Q_WS_X11)
898     d->request.addStyle.clear();
899 #endif // Q_WS_X11
900
901     resolve_mask |= QFont::FamilyResolved;
902 }
903
904 /*!
905     \since 4.8
906
907     Returns the requested font style name, it will be used to match the
908     font with irregular styles (that can't be normalized in other style
909     properties). It depends on system font support, thus only works for
910     Mac OS X and X11 so far. On Windows irregular styles will be added
911     as separate font families so there is no need for this.
912
913     \sa setFamily() setStyle()
914 */
915 QString QFont::styleName() const
916 {
917     return d->request.styleName;
918 }
919
920 /*!
921     \since 4.8
922
923     Sets the style name of the font. When set, other style properties
924     like \a style() and \a weight() will be ignored 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