From 344a4dcfe847dd778c33d1a852381672dd331409 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Fri, 12 Nov 2010 12:50:24 +0100 Subject: Fix text rendering offset for raster engine on Mac Since the bounding box returned by Core Text in smaller than the actual glyph rendered, we have 2 pixels padding around it, as a result, we have to leave 1 pixel above the glyph in glyph cache, so we need to put the text origin 1 pixel lower to draw it. Task-number: QTBUG-15223, QTBUG-15230, QTBUG-15243 Reviewed-by: Gunnar Sletta --- src/gui/text/qfontengine_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 7efb1cc..51e18ec 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -694,7 +694,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CGContextSetFont(ctx, cgFont); qreal pos_x = -br.x.toReal() + subPixelPosition.toReal(); - qreal pos_y = im.height()+br.y.toReal(); + qreal pos_y = im.height() + br.y.toReal() - 1; CGContextSetTextPosition(ctx, pos_x, pos_y); CGSize advance; -- cgit v0.12 From 215deeabaeba359a9b24681f33f99b80060c4fb1 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Fri, 12 Nov 2010 13:56:52 +0100 Subject: Use correct font for menu item shortcuts We used to use kThemeMenuItemCmdKeyFont for drawing menu item shortcuts, however, Apple is using the same font for both menu item text and shortcuts, it's likely that kThemeMenuItemCmdKeyFont is no longer valid. Change it to kThemeMenuItemFont will make the font for shortcuts consistent with other Mac applications. Task-number: QTBUG-15230 Reviewed-by: Fabien Freling --- src/gui/kernel/qapplication_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index e5364d0..3aafeb4 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -549,7 +549,7 @@ void qt_mac_update_os_settings() FontMap("QTipLabel", kThemeSmallSystemFont), FontMap("QLabel", kThemeSystemFont), FontMap("QToolButton", kThemeSmallSystemFont), - FontMap("QMenuItem", kThemeMenuItemCmdKeyFont), // It doesn't exist, but its unique. + FontMap("QMenuItem", kThemeMenuItemFont), // It doesn't exist, but its unique. FontMap("QComboLineEdit", kThemeViewsFont), // It doesn't exist, but its unique. FontMap("QSmallFont", kThemeSmallSystemFont), // It doesn't exist, but its unique. FontMap("QMiniFont", kThemeMiniSystemFont), // It doesn't exist, but its unique. -- cgit v0.12 From 0d6451ec1f1042dbf8c8cd7f2759e2a385d29696 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 11 Nov 2010 15:21:18 +0100 Subject: Introduced new class QAnimationDriver for plugging in what drives animations We need such a concept in place in order to do animations that are driven by vertical sync rather than QTimer, as vertical sync comes constantly at 16.66 ms. This means that animations do will not be jerking... Reviewed-by: bnilsen --- src/corelib/animation/qabstractanimation.cpp | 146 ++++++++++++++++++++- src/corelib/animation/qabstractanimation.h | 31 +++++ src/corelib/animation/qabstractanimation_p.h | 48 +++++-- tests/auto/qpauseanimation/tst_qpauseanimation.cpp | 5 +- 4 files changed, 214 insertions(+), 16 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 641b42b..9add36e 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -166,11 +166,12 @@ Q_GLOBAL_STATIC(QThreadStorage, unifiedTimer) #endif QUnifiedTimer::QUnifiedTimer() : - QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), + QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), currentAnimationIdx(0), consistentTiming(false), slowMode(false), slowdownFactor(5.0f), isPauseTimerActive(false), runningLeafAnimations(0) { time.invalidate(); + driver = &defaultDriver; } @@ -247,14 +248,27 @@ void QUnifiedTimer::restartAnimationTimer() qDebug() << runningPauseAnimations; qDebug() << closestPauseAnimationTimeToFinish(); } + driver->stop(); animationTimer.start(closestTimeToFinish, this); isPauseTimerActive = true; - } else if (!animationTimer.isActive() || isPauseTimerActive) { - animationTimer.start(timingInterval, this); + } else if (!driver->isRunning() || isPauseTimerActive) { + driver->start(); isPauseTimerActive = false; } } +void QUnifiedTimer::setTimingInterval(int interval) +{ + timingInterval = interval; + + if (driver->isRunning() && !isPauseTimerActive) { + //we changed the timing interval + driver->stop(); + driver->start(); + } +} + + void QUnifiedTimer::timerEvent(QTimerEvent *event) { //in the case of consistent timing we make sure the orders in which events come is always the same @@ -369,6 +383,129 @@ int QUnifiedTimer::closestPauseAnimationTimeToFinish() return closestTimeToFinish; } +void QUnifiedTimer::installAnimationDriver(QAnimationDriver *d) +{ + if (driver->isRunning()) { + qWarning("QUnifiedTimer: Cannot change animation driver while animations are running"); + return; + } + + if (driver && driver != &defaultDriver) + delete driver; + + driver = d; +} + +/*! + \class QAnimationDriver + + \brief The QAnimationDriver class is used to exchange the mechanism that drives animations. + + The default animation system is driven by a timer that fires at regular intervals. + In some scenarios, it is better to drive the animation based on other synchronization + mechanisms, such as the vertical refresh rate of the screen. + */ + +QAnimationDriver::QAnimationDriver(QObject *parent) + : QObject(*(new QAnimationDriverPrivate), parent) +{ +} + +QAnimationDriver::QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ +} + + +/*! + Advances the animation based on the current time. This function should + be continuously called by the driver while the animation is running. + */ +void QAnimationDriver::advance() +{ + QUnifiedTimer *instance = QUnifiedTimer::instance(); + + // update current time on all top level animations + instance->updateAnimationsTime(); + instance->restartAnimationTimer(); +} + + +/*! + Installs this animation driver. The animation driver is thread local and + will only apply for the thread its installed in. + */ +void QAnimationDriver::install() +{ + QUnifiedTimer *timer = QUnifiedTimer::instance(true); + timer->installAnimationDriver(this); +} + +bool QAnimationDriver::isRunning() const +{ + return d_func()->running; +} + + +void QAnimationDriver::start() +{ + Q_D(QAnimationDriver); + if (!d->running) { + started(); + d->running = true; + } +} + + +void QAnimationDriver::stop() +{ + Q_D(QAnimationDriver); + if (d->running) { + stopped(); + d->running = false; + } +} + +/*! + \fn QAnimationDriver::started() + + This function is called by the animation framework to notify the driver + that it should start running. + */ + +/*! + \fn QAnimationDriver::stopped() + + This function is called by the animation framework to notify the driver + that it should stop running. + */ + +/*! + The default animation driver just spins the timer... + */ +QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer) + : QAnimationDriver(0), m_unified_timer(timer) +{ +} + +void QDefaultAnimationDriver::timerEvent(QTimerEvent *e) +{ + Q_ASSERT(e->timerId() == m_timer.timerId()); + advance(); +} + +void QDefaultAnimationDriver::started() +{ + m_timer.start(m_unified_timer->timingInterval, this); +} + +void QDefaultAnimationDriver::stopped() +{ + m_timer.stop(); +} + + + void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) { Q_Q(QAbstractAnimation); @@ -794,6 +931,9 @@ void QAbstractAnimation::stop() { Q_D(QAbstractAnimation); + if (d->state == Stopped) + return; + d->setState(Stopped); } diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h index d3c0d0d..6abe8c1 100644 --- a/src/corelib/animation/qabstractanimation.h +++ b/src/corelib/animation/qabstractanimation.h @@ -54,6 +54,7 @@ QT_MODULE(Core) class QAnimationGroup; class QSequentialAnimationGroup; +class QAnimationDriver; class QAbstractAnimationPrivate; class Q_CORE_EXPORT QAbstractAnimation : public QObject @@ -132,6 +133,36 @@ private: Q_DECLARE_PRIVATE(QAbstractAnimation) }; +class QAnimationDriverPrivate; +class Q_CORE_EXPORT QAnimationDriver : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QAnimationDriver) + +public: + QAnimationDriver(QObject *parent); + + void advance(); + void install(); + + bool isRunning() const; + +protected: + virtual void started() = 0; + virtual void stopped() = 0; + + QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent = 0); + +private: + friend class QUnifiedTimer; + + void start(); + void stop(); +}; + + + + #endif //QT_NO_ANIMATION QT_END_NAMESPACE diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index d3d4098..bc3746d 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -58,6 +58,7 @@ #include #include #include +#include #ifdef Q_OS_WIN #include @@ -114,6 +115,30 @@ private: Q_DECLARE_PUBLIC(QAbstractAnimation) }; + +class QUnifiedTimer; +class QDefaultAnimationDriver : public QAnimationDriver +{ + Q_OBJECT +public: + QDefaultAnimationDriver(QUnifiedTimer *timer); + void timerEvent(QTimerEvent *e); + + void started(); + void stopped(); + +private: + QBasicTimer m_timer; + QUnifiedTimer *m_unified_timer; +}; + +class Q_CORE_EXPORT QAnimationDriverPrivate : public QObjectPrivate +{ +public: + QAnimationDriverPrivate() : running(false) {} + bool running; +}; + typedef QElapsedTimer ElapsedTimer; class QUnifiedTimer : public QObject @@ -130,14 +155,7 @@ public: static void unregisterAnimation(QAbstractAnimation *animation); //defines the timing interval. Default is DEFAULT_TIMER_INTERVAL - void setTimingInterval(int interval) - { - timingInterval = interval; - if (animationTimer.isActive() && !isPauseTimerActive) { - //we changed the timing interval - animationTimer.start(timingInterval, this); - } - } + void setTimingInterval(int interval); /* this allows to have a consistent timer interval at each tick from the timer @@ -161,11 +179,20 @@ public: */ static void updateAnimationTimer(); + void installAnimationDriver(QAnimationDriver *driver); + + void restartAnimationTimer(); + void updateAnimationsTime(); + protected: void timerEvent(QTimerEvent *); private: - // timer used for all active (running) animations + friend class QDefaultAnimationDriver; + + QAnimationDriver *driver; + QDefaultAnimationDriver defaultDriver; + QBasicTimer animationTimer; // timer used to delay the check if we should start/stop the animation timer QBasicTimer startStopAnimationTimer; @@ -195,9 +222,6 @@ private: void registerRunningAnimation(QAbstractAnimation *animation); void unregisterRunningAnimation(QAbstractAnimation *animation); - void restartAnimationTimer(); - - void updateAnimationsTime(); int closestPauseAnimationTimeToFinish(); }; diff --git a/tests/auto/qpauseanimation/tst_qpauseanimation.cpp b/tests/auto/qpauseanimation/tst_qpauseanimation.cpp index 605cee6..378eb1c 100644 --- a/tests/auto/qpauseanimation/tst_qpauseanimation.cpp +++ b/tests/auto/qpauseanimation/tst_qpauseanimation.cpp @@ -394,7 +394,10 @@ void tst_QPauseAnimation::multipleSequentialGroups() QVERIFY(subgroup3.state() == QAbstractAnimation::Running); QVERIFY(subgroup4.state() == QAbstractAnimation::Running); - QTest::qWait(group.totalDuration() + 100); + // This is a pretty long animation so it tends to get rather out of sync + // when using the consistent timer, so run for an extra half second for good + // measure... + QTest::qWait(group.totalDuration() + 500); #ifdef Q_OS_WIN if (group.state() != QAbstractAnimation::Stopped) -- cgit v0.12