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

« back to all changes in this revision

Viewing changes to qwt-5.0.1/src/qwt_color_map.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2007-10-05 15:20:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071005152041-qmybqh4fj9jejyo2
Tags: 5.0.2-2
* Handle nostrip build option. (Closes: #437877)
* Build libqwt5-doc package in binary-indep target. (Closes: #443110)

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 "qwt_array.h"
11
 
#include "qwt_math.h"
12
 
#include "qwt_double_interval.h"
13
 
#include "qwt_color_map.h"
14
 
 
15
 
#if QT_VERSION < 0x040000
16
 
#include <qvaluelist.h>
17
 
typedef QValueVector<QRgb> QwtColorTable;
18
 
#else
19
 
typedef QVector<QRgb> QwtColorTable;
20
 
#endif
21
 
 
22
 
class QwtLinearColorMap::ColorStops
23
 
{
24
 
public:
25
 
    ColorStops()
26
 
    {
27
 
#if QT_VERSION >= 0x040000
28
 
        _stops.reserve(256);
29
 
#endif
30
 
    }
31
 
 
32
 
    void insert(double pos, const QColor &color);
33
 
    QRgb rgb(QwtLinearColorMap::Mode, double pos) const;
34
 
 
35
 
    QwtArray<double> stops() const;
36
 
 
37
 
private:
38
 
 
39
 
    class ColorStop
40
 
    {
41
 
    public:
42
 
        ColorStop():
43
 
            pos(0.0),
44
 
            rgb(0)
45
 
        {
46
 
        };
47
 
 
48
 
        ColorStop(double p, const QColor &c):
49
 
            pos(p),
50
 
            rgb(c.rgb())
51
 
        {
52
 
            r = qRed(rgb);
53
 
            g = qGreen(rgb);
54
 
            b = qBlue(rgb);
55
 
        }
56
 
 
57
 
        double pos;
58
 
        QRgb rgb;
59
 
        int r, g, b;
60
 
    };
61
 
 
62
 
    inline int findUpper(double pos) const; 
63
 
    QwtArray<ColorStop> _stops;
64
 
};
65
 
 
66
 
void QwtLinearColorMap::ColorStops::insert(double pos, const QColor &color)
67
 
{
68
 
    // Lookups need to be very fast, insertions are not so important.
69
 
    // Anyway, a balanced tree is what we need here. TODO ...
70
 
 
71
 
    if ( pos < 0.0 || pos > 1.0 )
72
 
        return;
73
 
 
74
 
    int index;
75
 
    if ( _stops.size() == 0 )
76
 
    {
77
 
        index = 0;
78
 
#if QT_VERSION < 0x040000
79
 
        _stops.resize(1, QGArray::SpeedOptim);
80
 
#else
81
 
        _stops.resize(1);
82
 
#endif
83
 
    }
84
 
    else
85
 
    {
86
 
        index = findUpper(pos);
87
 
        if ( index == (int)_stops.size() || 
88
 
            qwtAbs(_stops[index].pos - pos) >= 0.001 )
89
 
        {
90
 
#if QT_VERSION < 0x040000
91
 
            _stops.resize(_stops.size() + 1, QGArray::SpeedOptim);
92
 
#else
93
 
            _stops.resize(_stops.size() + 1);
94
 
#endif
95
 
            for ( int i = _stops.size() - 1; i > index; i-- )
96
 
                _stops[i] = _stops[i-1];
97
 
        }
98
 
    }
99
 
 
100
 
    _stops[index] = ColorStop(pos, color);
101
 
}
102
 
 
103
 
inline QwtArray<double> QwtLinearColorMap::ColorStops::stops() const
104
 
{
105
 
    QwtArray<double> positions(_stops.size());
106
 
    for ( int i = 0; i < (int)_stops.size(); i++ )
107
 
        positions[i] = _stops[i].pos;
108
 
    return positions;
109
 
}
110
 
 
111
 
inline int QwtLinearColorMap::ColorStops::findUpper(double pos) const
112
 
{
113
 
    int index = 0;
114
 
    int n = _stops.size();
115
 
 
116
 
    const ColorStop *stops = _stops.data();
117
 
    
118
 
    while (n > 0) 
119
 
    {
120
 
        const int half = n >> 1;
121
 
        const int middle = index + half;
122
 
 
123
 
        if ( stops[middle].pos <= pos ) 
124
 
        {
125
 
            index = middle + 1;
126
 
            n -= half + 1;
127
 
        } 
128
 
        else 
129
 
            n = half;
130
 
    }
131
 
 
132
 
    return index;
133
 
}
134
 
 
135
 
inline QRgb QwtLinearColorMap::ColorStops::rgb(
136
 
    QwtLinearColorMap::Mode mode, double pos) const
137
 
{
138
 
    if ( pos <= 0.0 )
139
 
        return _stops[0].rgb;
140
 
    if ( pos >= 1.0 )
141
 
        return _stops[(int)(_stops.size() - 1)].rgb;
142
 
 
143
 
    const int index = findUpper(pos);
144
 
    if ( mode == FixedColors )
145
 
    {
146
 
        return _stops[index-1].rgb;
147
 
    }
148
 
    else
149
 
    {
150
 
        const ColorStop &s1 = _stops[index-1];
151
 
        const ColorStop &s2 = _stops[index];
152
 
 
153
 
        const double ratio = (pos - s1.pos) / (s2.pos - s1.pos);
154
 
 
155
 
        const int r = s1.r + qRound(ratio * (s2.r - s1.r));
156
 
        const int g = s1.g + qRound(ratio * (s2.g - s1.g));
157
 
        const int b = s1.b + qRound(ratio * (s2.b - s1.b));
158
 
    
159
 
        return qRgb(r, g, b);
160
 
    }
161
 
}
162
 
 
163
 
//! Constructor
164
 
QwtColorMap::QwtColorMap(Format format):
165
 
    d_format(format)
166
 
{
167
 
}
168
 
 
169
 
//! Destructor
170
 
QwtColorMap::~QwtColorMap()
171
 
{
172
 
}
173
 
 
174
 
/*!
175
 
   Build and return a color map of 256 colors
176
 
 
177
 
   The color table is needed for rendering indexed images in combination
178
 
   with using colorIndex(). 
179
 
 
180
 
   \param interval Range for the values
181
 
   \return A color table, that can be used for a QImage
182
 
*/
183
 
QwtColorTable QwtColorMap::colorTable(
184
 
    const QwtDoubleInterval &interval) const
185
 
{
186
 
    QwtColorTable table(256);
187
 
 
188
 
    if ( interval.isValid() )
189
 
    {
190
 
        const double step = interval.width() / (table.size() - 1);
191
 
        for ( int i = 0; i < (int) table.size(); i++ )
192
 
            table[i] = rgb(interval, interval.minValue() + step * i);
193
 
    }
194
 
 
195
 
    return table;
196
 
}
197
 
 
198
 
class QwtLinearColorMap::PrivateData
199
 
{
200
 
public:
201
 
    ColorStops colorStops;
202
 
    QwtLinearColorMap::Mode mode;
203
 
};
204
 
 
205
 
/*! 
206
 
   Build a color map with two stops at 0.0 and 1.0. The color
207
 
   at 0.0 is Qt::blue, at 1.0 it is Qt::yellow.
208
 
 
209
 
   \param format Preferred format of the color map
210
 
*/
211
 
QwtLinearColorMap::QwtLinearColorMap(QwtColorMap::Format format):
212
 
    QwtColorMap(format)
213
 
{
214
 
    d_data = new PrivateData;
215
 
    d_data->mode = ScaledColors;
216
 
 
217
 
    setColorInterval( Qt::blue, Qt::yellow);
218
 
}
219
 
 
220
 
//! Copy constructor
221
 
QwtLinearColorMap::QwtLinearColorMap(const QwtLinearColorMap &other):
222
 
    QwtColorMap(other)
223
 
{
224
 
    d_data = new PrivateData;
225
 
    *this = other;
226
 
}
227
 
 
228
 
/*!
229
 
   Build a color map with two stops at 0.0 and 1.0. 
230
 
 
231
 
   \param color1 Color used for the minimum value of the value interval
232
 
   \param color2 Color used for the maximum value of the value interval
233
 
   \param format Preferred format of the coor map
234
 
*/
235
 
QwtLinearColorMap::QwtLinearColorMap(const QColor &color1, 
236
 
        const QColor &color2, QwtColorMap::Format format):
237
 
    QwtColorMap(format)
238
 
{
239
 
    d_data = new PrivateData;
240
 
    d_data->mode = ScaledColors;
241
 
    setColorInterval(color1, color2); 
242
 
}
243
 
 
244
 
//! Destructor
245
 
QwtLinearColorMap::~QwtLinearColorMap()
246
 
{
247
 
    delete d_data;
248
 
}
249
 
 
250
 
//! Assignment operator
251
 
QwtLinearColorMap &QwtLinearColorMap::operator=(
252
 
    const QwtLinearColorMap &other)
253
 
{
254
 
    QwtColorMap::operator=(other);
255
 
    *d_data = *other.d_data;
256
 
    return *this;
257
 
}
258
 
 
259
 
//! Clone the color map
260
 
QwtColorMap *QwtLinearColorMap::copy() const
261
 
{
262
 
    QwtLinearColorMap* map = new QwtLinearColorMap();
263
 
    *map = *this;
264
 
 
265
 
    return map;
266
 
}
267
 
 
268
 
/*!
269
 
   \brief Set the mode of the color map
270
 
 
271
 
   FixedColors means the color is calculated from the next lower
272
 
   color stop. ScaledColors means the color is calculated
273
 
   by interpolating the colors of the adjacent stops. 
274
 
 
275
 
   \sa mode()
276
 
*/
277
 
void QwtLinearColorMap::setMode(Mode mode)
278
 
{
279
 
    d_data->mode = mode;
280
 
}
281
 
 
282
 
/*!
283
 
   \return Mode of the color map
284
 
   \sa setMode()
285
 
*/
286
 
QwtLinearColorMap::Mode QwtLinearColorMap::mode() const
287
 
{
288
 
    return d_data->mode;
289
 
}
290
 
 
291
 
/*!
292
 
   Set the color range 
293
 
 
294
 
   Add stops at 0.0 and 1.0. 
295
 
 
296
 
   \param color1 Color used for the minimum value of the value interval
297
 
   \param color2 Color used for the maximum value of the value interval
298
 
 
299
 
   \sa color1(), color2()
300
 
*/
301
 
void QwtLinearColorMap::setColorInterval(
302
 
    const QColor &color1, const QColor &color2)
303
 
{
304
 
    d_data->colorStops = ColorStops();
305
 
    d_data->colorStops.insert(0.0, color1);
306
 
    d_data->colorStops.insert(1.0, color2);
307
 
}
308
 
 
309
 
/*!
310
 
   Add a color stop
311
 
 
312
 
   The value has to be in the range [0.0, 1.0]. 
313
 
   F.e. a stop at position 17.0 for a range [10.0,20.0] must be
314
 
   passed as: (17.0 - 10.0) / (20.0 - 10.0)
315
 
 
316
 
   \param value Value between [0.0, 1.0]
317
 
   \param color Color stop
318
 
*/
319
 
void QwtLinearColorMap::addColorStop(double value, const QColor& color)
320
 
{
321
 
    if ( value >= 0.0 && value <= 1.0 )
322
 
        d_data->colorStops.insert(value, color);
323
 
}
324
 
 
325
 
/*!
326
 
   Return all positions of color stops in increasing order
327
 
*/
328
 
QwtArray<double> QwtLinearColorMap::colorStops() const
329
 
{
330
 
    return d_data->colorStops.stops();
331
 
}
332
 
 
333
 
/*! 
334
 
  \return the first color of the color range
335
 
  \sa setColorInterval()
336
 
*/
337
 
QColor QwtLinearColorMap::color1() const
338
 
{
339
 
    return QColor(d_data->colorStops.rgb(d_data->mode, 0.0));
340
 
}
341
 
 
342
 
/*! 
343
 
  \return the second color of the color range
344
 
  \sa setColorInterval()
345
 
*/
346
 
QColor QwtLinearColorMap::color2() const
347
 
{
348
 
    return QColor(d_data->colorStops.rgb(d_data->mode, 1.0));
349
 
}
350
 
 
351
 
/*!
352
 
  Map a value of a given interval into a rgb value
353
 
 
354
 
  \param interval Range for all values
355
 
  \param value Value to map into a rgb value
356
 
*/
357
 
QRgb QwtLinearColorMap::rgb(const QwtDoubleInterval &interval,
358
 
    double value) const
359
 
{
360
 
    const double ratio = (value - interval.minValue()) / interval.width();
361
 
    return d_data->colorStops.rgb(d_data->mode, ratio);
362
 
}
363
 
 
364
 
/*!
365
 
  Map a value of a given interval into a color index, between 0 and 255
366
 
 
367
 
  \param interval Range for all values
368
 
  \param value Value to map into a color index
369
 
*/
370
 
unsigned char QwtLinearColorMap::colorIndex(
371
 
    const QwtDoubleInterval &interval, double value) const
372
 
{
373
 
    if ( !interval.isValid() || value <= interval.minValue() )
374
 
        return 0;
375
 
 
376
 
    if ( value >= interval.maxValue() )
377
 
        return (unsigned char)255;
378
 
 
379
 
    const double ratio = (value - interval.minValue()) / interval.width();
380
 
    
381
 
    unsigned char index;
382
 
    if ( d_data->mode == FixedColors )
383
 
        index = (unsigned char)(ratio * 255); // always floor
384
 
    else
385
 
        index = (unsigned char)qRound(ratio * 255);
386
 
 
387
 
    return index;
388
 
}
389
 
 
390
 
class QwtAlphaColorMap::PrivateData
391
 
{
392
 
public:
393
 
    QColor color;
394
 
    QRgb rgb;
395
 
};
396
 
 
397
 
 
398
 
/*! 
399
 
   Constructor
400
 
   \param color Color of the map
401
 
*/
402
 
QwtAlphaColorMap::QwtAlphaColorMap(const QColor &color):
403
 
    QwtColorMap(QwtColorMap::RGB)
404
 
{
405
 
    d_data = new PrivateData;
406
 
    d_data->color = color;
407
 
    d_data->rgb = color.rgb() & qRgba(255, 255, 255, 0);
408
 
}
409
 
 
410
 
/*! 
411
 
   Copy constructor
412
 
   \param other Other color map
413
 
*/
414
 
QwtAlphaColorMap::QwtAlphaColorMap(const QwtAlphaColorMap &other):
415
 
    QwtColorMap(other)
416
 
{
417
 
    d_data = new PrivateData;
418
 
    *this = other;
419
 
}
420
 
 
421
 
//! Destructor
422
 
QwtAlphaColorMap::~QwtAlphaColorMap()
423
 
{
424
 
    delete d_data;
425
 
}
426
 
 
427
 
/*! 
428
 
   Assignment operator
429
 
   \param other Other color map
430
 
   \return *this
431
 
*/
432
 
QwtAlphaColorMap &QwtAlphaColorMap::operator=(
433
 
    const QwtAlphaColorMap &other)
434
 
{
435
 
    QwtColorMap::operator=(other);
436
 
    *d_data = *other.d_data;
437
 
    return *this;
438
 
}
439
 
 
440
 
//! Clone the color map
441
 
QwtColorMap *QwtAlphaColorMap::copy() const
442
 
{
443
 
    QwtAlphaColorMap* map = new QwtAlphaColorMap();
444
 
    *map = *this;
445
 
 
446
 
    return map;
447
 
}
448
 
 
449
 
/*!
450
 
   Set the color 
451
 
 
452
 
   \param color Color
453
 
   \sa color()
454
 
*/
455
 
void QwtAlphaColorMap::setColor(const QColor &color)
456
 
{
457
 
    d_data->color = color;
458
 
    d_data->rgb = color.rgb();
459
 
}
460
 
 
461
 
/*! 
462
 
  \return the color 
463
 
  \sa setColor()
464
 
*/
465
 
QColor QwtAlphaColorMap::color() const
466
 
{
467
 
    return d_data->color;
468
 
}
469
 
 
470
 
/*!
471
 
  \brief Map a value of a given interval into a alpha value
472
 
 
473
 
  alpha := (value - interval.minValue()) / interval.width();
474
 
 
475
 
  \param interval Range for all values
476
 
  \param value Value to map into a rgb value
477
 
  \return rgb value, with an alpha value
478
 
*/
479
 
QRgb QwtAlphaColorMap::rgb(const QwtDoubleInterval &interval,
480
 
    double value) const
481
 
{
482
 
    if ( interval.isValid() )
483
 
    {
484
 
        const double ratio = (value - interval.minValue()) / interval.width();
485
 
        int alpha = qRound(255 * ratio);
486
 
        if ( alpha < 0 )
487
 
            alpha = 0;
488
 
        if ( alpha > 255 )
489
 
            alpha = 255;
490
 
 
491
 
        return d_data->rgb | (alpha << 24);
492
 
    }
493
 
    return d_data->rgb;
494
 
}
495
 
 
496
 
/*!
497
 
  Dummy function, needed to be implemented as it is pure virtual
498
 
  in QwtColorMap. Color indices make no sense in combination with 
499
 
  an alpha channel.
500
 
 
501
 
  \return Always 0
502
 
*/
503
 
unsigned char QwtAlphaColorMap::colorIndex(
504
 
    const QwtDoubleInterval &, double) const
505
 
{
506
 
    return 0;
507
 
}