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

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

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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