source: trunk/src/kernel/qfont.cpp@ 127

Last change on this file since 127 was 80, checked in by dmik, 19 years ago

Fixed a trap after issuing exit() if a QAplication instance has been created on the stack in main() (see ticket:10 for more info).

  • Property svn:keywords set to Id
File size: 95.1 KB
Line 
1/****************************************************************************
2** $Id: qfont.cpp 80 2006-04-06 19:32:24Z dmik $
3**
4** Implementation of QFont, QFontMetrics and QFontInfo classes
5**
6** Created : 941207
7**
8** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#define QT_FATAL_ASSERT
39
40#include "qfont.h"
41#include "qfontdatabase.h"
42#include "qfontmetrics.h"
43#include "qfontinfo.h"
44#include "qpainter.h"
45#include "qdict.h"
46#include "qcache.h"
47#include "qdatastream.h"
48#include "qapplication.h"
49#include "qcleanuphandler.h"
50#include "qstringlist.h"
51#ifdef Q_WS_MAC
52#include "qpaintdevicemetrics.h"
53#endif
54
55#include <private/qunicodetables_p.h>
56#include "qfontdata_p.h"
57#include "qfontengine_p.h"
58#include "qpainter_p.h"
59#include "qtextengine_p.h"
60
61// #define QFONTCACHE_DEBUG
62#ifdef QFONTCACHE_DEBUG
63# define FC_DEBUG qDebug
64#else
65# define FC_DEBUG if (FALSE) qDebug
66#endif
67
68
69
70
71bool QFontDef::operator==( const QFontDef &other ) const
72{
73 /*
74 QFontDef comparison is more complicated than just simple
75 per-member comparisons.
76
77 When comparing point/pixel sizes, either point or pixelsize
78 could be -1. in This case we have to compare the non negative
79 size value.
80
81 This test will fail if the point-sizes differ by 1/2 point or
82 more or they do not round to the same value. We have to do this
83 since our API still uses 'int' point-sizes in the API, but store
84 deci-point-sizes internally.
85
86 To compare the family members, we need to parse the font names
87 and compare the family/foundry strings separately. This allows
88 us to compare e.g. "Helvetica" and "Helvetica [Adobe]" with
89 positive results.
90 */
91 if (pixelSize != -1 && other.pixelSize != -1) {
92 if (pixelSize != other.pixelSize)
93 return FALSE;
94 } else if (pointSize != -1 && other.pointSize != -1) {
95 if (pointSize != other.pointSize
96 && (QABS(pointSize - other.pointSize) >= 5
97 || qRound(pointSize/10.) != qRound(other.pointSize/10.)))
98 return FALSE;
99 } else {
100 return FALSE;
101 }
102
103 if (!ignorePitch && !other.ignorePitch && fixedPitch != other.fixedPitch)
104 return FALSE;
105
106 if (stretch != 0 && other.stretch != 0 && stretch != other.stretch)
107 return FALSE;
108
109 QString this_family, this_foundry, other_family, other_foundry;
110 QFontDatabase::parseFontName(family, this_foundry, this_family);
111 QFontDatabase::parseFontName(other.family, other_foundry, other_family);
112
113 return ( styleHint == other.styleHint
114 && styleStrategy == other.styleStrategy
115 && weight == other.weight
116 && italic == other.italic
117 && this_family == other_family
118 && (this_foundry.isEmpty()
119 || other_foundry.isEmpty()
120 || this_foundry == other_foundry)
121#ifdef Q_WS_X11
122 && addStyle == other.addStyle
123#endif // Q_WS_X11
124 );
125}
126
127
128
129
130QFontPrivate::QFontPrivate()
131 : engineData( 0 ), paintdevice( 0 ),
132 rawMode( FALSE ), underline( FALSE ), overline( FALSE ), strikeOut( FALSE ),
133 mask( 0 )
134{
135#ifdef Q_WS_X11
136 screen = QPaintDevice::x11AppScreen();
137#else
138 screen = 0;
139#endif // Q_WS_X11
140}
141
142QFontPrivate::QFontPrivate( const QFontPrivate &other )
143 : QShared(), request( other.request ), engineData( 0 ),
144 paintdevice( other.paintdevice ), screen( other.screen ),
145 rawMode( other.rawMode ), underline( other.underline ), overline( other.overline ),
146 strikeOut( other.strikeOut ), mask( other.mask )
147{
148}
149
150QFontPrivate::~QFontPrivate()
151{
152 if ( engineData )
153 engineData->deref();
154 engineData = 0;
155}
156
157void QFontPrivate::resolve( const QFontPrivate *other )
158{
159#ifdef QT_CHECK_STATE
160 Q_ASSERT( other != 0 );
161#endif
162
163 if ( ( mask & Complete ) == Complete ) return;
164
165 // assign the unset-bits with the set-bits of the other font def
166 if ( ! ( mask & Family ) )
167 request.family = other->request.family;
168
169 if ( ! ( mask & Size ) ) {
170 request.pointSize = other->request.pointSize;
171 request.pixelSize = other->request.pixelSize;
172 }
173
174 if ( ! ( mask & StyleHint ) )
175 request.styleHint = other->request.styleHint;
176
177 if ( ! ( mask & StyleStrategy ) )
178 request.styleStrategy = other->request.styleStrategy;
179
180 if ( ! ( mask & Weight ) )
181 request.weight = other->request.weight;
182
183 if ( ! ( mask & Italic ) )
184 request.italic = other->request.italic;
185
186 if ( ! ( mask & FixedPitch ) )
187 request.fixedPitch = other->request.fixedPitch;
188
189 if ( ! ( mask & Stretch ) )
190 request.stretch = other->request.stretch;
191
192 if ( ! ( mask & Underline ) )
193 underline = other->underline;
194
195 if ( ! ( mask & Overline ) )
196 overline = other->overline;
197
198 if ( ! ( mask & StrikeOut ) )
199 strikeOut = other->strikeOut;
200}
201
202
203
204
205QFontEngineData::QFontEngineData()
206 : lineWidth( 1 )
207{
208#if defined(Q_WS_X11) || defined(Q_WS_WIN)
209 memset( engines, 0, QFont::LastPrivateScript * sizeof( QFontEngine * ) );
210#else
211 engine = 0;
212#endif // Q_WS_X11 || Q_WS_WIN
213#ifndef Q_WS_MAC
214 memset( widthCache, 0, widthCacheSize*sizeof( uchar ) );
215#endif
216}
217
218QFontEngineData::~QFontEngineData()
219{
220#if defined(Q_WS_X11) || defined(Q_WS_WIN)
221 for ( int i = 0; i < QFont::LastPrivateScript; i++ ) {
222 if ( engines[i] )
223 engines[i]->deref();
224 engines[i] = 0;
225 }
226#else
227 if ( engine )
228 engine->deref();
229 engine = 0;
230#endif // Q_WS_X11 || Q_WS_WIN
231}
232
233
234
235
236/*!
237 \class QFont qfont.h
238 \brief The QFont class specifies a font used for drawing text.
239
240 \ingroup graphics
241 \ingroup appearance
242 \ingroup shared
243 \mainclass
244
245 When you create a QFont object you specify various attributes that
246 you want the font to have. Qt will use the font with the specified
247 attributes, or if no matching font exists, Qt will use the closest
248 matching installed font. The attributes of the font that is
249 actually used are retrievable from a QFontInfo object. If the
250 window system provides an exact match exactMatch() returns TRUE.
251 Use QFontMetrics to get measurements, e.g. the pixel length of a
252 string using QFontMetrics::width().
253
254 Use QApplication::setFont() to set the application's default font.
255
256 If a choosen X11 font does not include all the characters that
257 need to be displayed, QFont will try to find the characters in the
258 nearest equivalent fonts. When a QPainter draws a character from a
259 font the QFont will report whether or not it has the character; if
260 it does not, QPainter will draw an unfilled square.
261
262 Create QFonts like this:
263 \code
264 QFont serifFont( "Times", 10, Bold );
265 QFont sansFont( "Helvetica [Cronyx]", 12 );
266 \endcode
267
268 The attributes set in the constructor can also be set later, e.g.
269 setFamily(), setPointSize(), setPointSizeFloat(), setWeight() and
270 setItalic(). The remaining attributes must be set after
271 contstruction, e.g. setBold(), setUnderline(), setOverline(),
272 setStrikeOut() and setFixedPitch(). QFontInfo objects should be
273 created \e after the font's attributes have been set. A QFontInfo
274 object will not change, even if you change the font's
275 attributes. The corresponding "get" functions, e.g. family(),
276 pointSize(), etc., return the values that were set, even though
277 the values used may differ. The actual values are available from a
278 QFontInfo object.
279
280 If the requested font family is unavailable you can influence the
281 \link #fontmatching font matching algorithm\endlink by choosing a
282 particular \l{QFont::StyleHint} and \l{QFont::StyleStrategy} with
283 setStyleHint(). The default family (corresponding to the current
284 style hint) is returned by defaultFamily().
285
286 The font-matching algorithm has a lastResortFamily() and
287 lastResortFont() in cases where a suitable match cannot be found.
288 You can provide substitutions for font family names using
289 insertSubstitution() and insertSubstitutions(). Substitutions can
290 be removed with removeSubstitution(). Use substitute() to retrieve
291 a family's first substitute, or the family name itself if it has
292 no substitutes. Use substitutes() to retrieve a list of a family's
293 substitutes (which may be empty).
294
295 Every QFont has a key() which you can use, for example, as the key
296 in a cache or dictionary. If you want to store a user's font
297 preferences you could use QSettings, writing the font information
298 with toString() and reading it back with fromString(). The
299 operator<<() and operator>>() functions are also available, but
300 they work on a data stream.
301
302 It is possible to set the height of characters shown on the screen
303 to a specified number of pixels with setPixelSize(); however using
304 setPointSize() has a similar effect and provides device
305 independence.
306
307 Under the X Window System you can set a font using its system
308 specific name with setRawName().
309
310 Loading fonts can be expensive, especially on X11. QFont contains
311 extensive optimizations to make the copying of QFont objects fast,
312 and to cache the results of the slow window system functions it
313 depends upon.
314
315 \target fontmatching
316 The font matching algorithm works as follows:
317 \list 1
318 \i The specified font family is searched for.
319 \i If not found, the styleHint() is used to select a replacement
320 family.
321 \i Each replacement font family is searched for.
322 \i If none of these are found or there was no styleHint(), "helvetica"
323 will be searched for.
324 \i If "helvetica" isn't found Qt will try the lastResortFamily().
325 \i If the lastResortFamily() isn't found Qt will try the
326 lastResortFont() which will always return a name of some kind.
327 \endlist
328
329 Once a font is found, the remaining attributes are matched in order of
330 priority:
331 \list 1
332 \i fixedPitch()
333 \i pointSize() (see below)
334 \i weight()
335 \i italic()
336 \endlist
337
338 If you have a font which matches on family, even if none of the
339 other attributes match, this font will be chosen in preference to
340 a font which doesn't match on family but which does match on the
341 other attributes. This is because font family is the dominant
342 search criteria.
343
344 The point size is defined to match if it is within 20% of the
345 requested point size. When several fonts match and are only
346 distinguished by point size, the font with the closest point size
347 to the one requested will be chosen.
348
349 The actual family, font size, weight and other font attributes
350 used for drawing text will depend on what's available for the
351 chosen family under the window system. A QFontInfo object can be
352 used to determine the actual values used for drawing the text.
353
354 Examples:
355
356 \code
357 QFont f("Helvetica");
358 \endcode
359 If you had both an Adobe and a Cronyx Helvetica, you might get
360 either.
361
362 \code
363 QFont f1( "Helvetica [Cronyx]" ); // Qt 3.x
364 QFont f2( "Cronyx-Helvetica" ); // Qt 2.x compatibility
365 \endcode
366 You can specify the foundry you want in the family name. Both fonts,
367 f1 and f2, in the above example will be set to "Helvetica
368 [Cronyx]".
369
370 To determine the attributes of the font actually used in the window
371 system, use a QFontInfo object, e.g.
372 \code
373 QFontInfo info( f1 );
374 QString family = info.family();
375 \endcode
376
377 To find out font metrics use a QFontMetrics object, e.g.
378 \code
379 QFontMetrics fm( f1 );
380 int pixelWidth = fm.width( "How many pixels wide is this text?" );
381 int pixelHeight = fm.height();
382 \endcode
383
384 For more general information on fonts, see the
385 \link http://www.nwalsh.com/comp.fonts/FAQ/ comp.fonts FAQ.\endlink
386 Information on encodings can be found from
387 \link http://czyborra.com/ Roman Czyborra's\endlink page.
388
389 \sa QFontMetrics QFontInfo QFontDatabase QApplication::setFont()
390 QWidget::setFont() QPainter::setFont() QFont::StyleHint
391 QFont::Weight
392*/
393
394/*!
395 \enum QFont::Script
396
397 This enum represents \link unicode.html Unicode \endlink allocated
398 scripts. For exhaustive coverage see \link
399 http://www.amazon.com/exec/obidos/ASIN/0201616335/trolltech/t The
400 Unicode Standard Version 3.0 \endlink. The following scripts are
401 supported:
402
403 Modern European alphabetic scripts (left to right):
404
405 \value Latin consists of most alphabets based on the original Latin alphabet.
406 \value Greek covers ancient and modern Greek and Coptic.
407 \value Cyrillic covers the Slavic and non-Slavic languages using
408 cyrillic alphabets.
409 \value Armenian contains the Armenian alphabet used with the
410 Armenian language.
411 \value Georgian covers at least the language Georgian.
412 \value Runic covers the known constituents of the Runic alphabets used
413 by the early and medieval societies in the Germanic,
414 Scandinavian, and Anglo-Saxon areas.
415 \value Ogham is an alphabetical script used to write a very early
416 form of Irish.
417 \value SpacingModifiers are small signs indicating modifications
418 to the preceeding letter.
419 \value CombiningMarks consist of diacritical marks not specific to
420 a particular alphabet, diacritical marks used in
421 combination with mathematical and technical symbols, and
422 glyph encodings applied to multiple letterforms.
423
424 Middle Eastern scripts (right to left):
425
426 \value Hebrew is used for writing Hebrew, Yiddish, and some other languages.
427 \value Arabic covers the Arabic language as well as Persian, Urdu,
428 Kurdish and some others.
429 \value Syriac is used to write the active liturgical languages and
430 dialects of several Middle Eastern and Southeast Indian
431 communities.
432 \value Thaana is used to write the Maledivian Dhivehi language.
433
434 South and Southeast Asian scripts (left to right with few historical exceptions):
435
436 \value Devanagari covers classical Sanskrit and modern Hindi as
437 well as several other languages.
438 \value Bengali is a relative to Devanagari employed to write the
439 Bengali language used in West Bengal/India and Bangladesh
440 as well as several minority languages.
441 \value Gurmukhi is another Devanagari relative used to write Punjabi.
442 \value Gujarati is closely related to Devanagari and used to write
443 the Gujarati language of the Gujarat state in India.
444 \value Oriya is used to write the Oriya language of Orissa state/India.
445 \value Tamil is used to write the Tamil language of Tamil Nadu state/India,
446 Sri Lanka, Singapore and parts of Malaysia as well as some
447 minority languages.
448 \value Telugu is used to write the Telugu language of Andhra
449 Pradesh state/India and some minority languages.
450 \value Kannada is another South Indian script used to write the
451 Kannada language of Karnataka state/India and some minority
452 languages.
453 \value Malayalam is used to write the Malayalam language of Kerala
454 state/India.
455 \value Sinhala is used for Sri Lanka's majority language Sinhala
456 and is also employed to write Pali, Sanskrit, and Tamil.
457 \value Thai is used to write Thai and other Southeast Asian languages.
458 \value Lao is a language and script quite similar to Thai.
459 \value Tibetan is the script used to write Tibetan in several
460 countries like Tibet, the bordering Indian regions and
461 Nepal. It is also used in the Buddist philosophy and
462 liturgy of the Mongolian cultural area.
463 \value Myanmar is mainly used to write the Burmese language of
464 Myanmar (former Burma).
465 \value Khmer is the official language of Kampuchea.
466
467 East Asian scripts (traditionally top-down, right to left, modern
468 often horizontal left to right):
469
470 \value Han consists of the CJK (Chinese, Japanese, Korean)
471 idiographic characters.
472 \value Hiragana is a cursive syllabary used to indicate phonetics
473 and pronounciation of Japanese words.
474 \value Katakana is a non-cursive syllabic script used to write
475 Japanese words with visual emphasis and non-Japanese words
476 in a phonetical manner.
477 \value Hangul is a Korean script consisting of alphabetic components.
478 \value Bopomofo is a phonetic alphabet for Chinese (mainly Mandarin).
479 \value Yi (also called Cuan or Wei) is a syllabary used to write
480 the Yi language of Southwestern China, Myanmar, Laos, and Vietnam.
481
482 Additional scripts that do not fit well into the script categories above:
483
484 \value Ethiopic is a syllabary used by several Central East African languages.
485 \value Cherokee is a left-to-right syllabic script used to write
486 the Cherokee language.
487 \value CanadianAboriginal consists of the syllabics used by some
488 Canadian aboriginal societies.
489 \value Mongolian is the traditional (and recently reintroduced)
490 script used to write Mongolian.
491
492 Symbols:
493
494 \value CurrencySymbols contains currency symbols not encoded in other scripts.
495 \value LetterlikeSymbols consists of symbols derived from
496 ordinary letters of an alphabetical script.
497 \value NumberForms are provided for compatibility with other
498 existing character sets.
499 \value MathematicalOperators consists of encodings for operators,
500 relations and other symbols like arrows used in a mathematical context.
501 \value TechnicalSymbols contains representations for control
502 codes, the space symbol, APL symbols and other symbols
503 mainly used in the context of electronic data processing.
504 \value GeometricSymbols covers block elements and geometric shapes.
505 \value MiscellaneousSymbols consists of a heterogeneous collection
506 of symbols that do not fit any other Unicode character
507 block, e.g. Dingbats.
508 \value EnclosedAndSquare is provided for compatibility with some
509 East Asian standards.
510 \value Braille is an international writing system used by blind
511 people. This script encodes the 256 eight-dot patterns with
512 the 64 six-dot patterns as a subset.
513
514 \value Tagalog
515 \value Hanunoo
516 \value Buhid
517 \value Tagbanwa
518
519 \value KatakanaHalfWidth
520
521 \value Limbu (Unicode 4.0)
522 \value TaiLe (Unicode 4.0)
523
524 \value Unicode includes all the above scripts.
525*/
526
527/*! \internal
528
529 Constructs a font for use on the paint device \a pd using the
530 specified font \a data.
531*/
532QFont::QFont( QFontPrivate *data, QPaintDevice *pd )
533{
534 d = new QFontPrivate( *data );
535 Q_CHECK_PTR( d );
536 d->paintdevice = pd;
537
538 // now a single reference
539 d->count = 1;
540}
541
542/*! \internal
543 Detaches the font object from common font data.
544*/
545void QFont::detach()
546{
547 if (d->count == 1) {
548 if ( d->engineData )
549 d->engineData->deref();
550 d->engineData = 0;
551
552 return;
553 }
554
555 QFontPrivate *old_d = d;
556 d = new QFontPrivate( *old_d );
557
558 /*
559 if this font is a copy of the application default font, set the
560 fontdef mask to zero to indicate that *nothing* has been
561 explicitly set by the programmer.
562 */
563 const QFont appfont = QApplication::font();
564 if ( old_d == appfont.d )
565 d->mask = 0;
566
567 if ( old_d->deref() )
568 delete old_d;
569}
570
571/*!
572 Constructs a font object that uses the application's default font.
573
574 \sa QApplication::setFont(), QApplication::font()
575*/
576QFont::QFont()
577{
578 const QFont appfont = QApplication::font();
579 d = appfont.d;
580 d->ref();
581}
582
583/*!
584 Constructs a font object with the specified \a family, \a
585 pointSize, \a weight and \a italic settings.
586
587 If \a pointSize is <= 0 it is set to 1.
588
589 The \a family name may optionally also include a foundry name,
590 e.g. "Helvetica [Cronyx]". (The Qt 2.x syntax, i.e.
591 "Cronyx-Helvetica", is also supported.) If the \a family is
592 available from more than one foundry and the foundry isn't
593 specified, an arbitrary foundry is chosen. If the family isn't
594 available a family will be set using the \link #fontmatching font
595 matching\endlink algorithm.
596
597 \sa Weight, setFamily(), setPointSize(), setWeight(), setItalic(),
598 setStyleHint() QApplication::font()
599*/
600QFont::QFont( const QString &family, int pointSize, int weight, bool italic )
601{
602
603 d = new QFontPrivate;
604 Q_CHECK_PTR( d );
605
606 d->mask = QFontPrivate::Family;
607
608 if (pointSize <= 0) {
609 pointSize = 12;
610 } else {
611 d->mask |= QFontPrivate::Size;
612 }
613
614 if (weight < 0) {
615 weight = Normal;
616 } else {
617 d->mask |= QFontPrivate::Weight | QFontPrivate::Italic;
618 }
619
620 d->request.family = family;
621 d->request.pointSize = pointSize * 10;
622 d->request.pixelSize = -1;
623 d->request.weight = weight;
624 d->request.italic = italic;
625}
626
627/*!
628 Constructs a font that is a copy of \a font.
629*/
630QFont::QFont( const QFont &font )
631{
632 d = font.d;
633 d->ref();
634}
635
636/*!
637 Destroys the font object and frees all allocated resources.
638*/
639QFont::~QFont()
640{
641 if ( d->deref() )
642 delete d;
643 d = 0;
644}
645
646/*!
647 Assigns \a font to this font and returns a reference to it.
648*/
649QFont &QFont::operator=( const QFont &font )
650{
651 if ( font.d != d ) {
652 if ( d->deref() )
653 delete d;
654 d = font.d;
655 d->ref();
656 }
657
658 return *this;
659}
660
661/*!
662 Returns the requested font family name, i.e. the name set in the
663 constructor or the last setFont() call.
664
665 \sa setFamily() substitutes() substitute()
666*/
667QString QFont::family() const
668{
669 return d->request.family;
670}
671
672/*!
673 Sets the family name of the font. The name is case insensitive and
674 may include a foundry name.
675
676 The \a family name may optionally also include a foundry name,
677 e.g. "Helvetica [Cronyx]". (The Qt 2.x syntax, i.e.
678 "Cronyx-Helvetica", is also supported.) If the \a family is
679 available from more than one foundry and the foundry isn't
680 specified, an arbitrary foundry is chosen. If the family isn't
681 available a family will be set using the \link #fontmatching font
682 matching\endlink algorithm.
683
684 \sa family(), setStyleHint(), QFontInfo
685*/
686void QFont::setFamily( const QString &family )
687{
688 detach();
689
690 d->request.family = family;
691#if defined(Q_WS_X11)
692 d->request.addStyle = QString::null;
693#endif // Q_WS_X11
694
695 d->mask |= QFontPrivate::Family;
696}
697
698/*!
699 Returns the point size in 1/10ths of a point.
700
701 The returned value will be -1 if the font size has been specified
702 in pixels.
703
704 \sa pointSize() pointSizeFloat()
705 */
706int QFont::deciPointSize() const
707{
708 return d->request.pointSize;
709}
710
711/*!
712 Returns the point size of the font. Returns -1 if the font size
713 was specified in pixels.
714
715 \sa setPointSize() deciPointSize() pointSizeFloat()
716*/
717int QFont::pointSize() const
718{
719 return d->request.pointSize == -1 ? -1 : (d->request.pointSize + 5) / 10;
720}
721
722/*!
723 Sets the point size to \a pointSize. The point size must be
724 greater than zero.
725
726 \sa pointSize() setPointSizeFloat()
727*/
728void QFont::setPointSize( int pointSize )
729{
730 if ( pointSize <= 0 ) {
731
732#if defined(QT_CHECK_RANGE)
733 qWarning( "QFont::setPointSize: Point size <= 0 (%d)", pointSize );
734#endif
735
736 return;
737 }
738
739 detach();
740
741 d->request.pointSize = pointSize * 10;
742 d->request.pixelSize = -1;
743
744 d->mask |= QFontPrivate::Size;
745}
746
747/*!
748 Sets the point size to \a pointSize. The point size must be
749 greater than zero. The requested precision may not be achieved on
750 all platforms.
751
752 \sa pointSizeFloat() setPointSize() setPixelSize()
753*/
754void QFont::setPointSizeFloat( float pointSize )
755{
756 if ( pointSize <= 0.0 ) {
757#if defined(QT_CHECK_RANGE)
758 qWarning( "QFont::setPointSize: Point size <= 0 (%f)", pointSize );
759#endif
760 return;
761 }
762
763 detach();
764
765 d->request.pointSize = qRound(pointSize * 10.0);
766 d->request.pixelSize = -1;
767
768 d->mask |= QFontPrivate::Size;
769}
770
771/*!
772 Returns the point size of the font. Returns -1 if the font size was
773 specified in pixels.
774
775 \sa pointSize() setPointSizeFloat() pixelSize() QFontInfo::pointSize() QFontInfo::pixelSize()
776*/
777float QFont::pointSizeFloat() const
778{
779 return float( d->request.pointSize == -1 ? -10 : d->request.pointSize ) / 10.0;
780}
781
782/*!
783 Sets the font size to \a pixelSize pixels.
784
785 Using this function makes the font device dependent. Use
786 setPointSize() or setPointSizeFloat() to set the size of the font
787 in a device independent manner.
788
789 \sa pixelSize()
790*/
791void QFont::setPixelSize( int pixelSize )
792{
793 if ( pixelSize <= 0 ) {
794#if defined(QT_CHECK_RANGE)
795 qWarning( "QFont::setPixelSize: Pixel size <= 0 (%d)", pixelSize );
796#endif
797 return;
798 }
799
800 detach();
801
802 d->request.pixelSize = pixelSize;
803 d->request.pointSize = -1;
804
805 d->mask |= QFontPrivate::Size;
806}
807
808/*!
809 Returns the pixel size of the font if it was set with
810 setPixelSize(). Returns -1 if the size was set with setPointSize()
811 or setPointSizeFloat().
812
813 \sa setPixelSize() pointSize() QFontInfo::pointSize() QFontInfo::pixelSize()
814*/
815int QFont::pixelSize() const
816{
817 return d->request.pixelSize;
818}
819
820/*! \obsolete
821
822 Sets the logical pixel height of font characters when shown on
823 the screen to \a pixelSize.
824*/
825void QFont::setPixelSizeFloat( float pixelSize )
826{
827 setPixelSize( (int)pixelSize );
828}
829
830/*!
831 Returns TRUE if italic has been set; otherwise returns FALSE.
832
833 \sa setItalic()
834*/
835bool QFont::italic() const
836{
837 return d->request.italic;
838}
839
840/*!
841 If \a enable is TRUE, italic is set on; otherwise italic is set
842 off.
843
844 \sa italic(), QFontInfo
845*/
846void QFont::setItalic( bool enable )
847{
848 detach();
849
850 d->request.italic = enable;
851 d->mask |= QFontPrivate::Italic;
852}
853
854/*!
855 Returns the weight of the font which is one of the enumerated
856 values from \l{QFont::Weight}.
857
858 \sa setWeight(), Weight, QFontInfo
859*/
860int QFont::weight() const
861{
862 return d->request.weight;
863}
864
865/*!
866 \enum QFont::Weight
867
868 Qt uses a weighting scale from 0 to 99 similar to, but not the
869 same as, the scales used in Windows or CSS. A weight of 0 is
870 ultralight, whilst 99 will be an extremely black.
871
872 This enum contains the predefined font weights:
873
874 \value Light 25
875 \value Normal 50
876 \value DemiBold 63
877 \value Bold 75
878 \value Black 87
879*/
880
881/*!
882 Sets the weight the font to \a weight, which should be a value
883 from the \l QFont::Weight enumeration.
884
885 \sa weight(), QFontInfo
886*/
887void QFont::setWeight( int weight )
888{
889 if ( weight < 0 || weight > 99 ) {
890
891#if defined(QT_CHECK_RANGE)
892 qWarning( "QFont::setWeight: Value out of range (%d)", weight );
893#endif
894
895 return;
896 }
897
898 detach();
899
900 d->request.weight = weight;
901 d->mask |= QFontPrivate::Weight;
902}
903
904/*!
905 \fn bool QFont::bold() const
906
907 Returns TRUE if weight() is a value greater than \link Weight
908 QFont::Normal \endlink; otherwise returns FALSE.
909
910 \sa weight(), setBold(), QFontInfo::bold()
911*/
912
913/*!
914 \fn void QFont::setBold( bool enable )
915
916 If \a enable is true sets the font's weight to \link Weight
917 QFont::Bold \endlink; otherwise sets the weight to \link Weight
918 QFont::Normal\endlink.
919
920 For finer boldness control use setWeight().
921
922 \sa bold(), setWeight()
923*/
924
925/*!
926 Returns TRUE if underline has been set; otherwise returns FALSE.
927
928 \sa setUnderline()
929*/
930bool QFont::underline() const
931{
932 return d->underline;
933}
934
935/*!
936 If \a enable is TRUE, sets underline on; otherwise sets underline
937 off.
938
939 \sa underline(), QFontInfo
940*/
941void QFont::setUnderline( bool enable )
942{
943 detach();
944
945 d->underline = enable;
946 d->mask |= QFontPrivate::Underline;
947}
948
949/*!
950 Returns TRUE if overline has been set; otherwise returns FALSE.
951
952 \sa setOverline()
953*/
954bool QFont::overline() const
955{
956 return d->overline;
957}
958
959/*!
960 If \a enable is TRUE, sets overline on; otherwise sets overline off.
961
962 \sa overline(), QFontInfo
963*/
964void QFont::setOverline( bool enable )
965{
966 detach();
967
968 d->overline = enable;
969 d->mask |= QFontPrivate::Overline;
970}
971
972/*!
973 Returns TRUE if strikeout has been set; otherwise returns FALSE.
974
975 \sa setStrikeOut()
976*/
977bool QFont::strikeOut() const
978{
979 return d->strikeOut;
980}
981
982/*!
983 If \a enable is TRUE, sets strikeout on; otherwise sets strikeout
984 off.
985
986 \sa strikeOut(), QFontInfo
987*/
988void QFont::setStrikeOut( bool enable )
989{
990 detach();
991
992 d->strikeOut = enable;
993 d->mask |= QFontPrivate::StrikeOut;
994}
995
996/*!
997 Returns TRUE if fixed pitch has been set; otherwise returns FALSE.
998
999 \sa setFixedPitch(), QFontInfo::fixedPitch()
1000*/
1001bool QFont::fixedPitch() const
1002{
1003 return d->request.fixedPitch;
1004}
1005
1006/*!
1007 If \a enable is TRUE, sets fixed pitch on; otherwise sets fixed
1008 pitch off.
1009
1010 \sa fixedPitch(), QFontInfo
1011*/
1012void QFont::setFixedPitch( bool enable )
1013{
1014 detach();
1015
1016 d->request.fixedPitch = enable;
1017 d->request.ignorePitch = FALSE;
1018 d->mask |= QFontPrivate::FixedPitch;
1019}
1020
1021/*!
1022 Returns the StyleStrategy.
1023
1024 The style strategy affects the \link #fontmatching font
1025 matching\endlink algorithm. See \l QFont::StyleStrategy for the
1026 list of strategies.
1027
1028 \sa setStyleHint() QFont::StyleHint
1029*/
1030QFont::StyleStrategy QFont::styleStrategy() const
1031{
1032 return (StyleStrategy) d->request.styleStrategy;
1033}
1034
1035/*!
1036 Returns the StyleHint.
1037
1038 The style hint affects the \link #fontmatching font
1039 matching\endlink algorithm. See \l QFont::StyleHint for the list
1040 of strategies.
1041
1042 \sa setStyleHint(), QFont::StyleStrategy QFontInfo::styleHint()
1043*/
1044QFont::StyleHint QFont::styleHint() const
1045{
1046 return (StyleHint) d->request.styleHint;
1047}
1048
1049/*!
1050 \enum QFont::StyleHint
1051
1052 Style hints are used by the \link #fontmatching font
1053 matching\endlink algorithm to find an appropriate default family
1054 if a selected font family is not available.
1055
1056 \value AnyStyle leaves the font matching algorithm to choose the
1057 family. This is the default.
1058
1059 \value SansSerif the font matcher prefer sans serif fonts.
1060 \value Helvetica is a synonym for \c SansSerif.
1061
1062 \value Serif the font matcher prefers serif fonts.
1063 \value Times is a synonym for \c Serif.
1064
1065 \value TypeWriter the font matcher prefers fixed pitch fonts.
1066 \value Courier a synonym for \c TypeWriter.
1067
1068 \value OldEnglish the font matcher prefers decorative fonts.
1069 \value Decorative is a synonym for \c OldEnglish.
1070
1071 \value System the font matcher prefers system fonts.
1072*/
1073
1074/*!
1075 \enum QFont::StyleStrategy
1076
1077 The style strategy tells the \link #fontmatching font
1078 matching\endlink algorithm what type of fonts should be used to
1079 find an appropriate default family.
1080
1081 The following strategies are available:
1082
1083 \value PreferDefault the default style strategy. It does not prefer
1084 any type of font.
1085 \value PreferBitmap prefers bitmap fonts (as opposed to outline
1086 fonts). On X11, this will cause Qt to disregard fonts from
1087 the Xft font extension.
1088 \value PreferDevice prefers device fonts.
1089 \value PreferOutline prefers outline fonts (as opposed to bitmap fonts).
1090 \value ForceOutline forces the use of outline fonts.
1091 \value NoAntialias don't antialias the fonts.
1092 \value PreferAntialias antialias if possible.
1093 \value OpenGLCompatible forces the use of OpenGL compatible
1094 fonts. On X11, this will cause Qt to disregard fonts from
1095 the Xft font extension.
1096
1097 Any of these may be OR-ed with one of these flags:
1098
1099 \value PreferMatch prefer an exact match. The font matcher will try to
1100 use the exact font size that has been specified.
1101 \value PreferQuality prefer the best quality font. The font matcher
1102 will use the nearest standard point size that the font
1103 supports.
1104*/
1105
1106/*!
1107 Sets the style hint and strategy to \a hint and \a strategy,
1108 respectively.
1109
1110 If these aren't set explicitly the style hint will default to
1111 \c AnyStyle and the style strategy to \c PreferDefault.
1112
1113 Qt does not support style hints on X11 since this information
1114 is not provided by the window system.
1115
1116 \sa StyleHint, styleHint(), StyleStrategy, styleStrategy(), QFontInfo
1117*/
1118void QFont::setStyleHint( StyleHint hint, StyleStrategy strategy )
1119{
1120 detach();
1121
1122 if ( ( d->mask & ( QFontPrivate::StyleHint | QFontPrivate::StyleStrategy ) ) &&
1123 (StyleHint) d->request.styleHint == hint &&
1124 (StyleStrategy) d->request.styleStrategy == strategy )
1125 return;
1126
1127 d->request.styleHint = hint;
1128 d->request.styleStrategy = strategy;
1129 d->mask |= QFontPrivate::StyleHint;
1130 d->mask |= QFontPrivate::StyleStrategy;
1131
1132#if defined(Q_WS_X11)
1133 d->request.addStyle = QString::null;
1134#endif // Q_WS_X11
1135}
1136
1137/*!
1138 Sets the style strategy for the font to \a s.
1139
1140 \sa QFont::StyleStrategy
1141*/
1142void QFont::setStyleStrategy( StyleStrategy s )
1143{
1144 detach();
1145
1146 if ( ( d->mask & QFontPrivate::StyleStrategy ) &&
1147 s == (StyleStrategy)d->request.styleStrategy )
1148 return;
1149
1150 d->request.styleStrategy = s;
1151 d->mask |= QFontPrivate::StyleStrategy;
1152}
1153
1154
1155/*!
1156 \enum QFont::Stretch
1157
1158 Predefined stretch values that follow the CSS naming convention.
1159
1160 \value UltraCondensed 50
1161 \value ExtraCondensed 62
1162 \value Condensed 75
1163 \value SemiCondensed 87
1164 \value Unstretched 100
1165 \value SemiExpanded 112
1166 \value Expanded 125
1167 \value ExtraExpanded 150
1168 \value UltraExpanded 200
1169
1170 \sa setStretch() stretch()
1171*/
1172
1173/*!
1174 Returns the stretch factor for the font.
1175
1176 \sa setStretch()
1177 */
1178int QFont::stretch() const
1179{
1180 return d->request.stretch;
1181}
1182
1183/*!
1184 Sets the stretch factor for the font.
1185
1186 The stretch factor changes the width of all characters in the font
1187 by \a factor percent. For example, setting \a factor to 150
1188 results in all characters in the font being 1.5 times ( ie. 150% )
1189 wider. The default stretch factor is 100. The minimum stretch
1190 factor is 1, and the maximum stretch factor is 4000.
1191
1192 The stretch factor is only applied to outline fonts. The stretch
1193 factor is ignored for bitmap fonts.
1194
1195 NOTE: QFont cannot stretch XLFD fonts. When loading XLFD fonts on
1196 X11, the stretch factor is matched against a predefined set of
1197 values for the SETWIDTH_NAME field of the XLFD.
1198
1199 \sa stretch() QFont::StyleStrategy
1200*/
1201void QFont::setStretch( int factor )
1202{
1203 if ( factor < 1 || factor > 4000 ) {
1204#ifdef QT_CHECK_RANGE
1205 qWarning( "QFont::setStretch(): parameter '%d' out of range", factor );
1206#endif // QT_CHECK_RANGE
1207
1208 return;
1209 }
1210
1211 detach();
1212
1213 if ( ( d->mask & QFontPrivate::Stretch ) &&
1214 d->request.stretch == (uint)factor )
1215 return;
1216
1217 d->request.stretch = (uint)factor;
1218 d->mask |= QFontPrivate::Stretch;
1219}
1220
1221/*!
1222 If \a enable is TRUE, turns raw mode on; otherwise turns raw mode
1223 off. This function only has an effect under X11.
1224
1225 If raw mode is enabled, Qt will search for an X font with a
1226 complete font name matching the family name, ignoring all other
1227 values set for the QFont. If the font name matches several fonts,
1228 Qt will use the first font returned by X. QFontInfo \e cannot be
1229 used to fetch information about a QFont using raw mode (it will
1230 return the values set in the QFont for all parameters, including
1231 the family name).
1232
1233 \warning Do not use raw mode unless you really, really need it! In
1234 most (if not all) cases, setRawName() is a much better choice.
1235
1236 \sa rawMode(), setRawName()
1237*/
1238void QFont::setRawMode( bool enable )
1239{
1240 detach();
1241
1242 if ( (bool) d->rawMode == enable ) return;
1243
1244 d->rawMode = enable;
1245}
1246
1247/*!
1248 Returns TRUE if a window system font exactly matching the settings
1249 of this font is available.
1250
1251 \sa QFontInfo
1252*/
1253bool QFont::exactMatch() const
1254{
1255 QFontEngine *engine = d->engineForScript( QFont::NoScript );
1256#ifdef QT_CHECK_STATE
1257 Q_ASSERT( engine != 0 );
1258#endif // QT_CHECK_STATE
1259
1260 return d->rawMode ? engine->type() != QFontEngine::Box
1261 : d->request == engine->fontDef;
1262}
1263
1264/*!
1265 Returns TRUE if this font is equal to \a f; otherwise returns
1266 FALSE.
1267
1268 Two QFonts are considered equal if their font attributes are
1269 equal. If rawMode() is enabled for both fonts, only the family
1270 fields are compared.
1271
1272 \sa operator!=() isCopyOf()
1273*/
1274bool QFont::operator==( const QFont &f ) const
1275{
1276 return f.d == d || ( f.d->request == d->request &&
1277 f.d->underline == d->underline &&
1278 f.d->overline == d->overline &&
1279 f.d->strikeOut == d->strikeOut );
1280}
1281
1282/*!
1283 Returns TRUE if this font is different from \a f; otherwise
1284 returns FALSE.
1285
1286 Two QFonts are considered to be different if their font attributes
1287 are different. If rawMode() is enabled for both fonts, only the
1288 family fields are compared.
1289
1290 \sa operator==()
1291*/
1292bool QFont::operator!=( const QFont &f ) const
1293{
1294 return !(operator==( f ));
1295}
1296
1297/*!
1298 Returns TRUE if this font and \a f are copies of each other, i.e.
1299 one of them was created as a copy of the other and neither has
1300 been modified since. This is much stricter than equality.
1301
1302 \sa operator=() operator==()
1303*/
1304bool QFont::isCopyOf( const QFont & f ) const
1305{
1306 return d == f.d;
1307}
1308
1309/*!
1310 Returns TRUE if raw mode is used for font name matching; otherwise
1311 returns FALSE.
1312
1313 \sa setRawMode() rawName()
1314*/
1315bool QFont::rawMode() const
1316{
1317 return d->rawMode;
1318}
1319
1320/*!
1321 Returns a new QFont that has attributes copied from \a other.
1322*/
1323QFont QFont::resolve( const QFont &other ) const
1324{
1325 if ( *this == other && d->mask == other.d->mask )
1326 return *this;
1327
1328 QFont font( *this );
1329 font.detach();
1330
1331 /*
1332 if this font is a copy of the application default font, set the
1333 fontdef mask to zero to indicate that *nothing* has been
1334 explicitly set by the programmer.
1335 */
1336 const QFont appfont = QApplication::font();
1337 if ( d == appfont.d )
1338 font.d->mask = 0;
1339
1340 font.d->resolve( other.d );
1341
1342 return font;
1343}
1344
1345#ifndef QT_NO_COMPAT
1346
1347/*! \obsolete
1348
1349 Please use QApplication::font() instead.
1350*/
1351QFont QFont::defaultFont()
1352{
1353 return QApplication::font();
1354}
1355
1356/*! \obsolete
1357
1358 Please use QApplication::setFont() instead.
1359*/
1360void QFont::setDefaultFont( const QFont &f )
1361{
1362 QApplication::setFont( f );
1363}
1364
1365
1366#endif
1367
1368
1369
1370
1371#ifndef QT_NO_STRINGLIST
1372
1373/*****************************************************************************
1374 QFont substitution management
1375 *****************************************************************************/
1376
1377typedef QDict<QStringList> QFontSubst;
1378static QFontSubst *fontSubst = 0;
1379static QSingleCleanupHandler<QFontSubst> qfont_cleanup_fontsubst;
1380
1381
1382// create substitution dict
1383static void initFontSubst()
1384{
1385 // default substitutions
1386 static const char *initTbl[] = {
1387
1388#if defined(Q_WS_X11)
1389 "arial", "helvetica",
1390 "helv", "helvetica",
1391 "tms rmn", "times",
1392#elif defined(Q_WS_WIN)
1393 "times", "Times New Roman",
1394 "courier", "Courier New",
1395 "helvetica", "Arial",
1396#elif defined(Q_WS_PM)
1397 "times", "Times New Roman",
1398#endif
1399 0, 0
1400 };
1401
1402 if (fontSubst)
1403 return;
1404
1405 fontSubst = new QFontSubst(17, FALSE);
1406 Q_CHECK_PTR( fontSubst );
1407 fontSubst->setAutoDelete( TRUE );
1408 qfont_cleanup_fontsubst.set(&fontSubst);
1409
1410 for ( int i=0; initTbl[i] != 0; i += 2 )
1411 QFont::insertSubstitution(QString::fromLatin1(initTbl[i]),
1412 QString::fromLatin1(initTbl[i+1]));
1413}
1414
1415
1416/*!
1417 Returns the first family name to be used whenever \a familyName is
1418 specified. The lookup is case insensitive.
1419
1420 If there is no substitution for \a familyName, \a familyName is
1421 returned.
1422
1423 To obtain a list of substitutions use substitutes().
1424
1425 \sa setFamily() insertSubstitutions() insertSubstitution() removeSubstitution()
1426*/
1427QString QFont::substitute( const QString &familyName )
1428{
1429 initFontSubst();
1430
1431 QStringList *list = fontSubst->find(familyName);
1432 if (list && list->count() > 0)
1433 return *(list->at(0));
1434
1435 return familyName;
1436}
1437
1438
1439/*!
1440 Returns a list of family names to be used whenever \a familyName
1441 is specified. The lookup is case insensitive.
1442
1443 If there is no substitution for \a familyName, an empty list is
1444 returned.
1445
1446 \sa substitute() insertSubstitutions() insertSubstitution() removeSubstitution()
1447 */
1448QStringList QFont::substitutes(const QString &familyName)
1449{
1450 initFontSubst();
1451
1452 QStringList ret, *list = fontSubst->find(familyName);
1453 if (list)
1454 ret += *list;
1455 return ret;
1456}
1457
1458
1459/*!
1460 Inserts the family name \a substituteName into the substitution
1461 table for \a familyName.
1462
1463 \sa insertSubstitutions() removeSubstitution() substitutions() substitute() substitutes()
1464*/
1465void QFont::insertSubstitution(const QString &familyName,
1466 const QString &substituteName)
1467{
1468 initFontSubst();
1469
1470 QStringList *list = fontSubst->find(familyName);
1471 if (! list) {
1472 list = new QStringList;
1473 fontSubst->insert(familyName, list);
1474 }
1475
1476 if (! list->contains(substituteName))
1477 list->append(substituteName);
1478}
1479
1480
1481/*!
1482 Inserts the list of families \a substituteNames into the
1483 substitution list for \a familyName.
1484
1485 \sa insertSubstitution(), removeSubstitution(), substitutions(), substitute()
1486*/
1487void QFont::insertSubstitutions(const QString &familyName,
1488 const QStringList &substituteNames)
1489{
1490 initFontSubst();
1491
1492 QStringList *list = fontSubst->find(familyName);
1493 if (! list) {
1494 list = new QStringList;
1495 fontSubst->insert(familyName, list);
1496 }
1497
1498 QStringList::ConstIterator it = substituteNames.begin();
1499 while (it != substituteNames.end()) {
1500 if (! list->contains(*it))
1501 list->append(*it);
1502 it++;
1503 }
1504}
1505
1506// ### mark: should be called removeSubstitutions()
1507/*!
1508 Removes all the substitutions for \a familyName.
1509
1510 \sa insertSubstitutions(), insertSubstitution(), substitutions(), substitute()
1511*/
1512void QFont::removeSubstitution( const QString &familyName )
1513{ // ### function name should be removeSubstitutions() or
1514 // ### removeSubstitutionList()
1515 initFontSubst();
1516
1517 fontSubst->remove(familyName);
1518}
1519
1520
1521/*!
1522 Returns a sorted list of substituted family names.
1523
1524 \sa insertSubstitution(), removeSubstitution(), substitute()
1525*/
1526QStringList QFont::substitutions()
1527{
1528 initFontSubst();
1529
1530 QStringList ret;
1531 QDictIterator<QStringList> it(*fontSubst);
1532
1533 while (it.current()) {
1534 ret.append(it.currentKey());
1535 ++it;
1536 }
1537
1538 ret.sort();
1539
1540 return ret;
1541}
1542
1543#endif // QT_NO_STRINGLIST
1544
1545
1546/* \internal
1547 Internal function. Converts boolean font settings to an unsigned
1548 8-bit number. Used for serialization etc.
1549*/
1550static Q_UINT8 get_font_bits( const QFontPrivate *f )
1551{
1552#ifdef QT_CHECK_STATE
1553 Q_ASSERT( f != 0 );
1554#endif
1555
1556 Q_UINT8 bits = 0;
1557 if ( f->request.italic )
1558 bits |= 0x01;
1559 if ( f->underline )
1560 bits |= 0x02;
1561 if ( f->overline )
1562 bits |= 0x40;
1563 if ( f->strikeOut )
1564 bits |= 0x04;
1565 if ( f->request.fixedPitch )
1566 bits |= 0x08;
1567 // if ( f.hintSetByUser )
1568 // bits |= 0x10;
1569 if ( f->rawMode )
1570 bits |= 0x20;
1571 return bits;
1572}
1573
1574
1575#ifndef QT_NO_DATASTREAM
1576
1577/* \internal
1578 Internal function. Sets boolean font settings from an unsigned
1579 8-bit number. Used for serialization etc.
1580*/
1581static void set_font_bits( Q_UINT8 bits, QFontPrivate *f )
1582{
1583#ifdef QT_CHECK_STATE
1584 Q_ASSERT( f != 0 );
1585#endif
1586
1587 f->request.italic = (bits & 0x01) != 0;
1588 f->underline = (bits & 0x02) != 0;
1589 f->overline = (bits & 0x40) != 0;
1590 f->strikeOut = (bits & 0x04) != 0;
1591 f->request.fixedPitch = (bits & 0x08) != 0;
1592 // f->hintSetByUser = (bits & 0x10) != 0;
1593 f->rawMode = (bits & 0x20) != 0;
1594}
1595
1596#endif
1597
1598
1599/*!
1600 Returns the font's key, a textual representation of a font. It is
1601 typically used as the key for a cache or dictionary of fonts.
1602
1603 \sa QMap
1604*/
1605QString QFont::key() const
1606{
1607 return toString();
1608}
1609
1610/*!
1611 Returns a description of the font. The description is a
1612 comma-separated list of the attributes, perfectly suited for use
1613 in QSettings.
1614
1615 \sa fromString() operator<<()
1616 */
1617QString QFont::toString() const
1618{
1619 const QChar comma( ',' );
1620 return family() + comma +
1621 QString::number( pointSizeFloat() ) + comma +
1622 QString::number( pixelSize() ) + comma +
1623 QString::number( (int) styleHint() ) + comma +
1624 QString::number( weight() ) + comma +
1625 QString::number( (int) italic() ) + comma +
1626 QString::number( (int) underline() ) + comma +
1627 QString::number( (int) strikeOut() ) + comma +
1628 QString::number( (int)fixedPitch() ) + comma +
1629 QString::number( (int) rawMode() );
1630}
1631
1632
1633/*!
1634 Sets this font to match the description \a descrip. The description
1635 is a comma-separated list of the font attributes, as returned by
1636 toString().
1637
1638 \sa toString() operator>>()
1639 */
1640bool QFont::fromString(const QString &descrip)
1641{
1642#ifndef QT_NO_STRINGLIST
1643 QStringList l(QStringList::split(',', descrip));
1644
1645 int count = l.count();
1646#else
1647 int count = 0;
1648 QString l[11];
1649 int from = 0;
1650 int to = descrip.find( ',' );
1651 while ( to > 0 && count < 11 ) {
1652 l[count] = descrip.mid( from, to-from );
1653 count++;
1654 from = to+1;
1655 to = descrip.find( ',', from );
1656 }
1657#endif // QT_NO_STRINGLIST
1658 if ( !count || ( count > 2 && count < 9 ) || count > 11 ) {
1659
1660#ifdef QT_CHECK_STATE
1661 qWarning("QFont::fromString: invalid description '%s'", descrip.latin1());
1662#endif
1663
1664 return FALSE;
1665 }
1666
1667 setFamily(l[0]);
1668 if ( count > 1 && l[1].toDouble() > 0.0 )
1669 setPointSizeFloat(l[1].toDouble());
1670 if ( count == 9 ) {
1671 setStyleHint((StyleHint) l[2].toInt());
1672 setWeight(l[3].toInt());
1673 setItalic(l[4].toInt());
1674 setUnderline(l[5].toInt());
1675 setStrikeOut(l[6].toInt());
1676 setFixedPitch(l[7].toInt());
1677 setRawMode(l[8].toInt());
1678 } else if ( count == 10 ) {
1679 if ( l[2].toInt() > 0 )
1680 setPixelSize( l[2].toInt() );
1681 setStyleHint((StyleHint) l[3].toInt());
1682 setWeight(l[4].toInt());
1683 setItalic(l[5].toInt());
1684 setUnderline(l[6].toInt());
1685 setStrikeOut(l[7].toInt());
1686 setFixedPitch(l[8].toInt());
1687 setRawMode(l[9].toInt());
1688 }
1689
1690 return TRUE;
1691}
1692
1693#if !defined( Q_WS_QWS )
1694/*! \internal
1695
1696 Internal function that dumps font cache statistics.
1697*/
1698void QFont::cacheStatistics()
1699{
1700
1701
1702}
1703#endif // !Q_WS_QWS
1704
1705
1706
1707/*****************************************************************************
1708 QFont stream functions
1709 *****************************************************************************/
1710#ifndef QT_NO_DATASTREAM
1711
1712/*!
1713 \relates QFont
1714
1715 Writes the font \a font to the data stream \a s. (toString()
1716 writes to a text stream.)
1717
1718 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
1719*/
1720QDataStream &operator<<( QDataStream &s, const QFont &font )
1721{
1722 if ( s.version() == 1 ) {
1723 QCString fam( font.d->request.family.latin1() );
1724 s << fam;
1725 } else {
1726 s << font.d->request.family;
1727 }
1728
1729 if ( s.version() <= 3 ) {
1730 Q_INT16 pointSize = (Q_INT16) font.d->request.pointSize;
1731 if ( pointSize == -1 ) {
1732#ifdef Q_WS_X11
1733 pointSize = (Q_INT16)(font.d->request.pixelSize*720/QPaintDevice::x11AppDpiY());
1734#else
1735 pointSize = (Q_INT16)QFontInfo( font ).pointSize() * 10;
1736#endif
1737 }
1738 s << pointSize;
1739 } else {
1740 s << (Q_INT16) font.d->request.pointSize;
1741 s << (Q_INT16) font.d->request.pixelSize;
1742 }
1743
1744 s << (Q_UINT8) font.d->request.styleHint;
1745 if ( s.version() >= 5 )
1746 s << (Q_UINT8 ) font.d->request.styleStrategy;
1747 return s << (Q_UINT8) 0
1748 << (Q_UINT8) font.d->request.weight
1749 << get_font_bits(font.d);
1750}
1751
1752
1753/*!
1754 \relates QFont
1755
1756 Reads the font \a font from the data stream \a s. (fromString()
1757 reads from a text stream.)
1758
1759 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
1760*/
1761QDataStream &operator>>( QDataStream &s, QFont &font )
1762{
1763 if (font.d->deref()) delete font.d;
1764
1765 font.d = new QFontPrivate;
1766 font.d->mask = QFontPrivate::Complete;
1767
1768 Q_INT16 pointSize, pixelSize = -1;
1769 Q_UINT8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits;
1770
1771 if ( s.version() == 1 ) {
1772 QCString fam;
1773 s >> fam;
1774 font.d->request.family = QString( fam );
1775 } else {
1776 s >> font.d->request.family;
1777 }
1778
1779 s >> pointSize;
1780 if ( s.version() >= 4 )
1781 s >> pixelSize;
1782 s >> styleHint;
1783 if ( s.version() >= 5 )
1784 s >> styleStrategy;
1785 s >> charSet;
1786 s >> weight;
1787 s >> bits;
1788
1789 font.d->request.pointSize = pointSize;
1790 font.d->request.pixelSize = pixelSize;
1791 font.d->request.styleHint = styleHint;
1792 font.d->request.styleStrategy = styleStrategy;
1793 font.d->request.weight = weight;
1794
1795 set_font_bits( bits, font.d );
1796
1797 return s;
1798}
1799
1800#endif // QT_NO_DATASTREAM
1801
1802
1803
1804
1805/*****************************************************************************
1806 QFontMetrics member functions
1807 *****************************************************************************/
1808
1809/*!
1810 \class QFontMetrics qfontmetrics.h
1811 \brief The QFontMetrics class provides font metrics information.
1812
1813 \ingroup graphics
1814 \ingroup shared
1815
1816 QFontMetrics functions calculate the size of characters and
1817 strings for a given font. There are three ways you can create a
1818 QFontMetrics object:
1819
1820 \list 1
1821 \i Calling the QFontMetrics constructor with a QFont creates a
1822 font metrics object for a screen-compatible font, i.e. the font
1823 cannot be a printer font<sup>*</sup>. If the font is changed
1824 later, the font metrics object is \e not updated.
1825
1826 \i QWidget::fontMetrics() returns the font metrics for a widget's
1827 font. This is equivalent to QFontMetrics(widget->font()). If the
1828 widget's font is changed later, the font metrics object is \e not
1829 updated.
1830
1831 \i QPainter::fontMetrics() returns the font metrics for a
1832 painter's current font. If the painter's font is changed later, the
1833 font metrics object is \e not updated.
1834 \endlist
1835
1836 <sup>*</sup> If you use a printer font the values returned may be
1837 inaccurate. Printer fonts are not always accessible so the nearest
1838 screen font is used if a printer font is supplied.
1839
1840 Once created, the object provides functions to access the
1841 individual metrics of the font, its characters, and for strings
1842 rendered in the font.
1843
1844 There are several functions that operate on the font: ascent(),
1845 descent(), height(), leading() and lineSpacing() return the basic
1846 size properties of the font. The underlinePos(), overlinePos(),
1847 strikeOutPos() and lineWidth() functions, return the properties of
1848 the line that underlines, overlines or strikes out the
1849 characters. These functions are all fast.
1850
1851 There are also some functions that operate on the set of glyphs in
1852 the font: minLeftBearing(), minRightBearing() and maxWidth().
1853 These are by necessity slow, and we recommend avoiding them if
1854 possible.
1855
1856 For each character, you can get its width(), leftBearing() and
1857 rightBearing() and find out whether it is in the font using
1858 inFont(). You can also treat the character as a string, and use
1859 the string functions on it.
1860
1861 The string functions include width(), to return the width of a
1862 string in pixels (or points, for a printer), boundingRect(), to
1863 return a rectangle large enough to contain the rendered string,
1864 and size(), to return the size of that rectangle.
1865
1866 Example:
1867 \code
1868 QFont font( "times", 24 );
1869 QFontMetrics fm( font );
1870 int pixelsWide = fm.width( "What's the width of this text?" );
1871 int pixelsHigh = fm.height();
1872 \endcode
1873
1874 \sa QFont QFontInfo QFontDatabase
1875*/
1876
1877/*!
1878 Constructs a font metrics object for \a font.
1879
1880 The font must be screen-compatible, i.e. a font you use when
1881 drawing text in \link QWidget widgets\endlink or \link QPixmap
1882 pixmaps\endlink, not QPicture or QPrinter.
1883
1884 The font metrics object holds the information for the font that is
1885 passed in the constructor at the time it is created, and is not
1886 updated if the font's attributes are changed later.
1887
1888 Use QPainter::fontMetrics() to get the font metrics when painting.
1889 This will give correct results also when painting on paint device
1890 that is not screen-compatible.
1891*/
1892QFontMetrics::QFontMetrics( const QFont &font )
1893 : d( font.d ), painter( 0 ), fscript( QFont::NoScript )
1894{
1895 d->ref();
1896}
1897
1898/*!
1899 \overload
1900
1901 Constructs a font metrics object for \a font using the given \a
1902 script.
1903*/
1904QFontMetrics::QFontMetrics( const QFont &font, QFont::Script script )
1905 : d( font.d ), painter( 0 ), fscript( script )
1906{
1907 d->ref();
1908}
1909
1910/*! \internal
1911
1912 Constructs a font metrics object for the painter's font \a p.
1913*/
1914QFontMetrics::QFontMetrics( const QPainter *p )
1915 : painter ( (QPainter *) p ), fscript( QFont::NoScript )
1916{
1917#if defined(CHECK_STATE)
1918 if ( !painter->isActive() )
1919 qWarning( "QFontMetrics: Get font metrics between QPainter::begin() "
1920 "and QPainter::end()" );
1921#endif
1922
1923 if ( painter->testf(QPainter::DirtyFont) )
1924 painter->updateFont();
1925
1926 d = painter->pfont ? painter->pfont->d : painter->cfont.d;
1927
1928#if defined(Q_WS_X11)
1929 if ( d->screen != p->scrn ) {
1930 QFontPrivate *new_d = new QFontPrivate( *d );
1931 Q_CHECK_PTR( new_d );
1932 d = new_d;
1933 d->screen = p->scrn;
1934 d->count = 1;
1935 } else
1936#endif // Q_WS_X11
1937 d->ref();
1938}
1939
1940/*!
1941 Constructs a copy of \a fm.
1942*/
1943QFontMetrics::QFontMetrics( const QFontMetrics &fm )
1944 : d( fm.d ), painter( 0 ), fscript( fm.fscript )
1945{
1946 d->ref();
1947}
1948
1949/*!
1950 Destroys the font metrics object and frees all allocated
1951 resources.
1952*/
1953QFontMetrics::~QFontMetrics()
1954{
1955 if ( d->deref() )
1956 delete d;
1957}
1958
1959/*!
1960 Assigns the font metrics \a fm.
1961*/
1962QFontMetrics &QFontMetrics::operator=( const QFontMetrics &fm )
1963{
1964 if ( d != fm.d ) {
1965 if ( d->deref() )
1966 delete d;
1967 d = fm.d;
1968 d->ref();
1969 }
1970 painter = fm.painter;
1971 return *this;
1972}
1973
1974/*!
1975 Returns the ascent of the font.
1976
1977 The ascent of a font is the distance from the baseline to the
1978 highest position characters extend to. In practice, some font
1979 designers break this rule, e.g. when they put more than one accent
1980 on top of a character, or to accommodate an unusual character in
1981 an exotic language, so it is possible (though rare) that this
1982 value will be too small.
1983
1984 \sa descent()
1985*/
1986int QFontMetrics::ascent() const
1987{
1988 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
1989 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
1990#ifdef QT_CHECK_STATE
1991 Q_ASSERT( engine != 0 );
1992 Q_ASSERT( latin_engine != 0 );
1993#endif // QT_CHECK_STATE
1994
1995 return QMAX(engine->ascent(), latin_engine->ascent());
1996}
1997
1998
1999/*!
2000 Returns the descent of the font.
2001
2002 The descent is the distance from the base line to the lowest point
2003 characters extend to. (Note that this is different from X, which
2004 adds 1 pixel.) In practice, some font designers break this rule,
2005 e.g. to accommodate an unusual character in an exotic language, so
2006 it is possible (though rare) that this value will be too small.
2007
2008 \sa ascent()
2009*/
2010int QFontMetrics::descent() const
2011{
2012 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2013 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2014#ifdef QT_CHECK_STATE
2015 Q_ASSERT( engine != 0 );
2016 Q_ASSERT( latin_engine != 0 );
2017#endif // QT_CHECK_STATE
2018
2019 return QMAX(engine->descent(), latin_engine->descent());
2020}
2021
2022/*!
2023 Returns the height of the font.
2024
2025 This is always equal to ascent()+descent()+1 (the 1 is for the
2026 base line).
2027
2028 \sa leading(), lineSpacing()
2029*/
2030int QFontMetrics::height() const
2031{
2032 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2033 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2034#ifdef QT_CHECK_STATE
2035 Q_ASSERT( engine != 0 );
2036 Q_ASSERT( latin_engine != 0 );
2037#endif // QT_CHECK_STATE
2038
2039 return (QMAX(engine->ascent(), latin_engine->ascent()) +
2040 QMAX(engine->descent(), latin_engine->descent()) + 1);
2041}
2042
2043/*!
2044 Returns the leading of the font.
2045
2046 This is the natural inter-line spacing.
2047
2048 \sa height(), lineSpacing()
2049*/
2050int QFontMetrics::leading() const
2051{
2052 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2053 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2054#ifdef QT_CHECK_STATE
2055 Q_ASSERT( engine != 0 );
2056 Q_ASSERT( latin_engine != 0 );
2057#endif // QT_CHECK_STATE
2058
2059 return QMAX(engine->leading(), latin_engine->leading());
2060}
2061
2062/*!
2063 Returns the distance from one base line to the next.
2064
2065 This value is always equal to leading()+height().
2066
2067 \sa height(), leading()
2068*/
2069int QFontMetrics::lineSpacing() const
2070{
2071 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2072 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2073#ifdef QT_CHECK_STATE
2074 Q_ASSERT( engine != 0 );
2075 Q_ASSERT( latin_engine != 0 );
2076#endif // QT_CHECK_STATE
2077
2078 return (QMAX(engine->leading(), latin_engine->leading()) +
2079 QMAX(engine->ascent(), latin_engine->ascent()) +
2080 QMAX(engine->descent(), latin_engine->descent()) + 1);
2081}
2082
2083/*!
2084 Returns the minimum left bearing of the font.
2085
2086 This is the smallest leftBearing(char) of all characters in the
2087 font.
2088
2089 Note that this function can be very slow if the font is large.
2090
2091 \sa minRightBearing(), leftBearing()
2092*/
2093int QFontMetrics::minLeftBearing() const
2094{
2095 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2096 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2097#ifdef QT_CHECK_STATE
2098 Q_ASSERT( engine != 0 );
2099 Q_ASSERT( latin_engine != 0 );
2100#endif // QT_CHECK_STATE
2101
2102 return QMIN(engine->minLeftBearing(), latin_engine->minLeftBearing());
2103}
2104
2105/*!
2106 Returns the minimum right bearing of the font.
2107
2108 This is the smallest rightBearing(char) of all characters in the
2109 font.
2110
2111 Note that this function can be very slow if the font is large.
2112
2113 \sa minLeftBearing(), rightBearing()
2114*/
2115int QFontMetrics::minRightBearing() const
2116{
2117 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2118 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2119#ifdef QT_CHECK_STATE
2120 Q_ASSERT( engine != 0 );
2121 Q_ASSERT( latin_engine != 0 );
2122#endif // QT_CHECK_STATE
2123
2124 return QMIN(engine->minRightBearing(), latin_engine->minRightBearing());
2125}
2126
2127/*!
2128 Returns the width of the widest character in the font.
2129*/
2130int QFontMetrics::maxWidth() const
2131{
2132 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2133 QFontEngine *lengine = d->engineForScript( QFont::Latin );
2134#ifdef QT_CHECK_STATE
2135 Q_ASSERT( engine != 0 );
2136 Q_ASSERT( lengine != 0 );
2137#endif // QT_CHECK_STATE
2138
2139 return QMAX(engine->maxCharWidth(), lengine->maxCharWidth());
2140}
2141
2142/*!
2143 Returns TRUE if character \a ch is a valid character in the font;
2144 otherwise returns FALSE.
2145*/
2146bool QFontMetrics::inFont(QChar ch) const
2147{
2148 QFont::Script script;
2149 SCRIPT_FOR_CHAR( script, ch );
2150
2151 QFontEngine *engine = d->engineForScript( script );
2152#ifdef QT_CHECK_STATE
2153 Q_ASSERT( engine != 0 );
2154#endif // QT_CHECK_STATE
2155
2156 if ( engine->type() == QFontEngine::Box ) return FALSE;
2157 return engine->canRender( &ch, 1 );
2158}
2159
2160/*! \fn int QFontMetrics::leftBearing( QChar ch ) const
2161 Returns the left bearing of character \a ch in the font.
2162
2163 The left bearing is the right-ward distance of the left-most pixel
2164 of the character from the logical origin of the character. This
2165 value is negative if the pixels of the character extend to the
2166 left of the logical origin.
2167
2168 See width(QChar) for a graphical description of this metric.
2169
2170 \sa rightBearing(), minLeftBearing(), width()
2171*/
2172#if !defined(Q_WS_WIN) && !defined(Q_WS_QWS)
2173int QFontMetrics::leftBearing(QChar ch) const
2174{
2175 QFont::Script script;
2176 SCRIPT_FOR_CHAR( script, ch );
2177
2178 QFontEngine *engine = d->engineForScript( script );
2179#ifdef QT_CHECK_STATE
2180 Q_ASSERT( engine != 0 );
2181#endif // QT_CHECK_STATE
2182
2183 if ( engine->type() == QFontEngine::Box ) return 0;
2184
2185 glyph_t glyphs[10];
2186 int nglyphs = 9;
2187 engine->stringToCMap( &ch, 1, glyphs, 0, &nglyphs, FALSE );
2188 // ### can nglyphs != 1 happen at all? Not currently I think
2189 glyph_metrics_t gi = engine->boundingBox( glyphs[0] );
2190 return gi.x;
2191}
2192#endif // !Q_WS_WIN
2193
2194/*! \fn int QFontMetrics::rightBearing(QChar ch) const
2195 Returns the right bearing of character \a ch in the font.
2196
2197 The right bearing is the left-ward distance of the right-most
2198 pixel of the character from the logical origin of a subsequent
2199 character. This value is negative if the pixels of the character
2200 extend to the right of the width() of the character.
2201
2202 See width() for a graphical description of this metric.
2203
2204 \sa leftBearing(), minRightBearing(), width()
2205*/
2206#if !defined(Q_WS_WIN) && !defined(Q_WS_QWS)
2207int QFontMetrics::rightBearing(QChar ch) const
2208{
2209 QFont::Script script;
2210 SCRIPT_FOR_CHAR( script, ch );
2211
2212 QFontEngine *engine = d->engineForScript( script );
2213#ifdef QT_CHECK_STATE
2214 Q_ASSERT( engine != 0 );
2215#endif // QT_CHECK_STATE
2216
2217 if ( engine->type() == QFontEngine::Box ) return 0;
2218
2219 glyph_t glyphs[10];
2220 int nglyphs = 9;
2221 engine->stringToCMap( &ch, 1, glyphs, 0, &nglyphs, FALSE );
2222 // ### can nglyphs != 1 happen at all? Not currently I think
2223 glyph_metrics_t gi = engine->boundingBox( glyphs[0] );
2224 return gi.xoff - gi.x - gi.width;
2225}
2226#endif // !Q_WS_WIN
2227
2228
2229#ifndef Q_WS_QWS
2230/*!
2231 Returns the width in pixels of the first \a len characters of \a
2232 str. If \a len is negative (the default), the entire string is
2233 used.
2234
2235 Note that this value is \e not equal to boundingRect().width();
2236 boundingRect() returns a rectangle describing the pixels this
2237 string will cover whereas width() returns the distance to where
2238 the next string should be drawn.
2239
2240 \sa boundingRect()
2241*/
2242int QFontMetrics::width( const QString &str, int len ) const
2243{
2244 if (len < 0)
2245 len = str.length();
2246 if (len == 0)
2247 return 0;
2248
2249 int pos = 0;
2250 int width = 0;
2251#ifndef Q_WS_MAC
2252 const QChar *ch = str.unicode();
2253
2254 while (pos < len) {
2255 unsigned short uc = ch->unicode();
2256 if (uc < QFontEngineData::widthCacheSize && d->engineData && d->engineData->widthCache[uc])
2257 width += d->engineData->widthCache[uc];
2258 else if ( ::category( *ch ) != QChar::Mark_NonSpacing ) {
2259 QFont::Script script;
2260 SCRIPT_FOR_CHAR( script, *ch );
2261
2262 if (script >= QFont::Arabic && script <= QFont::Khmer)
2263 break;
2264
2265 QFontEngine *engine = d->engineForScript( script );
2266#ifdef QT_CHECK_STATE
2267 Q_ASSERT( engine != 0 );
2268#endif // QT_CHECK_STATE
2269
2270 glyph_t glyphs[8];
2271 advance_t advances[8];
2272 int nglyphs = 7;
2273 engine->stringToCMap( ch, 1, glyphs, advances, &nglyphs, FALSE );
2274
2275 // ### can nglyphs != 1 happen at all? Not currently I think
2276 if ( uc < QFontEngineData::widthCacheSize && advances[0] < 0x100 )
2277 d->engineData->widthCache[ uc ] = advances[0];
2278 width += advances[0];
2279 }
2280 ++pos;
2281 ++ch;
2282 }
2283 if ( pos < len ) {
2284#endif
2285 QTextEngine layout( str, d );
2286 layout.itemize( QTextEngine::WidthOnly );
2287 width += layout.width( pos, len-pos );
2288#ifndef Q_WS_MAC
2289 }
2290#endif
2291 return width;
2292}
2293#endif
2294
2295/*! \fn int QFontMetrics::width( QChar ch ) const
2296
2297 <img src="bearings.png" align=right>
2298
2299 Returns the logical width of character \a ch in pixels. This is a
2300 distance appropriate for drawing a subsequent character after \a
2301 ch.
2302
2303 Some of the metrics are described in the image to the right. The
2304 central dark rectangles cover the logical width() of each
2305 character. The outer pale rectangles cover the leftBearing() and
2306 rightBearing() of each character. Notice that the bearings of "f"
2307 in this particular font are both negative, while the bearings of
2308 "o" are both positive.
2309
2310 \warning This function will produce incorrect results for Arabic
2311 characters or non spacing marks in the middle of a string, as the
2312 glyph shaping and positioning of marks that happens when
2313 processing strings cannot be taken into account. Use charWidth()
2314 instead if you aren't looking for the width of isolated
2315 characters.
2316
2317 \sa boundingRect(), charWidth()
2318*/
2319
2320/*! \fn int QFontMetrics::width( char c ) const
2321
2322 \overload
2323 \obsolete
2324
2325 Provided to aid porting from Qt 1.x.
2326*/
2327
2328/*! \fn int QFontMetrics::charWidth( const QString &str, int pos ) const
2329 Returns the width of the character at position \a pos in the
2330 string \a str.
2331
2332 The whole string is needed, as the glyph drawn may change
2333 depending on the context (the letter before and after the current
2334 one) for some languages (e.g. Arabic).
2335
2336 This function also takes non spacing marks and ligatures into
2337 account.
2338*/
2339
2340#ifndef Q_WS_QWS
2341/*!
2342 Returns the bounding rectangle of the first \a len characters of
2343 \a str, which is the set of pixels the text would cover if drawn
2344 at (0, 0).
2345
2346 If \a len is negative (the default), the entire string is used.
2347
2348 Note that the bounding rectangle may extend to the left of (0, 0),
2349 e.g. for italicized fonts, and that the text output may cover \e
2350 all pixels in the bounding rectangle.
2351
2352 Newline characters are processed as normal characters, \e not as
2353 linebreaks.
2354
2355 Due to the different actual character heights, the height of the
2356 bounding rectangle of e.g. "Yes" and "yes" may be different.
2357
2358 \sa width(), QPainter::boundingRect()
2359*/
2360QRect QFontMetrics::boundingRect( const QString &str, int len ) const
2361{
2362 if (len < 0)
2363 len = str.length();
2364 if (len == 0)
2365 return QRect();
2366
2367 QTextEngine layout( str, d );
2368 layout.itemize( QTextEngine::NoBidi|QTextEngine::SingleLine );
2369 glyph_metrics_t gm = layout.boundingBox( 0, len );
2370 return QRect( gm.x, gm.y, gm.width, gm.height );
2371}
2372#endif
2373
2374/*!
2375 Returns the bounding rectangle of the character \a ch relative to
2376 the left-most point on the base line.
2377
2378 Note that the bounding rectangle may extend to the left of (0, 0),
2379 e.g. for italicized fonts, and that the text output may cover \e
2380 all pixels in the bounding rectangle.
2381
2382 Note that the rectangle usually extends both above and below the
2383 base line.
2384
2385 \sa width()
2386*/
2387QRect QFontMetrics::boundingRect( QChar ch ) const
2388{
2389 QFont::Script script;
2390 SCRIPT_FOR_CHAR( script, ch );
2391
2392 QFontEngine *engine = d->engineForScript( script );
2393#ifdef QT_CHECK_STATE
2394 Q_ASSERT( engine != 0 );
2395#endif // QT_CHECK_STATE
2396
2397 glyph_t glyphs[10];
2398 int nglyphs = 9;
2399 engine->stringToCMap( &ch, 1, glyphs, 0, &nglyphs, FALSE );
2400 glyph_metrics_t gi = engine->boundingBox( glyphs[0] );
2401 return QRect( gi.x, gi.y, gi.width, gi.height );
2402}
2403
2404/*!
2405 \overload
2406
2407 Returns the bounding rectangle of the first \a len characters of
2408 \a str, which is the set of pixels the text would cover if drawn
2409 at (0, 0). The drawing, and hence the bounding rectangle, is
2410 constrained to the rectangle (\a x, \a y, \a w, \a h).
2411
2412 If \a len is negative (which is the default), the entire string is
2413 used.
2414
2415 The \a flgs argument is the bitwise OR of the following flags:
2416 \list
2417 \i \c AlignAuto aligns to the left border for all languages except
2418 Arabic and Hebrew where it aligns to the right.
2419 \i \c AlignLeft aligns to the left border.
2420 \i \c AlignRight aligns to the right border.
2421 \i \c AlignJustify produces justified text.
2422 \i \c AlignHCenter aligns horizontally centered.
2423 \i \c AlignTop aligns to the top border.
2424 \i \c AlignBottom aligns to the bottom border.
2425 \i \c AlignVCenter aligns vertically centered
2426 \i \c AlignCenter (== \c{AlignHCenter | AlignVCenter})
2427 \i \c SingleLine ignores newline characters in the text.
2428 \i \c ExpandTabs expands tabs (see below)
2429 \i \c ShowPrefix interprets "&amp;x" as "<u>x</u>", i.e. underlined.
2430 \i \c WordBreak breaks the text to fit the rectangle.
2431 \endlist
2432
2433 Horizontal alignment defaults to \c AlignAuto and vertical
2434 alignment defaults to \c AlignTop.
2435
2436 If several of the horizontal or several of the vertical alignment
2437 flags are set, the resulting alignment is undefined.
2438
2439 These flags are defined in \c qnamespace.h.
2440
2441 If \c ExpandTabs is set in \a flgs, then: if \a tabarray is
2442 non-null, it specifies a 0-terminated sequence of pixel-positions
2443 for tabs; otherwise if \a tabstops is non-zero, it is used as the
2444 tab spacing (in pixels).
2445
2446 Note that the bounding rectangle may extend to the left of (0, 0),
2447 e.g. for italicized fonts, and that the text output may cover \e
2448 all pixels in the bounding rectangle.
2449
2450 Newline characters are processed as linebreaks.
2451
2452 Despite the different actual character heights, the heights of the
2453 bounding rectangles of "Yes" and "yes" are the same.
2454
2455 The bounding rectangle given by this function is somewhat larger
2456 than that calculated by the simpler boundingRect() function. This
2457 function uses the \link minLeftBearing() maximum left \endlink and
2458 \link minRightBearing() right \endlink font bearings as is
2459 necessary for multi-line text to align correctly. Also,
2460 fontHeight() and lineSpacing() are used to calculate the height,
2461 rather than individual character heights.
2462
2463 The \a intern argument should not be used.
2464
2465 \sa width(), QPainter::boundingRect(), Qt::AlignmentFlags
2466*/
2467QRect QFontMetrics::boundingRect( int x, int y, int w, int h, int flgs,
2468 const QString& str, int len, int tabstops,
2469 int *tabarray, QTextParag **intern ) const
2470{
2471 if ( len < 0 )
2472 len = str.length();
2473
2474 int tabarraylen=0;
2475 if (tabarray)
2476 while (tabarray[tabarraylen])
2477 tabarraylen++;
2478
2479 QRect rb;
2480 QRect r(x, y, w, h);
2481 qt_format_text( QFont( d, d->paintdevice ), r, flgs|Qt::DontPrint, str, len, &rb,
2482 tabstops, tabarray, tabarraylen, intern, 0 );
2483
2484 return rb;
2485}
2486
2487/*!
2488 Returns the size in pixels of the first \a len characters of \a
2489 str.
2490
2491 If \a len is negative (the default), the entire string is used.
2492
2493 The \a flgs argument is the bitwise OR of the following flags:
2494 \list
2495 \i \c SingleLine ignores newline characters.
2496 \i \c ExpandTabs expands tabs (see below)
2497 \i \c ShowPrefix interprets "&amp;x" as "<u>x</u>", i.e. underlined.
2498 \i \c WordBreak breaks the text to fit the rectangle.
2499 \endlist
2500
2501 These flags are defined in \c qnamespace.h.
2502
2503 If \c ExpandTabs is set in \a flgs, then: if \a tabarray is
2504 non-null, it specifies a 0-terminated sequence of pixel-positions
2505 for tabs; otherwise if \a tabstops is non-zero, it is used as the
2506 tab spacing (in pixels).
2507
2508 Newline characters are processed as linebreaks.
2509
2510 Despite the different actual character heights, the heights of the
2511 bounding rectangles of "Yes" and "yes" are the same.
2512
2513 The \a intern argument should not be used.
2514
2515 \sa boundingRect()
2516*/
2517QSize QFontMetrics::size( int flgs, const QString &str, int len, int tabstops,
2518 int *tabarray, QTextParag **intern ) const
2519{
2520 return boundingRect(0,0,0,0,flgs,str,len,tabstops,tabarray,intern).size();
2521}
2522
2523/*!
2524 Returns the distance from the base line to where an underscore
2525 should be drawn.
2526
2527 \sa overlinePos(), strikeOutPos(), lineWidth()
2528*/
2529int QFontMetrics::underlinePos() const
2530{
2531 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2532#ifdef QT_CHECK_STATE
2533 Q_ASSERT( engine != 0 );
2534#endif // QT_CHECK_STATE
2535
2536 return engine->underlinePosition();
2537}
2538
2539/*!
2540 Returns the distance from the base line to where an overline
2541 should be drawn.
2542
2543 \sa underlinePos(), strikeOutPos(), lineWidth()
2544*/
2545int QFontMetrics::overlinePos() const
2546{
2547 int pos = ascent() + 1;
2548 return pos > 0 ? pos : 1;
2549}
2550
2551/*!
2552 Returns the distance from the base line to where the strikeout
2553 line should be drawn.
2554
2555 \sa underlinePos(), overlinePos(), lineWidth()
2556*/
2557int QFontMetrics::strikeOutPos() const
2558{
2559 int pos = ascent() / 3;
2560 return pos > 0 ? pos : 1;
2561}
2562
2563/*!
2564 Returns the width of the underline and strikeout lines, adjusted
2565 for the point size of the font.
2566
2567 \sa underlinePos(), overlinePos(), strikeOutPos()
2568*/
2569int QFontMetrics::lineWidth() const
2570{
2571 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2572#ifdef QT_CHECK_STATE
2573 Q_ASSERT( engine != 0 );
2574#endif // QT_CHECK_STATE
2575
2576 return engine->lineThickness();
2577}
2578
2579
2580
2581
2582/*****************************************************************************
2583 QFontInfo member functions
2584 *****************************************************************************/
2585
2586/*!
2587 \class QFontInfo qfontinfo.h
2588
2589 \brief The QFontInfo class provides general information about fonts.
2590
2591 \ingroup graphics
2592 \ingroup shared
2593
2594 The QFontInfo class provides the same access functions as QFont,
2595 e.g. family(), pointSize(), italic(), weight(), fixedPitch(),
2596 styleHint() etc. But whilst the QFont access functions return the
2597 values that were set, a QFontInfo object returns the values that
2598 apply to the font that will actually be used to draw the text.
2599
2600 For example, when the program asks for a 25pt Courier font on a
2601 machine that has a non-scalable 24pt Courier font, QFont will
2602 (normally) use the 24pt Courier for rendering. In this case,
2603 QFont::pointSize() returns 25 and QFontInfo::pointSize() returns
2604 24.
2605
2606 There are three ways to create a QFontInfo object.
2607 \list 1
2608 \i Calling the QFontInfo constructor with a QFont creates a font
2609 info object for a screen-compatible font, i.e. the font cannot be
2610 a printer font<sup>*</sup>. If the font is changed later, the font
2611 info object is \e not updated.
2612
2613 \i QWidget::fontInfo() returns the font info for a widget's font.
2614 This is equivalent to calling QFontInfo(widget->font()). If the
2615 widget's font is changed later, the font info object is \e not
2616 updated.
2617
2618 \i QPainter::fontInfo() returns the font info for a painter's
2619 current font. If the painter's font is changed later, the font
2620 info object is \e not updated.
2621 \endlist
2622
2623 <sup>*</sup> If you use a printer font the values returned may be
2624 inaccurate. Printer fonts are not always accessible so the nearest
2625 screen font is used if a printer font is supplied.
2626
2627 \sa QFont QFontMetrics QFontDatabase
2628*/
2629
2630/*!
2631 Constructs a font info object for \a font.
2632
2633 The font must be screen-compatible, i.e. a font you use when
2634 drawing text in \link QWidget widgets\endlink or \link QPixmap
2635 pixmaps\endlink, not QPicture or QPrinter.
2636
2637 The font info object holds the information for the font that is
2638 passed in the constructor at the time it is created, and is not
2639 updated if the font's attributes are changed later.
2640
2641 Use QPainter::fontInfo() to get the font info when painting.
2642 This will give correct results also when painting on paint device
2643 that is not screen-compatible.
2644*/
2645QFontInfo::QFontInfo( const QFont &font )
2646 : d( font.d ), painter( 0 ), fscript( QFont::NoScript )
2647{
2648 d->ref();
2649}
2650
2651/*!
2652 Constructs a font info object for \a font using the specified \a
2653 script.
2654*/
2655QFontInfo::QFontInfo( const QFont &font, QFont::Script script )
2656 : d( font.d ), painter( 0 ), fscript( script )
2657{
2658 d->ref();
2659}
2660
2661/*! \internal
2662
2663 Constructs a font info object from the painter's font \a p.
2664*/
2665QFontInfo::QFontInfo( const QPainter *p )
2666 : painter( 0 ), fscript( QFont::NoScript )
2667{
2668 QPainter *painter = (QPainter *) p;
2669
2670#if defined(CHECK_STATE)
2671 if ( !painter->isActive() )
2672 qWarning( "QFontInfo: Get font info between QPainter::begin() "
2673 "and QPainter::end()" );
2674#endif
2675
2676 painter->setf( QPainter::FontInf );
2677 if ( painter->testf(QPainter::DirtyFont) )
2678 painter->updateFont();
2679 if ( painter->pfont )
2680 d = painter->pfont->d;
2681 else
2682 d = painter->cfont.d;
2683 d->ref();
2684}
2685
2686/*!
2687 Constructs a copy of \a fi.
2688*/
2689QFontInfo::QFontInfo( const QFontInfo &fi )
2690 : d(fi.d), painter(0), fscript( fi.fscript )
2691{
2692 d->ref();
2693}
2694
2695/*!
2696 Destroys the font info object.
2697*/
2698QFontInfo::~QFontInfo()
2699{
2700 if ( d->deref() )
2701 delete d;
2702}
2703
2704/*!
2705 Assigns the font info in \a fi.
2706*/
2707QFontInfo &QFontInfo::operator=( const QFontInfo &fi )
2708{
2709 if ( d != fi.d ) {
2710 if ( d->deref() )
2711 delete d;
2712 d = fi.d;
2713 d->ref();
2714 }
2715 painter = 0;
2716 fscript = fi.fscript;
2717 return *this;
2718}
2719
2720/*!
2721 Returns the family name of the matched window system font.
2722
2723 \sa QFont::family()
2724*/
2725QString QFontInfo::family() const
2726{
2727 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2728#ifdef QT_CHECK_STATE
2729 Q_ASSERT( engine != 0 );
2730#endif // QT_CHECK_STATE
2731 return engine->fontDef.family;
2732}
2733
2734/*!
2735 Returns the point size of the matched window system font.
2736
2737 \sa QFont::pointSize()
2738*/
2739int QFontInfo::pointSize() const
2740{
2741 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2742#ifdef QT_CHECK_STATE
2743 Q_ASSERT( engine != 0 );
2744#endif // QT_CHECK_STATE
2745 return ( engine->fontDef.pointSize + 5 ) / 10;
2746}
2747
2748/*!
2749 Returns the pixel size of the matched window system font.
2750
2751 \sa QFont::pointSize()
2752*/
2753int QFontInfo::pixelSize() const
2754{
2755 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2756#ifdef QT_CHECK_STATE
2757 Q_ASSERT( engine != 0 );
2758#endif // QT_CHECK_STATE
2759 return engine->fontDef.pixelSize;
2760}
2761
2762/*!
2763 Returns the italic value of the matched window system font.
2764
2765 \sa QFont::italic()
2766*/
2767bool QFontInfo::italic() const
2768{
2769 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2770#ifdef QT_CHECK_STATE
2771 Q_ASSERT( engine != 0 );
2772#endif // QT_CHECK_STATE
2773 return engine->fontDef.italic;
2774}
2775
2776/*!
2777 Returns the weight of the matched window system font.
2778
2779 \sa QFont::weight(), bold()
2780*/
2781int QFontInfo::weight() const
2782{
2783 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2784#ifdef QT_CHECK_STATE
2785 Q_ASSERT( engine != 0 );
2786#endif // QT_CHECK_STATE
2787 return engine->fontDef.weight;
2788
2789}
2790
2791/*!
2792 \fn bool QFontInfo::bold() const
2793
2794 Returns TRUE if weight() would return a value greater than \c
2795 QFont::Normal; otherwise returns FALSE.
2796
2797 \sa weight(), QFont::bold()
2798*/
2799
2800/*!
2801 Returns the underline value of the matched window system font.
2802
2803 \sa QFont::underline()
2804
2805 \internal
2806
2807 Here we read the underline flag directly from the QFont.
2808 This is OK for X11 and for Windows because we always get what we want.
2809*/
2810bool QFontInfo::underline() const
2811{
2812 return d->underline;
2813}
2814
2815/*!
2816 Returns the overline value of the matched window system font.
2817
2818 \sa QFont::overline()
2819
2820 \internal
2821
2822 Here we read the overline flag directly from the QFont.
2823 This is OK for X11 and for Windows because we always get what we want.
2824*/
2825bool QFontInfo::overline() const
2826{
2827 return d->overline;
2828}
2829
2830/*!
2831 Returns the strikeout value of the matched window system font.
2832
2833 \sa QFont::strikeOut()
2834
2835 \internal Here we read the strikeOut flag directly from the QFont.
2836 This is OK for X11 and for Windows because we always get what we want.
2837*/
2838bool QFontInfo::strikeOut() const
2839{
2840 return d->strikeOut;
2841}
2842
2843/*!
2844 Returns the fixed pitch value of the matched window system font.
2845
2846 \sa QFont::fixedPitch()
2847*/
2848bool QFontInfo::fixedPitch() const
2849{
2850 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2851#ifdef QT_CHECK_STATE
2852 Q_ASSERT( engine != 0 );
2853#endif // QT_CHECK_STATE
2854#ifdef Q_OS_MAC
2855 if (!engine->fontDef.fixedPitchComputed) {
2856 QChar ch[2] = { QChar('i'), QChar('m') };
2857 glyph_t g[2];
2858 int l = 2;
2859 advance_t a[2];
2860 engine->stringToCMap(ch, 2, g, a, &l, false);
2861 engine->fontDef.fixedPitch = a[0] == a[1];
2862 engine->fontDef.fixedPitchComputed = TRUE;
2863 }
2864#endif
2865 return engine->fontDef.fixedPitch;
2866}
2867
2868/*!
2869 Returns the style of the matched window system font.
2870
2871 Currently only returns the style hint set in QFont.
2872
2873 \sa QFont::styleHint() QFont::StyleHint
2874*/
2875QFont::StyleHint QFontInfo::styleHint() const
2876{
2877 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2878#ifdef QT_CHECK_STATE
2879 Q_ASSERT( engine != 0 );
2880#endif // QT_CHECK_STATE
2881 return (QFont::StyleHint) engine->fontDef.styleHint;
2882}
2883
2884/*!
2885 Returns TRUE if the font is a raw mode font; otherwise returns
2886 FALSE.
2887
2888 If it is a raw mode font, all other functions in QFontInfo will
2889 return the same values set in the QFont, regardless of the font
2890 actually used.
2891
2892 \sa QFont::rawMode()
2893*/
2894bool QFontInfo::rawMode() const
2895{
2896 return d->rawMode;
2897}
2898
2899/*!
2900 Returns TRUE if the matched window system font is exactly the same
2901 as the one specified by the font; otherwise returns FALSE.
2902
2903 \sa QFont::exactMatch()
2904*/
2905bool QFontInfo::exactMatch() const
2906{
2907 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2908#ifdef QT_CHECK_STATE
2909 Q_ASSERT( engine != 0 );
2910#endif // QT_CHECK_STATE
2911
2912 return d->rawMode ? engine->type() != QFontEngine::Box
2913 : d->request == engine->fontDef;
2914}
2915
2916
2917
2918
2919// **********************************************************************
2920// QFontCache
2921// **********************************************************************
2922
2923#ifdef QFONTCACHE_DEBUG
2924// fast timeouts for debugging
2925static const int fast_timeout = 1000; // 1s
2926static const int slow_timeout = 5000; // 5s
2927#else
2928static const int fast_timeout = 10000; // 10s
2929static const int slow_timeout = 300000; // 5m
2930#endif // QFONTCACHE_DEBUG
2931
2932QFontCache *QFontCache::instance = 0;
2933const uint QFontCache::min_cost = 4*1024; // 4mb
2934
2935#if defined (Q_OS_OS2)
2936
2937// On OS/2, destructors of static objects in a DLL cannot use objects created
2938// on the stack of the main thread when the application is being abnormally
2939// terminated (exit(), DosExit(), DosKillProcess(), etc), because at a time when
2940// these static destructors are called (from _DLL_InitTerm on most compilers,
2941// including GCC and IBM VAC) the stack is most likely reused by the DLL
2942// termination code. Since QFontCache is a child of QApplication (which is
2943// usually created as a local object inside the main() function) and wants to
2944// use its parent during destruction, this becomes a real problem and causes a
2945// guaranteed application trap during abnormal termination. The workaround is to
2946// use atexit() instead. Note that this will only work for the exit() case
2947// (on DosExit() or DosKillProcess(), the stdlib's exit list is not processed).
2948
2949static void cleanupFontCache()
2950{
2951 if (QFontCache::instance != 0)
2952 delete QFontCache::instance;
2953}
2954
2955#else
2956static QSingleCleanupHandler<QFontCache> cleanup_fontcache;
2957#endif
2958
2959QFontCache::QFontCache()
2960 : QObject( qApp, "global font cache" ), total_cost( 0 ), max_cost( min_cost ),
2961 current_timestamp( 0 ), fast( FALSE ), timer_id( -1 )
2962{
2963 Q_ASSERT( instance == 0 );
2964 instance = this;
2965#if defined (Q_OS_OS2)
2966 atexit( cleanupFontCache );
2967#else
2968 cleanup_fontcache.set( &instance );
2969#endif
2970}
2971
2972QFontCache::~QFontCache()
2973{
2974 {
2975 EngineDataCache::Iterator it = engineDataCache.begin(),
2976 end = engineDataCache.end();
2977 while ( it != end ) {
2978 if ( it.data()->count == 0 )
2979 delete it.data();
2980 else
2981 FC_DEBUG("QFontCache::~QFontCache: engineData %p still has refcount %d",
2982 it.data(), it.data()->count);
2983 ++it;
2984 }
2985 }
2986 EngineCache::Iterator it = engineCache.begin(),
2987 end = engineCache.end();
2988 while ( it != end ) {
2989 if ( it.data().data->count == 0 ) {
2990 if ( --it.data().data->cache_count == 0 ) {
2991 FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %d %d %d %d %d)",
2992 it.data().data, it.key().script, it.key().def.pointSize,
2993 it.key().def.pixelSize, it.key().def.weight, it.key().def.italic,
2994 it.key().def.fixedPitch);
2995
2996 delete it.data().data;
2997 }
2998 } else {
2999 FC_DEBUG("QFontCache::~QFontCache: engine = %p still has refcount %d",
3000 it.data().data, it.data().data->count);
3001 }
3002 ++it;
3003 }
3004 instance = 0;
3005}
3006
3007#ifdef Q_WS_QWS
3008void QFontCache::clear()
3009{
3010 {
3011 EngineDataCache::Iterator it = engineDataCache.begin(),
3012 end = engineDataCache.end();
3013 while ( it != end ) {
3014 QFontEngineData *data = it.data();
3015 if ( data->engine )
3016 data->engine->deref();
3017 data->engine = 0;
3018 ++it;
3019 }
3020 }
3021
3022 EngineCache::Iterator it = engineCache.begin(),
3023 end = engineCache.end();
3024 while ( it != end ) {
3025 if ( it.data().data->count == 0 ) {
3026 if ( --it.data().data->cache_count == 0 ) {
3027 FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %d %d %d %d %d)",
3028 it.data().data, it.key().script, it.key().def.pointSize,
3029 it.key().def.pixelSize, it.key().def.weight, it.key().def.italic,
3030 it.key().def.fixedPitch);
3031 delete it.data().data;
3032 }
3033 } else {
3034 FC_DEBUG("QFontCache::~QFontCache: engine = %p still has refcount %d",
3035 it.data().data, it.data().data->count);
3036 }
3037 ++it;
3038 }
3039}
3040#endif
3041
3042QFontEngineData *QFontCache::findEngineData( const Key &key ) const
3043{
3044 EngineDataCache::ConstIterator it = engineDataCache.find( key ),
3045 end = engineDataCache.end();
3046 if ( it == end ) return 0;
3047
3048 // found
3049 return it.data();
3050}
3051
3052void QFontCache::insertEngineData( const Key &key, QFontEngineData *engineData )
3053{
3054 FC_DEBUG( "QFontCache: inserting new engine data %p", engineData );
3055
3056 engineDataCache.insert( key, engineData );
3057 increaseCost( sizeof( QFontEngineData ) );
3058}
3059
3060QFontEngine *QFontCache::findEngine( const Key &key )
3061{
3062 EngineCache::Iterator it = engineCache.find( key ),
3063 end = engineCache.end();
3064 if ( it == end ) return 0;
3065
3066 // found... update the hitcount and timestamp
3067 it.data().hits++;
3068 it.data().timestamp = ++current_timestamp;
3069
3070 FC_DEBUG( "QFontCache: found font engine\n"
3071 " %p: timestamp %4u hits %3u ref %2d/%2d, type '%s'",
3072 it.data().data, it.data().timestamp, it.data().hits,
3073 it.data().data->count, it.data().data->cache_count,
3074 it.data().data->name() );
3075
3076 return it.data().data;
3077}
3078
3079void QFontCache::insertEngine( const Key &key, QFontEngine *engine )
3080{
3081 FC_DEBUG( "QFontCache: inserting new engine %p", engine );
3082
3083 Engine data( engine );
3084 data.timestamp = ++current_timestamp;
3085
3086 engineCache.insert( key, data );
3087
3088 // only increase the cost if this is the first time we insert the engine
3089 if ( engine->cache_count == 0 )
3090 increaseCost( engine->cache_cost );
3091
3092 ++engine->cache_count;
3093}
3094
3095void QFontCache::increaseCost( uint cost )
3096{
3097 cost = ( cost + 512 ) / 1024; // store cost in kb
3098 cost = cost > 0 ? cost : 1;
3099 total_cost += cost;
3100
3101 FC_DEBUG( " COST: increased %u kb, total_cost %u kb, max_cost %u kb",
3102 cost, total_cost, max_cost );
3103
3104 if ( total_cost > max_cost) {
3105 max_cost = total_cost;
3106
3107 if ( timer_id == -1 || ! fast ) {
3108 FC_DEBUG( " TIMER: starting fast timer (%d ms)", fast_timeout );
3109
3110 if (timer_id != -1) killTimer( timer_id );
3111 timer_id = startTimer( fast_timeout );
3112 fast = TRUE;
3113 }
3114 }
3115}
3116
3117void QFontCache::decreaseCost( uint cost )
3118{
3119 cost = ( cost + 512 ) / 1024; // cost is stored in kb
3120 cost = cost > 0 ? cost : 1;
3121 Q_ASSERT( cost <= total_cost );
3122 total_cost -= cost;
3123
3124 FC_DEBUG( " COST: decreased %u kb, total_cost %u kb, max_cost %u kb",
3125 cost, total_cost, max_cost );
3126}
3127
3128#if defined(Q_WS_WIN) || defined(Q_WS_PM) || defined (Q_WS_QWS)
3129void QFontCache::cleanupPrinterFonts()
3130{
3131 FC_DEBUG( "QFontCache::cleanupPrinterFonts" );
3132
3133 {
3134 FC_DEBUG( " CLEAN engine data:" );
3135
3136 // clean out all unused engine datas
3137 EngineDataCache::Iterator it = engineDataCache.begin(),
3138 end = engineDataCache.end();
3139 while ( it != end ) {
3140 if ( it.key().screen == 0 ) {
3141 ++it;
3142 continue;
3143 }
3144
3145 if( it.data()->count > 0 ) {
3146#ifdef Q_WS_WIN
3147 for(int i = 0; i < QFont::LastPrivateScript; ++i) {
3148 if( it.data()->engines[i] ) {
3149 it.data()->engines[i]->deref();
3150 it.data()->engines[i] = 0;
3151 }
3152 }
3153#else
3154 if ( it.data()->engine ) {
3155 it.data()->engine->deref();
3156 it.data()->engine = 0;
3157 }
3158#endif
3159 ++it;
3160 } else {
3161
3162 EngineDataCache::Iterator rem = it++;
3163
3164 decreaseCost( sizeof( QFontEngineData ) );
3165
3166 FC_DEBUG( " %p", rem.data() );
3167
3168 delete rem.data();
3169 engineDataCache.remove( rem );
3170 }
3171 }
3172 }
3173
3174 EngineCache::Iterator it = engineCache.begin(),
3175 end = engineCache.end();
3176 while( it != end ) {
3177 if ( it.data().data->count > 0 || it.key().screen == 0) {
3178 ++it;
3179 continue;
3180 }
3181
3182 FC_DEBUG( " %p: timestamp %4u hits %2u ref %2d/%2d, type '%s'",
3183 it.data().data, it.data().timestamp, it.data().hits,
3184 it.data().data->count, it.data().data->cache_count,
3185 it.data().data->name() );
3186
3187 if ( --it.data().data->cache_count == 0 ) {
3188 FC_DEBUG( " DELETE: last occurence in cache" );
3189
3190 decreaseCost( it.data().data->cache_cost );
3191 delete it.data().data;
3192 }
3193
3194 engineCache.remove( it++ );
3195 }
3196}
3197#endif
3198
3199void QFontCache::timerEvent( QTimerEvent * )
3200{
3201 FC_DEBUG( "QFontCache::timerEvent: performing cache maintenance (timestamp %u)",
3202 current_timestamp );
3203
3204 if ( total_cost <= max_cost && max_cost <= min_cost ) {
3205 FC_DEBUG( " cache redused sufficiently, stopping timer" );
3206
3207 killTimer( timer_id );
3208 timer_id = -1;
3209 fast = FALSE;
3210
3211 return;
3212 }
3213
3214 // go through the cache and count up everything in use
3215 uint in_use_cost = 0;
3216
3217 {
3218 FC_DEBUG( " SWEEP engine data:" );
3219
3220 // make sure the cost of each engine data is at least 1kb
3221 const uint engine_data_cost =
3222 sizeof( QFontEngineData ) > 1024 ? sizeof( QFontEngineData ) : 1024;
3223
3224 EngineDataCache::ConstIterator it = engineDataCache.begin(),
3225 end = engineDataCache.end();
3226 for ( ; it != end; ++it ) {
3227#ifdef QFONTCACHE_DEBUG
3228 FC_DEBUG( " %p: ref %2d", it.data(), it.data()->count );
3229
3230# if defined(Q_WS_X11) || defined(Q_WS_WIN)
3231 // print out all engines
3232 for ( int i = 0; i < QFont::LastPrivateScript; ++i ) {
3233 if ( ! it.data()->engines[i] ) continue;
3234 FC_DEBUG( " contains %p", it.data()->engines[i] );
3235 }
3236# endif // Q_WS_X11 || Q_WS_WIN
3237#endif // QFONTCACHE_DEBUG
3238
3239 if ( it.data()->count > 0 )
3240 in_use_cost += engine_data_cost;
3241 }
3242 }
3243
3244 {
3245 FC_DEBUG( " SWEEP engine:" );
3246
3247 EngineCache::ConstIterator it = engineCache.begin(),
3248 end = engineCache.end();
3249 for ( ; it != end; ++it ) {
3250 FC_DEBUG( " %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes",
3251 it.data().data, it.data().timestamp, it.data().hits,
3252 it.data().data->count, it.data().data->cache_count,
3253 it.data().data->cache_cost );
3254
3255 if ( it.data().data->count > 0 )
3256 in_use_cost += it.data().data->cache_cost / it.data().data->cache_count;
3257 }
3258
3259 // attempt to make up for rounding errors
3260 in_use_cost += engineCache.count();
3261 }
3262
3263 in_use_cost = ( in_use_cost + 512 ) / 1024; // cost is stored in kb
3264
3265 /*
3266 calculate the new maximum cost for the cache
3267
3268 NOTE: in_use_cost is *not* correct due to rounding errors in the
3269 above algorithm. instead of worrying about getting the
3270 calculation correct, we are more interested in speed, and use
3271 in_use_cost as a floor for new_max_cost
3272 */
3273 uint new_max_cost = QMAX( QMAX( max_cost / 2, in_use_cost ), min_cost );
3274
3275 FC_DEBUG( " after sweep, in use %u kb, total %u kb, max %u kb, new max %u kb",
3276 in_use_cost, total_cost, max_cost, new_max_cost );
3277
3278 if ( new_max_cost == max_cost ) {
3279 if ( fast ) {
3280 FC_DEBUG( " cannot shrink cache, slowing timer" );
3281
3282 killTimer( timer_id );
3283 timer_id = startTimer( slow_timeout );
3284 fast = FALSE;
3285 }
3286
3287 return;
3288 } else if ( ! fast ) {
3289 FC_DEBUG( " dropping into passing gear" );
3290
3291 killTimer( timer_id );
3292 timer_id = startTimer( fast_timeout );
3293 fast = TRUE;
3294 }
3295
3296 max_cost = new_max_cost;
3297
3298 {
3299 FC_DEBUG( " CLEAN engine data:" );
3300
3301 // clean out all unused engine datas
3302 EngineDataCache::Iterator it = engineDataCache.begin(),
3303 end = engineDataCache.end();
3304 while ( it != end ) {
3305 if ( it.data()->count > 0 ) {
3306 ++it;
3307 continue;
3308 }
3309
3310 EngineDataCache::Iterator rem = it++;
3311
3312 decreaseCost( sizeof( QFontEngineData ) );
3313
3314 FC_DEBUG( " %p", rem.data() );
3315
3316 delete rem.data();
3317 engineDataCache.remove( rem );
3318 }
3319 }
3320
3321 // clean out the engine cache just enough to get below our new max cost
3322 uint current_cost;
3323 do {
3324 current_cost = total_cost;
3325
3326 EngineCache::Iterator it = engineCache.begin(),
3327 end = engineCache.end();
3328 // determine the oldest and least popular of the unused engines
3329 uint oldest = ~0;
3330 uint least_popular = ~0;
3331
3332 for ( ; it != end; ++it ) {
3333 if ( it.data().data->count > 0 ) continue;
3334
3335 if ( it.data().timestamp < oldest &&
3336 it.data().hits <= least_popular ) {
3337 oldest = it.data().timestamp;
3338 least_popular = it.data().hits;
3339 }
3340 }
3341
3342 FC_DEBUG( " oldest %u least popular %u", oldest, least_popular );
3343
3344 for ( it = engineCache.begin(); it != end; ++it ) {
3345 if ( it.data().data->count == 0 &&
3346 it.data().timestamp == oldest &&
3347 it.data().hits == least_popular)
3348 break;
3349 }
3350
3351 if ( it != end ) {
3352 FC_DEBUG( " %p: timestamp %4u hits %2u ref %2d/%2d, type '%s'",
3353 it.data().data, it.data().timestamp, it.data().hits,
3354 it.data().data->count, it.data().data->cache_count,
3355 it.data().data->name() );
3356
3357 if ( --it.data().data->cache_count == 0 ) {
3358 FC_DEBUG( " DELETE: last occurence in cache" );
3359
3360 decreaseCost( it.data().data->cache_cost );
3361 delete it.data().data;
3362 } else {
3363 /*
3364 this particular font engine is in the cache multiple
3365 times... set current_cost to zero, so that we can
3366 keep looping to get rid of all occurences
3367 */
3368 current_cost = 0;
3369 }
3370
3371 engineCache.remove( it );
3372 }
3373 } while ( current_cost != total_cost && total_cost > max_cost );
3374}
Note: See TracBrowser for help on using the repository browser.