~ubuntu-branches/ubuntu/oneiric/qwt/oneiric-proposed

« back to all changes in this revision

Viewing changes to qwt-5.1.1/src/qwt_plot_rasteritem.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2008-05-26 10:26:31 UTC
  • mfrom: (1.1.3 upstream) (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526102631-bp95mfccnrb957nx
Tags: 5.1.1-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 
2
 * Qwt Widget Library
 
3
 * Copyright (C) 1997   Josef Wilgen
 
4
 * Copyright (C) 2002   Uwe Rathmann
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the Qwt License, Version 1.0
 
8
 *****************************************************************************/
 
9
 
 
10
#include <qapplication.h>
 
11
#include <qdesktopwidget.h>
 
12
#include <qpaintdevice.h>
 
13
#include <qpainter.h>
 
14
#include "qwt_legend.h"
 
15
#include "qwt_legend_item.h"
 
16
#include "qwt_scale_map.h"
 
17
#include "qwt_plot_rasteritem.h"
 
18
 
 
19
class QwtPlotRasterItem::PrivateData
 
20
{
 
21
public:
 
22
    PrivateData():
 
23
        alpha(-1)
 
24
    {
 
25
        cache.policy = QwtPlotRasterItem::NoCache;
 
26
    }
 
27
 
 
28
    int alpha;
 
29
 
 
30
    struct ImageCache
 
31
    {
 
32
        QwtPlotRasterItem::CachePolicy policy;
 
33
        QwtDoubleRect rect;
 
34
        QSize size;
 
35
        QImage image;
 
36
    } cache;
 
37
};
 
38
 
 
39
static QImage toRgba(const QImage& image, int alpha)
 
40
{
 
41
    if ( alpha < 0 || alpha >= 255 )  
 
42
        return image;
 
43
 
 
44
#if QT_VERSION < 0x040000
 
45
    QImage alphaImage(image.size(), 32);
 
46
    alphaImage.setAlphaBuffer(true);
 
47
#else
 
48
    QImage alphaImage(image.size(), QImage::Format_ARGB32);
 
49
#endif
 
50
 
 
51
    const QRgb mask1 = qRgba(0, 0, 0, alpha);
 
52
    const QRgb mask2 = qRgba(255, 255, 255, 0);
 
53
    const QRgb mask3 = qRgba(0, 0, 0, 255);
 
54
 
 
55
    const int w = image.size().width();
 
56
    const int h = image.size().height();
 
57
 
 
58
    if ( image.depth() == 8 )
 
59
    {
 
60
        for ( int y = 0; y < h; y++ )
 
61
        {
 
62
            QRgb* alphaLine = (QRgb*)alphaImage.scanLine(y);
 
63
            const unsigned char *line = image.scanLine(y);
 
64
 
 
65
            for ( int x = 0; x < w; x++ )
 
66
                *alphaLine++ = (image.color(*line++) & mask2) | mask1;
 
67
        }
 
68
    }
 
69
    else if ( image.depth() == 32 )
 
70
    {
 
71
        for ( int y = 0; y < h; y++ )
 
72
        {
 
73
            QRgb* alphaLine = (QRgb*)alphaImage.scanLine(y);
 
74
            const QRgb* line = (const QRgb*) image.scanLine(y);
 
75
 
 
76
            for ( int x = 0; x < w; x++ )
 
77
            {
 
78
                const QRgb rgb = *line++;
 
79
                if ( rgb & mask3 ) // alpha != 0
 
80
                    *alphaLine++ = (rgb & mask2) | mask1;
 
81
                else
 
82
                    *alphaLine++ = rgb;
 
83
            }
 
84
        }
 
85
    }
 
86
 
 
87
    return alphaImage;
 
88
}
 
89
 
 
90
//! Constructor
 
91
QwtPlotRasterItem::QwtPlotRasterItem(const QString& title):
 
92
    QwtPlotItem(QwtText(title))
 
93
{
 
94
    init();
 
95
}
 
96
 
 
97
//! Constructor
 
98
QwtPlotRasterItem::QwtPlotRasterItem(const QwtText& title):
 
99
    QwtPlotItem(title)
 
100
{
 
101
    init();
 
102
}
 
103
 
 
104
//! Destructor
 
105
QwtPlotRasterItem::~QwtPlotRasterItem()
 
106
{
 
107
    delete d_data;
 
108
}
 
109
 
 
110
void QwtPlotRasterItem::init()
 
111
{
 
112
    d_data = new PrivateData();
 
113
 
 
114
    setItemAttribute(QwtPlotItem::AutoScale, true);
 
115
    setItemAttribute(QwtPlotItem::Legend, false);
 
116
 
 
117
    setZ(8.0);
 
118
}
 
119
 
 
120
/*!
 
121
   \brief Set an alpha value for the raster data
 
122
 
 
123
   Often a plot has several types of raster data organized in layers.
 
124
   ( f.e a geographical map, with weather statistics ).
 
125
   Using setAlpha() raster items can be stacked easily.
 
126
 
 
127
   The alpha value is a value [0, 255] to
 
128
   control the transparency of the image. 0 represents a fully 
 
129
   transparent color, while 255 represents a fully opaque color.
 
130
   
 
131
   \param alpha Alpha value
 
132
 
 
133
   - alpha >= 0\n
 
134
     All alpha values of the pixels returned by renderImage() will be set to 
 
135
     alpha, beside those with an alpha value of 0 (invalid pixels). 
 
136
   - alpha < 0
 
137
     The alpha values returned by renderImage() are not changed.
 
138
 
 
139
   The default alpha value is -1.
 
140
 
 
141
   \sa alpha()
 
142
*/
 
143
void QwtPlotRasterItem::setAlpha(int alpha)
 
144
{
 
145
    if ( alpha < 0 )
 
146
        alpha = -1;
 
147
 
 
148
    if ( alpha > 255 )
 
149
        alpha = 255;
 
150
 
 
151
    if ( alpha != d_data->alpha )
 
152
    {
 
153
        d_data->alpha = alpha;
 
154
 
 
155
        itemChanged();
 
156
    }
 
157
}
 
158
 
 
159
/*!
 
160
  \return Alpha value of the raster item
 
161
  \sa setAlpha()
 
162
*/
 
163
int QwtPlotRasterItem::alpha() const
 
164
{
 
165
    return d_data->alpha;
 
166
}
 
167
 
 
168
/*!
 
169
  Change the cache policy
 
170
 
 
171
  The default policy is NoCache
 
172
 
 
173
  \param policy Cache policy
 
174
  \sa CachePolicy, cachePolicy()
 
175
*/
 
176
void QwtPlotRasterItem::setCachePolicy(
 
177
    QwtPlotRasterItem::CachePolicy policy)
 
178
{
 
179
    if ( d_data->cache.policy != policy )
 
180
    {
 
181
        d_data->cache.policy = policy;
 
182
 
 
183
        invalidateCache();
 
184
        itemChanged();
 
185
    }
 
186
}
 
187
 
 
188
/*!
 
189
  \return Cache policy
 
190
  \sa CachePolicy, setCachePolicy()
 
191
*/
 
192
QwtPlotRasterItem::CachePolicy QwtPlotRasterItem::cachePolicy() const
 
193
{
 
194
    return d_data->cache.policy;
 
195
}
 
196
 
 
197
/*!
 
198
   Invalidate the paint cache
 
199
   \sa setCachePolicy
 
200
*/
 
201
void QwtPlotRasterItem::invalidateCache()
 
202
{
 
203
    d_data->cache.image = QImage();
 
204
    d_data->cache.rect = QwtDoubleRect();
 
205
    d_data->cache.size = QSize();
 
206
}
 
207
 
 
208
/*!
 
209
   \brief Returns the recommended raster for a given rect.
 
210
 
 
211
   F.e the raster hint can be used to limit the resolution of
 
212
   the image that is rendered.
 
213
 
 
214
   The default implementation returns an invalid size (QSize()),
 
215
   what means: no hint.
 
216
*/
 
217
QSize QwtPlotRasterItem::rasterHint(const QwtDoubleRect &) const
 
218
{
 
219
    return QSize();
 
220
}
 
221
 
 
222
/*!
 
223
  \brief Draw the raster data
 
224
  \param painter Painter
 
225
  \param xMap X-Scale Map
 
226
  \param yMap Y-Scale Map
 
227
  \param canvasRect Contents rect of the plot canvas
 
228
*/
 
229
void QwtPlotRasterItem::draw(QPainter *painter,
 
230
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
 
231
    const QRect &canvasRect) const
 
232
{
 
233
    if ( canvasRect.isEmpty() || d_data->alpha == 0 )
 
234
        return;
 
235
 
 
236
    QwtDoubleRect area = invTransform(xMap, yMap, canvasRect);
 
237
    if ( boundingRect().isValid() )
 
238
        area &= boundingRect();
 
239
 
 
240
    const QRect paintRect = transform(xMap, yMap, area);
 
241
    if ( !paintRect.isValid() )
 
242
        return;
 
243
 
 
244
    QImage image;
 
245
 
 
246
    bool doCache = true;
 
247
    if ( painter->device()->devType() == QInternal::Printer 
 
248
            || painter->device()->devType() == QInternal::Picture )
 
249
    {
 
250
        doCache = false;
 
251
    }
 
252
 
 
253
    if ( !doCache || d_data->cache.policy == NoCache )
 
254
    {
 
255
        image = renderImage(xMap, yMap, area);
 
256
        if ( d_data->alpha >= 0 && d_data->alpha < 255 )
 
257
            image = toRgba(image, d_data->alpha);
 
258
 
 
259
    }
 
260
    else if ( d_data->cache.policy == PaintCache )
 
261
    {
 
262
        if ( d_data->cache.image.isNull() || d_data->cache.rect != area
 
263
            || d_data->cache.size != paintRect.size() )
 
264
        {
 
265
            d_data->cache.image = renderImage(xMap, yMap, area);
 
266
            d_data->cache.rect = area;
 
267
            d_data->cache.size = paintRect.size();
 
268
        }
 
269
 
 
270
        image = d_data->cache.image;
 
271
        if ( d_data->alpha >= 0 && d_data->alpha < 255 )
 
272
            image = toRgba(image, d_data->alpha);
 
273
    }
 
274
    else if ( d_data->cache.policy == ScreenCache )
 
275
    {
 
276
        const QSize screenSize =
 
277
            QApplication::desktop()->screenGeometry().size();
 
278
 
 
279
        if ( paintRect.width() > screenSize.width() ||
 
280
            paintRect.height() > screenSize.height() )
 
281
        {
 
282
            image = renderImage(xMap, yMap, area);
 
283
        }
 
284
        else
 
285
        {
 
286
            if ( d_data->cache.image.isNull() || d_data->cache.rect != area )
 
287
            {
 
288
                QwtScaleMap cacheXMap = xMap;
 
289
                cacheXMap.setPaintInterval( 0, screenSize.width());
 
290
 
 
291
                QwtScaleMap cacheYMap = yMap;
 
292
                cacheYMap.setPaintInterval(screenSize.height(), 0);
 
293
 
 
294
                d_data->cache.image = renderImage(
 
295
                    cacheXMap, cacheYMap, area);
 
296
                d_data->cache.rect = area;
 
297
                d_data->cache.size = paintRect.size();
 
298
            }
 
299
 
 
300
            image = d_data->cache.image;
 
301
        }
 
302
        image = toRgba(image, d_data->alpha);
 
303
    }
 
304
 
 
305
    painter->drawImage(paintRect, image);
 
306
}