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