source: trunk/src/gui/text/qfontdatabase_pm.cpp@ 318

Last change on this file since 318 was 318, checked in by Dmitry A. Kuminov, 16 years ago

gui/text: Keep track of scripts supported by individual styles within a font family to make sure that if some style doesn't support all scripts the other style does, the font matching algorithm will select another family for this style instead of drawing empty boxes.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Date Revision Author Id
File size: 26.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** Copyright (C) 2009 netlabs.org. OS/2 parts.
7**
8** This file is part of the QtGui module of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial Usage
12** Licensees holding valid Qt Commercial licenses may use this file in
13** accordance with the Qt Commercial License Agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and Nokia.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Nokia gives you certain
26** additional rights. These rights are described in the Nokia Qt LGPL
27** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
28** package.
29**
30** GNU General Public License Usage
31** Alternatively, this file may be used under the terms of the GNU
32** General Public License version 3.0 as published by the Free Software
33** Foundation and appearing in the file LICENSE.GPL included in the
34** packaging of this file. Please review the following information to
35** ensure the GNU General Public License version 3.0 requirements will be
36** met: http://www.gnu.org/copyleft/gpl.html.
37**
38** If you are unsure which license is appropriate for your use, please
39** contact the sales department at [email protected].
40** $QT_END_LICENSE$
41**
42****************************************************************************/
43
44#include "qabstractfileengine.h"
45
46#include "qfontengine_pm_p.h"
47
48#include "qsettings.h"
49#include "qfileinfo.h"
50#include "qdatetime.h"
51#include "qhash.h"
52
53#include <ft2build.h>
54#include FT_FREETYPE_H
55#include FT_TYPES_H
56#include FT_TRUETYPE_TABLES_H
57#include FT_LCD_FILTER_H
58
59QT_BEGIN_NAMESPACE
60
61struct FaceData
62{
63 int index;
64 QString familyName;
65 QtFontStyle::Key styleKey;
66 QList<QFontDatabase::WritingSystem> systems;
67 bool fixedPitch;
68 bool smoothScalable;
69 QList<unsigned short> pixelSizes;
70};
71
72static QDataStream &operator<<(QDataStream &data, const QFontDatabase::WritingSystem &ws)
73{
74 data << (int)ws;
75 return data;
76}
77
78static QDataStream &operator>>(QDataStream &data, QFontDatabase::WritingSystem &ws)
79{
80 data >> (int&)ws;
81 return data;
82}
83
84static QDataStream &operator<<(QDataStream &data, const FaceData &cached)
85{
86 data << cached.familyName;
87 data << cached.styleKey.style << cached.styleKey.weight
88 << cached.styleKey.stretch;
89 data << cached.systems;
90 data << cached.fixedPitch << cached.smoothScalable;
91 data << cached.pixelSizes;
92 return data;
93}
94
95static QDataStream &operator>>(QDataStream &data, FaceData &cached)
96{
97 data >> cached.familyName;
98 uint style;
99 int weight, stretch;
100 data >> style; cached.styleKey.style = style;
101 data >> weight; cached.styleKey.weight = weight;
102 data >> stretch; cached.styleKey.stretch = stretch;
103 data >> cached.systems;
104 data >> cached.fixedPitch >> cached.smoothScalable;
105 data >> cached.pixelSizes;
106 return data;
107}
108
109struct FileData
110{
111 FileData() : seen(false) {}
112 FileData(const QFileInfo &fi, bool s) : fileInfo(fi), seen(s) {}
113
114 QFileInfo fileInfo;
115 bool seen;
116};
117
118typedef QHash<QString, FileData> FontFileHash;
119static FontFileHash knownFontFiles;
120static bool knownFontFilesInitialized = false;
121
122static void populateDatabase(const QString& fam)
123{
124 QFontDatabasePrivate *db = privateDb();
125 if (!db)
126 return;
127
128 QtFontFamily *family = 0;
129 if(!fam.isEmpty()) {
130 family = db->family(fam);
131 if(family)
132 return;
133 } else if (db->count) {
134 return;
135 }
136
137 // we don't recognize foundries on OS/2, use an empty one
138 const QString foundryName;
139
140#ifdef QFONTDATABASE_DEBUG
141 QTime timer;
142 timer.start();
143#endif
144
145 QSettings fontCache(QSettings::UserScope, QLatin1String("Trolltech"));
146 fontCache.beginGroup(QLatin1String("Qt/Fonts/Cache 1.0"));
147
148 if (!knownFontFilesInitialized) {
149 // get the initial list of know font files from the cache (necessary to
150 // detect deleted font files)
151 knownFontFilesInitialized = true;
152 QStringList files = fontCache.childGroups();
153 foreach(QString file, files) {
154 file.replace("|", "/");
155 knownFontFiles.insert(file, FileData());
156 // note that QFileInfo is empty so the file will be considered as
157 // NEW which is necessary for the font to get into the database
158 }
159 } else {
160 // reset the 'seen' flag
161 for (FontFileHash::iterator it = knownFontFiles.begin();
162 it != knownFontFiles.end(); ++it)
163 it.value().seen = false;
164 }
165
166 QList<QFileInfo> fontFiles;
167
168 ULONG bufSize = 0;
169 BOOL ok = PrfQueryProfileSize(HINI_USERPROFILE, "PM_Fonts", 0, &bufSize);
170 Q_ASSERT(ok);
171 if (ok) {
172 char *buffer = new char[bufSize + 1 /*terminating NULL*/];
173 Q_ASSERT(buffer);
174 if (buffer) {
175 ULONG bufLen = PrfQueryProfileString(HINI_USERPROFILE, "PM_Fonts", 0, 0,
176 buffer, bufSize);
177 if (bufLen) {
178 char *key = buffer;
179 while (*key) {
180 ULONG keySize = 0;
181 ok = PrfQueryProfileSize(HINI_USERPROFILE, "PM_Fonts", key,
182 &keySize);
183 if (ok) {
184 QByteArray file(keySize, 0);
185 ULONG keyLen =
186 PrfQueryProfileString(HINI_USERPROFILE, "PM_Fonts", key, 0,
187 file.data(), file.size());
188 file.truncate(keyLen - 1 /*terminating NULL*/);
189 if (!file.isEmpty()) {
190 // FreeType doesn't understand .OFM but understands .PFB
191 if (file.toUpper().endsWith(".OFM")) {
192 file.chop(4);
193 file.append(".PFB");
194 }
195 QFileInfo fileInfo(QFile::decodeName(file));
196 QString fileName = fileInfo.canonicalFilePath().toLower();
197 if (!fileName.isEmpty()) { // file may have been deleted
198 fileInfo.setFile(fileName);
199 // check the in-process file name cache
200 FileData &cached = knownFontFiles[fileName];
201 if (cached.fileInfo.filePath().isEmpty() ||
202 cached.fileInfo.lastModified() != fileInfo.lastModified() ||
203 cached.fileInfo.size() != fileInfo.size()) {
204 // no cache entry or outdated, process it
205 cached.fileInfo = fileInfo;
206 cached.seen = true;
207 fontFiles << fileInfo;
208 FD_DEBUG("populateDatabase: NEW/UPDATED font file %s",
209 qPrintable(fileName));
210 } else {
211 // just set the 'seen' flag and skip this font
212 // (it's already in the database)
213 knownFontFiles[fileName].seen = true;
214 FD_DEBUG("populateDatabase: UNCHANGED font file %s",
215 qPrintable(fileName));
216 }
217 }
218 }
219 }
220 key += strlen(key) + 1;
221 }
222 }
223 delete buffer;
224 }
225 }
226
227 extern FT_Library qt_getFreetype(); // qfontengine_ft.cpp
228 FT_Library lib = qt_getFreetype();
229
230 // go through each font file and get available faces
231 foreach(const QFileInfo &fileInfo, fontFiles) {
232 QString fileKey = fileInfo.absoluteFilePath().toLower();
233 QByteArray file = QFile::encodeName(fileKey);
234
235 // QSettings uses / for splitting into groups, suppress it
236 fileKey.replace("/", "|");
237
238 QList<FaceData> cachedFaces;
239
240 // first, look up the cached data
241 fontCache.beginGroup(fileKey);
242
243 if (fontCache.value(QLatin1String("DateTime")).toDateTime() != fileInfo.lastModified() ||
244 fontCache.value(QLatin1String("Size")).toUInt() != fileInfo.size()) {
245 // the cache is outdated or doesn't exist, query the font file
246
247 FT_Long numFaces = 0;
248 FT_Face face;
249
250 FT_Error rc = FT_New_Face(lib, file, -1, &face);
251 if (rc == 0) {
252 numFaces = face->num_faces;
253 FT_Done_Face(face);
254 } else {
255 // invalid/unsupported font file, numFaces is left 0 so that
256 // only DateTime and Size will be cached indicating that this
257 // file is not recognized
258 }
259
260 FD_DEBUG("populateDatabase: Font file %s: FT error %d, has %ld faces",
261 file.constData(), (int) rc, numFaces);
262
263 // go throuhg each face
264 for (FT_Long idx = 0; idx < numFaces; ++idx) {
265 rc = FT_New_Face(lib, file, idx, &face);
266 if (rc != 0)
267 continue;
268
269 FaceData cached;
270
271 cached.index = idx;
272 cached.familyName = QString::fromLatin1(face->family_name);
273
274 // familyName may contain extra spaces (at least this is true for
275 // TNR.PFB that is reported as "Times New Roman ". Trim them.
276 cached.familyName = cached.familyName.trimmed();
277
278 cached.styleKey.style = face->style_flags & FT_STYLE_FLAG_ITALIC ?
279 QFont::StyleItalic : QFont::StyleNormal;
280
281 TT_OS2 *os2_table = 0;
282 if (face->face_flags & FT_FACE_FLAG_SFNT) {
283 os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
284 }
285 if (os2_table) {
286 // map weight and width values
287 if (os2_table->usWeightClass < 400)
288 cached.styleKey.weight = QFont::Light;
289 else if (os2_table->usWeightClass < 600)
290 cached.styleKey.weight = QFont::Normal;
291 else if (os2_table->usWeightClass < 700)
292 cached.styleKey.weight = QFont::DemiBold;
293 else if (os2_table->usWeightClass < 800)
294 cached.styleKey.weight = QFont::Bold;
295 else
296 cached.styleKey.weight = QFont::Black;
297FD_DEBUG("os2_table->usWeightClass %u", os2_table->usWeightClass);
298
299 switch (os2_table->usWidthClass) {
300 case 1: cached.styleKey.stretch = QFont::UltraCondensed; break;
301 case 2: cached.styleKey.stretch = QFont::ExtraCondensed; break;
302 case 3: cached.styleKey.stretch = QFont::Condensed; break;
303 case 4: cached.styleKey.stretch = QFont::SemiCondensed; break;
304 case 5: cached.styleKey.stretch = QFont::Unstretched; break;
305 case 6: cached.styleKey.stretch = QFont::SemiExpanded; break;
306 case 7: cached.styleKey.stretch = QFont::Expanded; break;
307 case 8: cached.styleKey.stretch = QFont::ExtraExpanded; break;
308 case 9: cached.styleKey.stretch = QFont::UltraExpanded; break;
309 default: cached.styleKey.stretch = QFont::Unstretched; break;
310 }
311
312 quint32 unicodeRange[4] = {
313 os2_table->ulUnicodeRange1, os2_table->ulUnicodeRange2,
314 os2_table->ulUnicodeRange3, os2_table->ulUnicodeRange4
315 };
316 quint32 codePageRange[2] = {
317 os2_table->ulCodePageRange1, os2_table->ulCodePageRange2
318 };
319 cached.systems =
320 determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
321FD_DEBUG() << "cached.systems" << cached.systems;
322 } else {
323 // we've only got simple weight information and no stretch
324 cached.styleKey.weight = face->style_flags & FT_STYLE_FLAG_BOLD ?
325 QFont::Bold : QFont::Normal;
326 cached.styleKey.stretch = QFont::Unstretched;
327 }
328
329 cached.fixedPitch = face->face_flags & FT_FACE_FLAG_FIXED_WIDTH;
330
331 cached.smoothScalable = face->face_flags & FT_FACE_FLAG_SCALABLE;
332
333 // the font may both be scalable and contain fixed size bitmaps
334 if (face->face_flags & FT_FACE_FLAG_FIXED_SIZES) {
335 for (FT_Int i = 0; i < face->num_fixed_sizes; ++i) {
336 cached.pixelSizes << face->available_sizes[i].height;
337 }
338 }
339
340 cachedFaces << cached;
341
342 FT_Done_Face(face);
343 }
344
345 // store the data into the cache
346 fontCache.setValue(QLatin1String("DateTime"), fileInfo.lastModified());
347 fontCache.setValue(QLatin1String("Size"), fileInfo.size());
348 foreach(FaceData cached, cachedFaces) {
349 QByteArray rawData;
350 QDataStream data(&rawData, QIODevice::WriteOnly);
351 data << cached;
352
353 QString face = QString::number(cached.index);
354 fontCache.beginGroup(face);
355 fontCache.setValue(QLatin1String("Info"), rawData);
356 fontCache.endGroup();
357 }
358 } else {
359 // take the face data from the cache
360
361 QStringList faces = fontCache.childGroups();
362
363 FD_DEBUG("populateDatabase: Font file %s: IN CACHE, has %d faces",
364 file.constData(), faces.count());
365
366 foreach(QString face, faces) {
367 bool ok = false;
368 FaceData cached;
369 cached.index = face.toInt(&ok);
370 if (!ok || cached.index < 0) // not a valid index
371 continue;
372
373 fontCache.beginGroup(face);
374 QByteArray rawData =
375 fontCache.value(QLatin1String("Info")).toByteArray();
376 QDataStream data(rawData);
377 data >> cached;
378 fontCache.endGroup();
379
380 cachedFaces << cached;
381 }
382 }
383
384 fontCache.endGroup();
385
386 // go throuhg each cached face and add it to the database
387 foreach(FaceData cached, cachedFaces) {
388
389 QtFontFamily *family = privateDb()->family(cached.familyName, true);
390
391 // @todo is it possible that the same family is both fixed and not?
392 Q_ASSERT(!family->fixedPitch || cached.fixedPitch);
393 family->fixedPitch = cached.fixedPitch;
394
395 if (cached.systems.isEmpty()) {
396 // it was hard or impossible to determine the actual writing system
397 // of the font (as in case of OS/2 bitmap and PFB fonts for which it is
398 // usually simply reported that they support standard/system codepages).
399 // Pretend that we support all writing systems to not miss the one.
400 //
401 // @todo find a proper way to detect actual supported scripts to make
402 // sure these fonts are not matched for scripts they don't support.
403 for (int ws = 0; ws < QFontDatabase::WritingSystemsCount; ++ws)
404 family->writingSystems[ws] = QtFontFamily::Supported;
405 } else {
406 for (int i = 0; i < cached.systems.count(); ++i)
407 family->writingSystems[cached.systems.at(i)] = QtFontFamily::Supported;
408 }
409
410 QtFontFoundry *foundry = family->foundry(foundryName, true);
411 QtFontStyle *style = foundry->style(cached.styleKey, true);
412
413 // so far, all recognized fonts are antialiased
414 style->antialiased = true;
415
416 if (cached.smoothScalable && !style->smoothScalable) {
417 // add new scalable style only if it hasn't been already added --
418 // the first one of two duplicate (in Qt terms) non-bitmap font
419 // styles wins.
420 style->smoothScalable = true;
421 QtFontSize *size =
422 style->pixelSize(SMOOTH_SCALABLE, true);
423 size->fileName = file;
424 size->fileIndex = cached.index;
425 size->systems = cached.systems;
426 }
427
428 foreach(unsigned short pixelSize, cached.pixelSizes) {
429 QtFontSize *size = style->pixelSize(pixelSize, true);
430 // the first bitmap style with a given pixel and point size wins
431 if (!size->fileName.isEmpty())
432 continue;
433 size->fileName = file;
434 size->fileIndex = cached.index;
435 size->systems = cached.systems;
436 }
437 }
438 }
439
440 // go through the known file list to detect what files have been removed
441 for (FontFileHash::iterator it = knownFontFiles.begin();
442 it != knownFontFiles.end();) {
443 if (!it.value().seen) {
444 FD_DEBUG("populateDatabase: DELETED font file %s",
445 qPrintable(it.key()));
446 // remove from the both caches
447 QString fileKey = it.key();
448 fileKey.replace("/", "|");
449 fontCache.remove(fileKey);
450 it = knownFontFiles.erase(it);
451 // @todo should we remove all references to this file from the
452 // font database? My concern is that this font may be in use by Qt
453 // and its glyphs may be still cached when file deletion happens
454 } else {
455 ++it;
456 }
457 }
458
459#ifdef QFONTDATABASE_DEBUG
460 FD_DEBUG("populateDatabase: took %d ms", timer.elapsed());
461#endif
462}
463
464static void initializeDb()
465{
466 QFontDatabasePrivate *db = privateDb();
467 if (!db || db->count)
468 return;
469
470 populateDatabase(QString());
471
472#ifdef QFONTDATABASE_DEBUG
473 // print the database
474 qDebug("initializeDb:");
475 for (int f = 0; f < db->count; f++) {
476 QtFontFamily *family = db->families[f];
477 qDebug(" %s: %p", qPrintable(family->name), family);
478 populateDatabase(family->name);
479#if 1
480 qDebug(" writing systems supported:");
481 QStringList systems;
482 for (int ws = 0; ws < QFontDatabase::WritingSystemsCount; ++ws)
483 if (family->writingSystems[ws] & QtFontFamily::Supported)
484 systems << QFontDatabase::writingSystemName((QFontDatabase::WritingSystem)ws);
485 qDebug() << " " << systems;
486 for (int fd = 0; fd < family->count; fd++) {
487 QtFontFoundry *foundry = family->foundries[fd];
488 qDebug(" %s", foundry->name.isEmpty() ? "(empty foundry)" :
489 qPrintable(foundry->name));
490 for (int s = 0; s < foundry->count; s++) {
491 QtFontStyle *style = foundry->styles[s];
492 qDebug(" style: style=%d weight=%d smooth=%d", style->key.style,
493 style->key.weight, style->smoothScalable);
494 for(int i = 0; i < style->count; ++i) {
495 if (style->pixelSizes[i].pixelSize == SMOOTH_SCALABLE)
496 qDebug(" smooth %s:%d",
497 style->pixelSizes[i].fileName.constData(),
498 style->pixelSizes[i].fileIndex);
499 else
500 qDebug(" %d px %s:%d", style->pixelSizes[i].pixelSize,
501 style->pixelSizes[i].fileName.constData(),
502 style->pixelSizes[i].fileIndex);
503 }
504 }
505 }
506#endif
507 }
508#endif // QFONTDATABASE_DEBUG
509}
510
511static inline void load(const QString &family = QString(), int = -1)
512{
513 populateDatabase(family);
514}
515
516static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
517{
518 // @todo implement
519}
520
521static QFontDef fontDescToFontDef(const QFontDef &req, const QtFontDesc &desc)
522{
523 static LONG dpi = -1;
524 if (dpi == -1) {
525 // PM cannot change resolutions on the fly so cache it
526 int hps = qt_display_ps();
527 DevQueryCaps(GpiQueryDevice(hps), CAPS_HORIZONTAL_FONT_RES, 1, &dpi);
528 }
529
530 QFontDef fontDef;
531
532 fontDef.family = desc.family->name;
533
534 if (desc.size->pixelSize == SMOOTH_SCALABLE) {
535 // scalable font matched, calculate the missing size (points or pixels)
536 fontDef.pointSize = req.pointSize;
537 fontDef.pixelSize = req.pixelSize;
538 if (req.pointSize < 0) {
539 fontDef.pointSize = req.pixelSize * 72. / dpi;
540 } else if (req.pixelSize == -1) {
541 fontDef.pixelSize = qRound(req.pointSize * dpi / 72.);
542 }
543 } else {
544 // non-scalable font matched, calculate both point and pixel size
545 fontDef.pixelSize = desc.size->pixelSize;
546 fontDef.pointSize = desc.size->pixelSize * 72. / dpi;
547 }
548
549 fontDef.styleStrategy = req.styleStrategy;
550 fontDef.styleHint = req.styleHint;
551
552 fontDef.weight = desc.style->key.weight;
553 fontDef.fixedPitch = desc.family->fixedPitch;
554 fontDef.style = desc.style->key.style;
555 fontDef.stretch = desc.style->key.stretch;
556
557 return fontDef;
558}
559
560static QFontEngine *loadEngine(const QFontDef &req, const QtFontDesc &desc)
561{
562 // @todo all these fixed so far; make configurable through the Registry
563 // on per-family basis
564 QFontEnginePMFT::HintStyle hintStyle = QFontEnginePMFT::HintFull;
565 bool autoHint = true;
566 QFontEngineFT::SubpixelAntialiasingType subPixel = QFontEngineFT::Subpixel_None;
567 int lcdFilter = FT_LCD_FILTER_DEFAULT;
568 bool useEmbeddedBitmap = true;
569
570 QFontEngine::FaceId faceId;
571 faceId.filename = desc.size->fileName;
572 faceId.index = desc.size->fileIndex;
573
574 QFontEngineFT *fe = new QFontEnginePMFT(fontDescToFontDef(req, desc), faceId,
575 desc.style->antialiased, hintStyle,
576 autoHint, subPixel, lcdFilter,
577 useEmbeddedBitmap);
578 Q_ASSERT(fe);
579 if (fe && fe->invalid()) {
580 FM_DEBUG(" --> invalid!\n");
581 delete fe;
582 fe = 0;
583 }
584 return fe;
585}
586
587static QFontEngine *loadPM(const QFontPrivate *d, int script, const QFontDef &req)
588{
589 // list of families to try
590 QStringList families = familyList(req);
591
592 const char *styleHint = qt_fontFamilyFromStyleHint(d->request);
593 if (styleHint)
594 families << QLatin1String(styleHint);
595
596 // add the default family
597 QString defaultFamily = QApplication::font().family();
598 if (! families.contains(defaultFamily))
599 families << defaultFamily;
600
601 // add QFont::defaultFamily() to the list, for compatibility with
602 // previous versions
603 families << QApplication::font().defaultFamily();
604
605 // null family means find the first font matching the specified script
606 families << QString();
607
608 QtFontDesc desc;
609 QFontEngine *fe = 0;
610 QList<int> blacklistedFamilies;
611
612 while (!fe) {
613 for (int i = 0; i < families.size(); ++i) {
614 QString family, foundry;
615 parseFontName(families.at(i), foundry, family);
616 FM_DEBUG("loadPM: >>>>>>>>>>>>>> trying to match '%s'", qPrintable(family));
617 QT_PREPEND_NAMESPACE(match)(script, req, family, foundry, -1, &desc, blacklistedFamilies);
618 if (desc.family)
619 break;
620 }
621 if (!desc.family)
622 break;
623 FM_DEBUG("loadPM: ============== matched '%s'", qPrintable(desc.family->name));
624 fe = loadEngine(req, desc);
625 if (!fe)
626 blacklistedFamilies.append(desc.familyIndex);
627 }
628 return fe;
629}
630
631void QFontDatabase::load(const QFontPrivate *d, int script)
632{
633 Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
634
635 // normalize the request to get better caching
636 QFontDef req = d->request;
637 if (req.pixelSize <= 0)
638 req.pixelSize = qMax(1, qRound(req.pointSize * d->dpi / 72.));
639 req.pointSize = 0;
640 if (req.weight == 0)
641 req.weight = QFont::Normal;
642 if (req.stretch == 0)
643 req.stretch = 100;
644
645 // @todo a hack to substitute "WarpSans" with "Workplace Sans". Remove this
646 // when we start supporting OS/2 bitmap fonts.
647 if (req.family == QLatin1String("WarpSans"))
648 req.family = QLatin1String("Workplace Sans");
649
650 QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen);
651 if (!d->engineData)
652 getEngineData(d, key);
653
654 // the cached engineData could have already loaded the engine we want
655 if (d->engineData->engines[script])
656 return;
657
658 // set it to the actual pointsize, so QFontInfo will do the right thing
659 req.pointSize = req.pixelSize * 72. / d->dpi;
660
661 QFontEngine *fe = QFontCache::instance()->findEngine(key);
662
663 if (!fe) {
664 if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
665 fe = new QTestFontEngine(req.pixelSize);
666 fe->fontDef = req;
667 } else {
668 QMutexLocker locker(fontDatabaseMutex());
669 if (!privateDb()->count)
670 initializeDb();
671 fe = loadPM(d, script, req);
672 }
673 if (!fe) {
674 fe = new QFontEngineBox(req.pixelSize);
675 fe->fontDef = QFontDef();
676 }
677 }
678 if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
679 for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
680 if (!d->engineData->engines[i]) {
681 d->engineData->engines[i] = fe;
682 fe->ref.ref();
683 }
684 }
685 } else {
686 d->engineData->engines[script] = fe;
687 fe->ref.ref();
688 }
689 QFontCache::instance()->insertEngine(key, fe);
690}
691
692bool QFontDatabase::removeApplicationFont(int handle)
693{
694 // @todo implement
695 return false;
696}
697
698bool QFontDatabase::removeAllApplicationFonts()
699{
700 // @todo implement
701 return false;
702}
703
704bool QFontDatabase::supportsThreadedFontRendering()
705{
706 // @todo implement
707 return false;
708}
709
710QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.