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

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

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 71.5 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_QWS)
879# include "qfontdatabase_qws.cpp"
880#endif
881QT_END_INCLUDE_NAMESPACE
882
883static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey)
884{
885 int best = 0;
886 int dist = 0xffff;
887
888 for ( int i = 0; i < foundry->count; i++ ) {
889 QtFontStyle *style = foundry->styles[i];
890
891 int d = qAbs( styleKey.weight - style->key.weight );
892
893 if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
894 d += qAbs( styleKey.stretch - style->key.stretch );
895 }
896
897 if (styleKey.style != style->key.style) {
898 if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal)
899 // one is italic, the other oblique
900 d += 0x0001;
901 else
902 d += 0x1000;
903 }
904
905 if ( d < dist ) {
906 best = i;
907 dist = d;
908 }
909 }
910
911 FM_DEBUG( " best style has distance 0x%x", dist );
912 return foundry->styles[best];
913}
914
915#if defined(Q_WS_X11)
916static QtFontEncoding *findEncoding(int script, int styleStrategy,
917 QtFontSize *size, int force_encoding_id)
918{
919 QtFontEncoding *encoding = 0;
920
921 if (force_encoding_id >= 0) {
922 encoding = size->encodingID(force_encoding_id);
923 if (!encoding)
924 FM_DEBUG(" required encoding_id not available");
925 return encoding;
926 }
927
928 if (styleStrategy & (QFont::OpenGLCompatible | QFont::PreferBitmap)) {
929 FM_DEBUG(" PreferBitmap and/or OpenGL set, skipping Freetype");
930 } else {
931 encoding = size->encodingID(-1); // -1 == prefer Freetype
932 if (encoding)
933 return encoding;
934 }
935
936 // FT not available, find an XLFD font, trying the default encoding first
937 encoding = size->encodingID(QFontPrivate::defaultEncodingID);
938 if (encoding) {
939 // does it support the requested script?
940 bool supportsScript = false;
941 for (int ws = 1; !supportsScript && ws < QFontDatabase::WritingSystemsCount; ++ws) {
942 if (scriptForWritingSystem[ws] != script)
943 continue;
944 supportsScript = writingSystems_for_xlfd_encoding[encoding->encoding][ws];
945 }
946 if (!supportsScript)
947 encoding = 0;
948 }
949 // find the first encoding that supports the requested script
950 for (int ws = 1; !encoding && ws < QFontDatabase::WritingSystemsCount; ++ws) {
951 if (scriptForWritingSystem[ws] != script)
952 continue;
953 for (int x = 0; !encoding && x < size->count; ++x) {
954 const int enc = size->encodings[x].encoding;
955 if (writingSystems_for_xlfd_encoding[enc][ws])
956 encoding = size->encodings + x;
957 }
958 }
959
960 return encoding;
961}
962#endif // Q_WS_X11
963
964#if !defined(Q_WS_MAC)
965static
966unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
967 const QtFontFamily *family, const QString &foundry_name,
968 QtFontStyle::Key styleKey, int pixelSize, char pitch,
969 QtFontDesc *desc, int force_encoding_id)
970{
971 Q_UNUSED(force_encoding_id);
972 Q_UNUSED(script);
973 Q_UNUSED(pitch);
974
975 desc->foundry = 0;
976 desc->style = 0;
977 desc->size = 0;
978 desc->encoding = 0;
979
980
981 FM_DEBUG(" REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
982
983 for (int x = 0; x < family->count; ++x) {
984 QtFontFoundry *foundry = family->foundries[x];
985 if (!foundry_name.isEmpty() && foundry->name.compare(foundry_name, Qt::CaseInsensitive) != 0)
986 continue;
987
988 FM_DEBUG(" looking for matching style in foundry '%s' %d",
989 foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
990
991 QtFontStyle *style = bestStyle(foundry, styleKey);
992
993 if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
994 FM_DEBUG(" ForceOutline set, but not smoothly scalable");
995 continue;
996 }
997
998 int px = -1;
999 QtFontSize *size = 0;
1000
1001 // 1. see if we have an exact matching size
1002 if (!(styleStrategy & QFont::ForceOutline)) {
1003 size = style->pixelSize(pixelSize);
1004 if (size) {
1005 FM_DEBUG(" found exact size match (%d pixels)", size->pixelSize);
1006 px = size->pixelSize;
1007 }
1008 }
1009
1010 // 2. see if we have a smoothly scalable font
1011 if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
1012 size = style->pixelSize(SMOOTH_SCALABLE);
1013 if (size) {
1014 FM_DEBUG(" found smoothly scalable font (%d pixels)", pixelSize);
1015 px = pixelSize;
1016 }
1017 }
1018
1019 // 3. see if we have a bitmap scalable font
1020 if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
1021 size = style->pixelSize(0);
1022 if (size) {
1023 FM_DEBUG(" found bitmap scalable font (%d pixels)", pixelSize);
1024 px = pixelSize;
1025 }
1026 }
1027
1028#ifdef Q_WS_X11
1029 QtFontEncoding *encoding = 0;
1030#endif
1031
1032 // 4. find closest size match
1033 if (! size) {
1034 unsigned int distance = ~0u;
1035 for (int x = 0; x < style->count; ++x) {
1036#ifdef Q_WS_X11
1037 encoding =
1038 findEncoding(script, styleStrategy, style->pixelSizes + x, force_encoding_id);
1039 if (!encoding) {
1040 FM_DEBUG(" size %3d does not support the script we want",
1041 style->pixelSizes[x].pixelSize);
1042 continue;
1043 }
1044#endif
1045
1046 unsigned int d;
1047 if (style->pixelSizes[x].pixelSize < pixelSize) {
1048 // penalize sizes that are smaller than the
1049 // requested size, due to truncation from floating
1050 // point to integer conversions
1051 d = pixelSize - style->pixelSizes[x].pixelSize + 1;
1052 } else {
1053 d = style->pixelSizes[x].pixelSize - pixelSize;
1054 }
1055
1056 if (d < distance) {
1057 distance = d;
1058 size = style->pixelSizes + x;
1059 FM_DEBUG(" best size so far: %3d (%d)", size->pixelSize, pixelSize);
1060 }
1061 }
1062
1063 if (!size) {
1064 FM_DEBUG(" no size supports the script we want");
1065 continue;
1066 }
1067
1068 if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
1069 (distance * 10 / pixelSize) >= 2) {
1070 // the closest size is not close enough, go ahead and
1071 // use a bitmap scaled font
1072 size = style->pixelSize(0);
1073 px = pixelSize;
1074 } else {
1075 px = size->pixelSize;
1076 }
1077 }
1078
1079#ifdef Q_WS_X11
1080 if (size) {
1081 encoding = findEncoding(script, styleStrategy, size, force_encoding_id);
1082 if (!encoding) size = 0;
1083 }
1084 if (! encoding) {
1085 FM_DEBUG(" foundry doesn't support the script we want");
1086 continue;
1087 }
1088#endif // Q_WS_X11
1089
1090 unsigned int this_score = 0x0000;
1091 enum {
1092 PitchMismatch = 0x4000,
1093 StyleMismatch = 0x2000,
1094 BitmapScaledPenalty = 0x1000,
1095 EncodingMismatch = 0x0002,
1096 XLFDPenalty = 0x0001
1097 };
1098#ifdef Q_WS_X11
1099 if (encoding->encoding != -1) {
1100 this_score += XLFDPenalty;
1101 if (encoding->encoding != QFontPrivate::defaultEncodingID)
1102 this_score += EncodingMismatch;
1103 }
1104 if (pitch != '*') {
1105 if (!(pitch == 'm' && encoding->pitch == 'c') && pitch != encoding->pitch)
1106 this_score += PitchMismatch;
1107 }
1108#else
1109 if (pitch != '*') {
1110#if !defined(QWS) && defined(Q_OS_MAC)
1111 qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family));
1112#endif
1113 if ((pitch == 'm' && !family->fixedPitch)
1114 || (pitch == 'p' && family->fixedPitch))
1115 this_score += PitchMismatch;
1116 }
1117#endif
1118 if (styleKey != style->key)
1119 this_score += StyleMismatch;
1120 if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled
1121 this_score += BitmapScaledPenalty;
1122 if (px != pixelSize) // close, but not exact, size match
1123 this_score += qAbs(px - pixelSize);
1124
1125 if (this_score < score) {
1126 FM_DEBUG(" found a match: score %x best score so far %x",
1127 this_score, score);
1128
1129 score = this_score;
1130 desc->foundry = foundry;
1131 desc->style = style;
1132 desc->size = size;
1133#ifdef Q_WS_X11
1134 desc->encoding = encoding;
1135#endif // Q_WS_X11
1136 } else {
1137 FM_DEBUG(" score %x no better than best %x", this_score, score);
1138 }
1139 }
1140
1141 return score;
1142}
1143#endif
1144
1145#if !defined(Q_WS_MAC)
1146/*!
1147 \internal
1148
1149 Tries to find the best match for a given request and family/foundry
1150*/
1151static void match(int script, const QFontDef &request,
1152 const QString &family_name, const QString &foundry_name, int force_encoding_id,
1153 QtFontDesc *desc, const QList<int> &blacklistedFamilies)
1154{
1155 Q_UNUSED(force_encoding_id);
1156
1157 QtFontStyle::Key styleKey;
1158 styleKey.style = request.style;
1159 styleKey.weight = request.weight;
1160 styleKey.stretch = request.stretch;
1161 char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
1162
1163 FM_DEBUG("QFontDatabase::match\n"
1164 " request:\n"
1165 " family: %s [%s], script: %d\n"
1166 " weight: %d, style: %d\n"
1167 " stretch: %d\n"
1168 " pixelSize: %d\n"
1169 " pitch: %c",
1170 family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
1171 foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
1172 script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
1173#if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11)
1174 if (force_encoding_id >= 0) {
1175 FM_DEBUG(" required encoding: %d", force_encoding_id);
1176 }
1177#endif
1178
1179 desc->family = 0;
1180 desc->foundry = 0;
1181 desc->style = 0;
1182 desc->size = 0;
1183 desc->encoding = 0;
1184 desc->familyIndex = -1;
1185
1186 unsigned int score = ~0u;
1187
1188 load(family_name, script);
1189
1190 QFontDatabasePrivate *db = privateDb();
1191 for (int x = 0; x < db->count; ++x) {
1192 if (blacklistedFamilies.contains(x))
1193 continue;
1194 QtFontDesc test;
1195 test.family = db->families[x];
1196 test.familyIndex = x;
1197
1198 if (!family_name.isEmpty()
1199 && test.family->name.compare(family_name, Qt::CaseInsensitive) != 0
1200#ifdef Q_WS_WIN
1201 && test.family->english_name.compare(family_name, Qt::CaseInsensitive) != 0
1202#endif
1203 )
1204 continue;
1205
1206 if (family_name.isEmpty())
1207 load(test.family->name, script);
1208
1209 uint score_adjust = 0;
1210
1211 bool supported = (script == QUnicodeTables::Common);
1212 for (int ws = 1; !supported && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1213 if (scriptForWritingSystem[ws] != script)
1214 continue;
1215 if (test.family->writingSystems[ws] & QtFontFamily::Supported)
1216 supported = true;
1217 }
1218 if (!supported) {
1219 // family not supported in the script we want
1220 continue;
1221 }
1222
1223 // as we know the script is supported, we can be sure
1224 // to find a matching font here.
1225 unsigned int newscore =
1226 bestFoundry(script, score, request.styleStrategy,
1227 test.family, foundry_name, styleKey, request.pixelSize, pitch,
1228 &test, force_encoding_id);
1229 if (test.foundry == 0) {
1230 // the specific foundry was not found, so look for
1231 // any foundry matching our requirements
1232 newscore = bestFoundry(script, score, request.styleStrategy, test.family,
1233 QString(), styleKey, request.pixelSize,
1234 pitch, &test, force_encoding_id);
1235 }
1236 newscore += score_adjust;
1237
1238 if (newscore < score) {
1239 score = newscore;
1240 *desc = test;
1241 }
1242 if (newscore < 10) // xlfd instead of FT... just accept it
1243 break;
1244 }
1245}
1246#endif
1247
1248static QString styleStringHelper(int weight, QFont::Style style)
1249{
1250 QString result;
1251 if (weight >= QFont::Black)
1252 result = qApp->translate("QFontDatabase", "Black");
1253 else if (weight >= QFont::Bold)
1254 result = qApp->translate("QFontDatabase", "Bold");
1255 else if (weight >= QFont::DemiBold)
1256 result = qApp->translate("QFontDatabase", "Demi Bold");
1257 else if (weight < QFont::Normal)
1258 result = qApp->translate("QFontDatabase", "Light");
1259
1260 if (style == QFont::StyleItalic)
1261 result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Italic");
1262 else if (style == QFont::StyleOblique)
1263 result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Oblique");
1264
1265 if (result.isEmpty())
1266 result = qApp->translate("QFontDatabase", "Normal");
1267
1268 return result.simplified();
1269}
1270
1271/*!
1272 Returns a string that describes the style of the \a font. For
1273 example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1274 string may be returned.
1275*/
1276QString QFontDatabase::styleString(const QFont &font)
1277{
1278 return styleStringHelper(font.weight(), font.style());
1279}
1280
1281/*!
1282 Returns a string that describes the style of the \a fontInfo. For
1283 example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1284 string may be returned.
1285*/
1286QString QFontDatabase::styleString(const QFontInfo &fontInfo)
1287{
1288 return styleStringHelper(fontInfo.weight(), fontInfo.style());
1289}
1290
1291
1292/*!
1293 \class QFontDatabase
1294 \threadsafe
1295
1296 \brief The QFontDatabase class provides information about the fonts available in the underlying window system.
1297
1298 \ingroup environment
1299 \ingroup multimedia
1300 \ingroup text
1301
1302 The most common uses of this class are to query the database for
1303 the list of font families() and for the pointSizes() and styles()
1304 that are available for each family. An alternative to pointSizes()
1305 is smoothSizes() which returns the sizes at which a given family
1306 and style will look attractive.
1307
1308 If the font family is available from two or more foundries the
1309 foundry name is included in the family name, e.g. "Helvetica
1310 [Adobe]" and "Helvetica [Cronyx]". When you specify a family you
1311 can either use the old hyphenated Qt 2.x "foundry-family" format,
1312 e.g. "Cronyx-Helvetica", or the new bracketed Qt 3.x "family
1313 [foundry]" format e.g. "Helvetica [Cronyx]". If the family has a
1314 foundry it is always returned, e.g. by families(), using the
1315 bracketed format.
1316
1317 The font() function returns a QFont given a family, style and
1318 point size.
1319
1320 A family and style combination can be checked to see if it is
1321 italic() or bold(), and to retrieve its weight(). Similarly we can
1322 call isBitmapScalable(), isSmoothlyScalable(), isScalable() and
1323 isFixedPitch().
1324
1325 Use the styleString() to obtain a text version of a style.
1326
1327 The QFontDatabase class also supports some static functions, for
1328 example, standardSizes(). You can retrieve the description of a
1329 writing system using writingSystemName(), and a sample of
1330 characters in a writing system with writingSystemSample().
1331
1332 Example:
1333
1334 \snippet doc/src/snippets/qfontdatabase/main.cpp 0
1335 \snippet doc/src/snippets/qfontdatabase/main.cpp 1
1336
1337 This example gets the list of font families, the list of
1338 styles for each family, and the point sizes that are available for
1339 each combination of family and style, displaying this information
1340 in a tree view.
1341
1342 \sa QFont, QFontInfo, QFontMetrics, QFontComboBox, {Character Map Example}
1343*/
1344
1345/*!
1346 Creates a font database object.
1347*/
1348QFontDatabase::QFontDatabase()
1349{
1350 QMutexLocker locker(fontDatabaseMutex());
1351 createDatabase();
1352 d = privateDb();
1353}
1354
1355/*!
1356 \enum QFontDatabase::WritingSystem
1357
1358 \value Any
1359 \value Latin
1360 \value Greek
1361 \value Cyrillic
1362 \value Armenian
1363 \value Hebrew
1364 \value Arabic
1365 \value Syriac
1366 \value Thaana
1367 \value Devanagari
1368 \value Bengali
1369 \value Gurmukhi
1370 \value Gujarati
1371 \value Oriya
1372 \value Tamil
1373 \value Telugu
1374 \value Kannada
1375 \value Malayalam
1376 \value Sinhala
1377 \value Thai
1378 \value Lao
1379 \value Tibetan
1380 \value Myanmar
1381 \value Georgian
1382 \value Khmer
1383 \value SimplifiedChinese
1384 \value TraditionalChinese
1385 \value Japanese
1386 \value Korean
1387 \value Vietnamese
1388 \value Symbol
1389 \value Other (the same as Symbol)
1390 \value Ogham
1391 \value Runic
1392
1393 \omitvalue WritingSystemsCount
1394*/
1395
1396/*!
1397 Returns a sorted list of the available writing systems. This is
1398 list generated from information about all installed fonts on the
1399 system.
1400
1401 \sa families()
1402*/
1403QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const
1404{
1405 QMutexLocker locker(fontDatabaseMutex());
1406
1407 QT_PREPEND_NAMESPACE(load)();
1408#ifdef Q_WS_X11
1409 checkSymbolFonts();
1410#endif
1411
1412 QList<WritingSystem> list;
1413 for (int i = 0; i < d->count; ++i) {
1414 QtFontFamily *family = d->families[i];
1415 if (family->count == 0)
1416 continue;
1417 for (int x = Latin; x < WritingSystemsCount; ++x) {
1418 const WritingSystem writingSystem = WritingSystem(x);
1419 if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported))
1420 continue;
1421 if (!list.contains(writingSystem))
1422 list.append(writingSystem);
1423 }
1424 }
1425 qSort(list);
1426 return list;
1427}
1428
1429
1430/*!
1431 Returns a sorted list of the writing systems supported by a given
1432 font \a family.
1433
1434 \sa families()
1435*/
1436QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems(const QString &family) const
1437{
1438 QString familyName, foundryName;
1439 parseFontName(family, foundryName, familyName);
1440
1441 QMutexLocker locker(fontDatabaseMutex());
1442
1443 QT_PREPEND_NAMESPACE(load)();
1444#ifdef Q_WS_X11
1445 checkSymbolFonts(familyName);
1446#endif
1447
1448 QList<WritingSystem> list;
1449 QtFontFamily *f = d->family(familyName);
1450 if (!f || f->count == 0)
1451 return list;
1452
1453 for (int x = Latin; x < WritingSystemsCount; ++x) {
1454 const WritingSystem writingSystem = WritingSystem(x);
1455 if (f->writingSystems[writingSystem] & QtFontFamily::Supported)
1456 list.append(writingSystem);
1457 }
1458 return list;
1459}
1460
1461
1462/*!
1463 Returns a sorted list of the available font families which support
1464 the \a writingSystem.
1465
1466 If a family exists in several foundries, the returned name for
1467 that font is in the form "family [foundry]". Examples: "Times
1468 [Adobe]", "Times [Cronyx]", "Palatino".
1469
1470 \sa writingSystems()
1471*/
1472QStringList QFontDatabase::families(WritingSystem writingSystem) const
1473{
1474 QMutexLocker locker(fontDatabaseMutex());
1475
1476 QT_PREPEND_NAMESPACE(load)();
1477#ifdef Q_WS_X11
1478 if (writingSystem != Any)
1479 checkSymbolFonts();
1480#endif
1481
1482 QStringList flist;
1483 for (int i = 0; i < d->count; i++) {
1484 QtFontFamily *f = d->families[i];
1485 if (f->count == 0)
1486 continue;
1487 if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported))
1488 continue;
1489 if (f->count == 1) {
1490 flist.append(f->name);
1491 } else {
1492 for (int j = 0; j < f->count; j++) {
1493 QString str = f->name;
1494 QString foundry = f->foundries[j]->name;
1495 if (!foundry.isEmpty()) {
1496 str += QLatin1String(" [");
1497 str += foundry;
1498 str += QLatin1String("]");
1499 }
1500 flist.append(str);
1501 }
1502 }
1503 }
1504 return flist;
1505}
1506
1507/*!
1508 Returns a list of the styles available for the font family \a
1509 family. Some example styles: "Light", "Light Italic", "Bold",
1510 "Oblique", "Demi". The list may be empty.
1511
1512 \sa families()
1513*/
1514QStringList QFontDatabase::styles(const QString &family) const
1515{
1516 QString familyName, foundryName;
1517 parseFontName(family, foundryName, familyName);
1518
1519 QMutexLocker locker(fontDatabaseMutex());
1520
1521 QT_PREPEND_NAMESPACE(load)(familyName);
1522
1523 QStringList l;
1524 QtFontFamily *f = d->family(familyName);
1525 if (!f)
1526 return l;
1527
1528 QtFontFoundry allStyles(foundryName);
1529 for (int j = 0; j < f->count; j++) {
1530 QtFontFoundry *foundry = f->foundries[j];
1531 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1532 for (int k = 0; k < foundry->count; k++) {
1533 QtFontStyle::Key ke(foundry->styles[k]->key);
1534 ke.stretch = 0;
1535 allStyles.style(ke, true);
1536 }
1537 }
1538 }
1539
1540 for (int i = 0; i < allStyles.count; i++)
1541 l.append(styleStringHelper(allStyles.styles[i]->key.weight, (QFont::Style)allStyles.styles[i]->key.style));
1542 return l;
1543}
1544
1545/*!
1546 Returns true if the font that has family \a family and style \a
1547 style is fixed pitch; otherwise returns false.
1548*/
1549
1550bool QFontDatabase::isFixedPitch(const QString &family,
1551 const QString &style) const
1552{
1553 Q_UNUSED(style);
1554
1555 QString familyName, foundryName;
1556 parseFontName(family, foundryName, familyName);
1557
1558 QMutexLocker locker(fontDatabaseMutex());
1559
1560 QT_PREPEND_NAMESPACE(load)(familyName);
1561
1562 QtFontFamily *f = d->family(familyName);
1563#if !defined(QWS) && defined(Q_OS_MAC)
1564 qt_mac_get_fixed_pitch(f);
1565#endif
1566 return (f && f->fixedPitch);
1567}
1568
1569/*!
1570 Returns true if the font that has family \a family and style \a
1571 style is a scalable bitmap font; otherwise returns false. Scaling
1572 a bitmap font usually produces an unattractive hardly readable
1573 result, because the pixels of the font are scaled. If you need to
1574 scale a bitmap font it is better to scale it to one of the fixed
1575 sizes returned by smoothSizes().
1576
1577 \sa isScalable(), isSmoothlyScalable()
1578*/
1579bool QFontDatabase::isBitmapScalable(const QString &family,
1580 const QString &style) const
1581{
1582 bool bitmapScalable = false;
1583 QString familyName, foundryName;
1584 parseFontName(family, foundryName, familyName);
1585
1586 QMutexLocker locker(fontDatabaseMutex());
1587
1588 QT_PREPEND_NAMESPACE(load)(familyName);
1589
1590 QtFontStyle::Key styleKey(style);
1591
1592 QtFontFamily *f = d->family(familyName);
1593 if (!f) return bitmapScalable;
1594
1595 for (int j = 0; j < f->count; j++) {
1596 QtFontFoundry *foundry = f->foundries[j];
1597 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1598 for (int k = 0; k < foundry->count; k++)
1599 if ((style.isEmpty() || foundry->styles[k]->key == styleKey)
1600 && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
1601 bitmapScalable = true;
1602 goto end;
1603 }
1604 }
1605 }
1606 end:
1607 return bitmapScalable;
1608}
1609
1610
1611/*!
1612 Returns true if the font that has family \a family and style \a
1613 style is smoothly scalable; otherwise returns false. If this
1614 function returns true, it's safe to scale this font to any size,
1615 and the result will always look attractive.
1616
1617 \sa isScalable(), isBitmapScalable()
1618*/
1619bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const
1620{
1621 bool smoothScalable = false;
1622 QString familyName, foundryName;
1623 parseFontName(family, foundryName, familyName);
1624
1625 QMutexLocker locker(fontDatabaseMutex());
1626
1627 QT_PREPEND_NAMESPACE(load)(familyName);
1628
1629 QtFontStyle::Key styleKey(style);
1630
1631 QtFontFamily *f = d->family(familyName);
1632 if (!f) return smoothScalable;
1633
1634 for (int j = 0; j < f->count; j++) {
1635 QtFontFoundry *foundry = f->foundries[j];
1636 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1637 for (int k = 0; k < foundry->count; k++)
1638 if ((style.isEmpty() || foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
1639 smoothScalable = true;
1640 goto end;
1641 }
1642 }
1643 }
1644 end:
1645 return smoothScalable;
1646}
1647
1648/*!
1649 Returns true if the font that has family \a family and style \a
1650 style is scalable; otherwise returns false.
1651
1652 \sa isBitmapScalable(), isSmoothlyScalable()
1653*/
1654bool QFontDatabase::isScalable(const QString &family,
1655 const QString &style) const
1656{
1657 QMutexLocker locker(fontDatabaseMutex());
1658 if (isSmoothlyScalable(family, style))
1659 return true;
1660 return isBitmapScalable(family, style);
1661}
1662
1663
1664/*!
1665 Returns a list of the point sizes available for the font that has
1666 family \a family and style \a style. The list may be empty.
1667
1668 \sa smoothSizes(), standardSizes()
1669*/
1670QList<int> QFontDatabase::pointSizes(const QString &family,
1671 const QString &style)
1672{
1673#if defined(Q_WS_WIN)
1674 // windows and macosx are always smoothly scalable
1675 Q_UNUSED(family);
1676 Q_UNUSED(style);
1677 return standardSizes();
1678#else
1679 bool smoothScalable = false;
1680 QString familyName, foundryName;
1681 parseFontName(family, foundryName, familyName);
1682
1683 QMutexLocker locker(fontDatabaseMutex());
1684
1685 QT_PREPEND_NAMESPACE(load)(familyName);
1686
1687 QtFontStyle::Key styleKey(style);
1688
1689 QList<int> sizes;
1690
1691 QtFontFamily *fam = d->family(familyName);
1692 if (!fam) return sizes;
1693
1694
1695#ifdef Q_WS_X11
1696 int dpi = QX11Info::appDpiY();
1697#else
1698 const int dpi = qt_defaultDpiY(); // embedded
1699#endif
1700
1701 for (int j = 0; j < fam->count; j++) {
1702 QtFontFoundry *foundry = fam->foundries[j];
1703 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1704 QtFontStyle *style = foundry->style(styleKey);
1705 if (!style) continue;
1706
1707 if (style->smoothScalable) {
1708 smoothScalable = true;
1709 goto end;
1710 }
1711 for (int l = 0; l < style->count; l++) {
1712 const QtFontSize *size = style->pixelSizes + l;
1713
1714 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1715 const uint pointSize = qRound(size->pixelSize * 72.0 / dpi);
1716 if (! sizes.contains(pointSize))
1717 sizes.append(pointSize);
1718 }
1719 }
1720 }
1721 }
1722 end:
1723 if (smoothScalable)
1724 return standardSizes();
1725
1726 qSort(sizes);
1727 return sizes;
1728#endif
1729}
1730
1731/*!
1732 Returns a QFont object that has family \a family, style \a style
1733 and point size \a pointSize. If no matching font could be created,
1734 a QFont object that uses the application's default font is
1735 returned.
1736*/
1737QFont QFontDatabase::font(const QString &family, const QString &style,
1738 int pointSize) const
1739{
1740 QString familyName, foundryName;
1741 parseFontName(family, foundryName, familyName);
1742
1743 QMutexLocker locker(fontDatabaseMutex());
1744
1745 QT_PREPEND_NAMESPACE(load)(familyName);
1746
1747 QtFontFoundry allStyles(foundryName);
1748 QtFontFamily *f = d->family(familyName);
1749 if (!f) return QApplication::font();
1750
1751 for (int j = 0; j < f->count; j++) {
1752 QtFontFoundry *foundry = f->foundries[j];
1753 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1754 for (int k = 0; k < foundry->count; k++)
1755 allStyles.style(foundry->styles[k]->key, true);
1756 }
1757 }
1758
1759 QtFontStyle::Key styleKey(style);
1760 QtFontStyle *s = bestStyle(&allStyles, styleKey);
1761
1762 if (!s) // no styles found?
1763 return QApplication::font();
1764 QFont fnt(family, pointSize, s->key.weight);
1765 fnt.setStyle((QFont::Style)s->key.style);
1766 return fnt;
1767}
1768
1769
1770/*!
1771 Returns the point sizes of a font that has family \a family and
1772 style \a style that will look attractive. The list may be empty.
1773 For non-scalable fonts and bitmap scalable fonts, this function
1774 is equivalent to pointSizes().
1775
1776 \sa pointSizes(), standardSizes()
1777*/
1778QList<int> QFontDatabase::smoothSizes(const QString &family,
1779 const QString &style)
1780{
1781#ifdef Q_WS_WIN
1782 Q_UNUSED(family);
1783 Q_UNUSED(style);
1784 return QFontDatabase::standardSizes();
1785#else
1786 bool smoothScalable = false;
1787 QString familyName, foundryName;
1788 parseFontName(family, foundryName, familyName);
1789
1790 QMutexLocker locker(fontDatabaseMutex());
1791
1792 QT_PREPEND_NAMESPACE(load)(familyName);
1793
1794 QtFontStyle::Key styleKey(style);
1795
1796 QList<int> sizes;
1797
1798 QtFontFamily *fam = d->family(familyName);
1799 if (!fam)
1800 return sizes;
1801
1802#ifdef Q_WS_X11
1803 int dpi = QX11Info::appDpiY();
1804#else
1805 const int dpi = qt_defaultDpiY(); // embedded
1806#endif
1807
1808 for (int j = 0; j < fam->count; j++) {
1809 QtFontFoundry *foundry = fam->foundries[j];
1810 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1811 QtFontStyle *style = foundry->style(styleKey);
1812 if (!style) continue;
1813
1814 if (style->smoothScalable) {
1815 smoothScalable = true;
1816 goto end;
1817 }
1818 for (int l = 0; l < style->count; l++) {
1819 const QtFontSize *size = style->pixelSizes + l;
1820
1821 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1822 const uint pointSize = qRound(size->pixelSize * 72.0 / dpi);
1823 if (! sizes.contains(pointSize))
1824 sizes.append(pointSize);
1825 }
1826 }
1827 }
1828 }
1829 end:
1830 if (smoothScalable)
1831 return QFontDatabase::standardSizes();
1832
1833 qSort(sizes);
1834 return sizes;
1835#endif
1836}
1837
1838
1839/*!
1840 Returns a list of standard font sizes.
1841
1842 \sa smoothSizes(), pointSizes()
1843*/
1844QList<int> QFontDatabase::standardSizes()
1845{
1846 QList<int> ret;
1847 static const unsigned short standard[] =
1848 { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
1849 const unsigned short *sizes = standard;
1850 while (*sizes) ret << *sizes++;
1851 return ret;
1852}
1853
1854
1855/*!
1856 Returns true if the font that has family \a family and style \a
1857 style is italic; otherwise returns false.
1858
1859 \sa weight(), bold()
1860*/
1861bool QFontDatabase::italic(const QString &family, const QString &style) const
1862{
1863 QString familyName, foundryName;
1864 parseFontName(family, foundryName, familyName);
1865
1866 QMutexLocker locker(fontDatabaseMutex());
1867
1868 QT_PREPEND_NAMESPACE(load)(familyName);
1869
1870 QtFontFoundry allStyles(foundryName);
1871 QtFontFamily *f = d->family(familyName);
1872 if (!f) return false;
1873
1874 for (int j = 0; j < f->count; j++) {
1875 QtFontFoundry *foundry = f->foundries[j];
1876 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1877 for (int k = 0; k < foundry->count; k++)
1878 allStyles.style(foundry->styles[k]->key, true);
1879 }
1880 }
1881
1882 QtFontStyle::Key styleKey(style);
1883 QtFontStyle *s = allStyles.style(styleKey);
1884 return s && s->key.style == QFont::StyleItalic;
1885}
1886
1887
1888/*!
1889 Returns true if the font that has family \a family and style \a
1890 style is bold; otherwise returns false.
1891
1892 \sa italic(), weight()
1893*/
1894bool QFontDatabase::bold(const QString &family,
1895 const QString &style) const
1896{
1897 QString familyName, foundryName;
1898 parseFontName(family, foundryName, familyName);
1899
1900 QMutexLocker locker(fontDatabaseMutex());
1901
1902 QT_PREPEND_NAMESPACE(load)(familyName);
1903
1904 QtFontFoundry allStyles(foundryName);
1905 QtFontFamily *f = d->family(familyName);
1906 if (!f) return false;
1907
1908 for (int j = 0; j < f->count; j++) {
1909 QtFontFoundry *foundry = f->foundries[j];
1910 if (foundryName.isEmpty() ||
1911 foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1912 for (int k = 0; k < foundry->count; k++)
1913 allStyles.style(foundry->styles[k]->key, true);
1914 }
1915 }
1916
1917 QtFontStyle::Key styleKey(style);
1918 QtFontStyle *s = allStyles.style(styleKey);
1919 return s && s->key.weight >= QFont::Bold;
1920}
1921
1922
1923/*!
1924 Returns the weight of the font that has family \a family and style
1925 \a style. If there is no such family and style combination,
1926 returns -1.
1927
1928 \sa italic(), bold()
1929*/
1930int QFontDatabase::weight(const QString &family,
1931 const QString &style) const
1932{
1933 QString familyName, foundryName;
1934 parseFontName(family, foundryName, familyName);
1935
1936 QMutexLocker locker(fontDatabaseMutex());
1937
1938 QT_PREPEND_NAMESPACE(load)(familyName);
1939
1940 QtFontFoundry allStyles(foundryName);
1941 QtFontFamily *f = d->family(familyName);
1942 if (!f) return -1;
1943
1944 for (int j = 0; j < f->count; j++) {
1945 QtFontFoundry *foundry = f->foundries[j];
1946 if (foundryName.isEmpty() ||
1947 foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1948 for (int k = 0; k < foundry->count; k++)
1949 allStyles.style(foundry->styles[k]->key, true);
1950 }
1951 }
1952
1953 QtFontStyle::Key styleKey(style);
1954 QtFontStyle *s = allStyles.style(styleKey);
1955 return s ? s->key.weight : -1;
1956}
1957
1958
1959/*!
1960 Returns the names the \a writingSystem (e.g. for displaying to the
1961 user in a dialog).
1962*/
1963QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
1964{
1965 const char *name = 0;
1966 switch (writingSystem) {
1967 case Any:
1968 name = QT_TRANSLATE_NOOP("QFontDatabase", "Any");
1969 break;
1970 case Latin:
1971 name = QT_TRANSLATE_NOOP("QFontDatabase", "Latin");
1972 break;
1973 case Greek:
1974 name = QT_TRANSLATE_NOOP("QFontDatabase", "Greek");
1975 break;
1976 case Cyrillic:
1977 name = QT_TRANSLATE_NOOP("QFontDatabase", "Cyrillic");
1978 break;
1979 case Armenian:
1980 name = QT_TRANSLATE_NOOP("QFontDatabase", "Armenian");
1981 break;
1982 case Hebrew:
1983 name = QT_TRANSLATE_NOOP("QFontDatabase", "Hebrew");
1984 break;
1985 case Arabic:
1986 name = QT_TRANSLATE_NOOP("QFontDatabase", "Arabic");
1987 break;
1988 case Syriac:
1989 name = QT_TRANSLATE_NOOP("QFontDatabase", "Syriac");
1990 break;
1991 case Thaana:
1992 name = QT_TRANSLATE_NOOP("QFontDatabase", "Thaana");
1993 break;
1994 case Devanagari:
1995 name = QT_TRANSLATE_NOOP("QFontDatabase", "Devanagari");
1996 break;
1997 case Bengali:
1998 name = QT_TRANSLATE_NOOP("QFontDatabase", "Bengali");
1999 break;
2000 case Gurmukhi:
2001 name = QT_TRANSLATE_NOOP("QFontDatabase", "Gurmukhi");
2002 break;
2003 case Gujarati:
2004 name = QT_TRANSLATE_NOOP("QFontDatabase", "Gujarati");
2005 break;
2006 case Oriya:
2007 name = QT_TRANSLATE_NOOP("QFontDatabase", "Oriya");
2008 break;
2009 case Tamil:
2010 name = QT_TRANSLATE_NOOP("QFontDatabase", "Tamil");
2011 break;
2012 case Telugu:
2013 name = QT_TRANSLATE_NOOP("QFontDatabase", "Telugu");
2014 break;
2015 case Kannada:
2016 name = QT_TRANSLATE_NOOP("QFontDatabase", "Kannada");
2017 break;
2018 case Malayalam:
2019 name = QT_TRANSLATE_NOOP("QFontDatabase", "Malayalam");
2020 break;
2021 case Sinhala:
2022 name = QT_TRANSLATE_NOOP("QFontDatabase", "Sinhala");
2023 break;
2024 case Thai:
2025 name = QT_TRANSLATE_NOOP("QFontDatabase", "Thai");
2026 break;
2027 case Lao:
2028 name = QT_TRANSLATE_NOOP("QFontDatabase", "Lao");
2029 break;
2030 case Tibetan:
2031 name = QT_TRANSLATE_NOOP("QFontDatabase", "Tibetan");
2032 break;
2033 case Myanmar:
2034 name = QT_TRANSLATE_NOOP("QFontDatabase", "Myanmar");
2035 break;
2036 case Georgian:
2037 name = QT_TRANSLATE_NOOP("QFontDatabase", "Georgian");
2038 break;
2039 case Khmer:
2040 name = QT_TRANSLATE_NOOP("QFontDatabase", "Khmer");
2041 break;
2042 case SimplifiedChinese:
2043 name = QT_TRANSLATE_NOOP("QFontDatabase", "Simplified Chinese");
2044 break;
2045 case TraditionalChinese:
2046 name = QT_TRANSLATE_NOOP("QFontDatabase", "Traditional Chinese");
2047 break;
2048 case Japanese:
2049 name = QT_TRANSLATE_NOOP("QFontDatabase", "Japanese");
2050 break;
2051 case Korean:
2052 name = QT_TRANSLATE_NOOP("QFontDatabase", "Korean");
2053 break;
2054 case Vietnamese:
2055 name = QT_TRANSLATE_NOOP("QFontDatabase", "Vietnamese");
2056 break;
2057 case Symbol:
2058 name = QT_TRANSLATE_NOOP("QFontDatabase", "Symbol");
2059 break;
2060 case Ogham:
2061 name = QT_TRANSLATE_NOOP("QFontDatabase", "Ogham");
2062 break;
2063 case Runic:
2064 name = QT_TRANSLATE_NOOP("QFontDatabase", "Runic");
2065 break;
2066 default:
2067 Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
2068 break;
2069 }
2070 return qApp ? qApp->translate("QFontDatabase", name) : QString::fromLatin1(name);
2071}
2072
2073
2074/*!
2075 Returns a string with sample characters from \a writingSystem.
2076*/
2077QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
2078{
2079 QString sample;
2080 switch (writingSystem) {
2081 case Any:
2082 case Symbol:
2083 // show only ascii characters
2084 sample += QLatin1String("AaBbzZ");
2085 break;
2086 case Latin:
2087 // This is cheating... we only show latin-1 characters so that we don't
2088 // end up loading lots of fonts - at least on X11...
2089 sample = QLatin1String("Aa");
2090 sample += QChar(0x00C3);
2091 sample += QChar(0x00E1);
2092 sample += QLatin1String("Zz");
2093 break;
2094 case Greek:
2095 sample += QChar(0x0393);
2096 sample += QChar(0x03B1);
2097 sample += QChar(0x03A9);
2098 sample += QChar(0x03C9);
2099 break;
2100 case Cyrillic:
2101 sample += QChar(0x0414);
2102 sample += QChar(0x0434);
2103 sample += QChar(0x0436);
2104 sample += QChar(0x044f);
2105 break;
2106 case Armenian:
2107 sample += QChar(0x053f);
2108 sample += QChar(0x054f);
2109 sample += QChar(0x056f);
2110 sample += QChar(0x057f);
2111 break;
2112 case Hebrew:
2113 sample += QChar(0x05D0);
2114 sample += QChar(0x05D1);
2115 sample += QChar(0x05D2);
2116 sample += QChar(0x05D3);
2117 break;
2118 case Arabic:
2119 sample += QChar(0x0628);
2120 sample += QChar(0x0629);
2121 sample += QChar(0x062A);
2122 sample += QChar(0x063A);
2123 break;
2124 case Syriac:
2125 sample += QChar(0x0715);
2126 sample += QChar(0x0725);
2127 sample += QChar(0x0716);
2128 sample += QChar(0x0726);
2129 break;
2130 case Thaana:
2131 sample += QChar(0x0784);
2132 sample += QChar(0x0794);
2133 sample += QChar(0x078c);
2134 sample += QChar(0x078d);
2135 break;
2136 case Devanagari:
2137 sample += QChar(0x0905);
2138 sample += QChar(0x0915);
2139 sample += QChar(0x0925);
2140 sample += QChar(0x0935);
2141 break;
2142 case Bengali:
2143 sample += QChar(0x0986);
2144 sample += QChar(0x0996);
2145 sample += QChar(0x09a6);
2146 sample += QChar(0x09b6);
2147 break;
2148 case Gurmukhi:
2149 sample += QChar(0x0a05);
2150 sample += QChar(0x0a15);
2151 sample += QChar(0x0a25);
2152 sample += QChar(0x0a35);
2153 break;
2154 case Gujarati:
2155 sample += QChar(0x0a85);
2156 sample += QChar(0x0a95);
2157 sample += QChar(0x0aa5);
2158 sample += QChar(0x0ab5);
2159 break;
2160 case Oriya:
2161 sample += QChar(0x0b06);
2162 sample += QChar(0x0b16);
2163 sample += QChar(0x0b2b);
2164 sample += QChar(0x0b36);
2165 break;
2166 case Tamil:
2167 sample += QChar(0x0b89);
2168 sample += QChar(0x0b99);
2169 sample += QChar(0x0ba9);
2170 sample += QChar(0x0bb9);
2171 break;
2172 case Telugu:
2173 sample += QChar(0x0c05);
2174 sample += QChar(0x0c15);
2175 sample += QChar(0x0c25);
2176 sample += QChar(0x0c35);
2177 break;
2178 case Kannada:
2179 sample += QChar(0x0c85);
2180 sample += QChar(0x0c95);
2181 sample += QChar(0x0ca5);
2182 sample += QChar(0x0cb5);
2183 break;
2184 case Malayalam:
2185 sample += QChar(0x0d05);
2186 sample += QChar(0x0d15);
2187 sample += QChar(0x0d25);
2188 sample += QChar(0x0d35);
2189 break;
2190 case Sinhala:
2191 sample += QChar(0x0d90);
2192 sample += QChar(0x0da0);
2193 sample += QChar(0x0db0);
2194 sample += QChar(0x0dc0);
2195 break;
2196 case Thai:
2197 sample += QChar(0x0e02);
2198 sample += QChar(0x0e12);
2199 sample += QChar(0x0e22);
2200 sample += QChar(0x0e32);
2201 break;
2202 case Lao:
2203 sample += QChar(0x0e8d);
2204 sample += QChar(0x0e9d);
2205 sample += QChar(0x0ead);
2206 sample += QChar(0x0ebd);
2207 break;
2208 case Tibetan:
2209 sample += QChar(0x0f00);
2210 sample += QChar(0x0f01);
2211 sample += QChar(0x0f02);
2212 sample += QChar(0x0f03);
2213 break;
2214 case Myanmar:
2215 sample += QChar(0x1000);
2216 sample += QChar(0x1001);
2217 sample += QChar(0x1002);
2218 sample += QChar(0x1003);
2219 break;
2220 case Georgian:
2221 sample += QChar(0x10a0);
2222 sample += QChar(0x10b0);
2223 sample += QChar(0x10c0);
2224 sample += QChar(0x10d0);
2225 break;
2226 case Khmer:
2227 sample += QChar(0x1780);
2228 sample += QChar(0x1790);
2229 sample += QChar(0x17b0);
2230 sample += QChar(0x17c0);
2231 break;
2232 case SimplifiedChinese:
2233 sample += QChar(0x4e2d);
2234 sample += QChar(0x6587);
2235 sample += QChar(0x8303);
2236 sample += QChar(0x4f8b);
2237 break;
2238 case TraditionalChinese:
2239 sample += QChar(0x4e2d);
2240 sample += QChar(0x6587);
2241 sample += QChar(0x7bc4);
2242 sample += QChar(0x4f8b);
2243 break;
2244 case Japanese:
2245 sample += QChar(0x3050);
2246 sample += QChar(0x3060);
2247 sample += QChar(0x30b0);
2248 sample += QChar(0x30c0);
2249 break;
2250 case Korean:
2251 sample += QChar(0xac00);
2252 sample += QChar(0xac11);
2253 sample += QChar(0xac1a);
2254 sample += QChar(0xac2f);
2255 break;
2256 case Vietnamese:
2257 break;
2258 case Ogham:
2259 sample += QChar(0x1681);
2260 sample += QChar(0x1682);
2261 sample += QChar(0x1683);
2262 sample += QChar(0x1684);
2263 break;
2264 case Runic:
2265 sample += QChar(0x16a0);
2266 sample += QChar(0x16a1);
2267 sample += QChar(0x16a2);
2268 sample += QChar(0x16a3);
2269 break;
2270 default:
2271 break;
2272 }
2273 return sample;
2274}
2275
2276
2277void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
2278{
2279 QT_PREPEND_NAMESPACE(parseFontName)(name, foundry, family);
2280}
2281
2282void QFontDatabase::createDatabase()
2283{ initializeDb(); }
2284
2285// used from qfontengine_ft.cpp
2286QByteArray qt_fontdata_from_index(int index)
2287{
2288 QMutexLocker locker(fontDatabaseMutex());
2289 return privateDb()->applicationFonts.value(index).data;
2290}
2291
2292int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &fileName)
2293{
2294 QFontDatabasePrivate::ApplicationFont font;
2295 font.data = fontData;
2296 font.fileName = fileName;
2297
2298 int i;
2299 for (i = 0; i < applicationFonts.count(); ++i)
2300 if (applicationFonts.at(i).families.isEmpty())
2301 break;
2302 if (i >= applicationFonts.count()) {
2303 applicationFonts.append(ApplicationFont());
2304 i = applicationFonts.count() - 1;
2305 }
2306
2307 if (font.fileName.isEmpty() && !fontData.isEmpty())
2308 font.fileName = QString::fromLatin1(":qmemoryfonts/") + QString::number(i);
2309
2310 registerFont(&font);
2311 if (font.families.isEmpty())
2312 return -1;
2313
2314 applicationFonts[i] = font;
2315
2316 invalidate();
2317 return i;
2318}
2319
2320bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
2321{
2322 for (int i = 0; i < applicationFonts.count(); ++i)
2323 if (applicationFonts.at(i).fileName == fileName)
2324 return true;
2325 return false;
2326}
2327
2328/*!
2329 \since 4.2
2330
2331 Loads the font from the file specified by \a fileName and makes it available to
2332 the application. An ID is returned that can be used to remove the font again
2333 with removeApplicationFont() or to retrieve the list of family names contained
2334 in the font.
2335
2336 The function returns -1 if the font could not be loaded.
2337
2338 Currently only TrueType fonts, TrueType font collections, and OpenType fonts are
2339 supported.
2340
2341 \note Adding application fonts on Unix/X11 platforms without fontconfig is
2342 currently not supported.
2343
2344 \sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont()
2345*/
2346int QFontDatabase::addApplicationFont(const QString &fileName)
2347{
2348 QByteArray data;
2349 QFile f(fileName);
2350 if (!(f.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
2351 if (!f.open(QIODevice::ReadOnly))
2352 return -1;
2353 data = f.readAll();
2354 }
2355 QMutexLocker locker(fontDatabaseMutex());
2356 return privateDb()->addAppFont(data, fileName);
2357}
2358
2359/*!
2360 \since 4.2
2361
2362 Loads the font from binary data specified by \a fontData and makes it available to
2363 the application. An ID is returned that can be used to remove the font again
2364 with removeApplicationFont() or to retrieve the list of family names contained
2365 in the font.
2366
2367 The function returns -1 if the font could not be loaded.
2368
2369 Currently only TrueType fonts and TrueType font collections are supported.
2370
2371 \bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is
2372 currently not supported.
2373
2374 \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont()
2375*/
2376int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
2377{
2378 QMutexLocker locker(fontDatabaseMutex());
2379 return privateDb()->addAppFont(fontData, QString() /* fileName */);
2380}
2381
2382/*!
2383 \since 4.2
2384
2385 Returns a list of font families for the given application font identified by
2386 \a id.
2387
2388 \sa addApplicationFont(), addApplicationFontFromData()
2389*/
2390QStringList QFontDatabase::applicationFontFamilies(int id)
2391{
2392 QMutexLocker locker(fontDatabaseMutex());
2393 return privateDb()->applicationFonts.value(id).families;
2394}
2395
2396/*!
2397 \fn bool QFontDatabase::removeApplicationFont(int id)
2398 \since 4.2
2399
2400 Removes the previously loaded application font identified by \a
2401 id. Returns true if unloading of the font succeeded; otherwise
2402 returns false.
2403
2404 \sa removeAllApplicationFonts(), addApplicationFont(),
2405 addApplicationFontFromData()
2406*/
2407
2408/*!
2409 \fn bool QFontDatabase::removeAllApplicationFonts()
2410 \since 4.2
2411
2412 Removes all application-local fonts previously added using addApplicationFont()
2413 and addApplicationFontFromData().
2414
2415 Returns true if unloading of the fonts succeeded; otherwise
2416 returns false.
2417
2418 \sa removeApplicationFont(), addApplicationFont(), addApplicationFontFromData()
2419*/
2420
2421/*!
2422 \fn bool QFontDatabase::supportsThreadedFontRendering()
2423 \since 4.4
2424
2425 Returns true if font rendering is supported outside the GUI
2426 thread, false otherwise. In other words, a return value of false
2427 means that all QPainter::drawText() calls outside the GUI thread
2428 will not produce readable output.
2429
2430 \sa threads.html#painting-in-threads
2431*/
2432
2433
2434QT_END_NAMESPACE
2435
Note: See TracBrowser for help on using the repository browser.