source: trunk/src/gui/text/qfontdatabase.cpp@ 95

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

gui: Added OS/2 stubs for platform-specific parts of all key GUI classes. Non-key classes are temporarily disabled with QT_NO_ defines.

File size: 71.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at qt-sales@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <qdir.h>
43#include "qfontdatabase.h"
44#include "qdebug.h"
45#include "qalgorithms.h"
46#include "qapplication.h"
47#include "qvarlengtharray.h" // here or earlier - workaround for VC++6
48#include "qthread.h"
49#include "qmutex.h"
50#include "private/qunicodetables_p.h"
51#include "qfontengine_p.h"
52
53#ifdef Q_WS_X11
54#include <locale.h>
55#endif
56#include <stdlib.h>
57#include <limits.h>
58
59// #define QFONTDATABASE_DEBUG
60#ifdef QFONTDATABASE_DEBUG
61# define FD_DEBUG qDebug
62#else
63# define FD_DEBUG if (false) qDebug
64#endif
65
66// #define FONT_MATCH_DEBUG
67#ifdef FONT_MATCH_DEBUG
68# define FM_DEBUG qDebug
69#else
70# define FM_DEBUG if (false) qDebug
71#endif
72
73#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
74# define for if(0){}else for
75#endif
76
77QT_BEGIN_NAMESPACE
78
79extern int qt_defaultDpiY(); // in qfont.cpp
80
81Q_GUI_EXPORT bool qt_enable_test_font = false;
82
83static int getFontWeight(const QString &weightString)
84{
85 QString s = weightString.toLower();
86
87 // Test in decreasing order of commonness
88 if (s == QLatin1String("medium") ||
89 s == QLatin1String("normal")
90 || s.compare(qApp->translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0)
91 return QFont::Normal;
92 if (s == QLatin1String("bold")
93 || s.compare(qApp->translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0)
94 return QFont::Bold;
95 if (s == QLatin1String("demibold") || s == QLatin1String("demi bold")
96 || s.compare(qApp->translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
97 return QFont::DemiBold;
98 if (s == QLatin1String("black")
99 || s.compare(qApp->translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
100 return QFont::Black;
101 if (s == QLatin1String("light"))
102 return QFont::Light;
103
104 if (s.contains(QLatin1String("bold"))
105 || s.contains(qApp->translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) {
106 if (s.contains(QLatin1String("demi"))
107 || s.compare(qApp->translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0)
108 return (int) QFont::DemiBold;
109 return (int) QFont::Bold;
110 }
111
112 if (s.contains(QLatin1String("light"))
113 || s.compare(qApp->translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0)
114 return (int) QFont::Light;
115
116 if (s.contains(QLatin1String("black"))
117 || s.compare(qApp->translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
118 return (int) QFont::Black;
119
120 return (int) QFont::Normal;
121}
122
123struct QtFontEncoding
124{
125 signed int encoding : 16;
126
127 uint xpoint : 16;
128 uint xres : 8;
129 uint yres : 8;
130 uint avgwidth : 16;
131 uchar pitch : 8;
132};
133
134struct QtFontSize
135{
136 unsigned short pixelSize;
137
138#ifdef Q_WS_X11
139 int count;
140 QtFontEncoding *encodings;
141 QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0,
142 uint yres = 0, uint avgwidth = 0, bool add = false);
143#endif // Q_WS_X11
144#ifdef Q_WS_QWS
145 QByteArray fileName;
146 int fileIndex;
147#endif
148};
149
150
151#ifdef Q_WS_X11
152QtFontEncoding *QtFontSize::encodingID(int id, uint xpoint, uint xres,
153 uint yres, uint avgwidth, bool add)
154{
155 // we don't match using the xpoint, xres and yres parameters, only the id
156 for (int i = 0; i < count; ++i) {
157 if (encodings[i].encoding == id)
158 return encodings + i;
159 }
160
161 if (!add) return 0;
162
163 if (!(count % 4))
164 encodings = (QtFontEncoding *)
165 realloc(encodings,
166 (((count+4) >> 2) << 2) * sizeof(QtFontEncoding));
167 encodings[count].encoding = id;
168 encodings[count].xpoint = xpoint;
169 encodings[count].xres = xres;
170 encodings[count].yres = yres;
171 encodings[count].avgwidth = avgwidth;
172 encodings[count].pitch = '*';
173 return encodings + count++;
174}
175#endif // Q_WS_X11
176
177struct QtFontStyle
178{
179 struct Key {
180 Key(const QString &styleString);
181 Key() : style(QFont::StyleNormal),
182 weight(QFont::Normal), stretch(0) { }
183 Key(const Key &o) : style(o.style),
184 weight(o.weight), stretch(o.stretch) { }
185 uint style : 2;
186 signed int weight : 8;
187 signed int stretch : 12;
188
189 bool operator==(const Key & other) {
190 return (style == other.style &&
191 weight == other.weight &&
192 (stretch == 0 || other.stretch == 0 || stretch == other.stretch));
193 }
194 bool operator!=(const Key &other) {
195 return !operator==(other);
196 }
197 bool operator <(const Key &o) {
198 int x = (style << 12) + (weight << 14) + stretch;
199 int y = (o.style << 12) + (o.weight << 14) + o.stretch;
200 return (x < y);
201 }
202 };
203
204 QtFontStyle(const Key &k)
205 : key(k), bitmapScalable(false), smoothScalable(false),
206 count(0), pixelSizes(0)
207 {
208#if defined(Q_WS_X11)
209 weightName = setwidthName = 0;
210#endif // Q_WS_X11
211 }
212
213 ~QtFontStyle() {
214#ifdef Q_WS_X11
215 delete [] weightName;
216 delete [] setwidthName;
217#endif
218#if defined(Q_WS_X11) || defined(Q_WS_QWS)
219 while (count--) {
220#ifdef Q_WS_X11
221 free(pixelSizes[count].encodings);
222#endif
223#ifdef Q_WS_QWS
224 pixelSizes[count].fileName.~QByteArray();
225#endif
226 }
227#endif
228 free(pixelSizes);
229 }
230
231 Key key;
232 bool bitmapScalable : 1;
233 bool smoothScalable : 1;
234 signed int count : 30;
235 QtFontSize *pixelSizes;
236
237#ifdef Q_WS_X11
238 const char *weightName;
239 const char *setwidthName;
240#endif // Q_WS_X11
241#ifdef Q_WS_QWS
242 bool antialiased;
243#endif
244
245 QtFontSize *pixelSize(unsigned short size, bool = false);
246};
247
248QtFontStyle::Key::Key(const QString &styleString)
249 : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
250{
251 weight = getFontWeight(styleString);
252
253 if (styleString.contains(QLatin1String("Italic"))
254 || styleString.contains(qApp->translate("QFontDatabase", "Italic")))
255 style = QFont::StyleItalic;
256 else if (styleString.contains(QLatin1String("Oblique"))
257 || styleString.contains(qApp->translate("QFontDatabase", "Oblique")))
258 style = QFont::StyleOblique;
259}
260
261QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
262{
263 for (int i = 0; i < count; i++) {
264 if (pixelSizes[i].pixelSize == size)
265 return pixelSizes + i;
266 }
267 if (!add)
268 return 0;
269
270 if (!(count % 8))
271 pixelSizes = (QtFontSize *)
272 realloc(pixelSizes,
273 (((count+8) >> 3) << 3) * sizeof(QtFontSize));
274 pixelSizes[count].pixelSize = size;
275#ifdef Q_WS_X11
276 pixelSizes[count].count = 0;
277 pixelSizes[count].encodings = 0;
278#endif
279#ifdef Q_WS_QWS
280 new (&pixelSizes[count].fileName) QByteArray;
281 pixelSizes[count].fileIndex = 0;
282#endif
283 return pixelSizes + (count++);
284}
285
286struct QtFontFoundry
287{
288 QtFontFoundry(const QString &n) : name(n), count(0), styles(0) {}
289 ~QtFontFoundry() {
290 while (count--)
291 delete styles[count];
292 free(styles);
293 }
294
295 QString name;
296
297 int count;
298 QtFontStyle **styles;
299 QtFontStyle *style(const QtFontStyle::Key &, bool = false);
300};
301
302QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create)
303{
304 int pos = 0;
305 if (count) {
306 int low = 0;
307 int high = count;
308 pos = count / 2;
309 while (high > low) {
310 if (styles[pos]->key == key)
311 return styles[pos];
312 if (styles[pos]->key < key)
313 low = pos + 1;
314 else
315 high = pos;
316 pos = (high + low) / 2;
317 };
318 pos = low;
319 }
320 if (!create)
321 return 0;
322
323// qDebug("adding key (weight=%d, style=%d, oblique=%d stretch=%d) at %d", key.weight, key.style, key.oblique, key.stretch, pos);
324 if (!(count % 8))
325 styles = (QtFontStyle **)
326 realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *));
327
328 memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *));
329 styles[pos] = new QtFontStyle(key);
330 count++;
331 return styles[pos];
332}
333
334
335struct QtFontFamily
336{
337 enum WritingSystemStatus {
338 Unknown = 0,
339 Supported = 1,
340 UnsupportedFT = 2,
341 UnsupportedXLFD = 4,
342 Unsupported = UnsupportedFT | UnsupportedXLFD
343 };
344
345 QtFontFamily(const QString &n)
346 :
347#ifdef Q_WS_X11
348 fixedPitch(true), ftWritingSystemCheck(false),
349 xlfdLoaded(false), synthetic(false), symbol_checked(false),
350#else
351 fixedPitch(false),
352#endif
353#ifdef Q_WS_WIN
354 writingSystemCheck(false),
355 loaded(false),
356#endif
357#if !defined(QWS) && defined(Q_OS_MAC)
358 fixedPitchComputed(false),
359#endif
360 name(n), count(0), foundries(0)
361#if defined(Q_WS_QWS)
362 , bogusWritingSystems(false)
363#endif
364 {
365 memset(writingSystems, 0, sizeof(writingSystems));
366 }
367 ~QtFontFamily() {
368 while (count--)
369 delete foundries[count];
370 free(foundries);
371 }
372
373 bool fixedPitch : 1;
374#ifdef Q_WS_X11
375 bool ftWritingSystemCheck : 1;
376 bool xlfdLoaded : 1;
377 bool synthetic : 1;
378#endif
379#ifdef Q_WS_WIN
380 bool writingSystemCheck : 1;
381 bool loaded : 1;
382#endif
383#if !defined(QWS) && defined(Q_OS_MAC)
384 bool fixedPitchComputed : 1;
385#endif
386#ifdef Q_WS_X11
387 bool symbol_checked;
388#endif
389
390 QString name;
391#ifdef Q_WS_X11
392 QByteArray fontFilename;
393 int fontFileIndex;
394#endif
395#ifdef Q_WS_WIN
396 QString english_name;
397#endif
398 int count;
399 QtFontFoundry **foundries;
400
401#ifdef Q_WS_QWS
402 bool bogusWritingSystems;
403 QStringList fallbackFamilies;
404#endif
405 unsigned char writingSystems[QFontDatabase::WritingSystemsCount];
406
407 QtFontFoundry *foundry(const QString &f, bool = false);
408};
409
410#if !defined(QWS) && defined(Q_OS_MAC)
411inline static void qt_mac_get_fixed_pitch(QtFontFamily *f)
412{
413 if(f && !f->fixedPitchComputed) {
414 QFontMetrics fm(f->name);
415 f->fixedPitch = fm.width(QLatin1Char('i')) == fm.width(QLatin1Char('m'));
416 f->fixedPitchComputed = true;
417 }
418}
419#endif
420
421
422QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
423{
424 if (f.isNull() && count == 1)
425 return foundries[0];
426
427 for (int i = 0; i < count; i++) {
428 if (foundries[i]->name.compare(f, Qt::CaseInsensitive) == 0)
429 return foundries[i];
430 }
431 if (!create)
432 return 0;
433
434 if (!(count % 8))
435 foundries = (QtFontFoundry **)
436 realloc(foundries,
437 (((count+8) >> 3) << 3) * sizeof(QtFontFoundry *));
438
439 foundries[count] = new QtFontFoundry(f);
440 return foundries[count++];
441}
442
443// ### copied to tools/makeqpf/qpf2.cpp
444
445#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_WS_MAC)
446// see the Unicode subset bitfields in the MSDN docs
447static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
448 // Any,
449 { 127, 127 },
450 // Latin,
451 { 0, 127 },
452 // Greek,
453 { 7, 127 },
454 // Cyrillic,
455 { 9, 127 },
456 // Armenian,
457 { 10, 127 },
458 // Hebrew,
459 { 11, 127 },
460 // Arabic,
461 { 13, 127 },
462 // Syriac,
463 { 71, 127 },
464 //Thaana,
465 { 72, 127 },
466 //Devanagari,
467 { 15, 127 },
468 //Bengali,
469 { 16, 127 },
470 //Gurmukhi,
471 { 17, 127 },
472 //Gujarati,
473 { 18, 127 },
474 //Oriya,
475 { 19, 127 },
476 //Tamil,
477 { 20, 127 },
478 //Telugu,
479 { 21, 127 },
480 //Kannada,
481 { 22, 127 },
482 //Malayalam,
483 { 23, 127 },
484 //Sinhala,
485 { 73, 127 },
486 //Thai,
487 { 24, 127 },
488 //Lao,
489 { 25, 127 },
490 //Tibetan,
491 { 70, 127 },
492 //Myanmar,
493 { 74, 127 },
494 // Georgian,
495 { 26, 127 },
496 // Khmer,
497 { 80, 127 },
498 // SimplifiedChinese,
499 { 126, 127 },
500 // TraditionalChinese,
501 { 126, 127 },
502 // Japanese,
503 { 126, 127 },
504 // Korean,
505 { 56, 127 },
506 // Vietnamese,
507 { 0, 127 }, // same as latin1
508 // Other,
509 { 126, 127 }
510};
511
512#define SimplifiedChineseCsbBit 18
513#define TraditionalChineseCsbBit 20
514#define JapaneseCsbBit 17
515#define KoreanCsbBit 21
516
517static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2])
518{
519 QList<QFontDatabase::WritingSystem> writingSystems;
520 bool hasScript = false;
521
522 int i;
523 for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) {
524 int bit = requiredUnicodeBits[i][0];
525 int index = bit/32;
526 int flag = 1 << (bit&31);
527 if (bit != 126 && unicodeRange[index] & flag) {
528 bit = requiredUnicodeBits[i][1];
529 index = bit/32;
530
531 flag = 1 << (bit&31);
532 if (bit == 127 || unicodeRange[index] & flag) {
533 writingSystems.append(QFontDatabase::WritingSystem(i));
534 hasScript = true;
535 // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i);
536 }
537 }
538 }
539 if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) {
540 writingSystems.append(QFontDatabase::SimplifiedChinese);
541 hasScript = true;
542 //qDebug("font %s supports Simplified Chinese", familyName.latin1());
543 }
544 if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) {
545 writingSystems.append(QFontDatabase::TraditionalChinese);
546 hasScript = true;
547 //qDebug("font %s supports Traditional Chinese", familyName.latin1());
548 }
549 if(codePageRange[0] & (1 << JapaneseCsbBit)) {
550 writingSystems.append(QFontDatabase::Japanese);
551 hasScript = true;
552 //qDebug("font %s supports Japanese", familyName.latin1());
553 }
554 if(codePageRange[0] & (1 << KoreanCsbBit)) {
555 writingSystems.append(QFontDatabase::Korean);
556 hasScript = true;
557 //qDebug("font %s supports Korean", familyName.latin1());
558 }
559 if (!hasScript)
560 writingSystems.append(QFontDatabase::Symbol);
561
562 return writingSystems;
563}
564#endif
565
566class QFontDatabasePrivate
567{
568public:
569 QFontDatabasePrivate()
570 : count(0), families(0), reregisterAppFonts(false)
571#if defined(Q_WS_QWS)
572 , stream(0)
573#endif
574 { }
575 ~QFontDatabasePrivate() {
576 free();
577 }
578 QtFontFamily *family(const QString &f, bool = false);
579 void free() {
580 while (count--)
581 delete families[count];
582 ::free(families);
583 families = 0;
584 count = 0;
585 // don't clear the memory fonts!
586 }
587
588 int count;
589 QtFontFamily **families;
590
591 struct ApplicationFont {
592 QString fileName;
593 QByteArray data;
594#if defined(Q_OS_WIN)
595 HANDLE handle;
596 bool memoryFont;
597 QVector<FONTSIGNATURE> signatures;
598#elif defined(Q_WS_MAC)
599 ATSFontContainerRef handle;
600#endif
601 QStringList families;
602 };
603 QVector<ApplicationFont> applicationFonts;
604 int addAppFont(const QByteArray &fontData, const QString &fileName);
605 bool reregisterAppFonts;
606 bool isApplicationFont(const QString &fileName);
607
608 void invalidate();
609
610#if defined(Q_WS_QWS)
611 bool loadFromCache(const QString &fontPath);
612 void addFont(const QString &familyname, const char *foundryname, int weight,
613 bool italic, int pixelSize, const QByteArray &file, int fileIndex,
614 bool antialiased,
615 const QList<QFontDatabase::WritingSystem> &writingSystems = QList<QFontDatabase::WritingSystem>());
616 void addQPF2File(const QByteArray &file);
617#ifndef QT_NO_FREETYPE
618 QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray());
619#endif
620
621 QDataStream *stream;
622 QStringList fallbackFamilies;
623#endif
624};
625
626void QFontDatabasePrivate::invalidate()
627{
628 QFontCache::instance()->clear();
629 free();
630 emit static_cast<QApplication *>(QApplication::instance())->fontDatabaseChanged();
631}
632
633QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
634{
635 int low = 0;
636 int high = count;
637 int pos = count / 2;
638 int res = 1;
639 if (count) {
640 while ((res = families[pos]->name.compare(f, Qt::CaseInsensitive)) && pos != low) {
641 if (res > 0)
642 high = pos;
643 else
644 low = pos;
645 pos = (high + low) / 2;
646 };
647 if (!res)
648 return families[pos];
649 }
650 if (!create)
651 return 0;
652
653 if (res < 0)
654 pos++;
655
656 // qDebug("adding family %s at %d total=%d", f.latin1(), pos, count);
657 if (!(count % 8))
658 families = (QtFontFamily **)
659 realloc(families,
660 (((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
661
662 memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
663 families[pos] = new QtFontFamily(f);
664 count++;
665 return families[pos];
666}
667
668
669static const int scriptForWritingSystem[] = {
670 QUnicodeTables::Common, // Any
671 QUnicodeTables::Latin, // Latin
672 QUnicodeTables::Greek, // Greek
673 QUnicodeTables::Cyrillic, // Cyrillic
674 QUnicodeTables::Armenian, // Armenian
675 QUnicodeTables::Hebrew, // Hebrew
676 QUnicodeTables::Arabic, // Arabic
677 QUnicodeTables::Syriac, // Syriac
678 QUnicodeTables::Thaana, // Thaana
679 QUnicodeTables::Devanagari, // Devanagari
680 QUnicodeTables::Bengali, // Bengali
681 QUnicodeTables::Gurmukhi, // Gurmukhi
682 QUnicodeTables::Gujarati, // Gujarati
683 QUnicodeTables::Oriya, // Oriya
684 QUnicodeTables::Tamil, // Tamil
685 QUnicodeTables::Telugu, // Telugu
686 QUnicodeTables::Kannada, // Kannada
687 QUnicodeTables::Malayalam, // Malayalam
688 QUnicodeTables::Sinhala, // Sinhala
689 QUnicodeTables::Thai, // Thai
690 QUnicodeTables::Lao, // Lao
691 QUnicodeTables::Tibetan, // Tibetan
692 QUnicodeTables::Myanmar, // Myanmar
693 QUnicodeTables::Georgian, // Georgian
694 QUnicodeTables::Khmer, // Khmer
695 QUnicodeTables::Common, // SimplifiedChinese
696 QUnicodeTables::Common, // TraditionalChinese
697 QUnicodeTables::Common, // Japanese
698 QUnicodeTables::Hangul, // Korean
699 QUnicodeTables::Common, // Vietnamese
700 QUnicodeTables::Common, // Yi
701 QUnicodeTables::Common, // Tagalog
702 QUnicodeTables::Common, // Hanunoo
703 QUnicodeTables::Common, // Buhid
704 QUnicodeTables::Common, // Tagbanwa
705 QUnicodeTables::Common, // Limbu
706 QUnicodeTables::Common, // TaiLe
707 QUnicodeTables::Common, // Braille
708 QUnicodeTables::Common, // Symbol
709 QUnicodeTables::Ogham, // Ogham
710 QUnicodeTables::Runic // Runic
711};
712
713
714#if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN)
715static inline bool requiresOpenType(int writingSystem)
716{
717 return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
718 || writingSystem == QFontDatabase::Khmer);
719}
720static inline bool scriptRequiresOpenType(int script)
721{
722 return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala)
723 || script == QUnicodeTables::Khmer);
724}
725#endif
726
727
728/*!
729 \internal
730
731 This makes sense of the font family name:
732
733 if the family name contains a '[' and a ']', then we take the text
734 between the square brackets as the foundry, and the text before the
735 square brackets as the family (ie. "Arial [Monotype]")
736*/
737static void parseFontName(const QString &name, QString &foundry, QString &family)
738{
739 int i = name.indexOf(QLatin1Char('['));
740 int li = name.lastIndexOf(QLatin1Char(']'));
741 if (i >= 0 && li >= 0 && i < li) {
742 foundry = name.mid(i + 1, li - i - 1);
743 if (i > 0 && name[i - 1] == QLatin1Char(' '))
744 i--;
745 family = name.left(i);
746 } else {
747 foundry.clear();
748 family = name;
749 }
750
751 // capitalize the family/foundry names
752 bool space = true;
753 QChar *s = family.data();
754 int len = family.length();
755 while(len--) {
756 if (space) *s = s->toUpper();
757 space = s->isSpace();
758 ++s;
759 }
760
761 space = true;
762 s = foundry.data();
763 len = foundry.length();
764 while(len--) {
765 if (space) *s = s->toUpper();
766 space = s->isSpace();
767 ++s;
768 }
769}
770
771
772struct QtFontDesc
773{
774 inline QtFontDesc() : family(0), foundry(0), style(0), size(0), encoding(0), familyIndex(-1) {}
775 QtFontFamily *family;
776 QtFontFoundry *foundry;
777 QtFontStyle *style;
778 QtFontSize *size;
779 QtFontEncoding *encoding;
780 int familyIndex;
781};
782
783#if !defined(Q_WS_MAC)
784static void match(int script, const QFontDef &request,
785 const QString &family_name, const QString &foundry_name, int force_encoding_id,
786 QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>());
787
788#if defined(Q_WS_X11) || defined(Q_WS_QWS)
789static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef)
790{
791 fontDef->family = desc.family->name;
792 if (! desc.foundry->name.isEmpty() && desc.family->count > 1) {
793 fontDef->family += QString::fromLatin1(" [");
794 fontDef->family += desc.foundry->name;
795 fontDef->family += QString::fromLatin1("]");
796 }
797
798 if (desc.style->smoothScalable)
799 fontDef->pixelSize = request.pixelSize;
800 else if ((desc.style->bitmapScalable && (request.styleStrategy & QFont::PreferMatch)))
801 fontDef->pixelSize = request.pixelSize;
802 else
803 fontDef->pixelSize = desc.size->pixelSize;
804
805 fontDef->styleHint = request.styleHint;
806 fontDef->styleStrategy = request.styleStrategy;
807
808 fontDef->weight = desc.style->key.weight;
809 fontDef->style = desc.style->key.style;
810 fontDef->fixedPitch = desc.family->fixedPitch;
811 fontDef->stretch = desc.style->key.stretch;
812 fontDef->ignorePitch = false;
813}
814#endif
815#endif
816
817#if defined(Q_WS_X11) || defined(Q_WS_WIN)
818static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key)
819{
820 // look for the requested font in the engine data cache
821 d->engineData = QFontCache::instance()->findEngineData(key);
822 if (!d->engineData) {
823 // create a new one
824 d->engineData = new QFontEngineData;
825 QFontCache::instance()->insertEngineData(key, d->engineData);
826 } else {
827 d->engineData->ref.ref();
828 }
829}
830
831static QStringList familyList(const QFontDef &req)
832{
833 // list of families to try
834 QStringList family_list;
835 if (req.family.isEmpty())
836 return family_list;
837
838 QStringList list = req.family.split(QLatin1Char(','));
839 for (int i = 0; i < list.size(); ++i) {
840 QString str = list.at(i).trimmed();
841 if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
842 || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
843 str = str.mid(1, str.length() - 2);
844 family_list << str;
845 }
846
847 // append the substitute list for each family in family_list
848 QStringList subs_list;
849 QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
850 for (; it != end; ++it)
851 subs_list += QFont::substitutes(*it);
852// qDebug() << "adding substs: " << subs_list;
853
854 family_list += subs_list;
855
856 return family_list;
857}
858#endif
859
860Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb)
861Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
862
863// used in qfontengine_x11.cpp
864QMutex *qt_fontdatabase_mutex()
865{
866 return fontDatabaseMutex();
867}
868
869#define SMOOTH_SCALABLE 0xffff
870
871QT_BEGIN_INCLUDE_NAMESPACE
872#if defined(Q_WS_X11)
873# include "qfontdatabase_x11.cpp"
874#elif defined(Q_WS_MAC)
875# include "qfontdatabase_mac.cpp"
876#elif defined(Q_WS_WIN)
877# include "qfontdatabase_win.cpp"
878#elif defined(Q_WS_PM)
879# include "qfontdatabase_pm.cpp"
880#elif defined(Q_WS_QWS)
881# include "qfontdatabase_qws.cpp"
882#endif
883QT_END_INCLUDE_NAMESPACE
884
885static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey)
886{
887 int best = 0;
888 int dist = 0xffff;
889
890 for ( int i = 0; i < foundry->count; i++ ) {
891 QtFontStyle *style = foundry->styles[i];
892
893 int d = qAbs( styleKey.weight - style->key.weight );
894
895 if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
896 d += qAbs( styleKey.stretch - style->key.stretch );
897 }
898
899 if (styleKey.style != style->key.style) {
900 if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal)
901 // one is italic, the other oblique
902 d += 0x0001;
903 else
904 d += 0x1000;
905 }
906
907 if ( d < dist ) {
908 best = i;
909 dist = d;
910 }
911 }
912
913 FM_DEBUG( " best style has distance 0x%x", dist );
914 return foundry->styles[best];
915}
916
917#if defined(Q_WS_X11)
918static QtFontEncoding *findEncoding(int script, int styleStrategy,
919 QtFontSize *size, int force_encoding_id)
920{
921 QtFontEncoding *encoding = 0;
922
923 if (force_encoding_id >= 0) {
924 encoding = size->encodingID(force_encoding_id);
925 if (!encoding)
926 FM_DEBUG(" required encoding_id not available");
927 return encoding;
928 }
929
930 if (styleStrategy & (QFont::OpenGLCompatible | QFont::PreferBitmap)) {
931 FM_DEBUG(" PreferBitmap and/or OpenGL set, skipping Freetype");
932 } else {
933 encoding = size->encodingID(-1); // -1 == prefer Freetype
934 if (encoding)
935 return encoding;
936 }
937
938 // FT not available, find an XLFD font, trying the default encoding first
939 encoding = size->encodingID(QFontPrivate::defaultEncodingID);
940 if (encoding) {
941 // does it support the requested script?
942 bool supportsScript = false;
943 for (int ws = 1; !supportsScript && ws < QFontDatabase::WritingSystemsCount; ++ws) {
944 if (scriptForWritingSystem[ws] != script)
945 continue;
946 supportsScript = writingSystems_for_xlfd_encoding[encoding->encoding][ws];
947 }
948 if (!supportsScript)
949 encoding = 0;
950 }
951 // find the first encoding that supports the requested script
952 for (int ws = 1; !encoding && ws < QFontDatabase::WritingSystemsCount; ++ws) {
953 if (scriptForWritingSystem[ws] != script)
954 continue;
955 for (int x = 0; !encoding && x < size->count; ++x) {
956 const int enc = size->encodings[x].encoding;
957 if (writingSystems_for_xlfd_encoding[enc][ws])
958 encoding = size->encodings + x;
959 }
960 }
961
962 return encoding;
963}
964#endif // Q_WS_X11
965
966#if !defined(Q_WS_MAC)
967static
968unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
969 const QtFontFamily *family, const QString &foundry_name,
970 QtFontStyle::Key styleKey, int pixelSize, char pitch,
971 QtFontDesc *desc, int force_encoding_id)
972{
973 Q_UNUSED(force_encoding_id);
974 Q_UNUSED(script);
975 Q_UNUSED(pitch);
976
977 desc->foundry = 0;
978 desc->style = 0;
979 desc->size = 0;
980 desc->encoding = 0;
981
982
983 FM_DEBUG(" REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
984
985 for (int x = 0; x < family->count; ++x) {
986 QtFontFoundry *foundry = family->foundries[x];
987 if (!foundry_name.isEmpty() && foundry->name.compare(foundry_name, Qt::CaseInsensitive) != 0)
988 continue;
989
990 FM_DEBUG(" looking for matching style in foundry '%s' %d",
991 foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
992
993 QtFontStyle *style = bestStyle(foundry, styleKey);
994
995 if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
996 FM_DEBUG(" ForceOutline set, but not smoothly scalable");
997 continue;
998 }
999
1000 int px = -1;
1001 QtFontSize *size = 0;
1002
1003 // 1. see if we have an exact matching size
1004 if (!(styleStrategy & QFont::ForceOutline)) {
1005 size = style->pixelSize(pixelSize);
1006 if (size) {
1007 FM_DEBUG(" found exact size match (%d pixels)", size->pixelSize);
1008 px = size->pixelSize;
1009 }
1010 }
1011
1012 // 2. see if we have a smoothly scalable font
1013 if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
1014 size = style->pixelSize(SMOOTH_SCALABLE);
1015 if (size) {
1016 FM_DEBUG(" found smoothly scalable font (%d pixels)", pixelSize);
1017 px = pixelSize;
1018 }
1019 }
1020
1021 // 3. see if we have a bitmap scalable font
1022 if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
1023 size = style->pixelSize(0);
1024 if (size) {
1025 FM_DEBUG(" found bitmap scalable font (%d pixels)", pixelSize);
1026 px = pixelSize;
1027 }
1028 }
1029
1030#ifdef Q_WS_X11
1031 QtFontEncoding *encoding = 0;
1032#endif
1033
1034 // 4. find closest size match
1035 if (! size) {
1036 unsigned int distance = ~0u;
1037 for (int x = 0; x < style->count; ++x) {
1038#ifdef Q_WS_X11
1039 encoding =
1040 findEncoding(script, styleStrategy, style->pixelSizes + x, force_encoding_id);
1041 if (!encoding) {
1042 FM_DEBUG(" size %3d does not support the script we want",
1043 style->pixelSizes[x].pixelSize);
1044 continue;
1045 }
1046#endif
1047
1048 unsigned int d;
1049 if (style->pixelSizes[x].pixelSize < pixelSize) {
1050 // penalize sizes that are smaller than the
1051 // requested size, due to truncation from floating
1052 // point to integer conversions
1053 d = pixelSize - style->pixelSizes[x].pixelSize + 1;
1054 } else {
1055 d = style->pixelSizes[x].pixelSize - pixelSize;
1056 }
1057
1058 if (d < distance) {
1059 distance = d;
1060 size = style->pixelSizes + x;
1061 FM_DEBUG(" best size so far: %3d (%d)", size->pixelSize, pixelSize);
1062 }
1063 }
1064
1065 if (!size) {
1066 FM_DEBUG(" no size supports the script we want");
1067 continue;
1068 }
1069
1070 if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
1071 (distance * 10 / pixelSize) >= 2) {
1072 // the closest size is not close enough, go ahead and
1073 // use a bitmap scaled font
1074 size = style->pixelSize(0);
1075 px = pixelSize;
1076 } else {
1077 px = size->pixelSize;
1078 }
1079 }
1080
1081#ifdef Q_WS_X11
1082 if (size) {
1083 encoding = findEncoding(script, styleStrategy, size, force_encoding_id);
1084 if (!encoding) size = 0;
1085 }
1086 if (! encoding) {
1087 FM_DEBUG(" foundry doesn't support the script we want");
1088 continue;
1089 }
1090#endif // Q_WS_X11
1091
1092 unsigned int this_score = 0x0000;
1093 enum {
1094 PitchMismatch = 0x4000,
1095 StyleMismatch = 0x2000,
1096 BitmapScaledPenalty = 0x1000,
1097 EncodingMismatch = 0x0002,
1098 XLFDPenalty = 0x0001
1099 };
1100#ifdef Q_WS_X11
1101 if (encoding->encoding != -1) {
1102 this_score += XLFDPenalty;
1103 if (encoding->encoding != QFontPrivate::defaultEncodingID)
1104 this_score += EncodingMismatch;
1105 }
1106 if (pitch != '*') {
1107 if (!(pitch == 'm' && encoding->pitch == 'c') && pitch != encoding->pitch)
1108 this_score += PitchMismatch;
1109 }
1110#else
1111 if (pitch != '*') {
1112#if !defined(QWS) && defined(Q_OS_MAC)
1113 qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family));
1114#endif
1115 if ((pitch == 'm' && !family->fixedPitch)
1116 || (pitch == 'p' && family->fixedPitch))
1117 this_score += PitchMismatch;
1118 }
1119#endif
1120 if (styleKey != style->key)
1121 this_score += StyleMismatch;
1122 if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled
1123 this_score += BitmapScaledPenalty;
1124 if (px != pixelSize) // close, but not exact, size match
1125 this_score += qAbs(px - pixelSize);
1126
1127 if (this_score < score) {
1128 FM_DEBUG(" found a match: score %x best score so far %x",
1129 this_score, score);
1130
1131 score = this_score;
1132 desc->foundry = foundry;
1133 desc->style = style;
1134 desc->size = size;
1135#ifdef Q_WS_X11
1136 desc->encoding = encoding;
1137#endif // Q_WS_X11
1138 } else {
1139 FM_DEBUG(" score %x no better than best %x", this_score, score);
1140 }
1141 }
1142
1143 return score;
1144}
1145#endif
1146
1147#if !defined(Q_WS_MAC)
1148/*!
1149 \internal
1150
1151 Tries to find the best match for a given request and family/foundry
1152*/
1153static void match(int script, const QFontDef &request,
1154 const QString &family_name, const QString &foundry_name, int force_encoding_id,
1155 QtFontDesc *desc, const QList<int> &blacklistedFamilies)
1156{
1157 Q_UNUSED(force_encoding_id);
1158
1159 QtFontStyle::Key styleKey;
1160 styleKey.style = request.style;
1161 styleKey.weight = request.weight;
1162 styleKey.stretch = request.stretch;
1163 char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
1164
1165 FM_DEBUG("QFontDatabase::match\n"
1166 " request:\n"
1167 " family: %s [%s], script: %d\n"
1168 " weight: %d, style: %d\n"
1169 " stretch: %d\n"
1170 " pixelSize: %d\n"
1171 " pitch: %c",
1172 family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
1173 foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
1174 script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
1175#if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11)
1176 if (force_encoding_id >= 0) {
1177 FM_DEBUG(" required encoding: %d", force_encoding_id);
1178 }
1179#endif
1180
1181 desc->family = 0;
1182 desc->foundry = 0;
1183 desc->style = 0;
1184 desc->size = 0;
1185 desc->encoding = 0;
1186 desc->familyIndex = -1;
1187
1188 unsigned int score = ~0u;
1189
1190 load(family_name, script);
1191
1192 QFontDatabasePrivate *db = privateDb();
1193 for (int x = 0; x < db->count; ++x) {
1194 if (blacklistedFamilies.contains(x))
1195 continue;
1196 QtFontDesc test;
1197 test.family = db->families[x];
1198 test.familyIndex = x;
1199
1200 if (!family_name.isEmpty()
1201 && test.family->name.compare(family_name, Qt::CaseInsensitive) != 0
1202#ifdef Q_WS_WIN
1203 && test.family->english_name.compare(family_name, Qt::CaseInsensitive) != 0
1204#endif
1205 )
1206 continue;
1207
1208 if (family_name.isEmpty())
1209 load(test.family->name, script);
1210
1211 uint score_adjust = 0;
1212
1213 bool supported = (script == QUnicodeTables::Common);
1214 for (int ws = 1; !supported && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1215 if (scriptForWritingSystem[ws] != script)
1216 continue;
1217 if (test.family->writingSystems[ws] & QtFontFamily::Supported)
1218 supported = true;
1219 }
1220 if (!supported) {
1221 // family not supported in the script we want
1222 continue;
1223 }
1224
1225 // as we know the script is supported, we can be sure
1226 // to find a matching font here.
1227 unsigned int newscore =
1228 bestFoundry(script, score, request.styleStrategy,
1229 test.family, foundry_name, styleKey, request.pixelSize, pitch,
1230 &test, force_encoding_id);
1231 if (test.foundry == 0) {
1232 // the specific foundry was not found, so look for
1233 // any foundry matching our requirements
1234 newscore = bestFoundry(script, score, request.styleStrategy, test.family,
1235 QString(), styleKey, request.pixelSize,
1236 pitch, &test, force_encoding_id);
1237 }
1238 newscore += score_adjust;
1239
1240 if (newscore < score) {
1241 score = newscore;
1242 *desc = test;
1243 }
1244 if (newscore < 10) // xlfd instead of FT... just accept it
1245 break;
1246 }
1247}
1248#endif
1249
1250static QString styleStringHelper(int weight, QFont::Style style)
1251{
1252 QString result;
1253 if (weight >= QFont::Black)
1254 result = qApp->translate("QFontDatabase", "Black");
1255 else if (weight >= QFont::Bold)
1256 result = qApp->translate("QFontDatabase", "Bold");
1257 else if (weight >= QFont::DemiBold)
1258 result = qApp->translate("QFontDatabase", "Demi Bold");
1259 else if (weight < QFont::Normal)
1260 result = qApp->translate("QFontDatabase", "Light");
1261
1262 if (style == QFont::StyleItalic)
1263 result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Italic");
1264 else if (style == QFont::StyleOblique)
1265 result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Oblique");
1266
1267 if (result.isEmpty())
1268 result = qApp->translate("QFontDatabase", "Normal");
1269
1270 return result.simplified();
1271}
1272
1273/*!
1274 Returns a string that describes the style of the \a font. For
1275 example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1276 string may be returned.
1277*/
1278QString QFontDatabase::styleString(const QFont &font)
1279{
1280 return styleStringHelper(font.weight(), font.style());
1281}
1282
1283/*!
1284 Returns a string that describes the style of the \a fontInfo. For
1285 example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1286 string may be returned.
1287*/
1288QString QFontDatabase::styleString(const QFontInfo &fontInfo)
1289{
1290 return styleStringHelper(fontInfo.weight(), fontInfo.style());
1291}
1292
1293
1294/*!
1295 \class QFontDatabase
1296 \threadsafe
1297
1298 \brief The QFontDatabase class provides information about the fonts available in the underlying window system.
1299
1300 \ingroup environment
1301 \ingroup multimedia
1302 \ingroup text
1303
1304 The most common uses of this class are to query the database for
1305 the list of font families() and for the pointSizes() and styles()
1306 that are available for each family. An alternative to pointSizes()
1307 is smoothSizes() which returns the sizes at which a given family
1308 and style will look attractive.
1309
1310 If the font family is available from two or more foundries the
1311 foundry name is included in the family name, e.g. "Helvetica
1312 [Adobe]" and "Helvetica [Cronyx]". When you specify a family you
1313 can either use the old hyphenated Qt 2.x "foundry-family" format,
1314 e.g. "Cronyx-Helvetica", or the new bracketed Qt 3.x "family
1315 [foundry]" format e.g. "Helvetica [Cronyx]". If the family has a
1316 foundry it is always returned, e.g. by families(), using the
1317 bracketed format.
1318
1319 The font() function returns a QFont given a family, style and
1320 point size.
1321
1322 A family and style combination can be checked to see if it is
1323 italic() or bold(), and to retrieve its weight(). Similarly we can
1324 call isBitmapScalable(), isSmoothlyScalable(), isScalable() and
1325 isFixedPitch().
1326
1327 Use the styleString() to obtain a text version of a style.
1328
1329 The QFontDatabase class also supports some static functions, for
1330 example, standardSizes(). You can retrieve the description of a
1331 writing system using writingSystemName(), and a sample of
1332 characters in a writing system with writingSystemSample().
1333
1334 Example:
1335
1336 \snippet doc/src/snippets/qfontdatabase/main.cpp 0
1337 \snippet doc/src/snippets/qfontdatabase/main.cpp 1
1338
1339 This example gets the list of font families, the list of
1340 styles for each family, and the point sizes that are available for
1341 each combination of family and style, displaying this information
1342 in a tree view.
1343
1344 \sa QFont, QFontInfo, QFontMetrics, QFontComboBox, {Character Map Example}
1345*/
1346
1347/*!
1348 Creates a font database object.
1349*/
1350QFontDatabase::QFontDatabase()
1351{
1352 QMutexLocker locker(fontDatabaseMutex());
1353 createDatabase();
1354 d = privateDb();
1355}
1356
1357/*!
1358 \enum QFontDatabase::WritingSystem
1359
1360 \value Any
1361 \value Latin
1362 \value Greek
1363 \value Cyrillic
1364 \value Armenian
1365 \value Hebrew
1366 \value Arabic
1367 \value Syriac
1368 \value Thaana
1369 \value Devanagari
1370 \value Bengali
1371 \value Gurmukhi
1372 \value Gujarati
1373 \value Oriya
1374 \value Tamil
1375 \value Telugu
1376 \value Kannada
1377 \value Malayalam
1378 \value Sinhala
1379 \value Thai
1380 \value Lao
1381 \value Tibetan
1382 \value Myanmar
1383 \value Georgian
1384 \value Khmer
1385 \value SimplifiedChinese
1386 \value TraditionalChinese
1387 \value Japanese
1388 \value Korean
1389 \value Vietnamese
1390 \value Symbol
1391 \value Other (the same as Symbol)
1392 \value Ogham
1393 \value Runic
1394
1395 \omitvalue WritingSystemsCount
1396*/
1397
1398/*!
1399 Returns a sorted list of the available writing systems. This is
1400 list generated from information about all installed fonts on the
1401 system.
1402
1403 \sa families()
1404*/
1405QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const
1406{
1407 QMutexLocker locker(fontDatabaseMutex());
1408
1409 QT_PREPEND_NAMESPACE(load)();
1410#ifdef Q_WS_X11
1411 checkSymbolFonts();
1412#endif
1413
1414 QList<WritingSystem> list;
1415 for (int i = 0; i < d->count; ++i) {
1416 QtFontFamily *family = d->families[i];
1417 if (family->count == 0)
1418 continue;
1419 for (int x = Latin; x < WritingSystemsCount; ++x) {
1420 const WritingSystem writingSystem = WritingSystem(x);
1421 if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported))
1422 continue;
1423 if (!list.contains(writingSystem))
1424 list.append(writingSystem);
1425 }
1426 }
1427 qSort(list);
1428 return list;
1429}
1430
1431
1432/*!
1433 Returns a sorted list of the writing systems supported by a given
1434 font \a family.
1435
1436 \sa families()
1437*/
1438QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems(const QString &family) const
1439{
1440 QString familyName, foundryName;
1441 parseFontName(family, foundryName, familyName);
1442
1443 QMutexLocker locker(fontDatabaseMutex());
1444
1445 QT_PREPEND_NAMESPACE(load)();
1446#ifdef Q_WS_X11
1447 checkSymbolFonts(familyName);
1448#endif
1449
1450 QList<WritingSystem> list;
1451 QtFontFamily *f = d->family(familyName);
1452 if (!f || f->count == 0)
1453 return list;
1454
1455 for (int x = Latin; x < WritingSystemsCount; ++x) {
1456 const WritingSystem writingSystem = WritingSystem(x);
1457 if (f->writingSystems[writingSystem] & QtFontFamily::Supported)
1458 list.append(writingSystem);
1459 }
1460 return list;
1461}
1462
1463
1464/*!
1465 Returns a sorted list of the available font families which support
1466 the \a writingSystem.
1467
1468 If a family exists in several foundries, the returned name for
1469 that font is in the form "family [foundry]". Examples: "Times
1470 [Adobe]", "Times [Cronyx]", "Palatino".
1471
1472 \sa writingSystems()
1473*/
1474QStringList QFontDatabase::families(WritingSystem writingSystem) const
1475{
1476 QMutexLocker locker(fontDatabaseMutex());
1477
1478 QT_PREPEND_NAMESPACE(load)();
1479#ifdef Q_WS_X11
1480 if (writingSystem != Any)
1481 checkSymbolFonts();
1482#endif
1483
1484 QStringList flist;
1485 for (int i = 0; i < d->count; i++) {
1486 QtFontFamily *f = d->families[i];
1487 if (f->count == 0)
1488 continue;
1489 if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported))
1490 continue;
1491 if (f->count == 1) {
1492 flist.append(f->name);
1493 } else {
1494 for (int j = 0; j < f->count; j++) {
1495 QString str = f->name;
1496 QString foundry = f->foundries[j]->name;
1497 if (!foundry.isEmpty()) {
1498 str += QLatin1String(" [");
1499 str += foundry;
1500 str += QLatin1String("]");
1501 }
1502 flist.append(str);
1503 }
1504 }
1505 }
1506 return flist;
1507}
1508
1509/*!
1510 Returns a list of the styles available for the font family \a
1511 family. Some example styles: "Light", "Light Italic", "Bold",
1512 "Oblique", "Demi". The list may be empty.
1513
1514 \sa families()
1515*/
1516QStringList QFontDatabase::styles(const QString &family) const
1517{
1518 QString familyName, foundryName;
1519 parseFontName(family, foundryName, familyName);
1520
1521 QMutexLocker locker(fontDatabaseMutex());
1522
1523 QT_PREPEND_NAMESPACE(load)(familyName);
1524
1525 QStringList l;
1526 QtFontFamily *f = d->family(familyName);
1527 if (!f)
1528 return l;
1529
1530 QtFontFoundry allStyles(foundryName);
1531 for (int j = 0; j < f->count; j++) {
1532 QtFontFoundry *foundry = f->foundries[j];
1533 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1534 for (int k = 0; k < foundry->count; k++) {
1535 QtFontStyle::Key ke(foundry->styles[k]->key);
1536 ke.stretch = 0;
1537 allStyles.style(ke, true);
1538 }
1539 }
1540 }
1541
1542 for (int i = 0; i < allStyles.count; i++)
1543 l.append(styleStringHelper(allStyles.styles[i]->key.weight, (QFont::Style)allStyles.styles[i]->key.style));
1544 return l;
1545}
1546
1547/*!
1548 Returns true if the font that has family \a family and style \a
1549 style is fixed pitch; otherwise returns false.
1550*/
1551
1552bool QFontDatabase::isFixedPitch(const QString &family,
1553 const QString &style) const
1554{
1555 Q_UNUSED(style);
1556
1557 QString familyName, foundryName;
1558 parseFontName(family, foundryName, familyName);
1559
1560 QMutexLocker locker(fontDatabaseMutex());
1561
1562 QT_PREPEND_NAMESPACE(load)(familyName);
1563
1564 QtFontFamily *f = d->family(familyName);
1565#if !defined(QWS) && defined(Q_OS_MAC)
1566 qt_mac_get_fixed_pitch(f);
1567#endif
1568 return (f && f->fixedPitch);
1569}
1570
1571/*!
1572 Returns true if the font that has family \a family and style \a
1573 style is a scalable bitmap font; otherwise returns false. Scaling
1574 a bitmap font usually produces an unattractive hardly readable
1575 result, because the pixels of the font are scaled. If you need to
1576 scale a bitmap font it is better to scale it to one of the fixed
1577 sizes returned by smoothSizes().
1578
1579 \sa isScalable(), isSmoothlyScalable()
1580*/
1581bool QFontDatabase::isBitmapScalable(const QString &family,
1582 const QString &style) const
1583{
1584 bool bitmapScalable = false;
1585 QString familyName, foundryName;
1586 parseFontName(family, foundryName, familyName);
1587
1588 QMutexLocker locker(fontDatabaseMutex());
1589
1590 QT_PREPEND_NAMESPACE(load)(familyName);
1591
1592 QtFontStyle::Key styleKey(style);
1593
1594 QtFontFamily *f = d->family(familyName);
1595 if (!f) return bitmapScalable;
1596
1597 for (int j = 0; j < f->count; j++) {
1598 QtFontFoundry *foundry = f->foundries[j];
1599 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1600 for (int k = 0; k < foundry->count; k++)
1601 if ((style.isEmpty() || foundry->styles[k]->key == styleKey)
1602 && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
1603 bitmapScalable = true;
1604 goto end;
1605 }
1606 }
1607 }
1608 end:
1609 return bitmapScalable;
1610}
1611
1612
1613/*!
1614 Returns true if the font that has family \a family and style \a
1615 style is smoothly scalable; otherwise returns false. If this
1616 function returns true, it's safe to scale this font to any size,
1617 and the result will always look attractive.
1618
1619 \sa isScalable(), isBitmapScalable()
1620*/
1621bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const
1622{
1623 bool smoothScalable = false;
1624 QString familyName, foundryName;
1625 parseFontName(family, foundryName, familyName);
1626
1627 QMutexLocker locker(fontDatabaseMutex());
1628
1629 QT_PREPEND_NAMESPACE(load)(familyName);
1630
1631 QtFontStyle::Key styleKey(style);
1632
1633 QtFontFamily *f = d->family(familyName);
1634 if (!f) return smoothScalable;
1635
1636 for (int j = 0; j < f->count; j++) {
1637 QtFontFoundry *foundry = f->foundries[j];
1638 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1639 for (int k = 0; k < foundry->count; k++)
1640 if ((style.isEmpty() || foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
1641 smoothScalable = true;
1642 goto end;
1643 }
1644 }
1645 }
1646 end:
1647 return smoothScalable;
1648}
1649
1650/*!
1651 Returns true if the font that has family \a family and style \a
1652 style is scalable; otherwise returns false.
1653
1654 \sa isBitmapScalable(), isSmoothlyScalable()
1655*/
1656bool QFontDatabase::isScalable(const QString &family,
1657 const QString &style) const
1658{
1659 QMutexLocker locker(fontDatabaseMutex());
1660 if (isSmoothlyScalable(family, style))
1661 return true;
1662 return isBitmapScalable(family, style);
1663}
1664
1665
1666/*!
1667 Returns a list of the point sizes available for the font that has
1668 family \a family and style \a style. The list may be empty.
1669
1670 \sa smoothSizes(), standardSizes()
1671*/
1672QList<int> QFontDatabase::pointSizes(const QString &family,
1673 const QString &style)
1674{
1675#if defined(Q_WS_WIN)
1676 // windows and macosx are always smoothly scalable
1677 Q_UNUSED(family);
1678 Q_UNUSED(style);
1679 return standardSizes();
1680#else
1681 bool smoothScalable = false;
1682 QString familyName, foundryName;
1683 parseFontName(family, foundryName, familyName);
1684
1685 QMutexLocker locker(fontDatabaseMutex());
1686
1687 QT_PREPEND_NAMESPACE(load)(familyName);
1688
1689 QtFontStyle::Key styleKey(style);
1690
1691 QList<int> sizes;
1692
1693 QtFontFamily *fam = d->family(familyName);
1694 if (!fam) return sizes;
1695
1696
1697#ifdef Q_WS_X11
1698 int dpi = QX11Info::appDpiY();
1699#else
1700 const int dpi = qt_defaultDpiY(); // embedded
1701#endif
1702
1703 for (int j = 0; j < fam->count; j++) {
1704 QtFontFoundry *foundry = fam->foundries[j];
1705 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1706 QtFontStyle *style = foundry->style(styleKey);
1707 if (!style) continue;
1708
1709 if (style->smoothScalable) {
1710 smoothScalable = true;
1711 goto end;
1712 }
1713 for (int l = 0; l < style->count; l++) {
1714 const QtFontSize *size = style->pixelSizes + l;
1715
1716 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1717 const uint pointSize = qRound(size->pixelSize * 72.0 / dpi);
1718 if (! sizes.contains(pointSize))
1719 sizes.append(pointSize);
1720 }
1721 }
1722 }
1723 }
1724 end:
1725 if (smoothScalable)
1726 return standardSizes();
1727
1728 qSort(sizes);
1729 return sizes;
1730#endif
1731}
1732
1733/*!
1734 Returns a QFont object that has family \a family, style \a style
1735 and point size \a pointSize. If no matching font could be created,
1736 a QFont object that uses the application's default font is
1737 returned.
1738*/
1739QFont QFontDatabase::font(const QString &family, const QString &style,
1740 int pointSize) const
1741{
1742 QString familyName, foundryName;
1743 parseFontName(family, foundryName, familyName);
1744
1745 QMutexLocker locker(fontDatabaseMutex());
1746
1747 QT_PREPEND_NAMESPACE(load)(familyName);
1748
1749 QtFontFoundry allStyles(foundryName);
1750 QtFontFamily *f = d->family(familyName);
1751 if (!f) return QApplication::font();
1752
1753 for (int j = 0; j < f->count; j++) {
1754 QtFontFoundry *foundry = f->foundries[j];
1755 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1756 for (int k = 0; k < foundry->count; k++)
1757 allStyles.style(foundry->styles[k]->key, true);
1758 }
1759 }
1760
1761 QtFontStyle::Key styleKey(style);
1762 QtFontStyle *s = bestStyle(&allStyles, styleKey);
1763
1764 if (!s) // no styles found?
1765 return QApplication::font();
1766 QFont fnt(family, pointSize, s->key.weight);
1767 fnt.setStyle((QFont::Style)s->key.style);
1768 return fnt;
1769}
1770
1771
1772/*!
1773 Returns the point sizes of a font that has family \a family and
1774 style \a style that will look attractive. The list may be empty.
1775 For non-scalable fonts and bitmap scalable fonts, this function
1776 is equivalent to pointSizes().
1777
1778 \sa pointSizes(), standardSizes()
1779*/
1780QList<int> QFontDatabase::smoothSizes(const QString &family,
1781 const QString &style)
1782{
1783#ifdef Q_WS_WIN
1784 Q_UNUSED(family);
1785 Q_UNUSED(style);
1786 return QFontDatabase::standardSizes();
1787#else
1788 bool smoothScalable = false;
1789 QString familyName, foundryName;
1790 parseFontName(family, foundryName, familyName);
1791
1792 QMutexLocker locker(fontDatabaseMutex());
1793
1794 QT_PREPEND_NAMESPACE(load)(familyName);
1795
1796 QtFontStyle::Key styleKey(style);
1797
1798 QList<int> sizes;
1799
1800 QtFontFamily *fam = d->family(familyName);
1801 if (!fam)
1802 return sizes;
1803
1804#ifdef Q_WS_X11
1805 int dpi = QX11Info::appDpiY();
1806#else
1807 const int dpi = qt_defaultDpiY(); // embedded
1808#endif
1809
1810 for (int j = 0; j < fam->count; j++) {
1811 QtFontFoundry *foundry = fam->foundries[j];
1812 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1813 QtFontStyle *style = foundry->style(styleKey);
1814 if (!style) continue;
1815
1816 if (style->smoothScalable) {
1817 smoothScalable = true;
1818 goto end;
1819 }
1820 for (int l = 0; l < style->count; l++) {
1821 const QtFontSize *size = style->pixelSizes + l;
1822
1823 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1824 const uint pointSize = qRound(size->pixelSize * 72.0 / dpi);
1825 if (! sizes.contains(pointSize))
1826 sizes.append(pointSize);
1827 }
1828 }
1829 }
1830 }
1831 end:
1832 if (smoothScalable)
1833 return QFontDatabase::standardSizes();
1834
1835 qSort(sizes);
1836 return sizes;
1837#endif
1838}
1839
1840
1841/*!
1842 Returns a list of standard font sizes.
1843
1844 \sa smoothSizes(), pointSizes()
1845*/
1846QList<int> QFontDatabase::standardSizes()
1847{
1848 QList<int> ret;
1849 static const unsigned short standard[] =
1850 { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
1851 const unsigned short *sizes = standard;
1852 while (*sizes) ret << *sizes++;
1853 return ret;
1854}
1855
1856
1857/*!
1858 Returns true if the font that has family \a family and style \a
1859 style is italic; otherwise returns false.
1860
1861 \sa weight(), bold()
1862*/
1863bool QFontDatabase::italic(const QString &family, const QString &style) const
1864{
1865 QString familyName, foundryName;
1866 parseFontName(family, foundryName, familyName);
1867
1868 QMutexLocker locker(fontDatabaseMutex());
1869
1870 QT_PREPEND_NAMESPACE(load)(familyName);
1871
1872 QtFontFoundry allStyles(foundryName);
1873 QtFontFamily *f = d->family(familyName);
1874 if (!f) return false;
1875
1876 for (int j = 0; j < f->count; j++) {
1877 QtFontFoundry *foundry = f->foundries[j];
1878 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1879 for (int k = 0; k < foundry->count; k++)
1880 allStyles.style(foundry->styles[k]->key, true);
1881 }
1882 }
1883
1884 QtFontStyle::Key styleKey(style);
1885 QtFontStyle *s = allStyles.style(styleKey);
1886 return s && s->key.style == QFont::StyleItalic;
1887}
1888
1889
1890/*!
1891 Returns true if the font that has family \a family and style \a
1892 style is bold; otherwise returns false.
1893
1894 \sa italic(), weight()
1895*/
1896bool QFontDatabase::bold(const QString &family,
1897 const QString &style) const
1898{
1899 QString familyName, foundryName;
1900 parseFontName(family, foundryName, familyName);
1901
1902 QMutexLocker locker(fontDatabaseMutex());
1903
1904 QT_PREPEND_NAMESPACE(load)(familyName);
1905
1906 QtFontFoundry allStyles(foundryName);
1907 QtFontFamily *f = d->family(familyName);
1908 if (!f) return false;
1909
1910 for (int j = 0; j < f->count; j++) {
1911 QtFontFoundry *foundry = f->foundries[j];
1912 if (foundryName.isEmpty() ||
1913 foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1914 for (int k = 0; k < foundry->count; k++)
1915 allStyles.style(foundry->styles[k]->key, true);
1916 }
1917 }
1918
1919 QtFontStyle::Key styleKey(style);
1920 QtFontStyle *s = allStyles.style(styleKey);
1921 return s && s->key.weight >= QFont::Bold;
1922}
1923
1924
1925/*!
1926 Returns the weight of the font that has family \a family and style
1927 \a style. If there is no such family and style combination,
1928 returns -1.
1929
1930 \sa italic(), bold()
1931*/
1932int QFontDatabase::weight(const QString &family,
1933 const QString &style) const
1934{
1935 QString familyName, foundryName;
1936 parseFontName(family, foundryName, familyName);
1937
1938 QMutexLocker locker(fontDatabaseMutex());
1939
1940 QT_PREPEND_NAMESPACE(load)(familyName);
1941
1942 QtFontFoundry allStyles(foundryName);
1943 QtFontFamily *f = d->family(familyName);
1944 if (!f) return -1;
1945
1946 for (int j = 0; j < f->count; j++) {
1947 QtFontFoundry *foundry = f->foundries[j];
1948 if (foundryName.isEmpty() ||
1949 foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1950 for (int k = 0; k < foundry->count; k++)
1951 allStyles.style(foundry->styles[k]->key, true);
1952 }
1953 }
1954
1955 QtFontStyle::Key styleKey(style);
1956 QtFontStyle *s = allStyles.style(styleKey);
1957 return s ? s->key.weight : -1;
1958}
1959
1960
1961/*!
1962 Returns the names the \a writingSystem (e.g. for displaying to the
1963 user in a dialog).
1964*/
1965QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
1966{
1967 const char *name = 0;
1968 switch (writingSystem) {
1969 case Any:
1970 name = QT_TRANSLATE_NOOP("QFontDatabase", "Any");
1971 break;
1972 case Latin:
1973 name = QT_TRANSLATE_NOOP("QFontDatabase", "Latin");
1974 break;
1975 case Greek:
1976 name = QT_TRANSLATE_NOOP("QFontDatabase", "Greek");
1977 break;
1978 case Cyrillic:
1979 name = QT_TRANSLATE_NOOP("QFontDatabase", "Cyrillic");
1980 break;
1981 case Armenian:
1982 name = QT_TRANSLATE_NOOP("QFontDatabase", "Armenian");
1983 break;
1984 case Hebrew:
1985 name = QT_TRANSLATE_NOOP("QFontDatabase", "Hebrew");
1986 break;
1987 case Arabic:
1988 name = QT_TRANSLATE_NOOP("QFontDatabase", "Arabic");
1989 break;
1990 case Syriac:
1991 name = QT_TRANSLATE_NOOP("QFontDatabase", "Syriac");
1992 break;
1993 case Thaana:
1994 name = QT_TRANSLATE_NOOP("QFontDatabase", "Thaana");
1995 break;
1996 case Devanagari:
1997 name = QT_TRANSLATE_NOOP("QFontDatabase", "Devanagari");
1998 break;
1999 case Bengali:
2000 name = QT_TRANSLATE_NOOP("QFontDatabase", "Bengali");
2001 break;
2002 case Gurmukhi:
2003 name = QT_TRANSLATE_NOOP("QFontDatabase", "Gurmukhi");
2004 break;
2005 case Gujarati:
2006 name = QT_TRANSLATE_NOOP("QFontDatabase", "Gujarati");
2007 break;
2008 case Oriya:
2009 name = QT_TRANSLATE_NOOP("QFontDatabase", "Oriya");
2010 break;
2011 case Tamil:
2012 name = QT_TRANSLATE_NOOP("QFontDatabase", "Tamil");
2013 break;
2014 case Telugu:
2015 name = QT_TRANSLATE_NOOP("QFontDatabase", "Telugu");
2016 break;
2017 case Kannada:
2018 name = QT_TRANSLATE_NOOP("QFontDatabase", "Kannada");
2019 break;
2020 case Malayalam:
2021 name = QT_TRANSLATE_NOOP("QFontDatabase", "Malayalam");
2022 break;
2023 case Sinhala:
2024 name = QT_TRANSLATE_NOOP("QFontDatabase", "Sinhala");
2025 break;
2026 case Thai:
2027 name = QT_TRANSLATE_NOOP("QFontDatabase", "Thai");
2028 break;
2029 case Lao:
2030 name = QT_TRANSLATE_NOOP("QFontDatabase", "Lao");
2031 break;
2032 case Tibetan:
2033 name = QT_TRANSLATE_NOOP("QFontDatabase", "Tibetan");
2034 break;
2035 case Myanmar:
2036 name = QT_TRANSLATE_NOOP("QFontDatabase", "Myanmar");
2037 break;
2038 case Georgian:
2039 name = QT_TRANSLATE_NOOP("QFontDatabase", "Georgian");
2040 break;
2041 case Khmer:
2042 name = QT_TRANSLATE_NOOP("QFontDatabase", "Khmer");
2043 break;
2044 case SimplifiedChinese:
2045 name = QT_TRANSLATE_NOOP("QFontDatabase", "Simplified Chinese");
2046 break;
2047 case TraditionalChinese:
2048 name = QT_TRANSLATE_NOOP("QFontDatabase", "Traditional Chinese");
2049 break;
2050 case Japanese:
2051 name = QT_TRANSLATE_NOOP("QFontDatabase", "Japanese");
2052 break;
2053 case Korean:
2054 name = QT_TRANSLATE_NOOP("QFontDatabase", "Korean");
2055 break;
2056 case Vietnamese:
2057 name = QT_TRANSLATE_NOOP("QFontDatabase", "Vietnamese");
2058 break;
2059 case Symbol:
2060 name = QT_TRANSLATE_NOOP("QFontDatabase", "Symbol");
2061 break;
2062 case Ogham:
2063 name = QT_TRANSLATE_NOOP("QFontDatabase", "Ogham");
2064 break;
2065 case Runic:
2066 name = QT_TRANSLATE_NOOP("QFontDatabase", "Runic");
2067 break;
2068 default:
2069 Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
2070 break;
2071 }
2072 return qApp ? qApp->translate("QFontDatabase", name) : QString::fromLatin1(name);
2073}
2074
2075
2076/*!
2077 Returns a string with sample characters from \a writingSystem.
2078*/
2079QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
2080{
2081 QString sample;
2082 switch (writingSystem) {
2083 case Any:
2084 case Symbol:
2085 // show only ascii characters
2086 sample += QLatin1String("AaBbzZ");
2087 break;
2088 case Latin:
2089 // This is cheating... we only show latin-1 characters so that we don't
2090 // end up loading lots of fonts - at least on X11...
2091 sample = QLatin1String("Aa");
2092 sample += QChar(0x00C3);
2093 sample += QChar(0x00E1);
2094 sample += QLatin1String("Zz");
2095 break;
2096 case Greek:
2097 sample += QChar(0x0393);
2098 sample += QChar(0x03B1);
2099 sample += QChar(0x03A9);
2100 sample += QChar(0x03C9);
2101 break;
2102 case Cyrillic:
2103 sample += QChar(0x0414);
2104 sample += QChar(0x0434);
2105 sample += QChar(0x0436);
2106 sample += QChar(0x044f);
2107 break;
2108 case Armenian:
2109 sample += QChar(0x053f);
2110 sample += QChar(0x054f);
2111 sample += QChar(0x056f);
2112 sample += QChar(0x057f);
2113 break;
2114 case Hebrew:
2115 sample += QChar(0x05D0);
2116 sample += QChar(0x05D1);
2117 sample += QChar(0x05D2);
2118 sample += QChar(0x05D3);
2119 break;
2120 case Arabic:
2121 sample += QChar(0x0628);
2122 sample += QChar(0x0629);
2123 sample += QChar(0x062A);
2124 sample += QChar(0x063A);
2125 break;
2126 case Syriac:
2127 sample += QChar(0x0715);
2128 sample += QChar(0x0725);
2129 sample += QChar(0x0716);
2130 sample += QChar(0x0726);
2131 break;
2132 case Thaana:
2133 sample += QChar(0x0784);
2134 sample += QChar(0x0794);
2135 sample += QChar(0x078c);
2136 sample += QChar(0x078d);
2137 break;
2138 case Devanagari:
2139 sample += QChar(0x0905);
2140 sample += QChar(0x0915);
2141 sample += QChar(0x0925);
2142 sample += QChar(0x0935);
2143 break;
2144 case Bengali:
2145 sample += QChar(0x0986);
2146 sample += QChar(0x0996);
2147 sample += QChar(0x09a6);
2148 sample += QChar(0x09b6);
2149 break;
2150 case Gurmukhi:
2151 sample += QChar(0x0a05);
2152 sample += QChar(0x0a15);
2153 sample += QChar(0x0a25);
2154 sample += QChar(0x0a35);
2155 break;
2156 case Gujarati:
2157 sample += QChar(0x0a85);
2158 sample += QChar(0x0a95);
2159 sample += QChar(0x0aa5);
2160 sample += QChar(0x0ab5);
2161 break;
2162 case Oriya:
2163 sample += QChar(0x0b06);
2164 sample += QChar(0x0b16);
2165 sample += QChar(0x0b2b);
2166 sample += QChar(0x0b36);
2167 break;
2168 case Tamil:
2169 sample += QChar(0x0b89);
2170 sample += QChar(0x0b99);
2171 sample += QChar(0x0ba9);
2172 sample += QChar(0x0bb9);
2173 break;
2174 case Telugu:
2175 sample += QChar(0x0c05);
2176 sample += QChar(0x0c15);
2177 sample += QChar(0x0c25);
2178 sample += QChar(0x0c35);
2179 break;
2180 case Kannada:
2181 sample += QChar(0x0c85);
2182 sample += QChar(0x0c95);
2183 sample += QChar(0x0ca5);
2184 sample += QChar(0x0cb5);
2185 break;
2186 case Malayalam:
2187 sample += QChar(0x0d05);
2188 sample += QChar(0x0d15);
2189 sample += QChar(0x0d25);
2190 sample += QChar(0x0d35);
2191 break;
2192 case Sinhala:
2193 sample += QChar(0x0d90);
2194 sample += QChar(0x0da0);
2195 sample += QChar(0x0db0);
2196 sample += QChar(0x0dc0);
2197 break;
2198 case Thai:
2199 sample += QChar(0x0e02);
2200 sample += QChar(0x0e12);
2201 sample += QChar(0x0e22);
2202 sample += QChar(0x0e32);
2203 break;
2204 case Lao:
2205 sample += QChar(0x0e8d);
2206 sample += QChar(0x0e9d);
2207 sample += QChar(0x0ead);
2208 sample += QChar(0x0ebd);
2209 break;
2210 case Tibetan:
2211 sample += QChar(0x0f00);
2212 sample += QChar(0x0f01);
2213 sample += QChar(0x0f02);
2214 sample += QChar(0x0f03);
2215 break;
2216 case Myanmar:
2217 sample += QChar(0x1000);
2218 sample += QChar(0x1001);
2219 sample += QChar(0x1002);
2220 sample += QChar(0x1003);
2221 break;
2222 case Georgian:
2223 sample += QChar(0x10a0);
2224 sample += QChar(0x10b0);
2225 sample += QChar(0x10c0);
2226 sample += QChar(0x10d0);
2227 break;
2228 case Khmer:
2229 sample += QChar(0x1780);
2230 sample += QChar(0x1790);
2231 sample += QChar(0x17b0);
2232 sample += QChar(0x17c0);
2233 break;
2234 case SimplifiedChinese:
2235 sample += QChar(0x4e2d);
2236 sample += QChar(0x6587);
2237 sample += QChar(0x8303);
2238 sample += QChar(0x4f8b);
2239 break;
2240 case TraditionalChinese:
2241 sample += QChar(0x4e2d);
2242 sample += QChar(0x6587);
2243 sample += QChar(0x7bc4);
2244 sample += QChar(0x4f8b);
2245 break;
2246 case Japanese:
2247 sample += QChar(0x3050);
2248 sample += QChar(0x3060);
2249 sample += QChar(0x30b0);
2250 sample += QChar(0x30c0);
2251 break;
2252 case Korean:
2253 sample += QChar(0xac00);
2254 sample += QChar(0xac11);
2255 sample += QChar(0xac1a);
2256 sample += QChar(0xac2f);
2257 break;
2258 case Vietnamese:
2259 break;
2260 case Ogham:
2261 sample += QChar(0x1681);
2262 sample += QChar(0x1682);
2263 sample += QChar(0x1683);
2264 sample += QChar(0x1684);
2265 break;
2266 case Runic:
2267 sample += QChar(0x16a0);
2268 sample += QChar(0x16a1);
2269 sample += QChar(0x16a2);
2270 sample += QChar(0x16a3);
2271 break;
2272 default:
2273 break;
2274 }
2275 return sample;
2276}
2277
2278
2279void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
2280{
2281 QT_PREPEND_NAMESPACE(parseFontName)(name, foundry, family);
2282}
2283
2284void QFontDatabase::createDatabase()
2285{ initializeDb(); }
2286
2287// used from qfontengine_ft.cpp
2288QByteArray qt_fontdata_from_index(int index)
2289{
2290 QMutexLocker locker(fontDatabaseMutex());
2291 return privateDb()->applicationFonts.value(index).data;
2292}
2293
2294int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &fileName)
2295{
2296 QFontDatabasePrivate::ApplicationFont font;
2297 font.data = fontData;
2298 font.fileName = fileName;
2299
2300 int i;
2301 for (i = 0; i < applicationFonts.count(); ++i)
2302 if (applicationFonts.at(i).families.isEmpty())
2303 break;
2304 if (i >= applicationFonts.count()) {
2305 applicationFonts.append(ApplicationFont());
2306 i = applicationFonts.count() - 1;
2307 }
2308
2309 if (font.fileName.isEmpty() && !fontData.isEmpty())
2310 font.fileName = QString::fromLatin1(":qmemoryfonts/") + QString::number(i);
2311
2312 registerFont(&font);
2313 if (font.families.isEmpty())
2314 return -1;
2315
2316 applicationFonts[i] = font;
2317
2318 invalidate();
2319 return i;
2320}
2321
2322bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
2323{
2324 for (int i = 0; i < applicationFonts.count(); ++i)
2325 if (applicationFonts.at(i).fileName == fileName)
2326 return true;
2327 return false;
2328}
2329
2330/*!
2331 \since 4.2
2332
2333 Loads the font from the file specified by \a fileName and makes it available to
2334 the application. An ID is returned that can be used to remove the font again
2335 with removeApplicationFont() or to retrieve the list of family names contained
2336 in the font.
2337
2338 The function returns -1 if the font could not be loaded.
2339
2340 Currently only TrueType fonts, TrueType font collections, and OpenType fonts are
2341 supported.
2342
2343 \note Adding application fonts on Unix/X11 platforms without fontconfig is
2344 currently not supported.
2345
2346 \sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont()
2347*/
2348int QFontDatabase::addApplicationFont(const QString &fileName)
2349{
2350 QByteArray data;
2351 QFile f(fileName);
2352 if (!(f.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
2353 if (!f.open(QIODevice::ReadOnly))
2354 return -1;
2355 data = f.readAll();
2356 }
2357 QMutexLocker locker(fontDatabaseMutex());
2358 return privateDb()->addAppFont(data, fileName);
2359}
2360
2361/*!
2362 \since 4.2
2363
2364 Loads the font from binary data specified by \a fontData and makes it available to
2365 the application. An ID is returned that can be used to remove the font again
2366 with removeApplicationFont() or to retrieve the list of family names contained
2367 in the font.
2368
2369 The function returns -1 if the font could not be loaded.
2370
2371 Currently only TrueType fonts and TrueType font collections are supported.
2372
2373 \bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is
2374 currently not supported.
2375
2376 \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont()
2377*/
2378int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
2379{
2380 QMutexLocker locker(fontDatabaseMutex());
2381 return privateDb()->addAppFont(fontData, QString() /* fileName */);
2382}
2383
2384/*!
2385 \since 4.2
2386
2387 Returns a list of font families for the given application font identified by
2388 \a id.
2389
2390 \sa addApplicationFont(), addApplicationFontFromData()
2391*/
2392QStringList QFontDatabase::applicationFontFamilies(int id)
2393{
2394 QMutexLocker locker(fontDatabaseMutex());
2395 return privateDb()->applicationFonts.value(id).families;
2396}
2397
2398/*!
2399 \fn bool QFontDatabase::removeApplicationFont(int id)
2400 \since 4.2
2401
2402 Removes the previously loaded application font identified by \a
2403 id. Returns true if unloading of the font succeeded; otherwise
2404 returns false.
2405
2406 \sa removeAllApplicationFonts(), addApplicationFont(),
2407 addApplicationFontFromData()
2408*/
2409
2410/*!
2411 \fn bool QFontDatabase::removeAllApplicationFonts()
2412 \since 4.2
2413
2414 Removes all application-local fonts previously added using addApplicationFont()
2415 and addApplicationFontFromData().
2416
2417 Returns true if unloading of the fonts succeeded; otherwise
2418 returns false.
2419
2420 \sa removeApplicationFont(), addApplicationFont(), addApplicationFontFromData()
2421*/
2422
2423/*!
2424 \fn bool QFontDatabase::supportsThreadedFontRendering()
2425 \since 4.4
2426
2427 Returns true if font rendering is supported outside the GUI
2428 thread, false otherwise. In other words, a return value of false
2429 means that all QPainter::drawText() calls outside the GUI thread
2430 will not produce readable output.
2431
2432 \sa threads.html#painting-in-threads
2433*/
2434
2435
2436QT_END_NAMESPACE
2437
Note: See TracBrowser for help on using the repository browser.