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

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

gui: Changed to using the Freetype2 library for populating the fonts. Implemented font matching against populated fonts.

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