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 <qplatformdefs.h>
00025
00026 #include <qdatetime.h>
00027 #include <qdebug.h>
00028 #include <qpaintdevice.h>
00029
00030 #include <private/qt_x11_p.h>
00031 #include "qx11info_x11.h"
00032 #include <qdebug.h>
00033 #include <qfile.h>
00034 #include <qtemporaryfile.h>
00035 #include <qabstractfileengine.h>
00036
00037 #include <ctype.h>
00038 #include <stdlib.h>
00039
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042 #include <fcntl.h>
00043 #include <sys/mman.h>
00044
00045 #ifndef QT_NO_FONTCONFIG
00046 #include <ft2build.h>
00047 #include FT_FREETYPE_H
00048 #endif
00049
00050
00051 extern double qt_pointSize(double pixelSize, int dpi);
00052 extern double qt_pixelSize(double pointSize, int dpi);
00053
00054 static inline void capitalize (char *s)
00055 {
00056 bool space = true;
00057 while(*s) {
00058 if (space)
00059 *s = toupper(*s);
00060 space = (*s == ' ');
00061 ++s;
00062 }
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #define make_tag( c1, c2, c3, c4 ) \
00074 ((((unsigned int)c1)<<24) | (((unsigned int)c2)<<16) | \
00075 (((unsigned int)c3)<<8) | ((unsigned int)c4))
00076
00077 struct XlfdEncoding {
00078 const char *name;
00079 int id;
00080 int mib;
00081 unsigned int hash1;
00082 unsigned int hash2;
00083 };
00084
00085 static const XlfdEncoding xlfd_encoding[] = {
00086 { "iso8859-1", 0, 4, make_tag('i','s','o','8'), make_tag('5','9','-','1') },
00087 { "iso8859-2", 1, 5, make_tag('i','s','o','8'), make_tag('5','9','-','2') },
00088 { "iso8859-3", 2, 6, make_tag('i','s','o','8'), make_tag('5','9','-','3') },
00089 { "iso8859-4", 3, 7, make_tag('i','s','o','8'), make_tag('5','9','-','4') },
00090 { "iso8859-9", 4, 12, make_tag('i','s','o','8'), make_tag('5','9','-','9') },
00091 { "iso8859-10", 5, 13, make_tag('i','s','o','8'), make_tag('9','-','1','0') },
00092 { "iso8859-13", 6, 109, make_tag('i','s','o','8'), make_tag('9','-','1','3') },
00093 { "iso8859-14", 7, 110, make_tag('i','s','o','8'), make_tag('9','-','1','4') },
00094 { "iso8859-15", 8, 111, make_tag('i','s','o','8'), make_tag('9','-','1','5') },
00095 { "hp-roman8", 9, 2004, make_tag('h','p','-','r'), make_tag('m','a','n','8') },
00096 { "iso8859-5", 10, 8, make_tag('i','s','o','8'), make_tag('5','9','-','5') },
00097 { "*-cp1251", 11, 2251, 0, make_tag('1','2','5','1') },
00098 { "koi8-ru", 12, 2084, make_tag('k','o','i','8'), make_tag('8','-','r','u') },
00099 { "koi8-u", 13, 2088, make_tag('k','o','i','8'), make_tag('i','8','-','u') },
00100 { "koi8-r", 14, 2084, make_tag('k','o','i','8'), make_tag('i','8','-','r') },
00101 { "iso8859-7", 15, 10, make_tag('i','s','o','8'), make_tag('5','9','-','7') },
00102 { "iso8859-8", 16, 85, make_tag('i','s','o','8'), make_tag('5','9','-','8') },
00103 { "gb18030-0", 17, -114, make_tag('g','b','1','8'), make_tag('3','0','-','0') },
00104 { "gb18030.2000-0", 18, -113, make_tag('g','b','1','8'), make_tag('0','0','-','0') },
00105 { "gbk-0", 19, -113, make_tag('g','b','k','-'), make_tag('b','k','-','0') },
00106 { "gb2312.*-0", 20, 57, make_tag('g','b','2','3'), 0 },
00107 { "jisx0201*-0", 21, 15, make_tag('j','i','s','x'), 0 },
00108 { "jisx0208*-0", 22, 63, make_tag('j','i','s','x'), 0 },
00109 { "ksc5601*-*", 23, 36, make_tag('k','s','c','5'), 0 },
00110 { "big5hkscs-0", 24, -2101, make_tag('b','i','g','5'), make_tag('c','s','-','0') },
00111 { "hkscs-1", 25, -2101, make_tag('h','k','s','c'), make_tag('c','s','-','1') },
00112 { "big5*-*", 26, -2026, make_tag('b','i','g','5'), 0 },
00113 { "tscii-*", 27, 2028, make_tag('t','s','c','i'), 0 },
00114 { "tis620*-*", 28, 2259, make_tag('t','i','s','6'), 0 },
00115 { "iso8859-11", 29, 2259, make_tag('i','s','o','8'), make_tag('9','-','1','1') },
00116 { "mulelao-1", 30, -4242, make_tag('m','u','l','e'), make_tag('a','o','-','1') },
00117 { "ethiopic-unicode", 31, 0, make_tag('e','t','h','i'), make_tag('c','o','d','e') },
00118 { "iso10646-1", 32, 0, make_tag('i','s','o','1'), make_tag('4','6','-','1') },
00119 { "unicode-*", 33, 0, make_tag('u','n','i','c'), 0 },
00120 { "*-symbol", 34, 0, 0, make_tag('m','b','o','l') },
00121 { "*-fontspecific", 35, 0, 0, make_tag('i','f','i','c') },
00122 { "fontspecific-*", 36, 0, make_tag('f','o','n','t'), 0 },
00123 { 0, 0, 0, 0, 0 }
00124 };
00125
00126 static const char writingSystems_for_xlfd_encoding[sizeof(xlfd_encoding)][QFontDatabase::WritingSystemsCount] = {
00127
00128 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00131 0 },
00132
00133 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00136 0 },
00137
00138 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00141 0 },
00142
00143 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00146 0 },
00147
00148 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00151 0 },
00152
00153 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00156 0 },
00157
00158 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00161 0 },
00162
00163 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00164 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00166 0 },
00167
00168 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00171 0 },
00172
00173 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
00174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00176 0 },
00177
00178 { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
00179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00181 0 },
00182
00183 { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
00184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00185 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00186 0 },
00187
00188 { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
00189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00191 0 },
00192
00193 { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
00194 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00195 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00196 0 },
00197
00198 { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
00199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00201 0 },
00202
00203 { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
00204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00205 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00206 0 },
00207
00208 { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
00209 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00210 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00211 0 },
00212
00213 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00214 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00215 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
00216 0 },
00217
00218 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00220 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
00221 0 },
00222
00223 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00224 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00225 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
00226 0 },
00227
00228 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00230 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
00231 0 },
00232
00233 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00235 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
00236 0 },
00237
00238 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00240 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
00241 0 },
00242
00243 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00244 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00245 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
00246 0 },
00247
00248 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00250 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
00251 0 },
00252
00253 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00254 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00255 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
00256 0 },
00257
00258 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00260 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
00261 0 },
00262
00263 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00264 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
00265 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00266 0 },
00267
00268 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00269 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
00270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00271 0 },
00272
00273 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00274 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
00275 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00276 0 },
00277
00278 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00279 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00280 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00281 0 },
00282
00283 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00286 0 },
00287
00288 { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
00289 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
00290 1, 1, 0, 1, 0, 1, 1, 0, 0, 0,
00291 0 },
00292
00293 { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
00294 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
00295 1, 1, 0, 1, 0, 1, 1, 0, 0, 0,
00296 0 },
00297
00298 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00301 1 },
00302
00303 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00306 1 },
00307
00308 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00311 1 }
00312
00313 };
00314
00315
00316
00317
00318 const int numEncodings = sizeof(xlfd_encoding) / sizeof(XlfdEncoding) - 1;
00319
00320 int qt_xlfd_encoding_id(const char *encoding)
00321 {
00322
00323 int len = strlen(encoding);
00324 if (len < 4)
00325 return -1;
00326 unsigned int hash1 = make_tag(encoding[0], encoding[1], encoding[2], encoding[3]);
00327 const char *ch = encoding + len - 4;
00328 unsigned int hash2 = make_tag(ch[0], ch[1], ch[2], ch[3]);
00329
00330 const XlfdEncoding *enc = xlfd_encoding;
00331 for (; enc->name; ++enc) {
00332 if ((enc->hash1 && enc->hash1 != hash1) ||
00333 (enc->hash2 && enc->hash2 != hash2))
00334 continue;
00335
00336
00337 const char *n = enc->name;
00338 const char *e = encoding;
00339 while (1) {
00340
00341 if (*e == '\0') {
00342 if (*n)
00343 break;
00344
00345 return enc->id;
00346 }
00347 if (*e == *n) {
00348 ++e;
00349 ++n;
00350 continue;
00351 }
00352 if (*n != '*')
00353 break;
00354 ++n;
00355
00356 while (*e && *e != *n)
00357 ++e;
00358 }
00359 }
00360
00361 return -1;
00362 }
00363
00364 int qt_mib_for_xlfd_encoding(const char *encoding)
00365 {
00366 int id = qt_xlfd_encoding_id(encoding);
00367 if (id != -1) return xlfd_encoding[id].mib;
00368 return 0;
00369 };
00370
00371 int qt_encoding_id_for_mib(int mib)
00372 {
00373 const XlfdEncoding *enc = xlfd_encoding;
00374 for (; enc->name; ++enc) {
00375 if (enc->mib == mib)
00376 return enc->id;
00377 }
00378 return -1;
00379 }
00380
00381 static const char * xlfd_for_id(int id)
00382 {
00383
00384
00385 if (id < 0 || id > numEncodings)
00386 return "*-*";
00387 return xlfd_encoding[id].name;
00388 }
00389
00390 enum XLFDFieldNames {
00391 Foundry,
00392 Family,
00393 Weight,
00394 Slant,
00395 Width,
00396 AddStyle,
00397 PixelSize,
00398 PointSize,
00399 ResolutionX,
00400 ResolutionY,
00401 Spacing,
00402 AverageWidth,
00403 CharsetRegistry,
00404 CharsetEncoding,
00405 NFontFields
00406 };
00407
00408
00409 static bool parseXFontName(char *fontName, char **tokens)
00410 {
00411 if (! fontName || fontName[0] == '0' || fontName[0] != '-') {
00412 tokens[0] = 0;
00413 return false;
00414 }
00415
00416 int i;
00417 ++fontName;
00418 for (i = 0; i < NFontFields && fontName && fontName[0]; ++i) {
00419 tokens[i] = fontName;
00420 for (;; ++fontName) {
00421 if (*fontName == '-')
00422 break;
00423 if (! *fontName) {
00424 fontName = 0;
00425 break;
00426 }
00427 }
00428
00429 if (fontName) *fontName++ = '\0';
00430 }
00431
00432 if (i < NFontFields) {
00433 for (int j = i ; j < NFontFields; ++j)
00434 tokens[j] = 0;
00435 return false;
00436 }
00437
00438 return true;
00439 }
00440
00441 static inline bool isZero(char *x)
00442 {
00443 return (x[0] == '0' && x[1] == 0);
00444 }
00445
00446 static inline bool isScalable(char **tokens)
00447 {
00448 return (isZero(tokens[PixelSize]) &&
00449 isZero(tokens[PointSize]) &&
00450 isZero(tokens[AverageWidth]));
00451 }
00452
00453 static inline bool isSmoothlyScalable(char **tokens)
00454 {
00455 return (isZero(tokens[ResolutionX]) &&
00456 isZero(tokens[ResolutionY]));
00457 }
00458
00459 static inline bool isFixedPitch(char **tokens)
00460 {
00461 return (tokens[Spacing][0] == 'm' ||
00462 tokens[Spacing][0] == 'c' ||
00463 tokens[Spacing][0] == 'M' ||
00464 tokens[Spacing][0] == 'C');
00465 }
00466
00467
00468
00469
00470
00471
00472
00473 bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi)
00474 {
00475 char *tokens[NFontFields];
00476 QByteArray buffer = xlfd;
00477 if (! parseXFontName(buffer.data(), tokens))
00478 return false;
00479
00480 capitalize(tokens[Family]);
00481 capitalize(tokens[Foundry]);
00482
00483 fd->family = QString::fromLatin1(tokens[Family]);
00484 QString foundry = QString::fromLatin1(tokens[Foundry]);
00485 if (! foundry.isEmpty() && foundry != QString::fromLatin1("*"))
00486 fd->family +=
00487 QString::fromLatin1(" [") + foundry + QString::fromLatin1("]");
00488
00489 if (qstrlen(tokens[AddStyle]) > 0)
00490 fd->addStyle = QString::fromLatin1(tokens[AddStyle]);
00491 else
00492 fd->addStyle.clear();
00493
00494 fd->pointSize = atoi(tokens[PointSize])/10.;
00495 fd->styleHint = QFont::AnyStyle;
00496
00497 char slant = tolower((uchar) tokens[Slant][0]);
00498 fd->style = (slant == 'o' ? QFont::StyleOblique : (slant == 'i' ? QFont::StyleItalic : QFont::StyleNormal));
00499 char fixed = tolower((uchar) tokens[Spacing][0]);
00500 fd->fixedPitch = (fixed == 'm' || fixed == 'c');
00501 fd->weight = getFontWeight(QLatin1String(tokens[Weight]));
00502
00503 int r = atoi(tokens[ResolutionY]);
00504 fd->pixelSize = atoi(tokens[PixelSize]);
00505
00506 if (r && fd->pixelSize && r != dpi) {
00507
00508 fd->pointSize = qt_pointSize(fd->pixelSize, dpi);
00509 } else if (fd->pixelSize == 0 && fd->pointSize) {
00510
00511 fd->pixelSize = qRound(qt_pixelSize(fd->pointSize, dpi));
00512 }
00513
00514 return true;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524 static bool qt_fillFontDef(XFontStruct *fs, QFontDef *fd, int dpi)
00525 {
00526 unsigned long value;
00527 if (!fs || !XGetFontProperty(fs, XA_FONT, &value))
00528 return false;
00529
00530 char *n = XGetAtomName(QX11Info::display(), value);
00531 QByteArray xlfd(n);
00532 if (n)
00533 XFree(n);
00534 return qt_fillFontDef(xlfd.toLower(), fd, dpi);
00535 }
00536
00537
00538 static QtFontStyle::Key getStyle(char ** tokens)
00539 {
00540 QtFontStyle::Key key;
00541
00542 char slant0 = tolower((uchar) tokens[Slant][0]);
00543
00544 if (slant0 == 'r') {
00545 if (tokens[Slant][1]) {
00546 char slant1 = tolower((uchar) tokens[Slant][1]);
00547
00548 if (slant1 == 'o')
00549 key.style = QFont::StyleOblique;
00550 else if (slant1 == 'i')
00551 key.style = QFont::StyleItalic;
00552 }
00553 } else if (slant0 == 'o')
00554 key.style = QFont::StyleOblique;
00555 else if (slant0 == 'i')
00556 key.style = QFont::StyleItalic;
00557
00558 key.weight = getFontWeight(QLatin1String(tokens[Weight]));
00559
00560 if (qstrcmp(tokens[Width], "normal") == 0) {
00561 key.stretch = 100;
00562 } else if (qstrcmp(tokens[Width], "semi condensed") == 0 ||
00563 qstrcmp(tokens[Width], "semicondensed") == 0) {
00564 key.stretch = 90;
00565 } else if (qstrcmp(tokens[Width], "condensed") == 0) {
00566 key.stretch = 80;
00567 } else if (qstrcmp(tokens[Width], "narrow") == 0) {
00568 key.stretch = 60;
00569 }
00570
00571 return key;
00572 }
00573
00574
00575 static bool xlfdsFullyLoaded = false;
00576 static unsigned char encodingLoaded[numEncodings];
00577
00578 static void loadXlfds(const char *reqFamily, int encoding_id)
00579 {
00580 QFontDatabasePrivate *db = privateDb();
00581 QtFontFamily *fontFamily = reqFamily ? db->family(QLatin1String(reqFamily)) : 0;
00582
00583
00584 if ((encoding_id == -1 && xlfdsFullyLoaded)
00585 || (encoding_id != -1 && encodingLoaded[encoding_id]))
00586 return;
00587 if (fontFamily && fontFamily->xlfdLoaded)
00588 return;
00589
00590 int fontCount;
00591
00592 QByteArray xlfd_pattern("-*-");
00593 xlfd_pattern += (reqFamily && reqFamily[0] != '\0') ? reqFamily : "*";
00594 xlfd_pattern += "-*-*-*-*-*-*-*-*-*-*-";
00595 xlfd_pattern += xlfd_for_id(encoding_id);
00596
00597 char **fontList = XListFonts(QX11Info::display(),
00598 xlfd_pattern,
00599 0xffff, &fontCount);
00600
00601
00602
00603 char *tokens[NFontFields];
00604
00605 for(int i = 0 ; i < fontCount ; i++) {
00606 if (! parseXFontName(fontList[i], tokens))
00607 continue;
00608
00609
00610
00611
00612 *(tokens[CharsetEncoding] - 1) = '-';
00613 int encoding_id = qt_xlfd_encoding_id(tokens[CharsetRegistry]);
00614 if (encoding_id == -1)
00615 continue;
00616
00617 char *familyName = tokens[Family];
00618 capitalize(familyName);
00619 char *foundryName = tokens[Foundry];
00620 capitalize(foundryName);
00621 QtFontStyle::Key styleKey = getStyle(tokens);
00622
00623 bool smooth_scalable = false;
00624 bool bitmap_scalable = false;
00625 if (isScalable(tokens)) {
00626 if (isSmoothlyScalable(tokens))
00627 smooth_scalable = true;
00628 else
00629 bitmap_scalable = true;
00630 }
00631 uint pixelSize = atoi(tokens[PixelSize]);
00632 uint xpointSize = atoi(tokens[PointSize]);
00633 uint xres = atoi(tokens[ResolutionX]);
00634 uint yres = atoi(tokens[ResolutionY]);
00635 uint avgwidth = atoi(tokens[AverageWidth]);
00636 bool fixedPitch = isFixedPitch(tokens);
00637
00638 if (avgwidth == 0 && pixelSize != 0) {
00639
00640
00641
00642
00643
00644
00645 continue;
00646 }
00647
00648 QtFontFamily *family = fontFamily ? fontFamily : db->family(QLatin1String(familyName), true);
00649 family->fontFileIndex = -1;
00650 family->symbol_checked = true;
00651 QtFontFoundry *foundry = family->foundry(QLatin1String(foundryName), true);
00652 QtFontStyle *style = foundry->style(styleKey, true);
00653
00654 delete [] style->weightName;
00655 style->weightName = qstrdup(tokens[Weight]);
00656 delete [] style->setwidthName;
00657 style->setwidthName = qstrdup(tokens[Width]);
00658
00659 if (smooth_scalable) {
00660 style->smoothScalable = true;
00661 style->bitmapScalable = false;
00662 pixelSize = SMOOTH_SCALABLE;
00663 }
00664 if (!style->smoothScalable && bitmap_scalable)
00665 style->bitmapScalable = true;
00666 if (!fixedPitch)
00667 family->fixedPitch = false;
00668
00669 QtFontSize *size = style->pixelSize(pixelSize, true);
00670 QtFontEncoding *enc =
00671 size->encodingID(encoding_id, xpointSize, xres, yres, avgwidth, true);
00672 enc->pitch = *tokens[Spacing];
00673 if (!enc->pitch) enc->pitch = '*';
00674
00675 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
00676 if (writingSystems_for_xlfd_encoding[encoding_id][i])
00677 family->writingSystems[i] = QtFontFamily::Supported;
00678 }
00679 }
00680 if (!reqFamily) {
00681
00682 if (encoding_id == -1)
00683 xlfdsFullyLoaded = true;
00684 else
00685 encodingLoaded[encoding_id] = true;
00686 }
00687
00688 XFreeFontNames(fontList);
00689 }
00690
00691
00692 #ifndef QT_NO_FONTCONFIG
00693
00694 #ifndef FC_WIDTH
00695 #define FC_WIDTH "width"
00696 #endif
00697
00698 static int getFCWeight(int fc_weight)
00699 {
00700 int qtweight = QFont::Black;
00701 if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
00702 qtweight = QFont::Light;
00703 else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
00704 qtweight = QFont::Normal;
00705 else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
00706 qtweight = QFont::DemiBold;
00707 else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
00708 qtweight = QFont::Bold;
00709
00710 return qtweight;
00711 }
00712
00713 QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request)
00714 {
00715 QFontDef fontDef;
00716
00717 FcChar8 *value = 0;
00718 if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) == FcResultMatch) {
00719 fontDef.family = QString::fromUtf8(reinterpret_cast<const char *>(value));
00720 fontDef.family.replace(QLatin1Char('-'), QLatin1Char(' '));
00721 fontDef.family.remove(QLatin1Char('/'));
00722 }
00723
00724 double dpi;
00725 if (FcPatternGetDouble(pattern, FC_DPI, 0, &dpi) != FcResultMatch)
00726 dpi = QX11Info::appDpiY();
00727
00728 double size;
00729 if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
00730 fontDef.pixelSize = qRound(size);
00731 else
00732 fontDef.pixelSize = 12;
00733
00734 fontDef.pointSize = qt_pointSize(fontDef.pixelSize, qRound(dpi));
00735
00736
00737
00738
00739
00740
00741 int weight;
00742 if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) != FcResultMatch)
00743 weight = FC_WEIGHT_MEDIUM;
00744 fontDef.weight = getFCWeight(weight);
00745
00746 int slant;
00747 if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant) != FcResultMatch)
00748 slant = FC_SLANT_ROMAN;
00749 fontDef.style = (slant == FC_SLANT_ITALIC)
00750 ? QFont::StyleItalic
00751 : ((slant == FC_SLANT_OBLIQUE)
00752 ? QFont::StyleOblique
00753 : QFont::StyleNormal);
00754
00755
00756 FcBool scalable;
00757 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
00758 scalable = false;
00759 if (scalable) {
00760 fontDef.stretch = request.stretch;
00761 fontDef.style = request.style;
00762 } else {
00763 int width;
00764 if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width) == FcResultMatch)
00765 fontDef.stretch = width;
00766 else
00767 fontDef.stretch = 100;
00768 }
00769
00770 int spacing;
00771 if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch) {
00772 fontDef.fixedPitch = (spacing >= FC_MONO);
00773 fontDef.ignorePitch = false;
00774 } else {
00775 fontDef.ignorePitch = true;
00776 }
00777
00778 return fontDef;
00779 }
00780
00781 static const char *specialLanguages[] = {
00782 "en",
00783 "el",
00784 "ru",
00785 "hy",
00786 "he",
00787 "ar",
00788 "syr",
00789 "div",
00790 "hi",
00791 "bn",
00792 "pa",
00793 "gu",
00794 "or",
00795 "ta",
00796 "te",
00797 "kn",
00798 "ml",
00799 "si",
00800 "th",
00801 "lo",
00802 "bo",
00803 "my",
00804 "ka",
00805 "ko",
00806 "",
00807 "",
00808 "km"
00809 };
00810 enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) };
00811
00812 static ushort specialChars[] = {
00813 0,
00814 0,
00815 0,
00816 0,
00817 0,
00818 0,
00819 0,
00820 0,
00821 0,
00822 0,
00823 0,
00824 0,
00825 0,
00826 0,
00827 0xc15,
00828 0xc95,
00829 0xd15,
00830 0xd9a,
00831 0,
00832 0,
00833 0,
00834 0x1000,
00835 0,
00836 0,
00837 0x1681,
00838 0x16a0,
00839 0
00840 };
00841 enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) };
00842
00843
00844
00845 static const char *languageForWritingSystem[] = {
00846 0,
00847 "en",
00848 "el",
00849 "ru",
00850 "hy",
00851 "he",
00852 "ar",
00853 "syr",
00854 "div",
00855 "hi",
00856 "bn",
00857 "pa",
00858 "gu",
00859 "or",
00860 "ta",
00861 "te",
00862 "kn",
00863 "ml",
00864 "si",
00865 "th",
00866 "lo",
00867 "bo",
00868 "my",
00869 "ka",
00870 "km",
00871 "zh-cn",
00872 "zh-tw",
00873 "ja",
00874 "ko",
00875 "vi",
00876 0,
00877 0,
00878 0
00879 };
00880 enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) };
00881
00882
00883
00884 static const ushort sampleCharForWritingSystem[] = {
00885 0,
00886 0,
00887 0,
00888 0,
00889 0,
00890 0,
00891 0,
00892 0,
00893 0,
00894 0,
00895 0,
00896 0,
00897 0,
00898 0,
00899 0,
00900 0xc15,
00901 0xc95,
00902 0xd15,
00903 0xd9a,
00904 0,
00905 0,
00906 0,
00907 0x1000,
00908 0,
00909 0,
00910 0,
00911 0,
00912 0,
00913 0,
00914 0,
00915 0,
00916 0x1681,
00917 0x16a0
00918 };
00919 enum { SampleCharCount = sizeof(sampleCharForWritingSystem) / sizeof(ushort) };
00920
00921
00922
00923
00924 static const char *openType[] = {
00925 0,
00926 0,
00927 0,
00928 0,
00929 0,
00930 0,
00931 0,
00932 "syrc",
00933 "thaa",
00934 "deva",
00935 "beng",
00936 "guru",
00937 "gurj",
00938 "orya",
00939 "taml",
00940 "telu",
00941 "knda",
00942 "mlym",
00943 "sinh",
00944 0,
00945 0,
00946 "tibt",
00947 "mymr",
00948 0,
00949 "khmr",
00950 0,
00951 0,
00952 0,
00953 0,
00954 0,
00955 0,
00956 0,
00957 0
00958 };
00959 enum { OpenTypeCount = sizeof(openType) / sizeof(const char *) };
00960
00961
00962 static void loadFontConfig()
00963 {
00964 Q_ASSERT_X(X11, "QFontDatabase",
00965 "A QApplication object needs to be constructed before FontConfig is used.");
00966 if (!X11->has_fontconfig)
00967 return;
00968
00969 Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialLanguageCount,
00970 "QFontDatabase", "New scripts have been added.");
00971 Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialCharCount,
00972 "QFontDatabase", "New scripts have been added.");
00973 Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == LanguageCount,
00974 "QFontDatabase", "New writing systems have been added.");
00975 Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == SampleCharCount,
00976 "QFontDatabase", "New writing systems have been added.");
00977 Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == OpenTypeCount,
00978 "QFontDatabase", "New writing systems have been added.");
00979
00980 QFontDatabasePrivate *db = privateDb();
00981 FcFontSet *fonts;
00982
00983 QString familyName;
00984 QString rawName;
00985 FcChar8 *value = 0;
00986 int weight_value;
00987 int slant_value;
00988 int spacing_value;
00989 FcChar8 *file_value;
00990 int index_value;
00991 FcChar8 *foundry_value;
00992 FcBool scalable;
00993
00994 {
00995 FcObjectSet *os = FcObjectSetCreate();
00996 FcPattern *pattern = FcPatternCreate();
00997 const char *properties [] = {
00998 FC_FAMILY, FC_WEIGHT, FC_SLANT,
00999 FC_SPACING, FC_FILE, FC_INDEX,
01000 FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT,
01001 FC_WIDTH,
01002 #if FC_VERSION >= 20297
01003 FC_CAPABILITY,
01004 #endif
01005 (const char *)0
01006 };
01007 const char **p = properties;
01008 while (*p) {
01009 FcObjectSetAdd(os, *p);
01010 ++p;
01011 }
01012 fonts = FcFontList(0, pattern, os);
01013 FcObjectSetDestroy(os);
01014 FcPatternDestroy(pattern);
01015 }
01016
01017 for (int i = 0; i < fonts->nfont; i++) {
01018 if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
01019 continue;
01020
01021 rawName = familyName = QString::fromUtf8((const char *)value);
01022 familyName.replace(QLatin1Char('-'), QLatin1Char(' '));
01023 familyName.remove(QLatin1Char('/'));
01024 slant_value = FC_SLANT_ROMAN;
01025 weight_value = FC_WEIGHT_MEDIUM;
01026 spacing_value = FC_PROPORTIONAL;
01027 file_value = 0;
01028 index_value = 0;
01029 scalable = FcTrue;
01030
01031 if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch)
01032 slant_value = FC_SLANT_ROMAN;
01033 if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch)
01034 weight_value = FC_WEIGHT_MEDIUM;
01035 if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch)
01036 spacing_value = FC_PROPORTIONAL;
01037 if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch)
01038 file_value = 0;
01039 if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &index_value) != FcResultMatch)
01040 index_value = 0;
01041 if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch)
01042 scalable = FcTrue;
01043 if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
01044 foundry_value = 0;
01045 QtFontFamily *family = db->family(familyName, true);
01046 family->rawName = rawName;
01047
01048 FcLangSet *langset = 0;
01049 FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset);
01050 if (res == FcResultMatch) {
01051 for (int i = 1; i < LanguageCount; ++i) {
01052 const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i];
01053 if (!lang) {
01054 family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
01055 } else {
01056 FcLangResult langRes = FcLangSetHasLang(langset, lang);
01057 if (langRes != FcLangDifferentLang)
01058 family->writingSystems[i] = QtFontFamily::Supported;
01059 else
01060 family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
01061 }
01062 }
01063 family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT;
01064 family->ftWritingSystemCheck = true;
01065 } else {
01066
01067
01068
01069 for (int i = 1; i < LanguageCount; ++i)
01070 family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
01071 family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported;
01072 }
01073
01074 FcCharSet *cs = 0;
01075 res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs);
01076 if (res == FcResultMatch) {
01077
01078
01079 for (int i = 1; i < SampleCharCount; ++i) {
01080 if (!sampleCharForWritingSystem[i])
01081 continue;
01082 if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i]))
01083 family->writingSystems[i] = QtFontFamily::Supported;
01084 }
01085 }
01086
01087 #if FC_VERSION >= 20297
01088 for (int j = 1; j < LanguageCount; ++j) {
01089 if (family->writingSystems[j] == QtFontFamily::Supported && requiresOpenType(j) && openType[j]) {
01090 FcChar8 *cap;
01091 res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap);
01092 if (res != FcResultMatch || !strstr((const char *)cap, openType[j]))
01093 family->writingSystems[j] = QtFontFamily::UnsupportedFT;
01094 }
01095 }
01096 #endif
01097
01098 QByteArray file((const char *)file_value);
01099 family->fontFilename = file;
01100 family->fontFileIndex = index_value;
01101
01102 QtFontStyle::Key styleKey;
01103 styleKey.style = (slant_value == FC_SLANT_ITALIC)
01104 ? QFont::StyleItalic
01105 : ((slant_value == FC_SLANT_OBLIQUE)
01106 ? QFont::StyleOblique
01107 : QFont::StyleNormal);
01108 styleKey.weight = getFCWeight(weight_value);
01109 if (!scalable) {
01110 int width = 100;
01111 FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width);
01112 styleKey.stretch = width;
01113 }
01114
01115 QtFontFoundry *foundry
01116 = family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true);
01117 QtFontStyle *style = foundry->style(styleKey, true);
01118
01119 if (spacing_value < FC_MONO)
01120 family->fixedPitch = false;
01121
01122 QtFontSize *size;
01123 if (scalable) {
01124 style->smoothScalable = true;
01125 size = style->pixelSize(SMOOTH_SCALABLE, true);
01126 } else {
01127 double pixel_size = 0;
01128 FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size);
01129 size = style->pixelSize((int)pixel_size, true);
01130 }
01131 QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
01132 enc->pitch = (spacing_value >= FC_CHARCELL ? 'c' :
01133 (spacing_value >= FC_MONO ? 'm' : 'p'));
01134 }
01135
01136 FcFontSetDestroy (fonts);
01137
01138 struct FcDefaultFont {
01139 const char *qtname;
01140 const char *rawname;
01141 bool fixed;
01142 };
01143 const FcDefaultFont defaults[] = {
01144 { "Serif", "serif", false },
01145 { "Sans Serif", "sans-serif", false },
01146 { "Monospace", "monospace", true },
01147 { 0, 0, false }
01148 };
01149 const FcDefaultFont *f = defaults;
01150 while (f->qtname) {
01151 QtFontFamily *family = db->family(QLatin1String(f->qtname), true);
01152 family->fixedPitch = f->fixed;
01153 family->rawName = QLatin1String(f->rawname);
01154 family->synthetic = true;
01155 QtFontFoundry *foundry = family->foundry(QString(), true);
01156
01157
01158 for (int i = 1; i < LanguageCount; ++i) {
01159 if (requiresOpenType(i))
01160 family->writingSystems[i] = QtFontFamily::UnsupportedFT;
01161 else
01162 family->writingSystems[i] = QtFontFamily::Supported;
01163 }
01164 family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT;
01165
01166 QtFontStyle::Key styleKey;
01167 for (int i = 0; i < 4; ++i) {
01168 styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic;
01169 styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal;
01170 QtFontStyle *style = foundry->style(styleKey, true);
01171 style->smoothScalable = true;
01172 QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true);
01173 QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
01174 enc->pitch = (f->fixed ? 'm' : 'p');
01175 }
01176 ++f;
01177 }
01178 }
01179 #endif // QT_NO_FONTCONFIG
01180
01181 static void initializeDb();
01182
01183 static void load(const QString &family = QString(), int script = -1)
01184 {
01185 if (X11->has_fontconfig) {
01186 initializeDb();
01187 return;
01188 }
01189
01190 #ifdef QFONTDATABASE_DEBUG
01191 QTime t;
01192 t.start();
01193 #endif
01194
01195 if (family.isNull() && script == -1) {
01196 loadXlfds(0, -1);
01197 } else {
01198 if (family.isNull()) {
01199
01200 for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
01201 if (scriptForWritingSystem[ws] != script)
01202 continue;
01203 for (int i = 0; i < numEncodings; ++i) {
01204 if (writingSystems_for_xlfd_encoding[i][ws])
01205 loadXlfds(0, i);
01206 }
01207 }
01208 } else {
01209 QtFontFamily *f = privateDb()->family(family);
01210
01211
01212 if (!f || !f->xlfdLoaded)
01213 loadXlfds(family.toLatin1(), -1);
01214 }
01215 }
01216
01217 #ifdef QFONTDATABASE_DEBUG
01218 FD_DEBUG("QFontDatabase: load(%s, %d) took %d ms",
01219 family.toLatin1().constData(), script, t.elapsed());
01220 #endif
01221 }
01222
01223 static void checkSymbolFont(QtFontFamily *family)
01224 {
01225 if (!family || family->symbol_checked || family->fontFilename.isEmpty())
01226 return;
01227
01228 family->symbol_checked = true;
01229
01230 extern FT_Library qt_getFreetype();
01231 FT_Library library = qt_getFreetype();
01232
01233 FT_Face face;
01234 FT_Error err = FT_New_Face(library, family->fontFilename, family->fontFileIndex, &face);
01235 if (err != FT_Err_Ok) {
01236 qWarning("checkSymbolFonts: Couldn't open face %s (%s/%d)",
01237 qPrintable(family->rawName), family->fontFilename.data(), family->fontFileIndex);
01238 return;
01239 }
01240 for (int i = 0; i < face->num_charmaps; ++i) {
01241 FT_CharMap cm = face->charmaps[i];
01242 if (cm->encoding == ft_encoding_adobe_custom
01243 || cm->encoding == ft_encoding_symbol) {
01244 for (int x = QFontDatabase::Latin; x < QFontDatabase::Other; ++x)
01245 family->writingSystems[x] = QtFontFamily::Unsupported;
01246 family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported;
01247 break;
01248 }
01249 }
01250
01251 FT_Done_Face(face);
01252 }
01253
01254 static void checkSymbolFonts(const QString &family = QString())
01255 {
01256 #ifndef QT_NO_FONTCONFIG
01257 QFontDatabasePrivate *d = privateDb();
01258
01259 if (family.isEmpty()) {
01260 for (int i = 0; i < d->count; ++i)
01261 checkSymbolFont(d->families[i]);
01262 } else {
01263 checkSymbolFont(d->family(family));
01264 }
01265 #endif
01266 }
01267
01268 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt);
01269
01270 static void initializeDb()
01271 {
01272 QFontDatabasePrivate *db = privateDb();
01273 if (!db || db->count)
01274 return;
01275
01276 QTime t;
01277 t.start();
01278
01279 #ifndef QT_NO_FONTCONFIG
01280 if (db->reregisterAppFonts) {
01281 db->reregisterAppFonts = false;
01282 for (int i = 0; i < db->applicationFonts.count(); ++i)
01283 if (!db->applicationFonts.at(i).families.isEmpty()) {
01284 registerFont(&db->applicationFonts[i]);
01285 }
01286 }
01287
01288 loadFontConfig();
01289 FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", t.elapsed());
01290 #endif
01291
01292 t.start();
01293
01294 #ifndef QT_NO_FONTCONFIG
01295 for (int i = 0; i < db->count; i++) {
01296 for (int j = 0; j < db->families[i]->count; ++j) {
01297 QtFontFoundry *foundry = db->families[i]->foundries[j];
01298 for (int k = 0; k < foundry->count; ++k) {
01299 QtFontStyle *style = foundry->styles[k];
01300 if (style->key.style != QFont::StyleNormal) continue;
01301
01302 QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE);
01303 if (! size) continue;
01304 QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
01305 if (! enc) continue;
01306
01307 QtFontStyle::Key key = style->key;
01308
01309
01310 key.style = QFont::StyleItalic;
01311 QtFontStyle *equiv = foundry->style(key);
01312 if (equiv) continue;
01313
01314
01315 key.style = QFont::StyleOblique;
01316 equiv = foundry->style(key);
01317 if (equiv) continue;
01318
01319
01320 equiv = foundry->style(key, true);
01321 equiv->smoothScalable = true;
01322
01323 QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true);
01324 QtFontEncoding *equiv_enc = equiv_size->encodingID(-1, 0, 0, 0, 0, true);
01325
01326
01327 equiv_enc->pitch = enc->pitch;
01328 }
01329 }
01330 }
01331 #endif
01332
01333
01334 #ifdef QFONTDATABASE_DEBUG
01335 #ifndef QT_NO_FONTCONFIG
01336 if (!X11->has_fontconfig)
01337 #endif
01338
01339 loadXlfds(0, -1);
01340
01341
01342 for (int f = 0; f < db->count; f++) {
01343 QtFontFamily *family = db->families[f];
01344 FD_DEBUG("'%s' %s fixed=%s", family->name.latin1(), (family->fixedPitch ? "fixed" : ""),
01345 (family->fixedPitch ? "yes" : "no"));
01346 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
01347 QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
01348 FD_DEBUG("\t%s: %s", QFontDatabase::writingSystemName(ws).toLatin1().constData(),
01349 ((family->writingSystems[i] & QtFontFamily::Supported) ? "Supported" :
01350 (family->writingSystems[i] & QtFontFamily::Unsupported) == QtFontFamily::Unsupported ?
01351 "Unsupported" : "Unknown"));
01352 }
01353
01354 for (int fd = 0; fd < family->count; fd++) {
01355 QtFontFoundry *foundry = family->foundries[fd];
01356 FD_DEBUG("\t\t'%s'", foundry->name.latin1());
01357 for (int s = 0; s < foundry->count; s++) {
01358 QtFontStyle *style = foundry->styles[s];
01359 FD_DEBUG("\t\t\tstyle: style=%d weight=%d (%s)\n"
01360 "\t\t\tstretch=%d (%s)",
01361 style->key.style, style->key.weight,
01362 style->weightName, style->key.stretch,
01363 style->setwidthName ? style->setwidthName : "nil");
01364 if (style->smoothScalable)
01365 FD_DEBUG("\t\t\t\tsmooth scalable");
01366 else if (style->bitmapScalable)
01367 FD_DEBUG("\t\t\t\tbitmap scalable");
01368 if (style->pixelSizes) {
01369 qDebug("\t\t\t\t%d pixel sizes", style->count);
01370 for (int z = 0; z < style->count; ++z) {
01371 QtFontSize *size = style->pixelSizes + z;
01372 for (int e = 0; e < size->count; ++e) {
01373 FD_DEBUG("\t\t\t\t size %5d pitch %c encoding %s",
01374 size->pixelSize,
01375 size->encodings[e].pitch,
01376 xlfd_for_id(size->encodings[e].encoding));
01377 }
01378 }
01379 }
01380 }
01381 }
01382 }
01383 #endif // QFONTDATABASE_DEBUG
01384 }
01385
01386
01387
01388
01389
01390
01391 static const char *styleHint(const QFontDef &request)
01392 {
01393 const char *stylehint = 0;
01394 switch (request.styleHint) {
01395 case QFont::SansSerif:
01396 stylehint = "sans-serif";
01397 break;
01398 case QFont::Serif:
01399 stylehint = "serif";
01400 break;
01401 case QFont::TypeWriter:
01402 stylehint = "monospace";
01403 break;
01404 default:
01405 if (request.fixedPitch)
01406 stylehint = "monospace";
01407 break;
01408 }
01409 return stylehint;
01410 }
01411
01412 #ifndef QT_NO_FONTCONFIG
01413
01414 void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontDef &request)
01415 {
01416 int weight_value = FC_WEIGHT_BLACK;
01417 if (request.weight == 0)
01418 weight_value = FC_WEIGHT_MEDIUM;
01419 else if (request.weight < (QFont::Light + QFont::Normal) / 2)
01420 weight_value = FC_WEIGHT_LIGHT;
01421 else if (request.weight < (QFont::Normal + QFont::DemiBold) / 2)
01422 weight_value = FC_WEIGHT_MEDIUM;
01423 else if (request.weight < (QFont::DemiBold + QFont::Bold) / 2)
01424 weight_value = FC_WEIGHT_DEMIBOLD;
01425 else if (request.weight < (QFont::Bold + QFont::Black) / 2)
01426 weight_value = FC_WEIGHT_BOLD;
01427 FcPatternAddInteger(pattern, FC_WEIGHT, weight_value);
01428
01429 int slant_value = FC_SLANT_ROMAN;
01430 if (request.style == QFont::StyleItalic)
01431 slant_value = FC_SLANT_ITALIC;
01432 else if (request.style == QFont::StyleOblique)
01433 slant_value = FC_SLANT_OBLIQUE;
01434 FcPatternAddInteger(pattern, FC_SLANT, slant_value);
01435
01436 double size_value = request.pixelSize;
01437 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value);
01438
01439 int stretch = request.stretch;
01440 if (!stretch)
01441 stretch = 100;
01442 FcPatternAddInteger(pattern, FC_WIDTH, stretch);
01443
01444 if (QX11Info::appDepth(screen) <= 8) {
01445
01446 FcPatternAddBool(pattern, FC_ANTIALIAS, false);
01447 } else if (request.styleStrategy & (QFont::PreferAntialias|QFont::NoAntialias)) {
01448 FcPatternAddBool(pattern, FC_ANTIALIAS,
01449 !(request.styleStrategy & QFont::NoAntialias));
01450 }
01451
01452 if (script != QUnicodeTables::Common) {
01453 Q_ASSERT(script < QUnicodeTables::ScriptCount);
01454 FcLangSet *ls = FcLangSetCreate();
01455 FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
01456 FcPatternAddLangSet(pattern, FC_LANG, ls);
01457 FcLangSetDestroy(ls);
01458 }
01459 }
01460
01461 static bool preferScalable(const QFontDef &request)
01462 {
01463 return request.styleStrategy & (QFont::PreferOutline|QFont::ForceOutline|QFont::PreferQuality|QFont::PreferAntialias);
01464 }
01465
01466
01467 static FcPattern *getFcPattern(const QFontPrivate *fp, int script, const QFontDef &request)
01468 {
01469 if (!X11->has_fontconfig)
01470 return 0;
01471
01472 FcPattern *pattern = FcPatternCreate();
01473 if (!pattern)
01474 return 0;
01475
01476 FcValue value;
01477 value.type = FcTypeString;
01478
01479 QtFontDesc desc;
01480 QStringList families_and_foundries = familyList(request);
01481 for (int i = 0; i < families_and_foundries.size(); ++i) {
01482 QString family, foundry;
01483 parseFontName(families_and_foundries.at(i), foundry, family);
01484 if (!family.isEmpty()) {
01485 QByteArray cs = family.toUtf8();
01486 value.u.s = (const FcChar8 *)cs.data();
01487 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
01488 }
01489 if (i == 0) {
01490 ::match(script, request, family, foundry, -1, &desc);
01491 if (!foundry.isEmpty()) {
01492 QByteArray cs = foundry.toUtf8();
01493 value.u.s = (const FcChar8 *)cs.data();
01494 FcPatternAddWeak(pattern, FC_FOUNDRY, value, FcTrue);
01495 }
01496 }
01497 }
01498
01499 const char *stylehint = styleHint(request);
01500 if (stylehint) {
01501 value.u.s = (const FcChar8 *)stylehint;
01502 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
01503 }
01504
01505 if (!request.ignorePitch) {
01506 char pitch_value = FC_PROPORTIONAL;
01507 if (request.fixedPitch || (desc.family && desc.family->fixedPitch))
01508 pitch_value = FC_MONO;
01509 FcPatternAddInteger(pattern, FC_SPACING, pitch_value);
01510 }
01511 FcPatternAddBool(pattern, FC_OUTLINE, !(request.styleStrategy & QFont::PreferBitmap));
01512 if (::preferScalable(request) || (desc.style && desc.style->smoothScalable))
01513 FcPatternAddBool(pattern, FC_SCALABLE, true);
01514
01515 qt_addPatternProps(pattern, fp->screen, script, request);
01516
01517 FcDefaultSubstitute(pattern);
01518 FcConfigSubstitute(0, pattern, FcMatchPattern);
01519 FcConfigSubstitute(0, pattern, FcMatchFont);
01520
01521
01522
01523 extern QString qt_fallback_font_family(int);
01524 QString fallback = qt_fallback_font_family(script);
01525 if (!fallback.isEmpty()) {
01526 QByteArray cs = fallback.toUtf8();
01527 value.u.s = (const FcChar8 *)cs.data();
01528 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
01529 }
01530
01531
01532 QString defaultFamily = QApplication::font().family();
01533 QByteArray cs = defaultFamily.toUtf8();
01534 value.u.s = (const FcChar8 *)cs.data();
01535 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
01536
01537
01538
01539 defaultFamily = QApplication::font().defaultFamily();
01540 cs = defaultFamily.toUtf8();
01541 value.u.s = (const FcChar8 *)cs.data();
01542 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
01543
01544 return pattern;
01545 }
01546
01547
01548 static void FcFontSetRemove(FcFontSet *fs, int at)
01549 {
01550 Q_ASSERT(at < fs->nfont);
01551 FcPatternDestroy(fs->fonts[at]);
01552 int len = (--fs->nfont - at) * sizeof(FcPattern *);;
01553 if (len > 0)
01554 memmove(fs->fonts + at, fs->fonts + at + 1, len);
01555 }
01556
01557 static QFontEngine *tryPatternLoad(FcPattern *p, int screen,
01558 const QFontDef &request, int script)
01559 {
01560 #ifdef FONT_MATCH_DEBUG
01561 FcChar8 *fam;
01562 FcPatternGetString(p, FC_FAMILY, 0, &fam);
01563 FM_DEBUG("==== trying %s\n", fam);
01564 #endif
01565 FM_DEBUG("passes charset test\n");
01566 FcPattern *pattern = FcPatternDuplicate(p);
01567
01568
01569 qt_addPatternProps(pattern, screen, script, request);
01570
01571 FcConfigSubstitute(0, pattern, FcMatchPattern);
01572 FcDefaultSubstitute(pattern);
01573 FcResult res;
01574 FcPattern *match = FcFontMatch(0, pattern, &res);
01575 QFontEngineFT *engine = 0;
01576
01577 if (script != QUnicodeTables::Common) {
01578
01579 if (specialChars[script]) {
01580
01581 FcCharSet *cs;
01582 if (FcPatternGetCharSet(match, FC_CHARSET, 0, &cs) != FcResultMatch)
01583 goto done;
01584 if (!FcCharSetHasChar(cs, specialChars[script]))
01585 goto done;
01586 } else {
01587 FcLangSet *langSet = 0;
01588 if (FcPatternGetLangSet(match, FC_LANG, 0, &langSet) != FcResultMatch)
01589 goto done;
01590 if (FcLangSetHasLang(langSet, (const FcChar8*)specialLanguages[script]) != FcLangEqual)
01591 goto done;
01592 }
01593 }
01594
01595
01596 if (request.styleStrategy & QFont::NoAntialias) {
01597 FcPatternDel(match, FC_ANTIALIAS);
01598 FcPatternAddBool(match, FC_ANTIALIAS, false);
01599 }
01600
01601 engine = new QFontEngineFT(match, qt_FcPatternToQFontDef(match, request), screen);
01602 if (engine->invalid()) {
01603 FM_DEBUG(" --> invalid!\n");
01604 delete engine;
01605 engine = 0;
01606 } else if (scriptRequiresOpenType(script)) {
01607 QOpenType *ot = engine->openType();
01608 if (!ot || !ot->supportsScript(script)) {
01609 FM_DEBUG(" OpenType support missing for script\n");
01610 delete engine;
01611 engine = 0;
01612 }
01613 }
01614 done:
01615 FcPatternDestroy(pattern);
01616 return engine;
01617 }
01618
01619 FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request)
01620 {
01621 FcResult result;
01622 FcFontSet *fs = FcFontSort(0, pattern, FcTrue, 0, &result);
01623 #ifdef FONT_MATCH_DEBUG
01624 FM_DEBUG("first font in fontset:\n");
01625 FcPatternPrint(fs->fonts[0]);
01626 #endif
01627
01628 FcBool forceScalable = request.styleStrategy & QFont::ForceOutline;
01629
01630
01631 if (forceScalable) {
01632 for (int i = 0; i < fs->nfont; ++i) {
01633 FcPattern *font = fs->fonts[i];
01634 FcResult res;
01635 FcBool scalable;
01636 res = FcPatternGetBool(font, FC_SCALABLE, 0, &scalable);
01637 if (res != FcResultMatch || !scalable) {
01638 FcFontSetRemove(fs, i);
01639 #ifdef FONT_MATCH_DEBUG
01640 FM_DEBUG("removing pattern:");
01641 FcPatternPrint(font);
01642 #endif
01643 --i;
01644 }
01645 }
01646 }
01647
01648 FM_DEBUG("final pattern contains %d fonts\n", fs->nfont);
01649
01650 return fs;
01651 }
01652
01653 static QFontEngine *loadFc(const QFontPrivate *fp, int script, const QFontDef &request)
01654 {
01655 FM_DEBUG("===================== loadFc: script=%d family='%s'\n", script, request.family.toLatin1().data());
01656 FcPattern *pattern = getFcPattern(fp, script, request);
01657
01658 #ifdef FONT_MATCH_DEBUG
01659 FM_DEBUG("\n\nfinal FcPattern contains:\n");
01660 FcPatternPrint(pattern);
01661 #endif
01662
01663 QFontEngine *fe = 0;
01664 fe = tryPatternLoad(pattern, fp->screen, request, script);
01665 if (!fe) {
01666 FcFontSet *fs = qt_fontSetForPattern(pattern, request);
01667
01668 for (int i = 0; !fe && i < fs->nfont; ++i)
01669 fe = tryPatternLoad(fs->fonts[i], fp->screen, request, script);
01670 FcFontSetDestroy(fs);
01671 FM_DEBUG("engine for script %d is %s\n", script, fe ? fe->fontDef.family.toLatin1().data(): "(null)");
01672 }
01673 if (fe
01674 && script == QUnicodeTables::Common
01675 && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) {
01676 fe = new QFontEngineMultiFT(fe, pattern, fp->screen, request);
01677 } else {
01678 FcPatternDestroy(pattern);
01679 }
01680 return fe;
01681 }
01682 #endif // QT_NO_FONTCONFIG
01683
01684 static QFontEngine *loadRaw(const QFontPrivate *fp, const QFontDef &request)
01685 {
01686 Q_ASSERT(fp && fp->rawMode);
01687
01688 QByteArray xlfd = request.family.toLatin1();
01689 FM_DEBUG("Loading XLFD (rawmode) '%s'", xlfd.data());
01690
01691 QFontEngine *fe;
01692 XFontStruct *xfs;
01693 if (!(xfs = XLoadQueryFont(QX11Info::display(), xlfd.data())))
01694 if (!(xfs = XLoadQueryFont(QX11Info::display(), "fixed")))
01695 return 0;
01696
01697 fe = new QFontEngineXLFD(xfs, xlfd, 0);
01698 if (! qt_fillFontDef(xfs, &fe->fontDef, fp->dpi) &&
01699 ! qt_fillFontDef(xlfd, &fe->fontDef, fp->dpi))
01700 fe->fontDef = QFontDef();
01701 return fe;
01702 }
01703
01704 QFontEngine *QFontDatabase::loadXlfd(int screen, int script, const QFontDef &request, int force_encoding_id)
01705 {
01706 QtFontDesc desc;
01707 FM_DEBUG() << "---> loadXlfd: request is" << request.family;
01708 QStringList families_and_foundries = ::familyList(request);
01709 const char *stylehint = styleHint(request);
01710 if (stylehint)
01711 families_and_foundries << QString::fromLatin1(stylehint);
01712 families_and_foundries << QString();
01713 FM_DEBUG() << "loadXlfd: list is" << families_and_foundries;
01714 for (int i = 0; i < families_and_foundries.size(); ++i) {
01715 QString family, foundry;
01716 ::parseFontName(families_and_foundries.at(i), foundry, family);
01717 FM_DEBUG("loadXlfd: >>>>>>>>>>>>>>trying to match '%s' encoding=%d", family.toLatin1().data(), force_encoding_id);
01718 ::match(script, request, family, foundry, force_encoding_id, &desc);
01719 if (desc.family)
01720 break;
01721 }
01722
01723 QFontEngine *fe = 0;
01724 if (force_encoding_id != -1
01725 || (request.styleStrategy & QFont::NoFontMerging)
01726 || (desc.family && desc.family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) {
01727 if (desc.family) {
01728 int px = desc.size->pixelSize;
01729 if (desc.style->smoothScalable && px == SMOOTH_SCALABLE)
01730 px = request.pixelSize;
01731 else if (desc.style->bitmapScalable && px == 0)
01732 px = request.pixelSize;
01733
01734 QByteArray xlfd("-");
01735 xlfd += desc.foundry->name.isEmpty() ? QByteArray("*") : desc.foundry->name.toLatin1();
01736 xlfd += "-";
01737 xlfd += desc.family->name.isEmpty() ? QByteArray("*") : desc.family->name.toLatin1();
01738 xlfd += "-";
01739 xlfd += desc.style->weightName ? desc.style->weightName : "*";
01740 xlfd += "-";
01741 xlfd += (desc.style->key.style == QFont::StyleItalic
01742 ? "i"
01743 : (desc.style->key.style == QFont::StyleOblique ? "o" : "r"));
01744 xlfd += "-";
01745 xlfd += desc.style->setwidthName ? desc.style->setwidthName : "*";
01746
01747 xlfd += "-*-";
01748 xlfd += QByteArray::number(px);
01749 xlfd += "-";
01750 xlfd += QByteArray::number(desc.encoding->xpoint);
01751 xlfd += "-";
01752 xlfd += QByteArray::number(desc.encoding->xres);
01753 xlfd += "-";
01754 xlfd += QByteArray::number(desc.encoding->yres);
01755 xlfd += "-";
01756 xlfd += desc.encoding->pitch;
01757 xlfd += "-";
01758 xlfd += QByteArray::number(desc.encoding->avgwidth);
01759 xlfd += "-";
01760 xlfd += xlfd_for_id(desc.encoding->encoding);
01761
01762 FM_DEBUG(" using XLFD: %s\n", xlfd.data());
01763
01764 const int mib = xlfd_encoding[desc.encoding->encoding].mib;
01765 XFontStruct *xfs;
01766 if ((xfs = XLoadQueryFont(QX11Info::display(), xlfd))) {
01767 fe = new QFontEngineXLFD(xfs, xlfd, mib);
01768 const int dpi = QX11Info::appDpiY();
01769 if (!qt_fillFontDef(xfs, &fe->fontDef, dpi)
01770 && !qt_fillFontDef(xlfd, &fe->fontDef, dpi)) {
01771 initFontDef(desc, request, &fe->fontDef);
01772 }
01773 }
01774 }
01775 if (!fe) {
01776 fe = new QFontEngineBox(request.pixelSize);
01777 fe->fontDef = QFontDef();
01778 }
01779 } else {
01780 QList<int> encodings;
01781 if (desc.encoding)
01782 encodings.append(int(desc.encoding->encoding));
01783
01784 if (desc.size) {
01785
01786 for (int i = 0; i < desc.size->count; ++i) {
01787 QtFontEncoding *e = desc.size->encodings + i;
01788 if (e == desc.encoding)
01789 continue;
01790 encodings.append(int(e->encoding));
01791 }
01792 }
01793
01794 const XlfdEncoding *enc = xlfd_encoding;
01795 for (; enc->name; ++enc) {
01796 if (!encodings.contains(enc->id))
01797 encodings.append(enc->id);
01798 }
01799
01800 #if defined(FONT_MATCH_DEBUG)
01801 FM_DEBUG(" using MultiXLFD, encodings:");
01802 for (int i = 0; i < encodings.size(); ++i) {
01803 const int id = encodings.at(i);
01804 FM_DEBUG(" %2d: %s", xlfd_encoding[id].id, xlfd_encoding[id].name);
01805 }
01806 #endif
01807
01808 fe = new QFontEngineMultiXLFD(request, encodings, screen);
01809 }
01810 return fe;
01811 }
01812
01817 void QFontDatabase::load(const QFontPrivate *d, int script)
01818 {
01819 Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
01820
01821 if (!privateDb()->count)
01822 initializeDb();
01823
01824
01825 QFontDef req = d->request;
01826 if (req.pixelSize <= 0)
01827 req.pixelSize = qRound(qt_pixelSize(req.pointSize, d->dpi));
01828 req.pointSize = 0;
01829 if (req.weight == 0)
01830 req.weight = QFont::Normal;
01831 if (req.stretch == 0)
01832 req.stretch = 100;
01833
01834 QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen);
01835 if (!d->engineData)
01836 getEngineData(d, key);
01837
01838
01839 if (d->engineData->engines[script])
01840 return;
01841
01842
01843 req.pointSize = qt_pointSize(req.pixelSize, d->dpi);
01844
01845 QFontEngine *fe = QFontCache::instance->findEngine(key);
01846
01847 if (!fe) {
01848 if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
01849 fe = new QTestFontEngine(req.pixelSize);
01850 fe->fontDef = req;
01851 } else if (d->rawMode) {
01852 fe = loadRaw(d, req);
01853 #ifndef QT_NO_FONTCONFIG
01854 } else if (X11->has_fontconfig) {
01855 fe = loadFc(d, script, req);
01856 #endif
01857 } else {
01858 fe = loadXlfd(d->screen, script, req);
01859 }
01860 if (!fe) {
01861 fe = new QFontEngineBox(req.pixelSize);
01862 fe->fontDef = QFontDef();
01863 }
01864 }
01865 if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
01866 for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
01867 if (!d->engineData->engines[i]) {
01868 d->engineData->engines[i] = fe;
01869 fe->ref.ref();
01870 }
01871 }
01872 } else {
01873 d->engineData->engines[script] = fe;
01874 fe->ref.ref();
01875 }
01876 QFontCache::instance->insertEngine(key, fe);
01877 }
01878
01879
01880 QByteArray qt_fontdata_from_index(int index)
01881 {
01882 return privateDb()->applicationFonts.value(index).data;
01883 }
01884
01885 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
01886 {
01887 #if defined(QT_NO_FONTCONFIG)
01888 return;
01889 #else
01890 if (!X11->has_fontconfig)
01891 return;
01892
01893 FcConfig *config = FcConfigGetCurrent();
01894 if (!config)
01895 return;
01896
01897 FcFontSet *set = FcConfigGetFonts(config, FcSetApplication);
01898 if (!set) {
01899 FcConfigAppFontAddFile(config, (const FcChar8 *)":/non-existant");
01900 set = FcConfigGetFonts(config, FcSetApplication);
01901 if (!set)
01902 return;
01903 }
01904
01905 QString fileNameForQuery = fnt->fileName;
01906 QTemporaryFile tmp;
01907
01908 if (!fnt->data.isEmpty()) {
01909 if (!tmp.open())
01910 return;
01911 tmp.write(fnt->data);
01912 tmp.flush();
01913 fileNameForQuery = tmp.fileName();
01914 }
01915
01916 int id = 0;
01917 FcBlanks *blanks = FcConfigGetBlanks(0);
01918 int count = 0;
01919
01920 QStringList families;
01921
01922 FcPattern *pattern = 0;
01923 do {
01924 pattern = FcFreeTypeQuery((const FcChar8 *)QFile::encodeName(fileNameForQuery).constData(),
01925 id, blanks, &count);
01926 if (!pattern)
01927 return;
01928
01929 FcPatternDel(pattern, FC_FILE);
01930 FcPatternAddString(pattern, FC_FILE, (const FcChar8 *)fnt->fileName.toUtf8().constData());
01931
01932 FcChar8 *fam = 0;
01933 if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
01934 QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam));
01935 family.replace(QLatin1Char('-'), QLatin1Char(' '));
01936 family.remove(QLatin1Char('/'));
01937 families << family;
01938 }
01939
01940 if (!FcFontSetAdd(set, pattern))
01941 return;
01942
01943 ++id;
01944 } while (pattern && id < count);
01945
01946 fnt->families = families;
01947 #endif
01948 }
01949
01950 bool QFontDatabase::removeApplicationFont(int handle)
01951 {
01952 #if defined(QT_NO_FONTCONFIG)
01953 return false;
01954 #else
01955 QFontDatabasePrivate *db = privateDb();
01956 if (handle < 0 || handle >= db->applicationFonts.count())
01957 return false;
01958
01959 FcConfigAppFontClear(0);
01960
01961 db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
01962
01963 db->reregisterAppFonts = true;
01964 db->invalidate();
01965 return true;
01966 #endif
01967 }
01968
01969 bool QFontDatabase::removeAllApplicationFonts()
01970 {
01971 #if defined(QT_NO_FONTCONFIG)
01972 return false;
01973 #else
01974 QFontDatabasePrivate *db = privateDb();
01975 if (db->applicationFonts.isEmpty())
01976 return false;
01977
01978 FcConfigAppFontClear(0);
01979 db->applicationFonts.clear();
01980 db->invalidate();
01981 return true;
01982 #endif
01983 }
01984