1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include <private/qapplication_p.h>
45 #include "qfontengine_s60_p.h"
46 #include "qabstractfileengine.h"
47 #include "qdesktopservices.h"
48 #include "qtemporaryfile.h"
49 #include <private/qpixmap_s60_p.h>
50 #include <private/qt_s60_p.h>
52 #include <private/qcore_symbian_p.h>
55 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
56 #include <graphics/openfontrasterizer.h> // COpenFontRasterizer has moved to a new header file
57 #endif // SYMBIAN_ENABLE_SPLIT_HEADERS
58 #endif // QT_NO_FREETYPE
62 QStringList qt_symbian_fontFamiliesOnFontServer() // Also used in qfont_s60.cpp
65 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
66 const int numTypeFaces = S60->screenDevice()->NumTypefaces();
67 for (int i = 0; i < numTypeFaces; i++) {
68 TTypefaceSupport typefaceSupport;
69 S60->screenDevice()->TypefaceSupport(typefaceSupport, i);
70 const QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length());
71 result.append(familyName);
77 QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameFilters,
78 QDir::Filters filters = QDir::NoFilter, QDir::SortFlags sort = QDir::NoSort,
79 bool uniqueFileNames = true)
83 // Prepare a 'soft to hard' drive list: W:, X: ... A:, Z:
84 QStringList driveStrings;
85 foreach (const QFileInfo &drive, QDir::drives())
86 driveStrings.append(drive.absolutePath());
88 const QString zDriveString(QLatin1String("Z:/"));
89 driveStrings.removeAll(zDriveString);
90 driveStrings.prepend(zDriveString);
92 QStringList uniqueFileNameList;
93 for (int i = driveStrings.count() - 1; i >= 0; --i) {
94 const QDir dirOnDrive(driveStrings.at(i) + path);
95 const QFileInfoList entriesOnDrive = dirOnDrive.entryInfoList(nameFilters, filters, sort);
96 if (uniqueFileNames) {
97 foreach(const QFileInfo &entry, entriesOnDrive) {
98 if (!uniqueFileNameList.contains(entry.fileName())) {
99 uniqueFileNameList.append(entry.fileName());
100 result.append(entry);
104 result.append(entriesOnDrive);
110 #ifdef QT_NO_FREETYPE
111 class QSymbianFontDatabaseExtrasImplementation : public QSymbianFontDatabaseExtras
114 QSymbianFontDatabaseExtrasImplementation();
115 ~QSymbianFontDatabaseExtrasImplementation();
117 const QSymbianTypeFaceExtras *extras(const QString &typeface, bool bold, bool italic) const;
118 void removeAppFontData(QFontDatabasePrivate::ApplicationFont *fnt);
119 static inline bool appFontLimitReached();
120 TUid addFontFileToFontStore(const QFileInfo &fontFileInfo);
123 static inline QString tempAppFontFolder();
124 static const QString appFontMarkerPrefix;
125 static QString appFontMarker(); // 'qaf<shortUid[+shortPid]>'
127 struct CFontFromFontStoreReleaser {
128 static inline void cleanup(CFont *font)
132 const QSymbianFontDatabaseExtrasImplementation *dbExtras =
133 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(privateDb()->symbianExtras);
134 dbExtras->m_store->ReleaseFont(font);
138 struct CFontFromScreenDeviceReleaser {
139 static inline void cleanup(CFont *font)
143 S60->screenDevice()->ReleaseFont(font);
147 // m_heap, m_store, m_rasterizer and m_extras are used if Symbian
148 // does not provide the Font Table API
151 COpenFontRasterizer *m_rasterizer;
152 mutable QList<const QSymbianTypeFaceExtras *> m_extras;
154 mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extrasHash;
157 const QString QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix =
158 QLatin1String("qaf");
160 inline QString QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()
162 return QDir::toNativeSeparators(QDir::tempPath()) + QLatin1Char('\\');
165 QString QSymbianFontDatabaseExtrasImplementation::appFontMarker()
167 static QString result;
168 if (result.isEmpty()) {
169 const quint32 uid = RProcess().Type().MostDerived().iUid;
170 quint16 crossSum = static_cast<quint16>(uid + (uid >> 16));
171 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
172 // If no font table Api is available, we must not even load a font
173 // from a previous (crashed) run of this application. Reason: we
174 // won't get the font tables, they are not in the CFontStore.
175 // So, we add the pid to the uniqueness of the marker.
176 const quint32 pid = static_cast<quint32>(RProcess().Id().Id());
177 crossSum += static_cast<quint16>(pid + (pid >> 16));
179 result = appFontMarkerPrefix + QString::number(crossSum, 16);
184 QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementation()
186 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
188 filters.append(QLatin1String("*.ttf"));
189 filters.append(QLatin1String("*.ccc"));
190 filters.append(QLatin1String("*.ltt"));
191 const QFileInfoList fontFiles = alternativeFilePaths(QLatin1String("resource\\Fonts"), filters);
193 const TInt heapMinLength = 0x1000;
194 const TInt heapMaxLength = qMax(0x20000 * fontFiles.count(), heapMinLength);
195 m_heap = User::ChunkHeap(NULL, heapMinLength, heapMaxLength);
197 m_store = CFontStore::NewL(m_heap);
198 m_rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E));
199 CleanupStack::PushL(m_rasterizer);
200 m_store->InstallRasterizerL(m_rasterizer);
201 CleanupStack::Pop(m_rasterizer););
203 foreach (const QFileInfo &fontFileInfo, fontFiles)
204 addFontFileToFontStore(fontFileInfo);
208 void QSymbianFontDatabaseExtrasImplementation::clear()
210 QFontDatabasePrivate *db = privateDb();
213 const QSymbianFontDatabaseExtrasImplementation *dbExtras =
214 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
216 return; // initializeDb() has never been called
217 if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
218 qDeleteAll(dbExtras->m_extrasHash);
220 typedef QList<const QSymbianTypeFaceExtras *>::iterator iterator;
221 for (iterator p = dbExtras->m_extras.begin(); p != dbExtras->m_extras.end(); ++p) {
222 dbExtras->m_store->ReleaseFont((*p)->fontOwner());
225 dbExtras->m_extras.clear();
227 dbExtras->m_extrasHash.clear();
230 void qt_cleanup_symbianFontDatabase()
232 QFontDatabasePrivate *db = privateDb();
236 QSymbianFontDatabaseExtrasImplementation::clear();
238 if (!db->applicationFonts.isEmpty()) {
239 QFontDatabase::removeAllApplicationFonts();
240 // We remove the left over temporary font files of Qt application.
241 // Active fonts are undeletable since the font server holds a handle
242 // on them, so we do not need to worry to delete other running
243 // applications' fonts.
244 const QDir dir(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder());
245 const QStringList filter(
246 QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix + QLatin1String("*.ttf"));
247 foreach (const QFileInfo &ttfFile, dir.entryInfoList(filter))
248 QFile(ttfFile.absoluteFilePath()).remove();
249 db->applicationFonts.clear();
253 QSymbianFontDatabaseExtrasImplementation::~QSymbianFontDatabaseExtrasImplementation()
255 qt_cleanup_symbianFontDatabase();
256 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
262 #ifndef FNTSTORE_H_INLINES_SUPPORT_FMM
264 Workaround: fntstore.h has an inlined function 'COpenFont* CBitmapFont::OpenFont()'
265 that returns a private data member. The header will change between SDKs. But Qt has
266 to build on any SDK version and run on other versions of Symbian OS.
267 This function performs the needed pointer arithmetic to get the right COpenFont*
269 COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont)
271 const TInt offsetIOpenFont = 92; // '_FOFF(CBitmapFont, iOpenFont)' ..if iOpenFont weren't private
272 const TUint valueIOpenFont = *(TUint*)PtrAdd(aBitmapFont, offsetIOpenFont);
273 return (valueIOpenFont & 1) ?
274 (COpenFont*)PtrAdd(aBitmapFont, valueIOpenFont & ~1) : // New behavior: iOpenFont is offset
275 (COpenFont*)valueIOpenFont; // Old behavior: iOpenFont is pointer
277 #endif // FNTSTORE_H_INLINES_SUPPORT_FMM
279 const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &typeface,
280 bool bold, bool italic) const
282 const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic));
283 if (!m_extrasHash.contains(searchKey)) {
284 TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1);
286 searchSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
288 searchSpec.iFontStyle.SetPosture(EPostureItalic);
291 if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
292 const TInt err = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(font, searchSpec);
293 Q_ASSERT(err == KErrNone && font);
294 QScopedPointer<CFont, CFontFromScreenDeviceReleaser> sFont(font);
295 QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font);
297 m_extrasHash.insert(searchKey, extras);
299 const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, searchSpec);
300 Q_ASSERT(err == KErrNone && font);
301 const CBitmapFont *bitmapFont = static_cast<CBitmapFont*>(font);
302 COpenFont *openFont =
303 #ifdef FNTSTORE_H_INLINES_SUPPORT_FMM
304 bitmapFont->OpenFont();
305 #else // FNTSTORE_H_INLINES_SUPPORT_FMM
306 OpenFontFromBitmapFont(bitmapFont);
307 #endif // FNTSTORE_H_INLINES_SUPPORT_FMM
308 const TOpenFontFaceAttrib* const attrib = openFont->FaceAttrib();
309 const QString foundKey =
310 QString((const QChar*)attrib->FullName().Ptr(), attrib->FullName().Length());
311 if (!m_extrasHash.contains(foundKey)) {
312 QScopedPointer<CFont, CFontFromFontStoreReleaser> sFont(font);
313 QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font, openFont);
315 m_extras.append(extras);
316 m_extrasHash.insert(searchKey, extras);
317 m_extrasHash.insert(foundKey, extras);
319 m_store->ReleaseFont(font);
320 m_extrasHash.insert(searchKey, m_extrasHash.value(foundKey));
324 return m_extrasHash.value(searchKey);
327 void QSymbianFontDatabaseExtrasImplementation::removeAppFontData(
328 QFontDatabasePrivate::ApplicationFont *fnt)
331 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()
332 && fnt->fontStoreFontFileUid.iUid != 0)
333 m_store->RemoveFile(fnt->fontStoreFontFileUid);
334 if (fnt->screenDeviceFontFileId != 0)
335 S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId);
336 QFile::remove(fnt->temporaryFileName);
337 *fnt = QFontDatabasePrivate::ApplicationFont();
340 bool QSymbianFontDatabaseExtrasImplementation::appFontLimitReached()
342 QFontDatabasePrivate *db = privateDb();
345 const int maxAppFonts = 5;
346 int registeredAppFonts = 0;
347 foreach (const QFontDatabasePrivate::ApplicationFont &appFont, db->applicationFonts)
348 if (!appFont.families.isEmpty() && ++registeredAppFonts == maxAppFonts)
353 TUid QSymbianFontDatabaseExtrasImplementation::addFontFileToFontStore(const QFileInfo &fontFileInfo)
355 Q_ASSERT(!QSymbianTypeFaceExtras::symbianFontTableApiAvailable());
356 const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath());
357 const TPtrC fontFilePtr(qt_QString2TPtrC(fontFile));
359 TRAP_IGNORE(fontUid = m_store->AddFileL(fontFilePtr));
363 #else // QT_NO_FREETYPE
364 class QFontEngineFTS60 : public QFontEngineFT
367 QFontEngineFTS60(const QFontDef &fd);
370 QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd)
373 default_hint_style = HintFull;
375 #endif // QT_NO_FREETYPE
378 QFontEngineS60::pixelsToPoints, QFontEngineS60::pointsToPixels, QFontEngineMultiS60::QFontEngineMultiS60
379 and QFontEngineMultiS60::QFontEngineMultiS60 should be in qfontengine_s60.cpp. But since also the
380 Freetype based font rendering need them, they are here.
382 qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation)
384 CWsScreenDevice* device = S60->screenDevice();
385 return (orientation == Qt::Horizontal?
386 device->HorizontalPixelsToTwips(pixels)
387 :device->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint;
390 qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation)
392 CWsScreenDevice* device = S60->screenDevice();
393 const int twips = points * KTwipsPerPoint;
394 return orientation == Qt::Horizontal?
395 device->HorizontalTwipsToPixels(twips)
396 :device->VerticalTwipsToPixels(twips);
399 QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies)
400 : QFontEngineMulti(fallbackFamilies.size() + 1)
402 , m_fallbackFamilies(fallbackFamilies)
406 fontDef = engines[0]->fontDef;
409 void QFontEngineMultiS60::loadEngine(int at)
411 Q_ASSERT(at < engines.size());
412 Q_ASSERT(engines.at(at) == 0);
414 QFontDef request = fontDef;
415 request.styleStrategy |= QFont::NoFontMerging;
416 request.family = m_fallbackFamilies.at(at-1);
417 engines[at] = QFontDatabase::findFont(m_script,
420 Q_ASSERT(engines[at]);
423 static bool registerScreenDeviceFont(int screenDeviceFontIndex,
424 const QSymbianFontDatabaseExtrasImplementation *dbExtras)
426 TTypefaceSupport typefaceSupport;
427 S60->screenDevice()->TypefaceSupport(typefaceSupport, screenDeviceFontIndex);
428 CFont *font; // We have to get a font instance in order to know all the details
429 TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11);
430 if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone)
432 QScopedPointer<CFont, QSymbianFontDatabaseExtrasImplementation::CFontFromScreenDeviceReleaser> sFont(font);
433 if (font->TypeUid() != KCFbsFontUid)
435 TOpenFontFaceAttrib faceAttrib;
436 const CFbsFont *cfbsFont = static_cast<const CFbsFont *>(font);
437 cfbsFont->GetFaceAttrib(faceAttrib);
439 QtFontStyle::Key styleKey;
440 styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal;
441 styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal;
443 QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length());
444 QtFontFamily *family = privateDb()->family(familyName, true);
445 family->fixedPitch = faceAttrib.IsMonoWidth();
446 QtFontFoundry *foundry = family->foundry(QString(), true);
447 QtFontStyle *style = foundry->style(styleKey, true);
448 style->smoothScalable = typefaceSupport.iIsScalable;
449 style->pixelSize(0, true);
451 const QSymbianTypeFaceExtras *typeFaceExtras =
452 dbExtras->extras(familyName, faceAttrib.IsBold(), faceAttrib.IsItalic());
453 const QByteArray os2Table = typeFaceExtras->getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
454 const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData());
455 const unsigned char* ulUnicodeRange = data + 42;
456 quint32 unicodeRange[4] = {
457 qFromBigEndian<quint32>(ulUnicodeRange),
458 qFromBigEndian<quint32>(ulUnicodeRange + 4),
459 qFromBigEndian<quint32>(ulUnicodeRange + 8),
460 qFromBigEndian<quint32>(ulUnicodeRange + 12)
462 const unsigned char* ulCodePageRange = data + 78;
463 quint32 codePageRange[2] = {
464 qFromBigEndian<quint32>(ulCodePageRange),
465 qFromBigEndian<quint32>(ulCodePageRange + 4)
467 const QList<QFontDatabase::WritingSystem> writingSystems =
468 determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
469 foreach (const QFontDatabase::WritingSystem system, writingSystems)
470 family->writingSystems[system] = QtFontFamily::Supported;
474 static void initializeDb()
476 QFontDatabasePrivate *db = privateDb();
480 #ifdef QT_NO_FREETYPE
481 if (!db->symbianExtras)
482 db->symbianExtras = new QSymbianFontDatabaseExtrasImplementation;
484 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
486 const int numTypeFaces = S60->screenDevice()->NumTypefaces();
487 const QSymbianFontDatabaseExtrasImplementation *dbExtras =
488 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
489 for (int i = 0; i < numTypeFaces; i++)
490 registerScreenDeviceFont(i, dbExtras);
492 // We have to clear/release all CFonts, here, in case one of the fonts is
493 // an application font of another running Qt app. Otherwise the other Qt app
494 // cannot remove it's application font, anymore -> "Zombie Font".
495 QSymbianFontDatabaseExtrasImplementation::clear();
499 #else // QT_NO_FREETYPE
500 QDir dir(QDesktopServices::storageLocation(QDesktopServices::FontsLocation));
501 dir.setNameFilters(QStringList() << QLatin1String("*.ttf")
502 << QLatin1String("*.ttc") << QLatin1String("*.pfa")
503 << QLatin1String("*.pfb"));
504 for (int i = 0; i < int(dir.count()); ++i) {
505 const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i]));
508 #endif // QT_NO_FREETYPE
511 static inline void load(const QString &family = QString(), int script = -1)
518 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
520 if (QSysInfo::symbianVersion() <= QSysInfo::SV_SF_2)
521 return; // See QTBUG-16514 for what 'font collisions' can cause in Symbian^1 and lower
523 if (QSymbianFontDatabaseExtrasImplementation::appFontLimitReached())
526 QFontDatabasePrivate *db = privateDb();
533 if (fnt->data.isEmpty() && !fnt->fileName.endsWith(QLatin1String(".ttf"), Qt::CaseInsensitive))
534 return; // Only buffer or .ttf
535 QSymbianFontDatabaseExtrasImplementation *dbExtras =
536 static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
540 // The QTemporaryFile object being used in the following section must be
541 // destructed before letting Symbian load the TTF file. Symbian would not
542 // load it otherwise, because QTemporaryFile will still keep some handle
543 // on it. The scope is used to reduce the life time of the QTemporaryFile.
544 // In order to prevent other processes from modifying the file between the
545 // moment where the QTemporaryFile is destructed and the file is loaded by
546 // Symbian, we have a QFile "tempFileGuard" outside the scope which opens
547 // the file in ReadOnly mode while the QTemporaryFile is still alive.
550 QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()
551 + QSymbianFontDatabaseExtrasImplementation::appFontMarker()
552 + QLatin1String("XXXXXX.ttf"));
553 if (!tempfile.open())
555 const QString tempFileName = QFileInfo(tempfile).canonicalFilePath();
556 if (fnt->data.isEmpty()) {
557 QFile sourceFile(fnt->fileName);
558 if (!sourceFile.open(QIODevice::ReadOnly))
560 fnt->data = sourceFile.readAll();
562 if (tempfile.write(fnt->data) == -1)
564 tempfile.setAutoRemove(false);
565 tempfile.close(); // Tempfile still keeps a file handle, forbidding write access
566 tempFileGuard.setFileName(tempFileName);
567 if (!tempFileGuard.open(QIODevice::ReadOnly))
569 fnt->temporaryFileName = tempFileName;
572 const QString fullFileName = QDir::toNativeSeparators(fnt->temporaryFileName);
573 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
574 const QStringList fontsOnServerBefore = qt_symbian_fontFamiliesOnFontServer();
576 S60->screenDevice()->AddFile(qt_QString2TPtrC(fullFileName), fnt->screenDeviceFontFileId);
577 tempFileGuard.close(); // Did its job
578 const QStringList fontsOnServerAfter = qt_symbian_fontFamiliesOnFontServer();
579 if (err == KErrNone && fontsOnServerBefore.count() < fontsOnServerAfter.count()) { // Added to screen device?
580 int fontOnServerIndex = fontsOnServerAfter.count() - 1;
581 for (int i = 0; i < fontsOnServerBefore.count(); i++) {
582 if (fontsOnServerBefore.at(i) != fontsOnServerAfter.at(i)) {
583 fontOnServerIndex = i;
588 // Must remove all font engines with their CFonts, first.
589 QFontCache::instance()->clear();
591 QSymbianFontDatabaseExtrasImplementation::clear();
593 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable())
594 fnt->fontStoreFontFileUid = dbExtras->addFontFileToFontStore(QFileInfo(fullFileName));
596 fnt->families.append(fontsOnServerAfter.at(fontOnServerIndex));
597 if (!registerScreenDeviceFont(fontOnServerIndex, dbExtras))
598 dbExtras->removeAppFontData(fnt);
600 QFile::remove(fnt->temporaryFileName);
601 *fnt = QFontDatabasePrivate::ApplicationFont();
606 bool QFontDatabase::removeApplicationFont(int handle)
608 QMutexLocker locker(fontDatabaseMutex());
610 QFontDatabasePrivate *db = privateDb();
611 if (!db || handle < 0 || handle >= db->applicationFonts.count())
613 QSymbianFontDatabaseExtrasImplementation *dbExtras =
614 static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
618 QFontDatabasePrivate::ApplicationFont *fnt = &db->applicationFonts[handle];
619 if (fnt->families.isEmpty())
620 return true; // Nothing to remove. Return peacefully.
622 // Must remove all font engines with their CFonts, first
623 QFontCache::instance()->clear();
625 dbExtras->removeAppFontData(fnt);
627 db->invalidate(); // This will just emit 'fontDatabaseChanged()'
631 bool QFontDatabase::removeAllApplicationFonts()
633 QMutexLocker locker(fontDatabaseMutex());
635 const int applicationFontsCount = privateDb()->applicationFonts.count();
636 for (int i = 0; i < applicationFontsCount; ++i)
637 if (!removeApplicationFont(i))
642 bool QFontDatabase::supportsThreadedFontRendering()
648 QFontDef cleanedFontDef(const QFontDef &req)
650 QFontDef result = req;
651 if (result.pixelSize <= 0) {
652 result.pixelSize = QFontEngineS60::pointsToPixels(qMax(qreal(1.0), result.pointSize));
653 result.pointSize = 0;
658 QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *d, const QFontDef &req)
660 const QFontCache::Key key(cleanedFontDef(req), script);
662 if (!privateDb()->count)
665 QFontEngine *fe = QFontCache::instance()->findEngine(key);
667 // Making sure that fe->fontDef.family will be an existing font.
669 QFontDatabasePrivate *db = privateDb();
671 QList<int> blacklistedFamilies;
672 match(script, req, req.family, QString(), -1, &desc, blacklistedFamilies);
673 if (!desc.family) // falling back to application font
674 desc.family = db->family(QApplication::font().defaultFamily());
675 Q_ASSERT(desc.family);
677 // Making sure that desc.family supports the requested script
678 QtFontDesc mappedDesc;
679 bool supportsScript = false;
681 match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies);
682 if (mappedDesc.family == desc.family) {
683 supportsScript = true;
686 blacklistedFamilies.append(mappedDesc.familyIndex);
687 } while (mappedDesc.family);
688 if (!supportsScript) {
689 blacklistedFamilies.clear();
690 match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies);
691 if (mappedDesc.family)
695 const QString fontFamily = desc.family->name;
696 QFontDef request = req;
697 request.family = fontFamily;
698 #ifdef QT_NO_FREETYPE
699 const QSymbianFontDatabaseExtrasImplementation *dbExtras =
700 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
701 const QSymbianTypeFaceExtras *typeFaceExtras =
702 dbExtras->extras(fontFamily, request.weight > QFont::Normal, request.style != QFont::StyleNormal);
704 // We need a valid pixelSize, e.g. for lineThickness()
705 if (request.pixelSize < 0)
706 request.pixelSize = request.pointSize * d->dpi / 72;
708 fe = new QFontEngineS60(request, typeFaceExtras);
709 #else // QT_NO_FREETYPE
711 QFontEngine::FaceId faceId;
712 const QtFontFamily * const reqQtFontFamily = db->family(fontFamily);
713 faceId.filename = reqQtFontFamily->fontFilename;
714 faceId.index = reqQtFontFamily->fontFileIndex;
716 QFontEngineFTS60 *fte = new QFontEngineFTS60(cleanedFontDef(request));
717 if (fte->init(faceId, true, QFontEngineFT::Format_A8))
721 #endif // QT_NO_FREETYPE
724 if (script == QUnicodeTables::Common
725 && !(req.styleStrategy & QFont::NoFontMerging)
728 QStringList commonFonts;
729 for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
730 if (scriptForWritingSystem[ws] != script)
732 for (int i = 0; i < db->count; ++i) {
733 if (db->families[i]->writingSystems[ws] & QtFontFamily::Supported)
734 commonFonts.append(db->families[i]->name);
738 // Hack: Prioritize .ccc fonts
739 const QString niceEastAsianFont(QLatin1String("Sans MT 936_S60"));
740 if (commonFonts.removeAll(niceEastAsianFont) > 0)
741 commonFonts.prepend(niceEastAsianFont);
743 fe = new QFontEngineMultiS60(fe, script, commonFonts);
747 QFontCache::instance()->insertEngine(key, fe);
751 void QFontDatabase::load(const QFontPrivate *d, int script)
754 QFontDef req = d->request;
756 if (!d->engineData) {
757 const QFontCache::Key key(cleanedFontDef(req), script);
758 getEngineData(d, key);
761 // the cached engineData could have already loaded the engine we want
762 if (d->engineData->engines[script])
763 fe = d->engineData->engines[script];
766 if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
767 fe = new QTestFontEngine(req.pixelSize);
770 fe = findFont(script, d, req);
772 d->engineData->engines[script] = fe;