source: vendor/trolltech/current/src/kernel/qfont.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 94.0 KB
Line 
1/****************************************************************************
2** $Id: qfont.cpp 2 2005-11-16 15:49:26Z 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#endif
1397
1398 0, 0
1399 };
1400
1401 if (fontSubst)
1402 return;
1403
1404 fontSubst = new QFontSubst(17, FALSE);
1405 Q_CHECK_PTR( fontSubst );
1406 fontSubst->setAutoDelete( TRUE );
1407 qfont_cleanup_fontsubst.set(&fontSubst);
1408
1409 for ( int i=0; initTbl[i] != 0; i += 2 )
1410 QFont::insertSubstitution(QString::fromLatin1(initTbl[i]),
1411 QString::fromLatin1(initTbl[i+1]));
1412}
1413
1414
1415/*!
1416 Returns the first family name to be used whenever \a familyName is
1417 specified. The lookup is case insensitive.
1418
1419 If there is no substitution for \a familyName, \a familyName is
1420 returned.
1421
1422 To obtain a list of substitutions use substitutes().
1423
1424 \sa setFamily() insertSubstitutions() insertSubstitution() removeSubstitution()
1425*/
1426QString QFont::substitute( const QString &familyName )
1427{
1428 initFontSubst();
1429
1430 QStringList *list = fontSubst->find(familyName);
1431 if (list && list->count() > 0)
1432 return *(list->at(0));
1433
1434 return familyName;
1435}
1436
1437
1438/*!
1439 Returns a list of family names to be used whenever \a familyName
1440 is specified. The lookup is case insensitive.
1441
1442 If there is no substitution for \a familyName, an empty list is
1443 returned.
1444
1445 \sa substitute() insertSubstitutions() insertSubstitution() removeSubstitution()
1446 */
1447QStringList QFont::substitutes(const QString &familyName)
1448{
1449 initFontSubst();
1450
1451 QStringList ret, *list = fontSubst->find(familyName);
1452 if (list)
1453 ret += *list;
1454 return ret;
1455}
1456
1457
1458/*!
1459 Inserts the family name \a substituteName into the substitution
1460 table for \a familyName.
1461
1462 \sa insertSubstitutions() removeSubstitution() substitutions() substitute() substitutes()
1463*/
1464void QFont::insertSubstitution(const QString &familyName,
1465 const QString &substituteName)
1466{
1467 initFontSubst();
1468
1469 QStringList *list = fontSubst->find(familyName);
1470 if (! list) {
1471 list = new QStringList;
1472 fontSubst->insert(familyName, list);
1473 }
1474
1475 if (! list->contains(substituteName))
1476 list->append(substituteName);
1477}
1478
1479
1480/*!
1481 Inserts the list of families \a substituteNames into the
1482 substitution list for \a familyName.
1483
1484 \sa insertSubstitution(), removeSubstitution(), substitutions(), substitute()
1485*/
1486void QFont::insertSubstitutions(const QString &familyName,
1487 const QStringList &substituteNames)
1488{
1489 initFontSubst();
1490
1491 QStringList *list = fontSubst->find(familyName);
1492 if (! list) {
1493 list = new QStringList;
1494 fontSubst->insert(familyName, list);
1495 }
1496
1497 QStringList::ConstIterator it = substituteNames.begin();
1498 while (it != substituteNames.end()) {
1499 if (! list->contains(*it))
1500 list->append(*it);
1501 it++;
1502 }
1503}
1504
1505// ### mark: should be called removeSubstitutions()
1506/*!
1507 Removes all the substitutions for \a familyName.
1508
1509 \sa insertSubstitutions(), insertSubstitution(), substitutions(), substitute()
1510*/
1511void QFont::removeSubstitution( const QString &familyName )
1512{ // ### function name should be removeSubstitutions() or
1513 // ### removeSubstitutionList()
1514 initFontSubst();
1515
1516 fontSubst->remove(familyName);
1517}
1518
1519
1520/*!
1521 Returns a sorted list of substituted family names.
1522
1523 \sa insertSubstitution(), removeSubstitution(), substitute()
1524*/
1525QStringList QFont::substitutions()
1526{
1527 initFontSubst();
1528
1529 QStringList ret;
1530 QDictIterator<QStringList> it(*fontSubst);
1531
1532 while (it.current()) {
1533 ret.append(it.currentKey());
1534 ++it;
1535 }
1536
1537 ret.sort();
1538
1539 return ret;
1540}
1541
1542#endif // QT_NO_STRINGLIST
1543
1544
1545/* \internal
1546 Internal function. Converts boolean font settings to an unsigned
1547 8-bit number. Used for serialization etc.
1548*/
1549static Q_UINT8 get_font_bits( const QFontPrivate *f )
1550{
1551#ifdef QT_CHECK_STATE
1552 Q_ASSERT( f != 0 );
1553#endif
1554
1555 Q_UINT8 bits = 0;
1556 if ( f->request.italic )
1557 bits |= 0x01;
1558 if ( f->underline )
1559 bits |= 0x02;
1560 if ( f->overline )
1561 bits |= 0x40;
1562 if ( f->strikeOut )
1563 bits |= 0x04;
1564 if ( f->request.fixedPitch )
1565 bits |= 0x08;
1566 // if ( f.hintSetByUser )
1567 // bits |= 0x10;
1568 if ( f->rawMode )
1569 bits |= 0x20;
1570 return bits;
1571}
1572
1573
1574#ifndef QT_NO_DATASTREAM
1575
1576/* \internal
1577 Internal function. Sets boolean font settings from an unsigned
1578 8-bit number. Used for serialization etc.
1579*/
1580static void set_font_bits( Q_UINT8 bits, QFontPrivate *f )
1581{
1582#ifdef QT_CHECK_STATE
1583 Q_ASSERT( f != 0 );
1584#endif
1585
1586 f->request.italic = (bits & 0x01) != 0;
1587 f->underline = (bits & 0x02) != 0;
1588 f->overline = (bits & 0x40) != 0;
1589 f->strikeOut = (bits & 0x04) != 0;
1590 f->request.fixedPitch = (bits & 0x08) != 0;
1591 // f->hintSetByUser = (bits & 0x10) != 0;
1592 f->rawMode = (bits & 0x20) != 0;
1593}
1594
1595#endif
1596
1597
1598/*!
1599 Returns the font's key, a textual representation of a font. It is
1600 typically used as the key for a cache or dictionary of fonts.
1601
1602 \sa QMap
1603*/
1604QString QFont::key() const
1605{
1606 return toString();
1607}
1608
1609/*!
1610 Returns a description of the font. The description is a
1611 comma-separated list of the attributes, perfectly suited for use
1612 in QSettings.
1613
1614 \sa fromString() operator<<()
1615 */
1616QString QFont::toString() const
1617{
1618 const QChar comma( ',' );
1619 return family() + comma +
1620 QString::number( pointSizeFloat() ) + comma +
1621 QString::number( pixelSize() ) + comma +
1622 QString::number( (int) styleHint() ) + comma +
1623 QString::number( weight() ) + comma +
1624 QString::number( (int) italic() ) + comma +
1625 QString::number( (int) underline() ) + comma +
1626 QString::number( (int) strikeOut() ) + comma +
1627 QString::number( (int)fixedPitch() ) + comma +
1628 QString::number( (int) rawMode() );
1629}
1630
1631
1632/*!
1633 Sets this font to match the description \a descrip. The description
1634 is a comma-separated list of the font attributes, as returned by
1635 toString().
1636
1637 \sa toString() operator>>()
1638 */
1639bool QFont::fromString(const QString &descrip)
1640{
1641#ifndef QT_NO_STRINGLIST
1642 QStringList l(QStringList::split(',', descrip));
1643
1644 int count = l.count();
1645#else
1646 int count = 0;
1647 QString l[11];
1648 int from = 0;
1649 int to = descrip.find( ',' );
1650 while ( to > 0 && count < 11 ) {
1651 l[count] = descrip.mid( from, to-from );
1652 count++;
1653 from = to+1;
1654 to = descrip.find( ',', from );
1655 }
1656#endif // QT_NO_STRINGLIST
1657 if ( !count || ( count > 2 && count < 9 ) || count > 11 ) {
1658
1659#ifdef QT_CHECK_STATE
1660 qWarning("QFont::fromString: invalid description '%s'", descrip.latin1());
1661#endif
1662
1663 return FALSE;
1664 }
1665
1666 setFamily(l[0]);
1667 if ( count > 1 && l[1].toDouble() > 0.0 )
1668 setPointSizeFloat(l[1].toDouble());
1669 if ( count == 9 ) {
1670 setStyleHint((StyleHint) l[2].toInt());
1671 setWeight(l[3].toInt());
1672 setItalic(l[4].toInt());
1673 setUnderline(l[5].toInt());
1674 setStrikeOut(l[6].toInt());
1675 setFixedPitch(l[7].toInt());
1676 setRawMode(l[8].toInt());
1677 } else if ( count == 10 ) {
1678 if ( l[2].toInt() > 0 )
1679 setPixelSize( l[2].toInt() );
1680 setStyleHint((StyleHint) l[3].toInt());
1681 setWeight(l[4].toInt());
1682 setItalic(l[5].toInt());
1683 setUnderline(l[6].toInt());
1684 setStrikeOut(l[7].toInt());
1685 setFixedPitch(l[8].toInt());
1686 setRawMode(l[9].toInt());
1687 }
1688
1689 return TRUE;
1690}
1691
1692#if !defined( Q_WS_QWS )
1693/*! \internal
1694
1695 Internal function that dumps font cache statistics.
1696*/
1697void QFont::cacheStatistics()
1698{
1699
1700
1701}
1702#endif // !Q_WS_QWS
1703
1704
1705
1706/*****************************************************************************
1707 QFont stream functions
1708 *****************************************************************************/
1709#ifndef QT_NO_DATASTREAM
1710
1711/*!
1712 \relates QFont
1713
1714 Writes the font \a font to the data stream \a s. (toString()
1715 writes to a text stream.)
1716
1717 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
1718*/
1719QDataStream &operator<<( QDataStream &s, const QFont &font )
1720{
1721 if ( s.version() == 1 ) {
1722 QCString fam( font.d->request.family.latin1() );
1723 s << fam;
1724 } else {
1725 s << font.d->request.family;
1726 }
1727
1728 if ( s.version() <= 3 ) {
1729 Q_INT16 pointSize = (Q_INT16) font.d->request.pointSize;
1730 if ( pointSize == -1 ) {
1731#ifdef Q_WS_X11
1732 pointSize = (Q_INT16)(font.d->request.pixelSize*720/QPaintDevice::x11AppDpiY());
1733#else
1734 pointSize = (Q_INT16)QFontInfo( font ).pointSize() * 10;
1735#endif
1736 }
1737 s << pointSize;
1738 } else {
1739 s << (Q_INT16) font.d->request.pointSize;
1740 s << (Q_INT16) font.d->request.pixelSize;
1741 }
1742
1743 s << (Q_UINT8) font.d->request.styleHint;
1744 if ( s.version() >= 5 )
1745 s << (Q_UINT8 ) font.d->request.styleStrategy;
1746 return s << (Q_UINT8) 0
1747 << (Q_UINT8) font.d->request.weight
1748 << get_font_bits(font.d);
1749}
1750
1751
1752/*!
1753 \relates QFont
1754
1755 Reads the font \a font from the data stream \a s. (fromString()
1756 reads from a text stream.)
1757
1758 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
1759*/
1760QDataStream &operator>>( QDataStream &s, QFont &font )
1761{
1762 if (font.d->deref()) delete font.d;
1763
1764 font.d = new QFontPrivate;
1765 font.d->mask = QFontPrivate::Complete;
1766
1767 Q_INT16 pointSize, pixelSize = -1;
1768 Q_UINT8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits;
1769
1770 if ( s.version() == 1 ) {
1771 QCString fam;
1772 s >> fam;
1773 font.d->request.family = QString( fam );
1774 } else {
1775 s >> font.d->request.family;
1776 }
1777
1778 s >> pointSize;
1779 if ( s.version() >= 4 )
1780 s >> pixelSize;
1781 s >> styleHint;
1782 if ( s.version() >= 5 )
1783 s >> styleStrategy;
1784 s >> charSet;
1785 s >> weight;
1786 s >> bits;
1787
1788 font.d->request.pointSize = pointSize;
1789 font.d->request.pixelSize = pixelSize;
1790 font.d->request.styleHint = styleHint;
1791 font.d->request.styleStrategy = styleStrategy;
1792 font.d->request.weight = weight;
1793
1794 set_font_bits( bits, font.d );
1795
1796 return s;
1797}
1798
1799#endif // QT_NO_DATASTREAM
1800
1801
1802
1803
1804/*****************************************************************************
1805 QFontMetrics member functions
1806 *****************************************************************************/
1807
1808/*!
1809 \class QFontMetrics qfontmetrics.h
1810 \brief The QFontMetrics class provides font metrics information.
1811
1812 \ingroup graphics
1813 \ingroup shared
1814
1815 QFontMetrics functions calculate the size of characters and
1816 strings for a given font. There are three ways you can create a
1817 QFontMetrics object:
1818
1819 \list 1
1820 \i Calling the QFontMetrics constructor with a QFont creates a
1821 font metrics object for a screen-compatible font, i.e. the font
1822 cannot be a printer font<sup>*</sup>. If the font is changed
1823 later, the font metrics object is \e not updated.
1824
1825 \i QWidget::fontMetrics() returns the font metrics for a widget's
1826 font. This is equivalent to QFontMetrics(widget->font()). If the
1827 widget's font is changed later, the font metrics object is \e not
1828 updated.
1829
1830 \i QPainter::fontMetrics() returns the font metrics for a
1831 painter's current font. If the painter's font is changed later, the
1832 font metrics object is \e not updated.
1833 \endlist
1834
1835 <sup>*</sup> If you use a printer font the values returned may be
1836 inaccurate. Printer fonts are not always accessible so the nearest
1837 screen font is used if a printer font is supplied.
1838
1839 Once created, the object provides functions to access the
1840 individual metrics of the font, its characters, and for strings
1841 rendered in the font.
1842
1843 There are several functions that operate on the font: ascent(),
1844 descent(), height(), leading() and lineSpacing() return the basic
1845 size properties of the font. The underlinePos(), overlinePos(),
1846 strikeOutPos() and lineWidth() functions, return the properties of
1847 the line that underlines, overlines or strikes out the
1848 characters. These functions are all fast.
1849
1850 There are also some functions that operate on the set of glyphs in
1851 the font: minLeftBearing(), minRightBearing() and maxWidth().
1852 These are by necessity slow, and we recommend avoiding them if
1853 possible.
1854
1855 For each character, you can get its width(), leftBearing() and
1856 rightBearing() and find out whether it is in the font using
1857 inFont(). You can also treat the character as a string, and use
1858 the string functions on it.
1859
1860 The string functions include width(), to return the width of a
1861 string in pixels (or points, for a printer), boundingRect(), to
1862 return a rectangle large enough to contain the rendered string,
1863 and size(), to return the size of that rectangle.
1864
1865 Example:
1866 \code
1867 QFont font( "times", 24 );
1868 QFontMetrics fm( font );
1869 int pixelsWide = fm.width( "What's the width of this text?" );
1870 int pixelsHigh = fm.height();
1871 \endcode
1872
1873 \sa QFont QFontInfo QFontDatabase
1874*/
1875
1876/*!
1877 Constructs a font metrics object for \a font.
1878
1879 The font must be screen-compatible, i.e. a font you use when
1880 drawing text in \link QWidget widgets\endlink or \link QPixmap
1881 pixmaps\endlink, not QPicture or QPrinter.
1882
1883 The font metrics object holds the information for the font that is
1884 passed in the constructor at the time it is created, and is not
1885 updated if the font's attributes are changed later.
1886
1887 Use QPainter::fontMetrics() to get the font metrics when painting.
1888 This will give correct results also when painting on paint device
1889 that is not screen-compatible.
1890*/
1891QFontMetrics::QFontMetrics( const QFont &font )
1892 : d( font.d ), painter( 0 ), fscript( QFont::NoScript )
1893{
1894 d->ref();
1895}
1896
1897/*!
1898 \overload
1899
1900 Constructs a font metrics object for \a font using the given \a
1901 script.
1902*/
1903QFontMetrics::QFontMetrics( const QFont &font, QFont::Script script )
1904 : d( font.d ), painter( 0 ), fscript( script )
1905{
1906 d->ref();
1907}
1908
1909/*! \internal
1910
1911 Constructs a font metrics object for the painter's font \a p.
1912*/
1913QFontMetrics::QFontMetrics( const QPainter *p )
1914 : painter ( (QPainter *) p ), fscript( QFont::NoScript )
1915{
1916#if defined(CHECK_STATE)
1917 if ( !painter->isActive() )
1918 qWarning( "QFontMetrics: Get font metrics between QPainter::begin() "
1919 "and QPainter::end()" );
1920#endif
1921
1922 if ( painter->testf(QPainter::DirtyFont) )
1923 painter->updateFont();
1924
1925 d = painter->pfont ? painter->pfont->d : painter->cfont.d;
1926
1927#if defined(Q_WS_X11)
1928 if ( d->screen != p->scrn ) {
1929 QFontPrivate *new_d = new QFontPrivate( *d );
1930 Q_CHECK_PTR( new_d );
1931 d = new_d;
1932 d->screen = p->scrn;
1933 d->count = 1;
1934 } else
1935#endif // Q_WS_X11
1936 d->ref();
1937}
1938
1939/*!
1940 Constructs a copy of \a fm.
1941*/
1942QFontMetrics::QFontMetrics( const QFontMetrics &fm )
1943 : d( fm.d ), painter( 0 ), fscript( fm.fscript )
1944{
1945 d->ref();
1946}
1947
1948/*!
1949 Destroys the font metrics object and frees all allocated
1950 resources.
1951*/
1952QFontMetrics::~QFontMetrics()
1953{
1954 if ( d->deref() )
1955 delete d;
1956}
1957
1958/*!
1959 Assigns the font metrics \a fm.
1960*/
1961QFontMetrics &QFontMetrics::operator=( const QFontMetrics &fm )
1962{
1963 if ( d != fm.d ) {
1964 if ( d->deref() )
1965 delete d;
1966 d = fm.d;
1967 d->ref();
1968 }
1969 painter = fm.painter;
1970 return *this;
1971}
1972
1973/*!
1974 Returns the ascent of the font.
1975
1976 The ascent of a font is the distance from the baseline to the
1977 highest position characters extend to. In practice, some font
1978 designers break this rule, e.g. when they put more than one accent
1979 on top of a character, or to accommodate an unusual character in
1980 an exotic language, so it is possible (though rare) that this
1981 value will be too small.
1982
1983 \sa descent()
1984*/
1985int QFontMetrics::ascent() const
1986{
1987 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
1988 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
1989#ifdef QT_CHECK_STATE
1990 Q_ASSERT( engine != 0 );
1991 Q_ASSERT( latin_engine != 0 );
1992#endif // QT_CHECK_STATE
1993
1994 return QMAX(engine->ascent(), latin_engine->ascent());
1995}
1996
1997
1998/*!
1999 Returns the descent of the font.
2000
2001 The descent is the distance from the base line to the lowest point
2002 characters extend to. (Note that this is different from X, which
2003 adds 1 pixel.) In practice, some font designers break this rule,
2004 e.g. to accommodate an unusual character in an exotic language, so
2005 it is possible (though rare) that this value will be too small.
2006
2007 \sa ascent()
2008*/
2009int QFontMetrics::descent() const
2010{
2011 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2012 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2013#ifdef QT_CHECK_STATE
2014 Q_ASSERT( engine != 0 );
2015 Q_ASSERT( latin_engine != 0 );
2016#endif // QT_CHECK_STATE
2017
2018 return QMAX(engine->descent(), latin_engine->descent());
2019}
2020
2021/*!
2022 Returns the height of the font.
2023
2024 This is always equal to ascent()+descent()+1 (the 1 is for the
2025 base line).
2026
2027 \sa leading(), lineSpacing()
2028*/
2029int QFontMetrics::height() const
2030{
2031 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2032 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2033#ifdef QT_CHECK_STATE
2034 Q_ASSERT( engine != 0 );
2035 Q_ASSERT( latin_engine != 0 );
2036#endif // QT_CHECK_STATE
2037
2038 return (QMAX(engine->ascent(), latin_engine->ascent()) +
2039 QMAX(engine->descent(), latin_engine->descent()) + 1);
2040}
2041
2042/*!
2043 Returns the leading of the font.
2044
2045 This is the natural inter-line spacing.
2046
2047 \sa height(), lineSpacing()
2048*/
2049int QFontMetrics::leading() const
2050{
2051 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2052 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2053#ifdef QT_CHECK_STATE
2054 Q_ASSERT( engine != 0 );
2055 Q_ASSERT( latin_engine != 0 );
2056#endif // QT_CHECK_STATE
2057
2058 return QMAX(engine->leading(), latin_engine->leading());
2059}
2060
2061/*!
2062 Returns the distance from one base line to the next.
2063
2064 This value is always equal to leading()+height().
2065
2066 \sa height(), leading()
2067*/
2068int QFontMetrics::lineSpacing() const
2069{
2070 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2071 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2072#ifdef QT_CHECK_STATE
2073 Q_ASSERT( engine != 0 );
2074 Q_ASSERT( latin_engine != 0 );
2075#endif // QT_CHECK_STATE
2076
2077 return (QMAX(engine->leading(), latin_engine->leading()) +
2078 QMAX(engine->ascent(), latin_engine->ascent()) +
2079 QMAX(engine->descent(), latin_engine->descent()) + 1);
2080}
2081
2082/*!
2083 Returns the minimum left bearing of the font.
2084
2085 This is the smallest leftBearing(char) of all characters in the
2086 font.
2087
2088 Note that this function can be very slow if the font is large.
2089
2090 \sa minRightBearing(), leftBearing()
2091*/
2092int QFontMetrics::minLeftBearing() const
2093{
2094 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2095 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2096#ifdef QT_CHECK_STATE
2097 Q_ASSERT( engine != 0 );
2098 Q_ASSERT( latin_engine != 0 );
2099#endif // QT_CHECK_STATE
2100
2101 return QMIN(engine->minLeftBearing(), latin_engine->minLeftBearing());
2102}
2103
2104/*!
2105 Returns the minimum right bearing of the font.
2106
2107 This is the smallest rightBearing(char) of all characters in the
2108 font.
2109
2110 Note that this function can be very slow if the font is large.
2111
2112 \sa minLeftBearing(), rightBearing()
2113*/
2114int QFontMetrics::minRightBearing() const
2115{
2116 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2117 QFontEngine *latin_engine = d->engineForScript( QFont::Latin );
2118#ifdef QT_CHECK_STATE
2119 Q_ASSERT( engine != 0 );
2120 Q_ASSERT( latin_engine != 0 );
2121#endif // QT_CHECK_STATE
2122
2123 return QMIN(engine->minRightBearing(), latin_engine->minRightBearing());
2124}
2125
2126/*!
2127 Returns the width of the widest character in the font.
2128*/
2129int QFontMetrics::maxWidth() const
2130{
2131 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2132 QFontEngine *lengine = d->engineForScript( QFont::Latin );
2133#ifdef QT_CHECK_STATE
2134 Q_ASSERT( engine != 0 );
2135 Q_ASSERT( lengine != 0 );
2136#endif // QT_CHECK_STATE
2137
2138 return QMAX(engine->maxCharWidth(), lengine->maxCharWidth());
2139}
2140
2141/*!
2142 Returns TRUE if character \a ch is a valid character in the font;
2143 otherwise returns FALSE.
2144*/
2145bool QFontMetrics::inFont(QChar ch) const
2146{
2147 QFont::Script script;
2148 SCRIPT_FOR_CHAR( script, ch );
2149
2150 QFontEngine *engine = d->engineForScript( script );
2151#ifdef QT_CHECK_STATE
2152 Q_ASSERT( engine != 0 );
2153#endif // QT_CHECK_STATE
2154
2155 if ( engine->type() == QFontEngine::Box ) return FALSE;
2156 return engine->canRender( &ch, 1 );
2157}
2158
2159/*! \fn int QFontMetrics::leftBearing( QChar ch ) const
2160 Returns the left bearing of character \a ch in the font.
2161
2162 The left bearing is the right-ward distance of the left-most pixel
2163 of the character from the logical origin of the character. This
2164 value is negative if the pixels of the character extend to the
2165 left of the logical origin.
2166
2167 See width(QChar) for a graphical description of this metric.
2168
2169 \sa rightBearing(), minLeftBearing(), width()
2170*/
2171#if !defined(Q_WS_WIN) && !defined(Q_WS_QWS)
2172int QFontMetrics::leftBearing(QChar ch) const
2173{
2174 QFont::Script script;
2175 SCRIPT_FOR_CHAR( script, ch );
2176
2177 QFontEngine *engine = d->engineForScript( script );
2178#ifdef QT_CHECK_STATE
2179 Q_ASSERT( engine != 0 );
2180#endif // QT_CHECK_STATE
2181
2182 if ( engine->type() == QFontEngine::Box ) return 0;
2183
2184 glyph_t glyphs[10];
2185 int nglyphs = 9;
2186 engine->stringToCMap( &ch, 1, glyphs, 0, &nglyphs, FALSE );
2187 // ### can nglyphs != 1 happen at all? Not currently I think
2188 glyph_metrics_t gi = engine->boundingBox( glyphs[0] );
2189 return gi.x;
2190}
2191#endif // !Q_WS_WIN
2192
2193/*! \fn int QFontMetrics::rightBearing(QChar ch) const
2194 Returns the right bearing of character \a ch in the font.
2195
2196 The right bearing is the left-ward distance of the right-most
2197 pixel of the character from the logical origin of a subsequent
2198 character. This value is negative if the pixels of the character
2199 extend to the right of the width() of the character.
2200
2201 See width() for a graphical description of this metric.
2202
2203 \sa leftBearing(), minRightBearing(), width()
2204*/
2205#if !defined(Q_WS_WIN) && !defined(Q_WS_QWS)
2206int QFontMetrics::rightBearing(QChar ch) const
2207{
2208 QFont::Script script;
2209 SCRIPT_FOR_CHAR( script, ch );
2210
2211 QFontEngine *engine = d->engineForScript( script );
2212#ifdef QT_CHECK_STATE
2213 Q_ASSERT( engine != 0 );
2214#endif // QT_CHECK_STATE
2215
2216 if ( engine->type() == QFontEngine::Box ) return 0;
2217
2218 glyph_t glyphs[10];
2219 int nglyphs = 9;
2220 engine->stringToCMap( &ch, 1, glyphs, 0, &nglyphs, FALSE );
2221 // ### can nglyphs != 1 happen at all? Not currently I think
2222 glyph_metrics_t gi = engine->boundingBox( glyphs[0] );
2223 return gi.xoff - gi.x - gi.width;
2224}
2225#endif // !Q_WS_WIN
2226
2227
2228#ifndef Q_WS_QWS
2229/*!
2230 Returns the width in pixels of the first \a len characters of \a
2231 str. If \a len is negative (the default), the entire string is
2232 used.
2233
2234 Note that this value is \e not equal to boundingRect().width();
2235 boundingRect() returns a rectangle describing the pixels this
2236 string will cover whereas width() returns the distance to where
2237 the next string should be drawn.
2238
2239 \sa boundingRect()
2240*/
2241int QFontMetrics::width( const QString &str, int len ) const
2242{
2243 if (len < 0)
2244 len = str.length();
2245 if (len == 0)
2246 return 0;
2247
2248 int pos = 0;
2249 int width = 0;
2250#ifndef Q_WS_MAC
2251 const QChar *ch = str.unicode();
2252
2253 while (pos < len) {
2254 unsigned short uc = ch->unicode();
2255 if (uc < QFontEngineData::widthCacheSize && d->engineData && d->engineData->widthCache[uc])
2256 width += d->engineData->widthCache[uc];
2257 else if ( ::category( *ch ) != QChar::Mark_NonSpacing ) {
2258 QFont::Script script;
2259 SCRIPT_FOR_CHAR( script, *ch );
2260
2261 if (script >= QFont::Arabic && script <= QFont::Khmer)
2262 break;
2263
2264 QFontEngine *engine = d->engineForScript( script );
2265#ifdef QT_CHECK_STATE
2266 Q_ASSERT( engine != 0 );
2267#endif // QT_CHECK_STATE
2268
2269 glyph_t glyphs[8];
2270 advance_t advances[8];
2271 int nglyphs = 7;
2272 engine->stringToCMap( ch, 1, glyphs, advances, &nglyphs, FALSE );
2273
2274 // ### can nglyphs != 1 happen at all? Not currently I think
2275 if ( uc < QFontEngineData::widthCacheSize && advances[0] < 0x100 )
2276 d->engineData->widthCache[ uc ] = advances[0];
2277 width += advances[0];
2278 }
2279 ++pos;
2280 ++ch;
2281 }
2282 if ( pos < len ) {
2283#endif
2284 QTextEngine layout( str, d );
2285 layout.itemize( QTextEngine::WidthOnly );
2286 width += layout.width( pos, len-pos );
2287#ifndef Q_WS_MAC
2288 }
2289#endif
2290 return width;
2291}
2292#endif
2293
2294/*! \fn int QFontMetrics::width( QChar ch ) const
2295
2296 <img src="bearings.png" align=right>
2297
2298 Returns the logical width of character \a ch in pixels. This is a
2299 distance appropriate for drawing a subsequent character after \a
2300 ch.
2301
2302 Some of the metrics are described in the image to the right. The
2303 central dark rectangles cover the logical width() of each
2304 character. The outer pale rectangles cover the leftBearing() and
2305 rightBearing() of each character. Notice that the bearings of "f"
2306 in this particular font are both negative, while the bearings of
2307 "o" are both positive.
2308
2309 \warning This function will produce incorrect results for Arabic
2310 characters or non spacing marks in the middle of a string, as the
2311 glyph shaping and positioning of marks that happens when
2312 processing strings cannot be taken into account. Use charWidth()
2313 instead if you aren't looking for the width of isolated
2314 characters.
2315
2316 \sa boundingRect(), charWidth()
2317*/
2318
2319/*! \fn int QFontMetrics::width( char c ) const
2320
2321 \overload
2322 \obsolete
2323
2324 Provided to aid porting from Qt 1.x.
2325*/
2326
2327/*! \fn int QFontMetrics::charWidth( const QString &str, int pos ) const
2328 Returns the width of the character at position \a pos in the
2329 string \a str.
2330
2331 The whole string is needed, as the glyph drawn may change
2332 depending on the context (the letter before and after the current
2333 one) for some languages (e.g. Arabic).
2334
2335 This function also takes non spacing marks and ligatures into
2336 account.
2337*/
2338
2339#ifndef Q_WS_QWS
2340/*!
2341 Returns the bounding rectangle of the first \a len characters of
2342 \a str, which is the set of pixels the text would cover if drawn
2343 at (0, 0).
2344
2345 If \a len is negative (the default), the entire string is used.
2346
2347 Note that the bounding rectangle may extend to the left of (0, 0),
2348 e.g. for italicized fonts, and that the text output may cover \e
2349 all pixels in the bounding rectangle.
2350
2351 Newline characters are processed as normal characters, \e not as
2352 linebreaks.
2353
2354 Due to the different actual character heights, the height of the
2355 bounding rectangle of e.g. "Yes" and "yes" may be different.
2356
2357 \sa width(), QPainter::boundingRect()
2358*/
2359QRect QFontMetrics::boundingRect( const QString &str, int len ) const
2360{
2361 if (len < 0)
2362 len = str.length();
2363 if (len == 0)
2364 return QRect();
2365
2366 QTextEngine layout( str, d );
2367 layout.itemize( QTextEngine::NoBidi|QTextEngine::SingleLine );
2368 glyph_metrics_t gm = layout.boundingBox( 0, len );
2369 return QRect( gm.x, gm.y, gm.width, gm.height );
2370}
2371#endif
2372
2373/*!
2374 Returns the bounding rectangle of the character \a ch relative to
2375 the left-most point on the base line.
2376
2377 Note that the bounding rectangle may extend to the left of (0, 0),
2378 e.g. for italicized fonts, and that the text output may cover \e
2379 all pixels in the bounding rectangle.
2380
2381 Note that the rectangle usually extends both above and below the
2382 base line.
2383
2384 \sa width()
2385*/
2386QRect QFontMetrics::boundingRect( QChar ch ) const
2387{
2388 QFont::Script script;
2389 SCRIPT_FOR_CHAR( script, ch );
2390
2391 QFontEngine *engine = d->engineForScript( script );
2392#ifdef QT_CHECK_STATE
2393 Q_ASSERT( engine != 0 );
2394#endif // QT_CHECK_STATE
2395
2396 glyph_t glyphs[10];
2397 int nglyphs = 9;
2398 engine->stringToCMap( &ch, 1, glyphs, 0, &nglyphs, FALSE );
2399 glyph_metrics_t gi = engine->boundingBox( glyphs[0] );
2400 return QRect( gi.x, gi.y, gi.width, gi.height );
2401}
2402
2403/*!
2404 \overload
2405
2406 Returns the bounding rectangle of the first \a len characters of
2407 \a str, which is the set of pixels the text would cover if drawn
2408 at (0, 0). The drawing, and hence the bounding rectangle, is
2409 constrained to the rectangle (\a x, \a y, \a w, \a h).
2410
2411 If \a len is negative (which is the default), the entire string is
2412 used.
2413
2414 The \a flgs argument is the bitwise OR of the following flags:
2415 \list
2416 \i \c AlignAuto aligns to the left border for all languages except
2417 Arabic and Hebrew where it aligns to the right.
2418 \i \c AlignLeft aligns to the left border.
2419 \i \c AlignRight aligns to the right border.
2420 \i \c AlignJustify produces justified text.
2421 \i \c AlignHCenter aligns horizontally centered.
2422 \i \c AlignTop aligns to the top border.
2423 \i \c AlignBottom aligns to the bottom border.
2424 \i \c AlignVCenter aligns vertically centered
2425 \i \c AlignCenter (== \c{AlignHCenter | AlignVCenter})
2426 \i \c SingleLine ignores newline characters in the text.
2427 \i \c ExpandTabs expands tabs (see below)
2428 \i \c ShowPrefix interprets "&amp;x" as "<u>x</u>", i.e. underlined.
2429 \i \c WordBreak breaks the text to fit the rectangle.
2430 \endlist
2431
2432 Horizontal alignment defaults to \c AlignAuto and vertical
2433 alignment defaults to \c AlignTop.
2434
2435 If several of the horizontal or several of the vertical alignment
2436 flags are set, the resulting alignment is undefined.
2437
2438 These flags are defined in \c qnamespace.h.
2439
2440 If \c ExpandTabs is set in \a flgs, then: if \a tabarray is
2441 non-null, it specifies a 0-terminated sequence of pixel-positions
2442 for tabs; otherwise if \a tabstops is non-zero, it is used as the
2443 tab spacing (in pixels).
2444
2445 Note that the bounding rectangle may extend to the left of (0, 0),
2446 e.g. for italicized fonts, and that the text output may cover \e
2447 all pixels in the bounding rectangle.
2448
2449 Newline characters are processed as linebreaks.
2450
2451 Despite the different actual character heights, the heights of the
2452 bounding rectangles of "Yes" and "yes" are the same.
2453
2454 The bounding rectangle given by this function is somewhat larger
2455 than that calculated by the simpler boundingRect() function. This
2456 function uses the \link minLeftBearing() maximum left \endlink and
2457 \link minRightBearing() right \endlink font bearings as is
2458 necessary for multi-line text to align correctly. Also,
2459 fontHeight() and lineSpacing() are used to calculate the height,
2460 rather than individual character heights.
2461
2462 The \a intern argument should not be used.
2463
2464 \sa width(), QPainter::boundingRect(), Qt::AlignmentFlags
2465*/
2466QRect QFontMetrics::boundingRect( int x, int y, int w, int h, int flgs,
2467 const QString& str, int len, int tabstops,
2468 int *tabarray, QTextParag **intern ) const
2469{
2470 if ( len < 0 )
2471 len = str.length();
2472
2473 int tabarraylen=0;
2474 if (tabarray)
2475 while (tabarray[tabarraylen])
2476 tabarraylen++;
2477
2478 QRect rb;
2479 QRect r(x, y, w, h);
2480 qt_format_text( QFont( d, d->paintdevice ), r, flgs|Qt::DontPrint, str, len, &rb,
2481 tabstops, tabarray, tabarraylen, intern, 0 );
2482
2483 return rb;
2484}
2485
2486/*!
2487 Returns the size in pixels of the first \a len characters of \a
2488 str.
2489
2490 If \a len is negative (the default), the entire string is used.
2491
2492 The \a flgs argument is the bitwise OR of the following flags:
2493 \list
2494 \i \c SingleLine ignores newline characters.
2495 \i \c ExpandTabs expands tabs (see below)
2496 \i \c ShowPrefix interprets "&amp;x" as "<u>x</u>", i.e. underlined.
2497 \i \c WordBreak breaks the text to fit the rectangle.
2498 \endlist
2499
2500 These flags are defined in \c qnamespace.h.
2501
2502 If \c ExpandTabs is set in \a flgs, then: if \a tabarray is
2503 non-null, it specifies a 0-terminated sequence of pixel-positions
2504 for tabs; otherwise if \a tabstops is non-zero, it is used as the
2505 tab spacing (in pixels).
2506
2507 Newline characters are processed as linebreaks.
2508
2509 Despite the different actual character heights, the heights of the
2510 bounding rectangles of "Yes" and "yes" are the same.
2511
2512 The \a intern argument should not be used.
2513
2514 \sa boundingRect()
2515*/
2516QSize QFontMetrics::size( int flgs, const QString &str, int len, int tabstops,
2517 int *tabarray, QTextParag **intern ) const
2518{
2519 return boundingRect(0,0,0,0,flgs,str,len,tabstops,tabarray,intern).size();
2520}
2521
2522/*!
2523 Returns the distance from the base line to where an underscore
2524 should be drawn.
2525
2526 \sa overlinePos(), strikeOutPos(), lineWidth()
2527*/
2528int QFontMetrics::underlinePos() const
2529{
2530 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2531#ifdef QT_CHECK_STATE
2532 Q_ASSERT( engine != 0 );
2533#endif // QT_CHECK_STATE
2534
2535 return engine->underlinePosition();
2536}
2537
2538/*!
2539 Returns the distance from the base line to where an overline
2540 should be drawn.
2541
2542 \sa underlinePos(), strikeOutPos(), lineWidth()
2543*/
2544int QFontMetrics::overlinePos() const
2545{
2546 int pos = ascent() + 1;
2547 return pos > 0 ? pos : 1;
2548}
2549
2550/*!
2551 Returns the distance from the base line to where the strikeout
2552 line should be drawn.
2553
2554 \sa underlinePos(), overlinePos(), lineWidth()
2555*/
2556int QFontMetrics::strikeOutPos() const
2557{
2558 int pos = ascent() / 3;
2559 return pos > 0 ? pos : 1;
2560}
2561
2562/*!
2563 Returns the width of the underline and strikeout lines, adjusted
2564 for the point size of the font.
2565
2566 \sa underlinePos(), overlinePos(), strikeOutPos()
2567*/
2568int QFontMetrics::lineWidth() const
2569{
2570 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2571#ifdef QT_CHECK_STATE
2572 Q_ASSERT( engine != 0 );
2573#endif // QT_CHECK_STATE
2574
2575 return engine->lineThickness();
2576}
2577
2578
2579
2580
2581/*****************************************************************************
2582 QFontInfo member functions
2583 *****************************************************************************/
2584
2585/*!
2586 \class QFontInfo qfontinfo.h
2587
2588 \brief The QFontInfo class provides general information about fonts.
2589
2590 \ingroup graphics
2591 \ingroup shared
2592
2593 The QFontInfo class provides the same access functions as QFont,
2594 e.g. family(), pointSize(), italic(), weight(), fixedPitch(),
2595 styleHint() etc. But whilst the QFont access functions return the
2596 values that were set, a QFontInfo object returns the values that
2597 apply to the font that will actually be used to draw the text.
2598
2599 For example, when the program asks for a 25pt Courier font on a
2600 machine that has a non-scalable 24pt Courier font, QFont will
2601 (normally) use the 24pt Courier for rendering. In this case,
2602 QFont::pointSize() returns 25 and QFontInfo::pointSize() returns
2603 24.
2604
2605 There are three ways to create a QFontInfo object.
2606 \list 1
2607 \i Calling the QFontInfo constructor with a QFont creates a font
2608 info object for a screen-compatible font, i.e. the font cannot be
2609 a printer font<sup>*</sup>. If the font is changed later, the font
2610 info object is \e not updated.
2611
2612 \i QWidget::fontInfo() returns the font info for a widget's font.
2613 This is equivalent to calling QFontInfo(widget->font()). If the
2614 widget's font is changed later, the font info object is \e not
2615 updated.
2616
2617 \i QPainter::fontInfo() returns the font info for a painter's
2618 current font. If the painter's font is changed later, the font
2619 info object is \e not updated.
2620 \endlist
2621
2622 <sup>*</sup> If you use a printer font the values returned may be
2623 inaccurate. Printer fonts are not always accessible so the nearest
2624 screen font is used if a printer font is supplied.
2625
2626 \sa QFont QFontMetrics QFontDatabase
2627*/
2628
2629/*!
2630 Constructs a font info object for \a font.
2631
2632 The font must be screen-compatible, i.e. a font you use when
2633 drawing text in \link QWidget widgets\endlink or \link QPixmap
2634 pixmaps\endlink, not QPicture or QPrinter.
2635
2636 The font info object holds the information for the font that is
2637 passed in the constructor at the time it is created, and is not
2638 updated if the font's attributes are changed later.
2639
2640 Use QPainter::fontInfo() to get the font info when painting.
2641 This will give correct results also when painting on paint device
2642 that is not screen-compatible.
2643*/
2644QFontInfo::QFontInfo( const QFont &font )
2645 : d( font.d ), painter( 0 ), fscript( QFont::NoScript )
2646{
2647 d->ref();
2648}
2649
2650/*!
2651 Constructs a font info object for \a font using the specified \a
2652 script.
2653*/
2654QFontInfo::QFontInfo( const QFont &font, QFont::Script script )
2655 : d( font.d ), painter( 0 ), fscript( script )
2656{
2657 d->ref();
2658}
2659
2660/*! \internal
2661
2662 Constructs a font info object from the painter's font \a p.
2663*/
2664QFontInfo::QFontInfo( const QPainter *p )
2665 : painter( 0 ), fscript( QFont::NoScript )
2666{
2667 QPainter *painter = (QPainter *) p;
2668
2669#if defined(CHECK_STATE)
2670 if ( !painter->isActive() )
2671 qWarning( "QFontInfo: Get font info between QPainter::begin() "
2672 "and QPainter::end()" );
2673#endif
2674
2675 painter->setf( QPainter::FontInf );
2676 if ( painter->testf(QPainter::DirtyFont) )
2677 painter->updateFont();
2678 if ( painter->pfont )
2679 d = painter->pfont->d;
2680 else
2681 d = painter->cfont.d;
2682 d->ref();
2683}
2684
2685/*!
2686 Constructs a copy of \a fi.
2687*/
2688QFontInfo::QFontInfo( const QFontInfo &fi )
2689 : d(fi.d), painter(0), fscript( fi.fscript )
2690{
2691 d->ref();
2692}
2693
2694/*!
2695 Destroys the font info object.
2696*/
2697QFontInfo::~QFontInfo()
2698{
2699 if ( d->deref() )
2700 delete d;
2701}
2702
2703/*!
2704 Assigns the font info in \a fi.
2705*/
2706QFontInfo &QFontInfo::operator=( const QFontInfo &fi )
2707{
2708 if ( d != fi.d ) {
2709 if ( d->deref() )
2710 delete d;
2711 d = fi.d;
2712 d->ref();
2713 }
2714 painter = 0;
2715 fscript = fi.fscript;
2716 return *this;
2717}
2718
2719/*!
2720 Returns the family name of the matched window system font.
2721
2722 \sa QFont::family()
2723*/
2724QString QFontInfo::family() const
2725{
2726 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2727#ifdef QT_CHECK_STATE
2728 Q_ASSERT( engine != 0 );
2729#endif // QT_CHECK_STATE
2730 return engine->fontDef.family;
2731}
2732
2733/*!
2734 Returns the point size of the matched window system font.
2735
2736 \sa QFont::pointSize()
2737*/
2738int QFontInfo::pointSize() const
2739{
2740 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2741#ifdef QT_CHECK_STATE
2742 Q_ASSERT( engine != 0 );
2743#endif // QT_CHECK_STATE
2744 return ( engine->fontDef.pointSize + 5 ) / 10;
2745}
2746
2747/*!
2748 Returns the pixel size of the matched window system font.
2749
2750 \sa QFont::pointSize()
2751*/
2752int QFontInfo::pixelSize() const
2753{
2754 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2755#ifdef QT_CHECK_STATE
2756 Q_ASSERT( engine != 0 );
2757#endif // QT_CHECK_STATE
2758 return engine->fontDef.pixelSize;
2759}
2760
2761/*!
2762 Returns the italic value of the matched window system font.
2763
2764 \sa QFont::italic()
2765*/
2766bool QFontInfo::italic() const
2767{
2768 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2769#ifdef QT_CHECK_STATE
2770 Q_ASSERT( engine != 0 );
2771#endif // QT_CHECK_STATE
2772 return engine->fontDef.italic;
2773}
2774
2775/*!
2776 Returns the weight of the matched window system font.
2777
2778 \sa QFont::weight(), bold()
2779*/
2780int QFontInfo::weight() const
2781{
2782 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2783#ifdef QT_CHECK_STATE
2784 Q_ASSERT( engine != 0 );
2785#endif // QT_CHECK_STATE
2786 return engine->fontDef.weight;
2787
2788}
2789
2790/*!
2791 \fn bool QFontInfo::bold() const
2792
2793 Returns TRUE if weight() would return a value greater than \c
2794 QFont::Normal; otherwise returns FALSE.
2795
2796 \sa weight(), QFont::bold()
2797*/
2798
2799/*!
2800 Returns the underline value of the matched window system font.
2801
2802 \sa QFont::underline()
2803
2804 \internal
2805
2806 Here we read the underline flag directly from the QFont.
2807 This is OK for X11 and for Windows because we always get what we want.
2808*/
2809bool QFontInfo::underline() const
2810{
2811 return d->underline;
2812}
2813
2814/*!
2815 Returns the overline value of the matched window system font.
2816
2817 \sa QFont::overline()
2818
2819 \internal
2820
2821 Here we read the overline flag directly from the QFont.
2822 This is OK for X11 and for Windows because we always get what we want.
2823*/
2824bool QFontInfo::overline() const
2825{
2826 return d->overline;
2827}
2828
2829/*!
2830 Returns the strikeout value of the matched window system font.
2831
2832 \sa QFont::strikeOut()
2833
2834 \internal Here we read the strikeOut flag directly from the QFont.
2835 This is OK for X11 and for Windows because we always get what we want.
2836*/
2837bool QFontInfo::strikeOut() const
2838{
2839 return d->strikeOut;
2840}
2841
2842/*!
2843 Returns the fixed pitch value of the matched window system font.
2844
2845 \sa QFont::fixedPitch()
2846*/
2847bool QFontInfo::fixedPitch() const
2848{
2849 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2850#ifdef QT_CHECK_STATE
2851 Q_ASSERT( engine != 0 );
2852#endif // QT_CHECK_STATE
2853#ifdef Q_OS_MAC
2854 if (!engine->fontDef.fixedPitchComputed) {
2855 QChar ch[2] = { QChar('i'), QChar('m') };
2856 glyph_t g[2];
2857 int l = 2;
2858 advance_t a[2];
2859 engine->stringToCMap(ch, 2, g, a, &l, false);
2860 engine->fontDef.fixedPitch = a[0] == a[1];
2861 engine->fontDef.fixedPitchComputed = TRUE;
2862 }
2863#endif
2864 return engine->fontDef.fixedPitch;
2865}
2866
2867/*!
2868 Returns the style of the matched window system font.
2869
2870 Currently only returns the style hint set in QFont.
2871
2872 \sa QFont::styleHint() QFont::StyleHint
2873*/
2874QFont::StyleHint QFontInfo::styleHint() const
2875{
2876 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2877#ifdef QT_CHECK_STATE
2878 Q_ASSERT( engine != 0 );
2879#endif // QT_CHECK_STATE
2880 return (QFont::StyleHint) engine->fontDef.styleHint;
2881}
2882
2883/*!
2884 Returns TRUE if the font is a raw mode font; otherwise returns
2885 FALSE.
2886
2887 If it is a raw mode font, all other functions in QFontInfo will
2888 return the same values set in the QFont, regardless of the font
2889 actually used.
2890
2891 \sa QFont::rawMode()
2892*/
2893bool QFontInfo::rawMode() const
2894{
2895 return d->rawMode;
2896}
2897
2898/*!
2899 Returns TRUE if the matched window system font is exactly the same
2900 as the one specified by the font; otherwise returns FALSE.
2901
2902 \sa QFont::exactMatch()
2903*/
2904bool QFontInfo::exactMatch() const
2905{
2906 QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
2907#ifdef QT_CHECK_STATE
2908 Q_ASSERT( engine != 0 );
2909#endif // QT_CHECK_STATE
2910
2911 return d->rawMode ? engine->type() != QFontEngine::Box
2912 : d->request == engine->fontDef;
2913}
2914
2915
2916
2917
2918// **********************************************************************
2919// QFontCache
2920// **********************************************************************
2921
2922#ifdef QFONTCACHE_DEBUG
2923// fast timeouts for debugging
2924static const int fast_timeout = 1000; // 1s
2925static const int slow_timeout = 5000; // 5s
2926#else
2927static const int fast_timeout = 10000; // 10s
2928static const int slow_timeout = 300000; // 5m
2929#endif // QFONTCACHE_DEBUG
2930
2931QFontCache *QFontCache::instance = 0;
2932const uint QFontCache::min_cost = 4*1024; // 4mb
2933
2934static QSingleCleanupHandler<QFontCache> cleanup_fontcache;
2935
2936
2937QFontCache::QFontCache()
2938 : QObject( qApp, "global font cache" ), total_cost( 0 ), max_cost( min_cost ),
2939 current_timestamp( 0 ), fast( FALSE ), timer_id( -1 )
2940{
2941 Q_ASSERT( instance == 0 );
2942 instance = this;
2943 cleanup_fontcache.set( &instance );
2944}
2945
2946QFontCache::~QFontCache()
2947{
2948 {
2949 EngineDataCache::Iterator it = engineDataCache.begin(),
2950 end = engineDataCache.end();
2951 while ( it != end ) {
2952 if ( it.data()->count == 0 )
2953 delete it.data();
2954 else
2955 FC_DEBUG("QFontCache::~QFontCache: engineData %p still has refcount %d",
2956 it.data(), it.data()->count);
2957 ++it;
2958 }
2959 }
2960 EngineCache::Iterator it = engineCache.begin(),
2961 end = engineCache.end();
2962 while ( it != end ) {
2963 if ( it.data().data->count == 0 ) {
2964 if ( --it.data().data->cache_count == 0 ) {
2965 FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %d %d %d %d %d)",
2966 it.data().data, it.key().script, it.key().def.pointSize,
2967 it.key().def.pixelSize, it.key().def.weight, it.key().def.italic,
2968 it.key().def.fixedPitch);
2969
2970 delete it.data().data;
2971 }
2972 } else {
2973 FC_DEBUG("QFontCache::~QFontCache: engine = %p still has refcount %d",
2974 it.data().data, it.data().data->count);
2975 }
2976 ++it;
2977 }
2978 instance = 0;
2979}
2980
2981#ifdef Q_WS_QWS
2982void QFontCache::clear()
2983{
2984 {
2985 EngineDataCache::Iterator it = engineDataCache.begin(),
2986 end = engineDataCache.end();
2987 while ( it != end ) {
2988 QFontEngineData *data = it.data();
2989 if ( data->engine )
2990 data->engine->deref();
2991 data->engine = 0;
2992 ++it;
2993 }
2994 }
2995
2996 EngineCache::Iterator it = engineCache.begin(),
2997 end = engineCache.end();
2998 while ( it != end ) {
2999 if ( it.data().data->count == 0 ) {
3000 if ( --it.data().data->cache_count == 0 ) {
3001 FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %d %d %d %d %d)",
3002 it.data().data, it.key().script, it.key().def.pointSize,
3003 it.key().def.pixelSize, it.key().def.weight, it.key().def.italic,
3004 it.key().def.fixedPitch);
3005 delete it.data().data;
3006 }
3007 } else {
3008 FC_DEBUG("QFontCache::~QFontCache: engine = %p still has refcount %d",
3009 it.data().data, it.data().data->count);
3010 }
3011 ++it;
3012 }
3013}
3014#endif
3015
3016QFontEngineData *QFontCache::findEngineData( const Key &key ) const
3017{
3018 EngineDataCache::ConstIterator it = engineDataCache.find( key ),
3019 end = engineDataCache.end();
3020 if ( it == end ) return 0;
3021
3022 // found
3023 return it.data();
3024}
3025
3026void QFontCache::insertEngineData( const Key &key, QFontEngineData *engineData )
3027{
3028 FC_DEBUG( "QFontCache: inserting new engine data %p", engineData );
3029
3030 engineDataCache.insert( key, engineData );
3031 increaseCost( sizeof( QFontEngineData ) );
3032}
3033
3034QFontEngine *QFontCache::findEngine( const Key &key )
3035{
3036 EngineCache::Iterator it = engineCache.find( key ),
3037 end = engineCache.end();
3038 if ( it == end ) return 0;
3039
3040 // found... update the hitcount and timestamp
3041 it.data().hits++;
3042 it.data().timestamp = ++current_timestamp;
3043
3044 FC_DEBUG( "QFontCache: found font engine\n"
3045 " %p: timestamp %4u hits %3u ref %2d/%2d, type '%s'",
3046 it.data().data, it.data().timestamp, it.data().hits,
3047 it.data().data->count, it.data().data->cache_count,
3048 it.data().data->name() );
3049
3050 return it.data().data;
3051}
3052
3053void QFontCache::insertEngine( const Key &key, QFontEngine *engine )
3054{
3055 FC_DEBUG( "QFontCache: inserting new engine %p", engine );
3056
3057 Engine data( engine );
3058 data.timestamp = ++current_timestamp;
3059
3060 engineCache.insert( key, data );
3061
3062 // only increase the cost if this is the first time we insert the engine
3063 if ( engine->cache_count == 0 )
3064 increaseCost( engine->cache_cost );
3065
3066 ++engine->cache_count;
3067}
3068
3069void QFontCache::increaseCost( uint cost )
3070{
3071 cost = ( cost + 512 ) / 1024; // store cost in kb
3072 cost = cost > 0 ? cost : 1;
3073 total_cost += cost;
3074
3075 FC_DEBUG( " COST: increased %u kb, total_cost %u kb, max_cost %u kb",
3076 cost, total_cost, max_cost );
3077
3078 if ( total_cost > max_cost) {
3079 max_cost = total_cost;
3080
3081 if ( timer_id == -1 || ! fast ) {
3082 FC_DEBUG( " TIMER: starting fast timer (%d ms)", fast_timeout );
3083
3084 if (timer_id != -1) killTimer( timer_id );
3085 timer_id = startTimer( fast_timeout );
3086 fast = TRUE;
3087 }
3088 }
3089}
3090
3091void QFontCache::decreaseCost( uint cost )
3092{
3093 cost = ( cost + 512 ) / 1024; // cost is stored in kb
3094 cost = cost > 0 ? cost : 1;
3095 Q_ASSERT( cost <= total_cost );
3096 total_cost -= cost;
3097
3098 FC_DEBUG( " COST: decreased %u kb, total_cost %u kb, max_cost %u kb",
3099 cost, total_cost, max_cost );
3100}
3101
3102#if defined(Q_WS_WIN ) || defined (Q_WS_QWS)
3103void QFontCache::cleanupPrinterFonts()
3104{
3105 FC_DEBUG( "QFontCache::cleanupPrinterFonts" );
3106
3107 {
3108 FC_DEBUG( " CLEAN engine data:" );
3109
3110 // clean out all unused engine datas
3111 EngineDataCache::Iterator it = engineDataCache.begin(),
3112 end = engineDataCache.end();
3113 while ( it != end ) {
3114 if ( it.key().screen == 0 ) {
3115 ++it;
3116 continue;
3117 }
3118
3119 if( it.data()->count > 0 ) {
3120#ifdef Q_WS_WIN
3121 for(int i = 0; i < QFont::LastPrivateScript; ++i) {
3122 if( it.data()->engines[i] ) {
3123 it.data()->engines[i]->deref();
3124 it.data()->engines[i] = 0;
3125 }
3126 }
3127#else
3128 if ( it.data()->engine ) {
3129 it.data()->engine->deref();
3130 it.data()->engine = 0;
3131 }
3132#endif
3133 ++it;
3134 } else {
3135
3136 EngineDataCache::Iterator rem = it++;
3137
3138 decreaseCost( sizeof( QFontEngineData ) );
3139
3140 FC_DEBUG( " %p", rem.data() );
3141
3142 delete rem.data();
3143 engineDataCache.remove( rem );
3144 }
3145 }
3146 }
3147
3148 EngineCache::Iterator it = engineCache.begin(),
3149 end = engineCache.end();
3150 while( it != end ) {
3151 if ( it.data().data->count > 0 || it.key().screen == 0) {
3152 ++it;
3153 continue;
3154 }
3155
3156 FC_DEBUG( " %p: timestamp %4u hits %2u ref %2d/%2d, type '%s'",
3157 it.data().data, it.data().timestamp, it.data().hits,
3158 it.data().data->count, it.data().data->cache_count,
3159 it.data().data->name() );
3160
3161 if ( --it.data().data->cache_count == 0 ) {
3162 FC_DEBUG( " DELETE: last occurence in cache" );
3163
3164 decreaseCost( it.data().data->cache_cost );
3165 delete it.data().data;
3166 }
3167
3168 engineCache.remove( it++ );
3169 }
3170}
3171#endif
3172
3173void QFontCache::timerEvent( QTimerEvent * )
3174{
3175 FC_DEBUG( "QFontCache::timerEvent: performing cache maintenance (timestamp %u)",
3176 current_timestamp );
3177
3178 if ( total_cost <= max_cost && max_cost <= min_cost ) {
3179 FC_DEBUG( " cache redused sufficiently, stopping timer" );
3180
3181 killTimer( timer_id );
3182 timer_id = -1;
3183 fast = FALSE;
3184
3185 return;
3186 }
3187
3188 // go through the cache and count up everything in use
3189 uint in_use_cost = 0;
3190
3191 {
3192 FC_DEBUG( " SWEEP engine data:" );
3193
3194 // make sure the cost of each engine data is at least 1kb
3195 const uint engine_data_cost =
3196 sizeof( QFontEngineData ) > 1024 ? sizeof( QFontEngineData ) : 1024;
3197
3198 EngineDataCache::ConstIterator it = engineDataCache.begin(),
3199 end = engineDataCache.end();
3200 for ( ; it != end; ++it ) {
3201#ifdef QFONTCACHE_DEBUG
3202 FC_DEBUG( " %p: ref %2d", it.data(), it.data()->count );
3203
3204# if defined(Q_WS_X11) || defined(Q_WS_WIN)
3205 // print out all engines
3206 for ( int i = 0; i < QFont::LastPrivateScript; ++i ) {
3207 if ( ! it.data()->engines[i] ) continue;
3208 FC_DEBUG( " contains %p", it.data()->engines[i] );
3209 }
3210# endif // Q_WS_X11 || Q_WS_WIN
3211#endif // QFONTCACHE_DEBUG
3212
3213 if ( it.data()->count > 0 )
3214 in_use_cost += engine_data_cost;
3215 }
3216 }
3217
3218 {
3219 FC_DEBUG( " SWEEP engine:" );
3220
3221 EngineCache::ConstIterator it = engineCache.begin(),
3222 end = engineCache.end();
3223 for ( ; it != end; ++it ) {
3224 FC_DEBUG( " %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes",
3225 it.data().data, it.data().timestamp, it.data().hits,
3226 it.data().data->count, it.data().data->cache_count,
3227 it.data().data->cache_cost );
3228
3229 if ( it.data().data->count > 0 )
3230 in_use_cost += it.data().data->cache_cost / it.data().data->cache_count;
3231 }
3232
3233 // attempt to make up for rounding errors
3234 in_use_cost += engineCache.count();
3235 }
3236
3237 in_use_cost = ( in_use_cost + 512 ) / 1024; // cost is stored in kb
3238
3239 /*
3240 calculate the new maximum cost for the cache
3241
3242 NOTE: in_use_cost is *not* correct due to rounding errors in the
3243 above algorithm. instead of worrying about getting the
3244 calculation correct, we are more interested in speed, and use
3245 in_use_cost as a floor for new_max_cost
3246 */
3247 uint new_max_cost = QMAX( QMAX( max_cost / 2, in_use_cost ), min_cost );
3248
3249 FC_DEBUG( " after sweep, in use %u kb, total %u kb, max %u kb, new max %u kb",
3250 in_use_cost, total_cost, max_cost, new_max_cost );
3251
3252 if ( new_max_cost == max_cost ) {
3253 if ( fast ) {
3254 FC_DEBUG( " cannot shrink cache, slowing timer" );
3255
3256 killTimer( timer_id );
3257 timer_id = startTimer( slow_timeout );
3258 fast = FALSE;
3259 }
3260
3261 return;
3262 } else if ( ! fast ) {
3263 FC_DEBUG( " dropping into passing gear" );
3264
3265 killTimer( timer_id );
3266 timer_id = startTimer( fast_timeout );
3267 fast = TRUE;
3268 }
3269
3270 max_cost = new_max_cost;
3271
3272 {
3273 FC_DEBUG( " CLEAN engine data:" );
3274
3275 // clean out all unused engine datas
3276 EngineDataCache::Iterator it = engineDataCache.begin(),
3277 end = engineDataCache.end();
3278 while ( it != end ) {
3279 if ( it.data()->count > 0 ) {
3280 ++it;
3281 continue;
3282 }
3283
3284 EngineDataCache::Iterator rem = it++;
3285
3286 decreaseCost( sizeof( QFontEngineData ) );
3287
3288 FC_DEBUG( " %p", rem.data() );
3289
3290 delete rem.data();
3291 engineDataCache.remove( rem );
3292 }
3293 }
3294
3295 // clean out the engine cache just enough to get below our new max cost
3296 uint current_cost;
3297 do {
3298 current_cost = total_cost;
3299
3300 EngineCache::Iterator it = engineCache.begin(),
3301 end = engineCache.end();
3302 // determine the oldest and least popular of the unused engines
3303 uint oldest = ~0;
3304 uint least_popular = ~0;
3305
3306 for ( ; it != end; ++it ) {
3307 if ( it.data().data->count > 0 ) continue;
3308
3309 if ( it.data().timestamp < oldest &&
3310 it.data().hits <= least_popular ) {
3311 oldest = it.data().timestamp;
3312 least_popular = it.data().hits;
3313 }
3314 }
3315
3316 FC_DEBUG( " oldest %u least popular %u", oldest, least_popular );
3317
3318 for ( it = engineCache.begin(); it != end; ++it ) {
3319 if ( it.data().data->count == 0 &&
3320 it.data().timestamp == oldest &&
3321 it.data().hits == least_popular)
3322 break;
3323 }
3324
3325 if ( it != end ) {
3326 FC_DEBUG( " %p: timestamp %4u hits %2u ref %2d/%2d, type '%s'",
3327 it.data().data, it.data().timestamp, it.data().hits,
3328 it.data().data->count, it.data().data->cache_count,
3329 it.data().data->name() );
3330
3331 if ( --it.data().data->cache_count == 0 ) {
3332 FC_DEBUG( " DELETE: last occurence in cache" );
3333
3334 decreaseCost( it.data().data->cache_cost );
3335 delete it.data().data;
3336 } else {
3337 /*
3338 this particular font engine is in the cache multiple
3339 times... set current_cost to zero, so that we can
3340 keep looping to get rid of all occurences
3341 */
3342 current_cost = 0;
3343 }
3344
3345 engineCache.remove( it );
3346 }
3347 } while ( current_cost != total_cost && total_cost > max_cost );
3348}
Note: See TracBrowser for help on using the repository browser.