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

Last change on this file since 890 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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