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

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

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