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