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