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

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

gui/text: Implemented QFontDatabase::addApplicationFont()/removeApplicationFont() and friends (closes #89).

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