You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
0 B
286 lines
0 B
15 years ago
|
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
|
||
|
* Qwt Widget Library
|
||
|
* Copyright (C) 1997 Josef Wilgen
|
||
|
* Copyright (C) 2002 Uwe Rathmann
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the Qwt License, Version 1.0
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include <qapplication.h>
|
||
|
#include <qdesktopwidget.h>
|
||
|
#include <qpaintdevice.h>
|
||
|
#include <qpainter.h>
|
||
|
#include "qwt_legend.h"
|
||
|
#include "qwt_legend_item.h"
|
||
|
#include "qwt_scale_map.h"
|
||
|
#include "qwt_plot_rasteritem.h"
|
||
|
|
||
|
class QwtPlotRasterItem::PrivateData
|
||
|
{
|
||
|
public:
|
||
|
PrivateData():
|
||
14 years ago
|
alpha(-1) {
|
||
15 years ago
|
cache.policy = QwtPlotRasterItem::NoCache;
|
||
|
}
|
||
|
|
||
|
int alpha;
|
||
|
|
||
14 years ago
|
struct ImageCache {
|
||
15 years ago
|
QwtPlotRasterItem::CachePolicy policy;
|
||
|
QwtDoubleRect rect;
|
||
|
QSize size;
|
||
|
QImage image;
|
||
|
} cache;
|
||
|
};
|
||
|
|
||
|
static QImage toRgba(const QImage& image, int alpha)
|
||
|
{
|
||
14 years ago
|
if ( alpha < 0 || alpha >= 255 )
|
||
15 years ago
|
return image;
|
||
|
|
||
|
#if QT_VERSION < 0x040000
|
||
|
QImage alphaImage(image.size(), 32);
|
||
|
alphaImage.setAlphaBuffer(true);
|
||
|
#else
|
||
|
QImage alphaImage(image.size(), QImage::Format_ARGB32);
|
||
|
#endif
|
||
|
|
||
|
const QRgb mask1 = qRgba(0, 0, 0, alpha);
|
||
|
const QRgb mask2 = qRgba(255, 255, 255, 0);
|
||
|
const QRgb mask3 = qRgba(0, 0, 0, 255);
|
||
|
|
||
|
const int w = image.size().width();
|
||
|
const int h = image.size().height();
|
||
|
|
||
14 years ago
|
if ( image.depth() == 8 ) {
|
||
|
for ( int y = 0; y < h; y++ ) {
|
||
15 years ago
|
QRgb* alphaLine = (QRgb*)alphaImage.scanLine(y);
|
||
|
const unsigned char *line = image.scanLine(y);
|
||
|
|
||
|
for ( int x = 0; x < w; x++ )
|
||
|
*alphaLine++ = (image.color(*line++) & mask2) | mask1;
|
||
|
}
|
||
14 years ago
|
} else if ( image.depth() == 32 ) {
|
||
|
for ( int y = 0; y < h; y++ ) {
|
||
15 years ago
|
QRgb* alphaLine = (QRgb*)alphaImage.scanLine(y);
|
||
|
const QRgb* line = (const QRgb*) image.scanLine(y);
|
||
|
|
||
14 years ago
|
for ( int x = 0; x < w; x++ ) {
|
||
15 years ago
|
const QRgb rgb = *line++;
|
||
|
if ( rgb & mask3 ) // alpha != 0
|
||
|
*alphaLine++ = (rgb & mask2) | mask1;
|
||
|
else
|
||
|
*alphaLine++ = rgb;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return alphaImage;
|
||
|
}
|
||
|
|
||
|
//! Constructor
|
||
|
QwtPlotRasterItem::QwtPlotRasterItem(const QString& title):
|
||
|
QwtPlotItem(QwtText(title))
|
||
|
{
|
||
|
init();
|
||
|
}
|
||
|
|
||
|
//! Constructor
|
||
|
QwtPlotRasterItem::QwtPlotRasterItem(const QwtText& title):
|
||
|
QwtPlotItem(title)
|
||
|
{
|
||
|
init();
|
||
|
}
|
||
|
|
||
|
//! Destructor
|
||
|
QwtPlotRasterItem::~QwtPlotRasterItem()
|
||
|
{
|
||
|
delete d_data;
|
||
|
}
|
||
|
|
||
|
void QwtPlotRasterItem::init()
|
||
|
{
|
||
|
d_data = new PrivateData();
|
||
|
|
||
|
setItemAttribute(QwtPlotItem::AutoScale, true);
|
||
|
setItemAttribute(QwtPlotItem::Legend, false);
|
||
|
|
||
|
setZ(8.0);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Set an alpha value for the raster data
|
||
|
|
||
|
Often a plot has several types of raster data organized in layers.
|
||
|
( f.e a geographical map, with weather statistics ).
|
||
|
Using setAlpha() raster items can be stacked easily.
|
||
|
|
||
|
The alpha value is a value [0, 255] to
|
||
14 years ago
|
control the transparency of the image. 0 represents a fully
|
||
15 years ago
|
transparent color, while 255 represents a fully opaque color.
|
||
14 years ago
|
|
||
15 years ago
|
\param alpha Alpha value
|
||
|
|
||
|
- alpha >= 0\n
|
||
14 years ago
|
All alpha values of the pixels returned by renderImage() will be set to
|
||
|
alpha, beside those with an alpha value of 0 (invalid pixels).
|
||
15 years ago
|
- alpha < 0
|
||
|
The alpha values returned by renderImage() are not changed.
|
||
|
|
||
|
The default alpha value is -1.
|
||
|
|
||
|
\sa alpha()
|
||
|
*/
|
||
|
void QwtPlotRasterItem::setAlpha(int alpha)
|
||
|
{
|
||
|
if ( alpha < 0 )
|
||
|
alpha = -1;
|
||
|
|
||
|
if ( alpha > 255 )
|
||
|
alpha = 255;
|
||
|
|
||
14 years ago
|
if ( alpha != d_data->alpha ) {
|
||
15 years ago
|
d_data->alpha = alpha;
|
||
|
|
||
|
itemChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\return Alpha value of the raster item
|
||
|
\sa setAlpha()
|
||
|
*/
|
||
|
int QwtPlotRasterItem::alpha() const
|
||
|
{
|
||
|
return d_data->alpha;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Change the cache policy
|
||
|
|
||
|
The default policy is NoCache
|
||
|
|
||
|
\param policy Cache policy
|
||
|
\sa CachePolicy, cachePolicy()
|
||
|
*/
|
||
|
void QwtPlotRasterItem::setCachePolicy(
|
||
|
QwtPlotRasterItem::CachePolicy policy)
|
||
|
{
|
||
14 years ago
|
if ( d_data->cache.policy != policy ) {
|
||
15 years ago
|
d_data->cache.policy = policy;
|
||
|
|
||
|
invalidateCache();
|
||
|
itemChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\return Cache policy
|
||
|
\sa CachePolicy, setCachePolicy()
|
||
|
*/
|
||
|
QwtPlotRasterItem::CachePolicy QwtPlotRasterItem::cachePolicy() const
|
||
|
{
|
||
|
return d_data->cache.policy;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Invalidate the paint cache
|
||
|
\sa setCachePolicy
|
||
|
*/
|
||
|
void QwtPlotRasterItem::invalidateCache()
|
||
|
{
|
||
|
d_data->cache.image = QImage();
|
||
|
d_data->cache.rect = QwtDoubleRect();
|
||
|
d_data->cache.size = QSize();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Returns the recommended raster for a given rect.
|
||
|
|
||
|
F.e the raster hint can be used to limit the resolution of
|
||
|
the image that is rendered.
|
||
|
|
||
|
The default implementation returns an invalid size (QSize()),
|
||
|
what means: no hint.
|
||
|
*/
|
||
|
QSize QwtPlotRasterItem::rasterHint(const QwtDoubleRect &) const
|
||
|
{
|
||
|
return QSize();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Draw the raster data
|
||
|
\param painter Painter
|
||
|
\param xMap X-Scale Map
|
||
|
\param yMap Y-Scale Map
|
||
|
\param canvasRect Contents rect of the plot canvas
|
||
|
*/
|
||
|
void QwtPlotRasterItem::draw(QPainter *painter,
|
||
14 years ago
|
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||
|
const QRect &canvasRect) const
|
||
15 years ago
|
{
|
||
|
if ( canvasRect.isEmpty() || d_data->alpha == 0 )
|
||
|
return;
|
||
|
|
||
|
QwtDoubleRect area = invTransform(xMap, yMap, canvasRect);
|
||
|
if ( boundingRect().isValid() )
|
||
|
area &= boundingRect();
|
||
|
|
||
|
const QRect paintRect = transform(xMap, yMap, area);
|
||
|
if ( !paintRect.isValid() )
|
||
|
return;
|
||
|
|
||
|
QImage image;
|
||
|
|
||
|
bool doCache = true;
|
||
14 years ago
|
if ( painter->device()->devType() == QInternal::Printer
|
||
|
|| painter->device()->devType() == QInternal::Picture ) {
|
||
15 years ago
|
doCache = false;
|
||
|
}
|
||
|
|
||
14 years ago
|
if ( !doCache || d_data->cache.policy == NoCache ) {
|
||
15 years ago
|
image = renderImage(xMap, yMap, area);
|
||
|
if ( d_data->alpha >= 0 && d_data->alpha < 255 )
|
||
|
image = toRgba(image, d_data->alpha);
|
||
|
|
||
14 years ago
|
} else if ( d_data->cache.policy == PaintCache ) {
|
||
15 years ago
|
if ( d_data->cache.image.isNull() || d_data->cache.rect != area
|
||
14 years ago
|
|| d_data->cache.size != paintRect.size() ) {
|
||
15 years ago
|
d_data->cache.image = renderImage(xMap, yMap, area);
|
||
|
d_data->cache.rect = area;
|
||
|
d_data->cache.size = paintRect.size();
|
||
|
}
|
||
|
|
||
|
image = d_data->cache.image;
|
||
|
if ( d_data->alpha >= 0 && d_data->alpha < 255 )
|
||
|
image = toRgba(image, d_data->alpha);
|
||
14 years ago
|
} else if ( d_data->cache.policy == ScreenCache ) {
|
||
15 years ago
|
const QSize screenSize =
|
||
|
QApplication::desktop()->screenGeometry().size();
|
||
|
|
||
|
if ( paintRect.width() > screenSize.width() ||
|
||
14 years ago
|
paintRect.height() > screenSize.height() ) {
|
||
15 years ago
|
image = renderImage(xMap, yMap, area);
|
||
14 years ago
|
} else {
|
||
|
if ( d_data->cache.image.isNull() || d_data->cache.rect != area ) {
|
||
15 years ago
|
QwtScaleMap cacheXMap = xMap;
|
||
|
cacheXMap.setPaintInterval( 0, screenSize.width());
|
||
|
|
||
|
QwtScaleMap cacheYMap = yMap;
|
||
|
cacheYMap.setPaintInterval(screenSize.height(), 0);
|
||
|
|
||
|
d_data->cache.image = renderImage(
|
||
14 years ago
|
cacheXMap, cacheYMap, area);
|
||
15 years ago
|
d_data->cache.rect = area;
|
||
|
d_data->cache.size = paintRect.size();
|
||
|
}
|
||
|
|
||
|
image = d_data->cache.image;
|
||
|
}
|
||
|
image = toRgba(image, d_data->alpha);
|
||
|
}
|
||
|
|
||
|
painter->drawImage(paintRect, image);
|
||
|
}
|