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

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

gui: Added enumeration of installed PM fonts.

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