summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-07-01 10:03:53 +0200
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-07-01 16:25:19 +0200
commita09a8d509a69ed16d8afbe15296b8332cacd6c66 (patch)
tree28645b437fd0390d903f753a44ba79626eecb8ac /src/gui
parent4b28152da64f7f23a1bbb810d8cdb7626a5f0b8e (diff)
parent83f06da1c6bffff61af78cbe75a0691d53742b53 (diff)
Merge remote-tracking branch 'origin/5.3' into dev
Conflicts: mkspecs/qnx-x86-qcc/qplatformdefs.h src/corelib/global/qglobal.h src/network/socket/qnativesocketengine_winrt.cpp src/plugins/platforms/android/androidjniaccessibility.cpp src/plugins/platforms/windows/qwindowswindow.cpp Manually adjusted: mkspecs/qnx-armle-v7-qcc/qplatformdefs.h to include 9ce697f2d54be6d94381c72af28dda79cbc027d4 Thanks goes to Sergio for the qnx mkspecs adjustments. Change-Id: I53b1fd6bc5bc884e5ee2c2b84975f58171a1cb8e
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/accessible/qaccessible.cpp4
-rw-r--r--src/gui/animation/qguivariantanimation.cpp2
-rw-r--r--src/gui/image/qgifhandler.cpp2
-rw-r--r--src/gui/image/qicon.cpp119
-rw-r--r--src/gui/image/qicon_p.h10
-rw-r--r--src/gui/image/qimage.cpp274
-rw-r--r--src/gui/image/qpixmap.cpp1
-rw-r--r--src/gui/image/qpixmap_raster.cpp6
-rw-r--r--src/gui/kernel/qguiapplication.cpp10
-rw-r--r--src/gui/kernel/qplatformclipboard.cpp3
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp11
-rw-r--r--src/gui/opengl/qopenglframebufferobject_p.h1
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp78
-rw-r--r--src/gui/painting/qdrawhelper.cpp67
-rw-r--r--src/gui/painting/qpaintengine.cpp2
-rw-r--r--src/gui/painting/qpaintengineex.cpp4
-rw-r--r--src/gui/text/qfontengine.cpp27
-rw-r--r--src/gui/text/qfontmetrics.cpp6
18 files changed, 326 insertions, 301 deletions
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index c715c5c7e0..3d1807ec05 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -1713,10 +1713,6 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
/*! \internal */
QDebug operator<<(QDebug d, const QAccessibleEvent &ev)
{
- if (!&ev) {
- d << "QAccessibleEvent(null)";
- return d;
- }
d.nospace() << "QAccessibleEvent(";
if (ev.object()) {
d.nospace() << "object=" << hex << ev.object() << dec;
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp
index 34abbca282..2cd31696ba 100644
--- a/src/gui/animation/qguivariantanimation.cpp
+++ b/src/gui/animation/qguivariantanimation.cpp
@@ -64,7 +64,7 @@ template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,con
return QQuaternion::slerp(f, t, progress);
}
-static void qRegisterGuiGetInterpolator()
+void qRegisterGuiGetInterpolator()
{
qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>);
qRegisterAnimationInterpolator<QVector2D>(_q_interpolateVariant<QVector2D>);
diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp
index 19b838240f..91588edd50 100644
--- a/src/gui/image/qgifhandler.cpp
+++ b/src/gui/image/qgifhandler.cpp
@@ -674,7 +674,7 @@ void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCo
return;
qint64 oldPos = device->pos();
- if (!device->seek(0))
+ if (device->isSequential() || !device->seek(0))
return;
int colorCount = 0;
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 0a4b50bbea..8172ecbb48 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -363,44 +363,93 @@ void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon
}
}
-void QPixmapIconEngine::addFile(const QString &fileName, const QSize &_size, QIcon::Mode mode, QIcon::State state)
+// Read out original image depth as set by ICOReader
+static inline int origIcoDepth(const QImage &image)
{
- if (!fileName.isEmpty()) {
- QString abs = fileName;
- if (fileName.at(0) != QLatin1Char(':'))
- abs = QFileInfo(fileName).absoluteFilePath();
- QImageReader reader(abs);
-
- do {
- QSize size = _size;
- QPixmap pixmap;
-
- for (int i = 0; i < pixmaps.count(); ++i) {
- if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
- QPixmapIconEngineEntry *pe = &pixmaps[i];
- if (size == QSize()) {
- pixmap.convertFromImage(reader.read());
- size = pixmap.size();
- }
- if (pe->size == QSize() && pe->pixmap.isNull()) {
- pe->pixmap = QPixmap(pe->fileName);
- // Reset the devicePixelRatio. The pixmap may be loaded from a @2x file,
- // but be used as a 1x pixmap by QIcon.
- pe->pixmap.setDevicePixelRatio(1.0);
- pe->size = pe->pixmap.size();
- }
- if (pe->size == size) {
- pe->pixmap = pixmap;
- pe->fileName = abs;
- return;
- }
- }
+ const QString s = image.text(QStringLiteral("_q_icoOrigDepth"));
+ return s.isEmpty() ? 32 : s.toInt();
+}
+
+static inline int findBySize(const QList<QImage> &images, const QSize &size)
+{
+ for (int i = 0; i < images.size(); ++i) {
+ if (images.at(i).size() == size)
+ return i;
+ }
+ return -1;
+}
+
+// Convenience class providing a bool read() function.
+namespace {
+class ImageReader
+{
+public:
+ ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) {}
+
+ QByteArray format() const { return m_reader.format(); }
+
+ bool read(QImage *image)
+ {
+ if (m_atEnd)
+ return false;
+ *image = m_reader.read();
+ if (!image->size().isValid()) {
+ m_atEnd = true;
+ return false;
+ }
+ m_atEnd = !m_reader.jumpToNextImage();
+ return true;
+ }
+
+private:
+ QImageReader m_reader;
+ bool m_atEnd;
+};
+} // namespace
+
+void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ if (fileName.isEmpty())
+ return;
+ const QString abs = fileName.startsWith(QLatin1Char(':')) ? fileName : QFileInfo(fileName).absoluteFilePath();
+ const bool ignoreSize = !size.isValid();
+ ImageReader imageReader(abs);
+ const QByteArray format = imageReader.format();
+ if (format.isEmpty()) // Device failed to open or unsupported format.
+ return;
+ QImage image;
+ if (format != "ico") {
+ if (ignoreSize) { // No size specified: Add all images.
+ while (imageReader.read(&image))
+ pixmaps += QPixmapIconEngineEntry(abs, image, mode, state);
+ } else {
+ // Try to match size. If that fails, add a placeholder with the filename and empty pixmap for the size.
+ while (imageReader.read(&image) && image.size() != size) {}
+ pixmaps += image.size() == size ?
+ QPixmapIconEngineEntry(abs, image, mode, state) : QPixmapIconEngineEntry(abs, size, mode, state);
+ }
+ return;
+ }
+ // Special case for reading Windows ".ico" files. Historically (QTBUG-39287),
+ // these files may contain low-resolution images. As this information is lost,
+ // ICOReader sets the original format as an image text key value. Read all matching
+ // images into a list trying to find the highest quality per size.
+ QList<QImage> icoImages;
+ while (imageReader.read(&image)) {
+ if (ignoreSize || image.size() == size) {
+ const int position = findBySize(icoImages, image.size());
+ if (position >= 0) { // Higher quality available? -> replace.
+ if (origIcoDepth(image) > origIcoDepth(icoImages.at(position)))
+ icoImages[position] = image;
+ } else {
+ icoImages.append(image);
}
- QPixmapIconEngineEntry e(abs, size, mode, state);
- e.pixmap = pixmap;
- pixmaps += e;
- } while (reader.jumpToNextImage());
+ }
}
+ foreach (const QImage &i, icoImages)
+ pixmaps += QPixmapIconEngineEntry(abs, i, mode, state);
+ if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size.
+ pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
}
QString QPixmapIconEngine::key() const
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index 7351ad489a..eb94457f48 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -89,6 +89,7 @@ struct QPixmapIconEngineEntry
:pixmap(pm), size(pm.size()), mode(m), state(s){}
QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
:fileName(file), size(sz), mode(m), state(s){}
+ QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off);
QPixmap pixmap;
QString fileName;
QSize size;
@@ -97,7 +98,14 @@ struct QPixmapIconEngineEntry
bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
};
-
+inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s)
+ : fileName(file), size(image.size()), mode(m), state(s)
+{
+ pixmap.convertFromImage(image);
+ // Reset the devicePixelRatio. The pixmap may be loaded from a @2x file,
+ // but be used as a 1x pixmap by QIcon.
+ pixmap.setDevicePixelRatio(1.0);
+}
class QPixmapIconEngine : public QIconEngine {
public:
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index dda8894722..b0b6b27b71 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1662,11 +1662,14 @@ void QImage::fill(uint pixel)
return;
}
- if (d->format == Format_RGB32 || d->format == Format_RGBX8888)
+ if (d->format == Format_RGB32)
pixel |= 0xff000000;
-
- if (d->format == Format_RGBX8888 || d->format == Format_RGBA8888 || d->format == Format_RGBA8888_Premultiplied)
- pixel = ARGB2RGBA(pixel);
+ if (d->format == Format_RGBX8888)
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ pixel |= 0xff000000;
+#else
+ pixel |= 0x000000ff;
+#endif
qt_rectfill<uint>(reinterpret_cast<uint*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
@@ -1716,22 +1719,27 @@ void QImage::fill(const QColor &color)
if (!d)
return;
- if (d->depth == 32) {
- uint pixel = color.rgba();
- if (d->format == QImage::Format_ARGB32_Premultiplied || d->format == QImage::Format_RGBA8888_Premultiplied)
- pixel = qPremultiply(pixel);
- fill((uint) pixel);
-
- } else if (d->format == QImage::Format_RGB16) {
+ switch (d->format) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ fill(color.rgba());
+ break;
+ case QImage::Format_ARGB32_Premultiplied:
+ fill(qPremultiply(color.rgba()));
+ break;
+ case QImage::Format_RGBX8888:
+ fill(ARGB2RGBA(color.rgba() | 0xff000000));
+ break;
+ case QImage::Format_RGBA8888:
+ fill(ARGB2RGBA(color.rgba()));
+ break;
+ case QImage::Format_RGBA8888_Premultiplied:
+ fill(ARGB2RGBA(qPremultiply(color.rgba())));
+ break;
+ case QImage::Format_RGB16:
fill((uint) qConvertRgb32To16(color.rgba()));
-
- } else if (d->depth == 1) {
- if (color == Qt::color1)
- fill((uint) 1);
- else
- fill((uint) 0);
-
- } else if (d->depth == 8) {
+ break;
+ case QImage::Format_Indexed8: {
uint pixel = 0;
for (int i=0; i<d->colortable.size(); ++i) {
if (color.rgba() == d->colortable.at(i)) {
@@ -1740,20 +1748,24 @@ void QImage::fill(const QColor &color)
}
}
fill(pixel);
-
- } else {
+ break;
+ }
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ if (color == Qt::color1)
+ fill((uint) 1);
+ else
+ fill((uint) 0);
+ break;
+ default: {
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(rect(), color);
- }
-
+ }}
}
-
-
-
/*!
Inverts all pixel values in the image.
@@ -2685,13 +2697,6 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
return maskImage;
}
-
-/*
- This code is contributed by Philipp Lang,
- GeneriCom Software Germany (www.generi.com)
- under the terms of the QPL, Version 1.0
-*/
-
/*!
\fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) const
Returns a mirror of the image, mirrored in the horizontal and/or
@@ -2703,61 +2708,108 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
\sa {QImage#Image Transformations}{Image Transformations}
*/
-template<typename T>
-inline void mirrored_helper_loop(int w, int h, int dxi, int dxs, int dyi, int dy, const uchar* sdata, uchar* ddata, int sbpl, int dbpl)
+template<class T> inline void do_mirror_data(QImageData *dst, QImageData *src,
+ int dstX0, int dstY0,
+ int dstXIncr, int dstYIncr,
+ int w, int h)
{
- for (int sy = 0; sy < h; sy++, dy += dyi) {
- const T* ssl = (T*)(sdata + sy*sbpl);
- T* dsl = (T*)(ddata + dy*dbpl);
- int dx = dxs;
- for (int sx = 0; sx < w; sx++, dx += dxi)
- dsl[dx] = ssl[sx];
+ if (dst == src) {
+ // When mirroring in-place, stop in the middle for one of the directions, since we
+ // are swapping the bytes instead of merely copying.
+ const int srcXEnd = dstX0 ? w / 2 : w;
+ const int srcYEnd = !dstX0 && dstY0 ? h / 2 : h;
+ for (int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) {
+ T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
+ T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
+ for (int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr)
+ std::swap(srcPtr[srcX], dstPtr[dstX]);
+ }
+ } else {
+ for (int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) {
+ T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
+ T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
+ for (int srcX = 0, dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr)
+ dstPtr[dstX] = srcPtr[srcX];
+ }
}
}
-template<typename T>
-inline void mirrored_helper_loop_inplace(int w, int h, int dxi, int dxs, int dyi, int dy, uchar* sdata, int sbpl)
+inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool vertical)
{
- for (int sy = 0; sy < h; sy++, dy += dyi) {
- T* ssl = (T*)(sdata + sy*sbpl);
- T* dsl = (T*)(sdata + dy*sbpl);
- int dx = dxs;
- for (int sx = 0; sx < w; sx++, dx += dxi)
- std::swap(dsl[dx], ssl[sx]);
+ Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth);
+ int w = src->width;
+ int h = src->height;
+ int depth = src->depth;
+
+ if (src->depth == 1) {
+ w = (w + 7) / 8; // byte aligned width
+ depth = 8;
}
-}
-inline void mirror_horizonal_bitmap(int w, int h, int dxs, uchar* data, int bpl, bool monolsb)
-{
- int shift = w % 8;
- const uchar* bitflip = qt_get_bitflip_array();
- for (int y = h-1; y >= 0; y--) {
- quint8* a0 = (quint8*)(data + y*bpl);
- // Swap bytes
- quint8* a = a0+dxs;
- while (a >= a0) {
- *a = bitflip[*a];
- a--;
- }
- // Shift bits if unaligned
- if (shift != 0) {
- a = a0+dxs;
- quint8 c = 0;
- if (monolsb) {
- while (a >= a0) {
- quint8 nc = *a << shift;
- *a = (*a >> (8-shift)) | c;
- --a;
- c = nc;
- }
- } else {
- while (a >= a0) {
- quint8 nc = *a >> shift;
- *a = (*a << (8-shift)) | c;
- --a;
- c = nc;
+ int dstX0 = 0, dstXIncr = 1;
+ int dstY0 = 0, dstYIncr = 1;
+ if (horizontal) {
+ // 0 -> w-1, 1 -> w-2, 2 -> w-3, ...
+ dstX0 = w - 1;
+ dstXIncr = -1;
+ }
+ if (vertical) {
+ // 0 -> h-1, 1 -> h-2, 2 -> h-3, ...
+ dstY0 = h - 1;
+ dstYIncr = -1;
+ }
+
+ switch (depth) {
+ case 32:
+ do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
+ case 24:
+ do_mirror_data<quint24>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
+ case 16:
+ do_mirror_data<quint16>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
+ case 8:
+ do_mirror_data<quint8>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+
+ // The bytes are now all in the correct place. In addition, the bits in the individual
+ // bytes have to be flipped too when horizontally mirroring a 1 bit-per-pixel image.
+ if (horizontal && dst->depth == 1) {
+ Q_ASSERT(dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB);
+ const int shift = 8 - (dst->width % 8);
+ const uchar *bitflip = qt_get_bitflip_array();
+ for (int y = 0; y < h; ++y) {
+ uchar *begin = dst->data + y * dst->bytes_per_line;
+ uchar *end = begin + dst->bytes_per_line;
+ for (uchar *p = begin; p < end; ++p) {
+ *p = bitflip[*p];
+ // When the data is non-byte aligned, an extra bit shift (of the number of
+ // unused bits at the end) is needed for the entire scanline.
+ if (shift != 8 && p != begin) {
+ if (dst->format == QImage::Format_Mono) {
+ for (int i = 0; i < shift; ++i) {
+ p[-1] <<= 1;
+ p[-1] |= (*p & (128 >> i)) >> (7 - i);
+ }
+ } else {
+ for (int i = 0; i < shift; ++i) {
+ p[-1] >>= 1;
+ p[-1] |= (*p & (1 << i)) << (7 - i);
+ }
+ }
}
}
+ if (shift != 8) {
+ if (dst->format == QImage::Format_Mono)
+ end[-1] <<= shift;
+ else
+ end[-1] >>= shift;
+ }
}
}
}
@@ -2773,8 +2825,6 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
return *this;
- int w = d->width;
- int h = d->height;
// Create result image, copy colormap
QImage result(d->width, d->height, d->format);
QIMAGE_SANITYCHECK_MEMORY(result);
@@ -2787,29 +2837,8 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
result.d->has_alpha_clut = d->has_alpha_clut;
result.d->devicePixelRatio = d->devicePixelRatio;
- if (d->depth == 1)
- w = (w+7)/8;
- int dxi = horizontal ? -1 : 1;
- int dxs = horizontal ? w-1 : 0;
- int dyi = vertical ? -1 : 1;
- int dys = vertical ? h-1 : 0;
-
- // 1 bit, 8 bit
- if (d->depth == 1 || d->depth == 8)
- mirrored_helper_loop<quint8>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
- // 16 bit
- else if (d->depth == 16)
- mirrored_helper_loop<quint16>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
- // 24 bit
- else if (d->depth == 24)
- mirrored_helper_loop<quint24>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
- // 32 bit
- else if (d->depth == 32)
- mirrored_helper_loop<quint32>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
-
- // special handling of 1 bit images for horizontal mirroring
- if (horizontal && d->depth == 1)
- mirror_horizonal_bitmap(d->width, d->height, dxs, result.d->data, result.d->bytes_per_line, d->format == Format_MonoLSB);
+ do_mirror(result.d, d, horizontal, vertical);
+
return result;
}
@@ -2818,45 +2847,12 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
*/
void QImage::mirrored_inplace(bool horizontal, bool vertical)
{
- if (!d)
- return;
-
- if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
+ if (!d || (d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
return;
detach();
- int w = d->width;
- int h = d->height;
-
- if (d->depth == 1)
- w = (w+7)/8;
- int dxi = horizontal ? -1 : 1;
- int dxs = horizontal ? w-1 : 0;
- int dyi = vertical ? -1 : 1;
- int dys = vertical ? h-1 : 0;
-
- if (vertical)
- h = h/2;
- else if (horizontal)
- w = w/2;
-
- // 1 bit, 8 bit
- if (d->depth == 1 || d->depth == 8)
- mirrored_helper_loop_inplace<quint8>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
- // 16 bit
- else if (d->depth == 16)
- mirrored_helper_loop_inplace<quint16>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
- // 24 bit
- else if (d->depth == 24)
- mirrored_helper_loop_inplace<quint24>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
- // 32 bit
- else if (d->depth == 32)
- mirrored_helper_loop_inplace<quint32>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
-
- // special handling of 1 bit images for horizontal mirroring
- if (horizontal && d->depth == 1)
- mirror_horizonal_bitmap(d->width, d->height, dxs, d->data, d->bytes_per_line, d->format == Format_MonoLSB);
+ do_mirror(d, d, horizontal, vertical);
}
/*!
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 86c4dfbdca..c6d8d19bb1 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1098,6 +1098,7 @@ bool QPixmap::isDetached() const
*/
bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
{
+ detach();
if (image.isNull() || !data)
*this = QPixmap::fromImage(image, flags);
else
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 1465fea8b9..d879a5cb61 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -363,10 +363,12 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC
}
is_null = (w <= 0 || h <= 0);
- image.d->devicePixelRatio = sourceImage.devicePixelRatio();
+ if (image.d)
+ image.d->devicePixelRatio = sourceImage.devicePixelRatio();
//ensure the pixmap and the image resulting from toImage() have the same cacheKey();
setSerialNumber(image.cacheKey() >> 32);
- setDetachNumber(image.d->detach_no);
+ if (image.d)
+ setDetachNumber(image.d->detach_no);
}
QImage* QRasterPlatformPixmap::buffer()
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 29ab7daca0..c155512e9d 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -171,6 +171,7 @@ bool QGuiApplicationPrivate::noGrab = false;
static qreal fontSmoothingGamma = 1.7;
extern void qRegisterGuiVariant();
+extern void qRegisterGuiGetInterpolator();
extern void qInitDrawhelperAsm();
extern void qInitImageConversions();
@@ -489,6 +490,12 @@ static QWindowGeometrySpecification windowGeometrySpecification;
\li \c{-platformtheme} \e platformTheme, specifies the platform theme.
Overridden by the \c QT_QPA_PLATFORMTHEME environment variable.
+
+ \li \c{-plugin} \e plugin, specifies additional plugins to load. The argument
+ may appear multiple times.
+
+ Overridden by the \c QT_QPA_GENERIC_PLUGINS environment variable.
+
\li \c{-qmljsdebugger=}, activates the QML/JS debugger with a specified port.
The value must be of format \c{port:1234}\e{[,block]}, where
\e block is optional
@@ -1281,6 +1288,9 @@ void QGuiApplicationPrivate::init()
// trigger registering of QVariant's GUI types
qRegisterGuiVariant();
+ // trigger registering of animation interpolators
+ qRegisterGuiGetInterpolator();
+
QWindowSystemInterfacePrivate::eventTime.start();
is_app_running = true;
diff --git a/src/gui/kernel/qplatformclipboard.cpp b/src/gui/kernel/qplatformclipboard.cpp
index 5c25054260..d93268c9f2 100644
--- a/src/gui/kernel/qplatformclipboard.cpp
+++ b/src/gui/kernel/qplatformclipboard.cpp
@@ -123,7 +123,8 @@ bool QPlatformClipboard::ownsMode(QClipboard::Mode mode) const
void QPlatformClipboard::emitChanged(QClipboard::Mode mode)
{
- QGuiApplication::clipboard()->emitChanged(mode);
+ if (!QGuiApplicationPrivate::is_app_closing) // QTBUG-39317, prevent emission when closing down.
+ QGuiApplication::clipboard()->emitChanged(mode);
}
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index 2651c23665..97b006b4fc 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -443,9 +443,10 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
samples = qBound(0, int(samples), int(maxSamples));
}
+ samples = qMax(0, samples);
+ requestedSamples = samples;
size = sz;
target = texture_target;
- // texture dimensions
QT_RESET_GLERROR(); // reset error state
GLuint fbo = 0;
@@ -477,6 +478,9 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
valid = checkFramebufferStatus(ctx);
if (valid) {
+ // Query the actual number of samples. This can be greater than the requested
+ // value since the typically supported values are 0, 4, 8, ..., and the
+ // requests are mapped to the next supported value.
funcs.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
color_buffer_guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
}
@@ -546,7 +550,10 @@ void QOpenGLFramebufferObjectPrivate::initTexture(GLenum target, GLenum internal
void QOpenGLFramebufferObjectPrivate::initAttachments(QOpenGLContext *ctx, QOpenGLFramebufferObject::Attachment attachment)
{
- int samples = format.samples();
+ // Use the same sample count for all attachments. format.samples() already contains
+ // the actual number of samples for the color attachment and is not suitable. Use
+ // requestedSamples instead.
+ const int samples = requestedSamples;
// free existing attachments
if (depth_buffer_guard) {
diff --git a/src/gui/opengl/qopenglframebufferobject_p.h b/src/gui/opengl/qopenglframebufferobject_p.h
index 7a653bc16d..75348d1481 100644
--- a/src/gui/opengl/qopenglframebufferobject_p.h
+++ b/src/gui/opengl/qopenglframebufferobject_p.h
@@ -131,6 +131,7 @@ public:
GLenum target;
QSize size;
QOpenGLFramebufferObjectFormat format;
+ int requestedSamples;
uint valid : 1;
QOpenGLFramebufferObject::Attachment fbo_attachment;
QOpenGLExtensions funcs;
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 57590cfece..db88fbb68c 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -283,46 +283,48 @@ static int qt_gl_resolve_features()
QSurfaceFormat format = QOpenGLContext::currentContext()->format();
QOpenGLExtensionMatcher extensions;
- // Recognize features by extension name.
- if (extensions.match("GL_ARB_multitexture"))
- features |= QOpenGLFunctions::Multitexture;
- if (extensions.match("GL_ARB_shader_objects"))
- features |= QOpenGLFunctions::Shaders;
- if (extensions.match("GL_EXT_framebuffer_object") ||
- extensions.match("GL_ARB_framebuffer_object"))
- features |= QOpenGLFunctions::Framebuffers;
- if (extensions.match("GL_EXT_blend_color"))
- features |= QOpenGLFunctions::BlendColor;
- if (extensions.match("GL_EXT_blend_equation_separate"))
- features |= QOpenGLFunctions::BlendEquationSeparate;
- if (extensions.match("GL_EXT_blend_func_separate"))
- features |= QOpenGLFunctions::BlendFuncSeparate;
- if (extensions.match("GL_EXT_blend_subtract"))
- features |= QOpenGLFunctions::BlendSubtract;
- if (extensions.match("GL_ARB_texture_compression"))
- features |= QOpenGLFunctions::CompressedTextures;
- if (extensions.match("GL_ARB_multisample"))
- features |= QOpenGLFunctions::Multisample;
- if (extensions.match("GL_ARB_texture_non_power_of_two"))
- features |= QOpenGLFunctions::NPOTTextures |
- QOpenGLFunctions::NPOTTextureRepeat;
-
- // assume version 2.0 or higher
- features |= QOpenGLFunctions::BlendColor |
- QOpenGLFunctions::BlendEquation |
- QOpenGLFunctions::Multitexture |
- QOpenGLFunctions::CompressedTextures |
- QOpenGLFunctions::Multisample |
- QOpenGLFunctions::BlendFuncSeparate |
- QOpenGLFunctions::Buffers |
- QOpenGLFunctions::Shaders |
- QOpenGLFunctions::StencilSeparate |
- QOpenGLFunctions::BlendEquationSeparate |
- QOpenGLFunctions::NPOTTextures |
- QOpenGLFunctions::NPOTTextureRepeat;
-
if (format.majorVersion() >= 3)
features |= QOpenGLFunctions::Framebuffers;
+ else if (extensions.match("GL_EXT_framebuffer_object") ||
+ extensions.match("GL_ARB_framebuffer_object"))
+ features |= QOpenGLFunctions::Framebuffers;
+
+ if (format.majorVersion() >= 2) {
+ features |= QOpenGLFunctions::BlendColor |
+ QOpenGLFunctions::BlendEquation |
+ QOpenGLFunctions::BlendSubtract |
+ QOpenGLFunctions::Multitexture |
+ QOpenGLFunctions::CompressedTextures |
+ QOpenGLFunctions::Multisample |
+ QOpenGLFunctions::BlendFuncSeparate |
+ QOpenGLFunctions::Buffers |
+ QOpenGLFunctions::Shaders |
+ QOpenGLFunctions::StencilSeparate |
+ QOpenGLFunctions::BlendEquationSeparate |
+ QOpenGLFunctions::NPOTTextures |
+ QOpenGLFunctions::NPOTTextureRepeat;
+ } else {
+ // Recognize features by extension name.
+ if (extensions.match("GL_ARB_multitexture"))
+ features |= QOpenGLFunctions::Multitexture;
+ if (extensions.match("GL_ARB_shader_objects"))
+ features |= QOpenGLFunctions::Shaders;
+ if (extensions.match("GL_EXT_blend_color"))
+ features |= QOpenGLFunctions::BlendColor;
+ if (extensions.match("GL_EXT_blend_equation_separate"))
+ features |= QOpenGLFunctions::BlendEquationSeparate;
+ if (extensions.match("GL_EXT_blend_subtract"))
+ features |= QOpenGLFunctions::BlendSubtract;
+ if (extensions.match("GL_EXT_blend_func_separate"))
+ features |= QOpenGLFunctions::BlendFuncSeparate;
+ if (extensions.match("GL_ARB_texture_compression"))
+ features |= QOpenGLFunctions::CompressedTextures;
+ if (extensions.match("GL_ARB_multisample"))
+ features |= QOpenGLFunctions::Multisample;
+ if (extensions.match("GL_ARB_texture_non_power_of_two"))
+ features |= QOpenGLFunctions::NPOTTextures |
+ QOpenGLFunctions::NPOTTextureRepeat;
+ }
const QPair<int, int> version = format.version();
if (version < qMakePair(3, 0)
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 2b40bf37e1..44b38dcf1c 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1798,71 +1798,6 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
}
fx = v_fx.i[0];
fy = v_fy.i[0];
-#elif defined(__ARM_NEON__)
- BILINEAR_ROTATE_BOUNDS_PROLOG
-
- const int16x8_t colorMask = vdupq_n_s16(0x00ff);
- const int16x8_t invColorMask = vmvnq_s16(colorMask);
- const int16x8_t v_256 = vdupq_n_s16(256);
- int32x4_t v_fdx = vdupq_n_s32(fdx*4);
- int32x4_t v_fdy = vdupq_n_s32(fdy*4);
-
- const uchar *textureData = data->texture.imageData;
- const int bytesPerLine = data->texture.bytesPerLine;
-
- union Vect_buffer { int32x4_t vect; quint32 i[4]; };
- Vect_buffer v_fx, v_fy;
-
- for (int i = 0; i < 4; i++) {
- v_fx.i[i] = fx;
- v_fy.i[i] = fy;
- fx += fdx;
- fy += fdy;
- }
-
- const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff);
-
- while (b < boundedEnd) {
- if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
- break;
- if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
- break;
- if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
- break;
- if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
- break;
-
- Vect_buffer tl, tr, bl, br;
-
- Vect_buffer v_fx_shifted, v_fy_shifted;
- v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16);
- v_fy_shifted.vect = vshrq_n_s32(v_fy.vect, 16);
-
- for (int i = 0; i < 4; i++) {
- const int x1 = v_fx_shifted.i[i];
- const int y1 = v_fy_shifted.i[i];
- const uchar *sl = textureData + bytesPerLine * y1;
- const uint *s1 = (const uint *)sl;
- const uint *s2 = (const uint *)(sl + bytesPerLine);
- tl.i[i] = s1[x1];
- tr.i[i] = s1[x1+1];
- bl.i[i] = s2[x1];
- br.i[i] = s2[x1+1];
- }
-
- int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12);
- int32x4_t v_disty = vshrq_n_s32(vandq_s32(v_fy.vect, v_ffff_mask), 12);
- v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16));
- v_disty = vorrq_s32(v_disty, vshlq_n_s32(v_disty, 16));
- int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4);
-
- interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b);
- b+=4;
- v_fx.vect = vaddq_s32(v_fx.vect, v_fdx);
- v_fy.vect = vaddq_s32(v_fy.vect, v_fdy);
- }
- fx = v_fx.i[0];
- fy = v_fy.i[0];
#endif
}
@@ -6318,6 +6253,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
}
}
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer,
int x, int y, quint32 color,
const uchar *map,
@@ -6326,6 +6262,7 @@ static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer,
{
qt_alphamapblit_argb32(rasterBuffer, x, y, ARGB2RGBA(color), map, mapWidth, mapHeight, mapStride, clip);
}
+#endif
static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, quint32 color,
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index acab08e794..ba20186d00 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -761,7 +761,7 @@ void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
bool((painter()->renderHints() & QPainter::TextAntialiasing)
&& !(painter()->font().styleStrategy() & QFont::NoAntialias)));
painter()->translate(p.x(), p.y());
- painter()->fillPath(path, state->pen().brush());
+ painter()->fillPath(path, painter()->pen().brush());
painter()->restore();
}
}
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index e75a59cc91..8487cf2394 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -830,6 +830,8 @@ void QPaintEngineEx::drawEllipse(const QRectF &r)
int point_count = 0;
x.points[0] = qt_curves_for_arc(r, 0, -360, x.points + 1, &point_count);
+ if (point_count == 0)
+ return;
QVectorPath vp((qreal *) pts, point_count + 1, qpaintengineex_ellipse_types, QVectorPath::EllipseHint);
draw(vp);
}
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index a165330913..3ce4ae67ae 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -181,9 +181,13 @@ static const HB_FontClass hb_fontClass = {
static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
{
- QFontEngine *fe = (QFontEngine *)font;
- Q_ASSERT(fe->faceData.get_font_table);
- if (!fe->faceData.get_font_table(fe->faceData.user_data, tableTag, buffer, length))
+ QFontEngine::FaceData *data = (QFontEngine::FaceData *)font;
+ Q_ASSERT(data);
+
+ qt_get_font_table_func_t get_font_table = data->get_font_table;
+ Q_ASSERT(get_font_table);
+
+ if (!get_font_table(data->user_data, tableTag, buffer, length))
return HB_Err_Invalid_Argument;
return HB_Err_Ok;
}
@@ -291,8 +295,11 @@ void *QFontEngine::harfbuzzFont() const
#endif
if (!font_) {
HB_Face hbFace = (HB_Face)harfbuzzFace();
- if (hbFace->font_for_init != 0)
+ if (hbFace->font_for_init) {
+ void *data = hbFace->font_for_init;
q_check_ptr(qHBLoadFace(hbFace));
+ free(data);
+ }
HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec));
Q_CHECK_PTR(hbFont);
@@ -323,7 +330,12 @@ void *QFontEngine::harfbuzzFace() const
return hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
#endif
if (!face_) {
- HB_Face hbFace = qHBNewFace(const_cast<QFontEngine *>(this), hb_getSFntTable);
+ QFontEngine::FaceData *data = (QFontEngine::FaceData *)malloc(sizeof(QFontEngine::FaceData));
+ Q_CHECK_PTR(data);
+ data->user_data = faceData.user_data;
+ data->get_font_table = faceData.get_font_table;
+
+ HB_Face hbFace = qHBNewFace(data, hb_getSFntTable);
Q_CHECK_PTR(hbFace);
hbFace->isSymbolFont = symbol;
@@ -376,8 +388,11 @@ bool QFontEngine::supportsScript(QChar::Script script) const
}
#endif
HB_Face hbFace = (HB_Face)harfbuzzFace();
- if (hbFace->font_for_init != 0)
+ if (hbFace->font_for_init) {
+ void *data = hbFace->font_for_init;
q_check_ptr(qHBLoadFace(hbFace));
+ free(data);
+ }
return hbFace->supported_scripts[script_to_hbscript(script)];
}
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 7868fd23d1..f6ab123739 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -295,8 +295,7 @@ int QFontMetrics::descent() const
/*!
Returns the height of the font.
- This is always equal to ascent()+descent()+1 (the 1 is for the
- base line).
+ This is always equal to ascent()+descent().
\sa leading(), lineSpacing()
*/
@@ -1159,8 +1158,7 @@ qreal QFontMetricsF::descent() const
/*!
Returns the height of the font.
- This is always equal to ascent()+descent()+1 (the 1 is for the
- base line).
+ This is always equal to ascent()+descent().
\sa leading(), lineSpacing()
*/