summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-02-05 00:47:42 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-02-05 00:47:42 (GMT)
commit3d5aacccdb14ca428cc05e2a0db36bf3baa1a1fa (patch)
treecf5f0dcc069c6342e3839e3cee606445bac28fce /src
parentd499f265aa42231fd08df18213083aebe0db59ec (diff)
parente2f439d8ff3529d9ef50ac58da61432627a8f350 (diff)
downloadQt-3d5aacccdb14ca428cc05e2a0db36bf3baa1a1fa.zip
Qt-3d5aacccdb14ca428cc05e2a0db36bf3baa1a1fa.tar.gz
Qt-3d5aacccdb14ca428cc05e2a0db36bf3baa1a1fa.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: (42 commits) 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. Compiler warning in QAbstractSlider. Optimize QPathClipper::pathToRect. QGraphicsScene: Use QPainter::setClipRect instead of setClipPath if possible. QStyleSheetStyle: Fix combinaison of border-image and border-radius Revert "QAbstractScrollArea: Wheel over a scrollarea that has only one horizontal scrollbar" Proper Fav icon is not shown, for all the links default fav icon shown Update changes-4.6.2. ...
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.cpp13
-rw-r--r--src/gui/kernel/qwidget_x11.cpp75
-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/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.cpp284
-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
36 files changed, 589 insertions, 164 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 ffad38b..4520a1b 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1439,7 +1439,16 @@ QWidget::~QWidget()
}
#endif
- if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
+ 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;
+ } else if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
bs->removeDirtyWidget(this);
if (testAttribute(Qt::WA_StaticContents))
bs->removeStaticWidget(this);
@@ -6414,6 +6423,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..007de7f 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,58 @@ 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
- }
- }
+ // first deliver events that are already in the local queue
+ QApplication::sendPostedEvents();
- while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), MapNotify, &ev)) {
- if (t.elapsed() > maximumWaitTime)
- return;
- qApp->syncX(); // non-busy wait
- }
+ // the normal sequence is:
+ // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose
+ // with X11BypassWindowManagerHint:
+ // ConfigureNotify ... MapNotify ... Expose
- qApp->x11ProcessEvent(&ev);
+ enum State {
+ Initial, Reparented, Mapped
+ } state = Initial;
- // 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)) {
+ 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)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose)
+ return;
+ break;
+ }
+ } else {
+ switch (state) {
+ case Initial:
+ if (ev.type == ReparentNotify)
+ state = Reparented;
+ break;
+ case Reparented:
+ if (ev.type == MapNotify)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose)
+ 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/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..6d473e3 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);
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,255 @@ 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)
+{
+ 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) {
+ 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: // fallthrough
+ 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 NetscapeExtensionBlock: // fallthrough
+ 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) {
@@ -765,7 +1011,7 @@ QGifHandler::QGifHandler()
nextDelay = 0;
loopCnt = 0;
frameNumber = -1;
- nextSize = QSize();
+ scanIsCached = false;
}
QGifHandler::~QGifHandler()
@@ -787,7 +1033,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 +1077,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 +1108,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);
+ 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,7 +1139,11 @@ int QGifHandler::nextImageDelay() const
int QGifHandler::imageCount() const
{
- return 0; // Don't know
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes);
+ scanIsCached = true;
+ }
+ return imageSizes.count();
}
int QGifHandler::loopCount() const
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;