00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_array.h"
00011 #include "qwt_math.h"
00012 #include "qwt_double_interval.h"
00013 #include "qwt_color_map.h"
00014
00015 #if QT_VERSION < 0x040000
00016 #include <qvaluelist.h>
00017 typedef QValueVector<QRgb> QwtColorTable;
00018 #else
00019 typedef QVector<QRgb> QwtColorTable;
00020 #endif
00021
00022 class QwtLinearColorMap::ColorStops
00023 {
00024 public:
00025 ColorStops()
00026 {
00027 #if QT_VERSION >= 0x040000
00028 _stops.reserve(256);
00029 #endif
00030 }
00031
00032 void insert(double pos, const QColor &color);
00033 QRgb rgb(QwtLinearColorMap::Mode, double pos) const;
00034
00035 QwtArray<double> stops() const;
00036
00037 private:
00038
00039 class ColorStop
00040 {
00041 public:
00042 ColorStop():
00043 pos(0.0),
00044 rgb(0)
00045 {
00046 };
00047
00048 ColorStop(double p, const QColor &c):
00049 pos(p),
00050 rgb(c.rgb())
00051 {
00052 r = qRed(rgb);
00053 g = qGreen(rgb);
00054 b = qBlue(rgb);
00055 }
00056
00057 double pos;
00058 QRgb rgb;
00059 int r, g, b;
00060 };
00061
00062 inline int findUpper(double pos) const;
00063 QwtArray<ColorStop> _stops;
00064 };
00065
00066 void QwtLinearColorMap::ColorStops::insert(double pos, const QColor &color)
00067 {
00068
00069
00070
00071 if ( pos < 0.0 || pos > 1.0 )
00072 return;
00073
00074 int index;
00075 if ( _stops.size() == 0 )
00076 {
00077 index = 0;
00078 #if QT_VERSION < 0x040000
00079 _stops.resize(1, QGArray::SpeedOptim);
00080 #else
00081 _stops.resize(1);
00082 #endif
00083 }
00084 else
00085 {
00086 index = findUpper(pos);
00087 if ( index == (int)_stops.size() ||
00088 qwtAbs(_stops[index].pos - pos) >= 0.001 )
00089 {
00090 #if QT_VERSION < 0x040000
00091 _stops.resize(_stops.size() + 1, QGArray::SpeedOptim);
00092 #else
00093 _stops.resize(_stops.size() + 1);
00094 #endif
00095 for ( int i = _stops.size() - 1; i > index; i-- )
00096 _stops[i] = _stops[i-1];
00097 }
00098 }
00099
00100 _stops[index] = ColorStop(pos, color);
00101 }
00102
00103 inline QwtArray<double> QwtLinearColorMap::ColorStops::stops() const
00104 {
00105 QwtArray<double> positions(_stops.size());
00106 for ( int i = 0; i < (int)_stops.size(); i++ )
00107 positions[i] = _stops[i].pos;
00108 return positions;
00109 }
00110
00111 inline int QwtLinearColorMap::ColorStops::findUpper(double pos) const
00112 {
00113 int index = 0;
00114 int n = _stops.size();
00115
00116 const ColorStop *stops = _stops.data();
00117
00118 while (n > 0)
00119 {
00120 const int half = n >> 1;
00121 const int middle = index + half;
00122
00123 if ( stops[middle].pos <= pos )
00124 {
00125 index = middle + 1;
00126 n -= half + 1;
00127 }
00128 else
00129 n = half;
00130 }
00131
00132 return index;
00133 }
00134
00135 inline QRgb QwtLinearColorMap::ColorStops::rgb(
00136 QwtLinearColorMap::Mode mode, double pos) const
00137 {
00138 if ( pos <= 0.0 )
00139 return _stops[0].rgb;
00140 if ( pos >= 1.0 )
00141 return _stops[(int)(_stops.size() - 1)].rgb;
00142
00143 const int index = findUpper(pos);
00144 if ( mode == FixedColors )
00145 {
00146 return _stops[index-1].rgb;
00147 }
00148 else
00149 {
00150 const ColorStop &s1 = _stops[index-1];
00151 const ColorStop &s2 = _stops[index];
00152
00153 const double ratio = (pos - s1.pos) / (s2.pos - s1.pos);
00154
00155 const int r = s1.r + qRound(ratio * (s2.r - s1.r));
00156 const int g = s1.g + qRound(ratio * (s2.g - s1.g));
00157 const int b = s1.b + qRound(ratio * (s2.b - s1.b));
00158
00159 return qRgb(r, g, b);
00160 }
00161 }
00162
00164 QwtColorMap::QwtColorMap(Format format):
00165 d_format(format)
00166 {
00167 }
00168
00170 QwtColorMap::~QwtColorMap()
00171 {
00172 }
00173
00183 QwtColorTable QwtColorMap::colorTable(
00184 const QwtDoubleInterval &interval) const
00185 {
00186 QwtColorTable table(256);
00187
00188 if ( interval.isValid() )
00189 {
00190 const double step = interval.width() / (table.size() - 1);
00191 for ( int i = 0; i < (int) table.size(); i++ )
00192 table[i] = rgb(interval, interval.minValue() + step * i);
00193 }
00194
00195 return table;
00196 }
00197
00198 class QwtLinearColorMap::PrivateData
00199 {
00200 public:
00201 ColorStops colorStops;
00202 QwtLinearColorMap::Mode mode;
00203 };
00204
00211 QwtLinearColorMap::QwtLinearColorMap(QwtColorMap::Format format):
00212 QwtColorMap(format)
00213 {
00214 d_data = new PrivateData;
00215 d_data->mode = ScaledColors;
00216
00217 setColorInterval( Qt::blue, Qt::yellow);
00218 }
00219
00221 QwtLinearColorMap::QwtLinearColorMap(const QwtLinearColorMap &other):
00222 QwtColorMap(other)
00223 {
00224 d_data = new PrivateData;
00225 *this = other;
00226 }
00227
00235 QwtLinearColorMap::QwtLinearColorMap(const QColor &color1,
00236 const QColor &color2, QwtColorMap::Format format):
00237 QwtColorMap(format)
00238 {
00239 d_data = new PrivateData;
00240 d_data->mode = ScaledColors;
00241 setColorInterval(color1, color2);
00242 }
00243
00245 QwtLinearColorMap::~QwtLinearColorMap()
00246 {
00247 delete d_data;
00248 }
00249
00251 QwtLinearColorMap &QwtLinearColorMap::operator=(
00252 const QwtLinearColorMap &other)
00253 {
00254 QwtColorMap::operator=(other);
00255 *d_data = *other.d_data;
00256 return *this;
00257 }
00258
00260 QwtColorMap *QwtLinearColorMap::copy() const
00261 {
00262 QwtLinearColorMap* map = new QwtLinearColorMap();
00263 *map = *this;
00264
00265 return map;
00266 }
00267
00277 void QwtLinearColorMap::setMode(Mode mode)
00278 {
00279 d_data->mode = mode;
00280 }
00281
00286 QwtLinearColorMap::Mode QwtLinearColorMap::mode() const
00287 {
00288 return d_data->mode;
00289 }
00290
00301 void QwtLinearColorMap::setColorInterval(
00302 const QColor &color1, const QColor &color2)
00303 {
00304 d_data->colorStops = ColorStops();
00305 d_data->colorStops.insert(0.0, color1);
00306 d_data->colorStops.insert(1.0, color2);
00307 }
00308
00319 void QwtLinearColorMap::addColorStop(double value, const QColor& color)
00320 {
00321 if ( value >= 0.0 && value <= 1.0 )
00322 d_data->colorStops.insert(value, color);
00323 }
00324
00328 QwtArray<double> QwtLinearColorMap::colorStops() const
00329 {
00330 return d_data->colorStops.stops();
00331 }
00332
00337 QColor QwtLinearColorMap::color1() const
00338 {
00339 return QColor(d_data->colorStops.rgb(d_data->mode, 0.0));
00340 }
00341
00346 QColor QwtLinearColorMap::color2() const
00347 {
00348 return QColor(d_data->colorStops.rgb(d_data->mode, 1.0));
00349 }
00350
00357 QRgb QwtLinearColorMap::rgb(const QwtDoubleInterval &interval,
00358 double value) const
00359 {
00360 const double ratio = (value - interval.minValue()) / interval.width();
00361 return d_data->colorStops.rgb(d_data->mode, ratio);
00362 }
00363
00370 unsigned char QwtLinearColorMap::colorIndex(
00371 const QwtDoubleInterval &interval, double value) const
00372 {
00373 if ( !interval.isValid() || value <= interval.minValue() )
00374 return 0;
00375
00376 if ( value >= interval.maxValue() )
00377 return (unsigned char)255;
00378
00379 const double ratio = (value - interval.minValue()) / interval.width();
00380
00381 unsigned char index;
00382 if ( d_data->mode == FixedColors )
00383 index = (unsigned char)(ratio * 255);
00384 else
00385 index = (unsigned char)qRound(ratio * 255);
00386
00387 return index;
00388 }
00389
00390 class QwtAlphaColorMap::PrivateData
00391 {
00392 public:
00393 QColor color;
00394 QRgb rgb;
00395 };
00396
00397
00402 QwtAlphaColorMap::QwtAlphaColorMap(const QColor &color):
00403 QwtColorMap(QwtColorMap::RGB)
00404 {
00405 d_data = new PrivateData;
00406 d_data->color = color;
00407 d_data->rgb = color.rgb() & qRgba(255, 255, 255, 0);
00408 }
00409
00414 QwtAlphaColorMap::QwtAlphaColorMap(const QwtAlphaColorMap &other):
00415 QwtColorMap(other)
00416 {
00417 d_data = new PrivateData;
00418 *this = other;
00419 }
00420
00422 QwtAlphaColorMap::~QwtAlphaColorMap()
00423 {
00424 delete d_data;
00425 }
00426
00432 QwtAlphaColorMap &QwtAlphaColorMap::operator=(
00433 const QwtAlphaColorMap &other)
00434 {
00435 QwtColorMap::operator=(other);
00436 *d_data = *other.d_data;
00437 return *this;
00438 }
00439
00441 QwtColorMap *QwtAlphaColorMap::copy() const
00442 {
00443 QwtAlphaColorMap* map = new QwtAlphaColorMap();
00444 *map = *this;
00445
00446 return map;
00447 }
00448
00455 void QwtAlphaColorMap::setColor(const QColor &color)
00456 {
00457 d_data->color = color;
00458 d_data->rgb = color.rgb();
00459 }
00460
00465 QColor QwtAlphaColorMap::color() const
00466 {
00467 return d_data->color;
00468 }
00469
00479 QRgb QwtAlphaColorMap::rgb(const QwtDoubleInterval &interval,
00480 double value) const
00481 {
00482 if ( interval.isValid() )
00483 {
00484 const double ratio = (value - interval.minValue()) / interval.width();
00485 int alpha = qRound(255 * ratio);
00486 if ( alpha < 0 )
00487 alpha = 0;
00488 if ( alpha > 255 )
00489 alpha = 255;
00490
00491 return d_data->rgb | (alpha << 24);
00492 }
00493 return d_data->rgb;
00494 }
00495
00503 unsigned char QwtAlphaColorMap::colorIndex(
00504 const QwtDoubleInterval &, double) const
00505 {
00506 return 0;
00507 }