diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-06-29 14:31:46 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-06-29 14:31:46 (GMT) |
commit | 33f01c58fa7e8f1d85f8cb591502f30a6ff30dd3 (patch) | |
tree | 800be290947ed46727f194c747e7d4f0dc34d50e | |
parent | 844171ae6d0a3a02cfb9a39ff18a27d7204a8755 (diff) | |
parent | c2c720cf948f2779aa82e003a2db4d951f94e77f (diff) | |
download | Qt-33f01c58fa7e8f1d85f8cb591502f30a6ff30dd3.zip Qt-33f01c58fa7e8f1d85f8cb591502f30a6ff30dd3.tar.gz Qt-33f01c58fa7e8f1d85f8cb591502f30a6ff30dd3.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2: (26 commits)
Doc: QSettings::sync() imports changes made by other processes.
Made -graphicssystem trace work with Qt::TextBypassShaping flag.
Fix an assertion in comp_func_SourceOver_sse2() if const_alpha == 0
Add a manual test for regular widget interaction with the table.
New variant of ::createPixmapData with origin for QGraphicsSystem.
EGL plane levels are the same as all other GL backends.
Need to access extensionFuncs in subclasses too.
Export QGLWindowSurface too.
Export the QGLPixmapData so that we can override it in a custom graphics system.
Fixed autotest failure in QPathClipper on N900.
Fixed autotest failure in QPainter::setOpacity when NEON is used.
Fix compilation when configured with -no-xrender
Add a new (internal) flag QGraphicsItem::ItemStopsClickFocusPropagation.
Fixed some potential index-out-of-bounds issues in QImage.
Fixed autotest failure in fillRect_stretchToDeviceMode
Adding a known issue for VC2010 64 bit
Added a note to desupport VC2010 64-bit
Normalize integers when calling glVertexAttribPointer()
Add an implementation of comp_func_solid_SourceOver_neon() with Neon.
Fix the casts of qdrawhelper_sse2
...
39 files changed, 640 insertions, 193 deletions
diff --git a/doc/src/getting-started/known-issues.qdoc b/doc/src/getting-started/known-issues.qdoc index b2c39c4..0fa23f6 100644 --- a/doc/src/getting-started/known-issues.qdoc +++ b/doc/src/getting-started/known-issues.qdoc @@ -129,6 +129,14 @@ will not compile. See \l{http://bugreports.qt.nokia.com/browse/QTBUG-6297} for a workaround for QtScript. + + \o Compile errors with Microsoft Visual C++ compiler. \br + There seems to be a bug in the Microsoft compiler when compiling with O2 + optimization level in 64 bit. + This problem will result in crashes in QAbstractItemView::viewOptions(). + See \l{http://bugreports.qt.nokia.com/browse/QTBUG-11445} for updates on this + bug. + \endlist diff --git a/doc/src/platforms/compiler-notes.qdoc b/doc/src/platforms/compiler-notes.qdoc index 7eb92e0..c6ecd68 100644 --- a/doc/src/platforms/compiler-notes.qdoc +++ b/doc/src/platforms/compiler-notes.qdoc @@ -237,8 +237,6 @@ Qt works with the Standard Edition, the Professional Edition and Team System Edition of Visual Studio 2005. - We also test Qt 4 on Windows XP with Visual Studio .NET and Visual Studio 2003. - In order to use Qt with the Visual Studio 2005/2008 Express Edition you need to download and install the platform SDK. Due to limitations in the Express Edition it is not possible for us to install the Qt Visual @@ -266,6 +264,10 @@ from Microsoft. See this \l{http://qt.nokia.com/developer/faqs/faq.2006-12-18.3281869860}{Knowledge Base entry} for more information. + + There currently is a problem when compiling Qt with Visual Studio 2010 for 64-bit. + Its optimizer causes trouble and crashes for the release builds and it is not supported + in that configuration. See task http://bugreports.qt.nokia.com/browse/QTBUG-11445. \section1 IBM xlC (AIX) diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 64015ce..f802412 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -2274,9 +2274,9 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, be different instances of your application running at the same time or different applications altogether) to read and write to the same system locations. It uses advisory file locking and a - smart merging algorithm to ensure data integrity. Changes - performed by another process aren't visible in the current - process until sync() is called. + smart merging algorithm to ensure data integrity. Note that sync() + imports changes made by other processes (in addition to writing + the changes from this QSettings). \section1 Platform-Specific Notes diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 2de3638..61285d2 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -411,6 +411,11 @@ these notifications are disabled by default. You must enable this flag to receive notifications for scene position changes. This flag was introduced in Qt 4.6. + + \omitvalue ItemStopsClickFocusPropagation \omit The item stops propagating + click focus to items underneath when being clicked on. This flag + allows you create a non-focusable item that can be clicked on without + changing the focus. \endomit */ /*! @@ -11432,6 +11437,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemSendsScenePositionChanges: str = "ItemSendsScenePositionChanges"; break; + case QGraphicsItem::ItemStopsClickFocusPropagation: + str = "ItemStopsClickFocusPropagation"; + break; } debug << str; return debug; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index d7d5332..3c193cd 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -106,7 +106,8 @@ public: ItemNegativeZStacksBehindParent = 0x2000, ItemIsPanel = 0x4000, ItemIsFocusScope = 0x8000, // internal - ItemSendsScenePositionChanges = 0x10000 + ItemSendsScenePositionChanges = 0x10000, + ItemStopsClickFocusPropagation = 0x20000 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index bde6e7d..f9f5d3d 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -556,7 +556,7 @@ public: quint32 dirtyChildrenBoundingRect : 1; // Packed 32 bits - quint32 flags : 17; + quint32 flags : 18; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; quint32 geometryChanged : 1; @@ -571,9 +571,9 @@ public: quint32 notifyBoundingRectChanged : 1; quint32 notifyInvalidated : 1; quint32 mouseSetsFocus : 1; - quint32 explicitActivate : 1; // New 32 bits + quint32 explicitActivate : 1; quint32 wantsActive : 1; quint32 holesInSiblingIndex : 1; quint32 sequentialOrdering : 1; @@ -582,7 +582,7 @@ public: quint32 pendingPolish : 1; quint32 mayHaveChildWithGraphicsEffect : 1; quint32 isDeclarativeItem : 1; - quint32 padding : 24; + quint32 padding : 23; // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ca3b56f..d04074a 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1336,6 +1336,8 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou break; } } + if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) + break; if (item->isPanel()) break; } diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index bb8a994..79f266d 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2338,6 +2338,12 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve const int width = data->width; const int src_pad = data->bytes_per_line - width; const int dest_pad = (dst_bytes_per_line >> 2) - width; + if (data->colortable.size() == 0) { + data->colortable.resize(256); + for (int i = 0; i < 256; ++i) + data->colortable[i] = qRgb(i, i, i); + } + const int tableSize = data->colortable.size() - 1; for (int i = 0; i < data->height; ++i) { src_data -= src_pad; @@ -2345,7 +2351,7 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve for (int pixI = 0; pixI < width; ++pixI) { --src_data; --dest_data; - const uint pixel = data->colortable[*src_data]; + const uint pixel = data->colortable[qMin<int>(tableSize, *src_data)]; *dest_data = (quint32) PREMUL(pixel); } } @@ -2377,6 +2383,12 @@ static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversio const int width = data->width; const int src_pad = data->bytes_per_line - width; const int dest_pad = (dst_bytes_per_line >> 2) - width; + if (data->colortable.size() == 0) { + data->colortable.resize(256); + for (int i = 0; i < 256; ++i) + data->colortable[i] = qRgb(i, i, i); + } + const int tableSize = data->colortable.size() - 1; for (int i = 0; i < data->height; ++i) { src_data -= src_pad; @@ -2384,7 +2396,7 @@ static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversio for (int pixI = 0; pixI < width; ++pixI) { --src_data; --dest_data; - *dest_data = (quint32) data->colortable[*src_data]; + *dest_data = (quint32) data->colortable[qMin<int>(tableSize, *src_data)]; } } @@ -2415,6 +2427,12 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers const int width = data->width; const int src_pad = data->bytes_per_line - width; const int dest_pad = (dst_bytes_per_line >> 1) - width; + if (data->colortable.size() == 0) { + data->colortable.resize(256); + for (int i = 0; i < 256; ++i) + data->colortable[i] = qRgb(i, i, i); + } + const int tableSize = data->colortable.size() - 1; for (int i = 0; i < data->height; ++i) { src_data -= src_pad; @@ -2422,7 +2440,7 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers for (int pixI = 0; pixI < width; ++pixI) { --src_data; --dest_data; - const uint pixel = data->colortable[*src_data]; + const uint pixel = data->colortable[qMin<int>(tableSize, *src_data)]; *dest_data = qt_colorConvert<quint16, quint32>(pixel, 0); } } @@ -4061,7 +4079,7 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) } break; case Format_Indexed8: - if (index_or_rgb > (uint)d->colortable.size()) { + if (index_or_rgb >= (uint)d->colortable.size()) { qWarning("QImage::setPixel: Index %d out of range", index_or_rgb); return; } diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 13c03a1..e188745 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -155,6 +155,11 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage, // from qwindowsurface.cpp extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); +void QRasterPixmapData::copy(const QPixmapData *data, const QRect &rect) +{ + fromImage(data->toImage(rect).copy(), Qt::NoOpaqueDetection); +} + bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect) { if (!image.isNull()) @@ -289,6 +294,20 @@ QImage QRasterPixmapData::toImage() const return image; } +QImage QRasterPixmapData::toImage(const QRect &rect) const +{ + if (rect.isNull()) + return image; + + QRect clipped = rect.intersected(QRect(0, 0, w, h)); + if (d % 8 == 0) + return QImage(image.scanLine(clipped.y()) + clipped.x() * (d / 8), + clipped.width(), clipped.height(), + image.bytesPerLine(), image.format()); + else + return image.copy(clipped); +} + void QRasterPixmapData::setAlphaChannel(const QPixmap &alphaChannel) { image.setAlphaChannel(alphaChannel.toImage()); diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h index d7e3f85..a46e054 100644 --- a/src/gui/image/qpixmap_raster_p.h +++ b/src/gui/image/qpixmap_raster_p.h @@ -75,12 +75,14 @@ public: bool fromData(const uchar *buffer, uint len, const char *format, Qt::ImageConversionFlags flags); void fromImage(const QImage &image, Qt::ImageConversionFlags flags); + void copy(const QPixmapData *data, const QRect &rect); bool scroll(int dx, int dy, const QRect &rect); void fill(const QColor &color); void setMask(const QBitmap &mask); bool hasAlphaChannel() const; void setAlphaChannel(const QPixmap &alphaChannel); QImage toImage() const; + QImage toImage(const QRect &rect) const; QPaintEngine* paintEngine() const; QImage* buffer(); diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index e8dc5ae..3d9c363 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -1458,6 +1458,105 @@ int QX11PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const } } +struct QXImageWrapper +{ + XImage *xi; +}; + +bool QX11PixmapData::canTakeQImageFromXImage(const QXImageWrapper &xiWrapper) const +{ + XImage *xi = xiWrapper.xi; + + // ARGB32_Premultiplied + if (picture && depth() == 32) + return true; + + Visual *visual = (Visual *)xinfo.visual(); + + // RGB32 + if (depth() == 24 && xi->bits_per_pixel == 32 && visual->red_mask == 0xff0000 + && visual->green_mask == 0xff00 && visual->blue_mask == 0xff) + return true; + + // RGB16 + if (depth() == 16 && xi->bits_per_pixel == 16 && visual->red_mask == 0xf800 + && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f) + return true; + + return false; +} + +QImage QX11PixmapData::takeQImageFromXImage(const QXImageWrapper &xiWrapper) const +{ + XImage *xi = xiWrapper.xi; + + QImage::Format format = QImage::Format_ARGB32_Premultiplied; + if (depth() == 24) + format = QImage::Format_RGB32; + else if (depth() == 16) + format = QImage::Format_RGB16; + + QImage image((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format); + // take ownership + image.data_ptr()->own_data = true; + xi->data = 0; + + // we may have to swap the byte order + if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst) + || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst)) + { + for (int i=0; i < image.height(); i++) { + if (depth() == 16) { + ushort *p = (ushort*)image.scanLine(i); + ushort *end = p + image.width(); + while (p < end) { + *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff); + p++; + } + } else { + uint *p = (uint*)image.scanLine(i); + uint *end = p + image.width(); + while (p < end) { + *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) + | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); + p++; + } + } + } + } + + // fix-up alpha channel + if (format == QImage::Format_RGB32) { + QRgb *p = (QRgb *)image.bits(); + for (int y = 0; y < xi->height; ++y) { + for (int x = 0; x < xi->width; ++x) + p[x] |= 0xff000000; + p += xi->bytes_per_line / 4; + } + } + + XDestroyImage(xi); + return image; +} + +QImage QX11PixmapData::toImage(const QRect &rect) const +{ + QXImageWrapper xiWrapper; + xiWrapper.xi = XGetImage(X11->display, hd, rect.x(), rect.y(), rect.width(), rect.height(), + AllPlanes, (depth() == 1) ? XYPixmap : ZPixmap); + + Q_CHECK_PTR(xiWrapper.xi); + if (!xiWrapper.xi) + return QImage(); + + if (canTakeQImageFromXImage(xiWrapper)) + return takeQImageFromXImage(xiWrapper); + + QImage image = toImage(xiWrapper, rect); + qSafeXDestroyImage(xiWrapper.xi); + return image; +} + /*! Converts the pixmap to a QImage. Returns a null image if the conversion fails. @@ -1475,6 +1574,13 @@ int QX11PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const QImage QX11PixmapData::toImage() const { + return toImage(QRect(0, 0, w, h)); +} + +QImage QX11PixmapData::toImage(const QXImageWrapper &xiWrapper, const QRect &rect) const +{ + XImage *xi = xiWrapper.xi; + int d = depth(); Visual *visual = (Visual *)xinfo.visual(); bool trucol = (visual->c_class >= TrueColor) && d > 1; @@ -1492,59 +1598,21 @@ QImage QX11PixmapData::toImage() const format = QImage::Format_RGB32; } - XImage *xi = XGetImage(X11->display, hd, 0, 0, w, h, AllPlanes, - (d == 1) ? XYPixmap : ZPixmap); - - Q_CHECK_PTR(xi); - if (!xi) - return QImage(); - - if (picture && depth() == 32) { - QImage image(w, h, QImage::Format_ARGB32_Premultiplied); - memcpy(image.bits(), xi->data, xi->bytes_per_line * xi->height); - - // we may have to swap the byte order - if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst) - || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst)) - { - for (int i=0; i < image.height(); i++) { - uint *p = (uint*)image.scanLine(i); - uint *end = p + image.width(); - if ((xi->byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) - || (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) { - while (p < end) { - *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) - | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); - p++; - } - } else if (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) { - while (p < end) { - *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff) - | ((*p ) & 0xff00ff00); - p++; - } - } - } - } - - // throw away image data - qSafeXDestroyImage(xi); - - return image; - } - if (d == 1 && xi->bitmap_bit_order == LSBFirst) format = QImage::Format_MonoLSB; if (x11_mask && format == QImage::Format_RGB32) format = QImage::Format_ARGB32; - QImage image(w, h, format); + QImage image(xi->width, xi->height, format); if (image.isNull()) // could not create image return image; QImage alpha; if (x11_mask) { - alpha = mask().toImage(); + if (rect.contains(QRect(0, 0, w, h))) + alpha = mask().toImage(); + else + alpha = mask().toImage().copy(rect); } bool ale = alpha.format() == QImage::Format_MonoLSB; @@ -1587,11 +1655,11 @@ QImage QX11PixmapData::toImage() const if (bppc > 8 && xi->byte_order == LSBFirst) bppc++; - for (int y = 0; y < h; ++y) { + for (int y = 0; y < xi->height; ++y) { uchar* asrc = x11_mask ? alpha.scanLine(y) : 0; dst = (QRgb *)image.scanLine(y); src = (uchar *)xi->data + xi->bytes_per_line*y; - for (int x = 0; x < w; x++) { + for (int x = 0; x < xi->width; x++) { switch (bppc) { case 8: pixel = *src++; @@ -1621,8 +1689,8 @@ QImage QX11PixmapData::toImage() const src += 4; break; default: // should not really happen - x = w; // leave loop - y = h; + x = xi->width; // leave loop + y = xi->height; pixel = 0; // eliminate compiler warning qWarning("QPixmap::convertToImage: Invalid depth %d", bppc); } @@ -1660,7 +1728,7 @@ QImage QX11PixmapData::toImage() const } else if (xi->bits_per_pixel == d) { // compatible depth char *xidata = xi->data; // copy each scanline int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line); - for (int y=0; y<h; y++) { + for (int y=0; y<xi->height; y++) { memcpy(image.scanLine(y), xidata, bpl); xidata += xi->bytes_per_line; } @@ -1686,17 +1754,17 @@ QImage QX11PixmapData::toImage() const bpl = image.bytesPerLine(); if (x11_mask) { // which pixels are used? - for (int i = 0; i < h; i++) { + for (int i = 0; i < xi->height; i++) { uchar* asrc = alpha.scanLine(i); p = image.scanLine(i); if (ale) { - for (int x = 0; x < w; x++) { + for (int x = 0; x < xi->width; x++) { if (asrc[x >> 3] & (1 << (x & 7))) use[*p] = 1; ++p; } } else { - for (int x = 0; x < w; x++) { + for (int x = 0; x < xi->width; x++) { if (asrc[x >> 3] & (0x80 >> (x & 7))) use[*p] = 1; ++p; @@ -1704,7 +1772,7 @@ QImage QX11PixmapData::toImage() const } } } else { - for (int i = 0; i < h; i++) { + for (int i = 0; i < xi->height; i++) { p = image.scanLine(i); end = p + bpl; while (p < end) @@ -1716,7 +1784,7 @@ QImage QX11PixmapData::toImage() const if (use[i]) pix[i] = ncols++; } - for (int i = 0; i < h; i++) { // translate pixels + for (int i = 0; i < xi->height; i++) { // translate pixels p = image.scanLine(i); end = p + bpl; while (p < end) { @@ -1736,17 +1804,17 @@ QImage QX11PixmapData::toImage() const // use first pixel in image (as good as any). trans = image.scanLine(0)[0]; } - for (int i = 0; i < h; i++) { + for (int i = 0; i < xi->height; i++) { uchar* asrc = alpha.scanLine(i); p = image.scanLine(i); if (ale) { - for (int x = 0; x < w; x++) { + for (int x = 0; x < xi->width; x++) { if (!(asrc[x >> 3] & (1 << (x & 7)))) *p = trans; ++p; } } else { - for (int x = 0; x < w; x++) { + for (int x = 0; x < xi->width; x++) { if (!(asrc[x >> 3] & (1 << (7 -(x & 7))))) *p = trans; ++p; @@ -1764,8 +1832,6 @@ QImage QX11PixmapData::toImage() const } } - qSafeXDestroyImage(xi); - return image; } diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h index 7575838..821fb69 100644 --- a/src/gui/image/qpixmap_x11_p.h +++ b/src/gui/image/qpixmap_x11_p.h @@ -62,6 +62,8 @@ QT_BEGIN_NAMESPACE class QX11PaintEngine; +struct QXImageWrapper; + class Q_GUI_EXPORT QX11PixmapData : public QPixmapData { public: @@ -87,6 +89,7 @@ public: QPixmap transformed(const QTransform &transform, Qt::TransformationMode mode) const; QImage toImage() const; + QImage toImage(const QRect &rect) const; QPaintEngine* paintEngine() const; Qt::HANDLE handle() const { return hd; } @@ -116,10 +119,15 @@ private: void release(); + QImage toImage(const QXImageWrapper &xi, const QRect &rect) const; + QBitmap mask_to_bitmap(int screen) const; static Qt::HANDLE bitmap_to_mask(const QBitmap &, int screen); void bitmapFromImage(const QImage &image); + bool canTakeQImageFromXImage(const QXImageWrapper &xi) const; + QImage takeQImageFromXImage(const QXImageWrapper &xi) const; + Qt::HANDLE hd; enum Flag { diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp index 31ca909..345e3cf 100644 --- a/src/gui/image/qpixmapdata.cpp +++ b/src/gui/image/qpixmapdata.cpp @@ -146,7 +146,7 @@ bool QPixmapData::fromData(const uchar *buf, uint len, const char *format, Qt::I void QPixmapData::copy(const QPixmapData *data, const QRect &rect) { - fromImage(data->toImage().copy(rect), Qt::NoOpaqueDetection); + fromImage(data->toImage(rect), Qt::NoOpaqueDetection); } bool QPixmapData::scroll(int dx, int dy, const QRect &rect) @@ -255,6 +255,14 @@ void QPixmapData::setSerialNumber(int serNo) ser_no = serNo; } +QImage QPixmapData::toImage(const QRect &rect) const +{ + if (rect.contains(QRect(0, 0, w, h))) + return toImage(); + else + return toImage().copy(rect); +} + QImage* QPixmapData::buffer() { return 0; diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 60ed26a..9a1505a 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -102,6 +102,7 @@ public: virtual void setAlphaChannel(const QPixmap &alphaChannel); virtual QPixmap alphaChannel() const; virtual QImage toImage() const = 0; + virtual QImage toImage(const QRect &rect) const; virtual QPaintEngine* paintEngine() const = 0; inline int serialNumber() const { return ser_no; } diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 3664743..e4d9848 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -2155,7 +2155,7 @@ void qt_init(QApplicationPrivate *priv, int, X11->fc_scale = fc_scale; for (int s = 0; s < ScreenCount(X11->display); ++s) { int subpixel = FC_RGBA_UNKNOWN; -#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 +#if !defined(QT_NO_XRENDER) && (RENDER_MAJOR > 0 || RENDER_MINOR >= 6) if (X11->use_xrender) { int rsp = XRenderQuerySubpixelOrder(X11->display, s); switch (rsp) { diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index bfa1136..5727b3c 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -7817,6 +7817,15 @@ void qInitDrawhelperAsm() #ifdef QT_HAVE_SSE2 if (features & SSE2) { + extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, + const uint *srcPixels, + int length, + uint const_alpha); + extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha); + + functionForModeAsm[0] = comp_func_SourceOver_sse2; + functionForModeSolidAsm[0] = comp_func_solid_SourceOver_sse2; + extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, @@ -7826,7 +7835,6 @@ void qInitDrawhelperAsm() int w, int h, int const_alpha); - qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; @@ -7890,6 +7898,7 @@ void qInitDrawhelperAsm() qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon; functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon; + functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon; destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon; destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon; } diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index ee5f24a..3ce90d2 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -579,6 +579,49 @@ void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int } } +void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha) +{ + if ((const_alpha & qAlpha(color)) == 255) { + QT_MEMFILL_UINT(destPixels, length, color); + } else { + if (const_alpha != 255) + color = BYTE_MUL(color, const_alpha); + + const quint32 minusAlphaOfColor = qAlpha(~color); + int x = 0; + + uint32_t *dst = (uint32_t *) destPixels; + const uint32x4_t colorVector = vdupq_n_u32(color); + uint16x8_t half = vdupq_n_u16(0x80); + const uint16x8_t minusAlphaOfColorVector = vdupq_n_u16(minusAlphaOfColor); + + for (; x < length-3; x += 4) { + uint32x4_t dstVector = vld1q_u32(&dst[x]); + + const uint8x16_t dst8 = vreinterpretq_u8_u32(dstVector); + + const uint8x8_t dst8_low = vget_low_u8(dst8); + const uint8x8_t dst8_high = vget_high_u8(dst8); + + const uint16x8_t dst16_low = vmovl_u8(dst8_low); + const uint16x8_t dst16_high = vmovl_u8(dst8_high); + + const uint16x8_t result16_low = qvbyte_mul_u16(dst16_low, minusAlphaOfColorVector, half); + const uint16x8_t result16_high = qvbyte_mul_u16(dst16_high, minusAlphaOfColorVector, half); + + const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result16_low)); + const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result16_high)); + + uint32x4_t blendedPixels = vcombine_u32(result32_low, result32_high); + uint32x4_t colorPlusBlendedPixels = vaddq_u32(colorVector, blendedPixels); + vst1q_u32(&dst[x], colorPlusBlendedPixels); + } + + for (;x < length; ++x) + destPixels[x] = color + BYTE_MUL(destPixels[x], minusAlphaOfColor); + } +} + QT_END_NAMESPACE #endif // QT_HAVE_NEON diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h index d6a4509..c054a1e 100644 --- a/src/gui/painting/qdrawhelper_neon_p.h +++ b/src/gui/painting/qdrawhelper_neon_p.h @@ -127,6 +127,8 @@ uint * QT_FASTCALL qt_destFetchRGB16_neon(uint *buffer, void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length); +void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha); + #endif // QT_HAVE_NEON QT_END_NAMESPACE diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 6ac64d3..6cd8688 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -126,13 +126,100 @@ QT_BEGIN_NAMESPACE result = _mm_or_si128(finalAG, finalRB); \ } +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +//const __m128i alphaMask = _mm_set1_epi32(0xff000000); +// +// The computation being done is: +// result = s + d * (1-alpha) +// with shortcuts if fully opaque or fully transparent. +#define BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ + int x = 0; \ + for (; x < length-3; x += 4) { \ + const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ + /* all opaque */ \ + _mm_storeu_si128((__m128i *)&dst[x], srcVector); \ + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ + /* not fully transparent */ \ + /* extract the alpha channel on 2 x 16 bits */ \ + /* so we have room for the multiplication */ \ + /* each 32 bits will be in the form 0x00AA00AA */ \ + /* with A being the 1 - alpha */ \ + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + \ + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + \ + /* result = s + d * (1-alpha) */\ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_storeu_si128((__m128i *)&dst[x], result); \ + } \ + } \ + for (; x < length; ++x) { \ + uint s = src[x]; \ + if (s >= 0xff000000) \ + dst[x] = s; \ + else if (s != 0) \ + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ + } \ +} + +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +// +// The computation being done is: +// dest = (s + d * sia) * ca + d * cia +// = s * ca + d * (sia * ca + cia) +// = s * ca + d * (1 - sa*ca) +#define BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector) \ +{ \ + int x = 0; \ + for (; x < length-3; x += 4) { \ + __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { \ + BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); \ +\ + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + \ + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + \ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_storeu_si128((__m128i *)&dst[x], result); \ + } \ + } \ + for (; x < length; ++x) { \ + quint32 s = src[x]; \ + if (s != 0) { \ + s = BYTE_MUL(s, const_alpha); \ + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ + } \ + } \ +} + void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, int const_alpha) { const quint32 *src = (const quint32 *) srcPixels; - quint32 *dst = (uint *) destPixels; + quint32 *dst = (quint32 *) destPixels; if (const_alpha == 256) { const __m128i alphaMask = _mm_set1_epi32(0xff000000); const __m128i nullVector = _mm_set1_epi32(0); @@ -140,41 +227,7 @@ void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const __m128i one = _mm_set1_epi16(0xff); const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); for (int y = 0; y < h; ++y) { - int x = 0; - for (; x < w-3; x += 4) { - const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); - const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); - if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { - // all opaque - _mm_storeu_si128((__m128i *)&dst[x], srcVector); - } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { - // not fully transparent - // result = s + d * (1-alpha) - - // extract the alpha channel on 2 x 16 bits - // so we have room for the multiplication - // each 32 bits will be in the form 0x00AA00AA - // with A being the 1 - alpha - __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); - alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); - alphaChannel = _mm_sub_epi16(one, alphaChannel); - - const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); - __m128i destMultipliedByOneMinusAlpha; - BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); - - // result = s + d * (1-alpha) - const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); - _mm_storeu_si128((__m128i *)&dst[x], result); - } - } - for (; x<w; ++x) { - uint s = src[x]; - if (s >= 0xff000000) - dst[x] = s; - else if (s != 0) - dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); - } + BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, w, nullVector, half, one, colorMask, alphaMask); dst = (quint32 *)(((uchar *) dst) + dbpl); src = (const quint32 *)(((const uchar *) src) + sbpl); } @@ -189,31 +242,7 @@ void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); const __m128i constAlphaVector = _mm_set1_epi16(const_alpha); for (int y = 0; y < h; ++y) { - int x = 0; - for (; x < w-3; x += 4) { - __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); - if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { - BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); - - __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); - alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); - alphaChannel = _mm_sub_epi16(one, alphaChannel); - - const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); - __m128i destMultipliedByOneMinusAlpha; - BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); - - const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); - _mm_storeu_si128((__m128i *)&dst[x], result); - } - } - for (; x<w; ++x) { - quint32 s = src[x]; - if (s != 0) { - s = BYTE_MUL(s, const_alpha); - dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); - } - } + BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, w, nullVector, half, one, colorMask, constAlphaVector) dst = (quint32 *)(((uchar *) dst) + dbpl); src = (const quint32 *)(((const uchar *) src) + sbpl); } @@ -232,7 +261,7 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, int const_alpha) { const quint32 *src = (const quint32 *) srcPixels; - quint32 *dst = (uint *) destPixels; + quint32 *dst = (quint32 *) destPixels; if (const_alpha != 256) { if (const_alpha != 0) { const __m128i nullVector = _mm_set1_epi32(0); @@ -268,6 +297,27 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, } } +void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha) +{ + Q_ASSERT(const_alpha >= 0); + Q_ASSERT(const_alpha < 256); + + const quint32 *src = (const quint32 *) srcPixels; + quint32 *dst = (quint32 *) destPixels; + + const __m128i nullVector = _mm_set1_epi32(0); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i one = _mm_set1_epi16(0xff); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + if (const_alpha == 255) { + const __m128i alphaMask = _mm_set1_epi32(0xff000000); + BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask); + } else { + const __m128i constAlphaVector = _mm_set1_epi16(const_alpha); + BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector); + } +} + void qt_memfill32_sse2(quint32 *dest, quint32 value, int count) { if (count < 7) { @@ -312,6 +362,34 @@ void qt_memfill32_sse2(quint32 *dest, quint32 value, int count) } } +void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha) +{ + if ((const_alpha & qAlpha(color)) == 255) { + qt_memfill32_sse2(destPixels, color, length); + } else { + if (const_alpha != 255) + color = BYTE_MUL(color, const_alpha); + + const quint32 minusAlphaOfColor = qAlpha(~color); + int x = 0; + + quint32 *dst = (quint32 *) destPixels; + const __m128i colorVector = _mm_set1_epi32(color); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i minusAlphaOfColorVector = _mm_set1_epi16(minusAlphaOfColor); + + for (; x < length-3; x += 4) { + __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); + BYTE_MUL_SSE2(dstVector, dstVector, minusAlphaOfColorVector, colorMask, half); + dstVector = _mm_add_epi8(colorVector, dstVector); + _mm_storeu_si128((__m128i *)&dst[x], dstVector); + } + for (;x < length; ++x) + destPixels[x] = color + BYTE_MUL(destPixels[x], minusAlphaOfColor); + } +} + void qt_memfill16_sse2(quint16 *dest, quint16 value, int count) { if (count < 3) { diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index 2ea3d33..69ce47e 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -79,5 +79,9 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ return 0; } +QPixmapData *QGraphicsSystem::createPixmapData(QPixmapData *origin) +{ + return createPixmapData(origin->pixelType()); +} QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem_p.h b/src/gui/painting/qgraphicssystem_p.h index ddca788..1211505 100644 --- a/src/gui/painting/qgraphicssystem_p.h +++ b/src/gui/painting/qgraphicssystem_p.h @@ -64,6 +64,7 @@ class Q_GUI_EXPORT QGraphicsSystem { public: virtual QPixmapData *createPixmapData(QPixmapData::PixelType type) const = 0; + virtual QPixmapData *createPixmapData(QPixmapData *origin); virtual QWindowSurface *createWindowSurface(QWidget *widget) const = 0; virtual ~QGraphicsSystem() = 0; diff --git a/src/gui/painting/qgraphicssystem_runtime.cpp b/src/gui/painting/qgraphicssystem_runtime.cpp index 32a8578..1c3ae10 100644 --- a/src/gui/painting/qgraphicssystem_runtime.cpp +++ b/src/gui/painting/qgraphicssystem_runtime.cpp @@ -416,7 +416,7 @@ void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name) for (int i = 0; i < m_pixmapDatas.size(); ++i) { QRuntimePixmapData *proxy = m_pixmapDatas.at(i); - QPixmapData *newData = m_graphicsSystem->createPixmapData(proxy->m_data->pixelType()); + QPixmapData *newData = m_graphicsSystem->createPixmapData(proxy->m_data); // ### TODO Optimize. Openvg and s60raster graphics systems could switch internal ARGB32_PRE QImage buffers. newData->fromImage(proxy->m_data->toImage(), Qt::AutoColor | Qt::OrderedAlphaDither); delete proxy->m_data; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index a212718..84b36c7 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2419,7 +2419,9 @@ void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, cons drawImage(r, image, sr); } } else { - const QImage image = pixmap.toImage(); + QRect clippedSource = sr.toAlignedRect().intersected(pixmap.rect()); + const QImage image = pd->toImage(clippedSource); + QRectF translatedSource = sr.translated(-clippedSource.topLeft()); if (image.depth() == 1) { Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); @@ -2430,10 +2432,10 @@ void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, cons drawBitmap(r.topLeft() + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); return; } else { - drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), sr); + drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), translatedSource); } } else { - drawImage(r, image, sr); + drawImage(r, image, translatedSource); } } } @@ -2688,7 +2690,11 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) { - if (s->flags.fast_images) { + QRectF targetBounds = s->matrix.mapRect(r); + bool exceedsPrecision = targetBounds.width() > 0xffff + || targetBounds.height() > 0xffff; + + if (s->flags.fast_images && !exceedsPrecision) { if (s->matrix.type() > QTransform::TxScale) { SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()]; if (func && (!clip || clip->hasRectClip)) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 71bc990..2ea6673 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5958,7 +5958,7 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice"); } - QTextItemInt gf(glyphs, &d->state->font, fontEngine); + QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine); drawTextItem(p, gf); return; } diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 78553c9..a17b7c1 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -86,9 +86,11 @@ static qreal dot(const QPointF &a, const QPointF &b) return a.x() * b.x() + a.y() * b.y(); } -static QPointF normalize(const QPointF &p) +static void normalize(double &x, double &y) { - return p / qSqrt(p.x() * p.x() + p.y() * p.y()); + double reciprocal = 1 / qSqrt(x * x + y * y); + x *= reciprocal; + y *= reciprocal; } struct QIntersection @@ -1017,8 +1019,8 @@ qreal QWingedEdge::delta(int vertex, int a, int b) const const QPathEdge *ap = edge(a); const QPathEdge *bp = edge(b); - qreal a_angle = ap->angle; - qreal b_angle = bp->angle; + double a_angle = ap->angle; + double b_angle = bp->angle; if (vertex == ap->second) a_angle = ap->invAngle; @@ -1026,7 +1028,7 @@ qreal QWingedEdge::delta(int vertex, int a, int b) const if (vertex == bp->second) b_angle = bp->invAngle; - qreal result = b_angle - a_angle; + double result = b_angle - a_angle; if (result >= 128.) return result - 128.; @@ -1036,26 +1038,6 @@ qreal QWingedEdge::delta(int vertex, int a, int b) const return result; } -static inline QPointF tangentAt(const QWingedEdge &list, int vi, int ei) -{ - const QPathEdge *ep = list.edge(ei); - Q_ASSERT(ep); - - qreal sign; - - if (ep->first == vi) { - sign = 1; - } else { - sign = -1; - } - - const QPointF a = *list.vertex(ep->first); - const QPointF b = *list.vertex(ep->second); - QPointF normal = b - a; - - return normalize(sign * normal); -} - static inline QPointF midPoint(const QWingedEdge &list, int ei) { const QPathEdge *ep = list.edge(ei); @@ -1191,7 +1173,7 @@ static int commonEdge(const QWingedEdge &list, int a, int b) return -1; } -static qreal computeAngle(const QPointF &v) +static double computeAngle(const QPointF &v) { #if 1 if (v.x() == 0) { @@ -1200,15 +1182,17 @@ static qreal computeAngle(const QPointF &v) return v.x() <= 0 ? 32. : 96.; } - QPointF nv = normalize(v); - if (nv.y() < 0) { - if (nv.x() < 0) { // 0 - 32 - return -32. * nv.x(); + double vx = v.x(); + double vy = v.y(); + normalize(vx, vy); + if (vy < 0) { + if (vx < 0) { // 0 - 32 + return -32. * vx; } else { // 96 - 128 - return 128. - 32. * nv.x(); + return 128. - 32. * vx; } } else { // 32 - 96 - return 64. + 32 * nv.x(); + return 64. + 32. * vx; } #else // doesn't seem to be robust enough diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h index fab618d..bdad4e1 100644 --- a/src/gui/painting/qpathclipper_p.h +++ b/src/gui/painting/qpathclipper_p.h @@ -148,8 +148,8 @@ public: int first; int second; - qreal angle; - qreal invAngle; + double angle; + double invAngle; int next(Traversal traversal, Direction direction) const; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 60195a8..439f2a4 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2668,9 +2668,9 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo flags |= QTextItem::StrikeOut; } -QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, QFontEngine *fe) +QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars_, int numChars, QFontEngine *fe) : flags(0), justified(false), underlineStyle(QTextCharFormat::NoUnderline), - num_chars(0), chars(0), logClusters(0), f(font), glyphs(g), fontEngine(fe) + num_chars(numChars), chars(chars_), logClusters(0), f(font), glyphs(g), fontEngine(fe) { } diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 908a0ec..e623fa5 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -311,7 +311,7 @@ public: logClusters(0), f(0), fontEngine(0) {} QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat()); - QTextItemInt(const QGlyphLayout &g, QFont *font, QFontEngine *fe); + QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars, int numChars, QFontEngine *fe); /// copy the structure items, adjusting the glyphs arrays to the right subarrays. /// the width of the returned QTextItemInt is not adjusted, for speed reasons diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 9effb34..9633da4 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2246,6 +2246,13 @@ static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum textu } } +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) +QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *) +{ + return qt_extensionFuncs; +} +#endif + QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format) { diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index 0a19531..58d3b0a 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -138,7 +138,7 @@ void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config) format.setDepthBufferSize(depthSize); format.setStencilBufferSize(stencilSize); format.setSamples(sampleCount); - format.setPlane(level + 1); // EGL calls level 0 "normal" whereas Qt calls 1 "normal" + format.setPlane(level); format.setDirectRendering(true); // All EGL contexts are direct-rendered format.setRgba(true); // EGL doesn't support colour index rendering format.setStereo(false); // EGL doesn't support stereo buffers diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index cd5dbbe..b57972c 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -415,7 +415,7 @@ public: #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) static QGLExtensionFuncs qt_extensionFuncs; - static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; } + static QGLExtensionFuncs& extensionFuncs(const QGLContext *); #endif static void setCurrentContext(QGLContext *context); diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 83b4b21..c7689b8 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -1490,7 +1490,7 @@ void QGLShaderProgram::setAttributeArray Q_D(QGLShaderProgram); Q_UNUSED(d); if (location != -1) { - glVertexAttribPointer(location, tupleSize, type, GL_FALSE, + glVertexAttribPointer(location, tupleSize, type, GL_TRUE, stride, values); } } @@ -1634,7 +1634,7 @@ void QGLShaderProgram::setAttributeBuffer Q_D(QGLShaderProgram); Q_UNUSED(d); if (location != -1) { - glVertexAttribPointer(location, tupleSize, type, GL_FALSE, stride, + glVertexAttribPointer(location, tupleSize, type, GL_TRUE, stride, reinterpret_cast<const void *>(offset)); } } diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index c239bcb..736a28e 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -96,7 +96,7 @@ private: }; -class QGLPixmapData : public QPixmapData +class Q_OPENGL_EXPORT QGLPixmapData : public QPixmapData { public: QGLPixmapData(PixelType type); diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h index 8ea714c..624236c 100644 --- a/src/opengl/qwindowsurface_gl_p.h +++ b/src/opengl/qwindowsurface_gl_p.h @@ -77,7 +77,7 @@ public: QGLWindowSurfacePrivate* d; }; -class QGLWindowSurface : public QObject, public QWindowSurface // , public QPaintDevice +class Q_OPENGL_EXPORT QGLWindowSurface : public QObject, public QWindowSurface // , public QPaintDevice { Q_OBJECT public: diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index fe68c8e..31a6845 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -442,6 +442,7 @@ private slots: void updateMicroFocus(); void textItem_shortcuts(); void scroll(); + void stopClickFocusPropagation(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -10268,6 +10269,59 @@ void tst_QGraphicsItem::scroll() QCOMPARE(item2->lastExposedRect, expectedItem2Expose); } +void tst_QGraphicsItem::stopClickFocusPropagation() +{ + class MyItem : public QGraphicsRectItem + { + public: + MyItem() : QGraphicsRectItem(0, 0, 100, 100) {} + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + { + painter->fillRect(boundingRect(), hasFocus() ? QBrush(Qt::red) : brush()); + } + }; + + QGraphicsScene scene(-50, -50, 400, 400); + scene.setStickyFocus(true); + + QGraphicsRectItem *noFocusOnTop = new MyItem; + noFocusOnTop->setBrush(Qt::yellow); + noFocusOnTop->setFlag(QGraphicsItem::ItemStopsClickFocusPropagation); + + QGraphicsRectItem *focusableUnder = new MyItem; + focusableUnder->setBrush(Qt::blue); + focusableUnder->setFlag(QGraphicsItem::ItemIsFocusable); + focusableUnder->setPos(50, 50); + + QGraphicsRectItem *itemWithFocus = new MyItem; + itemWithFocus->setBrush(Qt::black); + itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable); + itemWithFocus->setPos(250, 10); + + scene.addItem(noFocusOnTop); + scene.addItem(focusableUnder); + scene.addItem(itemWithFocus); + focusableUnder->stackBefore(noFocusOnTop); + itemWithFocus->setFocus(); + + QGraphicsView view(&scene); + view.show(); + QTest::qWaitForWindowShown(&view); + + QApplication::setActiveWindow(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + QVERIFY(itemWithFocus->hasFocus()); + + QPointF mousePressPoint = noFocusOnTop->mapToScene(QPointF()); + mousePressPoint.rx() += 60; + mousePressPoint.ry() += 60; + const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint); + QVERIFY(itemsAtMousePressPosition.contains(focusableUnder)); + + sendMousePress(&scene, mousePressPoint); + QVERIFY(itemWithFocus->hasFocus()); +} + void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor() { struct Item : public QGraphicsTextItem diff --git a/tests/auto/qimage/tst_qimage.cpp b/tests/auto/qimage/tst_qimage.cpp index 16deb03..5052114 100644 --- a/tests/auto/qimage/tst_qimage.cpp +++ b/tests/auto/qimage/tst_qimage.cpp @@ -945,11 +945,11 @@ void tst_QImage::rotate() const int n = original.colorTable().size(); for (int x = 0; x < w; ++x) { original.setPixel(x, 0, x % n); - original.setPixel(x,h - 1, n - (x % n)); + original.setPixel(x, h - 1, n - (x % n) - 1); } for (int y = 0; y < h; ++y) { original.setPixel(0, y, y % n); - original.setPixel(w - 1, y, n - (y % n)); + original.setPixel(w - 1, y, n - (y % n) - 1); } } diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp index 701dc2e..27ee6e7 100644 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ b/tests/auto/qpainter/tst_qpainter.cpp @@ -2648,12 +2648,16 @@ void tst_QPainter::setOpacity() p.drawImage(imageRect, src, imageRect); p.end(); - QImage expected(imageSize, destFormat); - p.begin(&expected); - p.fillRect(imageRect, QColor(127, 127, 127)); - p.end(); - - QCOMPARE(dest, expected); + QImage actual = dest.convertToFormat(QImage::Format_RGB32); + + for (int y = 0; y < actual.height(); ++y) { + QRgb *p = (QRgb *)actual.scanLine(y); + for (int x = 0; x < actual.width(); ++x) { + QVERIFY(qAbs(qRed(p[x]) - 127) <= 0xf); + QVERIFY(qAbs(qGreen(p[x]) - 127) <= 0xf); + QVERIFY(qAbs(qBlue(p[x]) - 127) <= 0xf); + } + } } void tst_QPainter::drawhelper_blend_untransformed_data() diff --git a/tests/manual/qtabletevent/regular_widgets/main.cpp b/tests/manual/qtabletevent/regular_widgets/main.cpp new file mode 100644 index 0000000..e0c53f5 --- /dev/null +++ b/tests/manual/qtabletevent/regular_widgets/main.cpp @@ -0,0 +1,109 @@ +#include <QApplication> +#include <QDebug> +#include <QMouseEvent> +#include <QTabletEvent> +#include <QWidget> + +class EventReportWidget : public QWidget +{ +public: + EventReportWidget(); +protected: + void mouseDoubleClickEvent(QMouseEvent *event) { outputMouseEvent(event); } + void mouseMoveEvent(QMouseEvent *event) { outputMouseEvent(event); } + void mousePressEvent(QMouseEvent *event) { outputMouseEvent(event); } + void mouseReleaseEvent(QMouseEvent *event) { outputMouseEvent(event); } + + void tabletEvent(QTabletEvent *); + +private: + void outputMouseEvent(QMouseEvent *event); + + bool m_lastIsMouseMove; + bool m_lastIsTabletMove; +}; + +EventReportWidget::EventReportWidget() + : m_lastIsMouseMove(false) + , m_lastIsTabletMove(false) +{ } + +void EventReportWidget::tabletEvent(QTabletEvent *event) +{ + QWidget::tabletEvent(event); + + QString type; + switch (event->type()) { + case QEvent::TabletEnterProximity: + m_lastIsTabletMove = false; + type = QString::fromLatin1("TabletEnterProximity"); + break; + case QEvent::TabletLeaveProximity: + m_lastIsTabletMove = false; + type = QString::fromLatin1("TabletLeaveProximity"); + break; + case QEvent::TabletMove: + if (m_lastIsTabletMove) + return; + + m_lastIsTabletMove = true; + type = QString::fromLatin1("TabletMove"); + break; + case QEvent::TabletPress: + m_lastIsTabletMove = false; + type = QString::fromLatin1("TabletPress"); + break; + case QEvent::TabletRelease: + m_lastIsTabletMove = false; + type = QString::fromLatin1("TabletRelease"); + break; + default: + Q_ASSERT(false); + break; + } + + qDebug() << "Tablet event, type = " << type + << " position = " << event->pos() + << " global position = " << event->globalPos(); +} + +void EventReportWidget::outputMouseEvent(QMouseEvent *event) +{ + QString type; + switch (event->type()) { + case QEvent::MouseButtonDblClick: + m_lastIsMouseMove = false; + type = QString::fromLatin1("MouseButtonDblClick"); + break; + case QEvent::MouseButtonPress: + m_lastIsMouseMove = false; + type = QString::fromLatin1("MouseButtonPress"); + break; + case QEvent::MouseButtonRelease: + m_lastIsMouseMove = false; + type = QString::fromLatin1("MouseButtonRelease"); + break; + case QEvent::MouseMove: + if (m_lastIsMouseMove) + return; // only show one move to keep things readable + + m_lastIsMouseMove = true; + type = QString::fromLatin1("MouseMove"); + break; + default: + Q_ASSERT(false); + break; + } + + qDebug() << "Mouse event, type = " << type + << " position = " << event->pos() + << " global position = " << event->globalPos(); +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + EventReportWidget widget; + widget.show(); + return app.exec(); +} diff --git a/tests/manual/qtabletevent/regular_widgets/regular_widgets.pro b/tests/manual/qtabletevent/regular_widgets/regular_widgets.pro new file mode 100644 index 0000000..9f0da76 --- /dev/null +++ b/tests/manual/qtabletevent/regular_widgets/regular_widgets.pro @@ -0,0 +1,3 @@ +TEMPLATE = app + +SOURCES += main.cpp |