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

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

trunk: Merged in qt 4.6.2 sources.

File size: 84.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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 && f.d->letterSpacingIsAbsolute == d->letterSpacingIsAbsolute
1635 && f.d->letterSpacing == d->letterSpacing
1636 && f.d->wordSpacing == d->wordSpacing
1637 ));
1638}
1639
1640
1641/*!
1642 Provides an arbitrary comparison of this font and font \a f.
1643 All that is guaranteed is that the operator returns false if both
1644 fonts are equal and that (f1 \< f2) == !(f2 \< f1) if the fonts
1645 are not equal.
1646
1647 This function is useful in some circumstances, for example if you
1648 want to use QFont objects as keys in a QMap.
1649
1650 \sa operator==() operator!=() isCopyOf()
1651*/
1652bool QFont::operator<(const QFont &f) const
1653{
1654 if (f.d == d) return false;
1655 // the < operator for fontdefs ignores point sizes.
1656 QFontDef &r1 = f.d->request;
1657 QFontDef &r2 = d->request;
1658 if (r1.pointSize != r2.pointSize) return r1.pointSize < r2.pointSize;
1659 if (r1.pixelSize != r2.pixelSize) return r1.pixelSize < r2.pixelSize;
1660 if (r1.weight != r2.weight) return r1.weight < r2.weight;
1661 if (r1.style != r2.style) return r1.style < r2.style;
1662 if (r1.stretch != r2.stretch) return r1.stretch < r2.stretch;
1663 if (r1.styleHint != r2.styleHint) return r1.styleHint < r2.styleHint;
1664 if (r1.styleStrategy != r2.styleStrategy) return r1.styleStrategy < r2.styleStrategy;
1665 if (r1.family != r2.family) return r1.family < r2.family;
1666#ifdef Q_WS_X11
1667 if (r1.addStyle != r2.addStyle) return r1.addStyle < r2.addStyle;
1668#endif // Q_WS_X11
1669 if (f.d->capital != d->capital) return f.d->capital < d->capital;
1670
1671 if (f.d->letterSpacingIsAbsolute != d->letterSpacingIsAbsolute) return f.d->letterSpacingIsAbsolute < d->letterSpacingIsAbsolute;
1672 if (f.d->letterSpacing != d->letterSpacing) return f.d->letterSpacing < d->letterSpacing;
1673 if (f.d->wordSpacing != d->wordSpacing) return f.d->wordSpacing < d->wordSpacing;
1674
1675 int f1attrs = (f.d->underline << 3) + (f.d->overline << 2) + (f.d->strikeOut<<1) + f.d->kerning;
1676 int f2attrs = (d->underline << 3) + (d->overline << 2) + (d->strikeOut<<1) + d->kerning;
1677 return f1attrs < f2attrs;
1678}
1679
1680
1681/*!
1682 Returns true if this font is different from \a f; otherwise
1683 returns false.
1684
1685 Two QFonts are considered to be different if their font attributes
1686 are different. If rawMode() is enabled for both fonts, only the
1687 family fields are compared.
1688
1689 \sa operator==()
1690*/
1691bool QFont::operator!=(const QFont &f) const
1692{
1693 return !(operator==(f));
1694}
1695
1696/*!
1697 Returns the font as a QVariant
1698*/
1699QFont::operator QVariant() const
1700{
1701 return QVariant(QVariant::Font, this);
1702}
1703
1704/*!
1705 Returns true if this font and \a f are copies of each other, i.e.
1706 one of them was created as a copy of the other and neither has
1707 been modified since. This is much stricter than equality.
1708
1709 \sa operator=() operator==()
1710*/
1711bool QFont::isCopyOf(const QFont & f) const
1712{
1713 return d == f.d;
1714}
1715
1716/*!
1717 Returns true if raw mode is used for font name matching; otherwise
1718 returns false.
1719
1720 \sa setRawMode() rawName()
1721*/
1722bool QFont::rawMode() const
1723{
1724 return d->rawMode;
1725}
1726
1727/*!
1728 Returns a new QFont that has attributes copied from \a other that
1729 have not been previously set on this font.
1730*/
1731QFont QFont::resolve(const QFont &other) const
1732{
1733 if (*this == other
1734 && (resolve_mask == other.resolve_mask || resolve_mask == 0)
1735 && d->dpi == other.d->dpi) {
1736 QFont o = other;
1737 o.resolve_mask = resolve_mask;
1738 return o;
1739 }
1740
1741 QFont font(*this);
1742 font.detach();
1743 font.d->resolve(resolve_mask, other.d.data());
1744
1745 return font;
1746}
1747
1748/*!
1749 \fn uint QFont::resolve() const
1750 \internal
1751*/
1752
1753/*!
1754 \fn void QFont::resolve(uint mask)
1755 \internal
1756*/
1757
1758#ifdef QT3_SUPPORT
1759
1760/*! \obsolete
1761
1762 Please use QApplication::font() instead.
1763*/
1764QFont QFont::defaultFont()
1765{
1766 return QApplication::font();
1767}
1768
1769/*! \obsolete
1770
1771 Please use QApplication::setFont() instead.
1772*/
1773void QFont::setDefaultFont(const QFont &f)
1774{
1775 QApplication::setFont(f);
1776}
1777
1778/*!
1779 \fn qreal QFont::pointSizeFloat() const
1780 \compat
1781
1782 Use pointSizeF() instead.
1783*/
1784
1785/*!
1786 \fn void QFont::setPointSizeFloat(qreal size)
1787 \compat
1788
1789 Use setPointSizeF() instead.
1790*/
1791#endif
1792
1793
1794
1795
1796/*****************************************************************************
1797 QFont substitution management
1798 *****************************************************************************/
1799
1800typedef QHash<QString, QStringList> QFontSubst;
1801Q_GLOBAL_STATIC(QFontSubst, globalFontSubst)
1802
1803// create substitution dict
1804static void initFontSubst()
1805{
1806 // default substitutions
1807 static const char * const initTbl[] = {
1808
1809#if defined(Q_WS_X11)
1810 "arial", "helvetica",
1811 "times new roman", "times",
1812 "courier new", "courier",
1813 "sans serif", "helvetica",
1814#elif defined(Q_WS_WIN)
1815 "times", "times new roman",
1816 "courier", "courier new",
1817 "helvetica", "arial",
1818 "sans serif", "arial",
1819#endif
1820
1821 0, 0
1822 };
1823
1824 QFontSubst *fontSubst = globalFontSubst();
1825 Q_ASSERT(fontSubst != 0);
1826 if (!fontSubst->isEmpty())
1827 return;
1828#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
1829 if (X11->has_fontconfig)
1830 return;
1831#endif
1832
1833 for (int i=0; initTbl[i] != 0; i += 2) {
1834 QStringList &list = (*fontSubst)[QString::fromLatin1(initTbl[i])];
1835 list.append(QString::fromLatin1(initTbl[i+1]));
1836 }
1837}
1838
1839/*!
1840 Returns the first family name to be used whenever \a familyName is
1841 specified. The lookup is case insensitive.
1842
1843 If there is no substitution for \a familyName, \a familyName is
1844 returned.
1845
1846 To obtain a list of substitutions use substitutes().
1847
1848 \sa setFamily() insertSubstitutions() insertSubstitution() removeSubstitution()
1849*/
1850QString QFont::substitute(const QString &familyName)
1851{
1852 initFontSubst();
1853
1854 QFontSubst *fontSubst = globalFontSubst();
1855 Q_ASSERT(fontSubst != 0);
1856 QFontSubst::ConstIterator it = fontSubst->constFind(familyName.toLower());
1857 if (it != fontSubst->constEnd() && !(*it).isEmpty())
1858 return (*it).first();
1859
1860 return familyName;
1861}
1862
1863
1864/*!
1865 Returns a list of family names to be used whenever \a familyName
1866 is specified. The lookup is case insensitive.
1867
1868 If there is no substitution for \a familyName, an empty list is
1869 returned.
1870
1871 \sa substitute() insertSubstitutions() insertSubstitution() removeSubstitution()
1872 */
1873QStringList QFont::substitutes(const QString &familyName)
1874{
1875 initFontSubst();
1876
1877 QFontSubst *fontSubst = globalFontSubst();
1878 Q_ASSERT(fontSubst != 0);
1879 return fontSubst->value(familyName.toLower(), QStringList());
1880}
1881
1882
1883/*!
1884 Inserts \a substituteName into the substitution
1885 table for the family \a familyName.
1886
1887 \sa insertSubstitutions() removeSubstitution() substitutions() substitute() substitutes()
1888*/
1889void QFont::insertSubstitution(const QString &familyName,
1890 const QString &substituteName)
1891{
1892 initFontSubst();
1893
1894 QFontSubst *fontSubst = globalFontSubst();
1895 Q_ASSERT(fontSubst != 0);
1896 QStringList &list = (*fontSubst)[familyName.toLower()];
1897 QString s = substituteName.toLower();
1898 if (!list.contains(s))
1899 list.append(s);
1900}
1901
1902
1903/*!
1904 Inserts the list of families \a substituteNames into the
1905 substitution list for \a familyName.
1906
1907 \sa insertSubstitution(), removeSubstitution(), substitutions(), substitute()
1908*/
1909void QFont::insertSubstitutions(const QString &familyName,
1910 const QStringList &substituteNames)
1911{
1912 initFontSubst();
1913
1914 QFontSubst *fontSubst = globalFontSubst();
1915 Q_ASSERT(fontSubst != 0);
1916 QStringList &list = (*fontSubst)[familyName.toLower()];
1917 QStringList::ConstIterator it = substituteNames.constBegin();
1918 while (it != substituteNames.constEnd()) {
1919 QString s = (*it).toLower();
1920 if (!list.contains(s))
1921 list.append(s);
1922 it++;
1923 }
1924}
1925
1926/*! \fn void QFont::initialize()
1927 \internal
1928
1929 Internal function that initializes the font system. The font cache
1930 and font dict do not alloc the keys. The key is a QString which is
1931 shared between QFontPrivate and QXFontName.
1932*/
1933
1934/*! \fn void QFont::cleanup()
1935 \internal
1936
1937 Internal function that cleans up the font system.
1938*/
1939
1940// ### mark: should be called removeSubstitutions()
1941/*!
1942 Removes all the substitutions for \a familyName.
1943
1944 \sa insertSubstitutions(), insertSubstitution(), substitutions(), substitute()
1945*/
1946void QFont::removeSubstitution(const QString &familyName)
1947{ // ### function name should be removeSubstitutions() or
1948 // ### removeSubstitutionList()
1949 initFontSubst();
1950
1951 QFontSubst *fontSubst = globalFontSubst();
1952 Q_ASSERT(fontSubst != 0);
1953 fontSubst->remove(familyName.toLower());
1954}
1955
1956
1957/*!
1958 Returns a sorted list of substituted family names.
1959
1960 \sa insertSubstitution(), removeSubstitution(), substitute()
1961*/
1962QStringList QFont::substitutions()
1963{
1964 initFontSubst();
1965
1966 QFontSubst *fontSubst = globalFontSubst();
1967 Q_ASSERT(fontSubst != 0);
1968 QStringList ret;
1969 QFontSubst::ConstIterator it = fontSubst->constBegin();
1970
1971 while (it != fontSubst->constEnd()) {
1972 ret.append(it.key());
1973 ++it;
1974 }
1975
1976 ret.sort();
1977 return ret;
1978}
1979
1980
1981/* \internal
1982 Internal function. Converts boolean font settings to an unsigned
1983 8-bit number. Used for serialization etc.
1984*/
1985static quint8 get_font_bits(int version, const QFontPrivate *f)
1986{
1987 Q_ASSERT(f != 0);
1988 quint8 bits = 0;
1989 if (f->request.style)
1990 bits |= 0x01;
1991 if (f->underline)
1992 bits |= 0x02;
1993 if (f->overline)
1994 bits |= 0x40;
1995 if (f->strikeOut)
1996 bits |= 0x04;
1997 if (f->request.fixedPitch)
1998 bits |= 0x08;
1999 // if (f.hintSetByUser)
2000 // bits |= 0x10;
2001 if (f->rawMode)
2002 bits |= 0x20;
2003 if (version >= QDataStream::Qt_4_0) {
2004 if (f->kerning)
2005 bits |= 0x10;
2006 }
2007 if (f->request.style == QFont::StyleOblique)
2008 bits |= 0x80;
2009 return bits;
2010}
2011
2012static quint8 get_extended_font_bits(const QFontPrivate *f)
2013{
2014 Q_ASSERT(f != 0);
2015 quint8 bits = 0;
2016 if (f->request.ignorePitch)
2017 bits |= 0x01;
2018 if (f->letterSpacingIsAbsolute)
2019 bits |= 0x02;
2020 return bits;
2021}
2022
2023#ifndef QT_NO_DATASTREAM
2024
2025/* \internal
2026 Internal function. Sets boolean font settings from an unsigned
2027 8-bit number. Used for serialization etc.
2028*/
2029static void set_font_bits(int version, quint8 bits, QFontPrivate *f)
2030{
2031 Q_ASSERT(f != 0);
2032 f->request.style = (bits & 0x01) != 0 ? QFont::StyleItalic : QFont::StyleNormal;
2033 f->underline = (bits & 0x02) != 0;
2034 f->overline = (bits & 0x40) != 0;
2035 f->strikeOut = (bits & 0x04) != 0;
2036 f->request.fixedPitch = (bits & 0x08) != 0;
2037 // f->hintSetByUser = (bits & 0x10) != 0;
2038 f->rawMode = (bits & 0x20) != 0;
2039 if (version >= QDataStream::Qt_4_0)
2040 f->kerning = (bits & 0x10) != 0;
2041 if ((bits & 0x80) != 0)
2042 f->request.style = QFont::StyleOblique;
2043}
2044
2045static void set_extended_font_bits(quint8 bits, QFontPrivate *f)
2046{
2047 Q_ASSERT(f != 0);
2048 f->request.ignorePitch = (bits & 0x01) != 0;
2049 f->letterSpacingIsAbsolute = (bits & 0x02) != 0;
2050}
2051#endif
2052
2053
2054/*!
2055 Returns the font's key, a textual representation of a font. It is
2056 typically used as the key for a cache or dictionary of fonts.
2057
2058 \sa QMap
2059*/
2060QString QFont::key() const
2061{
2062 return toString();
2063}
2064
2065/*!
2066 Returns a description of the font. The description is a
2067 comma-separated list of the attributes, perfectly suited for use
2068 in QSettings.
2069
2070 \sa fromString()
2071 */
2072QString QFont::toString() const
2073{
2074 const QChar comma(QLatin1Char(','));
2075 return family() + comma +
2076 QString::number( pointSizeF()) + comma +
2077 QString::number( pixelSize()) + comma +
2078 QString::number((int) styleHint()) + comma +
2079 QString::number( weight()) + comma +
2080 QString::number((int) style()) + comma +
2081 QString::number((int) underline()) + comma +
2082 QString::number((int) strikeOut()) + comma +
2083 QString::number((int)fixedPitch()) + comma +
2084 QString::number((int) rawMode());
2085}
2086
2087
2088/*!
2089 Sets this font to match the description \a descrip. The description
2090 is a comma-separated list of the font attributes, as returned by
2091 toString().
2092
2093 \sa toString()
2094 */
2095bool QFont::fromString(const QString &descrip)
2096{
2097 QStringList l(descrip.split(QLatin1Char(',')));
2098
2099 int count = l.count();
2100 if (!count || (count > 2 && count < 9) || count > 11) {
2101 qWarning("QFont::fromString: Invalid description '%s'",
2102 descrip.isEmpty() ? "(empty)" : descrip.toLatin1().data());
2103 return false;
2104 }
2105
2106 setFamily(l[0]);
2107 if (count > 1 && l[1].toDouble() > 0.0)
2108 setPointSizeF(l[1].toDouble());
2109 if (count == 9) {
2110 setStyleHint((StyleHint) l[2].toInt());
2111 setWeight(qMax(qMin(99, l[3].toInt()), 0));
2112 setItalic(l[4].toInt());
2113 setUnderline(l[5].toInt());
2114 setStrikeOut(l[6].toInt());
2115 setFixedPitch(l[7].toInt());
2116 setRawMode(l[8].toInt());
2117 } else if (count == 10) {
2118 if (l[2].toInt() > 0)
2119 setPixelSize(l[2].toInt());
2120 setStyleHint((StyleHint) l[3].toInt());
2121 setWeight(qMax(qMin(99, l[4].toInt()), 0));
2122 setStyle((QFont::Style)l[5].toInt());
2123 setUnderline(l[6].toInt());
2124 setStrikeOut(l[7].toInt());
2125 setFixedPitch(l[8].toInt());
2126 setRawMode(l[9].toInt());
2127 }
2128 if (count >= 9 && !d->request.fixedPitch) // assume 'false' fixedPitch equals default
2129 d->request.ignorePitch = true;
2130
2131 return true;
2132}
2133
2134#if !defined(Q_WS_QWS)
2135/*! \internal
2136
2137 Internal function that dumps font cache statistics.
2138*/
2139void QFont::cacheStatistics()
2140{
2141
2142
2143}
2144#endif // !Q_WS_QWS
2145
2146
2147
2148/*****************************************************************************
2149 QFont stream functions
2150 *****************************************************************************/
2151#ifndef QT_NO_DATASTREAM
2152
2153/*!
2154 \relates QFont
2155
2156 Writes the font \a font to the data stream \a s. (toString()
2157 writes to a text stream.)
2158
2159 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
2160*/
2161QDataStream &operator<<(QDataStream &s, const QFont &font)
2162{
2163 if (s.version() == 1) {
2164 s << font.d->request.family.toLatin1();
2165 } else {
2166 s << font.d->request.family;
2167 }
2168
2169 if (s.version() >= QDataStream::Qt_4_0) {
2170 // 4.0
2171 double pointSize = font.d->request.pointSize;
2172 qint32 pixelSize = font.d->request.pixelSize;
2173 s << pointSize;
2174 s << pixelSize;
2175 } else if (s.version() <= 3) {
2176 qint16 pointSize = (qint16) (font.d->request.pointSize * 10);
2177 if (pointSize < 0) {
2178#ifdef Q_WS_X11
2179 pointSize = (qint16)(font.d->request.pixelSize*720/QX11Info::appDpiY());
2180#else
2181 pointSize = (qint16)QFontInfo(font).pointSize() * 10;
2182#endif
2183 }
2184 s << pointSize;
2185 } else {
2186 s << (qint16) (font.d->request.pointSize * 10);
2187 s << (qint16) font.d->request.pixelSize;
2188 }
2189
2190 s << (quint8) font.d->request.styleHint;
2191 if (s.version() >= QDataStream::Qt_3_1)
2192 s << (quint8) font.d->request.styleStrategy;
2193 s << (quint8) 0
2194 << (quint8) font.d->request.weight
2195 << get_font_bits(s.version(), font.d.data());
2196 if (s.version() >= QDataStream::Qt_4_3)
2197 s << (quint16)font.d->request.stretch;
2198 if (s.version() >= QDataStream::Qt_4_4)
2199 s << get_extended_font_bits(font.d.data());
2200 if (s.version() >= QDataStream::Qt_4_5) {
2201 s << font.d->letterSpacing.value();
2202 s << font.d->wordSpacing.value();
2203 }
2204 return s;
2205}
2206
2207
2208/*!
2209 \relates QFont
2210
2211 Reads the font \a font from the data stream \a s. (fromString()
2212 reads from a text stream.)
2213
2214 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
2215*/
2216QDataStream &operator>>(QDataStream &s, QFont &font)
2217{
2218 font.d = new QFontPrivate;
2219 font.resolve_mask = QFont::AllPropertiesResolved;
2220
2221 quint8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits;
2222
2223 if (s.version() == 1) {
2224 QByteArray fam;
2225 s >> fam;
2226 font.d->request.family = QString::fromLatin1(fam);
2227 } else {
2228 s >> font.d->request.family;
2229 }
2230
2231 if (s.version() >= QDataStream::Qt_4_0) {
2232 // 4.0
2233 double pointSize;
2234 qint32 pixelSize;
2235 s >> pointSize;
2236 s >> pixelSize;
2237 font.d->request.pointSize = qreal(pointSize);
2238 font.d->request.pixelSize = pixelSize;
2239 } else {
2240 qint16 pointSize, pixelSize = -1;
2241 s >> pointSize;
2242 if (s.version() >= 4)
2243 s >> pixelSize;
2244 font.d->request.pointSize = qreal(pointSize / 10.);
2245 font.d->request.pixelSize = pixelSize;
2246 }
2247 s >> styleHint;
2248 if (s.version() >= QDataStream::Qt_3_1)
2249 s >> styleStrategy;
2250
2251 s >> charSet;
2252 s >> weight;
2253 s >> bits;
2254
2255 font.d->request.styleHint = styleHint;
2256 font.d->request.styleStrategy = styleStrategy;
2257 font.d->request.weight = weight;
2258
2259 set_font_bits(s.version(), bits, font.d.data());
2260
2261 if (s.version() >= QDataStream::Qt_4_3) {
2262 quint16 stretch;
2263 s >> stretch;
2264 font.d->request.stretch = stretch;
2265 }
2266
2267 if (s.version() >= QDataStream::Qt_4_4) {
2268 quint8 extendedBits;
2269 s >> extendedBits;
2270 set_extended_font_bits(extendedBits, font.d.data());
2271 }
2272 if (s.version() >= QDataStream::Qt_4_5) {
2273 int value;
2274 s >> value;
2275 font.d->letterSpacing.setValue(value);
2276 s >> value;
2277 font.d->wordSpacing.setValue(value);
2278 }
2279
2280 return s;
2281}
2282
2283#endif // QT_NO_DATASTREAM
2284
2285
2286/*****************************************************************************
2287 QFontInfo member functions
2288 *****************************************************************************/
2289
2290/*!
2291 \class QFontInfo
2292 \reentrant
2293
2294 \brief The QFontInfo class provides general information about fonts.
2295
2296 \ingroup appearance
2297 \ingroup shared
2298
2299 The QFontInfo class provides the same access functions as QFont,
2300 e.g. family(), pointSize(), italic(), weight(), fixedPitch(),
2301 styleHint() etc. But whilst the QFont access functions return the
2302 values that were set, a QFontInfo object returns the values that
2303 apply to the font that will actually be used to draw the text.
2304
2305 For example, when the program asks for a 25pt Courier font on a
2306 machine that has a non-scalable 24pt Courier font, QFont will
2307 (normally) use the 24pt Courier for rendering. In this case,
2308 QFont::pointSize() returns 25 and QFontInfo::pointSize() returns
2309 24.
2310
2311 There are three ways to create a QFontInfo object.
2312 \list 1
2313 \o Calling the QFontInfo constructor with a QFont creates a font
2314 info object for a screen-compatible font, i.e. the font cannot be
2315 a printer font. If the font is changed later, the font
2316 info object is \e not updated.
2317
2318 (Note: If you use a printer font the values returned may be
2319 inaccurate. Printer fonts are not always accessible so the nearest
2320 screen font is used if a printer font is supplied.)
2321
2322 \o QWidget::fontInfo() returns the font info for a widget's font.
2323 This is equivalent to calling QFontInfo(widget->font()). If the
2324 widget's font is changed later, the font info object is \e not
2325 updated.
2326
2327 \o QPainter::fontInfo() returns the font info for a painter's
2328 current font. If the painter's font is changed later, the font
2329 info object is \e not updated.
2330 \endlist
2331
2332 \sa QFont QFontMetrics QFontDatabase
2333*/
2334
2335/*!
2336 Constructs a font info object for \a font.
2337
2338 The font must be screen-compatible, i.e. a font you use when
2339 drawing text in \link QWidget widgets\endlink or \link QPixmap
2340 pixmaps\endlink, not QPicture or QPrinter.
2341
2342 The font info object holds the information for the font that is
2343 passed in the constructor at the time it is created, and is not
2344 updated if the font's attributes are changed later.
2345
2346 Use QPainter::fontInfo() to get the font info when painting.
2347 This will give correct results also when painting on paint device
2348 that is not screen-compatible.
2349*/
2350QFontInfo::QFontInfo(const QFont &font)
2351 : d(font.d.data())
2352{
2353}
2354
2355/*!
2356 Constructs a copy of \a fi.
2357*/
2358QFontInfo::QFontInfo(const QFontInfo &fi)
2359 : d(fi.d.data())
2360{
2361}
2362
2363/*!
2364 Destroys the font info object.
2365*/
2366QFontInfo::~QFontInfo()
2367{
2368}
2369
2370/*!
2371 Assigns the font info in \a fi.
2372*/
2373QFontInfo &QFontInfo::operator=(const QFontInfo &fi)
2374{
2375 d = fi.d.data();
2376 return *this;
2377}
2378
2379/*!
2380 Returns the family name of the matched window system font.
2381
2382 \sa QFont::family()
2383*/
2384QString QFontInfo::family() const
2385{
2386 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2387 Q_ASSERT(engine != 0);
2388 return engine->fontDef.family;
2389}
2390
2391/*!
2392 Returns the point size of the matched window system font.
2393
2394 \sa pointSizeF() QFont::pointSize()
2395*/
2396int QFontInfo::pointSize() const
2397{
2398 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2399 Q_ASSERT(engine != 0);
2400 return qRound(engine->fontDef.pointSize);
2401}
2402
2403/*!
2404 Returns the point size of the matched window system font.
2405
2406 \sa QFont::pointSizeF()
2407*/
2408qreal QFontInfo::pointSizeF() const
2409{
2410 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2411 Q_ASSERT(engine != 0);
2412 return engine->fontDef.pointSize;
2413}
2414
2415/*!
2416 Returns the pixel size of the matched window system font.
2417
2418 \sa QFont::pointSize()
2419*/
2420int QFontInfo::pixelSize() const
2421{
2422 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2423 Q_ASSERT(engine != 0);
2424 return engine->fontDef.pixelSize;
2425}
2426
2427/*!
2428 Returns the italic value of the matched window system font.
2429
2430 \sa QFont::italic()
2431*/
2432bool QFontInfo::italic() const
2433{
2434 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2435 Q_ASSERT(engine != 0);
2436 return engine->fontDef.style != QFont::StyleNormal;
2437}
2438
2439/*!
2440 Returns the style value of the matched window system font.
2441
2442 \sa QFont::style()
2443*/
2444QFont::Style QFontInfo::style() const
2445{
2446 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2447 Q_ASSERT(engine != 0);
2448 return (QFont::Style)engine->fontDef.style;
2449}
2450
2451/*!
2452 Returns the weight of the matched window system font.
2453
2454 \sa QFont::weight(), bold()
2455*/
2456int QFontInfo::weight() const
2457{
2458 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2459 Q_ASSERT(engine != 0);
2460 return engine->fontDef.weight;
2461
2462}
2463
2464/*!
2465 \fn bool QFontInfo::bold() const
2466
2467 Returns true if weight() would return a value greater than
2468 QFont::Normal; otherwise returns false.
2469
2470 \sa weight(), QFont::bold()
2471*/
2472
2473/*!
2474 Returns the underline value of the matched window system font.
2475
2476 \sa QFont::underline()
2477
2478 \internal
2479
2480 Here we read the underline flag directly from the QFont.
2481 This is OK for X11 and for Windows because we always get what we want.
2482*/
2483bool QFontInfo::underline() const
2484{
2485 return d->underline;
2486}
2487
2488/*!
2489 Returns the overline value of the matched window system font.
2490
2491 \sa QFont::overline()
2492
2493 \internal
2494
2495 Here we read the overline flag directly from the QFont.
2496 This is OK for X11 and for Windows because we always get what we want.
2497*/
2498bool QFontInfo::overline() const
2499{
2500 return d->overline;
2501}
2502
2503/*!
2504 Returns the strikeout value of the matched window system font.
2505
2506 \sa QFont::strikeOut()
2507
2508 \internal Here we read the strikeOut flag directly from the QFont.
2509 This is OK for X11 and for Windows because we always get what we want.
2510*/
2511bool QFontInfo::strikeOut() const
2512{
2513 return d->strikeOut;
2514}
2515
2516/*!
2517 Returns the fixed pitch value of the matched window system font.
2518
2519 \sa QFont::fixedPitch()
2520*/
2521bool QFontInfo::fixedPitch() const
2522{
2523 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2524 Q_ASSERT(engine != 0);
2525#ifdef Q_OS_MAC
2526 if (!engine->fontDef.fixedPitchComputed) {
2527 QChar ch[2] = { QLatin1Char('i'), QLatin1Char('m') };
2528 QGlyphLayoutArray<2> g;
2529 int l = 2;
2530 engine->stringToCMap(ch, 2, &g, &l, 0);
2531 engine->fontDef.fixedPitch = g.advances_x[0] == g.advances_x[1];
2532 engine->fontDef.fixedPitchComputed = true;
2533 }
2534#endif
2535 return engine->fontDef.fixedPitch;
2536}
2537
2538/*!
2539 Returns the style of the matched window system font.
2540
2541 Currently only returns the style hint set in QFont.
2542
2543 \sa QFont::styleHint() QFont::StyleHint
2544*/
2545QFont::StyleHint QFontInfo::styleHint() const
2546{
2547 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2548 Q_ASSERT(engine != 0);
2549 return (QFont::StyleHint) engine->fontDef.styleHint;
2550}
2551
2552/*!
2553 Returns true if the font is a raw mode font; otherwise returns
2554 false.
2555
2556 If it is a raw mode font, all other functions in QFontInfo will
2557 return the same values set in the QFont, regardless of the font
2558 actually used.
2559
2560 \sa QFont::rawMode()
2561*/
2562bool QFontInfo::rawMode() const
2563{
2564 return d->rawMode;
2565}
2566
2567/*!
2568 Returns true if the matched window system font is exactly the same
2569 as the one specified by the font; otherwise returns false.
2570
2571 \sa QFont::exactMatch()
2572*/
2573bool QFontInfo::exactMatch() const
2574{
2575 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
2576 Q_ASSERT(engine != 0);
2577 return (d->rawMode
2578 ? engine->type() != QFontEngine::Box
2579 : d->request.exactMatch(engine->fontDef));
2580}
2581
2582
2583
2584
2585// **********************************************************************
2586// QFontCache
2587// **********************************************************************
2588
2589#ifdef QFONTCACHE_DEBUG
2590// fast timeouts for debugging
2591static const int fast_timeout = 1000; // 1s
2592static const int slow_timeout = 5000; // 5s
2593#else
2594static const int fast_timeout = 10000; // 10s
2595static const int slow_timeout = 300000; // 5m
2596#endif // QFONTCACHE_DEBUG
2597
2598const uint QFontCache::min_cost = 4*1024; // 4mb
2599
2600#ifdef QT_NO_THREAD
2601Q_GLOBAL_STATIC(QFontCache, theFontCache)
2602
2603QFontCache *QFontCache::instance()
2604{
2605 return theFontCache();
2606}
2607
2608void QFontCache::cleanup()
2609{
2610}
2611#else
2612Q_GLOBAL_STATIC(QThreadStorage<QFontCache *>, theFontCache)
2613
2614QFontCache *QFontCache::instance()
2615{
2616 QFontCache *&fontCache = theFontCache()->localData();
2617 if (!fontCache)
2618 fontCache = new QFontCache;
2619 return fontCache;
2620}
2621
2622void QFontCache::cleanup()
2623{
2624 QThreadStorage<QFontCache *> *cache = 0;
2625 QT_TRY {
2626 cache = theFontCache();
2627 } QT_CATCH (const std::bad_alloc &) {
2628 // no cache - just ignore
2629 }
2630 if (cache && cache->hasLocalData())
2631 cache->setLocalData(0);
2632}
2633#endif // QT_NO_THREAD
2634
2635QFontCache::QFontCache()
2636 : QObject(), total_cost(0), max_cost(min_cost),
2637 current_timestamp(0), fast(false), timer_id(-1)
2638{
2639}
2640
2641QFontCache::~QFontCache()
2642{
2643 {
2644 EngineDataCache::ConstIterator it = engineDataCache.constBegin(),
2645 end = engineDataCache.constEnd();
2646 while (it != end) {
2647 if (it.value()->ref == 0)
2648 delete it.value();
2649 else
2650 FC_DEBUG("QFontCache::~QFontCache: engineData %p still has refcount %d",
2651 it.value(), int(it.value()->ref));
2652 ++it;
2653 }
2654 }
2655 EngineCache::ConstIterator it = engineCache.constBegin(),
2656 end = engineCache.constEnd();
2657 while (it != end) {
2658 if (--it.value().data->cache_count == 0) {
2659 if (it.value().data->ref == 0) {
2660 FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %g %g %d %d %d)",
2661 it.value().data, it.key().script, it.key().def.pointSize,
2662 it.key().def.pixelSize, it.key().def.weight, it.key().def.style,
2663 it.key().def.fixedPitch);
2664
2665 delete it.value().data;
2666 } else {
2667 FC_DEBUG("QFontCache::~QFontCache: engine = %p still has refcount %d",
2668 it.value().data, int(it.value().data->ref));
2669 }
2670 }
2671 ++it;
2672 }
2673}
2674
2675void QFontCache::clear()
2676{
2677 {
2678 EngineDataCache::Iterator it = engineDataCache.begin(),
2679 end = engineDataCache.end();
2680 while (it != end) {
2681 QFontEngineData *data = it.value();
2682#if !defined(Q_WS_MAC)
2683 for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
2684 if (data->engines[i]) {
2685 data->engines[i]->ref.deref();
2686 data->engines[i] = 0;
2687 }
2688 }
2689#else
2690 if (data->engine) {
2691 data->engine->ref.deref();
2692 data->engine = 0;
2693 }
2694#endif
2695 ++it;
2696 }
2697 }
2698
2699 for (EngineCache::Iterator it = engineCache.begin(), end = engineCache.end();
2700 it != end; ++it) {
2701 if (it->data->ref == 0) {
2702 delete it->data;
2703 it->data = 0;
2704 }
2705 }
2706
2707 for (EngineCache::Iterator it = engineCache.begin(), end = engineCache.end();
2708 it != end; ++it) {
2709 if (it->data && it->data->ref == 0) {
2710 delete it->data;
2711 it->data = 0;
2712 }
2713 }
2714
2715 engineCache.clear();
2716}
2717
2718#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2)
2719void QFontCache::removeEngineForFont(const QByteArray &_fontName)
2720{
2721
2722 /* This could be optimized but the code becomes much more complex if we want to handle multi
2723 * font engines and it is probably not worth it. Therefore we just clear the entire font cache.
2724 */
2725 Q_UNUSED(_fontName);
2726 clear();
2727}
2728#endif
2729
2730QFontEngineData *QFontCache::findEngineData(const Key &key) const
2731{
2732 EngineDataCache::ConstIterator it = engineDataCache.find(key),
2733 end = engineDataCache.end();
2734 if (it == end) return 0;
2735
2736 // found
2737 return it.value();
2738}
2739
2740void QFontCache::insertEngineData(const Key &key, QFontEngineData *engineData)
2741{
2742 FC_DEBUG("QFontCache: inserting new engine data %p", engineData);
2743
2744 engineDataCache.insert(key, engineData);
2745 increaseCost(sizeof(QFontEngineData));
2746}
2747
2748QFontEngine *QFontCache::findEngine(const Key &key)
2749{
2750 EngineCache::Iterator it = engineCache.find(key),
2751 end = engineCache.end();
2752 if (it == end) return 0;
2753
2754 // found... update the hitcount and timestamp
2755 it.value().hits++;
2756 it.value().timestamp = ++current_timestamp;
2757
2758 FC_DEBUG("QFontCache: found font engine\n"
2759 " %p: timestamp %4u hits %3u ref %2d/%2d, type '%s'",
2760 it.value().data, it.value().timestamp, it.value().hits,
2761 int(it.value().data->ref), it.value().data->cache_count,
2762 it.value().data->name());
2763
2764 return it.value().data;
2765}
2766
2767void QFontCache::insertEngine(const Key &key, QFontEngine *engine)
2768{
2769 FC_DEBUG("QFontCache: inserting new engine %p", engine);
2770
2771 Engine data(engine);
2772 data.timestamp = ++current_timestamp;
2773
2774 engineCache.insert(key, data);
2775
2776 // only increase the cost if this is the first time we insert the engine
2777 if (engine->cache_count == 0)
2778 increaseCost(engine->cache_cost);
2779
2780 ++engine->cache_count;
2781}
2782
2783void QFontCache::increaseCost(uint cost)
2784{
2785 cost = (cost + 512) / 1024; // store cost in kb
2786 cost = cost > 0 ? cost : 1;
2787 total_cost += cost;
2788
2789 FC_DEBUG(" COST: increased %u kb, total_cost %u kb, max_cost %u kb",
2790 cost, total_cost, max_cost);
2791
2792 if (total_cost > max_cost) {
2793 max_cost = total_cost;
2794
2795 if (timer_id == -1 || ! fast) {
2796 FC_DEBUG(" TIMER: starting fast timer (%d ms)", fast_timeout);
2797
2798 if (timer_id != -1) killTimer(timer_id);
2799 timer_id = startTimer(fast_timeout);
2800 fast = true;
2801 }
2802 }
2803}
2804
2805void QFontCache::decreaseCost(uint cost)
2806{
2807 cost = (cost + 512) / 1024; // cost is stored in kb
2808 cost = cost > 0 ? cost : 1;
2809 Q_ASSERT(cost <= total_cost);
2810 total_cost -= cost;
2811
2812 FC_DEBUG(" COST: decreased %u kb, total_cost %u kb, max_cost %u kb",
2813 cost, total_cost, max_cost);
2814}
2815
2816#if defined(Q_WS_WIN) || defined (Q_WS_QWS)
2817void QFontCache::cleanupPrinterFonts()
2818{
2819 FC_DEBUG("QFontCache::cleanupPrinterFonts");
2820
2821 {
2822 FC_DEBUG(" CLEAN engine data:");
2823
2824 // clean out all unused engine data
2825 EngineDataCache::Iterator it = engineDataCache.begin(),
2826 end = engineDataCache.end();
2827 while (it != end) {
2828 if (it.key().screen == 0) {
2829 ++it;
2830 continue;
2831 }
2832
2833 if(it.value()->ref != 0) {
2834 for(int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
2835 if(it.value()->engines[i]) {
2836 it.value()->engines[i]->ref.deref();
2837 it.value()->engines[i] = 0;
2838 }
2839 }
2840 ++it;
2841 } else {
2842
2843 EngineDataCache::Iterator rem = it++;
2844
2845 decreaseCost(sizeof(QFontEngineData));
2846
2847 FC_DEBUG(" %p", rem.value());
2848
2849 delete rem.value();
2850 engineDataCache.erase(rem);
2851 }
2852 }
2853 }
2854
2855 EngineCache::Iterator it = engineCache.begin(),
2856 end = engineCache.end();
2857 while(it != end) {
2858 if (it.value().data->ref != 0 || it.key().screen == 0) {
2859 ++it;
2860 continue;
2861 }
2862
2863 FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, type '%s'",
2864 it.value().data, it.value().timestamp, it.value().hits,
2865 int(it.value().data->ref), it.value().data->cache_count,
2866 it.value().data->name());
2867
2868 if (--it.value().data->cache_count == 0) {
2869 FC_DEBUG(" DELETE: last occurrence in cache");
2870
2871 decreaseCost(it.value().data->cache_cost);
2872 delete it.value().data;
2873 }
2874
2875 engineCache.erase(it++);
2876 }
2877}
2878#endif
2879
2880void QFontCache::timerEvent(QTimerEvent *)
2881{
2882 FC_DEBUG("QFontCache::timerEvent: performing cache maintenance (timestamp %u)",
2883 current_timestamp);
2884
2885 if (total_cost <= max_cost && max_cost <= min_cost) {
2886 FC_DEBUG(" cache redused sufficiently, stopping timer");
2887
2888 killTimer(timer_id);
2889 timer_id = -1;
2890 fast = false;
2891
2892 return;
2893 }
2894
2895 // go through the cache and count up everything in use
2896 uint in_use_cost = 0;
2897
2898 {
2899 FC_DEBUG(" SWEEP engine data:");
2900
2901 // make sure the cost of each engine data is at least 1kb
2902 const uint engine_data_cost =
2903 sizeof(QFontEngineData) > 1024 ? sizeof(QFontEngineData) : 1024;
2904
2905 EngineDataCache::ConstIterator it = engineDataCache.constBegin(),
2906 end = engineDataCache.constEnd();
2907 for (; it != end; ++it) {
2908#ifdef QFONTCACHE_DEBUG
2909 FC_DEBUG(" %p: ref %2d", it.value(), int(it.value()->ref));
2910
2911# if defined(Q_WS_X11) || defined(Q_WS_WIN)
2912 // print out all engines
2913 for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
2914 if (! it.value()->engines[i])
2915 continue;
2916 FC_DEBUG(" contains %p", it.value()->engines[i]);
2917 }
2918# endif // Q_WS_X11 || Q_WS_WIN
2919#endif // QFONTCACHE_DEBUG
2920
2921 if (it.value()->ref != 0)
2922 in_use_cost += engine_data_cost;
2923 }
2924 }
2925
2926 {
2927 FC_DEBUG(" SWEEP engine:");
2928
2929 EngineCache::ConstIterator it = engineCache.constBegin(),
2930 end = engineCache.constEnd();
2931 for (; it != end; ++it) {
2932 FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes",
2933 it.value().data, it.value().timestamp, it.value().hits,
2934 int(it.value().data->ref), it.value().data->cache_count,
2935 it.value().data->cache_cost);
2936
2937 if (it.value().data->ref != 0)
2938 in_use_cost += it.value().data->cache_cost / it.value().data->cache_count;
2939 }
2940
2941 // attempt to make up for rounding errors
2942 in_use_cost += engineCache.size();
2943 }
2944
2945 in_use_cost = (in_use_cost + 512) / 1024; // cost is stored in kb
2946
2947 /*
2948 calculate the new maximum cost for the cache
2949
2950 NOTE: in_use_cost is *not* correct due to rounding errors in the
2951 above algorithm. instead of worrying about getting the
2952 calculation correct, we are more interested in speed, and use
2953 in_use_cost as a floor for new_max_cost
2954 */
2955 uint new_max_cost = qMax(qMax(max_cost / 2, in_use_cost), min_cost);
2956
2957 FC_DEBUG(" after sweep, in use %u kb, total %u kb, max %u kb, new max %u kb",
2958 in_use_cost, total_cost, max_cost, new_max_cost);
2959
2960 if (new_max_cost == max_cost) {
2961 if (fast) {
2962 FC_DEBUG(" cannot shrink cache, slowing timer");
2963
2964 killTimer(timer_id);
2965 timer_id = startTimer(slow_timeout);
2966 fast = false;
2967 }
2968
2969 return;
2970 } else if (! fast) {
2971 FC_DEBUG(" dropping into passing gear");
2972
2973 killTimer(timer_id);
2974 timer_id = startTimer(fast_timeout);
2975 fast = true;
2976 }
2977
2978 max_cost = new_max_cost;
2979
2980 {
2981 FC_DEBUG(" CLEAN engine data:");
2982
2983 // clean out all unused engine data
2984 EngineDataCache::Iterator it = engineDataCache.begin(),
2985 end = engineDataCache.end();
2986 while (it != end) {
2987 if (it.value()->ref != 0) {
2988 ++it;
2989 continue;
2990 }
2991
2992 EngineDataCache::Iterator rem = it++;
2993
2994 decreaseCost(sizeof(QFontEngineData));
2995
2996 FC_DEBUG(" %p", rem.value());
2997
2998 delete rem.value();
2999 engineDataCache.erase(rem);
3000 }
3001 }
3002
3003 // clean out the engine cache just enough to get below our new max cost
3004 uint current_cost;
3005 do {
3006 current_cost = total_cost;
3007
3008 EngineCache::Iterator it = engineCache.begin(),
3009 end = engineCache.end();
3010 // determine the oldest and least popular of the unused engines
3011 uint oldest = ~0u;
3012 uint least_popular = ~0u;
3013
3014 for (; it != end; ++it) {
3015 if (it.value().data->ref != 0)
3016 continue;
3017
3018 if (it.value().timestamp < oldest &&
3019 it.value().hits <= least_popular) {
3020 oldest = it.value().timestamp;
3021 least_popular = it.value().hits;
3022 }
3023 }
3024
3025 FC_DEBUG(" oldest %u least popular %u", oldest, least_popular);
3026
3027 for (it = engineCache.begin(); it != end; ++it) {
3028 if (it.value().data->ref == 0 &&
3029 it.value().timestamp == oldest &&
3030 it.value().hits == least_popular)
3031 break;
3032 }
3033
3034 if (it != end) {
3035 FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, type '%s'",
3036 it.value().data, it.value().timestamp, it.value().hits,
3037 int(it.value().data->ref), it.value().data->cache_count,
3038 it.value().data->name());
3039
3040 if (--it.value().data->cache_count == 0) {
3041 FC_DEBUG(" DELETE: last occurrence in cache");
3042
3043 decreaseCost(it.value().data->cache_cost);
3044 delete it.value().data;
3045 } else {
3046 /*
3047 this particular font engine is in the cache multiple
3048 times... set current_cost to zero, so that we can
3049 keep looping to get rid of all occurrences
3050 */
3051 current_cost = 0;
3052 }
3053
3054 engineCache.erase(it);
3055 }
3056 } while (current_cost != total_cost && total_cost > max_cost);
3057}
3058
3059
3060#ifndef QT_NO_DEBUG_STREAM
3061QDebug operator<<(QDebug stream, const QFont &font)
3062{
3063 return stream << "QFont(" << font.toString() << ')';
3064}
3065#endif
3066
3067QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.