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

Last change on this file since 508 was 124, checked in by Dmitry A. Kuminov, 16 years ago

gui: Implemented QWidge::metric(). Added using of test (box) font engines on OS/2.

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