Make text rendering working outside the gui thread on Symbian.
It was previously not possible to render text (QPainter::drawText) in a secondary thread on Symbian, it always resulted in some kind of panic. This patch corrects it. For S60 5.0 and earlier the behavior is not changed, threaded text rendering is only supported on Symbian^3 and newer. This also means QFontDatabase::supportsThreadedFontRendering() will return true from now on, but only on Symbian^3 and higher. Task-number: QTBUG-18516 Reviewed-by: mread (cherry picked from commit 0c62e02b80570bf8b92eff7acceb9018df61c89e)
This commit is contained in:
parent
af6057918a
commit
d4eedda7d2
@ -2703,6 +2703,9 @@ QS60ThreadLocalData::QS60ThreadLocalData()
|
||||
|
||||
QS60ThreadLocalData::~QS60ThreadLocalData()
|
||||
{
|
||||
for (int i = 0; i < releaseFuncs.count(); ++i)
|
||||
releaseFuncs[i]();
|
||||
releaseFuncs.clear();
|
||||
if (!usingCONEinstances) {
|
||||
delete screenDevice;
|
||||
wsSession.Close();
|
||||
|
@ -97,6 +97,10 @@ static const int qt_symbian_max_screens = 4;
|
||||
//this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2
|
||||
#define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13)
|
||||
|
||||
class QSymbianTypeFaceExtras;
|
||||
typedef QHash<QString, const QSymbianTypeFaceExtras *> QSymbianTypeFaceExtrasHash;
|
||||
typedef void (*QThreadLocalReleaseFunc)();
|
||||
|
||||
class Q_AUTOTEST_EXPORT QS60ThreadLocalData
|
||||
{
|
||||
public:
|
||||
@ -105,6 +109,8 @@ public:
|
||||
bool usingCONEinstances;
|
||||
RWsSession wsSession;
|
||||
CWsScreenDevice *screenDevice;
|
||||
QSymbianTypeFaceExtrasHash fontData;
|
||||
QVector<QThreadLocalReleaseFunc> releaseFuncs;
|
||||
};
|
||||
|
||||
class QS60Data
|
||||
@ -175,6 +181,8 @@ public:
|
||||
inline CWsScreenDevice* screenDevice(const QWidget *widget);
|
||||
inline CWsScreenDevice* screenDevice(int screenNumber);
|
||||
static inline int screenNumberForWidget(const QWidget *widget);
|
||||
inline QSymbianTypeFaceExtrasHash& fontData();
|
||||
inline void addThreadLocalReleaseFunc(QThreadLocalReleaseFunc func);
|
||||
static inline CCoeAppUi* appUi();
|
||||
static inline CEikMenuBar* menuBar();
|
||||
#ifdef Q_WS_S60
|
||||
@ -470,6 +478,24 @@ inline int QS60Data::screenNumberForWidget(const QWidget *widget)
|
||||
return qt_widget_private(const_cast<QWidget *>(w))->symbianScreenNumber;
|
||||
}
|
||||
|
||||
inline QSymbianTypeFaceExtrasHash& QS60Data::fontData()
|
||||
{
|
||||
if (!tls.hasLocalData()) {
|
||||
tls.setLocalData(new QS60ThreadLocalData);
|
||||
}
|
||||
return tls.localData()->fontData;
|
||||
}
|
||||
|
||||
inline void QS60Data::addThreadLocalReleaseFunc(QThreadLocalReleaseFunc func)
|
||||
{
|
||||
if (!tls.hasLocalData()) {
|
||||
tls.setLocalData(new QS60ThreadLocalData);
|
||||
}
|
||||
QS60ThreadLocalData *data = tls.localData();
|
||||
if (!data->releaseFuncs.contains(func))
|
||||
data->releaseFuncs.append(func);
|
||||
}
|
||||
|
||||
inline CCoeAppUi* QS60Data::appUi()
|
||||
{
|
||||
return CCoeEnv::Static()-> AppUi();
|
||||
|
@ -152,7 +152,6 @@ public:
|
||||
COpenFontRasterizer *m_rasterizer;
|
||||
mutable QList<const QSymbianTypeFaceExtras *> m_extras;
|
||||
|
||||
mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extrasHash;
|
||||
mutable QSet<QString> m_applicationFontFamilies;
|
||||
};
|
||||
|
||||
@ -255,8 +254,9 @@ void QSymbianFontDatabaseExtrasImplementation::clear()
|
||||
static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
|
||||
if (!dbExtras)
|
||||
return; // initializeDb() has never been called
|
||||
QSymbianTypeFaceExtrasHash &extrasHash = S60->fontData();
|
||||
if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
|
||||
qDeleteAll(dbExtras->m_extrasHash);
|
||||
qDeleteAll(extrasHash);
|
||||
} else {
|
||||
typedef QList<const QSymbianTypeFaceExtras *>::iterator iterator;
|
||||
for (iterator p = dbExtras->m_extras.begin(); p != dbExtras->m_extras.end(); ++p) {
|
||||
@ -265,11 +265,16 @@ void QSymbianFontDatabaseExtrasImplementation::clear()
|
||||
}
|
||||
dbExtras->m_extras.clear();
|
||||
}
|
||||
dbExtras->m_extrasHash.clear();
|
||||
extrasHash.clear();
|
||||
}
|
||||
|
||||
void qt_cleanup_symbianFontDatabase()
|
||||
{
|
||||
static bool cleanupDone = false;
|
||||
if (cleanupDone)
|
||||
return;
|
||||
cleanupDone = true;
|
||||
|
||||
QFontDatabasePrivate *db = privateDb();
|
||||
if (!db)
|
||||
return;
|
||||
@ -320,9 +325,12 @@ COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont)
|
||||
const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &aTypeface,
|
||||
bool bold, bool italic) const
|
||||
{
|
||||
QSymbianTypeFaceExtrasHash &extrasHash = S60->fontData();
|
||||
if (extrasHash.isEmpty() && QThread::currentThread() != QApplication::instance()->thread())
|
||||
S60->addThreadLocalReleaseFunc(clear);
|
||||
const QString typeface = qt_symbian_fontNameWithAppFontMarker(aTypeface);
|
||||
const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic));
|
||||
if (!m_extrasHash.contains(searchKey)) {
|
||||
if (!extrasHash.contains(searchKey)) {
|
||||
TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1);
|
||||
if (bold)
|
||||
searchSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
|
||||
@ -336,7 +344,7 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c
|
||||
QScopedPointer<CFont, CFontFromScreenDeviceReleaser> sFont(font);
|
||||
QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font);
|
||||
sFont.take();
|
||||
m_extrasHash.insert(searchKey, extras);
|
||||
extrasHash.insert(searchKey, extras);
|
||||
} else {
|
||||
const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, searchSpec);
|
||||
Q_ASSERT(err == KErrNone && font);
|
||||
@ -350,20 +358,20 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c
|
||||
const TOpenFontFaceAttrib* const attrib = openFont->FaceAttrib();
|
||||
const QString foundKey =
|
||||
QString((const QChar*)attrib->FullName().Ptr(), attrib->FullName().Length());
|
||||
if (!m_extrasHash.contains(foundKey)) {
|
||||
if (!extrasHash.contains(foundKey)) {
|
||||
QScopedPointer<CFont, CFontFromFontStoreReleaser> sFont(font);
|
||||
QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font, openFont);
|
||||
sFont.take();
|
||||
m_extras.append(extras);
|
||||
m_extrasHash.insert(searchKey, extras);
|
||||
m_extrasHash.insert(foundKey, extras);
|
||||
extrasHash.insert(searchKey, extras);
|
||||
extrasHash.insert(foundKey, extras);
|
||||
} else {
|
||||
m_store->ReleaseFont(font);
|
||||
m_extrasHash.insert(searchKey, m_extrasHash.value(foundKey));
|
||||
extrasHash.insert(searchKey, extrasHash.value(foundKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_extrasHash.value(searchKey);
|
||||
return extrasHash.value(searchKey);
|
||||
}
|
||||
|
||||
void QSymbianFontDatabaseExtrasImplementation::removeAppFontData(
|
||||
@ -956,7 +964,7 @@ bool QFontDatabase::removeAllApplicationFonts()
|
||||
|
||||
bool QFontDatabase::supportsThreadedFontRendering()
|
||||
{
|
||||
return false;
|
||||
return QSymbianTypeFaceExtras::symbianFontTableApiAvailable();
|
||||
}
|
||||
|
||||
static
|
||||
|
Loading…
Reference in New Issue
Block a user