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

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

gui/text: Keep track of scripts supported by individual styles within a font family to make sure that if some style doesn't support all scripts the other style does, the font matching algorithm will select another family for this style instead of drawing empty boxes.

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