summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFrans Englich <frans.englich@nokia.com>2009-10-02 16:05:53 (GMT)
committerFrans Englich <frans.englich@nokia.com>2009-10-02 16:05:53 (GMT)
commit0981f27d76436f8058d8534b7454777910922ee0 (patch)
tree780a864cb0d9b163f15dbe9d84e64bb0dfbb9110 /src
parente658bcb0e64acca9684f0897510d639af98ab552 (diff)
parent5a26fa6da1986bdb507391fd8784c51258e81d80 (diff)
downloadQt-0981f27d76436f8058d8534b7454777910922ee0.zip
Qt-0981f27d76436f8058d8534b7454777910922ee0.tar.gz
Qt-0981f27d76436f8058d8534b7454777910922ee0.tar.bz2
Merge commit 'origin/4.6' into mmfphonon
Conflicts: demos/mediaplayer/mediaplayer.pro
Diffstat (limited to 'src')
-rw-r--r--src/corelib/animation/qabstractanimation.cpp17
-rw-r--r--src/corelib/animation/qabstractanimation_p.h8
-rw-r--r--src/corelib/kernel/kernel.pri6
-rw-r--r--src/corelib/kernel/qcoreevent.cpp4
-rw-r--r--src/corelib/kernel/qcoreevent.h4
-rw-r--r--src/corelib/kernel/qmath.cpp305
-rw-r--r--src/corelib/kernel/qmath.h24
-rw-r--r--src/corelib/statemachine/qeventtransition.cpp2
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp4
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp4
-rw-r--r--src/gui/kernel/qgesture.cpp1
-rw-r--r--src/gui/kernel/qstandardgestures.cpp3
-rw-r--r--src/gui/painting/qdrawutil.cpp457
-rw-r--r--src/gui/painting/qdrawutil.h57
-rw-r--r--src/gui/painting/qpaintengineex.cpp25
-rw-r--r--src/gui/painting/qpaintengineex_p.h9
-rw-r--r--src/gui/widgets/qabstractslider.cpp25
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp59
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h14
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h20
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp145
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h8
-rw-r--r--src/s60installs/qt.svg17
23 files changed, 925 insertions, 293 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index f92c22d..6bbd801 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -83,7 +83,7 @@
updateCurrentTime(). The duration() function lets you report a
duration for the animation (as discussed above). The animation
framework calls updateCurrentTime() when current time has changed.
- By reimplementing this function, you can track the animation
+ By reimplementing this function, you can track the animation
progress. Note that neither the interval between calls nor the
number of calls to this function are defined; though, it will
normally be 60 updates per second.
@@ -228,15 +228,16 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event)
void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation)
{
- if (animations.contains(animation) || animationsToStart.contains(animation))
- return;
+ Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer);
+ QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true;
animationsToStart << animation;
- startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); // we delay the check if we should start/stop the global timer
+ startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this);
}
void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
{
- Q_ASSERT(animations.count(animation) + animationsToStart.count(animation) <= 1);
+ if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer)
+ return;
int idx = animations.indexOf(animation);
if (idx != -1) {
@@ -244,13 +245,14 @@ void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
// this is needed if we unregister an animation while its running
if (idx <= currentAnimationIdx)
--currentAnimationIdx;
+ if (animations.isEmpty())
+ startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this);
} else {
animationsToStart.removeOne(animation);
}
- startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); // we delay the check if we should start/stop the global timer
+ QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false;
}
-
void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
{
Q_Q(QAbstractAnimation);
@@ -326,7 +328,6 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
}
break;
}
-
}
/*!
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index 20868f9..1a79f40 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -75,6 +75,7 @@ public:
currentTime(0),
loopCount(1),
currentLoop(0),
+ hasRegisteredTimer(false),
group(0)
{
}
@@ -96,6 +97,8 @@ public:
int loopCount;
int currentLoop;
+ bool hasRegisteredTimer;
+
QAnimationGroup *group;
private:
@@ -137,7 +140,10 @@ protected:
void timerEvent(QTimerEvent *);
private:
- QBasicTimer animationTimer, startStopAnimationTimer;
+ // timer used for all active animations
+ QBasicTimer animationTimer;
+ // timer used to delay the check if we should start/stop the global timer
+ QBasicTimer startStopAnimationTimer;
QTime time;
int lastTick;
int timingInterval;
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 003693b..d0dad49 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -33,7 +33,8 @@ HEADERS += \
kernel/qsystemsemaphore.h \
kernel/qsystemsemaphore_p.h \
kernel/qfunctions_p.h \
- kernel/qguard_p.h
+ kernel/qguard_p.h \
+ kernel/qmath.h
SOURCES += \
kernel/qabstracteventdispatcher.cpp \
@@ -55,7 +56,8 @@ SOURCES += \
kernel/qcoreglobaldata.cpp \
kernel/qsharedmemory.cpp \
kernel/qsystemsemaphore.cpp \
- kernel/qpointer.cpp
+ kernel/qpointer.cpp \
+ kernel/qmath.cpp
win32 {
SOURCES += \
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 3bef0d4..744e6a9 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -192,8 +192,9 @@ QT_BEGIN_NAMESPACE
\value ShortcutOverride Key press in child, for overriding shortcut key handling (QKeyEvent).
\value Show Widget was shown on screen (QShowEvent).
\value ShowToParent A child widget has been shown.
- \value Signal A signal delivered to a state machine (QStateMachine::SignalEvent).
\value SockAct Socket activated, used to implement QSocketNotifier.
+ \value StateMachineSignal A signal delivered to a state machine (QStateMachine::SignalEvent).
+ \value StateMachineWrapped The event is a wrapper for, i.e., contains, another event (QStateMachine::WrappedEvent).
\value StatusTip A status tip is requested (QStatusTipEvent).
\value StyleChange Widget's style has been changed.
\value TabletMove Wacom tablet move (QTabletEvent).
@@ -221,7 +222,6 @@ QT_BEGIN_NAMESPACE
\value WindowStateChange The \l{QWidget::windowState()}{window's state} (minimized, maximized or full-screen) has changed (QWindowStateChangeEvent).
\value WindowTitleChange The window title has changed.
\value WindowUnblocked The window is unblocked after a modal dialog exited.
- \value Wrapped The event is a wrapper for, i.e., contains, another event (QStateMachine::WrappedEvent).
\value ZOrderChange The widget's z-order has changed. This event is never sent to top level windows.
\value KeyboardLayoutChange The keyboard layout has changed.
\value DynamicPropertyChange A dynamic property was added, changed or removed from the object.
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index be25b41..a039d32 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -269,8 +269,8 @@ public:
CocoaRequestModal = 190, // Internal for requesting an application modal Cocoa Window
MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear
- Signal = 192,
- Wrapped = 193,
+ StateMachineSignal = 192,
+ StateMachineWrapped = 193,
TouchBegin = 194,
TouchUpdate = 195,
diff --git a/src/corelib/kernel/qmath.cpp b/src/corelib/kernel/qmath.cpp
new file mode 100644
index 0000000..24bec4a
--- /dev/null
+++ b/src/corelib/kernel/qmath.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT const qreal qt_sine_table[QT_SINE_TABLE_SIZE] = {
+ 0.0,
+ 0.024541228522912288,
+ 0.049067674327418015,
+ 0.073564563599667426,
+ 0.098017140329560604,
+ 0.1224106751992162,
+ 0.14673047445536175,
+ 0.17096188876030122,
+ 0.19509032201612825,
+ 0.2191012401568698,
+ 0.24298017990326387,
+ 0.26671275747489837,
+ 0.29028467725446233,
+ 0.31368174039889152,
+ 0.33688985339222005,
+ 0.35989503653498811,
+ 0.38268343236508978,
+ 0.40524131400498986,
+ 0.42755509343028208,
+ 0.44961132965460654,
+ 0.47139673682599764,
+ 0.49289819222978404,
+ 0.51410274419322166,
+ 0.53499761988709715,
+ 0.55557023301960218,
+ 0.57580819141784534,
+ 0.59569930449243336,
+ 0.61523159058062682,
+ 0.63439328416364549,
+ 0.65317284295377676,
+ 0.67155895484701833,
+ 0.68954054473706683,
+ 0.70710678118654746,
+ 0.72424708295146689,
+ 0.74095112535495911,
+ 0.75720884650648446,
+ 0.77301045336273699,
+ 0.78834642762660623,
+ 0.80320753148064483,
+ 0.81758481315158371,
+ 0.83146961230254524,
+ 0.84485356524970701,
+ 0.85772861000027212,
+ 0.87008699110871135,
+ 0.88192126434835494,
+ 0.89322430119551532,
+ 0.90398929312344334,
+ 0.91420975570353069,
+ 0.92387953251128674,
+ 0.93299279883473885,
+ 0.94154406518302081,
+ 0.94952818059303667,
+ 0.95694033573220894,
+ 0.96377606579543984,
+ 0.97003125319454397,
+ 0.97570213003852857,
+ 0.98078528040323043,
+ 0.98527764238894122,
+ 0.98917650996478101,
+ 0.99247953459870997,
+ 0.99518472667219682,
+ 0.99729045667869021,
+ 0.99879545620517241,
+ 0.99969881869620425,
+ 1.0,
+ 0.99969881869620425,
+ 0.99879545620517241,
+ 0.99729045667869021,
+ 0.99518472667219693,
+ 0.99247953459870997,
+ 0.98917650996478101,
+ 0.98527764238894122,
+ 0.98078528040323043,
+ 0.97570213003852857,
+ 0.97003125319454397,
+ 0.96377606579543984,
+ 0.95694033573220894,
+ 0.94952818059303667,
+ 0.94154406518302081,
+ 0.93299279883473885,
+ 0.92387953251128674,
+ 0.91420975570353069,
+ 0.90398929312344345,
+ 0.89322430119551521,
+ 0.88192126434835505,
+ 0.87008699110871146,
+ 0.85772861000027212,
+ 0.84485356524970723,
+ 0.83146961230254546,
+ 0.81758481315158371,
+ 0.80320753148064494,
+ 0.78834642762660634,
+ 0.7730104533627371,
+ 0.75720884650648468,
+ 0.74095112535495899,
+ 0.72424708295146689,
+ 0.70710678118654757,
+ 0.68954054473706705,
+ 0.67155895484701855,
+ 0.65317284295377664,
+ 0.63439328416364549,
+ 0.61523159058062693,
+ 0.59569930449243347,
+ 0.57580819141784545,
+ 0.55557023301960218,
+ 0.53499761988709715,
+ 0.51410274419322177,
+ 0.49289819222978415,
+ 0.47139673682599786,
+ 0.44961132965460687,
+ 0.42755509343028203,
+ 0.40524131400498992,
+ 0.38268343236508989,
+ 0.35989503653498833,
+ 0.33688985339222033,
+ 0.31368174039889141,
+ 0.29028467725446239,
+ 0.26671275747489848,
+ 0.24298017990326407,
+ 0.21910124015687005,
+ 0.19509032201612861,
+ 0.17096188876030122,
+ 0.1467304744553618,
+ 0.12241067519921635,
+ 0.098017140329560826,
+ 0.073564563599667732,
+ 0.049067674327417966,
+ 0.024541228522912326,
+ 0.0,
+ -0.02454122852291208,
+ -0.049067674327417724,
+ -0.073564563599667496,
+ -0.09801714032956059,
+ -0.1224106751992161,
+ -0.14673047445536158,
+ -0.17096188876030097,
+ -0.19509032201612836,
+ -0.2191012401568698,
+ -0.24298017990326382,
+ -0.26671275747489825,
+ -0.29028467725446211,
+ -0.31368174039889118,
+ -0.33688985339222011,
+ -0.35989503653498811,
+ -0.38268343236508967,
+ -0.40524131400498969,
+ -0.42755509343028181,
+ -0.44961132965460665,
+ -0.47139673682599764,
+ -0.49289819222978393,
+ -0.51410274419322155,
+ -0.53499761988709693,
+ -0.55557023301960196,
+ -0.57580819141784534,
+ -0.59569930449243325,
+ -0.61523159058062671,
+ -0.63439328416364527,
+ -0.65317284295377653,
+ -0.67155895484701844,
+ -0.68954054473706683,
+ -0.70710678118654746,
+ -0.72424708295146678,
+ -0.74095112535495888,
+ -0.75720884650648423,
+ -0.77301045336273666,
+ -0.78834642762660589,
+ -0.80320753148064505,
+ -0.81758481315158382,
+ -0.83146961230254524,
+ -0.84485356524970701,
+ -0.85772861000027201,
+ -0.87008699110871135,
+ -0.88192126434835494,
+ -0.89322430119551521,
+ -0.90398929312344312,
+ -0.91420975570353047,
+ -0.92387953251128652,
+ -0.93299279883473896,
+ -0.94154406518302081,
+ -0.94952818059303667,
+ -0.95694033573220882,
+ -0.96377606579543984,
+ -0.97003125319454397,
+ -0.97570213003852846,
+ -0.98078528040323032,
+ -0.98527764238894111,
+ -0.9891765099647809,
+ -0.99247953459871008,
+ -0.99518472667219693,
+ -0.99729045667869021,
+ -0.99879545620517241,
+ -0.99969881869620425,
+ -1.0,
+ -0.99969881869620425,
+ -0.99879545620517241,
+ -0.99729045667869021,
+ -0.99518472667219693,
+ -0.99247953459871008,
+ -0.9891765099647809,
+ -0.98527764238894122,
+ -0.98078528040323043,
+ -0.97570213003852857,
+ -0.97003125319454397,
+ -0.96377606579543995,
+ -0.95694033573220894,
+ -0.94952818059303679,
+ -0.94154406518302092,
+ -0.93299279883473907,
+ -0.92387953251128663,
+ -0.91420975570353058,
+ -0.90398929312344334,
+ -0.89322430119551532,
+ -0.88192126434835505,
+ -0.87008699110871146,
+ -0.85772861000027223,
+ -0.84485356524970723,
+ -0.83146961230254546,
+ -0.81758481315158404,
+ -0.80320753148064528,
+ -0.78834642762660612,
+ -0.77301045336273688,
+ -0.75720884650648457,
+ -0.74095112535495911,
+ -0.724247082951467,
+ -0.70710678118654768,
+ -0.68954054473706716,
+ -0.67155895484701866,
+ -0.65317284295377709,
+ -0.63439328416364593,
+ -0.61523159058062737,
+ -0.59569930449243325,
+ -0.57580819141784523,
+ -0.55557023301960218,
+ -0.53499761988709726,
+ -0.51410274419322188,
+ -0.49289819222978426,
+ -0.47139673682599792,
+ -0.44961132965460698,
+ -0.42755509343028253,
+ -0.40524131400499042,
+ -0.38268343236509039,
+ -0.359895036534988,
+ -0.33688985339222,
+ -0.31368174039889152,
+ -0.2902846772544625,
+ -0.26671275747489859,
+ -0.24298017990326418,
+ -0.21910124015687016,
+ -0.19509032201612872,
+ -0.17096188876030177,
+ -0.14673047445536239,
+ -0.12241067519921603,
+ -0.098017140329560506,
+ -0.073564563599667412,
+ -0.049067674327418091,
+ -0.024541228522912448
+};
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h
index b521323..a9e4378 100644
--- a/src/corelib/kernel/qmath.h
+++ b/src/corelib/kernel/qmath.h
@@ -52,6 +52,10 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
+#define QT_SINE_TABLE_SIZE 256
+
+extern Q_CORE_EXPORT const qreal qt_sine_table[QT_SINE_TABLE_SIZE];
+
inline int qCeil(qreal v)
{
#ifdef QT_USE_MATH_H_FLOATS
@@ -136,6 +140,26 @@ inline qreal qPow(qreal x, qreal y)
#define M_PI (3.14159265358979323846)
#endif
+inline qreal qFastSin(qreal x)
+{
+ int si = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
+ qreal d = x - si * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
+ int ci = si + QT_SINE_TABLE_SIZE / 4;
+ si &= QT_SINE_TABLE_SIZE - 1;
+ ci &= QT_SINE_TABLE_SIZE - 1;
+ return qt_sine_table[si] + (qt_sine_table[ci] - 0.5 * qt_sine_table[si] * d) * d;
+}
+
+inline qreal qFastCos(qreal x)
+{
+ int ci = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
+ qreal d = x - ci * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
+ int si = ci + QT_SINE_TABLE_SIZE / 4;
+ si &= QT_SINE_TABLE_SIZE - 1;
+ ci &= QT_SINE_TABLE_SIZE - 1;
+ return qt_sine_table[si] - (qt_sine_table[ci] + 0.5 * qt_sine_table[si] * d) * d;
+}
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp
index f278371..949f39e 100644
--- a/src/corelib/statemachine/qeventtransition.cpp
+++ b/src/corelib/statemachine/qeventtransition.cpp
@@ -231,7 +231,7 @@ void QEventTransition::setEventSource(QObject *object)
bool QEventTransition::eventTest(QEvent *event)
{
Q_D(const QEventTransition);
- if (event->type() == QEvent::Wrapped) {
+ if (event->type() == QEvent::StateMachineWrapped) {
QStateMachine::WrappedEvent *we = static_cast<QStateMachine::WrappedEvent*>(event);
return (we->object() == d->object)
&& (we->event()->type() == d->eventType);
diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp
index 9811725..f55f634 100644
--- a/src/corelib/statemachine/qsignaltransition.cpp
+++ b/src/corelib/statemachine/qsignaltransition.cpp
@@ -218,7 +218,7 @@ void QSignalTransition::setSignal(const QByteArray &signal)
bool QSignalTransition::eventTest(QEvent *event)
{
Q_D(const QSignalTransition);
- if (event->type() == QEvent::Signal) {
+ if (event->type() == QEvent::StateMachineSignal) {
if (d->signalIndex == -1)
return false;
QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(event);
@@ -248,7 +248,7 @@ void QSignalTransitionPrivate::callOnTransition(QEvent *e)
{
Q_Q(QSignalTransition);
- if (e->type() == QEvent::Signal) {
+ if (e->type() == QEvent::StateMachineSignal) {
QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent *>(e);
int savedSignalIndex = se->m_signalIndex;
se->m_signalIndex = originalSignalIndex;
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index c7144e4..e182c88 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -2206,7 +2206,7 @@ QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent)
*/
QStateMachine::SignalEvent::SignalEvent(QObject *sender, int signalIndex,
const QList<QVariant> &arguments)
- : QEvent(QEvent::Signal), m_sender(sender),
+ : QEvent(QEvent::StateMachineSignal), m_sender(sender),
m_signalIndex(signalIndex), m_arguments(arguments)
{
}
@@ -2269,7 +2269,7 @@ QStateMachine::SignalEvent::~SignalEvent()
The WrappedEvent object takes ownership of \a event.
*/
QStateMachine::WrappedEvent::WrappedEvent(QObject *object, QEvent *event)
- : QEvent(QEvent::Wrapped), m_object(object), m_event(event)
+ : QEvent(QEvent::StateMachineWrapped), m_object(object), m_event(event)
{
}
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp
index 00839d1..237ce46 100644
--- a/src/gui/kernel/qgesture.cpp
+++ b/src/gui/kernel/qgesture.cpp
@@ -67,6 +67,7 @@ private:
/*!
\class QGesture
\since 4.6
+ \preliminary
\brief The QGesture class is the base class for implementing custom
gestures.
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp
index bcc411a..3cfb987 100644
--- a/src/gui/kernel/qstandardgestures.cpp
+++ b/src/gui/kernel/qstandardgestures.cpp
@@ -57,6 +57,7 @@ QWidgetPrivate *qt_widget_private(QWidget *widget);
/*!
\class QPanGesture
+ \preliminary
\since 4.6
\brief The QPanGesture class represents a Pan gesture,
@@ -339,6 +340,7 @@ QSizeF QPanGesture::offset() const
/*!
\class QPinchGesture
+ \preliminary
\since 4.6
\brief The QPinchGesture class represents a Pinch gesture,
@@ -667,6 +669,7 @@ QPointF QPinchGesture::startCenterPoint() const
/*!
\class QSwipeGesture
+ \preliminary
\since 4.6
\brief The QSwipeGesture class represents a swipe gesture,
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index ac3796a..c20d8d8 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -45,6 +45,9 @@
#include "qapplication.h"
#include "qpainter.h"
#include "qpalette.h"
+#include <private/qpaintengineex_p.h>
+#include <qvarlengtharray.h>
+#include <qmath.h>
QT_BEGIN_NAMESPACE
@@ -1078,91 +1081,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
according to the \a margins structure.
*/
-static inline void qVerticalRepeat(QPainter *painter,
- const QRect &target,
- const QPixmap &pixmap,
- const QRect &source,
- void (*drawPixmap)(QPainter*,
- const QRect&,
- const QPixmap&,
- const QRect&))
-{
- const int x = target.x();
- const int width = target.width();
- const int height = source.height();
- const int bottom = target.bottom() - height;
- int y = target.y();
- for (; y < bottom; y += height)
- (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source);
- const QRect remaining(source.x(), source.y(), source.width(), target.bottom() - y + 1);
- (*drawPixmap)(painter, QRect(x, y, width, remaining.height()), pixmap, remaining);
-}
-
-static inline void qHorizontalRepeat(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
- void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
-{
- const int y = target.y();
- const int width = source.width();
- const int height = target.height();
- const int right = target.right() - width;
- int x = target.x();
- for (; x < right; x += width)
- (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source);
- const QRect remaining(source.x(), source.y(), target.right() - x + 1, source.height());
- (*drawPixmap)(painter, QRect(x, y, remaining.width(), height), pixmap, remaining);
-}
-
-static inline void qVerticalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
- void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
-{
- // qreal based - slow on non-fpu devices
- const qreal x = target.x();
- const qreal width = target.width();
- const qreal verticalFactor = static_cast<qreal>(target.height()) / static_cast<qreal>(source.height());
- const qreal verticalIncrement = static_cast<qreal>(target.height()) / static_cast<int>(verticalFactor + 0.5);
- const qreal bottom = target.bottom();
- for (qreal y = static_cast<qreal>(target.y()); y < bottom; y += verticalIncrement)
- (*drawPixmap)(painter, QRectF(x, y, width, verticalIncrement).toRect(), pixmap, source);
-
-}
-
-static inline void qHorizontalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
- void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
-{
- // qreal based - slow on non-fpu devices
- const qreal y = target.y();
- const qreal height = target.height();
- const qreal horizontalFactor = static_cast<qreal>(target.width()) / static_cast<qreal>(source.width());
- const qreal horizontalIncrement = static_cast<qreal>(target.width()) / static_cast<int>(horizontalFactor + 0.5);
- const qreal right = target.right();
- for (qreal x = target.x(); x < right; x += horizontalIncrement)
- (*drawPixmap)(painter, QRectF(x, y, horizontalIncrement, height).toRect(), pixmap, source);
-}
-
-static inline void qDrawPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
-{
- painter->drawPixmap(target, pixmap, source);
-}
-
-static inline void qDrawVerticallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
-{
- qVerticalRepeat(painter, target, pixmap, source, qDrawPixmap);
-}
-
-static inline void qDrawHorizontallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
-{
- qHorizontalRepeat(painter, target, pixmap, source, qDrawPixmap);
-}
-
-static inline void qDrawVerticallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
-{
- qVerticalRound(painter, target, pixmap, source, qDrawPixmap);
-}
-
-static inline void qDrawHorizontallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
-{
- qHorizontalRound(painter, target, pixmap, source, qDrawPixmap);
-}
+typedef QVarLengthArray<QDrawPixmaps::Data, 16> QDrawPixmapsDataArray;
/*!
\since 4.6
@@ -1179,176 +1098,282 @@ static inline void qDrawHorizontallyRoundedPixmap(QPainter *painter, const QRect
\sa Qt::TileRule, QTileRules, QMargins
*/
-void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap,
- const QRect &sourceRect, const QMargins &sourceMargins, const QTileRules &rules)
+void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins,
+ const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
+ const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
{
+ QDrawPixmaps::Data d;
+ d.opacity = 1.0;
+ d.rotation = 0.0;
+
+ QDrawPixmapsDataArray opaqueData;
+ QDrawPixmapsDataArray translucentData;
+
// source center
- const int sourceTop = sourceRect.top();
- const int sourceLeft = sourceRect.left();
- const int sourceCenterTop = sourceTop + sourceMargins.top();
- const int sourceCenterLeft = sourceLeft + sourceMargins.left();
+ const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
+ const int sourceCenterLeft = sourceRect.left() + sourceMargins.left();
const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1;
const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1;
- const int sourceCenterWidth = sourceCenterRight - sourceMargins.left();
- const int sourceCenterHeight = sourceCenterBottom - sourceMargins.top();
+ const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft;
+ const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop;
// target center
- const int targetTop = targetRect.top();
- const int targetLeft = targetRect.left();
- const int targetCenterTop = targetTop + targetMargins.top();
- const int targetCenterLeft = targetLeft + targetMargins.left();
+ const int targetCenterTop = targetRect.top() + targetMargins.top();
+ const int targetCenterLeft = targetRect.left() + targetMargins.left();
const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1;
const int targetCenterRight = targetRect.right() - targetMargins.right() + 1;
const int targetCenterWidth = targetCenterRight - targetCenterLeft;
const int targetCenterHeight = targetCenterBottom - targetCenterTop;
+ QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles
+ QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles
+
+ int columns = 3;
+ int rows = 3;
+ if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0)
+ columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth)));
+ if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0)
+ rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight)));
+
+ xTarget.resize(columns + 1);
+ yTarget.resize(rows + 1);
+
+ xTarget[0] = targetRect.left();
+ xTarget[1] = targetCenterLeft;
+ xTarget[columns - 1] = targetCenterRight;
+ xTarget[columns] = targetRect.left() + targetRect.width();
+
+ yTarget[0] = targetRect.top();
+ yTarget[1] = targetCenterTop;
+ yTarget[rows - 1] = targetCenterBottom;
+ yTarget[rows] = targetRect.top() + targetRect.height();
+
+ qreal dx;
+ qreal dy;
+
+ switch (rules.horizontal) {
+ case Qt::StretchTile:
+ dx = targetCenterWidth;
+ break;
+ case Qt::RepeatTile:
+ dx = sourceCenterWidth;
+ break;
+ case Qt::RoundTile:
+ dx = targetCenterWidth / qreal(columns - 2);
+ break;
+ }
+
+ for (int i = 2; i < columns - 1; ++i)
+ xTarget[i] = xTarget[i - 1] + dx;
+
+ switch (rules.vertical) {
+ case Qt::StretchTile:
+ dy = targetCenterHeight;
+ break;
+ case Qt::RepeatTile:
+ dy = sourceCenterHeight;
+ break;
+ case Qt::RoundTile:
+ dy = targetCenterHeight / qreal(rows - 2);
+ break;
+ }
+
+ for (int i = 2; i < rows - 1; ++i)
+ yTarget[i] = yTarget[i - 1] + dy;
+
// corners
if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
- const QRect targetTopLeftRect(targetLeft, targetTop, targetMargins.left(), targetMargins.top());
- const QRect sourceTopLeftRect(sourceLeft, sourceTop, sourceMargins.left(), sourceMargins.top());
- qDrawPixmap(painter, targetTopLeftRect, pixmap, sourceTopLeftRect);
+ d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
+ d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
+ d.source = QRectF(sourceRect.left(), sourceRect.top(), sourceMargins.left(), sourceMargins.top());
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ if (hints & QDrawBorderPixmap::OpaqueTopLeft)
+ opaqueData.append(d);
+ else
+ translucentData.append(d);
}
if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
- const QRect targetTopRightRect(targetCenterRight, targetTop, targetMargins.right(), targetMargins.top());
- const QRect sourceTopRightRect(sourceCenterRight, sourceTop, sourceMargins.right(), sourceMargins.top());
- qDrawPixmap(painter, targetTopRightRect, pixmap, sourceTopRightRect);
+ d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
+ d.source = QRectF(sourceCenterRight, sourceRect.top(), sourceMargins.right(), sourceMargins.top());
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ if (hints & QDrawBorderPixmap::OpaqueTopRight)
+ opaqueData.append(d);
+ else
+ translucentData.append(d);
}
if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
- const QRect targetBottomLeftRect(targetLeft, targetCenterBottom, targetMargins.left(), targetMargins.bottom());
- const QRect sourceBottomLeftRect(sourceLeft, sourceCenterBottom, sourceMargins.left(), sourceMargins.bottom());
- qDrawPixmap(painter, targetBottomLeftRect, pixmap, sourceBottomLeftRect);
+ d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
+ d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.source = QRectF(sourceRect.left(), sourceCenterBottom, sourceMargins.left(), sourceMargins.bottom());
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
+ opaqueData.append(d);
+ else
+ translucentData.append(d);
}
if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
- const QRect targetBottomRightRect(targetCenterRight, targetCenterBottom, targetMargins.right(), targetMargins.bottom());
- const QRect sourceBottomRightRect(sourceCenterRight, sourceCenterBottom, sourceMargins.right(), sourceMargins.bottom());
- qDrawPixmap(painter, targetBottomRightRect, pixmap, sourceBottomRightRect);
+ d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.source = QRectF(sourceCenterRight, sourceCenterBottom, sourceMargins.right(), sourceMargins.bottom());
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ if (hints & QDrawBorderPixmap::OpaqueBottomRight)
+ opaqueData.append(d);
+ else
+ translucentData.append(d);
}
// horizontal edges
- switch (rules.horizontal) {
- case Qt::StretchTile:
- if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
- const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top());
- const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top());
- qDrawPixmap(painter, targetTopRect, pixmap, sourceTopRect);
- }
- if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
- const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom());
- const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());
- qDrawPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
- }
- break;
- case Qt::RepeatTile:
- if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
- const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top());
- const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top());
- qDrawHorizontallyRepeatedPixmap(painter, targetTopRect, pixmap, sourceTopRect);
- }
- if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
- const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom());
- const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());
- qDrawHorizontallyRepeatedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
- }
- break;
- case Qt::RoundTile:
+ if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
- const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top());
- const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top());
- qDrawHorizontallyRoundedPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
+ d.source = QRectF(sourceCenterLeft, sourceRect.top(), sourceCenterWidth, sourceMargins.top());
+ d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
+ d.scaleX = dx / d.source.width();
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ for (int i = 1; i < columns - 1; ++i) {
+ d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ data.append(d);
+ }
+ if (rules.horizontal == Qt::RepeatTile)
+ data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
}
if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
- const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom());
- const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());
- qDrawHorizontallyRoundedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
+ d.source = QRectF(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());;
+ d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.scaleX = dx / d.source.width();
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ for (int i = 1; i < columns - 1; ++i) {
+ d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ data.append(d);
+ }
+ if (rules.horizontal == Qt::RepeatTile)
+ data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
}
- break;
}
// vertical edges
- switch (rules.vertical) {
- case Qt::StretchTile:
- if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
- const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left(), targetCenterHeight);
- const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
- qDrawPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
- }
- if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
- const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right(), targetCenterHeight);
- const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
- qDrawPixmap(painter, targetRightRect, pixmap, sourceRightRect);
- }
- break;
- case Qt::RepeatTile:
- if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
- const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left(), targetCenterHeight);
- const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
- qDrawVerticallyRepeatedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
- }
- if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
- const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right(), targetCenterHeight);
- const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
- qDrawVerticallyRepeatedPixmap(painter, targetRightRect, pixmap, sourceRightRect);
- }
- break;
- case Qt::RoundTile:
+ if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
- const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left(), targetCenterHeight);
- const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
- qDrawVerticallyRoundedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
+ d.source = QRectF(sourceRect.left(), sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
+ d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
+ d.scaleY = dy / d.source.height();
+ for (int i = 1; i < rows - 1; ++i) {
+ d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
+ data.append(d);
+ }
+ if (rules.vertical == Qt::RepeatTile)
+ data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
}
if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
- const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right(), targetCenterHeight);
- const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
- qDrawVerticallyRoundedPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
+ d.source = QRectF(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
+ d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
+ d.scaleY = dy / d.source.height();
+ for (int i = 1; i < rows - 1; ++i) {
+ d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
+ data.append(d);
+ }
+ if (rules.vertical == Qt::RepeatTile)
+ data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
}
- break;
}
// center
if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
- const QRect targetCenterRect(targetCenterLeft, targetCenterTop, targetCenterWidth, targetCenterHeight);
- const QRect sourceCenterRect(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
- switch (rules.horizontal) {
- case Qt::StretchTile:
- switch (rules.vertical) {
- case Qt::StretchTile: // stretch stretch
- qDrawPixmap(painter, targetCenterRect, pixmap, sourceCenterRect);
- break;
- case Qt::RepeatTile: // stretch repeat
- qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
- break;
- case Qt::RoundTile: // stretch round
- qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
- break;
- }
- break;
- case Qt::RepeatTile:
- switch (rules.vertical) {
- case Qt::StretchTile: // repeat stretch
- qHorizontalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
- break;
- case Qt::RepeatTile: // repeat repeat
- qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap);
- break;
- case Qt::RoundTile: // repeat round
- qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap);
- break;
+ QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
+ d.source = QRectF(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
+ d.scaleX = dx / d.source.width();
+ d.scaleY = dy / d.source.height();
+
+ qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
+ qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;
+
+ for (int j = 1; j < rows - 1; ++j) {
+ d.point.setY(0.5 * (yTarget[j + 1] + yTarget[j]));
+ for (int i = 1; i < columns - 1; ++i) {
+ d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ data.append(d);
}
- break;
- case Qt::RoundTile:
- switch (rules.vertical) {
- case Qt::StretchTile: // round stretch
- qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
- break;
- case Qt::RepeatTile: // round repeat
- qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRepeatedPixmap);
- break;
- case Qt::RoundTile: // round round
- qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRoundedPixmap);
- break;
- }
- break;
+ if (rules.horizontal == Qt::RepeatTile)
+ data[data.size() - 1].source.setWidth(repeatWidth);
+ }
+ if (rules.vertical == Qt::RepeatTile) {
+ for (int i = 1; i < columns - 1; ++i)
+ data[data.size() - i].source.setHeight(repeatHeight);
}
}
+
+ if (opaqueData.size())
+ qDrawPixmaps(painter, opaqueData.data(), opaqueData.size(), pixmap, QDrawPixmaps::OpaqueHint);
+ if (translucentData.size())
+ qDrawPixmaps(painter, translucentData.data(), translucentData.size(), pixmap);
+}
+
+/*!
+ \class QDrawPixmaps::Data
+ \since 4.6
+ \internal
+
+ This structure is used with the qDrawPixmaps() function.
+
+ QPointF point: Specifies the center of the target rectangle.
+ QRectF source: Specifies the source rectangle in the pixmap passed into the qDrawPixmaps() call.
+ qreal scaleX: Specifies the horizontal scale of the target rectangle.
+ qreal scaleY: Specifies the vertical scale of the target rectangle.
+ qreal rotation: Specifies the rotation of the target rectangle in degrees.
+ The target rectangle is rotated after scaling.
+ qreal opacity: Specifies the opacity of the rectangle.
+*/
+
+/*!
+ \enum QDrawPixmaps::DrawingHint
+ \internal
+*/
+
+/*!
+ \internal
+ \since 4.6
+
+ This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap, at multiple positions
+ with different scale, rotation and opacity on \a painter. \a drawingData is an array of \a
+ dataCount elements specifying the parameters used to draw each pixmap instance.
+ This can be used for example to implement a particle system.
+*/
+void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
+{
+ QPaintEngine *engine = painter->paintEngine();
+ if (!engine)
+ return;
+
+ if (engine->isExtended()) {
+ static_cast<QPaintEngineEx *>(engine)->drawPixmaps(drawingData, dataCount, pixmap, hints);
+ } else {
+ qreal oldOpacity = painter->opacity();
+ QTransform oldTransform = painter->transform();
+
+ for (int i = 0; i < dataCount; ++i) {
+ QTransform transform = oldTransform;
+ transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
+ transform.rotate(drawingData[i].rotation);
+ painter->setOpacity(oldOpacity * drawingData[i].opacity);
+ painter->setTransform(transform);
+
+ qreal w = drawingData[i].scaleX * drawingData[i].source.width();
+ qreal h = drawingData[i].scaleY * drawingData[i].source.height();
+ painter->drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, drawingData[i].source);
+ }
+
+ painter->setOpacity(oldOpacity);
+ painter->setTransform(oldTransform);
+ }
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawutil.h b/src/gui/painting/qdrawutil.h
index 22a57e9..fff1cc1 100644
--- a/src/gui/painting/qdrawutil.h
+++ b/src/gui/painting/qdrawutil.h
@@ -143,13 +143,43 @@ struct QTileRules
Qt::TileRule vertical;
};
+#ifndef Q_QDOC
+// For internal use only.
+namespace QDrawBorderPixmap
+{
+ enum DrawingHint
+ {
+ OpaqueTopLeft = 0x0001,
+ OpaqueTop = 0x0002,
+ OpaqueTopRight = 0x0004,
+ OpaqueLeft = 0x0008,
+ OpaqueCenter = 0x0010,
+ OpaqueRight = 0x0020,
+ OpaqueBottomLeft = 0x0040,
+ OpaqueBottom = 0x0080,
+ OpaqueBottomRight = 0x0100,
+ OpaqueCorners = OpaqueTopLeft | OpaqueTopRight | OpaqueBottomLeft | OpaqueBottomRight,
+ OpaqueEdges = OpaqueTop | OpaqueLeft | OpaqueRight | OpaqueBottom,
+ OpaqueFrame = OpaqueCorners | OpaqueEdges,
+ OpaqueAll = OpaqueCenter | OpaqueFrame
+ };
+
+ Q_DECLARE_FLAGS(DrawingHints, DrawingHint)
+}
+#endif
+
Q_GUI_EXPORT void qDrawBorderPixmap(QPainter *painter,
const QRect &targetRect,
const QMargins &targetMargins,
const QPixmap &pixmap,
const QRect &sourceRect,
const QMargins &sourceMargins,
- const QTileRules &rules = QTileRules());
+ const QTileRules &rules = QTileRules()
+#ifndef Q_QDOC
+ , QDrawBorderPixmap::DrawingHints hints = 0
+#endif
+ );
+
inline void qDrawBorderPixmap(QPainter *painter,
const QRect &target,
const QMargins &margins,
@@ -158,6 +188,31 @@ inline void qDrawBorderPixmap(QPainter *painter,
qDrawBorderPixmap(painter, target, margins, pixmap, pixmap.rect(), margins);
}
+// For internal use only.
+namespace QDrawPixmaps
+{
+ struct Data
+ {
+ QPointF point;
+ QRectF source;
+ qreal scaleX;
+ qreal scaleY;
+ qreal rotation;
+ qreal opacity;
+ };
+
+ enum DrawingHint
+ {
+ OpaqueHint = 0x01
+ };
+
+ Q_DECLARE_FLAGS(DrawingHints, DrawingHint)
+}
+
+// This function is private and may change without notice. Do not use outside Qt!!!
+Q_GUI_EXPORT void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData,
+ int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints = 0);
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 60e4df6..d712669 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -932,6 +932,31 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con
fill(path, brush);
}
+void QPaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
+{
+ qreal oldOpacity = state()->opacity;
+ QTransform oldTransform = state()->matrix;
+
+ for (int i = 0; i < dataCount; ++i) {
+ QTransform transform = oldTransform;
+ transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
+ transform.rotate(drawingData[i].rotation);
+ state()->opacity = oldOpacity * drawingData[i].opacity;
+ state()->matrix = transform;
+ opacityChanged();
+ transformChanged();
+
+ qreal w = drawingData[i].scaleX * drawingData[i].source.width();
+ qreal h = drawingData[i].scaleY * drawingData[i].source.height();
+ drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, drawingData[i].source);
+ }
+
+ state()->opacity = oldOpacity;
+ state()->matrix = oldTransform;
+ opacityChanged();
+ transformChanged();
+}
+
void QPaintEngineEx::setState(QPainterState *s)
{
QPaintEngine::state = s;
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index 814a0f0..81ed06b 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -71,6 +71,11 @@ class QPainterState;
class QPaintEngineExPrivate;
struct StrokeHandler;
+namespace QDrawPixmaps
+{
+ struct Data;
+ enum DrawingHint;
+}
struct QIntRect {
int x1, y1, x2, y2;
@@ -133,8 +138,6 @@ public:
qreal pts[8];
};
-
-
#ifndef QT_NO_DEBUG_STREAM
QDebug Q_GUI_EXPORT &operator<<(QDebug &, const QVectorPath &path);
#endif
@@ -198,6 +201,8 @@ public:
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
+ virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QFlags<QDrawPixmaps::DrawingHint> hints);
+
virtual void updateState(const QPaintEngineState &state);
virtual void setState(QPainterState *s);
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 28f3be3..19a8b63 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -694,7 +694,7 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e)
return;
qreal currentOffset = qreal(e->delta()) / 120;
- d->offset_accumulated += d->invertedControls ? -currentOffset : currentOffset;
+ d->offset_accumulated += currentOffset;
if (int(d->offset_accumulated) == 0) {
// QAbstractSlider works on integer values. So if the accumulated
// offset is less than +/- 1, we need to wait until we get more
@@ -703,17 +703,24 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e)
return;
}
- // Calculate the number of steps to scroll (per 15 degrees of rotate):
+ int stepsToScroll;
+ if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) {
+ stepsToScroll = currentOffset > 0 ? d->pageStep : -d->pageStep;
+ } else {
+ // Calculate the number of steps to scroll (per 15 degrees of rotate):
#ifdef Q_OS_MAC
- // On mac, since mouse wheel scrolling is accelerated and
- // fine tuned by the OS, we skip applying acceleration:
- int stepsToScroll = int(d->offset_accumulated);
+ // On mac, since mouse wheel scrolling is accelerated and
+ // fine tuned by the OS, we skip applying acceleration:
+ stepsToScroll = int(d->offset_accumulated);
#else
- int step = qMin(QApplication::wheelScrollLines() * d->singleStep, d->pageStep);
- if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier))
- step = d->pageStep;
- int stepsToScroll = step * int(d->offset_accumulated);
+ stepsToScroll = int(d->offset_accumulated) * QApplication::wheelScrollLines() * d->singleStep;
#endif
+ if (qAbs(stepsToScroll) > d->pageStep)
+ stepsToScroll = currentOffset > 0 ? d->pageStep : -d->pageStep;
+ }
+
+ if (d->invertedControls)
+ stepsToScroll = -stepsToScroll;
int prevValue = d->value;
d->position = d->overflowSafeAdd(stepsToScroll); // value will be updated by triggerAction()
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index fcb20b4..59c50aa 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -97,6 +97,7 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
code[MainVertexShader] = qglslMainVertexShader;
code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader;
+ code[MainWithTexCoordsAndOpacityVertexShader] = qglslMainWithTexCoordsAndOpacityVertexShader;
code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader;
code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader;
@@ -119,6 +120,7 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
code[MainFragmentShader_C] = qglslMainFragmentShader_C;
code[MainFragmentShader_O] = qglslMainFragmentShader_O;
code[MainFragmentShader] = qglslMainFragmentShader;
+ code[MainFragmentShader_ImageArrays] = qglslMainFragmentShader_ImageArrays;
code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader;
code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader;
@@ -285,6 +287,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
cached.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
if (cached.useTextureCoords)
cached.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+ if (cached.useOpacityAttribute)
+ cached.program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
cached.program->link();
if (!cached.program->isLinked()) {
@@ -331,7 +335,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
: ctx(context),
shaderProgNeedsChanging(true),
srcPixelType(Qt::NoBrush),
- useGlobalOpacity(false),
+ opacityMode(NoOpacity),
maskType(NoMask),
compositionMode(QPainter::CompositionMode_SourceOver),
customSrcStage(0),
@@ -407,12 +411,12 @@ void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type)
shaderProgNeedsChanging = true; //###
}
-void QGLEngineShaderManager::setUseGlobalOpacity(bool useOpacity)
+void QGLEngineShaderManager::setOpacityMode(OpacityMode mode)
{
- if (useGlobalOpacity == useOpacity)
+ if (opacityMode == mode)
return;
- useGlobalOpacity = useOpacity;
+ opacityMode = mode;
shaderProgNeedsChanging = true; //###
}
@@ -564,22 +568,28 @@ bool QGLEngineShaderManager::useCorrectShaderProg()
// Choose fragment shader main function:
QGLEngineSharedShaders::ShaderName mainFragShaderName;
- if (hasCompose && hasMask && useGlobalOpacity)
- mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CMO;
- if (hasCompose && hasMask && !useGlobalOpacity)
- mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CM;
- if (!hasCompose && hasMask && useGlobalOpacity)
- mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_MO;
- if (!hasCompose && hasMask && !useGlobalOpacity)
- mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_M;
- if (hasCompose && !hasMask && useGlobalOpacity)
- mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CO;
- if (hasCompose && !hasMask && !useGlobalOpacity)
- mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_C;
- if (!hasCompose && !hasMask && useGlobalOpacity)
- mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_O;
- if (!hasCompose && !hasMask && !useGlobalOpacity)
- mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader;
+ if (opacityMode == AttributeOpacity) {
+ Q_ASSERT(!hasCompose && !hasMask);
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_ImageArrays;
+ } else {
+ bool useGlobalOpacity = (opacityMode == UniformOpacity);
+ if (hasCompose && hasMask && useGlobalOpacity)
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CMO;
+ if (hasCompose && hasMask && !useGlobalOpacity)
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CM;
+ if (!hasCompose && hasMask && useGlobalOpacity)
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_MO;
+ if (!hasCompose && hasMask && !useGlobalOpacity)
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_M;
+ if (hasCompose && !hasMask && useGlobalOpacity)
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CO;
+ if (hasCompose && !hasMask && !useGlobalOpacity)
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_C;
+ if (!hasCompose && !hasMask && useGlobalOpacity)
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_O;
+ if (!hasCompose && !hasMask && !useGlobalOpacity)
+ mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader;
+ }
requiredProgram.mainFragShader = sharedShaders->compileNamedShader(mainFragShaderName, QGLShader::PartialFragmentShader);
@@ -652,12 +662,17 @@ bool QGLEngineShaderManager::useCorrectShaderProg()
// Choose vertex shader main function
QGLEngineSharedShaders::ShaderName mainVertexShaderName = QGLEngineSharedShaders::InvalidShaderName;
- if (texCoords)
+ if (opacityMode == AttributeOpacity) {
+ Q_ASSERT(texCoords);
+ mainVertexShaderName = QGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader;
+ } else if (texCoords) {
mainVertexShaderName = QGLEngineSharedShaders::MainWithTexCoordsVertexShader;
- else
+ } else {
mainVertexShaderName = QGLEngineSharedShaders::MainVertexShader;
+ }
requiredProgram.mainVertexShader = sharedShaders->compileNamedShader(mainVertexShaderName, QGLShader::PartialVertexShader);
requiredProgram.useTextureCoords = texCoords;
+ requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
// At this point, requiredProgram is fully populated so try to find the program in the cache
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index fbb6d9c..291d24c 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -247,6 +247,7 @@ struct QGLEngineShaderProg
QVector<uint> uniformLocations;
bool useTextureCoords;
+ bool useOpacityAttribute;
bool operator==(const QGLEngineShaderProg& other) {
// We don't care about the program
@@ -277,6 +278,7 @@ struct QGLEngineCachedShaderProg
static const GLuint QT_VERTEX_COORDS_ATTR = 0;
static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
+static const GLuint QT_OPACITY_ATTR = 2;
class QGLEngineSharedShaders : public QObject
{
@@ -285,6 +287,7 @@ public:
enum ShaderName {
MainVertexShader,
MainWithTexCoordsVertexShader,
+ MainWithTexCoordsAndOpacityVertexShader,
UntransformedPositionVertexShader,
PositionOnlyVertexShader,
@@ -307,6 +310,7 @@ public:
MainFragmentShader_C,
MainFragmentShader_O,
MainFragmentShader,
+ MainFragmentShader_ImageArrays,
ImageSrcFragmentShader,
ImageSrcWithPatternFragmentShader,
@@ -406,13 +410,19 @@ public:
NumUniforms
};
+ enum OpacityMode {
+ NoOpacity,
+ UniformOpacity,
+ AttributeOpacity
+ };
+
// There are optimisations we can do, depending on the brush transform:
// 1) May not have to apply perspective-correction
// 2) Can use lower precision for matrix
void optimiseForBrushTransform(const QTransform &transform);
void setSrcPixelType(Qt::BrushStyle);
void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images
- void setUseGlobalOpacity(bool);
+ void setOpacityMode(OpacityMode);
void setMaskType(MaskType);
void setCompositionMode(QPainter::CompositionMode);
void setCustomStage(QGLCustomShaderStage* stage);
@@ -451,7 +461,7 @@ private:
// Current state variables which influence the choice of shader:
QTransform brushTransform;
int srcPixelType;
- bool useGlobalOpacity;
+ OpacityMode opacityMode;
MaskType maskType;
QPainter::CompositionMode compositionMode;
QGLCustomShaderStage* customSrcStage;
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
index 8ae86d3..6712bf6 100644
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -84,6 +84,20 @@ static const char* const qglslMainWithTexCoordsVertexShader = "\
textureCoords = textureCoordArray; \
}";
+static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\
+ attribute highp vec2 textureCoordArray; \
+ attribute lowp float opacityArray; \
+ varying highp vec2 textureCoords; \
+ varying lowp float opacity; \
+ uniform highp float depth; \
+ void setPosition(); \
+ void main(void) \
+ { \
+ setPosition(); \
+ gl_Position.z = depth * gl_Position.w; \
+ textureCoords = textureCoordArray; \
+ opacity = opacityArray; \
+ }";
static const char* const qglslPositionOnlyVertexShader = "\
attribute highp vec4 vertexCoordsArray;\
@@ -331,6 +345,12 @@ static const char* const qglslShockingPinkSrcFragmentShader = "\
return vec4(0.98, 0.06, 0.75, 1.0); \
}";
+static const char* const qglslMainFragmentShader_ImageArrays = "\
+ varying lowp float opacity; \
+ lowp vec4 srcPixel(); \
+ void main() { \
+ gl_FragColor = srcPixel() * opacity; \
+ }";
static const char* const qglslMainFragmentShader_CMO = "\
uniform lowp float globalOpacity; \
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index f612bc0..992d47d 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -366,7 +366,7 @@ void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMod
}
-QColor QGL2PaintEngineExPrivate::premultiplyColor(QColor c, GLfloat opacity)
+inline QColor qt_premultiplyColor(QColor c, GLfloat opacity)
{
qreal alpha = c.alphaF() * opacity;
c.setAlphaF(alpha);
@@ -469,7 +469,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
QTransform brushQTransform = currentBrush->transform();
if (style == Qt::SolidPattern) {
- QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
+ QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::FragmentColor), col);
}
else {
@@ -479,7 +479,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (style <= Qt::DiagCrossPattern) {
translationPoint = q->state()->brushOrigin;
- QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
+ QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
@@ -541,7 +541,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
const QPixmap& texPixmap = currentBrush->texture();
if (qHasPixmapTexture(*currentBrush) && currentBrush->texture().isQBitmap()) {
- QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
+ QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
}
@@ -712,7 +712,7 @@ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& s
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
if (pattern) {
- QColor col = premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
+ QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
}
@@ -796,9 +796,10 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
if (newMode == mode)
return;
- if (mode == TextDrawingMode || mode == ImageDrawingMode) {
+ if (mode == TextDrawingMode || mode == ImageDrawingMode || mode == ImageArrayDrawingMode) {
glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_OPACITY_ATTR);
lastTexture = GLuint(-1);
}
@@ -824,6 +825,16 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticTextureCoordinateArray);
}
+ if (newMode == ImageArrayDrawingMode) {
+ glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_OPACITY_ATTR);
+
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
+ glVertexAttribPointer(QT_OPACITY_ATTR, 1, GL_FLOAT, GL_FALSE, 0, opacityArray.data());
+ }
+
// This needs to change when we implement high-quality anti-aliasing...
if (newMode != TextDrawingMode)
shaderManager->setMaskType(QGLEngineShaderManager::NoMask);
@@ -953,7 +964,7 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve
bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
{
- if (brushTextureDirty && mode != ImageDrawingMode)
+ if (brushTextureDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
updateBrushTexture();
if (compositionModeDirty)
@@ -972,16 +983,22 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
glEnable(GL_BLEND);
}
- bool useGlobalOpacityUniform = stateHasOpacity;
- if (stateHasOpacity && (mode != ImageDrawingMode)) {
- // Using a brush
- bool brushIsPattern = (currentBrush->style() >= Qt::Dense1Pattern) &&
- (currentBrush->style() <= Qt::DiagCrossPattern);
-
- if ((currentBrush->style() == Qt::SolidPattern) || brushIsPattern)
- useGlobalOpacityUniform = false; // Global opacity handled by srcPixel shader
+ QGLEngineShaderManager::OpacityMode opacityMode;
+ if (mode == ImageArrayDrawingMode) {
+ opacityMode = QGLEngineShaderManager::AttributeOpacity;
+ } else {
+ opacityMode = stateHasOpacity ? QGLEngineShaderManager::UniformOpacity
+ : QGLEngineShaderManager::NoOpacity;
+ if (stateHasOpacity && (mode != ImageDrawingMode)) {
+ // Using a brush
+ bool brushIsPattern = (currentBrush->style() >= Qt::Dense1Pattern) &&
+ (currentBrush->style() <= Qt::DiagCrossPattern);
+
+ if ((currentBrush->style() == Qt::SolidPattern) || brushIsPattern)
+ opacityMode = QGLEngineShaderManager::NoOpacity; // Global opacity handled by srcPixel shader
+ }
}
- shaderManager->setUseGlobalOpacity(useGlobalOpacityUniform);
+ shaderManager->setOpacityMode(opacityMode);
bool changed = shaderManager->useCorrectShaderProg();
// If the shader program needs changing, we change it and mark all uniforms as dirty
@@ -993,7 +1010,7 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
opacityUniformDirty = true;
}
- if (brushUniformsDirty && mode != ImageDrawingMode)
+ if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
updateBrushUniforms();
if (shaderMatrixUniformDirty) {
@@ -1006,7 +1023,7 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
depthUniformDirty = false;
}
- if (useGlobalOpacityUniform && opacityUniformDirty) {
+ if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) {
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity);
opacityUniformDirty = false;
}
@@ -1332,7 +1349,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly
QColor c = pensBrush.color();
qreal oldOpacity = q->state()->opacity;
if (compMode == QPainter::CompositionMode_Source) {
- c = premultiplyColor(c, q->state()->opacity);
+ c = qt_premultiplyColor(c, q->state()->opacity);
q->state()->opacity = 1;
opacityUniformDirty = true;
}
@@ -1411,6 +1428,96 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly
glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
}
+void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
+{
+ // Use fallback for extended composition modes.
+ if (state()->composition_mode > QPainter::CompositionMode_Plus) {
+ QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints);
+ return;
+ }
+
+ Q_D(QGL2PaintEngineEx);
+
+ GLfloat dx = 1.0f / pixmap.size().width();
+ GLfloat dy = 1.0f / pixmap.size().height();
+
+ d->vertexCoordinateArray.clear();
+ d->textureCoordinateArray.clear();
+ d->opacityArray.reset();
+
+ bool allOpaque = true;
+
+ for (int i = 0; i < dataCount; ++i) {
+ qreal s = 0;
+ qreal c = 1;
+ if (drawingData[i].rotation != 0) {
+ s = qFastSin(drawingData[i].rotation * Q_PI / 180);
+ c = qFastCos(drawingData[i].rotation * Q_PI / 180);
+ }
+
+ qreal right = 0.5 * drawingData[i].scaleX * drawingData[i].source.width();
+ qreal bottom = 0.5 * drawingData[i].scaleY * drawingData[i].source.height();
+ QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c);
+ QGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c);
+
+ d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y());
+ d->vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y());
+ d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y());
+ d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y());
+ d->vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y());
+ d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y());
+
+ QGLRect src(drawingData[i].source.left() * dx, drawingData[i].source.top() * dy,
+ drawingData[i].source.right() * dx, drawingData[i].source.bottom() * dy);
+
+ d->textureCoordinateArray.lineToArray(src.right, src.bottom);
+ d->textureCoordinateArray.lineToArray(src.right, src.top);
+ d->textureCoordinateArray.lineToArray(src.left, src.top);
+ d->textureCoordinateArray.lineToArray(src.left, src.top);
+ d->textureCoordinateArray.lineToArray(src.left, src.bottom);
+ d->textureCoordinateArray.lineToArray(src.right, src.bottom);
+
+ qreal opacity = drawingData[i].opacity * state()->opacity;
+ d->opacityArray << opacity << opacity << opacity << opacity << opacity << opacity;
+ allOpaque &= (opacity >= 0.99f);
+ }
+
+ ensureActive();
+
+ QGLContext *ctx = d->ctx;
+ glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA,
+ QGLContext::InternalBindOption
+ | QGLContext::CanFlipNativePixmapBindOption);
+
+ if (texture->options & QGLContext::InvertedYBindOption) {
+ // Flip texture y-coordinate.
+ QGLPoint *data = d->textureCoordinateArray.data();
+ for (int i = 0; i < 6 * dataCount; ++i)
+ data[i].y = 1 - data[i].y;
+ }
+
+ d->transferMode(ImageArrayDrawingMode);
+
+ bool isBitmap = pixmap.isQBitmap();
+ bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QDrawPixmaps::OpaqueHint)) && allOpaque;
+
+ d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
+ state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
+
+ // Setup for texture drawing
+ d->shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
+ if (d->prepareForDraw(isOpaque))
+ d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
+
+ if (isBitmap) {
+ QColor col = qt_premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity);
+ d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::PatternColor), col);
+ }
+
+ glDrawArrays(GL_TRIANGLES, 0, 6 * dataCount);
+}
+
bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
{
Q_D(QGL2PaintEngineEx);
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index f245945..4f42082 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -61,11 +61,13 @@
#include <private/qglpaintdevice_p.h>
#include <private/qglpixmapfilter_p.h>
#include <private/qfontengine_p.h>
+#include <private/qdatabuffer_p.h>
enum EngineMode {
ImageDrawingMode,
TextDrawingMode,
- BrushDrawingMode
+ BrushDrawingMode,
+ ImageArrayDrawingMode
};
QT_BEGIN_NAMESPACE
@@ -126,6 +128,8 @@ public:
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
+ virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints);
+
Type type() const { return OpenGL2; }
void setState(QPainterState *s);
@@ -195,7 +199,6 @@ public:
// ^ returns whether the current program changed or not
inline void useSimpleShader();
- inline QColor premultiplyColor(QColor c, GLfloat opacity);
float zValueForRenderText() const;
@@ -230,6 +233,7 @@ public:
QGL2PEXVertexArray vertexCoordinateArray;
QGL2PEXVertexArray textureCoordinateArray;
+ QDataBuffer<GLfloat> opacityArray;
GLfloat staticVertexCoordinateArray[8];
GLfloat staticTextureCoordinateArray[8];
diff --git a/src/s60installs/qt.svg b/src/s60installs/qt.svg
new file mode 100644
index 0000000..22cb204
--- /dev/null
+++ b/src/s60installs/qt.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" baseProfile="tiny" height="146.3063" version="1.0" viewBox="0 0 122 146" width="121.60006">
+<g transform="translate(-376.34283,-407.78046)">
+<g transform="matrix(0.697424,0,0,0.697424,376.34283,407.78046)">
+<path d="M 43.086,0.358597 C 40.9414,0.00358582 38.8399,-0.0824127 36.8086,0.0775909 L 36.8047,0.0735931 C 36.8047,0.0735931 22.9219,1.01859 22.2891,1.0696 C 9.6211,2.08159 0,12.5036 0,26.8896 L 0,196.554 L 14.1914,209.781 L 156.789,185.816 C 166.606,184.113 174.356,172.538 174.356,160.038 L 174.356,21.8786 L 43.086,0.358597 z" style="fill:#105000;fill-rule:evenodd;stroke:none"/>
+<path d="M 174.356,160.042 C 174.356,172.538 166.606,184.113 156.789,185.816 L 14.1914,209.781 L 14.1914,25.9916 C 14.1914,9.2726 27.5313,-2.20741 43.086,0.358597 L 174.356,21.8786 L 174.356,160.042 z" style="fill:#3fe400;fill-rule:evenodd;stroke:none"/>
+<path d="M 130.422,45.9136 L 141.938,47.1516 L 141.938,67.3626 L 154.899,68.2766 L 154.899,80.9566 L 141.938,80.3586 L 141.938,126.691 C 141.938,130.723 142.383,133.316 143.278,134.48 C 144.078,135.547 145.324,136.074 146.988,136.074 C 147.149,136.074 147.317,136.07 147.485,136.058 C 150.035,135.91 152.805,135.125 155.828,133.75 L 155.828,145.398 C 150.692,147.656 145.653,148.996 140.703,149.418 C 139.985,149.473 139.293,149.504 138.625,149.504 C 134.145,149.504 130.719,148.203 128.379,145.57 C 125.649,142.519 124.289,137.621 124.289,130.898 L 124.289,79.5426 L 118.063,79.2576 L 118.063,65.6716 L 125.649,66.2186 L 130.422,45.9136 z" style="fill:#ffffff;fill-rule:evenodd;stroke:none"/>
+<path d="M 154.899,80.9566 L 141.938,80.3586 L 141.938,80.6366 L 148.883,80.9566 L 154.899,80.9566 z" style="fill:#105000;fill-rule:evenodd;stroke:none"/>
+<path d="M 144.637,135.598 C 145.297,135.926 146.067,136.074 146.988,136.074 C 147.149,136.074 147.317,136.07 147.485,136.058 C 150.035,135.91 152.805,135.125 155.828,133.75 L 149.813,133.75 C 147.992,134.582 146.281,135.207 144.637,135.598 z" style="fill:#105000;fill-rule:evenodd;stroke:none"/>
+<path d="M 128.379,145.57 C 125.649,142.519 124.289,137.621 124.289,130.898 L 124.289,79.5426 L 118.063,79.2576 L 118.063,65.6716 L 112.047,65.6716 L 112.047,68.7066 C 112.918,71.9796 113.602,75.5266 114.11,79.3506 L 118.274,79.5426 L 118.274,130.898 C 118.274,137.621 119.641,142.519 122.364,145.57 C 124.707,148.203 128.129,149.504 132.61,149.504 L 138.625,149.504 C 134.145,149.504 130.719,148.203 128.379,145.57 z M 130.422,45.9136 L 124.406,45.9136 L 119.738,65.7966 L 125.649,66.2186 L 130.422,45.9136 z" style="fill:#105000;fill-rule:evenodd;stroke:none"/>
+<path d="M 91.1528,132.406 C 93.5038,126.355 94.6638,114.492 94.6638,96.7886 C 94.6638,80.8976 93.5158,69.9726 91.1798,63.9756 C 88.8438,57.9486 85.3478,54.6946 80.6598,54.2846 C 80.3008,54.2536 79.9458,54.2336 79.6018,54.2336 C 75.2618,54.2336 71.9218,56.7686 69.5938,61.8586 C 67.0738,67.4016 65.8008,78.8976 65.8008,96.2966 C 65.8008,113.113 67.0388,125.047 69.5348,132.051 C 71.8908,138.723 75.4138,142.027 80.0388,142.027 C 80.2458,142.027 80.4488,142.019 80.6598,142.008 C 85.2928,141.715 88.7808,138.512 91.1528,132.406 M 109.129,136.156 C 105.012,145.863 98.7348,152.214 90.1408,155.156 C 91.0078,159.605 92.3168,162.597 94.0628,164.175 C 95.4138,165.386 97.4958,165.996 100.285,165.996 C 101.09,165.996 101.953,165.941 102.875,165.839 L 102.875,178.964 L 96.9138,179.746 C 95.1558,179.976 93.4878,180.089 91.9098,180.089 C 86.6918,180.089 82.4648,178.824 79.2888,176.265 C 75.0818,172.886 71.9808,166.371 69.9918,156.73 C 60.8555,154.785 53.7344,148.976 48.8008,139.226 C 43.7969,129.324 41.25,114.836 41.25,95.8866 C 41.25,75.4566 44.7344,60.3786 51.5938,50.8156 C 57.3828,42.7456 65.4568,38.7766 75.6168,38.7766 C 77.2458,38.7766 78.9258,38.8786 80.6598,39.0816 C 92.6138,40.4566 101.278,46.0976 106.918,55.8706 C 112.453,65.4326 115.172,79.1366 115.172,97.1326 C 115.172,113.617 113.172,126.582 109.129,136.156 z" style="fill:#ffffff;fill-rule:evenodd;stroke:none"/>
+<path d="M 100.281,165.996 C 101.09,165.996 101.953,165.941 102.871,165.839 L 98.0348,165.839 C 98.7108,165.945 99.4878,165.996 100.281,165.996 z" style="fill:#105000;fill-rule:evenodd;stroke:none"/>
+<path d="M 84.8518,63.9756 C 87.1878,69.9726 88.3358,80.8976 88.3358,96.7886 C 88.3358,114.492 87.1758,126.355 84.8238,132.406 C 82.9298,137.285 80.2968,140.308 76.9608,141.476 C 77.9258,141.844 78.9528,142.027 80.0388,142.027 C 80.2458,142.027 80.4488,142.019 80.6598,142.008 C 85.2928,141.715 88.7808,138.512 91.1528,132.406 C 93.5038,126.355 94.6638,114.492 94.6638,96.7886 C 94.6638,80.8976 93.5158,69.9726 91.1798,63.9756 C 88.8438,57.9486 85.3478,54.6946 80.6598,54.2846 C 80.3008,54.2536 79.9458,54.2336 79.6018,54.2336 C 78.5118,54.2336 77.4848,54.3936 76.5198,54.7146 L 76.5198,54.7146 L 76.5158,54.7146 C 80.1168,55.8356 82.8948,58.9296 84.8518,63.9756 z M 82.5078,178.253 C 82.3948,178.203 82.2808,178.148 82.1718,178.093 C 82.1598,178.089 82.1488,178.081 82.1368,178.078 C 82.0348,178.027 81.9298,177.972 81.8278,177.921 C 81.8088,177.91 81.7888,177.902 81.7698,177.89 C 81.6798,177.839 81.5858,177.792 81.4918,177.742 C 81.4648,177.726 81.4378,177.706 81.4058,177.691 C 81.3238,177.648 81.2418,177.601 81.1638,177.554 C 81.1248,177.531 81.0858,177.507 81.0508,177.484 C 80.9808,177.445 80.9058,177.402 80.8358,177.359 C 80.7888,177.328 80.7418,177.3 80.6958,177.269 C 80.6368,177.23 80.5778,177.195 80.5198,177.156 C 80.4608,177.117 80.4058,177.081 80.3518,177.042 C 80.3008,177.011 80.2498,176.976 80.2028,176.945 C 80.1368,176.898 80.0708,176.851 80.0078,176.808 C 79.9688,176.781 79.9298,176.753 79.8948,176.726 C 79.8168,176.671 79.7418,176.613 79.6638,176.554 C 79.6408,176.538 79.6138,176.519 79.5858,176.499 C 79.4878,176.421 79.3868,176.343 79.2888,176.265 C 75.0818,172.886 71.9808,166.371 69.9918,156.73 C 60.8555,154.785 53.7344,148.976 48.8008,139.226 C 43.7969,129.324 41.25,114.836 41.25,95.8866 C 41.25,75.4566 44.7344,60.3786 51.5938,50.8156 C 57.3828,42.7456 65.4568,38.7766 75.6168,38.7766 C 75.6528,38.7766 69.2658,38.7766 69.2658,38.7766 L 69.2658,38.7766 C 59.1172,38.7846 51.0508,42.7536 45.2656,50.8156 C 38.4102,60.3786 34.9219,75.4566 34.9219,95.8866 C 34.9219,114.836 37.4688,129.324 42.4727,139.226 C 47.4063,148.976 54.5274,154.785 63.6638,156.73 C 65.6528,166.371 68.7538,172.886 72.9608,176.265 C 76.1368,178.824 80.3638,180.089 85.5858,180.089 C 85.6838,180.089 85.7848,180.089 85.8828,180.085 L 91.4218,180.085 C 88.0158,180.035 85.0388,179.425 82.5158,178.257 C 82.5158,178.257 82.5118,178.257 82.5078,178.253 z" style="fill:#105000;fill-rule:evenodd;stroke:none"/>
+</g>
+</g>
+</svg>