From d576d770b9b8251f1b5b4808a84045af33e62dba Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 23 Oct 2009 09:30:26 +0200 Subject: Removed pixelize, bloom and grayscale filter This is new API and we don't want to add several items that are not strictly needed. This is a new set of features and we can grow them once we have more input from users on what is needed. The Bloom filter was added based on input from designers, but is not implemented according to how designers think of blook, so the effect doesn't meet the requirements. The Grayscale filter is functionally a duplicate of the colorize filter and is therefore not needed. The Pixelize filter has no genuine usecase. Reviewed-by: Samuel --- src/gui/effects/qgraphicseffect.cpp | 453 +----------------------------------- src/gui/effects/qgraphicseffect.h | 88 ------- src/gui/effects/qgraphicseffect_p.h | 37 --- 3 files changed, 4 insertions(+), 574 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 96d35b0..e25b40b 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -65,9 +65,6 @@ \o QGraphicsDropShadowEffect - renders a dropshadow behind the item \o QGraphicsColorizeEffect - renders the item in shades of any given color \o QGraphicsOpacityEffect - renders the item with an opacity - \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size - \o QGraphicsGrayscaleEffect - renders the item in shades of gray - \o QGraphicsBloomEffect - applies a blooming / glowing effect \endlist \img graphicseffect-effects.png @@ -458,96 +455,6 @@ void QGraphicsEffect::sourceChanged(ChangeFlags flags) } /*! - \class QGraphicsGrayscaleEffect - \brief The QGraphicsGrayscaleEffect class provides a grayscale effect. - \since 4.6 - - A grayscale effect renders the source in shades of gray. - - \img graphicseffect-grayscale.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect -*/ - -/*! - Constructs a new QGraphicsGrayscale instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent) -{ -} - -/*! - Destroys the effect. -*/ -QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() -{ -} - - -/*! - \property QGraphicsGrayscaleEffect::strength - \brief the strength of the effect. - - By default, the strength is 1.0. - A strength 0.0 equals to no effect, while 1.0 means full grayscale. -*/ -qreal QGraphicsGrayscaleEffect::strength() const -{ - Q_D(const QGraphicsGrayscaleEffect); - return d->filter->strength(); -} - -void QGraphicsGrayscaleEffect::setStrength(qreal strength) -{ - Q_D(QGraphicsGrayscaleEffect); - if (qFuzzyCompare(d->filter->strength(), strength)) - return; - - d->filter->setStrength(strength); - d->opaque = !qFuzzyIsNull(strength); - update(); - emit strengthChanged(strength); -} - -/*! \fn void QGraphicsGrayscaleEffect::strengthChanged(qreal strength) - This signal is emitted whenever setStrength() changes the grayscale - strength property. \a strength contains the new strength value of - the grayscale effect. - */ - -/*! - \reimp -*/ -void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsGrayscaleEffect); - - if (!d->opaque) { - source->draw(painter); - return; - } - - QPoint offset; - if (source->isPixmap()) { - // No point in drawing in device coordinates (pixmap will be scaled anyways). - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - d->filter->draw(painter, offset, pixmap); - return; - } - - // Draw pixmap in device coordinates to avoid pixmap scaling; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - d->filter->draw(painter, offset, pixmap); - painter->setWorldTransform(restoreTransform); - -} - -/*! \class QGraphicsColorizeEffect \brief The QGraphicsColorizeEffect class provides a colorize effect. \since 4.6 @@ -559,8 +466,7 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so \img graphicseffect-colorize.png - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsOpacityEffect + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsOpacityEffect */ /*! @@ -669,126 +575,6 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou } /*! - \class QGraphicsPixelizeEffect - \brief The QGraphicsPixelizeEffect class provides a pixelize effect. - \since 4.6 - - A pixelize effect renders the source in lower resolution. This effect is - useful for reducing details, like censorship. The resolution can be - modified using the setPixelSize() function. - - By default, the pixel size is 3. - - \img graphicseffect-pixelize.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect -*/ - -/*! - Constructs a new QGraphicsPixelizeEffect instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent) -{ -} - -/*! - Destroys the effect. -*/ -QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect() -{ -} - -/*! - \property QGraphicsPixelizeEffect::pixelSize - \brief the size of a pixel in the effect. - - Setting the pixel size to 2 means two pixels in the source will be used to - represent one pixel. Using a bigger size results in lower resolution. - - By default, the pixel size is 3. -*/ -int QGraphicsPixelizeEffect::pixelSize() const -{ - Q_D(const QGraphicsPixelizeEffect); - return d->pixelSize; -} - -void QGraphicsPixelizeEffect::setPixelSize(int size) -{ - Q_D(QGraphicsPixelizeEffect); - if (d->pixelSize == size) - return; - - d->pixelSize = size; - update(); - emit pixelSizeChanged(size); -} - -/*! - \fn void QGraphicsPixelizeEffect::pixelSizeChanged(int size) - - This signal is emitted whenever the effect's pixel size changes. - The \a size parameter holds the effect's new pixel size. -*/ - -static inline void pixelize(QImage *image, int pixelSize) -{ - Q_ASSERT(pixelSize > 0); - Q_ASSERT(image); - int width = image->width(); - int height = image->height(); - for (int y = 0; y < height; y += pixelSize) { - int ys = qMin(height - 1, y + pixelSize / 2); - QRgb *sbuf = reinterpret_cast(image->scanLine(ys)); - for (int x = 0; x < width; x += pixelSize) { - int xs = qMin(width - 1, x + pixelSize / 2); - QRgb color = sbuf[xs]; - for (int yi = 0; yi < qMin(pixelSize, height - y); ++yi) { - QRgb *buf = reinterpret_cast(image->scanLine(y + yi)); - for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi) - buf[x + xi] = color; - } - } - } -} - -/*! - \reimp -*/ -void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsPixelizeEffect); - if (d->pixelSize <= 0) { - source->draw(painter); - return; - } - - QPoint offset; - if (source->isPixmap()) { - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - pixelize(&image, d->pixelSize); - painter->drawImage(offset, image); - return; - } - - // Draw pixmap in device coordinates to avoid pixmap scaling. - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - - // pixelize routine - QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - pixelize(&image, d->pixelSize); - - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - painter->drawImage(offset, image); - painter->setWorldTransform(restoreTransform); -} - -/*! \class QGraphicsBlurEffect \brief The QGraphicsBlurEffect class provides a blur effect. \since 4.6 @@ -802,8 +588,7 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou \img graphicseffect-blur.png - \sa QGraphicsDropShadowEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect + \sa QGraphicsDropShadowEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ /*! @@ -937,8 +722,7 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) \img graphicseffect-drop-shadow.png - \sa QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect + \sa QGraphicsBlurEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ /*! @@ -1117,8 +901,7 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s \img graphicseffect-opacity.png - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsColorizeEffect + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsColorizeEffect */ /*! @@ -1296,234 +1079,6 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour painter->restore(); } -/*! - \class QGraphicsBloomEffect - \brief The QGraphicsBloomEffect class provides a bloom/glow effect. - \since 4.6 - - A bloom/glow effect adds fringes of light around bright areas in the source. - - \img graphicseffect-bloom.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsColorizeEffect -*/ - -/*! - Constructs a new QGraphicsBloomEffect instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsBloomEffect::QGraphicsBloomEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsBloomEffectPrivate, parent) -{ - Q_D(QGraphicsBloomEffect); - for (int i = 0; i < 256; ++i) - d->colorTable[i] = qMin(i + d->brightness, 255); -} - -/*! - Destroys the effect. -*/ -QGraphicsBloomEffect::~QGraphicsBloomEffect() -{ -} - -/*! - \reimp -*/ -QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsBloomEffect); - const qreal delta = d->blurFilter.radius() * 2; - return rect.adjusted(-delta, -delta, delta, delta); -} - -/*! - \property QGraphicsBloomEffect::blurRadius - \brief the blur radius in pixels of the effect. - - Using a smaller radius results in a sharper appearance, whereas a bigger - radius results in a more blurred appearance. - - By default, the blur radius is 5 pixels. - - \sa strength(), brightness() -*/ -int QGraphicsBloomEffect::blurRadius() const -{ - Q_D(const QGraphicsBloomEffect); - return d->blurFilter.radius(); -} - -void QGraphicsBloomEffect::setBlurRadius(int radius) -{ - Q_D(QGraphicsBloomEffect); - if (d->blurFilter.radius() == radius) - return; - - d->blurFilter.setRadius(radius); - updateBoundingRect(); - emit blurRadiusChanged(radius); -} - -/*! - \fn void QGraphicsBloomEffect::blurRadiusChanged(int blurRadius) - - This signal is emitted whenever the effect's blur radius changes. - The \a blurRadius parameter holds the effect's new blur radius. -*/ - -/*! - \property QGraphicsBloomEffect::blurHint - \brief the blur hint of the effect. - - Use the Qt::PerformanceHint hint to say that you want a faster blur, - and the Qt::QualityHint hint to say that you prefer a higher quality blur. - - When animating the blur radius it's recommended to use Qt::PerformanceHint. - - By default, the blur hint is Qt::PerformanceHint. -*/ -Qt::RenderHint QGraphicsBloomEffect::blurHint() const -{ - Q_D(const QGraphicsBloomEffect); - return d->blurFilter.blurHint(); -} - -void QGraphicsBloomEffect::setBlurHint(Qt::RenderHint hint) -{ - Q_D(QGraphicsBloomEffect); - if (d->blurFilter.blurHint() == hint) - return; - - d->blurFilter.setBlurHint(hint); - emit blurHintChanged(hint); -} - -/*! - \fn void QGraphicsBloomEffect::blurHintChanged(Qt::RenderHint hint) - - This signal is emitted whenever the effect's blur hint changes. - The \a hint parameter holds the effect's new blur hint. -*/ - -/*! - \property QGraphicsBloomEffect::brightness - \brief the brightness of the glow. - - The value should be in the range of 0 to 255, where 0 is dark - and 255 is bright. - - By default, the brightness is 70. - - \sa strength(), blurRadius() -*/ -int QGraphicsBloomEffect::brightness() const -{ - Q_D(const QGraphicsBloomEffect); - return d->brightness; -} - -void QGraphicsBloomEffect::setBrightness(int brightness) -{ - Q_D(QGraphicsBloomEffect); - brightness = qBound(0, brightness, 255); - if (d->brightness == brightness) - return; - - d->brightness = brightness; - for (int i = 0; i < 256; ++i) - d->colorTable[i] = qMin(i + brightness, 255); - - update(); - emit brightnessChanged(brightness); -} - -/*! - \fn void QGraphicsBloomEffect::brightnessChanged(int brightness) - - This signal is emitted whenever the effect's brightness changes. - The \a brightness parameter holds the effect's new brightness. -*/ - -/*! - \property QGraphicsBloomEffect::strength - \brief the strength of the effect. - - A strength 0.0 equals to no effect, while 1.0 means maximum glow. - - By default, the strength is 0.7. -*/ -qreal QGraphicsBloomEffect::strength() const -{ - Q_D(const QGraphicsBloomEffect); - return d->strength; -} - -void QGraphicsBloomEffect::setStrength(qreal strength) -{ - Q_D(QGraphicsBloomEffect); - strength = qBound(qreal(0.0), strength, qreal(1.0)); - if (qFuzzyCompare(d->strength, strength)) - return; - - d->strength = strength; - update(); - emit strengthChanged(strength); -} - -/*! - \fn void QGraphicsBloomEffect::strengthChanged(qreal strength) - - This signal is emitted whenever the effect's strength changes. - The \a strength parameter holds the effect's new strength. -*/ - -extern QPixmap qt_toRasterPixmap(const QPixmap &pixmap); - -/*! - \reimp -*/ -void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsBloomEffect); - if (d->strength < 0.001) { - source->draw(painter); - return; - } - - QPoint offset; - QPixmap pixmap = qt_toRasterPixmap(source->pixmap(Qt::DeviceCoordinates, &offset)); - - // Blur. - QImage overlay(pixmap.size(), QImage::Format_ARGB32_Premultiplied); - overlay.fill(0); - - QPainter blurPainter(&overlay); - d->blurFilter.draw(&blurPainter, QPointF(), pixmap); - blurPainter.end(); - - // Brighten. - const int numBits = overlay.width() * overlay.height(); - QRgb *bits = reinterpret_cast(overlay.bits()); - for (int i = 0; i < numBits; ++i) { - const QRgb pixel = INV_PREMUL(bits[i]); - bits[i] = PREMUL(qRgba(d->colorTable[qRed(pixel)], d->colorTable[qGreen(pixel)], - d->colorTable[qBlue(pixel)], qAlpha(pixel))); - } - - // Composite. - QPainter compPainter(&pixmap); - compPainter.setCompositionMode(QPainter::CompositionMode_Overlay); - compPainter.setOpacity(d->strength); - compPainter.drawImage(0, 0, overlay); - compPainter.end(); - - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - painter->drawPixmap(offset, pixmap); - painter->setWorldTransform(restoreTransform); -} QT_END_NAMESPACE diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index c89851e..019e808 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -141,31 +141,6 @@ private: }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsEffect::ChangeFlags) -class QGraphicsGrayscaleEffectPrivate; -class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) -public: - QGraphicsGrayscaleEffect(QObject *parent = 0); - ~QGraphicsGrayscaleEffect(); - - qreal strength() const; - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -public Q_SLOTS: - void setStrength(qreal strength); - -Q_SIGNALS: - void strengthChanged(qreal strength); - -private: - Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) - Q_DISABLE_COPY(QGraphicsGrayscaleEffect) -}; - class QGraphicsColorizeEffectPrivate; class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { @@ -195,31 +170,6 @@ private: Q_DISABLE_COPY(QGraphicsColorizeEffect) }; -class QGraphicsPixelizeEffectPrivate; -class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize NOTIFY pixelSizeChanged) -public: - QGraphicsPixelizeEffect(QObject *parent = 0); - ~QGraphicsPixelizeEffect(); - - int pixelSize() const; - -public Q_SLOTS: - void setPixelSize(int pixelSize); - -Q_SIGNALS: - void pixelSizeChanged(int pixelSize); - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect) - Q_DISABLE_COPY(QGraphicsPixelizeEffect) -}; - class QGraphicsBlurEffectPrivate; class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { @@ -335,44 +285,6 @@ private: Q_DISABLE_COPY(QGraphicsOpacityEffect) }; -class QGraphicsBloomEffectPrivate; -class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) - Q_PROPERTY(Qt::RenderHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) - Q_PROPERTY(int brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged) - Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) -public: - QGraphicsBloomEffect(QObject *parent = 0); - ~QGraphicsBloomEffect(); - - QRectF boundingRectFor(const QRectF &rect) const; - int blurRadius() const; - Qt::RenderHint blurHint() const; - int brightness() const; - qreal strength() const; - -public Q_SLOTS: - void setBlurRadius(int blurRadius); - void setBlurHint(Qt::RenderHint hint); - void setBrightness(int brightness); - void setStrength(qreal strength); - -Q_SIGNALS: - void blurRadiusChanged(int blurRadius); - void blurHintChanged(Qt::RenderHint hint); - void brightnessChanged(int brightness); - void strengthChanged(qreal strength); - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsBloomEffect) - Q_DISABLE_COPY(QGraphicsBloomEffect) -}; - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 8fb55d8..87abbbc 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -118,22 +118,6 @@ public: quint32 padding : 31; // feel free to use }; -class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) -public: - QGraphicsGrayscaleEffectPrivate() - : opaque(true) - { - filter = new QPixmapColorizeFilter; - filter->setColor(Qt::black); - } - ~QGraphicsGrayscaleEffectPrivate() { delete filter; } - - QPixmapColorizeFilter *filter; - quint32 opaque : 1; - quint32 padding : 31; -}; class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate { @@ -151,15 +135,6 @@ public: quint32 padding : 31; }; -class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect) -public: - QGraphicsPixelizeEffectPrivate() : pixelSize(3) {} - - int pixelSize; -}; - class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsBlurEffect) @@ -195,18 +170,6 @@ public: uint hasOpacityMask : 1; }; -class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsBlurEffect) -public: - QGraphicsBloomEffectPrivate() : brightness(70), strength(qreal(0.7)) {} - - QPixmapBlurFilter blurFilter; - int colorTable[256]; - int brightness; - qreal strength; -}; - QT_END_NAMESPACE #endif // QGRAPHICSEFFECT_P_H -- cgit v0.12 From 6c83dadea241f2e52d0cbcfa5c81e43c7eaeb90f Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 26 Oct 2009 08:36:38 +0100 Subject: Kill a tiny few sin/cos/sqrt calls in the new stroker Reviewed-by: Eskil --- src/opengl/gl2paintengineex/qtriangulatingstroker.cpp | 4 ++-- src/opengl/gl2paintengineex/qtriangulatingstroker_p.h | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp index a3c8266..a5a743f 100644 --- a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp +++ b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp @@ -130,8 +130,8 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen) if (m_roundness > 24) m_roundness = 24; - m_sin_theta = qSin(Q_PI / m_roundness); // ### Use qFastSin - m_cos_theta = qCos(Q_PI / m_roundness); + m_sin_theta = qFastSin(Q_PI / m_roundness); + m_cos_theta = qFastCos(Q_PI / m_roundness); const qreal *endPts = pts + (count<<1); const qreal *startPts; diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h b/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h index b7354db..ae56e87 100644 --- a/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h +++ b/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h @@ -124,7 +124,16 @@ inline void QTriangulatingStroker::normalVector(float x1, float y1, float x2, fl { float dx = x2 - x1; float dy = y2 - y1; - float pw = m_width / sqrt(dx*dx + dy*dy); + + float pw; + + if (dx == 0) + pw = m_width / dy; + else if (dy == 0) + pw = m_width / dx; + else + pw = m_width / sqrt(dx*dx + dy*dy); + *nx = -dy * pw; *ny = dx * pw; } -- cgit v0.12 From 4e55bb8a761cc3e246c539fc5f7cce103ed4d730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 23 Oct 2009 15:32:21 +0200 Subject: Made sure we invalidate the cache when the effect rect changes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When blurring and the blur radius increases we need a bigger effect rect to do within-pixmap-bounds filtering. Reviewed-by: Bjørn Erik Nilsen --- src/gui/effects/qgraphicseffect.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 96d35b0..383627e 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -353,8 +353,10 @@ void QGraphicsEffect::setEnabled(bool enable) return; d->isEnabled = enable; - if (d->source) + if (d->source) { d->source->d_func()->effectBoundingRectChanged(); + d->source->d_func()->invalidateCache(); + } emit enabledChanged(enable); } @@ -408,8 +410,10 @@ QGraphicsEffectSource *QGraphicsEffect::source() const void QGraphicsEffect::updateBoundingRect() { Q_D(QGraphicsEffect); - if (d->source) + if (d->source) { d->source->d_func()->effectBoundingRectChanged(); + d->source->d_func()->invalidateCache(); + } } /*! -- cgit v0.12 From 085a994122afc05b0e94c1d035cfcd6d82bdf136 Mon Sep 17 00:00:00 2001 From: Trond Kjernaasen Date: Mon, 26 Oct 2009 13:24:13 +0100 Subject: Fixed PDF generation for Windows. Font names were not retrieved correctly after the QT_WA removal patch. The old code always used the GetTextOutlineA() API, except for WinCE, even when a Unicode compatible Windows platform was used. Reviewed-by: Kim --- src/gui/text/qfontengine_win.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index fd34d0f..6c367ab 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -208,7 +208,7 @@ void QFontEngineWin::getCMap() unitsPerEm = otm->otmEMSquare; x_height = (int)otm->otmsXHeight; loadKerningPairs(designToDevice); - _faceId.filename = (char *)otm + (int)otm->otmpFullName; + _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFullName)).toLatin1(); lineWidth = otm->otmsUnderscoreSize; fsType = otm->otmfsType; free(otm); @@ -987,8 +987,8 @@ QFontEngine::Properties QFontEngineWin::properties() const Properties p; p.emSquare = unitsPerEm; p.italicAngle = otm->otmItalicAngle; - p.postscriptName = (char *)otm + (int)otm->otmpFamilyName; - p.postscriptName += (char *)otm + (int)otm->otmpStyleName; + p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFamilyName)).toLatin1(); + p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpStyleName)).toLatin1(); #ifndef QT_NO_PRINTER p.postscriptName = QPdf::stripSpecialCharacters(p.postscriptName); #endif @@ -1110,7 +1110,7 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin ih + 2 * margin + 4, QNativeImage::systemFormat(), !qt_cleartype_enabled); - /*If cleartype is enabled we use the standard system format even on Windows CE + /*If cleartype is enabled we use the standard system format even on Windows CE and not the special textbuffer format we have to use if cleartype is disabled*/ ni->image.fill(0xffffffff); -- cgit v0.12 From f6480ca465af9617956752e60d9be3a19b710e0f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 26 Oct 2009 16:09:30 +0100 Subject: Cocoa: Synthesize italic text correct way when adding glyphs to path On Mac OS X, Cocoa, we would synthesize italics on the text by slanting it in the incorrect direction (so it leaned to the left) when generating a path from the text, e.g. when printing. The patch makes the text slant the correct way, and the logic now becomes identical with the synthesized italics in the draw() function. Task-number: QTBUG-4969 Reviewed-by: Trond --- 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 8ce437d..a4e7c04 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -546,7 +546,7 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); for (int i = 0; i < nGlyphs; ++i) { -- cgit v0.12 From 44e9d5264217782762432bb0f4b7c441b4a545cd Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 27 Oct 2009 08:36:23 +0100 Subject: Fixed crash when QPrintDialog parent is a subwidget Reviewed-by: Trond --- src/gui/dialogs/qprintdialog_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp index 843c4e2..51e83ac 100644 --- a/src/gui/dialogs/qprintdialog_win.cpp +++ b/src/gui/dialogs/qprintdialog_win.cpp @@ -139,7 +139,7 @@ static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWidget *parent, if (d->ep->printToFile) pd->Flags |= PD_PRINTTOFILE; Q_ASSERT(parent != 0 && parent->testAttribute(Qt::WA_WState_Created)); - pd->hwndOwner = parent->winId(); + pd->hwndOwner = parent->window()->winId(); pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage()); pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1; pd->nCopies = d->ep->num_copies; -- cgit v0.12 From c39fac87d62ef15867dc5571d03530d7e7240aa7 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 26 Oct 2009 10:39:38 +0100 Subject: Options on how to get a pixmap from an effect source Usable for future optimizations. Reviewed-by: Samuel --- src/gui/effects/qgraphicseffect.cpp | 22 +++-- src/gui/effects/qgraphicseffect.h | 10 ++- src/gui/effects/qgraphicseffect_p.h | 3 +- src/gui/graphicsview/qgraphicsitem.cpp | 31 +++++-- src/gui/graphicsview/qgraphicsitem_p.h | 9 +- src/gui/kernel/qwidget.cpp | 18 +++- src/gui/kernel/qwidget_p.h | 3 +- .../tst_qgraphicseffectsource.cpp | 99 ++++++++++++++++++++++ 8 files changed, 177 insertions(+), 18 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index f20480b..647fd1b 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -97,6 +97,7 @@ */ #include "qgraphicseffect_p.h" +#include #include #include @@ -248,16 +249,22 @@ bool QGraphicsEffectSource::isPixmap() const \sa QGraphicsEffect::draw(), boundingRect(), deviceRect() */ -QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset, PixmapPadMode mode) const { Q_D(const QGraphicsEffectSource); + // Shortcut, no cache for childless pixmap items... + const QGraphicsItem *item = graphicsItem(); + if (system == Qt::LogicalCoordinates && mode == NoExpandPadMode && item && isPixmap()) { + return ((QGraphicsPixmapItem *) item)->pixmap(); + } + QPixmap pm; if (d->m_cachedSystem == system) QPixmapCache::find(d->m_cacheKey, &pm); if (pm.isNull()) { - pm = d->pixmap(system, &d->m_cachedOffset); + pm = d->pixmap(system, &d->m_cachedOffset, mode); d->m_cachedSystem = system; d->invalidateCache(); @@ -565,7 +572,8 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou QPoint offset; if (source->isPixmap()) { // No point in drawing in device coordinates (pixmap will be scaled anyways). - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset, + QGraphicsEffectSource::NoExpandPadMode); d->filter->draw(painter, offset, pixmap); return; } @@ -776,6 +784,8 @@ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset) By default, the horizontal shadow offset is 8 pixels. + + \sa yOffset(), offset() */ @@ -1029,7 +1039,8 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour if (source->isPixmap()) { // No point in drawing in device coordinates (pixmap will be scaled anyways). if (!d->hasOpacityMask) { - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset, + QGraphicsEffectSource::NoExpandPadMode); painter->drawPixmap(offset, pixmap); } else { QRect srcBrect = source->boundingRect().toAlignedRect(); @@ -1050,7 +1061,8 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour } else { // Draw pixmap in device coordinates to avoid pixmap scaling; if (!d->hasOpacityMask) { - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset, + QGraphicsEffectSource::NoExpandPadMode); painter->setWorldTransform(QTransform()); painter->drawPixmap(offset, pixmap); } else { diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 019e808..abf03b3 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -64,6 +64,12 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject { Q_OBJECT public: + enum PixmapPadMode { + NoExpandPadMode, + ExpandToTransparentBorderPadMode, + ExpandToEffectRectPadMode + }; + ~QGraphicsEffectSource(); const QGraphicsItem *graphicsItem() const; const QWidget *widget() const; @@ -75,7 +81,9 @@ public: QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; QRect deviceRect() const; - QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; + QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, + QPoint *offset = 0, + PixmapPadMode mode = ExpandToEffectRectPadMode) const; protected: QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 24d8696..dff84a1 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -77,7 +77,8 @@ public: virtual void draw(QPainter *p) = 0; virtual void update() = 0; virtual bool isPixmap() const = 0; - virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0; + virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0, + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode) const = 0; virtual void effectBoundingRectChanged() = 0; void invalidateCache() const { QPixmapCache::remove(m_cacheKey); } diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index f892bb4..97357a7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1657,7 +1657,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); // Flags that alter the geometry of the item (or its children). - const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); + const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable); bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask); if (fullUpdate) d_ptr->paintedViewBoundingRectsNeedRepaint = 1; @@ -9138,10 +9138,14 @@ void QGraphicsPixmapItem::setOffset(const QPointF &offset) QRectF QGraphicsPixmapItem::boundingRect() const { Q_D(const QGraphicsPixmapItem); - qreal pw = 1.0; if (d->pixmap.isNull()) return QRectF(); - return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2); + if (d->flags & ItemIsSelectable) { + qreal pw = 1.0; + return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2); + } else { + return QRectF(d->offset, d->pixmap.size()); + } } /*! @@ -10660,7 +10664,8 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) } } -QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, + QGraphicsEffectSource::PixmapPadMode mode) const { const bool deviceCoordinates = (system == Qt::DeviceCoordinates); if (!info && deviceCoordinates) { @@ -10674,7 +10679,16 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); const QRectF sourceRect = boundingRect(system); - QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + QRect effectRect; + + if (mode == QGraphicsEffectSource::ExpandToEffectRectPadMode) { + effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + } else if (mode == QGraphicsEffectSource::ExpandToTransparentBorderPadMode) { + effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect(); + } else { + effectRect = sourceRect.toAlignedRect(); + } + if (offset) *offset = effectRect.topLeft(); @@ -10702,10 +10716,15 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP effectRect.setBottom(deviceHeight -1); } - if (effectRect.isEmpty()) return QPixmap(); + if (system == Qt::LogicalCoordinates + && effectRect.size() == sourceRect.size() + && isPixmap()) { + return static_cast(item)->pixmap(); + } + QPixmap pixmap(effectRect.size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 7c3c4f0..183e95b 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -61,6 +61,7 @@ #include #include +#include #include @@ -603,7 +604,9 @@ public: inline bool isPixmap() const { - return (item->type() == QGraphicsPixmapItem::Type); + return item->type() == QGraphicsPixmapItem::Type + && !(item->flags() & QGraphicsItem::ItemIsSelectable) + && item->d_ptr->children.size() == 0; //|| (item->d_ptr->isObject && qobject_cast(q_func())); } @@ -621,7 +624,9 @@ public: QRectF boundingRect(Qt::CoordinateSystem system) const; void draw(QPainter *); - QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; + QPixmap pixmap(Qt::CoordinateSystem system, + QPoint *offset, + QGraphicsEffectSource::PixmapPadMode mode) const; QGraphicsItem *item; QGraphicsItemPaintInfo *info; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 5fa9a92..27e73e0 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -5437,7 +5437,8 @@ void QWidgetEffectSourcePrivate::draw(QPainter *painter) context->sharedPainter, context->backingStore); } -QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, + QGraphicsEffectSource::PixmapPadMode mode) const { const bool deviceCoordinates = (system == Qt::DeviceCoordinates); if (!context && deviceCoordinates) { @@ -5455,7 +5456,20 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * pixmapOffset = painterTransform.map(pixmapOffset); } - QRect effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + + QRect effectRect; + + if (mode == QGraphicsEffectSource::ExpandToEffectRectPadMode) { + effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + + } else if (mode == QGraphicsEffectSource::ExpandToTransparentBorderPadMode) { + effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect(); + + } else { + effectRect = sourceRect.toAlignedRect(); + + } + if (offset) *offset = effectRect.topLeft(); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 159a3f2..616a972 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -819,7 +819,8 @@ public: QRectF boundingRect(Qt::CoordinateSystem system) const; void draw(QPainter *p); - QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; + QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset, + QGraphicsEffectSource::PixmapPadMode mode) const; QWidget *m_widget; QWidgetPaintContext *context; diff --git a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp index 855950b..0635989 100644 --- a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp +++ b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp @@ -166,6 +166,9 @@ private slots: void deviceRect(); void pixmap(); + void pixmapPadding_data(); + void pixmapPadding(); + private: QGraphicsView *view; QGraphicsScene *scene; @@ -318,6 +321,102 @@ void tst_QGraphicsEffectSource::pixmap() QCOMPARE(pixmap1, pixmap2); } +class PaddingEffect : public QGraphicsEffect +{ +public: + PaddingEffect(QObject *parent) : QGraphicsEffect(parent) + { + } + + QRectF boundingRectFor(const QRectF &src) const { + return src.adjusted(-10, -10, 10, 10); + } + + void draw(QPainter *p, QGraphicsEffectSource *source) { + pix = source->pixmap(coordinateMode, &offset, padMode); + } + + QPixmap pix; + QPoint offset; + QGraphicsEffectSource::PixmapPadMode padMode; + Qt::CoordinateSystem coordinateMode; +}; + +void tst_QGraphicsEffectSource::pixmapPadding_data() +{ + QTest::addColumn("coordinateMode"); + QTest::addColumn("padMode"); + QTest::addColumn("size"); + QTest::addColumn("offset"); + QTest::addColumn("ulPixel"); + + QTest::newRow("log,nopad") << int(Qt::LogicalCoordinates) + << int(QGraphicsEffectSource::NoPadMode) + << QSize(10, 10) << QPoint(0, 0) + << 0xffff0000u; + + QTest::newRow("log,transparent") << int(Qt::LogicalCoordinates) + << int(QGraphicsEffectSource::ExpandToTransparentBorderPadMode) + << QSize(12, 12) << QPoint(-1, -1) + << 0x00000000u; + + QTest::newRow("log,effectrect") << int(Qt::LogicalCoordinates) + << int(QGraphicsEffectSource::ExpandToEffectRectPadMode) + << QSize(30, 30) << QPoint(-10, -10) + << 0x00000000u; + + QTest::newRow("dev,nopad") << int(Qt::DeviceCoordinates) + << int(QGraphicsEffectSource::NoPadMode) + << QSize(20, 20) << QPoint(40, 40) + << 0xffff0000u; + + QTest::newRow("dev,transparent") << int(Qt::DeviceCoordinates) + << int(QGraphicsEffectSource::ExpandToTransparentBorderPadMode) + << QSize(22, 22) << QPoint(39, 39) + << 0x00000000u; + + QTest::newRow("dev,effectrect") << int(Qt::DeviceCoordinates) + << int(QGraphicsEffectSource::ExpandToEffectRectPadMode) + << QSize(40, 40) << QPoint(30, 30) + << 0x00000000u; + +} + +void tst_QGraphicsEffectSource::pixmapPadding() +{ + QPixmap dummyTarget(100, 100); + QPainter dummyPainter(&dummyTarget); + dummyPainter.translate(40, 40); + dummyPainter.scale(2, 2); + + QPixmap pm(10, 10); + pm.fill(Qt::red); + + QGraphicsScene *scene = new QGraphicsScene(); + PaddingEffect *effect = new PaddingEffect(scene); + QGraphicsPixmapItem *pmItem = new QGraphicsPixmapItem(pm); + scene->addItem(pmItem); + pmItem->setGraphicsEffect(effect); + + QFETCH(int, coordinateMode); + QFETCH(int, padMode); + QFETCH(QPoint, offset); + QFETCH(QSize, size); + QFETCH(uint, ulPixel); + + effect->padMode = (QGraphicsEffectSource::PixmapPadMode) padMode; + effect->coordinateMode = (Qt::CoordinateSystem) coordinateMode; + + scene->render(&dummyPainter, scene->itemsBoundingRect(), scene->itemsBoundingRect()); + + QCOMPARE(effect->pix.size(), size); + QCOMPARE(effect->offset, offset); + QCOMPARE(effect->pix.toImage().pixel(0, 0), ulPixel); + + // ### Fix corruption in scene destruction, then enable... + // delete scene; +} + QTEST_MAIN(tst_QGraphicsEffectSource) #include "tst_qgraphicseffectsource.moc" -- cgit v0.12 From cdd341bd8ca9834cd631188c5efc440038ad0b20 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 27 Oct 2009 09:08:12 +0100 Subject: Removed a redundant if() check. Its checked in the containing condition Reviewed-by: Samuel --- src/gui/painting/qpaintengine_raster.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index fd0e810..bf2c574 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1739,8 +1739,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) const QLineF *lines = reinterpret_cast(path.points()); for (int i = 0; i < lineCount; ++i) { - if (path.shape() == QVectorPath::LinesHint) - dashOffset = s->lastPen.dashOffset(); + dashOffset = s->lastPen.dashOffset(); if (lines[i].p1() == lines[i].p2()) { if (s->lastPen.capStyle() != Qt::FlatCap) { QPointF p = lines[i].p1(); -- cgit v0.12 From a46adcd714ec7c71c926511a7c29a8b29dbc1035 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 27 Oct 2009 09:12:09 +0100 Subject: Reworked QVectorPath API to allow for caching and convex curved shapes --- src/gui/painting/qpaintengine_raster.cpp | 2 +- src/gui/painting/qpaintengineex.cpp | 30 ++++++++++--- src/gui/painting/qpaintengineex_p.h | 6 +-- src/gui/painting/qpainterpath_p.h | 2 +- src/gui/painting/qvectorpath_p.h | 72 +++++++++++++++++++------------- 5 files changed, 72 insertions(+), 40 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index bf2c574..1a8dce1 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1686,7 +1686,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) if (!s->penData.blend) return; - if (s->flags.fast_pen && path.shape() <= QVectorPath::NonCurvedShapeHint + if (s->flags.fast_pen && !path.isCurved() && s->lastPen.brush().isOpaque()) { int count = path.elementCount(); QPointF *points = (QPointF *) path.points(); diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 195be0a..9e21182 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -92,6 +92,24 @@ QRectF QVectorPath::controlPointRect() const return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2)); } + +QVectorPath::CacheEntry *QVectorPath::addCacheData(QPaintEngineEx *engine, void *data, + qvectorpath_cache_cleanup cleanup) { + Q_ASSERT(!lookupCacheData(engine)); + if ((m_hints & IsCachedHint) == 0) { + m_cache = 0; + m_hints |= IsCachedHint; + } + CacheEntry *e = new CacheEntry; + e->engine = engine; + e->data = data; + e->cleanup = cleanup; + e->next = m_cache; + m_cache = e; + return m_cache; +} + + const QVectorPath &qtVectorPathForPath(const QPainterPath &path) { Q_ASSERT(path.d_func()); @@ -414,7 +432,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) // Some engines might decide to optimize for the non-shape hint later on... uint flags = QVectorPath::WindingFill; if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin) - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; // ### Perspective Xforms are currently not supported... if (!pen.isCosmetic()) { @@ -442,7 +460,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) points[4], points[5]); points += 6; types += 3; - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; break; default: break; @@ -504,7 +522,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); points += 6; types += 3; - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; break; } default: @@ -736,7 +754,7 @@ void QPaintEngineEx::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yR x1 + xRadius, y1 }; - QVectorPath path(pts, 17, qpaintengineex_roundedrect_types); + QVectorPath path(pts, 17, qpaintengineex_roundedrect_types, QVectorPath::RoundedRectHint); draw(path); } @@ -827,7 +845,7 @@ void QPaintEngineEx::drawPoints(const QPointF *points, int pointCount) pts[++oset] = points[i].x() + 0.001; pts[++oset] = points[i].y(); } - QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::NonCurvedShapeHint); + QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint); stroke(path, pen); pointCount -= 16; points += 16; @@ -858,7 +876,7 @@ void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount) pts[++oset] = points[i].x() + 0.001; pts[++oset] = points[i].y(); } - QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::NonCurvedShapeHint); + QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint); stroke(path, pen); pointCount -= 16; points += 16; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 3ec9bd6..02d77f4 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -250,9 +250,9 @@ public: inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) { switch (mode) { case QPaintEngine::ConvexMode: return ConvexPolygonHint | ImplicitClose; - case QPaintEngine::OddEvenMode: return NonCurvedShapeHint | OddEvenFill | ImplicitClose; - case QPaintEngine::WindingMode: return NonCurvedShapeHint | WindingFill | ImplicitClose; - case QPaintEngine::PolylineMode: return NonCurvedShapeHint; + case QPaintEngine::OddEvenMode: return PolygonHint | OddEvenFill | ImplicitClose; + case QPaintEngine::WindingMode: return PolygonHint | WindingFill | ImplicitClose; + case QPaintEngine::PolylineMode: return PolygonHint; default: return 0; } } diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index 54c182d..fbdb9a6 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -103,7 +103,7 @@ public: points[ptsPos++] = e.x; points[ptsPos++] = e.y; if (e.type == QPainterPath::CurveToElement) - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; } if (fillRule == Qt::WindingFill) diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h index d023131..ec27970 100644 --- a/src/gui/painting/qvectorpath_p.h +++ b/src/gui/painting/qvectorpath_p.h @@ -66,8 +66,9 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) +class QPaintEngineEx; -#define QVECTORPATH_NO_CACHE +typedef void (*qvectorpath_cache_cleanup)(void *data); struct QRealRect { qreal x1, y1, x2, y2; @@ -77,19 +78,27 @@ class Q_GUI_EXPORT QVectorPath { public: enum Hint { - // Basic shapes... - LinesHint = 0x0001, // Just plain lines... - RectangleHint = 0x0002, - ConvexPolygonHint = 0x0003, // Convex polygon... - NonISectPolygonHint = 0x0004, // concave polygon, but not intersecting.. - NonCurvedShapeHint = 0x0005, // Generic polygon, possibly self-intersecting... - CurvedShapeHint = 0x0006, // Generic vector path.. - EllipseHint = 0x0007, - ShapeHintMask = 0x000f, + // Shape hints, in 0x000000ff, access using shape() + AreaShapeMask = 0x0001, // shape covers an area + NonConvexShapeMask = 0x0002, // shape is not convex + CurvedShapeMask = 0x0004, // shape contains curves... + LinesShapeMask = 0x0008, + RectangleShapeMask = 0x0010, + ShapeMask = 0x001f, + + // Shape hints merged into basic shapes.. + LinesHint = LinesShapeMask, + RectangleHint = AreaShapeMask | RectangleShapeMask, + EllipseHint = AreaShapeMask | CurvedShapeMask, + ConvexPolygonHint = AreaShapeMask, + PolygonHint = AreaShapeMask | NonConvexShapeMask, + RoundedRectHint = AreaShapeMask | CurvedShapeMask, + ArbitraryShapeHint = AreaShapeMask | NonConvexShapeMask | CurvedShapeMask, // Other hints - CacheHint = 0x0100, - ControlPointRect = 0x0200, // Set if the control point rect has been calculated... + IsCachedHint = 0x0100, // Set if the cache hint is set + ShouldUseCacheHint = 0x0200, // Set if the path should be cached when possible.. + ControlPointRect = 0x0400, // Set if the control point rect has been calculated... // Shape rendering specifiers... OddEvenFill = 0x1000, @@ -101,22 +110,21 @@ public: QVectorPath(const qreal *points, int count, const QPainterPath::ElementType *elements = 0, - uint hints = CurvedShapeHint) + uint hints = ArbitraryShapeHint) : m_elements(elements), m_points(points), m_count(count), m_hints(hints) -#ifndef QVECTORPATH_NO_CACHE - , m_cache(0) -#endif { } QRectF controlPointRect() const; - inline Hint shape() const { return (Hint) (m_hints & ShapeHintMask); } + inline Hint shape() const { return (Hint) (m_hints & ShapeMask); } + inline bool isConvex() const { return (m_hints & NonConvexShapeMask) == 0; } + inline bool isCurved() const { return m_hints & CurvedShapeMask; } - inline bool hasCacheHint() const { return m_hints & CacheHint; } + inline bool isCacheable() const { return m_hints & ShouldUseCacheHint; } inline bool hasImplicitClose() const { return m_hints & ImplicitClose; } inline bool hasWindingFill() const { return m_hints & WindingFill; } @@ -131,24 +139,30 @@ public: static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode); -private: - Q_DISABLE_COPY(QVectorPath) - -#ifndef QVECTORPATH_NO_CACHE struct CacheEntry { - void *engine; - int id; - void *extra; + QPaintEngineEx *engine; + void *data; + qvectorpath_cache_cleanup cleanup; CacheEntry *next; }; - void addCacheData(CacheEntry *d) { - d->next = m_cache; - m_cache = d; + CacheEntry *addCacheData(QPaintEngineEx *engine, void *data, qvectorpath_cache_cleanup cleanup); + inline CacheEntry *lookupCacheData(QPaintEngineEx *engine) const { + Q_ASSERT(m_hints & IsCachedHint); + CacheEntry *e = m_cache; + while (e) { + if (e->engine == engine) + return e; + e = e->next; + } + return 0; } + +private: + Q_DISABLE_COPY(QVectorPath) + CacheEntry *m_cache; -#endif const QPainterPath::ElementType *m_elements; const qreal *m_points; -- cgit v0.12 From 487ebd770e1a406270e24aec97a90adea2062c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 26 Oct 2009 11:12:07 +0100 Subject: Made graphics effects autotest compile. There's no grayscale effect anymore, use colorize effect. Reviewed-by: Gunnar Sletta --- tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp index 0201bc4..b40cf43 100644 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -379,7 +379,8 @@ void tst_QGraphicsEffect::grayscale() item->setPen(Qt::NoPen); item->setBrush(QColor(122, 193, 66)); // Qt light green - QGraphicsGrayscaleEffect *effect = new QGraphicsGrayscaleEffect; + QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect; + effect->setColor(Qt::black); item->setGraphicsEffect(effect); QPainter painter; -- cgit v0.12 From 0ceeded769563914622d26f35397921001c889c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 26 Oct 2009 11:09:05 +0100 Subject: Made blur and drop shadow APIs use qreal instead of int for blur radius. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no reason to lock ourselves to int in the API when some of the backend could handle floating point blur radii. Reviewed-by: Bjørn Erik Nilsen --- src/gui/effects/qgraphicseffect.cpp | 16 ++++++++-------- src/gui/effects/qgraphicseffect.h | 16 ++++++++-------- src/gui/image/qpixmapfilter.cpp | 20 ++++++++++---------- src/gui/image/qpixmapfilter_p.h | 8 ++++---- src/opengl/qglpixmapfilter.cpp | 4 ++-- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 647fd1b..9ed003c 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -630,16 +630,16 @@ QGraphicsBlurEffect::~QGraphicsBlurEffect() By default, the blur radius is 5 pixels. */ -int QGraphicsBlurEffect::blurRadius() const +qreal QGraphicsBlurEffect::blurRadius() const { Q_D(const QGraphicsBlurEffect); return d->filter->radius(); } -void QGraphicsBlurEffect::setBlurRadius(int radius) +void QGraphicsBlurEffect::setBlurRadius(qreal radius) { Q_D(QGraphicsBlurEffect); - if (d->filter->radius() == radius) + if (qFuzzyCompare(d->filter->radius(), radius)) return; d->filter->setRadius(radius); @@ -648,7 +648,7 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) } /*! - \fn void QGraphicsBlurEffect::blurRadiusChanged(int radius) + \fn void QGraphicsBlurEffect::blurRadiusChanged(qreal radius) This signal is emitted whenever the effect's blur radius changes. The \a radius parameter holds the effect's new blur radius. @@ -816,16 +816,16 @@ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset) \sa color(), offset(). */ -int QGraphicsDropShadowEffect::blurRadius() const +qreal QGraphicsDropShadowEffect::blurRadius() const { Q_D(const QGraphicsDropShadowEffect); return d->filter->blurRadius(); } -void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) +void QGraphicsDropShadowEffect::setBlurRadius(qreal blurRadius) { Q_D(QGraphicsDropShadowEffect); - if (d->filter->blurRadius() == blurRadius) + if (qFuzzyCompare(d->filter->blurRadius(), blurRadius)) return; d->filter->setBlurRadius(blurRadius); @@ -834,7 +834,7 @@ void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) } /*! - \fn void QGraphicsDropShadowEffect::blurRadiusChanged(int blurRadius) + \fn void QGraphicsDropShadowEffect::blurRadiusChanged(qreal blurRadius) This signal is emitted whenever the effect's blur radius changes. The \a blurRadius parameter holds the effect's new blur radius. diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index abf03b3..bf18581 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -182,22 +182,22 @@ class QGraphicsBlurEffectPrivate; class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { Q_OBJECT - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) + Q_PROPERTY(qreal blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) Q_PROPERTY(Qt::RenderHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) public: QGraphicsBlurEffect(QObject *parent = 0); ~QGraphicsBlurEffect(); QRectF boundingRectFor(const QRectF &rect) const; - int blurRadius() const; + qreal blurRadius() const; Qt::RenderHint blurHint() const; public Q_SLOTS: - void setBlurRadius(int blurRadius); + void setBlurRadius(qreal blurRadius); void setBlurHint(Qt::RenderHint hint); Q_SIGNALS: - void blurRadiusChanged(int blurRadius); + void blurRadiusChanged(qreal blurRadius); void blurHintChanged(Qt::RenderHint hint); protected: @@ -215,7 +215,7 @@ class Q_GUI_EXPORT QGraphicsDropShadowEffect: public QGraphicsEffect Q_PROPERTY(QPointF offset READ offset WRITE setOffset NOTIFY offsetChanged) Q_PROPERTY(qreal xOffset READ xOffset WRITE setXOffset NOTIFY offsetChanged) Q_PROPERTY(qreal yOffset READ yOffset WRITE setYOffset NOTIFY offsetChanged) - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) + Q_PROPERTY(qreal blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: QGraphicsDropShadowEffect(QObject *parent = 0); @@ -230,7 +230,7 @@ public: inline qreal yOffset() const { return offset().y(); } - int blurRadius() const; + qreal blurRadius() const; QColor color() const; public Q_SLOTS: @@ -248,12 +248,12 @@ public Q_SLOTS: inline void setYOffset(qreal dy) { setOffset(QPointF(xOffset(), dy)); } - void setBlurRadius(int blurRadius); + void setBlurRadius(qreal blurRadius); void setColor(const QColor &color); Q_SIGNALS: void offsetChanged(const QPointF &offset); - void blurRadiusChanged(int blurRadius); + void blurRadiusChanged(qreal blurRadius); void colorChanged(const QColor &color); protected: diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 9fcf776..f9ac79f 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -506,7 +506,7 @@ class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate public: QPixmapBlurFilterPrivate() : radius(5), hint(Qt::PerformanceHint) {} - int radius; + qreal radius; Qt::RenderHint hint; }; @@ -535,7 +535,7 @@ QPixmapBlurFilter::~QPixmapBlurFilter() \internal */ -void QPixmapBlurFilter::setRadius(int radius) +void QPixmapBlurFilter::setRadius(qreal radius) { Q_D(QPixmapBlurFilter); d->radius = radius; @@ -546,7 +546,7 @@ void QPixmapBlurFilter::setRadius(int radius) \internal */ -int QPixmapBlurFilter::radius() const +qreal QPixmapBlurFilter::radius() const { Q_D(const QPixmapBlurFilter); return d->radius; @@ -668,7 +668,7 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap if (!painter->isActive()) return; - if (d->radius == 0) { + if (d->radius <= 0) { painter->drawPixmap(srcRect.translated(p), src, srcRect); return; } @@ -688,12 +688,12 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap if (srcRect.isNull()) { srcImage = src.toImage(); - destImage = blurred(srcImage, srcImage.rect(), d->radius); + destImage = blurred(srcImage, srcImage.rect(), qRound(d->radius)); } else { QRect rect = srcRect.toAlignedRect().intersected(src.rect()); srcImage = src.copy(rect).toImage(); - destImage = blurred(srcImage, srcImage.rect(), d->radius); + destImage = blurred(srcImage, srcImage.rect(), qRound(d->radius)); } painter->drawImage(p, destImage); @@ -902,7 +902,7 @@ public: QPointF offset; QColor color; - int radius; + qreal radius; }; /*! @@ -966,7 +966,7 @@ QPixmapDropShadowFilter::~QPixmapDropShadowFilter() \internal */ -int QPixmapDropShadowFilter::blurRadius() const +qreal QPixmapDropShadowFilter::blurRadius() const { Q_D(const QPixmapDropShadowFilter); return d->radius; @@ -981,7 +981,7 @@ int QPixmapDropShadowFilter::blurRadius() const \internal */ -void QPixmapDropShadowFilter::setBlurRadius(int radius) +void QPixmapDropShadowFilter::setBlurRadius(qreal radius) { Q_D(QPixmapDropShadowFilter); d->radius = radius; @@ -1090,7 +1090,7 @@ void QPixmapDropShadowFilter::draw(QPainter *p, QImage tmp = src.isNull() ? px.toImage() : px.copy(src.toAlignedRect()).toImage(); // blur the alpha channel - tmp = blurred(tmp, tmp.rect(), d->radius, true); + tmp = blurred(tmp, tmp.rect(), qRound(d->radius), true); // blacken the image... QPainter tmpPainter(&tmp); diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 8a2207a..fc70795 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -129,10 +129,10 @@ public: QPixmapBlurFilter(QObject *parent = 0); ~QPixmapBlurFilter(); - void setRadius(int radius); + void setRadius(qreal radius); void setBlurHint(Qt::RenderHint hint); - int radius() const; + qreal radius() const; Qt::RenderHint blurHint() const; QRectF boundingRectFor(const QRectF &rect) const; @@ -175,8 +175,8 @@ public: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src = QRectF()) const; - int blurRadius() const; - void setBlurRadius(int radius); + qreal blurRadius() const; + void setBlurRadius(qreal radius); QColor color() const; void setColor(const QColor &color); diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 0603369..656957d 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -341,7 +341,7 @@ bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const { QGLPixmapBlurFilter *filter = const_cast(this); - int radius = this->radius(); + int radius = qRound(this->radius()); if (!m_haveCached || (m_hint == Qt::QualityHint && radius != m_cachedRadius)) { // Only regenerate the shader from source if parameters have changed. m_haveCached = true; @@ -530,7 +530,7 @@ bool QGLPixmapDropShadowFilter::processGL(QPainter *painter, const QPointF &pos, { QGLPixmapDropShadowFilter *filter = const_cast(this); - int radius = this->blurRadius(); + int radius = qRound(this->blurRadius()); if (!m_haveCached || (m_hint == Qt::QualityHint && radius != m_cachedRadius)) { // Only regenerate the shader from source if parameters have changed. m_haveCached = true; -- cgit v0.12 From fdd29c588801b0c50a8d85c43c7754bc6e988883 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 27 Oct 2009 11:00:24 +0100 Subject: Make use of QVectorPath::isConvex() to speed up rounded rect filling Reviewed-by: Samuel --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index a0810bc..b70810d 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -858,9 +858,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y()); prepareForDraw(currentBrush->isOpaque()); composite(rect); - } else if (path.shape() == QVectorPath::EllipseHint - || path.shape() == QVectorPath::ConvexPolygonHint) - { + } else if (path.isConvex()) { vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale, false); prepareForDraw(currentBrush->isOpaque()); -- cgit v0.12 From 8b2a5214a46fa15b0394ee3c8147343fc79e44d4 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 27 Oct 2009 11:10:00 +0100 Subject: Reset the GL error stack prior to checking for errors in bindTexture() Reviewed-by: Tom --- src/opengl/qgl.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 6720ae7..e80521b 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2156,6 +2156,11 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G time.start(); #endif +#ifndef QT_NO_DEBUG + // Reset the gl error stack...git + while (glGetError() != GL_NO_ERROR); +#endif + // Scale the pixmap if needed. GL textures needs to have the // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL // 2.0 or use the GL_TEXTURE_RECTANGLE texture target -- cgit v0.12 From 3c6c4c6af0d5651097f7eb7c3b7b87eed5e8cc8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 27 Oct 2009 13:51:07 +0100 Subject: Fixed compilation of QGraphicsEffectSource autotest. --- tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp index 0635989..fbeb425 100644 --- a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp +++ b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp @@ -332,7 +332,7 @@ public: return src.adjusted(-10, -10, 10, 10); } - void draw(QPainter *p, QGraphicsEffectSource *source) { + void draw(QPainter *, QGraphicsEffectSource *source) { pix = source->pixmap(coordinateMode, &offset, padMode); } @@ -351,7 +351,7 @@ void tst_QGraphicsEffectSource::pixmapPadding_data() QTest::addColumn("ulPixel"); QTest::newRow("log,nopad") << int(Qt::LogicalCoordinates) - << int(QGraphicsEffectSource::NoPadMode) + << int(QGraphicsEffectSource::NoExpandPadMode) << QSize(10, 10) << QPoint(0, 0) << 0xffff0000u; @@ -366,7 +366,7 @@ void tst_QGraphicsEffectSource::pixmapPadding_data() << 0x00000000u; QTest::newRow("dev,nopad") << int(Qt::DeviceCoordinates) - << int(QGraphicsEffectSource::NoPadMode) + << int(QGraphicsEffectSource::NoExpandPadMode) << QSize(20, 20) << QPoint(40, 40) << 0xffff0000u; -- cgit v0.12 From a4b77f3887a4eb0f3ce103d2457f57e94938d771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 27 Oct 2009 14:32:05 +0100 Subject: Fix the combobox popup 1-second fadeout regression on Carbon. Regression caused by b946da648af0c5fa1c73fe1e57b0b1e08fb14d13. Prior to that commit, the default duration for macWindowFade was 0, but there was code in the implementation that set it to 0.15 in that case. Set the default duration to 0.15. This matches the old behavior when calling macWindowFade without specifying a duration, and makes it clearer what the default really is. --- src/gui/kernel/qt_cocoa_helpers_mac_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 62db064..5318d31 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -116,7 +116,7 @@ typedef struct CGPoint NSPoint; QT_BEGIN_NAMESPACE Qt::MouseButtons qt_mac_get_buttons(int buttons); Qt::MouseButton qt_mac_get_button(EventMouseButton button); -void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0); +void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0.15); bool macWindowIsTextured(void * /*OSWindowRef*/ window); void macWindowToolbarShow(const QWidget *widget, bool show ); void macWindowToolbarSet( void * /*OSWindowRef*/ window, void* toolbarRef ); -- cgit v0.12 From dbb127c226f131fabe39d9ce89ace5d3e6f7deb9 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 27 Oct 2009 15:04:48 +0100 Subject: Fixed QPainterPath to properly set the convex hint on QVectorPath's Reviewed-by: Samuel --- src/gui/painting/qpainterpath.cpp | 15 +++++++++++++++ src/gui/painting/qpainterpath_p.h | 37 +++++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 69e189c..c40bcee 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -688,6 +688,8 @@ void QPainterPath::lineTo(const QPointF &p) return; Element elm = { p.x(), p.y(), LineToElement }; d->elements.append(elm); + + d->convex = d->elements.size() == 3 || (d->elements.size() == 4 && d->isClosed()); } /*! @@ -960,6 +962,8 @@ void QPainterPath::addRect(const QRectF &r) ensureData(); detach(); + bool first = d_func()->elements.size() < 2; + d_func()->elements.reserve(d_func()->elements.size() + 5); moveTo(r.x(), r.y()); @@ -970,6 +974,7 @@ void QPainterPath::addRect(const QRectF &r) d_func()->elements << l1 << l2 << l3 << l4; d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -1039,6 +1044,7 @@ void QPainterPath::addEllipse(const QRectF &boundingRect) detach(); Q_D(QPainterPath); + bool first = d_func()->elements.size() < 2; d->elements.reserve(d->elements.size() + 13); QPointF pts[12]; @@ -1051,6 +1057,8 @@ void QPainterPath::addEllipse(const QRectF &boundingRect) cubicTo(pts[6], pts[7], pts[8]); // 180 -> 90 cubicTo(pts[9], pts[10], pts[11]); // 90 - >0 d_func()->require_moveTo = true; + + d_func()->convex = first; } /*! @@ -3027,6 +3035,8 @@ void QPainterPath::addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadi ensureData(); detach(); + bool first = d_func()->elements.size() < 2; + arcMoveTo(x, y, rxx2, ryy2, 90); arcTo(x, y, rxx2, ryy2, 90, 90); arcTo(x, y+h-ryy2, rxx2, ryy2, 2*90, 90); @@ -3035,6 +3045,7 @@ void QPainterPath::addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadi closeSubpath(); d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -3081,6 +3092,8 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd) ensureData(); detach(); + bool first = d_func()->elements.size() < 2; + arcMoveTo(x, y, rxx2, ryy2, 90); arcTo(x, y, rxx2, ryy2, 90, 90); arcTo(x, y+h-ryy2, rxx2, ryy2, 2*90, 90); @@ -3089,6 +3102,7 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd) closeSubpath(); d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -3269,6 +3283,7 @@ void QPainterPath::setDirty(bool dirty) d_func()->dirtyControlBounds = dirty; delete d_func()->pathConverter; d_func()->pathConverter = 0; + d_func()->convex = false; } void QPainterPath::computeBoundingRect() const diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index fbdb9a6..112c2bd 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -81,8 +81,8 @@ class QVectorPathConverter; class QVectorPathConverter { public: - QVectorPathConverter(const QVector &path, uint fillRule) - : pathData(path, fillRule), + QVectorPathConverter(const QVector &path, uint fillRule, bool convex) + : pathData(path, fillRule, convex), path(pathData.points.data(), path.size(), pathData.elements.data(), pathData.flags) {} @@ -91,7 +91,7 @@ public: } struct QVectorPathData { - QVectorPathData(const QVector &path, uint fillRule) + QVectorPathData(const QVector &path, uint fillRule, bool convex) : elements(path.size()), points(path.size() * 2), flags(0) @@ -111,6 +111,8 @@ public: else flags |= QVectorPath::OddEvenFill; + if (!convex) + flags |= QVectorPath::NonConvexShapeMask; } QVarLengthArray elements; QVarLengthArray points; @@ -128,20 +130,26 @@ class QPainterPathData : public QPainterPathPrivate { public: QPainterPathData() : - cStart(0), fillRule(Qt::OddEvenFill), - dirtyBounds(false), dirtyControlBounds(false), - pathConverter(0) + cStart(0), + fillRule(Qt::OddEvenFill), + pathConverter(0), + dirtyBounds(false), + dirtyControlBounds(false) + { ref = 1; require_moveTo = false; + convex = false; } QPainterPathData(const QPainterPathData &other) : QPainterPathPrivate(), cStart(other.cStart), fillRule(other.fillRule), - dirtyBounds(other.dirtyBounds), bounds(other.bounds), - dirtyControlBounds(other.dirtyControlBounds), + bounds(other.bounds), controlBounds(other.controlBounds), - pathConverter(0) + pathConverter(0), + dirtyBounds(other.dirtyBounds), + dirtyControlBounds(other.dirtyControlBounds), + convex(other.convex) { ref = 1; require_moveTo = false; @@ -158,20 +166,21 @@ public: const QVectorPath &vectorPath() { if (!pathConverter) - pathConverter = new QVectorPathConverter(elements, fillRule); + pathConverter = new QVectorPathConverter(elements, fillRule, convex); return pathConverter->path; } int cStart; Qt::FillRule fillRule; - bool require_moveTo; - - bool dirtyBounds; QRectF bounds; - bool dirtyControlBounds; QRectF controlBounds; + uint require_moveTo : 1; + uint dirtyBounds : 1; + uint dirtyControlBounds : 1; + uint convex : 1; + QVectorPathConverter *pathConverter; }; -- cgit v0.12 From 689184792390d539b7024ce800c6442c6a3dc213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl?= Date: Fri, 15 May 2009 05:29:29 +0000 Subject: Memory of fixedKernel is never returned, found by cppcheck. Cherry-picked from d8a2e52e Merge-request: 419 Reviewed-by: Olivier --- src/gui/image/qpixmapfilter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 4d143d2..1372189 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -401,6 +401,7 @@ static void convolute( } yk++; } + delete[] fixedKernel; } /*! -- cgit v0.12 From c6218e0e9b64e53391e3e0ddc4988f4f079712eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= Date: Tue, 27 Oct 2009 15:25:46 +0100 Subject: Use shared memory images when shared pixmaps are not available. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modern graphics drivers tend to disable shared memory pixmaps, since rendering operations often can't be accelerated by the GPU when the pixmap data is pinned in system RAM. Use XShmPutImage() to flush the window surface when this is case, instead of falling back to the slower XPutImage() method. Merge-request: 1684 Reviewed-by: Samuel Rødal --- src/gui/image/qnativeimage.cpp | 10 ++++++---- src/gui/kernel/qapplication_x11.cpp | 14 ++++++++------ src/gui/kernel/qt_x11_p.h | 1 + src/gui/painting/qwindowsurface_raster.cpp | 6 ++++++ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp index 88faea8..e4ea2e9 100644 --- a/src/gui/image/qnativeimage.cpp +++ b/src/gui/image/qnativeimage.cpp @@ -199,10 +199,12 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /* shmctl(xshminfo.shmid, IPC_RMID, 0); return; } - xshmpm = XShmCreatePixmap(X11->display, DefaultRootWindow(X11->display), xshmimg->data, - &xshminfo, width, height, dd); - if (!xshmpm) { - qWarning() << "QNativeImage: Unable to create shared Pixmap."; + if (X11->use_mitshm_pixmaps) { + xshmpm = XShmCreatePixmap(X11->display, DefaultRootWindow(X11->display), xshmimg->data, + &xshminfo, width, height, dd); + if (!xshmpm) { + qWarning() << "QNativeImage: Unable to create shared Pixmap."; + } } } diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index bf95684..7f11faa 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -1625,6 +1625,7 @@ void qt_init(QApplicationPrivate *priv, int, // MIT-SHM X11->use_mitshm = false; + X11->use_mitshm_pixmaps = false; X11->mitshm_major = 0; X11->sip_serial = 0; @@ -1918,12 +1919,13 @@ void qt_init(QApplicationPrivate *priv, int, bool local = displayName.isEmpty() || displayName.lastIndexOf(QLatin1Char(':')) == 0; if (local && (qgetenv("QT_X11_NO_MITSHM").toInt() == 0)) { Visual *defaultVisual = DefaultVisual(X11->display, DefaultScreen(X11->display)); - X11->use_mitshm = mitshm_pixmaps && ((defaultVisual->red_mask == 0xff0000 - || defaultVisual->red_mask == 0xf800) - && (defaultVisual->green_mask == 0xff00 - || defaultVisual->green_mask == 0x7e0) - && (defaultVisual->blue_mask == 0xff - || defaultVisual->blue_mask == 0x1f)); + X11->use_mitshm = ((defaultVisual->red_mask == 0xff0000 + || defaultVisual->red_mask == 0xf800) + && (defaultVisual->green_mask == 0xff00 + || defaultVisual->green_mask == 0x7e0) + && (defaultVisual->blue_mask == 0xff + || defaultVisual->blue_mask == 0x1f)); + X11->use_mitshm_pixmaps = X11->use_mitshm && mitshm_pixmaps; } } #endif // QT_NO_MITSHM diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index 61acbac..9f08dc6 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -428,6 +428,7 @@ struct QX11Data // true if Qt is compiled w/ MIT-SHM support and MIT-SHM is supported on the connected Display bool use_mitshm; + bool use_mitshm_pixmaps; int mitshm_major; // true if Qt is compiled w/ Tablet support and we have a tablet. diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 3a118bd..d412040 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -215,6 +215,12 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi XCopyArea(X11->display, d_ptr->image->xshmpm, widget->handle(), d_ptr->gc, br.x(), br.y(), br.width(), br.height(), wbr.x(), wbr.y()); XSync(X11->display, False); + } else if (d_ptr->image->xshmimg) { + const QImage &src = d->image->image; + br = br.intersected(src.rect()); + XShmPutImage(X11->display, widget->handle(), d_ptr->gc, d_ptr->image->xshmimg, + br.x(), br.y(), wbr.x(), wbr.y(), br.width(), br.height(), False); + XSync(X11->display, False); } else #endif { -- cgit v0.12 From 8caee839df56c005f5e7a289b2cd8b0544210a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Tue, 27 Oct 2009 15:34:29 +0100 Subject: Fix QtOpenGL linker issue by exporting qt_getClipRects It is used in qwindowsurface_x11gl.cpp. The problem only showed when building in release mode due to previous use of Q_AUTOTEST_EXPORT. Reviewed-by: Tom Cooksey --- src/gui/painting/qpaintengine_x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index 59482c6..35b77f7 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -146,7 +146,7 @@ static inline int qpainterOpToXrender(QPainter::CompositionMode mode) // hack, so we don't have to make QRegion::clipRectangles() public or include // X11 headers in qregion.h -Q_AUTOTEST_EXPORT void *qt_getClipRects(const QRegion &r, int &num) +Q_GUI_EXPORT void *qt_getClipRects(const QRegion &r, int &num) { return r.clipRectangles(num); } -- cgit v0.12 From 75d847ef4f23e16f69ffecff24f44584755f80f5 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 28 Oct 2009 07:58:23 +0100 Subject: Got tst_qpixmapfilter.cpp compiling again Reviewed-by: Trustme --- tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp index 5a9bad7..a80c787 100644 --- a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp +++ b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp @@ -383,7 +383,7 @@ void tst_QPixmapFilter::dropShadowBoundingRectFor() QPixmapDropShadowFilter filter; filter.setBlurRadius(0); - QCOMPARE(filter.blurRadius(), 0); + QCOMPARE(filter.blurRadius(), 0.); const QRectF rect1(0, 0, 50, 50); const QRectF rect2(30, 20, 10, 40); -- cgit v0.12 From 539294ab33467ceedbcd6054137b602865956915 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 28 Oct 2009 07:59:02 +0100 Subject: Adapt testcase to updates in QGraphicsPixmapItem Reviewed-by: TrustMe --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index dcad8e1..d8cd375 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -3109,7 +3109,7 @@ void tst_QGraphicsItem::boundingRects() void tst_QGraphicsItem::boundingRects2() { QGraphicsPixmapItem pixmap(QPixmap::fromImage(QImage(100, 100, QImage::Format_ARGB32_Premultiplied))); - QCOMPARE(pixmap.boundingRect(), QRectF(-0.5, -0.5, 101, 101)); + QCOMPARE(pixmap.boundingRect(), QRectF(0, 0, 100, 100)); QGraphicsLineItem line(0, 0, 100, 0); line.setPen(QPen(Qt::black, 1)); @@ -4039,7 +4039,7 @@ void tst_QGraphicsItem::defaultItemTest_QGraphicsPixmapItem() item.setOffset(QPointF(-10, -10)); QCOMPARE(item.offset(), QPointF(-10, -10)); - QCOMPARE(item.boundingRect(), QRectF(-10.5, -10.5, 301, 201)); + QCOMPARE(item.boundingRect(), QRectF(-10, -10, 300, 200)); } void tst_QGraphicsItem::defaultItemTest_QGraphicsTextItem() -- cgit v0.12 From e6767a4bd15f001df6927d7232598662977bea13 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 28 Oct 2009 09:40:21 +0100 Subject: Updated testcase to match new boundingRect logic --- tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp b/tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp index e25aef0..5a62dc0 100644 --- a/tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp +++ b/tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp @@ -165,7 +165,7 @@ void tst_QGraphicsPixmapItem::boundingRect_data() QTest::addColumn("pixmap"); QTest::addColumn("boundingRect"); QTest::newRow("null") << QPixmap() << QRectF(); - QTest::newRow("10x10") << QPixmap(10, 10) << QRectF(-0.5, -0.5, 11, 11); + QTest::newRow("10x10") << QPixmap(10, 10) << QRectF(0, 0, 10, 10); } // public QRectF boundingRect() const -- cgit v0.12 From 5a5990b8cd3c580e3325a7c3878275196ceb86dd Mon Sep 17 00:00:00 2001 From: Christoph Feck Date: Wed, 28 Oct 2009 09:57:53 +0100 Subject: Fix raster paintengine handling with invalid images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit initTexture() has explicit handling of invalid images, but when calling adjustSpanMethods() the invalid case is not handled for Type == Texture. This caused two types of crashes: * call to 0 address, because sourceFetch[] has 0 pointer for QImage::Format_Invalid (see https://bugs.kde.org/show_bug.cgi?id=176014) * division by zero in tiled blend functions, because of the " % image_size" modulo arithmetic. (see https://bugs.kde.org/show_bug.cgi?id=203231) Merge-request: 1213 Reviewed-by: Samuel Rødal --- src/gui/painting/qpaintengine_raster.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 1a8dce1..8d0b961 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -5119,6 +5119,9 @@ void QSpanData::adjustSpanMethods() #else unclipped_blend = qBlendTexture; #endif + if (!texture.imageData) + unclipped_blend = 0; + break; } // setup clipping -- cgit v0.12 From 69216ca888373e8ca82dfe75fd940fc2ab824c2c Mon Sep 17 00:00:00 2001 From: Stefano Pironato Date: Wed, 28 Oct 2009 14:48:44 +0200 Subject: Fix bug for message error "Texture updload failed, error code 0x500" The error message come from the QGLContextPrivate::bindTexture. But since OpenGl errors are retains until glGetError is called the actual error was happening somewhere else. After adding in all the gl* call a check for a gl error, I was able to get the place where opengl fail with a GL_INVALID_ENUM. This happen in the call of glEnable(GL_TEXTURE_2D) in the file qgl_x11egl.cpp. This glEnable call does not need: removed. Reviewed-by: Tom Cooksey --- src/opengl/qgl_x11egl.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 3894ed1..7180682 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -589,7 +589,6 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons GLuint textureId; glGenTextures(1, &textureId); - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, textureId); // bind the egl pixmap surface to a texture -- cgit v0.12 From f5c553078b7381c3dff7d0bd6b9990a7acf86abb Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Thu, 29 Oct 2009 10:13:18 +0100 Subject: Fixed highlighting of string components when inputting Japanese text. After typing a sentence in Japanese, and before committing the sentence, you can select each component and choose a different character representation for it. This commit fixes highlighting of the currently selected sentence component which was broken by commit 55137901. Reviewed-by: Marius Storm-Olsen --- src/gui/inputmethod/qwininputcontext_win.cpp | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp index e9ab870..ef2f5c0 100644 --- a/src/gui/inputmethod/qwininputcontext_win.cpp +++ b/src/gui/inputmethod/qwininputcontext_win.cpp @@ -327,28 +327,13 @@ static int getCursorPosition(HIMC himc) static QString getString(HIMC himc, DWORD dwindex, int *selStart = 0, int *selLength = 0) { - static wchar_t *buffer = 0; - static int buflen = 0; - - int len = getCompositionString(himc, dwindex, 0, 0) + 1; - if (!buffer || len > buflen) { - delete [] buffer; - buflen = qMin(len, 256); - buffer = new wchar_t[buflen]; - } - - len = getCompositionString(himc, dwindex, buffer, buflen * sizeof(wchar_t)); + const int bufferSize = 256; + wchar_t buffer[bufferSize]; + int len = getCompositionString(himc, dwindex, buffer, bufferSize * sizeof(wchar_t)); if (selStart) { - static wchar_t *attrbuffer = 0; - static int attrbuflen = 0; - int attrlen = getCompositionString(himc, dwindex, 0, 0) + 1; - if (!attrbuffer || attrlen> attrbuflen) { - delete [] attrbuffer; - attrbuflen = qMin(attrlen, 256); - attrbuffer = new wchar_t[attrbuflen]; - } - attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, attrbuflen * sizeof(wchar_t)); + char attrbuffer[bufferSize]; + int attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, bufferSize); *selStart = attrlen+1; *selLength = -1; for (int i = 0; i < attrlen; i++) { -- cgit v0.12 From 7d5b560f71e0f11c20b7ebef11f3095e760ca32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 28 Oct 2009 14:44:10 +0100 Subject: Added some optimizations to the blur and drop shadow GL filters. * Use ExpandToTransparentBorderPadMode since we can use GL_CLAMP_TO_EDGE to clamp to the texture. * Shrink the bounding rects reported by the blur and drop shadow filters (expanding by 2 * radius isn't needed). * Use a single-pass blur for radii <= 3 to avoid the overhead of rendering to an FBO. * Made the fast blur setting generate filters for only a predefined set of radii, and then use the actual blur radius to spread the sample points outwards. * Optimized the generated program to rely less on temporary variables, as those seemed to not be handled very well by certain GLSL compilers. Reviewed-by: Gunnar Sletta --- src/gui/effects/qgraphicseffect.cpp | 16 +- src/gui/effects/qgraphicseffect_p.h | 8 +- src/gui/graphicsview/qgraphicsitem.cpp | 3 +- src/gui/image/qpixmapfilter.cpp | 13 +- .../gl2paintengineex/qglengineshadermanager.cpp | 2 +- .../gl2paintengineex/qglengineshadersource_p.h | 16 +- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 8 +- src/opengl/qglpixmapfilter.cpp | 436 +++++++++++++-------- 8 files changed, 307 insertions(+), 195 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 9ed003c..3a6bab5 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -101,6 +101,7 @@ #include #include +#include #include #include #include @@ -260,12 +261,13 @@ QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offse } QPixmap pm; - if (d->m_cachedSystem == system) + if (d->m_cachedSystem == system && d->m_cachedMode == mode) QPixmapCache::find(d->m_cacheKey, &pm); if (pm.isNull()) { pm = d->pixmap(system, &d->m_cachedOffset, mode); d->m_cachedSystem = system; + d->m_cachedMode = mode; d->invalidateCache(); d->m_cacheKey = QPixmapCache::insert(pm); @@ -708,9 +710,13 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) return; } + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToEffectRectPadMode; + if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) + mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode; + // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset, mode); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap); @@ -893,9 +899,13 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s return; } + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToEffectRectPadMode; + if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) + mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode; + // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset, mode); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap); diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index dff84a1..1ed7103 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -66,7 +66,12 @@ class QGraphicsEffectSourcePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffectSource) public: - QGraphicsEffectSourcePrivate() : QObjectPrivate() {} + QGraphicsEffectSourcePrivate() + : QObjectPrivate() + , m_cachedSystem(Qt::DeviceCoordinates) + , m_cachedMode(QGraphicsEffectSource::ExpandToTransparentBorderPadMode) + {} + virtual ~QGraphicsEffectSourcePrivate() { invalidateCache(); } virtual void detach() = 0; virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; @@ -88,6 +93,7 @@ public: private: mutable Qt::CoordinateSystem m_cachedSystem; + mutable QGraphicsEffectSource::PixmapPadMode m_cachedMode; mutable QPoint m_cachedOffset; mutable QPixmapCache::Key m_cacheKey; }; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 7d9390c..738c6e3 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -10703,7 +10703,8 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP if (mode == QGraphicsEffectSource::ExpandToEffectRectPadMode) { effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); } else if (mode == QGraphicsEffectSource::ExpandToTransparentBorderPadMode) { - effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect(); + // adjust by 1.5 to account for cosmetic pens + effectRect = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5).toAlignedRect(); } else { effectRect = sourceRect.toAlignedRect(); } diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index f9ac79f..d0de03e 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -584,7 +584,7 @@ Qt::RenderHint QPixmapBlurFilter::blurHint() const QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const { Q_D(const QPixmapBlurFilter); - const qreal delta = d->radius * 2; + const qreal delta = d->radius + 1; return rect.adjusted(-delta, -delta, delta, delta); } @@ -1057,14 +1057,9 @@ void QPixmapDropShadowFilter::setOffset(const QPointF &offset) QRectF QPixmapDropShadowFilter::boundingRectFor(const QRectF &rect) const { Q_D(const QPixmapDropShadowFilter); - - const qreal delta = qreal(d->radius * 2); - qreal x1 = qMin(rect.left(), rect.left() + d->offset.x() - delta); - qreal y1 = qMin(rect.top(), rect.top() + d->offset.y() - delta); - qreal x2 = qMax(rect.right(), rect.right() + d->offset.x() + delta); - qreal y2 = qMax(rect.bottom(), rect.bottom() + d->offset.y() + delta); - - return QRectF(x1, y1, x2 - x1, y2 - y1); + qreal delta = d->radius + 1; + return rect.adjusted(-2, -2, 2, 2).united( + rect.translated(d->offset).adjusted(-delta, -delta, delta, delta)); } /*! diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index e22303d..af9306f 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -476,7 +476,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() return false; bool useCustomSrc = customSrcStage != 0; - if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc) { + if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) { useCustomSrc = false; qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src"); } diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 3eef808..2407979 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -258,7 +258,7 @@ static const char* const qglslPositionWithTextureBrushVertexShader = "\ uniform mediump vec2 halfViewportSize; \ uniform highp vec2 invertedTextureSize; \ uniform highp mat3 brushTransform; \ - varying highp vec2 brushTextureCoords; \ + varying highp vec2 textureCoords; \ void setPosition(void) { \ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ @@ -267,7 +267,7 @@ static const char* const qglslPositionWithTextureBrushVertexShader = "\ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ gl_Position.w = invertedHTexCoordsZ; \ - brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \ + textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \ }"; static const char* const qglslAffinePositionWithTextureBrushVertexShader @@ -278,26 +278,26 @@ static const char* const qglslAffinePositionWithTextureBrushVertexShader // we emulate GL_REPEAT by only taking the fractional part of the texture coords. // TODO: Special case POT textures which don't need this emulation static const char* const qglslTextureBrushSrcFragmentShader = "\ - varying highp vec2 brushTextureCoords; \ + varying highp vec2 textureCoords; \ uniform lowp sampler2D brushTexture; \ lowp vec4 srcPixel() { \ - return texture2D(brushTexture, fract(brushTextureCoords)); \ + return texture2D(brushTexture, fract(textureCoords)); \ }"; #else static const char* const qglslTextureBrushSrcFragmentShader = "\ - varying highp vec2 brushTextureCoords; \ + varying highp vec2 textureCoords; \ uniform lowp sampler2D brushTexture; \ lowp vec4 srcPixel() { \ - return texture2D(brushTexture, brushTextureCoords); \ + return texture2D(brushTexture, textureCoords); \ }"; #endif static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\ - varying highp vec2 brushTextureCoords; \ + varying highp vec2 textureCoords; \ uniform lowp vec4 patternColor; \ uniform lowp sampler2D brushTexture; \ lowp vec4 srcPixel() { \ - return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \ + return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \ }"; // Solid Fill Brush diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index b70810d..a9744b3 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -535,7 +535,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); } - QSizeF invertedTextureSize(1.0 / texPixmap.width(), 1.0 * textureInvertedY / texPixmap.height()); + QSizeF invertedTextureSize(1.0 / texPixmap.width(), 1.0 / texPixmap.height()); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::InvertedTextureSize), invertedTextureSize); QVector2D halfViewportSize(width*0.5, height*0.5); @@ -550,7 +550,11 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() QTransform translate(1, 0, 0, 1, -translationPoint.x(), -translationPoint.y()); QTransform gl_to_qt(1, 0, 0, -1, 0, height); - QTransform inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate; + QTransform inv_matrix; + if (style == Qt::TexturePattern && textureInvertedY == -1) + inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush->texture().height()) * brushQTransform * matrix).inverted() * translate; + else + inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate; shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BrushTransform), inv_matrix); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BrushTexture), QT_BRUSH_TEXTURE_UNIT); diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 656957d..e381a5d 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -104,7 +104,7 @@ public: void setUniforms(QGLShaderProgram *program); - static QByteArray generateGaussianShader(int radius, bool dropShadow = false); + static QByteArray generateGaussianShader(int radius, bool singlePass = false, bool dropShadow = false); protected: bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const; @@ -113,6 +113,7 @@ private: mutable QSize m_textureSize; mutable bool m_horizontalBlur; + mutable bool m_singlePass; mutable bool m_haveCached; mutable int m_cachedRadius; @@ -132,6 +133,7 @@ protected: private: mutable QSize m_textureSize; mutable bool m_horizontalBlur; + mutable bool m_singlePass; mutable bool m_haveCached; mutable int m_cachedRadius; @@ -298,123 +300,155 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *painter, const QPointF &pos return true; } -static const char *qt_gl_blur_filter_fast = - "const int samples = 9;" - "uniform mediump vec2 delta;" - "lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords) {" - " mediump vec4 color = vec4(0.0, 0.0, 0.0, 0.0);" - " mediump float offset = (float(samples) - 1.0) / 2.0;" - " for (int i = 0; i < samples; i++) {" - " mediump vec2 coord = srcCoords + delta * (offset - float(i)) / offset;" - " color += texture2D(src, coord);" - " }" - " return color * (1.0 / float(samples));" - "}"; - -static const char *qt_gl_drop_shadow_filter_fast = - "const int samples = 9;" - "uniform mediump vec2 delta;" - "uniform mediump vec4 shadowColor;" - "lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords) {" - " mediump vec4 color = vec4(0.0, 0.0, 0.0, 0.0);" - " mediump float offset = (float(samples) - 1.0) / 2.0;" - " for (int i = 0; i < samples; i++) {" - " mediump vec2 coord = srcCoords + delta * (offset - float(i)) / offset;" - " color += texture2D(src, coord).a * shadowColor;" - " }" - " return color * (1.0 / float(samples));" - "}"; +static const char *qt_gl_texture_sampling_helper = + "lowp float texture2DAlpha(lowp sampler2D src, highp vec2 srcCoords) {\n" + " return texture2D(src, srcCoords).a;\n" + "}\n"; + +static const char *qt_gl_clamped_texture_sampling_helper = + "highp vec4 texture_dimensions;\n" // x = width, y = height, z = 0.5/width, w = 0.5/height + "lowp float clampedTexture2DAlpha(lowp sampler2D src, highp vec2 srcCoords) {\n" + " highp vec2 clampedCoords = clamp(srcCoords, texture_dimensions.zw, vec2(1.0) - texture_dimensions.zw);\n" + " highp vec2 t = clamp(min(srcCoords, vec2(1.0) - srcCoords) * srcDim + 0.5, 0.0, 1.0);\n" + " return texture2D(src, clampedCoords).a * t.x * t.y;\n" + "}\n" + "lowp vec4 clampedTexture2D(lowp sampler2D src, highp vec2 srcCoords) {\n" + " highp vec2 clampedCoords = clamp(srcCoords, texture_dimensions.zw, vec2(1.0) - texture_dimensions.zw);\n" + " highp vec2 t = clamp(min(srcCoords, vec2(1.0) - srcCoords) * srcDim + 0.5, 0.0, 1.0);\n" + " return texture2D(src, clampedCoords) * t.x * t.y;\n" + "}\n"; + +static QByteArray qt_gl_convertToClamped(const QByteArray &source) +{ + QByteArray result; + result.append(qt_gl_clamped_texture_sampling_helper); + result.append(QByteArray(source).replace("texture2DAlpha", "clampedTexture2DAlpha") + .replace("texture2D", "clampedTexture2D")); + return result; +} QGLPixmapBlurFilter::QGLPixmapBlurFilter(Qt::RenderHint hint) : m_haveCached(false) - , m_cachedRadius(5) + , m_cachedRadius(0) , m_hint(hint) { - if (hint == Qt::PerformanceHint) { - QGLPixmapBlurFilter *filter = const_cast(this); - filter->setSource(qt_gl_blur_filter_fast); - m_haveCached = true; - } } bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const { QGLPixmapBlurFilter *filter = const_cast(this); - int radius = qRound(this->radius()); - if (!m_haveCached || (m_hint == Qt::QualityHint && radius != m_cachedRadius)) { - // Only regenerate the shader from source if parameters have changed. - m_haveCached = true; - m_cachedRadius = radius; - filter->setSource(generateGaussianShader(radius)); + int actualRadius = qRound(radius()); + int filterRadius = actualRadius; + int fastRadii[] = { 1, 2, 3, 5, 8, 15, 25 }; + if (m_hint == Qt::PerformanceHint) { + uint i = 0; + for (; i < (sizeof(fastRadii)/sizeof(*fastRadii))-1; ++i) { + if (fastRadii[i+1] > filterRadius) + break; + } + filterRadius = fastRadii[i]; } - QGLFramebufferObjectFormat format; - format.setInternalTextureFormat(GLenum(src.hasAlphaChannel() ? GL_RGBA : GL_RGB)); - QGLFramebufferObject *fbo = qgl_fbo_pool()->acquire(src.size(), format); + m_singlePass = filterRadius <= 3; - if (!fbo) - return false; + if (!m_haveCached || filterRadius != m_cachedRadius) { + // Only regenerate the shader from source if parameters have changed. + m_haveCached = true; + m_cachedRadius = filterRadius; + QByteArray source = generateGaussianShader(filterRadius, m_singlePass); + filter->setSource(source); + } - glBindTexture(GL_TEXTURE_2D, fbo->texture()); + QRect targetRect = QRectF(src.rect()).translated(pos).adjusted(-actualRadius, -actualRadius, actualRadius, actualRadius).toAlignedRect(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_2D, 0); + if (m_singlePass) { + // prepare for updateUniforms + m_textureSize = src.size(); - // prepare for updateUniforms - m_textureSize = src.size(); + // ensure GL_LINEAR filtering is used + painter->setRenderHint(QPainter::SmoothPixmapTransform); + filter->setOnPainter(painter); + QBrush pixmapBrush = src; + pixmapBrush.setTransform(QTransform::fromTranslate(pos.x(), pos.y())); + painter->fillRect(targetRect, pixmapBrush); + filter->removeFromPainter(painter); + } else { + QGLFramebufferObjectFormat format; + format.setInternalTextureFormat(GLenum(src.hasAlphaChannel() ? GL_RGBA : GL_RGB)); + QGLFramebufferObject *fbo = qgl_fbo_pool()->acquire(targetRect.size(), format); - // horizontal pass, to pixmap - m_horizontalBlur = true; + if (!fbo) + return false; - QPainter fboPainter(fbo); + glBindTexture(GL_TEXTURE_2D, fbo->texture()); - if (src.hasAlphaChannel()) { - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); - } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, 0); - // ensure GL_LINEAR filtering is used - fboPainter.setRenderHint(QPainter::SmoothPixmapTransform); - filter->setOnPainter(&fboPainter); - fboPainter.drawPixmap(0, 0, src); - filter->removeFromPainter(&fboPainter); - fboPainter.end(); + // prepare for updateUniforms + m_textureSize = src.size(); - QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); + // horizontal pass, to pixmap + m_horizontalBlur = true; - // vertical pass, to painter - m_horizontalBlur = false; + QPainter fboPainter(fbo); - painter->save(); - // ensure GL_LINEAR filtering is used - painter->setRenderHint(QPainter::SmoothPixmapTransform); - filter->setOnPainter(painter); - engine->drawTexture(src.rect().translated(pos.x(), pos.y()), fbo->texture(), fbo->size(), src.rect().translated(0, fbo->height() - src.height())); - filter->removeFromPainter(painter); - painter->restore(); + if (src.hasAlphaChannel()) { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + } - qgl_fbo_pool()->release(fbo); + // ensure GL_LINEAR filtering is used + fboPainter.setRenderHint(QPainter::SmoothPixmapTransform); + filter->setOnPainter(&fboPainter); + QBrush pixmapBrush = src; + pixmapBrush.setTransform(QTransform::fromTranslate(actualRadius, actualRadius)); + fboPainter.fillRect(QRect(0, 0, targetRect.width(), targetRect.height()), pixmapBrush); + filter->removeFromPainter(&fboPainter); + fboPainter.end(); + + QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); + + // vertical pass, to painter + m_horizontalBlur = false; + m_textureSize = fbo->size(); + + painter->save(); + // ensure GL_LINEAR filtering is used + painter->setRenderHint(QPainter::SmoothPixmapTransform); + filter->setOnPainter(painter); + engine->drawTexture(targetRect, fbo->texture(), fbo->size(), QRect(QPoint(), targetRect.size()).translated(0, fbo->height() - targetRect.height())); + filter->removeFromPainter(painter); + painter->restore(); + + qgl_fbo_pool()->release(fbo); + } return true; } void QGLPixmapBlurFilter::setUniforms(QGLShaderProgram *program) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (m_hint == Qt::QualityHint) { - if (m_horizontalBlur) + if (m_singlePass) + program->setUniformValue("delta", 1.0 / m_textureSize.width(), 1.0 / m_textureSize.height()); + else if (m_horizontalBlur) program->setUniformValue("delta", 1.0 / m_textureSize.width(), 0.0); else program->setUniformValue("delta", 0.0, 1.0 / m_textureSize.height()); } else { - // 1.4 is chosen to most closely match the blurriness of the gaussian blur - // at low radii - qreal blur = radius() / 1.4f; + qreal blur = radius() / qreal(m_cachedRadius); - if (m_horizontalBlur) + if (m_singlePass) + program->setUniformValue("delta", blur / m_textureSize.width(), blur / m_textureSize.height()); + else if (m_horizontalBlur) program->setUniformValue("delta", blur / m_textureSize.width(), 0.0); else program->setUniformValue("delta", 0.0, blur / m_textureSize.height()); @@ -426,12 +460,21 @@ static inline qreal gaussian(qreal dx, qreal sigma) return exp(-dx * dx / (2 * sigma * sigma)) / (Q_2PI * sigma * sigma); } -QByteArray QGLPixmapBlurFilter::generateGaussianShader(int radius, bool dropShadow) +QByteArray QGLPixmapBlurFilter::generateGaussianShader(int radius, bool singlePass, bool dropShadow) { Q_ASSERT(radius >= 1); + radius = qMin(127, radius); + + static QCache shaderSourceCache; + uint key = radius | (int(singlePass) << 7) | (int(dropShadow) << 8); + QByteArray *cached = shaderSourceCache.object(key); + if (cached) + return *cached; + QByteArray source; source.reserve(1000); + source.append(qt_gl_texture_sampling_helper); source.append("uniform highp vec2 delta;\n"); if (dropShadow) @@ -446,7 +489,7 @@ QByteArray QGLPixmapBlurFilter::generateGaussianShader(int radius, bool dropShad qreal sigma = radius / 1.65; qreal sum = 0; - for (int i = -radius; i <= radius; ++i) { + for (int i = -radius; i < radius; ++i) { float value = gaussian(i, sigma); gaussianComponents << value; sum += value; @@ -464,43 +507,67 @@ QByteArray QGLPixmapBlurFilter::generateGaussianShader(int radius, bool dropShad weights << weight; } - // odd size ? - if (gaussianComponents.size() & 1) { - sampleOffsets << radius; - weights << gaussianComponents.last(); - } - - int currentVariable = 1; - source.append(" mediump vec4 sample = vec4(0.0);\n"); - source.append(" mediump vec2 coord;\n"); - - qreal weightSum = 0; - source.append(" mediump float c;\n"); - for (int i = 0; i < sampleOffsets.size(); ++i) { - qreal delta = sampleOffsets.at(i); - - ++currentVariable; + int limit = sampleOffsets.size(); + if (singlePass) + limit *= limit; + + QByteArray baseCoordinate = "srcCoords"; + + for (int i = 0; i < limit; ++i) { + QByteArray coordinate = baseCoordinate; + + qreal weight; + if (singlePass) { + const int xIndex = i % sampleOffsets.size(); + const int yIndex = i / sampleOffsets.size(); + + const qreal deltaX = sampleOffsets.at(xIndex); + const qreal deltaY = sampleOffsets.at(yIndex); + weight = weights.at(xIndex) * weights.at(yIndex); + + if (!qFuzzyCompare(deltaX, deltaY)) { + coordinate.append(" + vec2(delta.x * float("); + coordinate.append(QByteArray::number(deltaX)); + coordinate.append("), delta.y * float("); + coordinate.append(QByteArray::number(deltaY)); + coordinate.append("))"); + } else if (!qFuzzyIsNull(deltaX)) { + coordinate.append(" + delta * float("); + coordinate.append(QByteArray::number(deltaX)); + coordinate.append(")"); + } + } else { + const qreal delta = sampleOffsets.at(i); + weight = weights.at(i); + if (!qFuzzyIsNull(delta)) { + coordinate.append(" + delta * float("); + coordinate.append(QByteArray::number(delta)); + coordinate.append(")"); + } + } - QByteArray coordinate = "srcCoords"; - if (delta != qreal(0)) { - coordinate.append(" + delta * float("); - coordinate.append(QByteArray::number(delta)); - coordinate.append(")"); + if (i == 0) { + if (dropShadow) + source.append(" mediump float sample = "); + else + source.append(" mediump vec4 sample = "); + } else { + if (dropShadow) + source.append(" sample += "); + else + source.append(" sample += "); } - source.append(" coord = "); + source.append("texture2D(src, "); source.append(coordinate); - source.append(";\n"); + source.append(")"); if (dropShadow) - source.append(" sample += texture2D(src, coord).a * shadowColor"); - else - source.append(" sample += texture2D(src, coord)"); + source.append(".a"); - weightSum += weights.at(i); - if (weights.at(i) != qreal(1)) { + if (!qFuzzyCompare(weight, qreal(1))) { source.append(" * float("); - source.append(QByteArray::number(weights.at(i))); + source.append(QByteArray::number(weight)); source.append(");\n"); } else { source.append(";\n"); @@ -508,86 +575,109 @@ QByteArray QGLPixmapBlurFilter::generateGaussianShader(int radius, bool dropShad } source.append(" return "); + if (dropShadow) + source.append("shadowColor * "); source.append("sample;\n"); source.append("}\n"); + cached = new QByteArray(source); + shaderSourceCache.insert(key, cached); + return source; } QGLPixmapDropShadowFilter::QGLPixmapDropShadowFilter(Qt::RenderHint hint) : m_haveCached(false) - , m_cachedRadius(5) + , m_cachedRadius(0) , m_hint(hint) { - if (hint == Qt::PerformanceHint) { - QGLPixmapDropShadowFilter *filter = const_cast(this); - filter->setSource(qt_gl_drop_shadow_filter_fast); - m_haveCached = true; - } } bool QGLPixmapDropShadowFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const { QGLPixmapDropShadowFilter *filter = const_cast(this); - int radius = qRound(this->blurRadius()); - if (!m_haveCached || (m_hint == Qt::QualityHint && radius != m_cachedRadius)) { + int actualRadius = qRound(blurRadius()); + int filterRadius = actualRadius; + m_singlePass = filterRadius <= 3; + + if (!m_haveCached || filterRadius != m_cachedRadius) { // Only regenerate the shader from source if parameters have changed. m_haveCached = true; - m_cachedRadius = radius; - filter->setSource(QGLPixmapBlurFilter::generateGaussianShader(radius, true)); + m_cachedRadius = filterRadius; + QByteArray source = QGLPixmapBlurFilter::generateGaussianShader(filterRadius, m_singlePass, true); + filter->setSource(source); } - QGLFramebufferObjectFormat format; - format.setInternalTextureFormat(GLenum(src.hasAlphaChannel() ? GL_RGBA : GL_RGB)); - QGLFramebufferObject *fbo = qgl_fbo_pool()->acquire(src.size(), format); - - if (!fbo) - return false; - - glBindTexture(GL_TEXTURE_2D, fbo->texture()); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_2D, 0); + QRect targetRect = QRectF(src.rect()).translated(pos + offset()).adjusted(-actualRadius, -actualRadius, actualRadius, actualRadius).toAlignedRect(); + + if (m_singlePass) { + // prepare for updateUniforms + m_textureSize = src.size(); + + painter->save(); + // ensure GL_LINEAR filtering is used + painter->setRenderHint(QPainter::SmoothPixmapTransform); + filter->setOnPainter(painter); + QBrush pixmapBrush = src; + pixmapBrush.setTransform(QTransform::fromTranslate(pos.x() + offset().x(), pos.y() + offset().y())); + painter->fillRect(targetRect, pixmapBrush); + filter->removeFromPainter(painter); + painter->restore(); + } else { + QGLFramebufferObjectFormat format; + format.setInternalTextureFormat(GLenum(src.hasAlphaChannel() ? GL_RGBA : GL_RGB)); + QGLFramebufferObject *fbo = qgl_fbo_pool()->acquire(targetRect.size(), format); - // prepare for updateUniforms - m_textureSize = src.size(); + if (!fbo) + return false; - // horizontal pass, to pixmap - m_horizontalBlur = true; + glBindTexture(GL_TEXTURE_2D, fbo->texture()); - QPainter fboPainter(fbo); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, 0); - if (src.hasAlphaChannel()) { - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); - } + // prepare for updateUniforms + m_textureSize = src.size(); - // ensure GL_LINEAR filtering is used - fboPainter.setRenderHint(QPainter::SmoothPixmapTransform); - filter->setOnPainter(&fboPainter); - fboPainter.drawPixmap(0, 0, src); - filter->removeFromPainter(&fboPainter); - fboPainter.end(); + // horizontal pass, to pixmap + m_horizontalBlur = true; - QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); + QPainter fboPainter(fbo); - // vertical pass, to painter - m_horizontalBlur = false; - - painter->save(); - // ensure GL_LINEAR filtering is used - painter->setRenderHint(QPainter::SmoothPixmapTransform); - filter->setOnPainter(painter); - QPointF ofs = offset(); - engine->drawTexture(src.rect().translated(pos.x() + ofs.x(), pos.y() + ofs.y()), fbo->texture(), fbo->size(), src.rect().translated(0, fbo->height() - src.height())); - filter->removeFromPainter(painter); - painter->restore(); + if (src.hasAlphaChannel()) { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + } - qgl_fbo_pool()->release(fbo); + // ensure GL_LINEAR filtering is used + fboPainter.setRenderHint(QPainter::SmoothPixmapTransform); + filter->setOnPainter(&fboPainter); + QBrush pixmapBrush = src; + pixmapBrush.setTransform(QTransform::fromTranslate(actualRadius, actualRadius)); + fboPainter.fillRect(QRect(0, 0, targetRect.width(), targetRect.height()), pixmapBrush); + filter->removeFromPainter(&fboPainter); + fboPainter.end(); + + QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); + + // vertical pass, to painter + m_horizontalBlur = false; + m_textureSize = fbo->size(); + + painter->save(); + // ensure GL_LINEAR filtering is used + painter->setRenderHint(QPainter::SmoothPixmapTransform); + filter->setOnPainter(painter); + engine->drawTexture(targetRect, fbo->texture(), fbo->size(), src.rect().translated(0, fbo->height() - src.height())); + filter->removeFromPainter(painter); + painter->restore(); + + qgl_fbo_pool()->release(fbo); + } // Now draw the actual pixmap over the top. painter->drawPixmap(pos, src, srcRect); @@ -597,8 +687,11 @@ bool QGLPixmapDropShadowFilter::processGL(QPainter *painter, const QPointF &pos, void QGLPixmapDropShadowFilter::setUniforms(QGLShaderProgram *program) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + QColor col = color(); - if (m_horizontalBlur) { + if (m_horizontalBlur && !m_singlePass) { program->setUniformValue("shadowColor", 1.0f, 1.0f, 1.0f, 1.0f); } else { qreal alpha = col.alphaF(); @@ -607,17 +700,20 @@ void QGLPixmapDropShadowFilter::setUniforms(QGLShaderProgram *program) col.blueF() * alpha, alpha); } + if (m_hint == Qt::QualityHint) { - if (m_horizontalBlur) + if (m_singlePass) + program->setUniformValue("delta", 1.0 / m_textureSize.width(), 1.0 / m_textureSize.height()); + else if (m_horizontalBlur) program->setUniformValue("delta", 1.0 / m_textureSize.width(), 0.0); else program->setUniformValue("delta", 0.0, 1.0 / m_textureSize.height()); } else { - // 1.4 is chosen to most closely match the blurriness of the gaussian blur - // at low radii - qreal blur = blurRadius() / 1.4f; + qreal blur = blurRadius() / qreal(m_cachedRadius); - if (m_horizontalBlur) + if (m_singlePass) + program->setUniformValue("delta", blur / m_textureSize.width(), blur / m_textureSize.height()); + else if (m_horizontalBlur) program->setUniformValue("delta", blur / m_textureSize.width(), 0.0); else program->setUniformValue("delta", 0.0, blur / m_textureSize.height()); -- cgit v0.12 From 8f527513fd2bc280d3613759d411e8e4e96a522e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 28 Oct 2009 18:02:40 +0100 Subject: Got rid of redundant texture parameter settings in GL pixmap filters. The texture parameters are set in drawTexture anyways. Reviewed-by: Gunnar Sletta --- src/opengl/qglpixmapfilter.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index e381a5d..2af69e0 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -381,14 +381,6 @@ bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const if (!fbo) return false; - glBindTexture(GL_TEXTURE_2D, fbo->texture()); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_2D, 0); - // prepare for updateUniforms m_textureSize = src.size(); @@ -632,14 +624,6 @@ bool QGLPixmapDropShadowFilter::processGL(QPainter *painter, const QPointF &pos, if (!fbo) return false; - glBindTexture(GL_TEXTURE_2D, fbo->texture()); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_2D, 0); - // prepare for updateUniforms m_textureSize = src.size(); -- cgit v0.12 From 7881773800c05c09f0e85a80c1cbb678981bd6c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 28 Oct 2009 17:57:12 +0100 Subject: Made internal FBOs snap to power-of-two when not wasting too much space. This improves performance on certain OpenGL ES 2.0 platforms. Reviewed-by: Gunnar Sletta --- src/opengl/qpixmapdata_gl.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 83ebece..c965947 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -76,6 +76,19 @@ static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo) return qAbs(size.width() * size.height() - fbo->width() * fbo->height()); } +extern int qt_next_power_of_two(int v); + +static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz) +{ +#ifdef QT_OPENGL_ES_2 + QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height())); + if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height()) + return rounded; +#endif + return sz; +} + + QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat) { QGLFramebufferObject *chosen = 0; @@ -106,7 +119,7 @@ QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize if (sz != fboSize) { delete candidate; - candidate = new QGLFramebufferObject(sz, requestFormat); + candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat); } chosen = candidate; @@ -114,7 +127,7 @@ QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize } if (!chosen) { - chosen = new QGLFramebufferObject(requestSize, requestFormat); + chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat); } if (!chosen->isValid()) { -- cgit v0.12 From 30099d68599d23b7e9c39e3f2e23a1bb5c6dd7dc Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 28 Oct 2009 17:24:05 +0100 Subject: QStateMachine::event() should call QState::event() Since QStateMachine inherits QState now. Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstatemachine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index e182c88..154445f 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1974,7 +1974,7 @@ bool QStateMachine::event(QEvent *e) return true; } } - return QObject::event(e); + return QState::event(e); } #ifndef QT_NO_STATEMACHINE_EVENTFILTER -- cgit v0.12 From 093ededb85c73f30ce3abf43bc6da0fff55323c2 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 28 Oct 2009 16:45:46 +0100 Subject: Cache QState's child states This is the same type of optimization as that done for transitions in commit 5d8dcd57cd13fdd9c8643fa3bdda9f197a4351ff. The idea is to avoid calling qobject_cast() because it's very expensive. Obtaining child states needs to be as fast as possible because it's in the critical path of the state machine algorithm; it's called by a ton of internal functions, like isCompound(), isAtomic(), isInFinalState(). It's also called heavily for parallel state groups. Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstate.cpp | 25 +++++++++++++++---------- src/corelib/statemachine/qstate_p.h | 2 ++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 9abf20b..bcd8364 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -125,7 +125,7 @@ QT_BEGIN_NAMESPACE QStatePrivate::QStatePrivate() : errorState(0), initialState(0), childMode(QState::ExclusiveStates), - transitionsListNeedsRefresh(true) + childStatesListNeedsRefresh(true), transitionsListNeedsRefresh(true) { } @@ -181,15 +181,18 @@ QState::~QState() QList QStatePrivate::childStates() const { - QList result; - QList::const_iterator it; - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QAbstractState *s = qobject_cast(*it); - if (!s || qobject_cast(s)) - continue; - result.append(s); + if (childStatesListNeedsRefresh) { + childStatesList.clear(); + QList::const_iterator it; + for (it = children.constBegin(); it != children.constEnd(); ++it) { + QAbstractState *s = qobject_cast(*it); + if (!s || qobject_cast(s)) + continue; + childStatesList.append(s); + } + childStatesListNeedsRefresh = false; } - return result; + return childStatesList; } QList QStatePrivate::historyStates() const @@ -473,8 +476,10 @@ void QState::setChildMode(ChildMode mode) bool QState::event(QEvent *e) { Q_D(QState); - if ((e->type() == QEvent::ChildAdded) || (e->type() == QEvent::ChildRemoved)) + if ((e->type() == QEvent::ChildAdded) || (e->type() == QEvent::ChildRemoved)) { + d->childStatesListNeedsRefresh = true; d->transitionsListNeedsRefresh = true; + } return QAbstractState::event(e); } diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 3b5f416..34c8838 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -99,6 +99,8 @@ public: QAbstractState *errorState; QAbstractState *initialState; QState::ChildMode childMode; + mutable bool childStatesListNeedsRefresh; + mutable QList childStatesList; mutable bool transitionsListNeedsRefresh; mutable QList transitionsList; -- cgit v0.12 From 414d5550f9ffe46faf1ee81b1a364683f2b2f066 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 28 Oct 2009 18:21:05 +0100 Subject: Test that we gracefully handle event posting after the state machine is stopped The internal slot _q_process() should never be called if the machine is not in the Running state. --- tests/auto/qstatemachine/tst_qstatemachine.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 1516346..346afc9 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -124,6 +124,7 @@ private slots: void postEvent(); void cancelDelayedEvent(); void postDelayedEventAndStop(); + void stopAndPostEvent(); void stateFinished(); void parallelStates(); void parallelRootState(); @@ -1681,6 +1682,22 @@ void tst_QStateMachine::postDelayedEventAndStop() QVERIFY(machine.configuration().contains(s1)); } +void tst_QStateMachine::stopAndPostEvent() +{ + QStateMachine machine; + QState *s1 = new QState(&machine); + machine.setInitialState(s1); + QSignalSpy startedSpy(&machine, SIGNAL(started())); + machine.start(); + QTRY_COMPARE(startedSpy.count(), 1); + QSignalSpy stoppedSpy(&machine, SIGNAL(stopped())); + machine.stop(); + QCOMPARE(stoppedSpy.count(), 0); + machine.postEvent(new QEvent(QEvent::User)); + QTRY_COMPARE(stoppedSpy.count(), 1); + QCoreApplication::processEvents(); +} + void tst_QStateMachine::stateFinished() { QStateMachine machine; -- cgit v0.12 From c3968d0981fd29764e3c665903f4c8db53cc1af3 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 28 Oct 2009 18:05:50 +0100 Subject: Make QStateMachine event posting functions thread-safe By popular demand on the Qt Labs blog. This makes it possible to readily use QStateMachine with e.g. worker threads that post events to the machine. Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstatemachine.cpp | 89 +++++++++++++++++++++----- src/corelib/statemachine/qstatemachine_p.h | 11 ++++ tests/auto/qstatemachine/tst_qstatemachine.cpp | 48 ++++++++++++++ 3 files changed, 131 insertions(+), 17 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 154445f..45b0286 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1216,8 +1216,7 @@ void QStateMachinePrivate::_q_process() delete e; e = 0; } - if (enabledTransitions.isEmpty() && !internalEventQueue.isEmpty()) { - e = internalEventQueue.takeFirst(); + if (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != 0)) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": dequeued internal event" << e << "of type" << e->type(); #endif @@ -1228,13 +1227,7 @@ void QStateMachinePrivate::_q_process() } } if (enabledTransitions.isEmpty()) { - if (externalEventQueue.isEmpty()) { - if (internalEventQueue.isEmpty()) { - processing = false; - stopProcessingReason = EventQueueEmpty; - } - } else { - e = externalEventQueue.takeFirst(); + if ((e = dequeueExternalEvent()) != 0) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": dequeued external event" << e << "of type" << e->type(); #endif @@ -1243,6 +1236,11 @@ void QStateMachinePrivate::_q_process() delete e; e = 0; } + } else { + if (isInternalEventQueueEmpty()) { + processing = false; + stopProcessingReason = EventQueueEmpty; + } } } if (!enabledTransitions.isEmpty()) { @@ -1278,17 +1276,60 @@ void QStateMachinePrivate::_q_process() } } +void QStateMachinePrivate::postInternalEvent(QEvent *e) +{ + QMutexLocker locker(&internalEventMutex); + internalEventQueue.append(e); +} + +void QStateMachinePrivate::postExternalEvent(QEvent *e) +{ + QMutexLocker locker(&externalEventMutex); + externalEventQueue.append(e); +} + +QEvent *QStateMachinePrivate::dequeueInternalEvent() +{ + QMutexLocker locker(&internalEventMutex); + if (internalEventQueue.isEmpty()) + return 0; + return internalEventQueue.takeFirst(); +} + +QEvent *QStateMachinePrivate::dequeueExternalEvent() +{ + QMutexLocker locker(&externalEventMutex); + if (externalEventQueue.isEmpty()) + return 0; + return externalEventQueue.takeFirst(); +} + +bool QStateMachinePrivate::isInternalEventQueueEmpty() +{ + QMutexLocker locker(&internalEventMutex); + return internalEventQueue.isEmpty(); +} + +bool QStateMachinePrivate::isExternalEventQueueEmpty() +{ + QMutexLocker locker(&externalEventMutex); + return externalEventQueue.isEmpty(); +} + void QStateMachinePrivate::processEvents(EventProcessingMode processingMode) { + Q_Q(QStateMachine); if ((state != Running) || processing || processingScheduled) return; switch (processingMode) { case DirectProcessing: - _q_process(); - break; + if (QThread::currentThread() == q->thread()) { + _q_process(); + break; + } // fallthrough -- processing must be done in the machine thread case QueuedProcessing: processingScheduled = true; - QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection); + QMetaObject::invokeMethod(q, "_q_process", Qt::QueuedConnection); break; } } @@ -1296,6 +1337,7 @@ void QStateMachinePrivate::processEvents(EventProcessingMode processingMode) void QStateMachinePrivate::cancelAllDelayedEvents() { Q_Q(QStateMachine); + QMutexLocker locker(&delayedEventsMutex); QHash::const_iterator it; for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) { int id = it.key(); @@ -1547,7 +1589,7 @@ void QStateMachinePrivate::handleFilteredEvent(QObject *watched, QEvent *event) { Q_ASSERT(qobjectEvents.contains(watched)); if (qobjectEvents[watched].contains(event->type())) { - internalEventQueue.append(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event))); + postInternalEvent(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event))); processEvents(DirectProcessing); } } @@ -1571,7 +1613,7 @@ void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalInd qDebug() << q_func() << ": sending signal event ( sender =" << sender << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')'; #endif - internalEventQueue.append(new QStateMachine::SignalEvent(sender, signalIndex, vargs)); + postInternalEvent(new QStateMachine::SignalEvent(sender, signalIndex, vargs)); processEvents(DirectProcessing); } @@ -1825,6 +1867,8 @@ void QStateMachine::stop() } /*! + \threadsafe + Posts the given \a event of the given \a priority for processing by this state machine. @@ -1852,16 +1896,18 @@ void QStateMachine::postEvent(QEvent *event, EventPriority priority) #endif switch (priority) { case NormalPriority: - d->externalEventQueue.append(event); + d->postExternalEvent(event); break; case HighPriority: - d->internalEventQueue.append(event); + d->postInternalEvent(event); break; } d->processEvents(QStateMachinePrivate::QueuedProcessing); } /*! + \threadsafe + Posts the given \a event for processing by this state machine, with the given \a delay in milliseconds. Returns an identifier associated with the delayed event, or -1 if the event could not be posted. @@ -1893,12 +1939,15 @@ int QStateMachine::postDelayedEvent(QEvent *event, int delay) #ifdef QSTATEMACHINE_DEBUG qDebug() << this << ": posting event" << event << "with delay" << delay; #endif + QMutexLocker locker(&d->delayedEventsMutex); int tid = startTimer(delay); d->delayedEvents[tid] = event; return tid; } /*! + \threadsafe + Cancels the delayed event identified by the given \a id. The id should be a value returned by a call to postDelayedEvent(). Returns true if the event was successfully cancelled, otherwise returns false. @@ -1912,6 +1961,7 @@ bool QStateMachine::cancelDelayedEvent(int id) qWarning("QStateMachine::cancelDelayedEvent: the machine is not running"); return false; } + QMutexLocker locker(&d->delayedEventsMutex); QEvent *e = d->delayedEvents.take(id); if (!e) return false; @@ -1963,15 +2013,20 @@ bool QStateMachine::event(QEvent *e) int tid = te->timerId(); if (d->state != QStateMachinePrivate::Running) { // This event has been cancelled already + QMutexLocker locker(&d->delayedEventsMutex); Q_ASSERT(!d->delayedEvents.contains(tid)); return true; } + d->delayedEventsMutex.lock(); QEvent *ee = d->delayedEvents.take(tid); if (ee != 0) { killTimer(tid); - d->externalEventQueue.append(ee); + d->delayedEventsMutex.unlock(); + d->postExternalEvent(ee); d->processEvents(QStateMachinePrivate::DirectProcessing); return true; + } else { + d->delayedEventsMutex.unlock(); } } return QState::event(e); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index cf7a073..69b727d 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -159,6 +160,13 @@ public: void unregisterAllTransitions(); void handleTransitionSignal(QObject *sender, int signalIndex, void **args); + + void postInternalEvent(QEvent *e); + void postExternalEvent(QEvent *e); + QEvent *dequeueInternalEvent(); + QEvent *dequeueExternalEvent(); + bool isInternalEventQueueEmpty(); + bool isExternalEventQueueEmpty(); void processEvents(EventProcessingMode processingMode); void cancelAllDelayedEvents(); @@ -181,6 +189,8 @@ public: QSet configuration; QList internalEventQueue; QList externalEventQueue; + QMutex internalEventMutex; + QMutex externalEventMutex; QStateMachine::Error error; QStateMachine::RestorePolicy globalRestorePolicy; @@ -214,6 +224,7 @@ public: QHash > qobjectEvents; #endif QHash delayedEvents; + QMutex delayedEventsMutex; typedef QEvent* (*f_cloneEvent)(QEvent*); struct Handler { diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 346afc9..97057c6 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -206,6 +206,7 @@ private slots: void goToState(); void task260403_clonedSignals(); + void postEventFromOtherThread(); }; tst_QStateMachine::tst_QStateMachine() @@ -4205,5 +4206,52 @@ void tst_QStateMachine::task260403_clonedSignals() QCOMPARE(t1->eventSignalIndex, emitter.metaObject()->indexOfSignal("signalWithDefaultArg()")); } +class EventPosterThread : public QThread +{ + Q_OBJECT +public: + EventPosterThread(QStateMachine *machine, QObject *parent = 0) + : QThread(parent), m_machine(machine), m_count(0) + { + moveToThread(this); + QObject::connect(m_machine, SIGNAL(started()), + this, SLOT(postEvent())); + } +protected: + virtual void run() + { + exec(); + } +private Q_SLOTS: + void postEvent() + { + m_machine->postEvent(new QEvent(QEvent::User)); + if (++m_count < 10000) + QTimer::singleShot(0, this, SLOT(postEvent())); + else + quit(); + } +private: + QStateMachine *m_machine; + int m_count; +}; + +void tst_QStateMachine::postEventFromOtherThread() +{ + QStateMachine machine; + EventPosterThread poster(&machine); + StringEventPoster *s1 = new StringEventPoster("foo", &machine); + s1->addTransition(new EventTransition(QEvent::User, s1)); + QFinalState *f = new QFinalState(&machine); + s1->addTransition(&poster, SIGNAL(finished()), f); + machine.setInitialState(s1); + + poster.start(); + + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" -- cgit v0.12 From c3b4522259bbbe216b31cd66ec6ce26d68847823 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 29 Oct 2009 10:49:52 +0100 Subject: doc: Remove \internal tag from QStateMachine::configuration() This function is useful for debugging, if nothing else, and has been requested by users. We also refer to it in one of our blog posts, so there's little point in trying to hide it any longer. Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstatemachine.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 45b0286..689967a 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1971,8 +1971,6 @@ bool QStateMachine::cancelDelayedEvent(int id) } /*! - \internal - Returns the maximal consistent set of states (including parallel and final states) that this state machine is currently in. If a state \c s is in the configuration, it is always the case that the parent of \c s is also in -- cgit v0.12 From 84c250448f8b1a3adee4dcaf2fc8edb282dda225 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 29 Oct 2009 13:32:50 +0100 Subject: Cache a state's parent state QAbstractState::parentState() is called heavily by the state machine algorithm. The parent state is obtained by qobject_cast'ing QObject::parent(). qobject_cast() is expensive. This commit introduces caching of the result in order to improve performance. We expect that the cache won't be invalidated much since the parent-child relationship of states usually doesn't change after the state machine is started. Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qabstractstate.cpp | 8 ++++++-- src/corelib/statemachine/qabstractstate_p.h | 2 ++ tests/auto/qstatemachine/tst_qstatemachine.cpp | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index 72d640b..cf67cdd 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -78,7 +78,8 @@ QT_BEGIN_NAMESPACE function to perform custom processing when the state is exited. */ -QAbstractStatePrivate::QAbstractStatePrivate() +QAbstractStatePrivate::QAbstractStatePrivate() + : parentState(0) { } @@ -150,7 +151,10 @@ QAbstractState::~QAbstractState() */ QState *QAbstractState::parentState() const { - return qobject_cast(parent()); + Q_D(const QAbstractState); + if (d->parentState != parent()) + d->parentState = qobject_cast(parent()); + return d->parentState; } /*! diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index 4b1306d..cd57815 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -76,6 +76,8 @@ public: void emitEntered(); void emitExited(); + + mutable QState *parentState; }; QT_END_NAMESPACE diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 97057c6..975b301 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -117,6 +117,7 @@ private slots: void cleanup(); void rootState(); + void machineWithParent(); void addAndRemoveState(); void stateEntryAndExit(); void assignProperty(); @@ -1045,6 +1046,14 @@ void tst_QStateMachine::rootState() QCOMPARE(s2->parentState(), static_cast(&machine)); } +void tst_QStateMachine::machineWithParent() +{ + QObject object; + QStateMachine *machine = new QStateMachine(&object); + QCOMPARE(machine->parent(), &object); + QCOMPARE(machine->parentState(), (QObject*)0); +} + void tst_QStateMachine::addAndRemoveState() { #ifdef QT_BUILD_INTERNAL -- cgit v0.12 From 4df10827546faafc3558bbe3c255e5cdab1984e5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 25 Sep 2009 16:49:50 +0200 Subject: Readd the Qt Evaluation timebomb, step 1. This is the QtCore part of the timebomb. Reviewed-by: Daniel Molkentin --- src/corelib/corelib.pro | 2 +- src/corelib/eval.pri | 2 + src/corelib/global/qlibraryinfo.cpp | 11 + src/corelib/global/qlibraryinfo.h | 2 + src/corelib/kernel/qtcore_eval.cpp | 569 ++++++++++++++++++++++++++++++++++++ 5 files changed, 585 insertions(+), 1 deletion(-) create mode 100644 src/corelib/eval.pri create mode 100644 src/corelib/kernel/qtcore_eval.cpp diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index f835bee..9a15bf1 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -35,4 +35,4 @@ symbian: { # Workaroud for problems with paging this dll MMP_RULES -= PAGED MMP_RULES *= UNPAGED -} \ No newline at end of file +} diff --git a/src/corelib/eval.pri b/src/corelib/eval.pri new file mode 100644 index 0000000..d50580b --- /dev/null +++ b/src/corelib/eval.pri @@ -0,0 +1,2 @@ +SOURCES += \ + $$QT_SOURCE_TREE/src/corelib/kernel/qtcore_eval.cpp \ diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index e227403..17273e9 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -208,6 +208,17 @@ QLibraryInfo::buildKey() } /*! + \since 4.6 + Returns the installation date for this build of Qt. The install date will + usually be the last time that Qt sources were configured. +*/ +QDate +QLibraryInfo::buildDate() +{ + return QDate::fromString(QString::fromLatin1(qt_configure_installation + 12), Qt::ISODate); +} + +/*! Returns the location specified by \a loc. */ diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 3195777..88e8566 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -43,6 +43,7 @@ #define QLIBRARYINFO_H #include +#include QT_BEGIN_HEADER @@ -59,6 +60,7 @@ public: static QString licensedProducts(); static QString buildKey(); + static QDate buildDate(); enum LibraryLocation { diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp new file mode 100644 index 0000000..0e18691 --- /dev/null +++ b/src/corelib/kernel/qtcore_eval.cpp @@ -0,0 +1,569 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include + +#include "stdio.h" +#include "stdlib.h" + +QT_BEGIN_NAMESPACE + +static const char boilerplate_unsuported[] = + "\nQt %1 Evaluation License\n" + "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).\n" + "All rights reserved.\n\n" + "This trial version may only be used for evaluation purposes\n" + "and will shut down after 120 minutes.\n" + "Registered to:\n" + " Licensee: %2\n\n" + "The evaluation expires in %4 days\n\n" + "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n"; + +static const char boilerplate_supported[] = + "\nQt %1 Evaluation License\n" + "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).\n" + "All rights reserved.\n\n" + "This trial version may only be used for evaluation purposes\n" + "Registered to:\n" + " Licensee: %2\n\n" + "The evaluation expires in %4 days\n\n" + "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n"; + +static const char boilerplate_expired[] = + "This software is using the trial version of the Qt GUI toolkit.\n" + "The trial period has expired. If you need more time to\n" + "evaluate Qt, or if you have any questions about Qt, contact us\n" + "at: http://qt.nokia.com/about/contact-us.\n\n"; + +static const char will_shutdown_1min[] = + "\nThe evaluation of Qt will SHUT DOWN in 1 minute.\n" + "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n"; + +static const char will_shutdown_now[] = + "\nThe evaluation of Qt has now reached its automatic\n" + "timeout and will shut down.\n" + "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n"; + +extern const char qt_eval_key_data[]; + +static int qt_eval_days_left() +{ + const char *const license_key = qt_eval_key_data + 12; + + // fast fail + if (!qt_eval_key_data[0] || !*license_key) + return -2; + + QDate today = QDate::currentDate(); + QDate build = QLibraryInfo::buildDate(); + return qMax(-1, today.daysTo(build) + 30); +} + +static int qt_eval_is_supported() +{ + const char *const license_key = qt_eval_key_data + 12; + if (!qt_eval_key_data[0] || !*license_key) + return -1; + + // is this an unsupported evaluation? + const char* typecode = license_key; + int field = 2; + for ( ; field && *typecode; ++typecode) + if (*typecode == '-') + --field; + + if (!field && typecode[1] == '4' && typecode[2] == 'M') { + if (typecode[0] == 'Q') + return 0; + else if (typecode[0] == 'R' || typecode[0] == 'Z') + return 1; + } + return -1; +} + +static QString qt_eval_string() +{ + const char *msg; + switch (qt_eval_is_supported()) { + case 0: + msg = boilerplate_unsuported; + break; + case 1: + msg = boilerplate_supported; + break; + default: + return QString(); + msg = 0; + } + + return QString::fromLatin1(msg) + .arg(QLatin1String(QT_VERSION_STR)) + .arg(QLibraryInfo::licensee()) + .arg(qt_eval_days_left()); +} + +#define WARN_TIMEOUT 60 * 1000 * 119 +#define KILL_DELAY 60 * 1000 * 1 + +class QCoreFuriCuri : public QObject +{ +public: + + int warn; + int kill; + + QCoreFuriCuri() : QObject(), warn(-1), kill(-1) + { + if (!qt_eval_is_supported()) { + warn = startTimer(WARN_TIMEOUT); + kill = 0; + } + } + + void timerEvent(QTimerEvent *e) { + if (e->timerId() == warn) { + killTimer(warn); + fprintf(stderr, "%s\n", will_shutdown_1min); + kill = startTimer(KILL_DELAY); + } else if (e->timerId() == kill) { + fprintf(stderr, "%s\n", will_shutdown_now); + QCoreApplication::instance()->quit(); + } + } +}; + +#if defined(QT_BUILD_CORE_LIB) || defined (QT_BOOTSTRAPPED) + +void qt_core_eval_init(uint type) +{ + switch (qt_eval_days_left()) { + case -2: + return; + + case -1: + fprintf(stderr, "%s\n", boilerplate_expired); + if (type == 0) { + // if we're a console app only. + exit(0); + } + + default: + fprintf(stderr, "%s\n", qPrintable(qt_eval_string())); + if (type == 0) { + Q_UNUSED(new QCoreFuriCuri()); + } + } +} +#endif + +#ifdef QT_BUILD_GUI_LIB + +QT_BEGIN_INCLUDE_NAMESPACE +#include +#include +#include +#include +#include +#include +#include +QT_END_INCLUDE_NAMESPACE + + +static const char * const qtlogo_eval_xpm[] = { +/* columns rows colors chars-per-pixel */ +"46 55 174 2", +" c #002E02", +". c #00370D", +"X c #003A0E", +"o c #003710", +"O c #013C13", +"+ c #043E1A", +"@ c #084F0A", +"# c #0B520C", +"$ c #054413", +"% c #0C4C17", +"& c #07421D", +"* c #09451D", +"= c #0D491E", +"- c #125515", +"; c #13541A", +": c #17591B", +"> c #1B5C1D", +", c #1F611F", +"< c #20621E", +"1 c #337B1E", +"2 c #0B4521", +"3 c #0F4923", +"4 c #114B24", +"5 c #154D2A", +"6 c #175323", +"7 c #1C5924", +"8 c #1C532F", +"9 c #1E5432", +"0 c #245936", +"q c #265938", +"w c #295C3B", +"e c #246324", +"r c #266823", +"t c #2A6C24", +"y c #276628", +"u c #2D7026", +"i c #327427", +"p c #367927", +"a c #37782A", +"s c #397C2A", +"d c #2E613E", +"f c #336C37", +"g c #2F6040", +"h c #356545", +"j c #3C6B4E", +"k c #3F6C51", +"l c #406E4F", +"z c #406D52", +"x c #477457", +"c c #497557", +"v c #4B7857", +"b c #517B5E", +"n c #3C8423", +"m c #3E812C", +"M c #53A61D", +"N c #41862C", +"B c #458A2D", +"V c #498F2D", +"C c #479324", +"Z c #489226", +"A c #4D952C", +"S c #478B30", +"D c #488C30", +"F c #4D9232", +"G c #509632", +"H c #549A33", +"J c #589F35", +"K c #56A526", +"L c #57A821", +"P c #5BAA27", +"I c #57A32A", +"U c #5CA72E", +"Y c #5DAB2A", +"T c #5CA336", +"R c #60AD2E", +"E c #63B12D", +"W c #65AF35", +"Q c #62A53F", +"! c #65AE39", +"~ c #66B036", +"^ c #6AB437", +"/ c #67B138", +"( c #6AB339", +") c #6DB838", +"_ c #70BA3C", +"` c #4D8545", +"' c #4E8942", +"] c #548851", +"[ c #6FAF4A", +"{ c #6DB243", +"} c #71B546", +"| c #70B840", +" . c #73B648", +".. c #79BA4E", +"X. c #7CBB53", +"o. c #598266", +"O. c #62886D", +"+. c #6A8F75", +"@. c #6B9173", +"#. c #70937A", +"$. c #799F79", +"%. c #7BAF66", +"&. c #81BD5B", +"*. c #85BF60", +"=. c #85AC7F", +"-. c #8DBA7B", +";. c #87C061", +":. c #8AC364", +">. c #8DC46A", +",. c #90C56E", +"<. c #93C771", +"1. c #96CA73", +"2. c #9ACB7C", +"3. c #9FD07D", +"4. c #779981", +"5. c #7F9F89", +"6. c #809F88", +"7. c #82A18B", +"8. c #86A192", +"9. c #8DA994", +"0. c #8FA998", +"q. c #94AF9B", +"w. c #97B991", +"e. c #97B19E", +"r. c #9DB6A3", +"t. c #A3BCA7", +"y. c #A6BCAB", +"u. c #A9BEB1", +"i. c #9ECD81", +"p. c #A2CF85", +"a. c #A5D284", +"s. c #A6D189", +"d. c #A9D28E", +"f. c #ABD491", +"g. c #B1D797", +"h. c #B1D699", +"j. c #B5D89E", +"k. c #ADC5AC", +"l. c #B1CAAE", +"z. c #B9DAA3", +"x. c #BDDDA8", +"c. c #ADC1B4", +"v. c #B2C6B6", +"b. c #B5C6BC", +"n. c #B6C9BA", +"m. c #BCD1BA", +"M. c #C6E1B4", +"N. c #CDE5BD", +"B. c #C2D2C6", +"V. c #CADEC2", +"C. c #C6D3CC", +"Z. c #C8D7CB", +"A. c #CEDAD2", +"S. c #D2DDD4", +"D. c #D3E9C6", +"F. c #D7EBC9", +"G. c #D9EBCD", +"H. c #DEEED4", +"J. c #D6E0D9", +"K. c #DAE4DC", +"L. c #E0EFD7", +"P. c #E5F2DD", +"I. c #DFE8E0", +"U. c #E4EBE5", +"Y. c #E9EFEA", +"T. c #EDF4EB", +"R. c #F0FAE6", +"E. c #F1F8EC", +"W. c #EDF0F0", +"Q. c #F4F7F3", +"!. c #F6F9F4", +"~. c #F8FAF7", +"^. c #FEFEFE", +"/. c None", +/* pixels */ +"/././././.c h ' Q / W _ &.p././././././././././././././././././././././././././././././././.", +"/././.4 O % Z ~ ~ W ~ W R U R R ( X.>.p././././././././././././././././././././././././././.", +"/./.. * = J _ ~ ~ ~ ~ ~ / / / / W W U P P U W .;.2././././././././././././././././././././.", +"/.= = & a ) W ~ ~ ~ ~ ~ / W / ~ ~ ~ ^ ( ( ^ ~ R R U P Y ~ .;.2././././././././././././././.", +"O.O = = T ^ W ~ ~ ~ ~ ~ ~ W W / W ~ ~ ~ ~ ~ ~ ~ ( ( ( ( ~ W Y Y Y Y W { &.1././././././././.", +"0 = * 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ / / W ~ ~ ~ ~ ~ ~ ~ ~ W W W ~ ~ ~ ~ ( ( ( W W R U P U W { X.1.f./.", +"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ / / ~ ~ ~ ~ ~ ~ ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ^ ( ( / ~ W R U U Y ", +"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W ~ ~ ~ ^ ^ ( ", +"= = * e ^ W ~ ~ ~ ~ ~ ~ / W / W ! ( / ~ W ^ ( ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ~ W W ~ ~ ~ ~ ~ ~ ", +"= = & e ^ ! ~ ~ ~ ~ ~ ~ W W ^ _ ~ K Y W W R P Y W ( ~ ~ ~ ~ ~ ~ ~ W / ~ ~ ~ ^ W ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W ~ ~ ~ ~ ~ ~ W ) W 1 ` w.V.L.H.D.z.,.~ Y ^ ~ ~ ~ ~ ~ W ~ ~ ~ ( ~ W W ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W ~ ~ ~ ~ ~ W ) V = 8.~.^.^.^.^.^.^.^.U.<.Y ~ ~ ~ ~ ~ W W ! ~ Y W ^ W ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W ~ ~ ~ ~ W ^ B O u.^.~.^.^.^.^.~.~.^.^.^.h.Y ^ ~ ~ ^ F $ k.R.G.1.Y / ~ ~ ~ ~ ~ ~ ", +"= = & e ^ ~ ~ ~ / W ( J X 7.^.~.^.^.^.^.^.^.^.^.^.^.^.s.Y / W ) a 2 U.^.^.d.U ( ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W / ~ ~ ~ ^ > w ~.^.^.^.^.^.F.%.v c.^.^.^.^.~.X.W ~ ^ > h ^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W ~ ~ W ^ H o e.^.^.^.^.^.G.Y E n . y.^.^.^.^.M.Y ( ! $ @.^.~.^.f.U ( / ~ ~ W ~ ~ ", +"= = & e ^ W ~ W ! ) t 4 U.^.^.^.^.^.>.U ( _ , 9 ~.^.^.^.~...^ A y.^.~.^.s.M W Y ~ ~ ~ ~ ~ ", +"= 3 & e ^ W ~ ( ^ ( $ c ^.^.^.^.^.E.) ~ ~ ^ S o n.^.^.^.^.=.- l.v.Y.^.^.^.M.:.:.X.~ ~ ~ ~ ~ ", +"= = & e ^ ! W W ( J X 7.^.^.^.^.^.F.Y ( W ^ T X 6.^.^.~.^.c.. J.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ", +"= = & r ^ W / W ) B o v.^.~.^.^.^.M.U / ~ ~ ! $ o.^.^.^.^.K.* S.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ", +"= = & e ^ ! ~ W ) a + S.^.^.^.^.^.z.P ( W ~ ( % z ^.^.^.^.~.f t.U.^.^.^.^.~.^.^.P.~ ~ ~ ~ ~ ", +"* = & e ^ W ~ W ) t 3 Y.^.^.^.^.^.f.P ( ~ ~ ^ ; h ^.^.^.^.^.:.@ j ^.^.^.^.h.{ X.&.~ ~ ~ ~ ~ ", +"3 = & e ^ W ~ ~ ^ e 8 Q.^.^.^.^.^.s.P ~ ~ W ^ > 0 ~.^.^.^.^.1.# z ^.^.^.^.d.L W R ~ ~ ~ ~ ~ ", +"= = & e ^ W ~ ~ ^ > q ~.^.^.^.^.^.p.U ^ ~ W ) e 9 ~.^.^.^.^.3.# k ^.^.^.^.f.Y ( / ~ ~ ~ ~ ~ ", +"= = & e ^ W / W ^ > w ~.^.^.^.^.^.i.Y / ~ W ^ e 8 Q.^.^.^.^.a.# z ^.^.^.^.f.Y / ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W / W ^ > w ^.^.^.^.^.^.2.Y / ~ ~ ) e 8 Q.^.^.^.^.s.# z ^.^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W W W ^ > q ^.^.^.^.^.^.p.Y / ~ ~ ^ e 9 Q.^.^.^.^.a.@ z ^.^.^.^.f.U / ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W / W ) 7 9 Q.^.^.^.^.^.a.P / ~ W ) , 9 Q.^.^.^.^.3.# z ^.^.~.^.f.P ^ ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W / W ) r 5 T.^.^.^.^.^.d.Y / ~ W ) > q ~.^.^.^.^.1.# k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ", +"= = & e ^ / / W ) i 2 I.^.^.^.^.^.h.P ( ~ W ( > g ^.^.^.^.^.:.# z ^.^.^.^.f.P / ~ ~ ~ ~ ~ ~ ", +"= = & e ( W / W ) m O Z.^.^.^.^.^.x.P / ~ ~ ( ; j ^.^.^.^.~.&.- k ^.^.~.^.f.P / ~ ~ ~ ~ ~ ~ ", +"= = & e ( W / W ) F o y.^.~.^.^.^.N.U ( ~ ~ W $ b ^.^.^.^.R._ - k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ", +"= = & e ^ W ~ ~ ^ J X 4.^.^.^.^.^.L.~ ~ W ^ T X #.^.^.^.^.F.~ ; j ^.^.^.^.f.U ( ~ ~ ~ ~ ~ ~ ", +"= = & e ^ ~ ~ ~ / ^ % l ^.^.^.^.^.!. .R ^ ^ G . r.^.~.^.^.j.E : j ^.^.^.^.f.P ) ( ~ ~ ~ ~ ~ ", +"= = & e ^ W ~ ~ W ) u = U.^.^.^.^.^.1.Y ! ) a & K.^.^.^.^.;.~ : j ^.^.~.^.z.M I I / ~ ~ W ~ ", +"= = & e ( W ~ ~ W ( G . q.^.^.^.^.^.D.U ^ ! X o.^.^.^.^.P.~ ^ > g ^.^.^.^.E.-.$.m.X.W ~ ~ ~ ", +"= = & e ^ / ~ ~ ^ ! ( > w ~.^.^.^.^.^.h.T > j T.^.^.~.^.a.Y _ i 3 U.^.^.^.^.^.^.^.X.R ~ ~ ~ ", +"= = & e ^ / ~ ~ W W ^ H . 9.^.~.^.^.^.^.K.C.~.^.^.^.^.H.W W ^ T . q.^.~.^.^.^.^.^.X.R ~ ~ ~ ", +"= = + e ^ W / ~ W W W ) m + B.^.~.^.^.^.^.^.^.^.^.^.E.X.Y ( W ^ B 6 y.^.^.^.E.D.2.( ~ ~ ~ ~ ", +"= = * e ^ ! / ! W ^ W W ) a 4 b.^.^.^.^.^.^.^.^.^.P...Y ( ! W ! ^ W Z [ *.X.{ Y U ~ ~ ~ ~ ~ ", +"= = & e ( W ~ ~ W / W / W ) A < +.A.~.^.^.^.^.!.p.W R ~ ~ ~ ~ ~ W / ) E U W W / ^ ~ ~ ~ ~ ~ ", +"= = & e ^ W ~ ~ / W / / / W ( _ Z X 6.^.^.^.^.E.W ~ ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ / ~ ~ ~ ~ ~ ~ ~ ~ ", +"= = & e ^ ~ ~ ~ W W / W ~ ~ ~ ~ ) ; h ^.^.^.^.^.d.M U ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ", +"= = & e ^ W ~ ~ ^ W W / ~ ~ ~ W ) p + S.^.^.^.^.~.M.f. .W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ .", +"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( T O +.^.~.^.^.^.^.^.&.Y ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( Y 2.", +"= = & e ( W ~ ~ ~ ~ ~ ~ ~ ~ ~ / W ) N + b.^.^.^.^.^.^.&.R ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W /.", +"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ^ N 7 r.W.^.^.^.!.X.W ~ ~ W ~ W ~ ~ ~ ~ ~ ~ / ( ( K p./.", +"= = & e ( W ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W C Q &.:.X.| ~ ~ ~ ~ W ~ / ~ ( / ( ~ W E U P 1././.", +"= = + e ^ / / / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W / ) ^ R Y W W ~ ~ ( / ( / W R Y Y U R ( X.,././././.", +"= = * e ( / ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W ! ( ( ( W W E U P Y W ( X.,.d./././././././././.", +"= = * e ( W ~ ~ ~ ~ W ! ~ W ~ W ~ ( ( / ^ W W U Y P W ( X.,.d./././././././././././././././.", +"8 $ * e ( W ~ ~ ~ ! ( ( ( / ( W R Y Y Y R ( X.>.d./././././././././././././././././././././.", +"/.d . y ^ / / / ( W Y Y P P W ( X.>.d./././././././././././././././././././././././././././.", +"/./.h : ^ R R R W ( X.<.f./././././././././././././././././././././././././././././././././.", +"/././.] _ *.3./././././././././././././././././././././././././././././././././././././././." +}; + +class EvalMessageBox : public QDialog +{ +public: + EvalMessageBox(bool expired) + { + setWindowTitle(" "); + + QString str = qt_eval_string(); + if (expired) { + str = QLatin1String(boilerplate_expired); + } else { + str = qt_eval_string(); + } + str = str.trimmed(); + + QFrame *border = new QFrame(this); + + QLabel *pixmap_label = new QLabel(border); + pixmap_label->setPixmap(qtlogo_eval_xpm); + pixmap_label->setAlignment(Qt::AlignTop); + + QLabel *text_label = new QLabel(str, border); + + QHBoxLayout *pm_and_text_layout = new QHBoxLayout(); + pm_and_text_layout->addWidget(pixmap_label); + pm_and_text_layout->addWidget(text_label); + + QVBoxLayout *master_layout = new QVBoxLayout(border); + master_layout->addLayout(pm_and_text_layout); + + QVBoxLayout *border_layout = new QVBoxLayout(this); + border_layout->setMargin(0); + border_layout->addWidget(border); + + if (expired) { + QPushButton *cmd = new QPushButton("OK", border); + cmd->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + cmd->setDefault(true); + + QHBoxLayout *button_layout = new QHBoxLayout(); + master_layout->addLayout(button_layout); + button_layout->addWidget(cmd); + + connect(cmd, SIGNAL(clicked()), this, SLOT(close())); + } else { + border->setFrameShape(QFrame::WinPanel); + border->setFrameShadow(QFrame::Raised); + setParent(parentWidget(), Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + QTimer::singleShot(7000, this, SLOT(close())); + setAttribute(Qt::WA_DeleteOnClose); + } + + setFixedSize(sizeHint()); + } +}; + +class QGuiFuriCuri : public QCoreFuriCuri +{ +public: + void timerEvent(QTimerEvent *e) { + if (e->timerId() == warn) { + killTimer(warn); + QMessageBox::information(0, "Automatic Timeout", will_shutdown_1min); + kill = startTimer(KILL_DELAY); + } else if (e->timerId() == kill) { + killTimer(kill); + QMessageBox::information(0, "Automatic Timeout", will_shutdown_now); + qApp->quit(); + } + } +}; + + +void qt_gui_eval_init(uint) +{ + switch (qt_eval_days_left()) { + case -2: + return; + + case -1: { + EvalMessageBox box(true); + box.exec(); + ::exit(0); + } + + default: { + EvalMessageBox *box = new EvalMessageBox(false); + box->show(); + Q_UNUSED(new QGuiFuriCuri()); + } + } +} + +static QString qt_eval_title_prefix() +{ + return QLatin1String("[Qt Evaluation] "); +} + +QString qt_eval_adapt_window_title(const QString &title) +{ + if (qt_eval_days_left() == -2) + return title; + return qt_eval_title_prefix() + title; +} + +void qt_eval_init_widget(QWidget *w) +{ + if (qt_eval_days_left() == -2) + return; + if (w->isTopLevel()) { + QString windowTitle = w->windowTitle(); + if (windowTitle.isEmpty()) { + w->setWindowTitle(" "); + } else if (!windowTitle.startsWith(qt_eval_title_prefix())) { + qt_eval_adapt_window_title(windowTitle); + } + } +} +#endif + +QT_END_NAMESPACE -- cgit v0.12 From ab7b164f60b0819d24d5b57d70988c4f5751329f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Oct 2009 13:01:28 +0100 Subject: Part 2 of the Evaluation notice feature, now for QtGui. Reviewed-by: Daniel Molkentin --- configure | 22 ++++++++++++++++++++++ src/corelib/eval.pri | 4 +++- src/corelib/kernel/qtcore_eval.cpp | 14 +++++++------- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 08ec524..e3022b7 100755 --- a/configure +++ b/configure @@ -431,6 +431,7 @@ elif [ $COMMERCIAL_USER = "yes" ]; then ;; Z4M|R4M|Q4M) LicenseType="Evaluation" + QMakeVar add DEFINES QT_EVAL case $ProductCode in B) Edition="Evaluation" @@ -4068,12 +4069,17 @@ SETTINGS_PATH_STR=`"$relpath/config.tests/unix/padstring" 268 "qt_stngpath=$QT_I EXAMPLES_PATH_STR=`"$relpath/config.tests/unix/padstring" 268 "qt_xmplpath=$QT_INSTALL_EXAMPLES"` DEMOS_PATH_STR=`"$relpath/config.tests/unix/padstring" 268 "qt_demopath=$QT_INSTALL_DEMOS"` +TODAY=`date +%Y-%m-%d` cat > "$outpath/src/corelib/global/qconfig.cpp.new" </dev/null 2>&1; then + EVALKEY=`"$relpath/config.tests/unix/padstring" 524 "qt_qevalkey="` +fi + +if [ -n "$EVALKEY" ]; then + cat > "$outpath/src/corelib/global/qconfig_eval.cpp" <addWidget(border); if (expired) { - QPushButton *cmd = new QPushButton("OK", border); + QPushButton *cmd = new QPushButton(QLatin1String("OK"), border); cmd->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); cmd->setDefault(true); @@ -508,11 +508,11 @@ public: void timerEvent(QTimerEvent *e) { if (e->timerId() == warn) { killTimer(warn); - QMessageBox::information(0, "Automatic Timeout", will_shutdown_1min); + QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_1min)); kill = startTimer(KILL_DELAY); } else if (e->timerId() == kill) { killTimer(kill); - QMessageBox::information(0, "Automatic Timeout", will_shutdown_now); + QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_now)); qApp->quit(); } } @@ -558,7 +558,7 @@ void qt_eval_init_widget(QWidget *w) if (w->isTopLevel()) { QString windowTitle = w->windowTitle(); if (windowTitle.isEmpty()) { - w->setWindowTitle(" "); + w->setWindowTitle(QLatin1String(" ")); } else if (!windowTitle.startsWith(qt_eval_title_prefix())) { qt_eval_adapt_window_title(windowTitle); } -- cgit v0.12 From 2e9be4eec0778ceea2e32b4826cba08d85b177d9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 25 Sep 2009 17:18:28 +0200 Subject: Add the Qt Evaluation message to the hidden libQtCore.so boilerplate. Reviewed-By: Trust Me --- src/corelib/global/qlibraryinfo.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 17273e9..15a06d7 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -492,12 +492,20 @@ void qt_core_boilerplate() "Contact: Nokia Corporation (qt-info@nokia.com)\n" "\n" "Build key: " QT_BUILD_KEY "\n" + "Build date: %s\n" "Installation prefix: %s\n" "Library path: %s\n" "Include path: %s\n", + qt_configure_installation + 12, qt_configure_prefix_path_str + 12, qt_configure_libraries_path_str + 12, qt_configure_headers_path_str + 12); + +#ifdef QT_EVAL + extern void qt_core_eval_init(uint); + qt_core_eval_init(1); +#endif + exit(0); } -- cgit v0.12 From 7e0c0d684a42371c3597441a2488e05ce520f91e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 28 Sep 2009 12:27:26 +0200 Subject: Also change the configure.exe to ensure that the necessary new configs are generated Reviewed-By: Daniel Molkentin --- tools/configure/configureapp.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index f57f3a8..f75b51b 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -3033,7 +3033,11 @@ void Configure::generateConfigfiles() tmpStream.setDevice(&tmpFile2); tmpStream << "/* Licensed */" << endl << "static const char qt_configure_licensee_str [512 + 12] = \"qt_lcnsuser=" << licenseInfo["LICENSEE"] << "\";" << endl - << "static const char qt_configure_licensed_products_str [512 + 12] = \"qt_lcnsprod=" << dictionary["EDITION"] << "\";" << endl; + << "static const char qt_configure_licensed_products_str [512 + 12] = \"qt_lcnsprod=" << dictionary["EDITION"] << "\";" << endl + << endl + << "/* Build date */" << endl + << "static const char qt_configure_installation [11 + 12] = \"" << QDate::currentDate().toString(Qt::ISODate) << "\";" << endl + << endl; if(!dictionary[ "QT_HOST_PREFIX" ].isNull()) tmpStream << "#if !defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE)" << endl; tmpStream << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << QString(dictionary["QT_INSTALL_PREFIX"]).replace( "\\", "\\\\" ) << "\";" << endl @@ -3087,6 +3091,24 @@ void Configure::generateConfigfiles() tmpFile2.copy(outName); tmpFile2.close(); } + + QTemporaryFile tmpFile3; + if (tmpFile3.open()) { + tmpStream.setDevice(&tmpFile3); + tmpStream << "/* Evaluation license key */" << endl + << "static const char qt_eval_key_data [512 + 12] = \"" << licenseInfo["LICENSEKEYEXT"] << "\";" << endl; + + tmpStream.flush(); + tmpFile3.flush(); + + outName = buildPath + "/src/corelib/global/qconfig_eval.cpp"; + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL ); + QFile::remove( outName ); + + if (dictionary["EDITION"] == "Evaluation" || qmakeDefines.contains("QT_EVAL")) + tmpFile3.copy(outName); + tmpFile3.close(); + } } #endif -- cgit v0.12 From 263c81d923a1ed90335a3fb05c87330630456073 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Thu, 29 Oct 2009 14:20:46 +0100 Subject: Plug some autorelease pool leaks. Calling QWidget::setCursor() outside of the event loop causes a memory leak in Cocoa. Adding an autorelease pool plugs it. Merge-request: 1791 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qwidget_mac.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index ef71194..db11815 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2872,6 +2872,7 @@ void QWidgetPrivate::setCursor_sys(const QCursor &) #else Q_Q(QWidget); if (q->testAttribute(Qt::WA_WState_Created)) { + QMacCocoaAutoReleasePool pool; [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)]; } #endif @@ -2884,6 +2885,7 @@ void QWidgetPrivate::unsetCursor_sys() #else Q_Q(QWidget); if (q->testAttribute(Qt::WA_WState_Created)) { + QMacCocoaAutoReleasePool pool; [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)]; } #endif -- cgit v0.12 From ef4276442f8421771c827ad4e29bc69baf24de2d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Oct 2009 14:28:42 +0100 Subject: Remove the fromUserInput implementation and tests. Reviewed-by: Trust Me --- src/corelib/io/qurl.cpp | 119 +++++++++++++++++-------------------------- tests/auto/qurl/tst_qurl.cpp | 55 -------------------- 2 files changed, 46 insertions(+), 128 deletions(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 6001d9d..a865d8d 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -5556,79 +5556,6 @@ QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode parsingMode) } /*! - Returns a valid URL from a user supplied \a userInput string if one can be - deducted. In the case that is not possible, an invalid QUrl() is returned. - - \since 4.6 - - Most applications that can browse the web, allow the user to input a URL - in the form of a plain string. This string can be manually typed into - a location bar, obtained from the clipboard, or passed in via command - line arguments. - - When the string is not already a valid URL, a best guess is performed, - making various web related assumptions. - - In the case the string corresponds to a valid file path on the system, - a file:// URL is constructed, using QUrl::fromLocalFile(). - - If that is not the case, an attempt is made to turn the string into a - http:// or ftp:// URL. The latter in the case the string starts with - 'ftp'. The result is then passed through QUrl's tolerant parser, and - in the case or success, a valid QUrl is returned, or else a QUrl(). - - \section1 Examples: - - \list - \o qt.nokia.com becomes http://qt.nokia.com - \o ftp.qt.nokia.com becomes ftp://ftp.qt.nokia.com - \o localhost becomes http://localhost - \o /home/user/test.html becomes file:///home/user/test.html (if exists) - \endlist - - \section2 Tips to avoid erroneous character conversion when dealing with - URLs and strings: - - \list - \o When creating an URL QString from a QByteArray or a char*, always use - QString::fromUtf8(). - \o Favor the use of QUrl::fromEncoded() and QUrl::toEncoded() instead of - QUrl(string) and QUrl::toString() when converting QUrl to/from string. - \endlist -*/ -QUrl QUrl::fromUserInput(const QString &userInput) -{ - QString trimmedString = userInput.trimmed(); - - // Absolute files - if (QDir::isAbsolutePath(trimmedString)) - return QUrl::fromLocalFile(trimmedString); - - // Check the most common case of a valid url with scheme and host first - QUrl url = QUrl::fromEncoded(trimmedString.toUtf8(), QUrl::TolerantMode); - if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) - return url; - - // If the string is missing the scheme or the scheme is not valid, prepend a scheme - QString scheme = url.scheme(); - if (scheme.isEmpty() || scheme.contains(QLatin1Char('.')) || scheme == QLatin1String("localhost")) { - // Do not do anything for strings such as "foo", only "foo.com" - int dotIndex = trimmedString.indexOf(QLatin1Char('.')); - if (dotIndex != -1 || trimmedString.startsWith(QLatin1String("localhost"))) { - const QString hostscheme = trimmedString.left(dotIndex).toLower(); - QByteArray scheme = (hostscheme == QLatin1String("ftp")) ? "ftp" : "http"; - trimmedString = QLatin1String(scheme) + QLatin1String("://") + trimmedString; - } - url = QUrl::fromEncoded(trimmedString.toUtf8(), QUrl::TolerantMode); - } - - if (url.isValid()) - return url; - - return QUrl(); -} - -/*! Returns a decoded copy of \a input. \a input is first decoded from percent encoding, then converted from UTF-8 to unicode. */ @@ -6227,4 +6154,50 @@ QString QUrl::errorString() const \internal */ + +/*! + Returns a valid URL from a user supplied \a userInput string if one can be + deducted. In the case that is not possible, an invalid QUrl() is returned. + + \since 4.6 + + Most applications that can browse the web, allow the user to input a URL + in the form of a plain string. This string can be manually typed into + a location bar, obtained from the clipboard, or passed in via command + line arguments. + + When the string is not already a valid URL, a best guess is performed, + making various web related assumptions. + + In the case the string corresponds to a valid file path on the system, + a file:// URL is constructed, using QUrl::fromLocalFile(). + + If that is not the case, an attempt is made to turn the string into a + http:// or ftp:// URL. The latter in the case the string starts with + 'ftp'. The result is then passed through QUrl's tolerant parser, and + in the case or success, a valid QUrl is returned, or else a QUrl(). + + \section1 Examples: + + \list + \o qt.nokia.com becomes http://qt.nokia.com + \o ftp.qt.nokia.com becomes ftp://ftp.qt.nokia.com + \o localhost becomes http://localhost + \o /home/user/test.html becomes file:///home/user/test.html (if exists) + \endlist + + \section2 Tips to avoid erroneous character conversion when dealing with + URLs and strings: + + \list + \o When creating an URL QString from a QByteArray or a char*, always use + QString::fromUtf8(). + \o Favor the use of QUrl::fromEncoded() and QUrl::toEncoded() instead of + QUrl(string) and QUrl::toString() when converting QUrl to/from string. + \endlist +*/ +QUrl QUrl::fromUserInput(const QString &userInput) +{ +} + QT_END_NAMESPACE diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 72c13bf..178e5e5 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -3679,65 +3679,10 @@ void tst_QUrl::binaryData() void tst_QUrl::fromUserInput_data() { - QTest::addColumn("string"); - QTest::addColumn("url"); - - // Null - QTest::newRow("null") << QString() << QUrl(); - - // File - QDirIterator it(QDir::homePath()); - QString fileString; - int c = 0; - while (it.hasNext()) { - it.next(); - QTest::newRow(QString("file-%1").arg(c++).toLatin1()) << it.filePath() << QUrl::fromLocalFile(it.filePath()); - } - - // basic latin1 - QTest::newRow("unicode-0") << QString::fromUtf8("\xC3\xA5.com/") << QUrl::fromEncoded(QString::fromUtf8("http://\xC3\xA5.com/").toUtf8(), QUrl::TolerantMode); - // unicode - QTest::newRow("unicode-1") << QString::fromUtf8("\xCE\xBB.com/") << QUrl::fromEncoded(QString::fromUtf8("http://\xCE\xBB.com/").toUtf8(), QUrl::TolerantMode); - - // no scheme - QTest::newRow("add scheme-0") << "webkit.org" << QUrl("http://webkit.org"); - QTest::newRow("add scheme-1") << "www.webkit.org" << QUrl("http://www.webkit.org"); - QTest::newRow("add scheme-2") << "ftp.webkit.org" << QUrl("ftp://ftp.webkit.org"); - QTest::newRow("add scheme-3") << "webkit" << QUrl("webkit"); - - // QUrl's tolerant parser should already handle this - QTest::newRow("not-encoded-0") << "http://webkit.org/test page.html" << QUrl("http://webkit.org/test%20page.html"); - - // Make sure the :80, i.e. port doesn't screw anything up - QUrl portUrl("http://webkit.org"); - portUrl.setPort(80); - QTest::newRow("port-0") << "webkit.org:80" << portUrl; - QTest::newRow("port-1") << "http://webkit.org:80" << portUrl; - - // mailto doesn't have a ://, but is valid - QUrl mailto("somebody@somewhere.net"); - mailto.setScheme("mailto"); - QTest::newRow("mailto") << "mailto:somebody@somewhere.net" << mailto; - - // misc - QTest::newRow("localhost-0") << "localhost" << QUrl("http://localhost"); - QTest::newRow("localhost-1") << "localhost:80" << QUrl("http://localhost:80"); - QTest::newRow("spaces-0") << " http://webkit.org/test page.html " << QUrl("http://webkit.org/test%20page.html"); - QTest::newRow("trash-0") << "webkit.org/test?someData=42%&someOtherData=abcde#anchor" << QUrl::fromEncoded("http://webkit.org/test?someData=42%25&someOtherData=abcde#anchor"); - - // FYI: The scheme in the resulting url user - QUrl authUrl("user:pass@domain.com"); - QTest::newRow("misc-1") << "user:pass@domain.com" << authUrl; } -// public static QUrl guessUrlFromString(QString const& string) void tst_QUrl::fromUserInput() { - QFETCH(QString, string); - QFETCH(QUrl, url); - - QUrl guessedUrl = QUrl::fromUserInput(string); - QCOMPARE(guessedUrl, url); } void tst_QUrl::task_199967() -- cgit v0.12 From 244c27d22cb7c0e686210ceb2973862ae514f95b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Oct 2009 14:41:12 +0100 Subject: Import a new implementation of fromUserInput. Imported from http://github.com/icefox/guessurlfromstring Licensed under the 3-clause BSD license by the copyright holder. --- src/corelib/io/qurl.cpp | 57 +++++++++++++++++++++++++++++++++++++++++ tests/auto/qurl/tst_qurl.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index a865d8d..86680a5 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -6154,6 +6154,34 @@ QString QUrl::errorString() const \internal */ +// The following code has the following copyright: +/* + Copyright (C) Research In Motion Limited 2009. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Research In Motion Limited nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Research In Motion Limited ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Research In Motion Limited BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + /*! Returns a valid URL from a user supplied \a userInput string if one can be @@ -6198,6 +6226,35 @@ QString QUrl::errorString() const */ QUrl QUrl::fromUserInput(const QString &userInput) { + QString trimmedString = userInput.trimmed(); + + // Check the most common case of a valid url with scheme and host first + QUrl url = QUrl::fromEncoded(trimmedString.toUtf8(), QUrl::TolerantMode); + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) + return url; + + // Absolute files that exists + if (QDir::isAbsolutePath(trimmedString) && QFile::exists(trimmedString)) + return QUrl::fromLocalFile(trimmedString); + + // If the string is missing the scheme or the scheme is not valid prepend a scheme + QString scheme = url.scheme(); + if (scheme.isEmpty() || scheme.contains(QLatin1Char('.')) || scheme == QLatin1String("localhost")) { + // Do not do anything for strings such as "foo", only "foo.com" + int dotIndex = trimmedString.indexOf(QLatin1Char('.')); + if (dotIndex != -1 || trimmedString.startsWith(QLatin1String("localhost"))) { + const QString hostscheme = trimmedString.left(dotIndex).toLower(); + QByteArray scheme = (hostscheme == QLatin1String("ftp")) ? "ftp" : "http"; + trimmedString = QLatin1String(scheme) + QLatin1String("://") + trimmedString; + } + url = QUrl::fromEncoded(trimmedString.toUtf8(), QUrl::TolerantMode); + } + + if (url.isValid()) + return url; + + return QUrl(); } +// end of BSD code QT_END_NAMESPACE diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 178e5e5..6424dcc 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -3679,10 +3679,70 @@ void tst_QUrl::binaryData() void tst_QUrl::fromUserInput_data() { + // + // most of this test is: + // Copyright (C) Research In Motion Limited 2009. All rights reserved. + // Distributed under the BSD license. + // See qurl.cpp + // + + QTest::addColumn("string"); + QTest::addColumn("guessUrlFromString"); + + // Null + QTest::newRow("null") << QString() << QUrl(); + + // File + QDirIterator it(QDir::homePath()); + QString fileString; + int c = 0; + while (it.hasNext()) { + it.next(); + QTest::newRow(QString("file-%1").arg(c++).toLatin1()) << it.filePath() << QUrl::fromLocalFile(it.filePath()); + } + + // basic latin1 + QTest::newRow("unicode-0") << QString::fromUtf8("å.com/") << QUrl::fromEncoded(QString::fromUtf8("http://å.com/").toUtf8(), QUrl::TolerantMode); + // unicode + QTest::newRow("unicode-1") << QString::fromUtf8("?.com/") << QUrl::fromEncoded(QString::fromUtf8("http://?.com/").toUtf8(), QUrl::TolerantMode); + + // no scheme + QTest::newRow("add scheme-0") << "webkit.org" << QUrl("http://webkit.org"); + QTest::newRow("add scheme-1") << "www.webkit.org" << QUrl("http://www.webkit.org"); + QTest::newRow("add scheme-2") << "ftp.webkit.org" << QUrl("ftp://ftp.webkit.org"); + QTest::newRow("add scheme-3") << "webkit" << QUrl("webkit"); + + // QUrl's tolerant parser should already handle this + QTest::newRow("not-encoded-0") << "http://webkit.org/test page.html" << QUrl("http://webkit.org/test%20page.html"); + + // Make sure the :80, i.e. port doesn't screw anything up + QUrl portUrl("http://webkit.org"); + portUrl.setPort(80); + QTest::newRow("port-0") << "webkit.org:80" << portUrl; + QTest::newRow("port-1") << "http://webkit.org:80" << portUrl; + + // mailto doesn't have a ://, but is valid + QUrl mailto("ben@meyerhome.net"); + mailto.setScheme("mailto"); + QTest::newRow("mailto") << "mailto:ben@meyerhome.net" << mailto; + + // misc + QTest::newRow("localhost-0") << "localhost" << QUrl("http://localhost"); + QTest::newRow("localhost-1") << "localhost:80" << QUrl("http://localhost:80"); + QTest::newRow("spaces-0") << " http://webkit.org/test page.html " << QUrl("http://webkit.org/test%20page.html"); + + // FYI: The scheme in the resulting url user + QUrl authUrl("user:pass@domain.com"); + QTest::newRow("misc-1") << "user:pass@domain.com" << authUrl; } void tst_QUrl::fromUserInput() { + QFETCH(QString, string); + QFETCH(QUrl, guessUrlFromString); + + QUrl url = QUrl::fromUserInput(string); + QCOMPARE(url, guessUrlFromString); } void tst_QUrl::task_199967() -- cgit v0.12 From 6cede417422d8ff421a513d2d031e21fa6080c8c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Oct 2009 14:44:45 +0100 Subject: Autotest: use example.org and example.net No need to publicise real sites and email addresses. Also, don't use 8-bit data. C escape sequences are ok. --- tests/auto/qurl/tst_qurl.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 6424dcc..65ca878 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -3702,34 +3702,34 @@ void tst_QUrl::fromUserInput_data() } // basic latin1 - QTest::newRow("unicode-0") << QString::fromUtf8("å.com/") << QUrl::fromEncoded(QString::fromUtf8("http://å.com/").toUtf8(), QUrl::TolerantMode); + QTest::newRow("unicode-0") << QString::fromUtf8("\xc3\xa5.com/") << QUrl::fromEncoded(QString::fromUtf8("http://\xc3\xa5.com/").toUtf8(), QUrl::TolerantMode); // unicode - QTest::newRow("unicode-1") << QString::fromUtf8("?.com/") << QUrl::fromEncoded(QString::fromUtf8("http://?.com/").toUtf8(), QUrl::TolerantMode); + QTest::newRow("unicode-1") << QString::fromUtf8("\xce\xbb.com/") << QUrl::fromEncoded(QString::fromUtf8("http://\xce\xbb.com/").toUtf8(), QUrl::TolerantMode); // no scheme - QTest::newRow("add scheme-0") << "webkit.org" << QUrl("http://webkit.org"); - QTest::newRow("add scheme-1") << "www.webkit.org" << QUrl("http://www.webkit.org"); - QTest::newRow("add scheme-2") << "ftp.webkit.org" << QUrl("ftp://ftp.webkit.org"); + QTest::newRow("add scheme-0") << "example.org" << QUrl("http://example.org"); + QTest::newRow("add scheme-1") << "www.example.org" << QUrl("http://www.example.org"); + QTest::newRow("add scheme-2") << "ftp.example.org" << QUrl("ftp://ftp.example.org"); QTest::newRow("add scheme-3") << "webkit" << QUrl("webkit"); // QUrl's tolerant parser should already handle this - QTest::newRow("not-encoded-0") << "http://webkit.org/test page.html" << QUrl("http://webkit.org/test%20page.html"); + QTest::newRow("not-encoded-0") << "http://example.org/test page.html" << QUrl("http://example.org/test%20page.html"); // Make sure the :80, i.e. port doesn't screw anything up - QUrl portUrl("http://webkit.org"); + QUrl portUrl("http://example.org"); portUrl.setPort(80); - QTest::newRow("port-0") << "webkit.org:80" << portUrl; - QTest::newRow("port-1") << "http://webkit.org:80" << portUrl; + QTest::newRow("port-0") << "example.org:80" << portUrl; + QTest::newRow("port-1") << "http://example.org:80" << portUrl; // mailto doesn't have a ://, but is valid - QUrl mailto("ben@meyerhome.net"); + QUrl mailto("ben@example.net"); mailto.setScheme("mailto"); - QTest::newRow("mailto") << "mailto:ben@meyerhome.net" << mailto; + QTest::newRow("mailto") << "mailto:ben@example.net" << mailto; // misc QTest::newRow("localhost-0") << "localhost" << QUrl("http://localhost"); QTest::newRow("localhost-1") << "localhost:80" << QUrl("http://localhost:80"); - QTest::newRow("spaces-0") << " http://webkit.org/test page.html " << QUrl("http://webkit.org/test%20page.html"); + QTest::newRow("spaces-0") << " http://example.org/test page.html " << QUrl("http://example.org/test%20page.html"); // FYI: The scheme in the resulting url user QUrl authUrl("user:pass@domain.com"); -- cgit v0.12 From 22e4b3dfa9f8ee6a596ac6e0d02cb39f364ef27d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Oct 2009 14:48:10 +0100 Subject: Autotest: add one test that was in the previous implementation but missing here --- tests/auto/qurl/tst_qurl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 65ca878..87018d3 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -3730,6 +3730,7 @@ void tst_QUrl::fromUserInput_data() QTest::newRow("localhost-0") << "localhost" << QUrl("http://localhost"); QTest::newRow("localhost-1") << "localhost:80" << QUrl("http://localhost:80"); QTest::newRow("spaces-0") << " http://example.org/test page.html " << QUrl("http://example.org/test%20page.html"); + QTest::newRow("trash-0") << "example.org/test?someData=42%&someOtherData=abcde#anchor" << QUrl::fromEncoded("http://example.org/test?someData=42%25&someOtherData=abcde#anchor"); // FYI: The scheme in the resulting url user QUrl authUrl("user:pass@domain.com"); -- cgit v0.12 From cfd4156e0dd3f42e23596bba40a30f93f7cdd64b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Oct 2009 14:55:59 +0100 Subject: Autotest: add a few more tests for Unicode (IDN) support --- tests/auto/qurl/tst_qurl.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 87018d3..c8fe4e5 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -3694,7 +3694,6 @@ void tst_QUrl::fromUserInput_data() // File QDirIterator it(QDir::homePath()); - QString fileString; int c = 0; while (it.hasNext()) { it.next(); @@ -3703,8 +3702,12 @@ void tst_QUrl::fromUserInput_data() // basic latin1 QTest::newRow("unicode-0") << QString::fromUtf8("\xc3\xa5.com/") << QUrl::fromEncoded(QString::fromUtf8("http://\xc3\xa5.com/").toUtf8(), QUrl::TolerantMode); + QTest::newRow("unicode-0b") << QString::fromUtf8("\xc3\xa5.com/") << QUrl::fromEncoded("http://%C3%A5.com/", QUrl::TolerantMode); + QTest::newRow("unicode-0c") << QString::fromUtf8("\xc3\xa5.com/") << QUrl::fromEncoded("http://xn--5ca.com/", QUrl::TolerantMode); // unicode QTest::newRow("unicode-1") << QString::fromUtf8("\xce\xbb.com/") << QUrl::fromEncoded(QString::fromUtf8("http://\xce\xbb.com/").toUtf8(), QUrl::TolerantMode); + QTest::newRow("unicode-1b") << QString::fromUtf8("\xce\xbb.com/") << QUrl::fromEncoded("http://%CE%BB.com/", QUrl::TolerantMode); + QTest::newRow("unicode-1c") << QString::fromUtf8("\xce\xbb.com/") << QUrl::fromEncoded("http://xn--wxa.com/", QUrl::TolerantMode); // no scheme QTest::newRow("add scheme-0") << "example.org" << QUrl("http://example.org"); @@ -3713,7 +3716,7 @@ void tst_QUrl::fromUserInput_data() QTest::newRow("add scheme-3") << "webkit" << QUrl("webkit"); // QUrl's tolerant parser should already handle this - QTest::newRow("not-encoded-0") << "http://example.org/test page.html" << QUrl("http://example.org/test%20page.html"); + QTest::newRow("not-encoded-0") << "http://example.org/test page.html" << QUrl::fromEncoded("http://example.org/test%20page.html"); // Make sure the :80, i.e. port doesn't screw anything up QUrl portUrl("http://example.org"); -- cgit v0.12 From 94be7bf47fe93ca4fa6ae90f5906f6ef711f558e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Oct 2009 15:23:03 +0100 Subject: Compile fix until configure.exe is rebuilt for Windows --- src/corelib/global/qlibraryinfo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 15a06d7..32693e0 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -215,7 +215,8 @@ QLibraryInfo::buildKey() QDate QLibraryInfo::buildDate() { - return QDate::fromString(QString::fromLatin1(qt_configure_installation + 12), Qt::ISODate); + return QDate(); + //return QDate::fromString(QString::fromLatin1(qt_configure_installation + 12), Qt::ISODate); } /*! -- cgit v0.12 From 89ccbd14fe8c0e6b0fefcca2151da28d98088bf5 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 29 Oct 2009 16:48:38 +0100 Subject: do not crash --- .../linguist/lupdate/testdata/good/parsecpp/main.cpp | 19 +++++++++++++++++++ .../lupdate/testdata/good/parsecpp/project.ts.result | 8 ++++++++ tools/linguist/lupdate/cpp.cpp | 12 +++++++----- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp b/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp index 8201add..e243e66 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp @@ -228,3 +228,22 @@ QT_TRID_NOOP("this_a_id") //~ some thing //% "This needs to be here. Really." QString test = qtTrId("this_another_id", n); + + + +class YetAnotherTest : QObject { + Q_OBJECT + + int function(void) + { + // + //: + //= + //~ + //# + //============= + //~~~~~~~~~~~~~ + //::::::::::::: + tr("nothing"); + } +}; diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result index d63c7c3..26e5a65 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result @@ -278,6 +278,14 @@ backslashed \ stuff. + YetAnotherTest + + + nothing + + + + scope diff --git a/tools/linguist/lupdate/cpp.cpp b/tools/linguist/lupdate/cpp.cpp index 6374912..4d89156 100644 --- a/tools/linguist/lupdate/cpp.cpp +++ b/tools/linguist/lupdate/cpp.cpp @@ -1896,25 +1896,26 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) prospectiveContext.clear(); } break; - case Tok_Comment: + case Tok_Comment: { if (!tor) goto case_default; - if (yyWord.at(0) == QLatin1Char(':') && yyWord.at(1).isSpace()) { + const QChar *ptr = yyWord.unicode(); + if (*ptr == QLatin1Char(':') && ptr[1].isSpace()) { yyWord.remove(0, 2); extracomment += yyWord; extracomment.detach(); - } else if (yyWord.at(0) == QLatin1Char('=') && yyWord.at(1).isSpace()) { + } else if (*ptr == QLatin1Char('=') && ptr[1].isSpace()) { yyWord.remove(0, 2); msgid = yyWord.simplified(); msgid.detach(); - } else if (yyWord.at(0) == QLatin1Char('~') && yyWord.at(1).isSpace()) { + } else if (*ptr == QLatin1Char('~') && ptr[1].isSpace()) { yyWord.remove(0, 2); text = yyWord.trimmed(); int k = text.indexOf(QLatin1Char(' ')); if (k > -1) extra.insert(text.left(k), text.mid(k + 1).trimmed()); text.clear(); - } else if (yyWord.at(0) == QLatin1Char('%') && yyWord.at(1).isSpace()) { + } else if (*ptr == QLatin1Char('%') && ptr[1].isSpace()) { sourcetext.reserve(sourcetext.length() + yyWord.length() - 2); ushort *ptr = (ushort *)sourcetext.data() + sourcetext.length(); int p = 2, c; @@ -1977,6 +1978,7 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) } yyTok = getToken(); break; + } case Tok_Arrow: yyTok = getToken(); if (yyTok == Tok_tr || yyTok == Tok_trUtf8) -- cgit v0.12 From 5641bd0cdd9c90427d7d976473b894c530cdb715 Mon Sep 17 00:00:00 2001 From: kh1 Date: Thu, 29 Oct 2009 17:51:24 +0100 Subject: Fix wrong version number in Assistant internal help. Task-number: QT-1522 Reviewed-by: kh --- tools/assistant/tools/assistant/assistant.qch | Bin 368640 -> 364544 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tools/assistant/tools/assistant/assistant.qch b/tools/assistant/tools/assistant/assistant.qch index 3e66bd9..78fe9f3 100644 Binary files a/tools/assistant/tools/assistant/assistant.qch and b/tools/assistant/tools/assistant/assistant.qch differ -- cgit v0.12 From f5589e3b4d352b9b8d9fd54e974d548713e7b640 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 30 Oct 2009 13:37:18 +1000 Subject: Make it possible to set the OpenVG swap interval The QT_VG_SWAP_INTERVAL environment variable can be used to specify a value for eglSwapInterval(). Task-number: QT-2409 Reviewed-by: trustme --- src/openvg/qwindowsurface_vgegl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp index 103f84d..29d82c8 100644 --- a/src/openvg/qwindowsurface_vgegl.cpp +++ b/src/openvg/qwindowsurface_vgegl.cpp @@ -193,6 +193,13 @@ static QEglContext *createContext(QPaintDevice *device) return 0; } + // Set the swap interval for the display. + QByteArray interval = qgetenv("QT_VG_SWAP_INTERVAL"); + if (!interval.isEmpty()) + eglSwapInterval(context->display(), interval.toInt()); + else + eglSwapInterval(context->display(), 1); + // Choose an appropriate configuration for rendering into the device. QEglProperties configProps; configProps.setPaintDeviceFormat(device); -- cgit v0.12 From 2833d72c3d0e67317b9aba3de59f0e90317ecb12 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 30 Oct 2009 15:08:36 +1000 Subject: Remove drawCursorImage() from the OpenVG composition helper The drawCursorPixmap() function is more efficient and can render the QImage form of the QPixmap directly if necessary. Reviewed-by: trustme --- src/openvg/qpaintengine_vg.cpp | 69 ++++++++++++++++++------------------- src/openvg/qvgcompositionhelper_p.h | 1 - 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 94e0793..8a485a0 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -3574,51 +3574,48 @@ void QVGCompositionHelper::fillBackground } } -void QVGCompositionHelper::drawCursorImage - (const QImage& image, const QPoint& offset) +void QVGCompositionHelper::drawCursorPixmap + (const QPixmap& pixmap, const QPoint& offset) { - QImage img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + VGImage vgImage = VG_INVALID_HANDLE; - VGImage vgImg = vgCreateImage - (VG_sARGB_8888_PRE, img.width(), img.height(), - VG_IMAGE_QUALITY_FASTER); - vgImageSubData - (vgImg, img.bits() + img.bytesPerLine() * (img.height() - 1), - -(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0, - img.width(), img.height()); + // Fetch the VGImage from the pixmap if possible. + QPixmapData *pd = pixmap.pixmapData(); + if (pd->classId() == QPixmapData::OpenVGClass) { + QVGPixmapData *vgpd = static_cast(pd); + if (vgpd->isValid()) + vgImage = vgpd->toVGImage(); + } - QTransform transform; - int y = screenSize.height() - (offset.y() + img.height()); - transform.translate(offset.x() + 0.5f, y + 0.5f); + // Set the image transformation and modes. + VGfloat devh = screenSize.height() - 1; + QTransform transform(1.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + -0.5f, devh + 0.5f, 1.0f); + transform.translate(offset.x(), offset.y()); d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform); - d->setImageMode(VG_DRAW_IMAGE_NORMAL); - vgDrawImage(vgImg); - vgDestroyImage(vgImg); -} + // Draw the VGImage. + if (vgImage != VG_INVALID_HANDLE) { + vgDrawImage(vgImage); + } else { + QImage img = pixmap.toImage().convertToFormat + (QImage::Format_ARGB32_Premultiplied); -void QVGCompositionHelper::drawCursorPixmap - (const QPixmap& pixmap, const QPoint& offset) -{ - QPixmapData *pd = pixmap.pixmapData(); - if (pd->classId() == QPixmapData::OpenVGClass) { - QVGPixmapData *vgpd = static_cast(pd); - if (vgpd->isValid()) { - VGfloat devh = screenSize.height() - 1; - QTransform transform(1.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, - -0.5f, devh + 0.5f, 1.0f); - transform.translate(offset.x(), offset.y()); - d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform); - - d->setImageMode(VG_DRAW_IMAGE_NORMAL); - vgDrawImage(vgpd->toVGImage()); + vgImage = vgCreateImage + (VG_sARGB_8888_PRE, img.width(), img.height(), + VG_IMAGE_QUALITY_FASTER); + if (vgImage == VG_INVALID_HANDLE) return; - } - } + vgImageSubData + (vgImage, img.bits() + img.bytesPerLine() * (img.height() - 1), + -(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0, + img.width(), img.height()); - drawCursorImage(pixmap.toImage(), offset); + vgDrawImage(vgImage); + vgDestroyImage(vgImage); + } } void QVGCompositionHelper::setScissor(const QRegion& region) diff --git a/src/openvg/qvgcompositionhelper_p.h b/src/openvg/qvgcompositionhelper_p.h index 6317c3f..3afe31e 100644 --- a/src/openvg/qvgcompositionhelper_p.h +++ b/src/openvg/qvgcompositionhelper_p.h @@ -74,7 +74,6 @@ public: void blitWindow(QVGEGLWindowSurfacePrivate *surface, const QRect& rect, const QPoint& topLeft, int opacity); void fillBackground(const QRegion& region, const QBrush& brush); - void drawCursorImage(const QImage& image, const QPoint& offset); void drawCursorPixmap(const QPixmap& pixmap, const QPoint& offset); void setScissor(const QRegion& region); void clearScissor(); -- cgit v0.12 From a9f7e08ab08ce25413b85272526907f7347e6fe3 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 30 Oct 2009 15:13:18 +1000 Subject: OpenVG pixmap filter classes don't need to be exported. Reviewed-by: trustme --- src/openvg/qpixmapfilter_vg_p.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/openvg/qpixmapfilter_vg_p.h b/src/openvg/qpixmapfilter_vg_p.h index efbbc7b..29dd37e 100644 --- a/src/openvg/qpixmapfilter_vg_p.h +++ b/src/openvg/qpixmapfilter_vg_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE #if !defined(QT_SHIVAVG) -class Q_OPENVG_EXPORT QVGPixmapConvolutionFilter : public QPixmapConvolutionFilter +class QVGPixmapConvolutionFilter : public QPixmapConvolutionFilter { Q_OBJECT public: @@ -71,7 +71,7 @@ public: void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const; }; -class Q_OPENVG_EXPORT QVGPixmapColorizeFilter : public QPixmapColorizeFilter +class QVGPixmapColorizeFilter : public QPixmapColorizeFilter { Q_OBJECT public: @@ -81,7 +81,7 @@ public: void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const; }; -class Q_OPENVG_EXPORT QVGPixmapDropShadowFilter : public QPixmapDropShadowFilter +class QVGPixmapDropShadowFilter : public QPixmapDropShadowFilter { Q_OBJECT public: @@ -91,7 +91,7 @@ public: void draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src) const; }; -class Q_OPENVG_EXPORT QVGPixmapBlurFilter : public QPixmapBlurFilter +class QVGPixmapBlurFilter : public QPixmapBlurFilter { Q_OBJECT public: -- cgit v0.12 From 83fff2f970b9a7b41861336c7dca0eadbda28099 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 29 Oct 2009 15:28:02 +0100 Subject: Introduce internal StateType to avoid excessive qobject_casts The state machine algorithm frequently needs to know what type a state is, e.g. if it is atomic, final or a history state. We were using qobject_cast() to determine this, but that function is expensive. This commit introduces an internal StateType to be able to differentiate between the different types of state. This vastly improves performance. Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qabstractstate.cpp | 11 +++-- src/corelib/statemachine/qabstractstate_p.h | 12 ++++- src/corelib/statemachine/qfinalstate.cpp | 1 + src/corelib/statemachine/qhistorystate.cpp | 3 +- src/corelib/statemachine/qstate.cpp | 3 +- src/corelib/statemachine/qstatemachine.cpp | 68 +++++++++++++++++++++-------- src/corelib/statemachine/qstatemachine_p.h | 7 +++ 7 files changed, 80 insertions(+), 25 deletions(-) diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index cf67cdd..ec5332f 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -78,8 +78,8 @@ QT_BEGIN_NAMESPACE function to perform custom processing when the state is exited. */ -QAbstractStatePrivate::QAbstractStatePrivate() - : parentState(0) +QAbstractStatePrivate::QAbstractStatePrivate(StateType type) + : stateType(type), isMachine(false), parentState(0) { } @@ -88,6 +88,11 @@ QAbstractStatePrivate *QAbstractStatePrivate::get(QAbstractState *q) return q->d_func(); } +const QAbstractStatePrivate *QAbstractStatePrivate::get(const QAbstractState *q) +{ + return q->d_func(); +} + QStateMachine *QAbstractStatePrivate::machine() const { QObject *par = parent; @@ -127,7 +132,7 @@ void QAbstractStatePrivate::emitExited() Constructs a new state with the given \a parent state. */ QAbstractState::QAbstractState(QState *parent) - : QObject(*new QAbstractStatePrivate, parent) + : QObject(*new QAbstractStatePrivate(QAbstractStatePrivate::AbstractState), parent) { } diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index cd57815..faea6b6 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -65,9 +65,17 @@ class QAbstractStatePrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QAbstractState) public: - QAbstractStatePrivate(); + enum StateType { + AbstractState, + StandardState, + FinalState, + HistoryState + }; + + QAbstractStatePrivate(StateType type); static QAbstractStatePrivate *get(QAbstractState *q); + static const QAbstractStatePrivate *get(const QAbstractState *q); QStateMachine *machine() const; @@ -77,6 +85,8 @@ public: void emitEntered(); void emitExited(); + uint stateType:31; + uint isMachine:1; mutable QState *parentState; }; diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp index 761eee4..d900ddd 100644 --- a/src/corelib/statemachine/qfinalstate.cpp +++ b/src/corelib/statemachine/qfinalstate.cpp @@ -92,6 +92,7 @@ public: }; QFinalStatePrivate::QFinalStatePrivate() + : QAbstractStatePrivate(FinalState) { } diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp index 0c2b858..18436d3 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -120,7 +120,8 @@ QT_BEGIN_NAMESPACE */ QHistoryStatePrivate::QHistoryStatePrivate() - : defaultState(0), historyType(QHistoryState::ShallowHistory) + : QAbstractStatePrivate(HistoryState), + defaultState(0), historyType(QHistoryState::ShallowHistory) { } diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index bcd8364..5dc310b 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -124,7 +124,8 @@ QT_BEGIN_NAMESPACE */ QStatePrivate::QStatePrivate() - : errorState(0), initialState(0), childMode(QState::ExclusiveStates), + : QAbstractStatePrivate(StandardState), + errorState(0), initialState(0), childMode(QState::ExclusiveStates), childStatesListNeedsRefresh(true), transitionsListNeedsRefresh(true) { } diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 689967a..ea5587e 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -178,6 +178,8 @@ QT_BEGIN_NAMESPACE QStateMachinePrivate::QStateMachinePrivate() { + QAbstractStatePrivate::isMachine = true; + state = NotRunning; _startState = 0; processing = false; @@ -336,7 +338,7 @@ QSet QStateMachinePrivate::selectTransitions(QEvent *event if (isPreempted(state, enabledTransitions)) continue; QList lst = properAncestors(state, rootState()->parentState()); - if (QState *grp = qobject_cast(state)) + if (QState *grp = toStandardState(state)) lst.prepend(grp); bool found = false; for (int j = 0; (j < lst.size()) && !found; ++j) { @@ -414,7 +416,7 @@ QList QStateMachinePrivate::exitStates(QEvent *event, const QLi qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan); for (int i = 0; i < statesToExit_sorted.size(); ++i) { QAbstractState *s = statesToExit_sorted.at(i); - if (QState *grp = qobject_cast(s)) { + if (QState *grp = toStandardState(s)) { QList hlst = QStatePrivate::get(grp)->historyStates(); for (int j = 0; j < hlst.size(); ++j) { QHistoryState *h = hlst.at(j); @@ -563,7 +565,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, QSet &statesToEnter, QSet &statesForDefaultEntry) { - if (QHistoryState *h = qobject_cast(s)) { + if (QHistoryState *h = toHistoryState(s)) { QList hconf = QHistoryStatePrivate::get(h)->configuration; if (!hconf.isEmpty()) { for (int k = 0; k < hconf.size(); ++k) { @@ -600,7 +602,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, } statesToEnter.insert(s); if (isParallel(s)) { - QState *grp = qobject_cast(s); + QState *grp = toStandardState(s); QList lst = QStatePrivate::get(grp)->childStates(); for (int i = 0; i < lst.size(); ++i) { QAbstractState *child = lst.at(i); @@ -608,7 +610,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, } } else if (isCompound(s)) { statesForDefaultEntry.insert(s); - QState *grp = qobject_cast(s); + QState *grp = toStandardState(s); QAbstractState *initial = grp->initialState(); if (initial != 0) { Q_ASSERT(initial->machine() == q_func()); @@ -660,7 +662,7 @@ void QStateMachinePrivate::applyProperties(const QList &tr QHash > propertyAssignmentsForState; QHash pendingRestorables = registeredRestorables; for (int i = 0; i < enteredStates.size(); ++i) { - QState *s = qobject_cast(enteredStates.at(i)); + QState *s = toStandardState(enteredStates.at(i)); if (!s) continue; @@ -831,7 +833,7 @@ void QStateMachinePrivate::applyProperties(const QList &tr // Emit polished signal for entered states that have no animated properties. for (int i = 0; i < enteredStates.size(); ++i) { - QState *s = qobject_cast(enteredStates.at(i)); + QState *s = toStandardState(enteredStates.at(i)); if (s #ifndef QT_NO_ANIMATION && !animationsForState.contains(s) @@ -845,21 +847,21 @@ void QStateMachinePrivate::applyProperties(const QList &tr bool QStateMachinePrivate::isFinal(const QAbstractState *s) { - return qobject_cast(s) != 0; + return s && (QAbstractStatePrivate::get(s)->stateType == QAbstractStatePrivate::FinalState); } bool QStateMachinePrivate::isParallel(const QAbstractState *s) { - const QState *ss = qobject_cast(s); + const QState *ss = toStandardState(s); return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates); } bool QStateMachinePrivate::isCompound(const QAbstractState *s) const { - const QState *group = qobject_cast(s); + const QState *group = toStandardState(s); if (!group) return false; - bool isMachine = (qobject_cast(group) != 0); + bool isMachine = QStatePrivate::get(group)->isMachine; // Don't treat the machine as compound if it's a sub-state of this machine if (isMachine && (group != rootState())) return false; @@ -869,11 +871,11 @@ bool QStateMachinePrivate::isCompound(const QAbstractState *s) const bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const { - const QState *ss = qobject_cast(s); + const QState *ss = toStandardState(s); return (ss && QStatePrivate::get(ss)->childStates().isEmpty()) || isFinal(s) // Treat the machine as atomic if it's a sub-state of this machine - || (ss && (qobject_cast(ss) != 0) && (ss != rootState())); + || (ss && QStatePrivate::get(ss)->isMachine && (ss != rootState())); } @@ -897,10 +899,38 @@ QList QStateMachinePrivate::properAncestors(const QAbstractState *state return result; } +QState *QStateMachinePrivate::toStandardState(QAbstractState *state) +{ + if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState)) + return static_cast(state); + return 0; +} + +const QState *QStateMachinePrivate::toStandardState(const QAbstractState *state) +{ + if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState)) + return static_cast(state); + return 0; +} + +QFinalState *QStateMachinePrivate::toFinalState(QAbstractState *state) +{ + if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::FinalState)) + return static_cast(state); + return 0; +} + +QHistoryState *QStateMachinePrivate::toHistoryState(QAbstractState *state) +{ + if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::HistoryState)) + return static_cast(state); + return 0; +} + bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const { if (isCompound(s)) { - QState *grp = qobject_cast(s); + QState *grp = toStandardState(s); QList lst = QStatePrivate::get(grp)->childStates(); for (int i = 0; i < lst.size(); ++i) { QAbstractState *cs = lst.at(i); @@ -909,7 +939,7 @@ bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const } return false; } else if (isParallel(s)) { - QState *grp = qobject_cast(s); + QState *grp = toStandardState(s); QList lst = QStatePrivate::get(grp)->childStates(); for (int i = 0; i < lst.size(); ++i) { QAbstractState *cs = lst.at(i); @@ -975,7 +1005,7 @@ QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context) // Find error state recursively in parent hierarchy if not set explicitly for context state QAbstractState *errorState = 0; if (context != 0) { - QState *s = qobject_cast(context); + QState *s = toStandardState(context); if (s != 0) errorState = s->errorState(); @@ -1100,7 +1130,7 @@ void QStateMachinePrivate::_q_animationFinished() animations.removeOne(anim); if (animations.isEmpty()) { animationsForState.erase(it); - QStatePrivate::get(qobject_cast(state))->emitPolished(); + QStatePrivate::get(toStandardState(state))->emitPolished(); } } @@ -1388,7 +1418,7 @@ void QStateMachinePrivate::goToState(QAbstractState *targetState) if (state == Running) { QSet::const_iterator it; for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - sourceState = qobject_cast(*it); + sourceState = toStandardState(*it); if (sourceState != 0) break; } @@ -1412,7 +1442,7 @@ void QStateMachinePrivate::goToState(QAbstractState *targetState) void QStateMachinePrivate::registerTransitions(QAbstractState *state) { - QState *group = qobject_cast(state); + QState *group = toStandardState(state); if (!group) return; QList transitions = QStatePrivate::get(group)->transitions(); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 69b727d..01c9361 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -73,6 +73,8 @@ class QSignalEventGenerator; class QSignalTransition; class QAbstractState; class QAbstractTransition; +class QFinalState; +class QHistoryState; class QState; #ifndef QT_NO_ANIMATION @@ -138,6 +140,11 @@ public: const QList &exitedStates, const QList &enteredStates); + static QState *toStandardState(QAbstractState *state); + static const QState *toStandardState(const QAbstractState *state); + static QFinalState *toFinalState(QAbstractState *state); + static QHistoryState *toHistoryState(QAbstractState *state); + bool isInFinalState(QAbstractState *s) const; static bool isFinal(const QAbstractState *s); static bool isParallel(const QAbstractState *s); -- cgit v0.12 From 5e95f9c3c224b87840e750d4280806a40ed40c92 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Fri, 30 Oct 2009 12:21:25 +0100 Subject: Remove a paintBox call that should have been moved a few lines down, but was instead copied in commit ea13922 Reviewed-by: TrustMe --- src/gui/styles/qgtkstyle.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index d315c98..b8d3674 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -1933,9 +1933,6 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom QRect grooveRect = option->rect.adjusted(focusFrameMargin, outerSize + focusFrameMargin, -focusFrameMargin, -outerSize - focusFrameMargin); - gtkPainter.paintBox( scaleWidget, "trough", grooveRect, state, - GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); - gboolean trough_side_details = false; // Indicates if the upper or lower scale background differs if (!QGtk::gtk_check_version(2, 10, 0)) QGtk::gtk_widget_style_get((GtkWidget*)(scaleWidget), "trough-side-details", &trough_side_details, NULL); -- cgit v0.12