00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qdir.h>
00025 #include "qfontdatabase.h"
00026 #include "qdebug.h"
00027 #include "qalgorithms.h"
00028 #include "qapplication.h"
00029 #include "qvarlengtharray.h"
00030 #include "private/qunicodetables_p.h"
00031 #include "qfontengine_p.h"
00032 #include "qopentype_p.h"
00033
00034 #ifdef Q_WS_X11
00035 #include <locale.h>
00036 #endif
00037 #include <stdlib.h>
00038 #include <limits.h>
00039
00040
00041 #ifdef QFONTDATABASE_DEBUG
00042 # define FD_DEBUG qDebug
00043 #else
00044 # define FD_DEBUG if (false) qDebug
00045 #endif
00046
00047
00048 #ifdef FONT_MATCH_DEBUG
00049 # define FM_DEBUG qDebug
00050 #else
00051 # define FM_DEBUG if (false) qDebug
00052 #endif
00053
00054 #if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
00055 # define for if(0){}else for
00056 #endif
00057
00058
00059 Q_GUI_EXPORT bool qt_enable_test_font = false;
00060
00061 static int ucstricmp(const QString &as, const QString &bs)
00062 {
00063 const QChar *a = as.unicode();
00064 const QChar *b = bs.unicode();
00065 if (a == b)
00066 return 0;
00067 if (a == 0)
00068 return 1;
00069 if (b == 0)
00070 return -1;
00071 int l=qMin(as.length(),bs.length());
00072 while (l-- && QUnicodeTables::lower(*a) == QUnicodeTables::lower(*b))
00073 a++,b++;
00074 if (l==-1)
00075 return (as.length()-bs.length());
00076 return QUnicodeTables::lower(*a).unicode() - QUnicodeTables::lower(*b).unicode();
00077 }
00078
00079 static int getFontWeight(const QString &weightString)
00080 {
00081 QString s = weightString.toLower();
00082
00083
00084 if (s == QLatin1String("medium") ||
00085 s == QLatin1String("normal"))
00086 return QFont::Normal;
00087 if (s == QLatin1String("bold"))
00088 return QFont::Bold;
00089 if (s == QLatin1String("demibold") || s == QLatin1String("demi bold"))
00090 return QFont::DemiBold;
00091 if (s == QLatin1String("black"))
00092 return QFont::Black;
00093 if (s == QLatin1String("light"))
00094 return QFont::Light;
00095
00096 if (s.contains(QLatin1String("bold"))) {
00097 if (s.contains(QLatin1String("demi")))
00098 return (int) QFont::DemiBold;
00099 return (int) QFont::Bold;
00100 }
00101
00102 if (s.contains(QLatin1String("light")))
00103 return (int) QFont::Light;
00104
00105 if (s.contains(QLatin1String("black")))
00106 return (int) QFont::Black;
00107
00108 return (int) QFont::Normal;
00109 }
00110
00111 struct QtFontEncoding
00112 {
00113 signed int encoding : 16;
00114
00115 uint xpoint : 16;
00116 uint xres : 8;
00117 uint yres : 8;
00118 uint avgwidth : 16;
00119 uchar pitch : 8;
00120 };
00121
00122 struct QtFontSize
00123 {
00124 unsigned short pixelSize;
00125
00126 #ifdef Q_WS_X11
00127 int count;
00128 QtFontEncoding *encodings;
00129 QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0,
00130 uint yres = 0, uint avgwidth = 0, bool add = false);
00131 #endif // Q_WS_X11
00132 #ifdef Q_WS_QWS
00133 QByteArray fileName;
00134 #endif
00135 };
00136
00137
00138 #ifdef Q_WS_X11
00139 QtFontEncoding *QtFontSize::encodingID(int id, uint xpoint, uint xres,
00140 uint yres, uint avgwidth, bool add)
00141 {
00142
00143 for (int i = 0; i < count; ++i) {
00144 if (encodings[i].encoding == id)
00145 return encodings + i;
00146 }
00147
00148 if (!add) return 0;
00149
00150 if (!(count % 4))
00151 encodings = (QtFontEncoding *)
00152 realloc(encodings,
00153 (((count+4) >> 2) << 2) * sizeof(QtFontEncoding));
00154 encodings[count].encoding = id;
00155 encodings[count].xpoint = xpoint;
00156 encodings[count].xres = xres;
00157 encodings[count].yres = yres;
00158 encodings[count].avgwidth = avgwidth;
00159 encodings[count].pitch = '*';
00160 return encodings + count++;
00161 }
00162 #endif // Q_WS_X11
00163
00164 struct QtFontStyle
00165 {
00166 struct Key {
00167 Key(const QString &styleString);
00168 Key() : style(QFont::StyleNormal),
00169 weight(QFont::Normal), stretch(0) { }
00170 Key(const Key &o) : style(o.style),
00171 weight(o.weight), stretch(o.stretch) { }
00172 uint style : 2;
00173 signed int weight : 8;
00174 signed int stretch : 12;
00175
00176 bool operator==(const Key & other) {
00177 return (style == other.style &&
00178 weight == other.weight &&
00179 (stretch == 0 || other.stretch == 0 || stretch == other.stretch));
00180 }
00181 bool operator!=(const Key &other) {
00182 return !operator==(other);
00183 }
00184 bool operator <(const Key &o) {
00185 int x = (style << 12) + (weight << 14) + stretch;
00186 int y = (o.style << 12) + (o.weight << 14) + o.stretch;
00187 return (x < y);
00188 }
00189 };
00190
00191 QtFontStyle(const Key &k)
00192 : key(k), bitmapScalable(false), smoothScalable(false),
00193 count(0), pixelSizes(0)
00194 {
00195 #if defined(Q_WS_X11)
00196 weightName = setwidthName = 0;
00197 #endif // Q_WS_X11
00198 }
00199
00200 ~QtFontStyle() {
00201 #ifdef Q_WS_X11
00202 delete [] weightName;
00203 delete [] setwidthName;
00204 #endif
00205 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
00206 while (count--) {
00207 #ifdef Q_WS_X11
00208 free(pixelSizes[count].encodings);
00209 #endif
00210 #ifdef Q_WS_QWS
00211 pixelSizes[count].fileName.~QByteArray();
00212 #endif
00213 }
00214 #endif
00215 free(pixelSizes);
00216 }
00217
00218 Key key;
00219 bool bitmapScalable : 1;
00220 bool smoothScalable : 1;
00221 signed int count : 30;
00222 QtFontSize *pixelSizes;
00223
00224 #ifdef Q_WS_X11
00225 const char *weightName;
00226 const char *setwidthName;
00227 #endif // Q_WS_X11
00228 #ifdef Q_WS_QWS
00229 bool antialiased;
00230 #endif
00231
00232 QtFontSize *pixelSize(unsigned short size, bool = false);
00233 };
00234
00235 QtFontStyle::Key::Key(const QString &styleString)
00236 : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
00237 {
00238 weight = getFontWeight(styleString);
00239
00240 if (styleString.contains(QLatin1String("Italic")))
00241 style = QFont::StyleItalic;
00242 else if (styleString.contains(QLatin1String("Oblique")))
00243 style = QFont::StyleOblique;
00244 }
00245
00246 QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
00247 {
00248 for (int i = 0; i < count; i++) {
00249 if (pixelSizes[i].pixelSize == size)
00250 return pixelSizes + i;
00251 }
00252 if (!add)
00253 return 0;
00254
00255 if (!(count % 8))
00256 pixelSizes = (QtFontSize *)
00257 realloc(pixelSizes,
00258 (((count+8) >> 3) << 3) * sizeof(QtFontSize));
00259 pixelSizes[count].pixelSize = size;
00260 #ifdef Q_WS_X11
00261 pixelSizes[count].count = 0;
00262 pixelSizes[count].encodings = 0;
00263 #endif
00264 #ifdef Q_WS_QWS
00265 new (&pixelSizes[count].fileName) QByteArray;
00266 #endif
00267 return pixelSizes + (count++);
00268 }
00269
00270 struct QtFontFoundry
00271 {
00272 QtFontFoundry(const QString &n) : name(n), count(0), styles(0) {}
00273 ~QtFontFoundry() {
00274 while (count--)
00275 delete styles[count];
00276 free(styles);
00277 }
00278
00279 QString name;
00280
00281 int count;
00282 QtFontStyle **styles;
00283 QtFontStyle *style(const QtFontStyle::Key &, bool = false);
00284 };
00285
00286 QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create)
00287 {
00288 int pos = 0;
00289 if (count) {
00290 int low = 0;
00291 int high = count;
00292 pos = count / 2;
00293 while (high > low) {
00294 if (styles[pos]->key == key)
00295 return styles[pos];
00296 if (styles[pos]->key < key)
00297 low = pos + 1;
00298 else
00299 high = pos;
00300 pos = (high + low) / 2;
00301 };
00302 pos = low;
00303 }
00304 if (!create)
00305 return 0;
00306
00307
00308 if (!(count % 8))
00309 styles = (QtFontStyle **)
00310 realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *));
00311
00312 memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *));
00313 styles[pos] = new QtFontStyle(key);
00314 count++;
00315 return styles[pos];
00316 }
00317
00318
00319 struct QtFontFamily
00320 {
00321 enum WritingSystemStatus {
00322 Unknown = 0,
00323 Supported = 1,
00324 UnsupportedFT = 2,
00325 UnsupportedXLFD = 4,
00326 Unsupported = UnsupportedFT | UnsupportedXLFD
00327 };
00328
00329 QtFontFamily(const QString &n)
00330 :
00331 #ifdef Q_WS_X11
00332 fixedPitch(true), ftWritingSystemCheck(false),
00333 xlfdLoaded(false), synthetic(false), symbol_checked(false),
00334 #else
00335 fixedPitch(false),
00336 #endif
00337 #ifdef Q_WS_WIN
00338 writingSystemCheck(false),
00339 loaded(false),
00340 #endif
00341 #if !defined(QWS) && defined(Q_OS_MAC)
00342 fixedPitchComputed(false),
00343 #endif
00344 name(n), count(0), foundries(0) {
00345 memset(writingSystems, 0, sizeof(writingSystems));
00346 }
00347 ~QtFontFamily() {
00348 while (count--)
00349 delete foundries[count];
00350 free(foundries);
00351 }
00352
00353 bool fixedPitch : 1;
00354 #ifdef Q_WS_X11
00355 bool ftWritingSystemCheck : 1;
00356 bool xlfdLoaded : 1;
00357 bool synthetic : 1;
00358 #endif
00359 #ifdef Q_WS_WIN
00360 bool writingSystemCheck : 1;
00361 bool loaded : 1;
00362 #endif
00363 #if !defined(QWS) && defined(Q_OS_MAC)
00364 bool fixedPitchComputed : 1;
00365 #endif
00366 #ifdef Q_WS_X11
00367 bool symbol_checked;
00368 #endif
00369
00370 QString name;
00371 QString rawName;
00372 #ifdef Q_WS_X11
00373 QByteArray fontFilename;
00374 int fontFileIndex;
00375 #endif
00376 #ifdef Q_WS_WIN
00377 QString english_name;
00378 #endif
00379 int count;
00380 QtFontFoundry **foundries;
00381
00382 unsigned char writingSystems[QFontDatabase::WritingSystemsCount];
00383
00384 QtFontFoundry *foundry(const QString &f, bool = false);
00385 };
00386
00387 #if !defined(QWS) && defined(Q_OS_MAC)
00388 inline static void qt_mac_get_fixed_pitch(QtFontFamily *f)
00389 {
00390 if(f && !f->fixedPitchComputed) {
00391 QFontMetrics fm(f->name);
00392 f->fixedPitch = fm.width('i') == fm.width('m');
00393 f->fixedPitchComputed = true;
00394 }
00395 }
00396 #endif
00397
00398
00399 QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
00400 {
00401 if (f.isNull() && count == 1)
00402 return foundries[0];
00403
00404 for (int i = 0; i < count; i++) {
00405 if (ucstricmp(foundries[i]->name, f) == 0)
00406 return foundries[i];
00407 }
00408 if (!create)
00409 return 0;
00410
00411 if (!(count % 8))
00412 foundries = (QtFontFoundry **)
00413 realloc(foundries,
00414 (((count+8) >> 3) << 3) * sizeof(QtFontFoundry *));
00415
00416 foundries[count] = new QtFontFoundry(f);
00417 return foundries[count++];
00418 }
00419
00420 class QFontDatabasePrivate : public QObject
00421 {
00422 Q_OBJECT
00423 public:
00424 QFontDatabasePrivate() : count(0), families(0), reregisterAppFonts(false) { }
00425 ~QFontDatabasePrivate() {
00426 free();
00427 }
00428 QtFontFamily *family(const QString &f, bool = false);
00429 void free() {
00430 while (count--)
00431 delete families[count];
00432 ::free(families);
00433 families = 0;
00434 count = 0;
00435
00436 }
00437
00438 int count;
00439 QtFontFamily **families;
00440
00441 struct ApplicationFont {
00442 QString fileName;
00443 QByteArray data;
00444 #if defined(Q_OS_WIN)
00445 HANDLE handle;
00446 bool memoryFont;
00447 #elif defined(Q_WS_MAC)
00448 ATSFontContainerRef handle;
00449 #endif
00450 QStringList families;
00451 };
00452 QVector<ApplicationFont> applicationFonts;
00453 int addAppFont(const QByteArray &fontData, const QString &fileName);
00454 bool reregisterAppFonts;
00455
00456 void invalidate();
00457
00458 Q_SIGNALS:
00459 void fontDatabaseChanged();
00460 };
00461
00462 void QFontDatabasePrivate::invalidate()
00463 {
00464 if (QFontCache::instance)
00465 QFontCache::instance->clear();
00466 free();
00467 emit fontDatabaseChanged();
00468 }
00469
00470 QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
00471 {
00472 int low = 0;
00473 int high = count;
00474 int pos = count / 2;
00475 int res = 1;
00476 if (count) {
00477 while ((res = ucstricmp(families[pos]->name, f)) && pos != low) {
00478 if (res > 0)
00479 high = pos;
00480 else
00481 low = pos;
00482 pos = (high + low) / 2;
00483 };
00484 if (!res)
00485 return families[pos];
00486 }
00487 if (!create)
00488 return 0;
00489
00490 if (res < 0)
00491 pos++;
00492
00493
00494 if (!(count % 8))
00495 families = (QtFontFamily **)
00496 realloc(families,
00497 (((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
00498
00499 memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
00500 families[pos] = new QtFontFamily(f);
00501 count++;
00502 return families[pos];
00503 }
00504
00505
00506 static const int scriptForWritingSystem[] = {
00507 QUnicodeTables::Common,
00508 QUnicodeTables::Latin,
00509 QUnicodeTables::Greek,
00510 QUnicodeTables::Cyrillic,
00511 QUnicodeTables::Armenian,
00512 QUnicodeTables::Hebrew,
00513 QUnicodeTables::Arabic,
00514 QUnicodeTables::Syriac,
00515 QUnicodeTables::Thaana,
00516 QUnicodeTables::Devanagari,
00517 QUnicodeTables::Bengali,
00518 QUnicodeTables::Gurmukhi,
00519 QUnicodeTables::Gujarati,
00520 QUnicodeTables::Oriya,
00521 QUnicodeTables::Tamil,
00522 QUnicodeTables::Telugu,
00523 QUnicodeTables::Kannada,
00524 QUnicodeTables::Malayalam,
00525 QUnicodeTables::Sinhala,
00526 QUnicodeTables::Thai,
00527 QUnicodeTables::Lao,
00528 QUnicodeTables::Tibetan,
00529 QUnicodeTables::Myanmar,
00530 QUnicodeTables::Georgian,
00531 QUnicodeTables::Khmer,
00532 QUnicodeTables::Common,
00533 QUnicodeTables::Common,
00534 QUnicodeTables::Common,
00535 QUnicodeTables::Hangul,
00536 QUnicodeTables::Common,
00537 QUnicodeTables::Common,
00538 QUnicodeTables::Common,
00539 QUnicodeTables::Common,
00540 QUnicodeTables::Common,
00541 QUnicodeTables::Common,
00542 QUnicodeTables::Common,
00543 QUnicodeTables::Common,
00544 QUnicodeTables::Common,
00545 QUnicodeTables::Common,
00546 QUnicodeTables::Ogham,
00547 QUnicodeTables::Runic
00548 };
00549
00550
00551 #if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG))
00552 static inline bool requiresOpenType(int writingSystem)
00553 {
00554 return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
00555 || writingSystem == QFontDatabase::Khmer);
00556 }
00557 static inline bool scriptRequiresOpenType(int script)
00558 {
00559 return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala)
00560 || script == QUnicodeTables::Khmer);
00561 }
00562 #endif
00563
00564
00574 static void parseFontName(const QString &name, QString &foundry, QString &family)
00575 {
00576 int i = name.indexOf(QLatin1Char('['));
00577 int li = name.lastIndexOf(QLatin1Char(']'));
00578 if (i >= 0 && li >= 0 && i < li) {
00579 foundry = name.mid(i + 1, li - i - 1);
00580 if (i > 0 && name[i - 1] == QLatin1Char(' '))
00581 i--;
00582 family = name.left(i);
00583 } else {
00584 foundry.clear();
00585 family = name;
00586 }
00587
00588
00589 bool space = true;
00590 QChar *s = family.data();
00591 int len = family.length();
00592 while(len--) {
00593 if (space) *s = s->toUpper();
00594 space = s->isSpace();
00595 ++s;
00596 }
00597
00598 space = true;
00599 s = foundry.data();
00600 len = foundry.length();
00601 while(len--) {
00602 if (space) *s = s->toUpper();
00603 space = s->isSpace();
00604 ++s;
00605 }
00606 }
00607
00608
00609 struct QtFontDesc
00610 {
00611 inline QtFontDesc() : family(0), foundry(0), style(0), size(0), encoding(0) {}
00612 QtFontFamily *family;
00613 QtFontFoundry *foundry;
00614 QtFontStyle *style;
00615 QtFontSize *size;
00616 QtFontEncoding *encoding;
00617 };
00618
00619 #if !defined(Q_WS_MAC)
00620 static void match(int script, const QFontDef &request,
00621 const QString &family_name, const QString &foundry_name, int force_encoding_id,
00622 QtFontDesc *desc);
00623
00624 static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef)
00625 {
00626 fontDef->family = desc.family->name;
00627 if (! desc.foundry->name.isEmpty()) {
00628 fontDef->family += QString::fromLatin1(" [");
00629 fontDef->family += desc.foundry->name;
00630 fontDef->family += QString::fromLatin1("]");
00631 }
00632
00633 if (desc.style->smoothScalable)
00634 fontDef->pixelSize = request.pixelSize;
00635 else if ((desc.style->bitmapScalable && (request.styleStrategy & QFont::PreferMatch)))
00636 fontDef->pixelSize = request.pixelSize;
00637 else
00638 fontDef->pixelSize = desc.size->pixelSize;
00639
00640 fontDef->styleHint = request.styleHint;
00641 fontDef->styleStrategy = request.styleStrategy;
00642
00643 fontDef->weight = desc.style->key.weight;
00644 fontDef->style = desc.style->key.style;
00645 fontDef->fixedPitch = desc.family->fixedPitch;
00646 fontDef->stretch = desc.style->key.stretch;
00647 fontDef->ignorePitch = false;
00648 }
00649 #endif
00650
00651 #if defined(Q_WS_X11) || defined(Q_WS_WIN)
00652 static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key)
00653 {
00654
00655 d->engineData = QFontCache::instance->findEngineData(key);
00656 if (!d->engineData) {
00657
00658 d->engineData = new QFontEngineData;
00659 QFontCache::instance->insertEngineData(key, d->engineData);
00660 } else {
00661 d->engineData->ref.ref();
00662 }
00663 }
00664
00665 static QStringList familyList(const QFontDef &req)
00666 {
00667
00668 QStringList family_list;
00669 if (req.family.isEmpty())
00670 return family_list;
00671
00672 QStringList list = req.family.split(QLatin1Char(','));
00673 for (int i = 0; i < list.size(); ++i) {
00674 QString str = list.at(i).trimmed();
00675 if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
00676 || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
00677 str = str.mid(1, str.length() - 2);
00678 family_list << str;
00679 }
00680
00681
00682 QStringList subs_list;
00683 QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
00684 for (; it != end; ++it)
00685 subs_list += QFont::substitutes(*it);
00686
00687
00688 family_list += subs_list;
00689
00690 return family_list;
00691 }
00692 #endif
00693
00694 Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb);
00695
00696
00697 QObject *qt_fontdatabase_private()
00698 {
00699 return privateDb();
00700 }
00701
00702 #define SMOOTH_SCALABLE 0xffff
00703
00704 #if defined(Q_WS_X11)
00705 # include "qfontdatabase_x11.cpp"
00706 #elif defined(Q_WS_MAC)
00707 # include "qfontdatabase_mac.cpp"
00708 #elif defined(Q_WS_WIN)
00709 # include "qfontdatabase_win.cpp"
00710 #elif defined(Q_WS_QWS)
00711 # include "qfontdatabase_qws.cpp"
00712 #endif
00713
00714 static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey)
00715 {
00716 int best = 0;
00717 int dist = 0xffff;
00718
00719 for ( int i = 0; i < foundry->count; i++ ) {
00720 QtFontStyle *style = foundry->styles[i];
00721
00722 int d = qAbs( styleKey.weight - style->key.weight );
00723
00724 if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
00725 d += qAbs( styleKey.stretch - style->key.stretch );
00726 }
00727
00728 if (styleKey.style != style->key.style) {
00729 if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal)
00730
00731 d += 0x0001;
00732 else
00733 d += 0x1000;
00734 }
00735
00736 if ( d < dist ) {
00737 best = i;
00738 dist = d;
00739 }
00740 }
00741
00742 FM_DEBUG( " best style has distance 0x%x", dist );
00743 return foundry->styles[best];
00744 }
00745
00746 #if defined(Q_WS_X11)
00747 static QtFontEncoding *findEncoding(int script, int styleStrategy,
00748 QtFontSize *size, int force_encoding_id)
00749 {
00750 QtFontEncoding *encoding = 0;
00751
00752 if (force_encoding_id >= 0) {
00753 encoding = size->encodingID(force_encoding_id);
00754 if (!encoding)
00755 FM_DEBUG(" required encoding_id not available");
00756 return encoding;
00757 }
00758
00759 if (styleStrategy & (QFont::OpenGLCompatible | QFont::PreferBitmap)) {
00760 FM_DEBUG(" PreferBitmap and/or OpenGL set, skipping Freetype");
00761 } else {
00762 encoding = size->encodingID(-1);
00763 if (encoding)
00764 return encoding;
00765 }
00766
00767
00768 encoding = size->encodingID(QFontPrivate::defaultEncodingID);
00769 if (encoding) {
00770
00771 bool supportsScript = false;
00772 for (int ws = 1; !supportsScript && ws < QFontDatabase::WritingSystemsCount; ++ws) {
00773 if (scriptForWritingSystem[ws] != script)
00774 continue;
00775 supportsScript = writingSystems_for_xlfd_encoding[encoding->encoding][ws];
00776 }
00777 if (!supportsScript)
00778 encoding = 0;
00779 }
00780
00781 for (int ws = 1; !encoding && ws < QFontDatabase::WritingSystemsCount; ++ws) {
00782 if (scriptForWritingSystem[ws] != script)
00783 continue;
00784 for (int x = 0; !encoding && x < size->count; ++x) {
00785 const int enc = size->encodings[x].encoding;
00786 if (writingSystems_for_xlfd_encoding[enc][ws])
00787 encoding = size->encodings + x;
00788 }
00789 }
00790
00791 return encoding;
00792 }
00793 #endif // Q_WS_X11
00794
00795 #if !defined(Q_WS_MAC)
00796 static
00797 unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
00798 const QtFontFamily *family, const QString &foundry_name,
00799 QtFontStyle::Key styleKey, int pixelSize, char pitch,
00800 QtFontDesc *desc, int force_encoding_id)
00801 {
00802 Q_UNUSED(force_encoding_id);
00803 Q_UNUSED(script);
00804 Q_UNUSED(pitch);
00805
00806 desc->foundry = 0;
00807 desc->style = 0;
00808 desc->size = 0;
00809 desc->encoding = 0;
00810
00811
00812 FM_DEBUG(" REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
00813
00814 for (int x = 0; x < family->count; ++x) {
00815 QtFontFoundry *foundry = family->foundries[x];
00816 if (!foundry_name.isEmpty() &&
00817 ucstricmp(foundry->name, foundry_name) != 0)
00818 continue;
00819
00820 FM_DEBUG(" looking for matching style in foundry '%s' %d",
00821 foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
00822
00823 QtFontStyle *style = bestStyle(foundry, styleKey);
00824
00825 if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
00826 FM_DEBUG(" ForceOutline set, but not smoothly scalable");
00827 continue;
00828 }
00829
00830 int px = -1;
00831 QtFontSize *size = 0;
00832
00833
00834 if (!(styleStrategy & QFont::ForceOutline)) {
00835 size = style->pixelSize(pixelSize);
00836 if (size) {
00837 FM_DEBUG(" found exact size match (%d pixels)", size->pixelSize);
00838 px = size->pixelSize;
00839 }
00840 }
00841
00842
00843 if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
00844 size = style->pixelSize(SMOOTH_SCALABLE);
00845 if (size) {
00846 FM_DEBUG(" found smoothly scalable font (%d pixels)", pixelSize);
00847 px = pixelSize;
00848 }
00849 }
00850
00851
00852 if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
00853 size = style->pixelSize(0);
00854 if (size) {
00855 FM_DEBUG(" found bitmap scalable font (%d pixels)", pixelSize);
00856 px = pixelSize;
00857 }
00858 }
00859
00860 #ifdef Q_WS_X11
00861 QtFontEncoding *encoding = 0;
00862 #endif
00863
00864
00865 if (! size) {
00866 unsigned int distance = ~0u;
00867 for (int x = 0; x < style->count; ++x) {
00868 #ifdef Q_WS_X11
00869 encoding =
00870 findEncoding(script, styleStrategy, style->pixelSizes + x, force_encoding_id);
00871 if (!encoding) {
00872 FM_DEBUG(" size %3d does not support the script we want",
00873 style->pixelSizes[x].pixelSize);
00874 continue;
00875 }
00876 #endif
00877
00878 unsigned int d;
00879 if (style->pixelSizes[x].pixelSize < pixelSize) {
00880
00881
00882
00883 d = pixelSize - style->pixelSizes[x].pixelSize + 1;
00884 } else {
00885 d = style->pixelSizes[x].pixelSize - pixelSize;
00886 }
00887
00888 if (d < distance) {
00889 distance = d;
00890 size = style->pixelSizes + x;
00891 FM_DEBUG(" best size so far: %3d (%d)", size->pixelSize, pixelSize);
00892 }
00893 }
00894
00895 if (!size) {
00896 FM_DEBUG(" no size supports the script we want");
00897 continue;
00898 }
00899
00900 if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
00901 (distance * 10 / pixelSize) >= 2) {
00902
00903
00904 size = style->pixelSize(0);
00905 px = pixelSize;
00906 } else {
00907 px = size->pixelSize;
00908 }
00909 }
00910
00911 #ifdef Q_WS_X11
00912 if (size) {
00913 encoding = findEncoding(script, styleStrategy, size, force_encoding_id);
00914 if (!encoding) size = 0;
00915 }
00916 if (! encoding) {
00917 FM_DEBUG(" foundry doesn't support the script we want");
00918 continue;
00919 }
00920 #endif // Q_WS_X11
00921
00922 unsigned int this_score = 0x0000;
00923 enum {
00924 PitchMismatch = 0x4000,
00925 StyleMismatch = 0x2000,
00926 BitmapScaledPenalty = 0x1000,
00927 EncodingMismatch = 0x0002,
00928 XLFDPenalty = 0x0001
00929 };
00930 #ifdef Q_WS_X11
00931 if (encoding->encoding != -1) {
00932 this_score += XLFDPenalty;
00933 if (encoding->encoding != QFontPrivate::defaultEncodingID)
00934 this_score += EncodingMismatch;
00935 }
00936 if (pitch != '*') {
00937 if (!(pitch == 'm' && encoding->pitch == 'c') && pitch != encoding->pitch)
00938 this_score += PitchMismatch;
00939 }
00940 #else
00941 if (pitch != '*') {
00942 #if !defined(QWS) && defined(Q_OS_MAC)
00943 qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family));
00944 #endif
00945 if ((pitch == 'm' && !family->fixedPitch)
00946 || (pitch == 'p' && family->fixedPitch))
00947 this_score += PitchMismatch;
00948 }
00949 #endif
00950 if (styleKey != style->key)
00951 this_score += StyleMismatch;
00952 if (!style->smoothScalable && px != size->pixelSize)
00953 this_score += BitmapScaledPenalty;
00954 if (px != pixelSize)
00955 this_score += qAbs(px - pixelSize);
00956
00957 if (this_score < score) {
00958 FM_DEBUG(" found a match: score %x best score so far %x",
00959 this_score, score);
00960
00961 score = this_score;
00962 desc->foundry = foundry;
00963 desc->style = style;
00964 desc->size = size;
00965 #ifdef Q_WS_X11
00966 desc->encoding = encoding;
00967 #endif // Q_WS_X11
00968 } else {
00969 FM_DEBUG(" score %x no better than best %x", this_score, score);
00970 }
00971 }
00972
00973 return score;
00974 }
00975 #endif
00976
00977 #if !defined(Q_WS_MAC)
00978
00983 static void match(int script, const QFontDef &request,
00984 const QString &family_name, const QString &foundry_name, int force_encoding_id,
00985 QtFontDesc *desc)
00986 {
00987 Q_UNUSED(force_encoding_id);
00988
00989 QtFontStyle::Key styleKey;
00990 styleKey.style = request.style;
00991 styleKey.weight = request.weight;
00992 styleKey.stretch = request.stretch;
00993 char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
00994
00995 FM_DEBUG("QFontDatabase::match\n"
00996 " request:\n"
00997 " family: %s [%s], script: %d\n"
00998 " weight: %d, style: %d\n"
00999 " stretch: %d\n"
01000 " pixelSize: %d\n"
01001 " pitch: %c",
01002 family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
01003 foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
01004 script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
01005 #if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11)
01006 if (force_encoding_id >= 0) {
01007 FM_DEBUG(" required encoding: %d", force_encoding_id);
01008 }
01009 #endif
01010
01011 desc->family = 0;
01012 desc->foundry = 0;
01013 desc->style = 0;
01014 desc->size = 0;
01015 desc->encoding = 0;
01016
01017 unsigned int score = ~0u;
01018
01019 ::load(family_name, script);
01020
01021 QFontDatabasePrivate *db = privateDb();
01022 for (int x = 0; x < db->count; ++x) {
01023 QtFontDesc test;
01024 test.family = db->families[x];
01025
01026 if (!family_name.isEmpty()
01027 && ucstricmp(test.family->name, family_name) != 0
01028 #ifdef Q_WS_WIN
01029 && ucstricmp(test.family->english_name, family_name) != 0
01030 #endif
01031 )
01032 continue;
01033
01034 if (family_name.isEmpty())
01035 ::load(test.family->name, script);
01036
01037 uint score_adjust = 0;
01038
01039 bool supported = (script == QUnicodeTables::Common);
01040 for (int ws = 1; !supported && ws < QFontDatabase::WritingSystemsCount; ++ws) {
01041 if (scriptForWritingSystem[ws] != script)
01042 continue;
01043 if (test.family->writingSystems[ws] & QtFontFamily::Supported)
01044 supported = true;
01045 }
01046 if (!supported) {
01047
01048 continue;
01049 }
01050
01051
01052
01053 unsigned int newscore =
01054 bestFoundry(script, score, request.styleStrategy,
01055 test.family, foundry_name, styleKey, request.pixelSize, pitch,
01056 &test, force_encoding_id);
01057 if (test.foundry == 0) {
01058
01059
01060 newscore = bestFoundry(script, score, request.styleStrategy, test.family,
01061 QString(), styleKey, request.pixelSize,
01062 pitch, &test, force_encoding_id);
01063 }
01064 newscore += score_adjust;
01065
01066 if (newscore < score) {
01067 score = newscore;
01068 *desc = test;
01069 }
01070 if (newscore < 10)
01071 break;
01072 }
01073 }
01074 #endif
01075
01076
01077 #if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
01078
01081 QFontEngine *
01082 QFontDatabase::findFont(int script, const QFontPrivate *fp,
01083 const QFontDef &request, int
01084 #ifdef Q_WS_X11
01085 force_encoding_id
01086 #endif
01087 )
01088 {
01089 #ifndef Q_WS_X11
01090 const int force_encoding_id = -1;
01091 #endif
01092
01093 if (!privateDb()->count)
01094 initializeDb();
01095
01096 QFontEngine *fe = 0;
01097 if (fp) {
01098 if (fp->rawMode) {
01099 fe = loadEngine(script, fp, request, 0, 0, 0
01100 #ifdef Q_WS_X11
01101 , 0, 0, false
01102 #endif
01103 #ifdef Q_WS_QWS
01104 , 0
01105 #endif
01106 );
01107
01108
01109 if (! fe) fe = new QFontEngineBox(12);
01110 return fe;
01111 }
01112
01113 QFontCache::Key key(request, script
01114 #if defined(Q_WS_X11)
01115 , fp->screen
01116 #endif
01117 );
01118 fe = QFontCache::instance->findEngine(key);
01119 if (fe)
01120 return fe;
01121 }
01122
01123 QString family_name, foundry_name;
01124 QtFontStyle::Key styleKey;
01125 styleKey.style = request.style;
01126 styleKey.weight = request.weight;
01127 styleKey.stretch = request.stretch;
01128 char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
01129
01130 parseFontName(request.family, foundry_name, family_name);
01131
01132 FM_DEBUG("QFontDatabase::findFont\n"
01133 " request:\n"
01134 " family: %s [%s], script: %d\n"
01135 " weight: %d, style: %d\n"
01136 " stretch: %d\n"
01137 " pixelSize: %d\n"
01138 " pitch: %c",
01139 family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
01140 foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
01141 script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
01142 #if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11)
01143 if (force_encoding_id >= 0) {
01144 FM_DEBUG(" required encoding: %d", force_encoding_id);
01145 }
01146 #endif
01147
01148 if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
01149 fe = new QTestFontEngine(request.pixelSize);
01150 fe->fontDef = request;
01151 }
01152
01153 if (!fe)
01154 {
01155 QtFontDesc desc;
01156 match(script, request, family_name, foundry_name, force_encoding_id, &desc);
01157
01158 if (desc.family != 0 && desc.foundry != 0 && desc.style != 0
01159 #ifdef Q_WS_X11
01160 && desc.size != 0 && desc.encoding != 0
01161 #endif
01162 ) {
01163 FM_DEBUG(" BEST:\n"
01164 " family: %s [%s]\n"
01165 " weight: %d, style: %d\n"
01166 " stretch: %d\n"
01167 " pixelSize: %d\n"
01168 " pitch: %c\n"
01169 " encoding: %d\n",
01170 desc.family->name.toLatin1().constData(),
01171 desc.foundry->name.isEmpty() ? "-- none --" : desc.foundry->name.toLatin1().constData(),
01172 desc.style->key.weight, desc.style->key.style,
01173 desc.style->key.stretch, desc.size ? desc.size->pixelSize : 0xffff,
01174 #ifdef Q_WS_X11
01175 desc.encoding->pitch, desc.encoding->encoding
01176 #else
01177 'p', 0
01178 #endif
01179 );
01180
01181 fe = loadEngine(script, fp, request, desc.family, desc.foundry, desc.style
01182 #ifdef Q_WS_X11
01183 , desc.size, desc.encoding, (force_encoding_id >= 0)
01184 #endif
01185 #ifdef Q_WS_QWS
01186 , desc.size
01187 #endif
01188 );
01189 } else {
01190 FM_DEBUG(" NO MATCH FOUND\n");
01191 }
01192 if (fe)
01193 initFontDef(desc, request, &fe->fontDef);
01194 }
01195
01196 if (fe) {
01197 if (fp) {
01198 QFontDef def = request;
01199 if (def.family.isEmpty()) {
01200 def.family = fp->request.family;
01201 def.family = def.family.left(def.family.indexOf(','));
01202 }
01203 QFontCache::Key key(def, script
01204 #if defined(Q_WS_X11)
01205 , fp->screen
01206 #endif
01207 );
01208 QFontCache::instance->insertEngine(key, fe);
01209 }
01210
01211 #if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
01212 if (scriptRequiresOpenType(script)) {
01213 QOpenType *ot = fe->openType();
01214 if (!ot || !ot->supportsScript(script)) {
01215 FM_DEBUG(" OpenType support missing for script");
01216 fe = 0;
01217 }
01218 }
01219 #endif
01220 }
01221
01222 if (!fe) {
01223 if (!request.family.isEmpty())
01224 return 0;
01225
01226 FM_DEBUG("returning box engine");
01227
01228 fe = new QFontEngineBox(request.pixelSize);
01229
01230 if (fp) {
01231 QFontCache::Key key(request, script
01232 #if defined(Q_WS_X11)
01233 , fp->screen
01234 #endif
01235 );
01236 QFontCache::instance->insertEngine(key, fe);
01237 }
01238 }
01239
01240 if (fp) {
01241 #if defined(Q_WS_X11)
01242 fe->fontDef.pointSize = qt_pointSize(fe->fontDef.pixelSize, fp->dpi);
01243 #elif defined(Q_WS_WIN)
01244 fe->fontDef.pointSize = qreal(fe->fontDef.pixelSize) * 72.0
01245 / GetDeviceCaps(shared_dc,LOGPIXELSY);
01246 #elif defined(Q_WS_MAC)
01247 fe->fontDef.pointSize = qt_mac_pointsize(fe->fontDef, fp->dpi);
01248 #else
01249 fe->fontDef.pointSize = qreal(fe->fontDef.pixelSize);
01250 #endif
01251 } else {
01252 fe->fontDef.pointSize = request.pointSize;
01253 }
01254
01255 return fe;
01256 }
01257 #endif
01258
01259 static QString styleString(int weight, QFont::Style style)
01260 {
01261 QString result;
01262 if (weight >= QFont::Black)
01263 result = QLatin1String("Black");
01264 else if (weight >= QFont::Bold)
01265 result = QLatin1String("Bold");
01266 else if (weight >= QFont::DemiBold)
01267 result = QLatin1String("Demi Bold");
01268 else if (weight < QFont::Normal)
01269 result = QLatin1String("Light");
01270
01271 if (style == QFont::StyleItalic)
01272 result += QLatin1String(" Italic");
01273 else if (style == QFont::StyleOblique)
01274 result += QLatin1String(" Oblique");
01275
01276 if (result.isEmpty())
01277 result = QLatin1String("Normal");
01278
01279 return result.simplified();
01280 }
01281
01287 QString QFontDatabase::styleString(const QFont &font)
01288 {
01289 return ::styleString(font.weight(), font.style());
01290 }
01291
01297 QString QFontDatabase::styleString(const QFontInfo &fontInfo)
01298 {
01299 return ::styleString(fontInfo.weight(), fontInfo.style());
01300 }
01301
01302
01359 QFontDatabase::QFontDatabase()
01360 {
01361 createDatabase();
01362
01363 d = privateDb();
01364 }
01365
01414 QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const
01415 {
01416 ::load();
01417 #ifdef Q_WS_X11
01418 ::checkSymbolFonts();
01419 #endif
01420
01421 QList<WritingSystem> list;
01422 for (int i = 0; i < d->count; ++i) {
01423 QtFontFamily *family = d->families[i];
01424 if (family->count == 0)
01425 continue;
01426 for (int x = Latin; x < WritingSystemsCount; ++x) {
01427 const WritingSystem writingSystem = WritingSystem(x);
01428 if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported))
01429 continue;
01430 if (!list.contains(writingSystem))
01431 list.append(writingSystem);
01432 }
01433 }
01434 qSort(list);
01435 return list;
01436 }
01437
01438
01445 QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems(const QString &family) const
01446 {
01447 QString familyName, foundryName;
01448 parseFontName(family, foundryName, familyName);
01449
01450 ::load();
01451 #ifdef Q_WS_X11
01452 ::checkSymbolFonts(familyName);
01453 #endif
01454
01455 QList<WritingSystem> list;
01456 QtFontFamily *f = d->family(familyName);
01457 if (!f || f->count == 0)
01458 return list;
01459
01460 for (int x = Latin; x < WritingSystemsCount; ++x) {
01461 const WritingSystem writingSystem = WritingSystem(x);
01462 if (f->writingSystems[writingSystem] & QtFontFamily::Supported)
01463 list.append(writingSystem);
01464 }
01465 return list;
01466 }
01467
01468
01479 QStringList QFontDatabase::families(WritingSystem writingSystem) const
01480 {
01481 ::load();
01482 #ifdef Q_WS_X11
01483 if (writingSystem != Any)
01484 ::checkSymbolFonts();
01485 #endif
01486
01487 QStringList flist;
01488 for (int i = 0; i < d->count; i++) {
01489 QtFontFamily *f = d->families[i];
01490 if (f->count == 0)
01491 continue;
01492 if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported))
01493 continue;
01494 if (f->count == 1) {
01495 flist.append(f->name);
01496 } else {
01497 for (int j = 0; j < f->count; j++) {
01498 QString str = f->name;
01499 QString foundry = f->foundries[j]->name;
01500 if (!foundry.isEmpty()) {
01501 str += QLatin1String(" [");
01502 str += foundry;
01503 str += QLatin1String("]");
01504 }
01505 flist.append(str);
01506 }
01507 }
01508 }
01509 return flist;
01510 }
01511
01519 QStringList QFontDatabase::styles(const QString &family) const
01520 {
01521 QString familyName, foundryName;
01522 parseFontName(family, foundryName, familyName);
01523
01524 ::load(familyName);
01525
01526 QStringList l;
01527 QtFontFamily *f = d->family(familyName);
01528 if (!f)
01529 return l;
01530
01531 QtFontFoundry allStyles(foundryName);
01532 for (int j = 0; j < f->count; j++) {
01533 QtFontFoundry *foundry = f->foundries[j];
01534 if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
01535 for (int k = 0; k < foundry->count; k++) {
01536 QtFontStyle::Key ke(foundry->styles[k]->key);
01537 ke.stretch = 0;
01538 allStyles.style(ke, true);
01539 }
01540 }
01541 }
01542
01543 for (int i = 0; i < allStyles.count; i++)
01544 l.append(::styleString(allStyles.styles[i]->key.weight, (QFont::Style)allStyles.styles[i]->key.style));
01545 return l;
01546 }
01547
01553 bool QFontDatabase::isFixedPitch(const QString &family,
01554 const QString &style) const
01555 {
01556 Q_UNUSED(style);
01557
01558 QString familyName, foundryName;
01559 parseFontName(family, foundryName, familyName);
01560
01561 ::load(familyName);
01562
01563 QtFontFamily *f = d->family(familyName);
01564 #if !defined(QWS) && defined(Q_OS_MAC)
01565 qt_mac_get_fixed_pitch(f);
01566 #endif
01567 return (f && f->fixedPitch);
01568 }
01569
01580 bool QFontDatabase::isBitmapScalable(const QString &family,
01581 const QString &style) const
01582 {
01583 bool bitmapScalable = false;
01584 QString familyName, foundryName;
01585 parseFontName(family, foundryName, familyName);
01586
01587 ::load(familyName);
01588
01589 QtFontStyle::Key styleKey(style);
01590
01591 QtFontFamily *f = d->family(familyName);
01592 if (!f) return bitmapScalable;
01593
01594 for (int j = 0; j < f->count; j++) {
01595 QtFontFoundry *foundry = f->foundries[j];
01596 if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
01597 for (int k = 0; k < foundry->count; k++)
01598 if ((style.isEmpty() || foundry->styles[k]->key == styleKey)
01599 && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
01600 bitmapScalable = true;
01601 goto end;
01602 }
01603 }
01604 }
01605 end:
01606 return bitmapScalable;
01607 }
01608
01609
01618 bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const
01619 {
01620 bool smoothScalable = false;
01621 QString familyName, foundryName;
01622 parseFontName(family, foundryName, familyName);
01623
01624 ::load(familyName);
01625
01626 QtFontStyle::Key styleKey(style);
01627
01628 QtFontFamily *f = d->family(familyName);
01629 if (!f) return smoothScalable;
01630
01631 for (int j = 0; j < f->count; j++) {
01632 QtFontFoundry *foundry = f->foundries[j];
01633 if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
01634 for (int k = 0; k < foundry->count; k++)
01635 if ((style.isEmpty() || foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
01636 smoothScalable = true;
01637 goto end;
01638 }
01639 }
01640 }
01641 end:
01642 return smoothScalable;
01643 }
01644
01651 bool QFontDatabase::isScalable(const QString &family,
01652 const QString &style) const
01653 {
01654 if (isSmoothlyScalable(family, style))
01655 return true;
01656
01657 return isBitmapScalable(family, style);
01658 }
01659
01660
01667 QList<int> QFontDatabase::pointSizes(const QString &family,
01668 const QString &style)
01669 {
01670 #if defined(Q_WS_WIN)
01671
01672 Q_UNUSED(family);
01673 Q_UNUSED(style);
01674 return standardSizes();
01675 #else
01676 bool smoothScalable = false;
01677 QString familyName, foundryName;
01678 parseFontName(family, foundryName, familyName);
01679
01680 ::load(familyName);
01681
01682 QtFontStyle::Key styleKey(style);
01683
01684 QList<int> sizes;
01685
01686 QtFontFamily *fam = d->family(familyName);
01687 if (!fam) return sizes;
01688
01689
01690 #ifdef Q_WS_X11
01691 int dpi = QX11Info::appDpiY();
01692 #else
01693 const int dpi = 72;
01694 #endif
01695
01696 for (int j = 0; j < fam->count; j++) {
01697 QtFontFoundry *foundry = fam->foundries[j];
01698 if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
01699 QtFontStyle *style = foundry->style(styleKey);
01700 if (!style) continue;
01701
01702 if (style->smoothScalable) {
01703 smoothScalable = true;
01704 goto end;
01705 }
01706 for (int l = 0; l < style->count; l++) {
01707 const QtFontSize *size = style->pixelSizes + l;
01708
01709 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
01710 const uint pointSize = qRound(size->pixelSize * dpi / 72.);
01711 if (! sizes.contains(pointSize))
01712 sizes.append(pointSize);
01713 }
01714 }
01715 }
01716 }
01717 end:
01718 if (smoothScalable)
01719 return standardSizes();
01720
01721 qSort(sizes);
01722 return sizes;
01723 #endif
01724 }
01725
01732 QFont QFontDatabase::font(const QString &family, const QString &style,
01733 int pointSize) const
01734 {
01735 QString familyName, foundryName;
01736 parseFontName(family, foundryName, familyName);
01737
01738 ::load(familyName);
01739
01740 QtFontFoundry allStyles(foundryName);
01741 QtFontFamily *f = d->family(familyName);
01742 if (!f) return QApplication::font();
01743
01744 for (int j = 0; j < f->count; j++) {
01745 QtFontFoundry *foundry = f->foundries[j];
01746 if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
01747 for (int k = 0; k < foundry->count; k++)
01748 allStyles.style(foundry->styles[k]->key, true);
01749 }
01750 }
01751
01752 QtFontStyle::Key styleKey(style);
01753 QtFontStyle *s = bestStyle(&allStyles, styleKey);
01754
01755 if (!s)
01756 return QApplication::font();
01757 QFont fnt(family, pointSize, s->key.weight);
01758 fnt.setStyle((QFont::Style)s->key.style);
01759 return fnt;
01760 }
01761
01762
01771 QList<int> QFontDatabase::smoothSizes(const QString &family,
01772 const QString &style)
01773 {
01774 #ifdef Q_WS_WIN
01775 Q_UNUSED(family);
01776 Q_UNUSED(style);
01777 return QFontDatabase::standardSizes();
01778 #else
01779 bool smoothScalable = false;
01780 QString familyName, foundryName;
01781 parseFontName(family, foundryName, familyName);
01782
01783 ::load(familyName);
01784
01785 QtFontStyle::Key styleKey(style);
01786
01787 QList<int> sizes;
01788
01789 QtFontFamily *fam = d->family(familyName);
01790 if (!fam)
01791 return sizes;
01792
01793 #ifdef Q_WS_X11
01794 int dpi = QX11Info::appDpiY();
01795 #else
01796 const int dpi = 72;
01797 #endif
01798 for (int j = 0; j < fam->count; j++) {
01799 QtFontFoundry *foundry = fam->foundries[j];
01800 if (foundryName.isEmpty() ||
01801 ucstricmp(foundry->name, foundryName) == 0) {
01802 QtFontStyle *style = foundry->style(styleKey);
01803 if (!style) continue;
01804
01805 if (style->smoothScalable) {
01806 smoothScalable = true;
01807 goto end;
01808 }
01809 for (int l = 0; l < style->count; l++) {
01810 const QtFontSize *size = style->pixelSizes + l;
01811
01812 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
01813 const uint pointSize = qRound(size->pixelSize * dpi / 72.);
01814 if (! sizes.contains(pointSize))
01815 sizes.append(pointSize);
01816 }
01817 }
01818 }
01819 }
01820 end:
01821 if (smoothScalable)
01822 return QFontDatabase::standardSizes();
01823
01824 qSort(sizes);
01825 return sizes;
01826 #endif
01827 }
01828
01829
01835 QList<int> QFontDatabase::standardSizes()
01836 {
01837 QList<int> ret;
01838 static const unsigned short standard[] =
01839 { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
01840 const unsigned short *sizes = standard;
01841 while (*sizes) ret << *sizes++;
01842 return ret;
01843 }
01844
01845
01852 bool QFontDatabase::italic(const QString &family, const QString &style) const
01853 {
01854 QString familyName, foundryName;
01855 parseFontName(family, foundryName, familyName);
01856
01857 ::load(familyName);
01858
01859 QtFontFoundry allStyles(foundryName);
01860 QtFontFamily *f = d->family(familyName);
01861 if (!f) return false;
01862
01863 for (int j = 0; j < f->count; j++) {
01864 QtFontFoundry *foundry = f->foundries[j];
01865 if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
01866 for (int k = 0; k < foundry->count; k++)
01867 allStyles.style(foundry->styles[k]->key, true);
01868 }
01869 }
01870
01871 QtFontStyle::Key styleKey(style);
01872 QtFontStyle *s = allStyles.style(styleKey);
01873 return s && s->key.style == QFont::StyleItalic;
01874 }
01875
01876
01883 bool QFontDatabase::bold(const QString &family,
01884 const QString &style) const
01885 {
01886 QString familyName, foundryName;
01887 parseFontName(family, foundryName, familyName);
01888
01889 ::load(familyName);
01890
01891 QtFontFoundry allStyles(foundryName);
01892 QtFontFamily *f = d->family(familyName);
01893 if (!f) return false;
01894
01895 for (int j = 0; j < f->count; j++) {
01896 QtFontFoundry *foundry = f->foundries[j];
01897 if (foundryName.isEmpty() ||
01898 ucstricmp(foundry->name, foundryName) == 0) {
01899 for (int k = 0; k < foundry->count; k++)
01900 allStyles.style(foundry->styles[k]->key, true);
01901 }
01902 }
01903
01904 QtFontStyle::Key styleKey(style);
01905 QtFontStyle *s = allStyles.style(styleKey);
01906 return s && s->key.weight >= QFont::Bold;
01907 }
01908
01909
01917 int QFontDatabase::weight(const QString &family,
01918 const QString &style) const
01919 {
01920 QString familyName, foundryName;
01921 parseFontName(family, foundryName, familyName);
01922
01923 ::load(familyName);
01924
01925 QtFontFoundry allStyles(foundryName);
01926 QtFontFamily *f = d->family(familyName);
01927 if (!f) return -1;
01928
01929 for (int j = 0; j < f->count; j++) {
01930 QtFontFoundry *foundry = f->foundries[j];
01931 if (foundryName.isEmpty() ||
01932 ucstricmp(foundry->name, foundryName) == 0) {
01933 for (int k = 0; k < foundry->count; k++)
01934 allStyles.style(foundry->styles[k]->key, true);
01935 }
01936 }
01937
01938 QtFontStyle::Key styleKey(style);
01939 QtFontStyle *s = allStyles.style(styleKey);
01940 return s ? s->key.weight : -1;
01941 }
01942
01943
01948 QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
01949 {
01950 const char *name = 0;
01951 switch (writingSystem) {
01952 case Any:
01953 name = "Any";
01954 break;
01955 case Latin:
01956 name = "Latin";
01957 break;
01958 case Greek:
01959 name = "Greek";
01960 break;
01961 case Cyrillic:
01962 name = "Cyrillic";
01963 break;
01964 case Armenian:
01965 name = "Armenian";
01966 break;
01967 case Hebrew:
01968 name = "Hebrew";
01969 break;
01970 case Arabic:
01971 name = "Arabic";
01972 break;
01973 case Syriac:
01974 name = "Syriac";
01975 break;
01976 case Thaana:
01977 name = "Thaana";
01978 break;
01979 case Devanagari:
01980 name = "Devanagari";
01981 break;
01982 case Bengali:
01983 name = "Bengali";
01984 break;
01985 case Gurmukhi:
01986 name = "Gurmukhi";
01987 break;
01988 case Gujarati:
01989 name = "Gujarati";
01990 break;
01991 case Oriya:
01992 name = "Oriya";
01993 break;
01994 case Tamil:
01995 name = "Tamil";
01996 break;
01997 case Telugu:
01998 name = "Telugu";
01999 break;
02000 case Kannada:
02001 name = "Kannada";
02002 break;
02003 case Malayalam:
02004 name = "Malayalam";
02005 break;
02006 case Sinhala:
02007 name = "Sinhala";
02008 break;
02009 case Thai:
02010 name = "Thai";
02011 break;
02012 case Lao:
02013 name = "Lao";
02014 break;
02015 case Tibetan:
02016 name = "Tibetan";
02017 break;
02018 case Myanmar:
02019 name = "Myanmar";
02020 break;
02021 case Georgian:
02022 name = "Georgian";
02023 break;
02024 case Khmer:
02025 name = "Khmer";
02026 break;
02027 case SimplifiedChinese:
02028 name = "Simplified Chinese";
02029 break;
02030 case TraditionalChinese:
02031 name = "Traditional Chinese";
02032 break;
02033 case Japanese:
02034 name = "Japanese";
02035 break;
02036 case Korean:
02037 name = "Korean";
02038 break;
02039 case Vietnamese:
02040 name = "Vietnamese";
02041 break;
02042 case Symbol:
02043 name = "Symbol";
02044 break;
02045 case Ogham:
02046 name = "Ogham";
02047 break;
02048 case Runic:
02049 name = "Runic";
02050 break;
02051 default:
02052 Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
02053 break;
02054 }
02055 return qApp ? qApp->translate("QFont", name) : QString::fromLatin1(name);
02056 }
02057
02058
02062 QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
02063 {
02064 QString sample;
02065 switch (writingSystem) {
02066 case Any:
02067 case Symbol:
02068
02069 sample += QLatin1String("AaBbzZ");
02070 break;
02071 case Latin:
02072
02073
02074 sample = QLatin1String("Aa");
02075 sample += QChar(0x00C3);
02076 sample += QChar(0x00E1);
02077 sample += QLatin1String("Zz");
02078 break;
02079 case Greek:
02080 sample += QChar(0x0393);
02081 sample += QChar(0x03B1);
02082 sample += QChar(0x03A9);
02083 sample += QChar(0x03C9);
02084 break;
02085 case Cyrillic:
02086 sample += QChar(0x0414);
02087 sample += QChar(0x0434);
02088 sample += QChar(0x0436);
02089 sample += QChar(0x0402);
02090 break;
02091 case Armenian:
02092 sample += QChar(0x053f);
02093 sample += QChar(0x054f);
02094 sample += QChar(0x056f);
02095 sample += QChar(0x057f);
02096 break;
02097 case Hebrew:
02098 sample += QChar(0x05D0);
02099 sample += QChar(0x05D1);
02100 sample += QChar(0x05D2);
02101 sample += QChar(0x05D3);
02102 break;
02103 case Arabic:
02104 sample += QChar(0x0628);
02105 sample += QChar(0x0629);
02106 sample += QChar(0x062A);
02107 sample += QChar(0x063A);
02108 break;
02109 case Syriac:
02110 sample += QChar(0x0715);
02111 sample += QChar(0x0725);
02112 sample += QChar(0x0716);
02113 sample += QChar(0x0726);
02114 break;
02115 case Thaana:
02116 sample += QChar(0x0784);
02117 sample += QChar(0x0794);
02118 sample += QChar(0x078c);
02119 sample += QChar(0x078d);
02120 break;
02121 case Devanagari:
02122 sample += QChar(0x0905);
02123 sample += QChar(0x0915);
02124 sample += QChar(0x0925);
02125 sample += QChar(0x0935);
02126 break;
02127 case Bengali:
02128 sample += QChar(0x0986);
02129 sample += QChar(0x0996);
02130 sample += QChar(0x09a6);
02131 sample += QChar(0x09b6);
02132 break;
02133 case Gurmukhi:
02134 sample += QChar(0x0a05);
02135 sample += QChar(0x0a15);
02136 sample += QChar(0x0a25);
02137 sample += QChar(0x0a35);
02138 break;
02139 case Gujarati:
02140 sample += QChar(0x0a85);
02141 sample += QChar(0x0a95);
02142 sample += QChar(0x0aa5);
02143 sample += QChar(0x0ab5);
02144 break;
02145 case Oriya:
02146 sample += QChar(0x0b06);
02147 sample += QChar(0x0b16);
02148 sample += QChar(0x0b2b);
02149 sample += QChar(0x0b36);
02150 break;
02151 case Tamil:
02152 sample += QChar(0x0b89);
02153 sample += QChar(0x0b99);
02154 sample += QChar(0x0ba9);
02155 sample += QChar(0x0bb9);
02156 break;
02157 case Telugu:
02158 sample += QChar(0x0c05);
02159 sample += QChar(0x0c15);
02160 sample += QChar(0x0c25);
02161 sample += QChar(0x0c35);
02162 break;
02163 case Kannada:
02164 sample += QChar(0x0c85);
02165 sample += QChar(0x0c95);
02166 sample += QChar(0x0ca5);
02167 sample += QChar(0x0cb5);
02168 break;
02169 case Malayalam:
02170 sample += QChar(0x0d05);
02171 sample += QChar(0x0d15);
02172 sample += QChar(0x0d25);
02173 sample += QChar(0x0d35);
02174 break;
02175 case Sinhala:
02176 sample += QChar(0x0d90);
02177 sample += QChar(0x0da0);
02178 sample += QChar(0x0db0);
02179 sample += QChar(0x0dc0);
02180 break;
02181 case Thai:
02182 sample += QChar(0x0e02);
02183 sample += QChar(0x0e12);
02184 sample += QChar(0x0e22);
02185 sample += QChar(0x0e32);
02186 break;
02187 case Lao:
02188 sample += QChar(0x0e8d);
02189 sample += QChar(0x0e9d);
02190 sample += QChar(0x0ead);
02191 sample += QChar(0x0ebd);
02192 break;
02193 case Tibetan:
02194 sample += QChar(0x0f00);
02195 sample += QChar(0x0f01);
02196 sample += QChar(0x0f02);
02197 sample += QChar(0x0f03);
02198 break;
02199 case Myanmar:
02200 sample += QChar(0x1000);
02201 sample += QChar(0x1001);
02202 sample += QChar(0x1002);
02203 sample += QChar(0x1003);
02204 break;
02205 case Georgian:
02206 sample += QChar(0x10a0);
02207 sample += QChar(0x10b0);
02208 sample += QChar(0x10c0);
02209 sample += QChar(0x10d0);
02210 break;
02211 case Khmer:
02212 sample += QChar(0x1780);
02213 sample += QChar(0x1790);
02214 sample += QChar(0x17b0);
02215 sample += QChar(0x17c0);
02216 break;
02217 case SimplifiedChinese:
02218 sample += QChar(0x4e2d);
02219 sample += QChar(0x6587);
02220 sample += QChar(0x8303);
02221 sample += QChar(0x4f8b);
02222 break;
02223 case TraditionalChinese:
02224 sample += QChar(0x4e2d);
02225 sample += QChar(0x6587);
02226 sample += QChar(0x7bc4);
02227 sample += QChar(0x4f8b);
02228 break;
02229 case Japanese:
02230 sample += QChar(0x3050);
02231 sample += QChar(0x3060);
02232 sample += QChar(0x30b0);
02233 sample += QChar(0x30c0);
02234 break;
02235 case Korean:
02236 sample += QChar(0xac00);
02237 sample += QChar(0xac11);
02238 sample += QChar(0xac1a);
02239 sample += QChar(0xac2f);
02240 break;
02241 case Vietnamese:
02242 break;
02243 case Ogham:
02244 sample += QChar(0x1681);
02245 sample += QChar(0x1682);
02246 sample += QChar(0x1683);
02247 sample += QChar(0x1684);
02248 break;
02249 case Runic:
02250 sample += QChar(0x16a0);
02251 sample += QChar(0x16a1);
02252 sample += QChar(0x16a2);
02253 sample += QChar(0x16a3);
02254 break;
02255 default:
02256 break;
02257 }
02258 return sample;
02259 }
02260
02261
02262 void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
02263 {
02264 ::parseFontName(name, foundry, family);
02265 }
02266
02267 void QFontDatabase::createDatabase()
02268 { initializeDb(); }
02269
02270 int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &fileName)
02271 {
02272 QFontDatabasePrivate::ApplicationFont font;
02273 font.data = fontData;
02274 font.fileName = fileName;
02275
02276 int i;
02277 for (i = 0; i < applicationFonts.count(); ++i)
02278 if (applicationFonts.at(i).families.isEmpty())
02279 break;
02280 if (i >= applicationFonts.count()) {
02281 applicationFonts.append(ApplicationFont());
02282 i = applicationFonts.count() - 1;
02283 }
02284
02285 if (font.fileName.isEmpty() && !fontData.isEmpty())
02286 font.fileName = QString::fromLatin1(":qmemoryfonts/") + QString::number(i);
02287
02288 registerFont(&font);
02289 if (font.families.isEmpty())
02290 return -1;
02291
02292 applicationFonts[i] = font;
02293
02294 invalidate();
02295 return i;
02296 }
02297
02315 int QFontDatabase::addApplicationFont(const QString &fileName)
02316 {
02317 QByteArray data;
02318 QFile f(fileName);
02319 if (!(f.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
02320 if (!f.open(QIODevice::ReadOnly))
02321 return -1;
02322 data = f.readAll();
02323 }
02324 return privateDb()->addAppFont(data, fileName);
02325 }
02326
02344 int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
02345 {
02346 return privateDb()->addAppFont(fontData, QString() );
02347 }
02348
02357 QStringList QFontDatabase::applicationFontFamilies(int id)
02358 {
02359 return privateDb()->applicationFonts.value(id).families;
02360 }
02361
02387 #include "qfontdatabase.moc"