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