From a8c3ed1dbe209488866e687d1a63c6143a04cfe0 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 23 Dec 2009 10:38:56 +0100 Subject: Fix text rendering on GL2 paint engine If you draw with a brush, then draw a pixmap, then draw with the same brush, the GL2 engine wouldn't update the fragment shader to use the brush. This is because it detected the brush hadn't changed and so didn't need updating. To fix this, we now set the current brush to noBrush when drawing an image/pixmap so the engine knows it needs to update the GL state for the brush. Reviewed-By: Kim --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 15 ++++++++++----- src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 1 + 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index f52ed92..32fa3dc 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -388,21 +388,24 @@ inline QColor qt_premultiplyColor(QColor c, GLfloat opacity) void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush) { - Q_ASSERT(brush.style() != Qt::NoBrush); - if (qbrush_fast_equals(currentBrush, brush)) return; + const Qt::BrushStyle newStyle = qbrush_style(brush); + Q_ASSERT(newStyle != Qt::NoBrush); + currentBrush = brush; + brushUniformsDirty = true; // All brushes have at least one uniform + + if (newStyle > Qt::SolidPattern) + brushTextureDirty = true; - brushTextureDirty = true; - brushUniformsDirty = true; if (currentBrush.style() == Qt::TexturePattern && qHasPixmapTexture(brush) && brush.texture().isQBitmap()) { shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern); } else { - shaderManager->setSrcPixelType(currentBrush.style()); + shaderManager->setSrcPixelType(newStyle); } shaderManager->optimiseForBrushTransform(currentBrush.transform()); } @@ -700,6 +703,7 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect) void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern) { // Setup for texture drawing + currentBrush = noBrush; shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); if (prepareForDraw(opaque)) shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); @@ -1782,6 +1786,7 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); // Setup for texture drawing + d->currentBrush = d->noBrush; d->shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); if (d->prepareForDraw(isOpaque)) d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index f1ec6e6..8de4a82 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -244,6 +244,7 @@ public: uint maxClip; QBrush currentBrush; // May not be the state's brush! + const QBrush noBrush; GLfloat inverseScale; -- cgit v0.12 From d2f10dae860cea0de33b4cb9005ba8d2203ce1d1 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 12 Oct 2009 15:34:36 +0200 Subject: QImageReader: Avoid errorString creation in the normal case Deploy the same idiom found in QIODevice::errorString(). Return "Unknown Error" in case of am empty string. This is a tiny improvement for QtWebKit. Reviewed-by: Andreas --- src/gui/image/qimagereader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 074f3eb..4fb07fb 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -471,7 +471,6 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq) handler = 0; quality = -1; imageReaderError = QImageReader::UnknownError; - errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error")); q = qq; } @@ -1302,6 +1301,8 @@ QImageReader::ImageReaderError QImageReader::error() const */ QString QImageReader::errorString() const { + if (d->errorString.isEmpty()) + return QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error")); return d->errorString; } -- cgit v0.12 From 5c0a117f62607ed439cdfa3d94aaef627c47ce8a Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 15 Oct 2009 05:21:30 +0200 Subject: png: Avoid calling QImage::scanLine(int) from within a loop Reviewed-by: Andreas --- src/gui/image/qpnghandler.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 14c863b..1de0f32 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -67,6 +67,9 @@ QT_BEGIN_NAMESPACE # define Q_INTERNAL_WIN_NO_THROW #endif +// avoid going through QImage::scanLine() which calls detach +#define FAST_SCAN_LINE(data, bpl, y) (data + (y) * bpl) + /* All PNG files load to the minimal QImage equivalent. @@ -510,7 +513,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) && outImage->format() == QImage::Format_Indexed8) { int color_table_size = outImage->colorCount(); for (int y=0; y<(int)height; ++y) { - uchar *p = outImage->scanLine(y); + uchar *p = FAST_SCAN_LINE(data, bpl, y); uchar *end = p + width; while (p < end) { if (*p >= color_table_size) -- cgit v0.12 From 3de151493f75dc52e693f84ef66ff1a86c79d8e3 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 13 Oct 2009 02:59:32 +0200 Subject: gif: 10% speedup on microbenchmark on QImageReader On the microbenchmark of what is executed during pure pageloading in regarding to QImageReader this is an improvement. Do not use the non const QImage::scanLine as this will go through the QImage::detach all the time making QImage::scanLine show up in the profile. Introduce a FAST_SCAN_LINE that is doing the scanLine calculation on local variables. Reviewed-by: Andreas --- src/plugins/imageformats/gif/qgifhandler.cpp | 40 ++++++++++++++++++---------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp index c95b63c..dee0e52 100644 --- a/src/plugins/imageformats/gif/qgifhandler.cpp +++ b/src/plugins/imageformats/gif/qgifhandler.cpp @@ -54,6 +54,10 @@ QT_BEGIN_NAMESPACE #define Q_TRANSPARENT 0x00ffffff +// avoid going through QImage::scanLine() which calls detach +#define FAST_SCAN_LINE(bits, bpl, y) (bits + (y) * bpl) + + /* Incremental image decoder for GIF image format. @@ -135,7 +139,7 @@ private: int frame; bool out_of_bounds; bool digress; - void nextY(QImage *image); + void nextY(unsigned char *bits, int bpl); void disposePrevious(QImage *image); }; @@ -232,6 +236,10 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, // CompuServe Incorporated. GIF(sm) is a Service Mark property of // CompuServe Incorporated." + image->detach(); + int bpl = image->bytesPerLine(); + unsigned char *bits = image->bits(); + #define LM(l, m) (((m)<<8)|l) digress = false; const int initial = length; @@ -335,7 +343,9 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32; if (image->isNull()) { (*image) = QImage(swidth, sheight, format); - memset(image->bits(), 0, image->byteCount()); + bpl = image->bytesPerLine(); + bits = image->bits(); + memset(bits, 0, image->byteCount()); // ### size of the upcoming frame, should rather // be known before decoding it. @@ -393,11 +403,13 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, backingstore = QImage(qMax(backingstore.width(), w), qMax(backingstore.height(), h), QImage::Format_RGB32); - memset(image->bits(), 0, image->byteCount()); + memset(bits, 0, image->byteCount()); } + const int dest_bpl = backingstore.bytesPerLine(); + unsigned char *dest_data = backingstore.bits(); for (int ln=0; lnscanLine(t+ln)+l, w*sizeof(QRgb)); + memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln), + FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb)); } } @@ -470,14 +482,14 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, if (needfirst) { firstcode=oldcode=code; if (!out_of_bounds && image->height() > y && firstcode!=trans_index) - ((QRgb*)image->scanLine(y))[x] = color(firstcode); + ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode); x++; if (x>=swidth) out_of_bounds = true; needfirst=false; if (x>=left+width) { x=left; out_of_bounds = left>=swidth || y>=sheight; - nextY(image); + nextY(bits, bpl); } } else { incode=code; @@ -515,7 +527,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, const QRgb *map = lcmap ? localcmap : globalcmap; QRgb *line = 0; if (!out_of_bounds && h > y) - line = (QRgb*)image->scanLine(y); + line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); while (sp>stack) { const uchar index = *(--sp); if (!out_of_bounds && h > y && index!=trans_index) { @@ -529,9 +541,9 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, if (x>=left+width) { x=left; out_of_bounds = left>=swidth || y>=sheight; - nextY(image); + nextY(bits, bpl); if (!out_of_bounds && h > y) - line = (QRgb*)image->scanLine(y); + line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); } } } @@ -644,7 +656,7 @@ void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb co } } -void QGIFFormat::nextY(QImage *image) +void QGIFFormat::nextY(unsigned char *bits, int bpl) { int my; switch (interlace) { @@ -660,7 +672,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } @@ -689,7 +701,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } @@ -713,7 +725,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } -- cgit v0.12 From b7d95c36f432f65d54343bf51e39e0b8b1d2d656 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 14 Dec 2009 09:05:37 +0100 Subject: gif: Add unit test for QImageReader::size calls Verify that QImageReader::size is not consuming a frame and can be called before each frame and that the last frame will return a QSize of (-1x-1). Task-number: QTBUG-6696 Reviewed-by: Andreas --- tests/auto/qimagereader/images/four-frames.gif | Bin 0 -> 427 bytes tests/auto/qimagereader/qimagereader.qrc | 2 + tests/auto/qimagereader/tst_qimagereader.cpp | 131 +++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 tests/auto/qimagereader/images/four-frames.gif diff --git a/tests/auto/qimagereader/images/four-frames.gif b/tests/auto/qimagereader/images/four-frames.gif new file mode 100644 index 0000000..6aff2e0 Binary files /dev/null and b/tests/auto/qimagereader/images/four-frames.gif differ diff --git a/tests/auto/qimagereader/qimagereader.qrc b/tests/auto/qimagereader/qimagereader.qrc index 11b9406..58f2f74 100644 --- a/tests/auto/qimagereader/qimagereader.qrc +++ b/tests/auto/qimagereader/qimagereader.qrc @@ -57,5 +57,7 @@ images/qt6.gif images/qt7.gif images/qt8.gif + images/endless-anim.gif + images/four-frames.gif diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 630cc03..3f9d005 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -141,6 +141,7 @@ private slots: #if defined QTEST_HAVE_GIF void gifHandlerBugs(); void animatedGif(); + void gifImageCount(); #endif void readCorruptImage_data(); @@ -739,6 +740,136 @@ void tst_QImageReader::animatedGif() image = io.read(); } } + +// http://bugreports.qt.nokia.com/browse/QTBUG-6696 +// Check the count of images in various call orders... +void tst_QImageReader::gifImageCount() +{ + // just read every frame... and see how much we got.. + { + QImageReader io(":images/four-frames.gif"); + + QVERIFY(io.canRead()); + QImage blackFrame = io.read(); + + QVERIFY(io.canRead()); + QImage whiteFrame = io.read(); + + QVERIFY(io.canRead()); + QImage greenFrame = io.read(); + + QVERIFY(io.canRead()); + QImage blueFrame = io.read(); + + QVERIFY(!io.canRead()); + QImage emptyFrame = io.read(); + + QVERIFY(!io.canRead()); + QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0)); + QCOMPARE(blackFrame.size(), QSize(64,64)); + + QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff)); + QCOMPARE(whiteFrame.size(), QSize(64,64)); + + QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0)); + QCOMPARE(greenFrame.size(), QSize(64,64)); + + QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff)); + QCOMPARE(blueFrame.size(), QSize(64,64)); + QVERIFY(emptyFrame.isNull()); + } + + // Read and get the size + { + QImageReader io(":images/four-frames.gif"); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QVERIFY(io.canRead()); + QImage blackFrame = io.read(); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QVERIFY(io.canRead()); + QImage whiteFrame = io.read(); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QVERIFY(io.canRead()); + QImage greenFrame = io.read(); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QVERIFY(io.canRead()); + QImage blueFrame = io.read(); + + QVERIFY(!io.canRead()); + QCOMPARE(io.size(), QSize()); + QCOMPARE(io.size(), QSize()); + QVERIFY(!io.canRead()); + QImage emptyFrame = io.read(); + + QVERIFY(!io.canRead()); + QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0)); + QCOMPARE(blackFrame.size(), QSize(64,64)); + + QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff)); + QCOMPARE(whiteFrame.size(), QSize(64,64)); + + QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0)); + QCOMPARE(greenFrame.size(), QSize(64,64)); + + QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff)); + QCOMPARE(blueFrame.size(), QSize(64,64)); + QVERIFY(emptyFrame.isNull()); + } + + // Do a Size query as substitute for canRead + { + QImageReader io(":images/four-frames.gif"); + + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QImage blackFrame = io.read(); + + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QImage whiteFrame = io.read(); + + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QImage greenFrame = io.read(); + + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QImage blueFrame = io.read(); + + QCOMPARE(io.size(), QSize()); + QVERIFY(!io.canRead()); + QImage emptyFrame = io.read(); + + QVERIFY(!io.canRead()); + QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0)); + QCOMPARE(blackFrame.size(), QSize(64,64)); + + QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff)); + QCOMPARE(whiteFrame.size(), QSize(64,64)); + + QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0)); + QCOMPARE(greenFrame.size(), QSize(64,64)); + + QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff)); + QCOMPARE(blueFrame.size(), QSize(64,64)); + QVERIFY(emptyFrame.isNull()); + } +} #endif class Server : public QObject -- cgit v0.12 From 6d9d6bf4b66127f7f24d22efa2fe6c24d05b3724 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 11 Oct 2009 04:12:47 +0200 Subject: images: Document QImageReader::loopCount behaviour for infinite loops The gif and mng reader will return -1 as QImageReader::loopCount() for infinite images. Document that this -1 is clashing with the error handling of this method. The documentation was mixing the default and error cases. In some cases "Otherwise -1" and "Otherwise 0" was used. Change this to mention the default coming from QImageIOHandler in the "Otherwise" clause and document the error case with -1. Add a test case to check that loopCount() returns -1 for infinite animations. Reviewed-by: Andreas --- src/gui/image/qimagereader.cpp | 22 ++++++++++++++-------- tests/auto/qimagereader/images/endless-anim.gif | Bin 0 -> 819 bytes tests/auto/qimagereader/tst_qimagereader.cpp | 7 +++++++ 3 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 tests/auto/qimagereader/images/endless-anim.gif diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 4fb07fb..c5aa28b 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1214,10 +1214,12 @@ bool QImageReader::jumpToImage(int imageNumber) /*! For image formats that support animation, this function returns - the number of times the animation should loop. Otherwise, it - returns -1. + the number of times the animation should loop. In case of an + infinite animation or an error -1 is returned. To differentiate + an infinite animation from an error, canRead() should be called + before this function. - \sa supportsAnimation(), QImageIOHandler::loopCount() + \sa supportsAnimation(), QImageIOHandler::loopCount(), canRead() */ int QImageReader::loopCount() const { @@ -1231,9 +1233,9 @@ int QImageReader::loopCount() const the total number of images in the animation. Certain animation formats do not support this feature, in which - case 0 is returned. + case 0 is returned. In case of an error -1 is returned. - \sa supportsAnimation(), QImageIOHandler::imageCount() + \sa supportsAnimation(), QImageIOHandler::imageCount(), canRead() */ int QImageReader::imageCount() const { @@ -1247,7 +1249,9 @@ int QImageReader::imageCount() const the number of milliseconds to wait until displaying the next frame in the animation. Otherwise, 0 is returned. - \sa supportsAnimation(), QImageIOHandler::nextImageDelay() + In case of an error -1 is returned. + + \sa supportsAnimation(), QImageIOHandler::nextImageDelay(), canRead() */ int QImageReader::nextImageDelay() const { @@ -1258,10 +1262,12 @@ int QImageReader::nextImageDelay() const /*! For image formats that support animation, this function returns - the sequence number of the current frame. Otherwise, -1 is + the sequence number of the current frame. Otherwise, 0 is returned. - \sa supportsAnimation(), QImageIOHandler::currentImageNumber() + In case of an error -1 is returned. + + \sa supportsAnimation(), QImageIOHandler::currentImageNumber(), canRead() */ int QImageReader::currentImageNumber() const { diff --git a/tests/auto/qimagereader/images/endless-anim.gif b/tests/auto/qimagereader/images/endless-anim.gif new file mode 100644 index 0000000..00df8da Binary files /dev/null and b/tests/auto/qimagereader/images/endless-anim.gif differ diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 3f9d005..8cfaac5 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -726,6 +726,13 @@ void tst_QImageReader::gifHandlerBugs() QVERIFY(!im1.isNull()); QVERIFY(!im2.isNull()); QCOMPARE(im1.convertToFormat(QImage::Format_ARGB32), im2.convertToFormat(QImage::Format_ARGB32)); } + + // Check the undocumented feature. + { + QImageReader io(prefix + "endless-anim.gif"); + QVERIFY(io.canRead()); + QCOMPARE(io.loopCount(), -1); + } } void tst_QImageReader::animatedGif() -- cgit v0.12 From 51b042f821f593808290e049e49f2f8bcd611fb0 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 23 Dec 2009 10:33:29 +0100 Subject: Docs: Amendments to latest changes to QImageReader docs. Reviewed-by: Holger Hans Peter Freyther --- src/gui/image/qimagereader.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index c5aa28b..7580446 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1213,11 +1213,10 @@ bool QImageReader::jumpToImage(int imageNumber) } /*! - For image formats that support animation, this function returns - the number of times the animation should loop. In case of an - infinite animation or an error -1 is returned. To differentiate - an infinite animation from an error, canRead() should be called - before this function. + For image formats that support animation, this function returns the number + of times the animation should loop. If this function returns -1, it can + either mean the animation should loop forever, or that an error occurred. + If an error occurred, canRead() will return false. \sa supportsAnimation(), QImageIOHandler::loopCount(), canRead() */ @@ -1229,11 +1228,11 @@ int QImageReader::loopCount() const } /*! - For image formats that support animation, this function returns - the total number of images in the animation. + For image formats that support animation, this function returns the total + number of images in the animation. If the format does not support + animation, 0 is returned. - Certain animation formats do not support this feature, in which - case 0 is returned. In case of an error -1 is returned. + This function returns -1 if an error occurred. \sa supportsAnimation(), QImageIOHandler::imageCount(), canRead() */ @@ -1245,11 +1244,11 @@ int QImageReader::imageCount() const } /*! - For image formats that support animation, this function returns - the number of milliseconds to wait until displaying the next frame - in the animation. Otherwise, 0 is returned. + For image formats that support animation, this function returns the number + of milliseconds to wait until displaying the next frame in the animation. + If the image format doesn't support animation, 0 is returned. - In case of an error -1 is returned. + This function returns -1 if an error occurred. \sa supportsAnimation(), QImageIOHandler::nextImageDelay(), canRead() */ @@ -1261,11 +1260,11 @@ int QImageReader::nextImageDelay() const } /*! - For image formats that support animation, this function returns - the sequence number of the current frame. Otherwise, 0 is - returned. + For image formats that support animation, this function returns the + sequence number of the current frame. If the image format doesn't support + animation, 0 is returned. - In case of an error -1 is returned. + This function returns -1 if an error occurred. \sa supportsAnimation(), QImageIOHandler::currentImageNumber(), canRead() */ -- cgit v0.12 From 0e03f6bbfd003d354c603a1a89b961e5f0d3769c Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Fri, 18 Dec 2009 10:08:45 -0800 Subject: Get rid of no_cast_from_ascii warning --- src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 4744eb6..8126fca 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1063,7 +1063,7 @@ static inline bool setIntOption(const QStringList &arguments, const QString &var static inline QColor colorFromName(const QString &name) { - QRegExp rx("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])"); + QRegExp rx(QLatin1String("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])")); rx.setCaseSensitivity(Qt::CaseInsensitive); if (rx.exactMatch(name)) { Q_ASSERT(rx.captureCount() == 4); -- cgit v0.12 From d27006b2a853924a11aa2bc45590c2c5c5fcfafa Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Fri, 18 Dec 2009 10:06:48 -0800 Subject: Read QWS_SIZE from layer rather than screen When running the X11 emulator of DirectFB IDirectFBScreen->GetSize returns the size of the entire X11 Display, not the actual DirectFB window. We can read this from the primary layer instead and this value is correct both on devices and on the desktop. Reviewed-by: Donald Carr --- src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 8126fca..bb26d29 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1278,7 +1278,14 @@ bool QDirectFBScreen::connect(const QString &displaySpec) #ifdef QT_NO_DIRECTFB_WM result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h); #elif (Q_DIRECTFB_VERSION >= 0x010000) - result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h); + IDirectFBSurface *layerSurface; + if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) != DFB_OK) { + result = layerSurface->GetSize(layerSurface, &w, &h); + layerSurface->Release(layerSurface); + } + if (w <= 0 || h <= 0) { + result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h); + } #else qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n" "query the size of the primary surface in windowed mode. You have to specify\n" -- cgit v0.12 From e416e8b439c7949faeeda5fda6edae2211e63eb2 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Wed, 23 Dec 2009 14:56:34 +0100 Subject: revert f36fb8b2b63b3734cc2bd66b329ca4fef1204845 as discussed at #qt-labs special dirs should be hidden on unix to preserve qt3-like behavior unhiding those dirs was not a good idea and now i do revert of my changes Merge-request: 1894 Reviewed-by: Joerg Bornemann --- src/corelib/io/qfsfileengine_unix.cpp | 5 ++--- src/corelib/io/qfsfileengine_win.cpp | 9 +++------ tests/auto/qfileinfo/tst_qfileinfo.cpp | 8 ++------ 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 71414ce..ea262bf 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -825,10 +825,9 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const ret |= RootFlag; } else { QString baseName = fileName(BaseName); - if ((baseName.size() > 1 - && baseName.at(0) == QLatin1Char('.') && baseName.at(1) != QLatin1Char('.')) + if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.')) # if !defined(QWS) && defined(Q_OS_MAC) - || _q_isMacHidden(d->filePath) + || _q_isMacHidden(d->filePath) # endif ) { ret |= HiddenFlag; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index a6cb5a9..a7719a8 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -1595,13 +1595,10 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil ret |= LocalDiskFlag; if (d->doStat()) { ret |= ExistsFlag; - if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath)) { + if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath)) ret |= RootFlag; - } else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN) { - QString baseName = fileName(BaseName); - if (baseName != QLatin1String(".") && baseName != QLatin1String("..")) - ret |= HiddenFlag; - } + else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN) + ret |= HiddenFlag; } } return ret; diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp index 1445f5b..84ea52b 100644 --- a/tests/auto/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp @@ -1083,13 +1083,9 @@ void tst_QFileInfo::isHidden_data() && !QDir().mkdir("./.hidden-directory")) qWarning("Unable to create directory './.hidden-directory'. Some tests will fail."); - QTest::newRow("./.hidden-directory") << QString("./.hidden-directory") << true; - QTest::newRow("./.hidden-directory/.") << QString("./.hidden-directory/.") << false; - QTest::newRow("./.hidden-directory/..") << QString("./.hidden-directory/..") << false; - QTest::newRow("/path/to/.hidden-directory") << QDir::currentPath() + QString("/.hidden-directory") << true; - QTest::newRow("/path/to/.hidden-directory/.") << QDir::currentPath() + QString("/.hidden-directory/.") << false; - QTest::newRow("/path/to/.hidden-directory/..") << QDir::currentPath() + QString("/.hidden-directory/..") << false; + QTest::newRow("/path/to/.hidden-directory/.") << QDir::currentPath() + QString("/.hidden-directory/.") << true; + QTest::newRow("/path/to/.hidden-directory/..") << QDir::currentPath() + QString("/.hidden-directory/..") << true; #endif #if defined(Q_OS_MAC) -- cgit v0.12 From 9709b10d691857209a684495799d163098bb44eb Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 28 Dec 2009 10:31:22 +0100 Subject: Move the 0.5 offset we add for aliased rendering to updateMatrix() The old code set and unset a temporary matrix for every draw command when doing aliased rendering. Instead, we just use a flag to indicate that updateMatrix() should add the offset. This means the offset is added only once. When doing lots of small rendering operations on a (non-multisampled) QGLWidget, this gives up to 72% performance boost on the SGX. Reviewed-By: Kim --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 75 +++++++++++++--------- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 5 +- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 32fa3dc..bfc640f 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -608,12 +608,18 @@ void QGL2PaintEngineExPrivate::updateMatrix() const GLfloat wfactor = 2.0f / width; const GLfloat hfactor = -2.0f / height; + if (addOffset) { + pmvMatrix[2][0] = (wfactor * (transform.dx() + 0.49f)) - transform.m33(); + pmvMatrix[2][1] = (hfactor * (transform.dy() + 0.49f)) + transform.m33(); + } else { + pmvMatrix[2][0] = (wfactor * transform.dx()) - transform.m33(); + pmvMatrix[2][1] = (hfactor * transform.dy()) + transform.m33(); + } + pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13(); pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23(); - pmvMatrix[2][0] = (wfactor * transform.dx() ) - transform.m33(); pmvMatrix[0][1] = (hfactor * transform.m12()) + transform.m13(); pmvMatrix[1][1] = (hfactor * transform.m22()) + transform.m23(); - pmvMatrix[2][1] = (hfactor * transform.dy() ) + transform.m33(); pmvMatrix[0][2] = transform.m13(); pmvMatrix[1][2] = transform.m23(); pmvMatrix[2][2] = transform.m33(); @@ -705,6 +711,12 @@ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& s // Setup for texture drawing currentBrush = noBrush; shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); + + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + if (prepareForDraw(opaque)) shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); @@ -867,6 +879,16 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) { transferMode(BrushDrawingMode); + const QOpenGL2PaintEngineState *s = q->state(); + const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && + (qbrush_style(currentBrush) == Qt::SolidPattern) && + !multisamplingAlwaysEnabled; + + if (addOffset != newAddOffset) { + addOffset = newAddOffset; + matrixDirty = true; + } + // Might need to call updateMatrix to re-calculate inverseScale if (matrixDirty) updateMatrix(); @@ -1278,31 +1300,14 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush) { Q_D(QGL2PaintEngineEx); - Qt::BrushStyle style = qbrush_style(brush); - if (style == Qt::NoBrush) + if (qbrush_style(brush) == Qt::NoBrush) return; + if (!d->inRenderText) ensureActive(); - QOpenGL2PaintEngineState *s = state(); - bool doOffset = !(s->renderHints & QPainter::Antialiasing) && - (style == Qt::SolidPattern) && - !d->multisamplingAlwaysEnabled; - - if (doOffset) { - d->temporaryTransform = s->matrix; - QTransform tx = QTransform::fromTranslate(.49, .49); - s->matrix = s->matrix * tx; - d->matrixDirty = true; - } - d->setBrush(brush); d->fill(path); - - if (doOffset) { - s->matrix = d->temporaryTransform; - d->matrixDirty = true; - } } extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp @@ -1326,11 +1331,9 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) ensureActive(); - bool doOffset = !(s->renderHints & QPainter::Antialiasing) && !d->multisamplingAlwaysEnabled; - if (doOffset) { - d->temporaryTransform = s->matrix; - QTransform tx = QTransform::fromTranslate(0.49, .49); - s->matrix = s->matrix * tx; + const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && !d->multisamplingAlwaysEnabled; + if (d->addOffset != newAddOffset) { + d->addOffset = newAddOffset; d->matrixDirty = true; } @@ -1401,11 +1404,6 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->updateClipScissorTest(); } - - if (doOffset) { - s->matrix = d->temporaryTransform; - d->matrixDirty = true; - } } void QGL2PaintEngineEx::penChanged() { } @@ -1613,6 +1611,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr) glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data()); + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + QBrush pensBrush = q->state()->pen.brush(); setBrush(pensBrush); @@ -1725,6 +1728,11 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d d->textureCoordinateArray.clear(); d->opacityArray.reset(); + if (d->addOffset) { + d->addOffset = false; + d->matrixDirty = true; + } + bool allOpaque = true; for (int i = 0; i < dataCount; ++i) { @@ -2006,6 +2014,11 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) { transferMode(BrushDrawingMode); + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + if (matrixDirty) updateMatrix(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 8de4a82..4ace030 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -171,6 +171,7 @@ public: q(q_ptr), width(0), height(0), ctx(0), + addOffset(false), inverseScale(1), shaderManager(0), inRenderText(false) @@ -246,8 +247,6 @@ public: QBrush currentBrush; // May not be the state's brush! const QBrush noBrush; - GLfloat inverseScale; - QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; QDataBuffer opacityArray; @@ -255,7 +254,9 @@ public: GLfloat staticVertexCoordinateArray[8]; GLfloat staticTextureCoordinateArray[8]; + bool addOffset; // When enabled, adds a 0.49,0.49 offset to matrix in updateMatrix GLfloat pmvMatrix[3][3]; + GLfloat inverseScale; QGLEngineShaderManager* shaderManager; -- cgit v0.12 From b06313579aad82f8dda64ad14384080754f2b222 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 28 Dec 2009 13:12:40 +0100 Subject: Lots of mostly cosmetic cleanups to GL2 paint engine * Move most of drawPixmaps to private * Move most of stroke to private * Remove dead code: context() * Make optimiseForBrushTransform use xform type * Use GLuint for uniform location * Rename lastTexture -> lastTextureUsed * Move qopengl2paintengine_cleanup_vectorpath to private * Re-ordered declarations in header * Remove dead temporaryTransform * Rename use_system_clip -> useSystemClip Reviewed-By: Kim --- .../gl2paintengineex/qglengineshadermanager.cpp | 6 +- .../gl2paintengineex/qglengineshadermanager_p.h | 4 +- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 177 +++++++++++---------- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 84 +++++----- 4 files changed, 133 insertions(+), 138 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 9d545b9..1d3801c 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -393,7 +393,7 @@ QGLEngineShaderManager::~QGLEngineShaderManager() removeCustomStage(); } -uint QGLEngineShaderManager::getUniformLocation(Uniform id) +GLuint QGLEngineShaderManager::getUniformLocation(const Uniform id) { if (!currentShaderProg) return 0; @@ -428,9 +428,9 @@ uint QGLEngineShaderManager::getUniformLocation(Uniform id) } -void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform &transform) +void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform::TransformationType transformType) { - Q_UNUSED(transform); // Currently ignored + Q_UNUSED(transformType); // Currently ignored } void QGLEngineShaderManager::setDirty() diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 50c1432..3749b5c 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -454,7 +454,7 @@ public: // There are optimisations we can do, depending on the brush transform: // 1) May not have to apply perspective-correction // 2) Can use lower precision for matrix - void optimiseForBrushTransform(const QTransform &transform); + void optimiseForBrushTransform(const QTransform::TransformationType transformType); void setSrcPixelType(Qt::BrushStyle); void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images void setOpacityMode(OpacityMode); @@ -463,7 +463,7 @@ public: void setCustomStage(QGLCustomShaderStage* stage); void removeCustomStage(); - uint getUniformLocation(Uniform id); + GLuint getUniformLocation(const Uniform id); void setDirty(); // someone has manually changed the current shader program bool useCorrectShaderProg(); // returns true if the shader program needed to be changed diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index bfc640f..d3a9547 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -358,10 +358,10 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) { // glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit? - if (id != GLuint(-1) && id == lastTexture) + if (id != GLuint(-1) && id == lastTextureUsed) return; - lastTexture = id; + lastTextureUsed = id; if (smoothPixmapTransform) { glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -407,7 +407,7 @@ void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush) } else { shaderManager->setSrcPixelType(newStyle); } - shaderManager->optimiseForBrushTransform(currentBrush.transform()); + shaderManager->optimiseForBrushTransform(currentBrush.transform().type()); } @@ -771,7 +771,7 @@ void QGL2PaintEngineEx::beginNativePainting() Q_UNUSED(ctx); #endif - d->lastTexture = GLuint(-1); + d->lastTextureUsed = GLuint(-1); d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); d->resetGLState(); @@ -798,12 +798,6 @@ void QGL2PaintEngineEx::endNativePainting() d->needsSync = true; } -const QGLContext *QGL2PaintEngineEx::context() -{ - Q_D(QGL2PaintEngineEx); - return d->ctx; -} - void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) { if (newMode == mode) @@ -814,7 +808,7 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); glDisableVertexAttribArray(QT_OPACITY_ATTR); - lastTexture = GLuint(-1); + lastTextureUsed = GLuint(-1); } if (newMode == TextDrawingMode) { @@ -862,13 +856,14 @@ struct QGL2PEVectorPathCache qreal iscale; }; -void qopengl2paintengine_cleanup_vectorpath(QPaintEngineEx *engine, void *data) +void QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data) { QGL2PEVectorPathCache *c = (QGL2PEVectorPathCache *) data; #ifdef QT_OPENGL_CACHE_AS_VBOS - QGL2PaintEngineExPrivate *d = QGL2PaintEngineExPrivate::getData((QGL2PaintEngineEx *) engine); - d->unusedVBOSToClean << c->vbo; + Q_ASSERT(engine->type() == QPaintEngine::OpenGL2); + static_cast(engine)->d_func()->unusedVBOSToClean << c->vbo; #else + Q_UNUSED(engine); qFree(c->vertices); #endif delete c; @@ -924,7 +919,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) } else { cache = new QGL2PEVectorPathCache; cache->vertexCount = 0; - data = const_cast(path).addCacheData(q, cache, qopengl2paintengine_cleanup_vectorpath); + data = const_cast(path).addCacheData(q, cache, cleanupVectorPath); } // Flatten the path at the current scale factor and fill it into the cache struct. @@ -1317,9 +1312,8 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) { Q_D(QGL2PaintEngineEx); - Qt::PenStyle penStyle = qpen_style(pen); const QBrush &penBrush = qpen_brush(pen); - if (penStyle == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush) + if (qpen_style(pen) == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush) return; QOpenGL2PaintEngineState *s = state(); @@ -1330,43 +1324,47 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) } ensureActive(); + d->setBrush(penBrush); + d->stroke(path, pen); +} - const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && !d->multisamplingAlwaysEnabled; - if (d->addOffset != newAddOffset) { - d->addOffset = newAddOffset; - d->matrixDirty = true; +void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen) +{ + const QOpenGL2PaintEngineState *s = q->state(); + const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && !multisamplingAlwaysEnabled; + if (addOffset != newAddOffset) { + addOffset = newAddOffset; + matrixDirty = true; } - bool opaque = penBrush.isOpaque() && s->opacity > 0.99; - d->setBrush(penBrush); - d->transferMode(BrushDrawingMode); + const Qt::PenStyle penStyle = qpen_style(pen); + const QBrush &penBrush = qpen_brush(pen); + const bool opaque = penBrush.isOpaque() && s->opacity > 0.99; + + transferMode(BrushDrawingMode); // updateMatrix() is responsible for setting the inverse scale on // the strokers, so we need to call it here and not wait for // prepareForDraw() down below. - d->updateMatrix(); + updateMatrix(); if (penStyle == Qt::SolidLine) { - d->stroker.process(path, pen); + stroker.process(path, pen); } else { // Some sort of dash - d->dasher.process(path, pen); + dasher.process(path, pen); - QVectorPath dashStroke(d->dasher.points(), - d->dasher.elementCount(), - d->dasher.elementTypes()); - d->stroker.process(dashStroke, pen); + QVectorPath dashStroke(dasher.points(), + dasher.elementCount(), + dasher.elementTypes()); + stroker.process(dashStroke, pen); } - - QGLContext *ctx = d->ctx; - Q_UNUSED(ctx); - if (opaque) { - d->prepareForDraw(opaque); + prepareForDraw(opaque); glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, d->stroker.vertices()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, d->stroker.vertexCount() / 2); + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, stroker.vertices()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, stroker.vertexCount() / 2); // QBrush b(Qt::green); // d->setBrush(&b); @@ -1384,25 +1382,25 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) : width; if (pen.isCosmetic()) - extra = extra * d->inverseScale; + extra = extra * inverseScale; QRectF bounds = path.controlPointRect().adjusted(-extra, -extra, extra, extra); - d->fillStencilWithVertexArray(d->stroker.vertices(), d->stroker.vertexCount() / 2, + fillStencilWithVertexArray(stroker.vertices(), stroker.vertexCount() / 2, 0, 0, bounds, QGL2PaintEngineExPrivate::TriStripStrokeFillMode); glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); // Pass when any bit is set, replace stencil value with 0 glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); - d->prepareForDraw(false); + prepareForDraw(false); // Stencil the brush onto the dest buffer - d->composite(bounds); + composite(bounds); glStencilMask(0); - d->updateClipScissorTest(); + updateClipScissorTest(); } } @@ -1442,7 +1440,7 @@ void QGL2PaintEngineEx::renderHintsChanged() #endif Q_D(QGL2PaintEngineEx); - d->lastTexture = GLuint(-1); + d->lastTextureUsed = GLuint(-1); d->brushTextureDirty = true; // qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!"); } @@ -1713,24 +1711,30 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) { + Q_D(QGL2PaintEngineEx); // Use fallback for extended composition modes. if (state()->composition_mode > QPainter::CompositionMode_Plus) { QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints); return; } - Q_D(QGL2PaintEngineEx); + ensureActive(); + d->drawPixmaps(drawingData, dataCount, pixmap, hints); +} + +void QGL2PaintEngineExPrivate::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) +{ GLfloat dx = 1.0f / pixmap.size().width(); GLfloat dy = 1.0f / pixmap.size().height(); - d->vertexCoordinateArray.clear(); - d->textureCoordinateArray.clear(); - d->opacityArray.reset(); + vertexCoordinateArray.clear(); + textureCoordinateArray.clear(); + opacityArray.reset(); - if (d->addOffset) { - d->addOffset = false; - d->matrixDirty = true; + if (addOffset) { + addOffset = false; + matrixDirty = true; } bool allOpaque = true; @@ -1748,31 +1752,28 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c); QGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c); - d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); QGLRect src(drawingData[i].source.left() * dx, drawingData[i].source.top() * dy, drawingData[i].source.right() * dx, drawingData[i].source.bottom() * dy); - d->textureCoordinateArray.lineToArray(src.right, src.bottom); - d->textureCoordinateArray.lineToArray(src.right, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.bottom); - d->textureCoordinateArray.lineToArray(src.right, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.top); + textureCoordinateArray.lineToArray(src.left, src.top); + textureCoordinateArray.lineToArray(src.left, src.top); + textureCoordinateArray.lineToArray(src.left, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.bottom); - qreal opacity = drawingData[i].opacity * state()->opacity; - d->opacityArray << opacity << opacity << opacity << opacity << opacity << opacity; + qreal opacity = drawingData[i].opacity * q->state()->opacity; + opacityArray << opacity << opacity << opacity << opacity << opacity << opacity; allOpaque &= (opacity >= 0.99f); } - ensureActive(); - - QGLContext *ctx = d->ctx; glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption @@ -1780,28 +1781,28 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d if (texture->options & QGLContext::InvertedYBindOption) { // Flip texture y-coordinate. - QGLPoint *data = d->textureCoordinateArray.data(); + QGLPoint *data = textureCoordinateArray.data(); for (int i = 0; i < 6 * dataCount; ++i) data[i].y = 1 - data[i].y; } - d->transferMode(ImageArrayDrawingMode); + transferMode(ImageArrayDrawingMode); bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QDrawPixmaps::OpaqueHint)) && allOpaque; - d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, - state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); + updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, + q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); // Setup for texture drawing - d->currentBrush = d->noBrush; - d->shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); - if (d->prepareForDraw(isOpaque)) - d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); + currentBrush = noBrush; + shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); + if (prepareForDraw(isOpaque)) + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); if (isBitmap) { - QColor col = qt_premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity); - d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::PatternColor), col); + QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); } glDrawArrays(GL_TRIANGLES, 0, 6 * dataCount); @@ -1833,7 +1834,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->compositionModeDirty = true; d->opacityUniformDirty = true; d->needsSync = true; - d->use_system_clip = !systemClip().isEmpty(); + d->useSystemClip = !systemClip().isEmpty(); d->currentBrush = QBrush(); d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); @@ -1954,12 +1955,12 @@ void QGL2PaintEngineExPrivate::updateClipScissorTest() #else QRect bounds = q->state()->rectangleClip; if (!q->state()->clipEnabled) { - if (use_system_clip) + if (useSystemClip) bounds = systemClip.boundingRect(); else bounds = QRect(0, 0, width, height); } else { - if (use_system_clip) + if (useSystemClip) bounds = bounds.intersected(systemClip.boundingRect()); else bounds = bounds.intersected(QRect(0, 0, width, height)); @@ -2118,7 +2119,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) switch (op) { case Qt::NoClip: - if (d->use_system_clip) { + if (d->useSystemClip) { state()->clipTestEnabled = true; state()->currentClip = 1; } else { @@ -2190,13 +2191,13 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->clipChanged = true; if (systemClip.isEmpty()) { - use_system_clip = false; + useSystemClip = false; } else { if (q->paintDevice()->devType() == QInternal::Widget && currentClipWidget) { QWidgetPrivate *widgetPrivate = qt_widget_private(currentClipWidget->window()); - use_system_clip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; + useSystemClip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; } else { - use_system_clip = true; + useSystemClip = true; } } @@ -2206,19 +2207,19 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->currentClip = 1; maxClip = 1; - q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height); + q->state()->rectangleClip = useSystemClip ? systemClip.boundingRect() : QRect(0, 0, width, height); updateClipScissorTest(); if (systemClip.rectCount() == 1) { if (systemClip.boundingRect() == QRect(0, 0, width, height)) - use_system_clip = false; + useSystemClip = false; #ifndef QT_GL_NO_SCISSOR_TEST // scissoring takes care of the system clip return; #endif } - if (use_system_clip) { + if (useSystemClip) { clearClip(0); QPainterPath path; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 4ace030..c94c4f4 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -105,13 +105,8 @@ public: ~QGL2PaintEngineEx(); bool begin(QPaintDevice *device); - bool end(); - void ensureActive(); - - virtual void fill(const QVectorPath &path, const QBrush &brush); - virtual void stroke(const QVectorPath &path, const QPen &pen); - virtual void clip(const QVectorPath &path, Qt::ClipOperation op); + bool end(); virtual void clipEnabledChanged(); virtual void penChanged(); @@ -122,20 +117,21 @@ public: virtual void renderHintsChanged(); virtual void transformChanged(); - + virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); - virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); - virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); + virtual void fill(const QVectorPath &path, const QBrush &brush); + virtual void stroke(const QVectorPath &path, const QPen &pen); + virtual void clip(const QVectorPath &path, Qt::ClipOperation op); - virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); Type type() const { return OpenGL2; } - void setState(QPainterState *s); - QPainterState *createState(QPainterState *orig) const; + virtual void setState(QPainterState *s); + virtual QPainterState *createState(QPainterState *orig) const; inline QOpenGL2PaintEngineState *state() { return static_cast(QPaintEngineEx::state()); } @@ -146,8 +142,6 @@ public: void beginNativePainting(); void endNativePainting(); - const QGLContext* context(); - QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype); void setRenderTextActive(bool); @@ -169,11 +163,12 @@ public: QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) : q(q_ptr), + shaderManager(0), width(0), height(0), ctx(0), + useSystemClip(true), addOffset(false), inverseScale(1), - shaderManager(0), inRenderText(false) { } @@ -185,45 +180,62 @@ public: void updateCompositionMode(); void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1); - void setBrush(const QBrush& brush); - - void transferMode(EngineMode newMode); void resetGLState(); - // fill, drawOutline, drawTexture & drawCachedGlyphs are the rendering entry points: + // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points, + // however writeClip can also be thought of as en entry point as it does similar things. void fill(const QVectorPath &path); + void stroke(const QVectorPath &path, const QPen &pen); void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); + void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); void drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType, const QTextItemInt &ti); + // draws whatever is in the vertex array: void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive); void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) { drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive); } - // ^ draws whatever is in the vertex array + // Composites the bounding rect onto dest buffer: void composite(const QGLRect& boundingRect); - // ^ Composites the bounding rect onto dest buffer + // Calls drawVertexArrays to render into stencil buffer: void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QGLRect &bounds, StencilFillMode mode); void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) { fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(), vertexArray.boundingRect(), useWindingFill ? WindingFillMode : OddEvenFillMode); } - // ^ Calls drawVertexArrays to render into stencil buffer - - bool prepareForDraw(bool srcPixelsAreOpaque); - // ^ returns whether the current program changed or not + void setBrush(const QBrush& brush); + void transferMode(EngineMode newMode); + bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed inline void useSimpleShader(); + inline GLuint location(const QGLEngineShaderManager::Uniform uniform) { + return shaderManager->getUniformLocation(uniform); + } + void prepareDepthRangeForRenderText(); void restoreDepthRangeForRenderText(); + void clearClip(uint value); + void writeClip(const QVectorPath &path, uint value); + void resetClipIfNeeded(); + + void updateClipScissorTest(); + void setScissor(const QRect &rect); + void regenerateClip(); + void systemStateChanged(); + + static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; } static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); } + static void cleanupVectorPath(QPaintEngineEx *engine, void *data); + QGL2PaintEngineEx* q; + QGLEngineShaderManager* shaderManager; QGLPaintDevice* device; int width, height; QGLContext *ctx; @@ -240,6 +252,7 @@ public: bool opacityUniformDirty; bool stencilClean; // Has the stencil not been used for clipping so far? + bool useSystemClip; QRegion dirtyStencilRegion; QRect currentScissorBounds; uint maxClip; @@ -250,7 +263,6 @@ public: QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; QDataBuffer opacityArray; - GLfloat staticVertexCoordinateArray[8]; GLfloat staticTextureCoordinateArray[8]; @@ -258,24 +270,7 @@ public: GLfloat pmvMatrix[3][3]; GLfloat inverseScale; - QGLEngineShaderManager* shaderManager; - - void clearClip(uint value); - void writeClip(const QVectorPath &path, uint value); - void resetClipIfNeeded(); - - void updateClipScissorTest(); - void setScissor(const QRect &rect); - void regenerateClip(); - void systemStateChanged(); - uint use_system_clip : 1; - - uint location(QGLEngineShaderManager::Uniform uniform) - { - return shaderManager->getUniformLocation(uniform); - } - - GLuint lastTexture; + GLuint lastTextureUsed; bool needsSync; bool inRenderText; @@ -287,7 +282,6 @@ public: QTriangulatingStroker stroker; QDashedStrokeProcessor dasher; - QTransform temporaryTransform; QScopedPointer convolutionFilter; QScopedPointer colorizeFilter; -- cgit v0.12 From 6e90192b599cee9b903177a0978198326f667613 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 28 Dec 2009 13:58:25 +0100 Subject: QStyleSheetStyle: Fixed some text croped when having padding with native border. The native border width need to be taken into account in QRenderRule::boxRect() Task-number: QTBUG-6855 Reviewed-by: Benjamin Poulain --- src/gui/styles/qstylesheetstyle.cpp | 2 +- tests/auto/uiloader/baseline/css_qtbug6855.ui | 57 +++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/auto/uiloader/baseline/css_qtbug6855.ui diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 8b40931..aff3ac0 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -1065,7 +1065,7 @@ QRect QRenderRule::boxRect(const QRect& cr, int flags) const r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]); } } - if (!hasNativeBorder() && (flags & Border)) { + if (hasBorder() && (flags & Border)) { const int *b = border()->borders; r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]); } diff --git a/tests/auto/uiloader/baseline/css_qtbug6855.ui b/tests/auto/uiloader/baseline/css_qtbug6855.ui new file mode 100644 index 0000000..0727f6b --- /dev/null +++ b/tests/auto/uiloader/baseline/css_qtbug6855.ui @@ -0,0 +1,57 @@ + + + Form + + + + 0 + 0 + 212 + 108 + + + + Form + + + QPushButton { padding: 20px; } + + + + + + Text not cropped + + + + + + + Qt::Horizontal + + + + 258 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 218 + + + + + + + + + -- cgit v0.12 From d0c3d9770b5c33810f12e409e2304957079a2608 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 28 Dec 2009 15:55:02 +0100 Subject: Fix tst_QFileInfo::isHidden_data on Windows Commit d27006b2a853924a11aa2bc45 did not fully revert the test --- tests/auto/qfileinfo/tst_qfileinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp index 84ea52b..5ea7100 100644 --- a/tests/auto/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp @@ -1074,8 +1074,8 @@ void tst_QFileInfo::isHidden_data() #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) QTest::newRow("C:/RECYCLER") << QString::fromLatin1("C:/RECYCLER") << true; - QTest::newRow("C:/RECYCLER/.") << QString::fromLatin1("C:/RECYCLER/.") << false; - QTest::newRow("C:/RECYCLER/..") << QString::fromLatin1("C:/RECYCLER/..") << false; + QTest::newRow("C:/RECYCLER/.") << QString::fromLatin1("C:/RECYCLER/.") << true; + QTest::newRow("C:/RECYCLER/..") << QString::fromLatin1("C:/RECYCLER/..") << true; #endif #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) -- cgit v0.12 From 8c306f8ee137baebc312a126c4e0d27bb9150f69 Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 28 Dec 2009 17:56:14 +0100 Subject: QUrl::toEncoded() fix for the case of "password, but no username". QUrl::setPassword() without QUrl::setUserName() is actually useful, e.g. for kde's ldap:// slave. QUrl::toString() already handled this correctly, but QUrl::toEncoded() would forget the password in such a case. Autotest added. Merge-request: 2276 Reviewed-by: Olivier Goffart --- src/corelib/io/qurl.cpp | 14 +++++++++----- tests/auto/qurl/tst_qurl.cpp | 7 +++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index fd51bcf..6ac6468 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -3864,14 +3864,18 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const url += "//"; if ((options & QUrl::RemoveUserInfo) != QUrl::RemoveUserInfo) { + bool hasUserOrPass = false; if (!userName.isEmpty()) { url += encodedUserName; - if (!(options & QUrl::RemovePassword) && !password.isEmpty()) { - url += ':'; - url += encodedPassword; - } - url += '@'; + hasUserOrPass = true; } + if (!(options & QUrl::RemovePassword) && !password.isEmpty()) { + url += ':'; + url += encodedPassword; + hasUserOrPass = true; + } + if (hasUserOrPass) + url += '@'; } if (host.startsWith(QLatin1Char('['))) { diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 03e77aa..70cfb61 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -1682,6 +1682,12 @@ void tst_QUrl::toString_constructed_data() << QByteArray("//qt.nokia.com/index.html"); QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QByteArray() << n << QString::fromLatin1("file:///root") << QByteArray("file:///root"); + QTest::newRow("userAndPass") << QString::fromLatin1("http") << QString::fromLatin1("dfaure") << QString::fromLatin1("kde") + << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n + << QString::fromLatin1("http://dfaure:kde@kde.org:443/") << QByteArray("http://dfaure:kde@kde.org:443/"); + QTest::newRow("PassWithoutUser") << QString::fromLatin1("http") << n << QString::fromLatin1("kde") + << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n + << QString::fromLatin1("http://:kde@kde.org:443/") << QByteArray("http://:kde@kde.org:443/"); } void tst_QUrl::toString_constructed() @@ -1717,6 +1723,7 @@ void tst_QUrl::toString_constructed() QVERIFY(url.isValid()); QCOMPARE(url.toString(), asString); + QCOMPARE(QString::fromLatin1(url.toEncoded()), QString::fromLatin1(asEncoded)); // readable in case of differences QCOMPARE(url.toEncoded(), asEncoded); } -- cgit v0.12