source: trunk/src/gui/text/qfont.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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