~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/text/qfontdatabase_x11.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the text module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include <qplatformdefs.h>
 
30
 
 
31
#include <qdatetime.h>
 
32
#include <qpaintdevice.h>
 
33
 
 
34
#include <private/qt_x11_p.h>
 
35
#include "qx11info_x11.h"
 
36
 
 
37
#include <ctype.h>
 
38
#include <stdlib.h>
 
39
 
 
40
#include <sys/types.h>
 
41
#include <sys/stat.h>
 
42
#include <fcntl.h>
 
43
#include <sys/mman.h>
 
44
 
 
45
#ifndef QT_NO_FONTCONFIG
 
46
#include <ft2build.h>
 
47
#include FT_FREETYPE_H
 
48
#endif
 
49
 
 
50
// from qfont_x11.cpp
 
51
extern double qt_pointSize(double pixelSize, int dpi);
 
52
extern double qt_pixelSize(double pointSize, int dpi);
 
53
 
 
54
static inline void capitalize (char *s)
 
55
{
 
56
    bool space = true;
 
57
    while(*s) {
 
58
        if (space)
 
59
            *s = toupper(*s);
 
60
        space = (*s == ' ');
 
61
        ++s;
 
62
    }
 
63
}
 
64
 
 
65
 
 
66
/*
 
67
  To regenerate the writingSystems_for_xlfd_encoding table, run
 
68
  'util/unicode/x11/makeencodings' and paste the generated
 
69
  'encodings.c' here.
 
70
*/
 
71
// ----- begin of generated code -----
 
72
 
 
73
#define make_tag( c1, c2, c3, c4 )                         \
 
74
    ((((unsigned int)c1)<<24) | (((unsigned int)c2)<<16) | \
 
75
    (((unsigned int)c3)<<8) | ((unsigned int)c4))
 
76
 
 
77
struct XlfdEncoding {
 
78
    const char *name;
 
79
    int id;
 
80
    int mib;
 
81
    unsigned int hash1;
 
82
    unsigned int hash2;
 
83
};
 
84
 
 
85
static const XlfdEncoding xlfd_encoding[] = {
 
86
    { "iso8859-1", 0, 4, make_tag('i','s','o','8'), make_tag('5','9','-','1') },
 
87
    { "iso8859-2", 1, 5, make_tag('i','s','o','8'), make_tag('5','9','-','2') },
 
88
    { "iso8859-3", 2, 6, make_tag('i','s','o','8'), make_tag('5','9','-','3') },
 
89
    { "iso8859-4", 3, 7, make_tag('i','s','o','8'), make_tag('5','9','-','4') },
 
90
    { "iso8859-9", 4, 12, make_tag('i','s','o','8'), make_tag('5','9','-','9') },
 
91
    { "iso8859-10", 5, 13, make_tag('i','s','o','8'), make_tag('9','-','1','0') },
 
92
    { "iso8859-13", 6, 109, make_tag('i','s','o','8'), make_tag('9','-','1','3') },
 
93
    { "iso8859-14", 7, 110, make_tag('i','s','o','8'), make_tag('9','-','1','4') },
 
94
    { "iso8859-15", 8, 111, make_tag('i','s','o','8'), make_tag('9','-','1','5') },
 
95
    { "hp-roman8", 9, 2004, make_tag('h','p','-','r'), make_tag('m','a','n','8') },
 
96
    { "iso8859-5", 10, 8, make_tag('i','s','o','8'), make_tag('5','9','-','5') },
 
97
    { "*-cp1251", 11, 2251, 0, make_tag('1','2','5','1') },
 
98
    { "koi8-ru", 12, 2084, make_tag('k','o','i','8'), make_tag('8','-','r','u') },
 
99
    { "koi8-u", 13, 2088, make_tag('k','o','i','8'), make_tag('i','8','-','u') },
 
100
    { "koi8-r", 14, 2084, make_tag('k','o','i','8'), make_tag('i','8','-','r') },
 
101
    { "iso8859-7", 15, 10, make_tag('i','s','o','8'), make_tag('5','9','-','7') },
 
102
    { "iso8859-8", 16, 85, make_tag('i','s','o','8'), make_tag('5','9','-','8') },
 
103
    { "gb18030-0", 17, -114, make_tag('g','b','1','8'), make_tag('3','0','-','0') },
 
104
    { "gb18030.2000-0", 18, -113, make_tag('g','b','1','8'), make_tag('0','0','-','0') },
 
105
    { "gbk-0", 19, -113, make_tag('g','b','k','-'), make_tag('b','k','-','0') },
 
106
    { "gb2312.*-0", 20, 57, make_tag('g','b','2','3'), 0 },
 
107
    { "jisx0201*-0", 21, 15, make_tag('j','i','s','x'), 0 },
 
108
    { "jisx0208*-0", 22, 63, make_tag('j','i','s','x'), 0 },
 
109
    { "ksc5601*-*", 23, 36, make_tag('k','s','c','5'), 0 },
 
110
    { "big5hkscs-0", 24, -2101, make_tag('b','i','g','5'), make_tag('c','s','-','0') },
 
111
    { "hkscs-1", 25, -2101, make_tag('h','k','s','c'), make_tag('c','s','-','1') },
 
112
    { "big5*-*", 26, -2026, make_tag('b','i','g','5'), 0 },
 
113
    { "tscii-*", 27, 2028, make_tag('t','s','c','i'), 0 },
 
114
    { "tis620*-*", 28, 2259, make_tag('t','i','s','6'), 0 },
 
115
    { "iso8859-11", 29, 2259, make_tag('i','s','o','8'), make_tag('9','-','1','1') },
 
116
    { "mulelao-1", 30, -4242, make_tag('m','u','l','e'), make_tag('a','o','-','1') },
 
117
    { "ethiopic-unicode", 31, 0, make_tag('e','t','h','i'), make_tag('c','o','d','e') },
 
118
    { "iso10646-1", 32, 0, make_tag('i','s','o','1'), make_tag('4','6','-','1') },
 
119
    { "unicode-*", 33, 0, make_tag('u','n','i','c'), 0 },
 
120
    { "*-symbol", 34, 0, 0, make_tag('m','b','o','l') },
 
121
    { "*-fontspecific", 35, 0, 0, make_tag('i','f','i','c') },
 
122
    { "fontspecific-*", 36, 0, make_tag('f','o','n','t'), 0 },
 
123
    { 0, 0, 0, 0, 0 }
 
124
};
 
125
 
 
126
static const char writingSystems_for_xlfd_encoding[37][39] = {
 
127
    // iso8859-1
 
128
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
129
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
130
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
131
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
132
    // iso8859-2
 
133
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
134
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
135
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
136
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
137
    // iso8859-3
 
138
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
139
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
140
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
141
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
142
    // iso8859-4
 
143
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
144
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
145
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
146
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
147
    // iso8859-9
 
148
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
149
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
150
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
151
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
152
    // iso8859-10
 
153
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
154
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
155
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
156
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
157
    // iso8859-13
 
158
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
159
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
160
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
161
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
162
    // iso8859-14
 
163
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
164
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
165
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
166
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
167
    // iso8859-15
 
168
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
169
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
170
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
171
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
172
    // hp-roman8
 
173
    { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 
174
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
175
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
176
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
177
    // iso8859-5
 
178
    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
 
179
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
180
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
181
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
182
    // *-cp1251
 
183
    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
 
184
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
185
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
186
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
187
    // koi8-ru
 
188
    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
 
189
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
190
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
191
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
192
    // koi8-u
 
193
    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
 
194
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
195
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
196
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
197
    // koi8-r
 
198
    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
 
199
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
200
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
201
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
202
    // iso8859-7
 
203
    { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
 
204
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
205
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
206
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
207
    // iso8859-8
 
208
    { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
 
209
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
210
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
211
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
212
    // gb18030-0
 
213
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
214
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
215
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
 
216
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
217
    // gb18030.2000-0
 
218
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
219
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
220
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
 
221
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
222
    // gbk-0
 
223
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
224
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
225
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
 
226
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
227
    // gb2312.*-0
 
228
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
229
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
230
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
 
231
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
232
    // jisx0201*-0
 
233
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
234
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
235
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
 
236
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
237
    // jisx0208*-0
 
238
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
239
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
240
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
 
241
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
242
    // ksc5601*-*
 
243
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
244
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
245
      0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
 
246
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
247
    // big5hkscs-0
 
248
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
249
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
250
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
 
251
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
252
    // hkscs-1
 
253
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
254
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
255
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
 
256
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
257
    // big5*-*
 
258
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
259
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
260
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
 
261
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
262
    // tscii-*
 
263
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
264
      0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
 
265
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
266
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
267
    // tis620*-*
 
268
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
269
      0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
 
270
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
271
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
272
    // iso8859-11
 
273
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
274
      0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
 
275
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
276
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
277
    // mulelao-1
 
278
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
279
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
280
      1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
281
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
282
    // ethiopic-unicode
 
283
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
284
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
285
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
286
      0, 0, 0, 0, 0, 0, 0, 0, 1 },
 
287
    // iso10646-1
 
288
    { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
 
289
      0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
 
290
      1, 1, 0, 1, 0, 1, 1, 0, 0, 0,
 
291
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
292
    // unicode-*
 
293
    { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
 
294
      0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
 
295
      1, 1, 0, 1, 0, 1, 1, 0, 0, 0,
 
296
      0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
297
    // *-symbol
 
298
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
299
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
300
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
301
      0, 0, 0, 0, 0, 0, 0, 0, 1 },
 
302
    // *-fontspecific
 
303
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
304
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
305
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
306
      0, 0, 0, 0, 0, 0, 0, 0, 1 },
 
307
    // fontspecific-*
 
308
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
309
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
310
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
311
      0, 0, 0, 0, 0, 0, 0, 0, 1 }
 
312
 
 
313
};
 
314
 
 
315
// ----- end of generated code -----
 
316
 
 
317
 
 
318
const int numEncodings = sizeof(xlfd_encoding) / sizeof(XlfdEncoding) - 1;
 
319
 
 
320
int qt_xlfd_encoding_id(const char *encoding)
 
321
{
 
322
    // qDebug("looking for encoding id for '%s'", encoding);
 
323
    int len = strlen(encoding);
 
324
    if (len < 4)
 
325
        return -1;
 
326
    unsigned int hash1 = make_tag(encoding[0], encoding[1], encoding[2], encoding[3]);
 
327
    const char *ch = encoding + len - 4;
 
328
    unsigned int hash2 = make_tag(ch[0], ch[1], ch[2], ch[3]);
 
329
 
 
330
    const XlfdEncoding *enc = xlfd_encoding;
 
331
    for (; enc->name; ++enc) {
 
332
        if ((enc->hash1 && enc->hash1 != hash1) ||
 
333
             (enc->hash2 && enc->hash2 != hash2))
 
334
            continue;
 
335
        // hashes match, do a compare if strings match
 
336
        // the enc->name can contain '*'s we have to interpret correctly
 
337
        const char *n = enc->name;
 
338
        const char *e = encoding;
 
339
        while (1) {
 
340
            // qDebug("bol: *e='%c', *n='%c'", *e, *n);
 
341
            if (*e == '\0') {
 
342
                if (*n)
 
343
                    break;
 
344
                // qDebug("found encoding id %d", enc->id);
 
345
                return enc->id;
 
346
            }
 
347
            if (*e == *n) {
 
348
                ++e;
 
349
                ++n;
 
350
                continue;
 
351
            }
 
352
            if (*n != '*')
 
353
                break;
 
354
            ++n;
 
355
            // qDebug("skip: *e='%c', *n='%c'", *e, *n);
 
356
            while (*e && *e != *n)
 
357
                ++e;
 
358
        }
 
359
    }
 
360
    // qDebug("couldn't find encoding %s", encoding);
 
361
    return -1;
 
362
}
 
363
 
 
364
int qt_mib_for_xlfd_encoding(const char *encoding)
 
365
{
 
366
    int id = qt_xlfd_encoding_id(encoding);
 
367
    if (id != -1) return xlfd_encoding[id].mib;
 
368
    return 0;
 
369
};
 
370
 
 
371
int qt_encoding_id_for_mib(int mib)
 
372
{
 
373
    const XlfdEncoding *enc = xlfd_encoding;
 
374
    for (; enc->name; ++enc) {
 
375
        if (enc->mib == mib)
 
376
            return enc->id;
 
377
    }
 
378
    return -1;
 
379
}
 
380
 
 
381
static const char * xlfd_for_id(int id)
 
382
{
 
383
    // special case: -1 returns the "*-*" encoding, allowing us to do full
 
384
    // database population in a single X server round trip.
 
385
    if (id < 0 || id > numEncodings)
 
386
        return "*-*";
 
387
    return xlfd_encoding[id].name;
 
388
}
 
389
 
 
390
enum XLFDFieldNames {
 
391
    Foundry,
 
392
    Family,
 
393
    Weight,
 
394
    Slant,
 
395
    Width,
 
396
    AddStyle,
 
397
    PixelSize,
 
398
    PointSize,
 
399
    ResolutionX,
 
400
    ResolutionY,
 
401
    Spacing,
 
402
    AverageWidth,
 
403
    CharsetRegistry,
 
404
    CharsetEncoding,
 
405
    NFontFields
 
406
};
 
407
 
 
408
// Splits an X font name into fields separated by '-'
 
409
static bool parseXFontName(char *fontName, char **tokens)
 
410
{
 
411
    if (! fontName || fontName[0] == '0' || fontName[0] != '-') {
 
412
        tokens[0] = 0;
 
413
        return false;
 
414
    }
 
415
 
 
416
    int          i;
 
417
    ++fontName;
 
418
    for (i = 0; i < NFontFields && fontName && fontName[0]; ++i) {
 
419
        tokens[i] = fontName;
 
420
        for (;; ++fontName) {
 
421
            if (*fontName == '-')
 
422
                break;
 
423
            if (! *fontName) {
 
424
                fontName = 0;
 
425
                break;
 
426
            }
 
427
        }
 
428
 
 
429
        if (fontName) *fontName++ = '\0';
 
430
    }
 
431
 
 
432
    if (i < NFontFields) {
 
433
        for (int j = i ; j < NFontFields; ++j)
 
434
            tokens[j] = 0;
 
435
        return false;
 
436
    }
 
437
 
 
438
    return true;
 
439
}
 
440
 
 
441
static inline bool isZero(char *x)
 
442
{
 
443
    return (x[0] == '0' && x[1] == 0);
 
444
}
 
445
 
 
446
static inline bool isScalable(char **tokens)
 
447
{
 
448
    return (isZero(tokens[PixelSize]) &&
 
449
            isZero(tokens[PointSize]) &&
 
450
            isZero(tokens[AverageWidth]));
 
451
}
 
452
 
 
453
static inline bool isSmoothlyScalable(char **tokens)
 
454
{
 
455
    return (isZero(tokens[ResolutionX]) &&
 
456
            isZero(tokens[ResolutionY]));
 
457
}
 
458
 
 
459
static inline bool isFixedPitch(char **tokens)
 
460
{
 
461
    return (tokens[Spacing][0] == 'm' ||
 
462
            tokens[Spacing][0] == 'c' ||
 
463
            tokens[Spacing][0] == 'M' ||
 
464
            tokens[Spacing][0] == 'C');
 
465
}
 
466
 
 
467
/*
 
468
  Fills in a font definition (QFontDef) from an XLFD (X Logical Font
 
469
  Description).
 
470
 
 
471
  Returns true if the the given xlfd is valid.
 
472
*/
 
473
bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi)
 
474
{
 
475
    char *tokens[NFontFields];
 
476
    QByteArray buffer = xlfd;
 
477
    if (! parseXFontName(buffer.data(), tokens))
 
478
        return false;
 
479
 
 
480
    capitalize(tokens[Family]);
 
481
    capitalize(tokens[Foundry]);
 
482
 
 
483
    fd->family = QString::fromLatin1(tokens[Family]);
 
484
    QString foundry = QString::fromLatin1(tokens[Foundry]);
 
485
    if (! foundry.isEmpty() && foundry != QString::fromLatin1("*"))
 
486
        fd->family +=
 
487
            QString::fromLatin1(" [") + foundry + QString::fromLatin1("]");
 
488
 
 
489
    if (qstrlen(tokens[AddStyle]) > 0)
 
490
        fd->addStyle = QString::fromLatin1(tokens[AddStyle]);
 
491
    else
 
492
        fd->addStyle.clear();
 
493
 
 
494
    fd->pointSize = atoi(tokens[PointSize]);
 
495
    fd->styleHint = QFont::AnyStyle;        // ### any until we match families
 
496
 
 
497
    char slant = tolower((uchar) tokens[Slant][0]);
 
498
    fd->style = (slant == 'o' ? QFont::StyleOblique : (slant == 'i' ? QFont::StyleItalic : QFont::StyleNormal));
 
499
    char fixed = tolower((uchar) tokens[Spacing][0]);
 
500
    fd->fixedPitch = (fixed == 'm' || fixed == 'c');
 
501
    fd->weight = getFontWeight(tokens[Weight]);
 
502
 
 
503
    int r = atoi(tokens[ResolutionY]);
 
504
    fd->pixelSize = atoi(tokens[PixelSize]);
 
505
    // not "0" or "*", or required DPI
 
506
    if (r && fd->pixelSize && r != dpi) {
 
507
        // calculate actual pointsize for display DPI
 
508
        fd->pointSize = qt_pointSize(fd->pixelSize, dpi);
 
509
    } else if (fd->pixelSize == 0 && fd->pointSize) {
 
510
        // calculate pixel size from pointsize/dpi
 
511
        fd->pixelSize = qRound(qt_pixelSize(fd->pointSize, dpi));
 
512
    }
 
513
 
 
514
    return true;
 
515
}
 
516
 
 
517
/*
 
518
  Fills in a font definition (QFontDef) from the font properties in an
 
519
  XFontStruct.
 
520
 
 
521
  Returns true if the QFontDef could be filled with properties from
 
522
  the XFontStruct.
 
523
*/
 
524
static bool qt_fillFontDef(XFontStruct *fs, QFontDef *fd, int dpi)
 
525
{
 
526
    unsigned long value;
 
527
    if (fs && !XGetFontProperty(fs, XA_FONT, &value))
 
528
        return false;
 
529
 
 
530
    char *n = XGetAtomName(QX11Info::display(), value);
 
531
    QByteArray xlfd(n);
 
532
    if (n)
 
533
        XFree(n);
 
534
    return qt_fillFontDef(xlfd.toLower(), fd, dpi);
 
535
}
 
536
 
 
537
 
 
538
static QtFontStyle::Key getStyle(char ** tokens)
 
539
{
 
540
    QtFontStyle::Key key;
 
541
 
 
542
    char slant0 = tolower((uchar) tokens[Slant][0]);
 
543
 
 
544
    if (slant0 == 'r') {
 
545
        if (tokens[Slant][1]) {
 
546
            char slant1 = tolower((uchar) tokens[Slant][1]);
 
547
 
 
548
            if (slant1 == 'o')
 
549
                key.style = QFont::StyleOblique;
 
550
            else if (slant1 == 'i')
 
551
                key.style = QFont::StyleItalic;
 
552
        }
 
553
    } else if (slant0 == 'o')
 
554
        key.style = QFont::StyleOblique;
 
555
    else if (slant0 == 'i')
 
556
        key.style = QFont::StyleItalic;
 
557
 
 
558
    key.weight = getFontWeight(tokens[Weight]);
 
559
 
 
560
    if (qstrcmp(tokens[Width], "normal") == 0) {
 
561
        key.stretch = 100;
 
562
    } else if (qstrcmp(tokens[Width], "semi condensed") == 0 ||
 
563
                qstrcmp(tokens[Width], "semicondensed") == 0) {
 
564
        key.stretch = 90;
 
565
    } else if (qstrcmp(tokens[Width], "condensed") == 0) {
 
566
        key.stretch = 80;
 
567
    } else if (qstrcmp(tokens[Width], "narrow") == 0) {
 
568
        key.stretch = 60;
 
569
    }
 
570
 
 
571
    return key;
 
572
}
 
573
 
 
574
 
 
575
static bool xlfdsFullyLoaded = false;
 
576
static unsigned char encodingLoaded[numEncodings];
 
577
 
 
578
static void loadXlfds(const char *reqFamily, int encoding_id)
 
579
{
 
580
    QFontDatabasePrivate *db = privateDb();
 
581
    QtFontFamily *fontFamily = reqFamily ? db->family(reqFamily) : 0;
 
582
 
 
583
    // make sure we don't load twice
 
584
    if ((encoding_id == -1 && xlfdsFullyLoaded)
 
585
        || (encoding_id != -1 && encodingLoaded[encoding_id]))
 
586
        return;
 
587
    if (fontFamily && fontFamily->xlfdLoaded)
 
588
        return;
 
589
 
 
590
    int fontCount;
 
591
    // force the X server to give us XLFDs
 
592
    QByteArray xlfd_pattern("-*-");
 
593
    xlfd_pattern += reqFamily ? reqFamily : "*";
 
594
    xlfd_pattern += "-*-*-*-*-*-*-*-*-*-*-";
 
595
    xlfd_pattern += xlfd_for_id(encoding_id);
 
596
 
 
597
    char **fontList = XListFonts(QX11Info::display(),
 
598
                                 xlfd_pattern,
 
599
                                 0xffff, &fontCount);
 
600
    // qDebug("requesting xlfd='%s', got %d fonts", xlfd_pattern.data(), fontCount);
 
601
 
 
602
 
 
603
    char *tokens[NFontFields];
 
604
 
 
605
    for(int i = 0 ; i < fontCount ; i++) {
 
606
        if (! parseXFontName(fontList[i], tokens))
 
607
            continue;
 
608
 
 
609
        // get the encoding_id for this xlfd.  we need to do this
 
610
        // here, since we can pass -1 to this function to do full
 
611
        // database population
 
612
        *(tokens[CharsetEncoding] - 1) = '-';
 
613
        int encoding_id = qt_xlfd_encoding_id(tokens[CharsetRegistry]);
 
614
        if (encoding_id == -1)
 
615
            continue;
 
616
 
 
617
        char *familyName = tokens[Family];
 
618
        capitalize(familyName);
 
619
        char *foundryName = tokens[Foundry];
 
620
        capitalize(foundryName);
 
621
        QtFontStyle::Key styleKey = getStyle(tokens);
 
622
 
 
623
        bool smooth_scalable = false;
 
624
        bool bitmap_scalable = false;
 
625
        if (isScalable(tokens)) {
 
626
            if (isSmoothlyScalable(tokens))
 
627
                smooth_scalable = true;
 
628
            else
 
629
                bitmap_scalable = true;
 
630
        }
 
631
        uint pixelSize = atoi(tokens[PixelSize]);
 
632
        uint xpointSize = atoi(tokens[PointSize]);
 
633
        uint xres = atoi(tokens[ResolutionX]);
 
634
        uint yres = atoi(tokens[ResolutionY]);
 
635
        uint avgwidth = atoi(tokens[AverageWidth]);
 
636
        bool fixedPitch = isFixedPitch(tokens);
 
637
 
 
638
        if (avgwidth == 0 && pixelSize != 0) {
 
639
            /*
 
640
              Ignore bitmap scalable fonts that are automatically
 
641
              generated by some X servers.  We know they are bitmap
 
642
              scalable because even though they have a specified pixel
 
643
              size, the average width is zero.
 
644
            */
 
645
            continue;
 
646
        }
 
647
 
 
648
        QtFontFamily *family = fontFamily ? fontFamily : db->family(familyName, true);
 
649
        family->fontFileIndex = -1;
 
650
        QtFontFoundry *foundry = family->foundry(foundryName, true);
 
651
        QtFontStyle *style = foundry->style(styleKey, true);
 
652
 
 
653
        delete [] style->weightName;
 
654
        style->weightName = qstrdup(tokens[Weight]);
 
655
        delete [] style->setwidthName;
 
656
        style->setwidthName = qstrdup(tokens[Width]);
 
657
 
 
658
        if (smooth_scalable) {
 
659
            style->smoothScalable = true;
 
660
            style->bitmapScalable = false;
 
661
            pixelSize = SMOOTH_SCALABLE;
 
662
        }
 
663
        if (!style->smoothScalable && bitmap_scalable)
 
664
            style->bitmapScalable = true;
 
665
        if (!fixedPitch)
 
666
            family->fixedPitch = false;
 
667
 
 
668
        QtFontSize *size = style->pixelSize(pixelSize, true);
 
669
        QtFontEncoding *enc =
 
670
            size->encodingID(encoding_id, xpointSize, xres, yres, avgwidth, true);
 
671
        enc->pitch = *tokens[Spacing];
 
672
        if (!enc->pitch) enc->pitch = '*';
 
673
 
 
674
        for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
 
675
            if (writingSystems_for_xlfd_encoding[encoding_id][i])
 
676
                family->writingSystems[i] = QtFontFamily::Supported;
 
677
            else
 
678
                family->writingSystems[i] |= QtFontFamily::UnsupportedXLFD;
 
679
        }
 
680
        if (encoding_id == -1)
 
681
            family->xlfdLoaded = true;
 
682
    }
 
683
    if (!reqFamily) {
 
684
        // mark encoding as loaded
 
685
        if (encoding_id == -1)
 
686
            xlfdsFullyLoaded = true;
 
687
        else
 
688
            encodingLoaded[encoding_id] = true;
 
689
    }
 
690
 
 
691
    XFreeFontNames(fontList);
 
692
}
 
693
 
 
694
 
 
695
#ifndef QT_NO_FONTCONFIG
 
696
static int getFCWeight(int fc_weight)
 
697
{
 
698
    int qtweight = QFont::Black;
 
699
    if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
 
700
        qtweight = QFont::Light;
 
701
    else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
 
702
        qtweight = QFont::Normal;
 
703
    else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
 
704
        qtweight = QFont::DemiBold;
 
705
    else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
 
706
        qtweight = QFont::Bold;
 
707
 
 
708
    return qtweight;
 
709
}
 
710
 
 
711
QFontDef FcPatternToQFontDef(FcPattern *pattern)
 
712
{
 
713
    QFontDef fontDef;
 
714
 
 
715
    FcChar8 *value = 0;
 
716
    if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) == FcResultMatch) {
 
717
        fontDef.family = QString::fromUtf8(reinterpret_cast<const char *>(value));
 
718
        fontDef.family.replace('-', ' ');
 
719
        fontDef.family.replace("/", "");
 
720
    }
 
721
 
 
722
    double dpi;
 
723
    if (FcPatternGetDouble(pattern, FC_DPI, 0, &dpi) != FcResultMatch)
 
724
        dpi = QX11Info::appDpiY();
 
725
 
 
726
    double size;
 
727
    if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
 
728
        fontDef.pixelSize = qRound(size);
 
729
    else
 
730
        fontDef.pixelSize = 12;
 
731
 
 
732
    fontDef.pointSize = qt_pointSize(fontDef.pixelSize, qRound(dpi));
 
733
 
 
734
    /* ###
 
735
       fontDef.styleStrategy
 
736
       fontDef.styleHint
 
737
    */
 
738
 
 
739
    int weight;
 
740
    if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) != FcResultMatch)
 
741
        weight = FC_WEIGHT_MEDIUM;
 
742
    fontDef.weight = getFCWeight(weight);
 
743
 
 
744
    int slant;
 
745
    if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant) != FcResultMatch)
 
746
        slant = FC_SLANT_ROMAN;
 
747
    fontDef.style = (slant == FC_SLANT_ITALIC)
 
748
                    ? QFont::StyleItalic
 
749
                    : ((slant == FC_SLANT_OBLIQUE)
 
750
                       ? QFont::StyleOblique
 
751
                       : QFont::StyleNormal);
 
752
 
 
753
    FcBool scalable;
 
754
    if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
 
755
        scalable = false;
 
756
    if (scalable) {
 
757
        FcMatrix identity;
 
758
        FcMatrix *matrix;
 
759
        if (FcPatternGetMatrix(pattern, FC_MATRIX, 0, &matrix) != FcResultMatch) {
 
760
            FcMatrixInit(&identity);
 
761
            matrix = &identity;
 
762
        }
 
763
        if (matrix->yx == 0.0 && matrix->yy == 1.0) {
 
764
            // get the stretch
 
765
            fontDef.stretch = qRound(matrix->xx * 100.0);
 
766
            // shear?
 
767
            if (matrix->xy != 0.0) {
 
768
                // yup... we're using our "fake oblique" trick
 
769
                fontDef.style = QFont::StyleOblique;
 
770
            }
 
771
        } else {
 
772
            // ###
 
773
            fontDef.stretch = 100;
 
774
        }
 
775
    } else {
 
776
#if FC_VERSION >= 20193
 
777
        int width;
 
778
        if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width) == FcResultMatch)
 
779
            fontDef.stretch = width;
 
780
        else
 
781
#endif
 
782
            fontDef.stretch = 100;
 
783
    }
 
784
 
 
785
    int spacing;
 
786
    if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch) {
 
787
        fontDef.fixedPitch = (spacing >= FC_MONO);
 
788
        fontDef.ignorePitch = false;
 
789
    } else {
 
790
        fontDef.ignorePitch = true;
 
791
    }
 
792
 
 
793
    return fontDef;
 
794
}
 
795
 
 
796
static const char *specialLanguages[] = {
 
797
    "en",
 
798
    "he",
 
799
    "ar",
 
800
    "syr",
 
801
    "div",
 
802
    "hi",
 
803
    "bn",
 
804
    "pa",
 
805
    "gu",
 
806
    "or",
 
807
    "ta",
 
808
    "te",
 
809
    "kn",
 
810
    "ml",
 
811
    "si",
 
812
    "th",
 
813
    "lo",
 
814
    "bo",
 
815
    "my",
 
816
    "ko",
 
817
    "km"
 
818
};
 
819
enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) };
 
820
 
 
821
// this could become a list of all languages used for each writing
 
822
// system, instead of using the single most common language.
 
823
static const char *languageForWritingSystem[] = {
 
824
    0,     // Any
 
825
    "en",  // Latin
 
826
    "el",  // Greek
 
827
    "ru",  // Cyrillic
 
828
    "hy",  // Armenian
 
829
    "he",  // Hebrew
 
830
    "ar",  // Arabic
 
831
    "syr", // Syriac
 
832
    "div", // Thaana
 
833
    "hi",  // Devanagari
 
834
    "bn",  // Bengali
 
835
    "pa",  // Gurmukhi
 
836
    "gu",  // Gujarati
 
837
    "or",  // Oriya
 
838
    "ta",  // Tamil
 
839
    "te",  // Telugu
 
840
    "kn",  // Kannada
 
841
    "ml",  // Malayalam
 
842
    "si",  // Sinhala
 
843
    "th",  // Thai
 
844
    "lo",  // Lao
 
845
    "bo",  // Tibetan
 
846
    "my",  // Myanmar
 
847
    "ka",  // Georgian
 
848
    "km",  // Khmer
 
849
    "zh-cn", // SimplifiedChinese
 
850
    "zh-tw", // TraditionalChinese
 
851
    "ja",  // Japanese
 
852
    "ko",  // Korean
 
853
    "vi",  // Vietnamese
 
854
};
 
855
enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) };
 
856
 
 
857
static void loadFontConfig()
 
858
{
 
859
    if (!X11->has_fontconfig)
 
860
        return;
 
861
 
 
862
    Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialLanguageCount,
 
863
               "QFontDatabase", "New scripts have been added.");
 
864
    Q_ASSERT_X((QFontDatabase::WritingSystemsCount - 1) == LanguageCount,
 
865
               "QFontDatabase", "New writing systems have been added.");
 
866
 
 
867
    QFontDatabasePrivate *db = privateDb();
 
868
    FcFontSet  *fonts;
 
869
 
 
870
    QString familyName;
 
871
    QString rawName;
 
872
    FcChar8 *value = 0;
 
873
    int weight_value;
 
874
    int slant_value;
 
875
    int spacing_value;
 
876
    FcChar8 *file_value;
 
877
    int index_value;
 
878
    FcChar8 *foundry_value;
 
879
    FcBool scalable;
 
880
 
 
881
    {
 
882
        FcObjectSet *os = FcObjectSetCreate();
 
883
        FcPattern *pattern = FcPatternCreate();
 
884
        const char *properties [] = {
 
885
            FC_FAMILY, FC_WEIGHT, FC_SLANT,
 
886
            FC_SPACING, FC_FILE, FC_INDEX,
 
887
            FC_LANG, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT,
 
888
#if FC_VERSION >= 20193
 
889
            FC_WIDTH,
 
890
#endif
 
891
            (const char *)0
 
892
        };
 
893
        const char **p = properties;
 
894
        while (*p) {
 
895
            FcObjectSetAdd(os, *p);
 
896
            ++p;
 
897
        }
 
898
        fonts = FcFontList(0, pattern, os);
 
899
        FcObjectSetDestroy(os);
 
900
        FcPatternDestroy(pattern);
 
901
    }
 
902
 
 
903
    for (int i = 0; i < fonts->nfont; i++) {
 
904
        if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
 
905
            continue;
 
906
        //         capitalize(value);
 
907
        rawName = familyName = QString::fromUtf8((const char *)value);
 
908
        familyName.replace('-', ' ');
 
909
        familyName.replace("/", "");
 
910
        slant_value = FC_SLANT_ROMAN;
 
911
        weight_value = FC_WEIGHT_MEDIUM;
 
912
        spacing_value = FC_PROPORTIONAL;
 
913
        file_value = 0;
 
914
        index_value = 0;
 
915
        scalable = FcTrue;
 
916
 
 
917
        if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch)
 
918
            slant_value = FC_SLANT_ROMAN;
 
919
        if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch)
 
920
            weight_value = FC_WEIGHT_MEDIUM;
 
921
        if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch)
 
922
            spacing_value = FC_PROPORTIONAL;
 
923
        if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch)
 
924
            file_value = 0;
 
925
        if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &index_value) != FcResultMatch)
 
926
            index_value = 0;
 
927
        if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch)
 
928
            scalable = FcTrue;
 
929
        if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
 
930
            foundry_value = 0;
 
931
        QtFontFamily *family = db->family(familyName, true);
 
932
        family->rawName = rawName;
 
933
        family->hasFT = true;
 
934
 
 
935
        FcLangSet *langset = 0;
 
936
        FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset);
 
937
        if (res == FcResultMatch) {
 
938
            for (int i = 1; i < LanguageCount; ++i) {
 
939
                const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i];
 
940
                if (!lang) {
 
941
                    family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
 
942
                } else {
 
943
                    FcLangResult langRes = FcLangSetHasLang(langset, lang);
 
944
                    if (langRes != FcLangDifferentLang)
 
945
                        family->writingSystems[i] = QtFontFamily::Supported;
 
946
                    else
 
947
                        family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
 
948
                }
 
949
            }
 
950
            family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT;
 
951
            family->ftWritingSystemCheck = true;
 
952
        } else {
 
953
            // we set Other to supported for symbol fonts. It makes no
 
954
            // sense to merge these with other ones, as they are
 
955
            // special in a way.
 
956
            for (int i = 1; i < LanguageCount; ++i)
 
957
                family->writingSystems[i] |= QtFontFamily::UnsupportedFT;
 
958
            family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported;
 
959
        }
 
960
 
 
961
        QByteArray file((const char *)file_value);
 
962
        family->fontFilename = file;
 
963
        family->fontFileIndex = index_value;
 
964
 
 
965
        QtFontStyle::Key styleKey;
 
966
        styleKey.style = (slant_value == FC_SLANT_ITALIC)
 
967
                         ? QFont::StyleItalic
 
968
                         : ((slant_value == FC_SLANT_OBLIQUE)
 
969
                            ? QFont::StyleOblique
 
970
                            : QFont::StyleNormal);
 
971
        styleKey.weight = getFCWeight(weight_value);
 
972
        if (!scalable) {
 
973
            int width = 100;
 
974
#if FC_VERSION >= 20193
 
975
            FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width);
 
976
#endif
 
977
            styleKey.stretch = width;
 
978
        }
 
979
 
 
980
        QtFontFoundry *foundry
 
981
            = family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true);
 
982
        QtFontStyle *style = foundry->style(styleKey, true);
 
983
 
 
984
        if (spacing_value < FC_MONO)
 
985
            family->fixedPitch = false;
 
986
 
 
987
        QtFontSize *size;
 
988
        if (scalable) {
 
989
            style->smoothScalable = true;
 
990
            size = style->pixelSize(SMOOTH_SCALABLE, true);
 
991
        } else {
 
992
            double pixel_size = 0;
 
993
            FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size);
 
994
            size = style->pixelSize((int)pixel_size, true);
 
995
        }
 
996
        QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
 
997
        enc->pitch = (spacing_value >= FC_CHARCELL ? 'c' :
 
998
                      (spacing_value >= FC_MONO ? 'm' : 'p'));
 
999
    }
 
1000
 
 
1001
    FcFontSetDestroy (fonts);
 
1002
 
 
1003
    struct FcDefaultFont {
 
1004
        const char *qtname;
 
1005
        const char *rawname;
 
1006
        bool fixed;
 
1007
    };
 
1008
    const FcDefaultFont defaults[] = {
 
1009
        { "Serif", "serif", false },
 
1010
        { "Sans Serif", "sans-serif", false },
 
1011
        { "Monospace", "monospace", true },
 
1012
        { 0, 0, false }
 
1013
    };
 
1014
    const FcDefaultFont *f = defaults;
 
1015
    while (f->qtname) {
 
1016
        QtFontFamily *family = db->family(f->qtname, true);
 
1017
        family->rawName = f->rawname;
 
1018
        family->hasFT = true;
 
1019
        family->synthetic = true;
 
1020
        QtFontFoundry *foundry = family->foundry(QString(), true);
 
1021
 
 
1022
        // aliases only make sense for 'common', not for any of the specials
 
1023
        for (int i = 1; i < LanguageCount; ++i) {
 
1024
            if (requiresOpenType(i))
 
1025
                family->writingSystems[i] = QtFontFamily::UnsupportedFT;
 
1026
            else
 
1027
                family->writingSystems[i] = QtFontFamily::Supported;
 
1028
        }
 
1029
        family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT;
 
1030
 
 
1031
        QtFontStyle::Key styleKey;
 
1032
        for (int i = 0; i < 4; ++i) {
 
1033
            styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic;
 
1034
            styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal;
 
1035
            QtFontStyle *style = foundry->style(styleKey, true);
 
1036
            style->smoothScalable = true;
 
1037
            QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true);
 
1038
            QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
 
1039
            enc->pitch = (f->fixed ? 'm' : 'p');
 
1040
        }
 
1041
        ++f;
 
1042
    }
 
1043
}
 
1044
#endif // QT_NO_FONTCONFIG
 
1045
 
 
1046
static void load(const QString &family = QString(), int script = -1)
 
1047
{
 
1048
    if (X11->has_fontconfig)
 
1049
        return;
 
1050
 
 
1051
#ifdef QFONTDATABASE_DEBUG
 
1052
    QTime t;
 
1053
    t.start();
 
1054
#endif
 
1055
 
 
1056
    if (family.isNull() && script == -1) {
 
1057
        loadXlfds(0, -1);
 
1058
    } else {
 
1059
        if (family.isNull()) {
 
1060
            // load all families in all writing systems that match \a script
 
1061
            for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
 
1062
                if (scriptForWritingSystem[ws] != script)
 
1063
                    continue;
 
1064
                for (int i = 0; i < numEncodings; ++i) {
 
1065
                    if (writingSystems_for_xlfd_encoding[i][ws])
 
1066
                        loadXlfds(0, i);
 
1067
                }
 
1068
            }
 
1069
        } else {
 
1070
            QtFontFamily *f = privateDb()->family(family, true);
 
1071
            // could reduce this further with some more magic:
 
1072
            // would need to remember the encodings loaded for the family.
 
1073
            if (!f->xlfdLoaded)
 
1074
                loadXlfds(family.toLatin1(), -1);
 
1075
        }
 
1076
    }
 
1077
 
 
1078
#ifdef QFONTDATABASE_DEBUG
 
1079
    FD_DEBUG("QFontDatabase: load(%s, %d) took %d ms",
 
1080
             family.toLatin1().constData(), script, t.elapsed());
 
1081
#endif
 
1082
}
 
1083
 
 
1084
static void initializeDb()
 
1085
{
 
1086
    QFontDatabasePrivate *db = privateDb();
 
1087
    if (!db || db->count)
 
1088
        return;
 
1089
 
 
1090
    QTime t;
 
1091
    t.start();
 
1092
 
 
1093
#ifndef QT_NO_FONTCONFIG
 
1094
    loadFontConfig();
 
1095
    FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", t.elapsed());
 
1096
#endif
 
1097
 
 
1098
    t.start();
 
1099
 
 
1100
#ifndef QT_NO_FONTCONFIG
 
1101
    for (int i = 0; i < db->count; i++) {
 
1102
        for (int j = 0; j < db->families[i]->count; ++j) {        // each foundry
 
1103
            QtFontFoundry *foundry = db->families[i]->foundries[j];
 
1104
            for (int k = 0; k < foundry->count; ++k) {
 
1105
                QtFontStyle *style = foundry->styles[k];
 
1106
                if (style->key.style != QFont::StyleNormal) continue;
 
1107
 
 
1108
                QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE);
 
1109
                if (! size) continue; // should not happen
 
1110
                QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true);
 
1111
                if (! enc) continue; // should not happen either
 
1112
 
 
1113
                QtFontStyle::Key key = style->key;
 
1114
 
 
1115
                // does this style have an italic equivalent?
 
1116
                key.style = QFont::StyleItalic;
 
1117
                QtFontStyle *equiv = foundry->style(key);
 
1118
                if (equiv) continue;
 
1119
 
 
1120
                // does this style have an oblique equivalent?
 
1121
                key.style = QFont::StyleOblique;
 
1122
                equiv = foundry->style(key);
 
1123
                if (equiv) continue;
 
1124
 
 
1125
                // let's fake one...
 
1126
                equiv = foundry->style(key, true);
 
1127
                equiv->smoothScalable = true;
 
1128
                equiv->fakeOblique = true;
 
1129
 
 
1130
                QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true);
 
1131
                QtFontEncoding *equiv_enc = equiv_size->encodingID(-1, 0, 0, 0, 0, true);
 
1132
 
 
1133
                // keep the same pitch
 
1134
                equiv_enc->pitch = enc->pitch;
 
1135
            }
 
1136
        }
 
1137
    }
 
1138
#endif
 
1139
 
 
1140
 
 
1141
#ifdef QFONTDATABASE_DEBUG
 
1142
#ifndef QT_NO_FONTCONFIG
 
1143
    if (!X11->has_fontconfig)
 
1144
#endif
 
1145
        // load everything at startup in debug mode.
 
1146
        loadXlfds(0, -1);
 
1147
 
 
1148
    // print the database
 
1149
    for (int f = 0; f < db->count; f++) {
 
1150
        QtFontFamily *family = db->families[f];
 
1151
        FD_DEBUG("'%s' %s  hasFT=%s", family->name.latin1(), (family->fixedPitch ? "fixed" : ""),
 
1152
                 (family->hasFT ? "yes" : "no"));
 
1153
        for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
 
1154
            QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
 
1155
            FD_DEBUG("\t%s: %s", QFontDatabase::writingSystemName(ws).toLatin1().constData(),
 
1156
                     ((family->writingSystems[i] & QtFontFamily::Supported) ? "Supported" :
 
1157
                      (family->writingSystems[i] & QtFontFamily::Unsupported) == QtFontFamily::Unsupported ?
 
1158
                      "Unsupported" : "Unknown"));
 
1159
        }
 
1160
 
 
1161
        for (int fd = 0; fd < family->count; fd++) {
 
1162
            QtFontFoundry *foundry = family->foundries[fd];
 
1163
            FD_DEBUG("\t\t'%s'", foundry->name.latin1());
 
1164
            for (int s = 0; s < foundry->count; s++) {
 
1165
                QtFontStyle *style = foundry->styles[s];
 
1166
                FD_DEBUG("\t\t\tstyle: style=%d weight=%d (%s)\n"
 
1167
                         "\t\t\tstretch=%d (%s)",
 
1168
                         style->key.style, style->key.weight,
 
1169
                         style->weightName, style->key.stretch,
 
1170
                         style->setwidthName ? style->setwidthName : "nil");
 
1171
                if (style->smoothScalable)
 
1172
                    FD_DEBUG("\t\t\t\tsmooth scalable");
 
1173
                else if (style->bitmapScalable)
 
1174
                    FD_DEBUG("\t\t\t\tbitmap scalable");
 
1175
                if (style->pixelSizes) {
 
1176
                    qDebug("\t\t\t\t%d pixel sizes", style->count);
 
1177
                    for (int z = 0; z < style->count; ++z) {
 
1178
                        QtFontSize *size = style->pixelSizes + z;
 
1179
                        for (int e = 0; e < size->count; ++e) {
 
1180
                            FD_DEBUG("\t\t\t\t  size %5d pitch %c encoding %s",
 
1181
                                      size->pixelSize,
 
1182
                                      size->encodings[e].pitch,
 
1183
                                      xlfd_for_id(size->encodings[e].encoding));
 
1184
                        }
 
1185
                    }
 
1186
                }
 
1187
            }
 
1188
        }
 
1189
    }
 
1190
#endif // QFONTDATABASE_DEBUG
 
1191
}
 
1192
 
 
1193
 
 
1194
// --------------------------------------------------------------------------------------
 
1195
// font loader
 
1196
// --------------------------------------------------------------------------------------
 
1197
 
 
1198
#ifndef QT_NO_FONTCONFIG
 
1199
 
 
1200
static void addPatternProps(FcPattern *pattern, const QtFontStyle::Key &key,
 
1201
                            bool fakeOblique, bool smoothScalable,
 
1202
                            const QFontPrivate *fp, const QFontDef &request, int script)
 
1203
{
 
1204
    int weight_value = FC_WEIGHT_BLACK;
 
1205
    if (key.weight == 0)
 
1206
        weight_value = FC_WEIGHT_MEDIUM;
 
1207
    else if (key.weight < (QFont::Light + QFont::Normal) / 2)
 
1208
        weight_value = FC_WEIGHT_LIGHT;
 
1209
    else if (key.weight < (QFont::Normal + QFont::DemiBold) / 2)
 
1210
        weight_value = FC_WEIGHT_MEDIUM;
 
1211
    else if (key.weight < (QFont::DemiBold + QFont::Bold) / 2)
 
1212
        weight_value = FC_WEIGHT_DEMIBOLD;
 
1213
    else if (key.weight < (QFont::Bold + QFont::Black) / 2)
 
1214
        weight_value = FC_WEIGHT_BOLD;
 
1215
    FcPatternAddInteger(pattern, FC_WEIGHT, weight_value);
 
1216
 
 
1217
    int slant_value = FC_SLANT_ROMAN;
 
1218
    if (key.style == QFont::StyleItalic)
 
1219
        slant_value = FC_SLANT_ITALIC;
 
1220
    else if (key.style == QFont::StyleOblique && !fakeOblique)
 
1221
        slant_value = FC_SLANT_OBLIQUE;
 
1222
    FcPatternAddInteger(pattern, FC_SLANT, slant_value);
 
1223
 
 
1224
    double size_value = request.pixelSize;
 
1225
    FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value);
 
1226
 
 
1227
    if (!smoothScalable) {
 
1228
#if FC_VERSION >= 20193
 
1229
        int stretch = request.stretch;
 
1230
        if (!stretch)
 
1231
            stretch = 100;
 
1232
        FcPatternAddInteger(pattern, FC_WIDTH, stretch);
 
1233
#endif
 
1234
    } else {
 
1235
        FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
 
1236
 
 
1237
        if ((request.stretch > 0 && request.stretch != 100) ||
 
1238
            (key.style == QFont::StyleOblique && fakeOblique)) {
 
1239
 
 
1240
            FcMatrix matrix;
 
1241
            FcMatrixInit(&matrix);
 
1242
 
 
1243
            if (request.stretch > 0 && request.stretch != 100)
 
1244
                FcMatrixScale(&matrix, double(request.stretch) / 100.0, 1.0);
 
1245
            if (key.style == QFont::StyleOblique && fakeOblique)
 
1246
                FcMatrixShear(&matrix, 0.20, 0.0);
 
1247
 
 
1248
            FcPatternAddMatrix(pattern, FC_MATRIX, &matrix);
 
1249
        }
 
1250
    }
 
1251
 
 
1252
    if (QX11Info::appDepth(fp->screen) <= 8) {
 
1253
        // can't do antialiasing on 8bpp
 
1254
        FcPatternAddBool(pattern, FC_ANTIALIAS, false);
 
1255
    } else if (request.styleStrategy & (QFont::PreferAntialias|QFont::NoAntialias)) {
 
1256
        FcPatternAddBool(pattern, FC_ANTIALIAS,
 
1257
                         !(request.styleStrategy & QFont::NoAntialias));
 
1258
    }
 
1259
 
 
1260
    if (script != QUnicodeTables::Common) {
 
1261
        Q_ASSERT(script < QUnicodeTables::ScriptCount);
 
1262
        FcLangSet *ls = FcLangSetCreate();
 
1263
        FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
 
1264
        FcPatternAddLangSet(pattern, FC_LANG, ls);
 
1265
        FcLangSetDestroy(ls);
 
1266
    }
 
1267
}
 
1268
 
 
1269
static void FcFontSetRemove(FcFontSet *fs, int at)
 
1270
{
 
1271
    Q_ASSERT(at < fs->nfont);
 
1272
    FcPatternDestroy(fs->fonts[at]);
 
1273
    int len = (--fs->nfont - at) * sizeof(FcPattern *);;
 
1274
    if (len > 0)
 
1275
        memmove(fs->fonts + at, fs->fonts + at + 1, len);
 
1276
}
 
1277
 
 
1278
static QFontEngine *loadFcEngineFromPattern(FcPattern *pattern, const QFontPrivate *fp,
 
1279
                                            const QFontDef &request, int script)
 
1280
{
 
1281
    FcBool forceScalable = true;
 
1282
    FcPatternGetBool(pattern, FC_SCALABLE, 0, &forceScalable);
 
1283
 
 
1284
    FcDefaultSubstitute(pattern);
 
1285
    FcConfigSubstitute(0, pattern, FcMatchPattern);
 
1286
    FcConfigSubstitute(0, pattern, FcMatchFont);
 
1287
 
 
1288
#ifdef FONT_MATCH_DEBUG
 
1289
    printf("forceScalable=%d", forceScalable);
 
1290
    printf("final FcPattern contains:\n");
 
1291
    FcPatternPrint(pattern);
 
1292
#endif
 
1293
 
 
1294
    FcResult result;
 
1295
    FcFontSet *fs = FcFontSort(0, pattern, FcTrue, 0, &result);
 
1296
    FcPatternDestroy(pattern);
 
1297
    if (!fs)
 
1298
        return 0;
 
1299
 
 
1300
    double size_value = request.pixelSize;
 
1301
 
 
1302
    // remove fonts if their size isn't close enough, or if they are
 
1303
    // not scalable (and should be)
 
1304
    for (int i = 0; i < fs->nfont; ++i) {
 
1305
        FcPattern *font = fs->fonts[i];
 
1306
        FcResult res;
 
1307
        FcBool scalable;
 
1308
        res = FcPatternGetBool(font, FC_SCALABLE, 0, &scalable);
 
1309
        if (res != FcResultMatch || !scalable) {
 
1310
            if (forceScalable) {
 
1311
                FcFontSetRemove(fs, i);
 
1312
#ifdef FONT_MATCH_DEBUG
 
1313
                printf("removing pattern:");
 
1314
                FcPatternPrint(font);
 
1315
#endif
 
1316
                --i; // go back one
 
1317
            } else {
 
1318
                double pixelSize;
 
1319
                res = FcPatternGetDouble(font, FC_PIXEL_SIZE, 0, &pixelSize);
 
1320
                if (res != FcResultMatch || qAbs((size_value-pixelSize)/size_value) > 0.2) {
 
1321
                    FcFontSetRemove(fs, i);
 
1322
#ifdef FONT_MATCH_DEBUG
 
1323
                    printf("removing pattern:");
 
1324
                    FcPatternPrint(font);
 
1325
#endif
 
1326
                    --i; // go back one
 
1327
                }
 
1328
            }
 
1329
        }
 
1330
    }
 
1331
 
 
1332
    QtFontStyle::Key key;
 
1333
    key.style = request.style;
 
1334
    key.weight = request.weight;
 
1335
    key.stretch = request.stretch;
 
1336
 
 
1337
    QFontEngine *fe = 0;
 
1338
    if (script != QUnicodeTables::Common) {
 
1339
        // load a single font for the script
 
1340
 
 
1341
        for (int i = 0; !fe && i < fs->nfont; ++i) {
 
1342
            // skip font if it doesn't support the language we want
 
1343
            FcLangSet *langSet = 0;
 
1344
            if (FcPatternGetLangSet(fs->fonts[i], FC_LANG, 0, &langSet) != FcResultMatch)
 
1345
                continue;
 
1346
            if (FcLangSetHasLang(langSet, (const FcChar8*)specialLanguages[script]) != FcLangEqual)
 
1347
                continue;
 
1348
 
 
1349
            FcPattern *pattern = FcPatternDuplicate(fs->fonts[i]);
 
1350
            // add properties back in as the font selected from the
 
1351
            // list doesn't contain them.
 
1352
            addPatternProps(pattern, key, false, true, fp, request, script);
 
1353
 
 
1354
            FcConfigSubstitute(0, pattern, FcMatchPattern);
 
1355
            FcDefaultSubstitute(pattern);
 
1356
            FcResult res;
 
1357
            FcPattern *match = FcFontMatch(0, pattern, &res);
 
1358
            QFontEngineFT *engine = new QFontEngineFT(match, request, fp->screen);
 
1359
            if (engine->invalid())
 
1360
                delete engine;
 
1361
            else
 
1362
                fe = engine;
 
1363
        }
 
1364
    } else {
 
1365
        // create a multi engine for the fontset fontconfig gave us
 
1366
        FcFontSet *fontSet = FcFontSetCreate();
 
1367
        for (int i = 0; i < fs->nfont; ++i) {
 
1368
            FcPattern *pattern = FcPatternDuplicate(fs->fonts[i]);
 
1369
            // add properties back in as the font selected from the
 
1370
            // list doesn't contain them.
 
1371
            addPatternProps(pattern, key, false, true, fp, request, script);
 
1372
            FcFontSetAdd(fontSet, pattern);
 
1373
        }
 
1374
 
 
1375
        fe = new QFontEngineMultiFT(fontSet, fp->screen);
 
1376
        fe->fontDef = request;
 
1377
    }
 
1378
 
 
1379
    FcFontSetDestroy(fs);
 
1380
    return fe;
 
1381
}
 
1382
 
 
1383
#endif // QT_NO_FONTCONFIG
 
1384
 
 
1385
static
 
1386
QFontEngine *loadEngine(int script,
 
1387
                        const QFontPrivate *fp, const QFontDef &request,
 
1388
                        QtFontFamily *family, QtFontFoundry *foundry,
 
1389
                        QtFontStyle *style, QtFontSize *size,
 
1390
                        QtFontEncoding *encoding, bool forced_encoding)
 
1391
{
 
1392
    Q_UNUSED(script);
 
1393
 
 
1394
    if (fp && fp->rawMode) {
 
1395
        QByteArray xlfd = request.family.toLatin1();
 
1396
        FM_DEBUG("Loading XLFD (rawmode) '%s'", xlfd.data());
 
1397
 
 
1398
        XFontStruct *xfs;
 
1399
        if (! (xfs = XLoadQueryFont(QX11Info::display(), xlfd.data())))
 
1400
            return 0;
 
1401
 
 
1402
        QFontEngine *fe = new QFontEngineXLFD(xfs, xlfd.data(), 0);
 
1403
        if (! qt_fillFontDef(xfs, &fe->fontDef, fp->dpi) &&
 
1404
            ! qt_fillFontDef(xlfd, &fe->fontDef, fp->dpi))
 
1405
            fe->fontDef = QFontDef();
 
1406
 
 
1407
        return fe;
 
1408
    }
 
1409
 
 
1410
#ifndef QT_NO_FONTCONFIG
 
1411
    if (X11->has_fontconfig && encoding->encoding == -1) {
 
1412
 
 
1413
        FM_DEBUG("    using FontConfig");
 
1414
 
 
1415
        FcPattern *pattern = FcPatternCreate();
 
1416
        if (!pattern)
 
1417
            return 0;
 
1418
 
 
1419
        if (!foundry->name.isEmpty()) {
 
1420
            FcPatternAddString(pattern, FC_FOUNDRY,
 
1421
                               (const FcChar8 *)foundry->name.toUtf8().constData());
 
1422
        }
 
1423
 
 
1424
        QStringList familyList;
 
1425
        if (!family->rawName.isEmpty()) {
 
1426
            FcPatternAddString(pattern, FC_FAMILY,
 
1427
                               (const FcChar8 *)family->rawName.toUtf8().constData());
 
1428
            familyList << family->name;
 
1429
        }
 
1430
 
 
1431
        QString stylehint;
 
1432
        switch (request.styleHint) {
 
1433
        case QFont::SansSerif:
 
1434
            stylehint = "sans-serif";
 
1435
            break;
 
1436
        case QFont::Serif:
 
1437
            stylehint = "serif";
 
1438
            break;
 
1439
        case QFont::TypeWriter:
 
1440
            stylehint = "monospace";
 
1441
            break;
 
1442
        default:
 
1443
            if (request.fixedPitch)
 
1444
                stylehint = "monospace";
 
1445
            break;
 
1446
        }
 
1447
        if (!stylehint.isEmpty()) {
 
1448
            FcPatternAddString(pattern, FC_FAMILY,
 
1449
                               (const FcChar8 *)stylehint.toUtf8().constData());
 
1450
            familyList << family->name;
 
1451
        }
 
1452
 
 
1453
        FcValue value;
 
1454
        value.type = FcTypeString;
 
1455
 
 
1456
        // these should only get added to the pattern _after_ substitution
 
1457
        // append the default fallback font for the specified script
 
1458
        extern QString qt_fallback_font_family(int);
 
1459
        QString fallback = qt_fallback_font_family(script);
 
1460
        if (!fallback.isEmpty() && !familyList.contains(fallback)) {
 
1461
            QByteArray cs = fallback.toUtf8();
 
1462
            value.u.s = (const FcChar8 *)cs.data();
 
1463
            FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
 
1464
        }
 
1465
 
 
1466
        // add the default family
 
1467
        QString defaultFamily = QApplication::font().family();
 
1468
        if (!familyList.contains(defaultFamily)) {
 
1469
            QByteArray cs = defaultFamily.toUtf8();
 
1470
            value.u.s = (const FcChar8 *)cs.data();
 
1471
            FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
 
1472
        }
 
1473
 
 
1474
        // add QFont::defaultFamily() to the list, for compatibility with
 
1475
        // previous versions
 
1476
        defaultFamily = QApplication::font().defaultFamily();
 
1477
        if (!familyList.contains(defaultFamily)) {
 
1478
            QByteArray cs = defaultFamily.toUtf8();
 
1479
            value.u.s = (const FcChar8 *)cs.data();
 
1480
            FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
 
1481
        }
 
1482
 
 
1483
        char pitch_value = (encoding->pitch == 'c' ? FC_CHARCELL :
 
1484
                            (encoding->pitch == 'm' ? FC_MONO : FC_PROPORTIONAL));
 
1485
        FcPatternAddInteger(pattern, FC_SPACING, pitch_value);
 
1486
        FcPatternAddBool(pattern, FC_SCALABLE, style->smoothScalable);
 
1487
 
 
1488
        addPatternProps(pattern, style->key, style->fakeOblique, style->smoothScalable,
 
1489
                        fp, request, script);
 
1490
        return loadFcEngineFromPattern(pattern, fp, request, script);
 
1491
    }
 
1492
#endif // QT_NO_FONTCONFIG
 
1493
 
 
1494
    int px = size->pixelSize;
 
1495
    if (style->smoothScalable && px == SMOOTH_SCALABLE)
 
1496
        px = request.pixelSize;
 
1497
    else if (style->bitmapScalable && px == 0)
 
1498
        px = request.pixelSize;
 
1499
 
 
1500
    QFontEngine *fe = 0;
 
1501
    if (forced_encoding || script != QUnicodeTables::Common) {
 
1502
        QByteArray xlfd("-");
 
1503
        xlfd += foundry->name.isEmpty() ? QByteArray("*") : foundry->name.toLatin1();
 
1504
        xlfd += "-";
 
1505
        xlfd += family->name.isEmpty() ? QByteArray("*") : family->name.toLatin1();
 
1506
        xlfd += "-";
 
1507
        xlfd += style->weightName ? style->weightName : "*";
 
1508
        xlfd += "-";
 
1509
        xlfd += (style->key.style == QFont::StyleItalic
 
1510
                 ? "i"
 
1511
                 : (style->key.style == QFont::StyleOblique ? "o" : "r"));
 
1512
        xlfd += "-";
 
1513
        xlfd += style->setwidthName ? style->setwidthName : "*";
 
1514
        // ### handle add-style
 
1515
        xlfd += "-*-";
 
1516
        xlfd += QByteArray::number(px);
 
1517
        xlfd += "-";
 
1518
        xlfd += QByteArray::number(encoding->xpoint);
 
1519
        xlfd += "-";
 
1520
        xlfd += QByteArray::number(encoding->xres);
 
1521
        xlfd += "-";
 
1522
        xlfd += QByteArray::number(encoding->yres);
 
1523
        xlfd += "-";
 
1524
        xlfd += encoding->pitch;
 
1525
        xlfd += "-";
 
1526
        xlfd += QByteArray::number(encoding->avgwidth);
 
1527
        xlfd += "-";
 
1528
        xlfd += xlfd_for_id(encoding->encoding);
 
1529
 
 
1530
        FM_DEBUG("    using XLFD: %s\n", xlfd.data());
 
1531
 
 
1532
        const int mib = xlfd_encoding[encoding->encoding].mib;
 
1533
        XFontStruct *xfs;
 
1534
        if (! (xfs = XLoadQueryFont(QX11Info::display(), xlfd)))
 
1535
            return 0;
 
1536
        fe = new QFontEngineXLFD(xfs, xlfd, mib);
 
1537
    } else {
 
1538
        QList<int> encodings;
 
1539
        encodings.append(int(encoding->encoding));
 
1540
 
 
1541
        // append all other encodings for the matched font
 
1542
        for (int i = 0; i < style->count; ++i) {
 
1543
            QtFontEncoding *e = size->encodings + i;
 
1544
            if (e == encoding)
 
1545
                break;
 
1546
            encodings.append(int(e->encoding));
 
1547
        }
 
1548
        // fill in the missing encodings
 
1549
        const XlfdEncoding *enc = xlfd_encoding;
 
1550
        for (; enc->name; ++enc) {
 
1551
            if (!encodings.contains(enc->id))
 
1552
                encodings.append(enc->id);
 
1553
        }
 
1554
 
 
1555
#if defined(FONT_MATCH_DEBUG)
 
1556
        FM_DEBUG("    using MultiXLFD, encodings:");
 
1557
        for (int i = 0; i < encodings.size(); ++i) {
 
1558
            const int id = encodings.at(i);
 
1559
            FM_DEBUG("      %2d: %s", xlfd_encoding[id].id, xlfd_encoding[id].name);
 
1560
        }
 
1561
#endif
 
1562
 
 
1563
        fe = new QFontEngineMultiXLFD(request, encodings, fp->screen);
 
1564
    }
 
1565
    return fe;
 
1566
}