# qwt_plot_rasteritem.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 #include <qapplication.h>
    00011 #include <qdesktopwidget.h>
    00012 #include <qpaintdevice.h>
    00013 #include <qpainter.h>
    00014 #include "qwt_legend.h"
    00015 #include "qwt_legend_item.h"
    00016 #include "qwt_scale_map.h"
    00017 #include "qwt_plot_rasteritem.h"
    00018
    00019 class QwtPlotRasterItem::PrivateData
    00020 {
    00021 public:
    00022     PrivateData():
    00023         alpha(-1)
    00024     {
    00025         cache.policy = QwtPlotRasterItem::NoCache;
    00026     }
    00027
    00028     int alpha;
    00029
    00030     struct ImageCache
    00031     {
    00032         QwtPlotRasterItem::CachePolicy policy;
    00033         QwtDoubleRect rect;
    00034         QSize size;
    00035         QImage image;
    00036     } cache;
    00037 };
    00038
    00039 static QImage toRgba(const QImage& image, int alpha)
    00040 {
    00041     if ( alpha < 0 || alpha >= 255 )
    00042         return image;
    00043
    00044 #if QT_VERSION < 0x040000
    00045     QImage alphaImage(image.size(), 32);
    00046     alphaImage.setAlphaBuffer(true);
    00047 #else
    00048     QImage alphaImage(image.size(), QImage::Format_ARGB32);
    00049 #endif
    00050
    00051     const QRgb mask1 = qRgba(0, 0, 0, alpha);
    00052     const QRgb mask2 = qRgba(255, 255, 255, 0);
    00053     const QRgb mask3 = qRgba(0, 0, 0, 255);
    00054
    00055     const int w = image.size().width();
    00056     const int h = image.size().height();
    00057
    00058     if ( image.depth() == 8 )
    00059     {
    00060         for ( int y = 0; y < h; y++ )
    00061         {
    00062             QRgb* alphaLine = (QRgb*)alphaImage.scanLine(y);
    00063             const unsigned char *line = image.scanLine(y);
    00064
    00065             for ( int x = 0; x < w; x++ )
    00066                 *alphaLine++ = (image.color(*line++) & mask2) | mask1;
    00067         }
    00068     }
    00069     else if ( image.depth() == 32 )
    00070     {
    00071         for ( int y = 0; y < h; y++ )
    00072         {
    00073             QRgb* alphaLine = (QRgb*)alphaImage.scanLine(y);
    00074             const QRgb* line = (const QRgb*) image.scanLine(y);
    00075
    00076             for ( int x = 0; x < w; x++ )
    00077             {
    00078                 const QRgb rgb = *line++;
    00079                 if ( rgb & mask3 ) // alpha != 0
    00080                     *alphaLine++ = (rgb & mask2) | mask1;
    00081                 else
    00082                     *alphaLine++ = rgb;
    00083             }
    00084         }
    00085     }
    00086
    00087     return alphaImage;
    00088 }
    00089
    00091 QwtPlotRasterItem::QwtPlotRasterItem(const QString& title):
    00092     QwtPlotItem(QwtText(title))
    00093 {
    00094     init();
    00095 }
    00096
    00098 QwtPlotRasterItem::QwtPlotRasterItem(const QwtText& title):
    00099     QwtPlotItem(title)
    00100 {
    00101     init();
    00102 }
    00103
    00105 QwtPlotRasterItem::~QwtPlotRasterItem()
    00106 {
    00107     delete d_data;
    00108 }
    00109
    00110 void QwtPlotRasterItem::init()
    00111 {
    00112     d_data = new PrivateData();
    00113
    00114     setItemAttribute(QwtPlotItem::AutoScale, true);
    00115     setItemAttribute(QwtPlotItem::Legend, false);
    00116
    00117     setZ(8.0);
    00118 }
    00119
    00143 void QwtPlotRasterItem::setAlpha(int alpha)
    00144 {
    00145     if ( alpha < 0 )
    00146         alpha = -1;
    00147
    00148     if ( alpha > 255 )
    00149         alpha = 255;
    00150
    00151     if ( alpha != d_data->alpha )
    00152     {
    00153         d_data->alpha = alpha;
    00154
    00155         itemChanged();
    00156     }
    00157 }
    00158
    00163 int QwtPlotRasterItem::alpha() const
    00164 {
    00165     return d_data->alpha;
    00166 }
    00167
    00176 void QwtPlotRasterItem::setCachePolicy(
    00177     QwtPlotRasterItem::CachePolicy policy)
    00178 {
    00179     if ( d_data->cache.policy != policy )
    00180     {
    00181         d_data->cache.policy = policy;
    00182
    00183         invalidateCache();
    00184         itemChanged();
    00185     }
    00186 }
    00187
    00192 QwtPlotRasterItem::CachePolicy QwtPlotRasterItem::cachePolicy() const
    00193 {
    00194     return d_data->cache.policy;
    00195 }
    00196
    00201 void QwtPlotRasterItem::invalidateCache()
    00202 {
    00203     d_data->cache.image = QImage();
    00204     d_data->cache.rect = QwtDoubleRect();
    00205     d_data->cache.size = QSize();
    00206 }
    00207
    00217 QSize QwtPlotRasterItem::rasterHint(const QwtDoubleRect &) const
    00218 {
    00219     return QSize();
    00220 }
    00221
    00229 void QwtPlotRasterItem::draw(QPainter *painter,
    00230     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    00231     const QRect &canvasRect) const
    00232 {
    00233     if ( canvasRect.isEmpty() || d_data->alpha == 0 )
    00234         return;
    00235
    00236     QwtDoubleRect area = invTransform(xMap, yMap, canvasRect);
    00237     if ( boundingRect().isValid() )
    00238         area &= boundingRect();
    00239
    00240     const QRect paintRect = transform(xMap, yMap, area);
    00241     if ( !paintRect.isValid() )
    00242         return;
    00243
    00244     QImage image;
    00245
    00246     bool doCache = true;
    00247     if ( painter->device()->devType() == QInternal::Printer
    00248             || painter->device()->devType() == QInternal::Picture )
    00249     {
    00250         doCache = false;
    00251     }
    00252
    00253     if ( !doCache || d_data->cache.policy == NoCache )
    00254     {
    00255         image = renderImage(xMap, yMap, area);
    00256         if ( d_data->alpha >= 0 && d_data->alpha < 255 )
    00257             image = toRgba(image, d_data->alpha);
    00258
    00259     }
    00260     else if ( d_data->cache.policy == PaintCache )
    00261     {
    00262         if ( d_data->cache.image.isNull() || d_data->cache.rect != area
    00263             || d_data->cache.size != paintRect.size() )
    00264         {
    00265             d_data->cache.image = renderImage(xMap, yMap, area);
    00266             d_data->cache.rect = area;
    00267             d_data->cache.size = paintRect.size();
    00268         }
    00269
    00270         image = d_data->cache.image;
    00271         if ( d_data->alpha >= 0 && d_data->alpha < 255 )
    00272             image = toRgba(image, d_data->alpha);
    00273     }
    00274     else if ( d_data->cache.policy == ScreenCache )
    00275     {
    00276         const QSize screenSize =
    00277             QApplication::desktop()->screenGeometry().size();
    00278
    00279         if ( paintRect.width() > screenSize.width() ||
    00280             paintRect.height() > screenSize.height() )
    00281         {
    00282             image = renderImage(xMap, yMap, area);
    00283         }
    00284         else
    00285         {
    00286             if ( d_data->cache.image.isNull() || d_data->cache.rect != area )
    00287             {
    00288                 QwtScaleMap cacheXMap = xMap;
    00289                 cacheXMap.setPaintInterval( 0, screenSize.width());
    00290
    00291                 QwtScaleMap cacheYMap = yMap;
    00292                 cacheYMap.setPaintInterval(screenSize.height(), 0);
    00293
    00294                 d_data->cache.image = renderImage(
    00295                     cacheXMap, cacheYMap, area);
    00296                 d_data->cache.rect = area;
    00297                 d_data->cache.size = paintRect.size();
    00298             }
    00299
    00300             image = d_data->cache.image;
    00301         }
    00302         image = toRgba(image, d_data->alpha);
    00303     }
    00304
    00305     painter->drawImage(paintRect, image);
    00306 }