src/gui/text/qfontdatabase_x11.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <qplatformdefs.h>
       
    43 
       
    44 #include <qdatetime.h>
       
    45 #include <qdebug.h>
       
    46 #include <qpaintdevice.h>
       
    47 
       
    48 #include <private/qt_x11_p.h>
       
    49 #include "qx11info_x11.h"
       
    50 #include <qdebug.h>
       
    51 #include <qfile.h>
       
    52 #include <qtemporaryfile.h>
       
    53 #include <qabstractfileengine.h>
       
    54 
       
    55 #include <ctype.h>
       
    56 #include <stdlib.h>
       
    57 
       
    58 #include <sys/types.h>
       
    59 #include <sys/stat.h>
       
    60 #include <fcntl.h>
       
    61 #include <sys/mman.h>
       
    62 
       
    63 #include <private/qfontengine_x11_p.h>
       
    64 
       
    65 #ifndef QT_NO_FONTCONFIG
       
    66 #include <ft2build.h>
       
    67 #include FT_FREETYPE_H
       
    68 
       
    69 #if FC_VERSION >= 20402
       
    70 #include <fontconfig/fcfreetype.h>
       
    71 #endif
       
    72 #endif
       
    73 
       
    74 QT_BEGIN_NAMESPACE
       
    75 
       
    76 // from qfont_x11.cpp
       
    77 extern double qt_pointSize(double pixelSize, int dpi);
       
    78 extern double qt_pixelSize(double pointSize, int dpi);
       
    79 
       
    80 static inline void capitalize (char *s)
       
    81 {
       
    82     bool space = true;
       
    83     while(*s) {
       
    84         if (space)
       
    85             *s = toupper(*s);
       
    86         space = (*s == ' ');
       
    87         ++s;
       
    88     }
       
    89 }
       
    90 
       
    91 
       
    92 /*
       
    93   To regenerate the writingSystems_for_xlfd_encoding table, run
       
    94   'util/unicode/x11/makeencodings' and paste the generated
       
    95   'encodings.c' here.
       
    96 */
       
    97 // ----- begin of generated code -----
       
    98 
       
    99 #define make_tag( c1, c2, c3, c4 )                              \
       
   100     ((((unsigned int)c1)<<24) | (((unsigned int)c2)<<16) |      \
       
   101      (((unsigned int)c3)<<8) | ((unsigned int)c4))
       
   102 
       
   103 struct XlfdEncoding {
       
   104     const char *name;
       
   105     int id;
       
   106     int mib;
       
   107     unsigned int hash1;
       
   108     unsigned int hash2;
       
   109 };
       
   110 
       
   111 static const XlfdEncoding xlfd_encoding[] = {
       
   112     { "iso8859-1", 0, 4, make_tag('i','s','o','8'), make_tag('5','9','-','1') },
       
   113     { "iso8859-2", 1, 5, make_tag('i','s','o','8'), make_tag('5','9','-','2') },
       
   114     { "iso8859-3", 2, 6, make_tag('i','s','o','8'), make_tag('5','9','-','3') },
       
   115     { "iso8859-4", 3, 7, make_tag('i','s','o','8'), make_tag('5','9','-','4') },
       
   116     { "iso8859-9", 4, 12, make_tag('i','s','o','8'), make_tag('5','9','-','9') },
       
   117     { "iso8859-10", 5, 13, make_tag('i','s','o','8'), make_tag('9','-','1','0') },
       
   118     { "iso8859-13", 6, 109, make_tag('i','s','o','8'), make_tag('9','-','1','3') },
       
   119     { "iso8859-14", 7, 110, make_tag('i','s','o','8'), make_tag('9','-','1','4') },
       
   120     { "iso8859-15", 8, 111, make_tag('i','s','o','8'), make_tag('9','-','1','5') },
       
   121     { "hp-roman8", 9, 2004, make_tag('h','p','-','r'), make_tag('m','a','n','8') },
       
   122     { "iso8859-5", 10, 8, make_tag('i','s','o','8'), make_tag('5','9','-','5') },
       
   123     { "*-cp1251", 11, 2251, 0, make_tag('1','2','5','1') },
       
   124     { "koi8-ru", 12, 2084, make_tag('k','o','i','8'), make_tag('8','-','r','u') },
       
   125     { "koi8-u", 13, 2088, make_tag('k','o','i','8'), make_tag('i','8','-','u') },
       
   126     { "koi8-r", 14, 2084, make_tag('k','o','i','8'), make_tag('i','8','-','r') },
       
   127     { "iso8859-7", 15, 10, make_tag('i','s','o','8'), make_tag('5','9','-','7') },
       
   128     { "iso8859-8", 16, 85, make_tag('i','s','o','8'), make_tag('5','9','-','8') },
       
   129     { "gb18030-0", 17, -114, make_tag('g','b','1','8'), make_tag('3','0','-','0') },
       
   130     { "gb18030.2000-0", 18, -113, make_tag('g','b','1','8'), make_tag('0','0','-','0') },
       
   131     { "gbk-0", 19, -113, make_tag('g','b','k','-'), make_tag('b','k','-','0') },
       
   132     { "gb2312.*-0", 20, 57, make_tag('g','b','2','3'), 0 },
       
   133     { "jisx0201*-0", 21, 15, make_tag('j','i','s','x'), 0 },
       
   134     { "jisx0208*-0", 22, 63, make_tag('j','i','s','x'), 0 },
       
   135     { "ksc5601*-*", 23, 36, make_tag('k','s','c','5'), 0 },
       
   136     { "big5hkscs-0", 24, -2101, make_tag('b','i','g','5'), make_tag('c','s','-','0') },
       
   137     { "hkscs-1", 25, -2101, make_tag('h','k','s','c'), make_tag('c','s','-','1') },
       
   138     { "big5*-*", 26, -2026, make_tag('b','i','g','5'), 0 },
       
   139     { "tscii-*", 27, 2028, make_tag('t','s','c','i'), 0 },
       
   140     { "tis620*-*", 28, 2259, make_tag('t','i','s','6'), 0 },
       
   141     { "iso8859-11", 29, 2259, make_tag('i','s','o','8'), make_tag('9','-','1','1') },
       
   142     { "mulelao-1", 30, -4242, make_tag('m','u','l','e'), make_tag('a','o','-','1') },
       
   143     { "ethiopic-unicode", 31, 0, make_tag('e','t','h','i'), make_tag('c','o','d','e') },
       
   144     { "iso10646-1", 32, 0, make_tag('i','s','o','1'), make_tag('4','6','-','1') },
       
   145     { "unicode-*", 33, 0, make_tag('u','n','i','c'), 0 },
       
   146     { "*-symbol", 34, 0, 0, make_tag('m','b','o','l') },
       
   147     { "*-fontspecific", 35, 0, 0, make_tag('i','f','i','c') },
       
   148     { "fontspecific-*", 36, 0, make_tag('f','o','n','t'), 0 },
       
   149     { 0, 0, 0, 0, 0 }
       
   150 };
       
   151 
       
   152 static const char writingSystems_for_xlfd_encoding[sizeof(xlfd_encoding)][QFontDatabase::WritingSystemsCount] = {
       
   153     // iso8859-1
       
   154     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   155       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   156       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   157       0 },
       
   158     // iso8859-2
       
   159     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   160       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   161       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   162       0 },
       
   163     // iso8859-3
       
   164     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   165       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   166       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   167       0 },
       
   168     // iso8859-4
       
   169     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   170       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   171       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   172       0 },
       
   173     // iso8859-9
       
   174     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   175       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   176       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   177       0 },
       
   178     // iso8859-10
       
   179     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   180       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   181       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   182       0 },
       
   183     // iso8859-13
       
   184     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   185       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   186       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   187       0 },
       
   188     // iso8859-14
       
   189     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   190       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   191       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   192       0 },
       
   193     // iso8859-15
       
   194     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   195       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   196       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   197       0 },
       
   198     // hp-roman8
       
   199     { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       
   200       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   201       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   202       0 },
       
   203     // iso8859-5
       
   204     { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
       
   205       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   206       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   207       0 },
       
   208     // *-cp1251
       
   209     { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
       
   210       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   211       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   212       0 },
       
   213     // koi8-ru
       
   214     { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
       
   215       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   216       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   217       0 },
       
   218     // koi8-u
       
   219     { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
       
   220       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   221       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   222       0 },
       
   223     // koi8-r
       
   224     { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
       
   225       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   226       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   227       0 },
       
   228     // iso8859-7
       
   229     { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
       
   230       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   231       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   232       0 },
       
   233     // iso8859-8
       
   234     { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       
   235       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   236       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   237       0 },
       
   238     // gb18030-0
       
   239     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   240       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   241       0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       
   242       0 },
       
   243     // gb18030.2000-0
       
   244     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   245       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   246       0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       
   247       0 },
       
   248     // gbk-0
       
   249     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   250       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   251       0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       
   252       0 },
       
   253     // gb2312.*-0
       
   254     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   255       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   256       0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       
   257       0 },
       
   258     // jisx0201*-0
       
   259     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   260       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   261       0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
       
   262       0 },
       
   263     // jisx0208*-0
       
   264     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   265       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   266       0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
       
   267       0 },
       
   268     // ksc5601*-*
       
   269     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   270       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   271       0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
       
   272       0 },
       
   273     // big5hkscs-0
       
   274     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   275       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   276       0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
       
   277       0 },
       
   278     // hkscs-1
       
   279     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   280       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   281       0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
       
   282       0 },
       
   283     // big5*-*
       
   284     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   285       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   286       0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
       
   287       0 },
       
   288     // tscii-*
       
   289     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   290       0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
       
   291       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   292       0 },
       
   293     // tis620*-*
       
   294     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   295       0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
       
   296       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   297       0 },
       
   298     // iso8859-11
       
   299     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   300       0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
       
   301       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   302       0 },
       
   303     // mulelao-1
       
   304     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   305       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   306       1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   307       0 },
       
   308     // ethiopic-unicode
       
   309     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   310       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   311       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   312       0 },
       
   313     // iso10646-1
       
   314     { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
       
   315       0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
       
   316       1, 1, 0, 1, 0, 1, 1, 0, 0, 0,
       
   317       0 },
       
   318     // unicode-*
       
   319     { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
       
   320       0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
       
   321       1, 1, 0, 1, 0, 1, 1, 0, 0, 0,
       
   322       0 },
       
   323     // *-symbol
       
   324     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   325       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   326       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   327       1 },
       
   328     // *-fontspecific
       
   329     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   330       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   331       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   332       1 },
       
   333     // fontspecific-*
       
   334     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   335       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   336       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
   337       1 }
       
   338 
       
   339 };
       
   340 
       
   341 // ----- end of generated code -----
       
   342 
       
   343 
       
   344 const int numEncodings = sizeof(xlfd_encoding) / sizeof(XlfdEncoding) - 1;
       
   345 
       
   346 int qt_xlfd_encoding_id(const char *encoding)
       
   347 {
       
   348     // qDebug("looking for encoding id for '%s'", encoding);
       
   349     int len = strlen(encoding);
       
   350     if (len < 4)
       
   351         return -1;
       
   352     unsigned int hash1 = make_tag(encoding[0], encoding[1], encoding[2], encoding[3]);
       
   353     const char *ch = encoding + len - 4;
       
   354     unsigned int hash2 = make_tag(ch[0], ch[1], ch[2], ch[3]);
       
   355 
       
   356     const XlfdEncoding *enc = xlfd_encoding;
       
   357     for (; enc->name; ++enc) {
       
   358         if ((enc->hash1 && enc->hash1 != hash1) ||
       
   359             (enc->hash2 && enc->hash2 != hash2))
       
   360             continue;
       
   361         // hashes match, do a compare if strings match
       
   362         // the enc->name can contain '*'s we have to interpret correctly
       
   363         const char *n = enc->name;
       
   364         const char *e = encoding;
       
   365         while (1) {
       
   366             // qDebug("bol: *e='%c', *n='%c'", *e, *n);
       
   367             if (*e == '\0') {
       
   368                 if (*n)
       
   369                     break;
       
   370                 // qDebug("found encoding id %d", enc->id);
       
   371                 return enc->id;
       
   372             }
       
   373             if (*e == *n) {
       
   374                 ++e;
       
   375                 ++n;
       
   376                 continue;
       
   377             }
       
   378             if (*n != '*')
       
   379                 break;
       
   380             ++n;
       
   381             // qDebug("skip: *e='%c', *n='%c'", *e, *n);
       
   382             while (*e && *e != *n)
       
   383                 ++e;
       
   384         }
       
   385     }
       
   386     // qDebug("couldn't find encoding %s", encoding);
       
   387     return -1;
       
   388 }
       
   389 
       
   390 int qt_mib_for_xlfd_encoding(const char *encoding)
       
   391 {
       
   392     int id = qt_xlfd_encoding_id(encoding);
       
   393     if (id != -1) return xlfd_encoding[id].mib;
       
   394     return 0;
       
   395 }
       
   396 
       
   397 int qt_encoding_id_for_mib(int mib)
       
   398 {
       
   399     const XlfdEncoding *enc = xlfd_encoding;
       
   400     for (; enc->name; ++enc) {
       
   401         if (enc->mib == mib)
       
   402             return enc->id;
       
   403     }
       
   404     return -1;
       
   405 }
       
   406 
       
   407 static const char * xlfd_for_id(int id)
       
   408 {
       
   409     // special case: -1 returns the "*-*" encoding, allowing us to do full
       
   410     // database population in a single X server round trip.
       
   411     if (id < 0 || id > numEncodings)
       
   412         return "*-*";
       
   413     return xlfd_encoding[id].name;
       
   414 }
       
   415 
       
   416 enum XLFDFieldNames {
       
   417     Foundry,
       
   418     Family,
       
   419     Weight,
       
   420     Slant,
       
   421     Width,
       
   422     AddStyle,
       
   423     PixelSize,
       
   424     PointSize,
       
   425     ResolutionX,
       
   426     ResolutionY,
       
   427     Spacing,
       
   428     AverageWidth,
       
   429     CharsetRegistry,
       
   430     CharsetEncoding,
       
   431     NFontFields
       
   432 };
       
   433 
       
   434 // Splits an X font name into fields separated by '-'
       
   435 static bool parseXFontName(char *fontName, char **tokens)
       
   436 {
       
   437     if (! fontName || fontName[0] == '0' || fontName[0] != '-') {
       
   438         tokens[0] = 0;
       
   439         return false;
       
   440     }
       
   441 
       
   442     int          i;
       
   443     ++fontName;
       
   444     for (i = 0; i < NFontFields && fontName && fontName[0]; ++i) {
       
   445         tokens[i] = fontName;
       
   446         for (;; ++fontName) {
       
   447             if (*fontName == '-')
       
   448                 break;
       
   449             if (! *fontName) {
       
   450                 fontName = 0;
       
   451                 break;
       
   452             }
       
   453         }
       
   454 
       
   455         if (fontName) *fontName++ = '\0';
       
   456     }
       
   457 
       
   458     if (i < NFontFields) {
       
   459         for (int j = i ; j < NFontFields; ++j)
       
   460             tokens[j] = 0;
       
   461         return false;
       
   462     }
       
   463 
       
   464     return true;
       
   465 }
       
   466 
       
   467 static inline bool isZero(char *x)
       
   468 {
       
   469     return (x[0] == '0' && x[1] == 0);
       
   470 }
       
   471 
       
   472 static inline bool isScalable(char **tokens)
       
   473 {
       
   474     return (isZero(tokens[PixelSize]) &&
       
   475             isZero(tokens[PointSize]) &&
       
   476             isZero(tokens[AverageWidth]));
       
   477 }
       
   478 
       
   479 static inline bool isSmoothlyScalable(char **tokens)
       
   480 {
       
   481     return (isZero(tokens[ResolutionX]) &&
       
   482             isZero(tokens[ResolutionY]));
       
   483 }
       
   484 
       
   485 static inline bool isFixedPitch(char **tokens)
       
   486 {
       
   487     return (tokens[Spacing][0] == 'm' ||
       
   488             tokens[Spacing][0] == 'c' ||
       
   489             tokens[Spacing][0] == 'M' ||
       
   490             tokens[Spacing][0] == 'C');
       
   491 }
       
   492 
       
   493 /*
       
   494   Fills in a font definition (QFontDef) from an XLFD (X Logical Font
       
   495   Description).
       
   496 
       
   497   Returns true if the given xlfd is valid.
       
   498 */
       
   499 bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi, QtFontDesc *desc)
       
   500 {
       
   501     char *tokens[NFontFields];
       
   502     QByteArray buffer = xlfd;
       
   503     if (! parseXFontName(buffer.data(), tokens))
       
   504         return false;
       
   505 
       
   506     capitalize(tokens[Family]);
       
   507     capitalize(tokens[Foundry]);
       
   508 
       
   509     fd->styleStrategy |= QFont::NoAntialias;
       
   510     fd->family = QString::fromLatin1(tokens[Family]);
       
   511     QString foundry = QString::fromLatin1(tokens[Foundry]);
       
   512     if (! foundry.isEmpty() && foundry != QLatin1String("*") && (!desc || desc->family->count > 1))
       
   513         fd->family +=
       
   514             QLatin1String(" [") + foundry + QLatin1Char(']');
       
   515 
       
   516     if (qstrlen(tokens[AddStyle]) > 0)
       
   517         fd->addStyle = QString::fromLatin1(tokens[AddStyle]);
       
   518     else
       
   519         fd->addStyle.clear();
       
   520 
       
   521     fd->pointSize = atoi(tokens[PointSize])/10.;
       
   522     fd->styleHint = QFont::AnyStyle;        // ### any until we match families
       
   523 
       
   524     char slant = tolower((uchar) tokens[Slant][0]);
       
   525     fd->style = (slant == 'o' ? QFont::StyleOblique : (slant == 'i' ? QFont::StyleItalic : QFont::StyleNormal));
       
   526     char fixed = tolower((uchar) tokens[Spacing][0]);
       
   527     fd->fixedPitch = (fixed == 'm' || fixed == 'c');
       
   528     fd->weight = getFontWeight(QLatin1String(tokens[Weight]));
       
   529 
       
   530     int r = atoi(tokens[ResolutionY]);
       
   531     fd->pixelSize = atoi(tokens[PixelSize]);
       
   532     // not "0" or "*", or required DPI
       
   533     if (r && fd->pixelSize && r != dpi) {
       
   534         // calculate actual pointsize for display DPI
       
   535         fd->pointSize = qt_pointSize(fd->pixelSize, dpi);
       
   536     } else if (fd->pixelSize == 0 && fd->pointSize) {
       
   537         // calculate pixel size from pointsize/dpi
       
   538         fd->pixelSize = qRound(qt_pixelSize(fd->pointSize, dpi));
       
   539     }
       
   540 
       
   541     return true;
       
   542 }
       
   543 
       
   544 /*
       
   545   Fills in a font definition (QFontDef) from the font properties in an
       
   546   XFontStruct.
       
   547 
       
   548   Returns true if the QFontDef could be filled with properties from
       
   549   the XFontStruct.
       
   550 */
       
   551 static bool qt_fillFontDef(XFontStruct *fs, QFontDef *fd, int dpi, QtFontDesc *desc)
       
   552 {
       
   553     unsigned long value;
       
   554     if (!fs || !XGetFontProperty(fs, XA_FONT, &value))
       
   555         return false;
       
   556 
       
   557     char *n = XGetAtomName(QX11Info::display(), value);
       
   558     QByteArray xlfd(n);
       
   559     if (n)
       
   560         XFree(n);
       
   561     return qt_fillFontDef(xlfd.toLower(), fd, dpi, desc);
       
   562 }
       
   563 
       
   564 
       
   565 static QtFontStyle::Key getStyle(char ** tokens)
       
   566 {
       
   567     QtFontStyle::Key key;
       
   568 
       
   569     char slant0 = tolower((uchar) tokens[Slant][0]);
       
   570 
       
   571     if (slant0 == 'r') {
       
   572         if (tokens[Slant][1]) {
       
   573             char slant1 = tolower((uchar) tokens[Slant][1]);
       
   574 
       
   575             if (slant1 == 'o')
       
   576                 key.style = QFont::StyleOblique;
       
   577             else if (slant1 == 'i')
       
   578                 key.style = QFont::StyleItalic;
       
   579         }
       
   580     } else if (slant0 == 'o')
       
   581         key.style = QFont::StyleOblique;
       
   582     else if (slant0 == 'i')
       
   583         key.style = QFont::StyleItalic;
       
   584 
       
   585     key.weight = getFontWeight(QLatin1String(tokens[Weight]));
       
   586 
       
   587     if (qstrcmp(tokens[Width], "normal") == 0) {
       
   588         key.stretch = 100;
       
   589     } else if (qstrcmp(tokens[Width], "semi condensed") == 0 ||
       
   590                qstrcmp(tokens[Width], "semicondensed") == 0) {
       
   591         key.stretch = 90;
       
   592     } else if (qstrcmp(tokens[Width], "condensed") == 0) {
       
   593         key.stretch = 80;
       
   594     } else if (qstrcmp(tokens[Width], "narrow") == 0) {
       
   595         key.stretch = 60;
       
   596     }
       
   597 
       
   598     return key;
       
   599 }
       
   600 
       
   601 
       
   602 static bool xlfdsFullyLoaded = false;
       
   603 static unsigned char encodingLoaded[numEncodings];
       
   604 
       
   605 static void loadXlfds(const char *reqFamily, int encoding_id)
       
   606 {
       
   607     QFontDatabasePrivate *db = privateDb();
       
   608     QtFontFamily *fontFamily = reqFamily ? db->family(QLatin1String(reqFamily)) : 0;
       
   609 
       
   610     // make sure we don't load twice
       
   611     if ((encoding_id == -1 && xlfdsFullyLoaded)
       
   612         || (encoding_id != -1 && encodingLoaded[encoding_id]))
       
   613         return;
       
   614     if (fontFamily && fontFamily->xlfdLoaded)
       
   615         return;
       
   616 
       
   617     int fontCount;
       
   618     // force the X server to give us XLFDs
       
   619     QByteArray xlfd_pattern("-*-");
       
   620     xlfd_pattern += (reqFamily && reqFamily[0] != '\0') ? reqFamily : "*";
       
   621     xlfd_pattern += "-*-*-*-*-*-*-*-*-*-*-";
       
   622     xlfd_pattern += xlfd_for_id(encoding_id);
       
   623 
       
   624     char **fontList = XListFonts(QX11Info::display(),
       
   625                                  xlfd_pattern,
       
   626                                  0xffff, &fontCount);
       
   627     // qDebug("requesting xlfd='%s', got %d fonts", xlfd_pattern.data(), fontCount);
       
   628 
       
   629 
       
   630     char *tokens[NFontFields];
       
   631 
       
   632     for(int i = 0 ; i < fontCount ; i++) {
       
   633         if (! parseXFontName(fontList[i], tokens))
       
   634             continue;
       
   635 
       
   636         // get the encoding_id for this xlfd.  we need to do this
       
   637         // here, since we can pass -1 to this function to do full
       
   638         // database population
       
   639         *(tokens[CharsetEncoding] - 1) = '-';
       
   640         int encoding_id = qt_xlfd_encoding_id(tokens[CharsetRegistry]);
       
   641         if (encoding_id == -1)
       
   642             continue;
       
   643 
       
   644         char *familyName = tokens[Family];
       
   645         capitalize(familyName);
       
   646         char *foundryName = tokens[Foundry];
       
   647         capitalize(foundryName);
       
   648         QtFontStyle::Key styleKey = getStyle(tokens);
       
   649 
       
   650         bool smooth_scalable = false;
       
   651         bool bitmap_scalable = false;
       
   652         if (isScalable(tokens)) {
       
   653             if (isSmoothlyScalable(tokens))
       
   654                 smooth_scalable = true;
       
   655             else
       
   656                 bitmap_scalable = true;
       
   657         }
       
   658         uint pixelSize = atoi(tokens[PixelSize]);
       
   659         uint xpointSize = atoi(tokens[PointSize]);
       
   660         uint xres = atoi(tokens[ResolutionX]);
       
   661         uint yres = atoi(tokens[ResolutionY]);
       
   662         uint avgwidth = atoi(tokens[AverageWidth]);
       
   663         bool fixedPitch = isFixedPitch(tokens);
       
   664 
       
   665         if (avgwidth == 0 && pixelSize != 0) {
       
   666             /*
       
   667               Ignore bitmap scalable fonts that are automatically
       
   668               generated by some X servers.  We know they are bitmap
       
   669               scalable because even though they have a specified pixel
       
   670               size, the average width is zero.
       
   671             */
       
   672             continue;
       
   673         }
       
   674 
       
   675         QtFontFamily *family = fontFamily ? fontFamily : db->family(QLatin1String(familyName), true);
       
   676         family->fontFileIndex = -1;
       
   677         family->symbol_checked = true;
       
   678         QtFontFoundry *foundry = family->foundry(QLatin1String(foundryName), true);
       
   679         QtFontStyle *style = foundry->style(styleKey, true);
       
   680 
       
   681         delete [] style->weightName;
       
   682         style->weightName = qstrdup(tokens[Weight]);
       
   683         delete [] style->setwidthName;
       
   684         style->setwidthName = qstrdup(tokens[Width]);
       
   685 
       
   686         if (smooth_scalable) {
       
   687             style->smoothScalable = true;
       
   688             style->bitmapScalable = false;
       
   689             pixelSize = SMOOTH_SCALABLE;
       
   690         }
       
   691         if (!style->smoothScalable && bitmap_scalable)
       
   692             style->bitmapScalable = true;
       
   693         if (!fixedPitch)
       
   694             family->fixedPitch = false;
       
   695 
       
   696         QtFontSize *size = style->pixelSize(pixelSize, true);
       
   697         QtFontEncoding *enc =
       
   698             size->encodingID(encoding_id, xpointSize, xres, yres, avgwidth, true);
       
   699         enc->pitch = *tokens[Spacing];
       
   700         if (!enc->pitch) enc->pitch = '*';
       
   701 
       
   702         for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
       
   703             if (writingSystems_for_xlfd_encoding[encoding_id][i])
       
   704                 family->writingSystems[i] = QtFontFamily::Supported;
       
   705         }
       
   706     }
       
   707     if (!reqFamily) {
       
   708         // mark encoding as loaded
       
   709         if (encoding_id == -1)
       
   710             xlfdsFullyLoaded = true;
       
   711         else
       
   712             encodingLoaded[encoding_id] = true;
       
   713     }
       
   714 
       
   715     XFreeFontNames(fontList);
       
   716 }
       
   717 
       
   718 
       
   719 #ifndef QT_NO_FONTCONFIG
       
   720 
       
   721 #ifndef FC_WIDTH
       
   722 #define FC_WIDTH "width"
       
   723 #endif
       
   724 
       
   725 static int getFCWeight(int fc_weight)
       
   726 {
       
   727     int qtweight = QFont::Black;
       
   728     if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
       
   729         qtweight = QFont::Light;
       
   730     else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
       
   731         qtweight = QFont::Normal;
       
   732     else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
       
   733         qtweight = QFont::DemiBold;
       
   734     else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
       
   735         qtweight = QFont::Bold;
       
   736 
       
   737     return qtweight;
       
   738 }
       
   739 
       
   740 QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request)
       
   741 {
       
   742     QFontDef fontDef;
       
   743     fontDef.styleStrategy = request.styleStrategy;
       
   744 
       
   745     FcChar8 *value = 0;
       
   746     if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) == FcResultMatch) {
       
   747         fontDef.family = QString::fromUtf8(reinterpret_cast<const char *>(value));
       
   748     }
       
   749 
       
   750     double dpi;
       
   751     if (FcPatternGetDouble(pattern, FC_DPI, 0, &dpi) != FcResultMatch) {
       
   752         if (X11->display)
       
   753             dpi = QX11Info::appDpiY();
       
   754         else
       
   755             dpi = qt_defaultDpiY();
       
   756     }
       
   757 
       
   758     double size;
       
   759     if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
       
   760         fontDef.pixelSize = qRound(size);
       
   761     else
       
   762         fontDef.pixelSize = 12;
       
   763 
       
   764     fontDef.pointSize = qt_pointSize(fontDef.pixelSize, qRound(dpi));
       
   765 
       
   766     /* ###
       
   767        fontDef.styleHint
       
   768     */
       
   769 
       
   770     int weight;
       
   771     if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) != FcResultMatch)
       
   772         weight = FC_WEIGHT_MEDIUM;
       
   773     fontDef.weight = getFCWeight(weight);
       
   774 
       
   775     int slant;
       
   776     if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant) != FcResultMatch)
       
   777         slant = FC_SLANT_ROMAN;
       
   778     fontDef.style = (slant == FC_SLANT_ITALIC)
       
   779                     ? QFont::StyleItalic
       
   780                     : ((slant == FC_SLANT_OBLIQUE)
       
   781                        ? QFont::StyleOblique
       
   782                        : QFont::StyleNormal);
       
   783 
       
   784 
       
   785     FcBool scalable;
       
   786     if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
       
   787         scalable = false;
       
   788     if (scalable) {
       
   789         fontDef.stretch = request.stretch;
       
   790         fontDef.style = request.style;
       
   791     } else {
       
   792         int width;
       
   793         if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width) == FcResultMatch)
       
   794             fontDef.stretch = width;
       
   795         else
       
   796             fontDef.stretch = 100;
       
   797     }
       
   798 
       
   799     int spacing;
       
   800     if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch) {
       
   801         fontDef.fixedPitch = (spacing >= FC_MONO);
       
   802         fontDef.ignorePitch = false;
       
   803     } else {
       
   804         fontDef.ignorePitch = true;
       
   805     }
       
   806 
       
   807     return fontDef;
       
   808 }
       
   809 
       
   810 static const char *specialLanguages[] = {
       
   811     "en", // Common
       
   812     "el", // Greek
       
   813     "ru", // Cyrillic
       
   814     "hy", // Armenian
       
   815     "he", // Hebrew
       
   816     "ar", // Arabic
       
   817     "syr", // Syriac
       
   818     "div", // Thaana
       
   819     "hi", // Devanagari
       
   820     "bn", // Bengali
       
   821     "pa", // Gurmukhi
       
   822     "gu", // Gujarati
       
   823     "or", // Oriya
       
   824     "ta", // Tamil
       
   825     "te", // Telugu
       
   826     "kn", // Kannada
       
   827     "ml", // Malayalam
       
   828     "si", // Sinhala
       
   829     "th", // Thai
       
   830     "lo", // Lao
       
   831     "bo", // Tibetan
       
   832     "my", // Myanmar
       
   833     "ka", // Georgian
       
   834     "ko", // Hangul
       
   835     "", // Ogham
       
   836     "", // Runic
       
   837     "km" // Khmer
       
   838 };
       
   839 enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) };
       
   840 
       
   841 static const ushort specialChars[] = {
       
   842     0, // English
       
   843     0, // Greek
       
   844     0, // Cyrillic
       
   845     0, // Armenian
       
   846     0, // Hebrew
       
   847     0, // Arabic
       
   848     0, // Syriac
       
   849     0, // Thaana
       
   850     0, // Devanagari
       
   851     0, // Bengali
       
   852     0, // Gurmukhi
       
   853     0, // Gujarati
       
   854     0, // Oriya
       
   855     0, // Tamil
       
   856     0xc15, // Telugu
       
   857     0xc95, // Kannada
       
   858     0xd15, // Malayalam
       
   859     0xd9a, // Sinhala
       
   860     0, // Thai
       
   861     0, // Lao
       
   862     0, // Tibetan
       
   863     0x1000, // Myanmar
       
   864     0, // Georgian
       
   865     0, // Hangul
       
   866     0x1681, // Ogham
       
   867     0x16a0, // Runic
       
   868     0  // Khmer
       
   869 };
       
   870 enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) };
       
   871 
       
   872 // this could become a list of all languages used for each writing
       
   873 // system, instead of using the single most common language.
       
   874 static const char *languageForWritingSystem[] = {
       
   875     0,     // Any
       
   876     "en",  // Latin
       
   877     "el",  // Greek
       
   878     "ru",  // Cyrillic
       
   879     "hy",  // Armenian
       
   880     "he",  // Hebrew
       
   881     "ar",  // Arabic
       
   882     "syr", // Syriac
       
   883     "div", // Thaana
       
   884     "hi",  // Devanagari
       
   885     "bn",  // Bengali
       
   886     "pa",  // Gurmukhi
       
   887     "gu",  // Gujarati
       
   888     "or",  // Oriya
       
   889     "ta",  // Tamil
       
   890     "te",  // Telugu
       
   891     "kn",  // Kannada
       
   892     "ml",  // Malayalam
       
   893     "si",  // Sinhala
       
   894     "th",  // Thai
       
   895     "lo",  // Lao
       
   896     "bo",  // Tibetan
       
   897     "my",  // Myanmar
       
   898     "ka",  // Georgian
       
   899     "km",  // Khmer
       
   900     "zh-cn", // SimplifiedChinese
       
   901     "zh-tw", // TraditionalChinese
       
   902     "ja",  // Japanese
       
   903     "ko",  // Korean
       
   904     "vi",  // Vietnamese
       
   905     0, // Symbol
       
   906     0, // Ogham
       
   907     0 // Runic
       
   908 };
       
   909 enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) };
       
   910 
       
   911 // Unfortunately FontConfig doesn't know about some languages. We have to test these through the
       
   912 // charset. The lists below contain the systems where we need to do this.
       
   913 static const ushort sampleCharForWritingSystem[] = {
       
   914     0,     // Any
       
   915     0,  // Latin
       
   916     0,  // Greek
       
   917     0,  // Cyrillic
       
   918     0,  // Armenian
       
   919     0,  // Hebrew
       
   920     0,  // Arabic
       
   921     0, // Syriac
       
   922     0, // Thaana
       
   923     0,  // Devanagari
       
   924     0,  // Bengali
       
   925     0,  // Gurmukhi
       
   926     0,  // Gujarati
       
   927     0,  // Oriya
       
   928     0,  // Tamil
       
   929     0xc15,  // Telugu
       
   930     0xc95,  // Kannada
       
   931     0xd15,  // Malayalam
       
   932     0xd9a,  // Sinhala
       
   933     0,  // Thai
       
   934     0,  // Lao
       
   935     0,  // Tibetan
       
   936     0x1000,  // Myanmar
       
   937     0,  // Georgian
       
   938     0,  // Khmer
       
   939     0, // SimplifiedChinese
       
   940     0, // TraditionalChinese
       
   941     0,  // Japanese
       
   942     0,  // Korean
       
   943     0,  // Vietnamese
       
   944     0, // Symbol
       
   945     0x1681, // Ogham
       
   946     0x16a0 // Runic
       
   947 };
       
   948 enum { SampleCharCount = sizeof(sampleCharForWritingSystem) / sizeof(ushort) };
       
   949 
       
   950 // Newer FontConfig let's us sort out fonts that contain certain glyphs, but no
       
   951 // open type tables for is directly. Do this so we don't pick some strange
       
   952 // pseudo unicode font
       
   953 static const char *openType[] = {
       
   954     0,     // Any
       
   955     0,  // Latin
       
   956     0,  // Greek
       
   957     0,  // Cyrillic
       
   958     0,  // Armenian
       
   959     0,  // Hebrew
       
   960     0,  // Arabic
       
   961     "syrc",  // Syriac
       
   962     "thaa",  // Thaana
       
   963     "deva",  // Devanagari
       
   964     "beng",  // Bengali
       
   965     "guru",  // Gurmukhi
       
   966     "gurj",  // Gujarati
       
   967     "orya",  // Oriya
       
   968     "taml",  // Tamil
       
   969     "telu",  // Telugu
       
   970     "knda",  // Kannada
       
   971     "mlym",  // Malayalam
       
   972     "sinh",  // Sinhala
       
   973     0,  // Thai
       
   974     0,  // Lao
       
   975     "tibt",  // Tibetan
       
   976     "mymr",  // Myanmar
       
   977     0,  // Georgian
       
   978     "khmr",  // Khmer
       
   979     0, // SimplifiedChinese
       
   980     0, // TraditionalChinese
       
   981     0,  // Japanese
       
   982     0,  // Korean
       
   983     0,  // Vietnamese
       
   984     0, // Symbol
       
   985     0, // Ogham
       
   986     0 // Runic
       
   987 };
       
   988 enum { OpenTypeCount = sizeof(openType) / sizeof(const char *) };
       
   989 
       
   990 
       
   991 static void loadFontConfig()
       
   992 {
       
   993     Q_ASSERT_X(X11, "QFontDatabase",
       
   994                "A QApplication object needs to be constructed before FontConfig is used.");
       
   995     if (!X11->has_fontconfig)
       
   996         return;
       
   997 
       
   998     Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialLanguageCount,
       
   999                "QFontDatabase", "New scripts have been added.");
       
  1000     Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialCharCount,
       
  1001                "QFontDatabase", "New scripts have been added.");
       
  1002     Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == LanguageCount,
       
  1003                "QFontDatabase", "New writing systems have been added.");
       
  1004     Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == SampleCharCount,
       
  1005                "QFontDatabase", "New writing systems have been added.");
       
  1006     Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == OpenTypeCount,
       
  1007                "QFontDatabase", "New writing systems have been added.");
       
  1008 
       
  1009     QFontDatabasePrivate *db = privateDb();
       
  1010     FcFontSet  *fonts;
       
  1011 
       
  1012     QString familyName;
       
  1013     FcChar8 *value = 0;
       
  1014     int weight_value;
       
  1015     int slant_value;
       
  1016     int spacing_value;
       
  1017     FcChar8 *file_value;
       
  1018     int index_value;
       
  1019     FcChar8 *foundry_value;
       
  1020     FcBool scalable;
       
  1021 
       
  1022     {
       
  1023         FcObjectSet *os = FcObjectSetCreate();
       
  1024         FcPattern *pattern = FcPatternCreate();
       
  1025         const char *properties [] = {
       
  1026             FC_FAMILY, FC_WEIGHT, FC_SLANT,
       
  1027             FC_SPACING, FC_FILE, FC_INDEX,
       
  1028             FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT,
       
  1029             FC_WIDTH,
       
  1030 #if FC_VERSION >= 20297
       
  1031             FC_CAPABILITY,
       
  1032 #endif
       
  1033             (const char *)0
       
  1034         };
       
  1035         const char **p = properties;
       
  1036         while (*p) {
       
  1037             FcObjectSetAdd(os, *p);
       
  1038             ++p;
       
  1039         }
       
  1040         fonts = FcFontList(0, pattern, os);
       
  1041         FcObjectSetDestroy(os);
       
  1042         FcPatternDestroy(pattern);
       
  1043     }
       
  1044 
       
  1045     for (int i = 0; i < fonts->nfont; i++) {
       
  1046         if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
       
  1047             continue;
       
  1048         //         capitalize(value);
       
  1049         familyName = QString::fromUtf8((const char *)value);
       
  1050         slant_value = FC_SLANT_ROMAN;
       
  1051         weight_value = FC_WEIGHT_MEDIUM;
       
  1052         spacing_value = FC_PROPORTIONAL;
       
  1053 	file_value = 0;
       
  1054 	index_value = 0;
       
  1055 	scalable = FcTrue;
       
  1056 
       
  1057         if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch)
       
  1058 	    slant_value = FC_SLANT_ROMAN;
       
  1059         if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch)
       
  1060 	    weight_value = FC_WEIGHT_MEDIUM;
       
  1061         if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch)
       
  1062 	    spacing_value = FC_PROPORTIONAL;
       
  1063         if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch)
       
  1064 	    file_value = 0;
       
  1065         if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &index_value) != FcResultMatch)
       
  1066 	    index_value = 0;
       
  1067         if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch)
       
  1068 	    scalable = FcTrue;
       
  1069         if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
       
  1070 	    foundry_value = 0;
       
  1071         QtFontFamily *family = db->family(familyName, true);
       
  1072 
       
  1073         FcLangSet *langset = 0;
       
  1074         FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset);
       
  1075         if (res == FcResultMatch) {
       
  1076             for (int i = 1; i < LanguageCount; ++i) {
       
  1077                 const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i];
       
  1078                 if (!lang) {
       
  1079                     family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
       
  1080                 } else {
       
  1081                     FcLangResult langRes = FcLangSetHasLang(langset, lang);
       
  1082                     if (langRes != FcLangDifferentLang)
       
  1083                         family->writingSystems[i] = QtFontFamily::Supported;
       
  1084                     else
       
  1085                         family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
       
  1086                 }
       
  1087             }
       
  1088             family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT;
       
  1089             family->ftWritingSystemCheck = true;
       
  1090         } else {
       
  1091             // we set Other to supported for symbol fonts. It makes no
       
  1092             // sense to merge these with other ones, as they are
       
  1093             // special in a way.
       
  1094             for (int i = 1; i < LanguageCount; ++i)
       
  1095                 family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
       
  1096             family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported;
       
  1097         }
       
  1098 
       
  1099         FcCharSet *cs = 0;
       
  1100         res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs);
       
  1101         if (res == FcResultMatch) {
       
  1102             // some languages are not supported by FontConfig, we rather check the
       
  1103             // charset to detect these
       
  1104             for (int i = 1; i < SampleCharCount; ++i) {
       
  1105                 if (!sampleCharForWritingSystem[i])
       
  1106                     continue;
       
  1107                 if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i]))
       
  1108                     family->writingSystems[i] = QtFontFamily::Supported;
       
  1109             }
       
  1110         }
       
  1111 
       
  1112 #if FC_VERSION >= 20297
       
  1113         for (int j = 1; j < LanguageCount; ++j) {
       
  1114             if (family->writingSystems[j] == QtFontFamily::Supported && requiresOpenType(j) && openType[j]) {
       
  1115                 FcChar8 *cap;
       
  1116                 res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap);
       
  1117                 if (res != FcResultMatch || !strstr((const char *)cap, openType[j]))
       
  1118                     family->writingSystems[j] = QtFontFamily::UnsupportedFT;
       
  1119             }
       
  1120         }
       
  1121 #endif
       
  1122 
       
  1123         QByteArray file((const char *)file_value);
       
  1124         family->fontFilename = file;
       
  1125         family->fontFileIndex = index_value;
       
  1126 
       
  1127         QtFontStyle::Key styleKey;
       
  1128         styleKey.style = (slant_value == FC_SLANT_ITALIC)
       
  1129                          ? QFont::StyleItalic
       
  1130                          : ((slant_value == FC_SLANT_OBLIQUE)
       
  1131                             ? QFont::StyleOblique
       
  1132                             : QFont::StyleNormal);
       
  1133         styleKey.weight = getFCWeight(weight_value);
       
  1134         if (!scalable) {
       
  1135             int width = 100;
       
  1136             FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width);
       
  1137             styleKey.stretch = width;
       
  1138         }
       
  1139 
       
  1140         QtFontFoundry *foundry
       
  1141             = family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true);
       
  1142         QtFontStyle *style = foundry->style(styleKey, true);
       
  1143 
       
  1144         if (spacing_value < FC_MONO)
       
  1145             family->fixedPitch = false;
       
  1146 
       
  1147         QtFontSize *size;
       
  1148         if (scalable) {
       
  1149             style->smoothScalable = true;
       
  1150             size = style->pixelSize(SMOOTH_SCALABLE, true);
       
  1151         } else {
       
  1152             double pixel_size = 0;
       
  1153             FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size);
       
  1154             size = style->pixelSize((int)pixel_size, true);
       
  1155         }
       
  1156         QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
       
  1157         enc->pitch = (spacing_value >= FC_CHARCELL ? 'c' :
       
  1158                       (spacing_value >= FC_MONO ? 'm' : 'p'));
       
  1159     }
       
  1160 
       
  1161     FcFontSetDestroy (fonts);
       
  1162 
       
  1163     struct FcDefaultFont {
       
  1164         const char *qtname;
       
  1165         const char *rawname;
       
  1166         bool fixed;
       
  1167     };
       
  1168     const FcDefaultFont defaults[] = {
       
  1169         { "Serif", "serif", false },
       
  1170         { "Sans Serif", "sans-serif", false },
       
  1171         { "Monospace", "monospace", true },
       
  1172         { 0, 0, false }
       
  1173     };
       
  1174     const FcDefaultFont *f = defaults;
       
  1175     while (f->qtname) {
       
  1176         QtFontFamily *family = db->family(QLatin1String(f->qtname), true);
       
  1177         family->fixedPitch = f->fixed;
       
  1178         family->synthetic = true;
       
  1179         QtFontFoundry *foundry = family->foundry(QString(), true);
       
  1180 
       
  1181         // aliases only make sense for 'common', not for any of the specials
       
  1182         for (int i = 1; i < LanguageCount; ++i) {
       
  1183             if (requiresOpenType(i))
       
  1184                 family->writingSystems[i] = QtFontFamily::UnsupportedFT;
       
  1185             else
       
  1186                 family->writingSystems[i] = QtFontFamily::Supported;
       
  1187         }
       
  1188         family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT;
       
  1189 
       
  1190         QtFontStyle::Key styleKey;
       
  1191         for (int i = 0; i < 4; ++i) {
       
  1192             styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic;
       
  1193             styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal;
       
  1194             QtFontStyle *style = foundry->style(styleKey, true);
       
  1195             style->smoothScalable = true;
       
  1196             QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true);
       
  1197             QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
       
  1198             enc->pitch = (f->fixed ? 'm' : 'p');
       
  1199         }
       
  1200         ++f;
       
  1201     }
       
  1202 }
       
  1203 #endif // QT_NO_FONTCONFIG
       
  1204 
       
  1205 static void initializeDb();
       
  1206 
       
  1207 static void load(const QString &family = QString(), int script = -1, bool forceXLFD = false)
       
  1208 {
       
  1209     if (X11->has_fontconfig && !forceXLFD) {
       
  1210         initializeDb();
       
  1211         return;
       
  1212     }
       
  1213 
       
  1214 #ifdef QFONTDATABASE_DEBUG
       
  1215     QTime t;
       
  1216     t.start();
       
  1217 #endif
       
  1218 
       
  1219     if (family.isNull() && script == -1) {
       
  1220         loadXlfds(0, -1);
       
  1221     } else {
       
  1222         if (family.isNull()) {
       
  1223             // load all families in all writing systems that match \a script
       
  1224             for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
       
  1225                 if (scriptForWritingSystem[ws] != script)
       
  1226                     continue;
       
  1227                 for (int i = 0; i < numEncodings; ++i) {
       
  1228                     if (writingSystems_for_xlfd_encoding[i][ws])
       
  1229                         loadXlfds(0, i);
       
  1230                 }
       
  1231             }
       
  1232         } else {
       
  1233             QtFontFamily *f = privateDb()->family(family);
       
  1234             // could reduce this further with some more magic:
       
  1235             // would need to remember the encodings loaded for the family.
       
  1236             if (!f || !f->xlfdLoaded)
       
  1237                 loadXlfds(family.toLatin1(), -1);
       
  1238         }
       
  1239     }
       
  1240 
       
  1241 #ifdef QFONTDATABASE_DEBUG
       
  1242     FD_DEBUG("QFontDatabase: load(%s, %d) took %d ms",
       
  1243              family.toLatin1().constData(), script, t.elapsed());
       
  1244 #endif
       
  1245 }
       
  1246 
       
  1247 static void checkSymbolFont(QtFontFamily *family)
       
  1248 {
       
  1249     if (!family || family->symbol_checked || family->fontFilename.isEmpty())
       
  1250         return;
       
  1251 //     qDebug() << "checking " << family->rawName;
       
  1252     family->symbol_checked = true;
       
  1253 
       
  1254     QFontEngine::FaceId id;
       
  1255     id.filename = family->fontFilename;
       
  1256     id.index = family->fontFileIndex;
       
  1257     QFreetypeFace *f = QFreetypeFace::getFace(id);
       
  1258     if (!f) {
       
  1259         qWarning("checkSymbolFonts: Couldn't open face %s (%s/%d)",
       
  1260                  qPrintable(family->name), family->fontFilename.data(), family->fontFileIndex);
       
  1261         return;
       
  1262     }
       
  1263     for (int i = 0; i < f->face->num_charmaps; ++i) {
       
  1264         FT_CharMap cm = f->face->charmaps[i];
       
  1265         if (cm->encoding == FT_ENCODING_ADOBE_CUSTOM
       
  1266             || cm->encoding == FT_ENCODING_MS_SYMBOL) {
       
  1267             for (int x = QFontDatabase::Latin; x < QFontDatabase::Other; ++x)
       
  1268                 family->writingSystems[x] = QtFontFamily::Unsupported;
       
  1269             family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported;
       
  1270             break;
       
  1271         }
       
  1272     }
       
  1273     f->release(id);
       
  1274 }
       
  1275 
       
  1276 static void checkSymbolFonts(const QString &family = QString())
       
  1277 {
       
  1278 #ifndef QT_NO_FONTCONFIG
       
  1279     QFontDatabasePrivate *d = privateDb();
       
  1280 
       
  1281     if (family.isEmpty()) {
       
  1282         for (int i = 0; i < d->count; ++i)
       
  1283             checkSymbolFont(d->families[i]);
       
  1284     } else {
       
  1285         checkSymbolFont(d->family(family));
       
  1286     }
       
  1287 #endif
       
  1288 }
       
  1289 
       
  1290 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt);
       
  1291 
       
  1292 static void initializeDb()
       
  1293 {
       
  1294     QFontDatabasePrivate *db = privateDb();
       
  1295     if (!db || db->count)
       
  1296         return;
       
  1297 
       
  1298     QTime t;
       
  1299     t.start();
       
  1300 
       
  1301 #ifndef QT_NO_FONTCONFIG
       
  1302     if (db->reregisterAppFonts) {
       
  1303         db->reregisterAppFonts = false;
       
  1304         for (int i = 0; i < db->applicationFonts.count(); ++i)
       
  1305             if (!db->applicationFonts.at(i).families.isEmpty()) {
       
  1306                 registerFont(&db->applicationFonts[i]);
       
  1307             }
       
  1308     }
       
  1309 
       
  1310     loadFontConfig();
       
  1311     FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", t.elapsed());
       
  1312 #endif
       
  1313 
       
  1314     t.start();
       
  1315 
       
  1316 #ifndef QT_NO_FONTCONFIG
       
  1317     for (int i = 0; i < db->count; i++) {
       
  1318         for (int j = 0; j < db->families[i]->count; ++j) {        // each foundry
       
  1319             QtFontFoundry *foundry = db->families[i]->foundries[j];
       
  1320             for (int k = 0; k < foundry->count; ++k) {
       
  1321                 QtFontStyle *style = foundry->styles[k];
       
  1322                 if (style->key.style != QFont::StyleNormal) continue;
       
  1323 
       
  1324                 QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE);
       
  1325                 if (! size) continue; // should not happen
       
  1326                 QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
       
  1327                 if (! enc) continue; // should not happen either
       
  1328 
       
  1329                 QtFontStyle::Key key = style->key;
       
  1330 
       
  1331                 // does this style have an italic equivalent?
       
  1332                 key.style = QFont::StyleItalic;
       
  1333                 QtFontStyle *equiv = foundry->style(key);
       
  1334                 if (equiv) continue;
       
  1335 
       
  1336                 // does this style have an oblique equivalent?
       
  1337                 key.style = QFont::StyleOblique;
       
  1338                 equiv = foundry->style(key);
       
  1339                 if (equiv) continue;
       
  1340 
       
  1341                 // let's fake one...
       
  1342                 equiv = foundry->style(key, true);
       
  1343                 equiv->smoothScalable = true;
       
  1344 
       
  1345                 QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true);
       
  1346                 QtFontEncoding *equiv_enc = equiv_size->encodingID(-1, 0, 0, 0, 0, true);
       
  1347 
       
  1348                 // keep the same pitch
       
  1349                 equiv_enc->pitch = enc->pitch;
       
  1350             }
       
  1351         }
       
  1352     }
       
  1353 #endif
       
  1354 
       
  1355 
       
  1356 #ifdef QFONTDATABASE_DEBUG
       
  1357 #ifndef QT_NO_FONTCONFIG
       
  1358     if (!X11->has_fontconfig)
       
  1359 #endif
       
  1360         // load everything at startup in debug mode.
       
  1361         loadXlfds(0, -1);
       
  1362 
       
  1363     // print the database
       
  1364     for (int f = 0; f < db->count; f++) {
       
  1365         QtFontFamily *family = db->families[f];
       
  1366         FD_DEBUG("'%s' %s  fixed=%s", family->name.latin1(), (family->fixedPitch ? "fixed" : ""),
       
  1367                  (family->fixedPitch ? "yes" : "no"));
       
  1368         for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
       
  1369             QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
       
  1370             FD_DEBUG("\t%s: %s", QFontDatabase::writingSystemName(ws).toLatin1().constData(),
       
  1371                      ((family->writingSystems[i] & QtFontFamily::Supported) ? "Supported" :
       
  1372                       (family->writingSystems[i] & QtFontFamily::Unsupported) == QtFontFamily::Unsupported ?
       
  1373                       "Unsupported" : "Unknown"));
       
  1374         }
       
  1375 
       
  1376         for (int fd = 0; fd < family->count; fd++) {
       
  1377             QtFontFoundry *foundry = family->foundries[fd];
       
  1378             FD_DEBUG("\t\t'%s'", foundry->name.latin1());
       
  1379             for (int s = 0; s < foundry->count; s++) {
       
  1380                 QtFontStyle *style = foundry->styles[s];
       
  1381                 FD_DEBUG("\t\t\tstyle: style=%d weight=%d (%s)\n"
       
  1382                          "\t\t\tstretch=%d (%s)",
       
  1383                          style->key.style, style->key.weight,
       
  1384                          style->weightName, style->key.stretch,
       
  1385                          style->setwidthName ? style->setwidthName : "nil");
       
  1386                 if (style->smoothScalable)
       
  1387                     FD_DEBUG("\t\t\t\tsmooth scalable");
       
  1388                 else if (style->bitmapScalable)
       
  1389                     FD_DEBUG("\t\t\t\tbitmap scalable");
       
  1390                 if (style->pixelSizes) {
       
  1391                     qDebug("\t\t\t\t%d pixel sizes", style->count);
       
  1392                     for (int z = 0; z < style->count; ++z) {
       
  1393                         QtFontSize *size = style->pixelSizes + z;
       
  1394                         for (int e = 0; e < size->count; ++e) {
       
  1395                             FD_DEBUG("\t\t\t\t  size %5d pitch %c encoding %s",
       
  1396                                      size->pixelSize,
       
  1397                                      size->encodings[e].pitch,
       
  1398                                      xlfd_for_id(size->encodings[e].encoding));
       
  1399                         }
       
  1400                     }
       
  1401                 }
       
  1402             }
       
  1403         }
       
  1404     }
       
  1405 #endif // QFONTDATABASE_DEBUG
       
  1406 }
       
  1407 
       
  1408 
       
  1409 // --------------------------------------------------------------------------------------
       
  1410 // font loader
       
  1411 // --------------------------------------------------------------------------------------
       
  1412 
       
  1413 static const char *styleHint(const QFontDef &request)
       
  1414 {
       
  1415     const char *stylehint = 0;
       
  1416     switch (request.styleHint) {
       
  1417     case QFont::SansSerif:
       
  1418         stylehint = "sans-serif";
       
  1419         break;
       
  1420     case QFont::Serif:
       
  1421         stylehint = "serif";
       
  1422         break;
       
  1423     case QFont::TypeWriter:
       
  1424         stylehint = "monospace";
       
  1425         break;
       
  1426     default:
       
  1427         if (request.fixedPitch)
       
  1428             stylehint = "monospace";
       
  1429         break;
       
  1430     }
       
  1431     return stylehint;
       
  1432 }
       
  1433 
       
  1434 #ifndef QT_NO_FONTCONFIG
       
  1435 
       
  1436 void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontDef &request)
       
  1437 {
       
  1438     int weight_value = FC_WEIGHT_BLACK;
       
  1439     if (request.weight == 0)
       
  1440         weight_value = FC_WEIGHT_MEDIUM;
       
  1441     else if (request.weight < (QFont::Light + QFont::Normal) / 2)
       
  1442         weight_value = FC_WEIGHT_LIGHT;
       
  1443     else if (request.weight < (QFont::Normal + QFont::DemiBold) / 2)
       
  1444         weight_value = FC_WEIGHT_MEDIUM;
       
  1445     else if (request.weight < (QFont::DemiBold + QFont::Bold) / 2)
       
  1446         weight_value = FC_WEIGHT_DEMIBOLD;
       
  1447     else if (request.weight < (QFont::Bold + QFont::Black) / 2)
       
  1448         weight_value = FC_WEIGHT_BOLD;
       
  1449     FcPatternAddInteger(pattern, FC_WEIGHT, weight_value);
       
  1450 
       
  1451     int slant_value = FC_SLANT_ROMAN;
       
  1452     if (request.style == QFont::StyleItalic)
       
  1453         slant_value = FC_SLANT_ITALIC;
       
  1454     else if (request.style == QFont::StyleOblique)
       
  1455         slant_value = FC_SLANT_OBLIQUE;
       
  1456     FcPatternAddInteger(pattern, FC_SLANT, slant_value);
       
  1457 
       
  1458     double size_value = qMax(1, request.pixelSize);
       
  1459     FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value);
       
  1460 
       
  1461     int stretch = request.stretch;
       
  1462     if (!stretch)
       
  1463         stretch = 100;
       
  1464     FcPatternAddInteger(pattern, FC_WIDTH, stretch);
       
  1465 
       
  1466     if (X11->display && QX11Info::appDepth(screen) <= 8) {
       
  1467         // can't do antialiasing on 8bpp
       
  1468         FcPatternAddBool(pattern, FC_ANTIALIAS, false);
       
  1469     } else if (request.styleStrategy & (QFont::PreferAntialias|QFont::NoAntialias)) {
       
  1470         FcPatternAddBool(pattern, FC_ANTIALIAS,
       
  1471                          !(request.styleStrategy & QFont::NoAntialias));
       
  1472     }
       
  1473 
       
  1474     if (script != QUnicodeTables::Common) {
       
  1475         Q_ASSERT(script < QUnicodeTables::ScriptCount);
       
  1476         FcLangSet *ls = FcLangSetCreate();
       
  1477         FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
       
  1478         FcPatternAddLangSet(pattern, FC_LANG, ls);
       
  1479         FcLangSetDestroy(ls);
       
  1480     }
       
  1481 }
       
  1482 
       
  1483 static bool preferScalable(const QFontDef &request)
       
  1484 {
       
  1485     return request.styleStrategy & (QFont::PreferOutline|QFont::ForceOutline|QFont::PreferQuality|QFont::PreferAntialias);
       
  1486 }
       
  1487 
       
  1488 
       
  1489 static FcPattern *getFcPattern(const QFontPrivate *fp, int script, const QFontDef &request)
       
  1490 {
       
  1491     if (!X11->has_fontconfig)
       
  1492         return 0;
       
  1493 
       
  1494     FcPattern *pattern = FcPatternCreate();
       
  1495     if (!pattern)
       
  1496         return 0;
       
  1497 
       
  1498     FcValue value;
       
  1499     value.type = FcTypeString;
       
  1500 
       
  1501     QtFontDesc desc;
       
  1502     QStringList families_and_foundries = familyList(request);
       
  1503     for (int i = 0; i < families_and_foundries.size(); ++i) {
       
  1504         QString family, foundry;
       
  1505         parseFontName(families_and_foundries.at(i), foundry, family);
       
  1506         if (!family.isEmpty()) {
       
  1507             QByteArray cs = family.toUtf8();
       
  1508             value.u.s = (const FcChar8 *)cs.data();
       
  1509             FcPatternAdd(pattern, FC_FAMILY, value, FcTrue);
       
  1510         }
       
  1511         if (i == 0) {
       
  1512             QT_PREPEND_NAMESPACE(match)(script, request, family, foundry, -1, &desc);
       
  1513             if (!foundry.isEmpty()) {
       
  1514                 QByteArray cs = foundry.toUtf8();
       
  1515                 value.u.s = (const FcChar8 *)cs.data();
       
  1516                 FcPatternAddWeak(pattern, FC_FOUNDRY, value, FcTrue);
       
  1517             }
       
  1518         }
       
  1519     }
       
  1520 
       
  1521     const char *stylehint = styleHint(request);
       
  1522     if (stylehint) {
       
  1523         value.u.s = (const FcChar8 *)stylehint;
       
  1524         FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
       
  1525     }
       
  1526 
       
  1527     if (!request.ignorePitch) {
       
  1528         char pitch_value = FC_PROPORTIONAL;
       
  1529         if (request.fixedPitch || (desc.family && desc.family->fixedPitch))
       
  1530             pitch_value = FC_MONO;
       
  1531         FcPatternAddInteger(pattern, FC_SPACING, pitch_value);
       
  1532     }
       
  1533     FcPatternAddBool(pattern, FC_OUTLINE, !(request.styleStrategy & QFont::PreferBitmap));
       
  1534     if (preferScalable(request) || (desc.style && desc.style->smoothScalable))
       
  1535         FcPatternAddBool(pattern, FC_SCALABLE, true);
       
  1536 
       
  1537     qt_addPatternProps(pattern, fp->screen, script, request);
       
  1538 
       
  1539     FcDefaultSubstitute(pattern);
       
  1540     FcConfigSubstitute(0, pattern, FcMatchPattern);
       
  1541     FcConfigSubstitute(0, pattern, FcMatchFont);
       
  1542 
       
  1543     // these should only get added to the pattern _after_ substitution
       
  1544     // append the default fallback font for the specified script
       
  1545     extern QString qt_fallback_font_family(int);
       
  1546     QString fallback = qt_fallback_font_family(script);
       
  1547     if (!fallback.isEmpty()) {
       
  1548         QByteArray cs = fallback.toUtf8();
       
  1549         value.u.s = (const FcChar8 *)cs.data();
       
  1550         FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
       
  1551     }
       
  1552 
       
  1553     // add the default family
       
  1554     QString defaultFamily = QApplication::font().family();
       
  1555     QByteArray cs = defaultFamily.toUtf8();
       
  1556     value.u.s = (const FcChar8 *)cs.data();
       
  1557     FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
       
  1558 
       
  1559     // add QFont::defaultFamily() to the list, for compatibility with
       
  1560     // previous versions
       
  1561     defaultFamily = QApplication::font().defaultFamily();
       
  1562     cs = defaultFamily.toUtf8();
       
  1563     value.u.s = (const FcChar8 *)cs.data();
       
  1564     FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
       
  1565 
       
  1566     return pattern;
       
  1567 }
       
  1568 
       
  1569 
       
  1570 static void FcFontSetRemove(FcFontSet *fs, int at)
       
  1571 {
       
  1572     Q_ASSERT(at < fs->nfont);
       
  1573     FcPatternDestroy(fs->fonts[at]);
       
  1574     int len = (--fs->nfont - at) * sizeof(FcPattern *);;
       
  1575     if (len > 0)
       
  1576         memmove(fs->fonts + at, fs->fonts + at + 1, len);
       
  1577 }
       
  1578 
       
  1579 static QFontEngine *tryPatternLoad(FcPattern *p, int screen,
       
  1580                                    const QFontDef &request, int script, FcPattern **matchedPattern = 0)
       
  1581 {
       
  1582 #ifdef FONT_MATCH_DEBUG
       
  1583     FcChar8 *fam;
       
  1584     FcPatternGetString(p, FC_FAMILY, 0, &fam);
       
  1585     FM_DEBUG("==== trying %s\n", fam);
       
  1586 #endif
       
  1587     FM_DEBUG("passes charset test\n");
       
  1588     FcPattern *pattern = FcPatternDuplicate(p);
       
  1589     // add properties back in as the font selected from the
       
  1590     // list doesn't contain them.
       
  1591     qt_addPatternProps(pattern, screen, script, request);
       
  1592 
       
  1593     FcConfigSubstitute(0, pattern, FcMatchPattern);
       
  1594     FcDefaultSubstitute(pattern);
       
  1595     FcResult res;
       
  1596     FcPattern *match = FcFontMatch(0, pattern, &res);
       
  1597 
       
  1598     if (matchedPattern)
       
  1599 	*matchedPattern = 0;
       
  1600 
       
  1601     QFontEngineX11FT *engine = 0;
       
  1602     if (!match) // probably no fonts available.
       
  1603         goto done;
       
  1604 
       
  1605     if (matchedPattern)
       
  1606 	*matchedPattern = FcPatternDuplicate(match);
       
  1607 
       
  1608     if (script != QUnicodeTables::Common) {
       
  1609         // skip font if it doesn't support the language we want
       
  1610         if (specialChars[script]) {
       
  1611             // need to check the charset, as the langset doesn't work for these scripts
       
  1612             FcCharSet *cs;
       
  1613             if (FcPatternGetCharSet(match, FC_CHARSET, 0, &cs) != FcResultMatch)
       
  1614                 goto done;
       
  1615             if (!FcCharSetHasChar(cs, specialChars[script]))
       
  1616                 goto done;
       
  1617         } else {
       
  1618             FcLangSet *langSet = 0;
       
  1619             if (FcPatternGetLangSet(match, FC_LANG, 0, &langSet) != FcResultMatch)
       
  1620                 goto done;
       
  1621             if (FcLangSetHasLang(langSet, (const FcChar8*)specialLanguages[script]) != FcLangEqual)
       
  1622                 goto done;
       
  1623         }
       
  1624     }
       
  1625 
       
  1626     // enforce non-antialiasing if requested. the ft font engine looks at this property.
       
  1627     if (request.styleStrategy & QFont::NoAntialias) {
       
  1628         FcPatternDel(match, FC_ANTIALIAS);
       
  1629         FcPatternAddBool(match, FC_ANTIALIAS, false);
       
  1630     }
       
  1631 
       
  1632     engine = new QFontEngineX11FT(match, qt_FcPatternToQFontDef(match, request), screen);
       
  1633     if (engine->invalid()) {
       
  1634         FM_DEBUG("   --> invalid!\n");
       
  1635         delete engine;
       
  1636         engine = 0;
       
  1637     } else if (scriptRequiresOpenType(script)) {
       
  1638         HB_Face hbFace = engine->harfbuzzFace();
       
  1639         if (!hbFace || !hbFace->supported_scripts[script]) {
       
  1640             FM_DEBUG("  OpenType support missing for script\n");
       
  1641             delete engine;
       
  1642             engine = 0;
       
  1643         }
       
  1644     }
       
  1645 done:
       
  1646     FcPatternDestroy(pattern);
       
  1647     if (!engine && matchedPattern && *matchedPattern) {
       
  1648         FcPatternDestroy(*matchedPattern);
       
  1649         *matchedPattern = 0;
       
  1650     }
       
  1651     return engine;
       
  1652 }
       
  1653 
       
  1654 FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request)
       
  1655 {
       
  1656     FcResult result;
       
  1657     FcFontSet *fs = FcFontSort(0, pattern, FcTrue, 0, &result);
       
  1658 #ifdef FONT_MATCH_DEBUG
       
  1659     FM_DEBUG("first font in fontset:\n");
       
  1660     FcPatternPrint(fs->fonts[0]);
       
  1661 #endif
       
  1662 
       
  1663     FcBool forceScalable = request.styleStrategy & QFont::ForceOutline;
       
  1664 
       
  1665     // remove fonts if they are not scalable (and should be)
       
  1666     if (forceScalable && fs) {
       
  1667         for (int i = 0; i < fs->nfont; ++i) {
       
  1668             FcPattern *font = fs->fonts[i];
       
  1669             FcResult res;
       
  1670             FcBool scalable;
       
  1671             res = FcPatternGetBool(font, FC_SCALABLE, 0, &scalable);
       
  1672             if (res != FcResultMatch || !scalable) {
       
  1673                 FcFontSetRemove(fs, i);
       
  1674 #ifdef FONT_MATCH_DEBUG
       
  1675                 FM_DEBUG("removing pattern:");
       
  1676                 FcPatternPrint(font);
       
  1677 #endif
       
  1678                 --i; // go back one
       
  1679             }
       
  1680         }
       
  1681     }
       
  1682 
       
  1683     FM_DEBUG("final pattern contains %d fonts\n", fs->nfont);
       
  1684 
       
  1685     return fs;
       
  1686 }
       
  1687 
       
  1688 static QFontEngine *loadFc(const QFontPrivate *fp, int script, const QFontDef &request)
       
  1689 {
       
  1690     FM_DEBUG("===================== loadFc: script=%d family='%s'\n", script, request.family.toLatin1().data());
       
  1691     FcPattern *pattern = getFcPattern(fp, script, request);
       
  1692 
       
  1693 #ifdef FONT_MATCH_DEBUG
       
  1694     FM_DEBUG("\n\nfinal FcPattern contains:\n");
       
  1695     FcPatternPrint(pattern);
       
  1696 #endif
       
  1697 
       
  1698     QFontEngine *fe = 0;
       
  1699     FcPattern *matchedPattern = 0;
       
  1700     fe = tryPatternLoad(pattern, fp->screen, request, script, &matchedPattern);
       
  1701     if (!fe) {
       
  1702         FcFontSet *fs = qt_fontSetForPattern(pattern, request);
       
  1703 
       
  1704         if (fs) {
       
  1705             for (int i = 0; !fe && i < fs->nfont; ++i)
       
  1706                 fe = tryPatternLoad(fs->fonts[i], fp->screen, request, script, &matchedPattern);
       
  1707             FcFontSetDestroy(fs);
       
  1708         }
       
  1709         FM_DEBUG("engine for script %d is %s\n", script, fe ? fe->fontDef.family.toLatin1().data(): "(null)");
       
  1710     }
       
  1711     if (fe
       
  1712         && script == QUnicodeTables::Common
       
  1713         && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) {
       
  1714         fe = new QFontEngineMultiFT(fe, matchedPattern, pattern, fp->screen, request);
       
  1715     } else {
       
  1716         FcPatternDestroy(pattern);
       
  1717         if (matchedPattern)
       
  1718             FcPatternDestroy(matchedPattern);
       
  1719     }
       
  1720     return fe;
       
  1721 }
       
  1722 
       
  1723 static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count)
       
  1724 {
       
  1725 #if FC_VERSION < 20402
       
  1726     Q_UNUSED(data)
       
  1727     return FcFreeTypeQuery(file, id, blanks, count);
       
  1728 #else
       
  1729     if (data.isEmpty())
       
  1730         return FcFreeTypeQuery(file, id, blanks, count);
       
  1731 
       
  1732     extern FT_Library qt_getFreetype();
       
  1733     FT_Library lib = qt_getFreetype();
       
  1734 
       
  1735     FcPattern *pattern = 0;
       
  1736 
       
  1737     FT_Face face;
       
  1738     if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) {
       
  1739         *count = face->num_faces;
       
  1740 
       
  1741         pattern = FcFreeTypeQueryFace(face, file, id, blanks);
       
  1742 
       
  1743         FT_Done_Face(face);
       
  1744     }
       
  1745 
       
  1746     return pattern;
       
  1747 #endif
       
  1748 }
       
  1749 #endif // QT_NO_FONTCONFIG
       
  1750 
       
  1751 static QFontEngine *loadRaw(const QFontPrivate *fp, const QFontDef &request)
       
  1752 {
       
  1753     Q_ASSERT(fp && fp->rawMode);
       
  1754 
       
  1755     QByteArray xlfd = request.family.toLatin1();
       
  1756     FM_DEBUG("Loading XLFD (rawmode) '%s'", xlfd.data());
       
  1757 
       
  1758     QFontEngine *fe;
       
  1759     XFontStruct *xfs;
       
  1760     if (!(xfs = XLoadQueryFont(QX11Info::display(), xlfd.data())))
       
  1761         if (!(xfs = XLoadQueryFont(QX11Info::display(), "fixed")))
       
  1762             return 0;
       
  1763 
       
  1764     fe = new QFontEngineXLFD(xfs, xlfd, 0);
       
  1765     if (! qt_fillFontDef(xfs, &fe->fontDef, fp->dpi, 0) &&
       
  1766         ! qt_fillFontDef(xlfd, &fe->fontDef, fp->dpi, 0))
       
  1767         fe->fontDef = QFontDef();
       
  1768     return fe;
       
  1769 }
       
  1770 
       
  1771 QFontEngine *QFontDatabase::loadXlfd(int screen, int script, const QFontDef &request, int force_encoding_id)
       
  1772 {
       
  1773     QMutexLocker locker(fontDatabaseMutex());
       
  1774 
       
  1775     QtFontDesc desc;
       
  1776     FM_DEBUG() << "---> loadXlfd: request is" << request.family;
       
  1777     QStringList families_and_foundries = familyList(request);
       
  1778     const char *stylehint = styleHint(request);
       
  1779     if (stylehint)
       
  1780         families_and_foundries << QString::fromLatin1(stylehint);
       
  1781     families_and_foundries << QString();
       
  1782     FM_DEBUG() << "loadXlfd: list is" << families_and_foundries;
       
  1783     for (int i = 0; i < families_and_foundries.size(); ++i) {
       
  1784         QString family, foundry;
       
  1785         QT_PREPEND_NAMESPACE(parseFontName)(families_and_foundries.at(i), foundry, family);
       
  1786         FM_DEBUG("loadXlfd: >>>>>>>>>>>>>>trying to match '%s' encoding=%d", family.toLatin1().data(), force_encoding_id);
       
  1787         QT_PREPEND_NAMESPACE(match)(script, request, family, foundry, force_encoding_id, &desc, QList<int>(), true);
       
  1788         if (desc.family)
       
  1789             break;
       
  1790     }
       
  1791 
       
  1792     QFontEngine *fe = 0;
       
  1793     if (force_encoding_id != -1
       
  1794         || (request.styleStrategy & QFont::NoFontMerging)
       
  1795         || (desc.family && desc.family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) {
       
  1796         if (desc.family) {
       
  1797             int px = desc.size->pixelSize;
       
  1798             if (desc.style->smoothScalable && px == SMOOTH_SCALABLE)
       
  1799                 px = request.pixelSize;
       
  1800             else if (desc.style->bitmapScalable && px == 0)
       
  1801                 px = request.pixelSize;
       
  1802 
       
  1803             QByteArray xlfd("-");
       
  1804             xlfd += desc.foundry->name.isEmpty() ? QByteArray("*") : desc.foundry->name.toLatin1();
       
  1805             xlfd += '-';
       
  1806             xlfd += desc.family->name.isEmpty() ? QByteArray("*") : desc.family->name.toLatin1();
       
  1807             xlfd += '-';
       
  1808             xlfd += desc.style->weightName ? desc.style->weightName : "*";
       
  1809             xlfd += '-';
       
  1810             xlfd += (desc.style->key.style == QFont::StyleItalic
       
  1811                      ? 'i'
       
  1812                      : (desc.style->key.style == QFont::StyleOblique ? 'o' : 'r'));
       
  1813             xlfd += '-';
       
  1814             xlfd += desc.style->setwidthName ? desc.style->setwidthName : "*";
       
  1815             // ### handle add-style
       
  1816             xlfd += "-*-";
       
  1817             xlfd += QByteArray::number(px);
       
  1818             xlfd += '-';
       
  1819             xlfd += QByteArray::number(desc.encoding->xpoint);
       
  1820             xlfd += '-';
       
  1821             xlfd += QByteArray::number(desc.encoding->xres);
       
  1822             xlfd += '-';
       
  1823             xlfd += QByteArray::number(desc.encoding->yres);
       
  1824             xlfd += '-';
       
  1825             xlfd += desc.encoding->pitch;
       
  1826             xlfd += '-';
       
  1827             xlfd += QByteArray::number(desc.encoding->avgwidth);
       
  1828             xlfd += '-';
       
  1829             xlfd += xlfd_for_id(desc.encoding->encoding);
       
  1830 
       
  1831             FM_DEBUG("    using XLFD: %s\n", xlfd.data());
       
  1832 
       
  1833             const int mib = xlfd_encoding[desc.encoding->encoding].mib;
       
  1834             XFontStruct *xfs;
       
  1835             if ((xfs = XLoadQueryFont(QX11Info::display(), xlfd))) {
       
  1836                 fe = new QFontEngineXLFD(xfs, xlfd, mib);
       
  1837                 const int dpi = QX11Info::appDpiY();
       
  1838                 if (!qt_fillFontDef(xfs, &fe->fontDef, dpi, &desc)
       
  1839                     && !qt_fillFontDef(xlfd, &fe->fontDef, dpi, &desc)) {
       
  1840                     initFontDef(desc, request, &fe->fontDef);
       
  1841                 }
       
  1842             }
       
  1843         }
       
  1844         if (!fe) {
       
  1845             fe = new QFontEngineBox(request.pixelSize);
       
  1846             fe->fontDef = QFontDef();
       
  1847         }
       
  1848     } else {
       
  1849         QList<int> encodings;
       
  1850         if (desc.encoding) {
       
  1851             if (desc.encoding->encoding >= 0)
       
  1852                 encodings.append(int(desc.encoding->encoding));
       
  1853         }
       
  1854 
       
  1855         if (desc.size) {
       
  1856             // append all other encodings for the matched font
       
  1857             for (int i = 0; i < desc.size->count; ++i) {
       
  1858                 QtFontEncoding *e = desc.size->encodings + i;
       
  1859                 if (e == desc.encoding || e->encoding < 0)
       
  1860                     continue;                
       
  1861                 encodings.append(int(e->encoding));
       
  1862             }
       
  1863         }
       
  1864         // fill in the missing encodings
       
  1865         const XlfdEncoding *enc = xlfd_encoding;
       
  1866         for (; enc->name; ++enc) {
       
  1867             if (!encodings.contains(enc->id) && enc->id >= 0) {
       
  1868                 encodings.append(enc->id);
       
  1869             }
       
  1870         }
       
  1871 
       
  1872 #if defined(FONT_MATCH_DEBUG)
       
  1873         FM_DEBUG("    using MultiXLFD, encodings:");
       
  1874         for (int i = 0; i < encodings.size(); ++i) {
       
  1875             const int id = encodings.at(i);
       
  1876             FM_DEBUG("      %2d: %s", xlfd_encoding[id].id, xlfd_encoding[id].name);
       
  1877         }
       
  1878 #endif
       
  1879 
       
  1880         fe = new QFontEngineMultiXLFD(request, encodings, screen);
       
  1881     }
       
  1882     return fe;
       
  1883 }
       
  1884 
       
  1885 /*! \internal
       
  1886   Loads a QFontEngine for the specified \a script that matches the
       
  1887   QFontDef \e request member variable.
       
  1888 */
       
  1889 void QFontDatabase::load(const QFontPrivate *d, int script)
       
  1890 {
       
  1891     Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
       
  1892 
       
  1893     // normalize the request to get better caching
       
  1894     QFontDef req = d->request;
       
  1895     if (req.pixelSize <= 0)
       
  1896         req.pixelSize = qRound(qt_pixelSize(req.pointSize, d->dpi));
       
  1897     req.pointSize = 0;
       
  1898     if (req.weight == 0)
       
  1899         req.weight = QFont::Normal;
       
  1900     if (req.stretch == 0)
       
  1901         req.stretch = 100;
       
  1902 
       
  1903     QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen);
       
  1904     if (!d->engineData)
       
  1905         getEngineData(d, key);
       
  1906 
       
  1907     // the cached engineData could have already loaded the engine we want
       
  1908     if (d->engineData->engines[script])
       
  1909         return;
       
  1910 
       
  1911     // set it to the actual pointsize, so QFontInfo will do the right thing
       
  1912     req.pointSize = qt_pointSize(req.pixelSize, d->dpi);
       
  1913 
       
  1914     QFontEngine *fe = QFontCache::instance()->findEngine(key);
       
  1915 
       
  1916     if (!fe) {
       
  1917         QMutexLocker locker(fontDatabaseMutex());
       
  1918         if (!privateDb()->count)
       
  1919             initializeDb();
       
  1920 
       
  1921         const bool mainThread = (qApp->thread() == QThread::currentThread());
       
  1922         if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
       
  1923             fe = new QTestFontEngine(req.pixelSize);
       
  1924             fe->fontDef = req;
       
  1925         } else if (d->rawMode) {
       
  1926             if (mainThread)
       
  1927                 fe = loadRaw(d, req);
       
  1928 #ifndef QT_NO_FONTCONFIG
       
  1929         } else if (X11->has_fontconfig) {
       
  1930             fe = loadFc(d, script, req);
       
  1931 
       
  1932             if (fe != 0 && fe->fontDef.pixelSize != req.pixelSize) {
       
  1933                 delete fe;
       
  1934                 fe = loadXlfd(d->screen, script, req);
       
  1935             }
       
  1936 
       
  1937 
       
  1938 #endif
       
  1939         } else if (mainThread) {
       
  1940             fe = loadXlfd(d->screen, script, req);
       
  1941         }
       
  1942         if (!fe) {
       
  1943             fe = new QFontEngineBox(req.pixelSize);
       
  1944             fe->fontDef = QFontDef();
       
  1945         }
       
  1946     }
       
  1947     if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
       
  1948         for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
       
  1949             if (!d->engineData->engines[i]) {
       
  1950                 d->engineData->engines[i] = fe;
       
  1951                 fe->ref.ref();
       
  1952             }
       
  1953         }
       
  1954     } else {
       
  1955         d->engineData->engines[script] = fe;
       
  1956         fe->ref.ref();
       
  1957     }
       
  1958     QFontCache::instance()->insertEngine(key, fe);
       
  1959 }
       
  1960 
       
  1961 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
       
  1962 {
       
  1963 #if defined(QT_NO_FONTCONFIG)
       
  1964     return;
       
  1965 #else
       
  1966     if (!X11->has_fontconfig)
       
  1967         return;
       
  1968 
       
  1969     FcConfig *config = FcConfigGetCurrent();
       
  1970     if (!config)
       
  1971         return;
       
  1972 
       
  1973     FcFontSet *set = FcConfigGetFonts(config, FcSetApplication);
       
  1974     if (!set) {
       
  1975         FcConfigAppFontAddFile(config, (const FcChar8 *)":/non-existant");
       
  1976         set = FcConfigGetFonts(config, FcSetApplication); // try again
       
  1977         if (!set)
       
  1978             return;
       
  1979     }
       
  1980 
       
  1981     QString fileNameForQuery = fnt->fileName;
       
  1982 #if FC_VERSION < 20402
       
  1983     QTemporaryFile tmp;
       
  1984 
       
  1985     if (!fnt->data.isEmpty()) {
       
  1986         if (!tmp.open())
       
  1987             return;
       
  1988         tmp.write(fnt->data);
       
  1989         tmp.flush();
       
  1990         fileNameForQuery = tmp.fileName();
       
  1991     }
       
  1992 #endif
       
  1993 
       
  1994     int id = 0;
       
  1995     FcBlanks *blanks = FcConfigGetBlanks(0);
       
  1996     int count = 0;
       
  1997 
       
  1998     QStringList families;
       
  1999 
       
  2000     FcPattern *pattern = 0;
       
  2001     do {
       
  2002         pattern = queryFont((const FcChar8 *)QFile::encodeName(fileNameForQuery).constData(),
       
  2003                             fnt->data, id, blanks, &count);
       
  2004         if (!pattern)
       
  2005             return;
       
  2006 
       
  2007         FcPatternDel(pattern, FC_FILE);
       
  2008         FcPatternAddString(pattern, FC_FILE, (const FcChar8 *)fnt->fileName.toUtf8().constData());
       
  2009 
       
  2010         FcChar8 *fam = 0;
       
  2011         if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
       
  2012             QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam));
       
  2013             families << family;
       
  2014         }
       
  2015 
       
  2016         if (!FcFontSetAdd(set, pattern))
       
  2017             return;
       
  2018 
       
  2019         ++id;
       
  2020     } while (pattern && id < count);
       
  2021 
       
  2022     fnt->families = families;
       
  2023 #endif
       
  2024 }
       
  2025 
       
  2026 bool QFontDatabase::removeApplicationFont(int handle)
       
  2027 {
       
  2028 #if defined(QT_NO_FONTCONFIG)
       
  2029     return false;
       
  2030 #else
       
  2031     QMutexLocker locker(fontDatabaseMutex());
       
  2032 
       
  2033     QFontDatabasePrivate *db = privateDb();
       
  2034     if (handle < 0 || handle >= db->applicationFonts.count())
       
  2035         return false;
       
  2036 
       
  2037     FcConfigAppFontClear(0);
       
  2038 
       
  2039     db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
       
  2040 
       
  2041     db->reregisterAppFonts = true;
       
  2042     db->invalidate();
       
  2043     return true;
       
  2044 #endif
       
  2045 }
       
  2046 
       
  2047 bool QFontDatabase::removeAllApplicationFonts()
       
  2048 {
       
  2049 #if defined(QT_NO_FONTCONFIG)
       
  2050     return false;
       
  2051 #else
       
  2052     QMutexLocker locker(fontDatabaseMutex());
       
  2053 
       
  2054     QFontDatabasePrivate *db = privateDb();
       
  2055     if (db->applicationFonts.isEmpty())
       
  2056         return false;
       
  2057 
       
  2058     FcConfigAppFontClear(0);
       
  2059     db->applicationFonts.clear();
       
  2060     db->invalidate();
       
  2061     return true;
       
  2062 #endif
       
  2063 }
       
  2064 
       
  2065 bool QFontDatabase::supportsThreadedFontRendering()
       
  2066 {
       
  2067 #if defined(QT_NO_FONTCONFIG)
       
  2068     return false;
       
  2069 #else
       
  2070     return X11->has_fontconfig;
       
  2071 #endif
       
  2072 }
       
  2073 
       
  2074 QT_END_NAMESPACE