Changeset 846 for trunk/src/gui/image


Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
66 edited
16 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/image/image.pri

    r561 r846  
    2929        image/qpixmapdatafactory_p.h \
    3030        image/qpixmapfilter_p.h \
    31         image/qimagepixmapcleanuphooks_p.h \
    32 
     31        image/qimagepixmapcleanuphooks_p.h
    3332
    3433SOURCES += \
     
    5352        image/qpixmap_raster.cpp \
    5453        image/qnativeimage.cpp \
    55         image/qimagepixmapcleanuphooks.cpp \
    56 
     54        image/qimagepixmapcleanuphooks.cpp
    5755
    5856win32 {
    5957    SOURCES += image/qpixmap_win.cpp
    6058}
    61 os2 {
     59else:os2 {
    6260    SOURCES += image/qpixmap_pm.cpp
    6361}
    64 embedded {
     62else:embedded {
    6563    SOURCES += image/qpixmap_qws.cpp
    6664}
    67 x11 {
     65else:x11 {
    6866    HEADERS += image/qpixmap_x11_p.h
    69     SOURCES += image/qpixmap_x11.cpp 
     67    SOURCES += image/qpixmap_x11.cpp
    7068}
    71 mac {
     69else:mac {
    7270    HEADERS += image/qpixmap_mac_p.h
    7371    SOURCES += image/qpixmap_mac.cpp
    7472}
    75 symbian {
     73else:symbian {
    7674    HEADERS += image/qpixmap_s60_p.h
    7775    SOURCES += image/qpixmap_s60.cpp
     
    9189        image/qxpmhandler.cpp
    9290
    93 # 3rd party / system PNG support
    94 !contains(QT_CONFIG, no-png) {
    95     HEADERS += image/qpnghandler_p.h
    96     SOURCES += image/qpnghandler.cpp
     91!contains(QT_CONFIG, no-png):include($$PWD/qpnghandler.pri)
     92else:DEFINES *= QT_NO_IMAGEFORMAT_PNG
    9793
    98     contains(QT_CONFIG, system-png) {
    99         unix:LIBS_PRIVATE  += -lpng
    100         win32:LIBS += libpng.lib
    101     } else {
    102         !isEqual(QT_ARCH, i386):!isEqual(QT_ARCH, x86_64):DEFINES += PNG_NO_ASSEMBLER_CODE
    103         INCLUDEPATH  += ../3rdparty/libpng ../3rdparty/zlib
    104         SOURCES += ../3rdparty/libpng/png.c \
    105           ../3rdparty/libpng/pngerror.c \
    106           ../3rdparty/libpng/pngget.c \
    107           ../3rdparty/libpng/pngmem.c \
    108           ../3rdparty/libpng/pngpread.c \
    109           ../3rdparty/libpng/pngread.c \
    110           ../3rdparty/libpng/pngrio.c \
    111           ../3rdparty/libpng/pngrtran.c \
    112           ../3rdparty/libpng/pngrutil.c \
    113           ../3rdparty/libpng/pngset.c \
    114           ../3rdparty/libpng/pngtrans.c \
    115           ../3rdparty/libpng/pngwio.c \
    116           ../3rdparty/libpng/pngwrite.c \
    117           ../3rdparty/libpng/pngwtran.c \
    118           ../3rdparty/libpng/pngwutil.c \
    119           ../3rdparty/libpng/pnggccrd.c
    120     }
    121 } else {
    122     DEFINES *= QT_NO_IMAGEFORMAT_PNG
    123 }
     94contains(QT_CONFIG, jpeg):include($$PWD/qjpeghandler.pri)
     95contains(QT_CONFIG, mng):include($$PWD/qmnghandler.pri)
     96contains(QT_CONFIG, tiff):include($$PWD/qtiffhandler.pri)
     97contains(QT_CONFIG, gif):include($$PWD/qgifhandler.pri)
     98
     99# SIMD
     100NEON_SOURCES += image/qimage_neon.cpp
     101SSE2_SOURCES += image/qimage_sse2.cpp
     102SSSE3_SOURCES += image/qimage_ssse3.cpp
  • trunk/src/gui/image/qbitmap.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qbitmap.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qbmphandler.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    247247    if (depth != 32) {
    248248        ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits;
     249        if (ncols > 256) // sanity check - don't run out of mem if color table is broken
     250            return false;
    249251        image.setColorCount(ncols);
    250252    }
     
    675677bool QBmpHandler::canRead() const
    676678{
    677     if (state == Ready) {
    678         if (!canRead(device()))
    679             return false;
     679    if (state == Ready && !canRead(device()))
     680        return false;
     681
     682    if (state != Error) {
    680683        setFormat("bmp");
    681684        return true;
    682685    }
    683     return state != Error;
     686
     687    return false;
    684688}
    685689
  • trunk/src/gui/image/qbmphandler_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qicon.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6767#endif
    6868
     69#include "private/qstylehelper_p.h"
     70
    6971#ifndef QT_NO_ICON
    7072QT_BEGIN_NAMESPACE
     
    262264        actualSize.scale(size, Qt::KeepAspectRatio);
    263265
    264     QString key = QLatin1String("$qt_icon_")
    265                   + QString::number(pm.cacheKey())
    266                   + QString::number(pe->mode)
    267                   + QString::number(QApplication::palette().cacheKey())
    268                   + QLatin1Char('_')
    269                   + QString::number(actualSize.width())
    270                   + QLatin1Char('_')
    271                   + QString::number(actualSize.height())
    272                   + QLatin1Char('_');
    273 
     266    QString key = QLatin1Literal("qt_")
     267                  % HexString<quint64>(pm.cacheKey())
     268                  % HexString<uint>(pe->mode)
     269                  % HexString<quint64>(QApplication::palette().cacheKey())
     270                  % HexString<uint>(actualSize.width())
     271                  % HexString<uint>(actualSize.height());
    274272
    275273    if (mode == QIcon::Active) {
    276         if (QPixmapCache::find(key + QString::number(mode), pm))
     274        if (QPixmapCache::find(key % HexString<uint>(mode), pm))
    277275            return pm; // horray
    278         if (QPixmapCache::find(key + QString::number(QIcon::Normal), pm)) {
     276        if (QPixmapCache::find(key % HexString<uint>(QIcon::Normal), pm)) {
    279277            QStyleOption opt(0);
    280278            opt.palette = QApplication::palette();
     
    285283    }
    286284
    287     if (!QPixmapCache::find(key + QString::number(mode), pm)) {
     285    if (!QPixmapCache::find(key % HexString<uint>(mode), pm)) {
    288286        if (pm.size() != actualSize)
    289287            pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
     
    295293                pm = generated;
    296294        }
    297         QPixmapCache::insert(key + QString::number(mode), pm);
     295        QPixmapCache::insert(key % HexString<uint>(mode), pm);
    298296    }
    299297    return pm;
     
    442440}
    443441
    444 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     442#ifndef QT_NO_LIBRARY
    445443Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
    446444    (QIconEngineFactoryInterface_iid, QLatin1String("/iconengines"), Qt::CaseInsensitive))
     
    880878
    881879/*!
     880    \since 4.7
     881
     882    Returns the name used to create the icon, if available.
     883
     884    Depending on the way the icon was created, it may have an associated
     885    name. This is the case for icons created with fromTheme() or icons
     886    using a QIconEngine which supports the QIconEngineV2::IconNameHook.
     887
     888    \sa fromTheme(), QIconEngine
     889*/
     890QString QIcon::name() const
     891{
     892    if (!d || !d->engine || d->engine_version < 2)
     893        return QString();
     894    QIconEngineV2 *engine = static_cast<QIconEngineV2*>(d->engine);
     895    return engine->iconName();
     896}
     897
     898/*!
    882899    \since 4.6
    883900
  • trunk/src/gui/image/qicon.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8282    QSize actualSize(const QSize &size, Mode mode = Normal, State state = Off) const;
    8383
     84    QString name() const;
     85
    8486    void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const;
    8587    inline void paint(QPainter *painter, int x, int y, int w, int h, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const
  • trunk/src/gui/image/qicon_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qiconengine.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    183183    that should be filled with icon sizes. Engines that work in terms
    184184    of a scalable, vectorial format normally return an empty list.
     185
     186    \value IconNameHook Allows to query the name used to create the
     187    icon, for example when instantiating an icon using
     188    QIcon::fromTheme().
    185189
    186190    \sa virtual_hook()
     
    302306}
    303307
     308/*!
     309    \since 4.7
     310
     311    Returns the name used to create the engine, if available.
     312
     313    \note This is a helper method and the actual work is done by
     314    virtual_hook() method, hence this method depends on icon engine support
     315    and may not work with all icon engines.
     316 */
     317QString QIconEngineV2::iconName()
     318{
     319    QString name;
     320    virtual_hook(QIconEngineV2::IconNameHook, reinterpret_cast<void*>(&name));
     321    return name;
     322}
     323
    304324QT_END_NAMESPACE
  • trunk/src/gui/image/qiconengine.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8181
    8282public:
    83     enum IconEngineHook { AvailableSizesHook = 1 };
     83    enum IconEngineHook { AvailableSizesHook = 1, IconNameHook };
    8484
    8585    struct AvailableSizesArgument
     
    9393    QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal,
    9494                                QIcon::State state = QIcon::Off);
     95
     96    // ### Qt 5: make this function const and virtual.
     97    QString iconName();
    9598};
    9699
  • trunk/src/gui/image/qiconengineplugin.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qiconengineplugin.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qiconloader.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6363#include <private/qt_x11_p.h>
    6464#endif
     65
     66#include <private/qstylehelper_p.h>
    6567
    6668QT_BEGIN_NAMESPACE
     
    150152    if (m_iconDirs.isEmpty()) {
    151153        m_iconDirs = qt_guiPlatformPlugin()->iconThemeSearchPaths();
    152         // Allways add resource directory as search path
     154        // Always add resource directory as search path
    153155        m_iconDirs.append(QLatin1String(":/icons"));
    154156    }
     
    265267            iconEntry->dir = dirInfo;
    266268            iconEntry->filename = currentDir.filePath(iconName + pngext);
    267             // Notice we ensure that pixmap entries allways come before
     269            // Notice we ensure that pixmap entries always come before
    268270            // scalable to preserve search order afterwards
    269271            entries.prepend(iconEntry);
     
    489491
    490492    int actualSize = qMin(size.width(), size.height());
    491     QString key = QLatin1String("$qt_theme_")
    492                   + QString::number(basePixmap.cacheKey(), 16)
    493                   + QLatin1Char('_')
    494                   + QString::number(mode)
    495                   + QLatin1Char('_')
    496                   + QString::number(qApp->palette().cacheKey(), 16)
    497                   + QLatin1Char('_')
    498                   + QString::number(actualSize);
     493
     494    QString key = QLatin1Literal("$qt_theme_")
     495                  % HexString<qint64>(basePixmap.cacheKey())
     496                  % HexString<int>(mode)
     497                  % HexString<qint64>(qApp->palette().cacheKey())
     498                  % HexString<int>(actualSize);
    499499
    500500    QPixmap cachedPixmap;
     
    555555        }
    556556        break;
     557    case QIconEngineV2::IconNameHook:
     558        {
     559            QString &name = *reinterpret_cast<QString*>(data);
     560            name = m_iconName;
     561        }
     562        break;
    557563    default:
    558564        QIconEngineV2::virtual_hook(id, data);
  • trunk/src/gui/image/qiconloader_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qimage.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5959#include <private/qpixmapdata_p.h>
    6060#include <private/qimagescale_p.h>
     61#include <private/qsimd_p.h>
    6162
    6263#include <qhash.h>
     
    210211    }
    211212
    212     const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 8)
     213    const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4)
    213214
    214215    // sanity check for potential overflows
     
    273274    switch (format) {
    274275
     276    case QImage::Format_Mono:
     277    case QImage::Format_MonoLSB:
    275278    case QImage::Format_Indexed8:
    276279        has_alpha_pixels = has_alpha_clut;
     
    481484    \o Low-level information
    482485    \o
     486
    483487    The depth() function returns the depth of the image. The supported
    484     depths are 1 (monochrome), 8 and 32 (for more information see the
    485     \l {QImage#Image Formats}{Image Formats} section).
     488    depths are 1 (monochrome), 8, 16, 24 and 32 bits. The
     489    bitPlaneCount() function tells how many of those bits that are
     490    used. For more information see the
     491    \l {QImage#Image Formats}{Image Formats} section.
    486492
    487493    The format(), bytesPerLine(), and byteCount() functions provide
     
    708714
    709715    \value Format_Indexed8  The image is stored using 8-bit indexes
    710                             into a colormap. 
     716                            into a colormap.
    711717
    712718    \value Format_RGB32     The image is stored using a 32-bit RGB format (0xffRRGGBB).
     
    11161122    : QPaintDevice()
    11171123{
    1118     d = image.d;
    1119     if (d)
    1120         d->ref.ref();
     1124    if (image.paintingActive()) {
     1125        d = 0;
     1126        operator=(image.copy());
     1127    } else {
     1128        d = image.d;
     1129        if (d)
     1130            d->ref.ref();
     1131    }
    11211132}
    11221133
     
    13151326QImage &QImage::operator=(const QImage &image)
    13161327{
    1317     if (image.d)
    1318         image.d->ref.ref();
    1319     if (d && !d->ref.deref())
    1320         delete d;
    1321     d = image.d;
     1328    if (image.paintingActive()) {
     1329        operator=(image.copy());
     1330    } else {
     1331        if (image.d)
     1332            image.d->ref.ref();
     1333        if (d && !d->ref.deref())
     1334            delete d;
     1335        d = image.d;
     1336    }
    13221337    return *this;
    13231338}
     
    15811596    Returns the depth of the image.
    15821597
    1583     The image depth is the number of bits used to encode a single
     1598    The image depth is the number of bits used to store a single
    15841599    pixel, also called bits per pixel (bpp).
    15851600
    15861601    The supported depths are 1, 8, 16, 24 and 32.
    15871602
    1588     \sa convertToFormat(), {QImage#Image Formats}{Image Formats},
     1603    \sa bitPlaneCount(), convertToFormat(), {QImage#Image Formats}{Image Formats},
    15891604    {QImage#Image Information}{Image Information}
    15901605
     
    18361851
    18371852    \sa bytesPerLine(), bits(), {QImage#Pixel Manipulation}{Pixel
    1838     Manipulation}
     1853    Manipulation}, constScanLine()
    18391854*/
    18401855uchar *QImage::scanLine(int i)
     
    18641879}
    18651880
     1881
     1882/*!
     1883    Returns a pointer to the pixel data at the scanline with index \a
     1884    i. The first scanline is at index 0.
     1885
     1886    The scanline data is aligned on a 32-bit boundary.
     1887
     1888    Note that QImage uses \l{Implicit Data Sharing} {implicit data
     1889    sharing}, but this function does \e not perform a deep copy of the
     1890    shared pixel data, because the returned data is const.
     1891
     1892    \sa scanLine(), constBits()
     1893    \since 4.7
     1894*/
     1895const uchar *QImage::constScanLine(int i) const
     1896{
     1897    if (!d)
     1898        return 0;
     1899
     1900    Q_ASSERT(i >= 0 && i < height());
     1901    return d->data + i * d->bytes_per_line;
     1902}
    18661903
    18671904/*!
     
    18741911    current return value.
    18751912
    1876     \sa scanLine(), byteCount()
     1913    \sa scanLine(), byteCount(), constBits()
    18771914*/
    18781915uchar *QImage::bits()
     
    19021939
    19031940
     1941/*!
     1942    Returns a pointer to the first pixel data.
     1943
     1944    Note that QImage uses \l{Implicit Data Sharing} {implicit data
     1945    sharing}, but this function does \e not perform a deep copy of the
     1946    shared pixel data, because the returned data is const.
     1947
     1948    \sa bits(), constScanLine()
     1949    \since 4.7
     1950*/
     1951const uchar *QImage::constBits() const
     1952{
     1953    return d ? d->data : 0;
     1954}
    19041955
    19051956/*!
     
    22342285typedef void (*Image_Converter)(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
    22352286
     2287typedef bool (*InPlace_Image_Converter)(QImageData *data, Qt::ImageConversionFlags);
     2288
    22362289static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
    22372290{
     
    22552308        src_data += src_pad;
    22562309        dest_data += dest_pad;
     2310    }
     2311}
     2312
     2313static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
     2314{
     2315    Q_ASSERT(data->format == QImage::Format_ARGB32);
     2316
     2317    const int pad = (data->bytes_per_line >> 2) - data->width;
     2318    QRgb *rgb_data = (QRgb *) data->data;
     2319
     2320    for (int i = 0; i < data->height; ++i) {
     2321        const QRgb *end = rgb_data + data->width;
     2322        while (rgb_data < end) {
     2323            *rgb_data = PREMUL(*rgb_data);
     2324            ++rgb_data;
     2325        }
     2326        rgb_data += pad;
     2327    }
     2328    data->format = QImage::Format_ARGB32_Premultiplied;
     2329    return true;
     2330}
     2331
     2332static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
     2333{
     2334    Q_ASSERT(data->format == QImage::Format_Indexed8);
     2335    const int depth = 32;
     2336
     2337    const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
     2338    const int nbytes = dst_bytes_per_line * data->height;
     2339    uchar *const newData = (uchar *)realloc(data->data, nbytes);
     2340    if (!newData)
     2341        return false;
     2342
     2343    data->data = newData;
     2344
     2345    // start converting from the end because the end image is bigger than the source
     2346    uchar *src_data = newData + data->nbytes; // end of src
     2347    quint32 *dest_data = (quint32 *) (newData + nbytes); // end of dest > end of src
     2348    const int width = data->width;
     2349    const int src_pad = data->bytes_per_line - width;
     2350    const int dest_pad = (dst_bytes_per_line >> 2) - width;
     2351    if (data->colortable.size() == 0) {
     2352        data->colortable.resize(256);
     2353        for (int i = 0; i < 256; ++i)
     2354            data->colortable[i] = qRgb(i, i, i);
     2355    } else {
     2356        for (int i = 0; i < data->colortable.size(); ++i)
     2357            data->colortable[i] = PREMUL(data->colortable.at(i));
     2358
     2359        // Fill the rest of the table in case src_data > colortable.size()
     2360        const int oldSize = data->colortable.size();
     2361        const QRgb lastColor = data->colortable.at(oldSize - 1);
     2362        data->colortable.insert(oldSize, 256 - oldSize, lastColor);
     2363    }
     2364
     2365    for (int i = 0; i < data->height; ++i) {
     2366        src_data -= src_pad;
     2367        dest_data -= dest_pad;
     2368        for (int pixI = 0; pixI < width; ++pixI) {
     2369            --src_data;
     2370            --dest_data;
     2371            *dest_data = data->colortable.at(*src_data);
     2372        }
     2373    }
     2374
     2375    data->colortable = QVector<QRgb>();
     2376    data->format = QImage::Format_ARGB32_Premultiplied;
     2377    data->bytes_per_line = dst_bytes_per_line;
     2378    data->depth = depth;
     2379    data->nbytes = nbytes;
     2380
     2381    return true;
     2382}
     2383
     2384static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags)
     2385{
     2386    Q_ASSERT(data->format == QImage::Format_Indexed8);
     2387    const int depth = 32;
     2388
     2389    const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
     2390    const int nbytes = dst_bytes_per_line * data->height;
     2391    uchar *const newData = (uchar *)realloc(data->data, nbytes);
     2392    if (!newData)
     2393        return false;
     2394
     2395    data->data = newData;
     2396
     2397    // start converting from the end because the end image is bigger than the source
     2398    uchar *src_data = newData + data->nbytes;
     2399    quint32 *dest_data = (quint32 *) (newData + nbytes);
     2400    const int width = data->width;
     2401    const int src_pad = data->bytes_per_line - width;
     2402    const int dest_pad = (dst_bytes_per_line >> 2) - width;
     2403    if (data->colortable.size() == 0) {
     2404        data->colortable.resize(256);
     2405        for (int i = 0; i < 256; ++i)
     2406            data->colortable[i] = qRgb(i, i, i);
     2407    } else {
     2408        // Fill the rest of the table in case src_data > colortable.size()
     2409        const int oldSize = data->colortable.size();
     2410        const QRgb lastColor = data->colortable.at(oldSize - 1);
     2411        data->colortable.insert(oldSize, 256 - oldSize, lastColor);
     2412    }
     2413
     2414    for (int i = 0; i < data->height; ++i) {
     2415        src_data -= src_pad;
     2416        dest_data -= dest_pad;
     2417        for (int pixI = 0; pixI < width; ++pixI) {
     2418            --src_data;
     2419            --dest_data;
     2420            *dest_data = (quint32) data->colortable.at(*src_data);
     2421        }
     2422    }
     2423
     2424    data->colortable = QVector<QRgb>();
     2425    data->format = QImage::Format_RGB32;
     2426    data->bytes_per_line = dst_bytes_per_line;
     2427    data->depth = depth;
     2428    data->nbytes = nbytes;
     2429
     2430    return true;
     2431}
     2432
     2433static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
     2434{
     2435    Q_ASSERT(data->format == QImage::Format_Indexed8);
     2436    const int depth = 16;
     2437
     2438    const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
     2439    const int nbytes = dst_bytes_per_line * data->height;
     2440    uchar *const newData = (uchar *)realloc(data->data, nbytes);
     2441    if (!newData)
     2442        return false;
     2443
     2444    data->data = newData;
     2445
     2446    // start converting from the end because the end image is bigger than the source
     2447    uchar *src_data = newData + data->nbytes;
     2448    quint16 *dest_data = (quint16 *) (newData + nbytes);
     2449    const int width = data->width;
     2450    const int src_pad = data->bytes_per_line - width;
     2451    const int dest_pad = (dst_bytes_per_line >> 1) - width;
     2452
     2453    quint16 colorTableRGB16[256];
     2454    if (data->colortable.isEmpty()) {
     2455        for (int i = 0; i < 256; ++i)
     2456            colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(qRgb(i, i, i), 0);
     2457    } else {
     2458        // 1) convert the existing colors to RGB16
     2459        const int tableSize = data->colortable.size();
     2460        for (int i = 0; i < tableSize; ++i)
     2461            colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(data->colortable.at(i), 0);
     2462        data->colortable = QVector<QRgb>();
     2463
     2464        // 2) fill the rest of the table in case src_data > colortable.size()
     2465        const quint16 lastColor = colorTableRGB16[tableSize - 1];
     2466        for (int i = tableSize; i < 256; ++i)
     2467            colorTableRGB16[i] = lastColor;
     2468    }
     2469
     2470    for (int i = 0; i < data->height; ++i) {
     2471        src_data -= src_pad;
     2472        dest_data -= dest_pad;
     2473        for (int pixI = 0; pixI < width; ++pixI) {
     2474            --src_data;
     2475            --dest_data;
     2476            *dest_data = colorTableRGB16[*src_data];
     2477        }
     2478    }
     2479
     2480    data->format = QImage::Format_RGB16;
     2481    data->bytes_per_line = dst_bytes_per_line;
     2482    data->depth = depth;
     2483    data->nbytes = nbytes;
     2484
     2485    return true;
     2486}
     2487
     2488static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
     2489{
     2490    Q_ASSERT(data->format == QImage::Format_RGB32);
     2491    const int depth = 16;
     2492
     2493    const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
     2494    const int src_bytes_per_line = data->bytes_per_line;
     2495    quint32 *src_data = (quint32 *) data->data;
     2496    quint16 *dst_data = (quint16 *) data->data;
     2497
     2498    for (int i = 0; i < data->height; ++i) {
     2499        qt_memconvert(dst_data, src_data, data->width);
     2500        src_data = (quint32 *) (((char*)src_data) + src_bytes_per_line);
     2501        dst_data = (quint16 *) (((char*)dst_data) + dst_bytes_per_line);
     2502    }
     2503    data->format = QImage::Format_RGB16;
     2504    data->bytes_per_line = dst_bytes_per_line;
     2505    data->depth = depth;
     2506    data->nbytes = dst_bytes_per_line * data->height;
     2507    uchar *const newData = (uchar *)realloc(data->data, data->nbytes);
     2508    if (newData) {
     2509        data->data = newData;
     2510        return true;
     2511    } else {
     2512        return false;
    22572513    }
    22582514}
     
    29503206        for (int i=0; i<256; ++i)
    29513207            colorTable[i] = qRgb(i, i, i);
    2952 
    29533208    }
    29543209
     
    29563211    const uchar *src_data = src->data;
    29573212    uchar *dest_data = dest->data;
     3213    int tableSize = colorTable.size() - 1;
    29583214    for (int y = 0; y < src->height; y++) {
    29593215        uint *p = (uint *)dest_data;
     
    29623218
    29633219        while (p < end)
    2964             *p++ = colorTable.at(*b++);
     3220            *p++ = colorTable.at(qMin<int>(tableSize, *b++));
    29653221
    29663222        src_data += src->bytes_per_line;
     
    31083364
    31093365// first index source, second dest
    3110 static const Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormats] =
     3366static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormats] =
    31113367{
    31123368    {
     
    34063662    } // Format_ARGB4444_Premultiplied
    34073663};
     3664
     3665static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
     3666{
     3667    {
     3668        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3669    },
     3670    {
     3671        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3672    }, // Format_Mono
     3673    {
     3674       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3675    }, // Format_MonoLSB
     3676    {
     3677        0,
     3678        0,
     3679        0,
     3680        0,
     3681        0,
     3682        convert_indexed8_to_RGB_inplace,
     3683        convert_indexed8_to_ARGB_PM_inplace,
     3684        convert_indexed8_to_RGB16_inplace,
     3685        0,
     3686        0,
     3687        0,
     3688        0,
     3689        0,
     3690        0,
     3691        0,
     3692        0,
     3693    }, // Format_Indexed8
     3694    {
     3695        0,
     3696        0,
     3697        0,
     3698        0,
     3699        0,
     3700        0,
     3701        0,
     3702        convert_RGB_to_RGB16_inplace,
     3703        0,
     3704        0,
     3705        0,
     3706        0,
     3707        0,
     3708        0,
     3709        0,
     3710        0,
     3711    }, // Format_ARGB32
     3712    {
     3713        0,
     3714        0,
     3715        0,
     3716        0,
     3717        0,
     3718        0,
     3719        convert_ARGB_to_ARGB_PM_inplace,
     3720        0,
     3721        0,
     3722        0,
     3723        0,
     3724        0,
     3725        0,
     3726        0,
     3727        0,
     3728        0,
     3729    }, // Format_ARGB32
     3730    {
     3731        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3732    },  // Format_ARGB32_Premultiplied
     3733    {
     3734        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3735    }, // Format_RGB16
     3736    {
     3737        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3738    }, // Format_ARGB8565_Premultiplied
     3739    {
     3740        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3741    }, // Format_RGB666
     3742    {
     3743        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3744    }, // Format_ARGB6666_Premultiplied
     3745    {
     3746        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3747    }, // Format_RGB555
     3748    {
     3749        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3750    }, // Format_ARGB8555_Premultiplied
     3751    {
     3752        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3753    }, // Format_RGB888
     3754    {
     3755        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3756    }, // Format_RGB444
     3757    {
     3758        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     3759    } // Format_ARGB4444_Premultiplied
     3760};
     3761
     3762void qInitImageConversions()
     3763{
     3764    const uint features = qDetectCPUFeatures();
     3765    Q_UNUSED(features);
     3766
     3767#ifdef QT_HAVE_SSE2
     3768    if (features & SSE2) {
     3769        extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags);
     3770        inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_sse2;
     3771    }
     3772#endif
     3773#ifdef QT_HAVE_SSSE3
     3774    if (features & SSSE3) {
     3775        extern void convert_RGB888_to_RGB32_ssse3(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
     3776        converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_ssse3;
     3777        converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_ssse3;
     3778        converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_ssse3;
     3779    }
     3780#endif
     3781#ifdef QT_HAVE_NEON
     3782    if (features & NEON) {
     3783        extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
     3784        converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon;
     3785        converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon;
     3786        converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_neon;
     3787    }
     3788#endif
     3789}
    34083790
    34093791/*!
     
    37594141        break;
    37604142    case Format_Indexed8:
    3761         if (index_or_rgb > (uint)d->colortable.size()) {
     4143        if (index_or_rgb >= (uint)d->colortable.size()) {
    37624144            qWarning("QImage::setPixel: Index %d out of range", index_or_rgb);
    37634145            return;
     
    41704552    int h = height();
    41714553    QImage m(w, h, Format_MonoLSB);
     4554    QIMAGE_SANITYCHECK_MEMORY(m);
    41724555    m.setColorCount(2);
    41734556    m.setColor(0, QColor(Qt::color0).rgba());
     
    42624645        return QImage();
    42634646    QImage maskImage(size(), QImage::Format_MonoLSB);
     4647    QIMAGE_SANITYCHECK_MEMORY(maskImage);
    42644648    maskImage.fill(0);
    42654649    uchar *s = maskImage.bits();
     
    43224706    // Create result image, copy colormap
    43234707    QImage result(d->width, d->height, d->format);
     4708    QIMAGE_SANITYCHECK_MEMORY(result);
    43244709
    43254710    // check if we ran out of of memory..
     
    44594844    case Format_ARGB32_Premultiplied:
    44604845        res = QImage(d->width, d->height, d->format);
     4846        QIMAGE_SANITYCHECK_MEMORY(res);
    44614847        for (int i = 0; i < d->height; i++) {
    44624848            uint *q = (uint*)res.scanLine(i);
    4463             uint *p = (uint*)scanLine(i);
     4849            uint *p = (uint*)constScanLine(i);
    44644850            uint *end = p + d->width;
    44654851            while (p < end) {
     
    44724858    case Format_RGB16:
    44734859        res = QImage(d->width, d->height, d->format);
     4860        QIMAGE_SANITYCHECK_MEMORY(res);
    44744861        for (int i = 0; i < d->height; i++) {
    44754862            ushort *q = (ushort*)res.scanLine(i);
    4476             const ushort *p = (const ushort*)scanLine(i);
     4863            const ushort *p = (const ushort*)constScanLine(i);
    44774864            const ushort *end = p + d->width;
    44784865            while (p < end) {
     
    44854872    case Format_ARGB8565_Premultiplied:
    44864873        res = QImage(d->width, d->height, d->format);
     4874        QIMAGE_SANITYCHECK_MEMORY(res);
    44874875        for (int i = 0; i < d->height; i++) {
    4488             quint8 *p = (quint8*)scanLine(i);
     4876            const quint8 *p = constScanLine(i);
     4877            quint8 *q = res.scanLine(i);
    44894878            const quint8 *end = p + d->width * sizeof(qargb8565);
    44904879            while (p < end) {
    4491                 quint16 *q = reinterpret_cast<quint16*>(p + 1);
    4492                 *q = ((*q << 11) & 0xf800) | ((*q >> 11) & 0x1f) | (*q & 0x07e0);
     4880                q[0] = p[0];
     4881                q[1] = (p[1] & 0xe0) | (p[2] >> 3);
     4882                q[2] = (p[2] & 0x07) | (p[1] << 3);
    44934883                p += sizeof(qargb8565);
     4884                q += sizeof(qargb8565);
    44944885            }
    44954886        }
     
    44974888    case Format_RGB666:
    44984889        res = QImage(d->width, d->height, d->format);
     4890        QIMAGE_SANITYCHECK_MEMORY(res);
    44994891        for (int i = 0; i < d->height; i++) {
    45004892            qrgb666 *q = reinterpret_cast<qrgb666*>(res.scanLine(i));
    4501             const qrgb666 *p = reinterpret_cast<const qrgb666*>(scanLine(i));
     4893            const qrgb666 *p = reinterpret_cast<const qrgb666*>(constScanLine(i));
    45024894            const qrgb666 *end = p + d->width;
    45034895            while (p < end) {
     
    45094901    case Format_ARGB6666_Premultiplied:
    45104902        res = QImage(d->width, d->height, d->format);
     4903        QIMAGE_SANITYCHECK_MEMORY(res);
    45114904        for (int i = 0; i < d->height; i++) {
    4512             qargb6666 *q = reinterpret_cast<qargb6666*>(res.scanLine(i));
    4513             const qargb6666 *p = reinterpret_cast<const qargb6666*>(scanLine(i));
    4514             const qargb6666 *end = p + d->width;
     4905            const quint8 *p = constScanLine(i);
     4906            const quint8 *end = p + d->width * sizeof(qargb6666);
     4907            quint8 *q = res.scanLine(i);
    45154908            while (p < end) {
    4516                 const QRgb rgb = quint32(*p++);
    4517                 *q++ = qRgba(qBlue(rgb), qGreen(rgb), qRed(rgb), qAlpha(rgb));
     4909                q[0] = (p[1] >> 4) | ((p[2] & 0x3) << 4) | (p[0] & 0xc0);
     4910                q[1] = (p[1] & 0xf) | (p[0] << 4);
     4911                q[2] = (p[2] & 0xfc) | ((p[0] >> 4) & 0x3);
     4912                p += sizeof(qargb6666);
     4913                q += sizeof(qargb6666);
    45184914            }
    45194915        }
     
    45214917    case Format_RGB555:
    45224918        res = QImage(d->width, d->height, d->format);
     4919        QIMAGE_SANITYCHECK_MEMORY(res);
    45234920        for (int i = 0; i < d->height; i++) {
    4524             ushort *q = (ushort*)res.scanLine(i);
    4525             const ushort *p = (const ushort*)scanLine(i);
    4526             const ushort *end = p + d->width;
     4921            quint16 *q = (quint16*)res.scanLine(i);
     4922            const quint16 *p = (const quint16*)constScanLine(i);
     4923            const quint16 *end = p + d->width;
    45274924            while (p < end) {
    4528                 *q = ((*p << 10) & 0x7800) | ((*p >> 10) & 0x1f) | (*p & 0x83e0);
     4925                *q = ((*p << 10) & 0x7c00) | ((*p >> 10) & 0x1f) | (*p & 0x3e0);
    45294926                p++;
    45304927                q++;
     
    45344931    case Format_ARGB8555_Premultiplied:
    45354932        res = QImage(d->width, d->height, d->format);
     4933        QIMAGE_SANITYCHECK_MEMORY(res);
    45364934        for (int i = 0; i < d->height; i++) {
    4537             quint8 *p = (quint8*)scanLine(i);
     4935            const quint8 *p = constScanLine(i);
     4936            quint8 *q = res.scanLine(i);
    45384937            const quint8 *end = p + d->width * sizeof(qargb8555);
    45394938            while (p < end) {
    4540                 quint16 *q = reinterpret_cast<quint16*>(p + 1);
    4541                 *q = ((*q << 10) & 0x7800) | ((*q >> 10) & 0x1f) | (*q & 0x83e0);
     4939                q[0] = p[0];
     4940                q[1] = (p[1] & 0xe0) | (p[2] >> 2);
     4941                q[2] = (p[2] & 0x03) | ((p[1] << 2) & 0x7f);
    45424942                p += sizeof(qargb8555);
     4943                q += sizeof(qargb8555);
    45434944            }
    45444945        }
     
    45464947    case Format_RGB888:
    45474948        res = QImage(d->width, d->height, d->format);
     4949        QIMAGE_SANITYCHECK_MEMORY(res);
    45484950        for (int i = 0; i < d->height; i++) {
    4549             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
    4550             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
     4951            quint8 *q = res.scanLine(i);
     4952            const quint8 *p = constScanLine(i);
    45514953            const quint8 *end = p + d->width * sizeof(qrgb888);
    45524954            while (p < end) {
     
    45604962        break;
    45614963    case Format_RGB444:
    4562         res = QImage(d->width, d->height, d->format);
    4563         for (int i = 0; i < d->height; i++) {
    4564             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
    4565             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
    4566             const quint8 *end = p + d->width * sizeof(qrgb444);
    4567             while (p < end) {
    4568                 q[0] = (p[0] & 0xf0) | ((p[1] & 0x0f) << 8);
    4569                 q[1] = ((p[0] & 0x0f) >> 8) | (p[1] & 0xf0);
    4570                 q += sizeof(qrgb444);
    4571                 p += sizeof(qrgb444);
    4572             }
    4573         }
    4574         break;
    45754964    case Format_ARGB4444_Premultiplied:
    45764965        res = QImage(d->width, d->height, d->format);
     4966        QIMAGE_SANITYCHECK_MEMORY(res);
    45774967        for (int i = 0; i < d->height; i++) {
    4578             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
    4579             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
    4580             const quint8 *end = p + d->width * sizeof(qargb4444);
     4968            quint16 *q = reinterpret_cast<quint16*>(res.scanLine(i));
     4969            const quint16 *p = reinterpret_cast<const quint16*>(constScanLine(i));
     4970            const quint16 *end = p + d->width;
    45814971            while (p < end) {
    4582                 q[0] = (p[0] & 0xf0) | ((p[1] & 0x0f) << 8);
    4583                 q[1] = ((p[0] & 0x0f) >> 8) | (p[1] & 0xf0);
    4584                 q += sizeof(qargb4444);
    4585                 p += sizeof(qargb4444);
     4972                *q = (*p & 0xf0f0) | ((*p & 0x0f) << 8) | ((*p & 0xf00) >> 8);
     4973                p++;
     4974                q++;
    45864975            }
    45874976        }
     
    47745163    the stream to a file will not produce a valid image file.
    47755164
    4776     \sa QImage::save(), {Format of the QDataStream Operators}
     5165    \sa QImage::save(), {Serializing Qt Data Types}
    47775166*/
    47785167
     
    48005189    \a image.
    48015190
    4802     \sa QImage::load(), {Format of the QDataStream Operators}
     5191    \sa QImage::load(), {Serializing Qt Data Types}
    48035192*/
    48045193
     
    56666055    }
    56676056
    5668     detach();
    5669 
    5670     QImage converted = convertToFormat(QImage::Format_ARGB32_Premultiplied);
    5671     if (!converted.isNull())
    5672         *this = converted;
     6057    if (d->format == QImage::Format_ARGB32_Premultiplied)
     6058        detach();
    56736059    else
     6060        *this = convertToFormat(QImage::Format_ARGB32_Premultiplied);
     6061
     6062    if (isNull())
    56746063        return;
    56756064
     
    58146203                                           || d->format == Format_Mono
    58156204                                           || d->format == Format_MonoLSB)));
     6205}
     6206
     6207
     6208/*!
     6209    \since 4.7
     6210    Returns the number of bit planes in the image.
     6211
     6212    The number of bit planes is the number of bits of color and
     6213    transparency information for each pixel. This is different from
     6214    (i.e. smaller than) the depth when the image format contains
     6215    unused bits.
     6216
     6217    \sa depth(), format(), {QImage#Image Formats}{Image Formats}
     6218*/
     6219int QImage::bitPlaneCount() const
     6220{
     6221    if (!d)
     6222        return 0;
     6223    int bpc = 0;
     6224    switch (d->format) {
     6225    case QImage::Format_Invalid:
     6226        break;
     6227    case QImage::Format_RGB32:
     6228        bpc = 24;
     6229        break;
     6230    case QImage::Format_RGB666:
     6231        bpc = 18;
     6232        break;
     6233    case QImage::Format_RGB555:
     6234        bpc = 15;
     6235        break;
     6236    case QImage::Format_ARGB8555_Premultiplied:
     6237        bpc = 23;
     6238        break;
     6239    case QImage::Format_RGB444:
     6240        bpc = 12;
     6241        break;
     6242    default:
     6243        bpc = depthForFormat(d->format);
     6244        break;
     6245    }
     6246    return bpc;
    58166247}
    58176248
     
    61816612}
    61826613
     6614bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
     6615{
     6616    if (format == newFormat)
     6617        return true;
     6618
     6619    // No in-place conversion if we have to detach
     6620    if (ref > 1)
     6621        return false;
     6622
     6623    const InPlace_Image_Converter *const converterPtr = &inplace_converter_map[format][newFormat];
     6624    InPlace_Image_Converter converter = *converterPtr;
     6625    if (converter)
     6626        return converter(this, flags);
     6627    else
     6628        return false;
     6629}
    61836630
    61846631/*!
  • trunk/src/gui/image/qimage.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    170170#endif
    171171    int colorCount() const;
     172    int bitPlaneCount() const;
    172173
    173174    QRgb color(int i) const;
     
    183184    uchar *bits();
    184185    const uchar *bits() const;
     186    const uchar *constBits() const;
    185187#ifdef QT_DEPRECATED
    186188    QT_DEPRECATED int numBytes() const;
     
    190192    uchar *scanLine(int);
    191193    const uchar *scanLine(int) const;
     194    const uchar *constScanLine(int) const;
    192195    int bytesPerLine() const;
    193196
  • trunk/src/gui/image/qimage_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6464QT_BEGIN_NAMESPACE
    6565
     66class QImageWriter;
     67
    6668struct Q_GUI_EXPORT QImageData {        // internal image data
    6769    QImageData();
     
    9799    bool checkForAlphaPixels() const;
    98100
     101    // Convert the image in-place, minimizing memory reallocation
     102    // Return false if the conversion cannot be done in-place.
     103    bool convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags);
    99104
    100105#ifndef QT_NO_IMAGE_TEXT
     
    106111};
    107112
     113void qInitImageConversions();
     114
    108115QT_END_NAMESPACE
    109116
  • trunk/src/gui/image/qimageiohandler.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qimageiohandler.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qimagepixmapcleanuphooks.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qimagepixmapcleanuphooks_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qimagereader.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    142142#include <private/qpnghandler_p.h>
    143143#endif
     144#ifndef QT_NO_IMAGEFORMAT_JPEG
     145#include <private/qjpeghandler_p.h>
     146#endif
     147#ifndef QT_NO_IMAGEFORMAT_MNG
     148#include <private/qmnghandler_p.h>
     149#endif
     150#ifndef QT_NO_IMAGEFORMAT_TIFF
     151#include <private/qtiffhandler_p.h>
     152#endif
     153#ifdef QT_BUILTIN_GIF_READER
     154#include <private/qgifhandler_p.h>
     155#endif
    144156
    145157QT_BEGIN_NAMESPACE
    146158
    147 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     159#ifndef QT_NO_LIBRARY
    148160Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
    149161                          (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
     
    153165#ifndef QT_NO_IMAGEFORMAT_PNG
    154166    _qt_PngFormat,
     167#endif
     168#ifndef QT_NO_IMAGEFORMAT_JPEG
     169    _qt_JpgFormat,
     170#endif
     171#ifndef QT_NO_IMAGEFORMAT_MNG
     172    _qt_MngFormat,
     173#endif
     174#ifndef QT_NO_IMAGEFORMAT_TIFF
     175    _qt_TifFormat,
     176#endif
     177#ifdef QT_BUILTIN_GIF_READER
     178    _qt_GifFormat,
    155179#endif
    156180    _qt_BmpFormat,
     
    180204    {_qt_PngFormat, "png"},
    181205#endif
     206#ifndef QT_NO_IMAGEFORMAT_JPEG
     207    {_qt_JpgFormat, "jpg"},
     208#endif
     209#ifndef QT_NO_IMAGEFORMAT_MNG
     210    {_qt_MngFormat, "mng"},
     211#endif
     212#ifndef QT_NO_IMAGEFORMAT_TIFF
     213    {_qt_TifFormat, "tif"},
     214#endif
     215#ifdef QT_BUILTIN_GIF_READER
     216    {_qt_GifFormat, "gif"},
     217#endif
    182218    {_qt_BmpFormat, "bmp"},
    183219#ifndef QT_NO_IMAGEFORMAT_PPM
     
    206242    QImageIOHandler *handler = 0;
    207243
    208 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     244#ifndef QT_NO_LIBRARY
    209245    // check if we have plugins that support the image format
    210246    QFactoryLoader *l = loader();
     
    218254#endif
    219255
    220 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     256#ifndef QT_NO_LIBRARY
    221257    int suffixPluginIndex = -1;
    222258    if (device && format.isEmpty() && autoDetectImageFormat && !ignoresFormatAndExtension) {
     
    247283        testFormat = QByteArray();
    248284
    249 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     285#ifndef QT_NO_LIBRARY
    250286    if (suffixPluginIndex != -1) {
    251287        // check if the plugin that claims support for this format can load
     
    302338        if (false) {
    303339#ifndef QT_NO_IMAGEFORMAT_PNG
    304         } else if (testFormat == "png") {
     340        } else if (testFormat == "png") {
    305341            handler = new QPngHandler;
     342#endif
     343#ifndef QT_NO_IMAGEFORMAT_JPEG
     344        } else if (testFormat == "jpg" || testFormat == "jpeg") {
     345            handler = new QJpegHandler;
     346#endif
     347#ifndef QT_NO_IMAGEFORMAT_MNG
     348        } else if (testFormat == "mng") {
     349            handler = new QMngHandler;
     350#endif
     351#ifndef QT_NO_IMAGEFORMAT_TIFF
     352        } else if (testFormat == "tif" || testFormat == "tiff") {
     353            handler = new QTiffHandler;
     354#endif
     355#ifdef QT_BUILTIN_GIF_READER
     356        } else if (testFormat == "gif") {
     357            handler = new QGifHandler;
    306358#endif
    307359#ifndef QT_NO_IMAGEFORMAT_BMP
     
    332384    }
    333385
    334 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     386#ifndef QT_NO_LIBRARY
    335387    if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) {
    336388        // check if any of our plugins recognize the file from its contents.
     
    351403            device->seek(pos);
    352404    }
    353 #endif
     405#endif // QT_NO_LIBRARY
    354406
    355407    if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) {
     
    381433                break;
    382434#endif
     435#ifndef QT_NO_IMAGEFORMAT_JPEG
     436            case _qt_JpgFormat:
     437                if (QJpegHandler::canRead(device))
     438                    handler = new QJpegHandler;
     439                break;
     440#endif
     441#ifndef QT_NO_IMAGEFORMAT_MNG
     442            case _qt_MngFormat:
     443                if (QMngHandler::canRead(device))
     444                    handler = new QMngHandler;
     445                break;
     446#endif
     447#ifndef QT_NO_IMAGEFORMAT_TIFF
     448            case _qt_TifFormat:
     449                if (QTiffHandler::canRead(device))
     450                    handler = new QTiffHandler;
     451                break;
     452#endif
     453#ifdef QT_BUILTIN_GIF_READER
     454            case _qt_GifFormat:
     455                if (QGifHandler::canRead(device))
     456                    handler = new QGifHandler;
     457                break;
     458#endif
    383459#ifndef QT_NO_IMAGEFORMAT_BMP
    384460            case _qt_BmpFormat:
     
    504580{
    505581    // check some preconditions
    506     if (!device || (!deleteDevice && !device->isOpen())) {
     582    if (!device || (!deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly))) {
    507583        imageReaderError = QImageReader::DeviceError;
    508584        errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Invalid device"));
     
    14151491        formats << _qt_BuiltInFormats[i].extension;
    14161492
    1417 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     1493#ifndef QT_NO_LIBRARY
    14181494    QFactoryLoader *l = loader();
    14191495    QStringList keys = l->keys();
  • trunk/src/gui/image/qimagereader.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qimagewriter.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    115115#include <private/qpnghandler_p.h>
    116116#endif
     117#ifndef QT_NO_IMAGEFORMAT_JPEG
     118#include <private/qjpeghandler_p.h>
     119#endif
     120#ifndef QT_NO_IMAGEFORMAT_MNG
     121#include <private/qmnghandler_p.h>
     122#endif
     123#ifndef QT_NO_IMAGEFORMAT_TIFF
     124#include <private/qtiffhandler_p.h>
     125#endif
     126#ifdef QT_BUILTIN_GIF_READER
     127#include <private/qgifhandler_p.h>
     128#endif
    117129
    118130QT_BEGIN_NAMESPACE
    119131
    120 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     132#ifndef QT_NO_LIBRARY
    121133Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
    122134                          (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
     
    130142    QImageIOHandler *handler = 0;
    131143
    132 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     144#ifndef QT_NO_LIBRARY
    133145    // check if any plugins can write the image
    134146    QFactoryLoader *l = loader();
     
    143155        if (QFile *file = qobject_cast<QFile *>(device)) {
    144156            if (!(suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1()).isEmpty()) {
    145 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     157#ifndef QT_NO_LIBRARY
    146158                int index = keys.indexOf(QString::fromLatin1(suffix));
    147159                if (index != -1)
     
    154166    QByteArray testFormat = !form.isEmpty() ? form : suffix;
    155167
    156 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     168#ifndef QT_NO_LIBRARY
    157169    if (suffixPluginIndex != -1) {
    158170        // when format is missing, check if we can find a plugin for the
     
    162174            handler = plugin->create(device, suffix);
    163175    }
    164 #endif // Q_NO_LIBRARY
     176#endif // QT_NO_LIBRARY
    165177
    166178    // check if any built-in handlers can write the image
     
    171183            handler = new QPngHandler;
    172184#endif
     185#ifndef QT_NO_IMAGEFORMAT_JPEG
     186        } else if (testFormat == "jpg" || testFormat == "jpeg") {
     187            handler = new QJpegHandler;
     188#endif
     189#ifndef QT_NO_IMAGEFORMAT_MNG
     190        } else if (testFormat == "mng") {
     191            handler = new QMngHandler;
     192#endif
     193#ifndef QT_NO_IMAGEFORMAT_TIFF
     194        } else if (testFormat == "tif" || testFormat == "tiff") {
     195            handler = new QTiffHandler;
     196#endif
     197#ifdef QT_BUILTIN_GIF_READER
     198        } else if (testFormat == "gif") {
     199            handler = new QGifHandler;
     200#endif
    173201#ifndef QT_NO_IMAGEFORMAT_BMP
    174202        } else if (testFormat == "bmp") {
     
    193221    }
    194222
    195 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     223#ifndef QT_NO_LIBRARY
    196224    if (!testFormat.isEmpty()) {
    197225        for (int i = 0; i < keys.size(); ++i) {
     
    204232        }
    205233    }
    206 #endif
     234#endif // QT_NO_LIBRARY
    207235
    208236    if (!handler)
     
    670698    formats << "png";
    671699#endif
    672 
    673 #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     700#ifndef QT_NO_IMAGEFORMAT_JPEG
     701    formats << "jpg" << "jpeg";
     702#endif
     703#ifndef QT_NO_IMAGEFORMAT_MNG
     704    formats << "mng";
     705#endif
     706#ifndef QT_NO_IMAGEFORMAT_TIFF
     707    formats << "tif" << "tiff";
     708#endif
     709#ifdef QT_BUILTIN_GIF_READER
     710    formats << "gif";
     711#endif
     712
     713#ifndef QT_NO_LIBRARY
    674714    QFactoryLoader *l = loader();
    675715    QStringList keys = l->keys();
  • trunk/src/gui/image/qimagewriter.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qmovie.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qmovie.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qnativeimage.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qnativeimage_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpaintengine_pic.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    487487#endif
    488488
     489    const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
     490    if (si.chars == 0)
     491        QPaintEngine::drawTextItem(p, ti); // Draw as path
     492
    489493    if (d->pic_d->formatMajor >= 9) {
    490         const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
    491494        int pos;
    492495        SERIALIZE_CMD(QPicturePrivate::PdcDrawTextItem);
  • trunk/src/gui/image/qpaintengine_pic_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpicture.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpicture.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpicture_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpictureformatplugin.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpictureformatplugin.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpixmap.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8383
    8484#include "qpixmap_raster_p.h"
     85#include "private/qstylehelper_p.h"
    8586
    8687QT_BEGIN_NAMESPACE
     
    579580QSize QPixmap::size() const
    580581{
    581     return data ? QSize(data->width(), data->height()) : QSize();
     582    return data ? QSize(data->width(), data->height()) : QSize(0, 0);
    582583}
    583584
     
    636637        return;
    637638
     639    // QPixmap.data member may be QRuntimePixmapData so use pixmapData() function to get
     640    // the actual underlaying runtime pixmap data.
     641    QPixmapData *pd = pixmapData();
     642
    638643    // Create new pixmap
    639     QPixmap pm(QSize(w, h), data ? data->type : QPixmapData::PixmapType);
     644    QPixmap pm(QSize(w, h), pd ? pd->type : QPixmapData::PixmapType);
    640645    bool uninit = false;
    641646#if defined(Q_WS_X11)
    642     QX11PixmapData *x11Data = data && data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data.data()) : 0;
     647    QX11PixmapData *x11Data = pd && pd->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(pd) : 0;
    643648    if (x11Data) {
    644649        pm.x11SetScreen(x11Data->xinfo.screen());
     
    646651    }
    647652#elif defined(Q_WS_MAC)
    648     QMacPixmapData *macData = data && data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
     653    QMacPixmapData *macData = pd && pd->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(pd) : 0;
    649654    if (macData)
    650655        uninit = macData->uninit;
     
    660665#if defined(Q_WS_X11)
    661666    if (x11Data && x11Data->x11_mask) {
    662         QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pm.data.data());
    663         pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display,
    664                                                      RootWindow(x11Data->xinfo.display(),
    665                                                                 x11Data->xinfo.screen()),
    666                                                       w, h, 1);
    667         GC gc = XCreateGC(X11->display, pmData->x11_mask, 0, 0);
    668         XCopyArea(X11->display, x11Data->x11_mask, pmData->x11_mask, gc, 0, 0, qMin(width(), w), qMin(height(), h), 0, 0);
    669         XFreeGC(X11->display, gc);
     667        QPixmapData *newPd = pm.pixmapData();
     668        QX11PixmapData *pmData = (newPd && newPd->classId() == QPixmapData::X11Class)
     669                                 ? static_cast<QX11PixmapData*>(newPd) : 0;
     670        if (pmData) {
     671            pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display,
     672                                                         RootWindow(x11Data->xinfo.display(),
     673                                                                    x11Data->xinfo.screen()),
     674                                                         w, h, 1);
     675            GC gc = XCreateGC(X11->display, pmData->x11_mask, 0, 0);
     676            XCopyArea(X11->display, x11Data->x11_mask, pmData->x11_mask, gc, 0, 0,
     677                      qMin(width(), w), qMin(height(), h), 0, 0);
     678            XFreeGC(X11->display, gc);
     679        }
    670680    }
    671681#endif
     
    766776    Creates and returns a mask for this pixmap based on the given \a
    767777    maskColor. If the \a mode is Qt::MaskInColor, all pixels matching the
    768     maskColor will be opaque. If \a mode is Qt::MaskOutColor, all pixels
    769     matching the maskColor will be transparent.
     778    maskColor will be transparent. If \a mode is Qt::MaskOutColor, all pixels
     779    matching the maskColor will be opaque.
    770780
    771781    This function is slow because it involves converting to/from a
     
    826836
    827837    QFileInfo info(fileName);
    828     QString key = QLatin1String("qt_pixmap_") + info.absoluteFilePath() + QLatin1Char('_') + QString::number(info.lastModified().toTime_t()) + QLatin1Char('_') +
    829         QString::number(info.size()) + QLatin1Char('_') + QString::number(data ? data->pixelType() : QPixmapData::PixmapType);
     838    QString key = QLatin1Literal("qt_pixmap")
     839                  % info.absoluteFilePath()
     840                  % HexString<uint>(info.lastModified().toTime_t())
     841                  % HexString<quint64>(info.size())
     842                  % HexString<uint>(data ? data->pixelType() : QPixmapData::PixmapType);
     843
     844    // Note: If no extension is provided, we try to match the
     845    // file against known plugin extensions
     846    if (!info.completeSuffix().isEmpty() && !info.exists())
     847        return false;
    830848
    831849    if (QPixmapCache::find(key, *this))
     
    10721090        sendResizeEvents(widget);
    10731091
     1092    widget->d_func()->prepareToRender(QRegion(),
     1093        QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
     1094
    10741095    QRect r(rect);
    10751096    if (r.width() < 0)
     
    10821103
    10831104    QPixmap res(r.size());
    1084     widget->render(&res, QPoint(), r,
    1085                    QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
     1105    if (!qt_widget_private(widget)->isOpaque)
     1106        res.fill(Qt::transparent);
     1107
     1108    widget->d_func()->render(&res, QPoint(), r, QWidget::DrawWindowBackground
     1109                             | QWidget::DrawChildren | QWidget::IgnoreMask, true);
    10861110    return res;
    10871111}
     
    11611185{
    11621186#if defined(Q_WS_X11)
    1163     if (data && data->classId() == QPixmapData::X11Class)
    1164         return static_cast<const QX11PixmapData*>(data.constData())->handle();
     1187    const QPixmapData *pd = pixmapData();
     1188    if (pd) {
     1189        if (pd->classId() == QPixmapData::X11Class)
     1190            return static_cast<const QX11PixmapData*>(pd)->handle();
     1191        else
     1192            qWarning("QPixmap::handle(): Pixmap is not an X11 class pixmap");
     1193    }
    11651194#endif
    11661195    return 0;
     
    12791308    valid image file.
    12801309
    1281     \sa QPixmap::save(), {Format of the QDataStream Operators}
     1310    \sa QPixmap::save(), {Serializing Qt Data Types}
    12821311*/
    12831312
     
    12921321    Reads an image from the given \a stream into the given \a pixmap.
    12931322
    1294     \sa QPixmap::load(), {Format of the QDataStream Operators}
     1323    \sa QPixmap::load(), {Serializing Qt Data Types}
    12951324*/
    12961325
     
    13641393
    13651394/*!
    1366     \fn bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
    1367 
    1368     Use the static fromImage() function instead.
    1369 */
     1395    Replaces this pixmap's data with the given \a image using the
     1396    specified \a flags to control the conversion.  The \a flags
     1397    argument is a bitwise-OR of the \l{Qt::ImageConversionFlags}.
     1398    Passing 0 for \a flags sets all the default options. Returns true
     1399    if the result is that this pixmap is not null.
     1400
     1401    Note: this function was part of Qt 3 support in Qt 4.6 and earlier.
     1402    It has been promoted to official API status in 4.7 to support updating
     1403    the pixmap's image without creating a new QPixmap as fromImage() would.
     1404
     1405    \sa fromImage()
     1406    \since 4.7
     1407*/
     1408bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
     1409{
     1410    if (image.isNull() || !data)
     1411        *this = QPixmap::fromImage(image, flags);
     1412    else
     1413        data->fromImage(image, flags);
     1414    return !isNull();
     1415}
    13701416
    13711417/*!
     
    17351781    pixmap.
    17361782
     1783    \note When using the native X11 graphics system, the pixmap
     1784    becomes invalid when the QApplication instance is destroyed.
     1785
    17371786    \sa QBitmap, QImage, QImageReader, QImageWriter
    17381787*/
     
    17531802    mask, otherwise returns false.
    17541803
    1755     \warning This is potentially an expensive operation.
    1756 
    17571804    \sa hasAlphaChannel(), mask()
    17581805*/
    17591806bool QPixmap::hasAlpha() const
    17601807{
    1761     return data && (data->hasAlphaChannel() || !data->mask().isNull());
     1808#if defined(Q_WS_X11)
     1809    if (data && data->hasAlphaChannel())
     1810        return true;
     1811    QPixmapData *pd = pixmapData();
     1812    if (pd && pd->classId() == QPixmapData::X11Class) {
     1813        QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(pd);
     1814#ifndef QT_NO_XRENDER
     1815        if (x11Data->picture && x11Data->d == 32)
     1816            return true;
     1817#endif
     1818        if (x11Data->d == 1 || x11Data->x11_mask)
     1819            return true;
     1820    }
     1821    return false;
     1822#else
     1823    return data && data->hasAlphaChannel();
     1824#endif
    17621825}
    17631826
     
    19271990        return;
    19281991
    1929     QPixmapData::ClassId id = data->classId();
     1992    // QPixmap.data member may be QRuntimePixmapData so use pixmapData() function to get
     1993    // the actual underlaying runtime pixmap data.
     1994    QPixmapData *pd = pixmapData();
     1995    QPixmapData::ClassId id = pd->classId();
    19301996    if (id == QPixmapData::RasterClass) {
    1931         QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data.data());
     1997        QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(pd);
    19321998        rasterData->image.detach();
    19331999    }
    19342000
    19352001    if (data->is_cached && data->ref == 1)
    1936         QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data());
     2002        QImagePixmapCleanupHooks::executePixmapDataModificationHooks(pd);
    19372003
    19382004#if defined(Q_WS_MAC)
    1939     QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
     2005    QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(pd) : 0;
    19402006    if (macData) {
    19412007        if (macData->cg_mask) {
     
    19522018
    19532019#if defined(Q_WS_X11)
    1954     if (data->classId() == QPixmapData::X11Class) {
    1955         QX11PixmapData *d = static_cast<QX11PixmapData*>(data.data());
     2020    if (pd->classId() == QPixmapData::X11Class) {
     2021        QX11PixmapData *d = static_cast<QX11PixmapData*>(pd);
    19562022        d->flags &= ~QX11PixmapData::Uninitialized;
    19572023
     
    19832049    use QBitmap::fromImage() instead.
    19842050
    1985     \sa toImage(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
     2051    \sa fromImageReader(), toImage(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
    19862052*/
    19872053QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
     
    19982064
    19992065/*!
     2066    \fn QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags)
     2067
     2068    Create a QPixmap from an image read directly from an \a imageReader.
     2069    The \a flags argument is a bitwise-OR of the \l{Qt::ImageConversionFlags}.
     2070    Passing 0 for \a flags sets all the default options.
     2071
     2072    On some systems, reading an image directly to QPixmap can use less memory than
     2073    reading a QImage to convert it to QPixmap.
     2074
     2075    \sa fromImage(), toImage(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
     2076*/
     2077QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags)
     2078{
     2079    QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem();
     2080    QScopedPointer<QPixmapData> data(gs ? gs->createPixmapData(QPixmapData::PixmapType)
     2081            : QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixmapType));
     2082    data->fromImageReader(imageReader, flags);
     2083    return QPixmap(data.take());
     2084}
     2085
     2086/*!
    20002087    \fn QPixmap QPixmap::grabWindow(WId window, int x, int y, int
    20012088    width, int height)
     
    20432130QPixmapData* QPixmap::pixmapData() const
    20442131{
    2045     return data.data();
    2046 }
     2132    if (data) {
     2133        QPixmapData* pm = data.data();
     2134        return pm->runtimeData() ? pm->runtimeData() : pm;
     2135    }
     2136
     2137    return 0;
     2138}
     2139
    20472140
    20482141/*!
  • trunk/src/gui/image/qpixmap.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6363
    6464class QImageWriter;
     65class QImageReader;
    6566class QColor;
    6667class QVariant;
     
    140141    QImage toImage() const;
    141142    static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
     143    static QPixmap fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags = Qt::AutoColor);
    142144
    143145    bool load(const QString& fileName, const char *format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor);
     
    146148    bool save(const QString& fileName, const char* format = 0, int quality = -1) const;
    147149    bool save(QIODevice* device, const char* format = 0, int quality = -1) const;
     150
     151    bool convertFromImage(const QImage &img, Qt::ImageConversionFlags flags = Qt::AutoColor);
    148152
    149153#if defined(Q_WS_WIN)
     
    240244    inline QT3_SUPPORT QImage convertToImage() const { return toImage(); }
    241245    QT3_SUPPORT bool convertFromImage(const QImage &, ColorMode mode);
    242     QT3_SUPPORT bool convertFromImage(const QImage &img, Qt::ImageConversionFlags flags = Qt::AutoColor)
    243         { (*this) = fromImage(img, flags); return !isNull(); }
    244246    inline QT3_SUPPORT operator QImage() const { return toImage(); }
    245247    inline QT3_SUPPORT QPixmap xForm(const QMatrix &matrix) const { return transformed(QTransform(matrix)); }
     
    287289    friend class QCoreGraphicsPaintEngine;
    288290    friend class QWidgetPrivate;
    289     friend class QRasterPaintEngine;
    290291    friend class QRasterBuffer;
    291     friend class QPixmapCacheEntry;
    292292#if !defined(QT_NO_DATASTREAM)
    293293    friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPixmap &);
  • trunk/src/gui/image/qpixmap_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpixmap_mac_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpixmap_qws.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpixmap_raster.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4545#include "qnativeimage_p.h"
    4646#include "qimage_p.h"
     47#include "qpaintengine.h"
    4748
    4849#include "qbitmap.h"
    4950#include "qimage.h"
     51#include <QBuffer>
     52#include <QImageReader>
     53#include <private/qimage_p.h>
     54#include <private/qsimd_p.h>
    5055#include <private/qwidget_p.h>
    5156#include <private/qdrawhelper_p.h>
     
    128133}
    129134
     135bool QRasterPixmapData::fromData(const uchar *buffer, uint len, const char *format,
     136                      Qt::ImageConversionFlags flags)
     137{
     138    QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len);
     139    QBuffer b(&a);
     140    b.open(QIODevice::ReadOnly);
     141    QImage image = QImageReader(&b, format).read();
     142    if (image.isNull())
     143        return false;
     144
     145    createPixmapForImage(image, flags, /* inplace = */true);
     146    return !isNull();
     147}
     148
    130149void QRasterPixmapData::fromImage(const QImage &sourceImage,
    131150                                  Qt::ImageConversionFlags flags)
    132151{
    133152    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());
     153    QImage image = sourceImage;
     154    createPixmapForImage(image, flags, /* inplace = */false);
     155}
     156
     157void QRasterPixmapData::fromImageReader(QImageReader *imageReader,
     158                                        Qt::ImageConversionFlags flags)
     159{
     160    Q_UNUSED(flags);
     161    QImage image = imageReader->read();
     162    if (image.isNull())
     163        return;
     164
     165    createPixmapForImage(image, flags, /* inplace = */true);
    213166}
    214167
    215168// from qwindowsurface.cpp
    216169extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
     170
     171void QRasterPixmapData::copy(const QPixmapData *data, const QRect &rect)
     172{
     173    fromImage(data->toImage(rect).copy(), Qt::NoOpaqueDetection);
     174}
    217175
    218176bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect)
     
    239197            if (!image.hasAlphaChannel()) {
    240198                QImage::Format toFormat;
     199#if !(defined(QT_HAVE_NEON) || defined(QT_ALWAYS_HAVE_SSE2))
    241200                if (image.format() == QImage::Format_RGB16)
    242201                    toFormat = QImage::Format_ARGB8565_Premultiplied;
     
    248207                    toFormat = QImage::Format_ARGB4444_Premultiplied;
    249208                else
     209#endif
    250210                    toFormat = QImage::Format_ARGB32_Premultiplied;
    251211                image = QImage(image.width(), image.height(), toFormat);
     
    345305QImage QRasterPixmapData::toImage() const
    346306{
     307    if (!image.isNull()) {
     308        QImageData *data = const_cast<QImage &>(image).data_ptr();
     309        if (data->paintEngine && data->paintEngine->isActive()
     310            && data->paintEngine->paintDevice() == &image)
     311        {
     312            return image.copy();
     313        }
     314    }
     315
    347316    return image;
     317}
     318
     319QImage QRasterPixmapData::toImage(const QRect &rect) const
     320{
     321    if (rect.isNull())
     322        return image;
     323
     324    QRect clipped = rect.intersected(QRect(0, 0, w, h));
     325    if (d % 8 == 0)
     326        return QImage(image.scanLine(clipped.y()) + clipped.x() * (d / 8),
     327                      clipped.width(), clipped.height(),
     328                      image.bytesPerLine(), image.format());
     329    else
     330        return image.copy(clipped);
    348331}
    349332
     
    395378}
    396379
     380void QRasterPixmapData::createPixmapForImage(QImage &sourceImage, Qt::ImageConversionFlags flags, bool inPlace)
     381{
     382    QImage::Format format;
     383#ifdef Q_WS_QWS
     384    if (pixelType() == BitmapType) {
     385        format = QImage::Format_Mono;
     386    } else {
     387        format = QScreen::instance()->pixelFormat();
     388        if (format == QImage::Format_Invalid)
     389            format = QImage::Format_ARGB32_Premultiplied;
     390        else if (format == QImage::Format_Indexed8) // currently not supported
     391            format = QImage::Format_RGB444;
     392    }
     393
     394    if (sourceImage.hasAlphaChannel()
     395        && ((flags & Qt::NoOpaqueDetection)
     396            || const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())) {
     397        switch (format) {
     398            case QImage::Format_RGB16:
     399                format = QImage::Format_ARGB8565_Premultiplied;
     400                break;
     401            case QImage::Format_RGB666:
     402                format = QImage::Format_ARGB6666_Premultiplied;
     403                break;
     404            case QImage::Format_RGB555:
     405                format = QImage::Format_ARGB8555_Premultiplied;
     406                break;
     407            case QImage::Format_RGB444:
     408                format = QImage::Format_ARGB4444_Premultiplied;
     409                break;
     410            default:
     411                format = QImage::Format_ARGB32_Premultiplied;
     412                break;
     413        }
     414    } else if (format == QImage::Format_Invalid) {
     415        format = QImage::Format_ARGB32_Premultiplied;
     416    }
     417#else
     418    if (pixelType() == BitmapType) {
     419        format = QImage::Format_MonoLSB;
     420    } else {
     421        if (sourceImage.depth() == 1) {
     422            format = sourceImage.hasAlphaChannel()
     423                    ? QImage::Format_ARGB32_Premultiplied
     424                    : QImage::Format_RGB32;
     425        } else {
     426            QImage::Format opaqueFormat = QNativeImage::systemFormat();
     427            QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
     428
     429#if !defined(QT_HAVE_NEON) && !defined(QT_ALWAYS_HAVE_SSE2)
     430            switch (opaqueFormat) {
     431            case QImage::Format_RGB16:
     432                alphaFormat = QImage::Format_ARGB8565_Premultiplied;
     433                break;
     434            default: // We don't care about the others...
     435                break;
     436            }
     437#endif
     438
     439            if (!sourceImage.hasAlphaChannel()) {
     440                format = opaqueFormat;
     441            } else if ((flags & Qt::NoOpaqueDetection) == 0
     442                       && !const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())
     443            {
     444                // image has alpha format but is really opaque, so try to do a
     445                // more efficient conversion
     446                if (sourceImage.format() == QImage::Format_ARGB32
     447                    || sourceImage.format() == QImage::Format_ARGB32_Premultiplied)
     448                {
     449                    if (!inPlace)
     450                        sourceImage.detach();
     451                    sourceImage.d->format = QImage::Format_RGB32;
     452                }
     453                format = opaqueFormat;
     454            } else {
     455                format = alphaFormat;
     456            }
     457        }
     458    }
     459#endif
     460
     461    if (inPlace && sourceImage.d->convertInPlace(format, flags)) {
     462        image = sourceImage;
     463    } else {
     464        image = sourceImage.convertToFormat(format);
     465    }
     466
     467    if (image.d) {
     468        w = image.d->width;
     469        h = image.d->height;
     470        d = image.d->depth;
     471    } else {
     472        w = h = d = 0;
     473    }
     474    is_null = (w <= 0 || h <= 0);
     475
     476    setSerialNumber(image.serialNumber());
     477}
     478
    397479QImage* QRasterPixmapData::buffer()
    398480{
  • trunk/src/gui/image/qpixmap_raster_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7373    void resize(int width, int height);
    7474    void fromFile(const QString &filename, Qt::ImageConversionFlags flags);
     75    bool fromData(const uchar *buffer, uint len, const char *format, Qt::ImageConversionFlags flags);
    7576    void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
     77    void fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags);
    7678
     79    void copy(const QPixmapData *data, const QRect &rect);
    7780    bool scroll(int dx, int dy, const QRect &rect);
    7881    void fill(const QColor &color);
     
    8184    void setAlphaChannel(const QPixmap &alphaChannel);
    8285    QImage toImage() const;
     86    QImage toImage(const QRect &rect) const;
    8387    QPaintEngine* paintEngine() const;
    8488    QImage* buffer();
     
    8690protected:
    8791    int metric(QPaintDevice::PaintDeviceMetric metric) const;
     92    void createPixmapForImage(QImage &sourceImage, Qt::ImageConversionFlags flags, bool inPlace);
     93    void setImage(const QImage &image);
    8894    QImage image;
    8995
  • trunk/src/gui/image/qpixmap_s60.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6464                                     0x10, 0x20, 0x40, 0x80 };
    6565
     66static bool cleanup_function_registered = false;
     67static QS60PixmapData *firstPixmap = 0;
     68
     69// static
     70void QS60PixmapData::qt_symbian_register_pixmap(QS60PixmapData *pd)
     71{
     72    if (!cleanup_function_registered) {
     73        qAddPostRoutine(qt_symbian_release_pixmaps);
     74        cleanup_function_registered = true;
     75    }
     76
     77    pd->next = firstPixmap;
     78    pd->prev = 0;
     79    if (firstPixmap)
     80        firstPixmap->prev = pd;
     81    firstPixmap = pd;
     82}
     83
     84// static
     85void QS60PixmapData::qt_symbian_unregister_pixmap(QS60PixmapData *pd)
     86{
     87    if (pd->next)
     88        pd->next->prev = pd->prev;
     89    if (pd->prev)
     90        pd->prev->next = pd->next;
     91    else
     92        firstPixmap = pd->next;
     93}
     94
     95// static
     96void QS60PixmapData::qt_symbian_release_pixmaps()
     97{
     98    // Scan all QS60PixmapData objects in the system and destroy them.
     99    QS60PixmapData *pd = firstPixmap;
     100    while (pd != 0) {
     101        pd->release();
     102        pd = pd->next;
     103    }
     104}
    66105
    67106/*
     
    158197public:
    159198
    160     bool heapWasLocked;
     199    static int heapRefCount;
    161200    QSysInfo::SymbianVersion symbianVersion;
    162201
    163     explicit QSymbianBitmapDataAccess() : heapWasLocked(false)
     202    explicit QSymbianBitmapDataAccess()
    164203    {
    165204        symbianVersion = QSysInfo::symbianVersion();
     
    170209    inline void beginDataAccess(CFbsBitmap *bitmap)
    171210    {
    172         if (symbianVersion == QSysInfo::SV_9_2)
    173             heapWasLocked = qt_symbianFbsClient()->lockHeap();
    174         else
     211        if (symbianVersion == QSysInfo::SV_9_2) {
     212            if (heapRefCount == 0)
     213                qt_symbianFbsClient()->lockHeap();
     214        } else {
    175215            bitmap->LockHeap(ETrue);
     216        }
     217
     218        heapRefCount++;
    176219    }
    177220
    178221    inline void endDataAccess(CFbsBitmap *bitmap)
    179222    {
     223        heapRefCount--;
     224
    180225        if (symbianVersion == QSysInfo::SV_9_2) {
    181             if (!heapWasLocked)
     226            if (heapRefCount == 0)
    182227                qt_symbianFbsClient()->unlockHeap();
    183228        } else {
     
    186231    }
    187232};
     233
     234int QSymbianBitmapDataAccess::heapRefCount = 0;
    188235
    189236
     
    349396    pengine(0),
    350397    bytes(0),
    351     formatLocked(false)
    352 {
    353 
     398    formatLocked(false),
     399    next(0),
     400    prev(0)
     401{
     402    qt_symbian_register_pixmap(this);
    354403}
    355404
     
    358407    release();
    359408    delete symbianBitmapDataAccess;
     409    qt_symbian_unregister_pixmap(this);
    360410}
    361411
     
    782832        bool needsCopy = false;
    783833
    784         QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
    785834        if (!(S60->supportsPremultipliedAlpha)) {
    786835            // Convert argb32_premultiplied to argb32 since Symbian 9.2 does
     
    920969
    921970            TSize size = sourceBitmap->SizeInPixels();
     971            int bytesPerLine = sourceBitmap->ScanLineLength(size.iWidth, displayMode);
    922972
    923973            QSymbianBitmapDataAccess da;
    924974            da.beginDataAccess(sourceBitmap);
    925975            uchar *bytes = (uchar*)sourceBitmap->DataAddress();
    926             QImage img = QImage(bytes, size.iWidth, size.iHeight, format);
     976            QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format);
    927977            img = img.copy();
    928978            da.endDataAccess(sourceBitmap);
     
    9631013}
    9641014
     1015void QS60PixmapData::convertToDisplayMode(int mode)
     1016{
     1017    const TDisplayMode displayMode = static_cast<TDisplayMode>(mode);
     1018    if (!cfbsBitmap || cfbsBitmap->DisplayMode() == displayMode)
     1019        return;
     1020    if (image.depth() != TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode)) {
     1021        qWarning("Cannot convert display mode due to depth mismatch");
     1022        return;
     1023    }
     1024
     1025    const TSize size = cfbsBitmap->SizeInPixels();
     1026    QScopedPointer<CFbsBitmap> newBitmap(createSymbianCFbsBitmap(size, displayMode));
     1027
     1028    const uchar *sptr = const_cast<const QImage &>(image).bits();
     1029    symbianBitmapDataAccess->beginDataAccess(newBitmap.data());
     1030    uchar *dptr = (uchar*)newBitmap->DataAddress();
     1031    Mem::Copy(dptr, sptr, image.byteCount());
     1032    symbianBitmapDataAccess->endDataAccess(newBitmap.data());
     1033
     1034    QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
     1035    delete cfbsBitmap;
     1036    lock.relock();
     1037    cfbsBitmap = newBitmap.take();
     1038    setSerialNumber(cfbsBitmap->Handle());
     1039    UPDATE_BUFFER();
     1040}
     1041
    9651042QPixmapData *QS60PixmapData::createCompatiblePixmapData() const
    9661043{
  • trunk/src/gui/image/qpixmap_s60_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    108108    void fromNativeType(void* pixmap, NativeType type);
    109109
     110    void convertToDisplayMode(int mode);
     111
    110112private:
    111113    void release();
     
    121123    bool formatLocked;
    122124
     125    QS60PixmapData *next;
     126    QS60PixmapData *prev;
     127
     128    static void qt_symbian_register_pixmap(QS60PixmapData *pd);
     129    static void qt_symbian_unregister_pixmap(QS60PixmapData *pd);
     130    static void qt_symbian_release_pixmaps();
     131
    123132    friend class QPixmap;
    124133    friend class QS60WindowSurface;
  • trunk/src/gui/image/qpixmap_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpixmap_x11.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    315315
    316316QX11PixmapData::QX11PixmapData(PixelType type)
    317     : QPixmapData(type, X11Class), hd(0),
    318       flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0), gl_surface(0),
     317    : QPixmapData(type, X11Class), gl_surface(0), hd(0),
     318      flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0),
    319319      share_mode(QPixmap::ImplicitlyShared), pengine(0)
    320320{
     
    11431143}
    11441144
    1145 void QX11PixmapData::bitmapFromImage(const QImage &image)
     1145Qt::HANDLE QX11PixmapData::createBitmapFromImage(const QImage &image)
    11461146{
    11471147    QImage img = image.convertToFormat(QImage::Format_MonoLSB);
     
    11561156    char  *bits;
    11571157    uchar *tmp_bits;
    1158     w = img.width();
    1159     h = img.height();
    1160     d = 1;
    1161     is_null = (w <= 0 || h <= 0);
     1158    int w = img.width();
     1159    int h = img.height();
    11621160    int bpl = (w + 7) / 8;
    11631161    int ibpl = img.bytesPerLine();
     
    11781176        tmp_bits = 0;
    11791177    }
    1180     hd = (Qt::HANDLE)XCreateBitmapFromData(xinfo.display(),
    1181                                            RootWindow(xinfo.display(), xinfo.screen()),
     1178    Qt::HANDLE hd = (Qt::HANDLE)XCreateBitmapFromData(X11->display,
     1179                                           QX11Info::appRootWindow(),
    11821180                                           bits, w, h);
    1183 
     1181    if (tmp_bits)                                // Avoid purify complaint
     1182        delete [] tmp_bits;
     1183    return hd;
     1184}
     1185
     1186void QX11PixmapData::bitmapFromImage(const QImage &image)
     1187{
     1188    w = image.width();
     1189    h = image.height();
     1190    d = 1;
     1191    is_null = (w <= 0 || h <= 0);
     1192    hd = createBitmapFromImage(image);
    11841193#ifndef QT_NO_XRENDER
    11851194    if (X11->use_xrender)
     
    11871196                                       XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
    11881197#endif // QT_NO_XRENDER
    1189 
    1190     if (tmp_bits)                                // Avoid purify complaint
    1191         delete [] tmp_bits;
    11921198}
    11931199
     
    12451251
    12461252    if (!X11) {
    1247 #ifndef QT_NO_DEBUG
    1248         qWarning("~QX11PixmapData(): QPixmap objects must be destroyed before the QApplication"
    1249                  " object, otherwise the native pixmap object will be leaked.");
    1250 #endif
     1253        // At this point, the X server will already have freed our resources,
     1254        // so there is nothing to do.
    12511255        return;
    12521256    }
     
    13171321    return mask;
    13181322}
    1319 
    13201323
    13211324/*!
     
    14551458}
    14561459
     1460struct QXImageWrapper
     1461{
     1462    XImage *xi;
     1463};
     1464
     1465bool QX11PixmapData::canTakeQImageFromXImage(const QXImageWrapper &xiWrapper) const
     1466{
     1467    XImage *xi = xiWrapper.xi;
     1468
     1469    // ARGB32_Premultiplied
     1470    if (picture && depth() == 32)
     1471        return true;
     1472
     1473    Visual *visual = (Visual *)xinfo.visual();
     1474
     1475    // RGB32
     1476    if (depth() == 24 && xi->bits_per_pixel == 32 && visual->red_mask == 0xff0000
     1477        && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
     1478        return true;
     1479
     1480    // RGB16
     1481    if (depth() == 16 && xi->bits_per_pixel == 16 && visual->red_mask == 0xf800
     1482        && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f)
     1483        return true;
     1484
     1485    return false;
     1486}
     1487
     1488QImage QX11PixmapData::takeQImageFromXImage(const QXImageWrapper &xiWrapper) const
     1489{
     1490    XImage *xi = xiWrapper.xi;
     1491
     1492    QImage::Format format = QImage::Format_ARGB32_Premultiplied;
     1493    if (depth() == 24)
     1494        format = QImage::Format_RGB32;
     1495    else if (depth() == 16)
     1496        format = QImage::Format_RGB16;
     1497
     1498    QImage image((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format);
     1499    // take ownership
     1500    image.data_ptr()->own_data = true;
     1501    xi->data = 0;
     1502
     1503    // we may have to swap the byte order
     1504    if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
     1505        || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
     1506    {
     1507        for (int i=0; i < image.height(); i++) {
     1508            if (depth() == 16) {
     1509                ushort *p = (ushort*)image.scanLine(i);
     1510                ushort *end = p + image.width();
     1511                while (p < end) {
     1512                    *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
     1513                    p++;
     1514                }
     1515            } else {
     1516                uint *p = (uint*)image.scanLine(i);
     1517                uint *end = p + image.width();
     1518                while (p < end) {
     1519                    *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
     1520                         | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
     1521                    p++;
     1522                }
     1523            }
     1524        }
     1525    }
     1526
     1527    // fix-up alpha channel
     1528    if (format == QImage::Format_RGB32) {
     1529        QRgb *p = (QRgb *)image.bits();
     1530        for (int y = 0; y < xi->height; ++y) {
     1531            for (int x = 0; x < xi->width; ++x)
     1532                p[x] |= 0xff000000;
     1533            p += xi->bytes_per_line / 4;
     1534        }
     1535    }
     1536
     1537    XDestroyImage(xi);
     1538    return image;
     1539}
     1540
     1541QImage QX11PixmapData::toImage(const QRect &rect) const
     1542{
     1543    QXImageWrapper xiWrapper;
     1544    xiWrapper.xi = XGetImage(X11->display, hd, rect.x(), rect.y(), rect.width(), rect.height(),
     1545                             AllPlanes, (depth() == 1) ? XYPixmap : ZPixmap);
     1546
     1547    Q_CHECK_PTR(xiWrapper.xi);
     1548    if (!xiWrapper.xi)
     1549        return QImage();
     1550
     1551    if (!x11_mask && canTakeQImageFromXImage(xiWrapper))
     1552        return takeQImageFromXImage(xiWrapper);
     1553
     1554    QImage image = toImage(xiWrapper, rect);
     1555    qSafeXDestroyImage(xiWrapper.xi);
     1556    return image;
     1557}
     1558
    14571559/*!
    14581560    Converts the pixmap to a QImage. Returns a null image if the
     
    14721574QImage QX11PixmapData::toImage() const
    14731575{
     1576    return toImage(QRect(0, 0, w, h));
     1577}
     1578
     1579QImage QX11PixmapData::toImage(const QXImageWrapper &xiWrapper, const QRect &rect) const
     1580{
     1581    XImage *xi = xiWrapper.xi;
     1582
    14741583    int d = depth();
    14751584    Visual *visual = (Visual *)xinfo.visual();
     
    14891598    }
    14901599
    1491     XImage *xi = XGetImage(X11->display, hd, 0, 0, w, h, AllPlanes,
    1492                            (d == 1) ? XYPixmap : ZPixmap);
    1493 
    1494     Q_CHECK_PTR(xi);
    1495     if (!xi)
    1496         return QImage();
    1497 
    1498     if (picture && depth() == 32) {
    1499         QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
    1500         memcpy(image.bits(), xi->data, xi->bytes_per_line * xi->height);
    1501 
    1502         // we may have to swap the byte order
    1503         if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
    1504             || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
    1505         {
    1506             for (int i=0; i < image.height(); i++) {
    1507                 uint *p = (uint*)image.scanLine(i);
    1508                 uint *end = p + image.width();
    1509                 if ((xi->byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
    1510                     || (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) {
    1511                     while (p < end) {
    1512                         *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
    1513                              | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
    1514                         p++;
    1515                     }
    1516                 } else if (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) {
    1517                     while (p < end) {
    1518                         *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff)
    1519                              | ((*p ) & 0xff00ff00);
    1520                         p++;
    1521                     }
    1522                 }
    1523             }
    1524         }
    1525 
    1526         // throw away image data
    1527         qSafeXDestroyImage(xi);
    1528 
    1529         return image;
    1530     }
    1531 
    15321600    if (d == 1 && xi->bitmap_bit_order == LSBFirst)
    15331601        format = QImage::Format_MonoLSB;
     
    15351603        format = QImage::Format_ARGB32;
    15361604
    1537     QImage image(w, h, format);
     1605    QImage image(xi->width, xi->height, format);
    15381606    if (image.isNull())                        // could not create image
    15391607        return image;
     
    15411609    QImage alpha;
    15421610    if (x11_mask) {
    1543         alpha = mask().toImage();
     1611        if (rect.contains(QRect(0, 0, w, h)))
     1612            alpha = mask().toImage();
     1613        else
     1614            alpha = mask().toImage().copy(rect);
    15441615    }
    15451616    bool ale = alpha.format() == QImage::Format_MonoLSB;
     
    15841655            bppc++;
    15851656
    1586         for (int y = 0; y < h; ++y) {
     1657        for (int y = 0; y < xi->height; ++y) {
    15871658            uchar* asrc = x11_mask ? alpha.scanLine(y) : 0;
    15881659            dst = (QRgb *)image.scanLine(y);
    15891660            src = (uchar *)xi->data + xi->bytes_per_line*y;
    1590             for (int x = 0; x < w; x++) {
     1661            for (int x = 0; x < xi->width; x++) {
    15911662                switch (bppc) {
    15921663                case 8:
     
    16181689                    break;
    16191690                default:                        // should not really happen
    1620                     x = w;                        // leave loop
    1621                     y = h;
     1691                    x = xi->width;                        // leave loop
     1692                    y = xi->height;
    16221693                    pixel = 0;                // eliminate compiler warning
    16231694                    qWarning("QPixmap::convertToImage: Invalid depth %d", bppc);
     
    16571728        char *xidata = xi->data;                // copy each scanline
    16581729        int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
    1659         for (int y=0; y<h; y++) {
     1730        for (int y=0; y<xi->height; y++) {
    16601731            memcpy(image.scanLine(y), xidata, bpl);
    16611732            xidata += xi->bytes_per_line;
     
    16831754
    16841755        if (x11_mask) {                         // which pixels are used?
    1685             for (int i = 0; i < h; i++) {
     1756            for (int i = 0; i < xi->height; i++) {
    16861757                uchar* asrc = alpha.scanLine(i);
    16871758                p = image.scanLine(i);
    16881759                if (ale) {
    1689                     for (int x = 0; x < w; x++) {
     1760                    for (int x = 0; x < xi->width; x++) {
    16901761                        if (asrc[x >> 3] & (1 << (x & 7)))
    16911762                            use[*p] = 1;
     
    16931764                    }
    16941765                } else {
    1695                     for (int x = 0; x < w; x++) {
     1766                    for (int x = 0; x < xi->width; x++) {
    16961767                        if (asrc[x >> 3] & (0x80 >> (x & 7)))
    16971768                            use[*p] = 1;
     
    17011772            }
    17021773        } else {
    1703             for (int i = 0; i < h; i++) {
     1774            for (int i = 0; i < xi->height; i++) {
    17041775                p = image.scanLine(i);
    17051776                end = p + bpl;
     
    17131784                pix[i] = ncols++;
    17141785        }
    1715         for (int i = 0; i < h; i++) {                        // translate pixels
     1786        for (int i = 0; i < xi->height; i++) {                        // translate pixels
    17161787            p = image.scanLine(i);
    17171788            end = p + bpl;
     
    17331804                trans = image.scanLine(0)[0];
    17341805            }
    1735             for (int i = 0; i < h; i++) {
     1806            for (int i = 0; i < xi->height; i++) {
    17361807                uchar* asrc = alpha.scanLine(i);
    17371808                p = image.scanLine(i);
    17381809                if (ale) {
    1739                     for (int x = 0; x < w; x++) {
     1810                    for (int x = 0; x < xi->width; x++) {
    17401811                        if (!(asrc[x >> 3] & (1 << (x & 7))))
    17411812                            *p = trans;
     
    17431814                    }
    17441815                } else {
    1745                     for (int x = 0; x < w; x++) {
     1816                    for (int x = 0; x < xi->width; x++) {
    17461817                        if (!(asrc[x >> 3] & (1 << (7 -(x & 7)))))
    17471818                            *p = trans;
     
    17601831        }
    17611832    }
    1762 
    1763     qSafeXDestroyImage(xi);
    17641833
    17651834    return image;
  • trunk/src/gui/image/qpixmap_x11_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6363class QX11PaintEngine;
    6464
     65struct QXImageWrapper;
     66
    6567class Q_GUI_EXPORT QX11PixmapData : public QPixmapData
    6668{
     
    8890                        Qt::TransformationMode mode) const;
    8991    QImage toImage() const;
     92    QImage toImage(const QRect &rect) const;
    9093    QPaintEngine* paintEngine() const;
    9194
    9295    Qt::HANDLE handle() const { return hd; }
    9396    Qt::HANDLE x11ConvertToDefaultDepth();
     97
     98    static Qt::HANDLE createBitmapFromImage(const QImage &image);
     99
     100    void* gl_surface;
     101#ifndef QT_NO_XRENDER
     102    void convertToARGB32(bool preserveContents = true);
     103#endif
    94104
    95105protected:
     
    104114    friend class QGLContextPrivate; // Needs to access xinfo, gl_surface & flags
    105115    friend class QEglContext; // Needs gl_surface
     116    friend class QGLContext; // Needs gl_surface
    106117    friend class QX11GLPixmapData; // Needs gl_surface
     118    friend class QMeeGoLivePixmapData; // Needs gl_surface and flags
    107119    friend bool  qt_createEGLSurfaceForPixmap(QPixmapData*, bool); // Needs gl_surface
    108120
    109121    void release();
    110122
     123    QImage toImage(const QXImageWrapper &xi, const QRect &rect) const;
     124
    111125    QBitmap mask_to_bitmap(int screen) const;
    112126    static Qt::HANDLE bitmap_to_mask(const QBitmap &, int screen);
    113127    void bitmapFromImage(const QImage &image);
     128
     129    bool canTakeQImageFromXImage(const QXImageWrapper &xi) const;
     130    QImage takeQImageFromXImage(const QXImageWrapper &xi) const;
    114131
    115132    Qt::HANDLE hd;
     
    129146    Qt::HANDLE mask_picture;
    130147    Qt::HANDLE hd2; // sorted in the default display depth
    131     Qt::HANDLE gl_surface;
    132 #ifndef QT_NO_XRENDER
    133     void convertToARGB32(bool preserveContents = true);
    134 #endif
    135148    QPixmap::ShareMode share_mode;
    136149
  • trunk/src/gui/image/qpixmapcache.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4040****************************************************************************/
    4141
     42#define Q_TEST_QPIXMAPCACHE
    4243#include "qpixmapcache.h"
    4344#include "qobject.h"
     
    195196    static QPixmapCache::KeyData* getKeyData(QPixmapCache::Key *key);
    196197
     198    QList< QPair<QString,QPixmap> > allPixmaps() const;
     199    bool flushDetachedPixmaps(bool nt);
     200
    197201private:
     202    enum { soon_time = 10000, flush_time = 30000 };
    198203    int *keyArray;
    199204    int theid;
     
    233238  cache is in active use.
    234239
    235   When the last pixmap has been deleted from the cache, kill the
    236   timer so Qt won't keep the CPU from going into sleep mode.
    237 */
    238 void QPMCache::timerEvent(QTimerEvent *)
     240  When the last detached pixmap has been deleted from the cache, kill the
     241  timer so Qt won't keep the CPU from going into sleep mode. Currently
     242  the timer is not restarted when the pixmap becomes unused, but it does
     243  restart once something else is added (i.e. the cache space is actually needed).
     244
     245  Returns true if any were removed.
     246*/
     247bool QPMCache::flushDetachedPixmaps(bool nt)
    239248{
    240249    int mc = maxCost();
    241     bool nt = totalCost() == ps;
    242250    setMaxCost(nt ? totalCost() * 3 / 4 : totalCost() -1);
    243251    setMaxCost(mc);
    244252    ps = totalCost();
    245253
     254    bool any = false;
    246255    QHash<QString, QPixmapCache::Key>::iterator it = cacheKeys.begin();
    247256    while (it != cacheKeys.end()) {
     
    249258            releaseKey(it.value());
    250259            it = cacheKeys.erase(it);
     260            any = true;
    251261        } else {
    252262            ++it;
     
    254264    }
    255265
    256     if (!size()) {
     266    return any;
     267}
     268
     269void QPMCache::timerEvent(QTimerEvent *)
     270{
     271    bool nt = totalCost() == ps;
     272    if (!flushDetachedPixmaps(nt)) {
    257273        killTimer(theid);
    258274        theid = 0;
    259275    } else if (nt != t) {
    260276        killTimer(theid);
    261         theid = startTimer(nt ? 10000 : 30000);
     277        theid = startTimer(nt ? soon_time : flush_time);
    262278        t = nt;
    263279    }
    264280}
     281
    265282
    266283QPixmap *QPMCache::object(const QString &key) const
     
    306323        cacheKeys.insert(key, cacheKey);
    307324        if (!theid) {
    308             theid = startTimer(30000);
     325            theid = startTimer(flush_time);
    309326            t = false;
    310327        }
     
    322339    if (success) {
    323340        if (!theid) {
    324             theid = startTimer(30000);
     341            theid = startTimer(flush_time);
    325342            t = false;
    326343        }
     
    343360    if (success) {
    344361        if(!theid) {
    345             theid = startTimer(30000);
     362            theid = startTimer(flush_time);
    346363            t = false;
    347364        }
     
    423440}
    424441
     442QList< QPair<QString,QPixmap> > QPMCache::allPixmaps() const
     443{
     444    QList< QPair<QString,QPixmap> > r;
     445    QHash<QString, QPixmapCache::Key>::const_iterator it = cacheKeys.begin();
     446    while (it != cacheKeys.end()) {
     447        QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(it.value());
     448        if (ptr)
     449            r.append(QPair<QString,QPixmap>(it.key(),*ptr));
     450        ++it;
     451    }
     452    return r;
     453}
     454
     455
    425456Q_GLOBAL_STATIC(QPMCache, pm_cache)
    426457
     
    634665}
    635666
     667void QPixmapCache::flushDetachedPixmaps()
     668{
     669    pm_cache()->flushDetachedPixmaps(true);
     670}
     671
     672int QPixmapCache::totalUsed()
     673{
     674    return (pm_cache()->totalCost()+1023) / 1024;
     675}
     676
     677QList< QPair<QString,QPixmap> > QPixmapCache::allPixmaps()
     678{
     679    return pm_cache()->allPixmaps();
     680}
     681
    636682QT_END_NAMESPACE
  • trunk/src/gui/image/qpixmapcache.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4545#include <QtGui/qpixmap.h>
    4646
     47#ifdef Q_TEST_QPIXMAPCACHE
     48#include <QtCore/qpair.h>
     49#endif
     50
    4751QT_BEGIN_HEADER
    4852
     
    8488    static void remove(const Key &key);
    8589    static void clear();
     90
     91#ifdef Q_TEST_QPIXMAPCACHE
     92    static void flushDetachedPixmaps();
     93    static int totalUsed();
     94    static QList< QPair<QString,QPixmap> > allPixmaps();
     95#endif
    8696};
    8797
  • trunk/src/gui/image/qpixmapcache_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8282    QPixmapCacheEntry(const QPixmapCache::Key &key, const QPixmap &pix) : QPixmap(pix), key(key)
    8383    {
    84         if (data && data->classId() == QPixmapData::RasterClass) {
    85             QRasterPixmapData *d = static_cast<QRasterPixmapData*>(data.data());
     84        QPixmapData *pd = pixmapData();
     85        if (pd && pd->classId() == QPixmapData::RasterClass) {
     86            QRasterPixmapData *d = static_cast<QRasterPixmapData*>(pd);
    8687            if (!d->image.isNull() && d->image.d->paintEngine
    8788                && !d->image.d->paintEngine->isActive())
     
    9697};
    9798
     99inline bool qIsDetached(QPixmapCacheEntry &t) { return t.isDetached(); }
     100
    98101QT_END_NAMESPACE
    99102
  • trunk/src/gui/image/qpixmapdata.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    125125}
    126126
     127void QPixmapData::fromImageReader(QImageReader *imageReader,
     128                                  Qt::ImageConversionFlags flags)
     129{
     130    const QImage image = imageReader->read();
     131    fromImage(image, flags);
     132}
     133
    127134bool QPixmapData::fromFile(const QString &fileName, const char *format,
    128135                           Qt::ImageConversionFlags flags)
     
    147154void QPixmapData::copy(const QPixmapData *data, const QRect &rect)
    148155{
    149     fromImage(data->toImage().copy(rect), Qt::AutoColor);
     156    fromImage(data->toImage(rect), Qt::NoOpaqueDetection);
    150157}
    151158
     
    256263}
    257264
     265QImage QPixmapData::toImage(const QRect &rect) const
     266{
     267    if (rect.contains(QRect(0, 0, w, h)))
     268        return toImage();
     269    else
     270        return toImage().copy(rect);
     271}
     272
    258273QImage* QPixmapData::buffer()
    259274{
  • trunk/src/gui/image/qpixmapdata_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5959QT_BEGIN_NAMESPACE
    6060
     61class QImageReader;
     62
    6163class Q_GUI_EXPORT QPixmapData
    6264{
     
    7476#endif
    7577    enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass,
    76                    OpenGLClass, OpenVGClass, CustomClass = 1024 };
     78                   OpenGLClass, OpenVGClass, RuntimeClass, CustomClass = 1024 };
    7779
    7880    QPixmapData(PixelType pixelType, int classId);
     
    8486    virtual void fromImage(const QImage &image,
    8587                           Qt::ImageConversionFlags flags) = 0;
     88    virtual void fromImageReader(QImageReader *imageReader,
     89                                 Qt::ImageConversionFlags flags);
    8690
    8791    virtual bool fromFile(const QString &filename, const char *format,
     
    103107    virtual QPixmap alphaChannel() const;
    104108    virtual QImage toImage() const = 0;
     109    virtual QImage toImage(const QRect &rect) const;
    105110    virtual QPaintEngine* paintEngine() const = 0;
    106111
     
    134139    static QPixmapData *create(int w, int h, PixelType type);
    135140
     141    virtual QPixmapData *runtimeData() const { return 0; }
     142
    136143protected:
     144
    137145    void setSerialNumber(int serNo);
    138146    int w;
  • trunk/src/gui/image/qpixmapdatafactory.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5757# include <private/qpixmap_mac_p.h>
    5858#endif
    59 #ifdef Q_WS_S60
     59#ifdef Q_OS_SYMBIAN
    6060# include <private/qpixmap_s60_p.h>
    6161#endif
     
    8888#elif defined(Q_WS_MAC)
    8989    return new QMacPixmapData(type);
    90 #elif defined(Q_WS_S60)
     90#elif defined(Q_OS_SYMBIAN)
    9191    return new QS60PixmapData(type);   
    9292#else
  • trunk/src/gui/image/qpixmapdatafactory_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpixmapfilter.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    727727    int img_height = img.height();
    728728    for (int row = 0; row < img_height; ++row) {
    729         for (int i = 0; i <= improvedQuality; ++i)
     729        for (int i = 0; i <= int(improvedQuality); ++i)
    730730            qt_blurrow<aprec, zprec, alphaOnly>(img, row, alpha);
    731731    }
     
    760760    img_height = temp.height();
    761761    for (int row = 0; row < img_height; ++row) {
    762         for (int i = 0; i <= improvedQuality; ++i)
     762        for (int i = 0; i <= int(improvedQuality); ++i)
    763763            qt_blurrow<aprec, zprec, alphaOnly>(temp, row, alpha);
    764764    }
    765765
    766766    if (transposed == 0) {
    767         qt_memrotate90(reinterpret_cast<const quint32*>(temp.bits()),
    768                        temp.width(), temp.height(), temp.bytesPerLine(),
    769                        reinterpret_cast<quint32*>(img.bits()),
    770                        img.bytesPerLine());
     767        if (img.depth() == 8) {
     768            qt_memrotate90(reinterpret_cast<const quint8*>(temp.bits()),
     769                           temp.width(), temp.height(), temp.bytesPerLine(),
     770                           reinterpret_cast<quint8*>(img.bits()),
     771                           img.bytesPerLine());
     772        } else {
     773            qt_memrotate90(reinterpret_cast<const quint32*>(temp.bits()),
     774                           temp.width(), temp.height(), temp.bytesPerLine(),
     775                           reinterpret_cast<quint32*>(img.bits()),
     776                           img.bytesPerLine());
     777        }
    771778    } else {
    772779        img = temp;
  • trunk/src/gui/image/qpixmapfilter_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qpnghandler.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5151#include <qvector.h>
    5252
     53#ifdef QT_USE_BUNDLED_LIBPNG
     54#include <../../3rdparty/libpng/png.h>
     55#include <../../3rdparty/libpng/pngconf.h>
     56#else
    5357#include <png.h>
    5458#include <pngconf.h>
     59#endif
    5560
    5661#ifdef Q_OS_WINCE
     
    7782  Never to grayscale.
    7883*/
     84
     85class QPngHandlerPrivate
     86{
     87public:
     88    enum State {
     89        Ready,
     90        ReadHeader,
     91        ReadingEnd,
     92        Error
     93    };
     94
     95    QPngHandlerPrivate(QPngHandler *qq)
     96        : gamma(0.0), quality(2), png_ptr(0), info_ptr(0),
     97          end_info(0), row_pointers(0), state(Ready), q(qq)
     98    { }
     99
     100    float gamma;
     101    int quality;
     102    QString description;
     103
     104    png_struct *png_ptr;
     105    png_info *info_ptr;
     106    png_info *end_info;
     107    png_byte **row_pointers;
     108
     109    bool readPngHeader();
     110    bool readPngImage(QImage *image);
     111
     112    QImage::Format readImageFormat();
     113
     114    State state;
     115
     116    QPngHandler *q;
     117};
     118
    79119
    80120#if defined(Q_C_CALLBACKS)
     
    114154void CALLBACK_CALL_TYPE iod_read_fn(png_structp png_ptr, png_bytep data, png_size_t length)
    115155{
    116     QIODevice *in = (QIODevice *)png_get_io_ptr(png_ptr);
     156    QPngHandlerPrivate *d = (QPngHandlerPrivate *)png_get_io_ptr(png_ptr);
     157    QIODevice *in = d->q->device();
     158
     159    if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && (in->size() - in->pos()) < 4 && length == 4) {
     160        // Workaround for certain malformed PNGs that lack the final crc bytes
     161        uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 };
     162        qMemCopy(data, endcrc, 4);
     163        in->seek(in->size());
     164        return;
     165    }
    117166
    118167    while (length) {
     
    163212    int bit_depth;
    164213    int color_type;
     214    png_bytep trans_alpha = 0;
     215    png_color_16p trans_color_p = 0;
     216    int num_trans;
     217    png_colorp palette = 0;
     218    int num_palette;
    165219    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
    166220
    167221    if (color_type == PNG_COLOR_TYPE_GRAY) {
    168222        // Black & White or 8-bit grayscale
    169         if (bit_depth == 1 && info_ptr->channels == 1) {
     223        if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
    170224            png_set_invert_mono(png_ptr);
    171225            png_read_update_info(png_ptr, info_ptr);
     
    208262                image.setColor(i, qRgba(c,c,c,0xff));
    209263            }
    210             if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    211 #if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
    212                 const int g = info_ptr->trans_values.gray;
    213 #else
    214                 const int g = info_ptr->trans_color.gray;
    215 #endif
     264            if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
     265                const int g = trans_color_p->gray;
    216266                if (g < ncols) {
    217267                    image.setColor(g, 0);
     
    220270        }
    221271    } else if (color_type == PNG_COLOR_TYPE_PALETTE
    222                && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
    223                && info_ptr->num_palette <= 256)
     272               && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
     273               && num_palette <= 256)
    224274    {
    225275        // 1-bit and 8-bit color
     
    234284                return;
    235285        }
    236         image.setColorCount(info_ptr->num_palette);
     286        png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
     287        image.setColorCount(num_palette);
    237288        int i = 0;
    238         if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    239             while (i < info_ptr->num_trans) {
     289        if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
     290            while (i < num_trans) {
    240291                image.setColor(i, qRgba(
    241                     info_ptr->palette[i].red,
    242                     info_ptr->palette[i].green,
    243                     info_ptr->palette[i].blue,
    244 #if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
    245                     info_ptr->trans[i]
    246 #else
    247                     info_ptr->trans_alpha[i]
    248 #endif
     292                    palette[i].red,
     293                    palette[i].green,
     294                    palette[i].blue,
     295                    trans_alpha[i]
    249296                   )
    250297               );
     
    252299            }
    253300        }
    254         while (i < info_ptr->num_palette) {
     301        while (i < num_palette) {
    255302            image.setColor(i, qRgba(
    256                 info_ptr->palette[i].red,
    257                 info_ptr->palette[i].green,
    258                 info_ptr->palette[i].blue,
     303                palette[i].red,
     304                palette[i].green,
     305                palette[i].blue,
    259306                0xff
    260307               )
     
    312359#endif
    313360
    314 class QPngHandlerPrivate
    315 {
    316 public:
    317     enum State {
    318         Ready,
    319         ReadHeader,
    320         Error
    321     };
    322 
    323     QPngHandlerPrivate(QPngHandler *qq)
    324         : gamma(0.0), quality(2), png_ptr(0), info_ptr(0),
    325           end_info(0), row_pointers(0), state(Ready), q(qq)
    326     { }
    327 
    328     float gamma;
    329     int quality;
    330     QString description;
    331 
    332     png_struct *png_ptr;
    333     png_info *info_ptr;
    334     png_info *end_info;
    335     png_byte **row_pointers;
    336 
    337     bool readPngHeader();
    338     bool readPngImage(QImage *image);
    339 
    340     QImage::Format readImageFormat();
    341 
    342     State state;
    343 
    344     QPngHandler *q;
    345 };
    346361
    347362/*!
     
    377392    }
    378393
    379     png_set_read_fn(png_ptr, q->device(), iod_read_fn);
     394    png_set_read_fn(png_ptr, this, iod_read_fn);
    380395    png_read_info(png_ptr, info_ptr);
    381396
     
    387402    while (num_text--) {
    388403        QString key, value;
    389 #if defined(PNG_iTXt_SUPPORTED)
     404#if defined(PNG_iTXt_SUPPORTED) && !defined(QT_NO_TEXTCODEC)
    390405        if (text_ptr->lang) {
    391406            QTextCodec *codec = QTextCodec::codecForName(text_ptr->lang);
     
    503518#endif
    504519
     520    state = ReadingEnd;
    505521    png_read_end(png_ptr, end_info);
    506522    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
     
    532548        png_uint_32 width, height;
    533549        int bit_depth, color_type;
    534         if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
     550        png_colorp palette;
     551        int num_palette;
     552        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
     553        if (color_type == PNG_COLOR_TYPE_GRAY) {
    535554            // Black & White or 8-bit grayscale
    536             if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) {
     555            if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
    537556                format = QImage::Format_Mono;
    538             } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
     557            } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    539558                format = QImage::Format_ARGB32;
    540559            } else {
    541560                format = QImage::Format_Indexed8;
    542561            }
    543         } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE
    544                 && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
    545                    && info_ptr->num_palette <= 256)
     562        } else if (color_type == PNG_COLOR_TYPE_PALETTE
     563                   && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
     564                   && num_palette <= 256)
    546565        {
    547566            // 1-bit and 8-bit color
    548             if (info_ptr->bit_depth != 1)
     567            if (bit_depth != 1)
    549568                png_set_packing(png_ptr);
    550569            png_read_update_info(png_ptr, info_ptr);
     
    553572        } else {
    554573            // 32-bit
    555             if (info_ptr->bit_depth == 16)
     574            if (bit_depth == 16)
    556575                png_set_strip_16(png_ptr);
    557576
    558577            format = QImage::Format_ARGB32;
    559578            // Only add filler if no alpha, or we can get 5 channel data.
    560             if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
     579            if (!(color_type & PNG_COLOR_MASK_ALPHA)
    561580                && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    562581                // We want 4 bytes, but it isn't an alpha channel
     
    649668        text_ptr[i].text_length = 0;
    650669        text_ptr[i].itxt_length = value.size();
    651         text_ptr[i].lang = "UTF-8";
     670        text_ptr[i].lang = const_cast<char*>("UTF-8");
    652671        text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
    653672#endif
     
    673692}
    674693
    675 bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in, int quality_in, const QString &description,
     694bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, int quality_in, const QString &description,
    676695                                 int off_x_in, int off_y_in)
    677696{
     
    679698    Q_UNUSED(description);
    680699#endif
    681 
    682     QImage image;
    683     switch (image_in.format()) {
    684     case QImage::Format_ARGB32_Premultiplied:
    685     case QImage::Format_ARGB4444_Premultiplied:
    686     case QImage::Format_ARGB8555_Premultiplied:
    687     case QImage::Format_ARGB8565_Premultiplied:
    688     case QImage::Format_ARGB6666_Premultiplied:
    689         image = image_in.convertToFormat(QImage::Format_ARGB32);
    690         break;
    691     case QImage::Format_RGB16:
    692     case QImage::Format_RGB444:
    693     case QImage::Format_RGB555:
    694     case QImage::Format_RGB666:
    695     case QImage::Format_RGB888:
    696         image = image_in.convertToFormat(QImage::Format_RGB32);
    697         break;
    698     default:
    699         image = image_in;
    700         break;
    701     }
    702700
    703701    QPoint offset = image.offset();
     
    707705    png_structp png_ptr;
    708706    png_infop info_ptr;
    709     png_bytep* row_pointers;
    710707
    711708    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
     
    736733    }
    737734
     735    png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
     736
     737
     738    int color_type = 0;
     739    if (image.colorCount())
     740        color_type = PNG_COLOR_TYPE_PALETTE;
     741    else if (image.hasAlphaChannel())
     742        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
     743    else
     744        color_type = PNG_COLOR_TYPE_RGB;
     745
     746    png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
     747                 image.depth() == 1 ? 1 : 8, // per channel
     748                 color_type, 0, 0, 0);       // sets #channels
     749
    738750    if (gamma != 0.0) {
    739751        png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
    740752    }
    741753
    742     png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
    743 
    744     info_ptr->channels =
    745         (image.depth() == 32)
    746         ? (image.format() == QImage::Format_RGB32 ? 3 : 4)
    747         : 1;
    748 
    749     png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
    750         image.depth() == 1 ? 1 : 8 /* per channel */,
    751         image.depth() == 32
    752             ? image.format() == QImage::Format_RGB32
    753                 ? PNG_COLOR_TYPE_RGB
    754                 : PNG_COLOR_TYPE_RGB_ALPHA
    755             : PNG_COLOR_TYPE_PALETTE, 0, 0, 0);
    756 
    757 
    758     //png_set_sBIT(png_ptr, info_ptr, 8);
    759     info_ptr->sig_bit.red = 8;
    760     info_ptr->sig_bit.green = 8;
    761     info_ptr->sig_bit.blue = 8;
     754    png_color_8 sig_bit;
     755    sig_bit.red = 8;
     756    sig_bit.green = 8;
     757    sig_bit.blue = 8;
     758    sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0;
     759    png_set_sBIT(png_ptr, info_ptr, &sig_bit);
    762760
    763761    if (image.format() == QImage::Format_MonoLSB)
    764762       png_set_packswap(png_ptr);
    765763
    766     png_colorp palette = 0;
    767     png_bytep copy_trans = 0;
    768764    if (image.colorCount()) {
    769765        // Paletted
    770         int num_palette = image.colorCount();
    771         palette = new png_color[num_palette];
    772         png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
    773         int* trans = new int[num_palette];
     766        int num_palette = qMin(256, image.colorCount());
     767        png_color palette[256];
     768        png_byte trans[256];
    774769        int num_trans = 0;
    775770        for (int i=0; i<num_palette; i++) {
    776             QRgb rgb=image.color(i);
    777             info_ptr->palette[i].red = qRed(rgb);
    778             info_ptr->palette[i].green = qGreen(rgb);
    779             info_ptr->palette[i].blue = qBlue(rgb);
    780             trans[i] = rgb >> 24;
     771            QRgb rgba=image.color(i);
     772            palette[i].red = qRed(rgba);
     773            palette[i].green = qGreen(rgba);
     774            palette[i].blue = qBlue(rgba);
     775            trans[i] = qAlpha(rgba);
    781776            if (trans[i] < 255) {
    782777                num_trans = i+1;
    783778            }
    784779        }
     780        png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
     781
    785782        if (num_trans) {
    786             copy_trans = new png_byte[num_trans];
    787             for (int i=0; i<num_trans; i++)
    788                 copy_trans[i] = trans[i];
    789             png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0);
    790         }
    791         delete [] trans;
    792     }
    793 
    794     if (image.format() != QImage::Format_RGB32) {
    795         info_ptr->sig_bit.alpha = 8;
     783            png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
     784        }
    796785    }
    797786
     
    802791    }
    803792
    804     // Qt==ARGB==Big(ARGB)==Little(BGRA)
    805     if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
     793    // Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless
     794    if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
     795        && image.format() != QImage::Format_RGB888) {
    806796        png_set_bgr(png_ptr);
    807797    }
     
    828818        png_set_packing(png_ptr);
    829819
    830     if (image.format() == QImage::Format_RGB32)
     820    if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888)
    831821        png_set_filler(png_ptr, 0,
    832822            QSysInfo::ByteOrder == QSysInfo::BigEndian ?
     
    849839    }
    850840
    851     png_uint_32 width;
    852     png_uint_32 height;
    853     int bit_depth;
    854     int color_type;
    855     png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
    856         0, 0, 0);
    857 
    858     const uchar *data = (static_cast<const QImage *>(&image))->bits();
    859     int bpl = image.bytesPerLine();
    860     row_pointers = new png_bytep[height];
    861     uint y;
    862     for (y=0; y<height; y++) {
    863         row_pointers[y] = (png_bytep)(data + y * bpl);
    864     }
    865     png_write_image(png_ptr, row_pointers);
    866     delete [] row_pointers;
     841    int height = image.height();
     842    int width = image.width();
     843    switch (image.format()) {
     844    case QImage::Format_Mono:
     845    case QImage::Format_MonoLSB:
     846    case QImage::Format_Indexed8:
     847    case QImage::Format_RGB32:
     848    case QImage::Format_ARGB32:
     849    case QImage::Format_RGB888:
     850        {
     851            png_bytep* row_pointers = new png_bytep[height];
     852            for (int y=0; y<height; y++)
     853                row_pointers[y] = (png_bytep)image.constScanLine(y);
     854            png_write_image(png_ptr, row_pointers);
     855            delete [] row_pointers;
     856        }
     857        break;
     858    default:
     859        {
     860            QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
     861            QImage row;
     862            png_bytep row_pointers[1];
     863            for (int y=0; y<height; y++) {
     864                row = image.copy(0, y, width, 1).convertToFormat(fmt);
     865                row_pointers[0] = png_bytep(row.constScanLine(0));
     866                png_write_rows(png_ptr, row_pointers, 1);
     867            }
     868        }
     869        break;
     870    }
    867871
    868872    png_write_end(png_ptr, info_ptr);
    869873    frames_written++;
    870 
    871     if (palette)
    872         delete [] palette;
    873     if (copy_trans)
    874         delete [] copy_trans;
    875874
    876875    png_destroy_write_struct(&png_ptr, &info_ptr);
     
    905904bool QPngHandler::canRead() const
    906905{
    907     if (d->state == QPngHandlerPrivate::Ready) {
    908         if (!canRead(device()))
    909             return false;
     906    if (d->state == QPngHandlerPrivate::Ready && !canRead(device()))
     907        return false;
     908
     909    if (d->state != QPngHandlerPrivate::Error) {
    910910        setFormat("png");
    911911        return true;
    912912    }
    913     return d->state != QPngHandlerPrivate::Error;
     913
     914    return false;
    914915}
    915916
     
    959960        return d->description;
    960961    else if (option == Size)
    961         return QSize(d->info_ptr->width, d->info_ptr->height);
     962        return QSize(png_get_image_width(d->png_ptr, d->info_ptr),
     963                     png_get_image_height(d->png_ptr, d->info_ptr));
    962964    else if (option == ImageFormat)
    963965        return d->readImageFormat();
  • trunk/src/gui/image/qpnghandler_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qppmhandler.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    410410bool QPpmHandler::canRead() const
    411411{
    412     if (state == Ready) {
    413         if (!canRead(device(), &subType))
    414             return false;
     412    if (state == Ready && !canRead(device(), &subType))
     413        return false;
     414
     415    if (state != Error) {
    415416        setFormat(subType);
    416417        return true;
    417418    }
    418     return state != Error;
     419
     420    return false;
    419421}
    420422
  • trunk/src/gui/image/qppmhandler_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qxbmhandler.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6767{
    6868    const int buflen = 300;
     69    const int maxlen = 4096;
    6970    char buf[buflen + 1];
    7071    QRegExp r1(QLatin1String("^#define[ \t]+[a-zA-Z0-9._]+[ \t]+"));
     
    7273
    7374    qint64 readBytes = 0;
    74 
    75     // "#define .._width <num>"
    76     readBytes = device->readLine(buf, buflen);
    77     if (readBytes <= 0)
    78         return false;
    79     buf[readBytes - 1] = '\0';
     75    qint64 totalReadBytes = 0;
     76
     77    buf[0] = '\0';
    8078
    8179    // skip initial comment, if any
    82     while (buf[0] != '#' && (readBytes = device->readLine( buf, buflen )) > 0) {}
    83 
    84     if (readBytes <= 0)
    85         return false;
     80    while (buf[0] != '#') {
     81        readBytes = device->readLine(buf, buflen);
     82
     83        // if readBytes >= buflen, it's very probably not a C file
     84        if (readBytes <= 0 || readBytes >= buflen -1)
     85            return false;
     86
     87        // limit xbm headers to the first 4k in the file to prevent
     88        // excessive reads on non-xbm files
     89        totalReadBytes += readBytes;
     90        if (totalReadBytes >= maxlen)
     91            return false;
     92    }
     93
    8694    buf[readBytes - 1] = '\0';
    8795    QString sbuf;
    8896    sbuf = QString::fromLatin1(buf);
    8997
     98    // "#define .._width <num>"
    9099    if (r1.indexIn(sbuf) == 0 &&
    91100         r2.indexIn(sbuf, r1.matchedLength()) == r1.matchedLength())
     
    262271bool QXbmHandler::canRead() const
    263272{
    264     if (state == Ready) {
    265         if (!canRead(device()))
    266             return false;
     273    if (state == Ready && !canRead(device()))
     274        return false;
     275
     276    if (state != Error) {
    267277        setFormat("xbm");
    268278        return true;
    269279    }
    270     return state != Error;
     280
     281    return false;
    271282}
    272283
  • trunk/src/gui/image/qxbmhandler_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/image/qxpmhandler.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    767767    XPMRGBData x;
    768768    x.name = name_no_space;
    769     // Funtion bsearch() is supposed to be
     769    // Function bsearch() is supposed to be
    770770    // void *bsearch(const void *key, const void *base, ...
    771771    // So why (char*)? Are there broken bsearch() declarations out there?
     
    12261226bool QXpmHandler::canRead() const
    12271227{
    1228     if (state == Ready && canRead(device())) {
     1228    if (state == Ready && !canRead(device()))
     1229        return false;
     1230
     1231    if (state != Error) {
    12291232        setFormat("xpm");
    12301233        return true;
    12311234    }
    1232     return state != Error;
     1235
     1236    return false;
    12331237}
    12341238
  • trunk/src/gui/image/qxpmhandler_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
Note: See TracChangeset for help on using the changeset viewer.