summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-02-05 21:28:41 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-02-05 21:28:41 (GMT)
commit941b13d52d975069d10093a873cd3a55bb2fd7dd (patch)
treebb66b6379a551808e76de8c936e03bc9432613f5 /src
parent777bf47da36292ffd37ae48a19796aafeb4d922e (diff)
parent2bc5d161e6820d459f00ac687ed99830a731cb74 (diff)
downloadQt-941b13d52d975069d10093a873cd3a55bb2fd7dd.zip
Qt-941b13d52d975069d10093a873cd3a55bb2fd7dd.tar.gz
Qt-941b13d52d975069d10093a873cd3a55bb2fd7dd.tar.bz2
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.6-integration
* '4.6' of scm.dev.nokia.troll.no:qt/oslo-staging-2: (49 commits) Fixed qt_x11_wait_for_window_manager Revert change 34f1758 on non-Synbian platforms Fixed QGifHandler::loopCount(). Fix tst_QAccessiblity failure. fix compile error when linuxinput keyboard driver is compiled as plugin Fixed the context menu test case in the qgraphicsscene autotest. fix regression from Qt 4.5 wrt missing text pixels in QTabBar Cleanup after "Changed qgraphicswidget autotest to use qWaitForWindowShown" Cleanup after "QGraphicsWidget is painted twice on the first show" Changed qgraphicswidget autotest to use qWaitForWindowShown. Improved QTest::qWaitForWindowShown on X11. Stabilize tst_QGraphicsWidget::initialShow2 (new test) Make sure we define S_IFDIR on Windows Fix copy/pasto Crash when closing any top-level widget on Symbian. Cache the sizes of the images in an animated GIF. Fix the QAbstractSlider autotest. Use OpenVG scissor on 90/180/270 rotations and simple clips. Optimize single-rect IntersectClip in OpenVG using the scissor QGraphicsWidget is painted twice on the first show. ...
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/phonon/ds9/videowidget.cpp3
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp3
-rw-r--r--src/gui/dialogs/qfiledialog.cpp3
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp5
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h10
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp32
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp1
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks.cpp20
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks_p.h23
-rw-r--r--src/gui/image/qpixmap.cpp12
-rw-r--r--src/gui/image/qpixmap_x11.cpp14
-rw-r--r--src/gui/image/qpixmapdata.cpp11
-rw-r--r--src/gui/image/qpixmapdata_p.h8
-rw-r--r--src/gui/kernel/qwidget.cpp14
-rw-r--r--src/gui/kernel/qwidget_x11.cpp77
-rw-r--r--src/gui/painting/qpainter.cpp4
-rw-r--r--src/gui/painting/qpathclipper.cpp6
-rw-r--r--src/gui/painting/qpathclipper_p.h2
-rw-r--r--src/gui/styles/qcommonstyle.cpp4
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp2
-rw-r--r--src/gui/text/qzip.cpp9
-rw-r--r--src/gui/text/qzipreader_p.h2
-rw-r--r--src/gui/text/qzipwriter_p.h2
-rw-r--r--src/gui/widgets/qabstractscrollarea.cpp11
-rw-r--r--src/gui/widgets/qabstractslider.cpp4
-rw-r--r--src/gui/widgets/qmainwindowlayout.cpp14
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp6
-rw-r--r--src/opengl/qgl.cpp31
-rw-r--r--src/opengl/qgl_p.h9
-rw-r--r--src/opengl/qglpixmapfilter.cpp22
-rw-r--r--src/openvg/qpaintengine_vg.cpp76
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp2
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp308
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.h3
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp24
-rw-r--r--src/plugins/imageformats/ico/qicohandler.h3
-rw-r--r--src/plugins/kbddrivers/linuxinput/main.cpp2
38 files changed, 619 insertions, 167 deletions
diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp
index 091be16..95423c6 100644
--- a/src/3rdparty/phonon/ds9/videowidget.cpp
+++ b/src/3rdparty/phonon/ds9/videowidget.cpp
@@ -218,6 +218,9 @@ namespace Phonon
if (toNative && m_noNativeRendererSupported)
return current; //no switch here
+ if (!mediaObject())
+ return current;
+
//firt we delete the renderer
//initialization of the widgets
for(int i = 0; i < FILTER_COUNT; ++i) {
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index dbf422e..36e4af9 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -1006,6 +1006,9 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
Returns the child of the model index that is stored in the given \a row and
\a column.
+ \note This function does not work for an invalid model index which is often
+ used as the root index.
+
\sa parent(), sibling()
*/
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 21650bb..089e04a 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -229,11 +229,10 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook
\value ReadOnly Indicates that the model is readonly.
\value HideNameFilterDetails Indicates if the is hidden or not.
- This value is obsolete and does nothing since Qt 4.5:
\value DontUseSheet In previous versions of Qt, the static
functions would create a sheet by default if the static function
- was given a parent. This is no longer supported in Qt 4.5, The
+ was given a parent. This is no longer supported and does nothing in Qt 4.5, The
static functions will always be an application modal dialog. If
you want to use sheets, use QFileDialog::open() instead.
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index ed36f87..b4e19d1 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -2569,6 +2569,7 @@ void QGraphicsItem::setOpacity(qreal opacity)
if (newOpacity == d_ptr->opacity)
return;
+ bool wasFullyTransparent = d_ptr->isOpacityNull();
d_ptr->opacity = newOpacity;
// Notify change.
@@ -2584,7 +2585,9 @@ void QGraphicsItem::setOpacity(qreal opacity)
d_ptr->scene->d_func()->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
/*force=*/false,
- /*ignoreOpacity=*/true);
+ /*ignoreOpacity=*/d_ptr->isOpacityNull());
+ if (wasFullyTransparent)
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
}
if (d_ptr->isObject)
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 5ad6cd5..b3ca3b5 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -358,14 +358,20 @@ public:
return o;
}
+ inline bool isOpacityNull() const
+ { return (opacity < qreal(0.001)); }
+
+ static inline bool isOpacityNull(qreal opacity)
+ { return (opacity < qreal(0.001)); }
+
inline bool isFullyTransparent() const
{
- if (opacity < 0.001)
+ if (isOpacityNull())
return true;
if (!parent)
return false;
- return calcEffectiveOpacity() < 0.001;
+ return isOpacityNull(calcEffectiveOpacity());
}
inline qreal effectiveOpacity() const {
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 54d47fa..66707fc 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -251,6 +251,7 @@
#endif
#include <private/qgraphicseffect_p.h>
#include <private/qgesturemanager_p.h>
+#include <private/qpathclipper_p.h>
// #define GESTURE_DEBUG
#ifndef GESTURE_DEBUG
@@ -372,7 +373,10 @@ void QGraphicsScenePrivate::_q_emitUpdated()
}
}
} else {
- updateAll = false;
+ if (views.isEmpty()) {
+ updateAll = false;
+ return;
+ }
for (int i = 0; i < views.size(); ++i)
views.at(i)->d_func()->processPendingUpdates();
// It's important that we update all views before we dispatch, hence two for-loops.
@@ -4603,6 +4607,7 @@ void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const
if (!unpolishedItems.isEmpty())
_q_polishItems();
+ updateAll = false;
QRectF exposedSceneRect;
if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
@@ -4630,7 +4635,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
return; // Item has neither contents nor children!(?)
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
return;
@@ -4750,7 +4755,7 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
qreal opacity, const QTransform *effectTransform,
bool wasDirtyParentSceneTransform, bool drawItem)
{
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
const bool itemHasChildren = !item->d_ptr->children.isEmpty();
@@ -4765,7 +4770,12 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
painter->setWorldTransform(*transformPtr * *effectTransform);
else
painter->setWorldTransform(*transformPtr);
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ QRectF clipRect;
+ const QPainterPath clipPath(item->shape());
+ if (QPathClipper::pathToRect(clipPath, &clipRect))
+ painter->setClipRect(clipRect, Qt::IntersectClip);
+ else
+ painter->setClipPath(clipPath, Qt::IntersectClip);
}
// Draw children behind
@@ -4801,8 +4811,14 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
painter->setWorldTransform(*transformPtr);
}
- if (itemClipsToShape)
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ if (itemClipsToShape) {
+ QRectF clipRect;
+ const QPainterPath clipPath(item->shape());
+ if (QPathClipper::pathToRect(clipPath, &clipRect))
+ painter->setClipRect(clipRect, Qt::IntersectClip);
+ else
+ painter->setClipPath(clipPath, Qt::IntersectClip);
+ }
painter->setOpacity(opacity);
if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
@@ -4980,7 +4996,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
}
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001;
+ const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
+ && QGraphicsItemPrivate::isOpacityNull(opacity);
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
resetDirtyItem(item, /*recursive=*/itemHasChildren);
return;
@@ -5153,6 +5170,7 @@ void QGraphicsScene::drawItems(QPainter *painter,
if (!d->unpolishedItems.isEmpty())
d->_q_polishItems();
+ d->updateAll = false;
QTransform viewTransform = painter->worldTransform();
Q_UNUSED(options);
diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp
index 043c4eb..707c71f 100644
--- a/src/gui/graphicsview/qgraphicssceneindex.cpp
+++ b/src/gui/graphicsview/qgraphicssceneindex.cpp
@@ -279,7 +279,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
return;
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
const bool itemHasChildren = !item->d_ptr->children.isEmpty();
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
return;
@@ -554,7 +554,7 @@ QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &
/*!
\fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const
-
+
This pure virtual function all items in the index and sort them using
\a order.
*/
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 451f183..96b9373 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -2748,7 +2748,6 @@ bool QGraphicsView::viewportEvent(QEvent *event)
}
}
}
- d->scene->d_func()->updateAll = false;
}
break;
case QEvent::TouchBegin:
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
index 61d538f..ace4bb6 100644
--- a/src/gui/image/qimagepixmapcleanuphooks.cpp
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -62,12 +62,12 @@ QImagePixmapCleanupHooks *QImagePixmapCleanupHooks::instance()
return qt_image_and_pixmap_cleanup_hooks();
}
-void QImagePixmapCleanupHooks::addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapModificationHooks.append(hook);
}
-void QImagePixmapCleanupHooks::addPixmapDestructionHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapDestructionHooks.append(hook);
}
@@ -78,12 +78,12 @@ void QImagePixmapCleanupHooks::addImageHook(_qt_image_cleanup_hook_64 hook)
imageHooks.append(hook);
}
-void QImagePixmapCleanupHooks::removePixmapModificationHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapModificationHooks.removeAll(hook);
}
-void QImagePixmapCleanupHooks::removePixmapDestructionHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapDestructionHooks.removeAll(hook);
}
@@ -93,24 +93,24 @@ void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook)
imageHooks.removeAll(hook);
}
-void QImagePixmapCleanupHooks::executePixmapModificationHooks(QPixmap* pm)
+void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
for (int i = 0; i < h->pixmapModificationHooks.count(); ++i)
- h->pixmapModificationHooks[i](pm);
+ h->pixmapModificationHooks[i](pmd);
if (qt_pixmap_cleanup_hook_64)
- qt_pixmap_cleanup_hook_64(pm->cacheKey());
+ qt_pixmap_cleanup_hook_64(pmd->cacheKey());
}
-void QImagePixmapCleanupHooks::executePixmapDestructionHooks(QPixmap* pm)
+void QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i)
- h->pixmapDestructionHooks[i](pm);
+ h->pixmapDestructionHooks[i](pmd);
if (qt_pixmap_cleanup_hook_64)
- qt_pixmap_cleanup_hook_64(pm->cacheKey());
+ qt_pixmap_cleanup_hook_64(pmd->cacheKey());
}
void QImagePixmapCleanupHooks::executeImageHooks(qint64 key)
diff --git a/src/gui/image/qimagepixmapcleanuphooks_p.h b/src/gui/image/qimagepixmapcleanuphooks_p.h
index 7176044..88dd3a6 100644
--- a/src/gui/image/qimagepixmapcleanuphooks_p.h
+++ b/src/gui/image/qimagepixmapcleanuphooks_p.h
@@ -58,7 +58,8 @@
QT_BEGIN_NAMESPACE
typedef void (*_qt_image_cleanup_hook_64)(qint64);
-typedef void (*_qt_pixmap_cleanup_hook_pm)(QPixmap*);
+typedef void (*_qt_pixmap_cleanup_hook_pmd)(QPixmapData*);
+
class QImagePixmapCleanupHooks;
@@ -71,27 +72,27 @@ public:
static void enableCleanupHooks(const QPixmap &pixmap);
static void enableCleanupHooks(QPixmapData *pixmapData);
- // Gets called when a pixmap is about to be modified:
- void addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm);
+ // Gets called when a pixmap data is about to be modified:
+ void addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd);
- // Gets called when a pixmap is about to be destroyed:
- void addPixmapDestructionHook(_qt_pixmap_cleanup_hook_pm);
+ // Gets called when a pixmap data is about to be destroyed:
+ void addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd);
// Gets called when an image is about to be modified or destroyed:
void addImageHook(_qt_image_cleanup_hook_64);
- void removePixmapModificationHook(_qt_pixmap_cleanup_hook_pm);
- void removePixmapDestructionHook(_qt_pixmap_cleanup_hook_pm);
+ void removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd);
+ void removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd);
void removeImageHook(_qt_image_cleanup_hook_64);
- static void executePixmapModificationHooks(QPixmap*);
- static void executePixmapDestructionHooks(QPixmap*);
+ static void executePixmapDataModificationHooks(QPixmapData*);
+ static void executePixmapDataDestructionHooks(QPixmapData*);
static void executeImageHooks(qint64 key);
private:
QList<_qt_image_cleanup_hook_64> imageHooks;
- QList<_qt_pixmap_cleanup_hook_pm> pixmapModificationHooks;
- QList<_qt_pixmap_cleanup_hook_pm> pixmapDestructionHooks;
+ QList<_qt_pixmap_cleanup_hook_pmd> pixmapModificationHooks;
+ QList<_qt_pixmap_cleanup_hook_pmd> pixmapDestructionHooks;
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index f823fdc..d1e5c40 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -320,8 +320,6 @@ QPixmap::QPixmap(const char * const xpm[])
QPixmap::~QPixmap()
{
Q_ASSERT(!data || data->ref >= 1); // Catch if ref-counting changes again
- if (data && data->is_cached && data->ref == 1) // ref will be decrememnted after destructor returns
- QImagePixmapCleanupHooks::executePixmapDestructionHooks(this);
}
/*!
@@ -1025,12 +1023,8 @@ qint64 QPixmap::cacheKey() const
if (isNull())
return 0;
- int classKey = data->classId();
- if (classKey >= 1024)
- classKey = -(classKey >> 10);
- return ((((qint64) classKey) << 56)
- | (((qint64) data->serialNumber()) << 32)
- | ((qint64) (data->detach_no)));
+ Q_ASSERT(data);
+ return data->cacheKey();
}
static void sendResizeEvents(QWidget *target)
@@ -1943,7 +1937,7 @@ void QPixmap::detach()
}
if (data->is_cached && data->ref == 1)
- QImagePixmapCleanupHooks::executePixmapModificationHooks(this);
+ QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data());
#if defined(Q_WS_MAC)
QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 0e66e09..e1e8a0d 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -68,6 +68,7 @@
#include "qx11info_x11.h"
#include <private/qdrawhelper_p.h>
#include <private/qimage_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
#include <stdlib.h>
@@ -1228,6 +1229,12 @@ void QX11PixmapData::fill(const QColor &fillColor)
QX11PixmapData::~QX11PixmapData()
{
+ // Cleanup hooks have to be called before the handles are freed
+ if (is_cached) {
+ QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
+ is_cached = false;
+ }
+
release();
}
@@ -1236,8 +1243,13 @@ void QX11PixmapData::release()
delete pengine;
pengine = 0;
- if (!X11)
+ if (!X11) {
+#ifndef QT_NO_DEBUG
+ qWarning("~QX11PixmapData(): QPixmap objects must be destroyed before the QApplication"
+ " object, otherwise the native pixmap object will be leaked.");
+#endif
return;
+ }
if (x11_mask) {
#ifndef QT_NO_XRENDER
diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp
index 65032da..ea4fe6b 100644
--- a/src/gui/image/qpixmapdata.cpp
+++ b/src/gui/image/qpixmapdata.cpp
@@ -45,6 +45,7 @@
#include <QtGui/qimagereader.h>
#include <private/qgraphicssystem_p.h>
#include <private/qapplication_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
QT_BEGIN_NAMESPACE
@@ -80,6 +81,16 @@ QPixmapData::QPixmapData(PixelType pixelType, int objectId)
QPixmapData::~QPixmapData()
{
+ // Sometimes the pixmap cleanup hooks will be called from derrived classes, which will
+ // then set is_cached to false. For example, on X11 QtOpenGL needs to delete the GLXPixmap
+ // or EGL Pixmap Surface for a given pixmap _before_ the native X11 pixmap is deleted,
+ // otherwise some drivers will leak the GL surface. In this case, QX11PixmapData will
+ // call the cleanup hooks itself before deleting the native pixmap and set is_cached to
+ // false.
+ if (is_cached) {
+ QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
+ is_cached = false;
+ }
}
QPixmapData *QPixmapData::createCompatiblePixmapData() const
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 1125515..827fa18 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -117,6 +117,14 @@ public:
inline int colorCount() const { return metric(QPaintDevice::PdmNumColors); }
inline int depth() const { return d; }
inline bool isNull() const { return is_null; }
+ inline qint64 cacheKey() const {
+ int classKey = id;
+ if (classKey >= 1024)
+ classKey = -(classKey >> 10);
+ return ((((qint64) classKey) << 56)
+ | (((qint64) ser_no) << 32)
+ | ((qint64) detach_no));
+ }
#if defined(Q_OS_SYMBIAN)
virtual void* toNativeType(NativeType type);
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 78a25ac..c072d9d 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1439,6 +1439,18 @@ QWidget::~QWidget()
}
#endif
+#ifdef Q_OS_SYMBIAN
+ if (d->extra && d->extra->topextra && d->extra->topextra->backingStore) {
+ // Okay, we are about to destroy the top-level window that owns
+ // the backing store. Make sure we delete the backing store right away
+ // before the window handle is invalid. This is important because
+ // the backing store will delete its window surface, which may or may
+ // not have a reference to this widget that will be used later to
+ // notify the window it no longer has a surface.
+ delete d->extra->topextra->backingStore;
+ d->extra->topextra->backingStore = 0;
+ }
+#endif
if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
bs->removeDirtyWidget(this);
if (testAttribute(Qt::WA_StaticContents))
@@ -6427,6 +6439,8 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
first = fp;
}
+ if (fp == second)
+ return;
if (QWidget *sp = second->focusProxy())
second = sp;
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 4684bc1..10fb009 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -346,11 +346,6 @@ Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
qt_x11_enforce_cursor(w, false);
}
-static Bool checkForConfigureAndExpose(Display *, XEvent *e, XPointer)
-{
- return e->type == ConfigureNotify || e->type == Expose;
-}
-
Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
{
if (!w || (!w->isWindow() && !w->internalWinId()))
@@ -363,38 +358,60 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
if (!w->testAttribute(Qt::WA_WState_Created))
return;
- if (!(w->windowFlags() & Qt::X11BypassWindowManagerHint)) {
- // if the window is not override-redirect, then the window manager
- // will reparent us to the frame decoration window.
- while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ReparentNotify, &ev)) {
- if (t.elapsed() > maximumWaitTime)
- return;
- qApp->syncX(); // non-busy wait
- }
- }
+ WId winid = w->internalWinId();
- while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), MapNotify, &ev)) {
- if (t.elapsed() > maximumWaitTime)
- return;
- qApp->syncX(); // non-busy wait
- }
+ // first deliver events that are already in the local queue
+ QApplication::sendPostedEvents();
- qApp->x11ProcessEvent(&ev);
+ // the normal sequence is:
+ // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose
+ // with X11BypassWindowManagerHint:
+ // ConfigureNotify ... MapNotify ... Expose
- // ok, seems like the window manager successfully reparented us, we'll wait
- // for the first paint event to arrive, while handling ConfigureNotify in
- // the arrival order
- while(1)
- {
- if (XCheckIfEvent(X11->display, &ev, checkForConfigureAndExpose, 0)) {
+ enum State {
+ Initial, Reparented, Mapped
+ } state = Initial;
+
+ do {
+ if (XEventsQueued(X11->display, QueuedAlready)) {
+ XNextEvent(X11->display, &ev);
qApp->x11ProcessEvent(&ev);
- if (ev.type == Expose)
- return;
+
+ if (w->windowFlags() & Qt::X11BypassWindowManagerHint) {
+ switch (state) {
+ case Initial:
+ case Reparented:
+ if (ev.type == MapNotify && ev.xany.window == winid)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose && ev.xany.window == winid)
+ return;
+ break;
+ }
+ } else {
+ switch (state) {
+ case Initial:
+ if (ev.type == ReparentNotify && ev.xany.window == winid)
+ state = Reparented;
+ break;
+ case Reparented:
+ if (ev.type == MapNotify && ev.xany.window == winid)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose && ev.xany.window == winid)
+ return;
+ break;
+ }
+ }
+ } else {
+ if (!XEventsQueued(X11->display, QueuedAfterFlush))
+ qApp->syncX(); // non-busy wait
}
if (t.elapsed() > maximumWaitTime)
return;
- qApp->syncX(); // non-busy wait
- }
+ } while(1);
}
void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index cde6a2d..bf12c6b 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -7509,7 +7509,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
return widgetPrivate->redirected(offset);
}
- if (*globalRedirectionAtomic() == 0)
+ if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
return 0;
QMutexLocker locker(globalRedirectionsMutex());
@@ -7529,7 +7529,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
void qt_painter_removePaintDevice(QPaintDevice *dev)
{
- if (*globalRedirectionAtomic() == 0)
+ if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
return;
QMutex *mutex = 0;
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 7997e77..bc81514 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -90,8 +90,6 @@ static QPointF normalize(const QPointF &p)
return p / qSqrt(p.x() * p.x() + p.y() * p.y());
}
-static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
-
struct QIntersection
{
qreal alphaA;
@@ -1660,7 +1658,7 @@ static bool fuzzyCompare(qreal a, qreal b)
return qFuzzyCompare(a, b);
}
-static bool pathToRect(const QPainterPath &path, QRectF *rect)
+bool QPathClipper::pathToRect(const QPainterPath &path, QRectF *rect)
{
if (path.elementCount() != 5)
return false;
@@ -1693,7 +1691,7 @@ static bool pathToRect(const QPainterPath &path, QRectF *rect)
return false;
if (rect)
- *rect = QRectF(QPointF(x1, y1), QPointF(x2, y2));
+ rect->setCoords(x1, y1, x2, y2);
return true;
}
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index 0d2c049..b900862 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -86,6 +86,8 @@ public:
bool intersect();
bool contains();
+ static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
+
private:
Q_DISABLE_COPY(QPathClipper)
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index 74d3ec3..b1924e7 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -1149,10 +1149,10 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget
int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2;
if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth)
verticalShift = -verticalShift;
- tr.adjust(hpadding, vpadding, horizontalShift - hpadding, verticalShift - vpadding);
+ tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding);
bool selected = opt->state & QStyle::State_Selected;
if (selected) {
- tr.setBottom(tr.bottom() - verticalShift);
+ tr.setTop(tr.top() - verticalShift);
tr.setRight(tr.right() - horizontalShift);
}
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index 498313b..b36294a 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -1125,6 +1125,7 @@ void QRenderRule::fixupBorder(int nativeWidth)
void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
{
+ setClip(p, rect);
static const Qt::TileRule tileMode2TileRule[] = {
Qt::StretchTile, Qt::RoundTile, Qt::StretchTile, Qt::RepeatTile, Qt::StretchTile };
@@ -1142,6 +1143,7 @@ void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
QRect(QPoint(), borderImageData->pixmap.size()), sourceMargins,
QTileRules(tileMode2TileRule[borderImageData->horizStretch], tileMode2TileRule[borderImageData->vertStretch]));
p->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothPixmapTransform);
+ unsetClip(p);
}
QRect QRenderRule::originRect(const QRect &rect, Origin origin) const
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index 2fc1940..d30c996 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -54,10 +54,13 @@
#include <zlib.h>
#if defined(Q_OS_WIN)
-#undef S_IFREG
-#define S_IFREG 0100000
+# undef S_IFREG
+# define S_IFREG 0100000
+# ifndef S_IFDIR
+# define S_IFDIR 0040000
+# endif
# ifndef S_ISDIR
-# define S_ISDIR(x) ((x) & 0040000) > 0
+# define S_ISDIR(x) ((x) & S_IFDIR) > 0
# endif
# ifndef S_ISREG
# define S_ISREG(x) ((x) & 0170000) == S_IFREG
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
index 1086464..67a2ace 100644
--- a/src/gui/text/qzipreader_p.h
+++ b/src/gui/text/qzipreader_p.h
@@ -49,7 +49,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
+// of the QZipReader class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h
index 7b97937..9322f4a 100644
--- a/src/gui/text/qzipwriter_p.h
+++ b/src/gui/text/qzipwriter_p.h
@@ -47,7 +47,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
+// of the QZipWriter class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index 87f6c83..1d496d5 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -1134,13 +1134,10 @@ void QAbstractScrollArea::mouseMoveEvent(QMouseEvent *e)
void QAbstractScrollArea::wheelEvent(QWheelEvent *e)
{
Q_D(QAbstractScrollArea);
- QScrollBar *const bars[2] = { d->hbar, d->vbar };
- int idx = (e->orientation() == Qt::Vertical) ? 1 : 0;
- int other = (idx + 1) % 2;
- if (!bars[idx]->isVisible() && bars[other]->isVisible())
- idx = other; // If the scrollbar of the event orientation is hidden, fallback to the other.
-
- QApplication::sendEvent(bars[idx], e);
+ if (static_cast<QWheelEvent*>(e)->orientation() == Qt::Horizontal)
+ QApplication::sendEvent(d->hbar, e);
+ else
+ QApplication::sendEvent(d->vbar, e);
}
#endif
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 2874647..defebb9 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -214,8 +214,8 @@ QT_BEGIN_NAMESPACE
*/
QAbstractSliderPrivate::QAbstractSliderPrivate()
- : minimum(0), maximum(99), singleStep(1), pageStep(10),
- value(0), position(0), pressValue(-1), offset_accumulated(0), tracking(true),
+ : minimum(0), maximum(99), pageStep(10), value(0), position(0), pressValue(-1),
+ singleStep(1), offset_accumulated(0), tracking(true),
blocktracking(false), pressed(false),
invertedAppearance(false), invertedControls(false),
orientation(Qt::Horizontal), repeatAction(QAbstractSlider::SliderNoAction)
diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp
index d1e7285..fc75c92 100644
--- a/src/gui/widgets/qmainwindowlayout.cpp
+++ b/src/gui/widgets/qmainwindowlayout.cpp
@@ -1627,6 +1627,13 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
tb->d_func()->plug(currentGapRect);
#endif
+ savedState.clear();
+ currentGapPos.clear();
+ pluggingWidget = 0;
+ //applying the state will make sure that the currentGap is updated correctly
+ //and all the geometries (especially the one from the central widget) is correct
+ layoutState.apply(false);
+
#ifndef QT_NO_DOCKWIDGET
#ifndef QT_NO_TABBAR
if (qobject_cast<QDockWidget*>(widget) != 0) {
@@ -1637,13 +1644,6 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
}
#endif
#endif
-
- savedState.clear();
- currentGapPos.clear();
- pluggingWidget = 0;
- //applying the state will make sure that the currentGap is updated correctly
- //and all the geometries (especially the one from the central widget) is correct
- layoutState.apply(false);
}
if (!widgetAnimator.animating()) {
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index b282676..07f3159 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -558,6 +558,12 @@ void QGL2PaintEngineExPrivate::resetGLState()
glStencilMask(0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, 0xff);
+ glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_OPACITY_ATTR);
+#ifndef QT_OPENGL_ES_2
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // color may have been changed by glVertexAttrib()
+#endif
}
void QGL2PaintEngineEx::endNativePainting()
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 2a60708..fce9fdb 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -1590,10 +1590,8 @@ QGLTextureCache::QGLTextureCache()
Q_ASSERT(qt_gl_texture_cache == 0);
qt_gl_texture_cache = this;
- QImagePixmapCleanupHooks::instance()->addPixmapModificationHook(cleanupTextures);
-#ifdef Q_WS_X11
- QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(cleanupPixmapSurfaces);
-#endif
+ QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTextures);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction);
QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook);
}
@@ -1601,10 +1599,8 @@ QGLTextureCache::~QGLTextureCache()
{
qt_gl_texture_cache = 0;
- QImagePixmapCleanupHooks::instance()->removePixmapModificationHook(cleanupTextures);
-#ifdef Q_WS_X11
- QImagePixmapCleanupHooks::instance()->removePixmapDestructionHook(cleanupPixmapSurfaces);
-#endif
+ QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTextures);
+ QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook);
}
@@ -1672,30 +1668,29 @@ void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
}
-void QGLTextureCache::cleanupTextures(QPixmap* pixmap)
+void QGLTextureCache::cleanupTextures(QPixmapData* pmd)
{
// ### remove when the GL texture cache becomes thread-safe
if (qApp->thread() == QThread::currentThread()) {
- const qint64 cacheKey = pixmap->cacheKey();
+ const qint64 cacheKey = pmd->cacheKey();
QGLTexture *texture = instance()->getTexture(cacheKey);
if (texture && texture->options & QGLContext::MemoryManagedBindOption)
instance()->remove(cacheKey);
}
}
-#if defined(Q_WS_X11)
-void QGLTextureCache::cleanupPixmapSurfaces(QPixmap* pixmap)
+void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd)
{
// Remove any bound textures first:
- cleanupTextures(pixmap);
+ cleanupTextures(pmd);
- QPixmapData *pd = pixmap->data_ptr().data();
- if (pd->classId() == QPixmapData::X11Class) {
- Q_ASSERT(pd->ref == 1); // Make sure reference counting isn't broken
- QGLContextPrivate::destroyGlSurfaceForPixmap(pd);
+#if defined(Q_WS_X11)
+ if (pmd->classId() == QPixmapData::X11Class) {
+ Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken
+ QGLContextPrivate::destroyGlSurfaceForPixmap(pmd);
}
-}
#endif
+}
void QGLTextureCache::deleteIfEmpty()
{
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 0104f07..713b067 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -522,7 +522,7 @@ public:
QSize bindCompressedTexturePVR(const char *buf, int len);
};
-class QGLTextureCache {
+class Q_AUTOTEST_EXPORT QGLTextureCache {
public:
QGLTextureCache();
~QGLTextureCache();
@@ -539,11 +539,8 @@ public:
static QGLTextureCache *instance();
static void deleteIfEmpty();
static void imageCleanupHook(qint64 cacheKey);
- static void cleanupTextures(QPixmap* pixmap);
-#ifdef Q_WS_X11
- // X11 needs to catch pixmap data destruction to delete EGL/GLX pixmap surfaces
- static void cleanupPixmapSurfaces(QPixmap* pixmap);
-#endif
+ static void cleanupTextures(QPixmapData* pixmap);
+ static void cleanupBeforePixmapDestruction(QPixmapData* pixmap);
private:
QCache<qint64, QGLTexture> m_cache;
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index 11011ee..37bb7c0 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -319,14 +319,14 @@ public:
~QGLBlurTextureCache();
QGLBlurTextureInfo *takeBlurTextureInfo(const QPixmap &pixmap);
- bool hasBlurTextureInfo(const QPixmap &pixmap) const;
+ bool hasBlurTextureInfo(quint64 cacheKey) const;
void insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info);
- void clearBlurTextureInfo(const QPixmap &pixmap);
+ void clearBlurTextureInfo(quint64 cacheKey);
void timerEvent(QTimerEvent *event);
private:
- static void pixmapDestroyed(QPixmap *pixmap);
+ static void pixmapDestroyed(QPixmapData *pixmap);
QCache<quint64, QGLBlurTextureInfo > cache;
@@ -379,21 +379,21 @@ QGLBlurTextureInfo *QGLBlurTextureCache::takeBlurTextureInfo(const QPixmap &pixm
return cache.take(pixmap.cacheKey());
}
-void QGLBlurTextureCache::clearBlurTextureInfo(const QPixmap &pixmap)
+void QGLBlurTextureCache::clearBlurTextureInfo(quint64 cacheKey)
{
- cache.remove(pixmap.cacheKey());
+ cache.remove(cacheKey);
}
-bool QGLBlurTextureCache::hasBlurTextureInfo(const QPixmap &pixmap) const
+bool QGLBlurTextureCache::hasBlurTextureInfo(quint64 cacheKey) const
{
- return cache.contains(pixmap.cacheKey());
+ return cache.contains(cacheKey);
}
void QGLBlurTextureCache::insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info)
{
static bool hookAdded = false;
if (!hookAdded) {
- QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(pixmapDestroyed);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(pixmapDestroyed);
hookAdded = true;
}
@@ -406,11 +406,11 @@ void QGLBlurTextureCache::insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTe
timerId = startTimer(8000);
}
-void QGLBlurTextureCache::pixmapDestroyed(QPixmap *pixmap)
+void QGLBlurTextureCache::pixmapDestroyed(QPixmapData *pmd)
{
foreach (QGLBlurTextureCache *cache, blurTextureCaches) {
- if (cache->hasBlurTextureInfo(*pixmap))
- cache->clearBlurTextureInfo(*pixmap);
+ if (cache->hasBlurTextureInfo(pmd->cacheKey()))
+ cache->clearBlurTextureInfo(pmd->cacheKey());
}
}
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index cc9ba77..6813d2f 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -188,6 +188,7 @@ public:
bool maskValid; // True if vgMask() contains valid data.
bool maskIsSet; // True if mask would be fully set if it was valid.
+ bool scissorMask; // True if scissor is used in place of the mask.
bool rawVG; // True if processing a raw VG escape.
QRect maskRect; // Rectangle version of mask if it is simple.
@@ -355,6 +356,7 @@ void QVGPaintEnginePrivate::init()
maskValid = false;
maskIsSet = false;
+ scissorMask = false;
rawVG = false;
scissorActive = false;
@@ -1542,7 +1544,28 @@ void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline bool clipTransformIsSimple(const QTransform& transform)
{
QTransform::TransformationType type = transform.type();
- return (type == QTransform::TxNone || type == QTransform::TxTranslate);
+ if (type == QTransform::TxNone || type == QTransform::TxTranslate)
+ return true;
+ if (type == QTransform::TxRotate) {
+ // Check for 0, 90, 180, and 270 degree rotations.
+ // (0 might happen after 4 rotations of 90 degrees).
+ qreal m11 = transform.m11();
+ qreal m12 = transform.m12();
+ qreal m21 = transform.m21();
+ qreal m22 = transform.m22();
+ if (m11 == 0.0f && m22 == 0.0f) {
+ if (m12 == 1.0f && m21 == -1.0f)
+ return true; // 90 degrees.
+ else if (m12 == -1.0f && m21 == 1.0f)
+ return true; // 270 degrees.
+ } else if (m12 == 0.0f && m21 == 0.0f) {
+ if (m11 == -1.0f && m22 == -1.0f)
+ return true; // 180 degrees.
+ else if (m11 == 1.0f && m22 == 1.0f)
+ return true; // 0 degrees.
+ }
+ }
+ return false;
}
#if defined(QVG_SCISSOR_CLIP)
@@ -1664,12 +1687,12 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
if (op == Qt::NoClip) {
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
return;
}
-#if defined(QVG_NO_RENDER_TO_MASK)
// We don't have vgRenderToMask(), so handle simple QRectF's only.
if (path.shape() == QVectorPath::RectangleHint &&
path.elementCount() == 4 && clipTransformIsSimple(d->transform)) {
@@ -1679,8 +1702,10 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
QRectF rect(points[0], points[1], points[2] - points[0],
points[5] - points[1]);
clip(rect.toRect(), op);
+ return;
}
-#else
+
+#if !defined(QVG_NO_RENDER_TO_MASK)
QPaintDevice *pdev = paintDevice();
int width = pdev->width();
int height = pdev->height();
@@ -1711,6 +1736,7 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_TRUE);
d->maskValid = true;
d->maskIsSet = false;
+ d->scissorMask = false;
#endif
}
@@ -1731,6 +1757,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
{
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
}
@@ -1746,6 +1773,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
// Special case: if the intersection of the system
@@ -1763,6 +1791,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
if (clip.rectCount() != 1) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
d->modifyMask(this, VG_FILL_MASK, r);
break;
@@ -1771,6 +1800,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
}
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = true;
d->maskRect = clipRect;
vgSeti(VG_MASKING, VG_FALSE);
updateScissor();
@@ -1781,13 +1811,30 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
case Qt::IntersectClip:
{
QRect r = d->transform.mapRect(rect);
- if (d->maskIsSet && isDefaultClipRect(r)) {
+ if (!d->maskValid) {
+ // Mask has not been used yet, so intersect with
+ // the previous scissor-based region in maskRect.
+ if (d->scissorMask)
+ r = r.intersect(d->maskRect);
+ if (isDefaultClipRect(r)) {
+ // The clip is the full window, so turn off clipping.
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ } else {
+ // Activate the scissor on a smaller maskRect.
+ d->maskIsSet = false;
+ d->maskRect = r;
+ }
+ d->scissorMask = true;
+ updateScissor();
+ } else if (d->maskIsSet && isDefaultClipRect(r)) {
// Intersecting a full-window clip with a full-window
// region is the same as turning off clipping.
if (d->maskValid)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
d->modifyMask(this, VG_INTERSECT_MASK, r);
@@ -1829,6 +1876,7 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
{
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
}
@@ -1844,6 +1892,7 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
// Special case: if the intersection of the system
@@ -1857,12 +1906,14 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
if (clip.rectCount() == 1) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = true;
d->maskRect = clip.boundingRect();
vgSeti(VG_MASKING, VG_FALSE);
updateScissor();
} else {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
d->modifyMask(this, VG_FILL_MASK, r);
}
@@ -1887,6 +1938,7 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
d->modifyMask(this, VG_INTERSECT_MASK, r);
@@ -1965,6 +2017,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
if (op == Qt::NoClip) {
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
return;
@@ -2000,6 +2053,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_TRUE);
d->maskValid = true;
d->maskIsSet = false;
+ d->scissorMask = false;
#else
QPaintEngineEx::clip(path, op);
#endif
@@ -2043,6 +2097,7 @@ void QVGPaintEnginePrivate::modifyMask
vgSeti(VG_MASKING, VG_TRUE);
maskValid = true;
maskIsSet = false;
+ scissorMask = false;
}
void QVGPaintEnginePrivate::modifyMask
@@ -2064,6 +2119,7 @@ void QVGPaintEnginePrivate::modifyMask
vgSeti(VG_MASKING, VG_TRUE);
maskValid = true;
maskIsSet = false;
+ scissorMask = false;
}
#endif // !QVG_SCISSOR_CLIP
@@ -2096,7 +2152,7 @@ void QVGPaintEngine::updateScissor()
{
#if !defined(QVG_SCISSOR_CLIP)
// Combine the system clip with the simple mask rectangle.
- if (!d->maskRect.isNull()) {
+ if (d->scissorMask) {
if (region.isEmpty())
region = d->maskRect;
else
@@ -2187,6 +2243,7 @@ void QVGPaintEngine::clipEnabledChanged()
// Replay the entire clip stack to put the mask into the right state.
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
s->clipRegion = defaultClipRegion();
d->replayClipOperations();
@@ -2196,6 +2253,7 @@ void QVGPaintEngine::clipEnabledChanged()
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
}
#endif
@@ -2314,12 +2372,7 @@ bool QVGPaintEngine::clearRect(const QRectF &rect, const QColor &color)
Q_D(QVGPaintEngine);
QVGPainterState *s = state();
if (!s->clipEnabled || s->clipOperation == Qt::NoClip) {
- // The transform will either be identity or a simple translation,
- // so do a simpler version of "r = d->transform.map(rect).toRect()".
- QRect r = QRect(qRound(rect.x() + d->transform.dx()),
- qRound(rect.y() + d->transform.dy()),
- qRound(rect.width()),
- qRound(rect.height()));
+ QRect r = d->transform.mapRect(rect).toRect();
int height = paintDevice()->height();
if (d->clearColor != color || d->clearOpacity != s->opacity) {
VGfloat values[4];
@@ -3398,6 +3451,7 @@ void QVGPaintEngine::restoreState(QPaintEngine::DirtyFlags dirty)
QPaintEngine::DirtyClipEnabled)) != 0) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
clipEnabledChanged();
}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
index 6b251c7..cd4d5c2 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -921,7 +921,7 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args)
qPrintable(flip));
}
} else {
- flipFlags = DSFLIP_BLIT;
+ flipFlags = DSFLIP_BLIT|DSFLIP_ONSYNC;
}
}
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index 6f049be..25d3dfa 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -71,7 +71,8 @@ public:
~QGIFFormat();
int decode(QImage *image, const uchar* buffer, int length,
- int *nextFrameDelay, int *loopCount, QSize *nextSize);
+ int *nextFrameDelay, int *loopCount);
+ static void scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount);
bool newFrame;
bool partialNewFrame;
@@ -229,7 +230,7 @@ void QGIFFormat::disposePrevious(QImage *image)
Returns the number of bytes consumed.
*/
int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
- int *nextFrameDelay, int *loopCount, QSize *nextSize)
+ int *nextFrameDelay, int *loopCount)
{
// We are required to state that
// "The Graphics Interchange Format(c) is the Copyright property of
@@ -346,10 +347,6 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
bpl = image->bytesPerLine();
bits = image->bits();
memset(bits, 0, image->byteCount());
-
- // ### size of the upcoming frame, should rather
- // be known before decoding it.
- *nextSize = QSize(swidth, sheight);
}
disposePrevious(image);
@@ -645,6 +642,273 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
return initial-length;
}
+/*!
+ Scans through the data stream defined by \a device and returns the image
+ sizes found in the stream in the \a imageSizes vector.
+*/
+void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount)
+{
+ if (!device)
+ return;
+
+ qint64 oldPos = device->pos();
+ if (!device->seek(0))
+ return;
+
+ int colorCount = 0;
+ int localColorCount = 0;
+ int globalColorCount = 0;
+ int colorReadCount = 0;
+ bool localColormap = false;
+ bool globalColormap = false;
+ int count = 0;
+ int blockSize = 0;
+ int imageWidth = 0;
+ int imageHeight = 0;
+ bool done = false;
+ uchar hold[16];
+ State state = Header;
+
+ const int readBufferSize = 40960; // 40k read buffer
+ QByteArray readBuffer(device->read(readBufferSize));
+
+ if (readBuffer.isEmpty()) {
+ device->seek(oldPos);
+ return;
+ }
+
+ // This is a specialized version of the state machine from decode(),
+ // which doesn't do any image decoding or mallocing, and has an
+ // optimized way of skipping SkipBlocks, ImageDataBlocks and
+ // Global/LocalColorMaps.
+
+ while (!readBuffer.isEmpty()) {
+ int length = readBuffer.size();
+ const uchar *buffer = (const uchar *) readBuffer.constData();
+ while (!done && length) {
+ length--;
+ uchar ch = *buffer++;
+ switch (state) {
+ case Header:
+ hold[count++] = ch;
+ if (count == 6) {
+ state = LogicalScreenDescriptor;
+ count = 0;
+ }
+ break;
+ case LogicalScreenDescriptor:
+ hold[count++] = ch;
+ if (count == 7) {
+ imageWidth = LM(hold[0], hold[1]);
+ imageHeight = LM(hold[2], hold[3]);
+ globalColormap = !!(hold[4] & 0x80);
+ globalColorCount = 2 << (hold[4] & 0x7);
+ count = 0;
+ colorCount = globalColorCount;
+ if (globalColormap) {
+ int colorTableSize = 3 * globalColorCount;
+ if (length >= colorTableSize) {
+ // skip the global color table in one go
+ length -= colorTableSize;
+ buffer += colorTableSize;
+ state = Introducer;
+ } else {
+ colorReadCount = 0;
+ state = GlobalColorMap;
+ }
+ } else {
+ state=Introducer;
+ }
+ }
+ break;
+ case GlobalColorMap:
+ case LocalColorMap:
+ hold[count++] = ch;
+ if (count == 3) {
+ if (++colorReadCount >= colorCount) {
+ if (state == LocalColorMap)
+ state = TableImageLZWSize;
+ else
+ state = Introducer;
+ }
+ count = 0;
+ }
+ break;
+ case Introducer:
+ hold[count++] = ch;
+ switch (ch) {
+ case 0x2c:
+ state = ImageDescriptor;
+ break;
+ case 0x21:
+ state = ExtensionLabel;
+ break;
+ case 0x3b:
+ state = Done;
+ break;
+ default:
+ done = true;
+ state = Error;
+ }
+ break;
+ case ImageDescriptor:
+ hold[count++] = ch;
+ if (count == 10) {
+ int newLeft = LM(hold[1], hold[2]);
+ int newTop = LM(hold[3], hold[4]);
+ int newWidth = LM(hold[5], hold[6]);
+ int newHeight = LM(hold[7], hold[8]);
+
+ if (imageWidth/10 > qMax(newWidth,200))
+ imageWidth = -1;
+ if (imageHeight/10 > qMax(newHeight,200))
+ imageHeight = -1;
+
+ if (imageWidth <= 0)
+ imageWidth = newLeft + newWidth;
+ if (imageHeight <= 0)
+ imageHeight = newTop + newHeight;
+
+ *imageSizes << QSize(imageWidth, imageHeight);
+
+ localColormap = !!(hold[9] & 0x80);
+ localColorCount = localColormap ? (2 << (hold[9] & 0x7)) : 0;
+ if (localColorCount)
+ colorCount = localColorCount;
+ else
+ colorCount = globalColorCount;
+
+ count = 0;
+ if (localColormap) {
+ int colorTableSize = 3 * localColorCount;
+ if (length >= colorTableSize) {
+ // skip the local color table in one go
+ length -= colorTableSize;
+ buffer += colorTableSize;
+ state = TableImageLZWSize;
+ } else {
+ colorReadCount = 0;
+ state = LocalColorMap;
+ }
+ } else {
+ state = TableImageLZWSize;
+ }
+ }
+ break;
+ case TableImageLZWSize:
+ if (ch > max_lzw_bits)
+ state = Error;
+ else
+ state = ImageDataBlockSize;
+ count = 0;
+ break;
+ case ImageDataBlockSize:
+ blockSize = ch;
+ if (blockSize) {
+ if (length >= blockSize) {
+ // we can skip the block in one go
+ length -= blockSize;
+ buffer += blockSize;
+ count = 0;
+ } else {
+ state = ImageDataBlock;
+ }
+ } else {
+ state = Introducer;
+ }
+ break;
+ case ImageDataBlock:
+ ++count;
+ if (count == blockSize) {
+ count = 0;
+ state = ImageDataBlockSize;
+ }
+ break;
+ case ExtensionLabel:
+ switch (ch) {
+ case 0xf9:
+ state = GraphicControlExtension;
+ break;
+ case 0xff:
+ state = ApplicationExtension;
+ break;
+ default:
+ state = SkipBlockSize;
+ }
+ count = 0;
+ break;
+ case ApplicationExtension:
+ if (count < 11)
+ hold[count] = ch;
+ ++count;
+ if (count == hold[0] + 1) {
+ if (qstrncmp((char*)(hold+1), "NETSCAPE", 8) == 0)
+ state=NetscapeExtensionBlockSize;
+ else
+ state=SkipBlockSize;
+ count = 0;
+ }
+ break;
+ case GraphicControlExtension:
+ if (count < 5)
+ hold[count] = ch;
+ ++count;
+ if (count == hold[0] + 1) {
+ count = 0;
+ state = SkipBlockSize;
+ }
+ break;
+ case NetscapeExtensionBlockSize:
+ blockSize = ch;
+ count = 0;
+ if (blockSize)
+ state = NetscapeExtensionBlock;
+ else
+ state = Introducer;
+ break;
+ case NetscapeExtensionBlock:
+ if (count < 3)
+ hold[count] = ch;
+ count++;
+ if (count == blockSize) {
+ *loopCount = LM(hold[1], hold[2]);
+ state = SkipBlockSize;
+ }
+ break;
+ case SkipBlockSize:
+ blockSize = ch;
+ count = 0;
+ if (blockSize) {
+ if (length >= blockSize) {
+ // we can skip the block in one go
+ length -= blockSize;
+ buffer += blockSize;
+ } else {
+ state = SkipBlock;
+ }
+ } else {
+ state = Introducer;
+ }
+ break;
+ case SkipBlock:
+ ++count;
+ if (count == blockSize)
+ state = SkipBlockSize;
+ break;
+ case Done:
+ done = true;
+ break;
+ case Error:
+ device->seek(oldPos);
+ return;
+ }
+ }
+ readBuffer = device->read(readBufferSize);
+ }
+ device->seek(oldPos);
+ return;
+}
+
void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb color)
{
if (w>0) {
@@ -763,9 +1027,9 @@ QGifHandler::QGifHandler()
{
gifFormat = new QGIFFormat;
nextDelay = 0;
- loopCnt = 0;
+ loopCnt = 1;
frameNumber = -1;
- nextSize = QSize();
+ scanIsCached = false;
}
QGifHandler::~QGifHandler()
@@ -787,7 +1051,7 @@ bool QGifHandler::imageIsComing() const
}
int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(),
- &nextDelay, &loopCnt, &nextSize);
+ &nextDelay, &loopCnt);
if (decoded == -1)
break;
buffer.remove(0, decoded);
@@ -831,7 +1095,7 @@ bool QGifHandler::read(QImage *image)
}
int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(),
- &nextDelay, &loopCnt, &nextSize);
+ &nextDelay, &loopCnt);
if (decoded == -1)
break;
buffer.remove(0, decoded);
@@ -862,8 +1126,18 @@ bool QGifHandler::supportsOption(ImageOption option) const
QVariant QGifHandler::option(ImageOption option) const
{
if (option == Size) {
- if (imageIsComing())
- return nextSize;
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes, &loopCnt);
+ scanIsCached = true;
+ }
+ // before the first frame is read, or we have an empty data stream
+ if (frameNumber == -1)
+ return (imageSizes.count() > 0) ? QVariant(imageSizes.at(0)) : QVariant();
+ // after the last frame has been read, the next size is undefined
+ if (frameNumber >= imageSizes.count() - 1)
+ return QVariant();
+ // and the last case: the size of the next frame
+ return imageSizes.at(frameNumber + 1);
} else if (option == Animation) {
return true;
}
@@ -883,11 +1157,19 @@ int QGifHandler::nextImageDelay() const
int QGifHandler::imageCount() const
{
- return 0; // Don't know
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes, &loopCnt);
+ scanIsCached = true;
+ }
+ return imageSizes.count();
}
int QGifHandler::loopCount() const
{
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes, &loopCnt);
+ scanIsCached = true;
+ }
return loopCnt-1; // In GIF, loop count is iteration count, so subtract one
}
diff --git a/src/plugins/imageformats/gif/qgifhandler.h b/src/plugins/imageformats/gif/qgifhandler.h
index a6e520f..8e07aff 100644
--- a/src/plugins/imageformats/gif/qgifhandler.h
+++ b/src/plugins/imageformats/gif/qgifhandler.h
@@ -87,7 +87,8 @@ private:
mutable int nextDelay;
mutable int loopCnt;
int frameNumber;
- mutable QSize nextSize;
+ mutable QVector<QSize> imageSizes;
+ mutable bool scanIsCached;
};
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index b2351fa..4edb87a 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -53,6 +53,7 @@
#include <QtGui/QImage>
#include <QtCore/QFile>
#include <QtCore/QBuffer>
+#include <qvariant.h>
// These next two structs represent how the icon information is stored
// in an ICO file.
typedef struct
@@ -772,6 +773,29 @@ QtIcoHandler::~QtIcoHandler()
delete m_pICOReader;
}
+QVariant QtIcoHandler::option(ImageOption option) const
+{
+ if (option == Size) {
+ QIODevice *device = QImageIOHandler::device();
+ qint64 oldPos = device->pos();
+ ICONDIRENTRY iconEntry;
+ if (device->seek(oldPos + ICONDIR_SIZE + (m_currentIconIndex * ICONDIRENTRY_SIZE))) {
+ if (readIconDirEntry(device, &iconEntry)) {
+ device->seek(oldPos);
+ return QSize(iconEntry.bWidth, iconEntry.bHeight);
+ }
+ }
+ if (!device->isSequential())
+ device->seek(oldPos);
+ }
+ return QVariant();
+}
+
+bool QtIcoHandler::supportsOption(ImageOption option) const
+{
+ return option == Size;
+}
+
/*!
* Verifies if some values (magic bytes) are set as expected in the header of the file.
* If the magic bytes were found, it is assumed that the QtIcoHandler can read the file.
diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h
index b9ef27e..394a5eb 100644
--- a/src/plugins/imageformats/ico/qicohandler.h
+++ b/src/plugins/imageformats/ico/qicohandler.h
@@ -62,6 +62,9 @@ public:
static bool canRead(QIODevice *device);
+ bool supportsOption(ImageOption option) const;
+ QVariant option(ImageOption option) const;
+
private:
int m_currentIconIndex;
ICOReader *m_pICOReader;
diff --git a/src/plugins/kbddrivers/linuxinput/main.cpp b/src/plugins/kbddrivers/linuxinput/main.cpp
index 19a3145..db5167e 100644
--- a/src/plugins/kbddrivers/linuxinput/main.cpp
+++ b/src/plugins/kbddrivers/linuxinput/main.cpp
@@ -69,7 +69,7 @@ QWSKeyboardHandler* QLinuxInputKbdDriver::create(const QString &driver,
Q_UNUSED(device);
if (driver.compare(QLatin1String("LinuxInput"), Qt::CaseInsensitive))
return 0;
- return new QWSLinuxInputKeyboardHandler(driver, device);
+ return new QWSLinuxInputKeyboardHandler(device);
}
Q_EXPORT_PLUGIN2(qwslinuxinputkbddriver, QLinuxInputKbdDriver)