src/gui/image/qpixmap_raster.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qpixmap.h"
       
    43 
       
    44 #include "qpixmap_raster_p.h"
       
    45 #include "qnativeimage_p.h"
       
    46 #include "qimage_p.h"
       
    47 
       
    48 #include "qbitmap.h"
       
    49 #include "qimage.h"
       
    50 #include <private/qwidget_p.h>
       
    51 #include <private/qdrawhelper_p.h>
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
       
    56                                      0x10, 0x20, 0x40, 0x80 };
       
    57 
       
    58 QPixmap qt_toRasterPixmap(const QImage &image)
       
    59 {
       
    60     QPixmapData *data =
       
    61         new QRasterPixmapData(image.depth() == 1
       
    62                            ? QPixmapData::BitmapType
       
    63                            : QPixmapData::PixmapType);
       
    64 
       
    65     data->fromImage(image, Qt::AutoColor);
       
    66 
       
    67     return QPixmap(data);
       
    68 }
       
    69 
       
    70 QPixmap qt_toRasterPixmap(const QPixmap &pixmap)
       
    71 {
       
    72     if (pixmap.isNull())
       
    73         return QPixmap();
       
    74 
       
    75     if (QPixmap(pixmap).data_ptr()->classId() == QPixmapData::RasterClass)
       
    76         return pixmap;
       
    77 
       
    78     return qt_toRasterPixmap(pixmap.toImage());
       
    79 }
       
    80 
       
    81 QRasterPixmapData::QRasterPixmapData(PixelType type)
       
    82     : QPixmapData(type, RasterClass)
       
    83 {
       
    84 }
       
    85 
       
    86 QRasterPixmapData::~QRasterPixmapData()
       
    87 {
       
    88 }
       
    89 
       
    90 QPixmapData *QRasterPixmapData::createCompatiblePixmapData() const
       
    91 {
       
    92     return new QRasterPixmapData(pixelType());
       
    93 }
       
    94 
       
    95 void QRasterPixmapData::resize(int width, int height)
       
    96 {
       
    97     QImage::Format format;
       
    98 #ifdef Q_WS_QWS
       
    99     if (pixelType() == BitmapType) {
       
   100         format = QImage::Format_Mono;
       
   101     } else {
       
   102         format = QScreen::instance()->pixelFormat();
       
   103         if (format == QImage::Format_Invalid)
       
   104             format = QImage::Format_ARGB32_Premultiplied;
       
   105         else if (format == QImage::Format_Indexed8) // currently not supported
       
   106             format = QImage::Format_RGB444;
       
   107     }
       
   108 #else
       
   109     if (pixelType() == BitmapType)
       
   110         format = QImage::Format_MonoLSB;
       
   111     else
       
   112         format = QNativeImage::systemFormat();
       
   113 #endif
       
   114 
       
   115     image = QImage(width, height, format);
       
   116     w = width;
       
   117     h = height;
       
   118     d = image.depth();
       
   119     is_null = (w <= 0 || h <= 0);
       
   120 
       
   121     if (pixelType() == BitmapType && !image.isNull()) {
       
   122         image.setNumColors(2);
       
   123         image.setColor(0, QColor(Qt::color0).rgba());
       
   124         image.setColor(1, QColor(Qt::color1).rgba());
       
   125     }
       
   126 
       
   127     setSerialNumber(image.serialNumber());
       
   128 }
       
   129 
       
   130 void QRasterPixmapData::fromImage(const QImage &sourceImage,
       
   131                                   Qt::ImageConversionFlags flags)
       
   132 {
       
   133     Q_UNUSED(flags);
       
   134 
       
   135 #ifdef Q_WS_QWS
       
   136     QImage::Format format;
       
   137     if (pixelType() == BitmapType) {
       
   138         format = QImage::Format_Mono;
       
   139     } else {
       
   140         format = QScreen::instance()->pixelFormat();
       
   141         if (format == QImage::Format_Invalid)
       
   142             format = QImage::Format_ARGB32_Premultiplied;
       
   143         else if (format == QImage::Format_Indexed8) // currently not supported
       
   144             format = QImage::Format_RGB444;
       
   145     }
       
   146 
       
   147     if (sourceImage.hasAlphaChannel()
       
   148         && ((flags & Qt::NoOpaqueDetection)
       
   149             || const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())) {
       
   150         switch (format) {
       
   151             case QImage::Format_RGB16:
       
   152                 format = QImage::Format_ARGB8565_Premultiplied;
       
   153                 break;
       
   154             case QImage::Format_RGB666:
       
   155                 format = QImage::Format_ARGB6666_Premultiplied;
       
   156                 break;
       
   157             case QImage::Format_RGB555:
       
   158                 format = QImage::Format_ARGB8555_Premultiplied;
       
   159                 break;
       
   160             case QImage::Format_RGB444:
       
   161                 format = QImage::Format_ARGB4444_Premultiplied;
       
   162                 break;
       
   163             default:
       
   164                 format = QImage::Format_ARGB32_Premultiplied;
       
   165                 break;
       
   166         }
       
   167     } else if (format == QImage::Format_Invalid) {
       
   168         format = QImage::Format_ARGB32_Premultiplied;
       
   169     }
       
   170 
       
   171     image = sourceImage.convertToFormat(format);
       
   172 #else
       
   173     if (pixelType() == BitmapType) {
       
   174         image = sourceImage.convertToFormat(QImage::Format_MonoLSB);
       
   175     } else {
       
   176         if (sourceImage.depth() == 1) {
       
   177             image = sourceImage.hasAlphaChannel()
       
   178                     ? sourceImage.convertToFormat(QImage::Format_ARGB32_Premultiplied)
       
   179                     : sourceImage.convertToFormat(QImage::Format_RGB32);
       
   180         } else {
       
   181 
       
   182             QImage::Format opaqueFormat = QNativeImage::systemFormat();
       
   183             QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
       
   184 
       
   185             switch (opaqueFormat) {
       
   186             case QImage::Format_RGB16:
       
   187                 alphaFormat = QImage::Format_ARGB8565_Premultiplied;
       
   188                 break;
       
   189             default: // We don't care about the others...
       
   190                 break;
       
   191             }
       
   192 
       
   193             if (!sourceImage.hasAlphaChannel()
       
   194                 || ((flags & Qt::NoOpaqueDetection) == 0
       
   195                     && !const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())) {
       
   196                 image = sourceImage.convertToFormat(opaqueFormat);
       
   197             } else {
       
   198                 image = sourceImage.convertToFormat(alphaFormat);
       
   199             }
       
   200         }
       
   201     }
       
   202 #endif
       
   203     if (image.d) {
       
   204         w = image.d->width;
       
   205         h = image.d->height;
       
   206         d = image.d->depth;
       
   207     } else {
       
   208         w = h = d = 0;
       
   209     }
       
   210     is_null = (w <= 0 || h <= 0);
       
   211 
       
   212     setSerialNumber(image.serialNumber());
       
   213 }
       
   214 
       
   215 // from qwindowsurface.cpp
       
   216 extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
       
   217 
       
   218 bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect)
       
   219 {
       
   220     if (!image.isNull())
       
   221         qt_scrollRectInImage(image, rect, QPoint(dx, dy));
       
   222     return true;
       
   223 }
       
   224 
       
   225 void QRasterPixmapData::fill(const QColor &color)
       
   226 {
       
   227     uint pixel;
       
   228 
       
   229     if (image.depth() == 1) {
       
   230         int gray = qGray(color.rgba());
       
   231         // Pick the best approximate color in the image's colortable.
       
   232         if (qAbs(qGray(image.color(0)) - gray) < qAbs(qGray(image.color(1)) - gray))
       
   233             pixel = 0;
       
   234         else
       
   235             pixel = 1;
       
   236     } else if (image.depth() >= 15) {
       
   237         int alpha = color.alpha();
       
   238         if (alpha != 255) {
       
   239             if (!image.hasAlphaChannel()) {
       
   240                 QImage::Format toFormat;
       
   241                 if (image.format() == QImage::Format_RGB16)
       
   242                     toFormat = QImage::Format_ARGB8565_Premultiplied;
       
   243                 else if (image.format() == QImage::Format_RGB666)
       
   244                     toFormat = QImage::Format_ARGB6666_Premultiplied;
       
   245                 else if (image.format() == QImage::Format_RGB555)
       
   246                     toFormat = QImage::Format_ARGB8555_Premultiplied;
       
   247                 else if (image.format() == QImage::Format_RGB444)
       
   248                     toFormat = QImage::Format_ARGB4444_Premultiplied;
       
   249                 else
       
   250                     toFormat = QImage::Format_ARGB32_Premultiplied;
       
   251                 image = QImage(image.width(), image.height(), toFormat);
       
   252             }
       
   253 
       
   254             switch (image.format()) {
       
   255             case QImage::Format_ARGB8565_Premultiplied:
       
   256                 pixel = qargb8565(color.rgba()).rawValue();
       
   257                 break;
       
   258             case QImage::Format_ARGB8555_Premultiplied:
       
   259                 pixel = qargb8555(color.rgba()).rawValue();
       
   260                 break;
       
   261             case QImage::Format_ARGB6666_Premultiplied:
       
   262                 pixel = qargb6666(color.rgba()).rawValue();
       
   263                 break;
       
   264             case QImage::Format_ARGB4444_Premultiplied:
       
   265                 pixel = qargb4444(color.rgba()).rawValue();
       
   266                 break;
       
   267             default:
       
   268                 pixel = PREMUL(color.rgba());
       
   269                 break;
       
   270             }
       
   271         } else {
       
   272             switch (image.format()) {
       
   273             case QImage::Format_RGB16:
       
   274                 pixel = qt_colorConvert<quint16, quint32>(color.rgba(), 0);
       
   275                 break;
       
   276             case QImage::Format_RGB444:
       
   277                 pixel = qrgb444(color.rgba()).rawValue();
       
   278                 break;
       
   279             case QImage::Format_RGB555:
       
   280                 pixel = qrgb555(color.rgba()).rawValue();
       
   281                 break;
       
   282             case QImage::Format_RGB666:
       
   283                 pixel = qrgb666(color.rgba()).rawValue();
       
   284                 break;
       
   285             case QImage::Format_RGB888:
       
   286                 pixel = qrgb888(color.rgba()).rawValue();
       
   287                 break;
       
   288             default:
       
   289                 pixel = color.rgba();
       
   290                 break;
       
   291             }
       
   292         }
       
   293     } else {
       
   294         pixel = 0;
       
   295         // ### what about 8 bits
       
   296     }
       
   297 
       
   298     image.fill(pixel);
       
   299 }
       
   300 
       
   301 void QRasterPixmapData::setMask(const QBitmap &mask)
       
   302 {
       
   303     if (mask.size().isEmpty()) {
       
   304         if (image.depth() != 1) { // hw: ????
       
   305             image = image.convertToFormat(QImage::Format_RGB32);
       
   306         }
       
   307     } else {
       
   308         const int w = image.width();
       
   309         const int h = image.height();
       
   310 
       
   311         switch (image.depth()) {
       
   312         case 1: {
       
   313             const QImage imageMask = mask.toImage().convertToFormat(image.format());
       
   314             for (int y = 0; y < h; ++y) {
       
   315                 const uchar *mscan = imageMask.scanLine(y);
       
   316                 uchar *tscan = image.scanLine(y);
       
   317                 int bytesPerLine = image.bytesPerLine();
       
   318                 for (int i = 0; i < bytesPerLine; ++i)
       
   319                     tscan[i] &= mscan[i];
       
   320             }
       
   321             break;
       
   322         }
       
   323         default: {
       
   324             const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
       
   325             image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
       
   326             for (int y = 0; y < h; ++y) {
       
   327                 const uchar *mscan = imageMask.scanLine(y);
       
   328                 QRgb *tscan = (QRgb *)image.scanLine(y);
       
   329                 for (int x = 0; x < w; ++x) {
       
   330                     if (!(mscan[x>>3] & qt_pixmap_bit_mask[x&7]))
       
   331                         tscan[x] = 0;
       
   332                 }
       
   333             }
       
   334             break;
       
   335         }
       
   336         }
       
   337     }
       
   338 }
       
   339 
       
   340 bool QRasterPixmapData::hasAlphaChannel() const
       
   341 {
       
   342     return image.hasAlphaChannel();
       
   343 }
       
   344 
       
   345 QImage QRasterPixmapData::toImage() const
       
   346 {
       
   347     return image;
       
   348 }
       
   349 
       
   350 void QRasterPixmapData::setAlphaChannel(const QPixmap &alphaChannel)
       
   351 {
       
   352     image.setAlphaChannel(alphaChannel.toImage());
       
   353 }
       
   354 
       
   355 QPaintEngine* QRasterPixmapData::paintEngine() const
       
   356 {
       
   357     return image.paintEngine();
       
   358 }
       
   359 
       
   360 extern int qt_defaultDpiX();
       
   361 extern int qt_defaultDpiY();
       
   362 
       
   363 int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
       
   364 {
       
   365     QImageData *d = image.d;
       
   366     if (!d)
       
   367         return 0;
       
   368 
       
   369     // override the image dpi with the screen dpi when rendering to a pixmap
       
   370     switch (metric) {
       
   371     case QPaintDevice::PdmWidth:
       
   372         return w;
       
   373     case QPaintDevice::PdmHeight:
       
   374         return h;
       
   375     case QPaintDevice::PdmWidthMM:
       
   376         return qRound(d->width * 25.4 / qt_defaultDpiX());
       
   377     case QPaintDevice::PdmHeightMM:
       
   378         return qRound(d->width * 25.4 / qt_defaultDpiY());
       
   379     case QPaintDevice::PdmNumColors:
       
   380         return d->colortable.size();
       
   381     case QPaintDevice::PdmDepth:
       
   382         return this->d;
       
   383     case QPaintDevice::PdmDpiX: // fall-through
       
   384     case QPaintDevice::PdmPhysicalDpiX:
       
   385         return qt_defaultDpiX();
       
   386     case QPaintDevice::PdmDpiY: // fall-through
       
   387     case QPaintDevice::PdmPhysicalDpiY:
       
   388         return qt_defaultDpiY();
       
   389     default:
       
   390         qWarning("QRasterPixmapData::metric(): Unhandled metric type %d", metric);
       
   391         break;
       
   392     }
       
   393 
       
   394     return 0;
       
   395 }
       
   396 
       
   397 QImage* QRasterPixmapData::buffer()
       
   398 {
       
   399     return &image;
       
   400 }
       
   401 
       
   402 QT_END_NAMESPACE