Blob Blame History Raw
commit 2b739c70f008ac2538eb635b7334104167ad0a50
Author: Marcel Wiesweg <marcel.wiesweg@gmx.de>
Date:   Sat Aug 6 16:51:41 2011 +0200

    Pass a persistent QImage to QPixmap::fromImage when paint engine is raster.
    For native engines, a temporary QImage can be provided, but raster will just take
    and store the QImage, so a memcpy is needed.
    The paint engine relevant for pixmaps can be detected by opening a painter on a
    1x1 pixmap and querying the QPaintEngine. For optimization, this is done only once
    per application lifetime because DImg::convertToPixmap is very time critical.
    
    BUG: 278320

--- a/libs/dimg/dimg.cpp
+++ b/libs/dimg/dimg.cpp
@@ -47,6 +47,8 @@ extern "C"
 #include <QFile>
 #include <QFileInfo>
 #include <QMap>
+#include <QPaintEngine>
+#include <QPainter>
 #include <QPixmap>
 #include <QSysInfo>
 #include <QDebug>
@@ -55,6 +57,7 @@ extern "C"
 // KDE includes
 
 #include <kdebug.h>
+#include <kglobal.h>
 
 // LibKDcraw includes
 
@@ -1768,6 +1771,34 @@ QImage DImg::copyQImage(int x, int y, int w, int h) const
     return img.copyQImage();
 }
 
+class PixmapPaintEngineDetector
+{
+public:
+
+    PixmapPaintEngineDetector()
+        : m_isRaster(detectRasterFromPixmap())
+    {
+    }
+
+    bool isRaster() const
+    {
+        return m_isRaster;
+    }
+
+private:
+
+    static bool detectRasterFromPixmap()
+    {
+        QPixmap pix(1,1);
+        QPainter p(&pix);
+        return p.paintEngine() && p.paintEngine()->type() == QPaintEngine::Raster;
+    }
+
+    const bool m_isRaster;
+};
+
+K_GLOBAL_STATIC(PixmapPaintEngineDetector, pixmapPaintEngineDetector)
+
 QPixmap DImg::convertToPixmap() const
 {
     if (isNull())
@@ -1796,18 +1827,21 @@ QPixmap DImg::convertToPixmap() const
             sptr += 4;
         }
 
-        // NOTE: Qt4 do not provide anymore QImage::setAlphaChannel() because
         // alpha channel is auto-detected during QImage->QPixmap conversion
-
         return QPixmap::fromImage(img);
     }
     else
     {
+        // This is a temporary image operating on the DImg buffer
         QImage img(bits(), width(), height(), hasAlpha() ? QImage::Format_ARGB32 : QImage::Format_RGB32);
 
-        // NOTE: Qt4 do not provide anymore QImage::setAlphaChannel() because
-        // alpha channel is auto-detected during QImage->QPixmap conversion
+        // For paint engines which base the QPixmap internally on a QImage, we must use a persistent QImage
+        if (pixmapPaintEngineDetector->isRaster())
+        {
+            img = img.copy();
+        }
 
+        // alpha channel is auto-detected during QImage->QPixmap conversion
         return QPixmap::fromImage(img);
     }
 }