| 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 |
#include <qdir.h> |
| 43 |
#include "qfontdatabase.h" |
| 44 |
#include "qdebug.h" |
| 45 |
#include "qalgorithms.h" |
| 46 |
#include "qapplication.h" |
| 47 |
#include "qvarlengtharray.h" // here or earlier - workaround for VC++6 |
| 48 |
#include "qthread.h" |
| 49 |
#include "qmutex.h" |
| 50 |
#include "private/qunicodetables_p.h" |
| 51 |
#include "qfontengine_p.h" |
| 52 |
|
| 53 |
#ifdef Q_WS_QPA |
| 54 |
#include <QtGui/private/qapplication_p.h> |
| 55 |
#include <QtGui/qplatformfontdatabase_qpa.h> |
| 56 |
#include "qabstractfileengine.h" |
| 57 |
#endif |
| 58 |
|
| 59 |
#ifdef Q_WS_X11 |
| 60 |
#include <locale.h> |
| 61 |
#endif |
| 62 |
#include <stdlib.h> |
| 63 |
#include <limits.h> |
| 64 |
|
| 65 |
#if (defined(Q_WS_QWS)|| defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) |
| 66 |
# include <ft2build.h> |
| 67 |
# include FT_TRUETYPE_TABLES_H |
| 68 |
#endif |
| 69 |
|
| 70 |
// #define QFONTDATABASE_DEBUG |
| 71 |
#ifdef QFONTDATABASE_DEBUG |
| 72 |
# define FD_DEBUG qDebug |
| 73 |
#else |
| 74 |
# define FD_DEBUG if (false) qDebug |
| 75 |
#endif |
| 76 |
|
| 77 |
// #define FONT_MATCH_DEBUG |
| 78 |
#ifdef FONT_MATCH_DEBUG |
| 79 |
# define FM_DEBUG qDebug |
| 80 |
#else |
| 81 |
# define FM_DEBUG if (false) qDebug |
| 82 |
#endif |
| 83 |
|
| 84 |
#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECTWRITE) |
| 85 |
# include <dwrite.h> |
| 86 |
#endif |
| 87 |
|
| 88 |
QT_BEGIN_NAMESPACE |
| 89 |
|
| 90 |
#define SMOOTH_SCALABLE 0xffff |
| 91 |
|
| 92 |
bool qt_enable_test_font = false; |
| 93 |
|
| 94 |
static QString styleStringHelper(int weight, QFont::Style style); |
| 95 |
|
| 96 |
Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value) |
| 97 |
{ |
| 98 |
qt_enable_test_font = value; |
| 99 |
} |
| 100 |
|
| 101 |
static int getFontWeight(const QString &weightString) |
| 102 |
{ |
| 103 |
QString s = weightString.toLower(); |
| 104 |
|
| 105 |
// Test in decreasing order of commonness |
| 106 |
if (s == QLatin1String("medium") || |
| 107 |
s == QLatin1String("normal") |
| 108 |
|| s.compare(QApplication::translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0) |
| 109 |
return QFont::Normal; |
| 110 |
if (s == QLatin1String("bold") |
| 111 |
|| s.compare(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0) |
| 112 |
return QFont::Bold; |
| 113 |
if (s == QLatin1String("demibold") || s == QLatin1String("demi bold") |
| 114 |
|| s.compare(QApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0) |
| 115 |
return QFont::DemiBold; |
| 116 |
if (s == QLatin1String("black") |
| 117 |
|| s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0) |
| 118 |
return QFont::Black; |
| 119 |
if (s == QLatin1String("light")) |
| 120 |
return QFont::Light; |
| 121 |
|
| 122 |
if (s.contains(QLatin1String("bold")) |
| 123 |
|| s.contains(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) { |
| 124 |
if (s.contains(QLatin1String("demi")) |
| 125 |
|| s.compare(QApplication::translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0) |
| 126 |
return (int) QFont::DemiBold; |
| 127 |
return (int) QFont::Bold; |
| 128 |
} |
| 129 |
|
| 130 |
if (s.contains(QLatin1String("light")) |
| 131 |
|| s.compare(QApplication::translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0) |
| 132 |
return (int) QFont::Light; |
| 133 |
|
| 134 |
if (s.contains(QLatin1String("black")) |
| 135 |
|| s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0) |
| 136 |
return (int) QFont::Black; |
| 137 |
|
| 138 |
return (int) QFont::Normal; |
| 139 |
} |
| 140 |
|
| 141 |
// convert 0 ~ 1000 integer to QFont::Weight |
| 142 |
QFont::Weight weightFromInteger(int weight) |
| 143 |
{ |
| 144 |
if (weight < 400) |
| 145 |
return QFont::Light; |
| 146 |
else if (weight < 600) |
| 147 |
return QFont::Normal; |
| 148 |
else if (weight < 700) |
| 149 |
return QFont::DemiBold; |
| 150 |
else if (weight < 800) |
| 151 |
return QFont::Bold; |
| 152 |
else |
| 153 |
return QFont::Black; |
| 154 |
} |
| 155 |
|
| 156 |
struct QtFontEncoding |
| 157 |
{ |
| 158 |
signed int encoding : 16; |
| 159 |
|
| 160 |
uint xpoint : 16; |
| 161 |
uint xres : 8; |
| 162 |
uint yres : 8; |
| 163 |
uint avgwidth : 16; |
| 164 |
uchar pitch : 8; |
| 165 |
}; |
| 166 |
|
| 167 |
struct QtFontSize |
| 168 |
{ |
| 169 |
#ifdef Q_WS_X11 |
| 170 |
QtFontEncoding *encodings; |
| 171 |
QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0, |
| 172 |
uint yres = 0, uint avgwidth = 0, bool add = false); |
| 173 |
unsigned short count : 16; |
| 174 |
#endif // Q_WS_X11 |
| 175 |
|
| 176 |
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) |
| 177 |
QByteArray fileName; |
| 178 |
int fileIndex; |
| 179 |
#endif // defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) |
| 180 |
#if defined(Q_WS_QPA) |
| 181 |
void *handle; |
| 182 |
#endif |
| 183 |
|
| 184 |
unsigned short pixelSize : 16; |
| 185 |
}; |
| 186 |
|
| 187 |
|
| 188 |
#ifdef Q_WS_X11 |
| 189 |
QtFontEncoding *QtFontSize::encodingID(int id, uint xpoint, uint xres, |
| 190 |
uint yres, uint avgwidth, bool add) |
| 191 |
{ |
| 192 |
// we don't match using the xpoint, xres and yres parameters, only the id |
| 193 |
for (int i = 0; i < count; ++i) { |
| 194 |
if (encodings[i].encoding == id) |
| 195 |
return encodings + i; |
| 196 |
} |
| 197 |
|
| 198 |
if (!add) return 0; |
| 199 |
|
| 200 |
if (!(count % 4)) { |
| 201 |
QtFontEncoding *newEncodings = (QtFontEncoding *) |
| 202 |
realloc(encodings, |
| 203 |
(((count+4) >> 2) << 2) * sizeof(QtFontEncoding)); |
| 204 |
Q_CHECK_PTR(newEncodings); |
| 205 |
encodings = newEncodings; |
| 206 |
} |
| 207 |
encodings[count].encoding = id; |
| 208 |
encodings[count].xpoint = xpoint; |
| 209 |
encodings[count].xres = xres; |
| 210 |
encodings[count].yres = yres; |
| 211 |
encodings[count].avgwidth = avgwidth; |
| 212 |
encodings[count].pitch = '*'; |
| 213 |
return encodings + count++; |
| 214 |
} |
| 215 |
#endif // Q_WS_X11 |
| 216 |
|
| 217 |
struct QtFontStyle |
| 218 |
{ |
| 219 |
struct Key { |
| 220 |
Key(const QString &styleString); |
| 221 |
Key() : style(QFont::StyleNormal), |
| 222 |
weight(QFont::Normal), stretch(0) { } |
| 223 |
Key(const Key &o) : style(o.style), weight(o.weight), stretch(o.stretch) { } |
| 224 |
uint style : 2; |
| 225 |
signed int weight : 8; |
| 226 |
signed int stretch : 12; |
| 227 |
|
| 228 |
bool operator==(const Key & other) { |
| 229 |
return (style == other.style && weight == other.weight && |
| 230 |
(stretch == 0 || other.stretch == 0 || stretch == other.stretch)); |
| 231 |
} |
| 232 |
bool operator!=(const Key &other) { |
| 233 |
return !operator==(other); |
| 234 |
} |
| 235 |
bool operator <(const Key &o) { |
| 236 |
int x = (style << 12) + (weight << 14) + stretch; |
| 237 |
int y = (o.style << 12) + (o.weight << 14) + o.stretch; |
| 238 |
return (x < y); |
| 239 |
} |
| 240 |
}; |
| 241 |
|
| 242 |
QtFontStyle(const Key &k) |
| 243 |
: key(k), bitmapScalable(false), smoothScalable(false), |
| 244 |
count(0), pixelSizes(0) |
| 245 |
{ |
| 246 |
#if defined(Q_WS_X11) |
| 247 |
weightName = setwidthName = 0; |
| 248 |
#endif // Q_WS_X11 |
| 249 |
} |
| 250 |
|
| 251 |
~QtFontStyle() { |
| 252 |
#ifdef Q_WS_X11 |
| 253 |
delete [] weightName; |
| 254 |
delete [] setwidthName; |
| 255 |
#endif |
| 256 |
#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) |
| 257 |
while (count) { |
| 258 |
// bitfield count-- in while condition does not work correctly in mwccsym2 |
| 259 |
count--; |
| 260 |
#ifdef Q_WS_X11 |
| 261 |
free(pixelSizes[count].encodings); |
| 262 |
#endif |
| 263 |
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) |
| 264 |
pixelSizes[count].fileName.~QByteArray(); |
| 265 |
#endif |
| 266 |
#if defined (Q_WS_QPA) |
| 267 |
QPlatformIntegration *integration = QApplicationPrivate::platformIntegration(); |
| 268 |
if (integration) { //on shut down there will be some that we don't release. |
| 269 |
integration->fontDatabase()->releaseHandle(pixelSizes[count].handle); |
| 270 |
} |
| 271 |
#endif |
| 272 |
} |
| 273 |
#endif |
| 274 |
free(pixelSizes); |
| 275 |
} |
| 276 |
|
| 277 |
Key key; |
| 278 |
bool bitmapScalable : 1; |
| 279 |
bool smoothScalable : 1; |
| 280 |
signed int count : 30; |
| 281 |
QtFontSize *pixelSizes; |
| 282 |
QString styleName; |
| 283 |
|
| 284 |
#ifdef Q_WS_X11 |
| 285 |
const char *weightName; |
| 286 |
const char *setwidthName; |
| 287 |
#endif // Q_WS_X11 |
| 288 |
#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) |
| 289 |
bool antialiased; |
| 290 |
#endif |
| 291 |
|
| 292 |
QtFontSize *pixelSize(unsigned short size, bool = false); |
| 293 |
}; |
| 294 |
|
| 295 |
QtFontStyle::Key::Key(const QString &styleString) |
| 296 |
: style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) |
| 297 |
{ |
| 298 |
weight = getFontWeight(styleString); |
| 299 |
|
| 300 |
if (styleString.contains(QLatin1String("Italic")) |
| 301 |
|| styleString.contains(QApplication::translate("QFontDatabase", "Italic"))) |
| 302 |
style = QFont::StyleItalic; |
| 303 |
else if (styleString.contains(QLatin1String("Oblique")) |
| 304 |
|| styleString.contains(QApplication::translate("QFontDatabase", "Oblique"))) |
| 305 |
style = QFont::StyleOblique; |
| 306 |
} |
| 307 |
|
| 308 |
QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add) |
| 309 |
{ |
| 310 |
for (int i = 0; i < count; i++) { |
| 311 |
if (pixelSizes[i].pixelSize == size) |
| 312 |
return pixelSizes + i; |
| 313 |
} |
| 314 |
if (!add) |
| 315 |
return 0; |
| 316 |
|
| 317 |
if (!pixelSizes) { |
| 318 |
// Most style have only one font size, we avoid waisting memory |
| 319 |
QtFontSize *newPixelSizes = (QtFontSize *)malloc(sizeof(QtFontSize)); |
| 320 |
Q_CHECK_PTR(newPixelSizes); |
| 321 |
pixelSizes = newPixelSizes; |
| 322 |
} else if (!(count % 8) || count == 1) { |
| 323 |
QtFontSize *newPixelSizes = (QtFontSize *) |
| 324 |
realloc(pixelSizes, |
| 325 |
(((count+8) >> 3) << 3) * sizeof(QtFontSize)); |
| 326 |
Q_CHECK_PTR(newPixelSizes); |
| 327 |
pixelSizes = newPixelSizes; |
| 328 |
} |
| 329 |
pixelSizes[count].pixelSize = size; |
| 330 |
#ifdef Q_WS_X11 |
| 331 |
pixelSizes[count].count = 0; |
| 332 |
pixelSizes[count].encodings = 0; |
| 333 |
#endif |
| 334 |
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) |
| 335 |
new (&pixelSizes[count].fileName) QByteArray; |
| 336 |
pixelSizes[count].fileIndex = 0; |
| 337 |
#endif |
| 338 |
#if defined(Q_WS_QPA) |
| 339 |
pixelSizes[count].handle = 0; |
| 340 |
#endif |
| 341 |
return pixelSizes + (count++); |
| 342 |
} |
| 343 |
|
| 344 |
struct QtFontFoundry |
| 345 |
{ |
| 346 |
QtFontFoundry(const QString &n) : name(n), count(0), styles(0) {} |
| 347 |
~QtFontFoundry() { |
| 348 |
while (count--) |
| 349 |
delete styles[count]; |
| 350 |
free(styles); |
| 351 |
} |
| 352 |
|
| 353 |
QString name; |
| 354 |
|
| 355 |
int count; |
| 356 |
QtFontStyle **styles; |
| 357 |
QtFontStyle *style(const QtFontStyle::Key &, const QString & = QString(), bool = false); |
| 358 |
}; |
| 359 |
|
| 360 |
QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &styleName, bool create) |
| 361 |
{ |
| 362 |
int pos = 0; |
| 363 |
for (; pos < count; pos++) { |
| 364 |
bool hasStyleName = !styleName.isEmpty(); // search styleName first if available |
| 365 |
if (hasStyleName && !styles[pos]->styleName.isEmpty()) { |
| 366 |
if (styles[pos]->styleName == styleName) |
| 367 |
return styles[pos]; |
| 368 |
} else { |
| 369 |
if (styles[pos]->key == key) |
| 370 |
return styles[pos]; |
| 371 |
} |
| 372 |
} |
| 373 |
if (!create) |
| 374 |
return 0; |
| 375 |
|
| 376 |
// qDebug("adding key (weight=%d, style=%d, stretch=%d) at %d", key.weight, key.style, key.stretch, pos); |
| 377 |
if (!(count % 8)) { |
| 378 |
QtFontStyle **newStyles = (QtFontStyle **) |
| 379 |
realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *)); |
| 380 |
Q_CHECK_PTR(newStyles); |
| 381 |
styles = newStyles; |
| 382 |
} |
| 383 |
|
| 384 |
QtFontStyle *style = new QtFontStyle(key); |
| 385 |
style->styleName = styleName; |
| 386 |
styles[pos] = style; |
| 387 |
count++; |
| 388 |
return styles[pos]; |
| 389 |
} |
| 390 |
|
| 391 |
struct QtFontFamily |
| 392 |
{ |
| 393 |
enum WritingSystemStatus { |
| 394 |
Unknown = 0, |
| 395 |
Supported = 1, |
| 396 |
UnsupportedFT = 2, |
| 397 |
UnsupportedXLFD = 4, |
| 398 |
Unsupported = UnsupportedFT | UnsupportedXLFD |
| 399 |
}; |
| 400 |
|
| 401 |
QtFontFamily(const QString &n) |
| 402 |
: |
| 403 |
#ifdef Q_WS_X11 |
| 404 |
fixedPitch(true), ftWritingSystemCheck(false), |
| 405 |
xlfdLoaded(false), synthetic(false), symbol_checked(false), |
| 406 |
#else |
| 407 |
fixedPitch(false), |
| 408 |
#endif |
| 409 |
#ifdef Q_WS_WIN |
| 410 |
writingSystemCheck(false), |
| 411 |
loaded(false), |
| 412 |
#endif |
| 413 |
#if !defined(QWS) && defined(Q_OS_MAC) |
| 414 |
fixedPitchComputed(false), |
| 415 |
#endif |
| 416 |
name(n), count(0), foundries(0) |
| 417 |
#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) |
| 418 |
, bogusWritingSystems(false) |
| 419 |
#endif |
| 420 |
#if defined(Q_WS_QPA) |
| 421 |
, askedForFallback(false) |
| 422 |
#endif |
| 423 |
{ |
| 424 |
memset(writingSystems, 0, sizeof(writingSystems)); |
| 425 |
} |
| 426 |
~QtFontFamily() { |
| 427 |
while (count--) |
| 428 |
delete foundries[count]; |
| 429 |
free(foundries); |
| 430 |
} |
| 431 |
|
| 432 |
bool fixedPitch : 1; |
| 433 |
#ifdef Q_WS_X11 |
| 434 |
bool ftWritingSystemCheck : 1; |
| 435 |
bool xlfdLoaded : 1; |
| 436 |
bool synthetic : 1; |
| 437 |
#endif |
| 438 |
#ifdef Q_WS_WIN |
| 439 |
bool writingSystemCheck : 1; |
| 440 |
bool loaded : 1; |
| 441 |
#endif |
| 442 |
#if !defined(QWS) && defined(Q_OS_MAC) |
| 443 |
bool fixedPitchComputed : 1; |
| 444 |
#endif |
| 445 |
#ifdef Q_WS_X11 |
| 446 |
bool symbol_checked : 1; |
| 447 |
#endif |
| 448 |
|
| 449 |
QString name; |
| 450 |
#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) |
| 451 |
QByteArray fontFilename; |
| 452 |
int fontFileIndex; |
| 453 |
#endif |
| 454 |
#ifdef Q_WS_WIN |
| 455 |
QString english_name; |
| 456 |
#endif |
| 457 |
int count; |
| 458 |
QtFontFoundry **foundries; |
| 459 |
|
| 460 |
#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) |
| 461 |
bool bogusWritingSystems; |
| 462 |
QStringList fallbackFamilies; |
| 463 |
#endif |
| 464 |
#if defined (Q_WS_QPA) |
| 465 |
bool askedForFallback; |
| 466 |
#endif |
| 467 |
unsigned char writingSystems[QFontDatabase::WritingSystemsCount]; |
| 468 |
|
| 469 |
QtFontFoundry *foundry(const QString &f, bool = false); |
| 470 |
}; |
| 471 |
|
| 472 |
#if !defined(QWS) && defined(Q_OS_MAC) |
| 473 |
inline static void qt_mac_get_fixed_pitch(QtFontFamily *f) |
| 474 |
{ |
| 475 |
if(f && !f->fixedPitchComputed) { |
| 476 |
QFontMetrics fm(f->name); |
| 477 |
f->fixedPitch = fm.width(QLatin1Char('i')) == fm.width(QLatin1Char('m')); |
| 478 |
f->fixedPitchComputed = true; |
| 479 |
} |
| 480 |
} |
| 481 |
#endif |
| 482 |
|
| 483 |
|
| 484 |
QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) |
| 485 |
{ |
| 486 |
if (f.isNull() && count == 1) |
| 487 |
return foundries[0]; |
| 488 |
|
| 489 |
for (int i = 0; i < count; i++) { |
| 490 |
if (foundries[i]->name.compare(f, Qt::CaseInsensitive) == 0) |
| 491 |
return foundries[i]; |
| 492 |
} |
| 493 |
if (!create) |
| 494 |
return 0; |
| 495 |
|
| 496 |
if (!(count % 8)) { |
| 497 |
QtFontFoundry **newFoundries = (QtFontFoundry **) |
| 498 |
realloc(foundries, |
| 499 |
(((count+8) >> 3) << 3) * sizeof(QtFontFoundry *)); |
| 500 |
Q_CHECK_PTR(newFoundries); |
| 501 |
foundries = newFoundries; |
| 502 |
} |
| 503 |
|
| 504 |
foundries[count] = new QtFontFoundry(f); |
| 505 |
return foundries[count++]; |
| 506 |
} |
| 507 |
|
| 508 |
// ### copied to tools/makeqpf/qpf2.cpp |
| 509 |
|
| 510 |
// see the Unicode subset bitfields in the MSDN docs |
| 511 |
static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { |
| 512 |
// Any, |
| 513 |
{ 127, 127 }, |
| 514 |
// Latin, |
| 515 |
{ 0, 127 }, |
| 516 |
// Greek, |
| 517 |
{ 7, 127 }, |
| 518 |
// Cyrillic, |
| 519 |
{ 9, 127 }, |
| 520 |
// Armenian, |
| 521 |
{ 10, 127 }, |
| 522 |
// Hebrew, |
| 523 |
{ 11, 127 }, |
| 524 |
// Arabic, |
| 525 |
{ 13, 127 }, |
| 526 |
// Syriac, |
| 527 |
{ 71, 127 }, |
| 528 |
//Thaana, |
| 529 |
{ 72, 127 }, |
| 530 |
//Devanagari, |
| 531 |
{ 15, 127 }, |
| 532 |
//Bengali, |
| 533 |
{ 16, 127 }, |
| 534 |
//Gurmukhi, |
| 535 |
{ 17, 127 }, |
| 536 |
//Gujarati, |
| 537 |
{ 18, 127 }, |
| 538 |
//Oriya, |
| 539 |
{ 19, 127 }, |
| 540 |
//Tamil, |
| 541 |
{ 20, 127 }, |
| 542 |
//Telugu, |
| 543 |
{ 21, 127 }, |
| 544 |
//Kannada, |
| 545 |
{ 22, 127 }, |
| 546 |
//Malayalam, |
| 547 |
{ 23, 127 }, |
| 548 |
//Sinhala, |
| 549 |
{ 73, 127 }, |
| 550 |
//Thai, |
| 551 |
{ 24, 127 }, |
| 552 |
//Lao, |
| 553 |
{ 25, 127 }, |
| 554 |
//Tibetan, |
| 555 |
{ 70, 127 }, |
| 556 |
//Myanmar, |
| 557 |
{ 74, 127 }, |
| 558 |
// Georgian, |
| 559 |
{ 26, 127 }, |
| 560 |
// Khmer, |
| 561 |
{ 80, 127 }, |
| 562 |
// SimplifiedChinese, |
| 563 |
{ 126, 127 }, |
| 564 |
// TraditionalChinese, |
| 565 |
{ 126, 127 }, |
| 566 |
// Japanese, |
| 567 |
{ 126, 127 }, |
| 568 |
// Korean, |
| 569 |
{ 56, 127 }, |
| 570 |
// Vietnamese, |
| 571 |
{ 0, 127 }, // same as latin1 |
| 572 |
// Other, |
| 573 |
{ 126, 127 }, |
| 574 |
// Ogham, |
| 575 |
{ 78, 127 }, |
| 576 |
// Runic, |
| 577 |
{ 79, 127 }, |
| 578 |
// Nko, |
| 579 |
{ 14, 127 }, |
| 580 |
}; |
| 581 |
|
| 582 |
#define SimplifiedChineseCsbBit 18 |
| 583 |
#define TraditionalChineseCsbBit 20 |
| 584 |
#define JapaneseCsbBit 17 |
| 585 |
#define KoreanCsbBit 21 |
| 586 |
|
| 587 |
QList<QFontDatabase::WritingSystem> qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2]) |
| 588 |
{ |
| 589 |
QList<QFontDatabase::WritingSystem> writingSystems; |
| 590 |
bool hasScript = false; |
| 591 |
|
| 592 |
int i; |
| 593 |
for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) { |
| 594 |
int bit = requiredUnicodeBits[i][0]; |
| 595 |
int index = bit/32; |
| 596 |
int flag = 1 << (bit&31); |
| 597 |
if (bit != 126 && unicodeRange[index] & flag) { |
| 598 |
bit = requiredUnicodeBits[i][1]; |
| 599 |
index = bit/32; |
| 600 |
|
| 601 |
flag = 1 << (bit&31); |
| 602 |
if (bit == 127 || unicodeRange[index] & flag) { |
| 603 |
writingSystems.append(QFontDatabase::WritingSystem(i)); |
| 604 |
hasScript = true; |
| 605 |
// qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i); |
| 606 |
} |
| 607 |
} |
| 608 |
} |
| 609 |
if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) { |
| 610 |
writingSystems.append(QFontDatabase::SimplifiedChinese); |
| 611 |
hasScript = true; |
| 612 |
//qDebug("font %s supports Simplified Chinese", familyName.latin1()); |
| 613 |
} |
| 614 |
if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) { |
| 615 |
writingSystems.append(QFontDatabase::TraditionalChinese); |
| 616 |
hasScript = true; |
| 617 |
//qDebug("font %s supports Traditional Chinese", familyName.latin1()); |
| 618 |
} |
| 619 |
if(codePageRange[0] & (1 << JapaneseCsbBit)) { |
| 620 |
writingSystems.append(QFontDatabase::Japanese); |
| 621 |
hasScript = true; |
| 622 |
//qDebug("font %s supports Japanese", familyName.latin1()); |
| 623 |
} |
| 624 |
if(codePageRange[0] & (1 << KoreanCsbBit)) { |
| 625 |
writingSystems.append(QFontDatabase::Korean); |
| 626 |
hasScript = true; |
| 627 |
//qDebug("font %s supports Korean", familyName.latin1()); |
| 628 |
} |
| 629 |
if (!hasScript) |
| 630 |
writingSystems.append(QFontDatabase::Symbol); |
| 631 |
|
| 632 |
return writingSystems; |
| 633 |
} |
| 634 |
|
| 635 |
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) |
| 636 |
// class with virtual destructor, derived in qfontdatabase_s60.cpp |
| 637 |
class QSymbianFontDatabaseExtras |
| 638 |
{ |
| 639 |
public: |
| 640 |
virtual ~QSymbianFontDatabaseExtras() {} |
| 641 |
}; |
| 642 |
#endif |
| 643 |
|
| 644 |
class QFontDatabasePrivate |
| 645 |
{ |
| 646 |
public: |
| 647 |
QFontDatabasePrivate() |
| 648 |
: count(0), families(0), reregisterAppFonts(false) |
| 649 |
#if defined(Q_WS_QWS) |
| 650 |
, stream(0) |
| 651 |
#endif |
| 652 |
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) |
| 653 |
, symbianExtras(0) |
| 654 |
#endif |
| 655 |
#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECTWRITE) |
| 656 |
, directWriteFactory(0) |
| 657 |
, directWriteGdiInterop(0) |
| 658 |
#endif |
| 659 |
{ } |
| 660 |
|
| 661 |
~QFontDatabasePrivate() { |
| 662 |
free(); |
| 663 |
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) |
| 664 |
if (symbianExtras) |
| 665 |
delete symbianExtras; |
| 666 |
#endif |
| 667 |
#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECTWRITE) |
| 668 |
if (directWriteGdiInterop) |
| 669 |
directWriteGdiInterop->Release(); |
| 670 |
if (directWriteFactory != 0) |
| 671 |
directWriteFactory->Release(); |
| 672 |
#endif |
| 673 |
} |
| 674 |
QtFontFamily *family(const QString &f, bool = false); |
| 675 |
void free() { |
| 676 |
while (count--) |
| 677 |
delete families[count]; |
| 678 |
::free(families); |
| 679 |
families = 0; |
| 680 |
count = 0; |
| 681 |
// don't clear the memory fonts! |
| 682 |
} |
| 683 |
|
| 684 |
int count; |
| 685 |
#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG) |
| 686 |
QString systemLang; |
| 687 |
#endif |
| 688 |
QtFontFamily **families; |
| 689 |
|
| 690 |
#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECTWRITE) |
| 691 |
IDWriteFactory *directWriteFactory; |
| 692 |
IDWriteGdiInterop *directWriteGdiInterop; |
| 693 |
#endif |
| 694 |
|
| 695 |
|
| 696 |
struct ApplicationFont { |
| 697 |
QString fileName; |
| 698 |
QByteArray data; |
| 699 |
#if defined(Q_OS_WIN) |
| 700 |
HANDLE handle; |
| 701 |
bool memoryFont; |
| 702 |
QVector<FONTSIGNATURE> signatures; |
| 703 |
#elif defined(Q_WS_MAC) |
| 704 |
ATSFontContainerRef handle; |
| 705 |
#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) |
| 706 |
QString temporaryFileName; |
| 707 |
TInt screenDeviceFontFileId; |
| 708 |
TUid fontStoreFontFileUid; |
| 709 |
#endif |
| 710 |
QStringList families; |
| 711 |
}; |
| 712 |
QVector<ApplicationFont> applicationFonts; |
| 713 |
int addAppFont(const QByteArray &fontData, const QString &fileName); |
| 714 |
bool reregisterAppFonts; |
| 715 |
bool isApplicationFont(const QString &fileName); |
| 716 |
|
| 717 |
void invalidate(); |
| 718 |
|
| 719 |
#if defined(Q_WS_QWS) |
| 720 |
bool loadFromCache(const QString &fontPath); |
| 721 |
void addQPF2File(const QByteArray &file); |
| 722 |
#endif // Q_WS_QWS |
| 723 |
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) |
| 724 |
void addFont(const QString &familyname, const char *foundryname, int weight, |
| 725 |
bool italic, int pixelSize, const QByteArray &file, int fileIndex, |
| 726 |
bool antialiased, |
| 727 |
const QList<QFontDatabase::WritingSystem> &writingSystems = QList<QFontDatabase::WritingSystem>()); |
| 728 |
#ifndef QT_NO_FREETYPE |
| 729 |
QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray()); |
| 730 |
#endif // QT_NO_FREETYPE |
| 731 |
#endif |
| 732 |
#if defined(Q_WS_QWS) |
| 733 |
QDataStream *stream; |
| 734 |
#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) |
| 735 |
QSymbianFontDatabaseExtras *symbianExtras; |
| 736 |
#endif |
| 737 |
#if defined(Q_WS_QWS) || defined(Q_WS_QPA) |
| 738 |
QStringList fallbackFamilies; |
| 739 |
#endif |
| 740 |
}; |
| 741 |
|
| 742 |
void QFontDatabasePrivate::invalidate() |
| 743 |
{ |
| 744 |
QFontCache::instance()->clear(); |
| 745 |
free(); |
| 746 |
emit static_cast<QApplication *>(QApplication::instance())->fontDatabaseChanged(); |
| 747 |
} |
| 748 |
|
| 749 |
QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) |
| 750 |
{ |
| 751 |
int low = 0; |
| 752 |
int high = count; |
| 753 |
int pos = count / 2; |
| 754 |
int res = 1; |
| 755 |
if (count) { |
| 756 |
while ((res = families[pos]->name.compare(f, Qt::CaseInsensitive)) && pos != low) { |
| 757 |
if (res > 0) |
| 758 |
high = pos; |
| 759 |
else |
| 760 |
low = pos; |
| 761 |
pos = (high + low) / 2; |
| 762 |
} |
| 763 |
if (!res) |
| 764 |
return families[pos]; |
| 765 |
} |
| 766 |
if (!create) |
| 767 |
return 0; |
| 768 |
|
| 769 |
if (res < 0) |
| 770 |
pos++; |
| 771 |
|
| 772 |
// qDebug("adding family %s at %d total=%d", f.latin1(), pos, count); |
| 773 |
if (!(count % 8)) { |
| 774 |
QtFontFamily **newFamilies = (QtFontFamily **) |
| 775 |
realloc(families, |
| 776 |
(((count+8) >> 3) << 3) * sizeof(QtFontFamily *)); |
| 777 |
Q_CHECK_PTR(newFamilies); |
| 778 |
families = newFamilies; |
| 779 |
} |
| 780 |
|
| 781 |
QtFontFamily *family = new QtFontFamily(f); |
| 782 |
memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *)); |
| 783 |
families[pos] = family; |
| 784 |
count++; |
| 785 |
return families[pos]; |
| 786 |
} |
| 787 |
|
| 788 |
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) |
| 789 |
void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, |
| 790 |
const QByteArray &file, int fileIndex, bool antialiased, |
| 791 |
const QList<QFontDatabase::WritingSystem> &writingSystems) |
| 792 |
{ |
| 793 |
// qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased; |
| 794 |
QtFontStyle::Key styleKey; |
| 795 |
styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal; |
| 796 |
styleKey.weight = weight; |
| 797 |
styleKey.stretch = 100; |
| 798 |
QtFontFamily *f = family(familyname, true); |
| 799 |
|
| 800 |
if (writingSystems.isEmpty()) { |
| 801 |
for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { |
| 802 |
f->writingSystems[ws] = QtFontFamily::Supported; |
| 803 |
} |
| 804 |
f->bogusWritingSystems = true; |
| 805 |
} else { |
| 806 |
for (int i = 0; i < writingSystems.count(); ++i) { |
| 807 |
f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported; |
| 808 |
} |
| 809 |
} |
| 810 |
|
| 811 |
QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true); |
| 812 |
QtFontStyle *style = foundry->style(styleKey, QString(), true); |
| 813 |
style->smoothScalable = (pixelSize == 0); |
| 814 |
style->antialiased = antialiased; |
| 815 |
QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); |
| 816 |
size->fileName = file; |
| 817 |
size->fileIndex = fileIndex; |
| 818 |
|
| 819 |
#if defined(Q_WS_QWS) |
| 820 |
if (stream) { |
| 821 |
*stream << familyname << foundry->name << weight << quint8(italic) << pixelSize |
| 822 |
<< file << fileIndex << quint8(antialiased); |
| 823 |
*stream << quint8(writingSystems.count()); |
| 824 |
for (int i = 0; i < writingSystems.count(); ++i) |
| 825 |
*stream << quint8(writingSystems.at(i)); |
| 826 |
} |
| 827 |
#else // ..in case of defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) |
| 828 |
f->fontFilename = file; |
| 829 |
f->fontFileIndex = fileIndex; |
| 830 |
#endif |
| 831 |
} |
| 832 |
#endif |
| 833 |
|
| 834 |
#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) |
| 835 |
QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData) |
| 836 |
{ |
| 837 |
QStringList families; |
| 838 |
extern FT_Library qt_getFreetype(); |
| 839 |
FT_Library library = qt_getFreetype(); |
| 840 |
|
| 841 |
int index = 0; |
| 842 |
int numFaces = 0; |
| 843 |
do { |
| 844 |
FT_Face face; |
| 845 |
FT_Error error; |
| 846 |
if (!fontData.isEmpty()) { |
| 847 |
error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face); |
| 848 |
} else { |
| 849 |
error = FT_New_Face(library, file, index, &face); |
| 850 |
} |
| 851 |
if (error != FT_Err_Ok) { |
| 852 |
qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error; |
| 853 |
break; |
| 854 |
} |
| 855 |
numFaces = face->num_faces; |
| 856 |
|
| 857 |
int weight = QFont::Normal; |
| 858 |
bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC; |
| 859 |
|
| 860 |
if (face->style_flags & FT_STYLE_FLAG_BOLD) |
| 861 |
weight = QFont::Bold; |
| 862 |
|
| 863 |
QList<QFontDatabase::WritingSystem> writingSystems; |
| 864 |
// detect symbol fonts |
| 865 |
for (int i = 0; i < face->num_charmaps; ++i) { |
| 866 |
FT_CharMap cm = face->charmaps[i]; |
| 867 |
if (cm->encoding == ft_encoding_adobe_custom |
| 868 |
|| cm->encoding == ft_encoding_symbol) { |
| 869 |
writingSystems.append(QFontDatabase::Symbol); |
| 870 |
break; |
| 871 |
} |
| 872 |
} |
| 873 |
if (writingSystems.isEmpty()) { |
| 874 |
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); |
| 875 |
if (os2) { |
| 876 |
quint32 unicodeRange[4] = { |
| 877 |
static_cast<quint32>(os2->ulUnicodeRange1), static_cast<quint32>(os2->ulUnicodeRange2), static_cast<quint32>(os2->ulUnicodeRange3), static_cast<quint32>(os2->ulUnicodeRange4) |
| 878 |
}; |
| 879 |
quint32 codePageRange[2] = { |
| 880 |
static_cast<quint32>(os2->ulCodePageRange1), static_cast<quint32>(os2->ulCodePageRange2) |
| 881 |
}; |
| 882 |
|
| 883 |
writingSystems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange); |
| 884 |
//for (int i = 0; i < writingSystems.count(); ++i) |
| 885 |
// qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i)); |
| 886 |
} |
| 887 |
} |
| 888 |
|
| 889 |
QString family = QString::fromAscii(face->family_name); |
| 890 |
families.append(family); |
| 891 |
addFont(family, /*foundry*/ "", weight, italic, |
| 892 |
/*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems); |
| 893 |
|
| 894 |
FT_Done_Face(face); |
| 895 |
++index; |
| 896 |
} while (index < numFaces); |
| 897 |
return families; |
| 898 |
} |
| 899 |
#endif |
| 900 |
|
| 901 |
static const int scriptForWritingSystem[] = { |
| 902 |
QUnicodeTables::Common, // Any |
| 903 |
QUnicodeTables::Latin, // Latin |
| 904 |
QUnicodeTables::Greek, // Greek |
| 905 |
QUnicodeTables::Cyrillic, // Cyrillic |
| 906 |
QUnicodeTables::Armenian, // Armenian |
| 907 |
QUnicodeTables::Hebrew, // Hebrew |
| 908 |
QUnicodeTables::Arabic, // Arabic |
| 909 |
QUnicodeTables::Syriac, // Syriac |
| 910 |
QUnicodeTables::Thaana, // Thaana |
| 911 |
QUnicodeTables::Devanagari, // Devanagari |
| 912 |
QUnicodeTables::Bengali, // Bengali |
| 913 |
QUnicodeTables::Gurmukhi, // Gurmukhi |
| 914 |
QUnicodeTables::Gujarati, // Gujarati |
| 915 |
QUnicodeTables::Oriya, // Oriya |
| 916 |
QUnicodeTables::Tamil, // Tamil |
| 917 |
QUnicodeTables::Telugu, // Telugu |
| 918 |
QUnicodeTables::Kannada, // Kannada |
| 919 |
QUnicodeTables::Malayalam, // Malayalam |
| 920 |
QUnicodeTables::Sinhala, // Sinhala |
| 921 |
QUnicodeTables::Thai, // Thai |
| 922 |
QUnicodeTables::Lao, // Lao |
| 923 |
QUnicodeTables::Tibetan, // Tibetan |
| 924 |
QUnicodeTables::Myanmar, // Myanmar |
| 925 |
QUnicodeTables::Georgian, // Georgian |
| 926 |
QUnicodeTables::Khmer, // Khmer |
| 927 |
QUnicodeTables::Common, // SimplifiedChinese |
| 928 |
QUnicodeTables::Common, // TraditionalChinese |
| 929 |
QUnicodeTables::Common, // Japanese |
| 930 |
QUnicodeTables::Hangul, // Korean |
| 931 |
QUnicodeTables::Common, // Vietnamese |
| 932 |
QUnicodeTables::Common, // Yi |
| 933 |
QUnicodeTables::Common, // Tagalog |
| 934 |
QUnicodeTables::Common, // Hanunoo |
| 935 |
QUnicodeTables::Common, // Buhid |
| 936 |
QUnicodeTables::Common, // Tagbanwa |
| 937 |
QUnicodeTables::Common, // Limbu |
| 938 |
QUnicodeTables::Common, // TaiLe |
| 939 |
QUnicodeTables::Common, // Braille |
| 940 |
QUnicodeTables::Common, // Symbol |
| 941 |
QUnicodeTables::Ogham, // Ogham |
| 942 |
QUnicodeTables::Runic, // Runic |
| 943 |
QUnicodeTables::Nko // Nko |
| 944 |
}; |
| 945 |
|
| 946 |
int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem) |
| 947 |
{ |
| 948 |
return scriptForWritingSystem[writingSystem]; |
| 949 |
} |
| 950 |
|
| 951 |
|
| 952 |
#if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN) |
| 953 |
static inline bool requiresOpenType(int writingSystem) |
| 954 |
{ |
| 955 |
return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) |
| 956 |
|| writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); |
| 957 |
} |
| 958 |
static inline bool scriptRequiresOpenType(int script) |
| 959 |
{ |
| 960 |
return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) |
| 961 |
|| script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); |
| 962 |
} |
| 963 |
#endif |
| 964 |
|
| 965 |
|
| 966 |
/*! |
| 967 |
\internal |
| 968 |
|
| 969 |
This makes sense of the font family name: |
| 970 |
|
| 971 |
if the family name contains a '[' and a ']', then we take the text |
| 972 |
between the square brackets as the foundry, and the text before the |
| 973 |
square brackets as the family (ie. "Arial [Monotype]") |
| 974 |
*/ |
| 975 |
static void parseFontName(const QString &name, QString &foundry, QString &family) |
| 976 |
{ |
| 977 |
int i = name.indexOf(QLatin1Char('[')); |
| 978 |
int li = name.lastIndexOf(QLatin1Char(']')); |
| 979 |
if (i >= 0 && li >= 0 && i < li) { |
| 980 |
foundry = name.mid(i + 1, li - i - 1); |
| 981 |
if (i > 0 && name[i - 1] == QLatin1Char(' ')) |
| 982 |
i--; |
| 983 |
family = name.left(i); |
| 984 |
} else { |
| 985 |
foundry.clear(); |
| 986 |
family = name; |
| 987 |
} |
| 988 |
|
| 989 |
// capitalize the family/foundry names |
| 990 |
bool space = true; |
| 991 |
QChar *s = family.data(); |
| 992 |
int len = family.length(); |
| 993 |
while(len--) { |
| 994 |
if (space) *s = s->toUpper(); |
| 995 |
space = s->isSpace(); |
| 996 |
++s; |
| 997 |
} |
| 998 |
|
| 999 |
space = true; |
| 1000 |
s = foundry.data(); |
| 1001 |
len = foundry.length(); |
| 1002 |
while(len--) { |
| 1003 |
if (space) *s = s->toUpper(); |
| 1004 |
space = s->isSpace(); |
| 1005 |
++s; |
| 1006 |
} |
| 1007 |
} |
| 1008 |
|
| 1009 |
|
| 1010 |
struct QtFontDesc |
| 1011 |
{ |
| 1012 |
inline QtFontDesc() : family(0), foundry(0), style(0), size(0), encoding(0), familyIndex(-1) {} |
| 1013 |
QtFontFamily *family; |
| 1014 |
QtFontFoundry *foundry; |
| 1015 |
QtFontStyle *style; |
| 1016 |
QtFontSize *size; |
| 1017 |
QtFontEncoding *encoding; |
| 1018 |
int familyIndex; |
| 1019 |
}; |
| 1020 |
|
| 1021 |
#if !defined(Q_WS_MAC) |
| 1022 |
static void match(int script, const QFontDef &request, |
| 1023 |
const QString &family_name, const QString &foundry_name, int force_encoding_id, |
| 1024 |
QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>(), bool forceXLFD=false); |
| 1025 |
|
| 1026 |
#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) |
| 1027 |
static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef) |
| 1028 |
{ |
| 1029 |
fontDef->family = desc.family->name; |
| 1030 |
if (! desc.foundry->name.isEmpty() && desc.family->count > 1) { |
| 1031 |
fontDef->family += QString::fromLatin1(" ["); |
| 1032 |
fontDef->family += desc.foundry->name; |
| 1033 |
fontDef->family += QLatin1Char(']'); |
| 1034 |
} |
| 1035 |
|
| 1036 |
if (desc.style->smoothScalable) |
| 1037 |
fontDef->pixelSize = request.pixelSize; |
| 1038 |
else if ((desc.style->bitmapScalable && (request.styleStrategy & QFont::PreferMatch))) |
| 1039 |
fontDef->pixelSize = request.pixelSize; |
| 1040 |
else |
| 1041 |
fontDef->pixelSize = desc.size->pixelSize; |
| 1042 |
|
| 1043 |
fontDef->styleHint = request.styleHint; |
| 1044 |
fontDef->styleStrategy = request.styleStrategy; |
| 1045 |
|
| 1046 |
fontDef->weight = desc.style->key.weight; |
| 1047 |
fontDef->style = desc.style->key.style; |
| 1048 |
fontDef->fixedPitch = desc.family->fixedPitch; |
| 1049 |
fontDef->stretch = desc.style->key.stretch; |
| 1050 |
fontDef->ignorePitch = false; |
| 1051 |
} |
| 1052 |
#endif |
| 1053 |
#endif |
| 1054 |
|
| 1055 |
#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || defined(Q_WS_QPA) |
| 1056 |
static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key) |
| 1057 |
{ |
| 1058 |
// look for the requested font in the engine data cache |
| 1059 |
d->engineData = QFontCache::instance()->findEngineData(key); |
| 1060 |
if (!d->engineData) { |
| 1061 |
// create a new one |
| 1062 |
d->engineData = new QFontEngineData; |
| 1063 |
QFontCache::instance()->insertEngineData(key, d->engineData); |
| 1064 |
} else { |
| 1065 |
d->engineData->ref.ref(); |
| 1066 |
} |
| 1067 |
} |
| 1068 |
#endif |
| 1069 |
|
| 1070 |
static QStringList familyList(const QFontDef &req) |
| 1071 |
{ |
| 1072 |
// list of families to try |
| 1073 |
QStringList family_list; |
| 1074 |
if (req.family.isEmpty()) |
| 1075 |
return family_list; |
| 1076 |
|
| 1077 |
QStringList list = req.family.split(QLatin1Char(',')); |
| 1078 |
for (int i = 0; i < list.size(); ++i) { |
| 1079 |
QString str = list.at(i).trimmed(); |
| 1080 |
if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"'))) |
| 1081 |
|| (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\'')))) |
| 1082 |
str = str.mid(1, str.length() - 2); |
| 1083 |
family_list << str; |
| 1084 |
} |
| 1085 |
|
| 1086 |
// append the substitute list for each family in family_list |
| 1087 |
QStringList subs_list; |
| 1088 |
QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd(); |
| 1089 |
for (; it != end; ++it) |
| 1090 |
subs_list += QFont::substitutes(*it); |
| 1091 |
// qDebug() << "adding substs: " << subs_list; |
| 1092 |
|
| 1093 |
family_list += subs_list; |
| 1094 |
|
| 1095 |
return family_list; |
| 1096 |
} |
| 1097 |
|
| 1098 |
Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb) |
| 1099 |
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive)) |
| 1100 |
|
| 1101 |
// used in qfontengine_x11.cpp |
| 1102 |
QMutex *qt_fontdatabase_mutex() |
| 1103 |
{ |
| 1104 |
return fontDatabaseMutex(); |
| 1105 |
} |
| 1106 |
|
| 1107 |
QT_BEGIN_INCLUDE_NAMESPACE |
| 1108 |
#if defined(Q_WS_X11) |
| 1109 |
# include "qfontdatabase_x11.cpp" |
| 1110 |
#elif defined(Q_WS_MAC) |
| 1111 |
# include "qfontdatabase_mac.cpp" |
| 1112 |
#elif defined(Q_WS_WIN) |
| 1113 |
# include "qfontdatabase_win.cpp" |
| 1114 |
#elif defined(Q_WS_QWS) |
| 1115 |
# include "qfontdatabase_qws.cpp" |
| 1116 |
#elif defined(Q_WS_QPA) |
| 1117 |
# include "qfontdatabase_qpa.cpp" |
| 1118 |
#elif defined(Q_OS_SYMBIAN) |
| 1119 |
# include "qfontdatabase_s60.cpp" |
| 1120 |
#endif |
| 1121 |
QT_END_INCLUDE_NAMESPACE |
| 1122 |
|
| 1123 |
#if !defined(Q_WS_X11) && !defined(Q_WS_MAC) |
| 1124 |
QString QFontDatabase::resolveFontFamilyAlias(const QString &family) |
| 1125 |
{ |
| 1126 |
return family; |
| 1127 |
} |
| 1128 |
#endif |
| 1129 |
|
| 1130 |
static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey, |
| 1131 |
const QString &styleName = QString()) |
| 1132 |
{ |
| 1133 |
int best = 0; |
| 1134 |
int dist = 0xffff; |
| 1135 |
|
| 1136 |
for ( int i = 0; i < foundry->count; i++ ) { |
| 1137 |
QtFontStyle *style = foundry->styles[i]; |
| 1138 |
|
| 1139 |
if (!styleName.isEmpty() && styleName == style->styleName) { |
| 1140 |
dist = 0; |
| 1141 |
best = i; |
| 1142 |
break; |
| 1143 |
} |
| 1144 |
|
| 1145 |
int d = qAbs( styleKey.weight - style->key.weight ); |
| 1146 |
|
| 1147 |
if ( styleKey.stretch != 0 && style->key.stretch != 0 ) { |
| 1148 |
d += qAbs( styleKey.stretch - style->key.stretch ); |
| 1149 |
} |
| 1150 |
|
| 1151 |
if (styleKey.style != style->key.style) { |
| 1152 |
if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal) |
| 1153 |
// one is italic, the other oblique |
| 1154 |
d += 0x0001; |
| 1155 |
else |
| 1156 |
d += 0x1000; |
| 1157 |
} |
| 1158 |
|
| 1159 |
if ( d < dist ) { |
| 1160 |
best = i; |
| 1161 |
dist = d; |
| 1162 |
} |
| 1163 |
} |
| 1164 |
|
| 1165 |
FM_DEBUG( " best style has distance 0x%x", dist ); |
| 1166 |
return foundry->styles[best]; |
| 1167 |
} |
| 1168 |
|
| 1169 |
#if defined(Q_WS_X11) |
| 1170 |
static QtFontEncoding *findEncoding(int script, int styleStrategy, |
| 1171 |
QtFontSize *size, int force_encoding_id) |
| 1172 |
{ |
| 1173 |
QtFontEncoding *encoding = 0; |
| 1174 |
|
| 1175 |
if (force_encoding_id >= 0) { |
| 1176 |
encoding = size->encodingID(force_encoding_id); |
| 1177 |
if (!encoding) |
| 1178 |
FM_DEBUG(" required encoding_id not available"); |
| 1179 |
return encoding; |
| 1180 |
} |
| 1181 |
|
| 1182 |
if (styleStrategy & (QFont::OpenGLCompatible | QFont::PreferBitmap)) { |
| 1183 |
FM_DEBUG(" PreferBitmap and/or OpenGL set, skipping Freetype"); |
| 1184 |
} else { |
| 1185 |
encoding = size->encodingID(-1); // -1 == prefer Freetype |
| 1186 |
if (encoding) |
| 1187 |
return encoding; |
| 1188 |
} |
| 1189 |
|
| 1190 |
// FT not available, find an XLFD font, trying the default encoding first |
| 1191 |
encoding = size->encodingID(QFontPrivate::defaultEncodingID); |
| 1192 |
if (encoding) { |
| 1193 |
// does it support the requested script? |
| 1194 |
bool supportsScript = false; |
| 1195 |
for (int ws = 1; !supportsScript && ws < QFontDatabase::WritingSystemsCount; ++ws) { |
| 1196 |
if (scriptForWritingSystem[ws] != script) |
| 1197 |
continue; |
| 1198 |
supportsScript = writingSystems_for_xlfd_encoding[encoding->encoding][ws]; |
| 1199 |
} |
| 1200 |
if (!supportsScript) |
| 1201 |
encoding = 0; |
| 1202 |
} |
| 1203 |
// find the first encoding that supports the requested script |
| 1204 |
for (int ws = 1; !encoding && ws < QFontDatabase::WritingSystemsCount; ++ws) { |
| 1205 |
if (scriptForWritingSystem[ws] != script) |
| 1206 |
continue; |
| 1207 |
for (int x = 0; !encoding && x < size->count; ++x) { |
| 1208 |
const int enc = size->encodings[x].encoding; |
| 1209 |
if (writingSystems_for_xlfd_encoding[enc][ws]) |
| 1210 |
encoding = size->encodings + x; |
| 1211 |
} |
| 1212 |
} |
| 1213 |
|
| 1214 |
return encoding; |
| 1215 |
} |
| 1216 |
#endif // Q_WS_X11 |
| 1217 |
|
| 1218 |
#if !defined(Q_WS_MAC) |
| 1219 |
static |
| 1220 |
unsigned int bestFoundry(int script, unsigned int score, int styleStrategy, |
| 1221 |
const QtFontFamily *family, const QString &foundry_name, |
| 1222 |
QtFontStyle::Key styleKey, int pixelSize, char pitch, |
| 1223 |
QtFontDesc *desc, int force_encoding_id) |
| 1224 |
{ |
| 1225 |
Q_UNUSED(force_encoding_id); |
| 1226 |
Q_UNUSED(script); |
| 1227 |
Q_UNUSED(pitch); |
| 1228 |
|
| 1229 |
desc->foundry = 0; |
| 1230 |
desc->style = 0; |
| 1231 |
desc->size = 0; |
| 1232 |
desc->encoding = 0; |
| 1233 |
|
| 1234 |
|
| 1235 |
FM_DEBUG(" REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count); |
| 1236 |
|
| 1237 |
for (int x = 0; x < family->count; ++x) { |
| 1238 |
QtFontFoundry *foundry = family->foundries[x]; |
| 1239 |
if (!foundry_name.isEmpty() && foundry->name.compare(foundry_name, Qt::CaseInsensitive) != 0) |
| 1240 |
continue; |
| 1241 |
|
| 1242 |
FM_DEBUG(" looking for matching style in foundry '%s' %d", |
| 1243 |
foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count); |
| 1244 |
|
| 1245 |
QtFontStyle *style = bestStyle(foundry, styleKey); |
| 1246 |
|
| 1247 |
if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) { |
| 1248 |
FM_DEBUG(" ForceOutline set, but not smoothly scalable"); |
| 1249 |
continue; |
| 1250 |
} |
| 1251 |
|
| 1252 |
int px = -1; |
| 1253 |
QtFontSize *size = 0; |
| 1254 |
|
| 1255 |
// 1. see if we have an exact matching size |
| 1256 |
if (!(styleStrategy & QFont::ForceOutline)) { |
| 1257 |
size = style->pixelSize(pixelSize); |
| 1258 |
if (size) { |
| 1259 |
FM_DEBUG(" found exact size match (%d pixels)", size->pixelSize); |
| 1260 |
px = size->pixelSize; |
| 1261 |
} |
| 1262 |
} |
| 1263 |
|
| 1264 |
// 2. see if we have a smoothly scalable font |
| 1265 |
if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) { |
| 1266 |
size = style->pixelSize(SMOOTH_SCALABLE); |
| 1267 |
if (size) { |
| 1268 |
FM_DEBUG(" found smoothly scalable font (%d pixels)", pixelSize); |
| 1269 |
px = pixelSize; |
| 1270 |
} |
| 1271 |
} |
| 1272 |
|
| 1273 |
// 3. see if we have a bitmap scalable font |
| 1274 |
if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) { |
| 1275 |
size = style->pixelSize(0); |
| 1276 |
if (size) { |
| 1277 |
FM_DEBUG(" found bitmap scalable font (%d pixels)", pixelSize); |
| 1278 |
px = pixelSize; |
| 1279 |
} |
| 1280 |
} |
| 1281 |
|
| 1282 |
#ifdef Q_WS_X11 |
| 1283 |
QtFontEncoding *encoding = 0; |
| 1284 |
#endif |
| 1285 |
|
| 1286 |
// 4. find closest size match |
| 1287 |
if (! size) { |
| 1288 |
unsigned int distance = ~0u; |
| 1289 |
for (int x = 0; x < style->count; ++x) { |
| 1290 |
#ifdef Q_WS_X11 |
| 1291 |
encoding = |
| 1292 |
findEncoding(script, styleStrategy, style->pixelSizes + x, force_encoding_id); |
| 1293 |
if (!encoding) { |
| 1294 |
FM_DEBUG(" size %3d does not support the script we want", |
| 1295 |
style->pixelSizes[x].pixelSize); |
| 1296 |
continue; |
| 1297 |
} |
| 1298 |
#endif |
| 1299 |
|
| 1300 |
unsigned int d; |
| 1301 |
if (style->pixelSizes[x].pixelSize < pixelSize) { |
| 1302 |
// penalize sizes that are smaller than the |
| 1303 |
// requested size, due to truncation from floating |
| 1304 |
// point to integer conversions |
| 1305 |
d = pixelSize - style->pixelSizes[x].pixelSize + 1; |
| 1306 |
} else { |
| 1307 |
d = style->pixelSizes[x].pixelSize - pixelSize; |
| 1308 |
} |
| 1309 |
|
| 1310 |
if (d < distance) { |
| 1311 |
distance = d; |
| 1312 |
size = style->pixelSizes + x; |
| 1313 |
FM_DEBUG(" best size so far: %3d (%d)", size->pixelSize, pixelSize); |
| 1314 |
} |
| 1315 |
} |
| 1316 |
|
| 1317 |
if (!size) { |
| 1318 |
FM_DEBUG(" no size supports the script we want"); |
| 1319 |
continue; |
| 1320 |
} |
| 1321 |
|
| 1322 |
if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) && |
| 1323 |
(distance * 10 / pixelSize) >= 2) { |
| 1324 |
// the closest size is not close enough, go ahead and |
| 1325 |
// use a bitmap scaled font |
| 1326 |
size = style->pixelSize(0); |
| 1327 |
px = pixelSize; |
| 1328 |
} else { |
| 1329 |
px = size->pixelSize; |
| 1330 |
} |
| 1331 |
} |
| 1332 |
|
| 1333 |
#ifdef Q_WS_X11 |
| 1334 |
if (size) { |
| 1335 |
encoding = findEncoding(script, styleStrategy, size, force_encoding_id); |
| 1336 |
if (!encoding) size = 0; |
| 1337 |
} |
| 1338 |
if (! encoding) { |
| 1339 |
FM_DEBUG(" foundry doesn't support the script we want"); |
| 1340 |
continue; |
| 1341 |
} |
| 1342 |
#endif // Q_WS_X11 |
| 1343 |
|
| 1344 |
unsigned int this_score = 0x0000; |
| 1345 |
enum { |
| 1346 |
PitchMismatch = 0x4000, |
| 1347 |
StyleMismatch = 0x2000, |
| 1348 |
BitmapScaledPenalty = 0x1000, |
| 1349 |
EncodingMismatch = 0x0002, |
| 1350 |
XLFDPenalty = 0x0001 |
| 1351 |
}; |
| 1352 |
#ifdef Q_WS_X11 |
| 1353 |
if (encoding->encoding != -1) { |
| 1354 |
this_score += XLFDPenalty; |
| 1355 |
if (encoding->encoding != QFontPrivate::defaultEncodingID) |
| 1356 |
this_score += EncodingMismatch; |
| 1357 |
} |
| 1358 |
if (pitch != '*') { |
| 1359 |
if (!(pitch == 'm' && encoding->pitch == 'c') && pitch != encoding->pitch) |
| 1360 |
this_score += PitchMismatch; |
| 1361 |
} |
| 1362 |
#else |
| 1363 |
if (pitch != '*') { |
| 1364 |
#if !defined(QWS) && defined(Q_OS_MAC) |
| 1365 |
qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family)); |
| 1366 |
#endif |
| 1367 |
if ((pitch == 'm' && !family->fixedPitch) |
| 1368 |
|| (pitch == 'p' && family->fixedPitch)) |
| 1369 |
this_score += PitchMismatch; |
| 1370 |
} |
| 1371 |
#endif |
| 1372 |
if (styleKey != style->key) |
| 1373 |
this_score += StyleMismatch; |
| 1374 |
if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled |
| 1375 |
this_score += BitmapScaledPenalty; |
| 1376 |
if (px != pixelSize) // close, but not exact, size match |
| 1377 |
this_score += qAbs(px - pixelSize); |
| 1378 |
|
| 1379 |
if (this_score < score) { |
| 1380 |
FM_DEBUG(" found a match: score %x best score so far %x", |
| 1381 |
this_score, score); |
| 1382 |
|
| 1383 |
score = this_score; |
| 1384 |
desc->foundry = foundry; |
| 1385 |
desc->style = style; |
| 1386 |
desc->size = size; |
| 1387 |
#ifdef Q_WS_X11 |
| 1388 |
desc->encoding = encoding; |
| 1389 |
#endif // Q_WS_X11 |
| 1390 |
} else { |
| 1391 |
FM_DEBUG(" score %x no better than best %x", this_score, score); |
| 1392 |
} |
| 1393 |
} |
| 1394 |
|
| 1395 |
return score; |
| 1396 |
} |
| 1397 |
#endif |
| 1398 |
|
| 1399 |
#if !defined(Q_WS_MAC) |
| 1400 |
/*! |
| 1401 |
\internal |
| 1402 |
|
| 1403 |
Tries to find the best match for a given request and family/foundry |
| 1404 |
*/ |
| 1405 |
static void match(int script, const QFontDef &request, |
| 1406 |
const QString &family_name, const QString &foundry_name, int force_encoding_id, |
| 1407 |
QtFontDesc *desc, const QList<int> &blacklistedFamilies, bool forceXLFD) |
| 1408 |
{ |
| 1409 |
Q_UNUSED(force_encoding_id); |
| 1410 |
|
| 1411 |
QtFontStyle::Key styleKey; |
| 1412 |
styleKey.style = request.style; |
| 1413 |
styleKey.weight = request.weight; |
| 1414 |
styleKey.stretch = request.stretch; |
| 1415 |
char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p'; |
| 1416 |
|
| 1417 |
|
| 1418 |
FM_DEBUG("QFontDatabase::match\n" |
| 1419 |
" request:\n" |
| 1420 |
" family: %s [%s], script: %d\n" |
| 1421 |
" weight: %d, style: %d\n" |
| 1422 |
" stretch: %d\n" |
| 1423 |
" pixelSize: %g\n" |
| 1424 |
" pitch: %c", |
| 1425 |
family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(), |
| 1426 |
foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(), |
| 1427 |
script, request.weight, request.style, request.stretch, request.pixelSize, pitch); |
| 1428 |
#if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11) |
| 1429 |
if (force_encoding_id >= 0) { |
| 1430 |
FM_DEBUG(" required encoding: %d", force_encoding_id); |
| 1431 |
} |
| 1432 |
#endif |
| 1433 |
|
| 1434 |
desc->family = 0; |
| 1435 |
desc->foundry = 0; |
| 1436 |
desc->style = 0; |
| 1437 |
desc->size = 0; |
| 1438 |
desc->encoding = 0; |
| 1439 |
desc->familyIndex = -1; |
| 1440 |
|
| 1441 |
unsigned int score = ~0u; |
| 1442 |
|
| 1443 |
#ifdef Q_WS_X11 |
| 1444 |
load(family_name, script, forceXLFD); |
| 1445 |
#else |
| 1446 |
Q_UNUSED(forceXLFD); |
| 1447 |
load(family_name, script); |
| 1448 |
#endif |
| 1449 |
|
| 1450 |
QFontDatabasePrivate *db = privateDb(); |
| 1451 |
for (int x = 0; x < db->count; ++x) { |
| 1452 |
if (blacklistedFamilies.contains(x)) |
| 1453 |
continue; |
| 1454 |
QtFontDesc test; |
| 1455 |
test.family = db->families[x]; |
| 1456 |
test.familyIndex = x; |
| 1457 |
|
| 1458 |
if (!family_name.isEmpty() |
| 1459 |
&& test.family->name.compare(family_name, Qt::CaseInsensitive) != 0 |
| 1460 |
#ifdef Q_WS_WIN |
| 1461 |
&& test.family->english_name.compare(family_name, Qt::CaseInsensitive) != 0 |
| 1462 |
#endif |
| 1463 |
) |
| 1464 |
continue; |
| 1465 |
|
| 1466 |
if (family_name.isEmpty()) |
| 1467 |
load(test.family->name, script); |
| 1468 |
|
| 1469 |
uint score_adjust = 0; |
| 1470 |
|
| 1471 |
bool supported = (script == QUnicodeTables::Common); |
| 1472 |
for (int ws = 1; !supported && ws < QFontDatabase::WritingSystemsCount; ++ws) { |
| 1473 |
if (scriptForWritingSystem[ws] != script) |
| 1474 |
continue; |
| 1475 |
if (test.family->writingSystems[ws] & QtFontFamily::Supported) |
| 1476 |
supported = true; |
| 1477 |
} |
| 1478 |
if (!supported) { |
| 1479 |
// family not supported in the script we want |
| 1480 |
continue; |
| 1481 |
} |
| 1482 |
|
| 1483 |
// as we know the script is supported, we can be sure |
| 1484 |
// to find a matching font here. |
| 1485 |
unsigned int newscore = |
| 1486 |
bestFoundry(script, score, request.styleStrategy, |
| 1487 |
test.family, foundry_name, styleKey, request.pixelSize, pitch, |
| 1488 |
&test, force_encoding_id); |
| 1489 |
if (test.foundry == 0) { |
| 1490 |
// the specific foundry was not found, so look for |
| 1491 |
// any foundry matching our requirements |
| 1492 |
newscore = bestFoundry(script, score, request.styleStrategy, test.family, |
| 1493 |
QString(), styleKey, request.pixelSize, |
| 1494 |
pitch, &test, force_encoding_id); |
| 1495 |
} |
| 1496 |
newscore += score_adjust; |
| 1497 |
|
| 1498 |
if (newscore < score) { |
| 1499 |
score = newscore; |
| 1500 |
*desc = test; |
| 1501 |
} |
| 1502 |
if (newscore < 10) // xlfd instead of FT... just accept it |
| 1503 |
break; |
| 1504 |
} |
| 1505 |
} |
| 1506 |
#endif |
| 1507 |
|
| 1508 |
static QString styleStringHelper(int weight, QFont::Style style) |
| 1509 |
{ |
| 1510 |
QString result; |
| 1511 |
if (weight >= QFont::Black) |
| 1512 |
result = QApplication::translate("QFontDatabase", "Black"); |
| 1513 |
else if (weight >= QFont::Bold) |
| 1514 |
result = QApplication::translate("QFontDatabase", "Bold"); |
| 1515 |
else if (weight >= QFont::DemiBold) |
| 1516 |
result = QApplication::translate("QFontDatabase", "Demi Bold"); |
| 1517 |
else if (weight < QFont::Normal) |
| 1518 |
result = QApplication::translate("QFontDatabase", "Light"); |
| 1519 |
|
| 1520 |
if (style == QFont::StyleItalic) |
| 1521 |
result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Italic"); |
| 1522 |
else if (style == QFont::StyleOblique) |
| 1523 |
result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Oblique"); |
| 1524 |
|
| 1525 |
if (result.isEmpty()) |
| 1526 |
result = QApplication::translate("QFontDatabase", "Normal"); |
| 1527 |
|
| 1528 |
return result.simplified(); |
| 1529 |
} |
| 1530 |
|
| 1531 |
/*! |
| 1532 |
Returns a string that describes the style of the \a font. For |
| 1533 |
example, "Bold Italic", "Bold", "Italic" or "Normal". An empty |
| 1534 |
string may be returned. |
| 1535 |
*/ |
| 1536 |
QString QFontDatabase::styleString(const QFont &font) |
| 1537 |
{ |
| 1538 |
return font.styleName().isEmpty() ? styleStringHelper(font.weight(), font.style()) |
| 1539 |
: font.styleName(); |
| 1540 |
} |
| 1541 |
|
| 1542 |
/*! |
| 1543 |
Returns a string that describes the style of the \a fontInfo. For |
| 1544 |
example, "Bold Italic", "Bold", "Italic" or "Normal". An empty |
| 1545 |
string may be returned. |
| 1546 |
*/ |
| 1547 |
QString QFontDatabase::styleString(const QFontInfo &fontInfo) |
| 1548 |
{ |
| 1549 |
return fontInfo.styleName().isEmpty() ? styleStringHelper(fontInfo.weight(), fontInfo.style()) |
| 1550 |
: fontInfo.styleName(); |
| 1551 |
} |
| 1552 |
|
| 1553 |
|
| 1554 |
/*! |
| 1555 |
\class QFontDatabase |
| 1556 |
\threadsafe |
| 1557 |
|
| 1558 |
\brief The QFontDatabase class provides information about the fonts available in the underlying window system. |
| 1559 |
|
| 1560 |
\ingroup appearance |
| 1561 |
|
| 1562 |
The most common uses of this class are to query the database for |
| 1563 |
the list of font families() and for the pointSizes() and styles() |
| 1564 |
that are available for each family. An alternative to pointSizes() |
| 1565 |
is smoothSizes() which returns the sizes at which a given family |
| 1566 |
and style will look attractive. |
| 1567 |
|
| 1568 |
If the font family is available from two or more foundries the |
| 1569 |
foundry name is included in the family name; for example: |
| 1570 |
"Helvetica [Adobe]" and "Helvetica [Cronyx]". When you specify a |
| 1571 |
family, you can either use the old hyphenated "foundry-family" |
| 1572 |
format or the bracketed "family [foundry]" format; for example: |
| 1573 |
"Cronyx-Helvetica" or "Helvetica [Cronyx]". If the family has a |
| 1574 |
foundry it is always returned using the bracketed format, as is |
| 1575 |
the case with the value returned by families(). |
| 1576 |
|
| 1577 |
The font() function returns a QFont given a family, style and |
| 1578 |
point size. |
| 1579 |
|
| 1580 |
A family and style combination can be checked to see if it is |
| 1581 |
italic() or bold(), and to retrieve its weight(). Similarly we can |
| 1582 |
call isBitmapScalable(), isSmoothlyScalable(), isScalable() and |
| 1583 |
isFixedPitch(). |
| 1584 |
|
| 1585 |
Use the styleString() to obtain a text version of a style. |
| 1586 |
|
| 1587 |
The QFontDatabase class also supports some static functions, for |
| 1588 |
example, standardSizes(). You can retrieve the description of a |
| 1589 |
writing system using writingSystemName(), and a sample of |
| 1590 |
characters in a writing system with writingSystemSample(). |
| 1591 |
|
| 1592 |
Example: |
| 1593 |
|
| 1594 |
\snippet doc/src/snippets/qfontdatabase/main.cpp 0 |
| 1595 |
\snippet doc/src/snippets/qfontdatabase/main.cpp 1 |
| 1596 |
|
| 1597 |
This example gets the list of font families, the list of |
| 1598 |
styles for each family, and the point sizes that are available for |
| 1599 |
each combination of family and style, displaying this information |
| 1600 |
in a tree view. |
| 1601 |
|
| 1602 |
\sa QFont, QFontInfo, QFontMetrics, QFontComboBox, {Character Map Example} |
| 1603 |
*/ |
| 1604 |
|
| 1605 |
/*! |
| 1606 |
Creates a font database object. |
| 1607 |
*/ |
| 1608 |
QFontDatabase::QFontDatabase() |
| 1609 |
{ |
| 1610 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1611 |
createDatabase(); |
| 1612 |
d = privateDb(); |
| 1613 |
} |
| 1614 |
|
| 1615 |
/*! |
| 1616 |
\enum QFontDatabase::WritingSystem |
| 1617 |
|
| 1618 |
\value Any |
| 1619 |
\value Latin |
| 1620 |
\value Greek |
| 1621 |
\value Cyrillic |
| 1622 |
\value Armenian |
| 1623 |
\value Hebrew |
| 1624 |
\value Arabic |
| 1625 |
\value Syriac |
| 1626 |
\value Thaana |
| 1627 |
\value Devanagari |
| 1628 |
\value Bengali |
| 1629 |
\value Gurmukhi |
| 1630 |
\value Gujarati |
| 1631 |
\value Oriya |
| 1632 |
\value Tamil |
| 1633 |
\value Telugu |
| 1634 |
\value Kannada |
| 1635 |
\value Malayalam |
| 1636 |
\value Sinhala |
| 1637 |
\value Thai |
| 1638 |
\value Lao |
| 1639 |
\value Tibetan |
| 1640 |
\value Myanmar |
| 1641 |
\value Georgian |
| 1642 |
\value Khmer |
| 1643 |
\value SimplifiedChinese |
| 1644 |
\value TraditionalChinese |
| 1645 |
\value Japanese |
| 1646 |
\value Korean |
| 1647 |
\value Vietnamese |
| 1648 |
\value Symbol |
| 1649 |
\value Other (the same as Symbol) |
| 1650 |
\value Ogham |
| 1651 |
\value Runic |
| 1652 |
\value Nko |
| 1653 |
|
| 1654 |
\omitvalue WritingSystemsCount |
| 1655 |
*/ |
| 1656 |
|
| 1657 |
/*! |
| 1658 |
Returns a sorted list of the available writing systems. This is |
| 1659 |
list generated from information about all installed fonts on the |
| 1660 |
system. |
| 1661 |
|
| 1662 |
\sa families() |
| 1663 |
*/ |
| 1664 |
QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const |
| 1665 |
{ |
| 1666 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1667 |
|
| 1668 |
QT_PREPEND_NAMESPACE(load)(); |
| 1669 |
#ifdef Q_WS_X11 |
| 1670 |
checkSymbolFonts(); |
| 1671 |
#endif |
| 1672 |
|
| 1673 |
QList<WritingSystem> list; |
| 1674 |
for (int i = 0; i < d->count; ++i) { |
| 1675 |
QtFontFamily *family = d->families[i]; |
| 1676 |
if (family->count == 0) |
| 1677 |
continue; |
| 1678 |
for (int x = Latin; x < WritingSystemsCount; ++x) { |
| 1679 |
const WritingSystem writingSystem = WritingSystem(x); |
| 1680 |
if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported)) |
| 1681 |
continue; |
| 1682 |
if (!list.contains(writingSystem)) |
| 1683 |
list.append(writingSystem); |
| 1684 |
} |
| 1685 |
} |
| 1686 |
qSort(list); |
| 1687 |
return list; |
| 1688 |
} |
| 1689 |
|
| 1690 |
|
| 1691 |
/*! |
| 1692 |
Returns a sorted list of the writing systems supported by a given |
| 1693 |
font \a family. |
| 1694 |
|
| 1695 |
\sa families() |
| 1696 |
*/ |
| 1697 |
QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems(const QString &family) const |
| 1698 |
{ |
| 1699 |
QString familyName, foundryName; |
| 1700 |
parseFontName(family, foundryName, familyName); |
| 1701 |
|
| 1702 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1703 |
|
| 1704 |
QT_PREPEND_NAMESPACE(load)(); |
| 1705 |
#ifdef Q_WS_X11 |
| 1706 |
checkSymbolFonts(familyName); |
| 1707 |
#endif |
| 1708 |
|
| 1709 |
QList<WritingSystem> list; |
| 1710 |
QtFontFamily *f = d->family(familyName); |
| 1711 |
if (!f || f->count == 0) |
| 1712 |
return list; |
| 1713 |
|
| 1714 |
for (int x = Latin; x < WritingSystemsCount; ++x) { |
| 1715 |
const WritingSystem writingSystem = WritingSystem(x); |
| 1716 |
if (f->writingSystems[writingSystem] & QtFontFamily::Supported) |
| 1717 |
list.append(writingSystem); |
| 1718 |
} |
| 1719 |
return list; |
| 1720 |
} |
| 1721 |
|
| 1722 |
|
| 1723 |
/*! |
| 1724 |
Returns a sorted list of the available font families which support |
| 1725 |
the \a writingSystem. |
| 1726 |
|
| 1727 |
If a family exists in several foundries, the returned name for |
| 1728 |
that font is in the form "family [foundry]". Examples: "Times |
| 1729 |
[Adobe]", "Times [Cronyx]", "Palatino". |
| 1730 |
|
| 1731 |
\sa writingSystems() |
| 1732 |
*/ |
| 1733 |
QStringList QFontDatabase::families(WritingSystem writingSystem) const |
| 1734 |
{ |
| 1735 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1736 |
|
| 1737 |
QT_PREPEND_NAMESPACE(load)(); |
| 1738 |
#ifdef Q_WS_X11 |
| 1739 |
if (writingSystem != Any) |
| 1740 |
checkSymbolFonts(); |
| 1741 |
#endif |
| 1742 |
|
| 1743 |
QStringList flist; |
| 1744 |
for (int i = 0; i < d->count; i++) { |
| 1745 |
QtFontFamily *f = d->families[i]; |
| 1746 |
if (f->count == 0) |
| 1747 |
continue; |
| 1748 |
if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported)) |
| 1749 |
continue; |
| 1750 |
if (f->count == 1) { |
| 1751 |
flist.append(f->name); |
| 1752 |
} else { |
| 1753 |
for (int j = 0; j < f->count; j++) { |
| 1754 |
QString str = f->name; |
| 1755 |
QString foundry = f->foundries[j]->name; |
| 1756 |
if (!foundry.isEmpty()) { |
| 1757 |
str += QLatin1String(" ["); |
| 1758 |
str += foundry; |
| 1759 |
str += QLatin1Char(']'); |
| 1760 |
} |
| 1761 |
flist.append(str); |
| 1762 |
} |
| 1763 |
} |
| 1764 |
} |
| 1765 |
return flist; |
| 1766 |
} |
| 1767 |
|
| 1768 |
/*! |
| 1769 |
Returns a list of the styles available for the font family \a |
| 1770 |
family. Some example styles: "Light", "Light Italic", "Bold", |
| 1771 |
"Oblique", "Demi". The list may be empty. |
| 1772 |
|
| 1773 |
\sa families() |
| 1774 |
*/ |
| 1775 |
QStringList QFontDatabase::styles(const QString &family) const |
| 1776 |
{ |
| 1777 |
QString familyName, foundryName; |
| 1778 |
parseFontName(family, foundryName, familyName); |
| 1779 |
|
| 1780 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1781 |
|
| 1782 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 1783 |
|
| 1784 |
QStringList l; |
| 1785 |
QtFontFamily *f = d->family(familyName); |
| 1786 |
if (!f) |
| 1787 |
return l; |
| 1788 |
|
| 1789 |
QtFontFoundry allStyles(foundryName); |
| 1790 |
for (int j = 0; j < f->count; j++) { |
| 1791 |
QtFontFoundry *foundry = f->foundries[j]; |
| 1792 |
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 1793 |
for (int k = 0; k < foundry->count; k++) { |
| 1794 |
QtFontStyle::Key ke(foundry->styles[k]->key); |
| 1795 |
ke.stretch = 0; |
| 1796 |
allStyles.style(ke, foundry->styles[k]->styleName, true); |
| 1797 |
} |
| 1798 |
} |
| 1799 |
} |
| 1800 |
|
| 1801 |
for (int i = 0; i < allStyles.count; i++) { |
| 1802 |
l.append(allStyles.styles[i]->styleName.isEmpty() ? |
| 1803 |
styleStringHelper(allStyles.styles[i]->key.weight, |
| 1804 |
(QFont::Style)allStyles.styles[i]->key.style) : |
| 1805 |
allStyles.styles[i]->styleName); |
| 1806 |
} |
| 1807 |
return l; |
| 1808 |
} |
| 1809 |
|
| 1810 |
/*! |
| 1811 |
Returns true if the font that has family \a family and style \a |
| 1812 |
style is fixed pitch; otherwise returns false. |
| 1813 |
*/ |
| 1814 |
|
| 1815 |
bool QFontDatabase::isFixedPitch(const QString &family, |
| 1816 |
const QString &style) const |
| 1817 |
{ |
| 1818 |
Q_UNUSED(style); |
| 1819 |
|
| 1820 |
QString familyName, foundryName; |
| 1821 |
parseFontName(family, foundryName, familyName); |
| 1822 |
|
| 1823 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1824 |
|
| 1825 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 1826 |
|
| 1827 |
QtFontFamily *f = d->family(familyName); |
| 1828 |
#if !defined(QWS) && defined(Q_OS_MAC) |
| 1829 |
qt_mac_get_fixed_pitch(f); |
| 1830 |
#endif |
| 1831 |
return (f && f->fixedPitch); |
| 1832 |
} |
| 1833 |
|
| 1834 |
/*! |
| 1835 |
Returns true if the font that has family \a family and style \a |
| 1836 |
style is a scalable bitmap font; otherwise returns false. Scaling |
| 1837 |
a bitmap font usually produces an unattractive hardly readable |
| 1838 |
result, because the pixels of the font are scaled. If you need to |
| 1839 |
scale a bitmap font it is better to scale it to one of the fixed |
| 1840 |
sizes returned by smoothSizes(). |
| 1841 |
|
| 1842 |
\sa isScalable(), isSmoothlyScalable() |
| 1843 |
*/ |
| 1844 |
bool QFontDatabase::isBitmapScalable(const QString &family, |
| 1845 |
const QString &style) const |
| 1846 |
{ |
| 1847 |
bool bitmapScalable = false; |
| 1848 |
QString familyName, foundryName; |
| 1849 |
parseFontName(family, foundryName, familyName); |
| 1850 |
|
| 1851 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1852 |
|
| 1853 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 1854 |
|
| 1855 |
QtFontStyle::Key styleKey(style); |
| 1856 |
|
| 1857 |
QtFontFamily *f = d->family(familyName); |
| 1858 |
if (!f) return bitmapScalable; |
| 1859 |
|
| 1860 |
for (int j = 0; j < f->count; j++) { |
| 1861 |
QtFontFoundry *foundry = f->foundries[j]; |
| 1862 |
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 1863 |
for (int k = 0; k < foundry->count; k++) |
| 1864 |
if ((style.isEmpty() || |
| 1865 |
foundry->styles[k]->styleName == style || |
| 1866 |
foundry->styles[k]->key == styleKey) |
| 1867 |
&& foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) { |
| 1868 |
bitmapScalable = true; |
| 1869 |
goto end; |
| 1870 |
} |
| 1871 |
} |
| 1872 |
} |
| 1873 |
end: |
| 1874 |
return bitmapScalable; |
| 1875 |
} |
| 1876 |
|
| 1877 |
|
| 1878 |
/*! |
| 1879 |
Returns true if the font that has family \a family and style \a |
| 1880 |
style is smoothly scalable; otherwise returns false. If this |
| 1881 |
function returns true, it's safe to scale this font to any size, |
| 1882 |
and the result will always look attractive. |
| 1883 |
|
| 1884 |
\sa isScalable(), isBitmapScalable() |
| 1885 |
*/ |
| 1886 |
bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const |
| 1887 |
{ |
| 1888 |
bool smoothScalable = false; |
| 1889 |
QString familyName, foundryName; |
| 1890 |
parseFontName(family, foundryName, familyName); |
| 1891 |
|
| 1892 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1893 |
|
| 1894 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 1895 |
|
| 1896 |
QtFontStyle::Key styleKey(style); |
| 1897 |
|
| 1898 |
QtFontFamily *f = d->family(familyName); |
| 1899 |
if (!f) return smoothScalable; |
| 1900 |
|
| 1901 |
for (int j = 0; j < f->count; j++) { |
| 1902 |
QtFontFoundry *foundry = f->foundries[j]; |
| 1903 |
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 1904 |
for (int k = 0; k < foundry->count; k++) |
| 1905 |
if ((style.isEmpty() || |
| 1906 |
foundry->styles[k]->styleName == style || |
| 1907 |
foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) { |
| 1908 |
smoothScalable = true; |
| 1909 |
goto end; |
| 1910 |
} |
| 1911 |
} |
| 1912 |
} |
| 1913 |
end: |
| 1914 |
return smoothScalable; |
| 1915 |
} |
| 1916 |
|
| 1917 |
/*! |
| 1918 |
Returns true if the font that has family \a family and style \a |
| 1919 |
style is scalable; otherwise returns false. |
| 1920 |
|
| 1921 |
\sa isBitmapScalable(), isSmoothlyScalable() |
| 1922 |
*/ |
| 1923 |
bool QFontDatabase::isScalable(const QString &family, |
| 1924 |
const QString &style) const |
| 1925 |
{ |
| 1926 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1927 |
if (isSmoothlyScalable(family, style)) |
| 1928 |
return true; |
| 1929 |
return isBitmapScalable(family, style); |
| 1930 |
} |
| 1931 |
|
| 1932 |
|
| 1933 |
/*! |
| 1934 |
\fn QList<int> QFontDatabase::pointSizes(const QString &family, const QString &style) |
| 1935 |
Returns a list of the point sizes available for the font with the |
| 1936 |
given \a family and \a style. The list may be empty. |
| 1937 |
|
| 1938 |
\sa smoothSizes(), standardSizes() |
| 1939 |
*/ |
| 1940 |
QList<int> QFontDatabase::pointSizes(const QString &family, |
| 1941 |
const QString &styleName) |
| 1942 |
{ |
| 1943 |
#if defined(Q_WS_WIN) |
| 1944 |
// windows and macosx are always smoothly scalable |
| 1945 |
Q_UNUSED(family); |
| 1946 |
Q_UNUSED(styleName); |
| 1947 |
return standardSizes(); |
| 1948 |
#else |
| 1949 |
bool smoothScalable = false; |
| 1950 |
QString familyName, foundryName; |
| 1951 |
parseFontName(family, foundryName, familyName); |
| 1952 |
|
| 1953 |
QMutexLocker locker(fontDatabaseMutex()); |
| 1954 |
|
| 1955 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 1956 |
|
| 1957 |
QtFontStyle::Key styleKey(styleName); |
| 1958 |
|
| 1959 |
QList<int> sizes; |
| 1960 |
|
| 1961 |
QtFontFamily *fam = d->family(familyName); |
| 1962 |
if (!fam) return sizes; |
| 1963 |
|
| 1964 |
|
| 1965 |
#ifdef Q_WS_X11 |
| 1966 |
int dpi = QX11Info::appDpiY(); |
| 1967 |
#else |
| 1968 |
const int dpi = qt_defaultDpiY(); // embedded |
| 1969 |
#endif |
| 1970 |
|
| 1971 |
for (int j = 0; j < fam->count; j++) { |
| 1972 |
QtFontFoundry *foundry = fam->foundries[j]; |
| 1973 |
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 1974 |
QtFontStyle *style = foundry->style(styleKey, styleName); |
| 1975 |
if (!style) continue; |
| 1976 |
|
| 1977 |
if (style->smoothScalable) { |
| 1978 |
smoothScalable = true; |
| 1979 |
goto end; |
| 1980 |
} |
| 1981 |
for (int l = 0; l < style->count; l++) { |
| 1982 |
const QtFontSize *size = style->pixelSizes + l; |
| 1983 |
|
| 1984 |
if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) { |
| 1985 |
const uint pointSize = qRound(size->pixelSize * qreal(72.0) / dpi); |
| 1986 |
if (! sizes.contains(pointSize)) |
| 1987 |
sizes.append(pointSize); |
| 1988 |
} |
| 1989 |
} |
| 1990 |
} |
| 1991 |
} |
| 1992 |
end: |
| 1993 |
if (smoothScalable) |
| 1994 |
return standardSizes(); |
| 1995 |
|
| 1996 |
qSort(sizes); |
| 1997 |
return sizes; |
| 1998 |
#endif |
| 1999 |
} |
| 2000 |
|
| 2001 |
/*! |
| 2002 |
Returns a QFont object that has family \a family, style \a style |
| 2003 |
and point size \a pointSize. If no matching font could be created, |
| 2004 |
a QFont object that uses the application's default font is |
| 2005 |
returned. |
| 2006 |
*/ |
| 2007 |
QFont QFontDatabase::font(const QString &family, const QString &style, |
| 2008 |
int pointSize) const |
| 2009 |
{ |
| 2010 |
QString familyName, foundryName; |
| 2011 |
parseFontName(family, foundryName, familyName); |
| 2012 |
|
| 2013 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2014 |
|
| 2015 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 2016 |
|
| 2017 |
QtFontFoundry allStyles(foundryName); |
| 2018 |
QtFontFamily *f = d->family(familyName); |
| 2019 |
if (!f) return QApplication::font(); |
| 2020 |
|
| 2021 |
for (int j = 0; j < f->count; j++) { |
| 2022 |
QtFontFoundry *foundry = f->foundries[j]; |
| 2023 |
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 2024 |
for (int k = 0; k < foundry->count; k++) |
| 2025 |
allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); |
| 2026 |
} |
| 2027 |
} |
| 2028 |
|
| 2029 |
QtFontStyle::Key styleKey(style); |
| 2030 |
QtFontStyle *s = bestStyle(&allStyles, styleKey, style); |
| 2031 |
|
| 2032 |
if (!s) // no styles found? |
| 2033 |
return QApplication::font(); |
| 2034 |
|
| 2035 |
QFont fnt(family, pointSize, s->key.weight); |
| 2036 |
fnt.setStyle((QFont::Style)s->key.style); |
| 2037 |
if (!s->styleName.isEmpty()) |
| 2038 |
fnt.setStyleName(s->styleName); |
| 2039 |
return fnt; |
| 2040 |
} |
| 2041 |
|
| 2042 |
|
| 2043 |
/*! |
| 2044 |
\fn QList<int> QFontDatabase::smoothSizes(const QString &family, const QString &style) |
| 2045 |
Returns the point sizes of a font with the given \a family and \a style |
| 2046 |
that will look attractive. The list may be empty. |
| 2047 |
For non-scalable fonts and bitmap scalable fonts, this function |
| 2048 |
is equivalent to pointSizes(). |
| 2049 |
|
| 2050 |
\sa pointSizes(), standardSizes() |
| 2051 |
*/ |
| 2052 |
QList<int> QFontDatabase::smoothSizes(const QString &family, |
| 2053 |
const QString &styleName) |
| 2054 |
{ |
| 2055 |
#ifdef Q_WS_WIN |
| 2056 |
Q_UNUSED(family); |
| 2057 |
Q_UNUSED(styleName); |
| 2058 |
return QFontDatabase::standardSizes(); |
| 2059 |
#else |
| 2060 |
bool smoothScalable = false; |
| 2061 |
QString familyName, foundryName; |
| 2062 |
parseFontName(family, foundryName, familyName); |
| 2063 |
|
| 2064 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2065 |
|
| 2066 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 2067 |
|
| 2068 |
QtFontStyle::Key styleKey(styleName); |
| 2069 |
|
| 2070 |
QList<int> sizes; |
| 2071 |
|
| 2072 |
QtFontFamily *fam = d->family(familyName); |
| 2073 |
if (!fam) |
| 2074 |
return sizes; |
| 2075 |
|
| 2076 |
#ifdef Q_WS_X11 |
| 2077 |
int dpi = QX11Info::appDpiY(); |
| 2078 |
#else |
| 2079 |
const int dpi = qt_defaultDpiY(); // embedded |
| 2080 |
#endif |
| 2081 |
|
| 2082 |
for (int j = 0; j < fam->count; j++) { |
| 2083 |
QtFontFoundry *foundry = fam->foundries[j]; |
| 2084 |
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 2085 |
QtFontStyle *style = foundry->style(styleKey, styleName); |
| 2086 |
if (!style) continue; |
| 2087 |
|
| 2088 |
if (style->smoothScalable) { |
| 2089 |
smoothScalable = true; |
| 2090 |
goto end; |
| 2091 |
} |
| 2092 |
for (int l = 0; l < style->count; l++) { |
| 2093 |
const QtFontSize *size = style->pixelSizes + l; |
| 2094 |
|
| 2095 |
if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) { |
| 2096 |
const uint pointSize = qRound(size->pixelSize * qreal(72.0) / dpi); |
| 2097 |
if (! sizes.contains(pointSize)) |
| 2098 |
sizes.append(pointSize); |
| 2099 |
} |
| 2100 |
} |
| 2101 |
} |
| 2102 |
} |
| 2103 |
end: |
| 2104 |
if (smoothScalable) |
| 2105 |
return QFontDatabase::standardSizes(); |
| 2106 |
|
| 2107 |
qSort(sizes); |
| 2108 |
return sizes; |
| 2109 |
#endif |
| 2110 |
} |
| 2111 |
|
| 2112 |
|
| 2113 |
/*! |
| 2114 |
Returns a list of standard font sizes. |
| 2115 |
|
| 2116 |
\sa smoothSizes(), pointSizes() |
| 2117 |
*/ |
| 2118 |
QList<int> QFontDatabase::standardSizes() |
| 2119 |
{ |
| 2120 |
QList<int> ret; |
| 2121 |
static const unsigned short standard[] = |
| 2122 |
{ 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 }; |
| 2123 |
const unsigned short *sizes = standard; |
| 2124 |
while (*sizes) ret << *sizes++; |
| 2125 |
return ret; |
| 2126 |
} |
| 2127 |
|
| 2128 |
|
| 2129 |
/*! |
| 2130 |
Returns true if the font that has family \a family and style \a |
| 2131 |
style is italic; otherwise returns false. |
| 2132 |
|
| 2133 |
\sa weight(), bold() |
| 2134 |
*/ |
| 2135 |
bool QFontDatabase::italic(const QString &family, const QString &style) const |
| 2136 |
{ |
| 2137 |
QString familyName, foundryName; |
| 2138 |
parseFontName(family, foundryName, familyName); |
| 2139 |
|
| 2140 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2141 |
|
| 2142 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 2143 |
|
| 2144 |
QtFontFoundry allStyles(foundryName); |
| 2145 |
QtFontFamily *f = d->family(familyName); |
| 2146 |
if (!f) return false; |
| 2147 |
|
| 2148 |
for (int j = 0; j < f->count; j++) { |
| 2149 |
QtFontFoundry *foundry = f->foundries[j]; |
| 2150 |
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 2151 |
for (int k = 0; k < foundry->count; k++) |
| 2152 |
allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); |
| 2153 |
} |
| 2154 |
} |
| 2155 |
|
| 2156 |
QtFontStyle::Key styleKey(style); |
| 2157 |
QtFontStyle *s = allStyles.style(styleKey, style); |
| 2158 |
return s && s->key.style == QFont::StyleItalic; |
| 2159 |
} |
| 2160 |
|
| 2161 |
|
| 2162 |
/*! |
| 2163 |
Returns true if the font that has family \a family and style \a |
| 2164 |
style is bold; otherwise returns false. |
| 2165 |
|
| 2166 |
\sa italic(), weight() |
| 2167 |
*/ |
| 2168 |
bool QFontDatabase::bold(const QString &family, |
| 2169 |
const QString &style) const |
| 2170 |
{ |
| 2171 |
QString familyName, foundryName; |
| 2172 |
parseFontName(family, foundryName, familyName); |
| 2173 |
|
| 2174 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2175 |
|
| 2176 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 2177 |
|
| 2178 |
QtFontFoundry allStyles(foundryName); |
| 2179 |
QtFontFamily *f = d->family(familyName); |
| 2180 |
if (!f) return false; |
| 2181 |
|
| 2182 |
for (int j = 0; j < f->count; j++) { |
| 2183 |
QtFontFoundry *foundry = f->foundries[j]; |
| 2184 |
if (foundryName.isEmpty() || |
| 2185 |
foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 2186 |
for (int k = 0; k < foundry->count; k++) |
| 2187 |
allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); |
| 2188 |
} |
| 2189 |
} |
| 2190 |
|
| 2191 |
QtFontStyle::Key styleKey(style); |
| 2192 |
QtFontStyle *s = allStyles.style(styleKey, style); |
| 2193 |
return s && s->key.weight >= QFont::Bold; |
| 2194 |
} |
| 2195 |
|
| 2196 |
|
| 2197 |
/*! |
| 2198 |
Returns the weight of the font that has family \a family and style |
| 2199 |
\a style. If there is no such family and style combination, |
| 2200 |
returns -1. |
| 2201 |
|
| 2202 |
\sa italic(), bold() |
| 2203 |
*/ |
| 2204 |
int QFontDatabase::weight(const QString &family, |
| 2205 |
const QString &style) const |
| 2206 |
{ |
| 2207 |
QString familyName, foundryName; |
| 2208 |
parseFontName(family, foundryName, familyName); |
| 2209 |
|
| 2210 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2211 |
|
| 2212 |
QT_PREPEND_NAMESPACE(load)(familyName); |
| 2213 |
|
| 2214 |
QtFontFoundry allStyles(foundryName); |
| 2215 |
QtFontFamily *f = d->family(familyName); |
| 2216 |
if (!f) return -1; |
| 2217 |
|
| 2218 |
for (int j = 0; j < f->count; j++) { |
| 2219 |
QtFontFoundry *foundry = f->foundries[j]; |
| 2220 |
if (foundryName.isEmpty() || |
| 2221 |
foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { |
| 2222 |
for (int k = 0; k < foundry->count; k++) |
| 2223 |
allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); |
| 2224 |
} |
| 2225 |
} |
| 2226 |
|
| 2227 |
QtFontStyle::Key styleKey(style); |
| 2228 |
QtFontStyle *s = allStyles.style(styleKey, style); |
| 2229 |
return s ? s->key.weight : -1; |
| 2230 |
} |
| 2231 |
|
| 2232 |
|
| 2233 |
/*! \internal */ |
| 2234 |
bool QFontDatabase::hasFamily(const QString &family) const |
| 2235 |
{ |
| 2236 |
QString parsedFamily, foundry; |
| 2237 |
parseFontName(family, foundry, parsedFamily); |
| 2238 |
const QString familyAlias = resolveFontFamilyAlias(parsedFamily); |
| 2239 |
return families().contains(familyAlias, Qt::CaseInsensitive); |
| 2240 |
} |
| 2241 |
|
| 2242 |
|
| 2243 |
/*! |
| 2244 |
Returns the names the \a writingSystem (e.g. for displaying to the |
| 2245 |
user in a dialog). |
| 2246 |
*/ |
| 2247 |
QString QFontDatabase::writingSystemName(WritingSystem writingSystem) |
| 2248 |
{ |
| 2249 |
const char *name = 0; |
| 2250 |
switch (writingSystem) { |
| 2251 |
case Any: |
| 2252 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Any"); |
| 2253 |
break; |
| 2254 |
case Latin: |
| 2255 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Latin"); |
| 2256 |
break; |
| 2257 |
case Greek: |
| 2258 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Greek"); |
| 2259 |
break; |
| 2260 |
case Cyrillic: |
| 2261 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Cyrillic"); |
| 2262 |
break; |
| 2263 |
case Armenian: |
| 2264 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Armenian"); |
| 2265 |
break; |
| 2266 |
case Hebrew: |
| 2267 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Hebrew"); |
| 2268 |
break; |
| 2269 |
case Arabic: |
| 2270 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Arabic"); |
| 2271 |
break; |
| 2272 |
case Syriac: |
| 2273 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Syriac"); |
| 2274 |
break; |
| 2275 |
case Thaana: |
| 2276 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Thaana"); |
| 2277 |
break; |
| 2278 |
case Devanagari: |
| 2279 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Devanagari"); |
| 2280 |
break; |
| 2281 |
case Bengali: |
| 2282 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Bengali"); |
| 2283 |
break; |
| 2284 |
case Gurmukhi: |
| 2285 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Gurmukhi"); |
| 2286 |
break; |
| 2287 |
case Gujarati: |
| 2288 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Gujarati"); |
| 2289 |
break; |
| 2290 |
case Oriya: |
| 2291 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Oriya"); |
| 2292 |
break; |
| 2293 |
case Tamil: |
| 2294 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Tamil"); |
| 2295 |
break; |
| 2296 |
case Telugu: |
| 2297 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Telugu"); |
| 2298 |
break; |
| 2299 |
case Kannada: |
| 2300 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Kannada"); |
| 2301 |
break; |
| 2302 |
case Malayalam: |
| 2303 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Malayalam"); |
| 2304 |
break; |
| 2305 |
case Sinhala: |
| 2306 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Sinhala"); |
| 2307 |
break; |
| 2308 |
case Thai: |
| 2309 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Thai"); |
| 2310 |
break; |
| 2311 |
case Lao: |
| 2312 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Lao"); |
| 2313 |
break; |
| 2314 |
case Tibetan: |
| 2315 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Tibetan"); |
| 2316 |
break; |
| 2317 |
case Myanmar: |
| 2318 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Myanmar"); |
| 2319 |
break; |
| 2320 |
case Georgian: |
| 2321 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Georgian"); |
| 2322 |
break; |
| 2323 |
case Khmer: |
| 2324 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Khmer"); |
| 2325 |
break; |
| 2326 |
case SimplifiedChinese: |
| 2327 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Simplified Chinese"); |
| 2328 |
break; |
| 2329 |
case TraditionalChinese: |
| 2330 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Traditional Chinese"); |
| 2331 |
break; |
| 2332 |
case Japanese: |
| 2333 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Japanese"); |
| 2334 |
break; |
| 2335 |
case Korean: |
| 2336 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Korean"); |
| 2337 |
break; |
| 2338 |
case Vietnamese: |
| 2339 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Vietnamese"); |
| 2340 |
break; |
| 2341 |
case Symbol: |
| 2342 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Symbol"); |
| 2343 |
break; |
| 2344 |
case Ogham: |
| 2345 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Ogham"); |
| 2346 |
break; |
| 2347 |
case Runic: |
| 2348 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "Runic"); |
| 2349 |
break; |
| 2350 |
case Nko: |
| 2351 |
name = QT_TRANSLATE_NOOP("QFontDatabase", "N'Ko"); |
| 2352 |
break; |
| 2353 |
default: |
| 2354 |
Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter"); |
| 2355 |
break; |
| 2356 |
} |
| 2357 |
return QApplication::translate("QFontDatabase", name); |
| 2358 |
} |
| 2359 |
|
| 2360 |
|
| 2361 |
/*! |
| 2362 |
Returns a string with sample characters from \a writingSystem. |
| 2363 |
*/ |
| 2364 |
QString QFontDatabase::writingSystemSample(WritingSystem writingSystem) |
| 2365 |
{ |
| 2366 |
QString sample; |
| 2367 |
switch (writingSystem) { |
| 2368 |
case Any: |
| 2369 |
case Symbol: |
| 2370 |
// show only ascii characters |
| 2371 |
sample += QLatin1String("AaBbzZ"); |
| 2372 |
break; |
| 2373 |
case Latin: |
| 2374 |
// This is cheating... we only show latin-1 characters so that we don't |
| 2375 |
// end up loading lots of fonts - at least on X11... |
| 2376 |
sample = QLatin1String("Aa"); |
| 2377 |
sample += QChar(0x00C3); |
| 2378 |
sample += QChar(0x00E1); |
| 2379 |
sample += QLatin1String("Zz"); |
| 2380 |
break; |
| 2381 |
case Greek: |
| 2382 |
sample += QChar(0x0393); |
| 2383 |
sample += QChar(0x03B1); |
| 2384 |
sample += QChar(0x03A9); |
| 2385 |
sample += QChar(0x03C9); |
| 2386 |
break; |
| 2387 |
case Cyrillic: |
| 2388 |
sample += QChar(0x0414); |
| 2389 |
sample += QChar(0x0434); |
| 2390 |
sample += QChar(0x0436); |
| 2391 |
sample += QChar(0x044f); |
| 2392 |
break; |
| 2393 |
case Armenian: |
| 2394 |
sample += QChar(0x053f); |
| 2395 |
sample += QChar(0x054f); |
| 2396 |
sample += QChar(0x056f); |
| 2397 |
sample += QChar(0x057f); |
| 2398 |
break; |
| 2399 |
case Hebrew: |
| 2400 |
sample += QChar(0x05D0); |
| 2401 |
sample += QChar(0x05D1); |
| 2402 |
sample += QChar(0x05D2); |
| 2403 |
sample += QChar(0x05D3); |
| 2404 |
break; |
| 2405 |
case Arabic: |
| 2406 |
sample += QChar(0x0628); |
| 2407 |
sample += QChar(0x0629); |
| 2408 |
sample += QChar(0x062A); |
| 2409 |
sample += QChar(0x063A); |
| 2410 |
break; |
| 2411 |
case Syriac: |
| 2412 |
sample += QChar(0x0715); |
| 2413 |
sample += QChar(0x0725); |
| 2414 |
sample += QChar(0x0716); |
| 2415 |
sample += QChar(0x0726); |
| 2416 |
break; |
| 2417 |
case Thaana: |
| 2418 |
sample += QChar(0x0784); |
| 2419 |
sample += QChar(0x0794); |
| 2420 |
sample += QChar(0x078c); |
| 2421 |
sample += QChar(0x078d); |
| 2422 |
break; |
| 2423 |
case Devanagari: |
| 2424 |
sample += QChar(0x0905); |
| 2425 |
sample += QChar(0x0915); |
| 2426 |
sample += QChar(0x0925); |
| 2427 |
sample += QChar(0x0935); |
| 2428 |
break; |
| 2429 |
case Bengali: |
| 2430 |
sample += QChar(0x0986); |
| 2431 |
sample += QChar(0x0996); |
| 2432 |
sample += QChar(0x09a6); |
| 2433 |
sample += QChar(0x09b6); |
| 2434 |
break; |
| 2435 |
case Gurmukhi: |
| 2436 |
sample += QChar(0x0a05); |
| 2437 |
sample += QChar(0x0a15); |
| 2438 |
sample += QChar(0x0a25); |
| 2439 |
sample += QChar(0x0a35); |
| 2440 |
break; |
| 2441 |
case Gujarati: |
| 2442 |
sample += QChar(0x0a85); |
| 2443 |
sample += QChar(0x0a95); |
| 2444 |
sample += QChar(0x0aa5); |
| 2445 |
sample += QChar(0x0ab5); |
| 2446 |
break; |
| 2447 |
case Oriya: |
| 2448 |
sample += QChar(0x0b06); |
| 2449 |
sample += QChar(0x0b16); |
| 2450 |
sample += QChar(0x0b2b); |
| 2451 |
sample += QChar(0x0b36); |
| 2452 |
break; |
| 2453 |
case Tamil: |
| 2454 |
sample += QChar(0x0b89); |
| 2455 |
sample += QChar(0x0b99); |
| 2456 |
sample += QChar(0x0ba9); |
| 2457 |
sample += QChar(0x0bb9); |
| 2458 |
break; |
| 2459 |
case Telugu: |
| 2460 |
sample += QChar(0x0c05); |
| 2461 |
sample += QChar(0x0c15); |
| 2462 |
sample += QChar(0x0c25); |
| 2463 |
sample += QChar(0x0c35); |
| 2464 |
break; |
| 2465 |
case Kannada: |
| 2466 |
sample += QChar(0x0c85); |
| 2467 |
sample += QChar(0x0c95); |
| 2468 |
sample += QChar(0x0ca5); |
| 2469 |
sample += QChar(0x0cb5); |
| 2470 |
break; |
| 2471 |
case Malayalam: |
| 2472 |
sample += QChar(0x0d05); |
| 2473 |
sample += QChar(0x0d15); |
| 2474 |
sample += QChar(0x0d25); |
| 2475 |
sample += QChar(0x0d35); |
| 2476 |
break; |
| 2477 |
case Sinhala: |
| 2478 |
sample += QChar(0x0d90); |
| 2479 |
sample += QChar(0x0da0); |
| 2480 |
sample += QChar(0x0db0); |
| 2481 |
sample += QChar(0x0dc0); |
| 2482 |
break; |
| 2483 |
case Thai: |
| 2484 |
sample += QChar(0x0e02); |
| 2485 |
sample += QChar(0x0e12); |
| 2486 |
sample += QChar(0x0e22); |
| 2487 |
sample += QChar(0x0e32); |
| 2488 |
break; |
| 2489 |
case Lao: |
| 2490 |
sample += QChar(0x0e8d); |
| 2491 |
sample += QChar(0x0e9d); |
| 2492 |
sample += QChar(0x0ead); |
| 2493 |
sample += QChar(0x0ebd); |
| 2494 |
break; |
| 2495 |
case Tibetan: |
| 2496 |
sample += QChar(0x0f00); |
| 2497 |
sample += QChar(0x0f01); |
| 2498 |
sample += QChar(0x0f02); |
| 2499 |
sample += QChar(0x0f03); |
| 2500 |
break; |
| 2501 |
case Myanmar: |
| 2502 |
sample += QChar(0x1000); |
| 2503 |
sample += QChar(0x1001); |
| 2504 |
sample += QChar(0x1002); |
| 2505 |
sample += QChar(0x1003); |
| 2506 |
break; |
| 2507 |
case Georgian: |
| 2508 |
sample += QChar(0x10a0); |
| 2509 |
sample += QChar(0x10b0); |
| 2510 |
sample += QChar(0x10c0); |
| 2511 |
sample += QChar(0x10d0); |
| 2512 |
break; |
| 2513 |
case Khmer: |
| 2514 |
sample += QChar(0x1780); |
| 2515 |
sample += QChar(0x1790); |
| 2516 |
sample += QChar(0x17b0); |
| 2517 |
sample += QChar(0x17c0); |
| 2518 |
break; |
| 2519 |
case SimplifiedChinese: |
| 2520 |
sample += QChar(0x4e2d); |
| 2521 |
sample += QChar(0x6587); |
| 2522 |
sample += QChar(0x8303); |
| 2523 |
sample += QChar(0x4f8b); |
| 2524 |
break; |
| 2525 |
case TraditionalChinese: |
| 2526 |
sample += QChar(0x4e2d); |
| 2527 |
sample += QChar(0x6587); |
| 2528 |
sample += QChar(0x7bc4); |
| 2529 |
sample += QChar(0x4f8b); |
| 2530 |
break; |
| 2531 |
case Japanese: |
| 2532 |
sample += QChar(0x30b5); |
| 2533 |
sample += QChar(0x30f3); |
| 2534 |
sample += QChar(0x30d7); |
| 2535 |
sample += QChar(0x30eb); |
| 2536 |
sample += QChar(0x3067); |
| 2537 |
sample += QChar(0x3059); |
| 2538 |
break; |
| 2539 |
case Korean: |
| 2540 |
sample += QChar(0xac00); |
| 2541 |
sample += QChar(0xac11); |
| 2542 |
sample += QChar(0xac1a); |
| 2543 |
sample += QChar(0xac2f); |
| 2544 |
break; |
| 2545 |
case Vietnamese: |
| 2546 |
{ |
| 2547 |
static const char vietnameseUtf8[] = { |
| 2548 |
char(0xef), char(0xbb), char(0xbf), char(0xe1), char(0xbb), char(0x97), |
| 2549 |
char(0xe1), char(0xbb), char(0x99), |
| 2550 |
char(0xe1), char(0xbb), char(0x91), |
| 2551 |
char(0xe1), char(0xbb), char(0x93), |
| 2552 |
}; |
| 2553 |
sample += QString::fromUtf8(vietnameseUtf8, sizeof(vietnameseUtf8)); |
| 2554 |
break; |
| 2555 |
} |
| 2556 |
case Ogham: |
| 2557 |
sample += QChar(0x1681); |
| 2558 |
sample += QChar(0x1682); |
| 2559 |
sample += QChar(0x1683); |
| 2560 |
sample += QChar(0x1684); |
| 2561 |
break; |
| 2562 |
case Runic: |
| 2563 |
sample += QChar(0x16a0); |
| 2564 |
sample += QChar(0x16a1); |
| 2565 |
sample += QChar(0x16a2); |
| 2566 |
sample += QChar(0x16a3); |
| 2567 |
break; |
| 2568 |
case Nko: |
| 2569 |
sample += QChar(0x7ca); |
| 2570 |
sample += QChar(0x7cb); |
| 2571 |
sample += QChar(0x7cc); |
| 2572 |
sample += QChar(0x7cd); |
| 2573 |
break; |
| 2574 |
default: |
| 2575 |
break; |
| 2576 |
} |
| 2577 |
return sample; |
| 2578 |
} |
| 2579 |
|
| 2580 |
|
| 2581 |
void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family) |
| 2582 |
{ |
| 2583 |
QT_PREPEND_NAMESPACE(parseFontName)(name, foundry, family); |
| 2584 |
} |
| 2585 |
|
| 2586 |
void QFontDatabase::createDatabase() |
| 2587 |
{ initializeDb(); } |
| 2588 |
|
| 2589 |
// used from qfontengine_ft.cpp |
| 2590 |
Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index) |
| 2591 |
{ |
| 2592 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2593 |
return privateDb()->applicationFonts.value(index).data; |
| 2594 |
} |
| 2595 |
|
| 2596 |
int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &fileName) |
| 2597 |
{ |
| 2598 |
QFontDatabasePrivate::ApplicationFont font; |
| 2599 |
font.data = fontData; |
| 2600 |
font.fileName = fileName; |
| 2601 |
|
| 2602 |
int i; |
| 2603 |
for (i = 0; i < applicationFonts.count(); ++i) |
| 2604 |
if (applicationFonts.at(i).families.isEmpty()) |
| 2605 |
break; |
| 2606 |
if (i >= applicationFonts.count()) { |
| 2607 |
applicationFonts.append(ApplicationFont()); |
| 2608 |
i = applicationFonts.count() - 1; |
| 2609 |
} |
| 2610 |
|
| 2611 |
if (font.fileName.isEmpty() && !fontData.isEmpty()) |
| 2612 |
font.fileName = QString::fromLatin1(":qmemoryfonts/") + QString::number(i); |
| 2613 |
|
| 2614 |
registerFont(&font); |
| 2615 |
if (font.families.isEmpty()) |
| 2616 |
return -1; |
| 2617 |
|
| 2618 |
applicationFonts[i] = font; |
| 2619 |
|
| 2620 |
invalidate(); |
| 2621 |
return i; |
| 2622 |
} |
| 2623 |
|
| 2624 |
bool QFontDatabasePrivate::isApplicationFont(const QString &fileName) |
| 2625 |
{ |
| 2626 |
for (int i = 0; i < applicationFonts.count(); ++i) |
| 2627 |
if (applicationFonts.at(i).fileName == fileName) |
| 2628 |
return true; |
| 2629 |
return false; |
| 2630 |
} |
| 2631 |
|
| 2632 |
/*! |
| 2633 |
\since 4.2 |
| 2634 |
|
| 2635 |
Loads the font from the file specified by \a fileName and makes it available to |
| 2636 |
the application. An ID is returned that can be used to remove the font again |
| 2637 |
with removeApplicationFont() or to retrieve the list of family names contained |
| 2638 |
in the font. |
| 2639 |
|
| 2640 |
The function returns -1 if the font could not be loaded. |
| 2641 |
|
| 2642 |
Currently only TrueType fonts, TrueType font collections, and OpenType fonts are |
| 2643 |
supported. |
| 2644 |
|
| 2645 |
\note Adding application fonts on Unix/X11 platforms without fontconfig is |
| 2646 |
currently not supported. |
| 2647 |
|
| 2648 |
\note On Symbian, the font family names get truncated to a length of 20 characters. |
| 2649 |
|
| 2650 |
\sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont() |
| 2651 |
*/ |
| 2652 |
int QFontDatabase::addApplicationFont(const QString &fileName) |
| 2653 |
{ |
| 2654 |
QByteArray data; |
| 2655 |
QFile f(fileName); |
| 2656 |
if (!(f.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) { |
| 2657 |
if (!f.open(QIODevice::ReadOnly)) |
| 2658 |
return -1; |
| 2659 |
data = f.readAll(); |
| 2660 |
} |
| 2661 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2662 |
return privateDb()->addAppFont(data, fileName); |
| 2663 |
} |
| 2664 |
|
| 2665 |
/*! |
| 2666 |
\since 4.2 |
| 2667 |
|
| 2668 |
Loads the font from binary data specified by \a fontData and makes it available to |
| 2669 |
the application. An ID is returned that can be used to remove the font again |
| 2670 |
with removeApplicationFont() or to retrieve the list of family names contained |
| 2671 |
in the font. |
| 2672 |
|
| 2673 |
The function returns -1 if the font could not be loaded. |
| 2674 |
|
| 2675 |
Currently only TrueType fonts and TrueType font collections are supported. |
| 2676 |
|
| 2677 |
\bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is |
| 2678 |
currently not supported. |
| 2679 |
|
| 2680 |
\note On Symbian, the font family names get truncated to a length of 20 characters. |
| 2681 |
|
| 2682 |
\sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont() |
| 2683 |
*/ |
| 2684 |
int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData) |
| 2685 |
{ |
| 2686 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2687 |
return privateDb()->addAppFont(fontData, QString() /* fileName */); |
| 2688 |
} |
| 2689 |
|
| 2690 |
/*! |
| 2691 |
\since 4.2 |
| 2692 |
|
| 2693 |
Returns a list of font families for the given application font identified by |
| 2694 |
\a id. |
| 2695 |
|
| 2696 |
\sa addApplicationFont(), addApplicationFontFromData() |
| 2697 |
*/ |
| 2698 |
QStringList QFontDatabase::applicationFontFamilies(int id) |
| 2699 |
{ |
| 2700 |
QMutexLocker locker(fontDatabaseMutex()); |
| 2701 |
return privateDb()->applicationFonts.value(id).families; |
| 2702 |
} |
| 2703 |
|
| 2704 |
/*! |
| 2705 |
\fn bool QFontDatabase::removeApplicationFont(int id) |
| 2706 |
\since 4.2 |
| 2707 |
|
| 2708 |
Removes the previously loaded application font identified by \a |
| 2709 |
id. Returns true if unloading of the font succeeded; otherwise |
| 2710 |
returns false. |
| 2711 |
|
| 2712 |
\sa removeAllApplicationFonts(), addApplicationFont(), |
| 2713 |
addApplicationFontFromData() |
| 2714 |
*/ |
| 2715 |
|
| 2716 |
/*! |
| 2717 |
\fn bool QFontDatabase::removeAllApplicationFonts() |
| 2718 |
\since 4.2 |
| 2719 |
|
| 2720 |
Removes all application-local fonts previously added using addApplicationFont() |
| 2721 |
and addApplicationFontFromData(). |
| 2722 |
|
| 2723 |
Returns true if unloading of the fonts succeeded; otherwise |
| 2724 |
returns false. |
| 2725 |
|
| 2726 |
\sa removeApplicationFont(), addApplicationFont(), addApplicationFontFromData() |
| 2727 |
*/ |
| 2728 |
|
| 2729 |
/*! |
| 2730 |
\fn bool QFontDatabase::supportsThreadedFontRendering() |
| 2731 |
\since 4.4 |
| 2732 |
|
| 2733 |
Returns true if font rendering is supported outside the GUI |
| 2734 |
thread, false otherwise. In other words, a return value of false |
| 2735 |
means that all QPainter::drawText() calls outside the GUI thread |
| 2736 |
will not produce readable output. |
| 2737 |
|
| 2738 |
\sa {Thread-Support in Qt Modules#Painting In Threads}{Painting In Threads} |
| 2739 |
*/ |
| 2740 |
|
| 2741 |
|
| 2742 |
QT_END_NAMESPACE |