1
/****************************************************************************
2
**
3
** Copyright (C) 2012 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
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#define QT_FATAL_ASSERT
43
44
#include "qplatformdefs.h"
45
46
#include "qfont.h"
47
#include "qapplication.h"
48
#include "qfontinfo.h"
49
#include "qfontdatabase.h"
50
#include "qfontmetrics.h"
51
#include "qpaintdevice.h"
52
#include "qtextcodec.h"
53
#include "qiodevice.h"
54
#include "qhash.h"
55
56
#include <private/qunicodetables_p.h>
57
#include "qfont_p.h"
58
#include "qfontengine_p.h"
59
#include "qfontengine_x11_p.h"
60
#include "qtextengine_p.h"
61
62
#include <private/qt_x11_p.h>
63
#include "qx11info_x11.h"
64
65
#include <time.h>
66
#include <stdlib.h>
67
#include <ctype.h>
68
69
#define QFONTLOADER_DEBUG
70
#define QFONTLOADER_DEBUG_VERBOSE
71
72
QT_BEGIN_NAMESPACE
73
74
double qt_pixelSize(double pointSize, int dpi)
75
{
76
    if (pointSize < 0)
77
        return -1.;
78
    if (dpi == 75) // the stupid 75 dpi setting on X11
79
        dpi = 72;
80
    return (pointSize * dpi) /72.;
81
}
82
83
double qt_pointSize(double pixelSize, int dpi)
84
{
85
    if (pixelSize < 0)
86
        return -1.;
87
    if (dpi == 75) // the stupid 75 dpi setting on X11
88
        dpi = 72;
89
    return pixelSize * 72. / ((double) dpi);
90
}
91
92
/*
93
  Removes wildcards from an XLFD.
94
95
  Returns \a xlfd with all wildcards removed if a match for \a xlfd is
96
  found, otherwise it returns \a xlfd.
97
*/
98
static QByteArray qt_fixXLFD(const QByteArray &xlfd)
99
{
100
    QByteArray ret = xlfd;
101
    int count = 0;
102
    char **fontNames =
103
        XListFonts(QX11Info::display(), xlfd, 32768, &count);
104
    if (count > 0)
105
        ret = fontNames[0];
106
    XFreeFontNames(fontNames);
107
    return ret ;
108
}
109
110
typedef QHash<int, QString> FallBackHash;
111
Q_GLOBAL_STATIC(FallBackHash, fallBackHash)
112
113
// Returns the user-configured fallback family for the specified script.
114
QString qt_fallback_font_family(int script)
115
{
116
    FallBackHash *hash = fallBackHash();
117
    return hash->value(script);
118
}
119
120
// Sets the fallback family for the specified script.
121
Q_GUI_EXPORT void qt_x11_set_fallback_font_family(int script, const QString &family)
122
{
123
    FallBackHash *hash = fallBackHash();
124
    if (!family.isEmpty())
125
        hash->insert(script, family);
126
    else
127
        hash->remove(script);
128
}
129
130
int QFontPrivate::defaultEncodingID = -1;
131
132
void QFont::initialize()
133
{
134
    extern int qt_encoding_id_for_mib(int mib); // from qfontdatabase_x11.cpp
135
    QTextCodec *codec = QTextCodec::codecForLocale();
136
    // determine the default encoding id using the locale, otherwise
137
    // fallback to latin1 (mib == 4)
138
    int mib = codec ? codec->mibEnum() : 4;
139
140
    // for asian locales, use the mib for the font codec instead of the locale codec
141
    switch (mib) {
142
    case 38: // eucKR
143
        mib = 36;
144
        break;
145
146
    case 2025: // GB2312
147
        mib = 57;
148
        break;
149
150
    case 113: // GBK
151
        mib = -113;
152
        break;
153
154
    case 114: // GB18030
155
        mib = -114;
156
        break;
157
158
    case 2026: // Big5
159
        mib = -2026;
160
        break;
161
162
    case 2101: // Big5-HKSCS
163
        mib = -2101;
164
        break;
165
166
    case 16: // JIS7
167
        mib = 15;
168
        break;
169
170
    case 17: // SJIS
171
    case 18: // eucJP
172
        mib = 63;
173
        break;
174
    }
175
176
    // get the default encoding id for the locale encoding...
177
    QFontPrivate::defaultEncodingID = qt_encoding_id_for_mib(mib);
178
}
179
180
void QFont::cleanup()
181
{
182
    QFontCache::cleanup();
183
}
184
185
/*!
186
  \internal
187
  X11 Only: Returns the screen with which this font is associated.
188
*/
189
int QFont::x11Screen() const
190
{
191
    return d->screen;
192
}
193
194
/*! \internal
195
    X11 Only: Associate the font with the specified \a screen.
196
*/
197
void QFont::x11SetScreen(int screen)
198
{
199
    if (screen < 0) // assume default
200
        screen = QX11Info::appScreen();
201
202
    if (screen == d->screen)
203
        return; // nothing to do
204
205
    detach();
206
    d->screen = screen;
207
}
208
209
Qt::HANDLE QFont::handle() const
210
{
211
    QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
212
    Q_ASSERT(engine != 0);
213
    if (engine->type() == QFontEngine::Multi)
214
        engine = static_cast<QFontEngineMulti *>(engine)->engine(0);
215
    if (engine->type() == QFontEngine::XLFD)
216
        return static_cast<QFontEngineXLFD *>(engine)->fontStruct()->fid;
217
    return 0;
218
}
219
220
221
FT_Face QFont::freetypeFace() const
222
{
223
#ifndef QT_NO_FREETYPE
224
    QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
225
    if (engine->type() == QFontEngine::Multi)
226
        engine = static_cast<QFontEngineMulti *>(engine)->engine(0);
227
#ifndef QT_NO_FONTCONFIG
228
    if (engine->type() == QFontEngine::Freetype) {
229
        const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine);
230
        return ft->non_locked_face();
231
    } else
232
#endif
233
    if (engine->type() == QFontEngine::XLFD) {
234
        const QFontEngineXLFD *xlfd = static_cast<const QFontEngineXLFD *>(engine);
235
        return xlfd->non_locked_face();
236
    }
237
#endif
238
    return 0;
239
}
240
241
QString QFont::rawName() const
242
{
243
    QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
244
    Q_ASSERT(engine != 0);
245
    if (engine->type() == QFontEngine::Multi)
246
        engine = static_cast<QFontEngineMulti *>(engine)->engine(0);
247
    if (engine->type() == QFontEngine::XLFD)
248
        return QString::fromLatin1(engine->name());
249
    return QString();
250
}
251
struct QtFontDesc;
252
253
void QFont::setRawName(const QString &name)
254
{
255
    detach();
256
257
    // from qfontdatabase_x11.cpp
258
    extern bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi, QtFontDesc *desc);
259
260
    if (!qt_fillFontDef(qt_fixXLFD(name.toLatin1()), &d->request, d->dpi, 0)) {
261
        qWarning("QFont::setRawName: Invalid XLFD: \"%s\"", name.toLatin1().constData());
262
263
        setFamily(name);
264
        setRawMode(true);
265
    } else {
266
        resolve_mask = QFont::AllPropertiesResolved;
267
    }
268
}
269
270
QString QFont::lastResortFamily() const
271
{
272
    return QString::fromLatin1("Helvetica");
273
}
274
275
QString QFont::defaultFamily() const
276
{
277
    switch (d->request.styleHint) {
278
    case QFont::Times:
279
        return QString::fromLatin1("Times");
280
281
    case QFont::Courier:
282
        return QString::fromLatin1("Courier");
283
284
    case QFont::Monospace:
285
        return QString::fromLatin1("Courier New");
286
287
    case QFont::Cursive:
288
        return QString::fromLatin1("Comic Sans MS");
289
290
    case QFont::Fantasy:
291
        return QString::fromLatin1("Impact");
292
293
    case QFont::Decorative:
294
        return QString::fromLatin1("Old English");
295
296
    case QFont::Helvetica:
297
    case QFont::System:
298
    default:
299
        return QString::fromLatin1("Helvetica");
300
    }
301
}
302
303
/*
304
  Returns a last resort raw font name for the font matching algorithm.
305
  This is used if even the last resort family is not available. It
306
  returns \e something, almost no matter what.  The current
307
  implementation tries a wide variety of common fonts, returning the
308
  first one it finds. The implementation may change at any time.
309
*/
310
static const char * const tryFonts[] = {
311
    "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
312
    "-*-courier-medium-r-*-*-*-120-*-*-*-*-*-*",
313
    "-*-times-medium-r-*-*-*-120-*-*-*-*-*-*",
314
    "-*-lucida-medium-r-*-*-*-120-*-*-*-*-*-*",
315
    "-*-helvetica-*-*-*-*-*-120-*-*-*-*-*-*",
316
    "-*-courier-*-*-*-*-*-120-*-*-*-*-*-*",
317
    "-*-times-*-*-*-*-*-120-*-*-*-*-*-*",
318
    "-*-lucida-*-*-*-*-*-120-*-*-*-*-*-*",
319
    "-*-helvetica-*-*-*-*-*-*-*-*-*-*-*-*",
320
    "-*-courier-*-*-*-*-*-*-*-*-*-*-*-*",
321
    "-*-times-*-*-*-*-*-*-*-*-*-*-*-*",
322
    "-*-lucida-*-*-*-*-*-*-*-*-*-*-*-*",
323
    "-*-fixed-*-*-*-*-*-*-*-*-*-*-*-*",
324
    "6x13",
325
    "7x13",
326
    "8x13",
327
    "9x15",
328
    "fixed",
329
    0
330
};
331
332
// Returns true if the font exists, false otherwise
333
static bool fontExists(const QString &fontName)
334
{
335
    int count;
336
    char **fontNames = XListFonts(QX11Info::display(), (char*)fontName.toLatin1().constData(), 32768, &count);
337
    if (fontNames) XFreeFontNames(fontNames);
338
339
    return count != 0;
340
}
341
342
QString QFont::lastResortFont() const
343
{
344
    static QString last;
345
346
    // already found
347
    if (! last.isNull())
348
        return last;
349
350
    int i = 0;
351
    const char* f;
352
353
    while ((f = tryFonts[i])) {
354
        last = QString::fromLatin1(f);
355
356
        if (fontExists(last))
357
            return last;
358
359
        i++;
360
    }
361
362
#if defined(CHECK_NULL)
363
    qFatal("QFontPrivate::lastResortFont: Cannot find any reasonable font");
364
#endif
365
    return last;
366
}
367
368
QT_END_NAMESPACE