summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorBea Lam <bea.lam@nokia.com>2011-01-27 04:03:13 (GMT)
committerBea Lam <bea.lam@nokia.com>2011-01-27 04:03:13 (GMT)
commit05ba01a2519996a3dffaab2e498dc3d2a999dc45 (patch)
treec478929354b59407bea92e885baf0eecb4e351c8 /src/gui
parentf15778e60ba538b8715f6433a472ffe08a21d934 (diff)
parent5c91e32a6238fd112a7282443214c8686cda51de (diff)
downloadQt-05ba01a2519996a3dffaab2e498dc3d2a999dc45.zip
Qt-05ba01a2519996a3dffaab2e498dc3d2a999dc45.tar.gz
Qt-05ba01a2519996a3dffaab2e498dc3d2a999dc45.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into qtquick11
Conflicts: src/declarative/graphicsitems/qdeclarativegridview.cpp src/declarative/graphicsitems/qdeclarativelistview.cpp
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/image/qgifhandler.cpp10
-rw-r--r--src/gui/kernel/qapplication_s60.cpp4
-rw-r--r--src/gui/kernel/qkeymapper_x11_p.cpp1
-rw-r--r--src/gui/kernel/qmacgesturerecognizer_mac.mm6
-rw-r--r--src/gui/kernel/qwidget_p.h2
-rw-r--r--src/gui/kernel/qwidget_x11.cpp78
-rw-r--r--src/gui/painting/qdrawhelper.cpp2
-rw-r--r--src/gui/styles/qs60style_s60.cpp8
-rw-r--r--src/gui/text/qfontdatabase.cpp20
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp551
-rw-r--r--src/gui/text/qfontengine_s60.cpp5
-rw-r--r--src/gui/text/qtextdocument_p.cpp4
-rw-r--r--src/gui/widgets/qcombobox.cpp16
13 files changed, 648 insertions, 59 deletions
diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp
index 4dd4743..7cb7373 100644
--- a/src/gui/image/qgifhandler.cpp
+++ b/src/gui/image/qgifhandler.cpp
@@ -1046,7 +1046,7 @@ QGifHandler::QGifHandler()
{
gifFormat = new QGIFFormat;
nextDelay = 100;
- loopCnt = 1;
+ loopCnt = -1;
frameNumber = -1;
scanIsCached = false;
}
@@ -1192,7 +1192,13 @@ int QGifHandler::loopCount() const
QGIFFormat::scan(device(), &imageSizes, &loopCnt);
scanIsCached = true;
}
- return loopCnt-1; // In GIF, loop count is iteration count, so subtract one
+
+ if (loopCnt == 0)
+ return -1;
+ else if (loopCnt == -1)
+ return 0;
+ else
+ return loopCnt;
}
int QGifHandler::currentImageNumber() const
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index ba06312..40a7ec6 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -1616,7 +1616,7 @@ void qt_init(QApplicationPrivate * /* priv */, int)
qRegisterMetaType<WId>("WId");
}
-extern void qt_cleanup_symbianFontDatabaseExtras(); // qfontdatabase_s60.cpp
+extern void qt_cleanup_symbianFontDatabase(); // qfontdatabase_s60.cpp
/*****************************************************************************
qt_cleanup() - cleans up when the application is finished
@@ -1630,7 +1630,7 @@ void qt_cleanup()
QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles
QPixmapCache::clear(); // Has to happen now, since QS60PixmapData has FBS handles
- qt_cleanup_symbianFontDatabaseExtras();
+ qt_cleanup_symbianFontDatabase();
// S60 structure and window server session are freed in eventdispatcher destructor as they are needed there
// It's important that this happens here, before the event dispatcher gets
diff --git a/src/gui/kernel/qkeymapper_x11_p.cpp b/src/gui/kernel/qkeymapper_x11_p.cpp
index 1fad4b0..2dbe1e7 100644
--- a/src/gui/kernel/qkeymapper_x11_p.cpp
+++ b/src/gui/kernel/qkeymapper_x11_p.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
// This file is auto-generated, do not edit!
+// (Generated using util/xkbdatagen)
static struct {
const char *layout;
diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm
index 0e432f3..6a4f0bb 100644
--- a/src/gui/kernel/qmacgesturerecognizer_mac.mm
+++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm
@@ -69,6 +69,7 @@ QMacSwipeGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e
case QNativeGestureEvent::Swipe: {
QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture);
g->setSwipeAngle(ev->angle);
+ g->setHotSpot(ev->position);
return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint;
break; }
default:
@@ -110,6 +111,7 @@ QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e
g->setCenterPoint(g->startCenterPoint());
g->setChangeFlags(QPinchGesture::CenterPointChanged);
g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags());
+ g->setHotSpot(ev->position);
return QGestureRecognizer::MayBeGesture | QGestureRecognizer::ConsumeEventHint;
case QNativeGestureEvent::Rotate: {
g->setLastScaleFactor(g->scaleFactor());
@@ -117,6 +119,7 @@ QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e
g->setRotationAngle(g->rotationAngle() + ev->percentage);
g->setChangeFlags(QPinchGesture::RotationAngleChanged);
g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags());
+ g->setHotSpot(ev->position);
return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint;
}
case QNativeGestureEvent::Zoom:
@@ -125,6 +128,7 @@ QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e
g->setScaleFactor(g->scaleFactor() * (1 + ev->percentage));
g->setChangeFlags(QPinchGesture::ScaleFactorChanged);
g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags());
+ g->setHotSpot(ev->position);
return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint;
case QNativeGestureEvent::GestureEnd:
return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint;
@@ -221,6 +225,7 @@ QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent *
const QPointF posOffset = p - _startPos;
g->setLastOffset(g->offset());
g->setOffset(QPointF(posOffset.x(), posOffset.y()));
+ g->setHotSpot(_startPos);
return QGestureRecognizer::TriggerGesture;
}
} else if (_panTimer.isActive()) {
@@ -239,6 +244,7 @@ QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent *
break;
// Begin new pan session!
_startPos = QCursor::pos();
+ g->setHotSpot(_startPos);
return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint;
}
break; }
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 693984a..3759dd1 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -767,6 +767,8 @@ public:
void x11UpdateIsOpaque();
bool isBackgroundInherited() const;
void updateX11AcceptFocus();
+ QPoint mapToGlobal(const QPoint &pos) const;
+ QPoint mapFromGlobal(const QPoint &pos) const;
#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
#ifndef QT_NO_GESTURES
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index a93c545..9893478 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -1280,39 +1280,77 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
#endif
}
-
-QPoint QWidget::mapToGlobal(const QPoint &pos) const
+QPoint QWidgetPrivate::mapToGlobal(const QPoint &pos) const
{
- Q_D(const QWidget);
- if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
- QPoint p = pos + data->crect.topLeft();
+ Q_Q(const QWidget);
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) {
+ QPoint p = pos + q->data->crect.topLeft();
//cannot trust that !isWindow() implies parentWidget() before create
- return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p);
+ return (q->isWindow() || !q->parentWidget()) ? p : q->parentWidget()->d_func()->mapToGlobal(p);
}
- int x, y;
+ int x, y;
Window child;
- QPoint p = d->mapToWS(pos);
- XTranslateCoordinates(X11->display, internalWinId(),
- QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
+ QPoint p = mapToWS(pos);
+ XTranslateCoordinates(X11->display, q->internalWinId(),
+ QApplication::desktop()->screen(xinfo.screen())->internalWinId(),
p.x(), p.y(), &x, &y, &child);
return QPoint(x, y);
}
-
-QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const
{
- Q_D(const QWidget);
- if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+ Q_Q(const QWidget);
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) {
//cannot trust that !isWindow() implies parentWidget() before create
- QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos);
- return p - data->crect.topLeft();
+ QPoint p = (q->isWindow() || !q->parentWidget()) ? pos : q->parentWidget()->d_func()->mapFromGlobal(pos);
+ return p - q->data->crect.topLeft();
}
- int x, y;
+ int x, y;
Window child;
XTranslateCoordinates(X11->display,
- QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
- internalWinId(), pos.x(), pos.y(), &x, &y, &child);
- return d->mapFromWS(QPoint(x, y));
+ QApplication::desktop()->screen(xinfo.screen())->internalWinId(),
+ q->internalWinId(), pos.x(), pos.y(), &x, &y, &child);
+ return mapFromWS(QPoint(x, y));
+}
+
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ QPoint offset = data->crect.topLeft();
+ const QWidget *w = this;
+ const QWidget *p = w->parentWidget();
+ while (!w->isWindow() && p) {
+ w = p;
+ p = p->parentWidget();
+ offset += w->data->crect.topLeft();
+ }
+
+ const QWidgetPrivate *wd = w->d_func();
+ QTLWExtra *tlw = wd->topData();
+ if (!tlw->embedded)
+ return pos + offset;
+
+ return d->mapToGlobal(pos);
+}
+
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ QPoint offset = data->crect.topLeft();
+ const QWidget *w = this;
+ const QWidget *p = w->parentWidget();
+ while (!w->isWindow() && p) {
+ w = p;
+ p = p->parentWidget();
+ offset += w->data->crect.topLeft();
+ }
+
+ const QWidgetPrivate *wd = w->d_func();
+ QTLWExtra *tlw = wd->topData();
+ if (!tlw->embedded)
+ return pos - offset;
+
+ return d->mapFromGlobal(pos);
}
void QWidgetPrivate::updateSystemBackground()
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 9928dea..5904296 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -43,7 +43,9 @@
#include <private/qpaintengine_raster_p.h>
#include <private/qpainter_p.h>
#include <private/qdrawhelper_x86_p.h>
+#ifdef QT_HAVE_ARM_SIMD
#include <private/qdrawhelper_arm_simd_p.h>
+#endif
#include <private/qdrawhelper_neon_p.h>
#include <private/qmath_p.h>
#include <qmath.h>
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
index 04c40aa..605872e 100644
--- a/src/gui/styles/qs60style_s60.cpp
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -1378,12 +1378,13 @@ QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, Skin
QPixmap QS60StylePrivate::backgroundTexture()
{
bool createNewBackground = false;
+ TRect applicationRect = (static_cast<CEikAppUi*>(S60->appUi())->ApplicationRect());
if (!m_background) {
createNewBackground = true;
} else {
//if background brush does not match screensize, re-create it
- if (m_background->width() != S60->screenWidthInPixels ||
- m_background->height() != S60->screenHeightInPixels) {
+ if (m_background->width() != applicationRect.Width() ||
+ m_background->height() != applicationRect.Height()) {
delete m_background;
createNewBackground = true;
}
@@ -1391,7 +1392,7 @@ QPixmap QS60StylePrivate::backgroundTexture()
if (createNewBackground) {
QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen,
- QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), 0, SkinElementFlags());
+ QSize(applicationRect.Width(), applicationRect.Height()), 0, SkinElementFlags());
m_background = new QPixmap(background);
}
return *m_background;
@@ -1411,7 +1412,6 @@ QS60Style::QS60Style()
void QS60StylePrivate::handleDynamicLayoutVariantSwitch()
{
clearCaches(QS60StylePrivate::CC_LayoutChange);
- setBackgroundTexture(qApp);
setActiveLayout();
refreshUI();
foreach (QWidget *widget, QApplication::allWidgets())
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 5cecf08..6b612eb 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -624,6 +624,10 @@ public:
{ }
~QFontDatabasePrivate() {
free();
+#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+ if (symbianExtras)
+ delete symbianExtras;
+#endif
}
QtFontFamily *family(const QString &f, bool = false);
void free() {
@@ -632,12 +636,6 @@ public:
::free(families);
families = 0;
count = 0;
-#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
- if (symbianExtras) {
- delete symbianExtras;
- symbianExtras = 0;
- }
-#endif
// don't clear the memory fonts!
}
@@ -653,6 +651,10 @@ public:
QVector<FONTSIGNATURE> signatures;
#elif defined(Q_WS_MAC)
ATSFontContainerRef handle;
+#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+ QString temporaryFileName;
+ TInt screenDeviceFontFileId;
+ TUid fontStoreFontFileUid;
#endif
QStringList families;
};
@@ -680,7 +682,7 @@ public:
QDataStream *stream;
QStringList fallbackFamilies;
#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
- const QSymbianFontDatabaseExtras *symbianExtras;
+ QSymbianFontDatabaseExtras *symbianExtras;
#endif
};
@@ -2541,6 +2543,8 @@ bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
\note Adding application fonts on Unix/X11 platforms without fontconfig is
currently not supported.
+ \note On Symbian, the font family names get truncated to a length of 20 characters.
+
\sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont()
*/
int QFontDatabase::addApplicationFont(const QString &fileName)
@@ -2571,6 +2575,8 @@ int QFontDatabase::addApplicationFont(const QString &fileName)
\bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is
currently not supported.
+ \note On Symbian, the font family names get truncated to a length of 20 characters.
+
\sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont()
*/
int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 6ba035e..97426a8 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -45,6 +45,8 @@
#include "qfontengine_s60_p.h"
#include "qabstractfileengine.h"
#include "qdesktopservices.h"
+#include "qtemporaryfile.h"
+#include "qtextcodec.h"
#include <private/qpixmap_s60_p.h>
#include <private/qt_s60_p.h>
#include "qendian.h"
@@ -114,7 +116,14 @@ public:
~QSymbianFontDatabaseExtrasImplementation();
const QSymbianTypeFaceExtras *extras(const QString &typeface, bool bold, bool italic) const;
- void addFontFileToFontStore(const QFileInfo &fontFileInfo);
+ void removeAppFontData(QFontDatabasePrivate::ApplicationFont *fnt);
+ static inline bool appFontLimitReached();
+ TUid addFontFileToFontStore(const QFileInfo &fontFileInfo);
+ static void clear();
+
+ static inline QString tempAppFontFolder();
+ static const QString appFontMarkerPrefix;
+ static QString appFontMarker(); // 'qaf<shortUid[+shortPid]>'
struct CFontFromFontStoreReleaser {
static inline void cleanup(CFont *font)
@@ -144,8 +153,75 @@ public:
mutable QList<const QSymbianTypeFaceExtras *> m_extras;
mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extrasHash;
+ mutable QSet<QString> m_applicationFontFamilies;
};
+const QString QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix =
+ QLatin1String("Q");
+
+inline QString QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()
+{
+ return QDir::toNativeSeparators(QDir::tempPath()) + QLatin1Char('\\');
+}
+
+QString QSymbianFontDatabaseExtrasImplementation::appFontMarker()
+{
+ static QString result;
+ if (result.isEmpty()) {
+ quint16 id = 0;
+ if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
+ // We are allowed to load app fonts even from previous, crashed runs
+ // of this application, since we can access the font tables.
+ const quint32 uid = RProcess().Type().MostDerived().iUid;
+ id = static_cast<quint16>(uid + (uid >> 16));
+ } else {
+ // If no font table Api is available, we must not even load a font
+ // from a previous (crashed) run of this application. Reason: we
+ // won't get the font tables, they are not in the CFontStore.
+ // So, we use the pid, for more uniqueness.
+ id = static_cast<quint16>(RProcess().Id().Id());
+ }
+ result = appFontMarkerPrefix + QString::fromLatin1("%1").arg(id & 0x7fff, 3, 32, QLatin1Char('0'));
+ Q_ASSERT(appFontMarkerPrefix.length() == 1 && result.length() == 4);
+ }
+ return result;
+}
+
+static inline bool qt_symbian_fontNameHasAppFontMarker(const QString &fontName)
+{
+ const int idLength = 3; // Keep in sync with id length in appFontMarker().
+ const QString &prefix = QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix;
+ if (fontName.length() < prefix.length() + idLength
+ || fontName.mid(fontName.length() - idLength - prefix.length(), prefix.length()) != prefix)
+ return false;
+ // Testing if the the id is base32 data
+ for (int i = fontName.length() - idLength; i < fontName.length(); ++i) {
+ const QChar &c = fontName.at(i);
+ if (!(c >= QLatin1Char('0') && c <= QLatin1Char('9')
+ || c >= QLatin1Char('a') && c <= QLatin1Char('v')))
+ return false;
+ }
+ return true;
+}
+
+// If fontName is an application font of this app, prepend the app font marker
+QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName)
+{
+ QFontDatabasePrivate *db = privateDb();
+ Q_ASSERT(db);
+ const QSymbianFontDatabaseExtrasImplementation *dbExtras =
+ static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
+ return dbExtras->m_applicationFontFamilies.contains(fontName) ?
+ fontName + QSymbianFontDatabaseExtrasImplementation::appFontMarker()
+ : fontName;
+}
+
+static inline QString qt_symbian_appFontNameWithoutMarker(const QString &markedFontName)
+{
+ return markedFontName.left(markedFontName.length()
+ - QSymbianFontDatabaseExtrasImplementation::appFontMarker().length());
+}
+
QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementation()
{
if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
@@ -170,10 +246,13 @@ QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementati
}
}
-void qt_cleanup_symbianFontDatabaseExtras()
+void QSymbianFontDatabaseExtrasImplementation::clear()
{
+ QFontDatabasePrivate *db = privateDb();
+ if (!db)
+ return;
const QSymbianFontDatabaseExtrasImplementation *dbExtras =
- static_cast<const QSymbianFontDatabaseExtrasImplementation*>(privateDb()->symbianExtras);
+ static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
if (!dbExtras)
return; // initializeDb() has never been called
if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
@@ -189,9 +268,32 @@ void qt_cleanup_symbianFontDatabaseExtras()
dbExtras->m_extrasHash.clear();
}
+void qt_cleanup_symbianFontDatabase()
+{
+ QFontDatabasePrivate *db = privateDb();
+ if (!db)
+ return;
+
+ QSymbianFontDatabaseExtrasImplementation::clear();
+
+ if (!db->applicationFonts.isEmpty()) {
+ QFontDatabase::removeAllApplicationFonts();
+ // We remove the left over temporary font files of Qt application.
+ // Active fonts are undeletable since the font server holds a handle
+ // on them, so we do not need to worry to delete other running
+ // applications' fonts.
+ const QDir dir(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder());
+ const QStringList filter(
+ QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix + QLatin1String("*.ttf"));
+ foreach (const QFileInfo &ttfFile, dir.entryInfoList(filter))
+ QFile(ttfFile.absoluteFilePath()).remove();
+ db->applicationFonts.clear();
+ }
+}
+
QSymbianFontDatabaseExtrasImplementation::~QSymbianFontDatabaseExtrasImplementation()
{
- qt_cleanup_symbianFontDatabaseExtras();
+ qt_cleanup_symbianFontDatabase();
if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
delete m_store;
m_heap->Close();
@@ -215,9 +317,10 @@ COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont)
}
#endif // FNTSTORE_H_INLINES_SUPPORT_FMM
-const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &typeface,
+const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &aTypeface,
bool bold, bool italic) const
{
+ const QString typeface = qt_symbian_fontNameWithAppFontMarker(aTypeface);
const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic));
if (!m_extrasHash.contains(searchKey)) {
TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1);
@@ -263,12 +366,42 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c
return m_extrasHash.value(searchKey);
}
-void QSymbianFontDatabaseExtrasImplementation::addFontFileToFontStore(const QFileInfo &fontFileInfo)
+void QSymbianFontDatabaseExtrasImplementation::removeAppFontData(
+ QFontDatabasePrivate::ApplicationFont *fnt)
+{
+ clear();
+ if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()
+ && fnt->fontStoreFontFileUid.iUid != 0)
+ m_store->RemoveFile(fnt->fontStoreFontFileUid);
+ if (!fnt->families.isEmpty())
+ m_applicationFontFamilies.remove(fnt->families.first());
+ if (fnt->screenDeviceFontFileId != 0)
+ S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId);
+ QFile::remove(fnt->temporaryFileName);
+ *fnt = QFontDatabasePrivate::ApplicationFont();
+}
+
+bool QSymbianFontDatabaseExtrasImplementation::appFontLimitReached()
+{
+ QFontDatabasePrivate *db = privateDb();
+ if (!db)
+ return false;
+ const int maxAppFonts = 5;
+ int registeredAppFonts = 0;
+ foreach (const QFontDatabasePrivate::ApplicationFont &appFont, db->applicationFonts)
+ if (!appFont.families.isEmpty() && ++registeredAppFonts == maxAppFonts)
+ return true;
+ return false;
+}
+
+TUid QSymbianFontDatabaseExtrasImplementation::addFontFileToFontStore(const QFileInfo &fontFileInfo)
{
Q_ASSERT(!QSymbianTypeFaceExtras::symbianFontTableApiAvailable());
const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath());
- TPtrC fontFilePtr(qt_QString2TPtrC(fontFile));
- QT_TRAP_THROWING(m_store->AddFileL(fontFilePtr));
+ const TPtrC fontFilePtr(qt_QString2TPtrC(fontFile));
+ TUid fontUid = {0};
+ TRAP_IGNORE(fontUid = m_store->AddFileL(fontFilePtr));
+ return fontUid;
}
#else // QT_NO_FREETYPE
@@ -331,11 +464,23 @@ void QFontEngineMultiS60::loadEngine(int at)
Q_ASSERT(engines[at]);
}
-static bool addFontToScreenDevice(int screenDeviceFontIndex,
- const QSymbianFontDatabaseExtrasImplementation *dbExtras)
-{
+static bool registerScreenDeviceFont(int screenDeviceFontIndex,
+ const QSymbianFontDatabaseExtrasImplementation *dbExtras)
+{
TTypefaceSupport typefaceSupport;
S60->screenDevice()->TypefaceSupport(typefaceSupport, screenDeviceFontIndex);
+
+ QString familyName((const QChar*)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length());
+ if (qt_symbian_fontNameHasAppFontMarker(familyName)) {
+ const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker();
+ if (familyName.endsWith(marker)) {
+ familyName = qt_symbian_appFontNameWithoutMarker(familyName);
+ dbExtras->m_applicationFontFamilies.insert(familyName);
+ } else {
+ return false; // This was somebody else's application font. Skip it.
+ }
+ }
+
CFont *font; // We have to get a font instance in order to know all the details
TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11);
if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone)
@@ -351,7 +496,6 @@ static bool addFontToScreenDevice(int screenDeviceFontIndex,
styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal;
styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal;
- QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length());
QtFontFamily *family = privateDb()->family(familyName, true);
family->fixedPitch = faceAttrib.IsMonoWidth();
QtFontFoundry *foundry = family->foundry(QString(), true);
@@ -398,7 +542,12 @@ static void initializeDb()
const QSymbianFontDatabaseExtrasImplementation *dbExtras =
static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
for (int i = 0; i < numTypeFaces; i++)
- addFontToScreenDevice(i, dbExtras);
+ registerScreenDeviceFont(i, dbExtras);
+
+ // We have to clear/release all CFonts, here, in case one of the fonts is
+ // an application font of another running Qt app. Otherwise the other Qt app
+ // cannot remove it's application font, anymore -> "Zombie Font".
+ QSymbianFontDatabaseExtrasImplementation::clear();
lock.relock();
@@ -421,20 +570,386 @@ static inline void load(const QString &family = QString(), int script = -1)
initializeDb();
}
+struct OffsetTable {
+ quint32 sfntVersion;
+ quint16 numTables, searchRange, entrySelector, rangeShift;
+};
+
+struct TableRecord {
+ quint32 tag, checkSum, offset, length;
+};
+
+struct NameTableHead {
+ quint16 format, count, stringOffset;
+};
+
+struct NameRecord {
+ quint16 platformID, encodingID, languageID, nameID, length, offset;
+};
+
+static quint32 ttfCalcChecksum(const char *data, quint32 bytesCount)
+{
+ quint32 result = 0;
+ const quint32 *ptr = reinterpret_cast<const quint32*>(data);
+ const quint32 *endPtr =
+ ptr + (bytesCount + sizeof(quint32) - 1) / sizeof(quint32);
+ while (ptr < endPtr) {
+ const quint32 unit32Value = *ptr++;
+ result += qFromBigEndian(unit32Value);
+ }
+ return result;
+}
+
+static inline quint32 toDWordBoundary(quint32 value)
+{
+ return (value + 3) & ~3;
+}
+
+static inline quint32 dWordPadding(quint32 value)
+{
+ return (4 - (value & 3)) & 3;
+}
+
+static inline bool ttfMarkNameTable(QByteArray &table, const QString &marker)
+{
+ const quint32 tableLength = static_cast<quint32>(table.size());
+
+ if (tableLength > 50000 // hard limit
+ || tableLength < sizeof(NameTableHead)) // corrupt name table
+ return false;
+
+ const NameTableHead *head = reinterpret_cast<const NameTableHead*>(table.constData());
+ const quint16 count = qFromBigEndian(head->count);
+ const quint16 stringOffset = qFromBigEndian(head->stringOffset);
+ if (count > 200 // hard limit
+ || stringOffset >= tableLength // corrupt name table
+ || sizeof(NameTableHead) + count * sizeof(NameRecord) >= tableLength) // corrupt name table
+ return false;
+
+ QTextEncoder encoder(QTextCodec::codecForName("UTF-16BE"), QTextCodec::IgnoreHeader);
+ const QByteArray markerUtf16BE = encoder.fromUnicode(marker);
+ const QByteArray markerAscii = marker.toAscii();
+
+ QByteArray markedTable;
+ markedTable.reserve(tableLength + marker.length() * 20); // Original size plus some extra
+ markedTable.append(table, stringOffset);
+ QByteArray markedStrings;
+ quint32 stringDataCount = stringOffset;
+ for (quint16 i = 0; i < count; ++i) {
+ const quint32 nameRecordOffset = sizeof(NameTableHead) + sizeof(NameRecord) * i;
+ NameRecord *nameRecord =
+ reinterpret_cast<NameRecord*>(markedTable.data() + nameRecordOffset);
+ const quint16 nameID = qFromBigEndian(nameRecord->nameID);
+ const quint16 platformID = qFromBigEndian(nameRecord->platformID);
+ const quint16 encodingID = qFromBigEndian(nameRecord->encodingID);
+ const quint16 offset = qFromBigEndian(nameRecord->offset);
+ const quint16 length = qFromBigEndian(nameRecord->length);
+ stringDataCount += length;
+ if (stringDataCount > 80000 // hard limit. String data may be > name table size. Multiple records can reference the same string.
+ || static_cast<quint32>(stringOffset + offset + length) > tableLength) // String outside bounds
+ return false;
+ const bool needsMarker =
+ nameID == 1 || nameID == 3 || nameID == 4 || nameID == 16 || nameID == 21;
+ const bool isUnicode =
+ platformID == 0 || platformID == 3 && encodingID == 1;
+ const QByteArray originalString =
+ QByteArray::fromRawData(table.constData() + stringOffset + offset, length);
+ QByteArray markedString;
+ if (needsMarker) {
+ const int maxBytesLength = (KMaxTypefaceNameLength - marker.length()) * (isUnicode ? 2 : 1);
+ markedString = originalString.left(maxBytesLength) + (isUnicode ? markerUtf16BE : markerAscii);
+ } else {
+ markedString = originalString;
+ }
+ nameRecord->offset = qToBigEndian(static_cast<quint16>(markedStrings.length()));
+ nameRecord->length = qToBigEndian(static_cast<quint16>(markedString.length()));
+ markedStrings.append(markedString);
+ }
+ markedTable.append(markedStrings);
+ table = markedTable;
+ return true;
+}
+
+const quint32 ttfMaxFileSize = 3500000;
+
+static inline bool ttfMarkAppFont(QByteArray &ttf, const QString &marker)
+{
+ const quint32 ttfChecksumNumber = 0xb1b0afba;
+ const quint32 alignment = 4;
+ const quint32 ttfLength = static_cast<quint32>(ttf.size());
+ if (ttfLength > ttfMaxFileSize // hard limit
+ || ttfLength % alignment != 0 // ttf sizes are always factors of 4
+ || ttfLength <= sizeof(OffsetTable) // ttf too short
+ || ttfCalcChecksum(ttf.constData(), ttf.size()) != ttfChecksumNumber) // ttf checksum is invalid
+ return false;
+
+ const OffsetTable *offsetTable = reinterpret_cast<const OffsetTable*>(ttf.constData());
+ const quint16 numTables = qFromBigEndian(offsetTable->numTables);
+ const quint32 recordsLength =
+ toDWordBoundary(sizeof(OffsetTable) + numTables * sizeof(TableRecord));
+ if (numTables > 30 // hard limit
+ || recordsLength + numTables * alignment > ttfLength) // Corrupt ttf. Tables would not fit, even if empty.
+ return false;
+
+ QByteArray markedTtf;
+ markedTtf.reserve(ttfLength + marker.length() * 20); // Original size plus some extra
+ markedTtf.append(ttf.constData(), recordsLength);
+
+ const quint32 ttfCheckSumAdjustmentOffset = 8; // Offset from the start of 'head'
+ int indexOfHeadTable = -1;
+ quint32 ttfDataSize = recordsLength;
+ typedef QPair<quint32, quint32> Range;
+ QList<Range> memoryRanges;
+ memoryRanges.reserve(numTables);
+ for (int i = 0; i < numTables; ++i) {
+ TableRecord *tableRecord =
+ reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord));
+ const quint32 offset = qFromBigEndian(tableRecord->offset);
+ const quint32 length = qFromBigEndian(tableRecord->length);
+ const quint32 lengthAligned = toDWordBoundary(length);
+ ttfDataSize += lengthAligned;
+ if (offset < recordsLength // must not intersect ttf header/records
+ || offset % alignment != 0 // must be aligned
+ || offset > ttfLength - alignment // table out of bounds
+ || offset + lengthAligned > ttfLength // table out of bounds
+ || ttfDataSize > ttfLength) // tables would not fit into the ttf
+ return false;
+
+ foreach (const Range &range, memoryRanges)
+ if (offset < range.first + range.second && offset + lengthAligned > range.first)
+ return false; // Overlaps with another table
+ memoryRanges.append(Range(offset, lengthAligned));
+
+ quint32 checkSum = qFromBigEndian(tableRecord->checkSum);
+ if (tableRecord->tag == qToBigEndian(static_cast<quint32>('head'))) {
+ if (length < ttfCheckSumAdjustmentOffset + sizeof(quint32))
+ return false; // Invalid 'head' table
+ const quint32 *checkSumAdjustmentTag =
+ reinterpret_cast<const quint32*>(ttf.constData() + offset + ttfCheckSumAdjustmentOffset);
+ const quint32 checkSumAdjustment = qFromBigEndian(*checkSumAdjustmentTag);
+ checkSum += checkSumAdjustment;
+ indexOfHeadTable = i; // For the ttf checksum re-calculation, later
+ }
+ if (checkSum != ttfCalcChecksum(ttf.constData() + offset, length))
+ return false; // Table checksum is invalid
+
+ bool updateTableChecksum = false;
+ QByteArray table;
+ if (tableRecord->tag == qToBigEndian(static_cast<quint32>('name'))) {
+ table = QByteArray(ttf.constData() + offset, length);
+ if (!ttfMarkNameTable(table, marker))
+ return false; // Name table was not markable.
+ updateTableChecksum = true;
+ } else {
+ table = QByteArray::fromRawData(ttf.constData() + offset, length);
+ }
+
+ tableRecord->offset = qToBigEndian(markedTtf.size());
+ tableRecord->length = qToBigEndian(table.size());
+ markedTtf.append(table);
+ markedTtf.append(QByteArray(dWordPadding(table.size()), 0)); // 0-padding
+ if (updateTableChecksum) {
+ TableRecord *tableRecord = // Need to recalculate, since markedTtf changed
+ reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord));
+ const quint32 offset = qFromBigEndian(tableRecord->offset);
+ const quint32 length = qFromBigEndian(tableRecord->length);
+ tableRecord->checkSum = qToBigEndian(ttfCalcChecksum(markedTtf.constData() + offset, length));
+ }
+ }
+ if (indexOfHeadTable == -1 // 'head' table is mandatory
+ || ttfDataSize != ttfLength) // We do not allow ttf data "holes". Neither does Symbian.
+ return false;
+ TableRecord *headRecord =
+ reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + indexOfHeadTable * sizeof(TableRecord));
+ quint32 *checkSumAdjustmentTag =
+ reinterpret_cast<quint32*>(markedTtf.data() + qFromBigEndian(headRecord->offset) + ttfCheckSumAdjustmentOffset);
+ *checkSumAdjustmentTag = 0;
+ const quint32 ttfChecksum = ttfCalcChecksum(markedTtf.constData(), markedTtf.count());
+ *checkSumAdjustmentTag = qToBigEndian(ttfChecksumNumber - ttfChecksum);
+ ttf = markedTtf;
+ return true;
+}
+
+static inline bool ttfCanSymbianLoadFont(const QByteArray &data, const QString &fileName)
+{
+ bool result = false;
+ QString ttfFileName;
+ QFile tempFileGuard;
+ QFileInfo info(fileName);
+ if (!data.isEmpty()) {
+ QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()
+ + QSymbianFontDatabaseExtrasImplementation::appFontMarker()
+ + QLatin1String("XXXXXX.ttf"));
+ if (!tempfile.open() || tempfile.write(data) == -1)
+ return false;
+ ttfFileName = QDir::toNativeSeparators(QFileInfo(tempfile).canonicalFilePath());
+ tempfile.setAutoRemove(false);
+ tempfile.close();
+ tempFileGuard.setFileName(ttfFileName);
+ if (!tempFileGuard.open(QIODevice::ReadOnly))
+ return false;
+ } else if (info.isFile()) {
+ ttfFileName = QDir::toNativeSeparators(info.canonicalFilePath());
+ } else {
+ return false;
+ }
+
+ CFontStore *store = 0;
+ RHeap* heap = User::ChunkHeap(NULL, 0x1000, 0x20000);
+ if (heap) {
+ QT_TRAP_THROWING(
+ CleanupClosePushL(*heap);
+ store = CFontStore::NewL(heap);
+ CleanupStack::PushL(store);
+ COpenFontRasterizer *rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E));
+ CleanupStack::PushL(rasterizer);
+ store->InstallRasterizerL(rasterizer);
+ CleanupStack::Pop(rasterizer);
+ TUid fontUid = {-1};
+ TRAP_IGNORE(fontUid = store->AddFileL(qt_QString2TPtrC(ttfFileName)));
+ if (fontUid.iUid != -1)
+ result = true;
+ CleanupStack::PopAndDestroy(2, heap); // heap, store
+ );
+ }
+
+ if (tempFileGuard.isOpen())
+ tempFileGuard.remove();
+
+ return result;
+}
+
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
{
- Q_UNUSED(fnt);
+ if (QSymbianFontDatabaseExtrasImplementation::appFontLimitReached()
+ || fnt->data.size() > ttfMaxFileSize // hard limit
+ || fnt->data.isEmpty() && (!fnt->fileName.endsWith(QLatin1String(".ttf"), Qt::CaseInsensitive) // Only buffer or .ttf
+ || QFileInfo(fnt->fileName).size() > ttfMaxFileSize)) // hard limit
+ return;
+
+// Using ttfCanSymbianLoadFont() causes crashes on app destruction (Symbian^3|PR1 and lower).
+// Therefore, not using it for now, but eventually in a later version.
+// if (!ttfCanSymbianLoadFont(fnt->data, fnt->fileName))
+// return;
+
+ QFontDatabasePrivate *db = privateDb();
+ if (!db)
+ return;
+
+ if (!db->count)
+ initializeDb();
+
+ QSymbianFontDatabaseExtrasImplementation *dbExtras =
+ static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
+ if (!dbExtras)
+ return;
+
+ const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker();
+
+ // The QTemporaryFile object being used in the following section must be
+ // destructed before letting Symbian load the TTF file. Symbian would not
+ // load it otherwise, because QTemporaryFile will still keep some handle
+ // on it. The scope is used to reduce the life time of the QTemporaryFile.
+ // In order to prevent other processes from modifying the file between the
+ // moment where the QTemporaryFile is destructed and the file is loaded by
+ // Symbian, we have a QFile "tempFileGuard" outside the scope which opens
+ // the file in ReadOnly mode while the QTemporaryFile is still alive.
+ QFile tempFileGuard;
+ {
+ QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()
+ + marker + QLatin1String("XXXXXX.ttf"));
+ if (!tempfile.open())
+ return;
+ const QString tempFileName = QFileInfo(tempfile).canonicalFilePath();
+ if (fnt->data.isEmpty()) {
+ QFile sourceFile(fnt->fileName);
+ if (!sourceFile.open(QIODevice::ReadOnly))
+ return;
+ fnt->data = sourceFile.readAll();
+ }
+ if (!ttfMarkAppFont(fnt->data, marker) || tempfile.write(fnt->data) == -1)
+ return;
+ tempfile.setAutoRemove(false);
+ tempfile.close(); // Tempfile still keeps a file handle, forbidding write access
+ fnt->data.clear(); // The TTF data was marked and saved. Not needed in memory, anymore.
+ tempFileGuard.setFileName(tempFileName);
+ if (!tempFileGuard.open(QIODevice::ReadOnly))
+ return;
+ fnt->temporaryFileName = tempFileName;
+ }
+
+ const QString fullFileName = QDir::toNativeSeparators(fnt->temporaryFileName);
+ QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
+ const QStringList fontsOnServerBefore = qt_symbian_fontFamiliesOnFontServer();
+ const TInt err =
+ S60->screenDevice()->AddFile(qt_QString2TPtrC(fullFileName), fnt->screenDeviceFontFileId);
+ tempFileGuard.close(); // Did its job
+ const QStringList fontsOnServerAfter = qt_symbian_fontFamiliesOnFontServer();
+ if (err == KErrNone && fontsOnServerBefore.count() < fontsOnServerAfter.count()) { // Added to screen device?
+ int fontOnServerIndex = fontsOnServerAfter.count() - 1;
+ for (int i = 0; i < fontsOnServerBefore.count(); i++) {
+ if (fontsOnServerBefore.at(i) != fontsOnServerAfter.at(i)) {
+ fontOnServerIndex = i;
+ break;
+ }
+ }
+
+ // Must remove all font engines with their CFonts, first.
+ QFontCache::instance()->clear();
+ db->free();
+ QSymbianFontDatabaseExtrasImplementation::clear();
+
+ if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable())
+ fnt->fontStoreFontFileUid = dbExtras->addFontFileToFontStore(QFileInfo(fullFileName));
+
+ const QString &appFontName = fontsOnServerAfter.at(fontOnServerIndex);
+ fnt->families.append(qt_symbian_appFontNameWithoutMarker(appFontName));
+ if (!qt_symbian_fontNameHasAppFontMarker(appFontName)
+ || !registerScreenDeviceFont(fontOnServerIndex, dbExtras))
+ dbExtras->removeAppFontData(fnt);
+ } else {
+ if (fnt->screenDeviceFontFileId > 0)
+ S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); // May still have the file open!
+ QFile::remove(fnt->temporaryFileName);
+ *fnt = QFontDatabasePrivate::ApplicationFont();
+ }
+ lock.relock();
}
bool QFontDatabase::removeApplicationFont(int handle)
{
- Q_UNUSED(handle);
- return false;
+ QMutexLocker locker(fontDatabaseMutex());
+
+ QFontDatabasePrivate *db = privateDb();
+ if (!db || handle < 0 || handle >= db->applicationFonts.count())
+ return false;
+ QSymbianFontDatabaseExtrasImplementation *dbExtras =
+ static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
+ if (!dbExtras)
+ return false;
+
+ QFontDatabasePrivate::ApplicationFont *fnt = &db->applicationFonts[handle];
+ if (fnt->families.isEmpty())
+ return true; // Nothing to remove. Return peacefully.
+
+ // Must remove all font engines with their CFonts, first
+ QFontCache::instance()->clear();
+ db->free();
+ dbExtras->removeAppFontData(fnt);
+
+ db->invalidate(); // This will just emit 'fontDatabaseChanged()'
+ return true;
}
bool QFontDatabase::removeAllApplicationFonts()
{
- return false;
+ QMutexLocker locker(fontDatabaseMutex());
+
+ const int applicationFontsCount = privateDb()->applicationFonts.count();
+ for (int i = 0; i < applicationFontsCount; ++i)
+ if (!removeApplicationFont(i))
+ return false;
+ return true;
}
bool QFontDatabase::supportsThreadedFontRendering()
@@ -467,7 +982,7 @@ QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *d, const QF
QFontDatabasePrivate *db = privateDb();
QtFontDesc desc;
QList<int> blacklistedFamilies;
- match(script, req, req.family, QString(), -1, &desc, blacklistedFamilies);
+ match(script, key.def, key.def.family, QString(), -1, &desc, blacklistedFamilies);
if (!desc.family) // falling back to application font
desc.family = db->family(QApplication::font().defaultFamily());
Q_ASSERT(desc.family);
diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp
index b572cdd..f2b6f5c 100644
--- a/src/gui/text/qfontengine_s60.cpp
+++ b/src/gui/text/qfontengine_s60.cpp
@@ -243,10 +243,13 @@ static inline unsigned int getChar(const QChar *str, int &i, const int len)
return uc;
}
+extern QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName); // qfontdatabase_s60.cpp
+
CFont *QFontEngineS60::fontWithSize(qreal size) const
{
CFont *result = 0;
- TFontSpec fontSpec(qt_QString2TPtrC(QFontEngine::fontDef.family), TInt(size));
+ const QString family = qt_symbian_fontNameWithAppFontMarker(QFontEngine::fontDef.family);
+ TFontSpec fontSpec(qt_QString2TPtrC(family), TInt(size));
fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
fontSpec.iFontStyle.SetPosture(QFontEngine::fontDef.style == QFont::StyleNormal?EPostureUpright:EPostureItalic);
fontSpec.iFontStyle.SetStrokeWeight(QFontEngine::fontDef.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal);
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 498a432..2172f74 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -663,7 +663,8 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
Q_ASSERT(blocks.length() == fragments.length());
- finishEdit();
+ if (!blockCursorAdjustment)
+ finishEdit();
}
void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operation op)
@@ -678,6 +679,7 @@ void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operati
curs->changed = true;
}
}
+ finishEdit();
}
void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode)
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index 3e5f1b3..dbbf49a 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -2476,10 +2476,18 @@ void QComboBox::showPopup()
listRect.setWidth(listRect.height());
//by default popup is centered on screen in landscape
listRect.moveCenter(screen.center());
- if (staConTopRect.IsEmpty() && AknLayoutUtils::CbaLocation() != AknLayoutUtils::EAknCbaLocationBottom) {
- // landscape without stacon, menu should be at the right
- (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) :
- listRect.setLeft(screen.left());
+ if (staConTopRect.IsEmpty()) {
+ TRect cbaRect = TRect();
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect);
+ AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation();
+ switch (cbaLocation) {
+ case AknLayoutUtils::EAknCbaLocationRight:
+ listRect.setRight(screen.right());
+ break;
+ case AknLayoutUtils::EAknCbaLocationLeft:
+ listRect.setLeft(screen.left());
+ break;
+ }
}
}
#endif