source: trunk/src/kernel/qfontdatabase.cpp@ 8

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

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

  • Property svn:keywords set to Id
File size: 67.3 KB
Line 
1/****************************************************************************
2** $Id: qfontdatabase.cpp 8 2005-11-16 19:36:46Z dmik $
3**
4** Implementation of font database class.
5**
6** Created : 990603
7**
8** Copyright (C) 1999-2000 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#include "qfontdatabase.h"
39
40#ifndef QT_NO_FONTDATABASE
41
42#include <qtl.h>
43#include <qapplication.h>
44
45#include <private/qunicodetables_p.h>
46#include "qfontengine_p.h"
47
48#include <qcleanuphandler.h>
49
50#ifdef Q_WS_X11
51#include <locale.h>
52#endif
53#include <stdlib.h>
54
55// #define QFONTDATABASE_DEBUG
56#ifdef QFONTDATABASE_DEBUG
57# define FD_DEBUG qDebug
58#else
59# define FD_DEBUG if (FALSE) qDebug
60#endif
61
62// #define FONT_MATCH_DEBUG
63#ifdef FONT_MATCH_DEBUG
64# define FM_DEBUG qDebug
65#else
66# define FM_DEBUG if (FALSE) qDebug
67#endif
68
69#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
70# define for if(0){}else for
71#endif
72
73#define SMOOTH_SCALABLE 0xffff
74
75static int ucstricmp( const QString &as, const QString &bs )
76{
77 const QChar *a = as.unicode();
78 const QChar *b = bs.unicode();
79 if ( a == b )
80 return 0;
81 if ( a == 0 )
82 return 1;
83 if ( b == 0 )
84 return -1;
85 int l=QMIN(as.length(),bs.length());
86 while ( l-- && ::lower( *a ) == ::lower( *b ) )
87 a++,b++;
88 if ( l==-1 )
89 return ( as.length()-bs.length() );
90 return ::lower( *a ).unicode() - ::lower( *b ).unicode();
91}
92
93static int getFontWeight( const QString &weightString )
94{
95 QString s = weightString.lower();
96
97 // Test in decreasing order of commonness
98 if (s == "medium" ||
99 s == "normal")
100 return QFont::Normal;
101 if (s == "bold")
102 return QFont::Bold;
103 if (s == "demibold" || s == "demi bold")
104 return QFont::DemiBold;
105 if (s == "black")
106 return QFont::Black;
107 if (s == "light")
108 return QFont::Light;
109
110 if (s.contains("bold")) {
111 if (s.contains("demi"))
112 return (int) QFont::DemiBold;
113 return (int) QFont::Bold;
114 }
115
116 if (s.contains("light"))
117 return (int) QFont::Light;
118
119 if (s.contains("black"))
120 return (int) QFont::Black;
121
122 return (int) QFont::Normal;
123}
124
125#ifdef Q_WS_X11
126struct QtFontEncoding
127{
128 signed int encoding : 16;
129
130 uint xpoint : 16;
131 uint xres : 8;
132 uint yres : 8;
133 uint avgwidth : 16;
134 uchar pitch : 8;
135};
136#endif // Q_WS_X11
137
138struct QtFontSize
139{
140 unsigned short pixelSize;
141
142#ifdef Q_WS_PM
143 unsigned short pointSize; // in deca-points
144 LONG lMatch;
145#endif
146#ifdef Q_WS_X11
147 int count;
148 QtFontEncoding *encodings;
149 QtFontEncoding *encodingID( int id, uint xpoint = 0, uint xres = 0,
150 uint yres = 0, uint avgwidth = 0, bool add = FALSE);
151#endif // Q_WS_X11
152};
153
154
155#ifdef Q_WS_X11
156QtFontEncoding *QtFontSize::encodingID( int id, uint xpoint, uint xres,
157 uint yres, uint avgwidth, bool add )
158{
159 // we don't match using the xpoint, xres and yres parameters, only the id
160 for ( int i = 0; i < count; ++i ) {
161 if ( encodings[i].encoding == id )
162 return encodings + i;
163 }
164
165 if ( !add ) return 0;
166
167 if ( !(count % 4) )
168 encodings = ( QtFontEncoding * )
169 realloc( encodings,
170 (((count+4) >> 2 ) << 2 ) * sizeof( QtFontEncoding ) );
171 encodings[count].encoding = id;
172 encodings[count].xpoint = xpoint;
173 encodings[count].xres = xres;
174 encodings[count].yres = yres;
175 encodings[count].avgwidth = avgwidth;
176 encodings[count].pitch = '*';
177 return encodings + count++;
178}
179#endif // Q_WS_X11
180
181struct QtFontStyle
182{
183 struct Key {
184 Key( const QString &styleString );
185 Key() : italic( FALSE ), oblique( FALSE ),
186 weight( QFont::Normal ), stretch( 0 ) { }
187 Key( const Key &o ) : italic( o.italic ), oblique( o.oblique ),
188 weight( o.weight ), stretch( o.stretch ) { }
189 uint italic : 1;
190 uint oblique : 1;
191 signed int weight : 8;
192 signed int stretch : 12;
193
194 bool operator==( const Key & other ) {
195 return ( italic == other.italic &&
196 oblique == other.oblique &&
197 weight == other.weight &&
198 (stretch == 0 || other.stretch == 0 || stretch == other.stretch) );
199 }
200 bool operator!=( const Key &other ) {
201 return !operator==(other);
202 }
203 bool operator <( const Key &o ) {
204 int x = (italic << 13) + (oblique << 12) + (weight << 14) + stretch;
205 int y = (o.italic << 13) + (o.oblique << 12) + (o.weight << 14) + o.stretch;
206 return ( x < y );
207 }
208 };
209
210 QtFontStyle( const Key &k )
211 : key( k ), bitmapScalable( FALSE ), smoothScalable( FALSE ),
212 fakeOblique( FALSE ), count( 0 ), pixelSizes( 0 )
213 {
214#if defined(Q_WS_PM)
215 szFacename[0] = 0;
216#elif defined(Q_WS_X11)
217 weightName = setwidthName = 0;
218#endif
219 }
220
221 ~QtFontStyle() {
222#ifdef Q_WS_X11
223 delete [] weightName;
224 delete [] setwidthName;
225 while ( count-- )
226 free(pixelSizes[count].encodings);
227#endif
228 free( pixelSizes );
229 }
230
231 Key key;
232 bool bitmapScalable : 1;
233 bool smoothScalable : 1;
234 bool fakeOblique : 1;
235 int count : 29;
236 QtFontSize *pixelSizes;
237
238#ifdef Q_WS_PM
239 CHAR szFacename [FACESIZE];
240#endif
241#ifdef Q_WS_X11
242 const char *weightName;
243 const char *setwidthName;
244#endif // Q_WS_X11
245
246#ifdef Q_WS_PM
247 QtFontSize *pixelSize(
248 unsigned short size, bool = FALSE, unsigned short pointSize = 0 );
249#else
250 QtFontSize *pixelSize( unsigned short size, bool = FALSE );
251#endif
252};
253
254QtFontStyle::Key::Key( const QString &styleString )
255 : italic( FALSE ), oblique( FALSE ), weight( QFont::Normal ), stretch( 0 )
256{
257 weight = getFontWeight( styleString );
258
259 if ( styleString.contains( "Italic" ) )
260 italic = TRUE;
261 else if ( styleString.contains( "Oblique" ) )
262 oblique = TRUE;
263}
264
265#ifdef Q_WS_PM
266QtFontSize *QtFontStyle::pixelSize(
267 unsigned short size, bool add, unsigned short pointSize )
268#else
269QtFontSize *QtFontStyle::pixelSize( unsigned short size, bool add )
270#endif
271{
272 for ( int i = 0; i < count; i++ ) {
273#ifdef Q_WS_PM
274 if (
275 pixelSizes[i].pixelSize == size &&
276 (
277 size == SMOOTH_SCALABLE ||
278 !pointSize ||
279 pixelSizes[i].pointSize == pointSize
280 )
281 )
282#else
283 if ( pixelSizes[i].pixelSize == size )
284#endif
285 return pixelSizes + i;
286 }
287 if ( !add )
288 return 0;
289
290 if ( !(count % 8) )
291 pixelSizes = (QtFontSize *)
292 realloc( pixelSizes,
293 (((count+8) >> 3 ) << 3) * sizeof(QtFontSize) );
294 pixelSizes[count].pixelSize = size;
295#ifdef Q_WS_PM
296 pixelSizes[count].pointSize = pointSize;
297 pixelSizes[count].lMatch = 0;
298#endif
299#ifdef Q_WS_X11
300 pixelSizes[count].count = 0;
301 pixelSizes[count].encodings = 0;
302#endif
303 return pixelSizes + (count++);
304}
305
306struct QtFontFoundry
307{
308 QtFontFoundry( const QString &n ) : name( n ), count( 0 ), styles( 0 ) {}
309 ~QtFontFoundry() {
310 while ( count-- )
311 delete styles[count];
312 free( styles );
313 }
314
315 QString name;
316
317 int count;
318 QtFontStyle **styles;
319 QtFontStyle *style( const QtFontStyle::Key &, bool = FALSE );
320};
321
322QtFontStyle *QtFontFoundry::style( const QtFontStyle::Key &key, bool create )
323{
324 int pos = 0;
325 if ( count ) {
326 int low = 0;
327 int high = count;
328 pos = count / 2;
329 while ( high > low ) {
330 if ( styles[pos]->key == key )
331 return styles[pos];
332 if ( styles[pos]->key < key )
333 low = pos + 1;
334 else
335 high = pos;
336 pos = (high + low) / 2;
337 };
338 pos = low;
339 }
340 if ( !create )
341 return 0;
342
343// qDebug("adding key (weight=%d, italic=%d, oblique=%d stretch=%d) at %d", key.weight, key.italic, key.oblique, key.stretch, pos );
344 if ( !(count % 8) )
345 styles = (QtFontStyle **)
346 realloc( styles, (((count+8) >> 3 ) << 3) * sizeof( QtFontStyle * ) );
347
348 memmove( styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *) );
349 styles[pos] = new QtFontStyle( key );
350 count++;
351 return styles[pos];
352}
353
354
355struct QtFontFamily
356{
357 enum ScriptStatus { Unknown = 0, Supported = 1,
358 UnSupported_Xft= 2, UnSupported_Xlfd = 4, UnSupported = 6 };
359
360 QtFontFamily(const QString &n )
361 : fixedPitch( FALSE ),
362#ifdef Q_WS_X11
363 hasXft( FALSE ), xftScriptCheck( FALSE ), xlfdLoaded( FALSE ),
364#endif
365#ifdef Q_WS_WIN
366 scriptCheck( FALSE ),
367#endif
368#if defined(Q_OS_MAC) && !defined(QWS)
369 fixedPitchComputed(FALSE),
370#endif
371 fullyLoaded( FALSE ),
372 name( n ), count( 0 ), foundries( 0 ) {
373 memset( scripts, 0, sizeof( scripts ) );
374#ifdef Q_WS_PM
375//@@TODO (dmik): temporary solution to let QFontDialog work:
376// at least UnknownScript is supported.
377 scripts[QFont::UnknownScript] = Supported;
378#endif
379 }
380 ~QtFontFamily() {
381 while ( count-- )
382 delete foundries[count];
383 free( foundries );
384 }
385
386 bool fixedPitch : 1;
387#ifdef Q_WS_X11
388 bool hasXft : 1;
389 bool xftScriptCheck : 1;
390 bool xlfdLoaded : 1;
391#endif
392#ifdef Q_WS_WIN
393 bool scriptCheck : 1;
394#endif
395#if defined(Q_OS_MAC) && !defined(QWS)
396 bool fixedPitchComputed : 1;
397#endif
398 bool fullyLoaded : 1;
399 QString name;
400#ifndef Q_WS_X11
401 QString rawName;
402#endif
403#ifdef Q_WS_X11
404 QCString fontFilename;
405 int fontFileIndex;
406#endif
407 int count;
408 QtFontFoundry **foundries;
409
410 unsigned char scripts[QFont::LastPrivateScript];
411
412 QtFontFoundry *foundry( const QString &f, bool = FALSE );
413};
414
415QtFontFoundry *QtFontFamily::foundry( const QString &f, bool create )
416{
417 if ( f.isNull() && count == 1 )
418 return foundries[0];
419
420 for ( int i = 0; i < count; i++ ) {
421 if ( ucstricmp( foundries[i]->name, f ) == 0 )
422 return foundries[i];
423 }
424 if ( !create )
425 return 0;
426
427 if ( !(count % 8) )
428 foundries = (QtFontFoundry **)
429 realloc( foundries,
430 (((count+8) >> 3 ) << 3) * sizeof( QtFontFoundry * ) );
431
432 foundries[count] = new QtFontFoundry( f );
433 return foundries[count++];
434}
435
436class QFontDatabasePrivate {
437public:
438 QFontDatabasePrivate() :
439 count( 0 ), families( 0 ) { }
440 ~QFontDatabasePrivate() {
441#ifdef Q_WS_PM
442 cleanup();
443#else
444 while ( count-- )
445 delete families[count];
446 free( families );
447#endif
448 }
449 QtFontFamily *family( const QString &f, bool = FALSE );
450
451 int count;
452 QtFontFamily **families;
453
454#ifdef Q_WS_PM
455 static QFontDatabasePrivate* instance();
456private:
457 void cleanup() {
458 while ( count )
459 delete families[--count];
460 free( families );
461 families = 0;
462 }
463 void reload();
464#endif
465};
466
467QtFontFamily *QFontDatabasePrivate::family( const QString &f, bool create )
468{
469 int low = 0;
470 int high = count;
471 int pos = count / 2;
472 int res = 1;
473 if ( count ) {
474 while ( (res = ucstricmp( families[pos]->name, f )) && pos != low ) {
475 if ( res > 0 )
476 high = pos;
477 else
478 low = pos;
479 pos = (high + low) / 2;
480 };
481 if ( !res )
482 return families[pos];
483 }
484 if ( !create )
485 return 0;
486
487 if ( res < 0 )
488 pos++;
489
490 // qDebug("adding family %s at %d total=%d", f.latin1(), pos, count);
491 if ( !(count % 8) )
492 families = (QtFontFamily **)
493 realloc( families,
494 (((count+8) >> 3 ) << 3) * sizeof( QtFontFamily * ) );
495
496 memmove( families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *) );
497 families[pos] = new QtFontFamily( f );
498 count++;
499 return families[pos];
500}
501
502
503
504
505#if defined(Q_WS_X11) || defined(Q_WS_WIN)
506static const unsigned short sample_chars[QFont::LastPrivateScript] =
507{
508 // European Alphabetic Scripts
509 // Latin,
510 0x0041,
511 // Greek,
512 0x0390,
513 // Cyrillic,
514 0x0410,
515 // Armenian,
516 0x0540,
517 // Georgian,
518 0x10d0,
519 // Runic,
520 0x16a0,
521 // Ogham,
522 0x1680,
523 // SpacingModifiers,
524 0x02b0,
525 // CombiningMarks,
526 0x0300,
527
528 // Middle Eastern Scripts
529 // Hebrew,
530 0x05d0,
531 // Arabic,
532 0x0630,
533 // Syriac,
534 0x0710,
535 // Thaana,
536 0x0780,
537
538 // South and Southeast Asian Scripts
539 // Devanagari,
540 0x0910,
541 // Bengali,
542 0x0990,
543 // Gurmukhi,
544 0x0a10,
545 // Gujarati,
546 0x0a90,
547 // Oriya,
548 0x0b10,
549 // Tamil,
550 0x0b90,
551 // Telugu,
552 0x0c10,
553 // Kannada,
554 0x0c90,
555 // Malayalam,
556 0x0d10,
557 // Sinhala,
558 0x0d90,
559 // Thai,
560 0x0e10,
561 // Lao,
562 0x0e81,
563 // Tibetan,
564 0x0f00,
565 // Myanmar,
566 0x1000,
567 // Khmer,
568 0x1780,
569
570 // East Asian Scripts
571 // Han,
572 0x4e00,
573 // Hiragana,
574 0x3050,
575 // Katakana,
576 0x30b0,
577 // Hangul,
578 0xac00,
579 // Bopomofo,
580 0x3110,
581 // Yi,
582 0xa000,
583
584 // Additional Scripts
585 // Ethiopic,
586 0x1200,
587 // Cherokee,
588 0x13a0,
589 // CanadianAboriginal,
590 0x1410,
591 // Mongolian,
592 0x1800,
593
594 // Symbols
595 // CurrencySymbols,
596 0x20aa,
597 // LetterlikeSymbols,
598 0x2122,
599 // NumberForms,
600 0x215b,
601 // MathematicalOperators,
602 0x222b,
603 // TechnicalSymbols,
604 0x2440,
605 // GeometricSymbols,
606 0x2500,
607 // MiscellaneousSymbols,
608 0x2600,
609 // EnclosedAndSquare,
610 0x2460,
611 // Braille,
612 0x2800,
613
614 // Unicode,
615 0xfffd,
616
617 // some scripts added in Unicode 3.2
618 // Tagalog,
619 0x1700,
620 // Hanunoo,
621 0x1720,
622 // Buhid,
623 0x1740,
624 // Tagbanwa,
625 0x1770,
626
627 // KatakanaHalfWidth
628 0xff65,
629
630 // Limbu
631 0x1901,
632 // TaiLe
633 0x1950,
634
635 // NScripts
636 0x0000,
637 // NoScript
638 0x0000,
639
640 // Han_Japanese
641 0x4e00,
642 // Han_SimplifiedChinese,
643 0x4e00,
644 // Han_TraditionalChinese,
645 0x4e00,
646 // Han_Korean
647 0x4e00
648};
649
650#if defined(Q_WS_X11) && !defined(QT_NO_XFTFREETYPE)
651static inline bool requiresOpenType(QFont::Script s)
652{
653 return (s >= QFont::Syriac && s <= QFont::Sinhala)
654 || (s >= QFont::Tibetan && s <= QFont::Khmer);
655}
656#endif
657
658// returns a sample unicode character for the specified script
659static QChar sampleCharacter(QFont::Script script)
660{
661 return QChar(sample_chars[script]);
662}
663
664static inline bool canRender( QFontEngine *fe, QFont::Script script )
665{
666 if ( !fe ) return FALSE;
667
668 QChar sample = sampleCharacter(script);
669 bool hasChar = fe->canRender( &sample, 1 );
670
671#ifdef FONT_MATCH_DEBUG
672 if (hasChar)
673 FM_DEBUG(" font has char 0x%04x", sample.unicode() );
674#endif
675#if defined(Q_WS_X11) && !defined(QT_NO_XFTFREETYPE)
676 if (hasChar && requiresOpenType(script)) {
677 QOpenType *ot = fe->openType();
678 if (!ot || !ot->supportsScript(script))
679 return false;
680 }
681#endif
682
683 return hasChar;
684}
685#endif // Q_WS_X11 || Q_WS_WIN
686
687
688static QSingleCleanupHandler<QFontDatabasePrivate> qfontdatabase_cleanup;
689#ifdef Q_WS_PM
690QFontDatabasePrivate* QFontDatabasePrivate::instance()
691{
692 static QFontDatabasePrivate *db = 0;
693 if ( !db ) {
694 db = new QFontDatabasePrivate;
695 qfontdatabase_cleanup.set(&db);
696 db->reload();
697 }
698 return db;
699}
700#else
701static QFontDatabasePrivate *db=0;
702#endif
703
704#if defined( Q_WS_X11 )
705# include "qfontdatabase_x11.cpp"
706#elif defined( Q_WS_MAC )
707# include "qfontdatabase_mac.cpp"
708#elif defined( Q_WS_WIN )
709# include "qfontdatabase_win.cpp"
710#elif defined( Q_WS_PM )
711# include "qfontdatabase_pm.cpp"
712#elif defined( Q_WS_QWS )
713# include "qfontdatabase_qws.cpp"
714#endif
715
716
717
718
719#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_PM)
720static
721unsigned int bestFoundry( QFont::Script script, unsigned int score, int styleStrategy,
722 const QtFontFamily *family, const QString &foundry_name,
723 QtFontStyle::Key styleKey, int pixelSize, char pitch,
724 QtFontFoundry **best_foundry, QtFontStyle **best_style,
725 QtFontSize **best_size
726#if defined(Q_WS_X11)
727 , QtFontEncoding **best_encoding, int force_encoding_id
728#elif defined(Q_WS_PM)
729 , int pointSize
730#endif
731 )
732{
733 Q_UNUSED( script );
734 Q_UNUSED( pitch );
735
736 FM_DEBUG( " REMARK: looking for best foundry for family '%s'", family->name.latin1() );
737
738 for ( int x = 0; x < family->count; ++x ) {
739 QtFontFoundry *foundry = family->foundries[x];
740 if ( ! foundry_name.isEmpty() &&
741 ucstricmp( foundry->name, foundry_name ) != 0 )
742 continue;
743
744 FM_DEBUG( " looking for matching style in foundry '%s'",
745 foundry->name.isEmpty() ? "-- none --" : foundry->name.latin1() );
746
747 QtFontStyle *style = 0;
748 int best = 0;
749 int dist = 0xffff;
750
751 for ( int i = 0; i < foundry->count; i++ ) {
752 style = foundry->styles[i];
753
754 int d = QABS( styleKey.weight - style->key.weight );
755
756 if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
757 d += QABS( styleKey.stretch - style->key.stretch );
758 }
759
760 if ( styleKey.italic ) {
761 if ( !style->key.italic )
762 d += style->key.oblique ? 0x0800 : 0x1000;
763 } else if ( styleKey.oblique ) {
764 if (!style->key.oblique )
765 d += style->key.italic ? 0x0800 : 0x1000;
766 } else if ( style->key.italic || style->key.oblique ) {
767 d += 0x1000;
768 }
769
770 if ( d < dist ) {
771 best = i;
772 dist = d;
773 }
774 }
775
776 FM_DEBUG( " best style has distance 0x%x", dist );
777 style = foundry->styles[best];
778
779 if ( ! style->smoothScalable && ( styleStrategy & QFont::ForceOutline ) ) {
780 FM_DEBUG( " ForceOutline set, but not smoothly scalable" );
781 continue;
782 }
783
784 int px = -1;
785 QtFontSize *size = 0;
786
787 // 1. see if we have an exact matching size
788 if (! (styleStrategy & QFont::ForceOutline)) {
789#if defined(Q_WS_PM)
790 size = style->pixelSize(pixelSize, FALSE, pointSize);
791#else
792 size = style->pixelSize(pixelSize);
793#endif
794 if (size) px = size->pixelSize;
795 }
796
797 // 2. see if we have a smoothly scalable font
798 if (! size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
799 size = style->pixelSize(SMOOTH_SCALABLE);
800 if (size) px = pixelSize;
801 }
802
803 // 3. see if we have a bitmap scalable font
804 if (! size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
805 size = style->pixelSize(0);
806 if (size) px = pixelSize;
807 }
808
809 // 4. find closest size match
810 if (! size) {
811 unsigned int distance = ~0u;
812 for (int x = 0; x < style->count; ++x) {
813 unsigned int d = QABS(style->pixelSizes[x].pixelSize - pixelSize);
814 if (d < distance) {
815 distance = d;
816 size = style->pixelSizes + x;
817 }
818 }
819
820 if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
821 (distance * 10 / pixelSize) >= 2) {
822 // the closest size is not close enough, go ahead and
823 // use a bitmap scaled font
824 size = style->pixelSize(0);
825 px = pixelSize;
826 } else {
827 px = size->pixelSize;
828 }
829 }
830
831#ifdef Q_WS_X11
832 QtFontEncoding *encoding = 0;
833 if ( force_encoding_id >= 0 ) {
834 encoding = size->encodingID( force_encoding_id );
835 if ( ! encoding ) {
836 FM_DEBUG( " required encoding_id not available" );
837 continue;
838 }
839 } else {
840 encoding = size->encodingID( -1 ); // -1 == prefer Xft
841
842 if ( encoding && ( styleStrategy & ( QFont::OpenGLCompatible |
843 QFont::PreferBitmap ) ) ) {
844 FM_DEBUG( " PreferBitmap and/or OpenGL set, skipping Xft" );
845 continue;
846 }
847
848 if ( ! encoding ) { // Xft not available, find an XLFD font
849 // try the default encoding first
850 encoding = size->encodingID( QFontPrivate::defaultEncodingID );
851
852 if ( ! encoding || ! scripts_for_xlfd_encoding[encoding->encoding][script] ) {
853 // find the first encoding that supports the requested script
854 encoding = 0;
855 for (int x = 0; !encoding && x < size->count; ++x ) {
856 const int enc = size->encodings[x].encoding;
857 if ( scripts_for_xlfd_encoding[enc][script] ) {
858 encoding = &size->encodings[x];
859 break;
860 }
861 }
862 }
863 }
864 }
865
866 if ( ! encoding ) {
867 FM_DEBUG( " foundry doesn't support the script we want" );
868 continue;
869 }
870#endif // Q_WS_X11
871
872 unsigned int this_score = 0x0000;
873#ifdef Q_WS_X11
874 if ( encoding->encoding != -1 ) {
875 this_score += 1;
876 if ( encoding->encoding != QFontPrivate::defaultEncodingID )
877 this_score += 10;
878 }
879 if (pitch != '*') {
880 if ( !( pitch == 'm' && encoding->pitch == 'c' ) && pitch != encoding->pitch )
881 this_score += 200;
882 }
883#else
884 if (pitch != '*') {
885 if ((pitch == 'm' && !family->fixedPitch)
886 || (pitch == 'p' && family->fixedPitch))
887 this_score += 200;
888 }
889#endif
890 if ( styleKey != style->key )
891 this_score += 100;
892 if ( !style->smoothScalable && px != size->pixelSize ) // bitmap scaled
893 this_score += 50;
894
895 if ( this_score < score ) {
896 FM_DEBUG( " found a match: score %u best score so far %u",
897 this_score, score );
898
899 score = this_score;
900 *best_foundry = foundry;
901 *best_style = style;
902 *best_size = size;
903#ifdef Q_WS_X11
904 *best_encoding = encoding;
905#endif // Q_WS_X11
906 } else {
907 FM_DEBUG( " score %u no better than best %u", this_score, score);
908 }
909 }
910
911 return score;
912}
913
914/*!
915 \internal
916*/
917QFontEngine *
918QFontDatabase::findFont( QFont::Script script, const QFontPrivate *fp,
919 const QFontDef &request, int force_encoding_id )
920{
921#ifndef Q_WS_X11
922 Q_UNUSED( force_encoding_id );
923#endif
924
925#ifdef Q_WS_PM
926 QFontDatabasePrivate *db = QFontDatabasePrivate::instance();
927#else
928 if ( !db )
929 initializeDb();
930#endif
931
932 QFontEngine *fe = 0;
933 if ( fp ) {
934#ifndef Q_WS_PM
935 if ( fp->rawMode ) {
936 fe = loadEngine( script, fp, request, 0, 0, 0
937#ifdef Q_WS_X11
938 , 0, 0, FALSE
939#endif
940 );
941
942 // if we fail to load the rawmode font, use a 12pixel box engine instead
943 if (! fe) fe = new QFontEngineBox( 12 );
944 return fe;
945 }
946#endif // !Q_WS_PM
947
948 QFontCache::Key key( request, script,
949#if defined(Q_WS_WIN) || defined(Q_WS_PM)
950 (int)fp->paintdevice
951#else
952 fp->screen
953#endif
954 );
955 fe = QFontCache::instance->findEngine( key );
956 if ( fe ) return fe;
957 }
958
959 QString family_name, foundry_name;
960 QtFontStyle::Key styleKey;
961 styleKey.italic = request.italic;
962 styleKey.weight = request.weight;
963 styleKey.stretch = request.stretch;
964 char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
965
966 parseFontName( request.family, foundry_name, family_name );
967
968#ifdef Q_WS_PM
969 // the "System VIO" PM font is broken in such way that its real pixel
970 // sizes do not correspond to their nominal point sizes specified in the
971 // font header (i.e. pixelSize is not equal to (pointSize * dpi) / 720).
972 // therefore we use the special table to convert pointSize to pixelSize
973 // in order to let bestFoundry() select the proper font with its nominal
974 // point size corresponding to the requested one.
975 // NOTE: this will produce incorrect results if "System VIO" is NOT
976 // an OS/2 standatd supplied bitmap font.
977 if( !ucstricmp( family_name, "System VIO") ) {
978 // possible sizes of the "System VIO" font ("pixel, point" pairs),
979 // sorted by point size
980 static const short SystemVIO_sz[] = {
981 12, 20, 16, 30,
982 8, 40, 13, 50,
983 15, 60, 24, 70,
984 8, 80, 10, 90,
985 12, 100, 14, 110,
986 16, 120, 18, 130,
987 16, 140, 12, 150,
988 20, 160, 21, 170,
989 29, 180,
990 };
991 const int SystemVIO_sz_len = sizeof(SystemVIO_sz) / sizeof(SystemVIO_sz[0]);
992 int pt = request.pointSize;
993 pt = QMAX( pt, SystemVIO_sz [1] ); // min limit
994 pt = QMIN( pt, SystemVIO_sz [SystemVIO_sz_len - 1] ); // max limit
995 int i = 1;
996 while ( SystemVIO_sz[i] < pt ) i += 2;
997 if ( SystemVIO_sz[i] > pt ) {
998 int prev = SystemVIO_sz[i-2];
999 int mid = prev + (SystemVIO_sz[i] - prev + 1) / 2;
1000 if ( pt < mid ) i -= 2;
1001 }
1002 ((QFontDef&)request).pixelSize = SystemVIO_sz[i-1];
1003 ((QFontDef&)request).pointSize = SystemVIO_sz[i];
1004 }
1005#endif
1006
1007#ifdef Q_WS_X11
1008 if (family_name.isEmpty() && script == QFont::Han) {
1009 // modify script according to locale
1010 static QFont::Script defaultHan = QFont::UnknownScript;
1011 if (defaultHan == QFont::UnknownScript) {
1012 QCString locale = setlocale(LC_ALL, NULL);
1013 if (locale.contains("ko"))
1014 defaultHan = QFont::Han_Korean;
1015 else if (locale.contains("zh_TW"))
1016 defaultHan = QFont::Han_TraditionalChinese;
1017 else if (locale.contains("zh"))
1018 defaultHan = QFont::Han_SimplifiedChinese;
1019 else
1020 defaultHan = QFont::Han_Japanese;
1021 }
1022 script = defaultHan;
1023 }
1024#endif
1025
1026 FM_DEBUG( "QFontDatabase::findFont\n"
1027 " request:\n"
1028 " family: %s [%s], script: %d (%s)\n"
1029 " weight: %d, italic: %d\n"
1030 " stretch: %d\n"
1031 " pixelSize: %d\n"
1032 " pointSize: %d\n"
1033 " pitch: %c",
1034 family_name.isEmpty() ? "-- first in script --" : family_name.latin1(),
1035 foundry_name.isEmpty() ? "-- any --" : foundry_name.latin1(),
1036 script, scriptName( script ).latin1(),
1037 request.weight, request.italic, request.stretch,
1038 request.pixelSize, request.pointSize,
1039 pitch );
1040
1041#ifdef QT_XFT2
1042 if (family_name.isEmpty()
1043 || family_name == "Sans Serif"
1044 || family_name == "Serif"
1045 || family_name == "Monospace") {
1046 fe = loadFontConfigFont(fp, request, script);
1047 }
1048 if (!fe)
1049#endif
1050 {
1051 QtFontFamily *best_family = 0;
1052 QtFontFoundry *best_foundry = 0;
1053 QtFontStyle *best_style = 0;
1054 QtFontSize *best_size = 0;
1055#ifdef Q_WS_X11
1056 QtFontEncoding *best_encoding = 0;
1057#endif // Q_WS_X11
1058
1059 unsigned int score = ~0;
1060
1061 load( family_name, script );
1062
1063 for ( int x = 0; x < db->count; ++x ) {
1064 QtFontFamily *try_family = db->families[x];
1065 if ( !family_name.isEmpty() &&
1066 ucstricmp( try_family->name, family_name ) != 0 )
1067 continue;
1068
1069 if ( family_name.isEmpty() )
1070 load( try_family->name, script );
1071
1072 uint score_adjust = 0;
1073 QFont::Script override_script = script;
1074#ifndef Q_WS_PM
1075 if ( ! ( try_family->scripts[script] & QtFontFamily::Supported )
1076 && script != QFont::Unicode) {
1077 // family not supported in the script we want
1078#ifdef Q_WS_X11
1079 if (script >= QFont::Han_Japanese && script <= QFont::Han_Korean
1080 && try_family->scripts[QFont::Han] == QtFontFamily::Supported) {
1081 // try with the han script instead, give it a penalty
1082 if (override_script == QFont::Han_TraditionalChinese
1083 && (try_family->scripts[QFont::Han_SimplifiedChinese] & QtFontFamily::Supported)) {
1084 override_script = QFont::Han_SimplifiedChinese;
1085 score_adjust = 200;
1086 } else if (override_script == QFont::Han_SimplifiedChinese
1087 && (try_family->scripts[QFont::Han_TraditionalChinese] & QtFontFamily::Supported)) {
1088 override_script = QFont::Han_TraditionalChinese;
1089 score_adjust = 200;
1090 } else {
1091 override_script = QFont::Han;
1092 score_adjust = 400;
1093 }
1094 } else
1095#endif
1096 if (family_name.isEmpty()) {
1097 continue;
1098 } else if (try_family->scripts[QFont::UnknownScript] & QtFontFamily::Supported) {
1099 // try with the unknown script (for a symbol font)
1100 override_script = QFont::UnknownScript;
1101 } else if (try_family->scripts[QFont::Unicode] & QtFontFamily::Supported) {
1102 // try with the unicode script instead
1103 override_script = QFont::Unicode;
1104 } else {
1105 // family not supported by unicode/unknown scripts
1106 continue;
1107 }
1108 }
1109#endif // !Q_WS_PM
1110
1111 QtFontFoundry *try_foundry = 0;
1112 QtFontStyle *try_style = 0;
1113 QtFontSize *try_size = 0;
1114#ifdef Q_WS_X11
1115 QtFontEncoding *try_encoding = 0;
1116#endif // Q_WS_X11
1117
1118 // as we know the script is supported, we can be sure
1119 // to find a matching font here.
1120 unsigned int newscore =
1121 bestFoundry( override_script, score, request.styleStrategy,
1122 try_family, foundry_name, styleKey, request.pixelSize, pitch,
1123 &try_foundry, &try_style, &try_size
1124#if defined(Q_WS_X11)
1125 , &try_encoding, force_encoding_id
1126#elif defined(Q_WS_PM)
1127 , request.pointSize
1128#endif
1129 );
1130 if ( try_foundry == 0 ) {
1131 // the specific foundry was not found, so look for
1132 // any foundry matching our requirements
1133 newscore = bestFoundry( override_script, score, request.styleStrategy, try_family,
1134 QString::null, styleKey, request.pixelSize,
1135 pitch, &try_foundry, &try_style, &try_size
1136#if defined(Q_WS_X11)
1137 , &try_encoding, force_encoding_id
1138#elif defined(Q_WS_PM)
1139 , request.pointSize
1140#endif
1141 );
1142 }
1143 newscore += score_adjust;
1144
1145 if ( newscore < score ) {
1146 score = newscore;
1147 best_family = try_family;
1148 best_foundry = try_foundry;
1149 best_style = try_style;
1150 best_size = try_size;
1151#ifdef Q_WS_X11
1152 best_encoding = try_encoding;
1153#endif // Q_WS_X11
1154 }
1155 if ( newscore < 10 ) // xlfd instead of xft... just accept it
1156 break;
1157 }
1158
1159 if ( best_family != 0 && best_foundry != 0 && best_style != 0
1160#ifdef Q_WS_X11
1161 && best_size != 0 && best_encoding != 0
1162#endif
1163 ) {
1164 FM_DEBUG( " BEST:\n"
1165 " family: %s [%s]\n"
1166 " weight: %d, italic: %d, oblique: %d\n"
1167 " stretch: %d\n"
1168 " pixelSize: %d\n"
1169 " pitch: %c\n"
1170 " encoding: %d\n",
1171 best_family->name.latin1(),
1172 best_foundry->name.isEmpty() ? "-- none --" : best_foundry->name.latin1(),
1173 best_style->key.weight, best_style->key.italic, best_style->key.oblique,
1174 best_style->key.stretch, best_size ? best_size->pixelSize : 0xffff,
1175#ifdef Q_WS_X11
1176 best_encoding->pitch, best_encoding->encoding
1177#else
1178 'p', 0
1179#endif
1180 );
1181
1182 fe = loadEngine( script, fp, request, best_family, best_foundry, best_style
1183#if defined(Q_WS_PM)
1184 , best_size
1185#elif defined(Q_WS_X11)
1186 , best_size, best_encoding, ( force_encoding_id >= 0 )
1187#endif
1188 );
1189 }
1190 if (fe) {
1191 fe->fontDef.family = best_family->name;
1192 if ( ! best_foundry->name.isEmpty() ) {
1193 fe->fontDef.family += QString::fromLatin1( " [" );
1194 fe->fontDef.family += best_foundry->name;
1195 fe->fontDef.family += QString::fromLatin1( "]" );
1196 }
1197
1198#ifdef Q_WS_PM
1199 // On OS/2, fontDef.pixelSize and fontDef.pointSize are filled
1200 // by QFontEnginePM constructor
1201#else
1202 if ( best_style->smoothScalable )
1203 fe->fontDef.pixelSize = request.pixelSize;
1204 else if ( best_style->bitmapScalable &&
1205 ( request.styleStrategy & QFont::PreferMatch ) )
1206 fe->fontDef.pixelSize = request.pixelSize;
1207 else
1208 fe->fontDef.pixelSize = best_size->pixelSize;
1209
1210 if ( fp ) {
1211#if defined(Q_WS_X11)
1212 fe->fontDef.pointSize =
1213 qRound(10. * qt_pointSize(fe->fontDef.pixelSize, fp->paintdevice, fp->screen));
1214#elif defined(Q_WS_WIN)
1215 fe->fontDef.pointSize = int( double( fe->fontDef.pixelSize ) * 720.0 /
1216 GetDeviceCaps(shared_dc,LOGPIXELSY) );
1217#else
1218 fe->fontDef.pointSize = int( double( fe->fontDef.pixelSize ) * 720.0 /
1219 96.0 );
1220#endif
1221 } else {
1222 fe->fontDef.pointSize = request.pointSize;
1223 }
1224#endif
1225 fe->fontDef.styleHint = request.styleHint;
1226 fe->fontDef.styleStrategy = request.styleStrategy;
1227
1228 fe->fontDef.weight = best_style->key.weight;
1229 fe->fontDef.italic = best_style->key.italic || best_style->key.oblique;
1230 fe->fontDef.fixedPitch = best_family->fixedPitch;
1231 fe->fontDef.stretch = best_style->key.stretch;
1232 fe->fontDef.ignorePitch = FALSE;
1233 }
1234 }
1235
1236 if ( fe ) {
1237#ifdef Q_WS_PM
1238///@@TODO (dmik): should do something here?
1239#else
1240 if ( script != QFont::Unicode && !canRender( fe, script ) ) {
1241 FM_DEBUG( " WARN: font loaded cannot render sample 0x%04x",
1242 sampleCharacter(script).unicode() );
1243 delete fe;
1244
1245 if ( ! request.family.isEmpty() )
1246 return 0;
1247
1248 FM_DEBUG( "returning box engine" );
1249
1250 fe = new QFontEngineBox( request.pixelSize );
1251
1252 if ( fp
1253#ifdef Q_WS_WIN
1254 && !fp->paintdevice
1255#endif
1256 ) {
1257 QFontCache::Key key( request, script, fp->screen );
1258 QFontCache::instance->insertEngine( key, fe );
1259 }
1260
1261 return fe;
1262 }
1263#endif // !Q_WS_PM
1264
1265 if ( fp ) {
1266 QFontCache::Key key( request, script,
1267#if defined(Q_WS_WIN) || defined(Q_WS_PM)
1268 (int)fp->paintdevice
1269#else
1270 fp->screen
1271#endif
1272 );
1273 QFontCache::instance->insertEngine( key, fe );
1274
1275#ifndef Q_WS_PM
1276 for ( int i = 0; i < QFont::NScripts; ++i ) {
1277 if ( i == script ) continue;
1278
1279 if (!canRender(fe, (QFont::Script) i))
1280 continue;
1281
1282 key.script = i;
1283 QFontCache::instance->insertEngine( key, fe );
1284 }
1285#endif // !Q_WS_PM
1286 }
1287 } else {
1288 if ( request.family.isEmpty() ) {
1289#ifdef Q_WS_PM
1290//@@TODO (dmik): what to return in such case?
1291 qFatal( "QFontDatabase::findFont: request.family is empty and nothing is found, should it ever happen?" );
1292#else
1293 FM_DEBUG( "returning box engine" );
1294
1295 fe = new QFontEngineBox( request.pixelSize );
1296
1297 if ( fp ) {
1298 QFontCache::Key key( request, script,
1299#if defined(Q_WS_WIN) || defined(Q_WS_PM)
1300 (int)fp->paintdevice
1301#else
1302 fp->screen
1303#endif
1304 );
1305 QFontCache::instance->insertEngine( key, fe );
1306 }
1307#endif // Q_WS_PM
1308 }
1309 }
1310
1311 return fe;
1312}
1313#endif // Q_WS_X11 || Q_WS_WIN || Q_WS_PM
1314
1315
1316
1317
1318static QString styleString( int weight, bool italic, bool oblique )
1319{
1320 QString result;
1321 if ( weight >= QFont::Black )
1322 result = "Black";
1323 else if ( weight >= QFont::Bold )
1324 result = "Bold";
1325 else if ( weight >= QFont::DemiBold )
1326 result = "Demi Bold";
1327 else if ( weight < QFont::Normal )
1328 result = "Light";
1329
1330 if ( italic )
1331 result += " Italic";
1332 else if ( oblique )
1333 result += " Oblique";
1334
1335 if ( result.isEmpty() )
1336 result = "Normal";
1337
1338 return result.simplifyWhiteSpace();
1339}
1340
1341/*!
1342 Returns a string that describes the style of the font \a f. For
1343 example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1344 string may be returned.
1345*/
1346QString QFontDatabase::styleString( const QFont &f )
1347{
1348 // ### fix oblique here
1349 return ::styleString( f.weight(), f.italic(), FALSE );
1350}
1351
1352
1353/*!
1354 \class QFontDatabase qfontdatabase.h
1355 \brief The QFontDatabase class provides information about the fonts available in the underlying window system.
1356
1357 \ingroup environment
1358 \ingroup graphics
1359
1360 The most common uses of this class are to query the database for
1361 the list of font families() and for the pointSizes() and styles()
1362 that are available for each family. An alternative to pointSizes()
1363 is smoothSizes() which returns the sizes at which a given family
1364 and style will look attractive.
1365
1366 If the font family is available from two or more foundries the
1367 foundry name is included in the family name, e.g. "Helvetica
1368 [Adobe]" and "Helvetica [Cronyx]". When you specify a family you
1369 can either use the old hyphenated Qt 2.x "foundry-family" format,
1370 e.g. "Cronyx-Helvetica", or the new bracketed Qt 3.x "family
1371 [foundry]" format e.g. "Helvetica [Cronyx]". If the family has a
1372 foundry it is always returned, e.g. by families(), using the
1373 bracketed format.
1374
1375 The font() function returns a QFont given a family, style and
1376 point size.
1377
1378 A family and style combination can be checked to see if it is
1379 italic() or bold(), and to retrieve its weight(). Similarly we can
1380 call isBitmapScalable(), isSmoothlyScalable(), isScalable() and
1381 isFixedPitch().
1382
1383 A text version of a style is given by styleString().
1384
1385 The QFontDatabase class also supports some static functions, for
1386 example, standardSizes(). You can retrieve the Unicode 3.0
1387 description of a \link QFont::Script script\endlink using
1388 scriptName(), and a sample of characters in a script with
1389 scriptSample().
1390
1391 Example:
1392\code
1393#include <qapplication.h>
1394#include <qfontdatabase.h>
1395#include <else.h>
1396
1397int main( int argc, char **argv )
1398{
1399 QApplication app( argc, argv );
1400 QFontDatabase fdb;
1401 QStringList families = fdb.families();
1402 for ( QStringList::Iterator f = families.begin(); f != families.end(); ++f ) {
1403 QString family = *f;
1404 qDebug( family );
1405 QStringList styles = fdb.styles( family );
1406 for ( QStringList::Iterator s = styles.begin(); s != styles.end(); ++s ) {
1407 QString style = *s;
1408 QString dstyle = "\t" + style + " (";
1409 QValueList<int> smoothies = fdb.smoothSizes( family, style );
1410 for ( QValueList<int>::Iterator points = smoothies.begin();
1411 points != smoothies.end(); ++points ) {
1412 dstyle += QString::number( *points ) + " ";
1413 }
1414 dstyle = dstyle.left( dstyle.length() - 1 ) + ")";
1415 qDebug( dstyle );
1416 }
1417 }
1418 return 0;
1419}
1420\endcode
1421 This example gets the list of font families, then the list of
1422 styles for each family and the point sizes that are available for
1423 each family/style combination.
1424*/
1425/*!
1426 \obsolete
1427 \fn inline QStringList QFontDatabase::families( bool ) const
1428*/
1429/*!
1430 \obsolete
1431 \fn inline QStringList QFontDatabase::styles( const QString &family,
1432 const QString & ) const
1433*/
1434/*!
1435 \obsolete
1436 \fn inline QValueList<int> QFontDatabase::pointSizes( const QString &family,
1437 const QString &style ,
1438 const QString & )
1439*/
1440
1441/*!
1442 \obsolete
1443 \fn inline QValueList<int> QFontDatabase::smoothSizes( const QString &family,
1444 const QString &style,
1445 const QString & )
1446*/
1447/*!
1448 \obsolete
1449 \fn inline QFont QFontDatabase::font( const QString &familyName,
1450 const QString &style,
1451 int pointSize,
1452 const QString &)
1453*/
1454/*!
1455 \obsolete
1456 \fn inline bool QFontDatabase::isBitmapScalable( const QString &family,
1457 const QString &style,
1458 const QString & ) const
1459*/
1460
1461/*!
1462 \obsolete
1463 \fn inline bool QFontDatabase::isSmoothlyScalable( const QString &family,
1464 const QString &style,
1465 const QString & ) const
1466*/
1467
1468/*!
1469 \obsolete
1470 \fn inline bool QFontDatabase::isScalable( const QString &family,
1471 const QString &style,
1472 const QString & ) const
1473*/
1474
1475/*!
1476 \obsolete
1477 \fn inline bool QFontDatabase::isFixedPitch( const QString &family,
1478 const QString &style,
1479 const QString & ) const
1480*/
1481
1482/*!
1483 \obsolete
1484 \fn inline bool QFontDatabase::italic( const QString &family,
1485 const QString &style,
1486 const QString & ) const
1487*/
1488
1489/*!
1490 \obsolete
1491 \fn inline bool QFontDatabase::bold( const QString &family,
1492 const QString &style,
1493 const QString & ) const
1494*/
1495
1496/*!
1497 \obsolete
1498 \fn inline int QFontDatabase::weight( const QString &family,
1499 const QString &style,
1500 const QString & ) const
1501*/
1502
1503
1504/*!
1505 Creates a font database object.
1506*/
1507QFontDatabase::QFontDatabase()
1508{
1509#ifdef Q_WS_PM
1510 d = QFontDatabasePrivate::instance();
1511#else
1512 createDatabase();
1513
1514 d = db;
1515#endif
1516}
1517
1518
1519/*! Returns a sorted list of the names of the available font families.
1520
1521 If a family exists in several foundries, the returned name for
1522 that font is in the form "family [foundry]". Examples: "Times
1523 [Adobe]", "Times [Cronyx]", "Palatino".
1524*/
1525QStringList QFontDatabase::families() const
1526{
1527 load();
1528
1529 QStringList flist;
1530 for ( int i = 0; i < d->count; i++ ) {
1531 QtFontFamily *f = d->families[i];
1532 if ( f->count == 0 )
1533 continue;
1534 if ( f->count == 1 ) {
1535 flist.append( f->name );
1536 } else {
1537 for ( int j = 0; j < f->count; j++ ) {
1538 QString str = f->name;
1539 QString foundry = f->foundries[j]->name;
1540 if ( !foundry.isEmpty() ) {
1541 str += " [";
1542 str += foundry;
1543 str += "]";
1544 }
1545 flist.append( str );
1546 }
1547 }
1548 }
1549 return flist;
1550}
1551
1552/*!
1553 \overload
1554
1555 Returns a sorted list of the available font families which support
1556 the Unicode script \a script.
1557
1558 If a family exists in several foundries, the returned name for
1559 that font is in the form "family [foundry]". Examples: "Times
1560 [Adobe]", "Times [Cronyx]", "Palatino".
1561*/
1562QStringList QFontDatabase::families( QFont::Script script ) const
1563{
1564 load();
1565
1566 QStringList flist;
1567 for ( int i = 0; i < d->count; i++ ) {
1568 QtFontFamily *f = d->families[i];
1569 if ( f->count == 0 )
1570 continue;
1571 if (!(f->scripts[script] & QtFontFamily::Supported))
1572 continue;
1573 if ( f->count == 1 ) {
1574 flist.append( f->name );
1575 } else {
1576 for ( int j = 0; j < f->count; j++ ) {
1577 QString str = f->name;
1578 QString foundry = f->foundries[j]->name;
1579 if ( !foundry.isEmpty() ) {
1580 str += " [";
1581 str += foundry;
1582 str += "]";
1583 }
1584 flist.append( str );
1585 }
1586 }
1587 }
1588 return flist;
1589}
1590
1591/*!
1592 Returns a list of the styles available for the font family \a
1593 family. Some example styles: "Light", "Light Italic", "Bold",
1594 "Oblique", "Demi". The list may be empty.
1595*/
1596QStringList QFontDatabase::styles( const QString &family ) const
1597{
1598 QString familyName, foundryName;
1599 parseFontName( family, foundryName, familyName );
1600
1601 load( familyName );
1602
1603 QStringList l;
1604 QtFontFamily *f = d->family( familyName );
1605 if ( !f )
1606 return l;
1607
1608 QtFontFoundry allStyles( foundryName );
1609 for ( int j = 0; j < f->count; j++ ) {
1610 QtFontFoundry *foundry = f->foundries[j];
1611 if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
1612 for ( int k = 0; k < foundry->count; k++ ) {
1613 QtFontStyle::Key ke( foundry->styles[k]->key );
1614 ke.stretch = 0;
1615 allStyles.style( ke, TRUE );
1616 }
1617 }
1618 }
1619
1620 for ( int i = 0; i < allStyles.count; i++ )
1621 l.append( ::styleString( allStyles.styles[i]->key.weight,
1622 allStyles.styles[i]->key.italic,
1623 allStyles.styles[i]->key.oblique ) );
1624 return l;
1625}
1626
1627/*!
1628 Returns TRUE if the font that has family \a family and style \a
1629 style is fixed pitch; otherwise returns FALSE.
1630*/
1631
1632bool QFontDatabase::isFixedPitch(const QString &family,
1633 const QString &style) const
1634{
1635 Q_UNUSED(style);
1636
1637 QString familyName, foundryName;
1638 parseFontName( family, foundryName, familyName );
1639
1640 load( familyName );
1641
1642 QtFontFamily *f = d->family( familyName );
1643#if defined(Q_OS_MAC) && !defined(QWS)
1644 if (f) {
1645 if (!f->fixedPitchComputed) {
1646 QFontMetrics fm(familyName);
1647 f->fixedPitch = fm.width('i') == fm.width('m');
1648 f->fixedPitchComputed = TRUE;
1649 }
1650 }
1651#endif
1652
1653 return ( f && f->fixedPitch );
1654}
1655
1656/*!
1657 Returns TRUE if the font that has family \a family and style \a
1658 style is a scalable bitmap font; otherwise returns FALSE. Scaling
1659 a bitmap font usually produces an unattractive hardly readable
1660 result, because the pixels of the font are scaled. If you need to
1661 scale a bitmap font it is better to scale it to one of the fixed
1662 sizes returned by smoothSizes().
1663
1664 \sa isScalable(), isSmoothlyScalable()
1665*/
1666bool QFontDatabase::isBitmapScalable( const QString &family,
1667 const QString &style) const
1668{
1669 bool bitmapScalable = FALSE;
1670 QString familyName, foundryName;
1671 parseFontName( family, foundryName, familyName );
1672
1673 load( familyName );
1674
1675 QtFontStyle::Key styleKey( style );
1676
1677 QtFontFamily *f = d->family( familyName );
1678 if ( !f ) return bitmapScalable;
1679
1680 for ( int j = 0; j < f->count; j++ ) {
1681 QtFontFoundry *foundry = f->foundries[j];
1682 if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
1683 for ( int k = 0; k < foundry->count; k++ )
1684 if ( foundry->styles[k]->key == styleKey &&
1685 foundry->styles[k]->bitmapScalable &&
1686 !foundry->styles[k]->smoothScalable ) {
1687 bitmapScalable = TRUE;
1688 goto end;
1689 }
1690 }
1691 }
1692 end:
1693 return bitmapScalable;
1694}
1695
1696
1697/*!
1698 Returns TRUE if the font that has family \a family and style \a
1699 style is smoothly scalable; otherwise returns FALSE. If this
1700 function returns TRUE, it's safe to scale this font to any size,
1701 and the result will always look attractive.
1702
1703 \sa isScalable(), isBitmapScalable()
1704*/
1705bool QFontDatabase::isSmoothlyScalable( const QString &family,
1706 const QString &style) const
1707{
1708 bool smoothScalable = FALSE;
1709 QString familyName, foundryName;
1710 parseFontName( family, foundryName, familyName );
1711
1712 load( familyName );
1713
1714 QtFontStyle::Key styleKey( style );
1715
1716 QtFontFamily *f = d->family( familyName );
1717 if ( !f ) return smoothScalable;
1718
1719 for ( int j = 0; j < f->count; j++ ) {
1720 QtFontFoundry *foundry = f->foundries[j];
1721 if ( foundryName.isEmpty() ||
1722 ucstricmp( foundry->name, foundryName ) == 0 ) {
1723 for ( int k = 0; k < foundry->count; k++ )
1724 if ( foundry->styles[k]->key == styleKey &&
1725 foundry->styles[k]->smoothScalable ) {
1726 smoothScalable = TRUE;
1727 goto end;
1728 }
1729 }
1730 }
1731 end:
1732 return smoothScalable;
1733}
1734
1735/*!
1736 Returns TRUE if the font that has family \a family and style \a
1737 style is scalable; otherwise returns FALSE.
1738
1739 \sa isBitmapScalable(), isSmoothlyScalable()
1740*/
1741bool QFontDatabase::isScalable( const QString &family,
1742 const QString &style) const
1743{
1744 if ( isSmoothlyScalable( family, style) )
1745 return TRUE;
1746
1747 return isBitmapScalable( family, style);
1748}
1749
1750
1751/*!
1752 Returns a list of the point sizes available for the font that has
1753 family \a family and style \a style. The list may be empty.
1754
1755 \sa smoothSizes(), standardSizes()
1756*/
1757QValueList<int> QFontDatabase::pointSizes( const QString &family,
1758 const QString &style)
1759{
1760#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
1761 // windows and macosx are always smoothly scalable
1762 Q_UNUSED( family );
1763 Q_UNUSED( style );
1764 return standardSizes();
1765#else
1766 bool smoothScalable = FALSE;
1767 QString familyName, foundryName;
1768 parseFontName( family, foundryName, familyName );
1769
1770 load( familyName );
1771
1772 QtFontStyle::Key styleKey( style );
1773
1774 QValueList<int> sizes;
1775
1776 QtFontFamily *fam = d->family( familyName );
1777 if ( !fam ) return sizes;
1778
1779 for ( int j = 0; j < fam->count; j++ ) {
1780 QtFontFoundry *foundry = fam->foundries[j];
1781 if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
1782 QtFontStyle *style = foundry->style( styleKey );
1783 if ( !style ) continue;
1784
1785 if ( style->smoothScalable ) {
1786 smoothScalable = TRUE;
1787 goto end;
1788 }
1789 for ( int l = 0; l < style->count; l++ ) {
1790 const QtFontSize *size = style->pixelSizes + l;
1791
1792 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1793#if defined(Q_WS_X11)
1794 const uint pointSize = qRound(qt_pointSize(size->pixelSize, 0, -1));
1795#elif defined(Q_WS_PM)
1796//@@TODO (dmik): some bitmap fonts (i.e. System VIO) have point sizes
1797// that do not really correlate with their actual pixel sizes (i.e.
1798// their pointsize != pixelsizde * DPI / 72), What to return in that case?
1799 const uint pointSize = size->pointSize / 10;
1800#else
1801 const uint pointSize = size->pixelSize; // embedded uses 72dpi
1802#endif
1803 if (! sizes.contains(pointSize))
1804 sizes.append(pointSize);
1805 }
1806 }
1807 }
1808 }
1809 end:
1810 if ( smoothScalable )
1811 return standardSizes();
1812
1813 qHeapSort( sizes );
1814 return sizes;
1815#endif
1816}
1817
1818/*!
1819 Returns a QFont object that has family \a family, style \a style
1820 and point size \a pointSize. If no matching font could be created,
1821 a QFont object that uses the application's default font is
1822 returned.
1823*/
1824QFont QFontDatabase::font( const QString &family, const QString &style,
1825 int pointSize)
1826{
1827 QString familyName, foundryName;
1828 parseFontName( family, foundryName, familyName );
1829
1830 load( familyName );
1831
1832 QtFontFoundry allStyles( foundryName );
1833 QtFontFamily *f = d->family( familyName );
1834 if ( !f ) return QApplication::font();
1835
1836 for ( int j = 0; j < f->count; j++ ) {
1837 QtFontFoundry *foundry = f->foundries[j];
1838 if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
1839 for ( int k = 0; k < foundry->count; k++ )
1840 allStyles.style( foundry->styles[k]->key, TRUE );
1841 }
1842 }
1843
1844 QtFontStyle::Key styleKey( style );
1845 QtFontStyle *s = allStyles.style( styleKey );
1846
1847 // ### perhaps do a bit of matching to find the most compatible font?
1848 if ( !s && allStyles.count )
1849 s = allStyles.styles[0];
1850
1851 if ( !s ) // no styles found?
1852 return QApplication::font();
1853 return QFont( family, pointSize, s->key.weight,
1854 s->key.italic ? TRUE : s->key.oblique ? TRUE : FALSE );
1855}
1856
1857
1858/*!
1859 Returns the point sizes of a font that has family \a family and
1860 style \a style that will look attractive. The list may be empty.
1861 For non-scalable fonts and bitmap scalable fonts, this function
1862 is equivalent to pointSizes().
1863
1864 \sa pointSizes(), standardSizes()
1865*/
1866QValueList<int> QFontDatabase::smoothSizes( const QString &family,
1867 const QString &style)
1868{
1869#ifdef Q_WS_WIN
1870 Q_UNUSED( family );
1871 Q_UNUSED( style );
1872 return QFontDatabase::standardSizes();
1873#else
1874 bool smoothScalable = FALSE;
1875 QString familyName, foundryName;
1876 parseFontName( family, foundryName, familyName );
1877
1878 load( familyName );
1879
1880 QtFontStyle::Key styleKey( style );
1881
1882 QValueList<int> sizes;
1883
1884 QtFontFamily *fam = d->family( familyName );
1885 if ( !fam )
1886 return sizes;
1887
1888 for ( int j = 0; j < fam->count; j++ ) {
1889 QtFontFoundry *foundry = fam->foundries[j];
1890 if ( foundryName.isEmpty() ||
1891 ucstricmp( foundry->name, foundryName ) == 0 ) {
1892 QtFontStyle *style = foundry->style( styleKey );
1893 if ( !style ) continue;
1894
1895 if ( style->smoothScalable ) {
1896 smoothScalable = TRUE;
1897 goto end;
1898 }
1899 for ( int l = 0; l < style->count; l++ ) {
1900 const QtFontSize *size = style->pixelSizes + l;
1901
1902 if ( size->pixelSize != 0 && size->pixelSize != USHRT_MAX ) {
1903#if defined(Q_WS_X11)
1904 const uint pointSize = qRound(qt_pointSize(size->pixelSize, 0, -1));
1905#elif defined(Q_WS_PM)
1906//@@TODO (dmik): some bitmap fonts (i.e. System VIO) have point sizes
1907// that do not really correlate with their actual pixel sizes (i.e.
1908// their pointsize != pixelsizde * DPI / 72), What to return in that case?
1909 const uint pointSize = size->pointSize / 10;
1910#else
1911 const uint pointSize = size->pixelSize; // embedded uses 72dpi
1912#endif
1913 if (! sizes.contains(pointSize))
1914 sizes.append( pointSize );
1915 }
1916 }
1917 }
1918 }
1919 end:
1920 if ( smoothScalable )
1921 return QFontDatabase::standardSizes();
1922
1923 qHeapSort( sizes );
1924 return sizes;
1925#endif
1926}
1927
1928
1929/*!
1930 Returns a list of standard font sizes.
1931
1932 \sa smoothSizes(), pointSizes()
1933*/
1934QValueList<int> QFontDatabase::standardSizes()
1935{
1936 QValueList<int> ret;
1937 static const unsigned short standard[] =
1938 { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
1939 const unsigned short *sizes = standard;
1940 while ( *sizes ) ret << *sizes++;
1941 return ret;
1942}
1943
1944
1945/*!
1946 Returns TRUE if the font that has family \a family and style \a
1947 style is italic; otherwise returns FALSE.
1948
1949 \sa weight(), bold()
1950*/
1951bool QFontDatabase::italic( const QString &family,
1952 const QString &style) const
1953{
1954 QString familyName, foundryName;
1955 parseFontName( family, foundryName, familyName );
1956
1957 load( familyName );
1958
1959 QtFontFoundry allStyles( foundryName );
1960 QtFontFamily *f = d->family( familyName );
1961 if ( !f ) return FALSE;
1962
1963 for ( int j = 0; j < f->count; j++ ) {
1964 QtFontFoundry *foundry = f->foundries[j];
1965 if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
1966 for ( int k = 0; k < foundry->count; k++ )
1967 allStyles.style( foundry->styles[k]->key, TRUE );
1968 }
1969 }
1970
1971 QtFontStyle::Key styleKey( style );
1972 QtFontStyle *s = allStyles.style( styleKey );
1973 return s && s->key.italic;
1974}
1975
1976
1977/*!
1978 Returns TRUE if the font that has family \a family and style \a
1979 style is bold; otherwise returns FALSE.
1980
1981 \sa italic(), weight()
1982*/
1983bool QFontDatabase::bold( const QString &family,
1984 const QString &style) const
1985{
1986 QString familyName, foundryName;
1987 parseFontName( family, foundryName, familyName );
1988
1989 load( familyName );
1990
1991 QtFontFoundry allStyles( foundryName );
1992 QtFontFamily *f = d->family( familyName );
1993 if ( !f ) return FALSE;
1994
1995 for ( int j = 0; j < f->count; j++ ) {
1996 QtFontFoundry *foundry = f->foundries[j];
1997 if ( foundryName.isEmpty() ||
1998 ucstricmp( foundry->name, foundryName ) == 0 ) {
1999 for ( int k = 0; k < foundry->count; k++ )
2000 allStyles.style( foundry->styles[k]->key, TRUE );
2001 }
2002 }
2003
2004 QtFontStyle::Key styleKey( style );
2005 QtFontStyle *s = allStyles.style( styleKey );
2006 return s && s->key.weight >= QFont::Bold;
2007}
2008
2009
2010/*!
2011 Returns the weight of the font that has family \a family and style
2012 \a style. If there is no such family and style combination,
2013 returns -1.
2014
2015 \sa italic(), bold()
2016*/
2017int QFontDatabase::weight( const QString &family,
2018 const QString &style) const
2019{
2020 QString familyName, foundryName;
2021 parseFontName( family, foundryName, familyName );
2022
2023 load( familyName );
2024
2025 QtFontFoundry allStyles( foundryName );
2026 QtFontFamily *f = d->family( familyName );
2027 if ( !f ) return -1;
2028
2029 for ( int j = 0; j < f->count; j++ ) {
2030 QtFontFoundry *foundry = f->foundries[j];
2031 if ( foundryName.isEmpty() ||
2032 ucstricmp( foundry->name, foundryName ) == 0 ) {
2033 for ( int k = 0; k < foundry->count; k++ )
2034 allStyles.style( foundry->styles[k]->key, TRUE );
2035 }
2036 }
2037
2038 QtFontStyle::Key styleKey( style );
2039 QtFontStyle *s = allStyles.style( styleKey );
2040 return s ? s->key.weight : -1;
2041}
2042
2043
2044/*!
2045 Returns a string that gives a default description of the \a script
2046 (e.g. for displaying to the user in a dialog). The name matches
2047 the name of the script as defined by the Unicode 3.0 standard.
2048
2049 \sa QFont::Script
2050*/
2051QString QFontDatabase::scriptName(QFont::Script script)
2052{
2053 const char *name = 0;
2054
2055 switch (script) {
2056 case QFont::Latin:
2057 name = QT_TRANSLATE_NOOP("QFont", "Latin");
2058 break;
2059 case QFont::Greek:
2060 name = QT_TRANSLATE_NOOP("QFont", "Greek" );
2061 break;
2062 case QFont::Cyrillic:
2063 name = QT_TRANSLATE_NOOP("QFont", "Cyrillic" );
2064 break;
2065 case QFont::Armenian:
2066 name = QT_TRANSLATE_NOOP("QFont", "Armenian" );
2067 break;
2068 case QFont::Georgian:
2069 name = QT_TRANSLATE_NOOP("QFont", "Georgian" );
2070 break;
2071 case QFont::Runic:
2072 name = QT_TRANSLATE_NOOP("QFont", "Runic" );
2073 break;
2074 case QFont::Ogham:
2075 name = QT_TRANSLATE_NOOP("QFont", "Ogham" );
2076 break;
2077 case QFont::SpacingModifiers:
2078 name = QT_TRANSLATE_NOOP("QFont", "SpacingModifiers" );
2079 break;
2080 case QFont::CombiningMarks:
2081 name = QT_TRANSLATE_NOOP("QFont", "CombiningMarks" );
2082 break;
2083 case QFont::Hebrew:
2084 name = QT_TRANSLATE_NOOP("QFont", "Hebrew" );
2085 break;
2086 case QFont::Arabic:
2087 name = QT_TRANSLATE_NOOP("QFont", "Arabic" );
2088 break;
2089 case QFont::Syriac:
2090 name = QT_TRANSLATE_NOOP("QFont", "Syriac" );
2091 break;
2092 case QFont::Thaana:
2093 name = QT_TRANSLATE_NOOP("QFont", "Thaana" );
2094 break;
2095 case QFont::Devanagari:
2096 name = QT_TRANSLATE_NOOP("QFont", "Devanagari" );
2097 break;
2098 case QFont::Bengali:
2099 name = QT_TRANSLATE_NOOP("QFont", "Bengali" );
2100 break;
2101 case QFont::Gurmukhi:
2102 name = QT_TRANSLATE_NOOP("QFont", "Gurmukhi" );
2103 break;
2104 case QFont::Gujarati:
2105 name = QT_TRANSLATE_NOOP("QFont", "Gujarati" );
2106 break;
2107 case QFont::Oriya:
2108 name = QT_TRANSLATE_NOOP("QFont", "Oriya" );
2109 break;
2110 case QFont::Tamil:
2111 name = QT_TRANSLATE_NOOP("QFont", "Tamil" );
2112 break;
2113 case QFont::Telugu:
2114 name = QT_TRANSLATE_NOOP("QFont", "Telugu" );
2115 break;
2116 case QFont::Kannada:
2117 name = QT_TRANSLATE_NOOP("QFont", "Kannada" );
2118 break;
2119 case QFont::Malayalam:
2120 name = QT_TRANSLATE_NOOP("QFont", "Malayalam" );
2121 break;
2122 case QFont::Sinhala:
2123 name = QT_TRANSLATE_NOOP("QFont", "Sinhala" );
2124 break;
2125 case QFont::Thai:
2126 name = QT_TRANSLATE_NOOP("QFont", "Thai" );
2127 break;
2128 case QFont::Lao:
2129 name = QT_TRANSLATE_NOOP("QFont", "Lao" );
2130 break;
2131 case QFont::Tibetan:
2132 name = QT_TRANSLATE_NOOP("QFont", "Tibetan" );
2133 break;
2134 case QFont::Myanmar:
2135 name = QT_TRANSLATE_NOOP("QFont", "Myanmar" );
2136 break;
2137 case QFont::Khmer:
2138 name = QT_TRANSLATE_NOOP("QFont", "Khmer" );
2139 break;
2140 case QFont::Han:
2141 name = QT_TRANSLATE_NOOP("QFont", "Han" );
2142 break;
2143 case QFont::Hiragana:
2144 name = QT_TRANSLATE_NOOP("QFont", "Hiragana" );
2145 break;
2146 case QFont::Katakana:
2147 name = QT_TRANSLATE_NOOP("QFont", "Katakana" );
2148 break;
2149 case QFont::Hangul:
2150 name = QT_TRANSLATE_NOOP("QFont", "Hangul" );
2151 break;
2152 case QFont::Bopomofo:
2153 name = QT_TRANSLATE_NOOP("QFont", "Bopomofo" );
2154 break;
2155 case QFont::Yi:
2156 name = QT_TRANSLATE_NOOP("QFont", "Yi" );
2157 break;
2158 case QFont::Ethiopic:
2159 name = QT_TRANSLATE_NOOP("QFont", "Ethiopic" );
2160 break;
2161 case QFont::Cherokee:
2162 name = QT_TRANSLATE_NOOP("QFont", "Cherokee" );
2163 break;
2164 case QFont::CanadianAboriginal:
2165 name = QT_TRANSLATE_NOOP("QFont", "Canadian Aboriginal" );
2166 break;
2167 case QFont::Mongolian:
2168 name = QT_TRANSLATE_NOOP("QFont", "Mongolian" );
2169 break;
2170
2171 case QFont::CurrencySymbols:
2172 name = QT_TRANSLATE_NOOP("QFont", "Currency Symbols" );
2173 break;
2174
2175 case QFont::LetterlikeSymbols:
2176 name = QT_TRANSLATE_NOOP("QFont", "Letterlike Symbols" );
2177 break;
2178
2179 case QFont::NumberForms:
2180 name = QT_TRANSLATE_NOOP("QFont", "Number Forms" );
2181 break;
2182
2183 case QFont::MathematicalOperators:
2184 name = QT_TRANSLATE_NOOP("QFont", "Mathematical Operators" );
2185 break;
2186
2187 case QFont::TechnicalSymbols:
2188 name = QT_TRANSLATE_NOOP("QFont", "Technical Symbols" );
2189 break;
2190
2191 case QFont::GeometricSymbols:
2192 name = QT_TRANSLATE_NOOP("QFont", "Geometric Symbols" );
2193 break;
2194
2195 case QFont::MiscellaneousSymbols:
2196 name = QT_TRANSLATE_NOOP("QFont", "Miscellaneous Symbols" );
2197 break;
2198
2199 case QFont::EnclosedAndSquare:
2200 name = QT_TRANSLATE_NOOP("QFont", "Enclosed and Square" );
2201 break;
2202
2203 case QFont::Braille:
2204 name = QT_TRANSLATE_NOOP("QFont", "Braille" );
2205 break;
2206
2207 case QFont::Unicode:
2208 name = QT_TRANSLATE_NOOP("QFont", "Unicode" );
2209 break;
2210
2211 case QFont::Tagalog:
2212 name = QT_TRANSLATE_NOOP( "QFont", "Tagalog" );
2213 break;
2214
2215 case QFont::Hanunoo:
2216 name = QT_TRANSLATE_NOOP( "QFont", "Hanunoo" );
2217 break;
2218
2219 case QFont::Buhid:
2220 name = QT_TRANSLATE_NOOP( "QFont", "Buhid" );
2221 break;
2222
2223 case QFont::Tagbanwa:
2224 name = QT_TRANSLATE_NOOP( "QFont", "Tagbanwa" );
2225 break;
2226
2227 case QFont::KatakanaHalfWidth:
2228 name = QT_TRANSLATE_NOOP( "QFont", "Katakana Half-Width Forms" );
2229 break;
2230
2231 case QFont::Han_Japanese:
2232 name = QT_TRANSLATE_NOOP( "QFont", "Han (Japanese)" );
2233 break;
2234
2235 case QFont::Han_SimplifiedChinese:
2236 name = QT_TRANSLATE_NOOP( "QFont", "Han (Simplified Chinese)" );
2237 break;
2238
2239 case QFont::Han_TraditionalChinese:
2240 name = QT_TRANSLATE_NOOP( "QFont", "Han (Traditional Chinese)" );
2241 break;
2242
2243 case QFont::Han_Korean:
2244 name = QT_TRANSLATE_NOOP( "QFont", "Han (Korean)" );
2245 break;
2246
2247 default:
2248 name = QT_TRANSLATE_NOOP( "QFont", "Unknown Script" );
2249 break;
2250 }
2251
2252 return qApp ? qApp->translate("QFont", name) : QString::fromLatin1(name);
2253}
2254
2255
2256/*!
2257 Returns a string with sample characters from \a script.
2258
2259 \sa QFont::Script
2260*/
2261QString QFontDatabase::scriptSample(QFont::Script script)
2262{
2263 QString sample = "AaBb";
2264
2265 switch (script) {
2266 case QFont::Latin:
2267 // This is cheating... we only show latin-1 characters so that we don't
2268 // end up loading lots of fonts - at least on X11...
2269 sample += QChar(0x00C3);
2270 sample += QChar(0x00E1);
2271 sample += "Zz";
2272 break;
2273 case QFont::Greek:
2274 sample += QChar(0x0393);
2275 sample += QChar(0x03B1);
2276 sample += QChar(0x03A9);
2277 sample += QChar(0x03C9);
2278 break;
2279 case QFont::Cyrillic:
2280 sample += QChar(0x0414);
2281 sample += QChar(0x0434);
2282 sample += QChar(0x0436);
2283 sample += QChar(0x0402);
2284 break;
2285 case QFont::Armenian:
2286 sample += QChar(0x053f);
2287 sample += QChar(0x054f);
2288 sample += QChar(0x056f);
2289 sample += QChar(0x057f);
2290 break;
2291 case QFont::Georgian:
2292 sample += QChar(0x10a0);
2293 sample += QChar(0x10b0);
2294 sample += QChar(0x10c0);
2295 sample += QChar(0x10d0);
2296 break;
2297 case QFont::Runic:
2298 sample += QChar(0x16a0);
2299 sample += QChar(0x16b0);
2300 sample += QChar(0x16c0);
2301 sample += QChar(0x16d0);
2302 break;
2303 case QFont::Ogham:
2304 sample += QChar(0x1681);
2305 sample += QChar(0x1687);
2306 sample += QChar(0x1693);
2307 sample += QChar(0x168d);
2308 break;
2309
2310
2311
2312 case QFont::Hebrew:
2313 sample += QChar(0x05D0);
2314 sample += QChar(0x05D1);
2315 sample += QChar(0x05D2);
2316 sample += QChar(0x05D3);
2317 break;
2318 case QFont::Arabic:
2319 sample += QChar(0x0628);
2320 sample += QChar(0x0629);
2321 sample += QChar(0x062A);
2322 sample += QChar(0x063A);
2323 break;
2324 case QFont::Syriac:
2325 sample += QChar(0x0715);
2326 sample += QChar(0x0725);
2327 sample += QChar(0x0716);
2328 sample += QChar(0x0726);
2329 break;
2330 case QFont::Thaana:
2331 sample += QChar(0x0784);
2332 sample += QChar(0x0794);
2333 sample += QChar(0x078c);
2334 sample += QChar(0x078d);
2335 break;
2336
2337
2338
2339 case QFont::Devanagari:
2340 sample += QChar(0x0905);
2341 sample += QChar(0x0915);
2342 sample += QChar(0x0925);
2343 sample += QChar(0x0935);
2344 break;
2345 case QFont::Bengali:
2346 sample += QChar(0x0986);
2347 sample += QChar(0x0996);
2348 sample += QChar(0x09a6);
2349 sample += QChar(0x09b6);
2350 break;
2351 case QFont::Gurmukhi:
2352 sample += QChar(0x0a05);
2353 sample += QChar(0x0a15);
2354 sample += QChar(0x0a25);
2355 sample += QChar(0x0a35);
2356 break;
2357 case QFont::Gujarati:
2358 sample += QChar(0x0a85);
2359 sample += QChar(0x0a95);
2360 sample += QChar(0x0aa5);
2361 sample += QChar(0x0ab5);
2362 break;
2363 case QFont::Oriya:
2364 sample += QChar(0x0b06);
2365 sample += QChar(0x0b16);
2366 sample += QChar(0x0b2b);
2367 sample += QChar(0x0b36);
2368 break;
2369 case QFont::Tamil:
2370 sample += QChar(0x0b89);
2371 sample += QChar(0x0b99);
2372 sample += QChar(0x0ba9);
2373 sample += QChar(0x0bb9);
2374 break;
2375 case QFont::Telugu:
2376 sample += QChar(0x0c05);
2377 sample += QChar(0x0c15);
2378 sample += QChar(0x0c25);
2379 sample += QChar(0x0c35);
2380 break;
2381 case QFont::Kannada:
2382 sample += QChar(0x0c85);
2383 sample += QChar(0x0c95);
2384 sample += QChar(0x0ca5);
2385 sample += QChar(0x0cb5);
2386 break;
2387 case QFont::Malayalam:
2388 sample += QChar(0x0d05);
2389 sample += QChar(0x0d15);
2390 sample += QChar(0x0d25);
2391 sample += QChar(0x0d35);
2392 break;
2393 case QFont::Sinhala:
2394 sample += QChar(0x0d90);
2395 sample += QChar(0x0da0);
2396 sample += QChar(0x0db0);
2397 sample += QChar(0x0dc0);
2398 break;
2399 case QFont::Thai:
2400 sample += QChar(0x0e02);
2401 sample += QChar(0x0e12);
2402 sample += QChar(0x0e22);
2403 sample += QChar(0x0e32);
2404 break;
2405 case QFont::Lao:
2406 sample += QChar(0x0e8d);
2407 sample += QChar(0x0e9d);
2408 sample += QChar(0x0ead);
2409 sample += QChar(0x0ebd);
2410 break;
2411 case QFont::Tibetan:
2412 sample += QChar(0x0f00);
2413 sample += QChar(0x0f01);
2414 sample += QChar(0x0f02);
2415 sample += QChar(0x0f03);
2416 break;
2417 case QFont::Myanmar:
2418 sample += QChar(0x1000);
2419 sample += QChar(0x1001);
2420 sample += QChar(0x1002);
2421 sample += QChar(0x1003);
2422 break;
2423 case QFont::Khmer:
2424 sample += QChar(0x1780);
2425 sample += QChar(0x1790);
2426 sample += QChar(0x17b0);
2427 sample += QChar(0x17c0);
2428 break;
2429
2430
2431
2432 case QFont::Han:
2433 sample += QChar(0x6f84);
2434 sample += QChar(0x820a);
2435 sample += QChar(0x61a9);
2436 sample += QChar(0x9781);
2437 break;
2438 case QFont::Hiragana:
2439 sample += QChar(0x3050);
2440 sample += QChar(0x3060);
2441 sample += QChar(0x3070);
2442 sample += QChar(0x3080);
2443 break;
2444 case QFont::Katakana:
2445 sample += QChar(0x30b0);
2446 sample += QChar(0x30c0);
2447 sample += QChar(0x30d0);
2448 sample += QChar(0x30e0);
2449 break;
2450 case QFont::Hangul:
2451 sample += QChar(0xac00);
2452 sample += QChar(0xac11);
2453 sample += QChar(0xac1a);
2454 sample += QChar(0xac2f);
2455 break;
2456 case QFont::Bopomofo:
2457 sample += QChar(0x3105);
2458 sample += QChar(0x3115);
2459 sample += QChar(0x3125);
2460 sample += QChar(0x3129);
2461 break;
2462 case QFont::Yi:
2463 sample += QChar(0xa1a8);
2464 sample += QChar(0xa1a6);
2465 sample += QChar(0xa200);
2466 sample += QChar(0xa280);
2467 break;
2468
2469
2470
2471 case QFont::Ethiopic:
2472 sample += QChar(0x1200);
2473 sample += QChar(0x1240);
2474 sample += QChar(0x1280);
2475 sample += QChar(0x12c0);
2476 break;
2477 case QFont::Cherokee:
2478 sample += QChar(0x13a0);
2479 sample += QChar(0x13b0);
2480 sample += QChar(0x13c0);
2481 sample += QChar(0x13d0);
2482 break;
2483 case QFont::CanadianAboriginal:
2484 sample += QChar(0x1410);
2485 sample += QChar(0x1500);
2486 sample += QChar(0x15f0);
2487 sample += QChar(0x1650);
2488 break;
2489 case QFont::Mongolian:
2490 sample += QChar(0x1820);
2491 sample += QChar(0x1840);
2492 sample += QChar(0x1860);
2493 sample += QChar(0x1880);
2494 break;
2495
2496
2497 case QFont::CurrencySymbols:
2498 case QFont::LetterlikeSymbols:
2499 case QFont::NumberForms:
2500 case QFont::MathematicalOperators:
2501 case QFont::TechnicalSymbols:
2502 case QFont::GeometricSymbols:
2503 case QFont::MiscellaneousSymbols:
2504 case QFont::EnclosedAndSquare:
2505 case QFont::Braille:
2506 break;
2507
2508
2509 case QFont::Unicode:
2510 sample += QChar(0x0174);
2511 sample += QChar(0x0628);
2512 sample += QChar(0x0e02);
2513 sample += QChar(0x263A);
2514 sample += QChar(0x3129);
2515 sample += QChar(0x61a9);
2516 sample += QChar(0xac2f);
2517 break;
2518
2519
2520
2521 default:
2522 sample += QChar(0xfffd);
2523 sample += QChar(0xfffd);
2524 sample += QChar(0xfffd);
2525 sample += QChar(0xfffd);
2526 break;
2527 }
2528
2529 return sample;
2530}
2531
2532
2533
2534
2535/*!
2536 \internal
2537
2538 This makes sense of the font family name:
2539
2540 1) if the family name contains a '-' (ie. "Adobe-Courier"), then we
2541 split at the '-', and use the string as the foundry, and the string to
2542 the right as the family
2543
2544 2) if the family name contains a '[' and a ']', then we take the text
2545 between the square brackets as the foundry, and the text before the
2546 square brackets as the family (ie. "Arial [Monotype]")
2547*/
2548void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
2549{
2550 if ( name.contains('-') ) {
2551 int i = name.find('-');
2552 foundry = name.left( i );
2553 family = name.right( name.length() - i - 1 );
2554 } else if ( name.contains('[') && name.contains(']')) {
2555 int i = name.find('[');
2556 int li = name.findRev(']');
2557
2558 if (i < li) {
2559 foundry = name.mid(i + 1, li - i - 1);
2560 if (name[i - 1] == ' ')
2561 i--;
2562 family = name.left(i);
2563 }
2564 } else {
2565 foundry = QString::null;
2566 family = name;
2567 }
2568}
2569
2570#endif // QT_NO_FONTDATABASE
Note: See TracBrowser for help on using the repository browser.