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

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

gui: Fixed: Hack to enable all scripts for the Workplace Sans font didn't work.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Date Revision Author Id
File size: 26.5 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;
297
298 switch (os2_table->usWidthClass) {
299 case 1: cached.styleKey.stretch = QFont::UltraCondensed; break;
300 case 2: cached.styleKey.stretch = QFont::ExtraCondensed; break;
301 case 3: cached.styleKey.stretch = QFont::Condensed; break;
302 case 4: cached.styleKey.stretch = QFont::SemiCondensed; break;
303 case 5: cached.styleKey.stretch = QFont::Unstretched; break;
304 case 6: cached.styleKey.stretch = QFont::SemiExpanded; break;
305 case 7: cached.styleKey.stretch = QFont::Expanded; break;
306 case 8: cached.styleKey.stretch = QFont::ExtraExpanded; break;
307 case 9: cached.styleKey.stretch = QFont::UltraExpanded; break;
308 default: cached.styleKey.stretch = QFont::Unstretched; break;
309 }
310
311 quint32 unicodeRange[4] = {
312 os2_table->ulUnicodeRange1, os2_table->ulUnicodeRange2,
313 os2_table->ulUnicodeRange3, os2_table->ulUnicodeRange4
314 };
315 quint32 codePageRange[2] = {
316 os2_table->ulCodePageRange1, os2_table->ulCodePageRange2
317 };
318 cached.systems =
319 determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
320 } else {
321 // we've only got simple weight information and no stretch
322 cached.styleKey.weight = face->style_flags & FT_STYLE_FLAG_BOLD ?
323 QFont::Bold : QFont::Normal;
324 cached.styleKey.stretch = QFont::Unstretched;
325 }
326
327 cached.fixedPitch = face->face_flags & FT_FACE_FLAG_FIXED_WIDTH;
328
329 cached.smoothScalable = face->face_flags & FT_FACE_FLAG_SCALABLE;
330
331 // the font may both be scalable and contain fixed size bitmaps
332 if (face->face_flags & FT_FACE_FLAG_FIXED_SIZES) {
333 for (FT_Int i = 0; i < face->num_fixed_sizes; ++i) {
334 cached.pixelSizes << face->available_sizes[i].height;
335 }
336 }
337
338 cachedFaces << cached;
339
340 FT_Done_Face(face);
341 }
342
343 // store the data into the cache
344 fontCache.setValue(QLatin1String("DateTime"), fileInfo.lastModified());
345 fontCache.setValue(QLatin1String("Size"), fileInfo.size());
346 foreach(FaceData cached, cachedFaces) {
347 QByteArray rawData;
348 QDataStream data(&rawData, QIODevice::WriteOnly);
349 data << cached;
350
351 QString face = QString::number(cached.index);
352 fontCache.beginGroup(face);
353 fontCache.setValue(QLatin1String("Info"), rawData);
354 fontCache.endGroup();
355 }
356 } else {
357 // take the face data from the cache
358
359 QStringList faces = fontCache.childGroups();
360
361 FD_DEBUG("populateDatabase: Font file %s: IN CACHE, has %d faces",
362 file.constData(), faces.count());
363
364 foreach(QString face, faces) {
365 bool ok = false;
366 FaceData cached;
367 cached.index = face.toInt(&ok);
368 if (!ok || cached.index < 0) // not a valid index
369 continue;
370
371 fontCache.beginGroup(face);
372 QByteArray rawData =
373 fontCache.value(QLatin1String("Info")).toByteArray();
374 QDataStream data(rawData);
375 data >> cached;
376 fontCache.endGroup();
377
378 cachedFaces << cached;
379 }
380 }
381
382 fontCache.endGroup();
383
384 // go throuhg each cached face and add it to the database
385 foreach(FaceData cached, cachedFaces) {
386
387 QtFontFamily *family = privateDb()->family(cached.familyName, true);
388
389 // @todo is it possible that the same family is both fixed and not?
390 Q_ASSERT(!family->fixedPitch || cached.fixedPitch);
391 family->fixedPitch = cached.fixedPitch;
392
393 if (cached.systems.isEmpty() || cached.familyName == QLatin1String("Workplace Sans")) {
394 // it was hard or impossible to determine the actual writing system
395 // of the font (as in case of OS/2 bitmap and PFB fonts for which it is
396 // usually simply reported that they support standard/system codepages).
397 // Pretend that we support all writing systems to not miss the one.
398 // Note that "Workplace Sans" TTF by Alex Taylor doesn't provide correct
399 // unicode and codepage ranges in os2_table for some reason but versions
400 // 0.4 and earlier are known to support many popular scripts so hack it.
401 //
402 // @todo find a proper way to detect actual supported scripts to make
403 // sure these fonts are not matched for scripts they don't support
404 for (int ws = 0; ws < QFontDatabase::WritingSystemsCount; ++ws)
405 family->writingSystems[ws] = QtFontFamily::Supported;
406 } else {
407 for (int i = 0; i < cached.systems.count(); ++i)
408 family->writingSystems[cached.systems.at(i)] = QtFontFamily::Supported;
409 }
410
411 QtFontFoundry *foundry = family->foundry(foundryName, true);
412 QtFontStyle *style = foundry->style(cached.styleKey, true);
413
414 // so far, all recognized fonts are antialiased
415 style->antialiased = true;
416
417 if (cached.smoothScalable && !style->smoothScalable) {
418 // add new scalable style only if it hasn't been already added --
419 // the first one of two duplicate (in Qt terms) non-bitmap font
420 // styles wins.
421 style->smoothScalable = true;
422 QtFontSize *size =
423 style->pixelSize(SMOOTH_SCALABLE, true);
424 size->fileName = file;
425 size->fileIndex = cached.index;
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 }
436 }
437 }
438
439 // go through the known file list to detect what files have been removed
440 for (FontFileHash::iterator it = knownFontFiles.begin();
441 it != knownFontFiles.end();) {
442 if (!it.value().seen) {
443 FD_DEBUG("populateDatabase: DELETED font file %s",
444 qPrintable(it.key()));
445 // remove from the both caches
446 QString fileKey = it.key();
447 fileKey.replace("/", "|");
448 fontCache.remove(fileKey);
449 it = knownFontFiles.erase(it);
450 // @todo should we remove all references to this file from the
451 // font database? My concern is that this font may be in use by Qt
452 // and its glyphs may be still cached when file deletion happens
453 } else {
454 ++it;
455 }
456 }
457
458#ifdef QFONTDATABASE_DEBUG
459 FD_DEBUG("populateDatabase: took %d ms", timer.elapsed());
460#endif
461}
462
463static void initializeDb()
464{
465 QFontDatabasePrivate *db = privateDb();
466 if (!db || db->count)
467 return;
468
469 populateDatabase(QString());
470
471#ifdef QFONTDATABASE_DEBUG
472 // print the database
473 qDebug("initializeDb:");
474 for (int f = 0; f < db->count; f++) {
475 QtFontFamily *family = db->families[f];
476 qDebug(" %s: %p", qPrintable(family->name), family);
477 populateDatabase(family->name);
478#if 1
479 qDebug(" writing systems supported:");
480 QStringList systems;
481 for (int ws = 0; ws < QFontDatabase::WritingSystemsCount; ++ws)
482 if (family->writingSystems[ws] & QtFontFamily::Supported)
483 systems << QFontDatabase::writingSystemName((QFontDatabase::WritingSystem)ws);
484 qDebug() << " " << systems;
485 for (int fd = 0; fd < family->count; fd++) {
486 QtFontFoundry *foundry = family->foundries[fd];
487 qDebug(" %s", foundry->name.isEmpty() ? "(empty foundry)" :
488 qPrintable(foundry->name));
489 for (int s = 0; s < foundry->count; s++) {
490 QtFontStyle *style = foundry->styles[s];
491 qDebug(" style: style=%d weight=%d smooth=%d", style->key.style,
492 style->key.weight, style->smoothScalable);
493 for(int i = 0; i < style->count; ++i) {
494 if (style->pixelSizes[i].pixelSize == SMOOTH_SCALABLE)
495 qDebug(" smooth %s:%d",
496 style->pixelSizes[i].fileName.constData(),
497 style->pixelSizes[i].fileIndex);
498 else
499 qDebug(" %d px %s:%d", style->pixelSizes[i].pixelSize,
500 style->pixelSizes[i].fileName.constData(),
501 style->pixelSizes[i].fileIndex);
502 }
503 }
504 }
505#endif
506 }
507#endif // QFONTDATABASE_DEBUG
508}
509
510static inline void load(const QString &family = QString(), int = -1)
511{
512 populateDatabase(family);
513}
514
515static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
516{
517 // @todo implement
518}
519
520static QFontDef fontDescToFontDef(const QFontDef &req, const QtFontDesc &desc)
521{
522 static LONG dpi = -1;
523 if (dpi == -1) {
524 // PM cannot change resolutions on the fly so cache it
525 int hps = qt_display_ps();
526 DevQueryCaps(GpiQueryDevice(hps), CAPS_HORIZONTAL_FONT_RES, 1, &dpi);
527 }
528
529 QFontDef fontDef;
530
531 fontDef.family = desc.family->name;
532
533 if (desc.size->pixelSize == SMOOTH_SCALABLE) {
534 // scalable font matched, calculate the missing size (points or pixels)
535 fontDef.pointSize = req.pointSize;
536 fontDef.pixelSize = req.pixelSize;
537 if (req.pointSize < 0) {
538 fontDef.pointSize = req.pixelSize * 72. / dpi;
539 } else if (req.pixelSize == -1) {
540 fontDef.pixelSize = qRound(req.pointSize * dpi / 72.);
541 }
542 } else {
543 // non-scalable font matched, calculate both point and pixel size
544 fontDef.pixelSize = desc.size->pixelSize;
545 fontDef.pointSize = desc.size->pixelSize * 72. / dpi;
546 }
547
548 fontDef.styleStrategy = req.styleStrategy;
549 fontDef.styleHint = req.styleHint;
550
551 fontDef.weight = desc.style->key.weight;
552 fontDef.fixedPitch = desc.family->fixedPitch;
553 fontDef.style = desc.style->key.style;
554 fontDef.stretch = desc.style->key.stretch;
555
556 return fontDef;
557}
558
559static QFontEngine *loadEngine(const QFontDef &req, const QtFontDesc &desc)
560{
561 // @todo all these fixed so far; make configurable through the Registry
562 // on per-family basis
563 QFontEnginePMFT::HintStyle hintStyle = QFontEnginePMFT::HintFull;
564 bool autoHint = true;
565 QFontEngineFT::SubpixelAntialiasingType subPixel = QFontEngineFT::Subpixel_None;
566 int lcdFilter = FT_LCD_FILTER_DEFAULT;
567 bool useEmbeddedBitmap = true;
568
569 QFontEngine::FaceId faceId;
570 faceId.filename = desc.size->fileName;
571 faceId.index = desc.size->fileIndex;
572
573 QFontEngineFT *fe = new QFontEnginePMFT(fontDescToFontDef(req, desc), faceId,
574 desc.style->antialiased, hintStyle,
575 autoHint, subPixel, lcdFilter,
576 useEmbeddedBitmap);
577 Q_ASSERT(fe);
578 if (fe && fe->invalid()) {
579 FM_DEBUG(" --> invalid!\n");
580 delete fe;
581 fe = 0;
582 }
583 return fe;
584}
585
586static QFontEngine *loadPM(const QFontPrivate *d, int script, const QFontDef &req)
587{
588 // list of families to try
589 QStringList families = familyList(req);
590
591 const char *styleHint = qt_fontFamilyFromStyleHint(d->request);
592 if (styleHint)
593 families << QLatin1String(styleHint);
594
595 // add the default family
596 QString defaultFamily = QApplication::font().family();
597 if (! families.contains(defaultFamily))
598 families << defaultFamily;
599
600 // add QFont::defaultFamily() to the list, for compatibility with
601 // previous versions
602 families << QApplication::font().defaultFamily();
603
604 // null family means find the first font matching the specified script
605 families << QString();
606
607 QtFontDesc desc;
608 QFontEngine *fe = 0;
609 QList<int> blacklistedFamilies;
610
611 while (!fe) {
612 for (int i = 0; i < families.size(); ++i) {
613 QString family, foundry;
614 parseFontName(families.at(i), foundry, family);
615 FM_DEBUG("loadPM: >>>>>>>>>>>>>> trying to match '%s'", qPrintable(family));
616 QT_PREPEND_NAMESPACE(match)(script, req, family, foundry, -1, &desc, blacklistedFamilies);
617 if (desc.family)
618 break;
619 }
620 if (!desc.family)
621 break;
622 FM_DEBUG("loadPM: ============== matched '%s'", qPrintable(desc.family->name));
623 fe = loadEngine(req, desc);
624 if (!fe)
625 blacklistedFamilies.append(desc.familyIndex);
626 }
627 return fe;
628}
629
630void QFontDatabase::load(const QFontPrivate *d, int script)
631{
632 Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
633
634 // normalize the request to get better caching
635 QFontDef req = d->request;
636 if (req.pixelSize <= 0)
637 req.pixelSize = qMax(1, qRound(req.pointSize * d->dpi / 72.));
638 req.pointSize = 0;
639 if (req.weight == 0)
640 req.weight = QFont::Normal;
641 if (req.stretch == 0)
642 req.stretch = 100;
643
644 QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen);
645 if (!d->engineData)
646 getEngineData(d, key);
647
648 // the cached engineData could have already loaded the engine we want
649 if (d->engineData->engines[script])
650 return;
651
652 // set it to the actual pointsize, so QFontInfo will do the right thing
653 req.pointSize = req.pixelSize * 72. / d->dpi;
654
655 QFontEngine *fe = QFontCache::instance()->findEngine(key);
656
657 if (!fe) {
658 if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
659 fe = new QTestFontEngine(req.pixelSize);
660 fe->fontDef = req;
661 } else {
662 QMutexLocker locker(fontDatabaseMutex());
663 if (!privateDb()->count)
664 initializeDb();
665 fe = loadPM(d, script, req);
666 }
667 if (!fe) {
668 fe = new QFontEngineBox(req.pixelSize);
669 fe->fontDef = QFontDef();
670 }
671 }
672 if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
673 for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
674 if (!d->engineData->engines[i]) {
675 d->engineData->engines[i] = fe;
676 fe->ref.ref();
677 }
678 }
679 } else {
680 d->engineData->engines[script] = fe;
681 fe->ref.ref();
682 }
683 QFontCache::instance()->insertEngine(key, fe);
684}
685
686bool QFontDatabase::removeApplicationFont(int handle)
687{
688 // @todo implement
689 return false;
690}
691
692bool QFontDatabase::removeAllApplicationFonts()
693{
694 // @todo implement
695 return false;
696}
697
698bool QFontDatabase::supportsThreadedFontRendering()
699{
700 // @todo implement
701 return false;
702}
703
704QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.