src/gui/painting/qcolor.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qcolor.h"
00025 #include "qcolor_p.h"
00026 #include "qnamespace.h"
00027 #include "qcolormap.h"
00028 #include "qdatastream.h"
00029 #include "qvariant.h"
00030 #include "qdebug.h"
00031 
00032 #include <math.h>
00033 #include <stdio.h>
00034 #include <limits.h>
00035 
00036 
00249 #define QCOLOR_INT_RANGE_CHECK(fn, var) \
00250     do { \
00251         if (var < 0 || var > 255) { \
00252             qWarning(#fn": invalid value %d", var); \
00253             var = qMax(0, qMin(var, 255)); \
00254         } \
00255     } while (0)
00256 
00257 #define QCOLOR_REAL_RANGE_CHECK(fn, var) \
00258     do { \
00259         if (var < qreal(0.0) || var > qreal(1.0)) { \
00260             qWarning(#fn": invalid value %g", var); \
00261             var = qMax(qreal(0.0), qMin(var, qreal(1.0)));      \
00262         } \
00263     } while (0)
00264 
00265 /*****************************************************************************
00266   QColor member functions
00267  *****************************************************************************/
00268 
00310 QColor::QColor(Qt::GlobalColor color)
00311 {
00312 #define QRGB(r, g, b) \
00313     QRgb(((0xff << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff)))
00314 #define QRGBA(r, g, b, a) \
00315     QRgb(((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff))
00316 
00317     static const QRgb global_colors[] = {
00318         QRGB(255, 255, 255), // Qt::color0
00319         QRGB(  0,   0,   0), // Qt::color1
00320         QRGB(  0,   0,   0), // black
00321         QRGB(255, 255, 255), // white
00322         /*
00323          * From the "The Palette Manager: How and Why" by Ron Gery,
00324          * March 23, 1992, archived on MSDN:
00325          *
00326          *     The Windows system palette is broken up into two
00327          *     sections, one with fixed colors and one with colors
00328          *     that can be changed by applications. The system palette
00329          *     predefines 20 entries; these colors are known as the
00330          *     static or reserved colors and consist of the 16 colors
00331          *     found in the Windows version 3.0 VGA driver and 4
00332          *     additional colors chosen for their visual appeal.  The
00333          *     DEFAULT_PALETTE stock object is, as the name implies,
00334          *     the default palette selected into a device context (DC)
00335          *     and consists of these static colors. Applications can
00336          *     set the remaining 236 colors using the Palette Manager.
00337          *
00338          * The 20 reserved entries have indices in [0,9] and
00339          * [246,255]. We reuse 17 of them.
00340          */
00341         QRGB(128, 128, 128), // index 248   medium gray
00342         QRGB(160, 160, 164), // index 247   light gray
00343         QRGB(192, 192, 192), // index 7     light gray
00344         QRGB(255,   0,   0), // index 249   red
00345         QRGB(  0, 255,   0), // index 250   green
00346         QRGB(  0,   0, 255), // index 252   blue
00347         QRGB(  0, 255, 255), // index 254   cyan
00348         QRGB(255,   0, 255), // index 253   magenta
00349         QRGB(255, 255,   0), // index 251   yellow
00350         QRGB(128,   0,   0), // index 1     dark red
00351         QRGB(  0, 128,   0), // index 2     dark green
00352         QRGB(  0,   0, 128), // index 4     dark blue
00353         QRGB(  0, 128, 128), // index 6     dark cyan
00354         QRGB(128,   0, 128), // index 5     dark magenta
00355         QRGB(128, 128,   0), // index 3     dark yellow
00356         QRGBA(0, 0, 0, 0)    //             transparent
00357     };
00358 #undef QRGB
00359 #undef QRGBA
00360 
00361     setRgb(qRed(global_colors[color]),
00362            qGreen(global_colors[color]),
00363            qBlue(global_colors[color]),
00364            qAlpha(global_colors[color]));
00365 }
00366 
00385 QColor::QColor(QRgb color)
00386 {
00387     cspec = Rgb;
00388     ct.argb.alpha = 0xffff;
00389     ct.argb.red   = qRed(color)   * 0x101;
00390     ct.argb.green = qGreen(color) * 0x101;
00391     ct.argb.blue  = qBlue(color)  * 0x101;
00392     ct.argb.pad   = 0;
00393 }
00394 
00395 
00405 QColor::QColor(Spec spec)
00406 {
00407     switch (spec) {
00408     case Invalid:
00409         invalidate();
00410         break;
00411     case Rgb:
00412         setRgb(0, 0, 0);
00413         break;
00414     case Hsv:
00415         setHsv(0, 0, 0);
00416         break;
00417     case Cmyk:
00418         setCmyk(0, 0, 0, 0);
00419         break;
00420     }
00421 }
00422 
00466 QString QColor::name() const
00467 {
00468     QString s;
00469     s.sprintf("#%02x%02x%02x", red(), green(), blue());
00470     return s;
00471 }
00472 
00493 void QColor::setNamedColor(const QString &name)
00494 {
00495     if (name.isEmpty()) {
00496         invalidate();
00497         return;
00498     }
00499 
00500     QByteArray n = name.toLatin1();
00501     if (n.startsWith('#')) {
00502         QRgb rgb;
00503         if (qt_get_hex_rgb(n, &rgb)) {
00504             setRgb(rgb);
00505         } else {
00506             qWarning("QColor::setNamedColor: Could not parse color '%s'", n.constData());
00507             invalidate();
00508         }
00509         return;
00510     }
00511 
00512     QRgb rgb;
00513     if (qt_get_named_rgb(n, &rgb)) {
00514         setRgb(rgb);
00515     } else {
00516         qWarning("QColor::setNamedColor: Unknown color name '%s'", n.constData());
00517         invalidate();
00518     }
00519 }
00520 
00526 QStringList QColor::colorNames()
00527 {
00528     return qt_get_colornames();
00529 }
00530 
00541 void QColor::getHsvF(qreal *h, qreal *s, qreal *v, qreal *a) const
00542 {
00543         if (!h || !s || !v)
00544         return;
00545 
00546     if (cspec != Invalid && cspec != Hsv) {
00547         toHsv().getHsvF(h, s, v, a);
00548         return;
00549     }
00550 
00551     *h = ct.ahsv.hue == USHRT_MAX ? -1.0 : ct.ahsv.hue / 36000.0;
00552     *s = ct.ahsv.saturation / qreal(USHRT_MAX);
00553     *v = ct.ahsv.value / qreal(USHRT_MAX);
00554 
00555     if (a)
00556         *a = ct.ahsv.alpha / qreal(USHRT_MAX);
00557 }
00558 
00569 void QColor::getHsv(int *h, int *s, int *v, int *a) const
00570 {
00571     if (!h || !s || !v)
00572         return;
00573 
00574     if (cspec != Invalid && cspec != Hsv) {
00575         toHsv().getHsv(h, s, v, a);
00576         return;
00577     }
00578 
00579     *h = ct.ahsv.hue == USHRT_MAX ? -1 : ct.ahsv.hue / 100;
00580     *s = ct.ahsv.saturation >> 8;
00581     *v = ct.ahsv.value      >> 8;
00582 
00583     if (a)
00584         *a = ct.ahsv.alpha >> 8;
00585 }
00586 
00597 void QColor::setHsvF(qreal h, qreal s, qreal v, qreal a)
00598 {
00599     if (((h < 0.0 || h > 1.0) && h != -1.0)
00600         || (s < 0.0 || s > 1.0)
00601         || (v < 0.0 || v > 1.0)
00602         || (a < 0.0 || a > 1.0)) {
00603         qWarning("QColor::setHsvF: HSV parameters out of range");
00604         return;
00605     }
00606 
00607     cspec = Hsv;
00608     ct.ahsv.alpha      = qRound(a * USHRT_MAX);
00609     ct.ahsv.hue        = h == -1.0 ? USHRT_MAX : qRound(h * 36000);
00610     ct.ahsv.saturation = qRound(s * USHRT_MAX);
00611     ct.ahsv.value      = qRound(v * USHRT_MAX);
00612     ct.ahsv.pad        = 0;
00613 }
00614 
00626 void QColor::setHsv(int h, int s, int v, int a)
00627 {
00628     if (h < -1 || (uint)s > 255 || (uint)v > 255 || (uint)a > 255) {
00629         qWarning("QColor::setHsv: HSV parameters out of range");
00630         invalidate();
00631         return;
00632     }
00633 
00634     cspec = Hsv;
00635     ct.ahsv.alpha      = a * 0x101;
00636     ct.ahsv.hue        = h == -1 ? USHRT_MAX : (h % 360) * 100;
00637     ct.ahsv.saturation = s * 0x101;
00638     ct.ahsv.value      = v * 0x101;
00639     ct.ahsv.pad        = 0;
00640 }
00641 
00652 void QColor::getRgbF(qreal *r, qreal *g, qreal *b, qreal *a) const
00653 {
00654     if (!r || !g || !b)
00655         return;
00656 
00657     if (cspec != Invalid && cspec != Rgb) {
00658         toRgb().getRgbF(r, g, b, a);
00659         return;
00660     }
00661 
00662     *r = ct.argb.red   / qreal(USHRT_MAX);
00663     *g = ct.argb.green / qreal(USHRT_MAX);
00664     *b = ct.argb.blue  / qreal(USHRT_MAX);
00665 
00666     if (a)
00667         *a = ct.argb.alpha / qreal(USHRT_MAX);
00668 
00669 }
00670 
00681 void QColor::getRgb(int *r, int *g, int *b, int *a) const
00682 {
00683     if (!r || !g || !b)
00684         return;
00685 
00686     if (cspec != Invalid && cspec != Rgb) {
00687         toRgb().getRgb(r, g, b, a);
00688         return;
00689     }
00690 
00691     *r = ct.argb.red   >> 8;
00692     *g = ct.argb.green >> 8;
00693     *b = ct.argb.blue  >> 8;
00694 
00695     if (a)
00696         *a = ct.argb.alpha >> 8;
00697 }
00698 
00716 void QColor::setRgbF(qreal r, qreal g, qreal b, qreal a)
00717 {
00718     if (r < 0.0 || r > 1.0
00719         || g < 0.0 || g > 1.0
00720         || b < 0.0 || b > 1.0
00721         || a < 0.0 || a > 1.0) {
00722         qWarning("QColor::setRgbF: RGB parameters out of range");
00723         invalidate();
00724         return;
00725     }
00726 
00727     cspec = Rgb;
00728     ct.argb.alpha = qRound(a * USHRT_MAX);
00729     ct.argb.red   = qRound(r * USHRT_MAX);
00730     ct.argb.green = qRound(g * USHRT_MAX);
00731     ct.argb.blue  = qRound(b * USHRT_MAX);
00732     ct.argb.pad   = 0;
00733 }
00734 
00743 void QColor::setRgb(int r, int g, int b, int a)
00744 {
00745     if ((uint)r > 255 || (uint)g > 255 || (uint)b > 255 || (uint)a > 255) {
00746         qWarning("QColor::setRgb: RGB parameters out of range");
00747         invalidate();
00748         return;
00749     }
00750 
00751     cspec = Rgb;
00752     ct.argb.alpha = a * 0x101;
00753     ct.argb.red   = r * 0x101;
00754     ct.argb.green = g * 0x101;
00755     ct.argb.blue  = b * 0x101;
00756     ct.argb.pad   = 0;
00757 }
00758 
00778 QRgb QColor::rgba() const
00779 {
00780     if (cspec != Invalid && cspec != Rgb)
00781         return toRgb().rgba();
00782     return qRgba(ct.argb.red >> 8, ct.argb.green >> 8, ct.argb.blue >> 8, ct.argb.alpha >> 8);
00783 }
00784 
00791 void QColor::setRgba(QRgb rgba)
00792 {
00793     cspec = Rgb;
00794     ct.argb.alpha = qAlpha(rgba) * 0x101;
00795     ct.argb.red   = qRed(rgba)   * 0x101;
00796     ct.argb.green = qGreen(rgba) * 0x101;
00797     ct.argb.blue  = qBlue(rgba)  * 0x101;
00798     ct.argb.pad   = 0;
00799 }
00800 
00808 QRgb QColor::rgb() const
00809 {
00810     if (cspec != Invalid && cspec != Rgb)
00811         return toRgb().rgb();
00812     return qRgb(ct.argb.red >> 8, ct.argb.green >> 8, ct.argb.blue >> 8);
00813 }
00814 
00820 void QColor::setRgb(QRgb rgb)
00821 {
00822     cspec = Rgb;
00823     ct.argb.alpha = 0xffff;
00824     ct.argb.red   = qRed(rgb)   * 0x101;
00825     ct.argb.green = qGreen(rgb) * 0x101;
00826     ct.argb.blue  = qBlue(rgb)  * 0x101;
00827     ct.argb.pad   = 0;
00828 }
00829 
00836 int QColor::alpha() const
00837 { return ct.argb.alpha >> 8; }
00838 
00839 
00848 void QColor::setAlpha(int alpha)
00849 {
00850     QCOLOR_INT_RANGE_CHECK("QColor::setAlpha", alpha);
00851     ct.argb.alpha = alpha * 0x101;
00852 }
00853 
00860 qreal QColor::alphaF() const
00861 { return ct.argb.alpha / qreal(USHRT_MAX); }
00862 
00871 void QColor::setAlphaF(qreal alpha)
00872 {
00873     QCOLOR_REAL_RANGE_CHECK("QColor::setAlphaF", alpha);
00874     qreal tmp = alpha * USHRT_MAX;
00875     ct.argb.alpha = qRound(tmp);
00876 }
00877 
00878 
00884 int QColor::red() const
00885 {
00886     if (cspec != Invalid && cspec != Rgb)
00887         return toRgb().red();
00888     return ct.argb.red >> 8;
00889 }
00890 
00897 void QColor::setRed(int red)
00898 {
00899     QCOLOR_INT_RANGE_CHECK("QColor::setRed", red);
00900     if (cspec != Rgb)
00901         setRgb(red, green(), blue(), alpha());
00902     else
00903         ct.argb.red = red * 0x101;
00904 }
00905 
00911 int QColor::green() const
00912 {
00913     if (cspec != Invalid && cspec != Rgb)
00914         return toRgb().green();
00915     return ct.argb.green >> 8;
00916 }
00917 
00924 void QColor::setGreen(int green)
00925 {
00926     QCOLOR_INT_RANGE_CHECK("QColor::setGreen", green);
00927     if (cspec != Rgb)
00928         setRgb(red(), green, blue(), alpha());
00929     else
00930         ct.argb.green = green * 0x101;
00931 }
00932 
00933 
00939 int QColor::blue() const
00940 {
00941     if (cspec != Invalid && cspec != Rgb)
00942         return toRgb().blue();
00943     return ct.argb.blue >> 8;
00944 }
00945 
00946 
00953 void QColor::setBlue(int blue)
00954 {
00955     QCOLOR_INT_RANGE_CHECK("QColor::setBlue", blue);
00956     if (cspec != Rgb)
00957         setRgb(red(), green(), blue, alpha());
00958     else
00959         ct.argb.blue = blue * 0x101;
00960 }
00961 
00967 qreal QColor::redF() const
00968 {
00969     if (cspec != Invalid && cspec != Rgb)
00970         return toRgb().redF();
00971     return ct.argb.red / qreal(USHRT_MAX);
00972 }
00973 
00974 
00981 void QColor::setRedF(qreal red)
00982 {
00983     QCOLOR_REAL_RANGE_CHECK("QColor::setRedF", red);
00984     if (cspec != Rgb)
00985         setRgbF(red, greenF(), blueF(), alphaF());
00986     else
00987         ct.argb.red = qRound(red * USHRT_MAX);
00988 }
00989 
00995 qreal QColor::greenF() const
00996 {
00997     if (cspec != Invalid && cspec != Rgb)
00998         return toRgb().greenF();
00999     return ct.argb.green / qreal(USHRT_MAX);
01000 }
01001 
01002 
01009 void QColor::setGreenF(qreal green)
01010 {
01011     QCOLOR_REAL_RANGE_CHECK("QColor::setGreenF", green);
01012     if (cspec != Rgb)
01013         setRgbF(redF(), green, blueF(), alphaF());
01014     else
01015         ct.argb.green = qRound(green * USHRT_MAX);
01016 }
01017 
01023 qreal QColor::blueF() const
01024 {
01025     if (cspec != Invalid && cspec != Rgb)
01026         return toRgb().blueF();
01027     return ct.argb.blue / qreal(USHRT_MAX);
01028 }
01029 
01036 void QColor::setBlueF(qreal blue)
01037 {
01038     QCOLOR_REAL_RANGE_CHECK("QColor::setBlueF", blue);
01039     if (cspec != Rgb)
01040         setRgbF(redF(), greenF(), blue, alphaF());
01041     else
01042         ct.argb.blue = qRound(blue * USHRT_MAX);
01043 }
01044 
01051 int QColor::hue() const
01052 {
01053     if (cspec != Invalid && cspec != Hsv)
01054         return toHsv().hue();
01055     return ct.ahsv.hue == USHRT_MAX ? -1 : ct.ahsv.hue / 100;
01056 }
01057 
01064 int QColor::saturation() const
01065 {
01066     if (cspec != Invalid && cspec != Hsv)
01067         return toHsv().saturation();
01068     return ct.ahsv.saturation >> 8;
01069 }
01070 
01077 int QColor::value() const
01078 {
01079     if (cspec != Invalid && cspec != Hsv)
01080         return toHsv().value();
01081     return ct.ahsv.value >> 8;
01082 }
01083 
01090 qreal QColor::hueF() const
01091 {
01092     if (cspec != Invalid && cspec != Hsv)
01093         return toHsv().hueF();
01094     return ct.ahsv.hue == USHRT_MAX ? -1.0 : ct.ahsv.hue / 36000.0;
01095 }
01096 
01103 qreal QColor::saturationF() const
01104 {
01105     if (cspec != Invalid && cspec != Hsv)
01106         return toHsv().saturationF();
01107     return ct.ahsv.saturation / qreal(USHRT_MAX);
01108 }
01109 
01116 qreal QColor::valueF() const
01117 {
01118     if (cspec != Invalid && cspec != Hsv)
01119         return toHsv().valueF();
01120     return ct.ahsv.value / qreal(USHRT_MAX);
01121 }
01122 
01129 int QColor::cyan() const
01130 {
01131     if (cspec != Invalid && cspec != Cmyk)
01132         return toCmyk().cyan();
01133     return ct.acmyk.cyan >> 8;
01134 }
01135 
01142 int QColor::magenta() const
01143 {
01144     if (cspec != Invalid && cspec != Cmyk)
01145         return toCmyk().magenta();
01146     return ct.acmyk.magenta >> 8;
01147 }
01148 
01155 int QColor::yellow() const
01156 {
01157     if (cspec != Invalid && cspec != Cmyk)
01158         return toCmyk().yellow();
01159     return ct.acmyk.yellow >> 8;
01160 }
01161 
01169 int QColor::black() const
01170 {
01171     if (cspec != Invalid && cspec != Cmyk)
01172         return toCmyk().black();
01173     return ct.acmyk.black >> 8;
01174 }
01175 
01182 qreal QColor::cyanF() const
01183 {
01184     if (cspec != Invalid && cspec != Cmyk)
01185         return toCmyk().cyanF();
01186     return ct.acmyk.cyan / qreal(USHRT_MAX);
01187 }
01188 
01195 qreal QColor::magentaF() const
01196 {
01197     if (cspec != Invalid && cspec != Cmyk)
01198         return toCmyk().magentaF();
01199     return ct.acmyk.magenta / qreal(USHRT_MAX);
01200 }
01201 
01208 qreal QColor::yellowF() const
01209 {
01210     if (cspec != Invalid && cspec != Cmyk)
01211         return toCmyk().yellowF();
01212     return ct.acmyk.yellow / qreal(USHRT_MAX);
01213 }
01214 
01221 qreal QColor::blackF() const
01222 {
01223     if (cspec != Invalid && cspec != Cmyk)
01224         return toCmyk().blackF();
01225     return ct.acmyk.black / qreal(USHRT_MAX);
01226 }
01227 
01233 QColor QColor::toRgb() const
01234 {
01235     if (!isValid() || cspec == Rgb)
01236         return *this;
01237 
01238     QColor color;
01239     color.cspec = Rgb;
01240     color.ct.argb.alpha = ct.argb.alpha;
01241     color.ct.argb.pad = 0;
01242 
01243     switch (cspec) {
01244     case Hsv:
01245         {
01246             if (ct.ahsv.saturation == 0 || ct.ahsv.hue == USHRT_MAX) {
01247                 // achromatic case
01248                 color.ct.argb.red = color.ct.argb.green = color.ct.argb.blue = ct.ahsv.value;
01249                 break;
01250             }
01251 
01252             // chromatic case
01253             const qreal h = ct.ahsv.hue / 6000.;
01254             const qreal s = ct.ahsv.saturation / qreal(USHRT_MAX);
01255             const qreal v = ct.ahsv.value / qreal(USHRT_MAX);
01256             const int i = int(h);
01257             const qreal f = h - i;
01258             const qreal p = v * (1.0 - s);
01259 
01260             if (i & 1) {
01261                 const qreal q = v * (1.0 - (s * f));
01262 
01263                 switch (i) {
01264                 case 1:
01265                     color.ct.argb.red   = qRound(q * USHRT_MAX);
01266                     color.ct.argb.green = qRound(v * USHRT_MAX);
01267                     color.ct.argb.blue  = qRound(p * USHRT_MAX);
01268                     break;
01269                 case 3:
01270                     color.ct.argb.red   = qRound(p * USHRT_MAX);
01271                     color.ct.argb.green = qRound(q * USHRT_MAX);
01272                     color.ct.argb.blue  = qRound(v * USHRT_MAX);
01273                     break;
01274                 case 5:
01275                     color.ct.argb.red   = qRound(v * USHRT_MAX);
01276                     color.ct.argb.green = qRound(p * USHRT_MAX);
01277                     color.ct.argb.blue  = qRound(q * USHRT_MAX);
01278                     break;
01279                 }
01280             } else {
01281                 const qreal t = v * (1.0 - (s * (1.0 - f)));
01282 
01283                 switch (i) {
01284                 case 0:
01285                     color.ct.argb.red   = qRound(v * USHRT_MAX);
01286                     color.ct.argb.green = qRound(t * USHRT_MAX);
01287                     color.ct.argb.blue  = qRound(p * USHRT_MAX);
01288                     break;
01289                 case 2:
01290                     color.ct.argb.red   = qRound(p * USHRT_MAX);
01291                     color.ct.argb.green = qRound(v * USHRT_MAX);
01292                     color.ct.argb.blue  = qRound(t * USHRT_MAX);
01293                     break;
01294                 case 4:
01295                     color.ct.argb.red   = qRound(t * USHRT_MAX);
01296                     color.ct.argb.green = qRound(p * USHRT_MAX);
01297                     color.ct.argb.blue  = qRound(v * USHRT_MAX);
01298                     break;
01299                 }
01300             }
01301             break;
01302         }
01303     case Cmyk:
01304         {
01305             const qreal c = ct.acmyk.cyan / qreal(USHRT_MAX);
01306             const qreal m = ct.acmyk.magenta / qreal(USHRT_MAX);
01307             const qreal y = ct.acmyk.yellow / qreal(USHRT_MAX);
01308             const qreal k = ct.acmyk.black / qreal(USHRT_MAX);
01309 
01310             color.ct.argb.red   = qRound((1.0 - (c * (1.0 - k) + k)) * USHRT_MAX);
01311             color.ct.argb.green = qRound((1.0 - (m * (1.0 - k) + k)) * USHRT_MAX);
01312             color.ct.argb.blue  = qRound((1.0 - (y * (1.0 - k) + k)) * USHRT_MAX);
01313             break;
01314         }
01315     default:
01316         break;
01317     }
01318 
01319     return color;
01320 }
01321 
01322 
01323 #define Q_MAX_3(a, b, c) ( ( a > b && a > c) ? a : (b > c ? b : c) )
01324 #define Q_MIN_3(a, b, c) ( ( a < b && a < c) ? a : (b < c ? b : c) )
01325 
01326 
01333 QColor QColor::toHsv() const
01334 {
01335     if (!isValid())
01336         return *this;
01337 
01338     if (cspec != Rgb)
01339         return toRgb().toHsv();
01340 
01341     QColor color;
01342     color.cspec = Hsv;
01343     color.ct.ahsv.alpha = ct.argb.alpha;
01344     color.ct.ahsv.pad = 0;
01345 
01346     const qreal r = ct.argb.red   / qreal(USHRT_MAX);
01347     const qreal g = ct.argb.green / qreal(USHRT_MAX);
01348     const qreal b = ct.argb.blue  / qreal(USHRT_MAX);
01349     const qreal max = Q_MAX_3(r, g, b);
01350     const qreal min = Q_MIN_3(r, g, b);
01351     const qreal delta = max - min;
01352     color.ct.ahsv.value = qRound(max * USHRT_MAX);
01353     if (delta == 0.0) {
01354         // achromatic case, hue is undefined
01355         color.ct.ahsv.hue = USHRT_MAX;
01356         color.ct.ahsv.saturation = 0;
01357     } else {
01358         // chromatic case
01359         qreal hue = 0;
01360         color.ct.ahsv.saturation = qRound((delta / max) * USHRT_MAX);
01361         if (r == max) {
01362             hue = ((g - b) /delta);
01363         } else if (g == max) {
01364             hue = (2.0 + (b - r) / delta);
01365         } else if (b == max) {
01366             hue = (4.0 + (r - g) / delta);
01367         } else {
01368             Q_ASSERT_X(false, "QColor::toHsv", "internal error");
01369         }
01370         hue *= 60.0;
01371         if (hue < 0.0)
01372             hue += 360.0;
01373         color.ct.ahsv.hue = qRound(hue * 100);
01374     }
01375 
01376     return color;
01377 }
01378 
01385 QColor QColor::toCmyk() const
01386 {
01387     if (!isValid())
01388         return *this;
01389     if (cspec != Rgb)
01390         return toRgb().toCmyk();
01391 
01392     QColor color;
01393     color.cspec = Cmyk;
01394     color.ct.acmyk.alpha = ct.argb.alpha;
01395 
01396     // rgb -> cmy
01397     const qreal r = ct.argb.red   / qreal(USHRT_MAX);
01398     const qreal g = ct.argb.green / qreal(USHRT_MAX);
01399     const qreal b = ct.argb.blue  / qreal(USHRT_MAX);
01400     qreal c = 1.0 - r;
01401     qreal m = 1.0 - g;
01402     qreal y = 1.0 - b;
01403 
01404     // cmy -> cmyk
01405     const qreal k = qMin(c, qMin(m, y));
01406 
01407     if (!qFuzzyCompare(k,1)) {
01408         c = (c - k) / (1.0 - k);
01409         m = (m - k) / (1.0 - k);
01410         y = (y - k) / (1.0 - k);
01411     }
01412 
01413     color.ct.acmyk.cyan    = qRound(c * USHRT_MAX);
01414     color.ct.acmyk.magenta = qRound(m * USHRT_MAX);
01415     color.ct.acmyk.yellow  = qRound(y * USHRT_MAX);
01416     color.ct.acmyk.black   = qRound(k * USHRT_MAX);
01417 
01418     return color;
01419 }
01420 
01421 QColor QColor::convertTo(QColor::Spec colorSpec) const
01422 {
01423     if (colorSpec == cspec)
01424         return *this;
01425     switch (colorSpec) {
01426     case Rgb:
01427         return toRgb();
01428     case Hsv:
01429         return toHsv();
01430     case Cmyk:
01431         return toCmyk();
01432     case Invalid:
01433         break;
01434     }
01435     return QColor(); // must be invalid
01436 }
01437 
01438 
01450 QColor QColor::fromRgb(QRgb rgb)
01451 {
01452     return fromRgb(qRed(rgb), qGreen(rgb), qBlue(rgb));
01453 }
01454 
01455 
01466 QColor QColor::fromRgba(QRgb rgba)
01467 {
01468     return fromRgb(qRed(rgba), qGreen(rgba), qBlue(rgba), qAlpha(rgba));
01469 }
01470 
01480 QColor QColor::fromRgb(int r, int g, int b, int a)
01481 {
01482     if (r < 0 || r > 255
01483         || g < 0 || g > 255
01484         || b < 0 || b > 255
01485         || a < 0 || a > 255) {
01486         qWarning("QColor::fromRgb: RGB parameters out of range");
01487         return QColor();
01488     }
01489 
01490     QColor color;
01491     color.cspec = Rgb;
01492     color.ct.argb.alpha = a * 0x101;
01493     color.ct.argb.red   = r * 0x101;
01494     color.ct.argb.green = g * 0x101;
01495     color.ct.argb.blue  = b * 0x101;
01496     color.ct.argb.pad   = 0;
01497     return color;
01498 }
01499 
01509 QColor QColor::fromRgbF(qreal r, qreal g, qreal b, qreal a)
01510 {
01511     if (r < 0.0 || r > 1.0
01512         || g < 0.0 || g > 1.0
01513         || b < 0.0 || b > 1.0
01514         || a < 0.0 || a > 1.0) {
01515         qWarning("QColor::fromRgbF: RGB parameters out of range");
01516         return QColor();
01517     }
01518 
01519     QColor color;
01520     color.cspec = Rgb;
01521     color.ct.argb.alpha = qRound(a * USHRT_MAX);
01522     color.ct.argb.red   = qRound(r * USHRT_MAX);
01523     color.ct.argb.green = qRound(g * USHRT_MAX);
01524     color.ct.argb.blue  = qRound(b * USHRT_MAX);
01525     color.ct.argb.pad   = 0;
01526     return color;
01527 }
01528 
01540 QColor QColor::fromHsv(int h, int s, int v, int a)
01541 {
01542     if (((h < 0 || h >= 360) && h != -1)
01543         || s < 0 || s > 255
01544         || v < 0 || v > 255
01545         || a < 0 || a > 255) {
01546         qWarning("QColor::fromHsv: HSV parameters out of range");
01547         return QColor();
01548     }
01549 
01550     QColor color;
01551     color.cspec = Hsv;
01552     color.ct.ahsv.alpha      = a * 0x101;
01553     color.ct.ahsv.hue        = h == -1 ? USHRT_MAX : (h % 360) * 100;
01554     color.ct.ahsv.saturation = s * 0x101;
01555     color.ct.ahsv.value      = v * 0x101;
01556     color.ct.ahsv.pad        = 0;
01557     return color;
01558 }
01559 
01572 QColor QColor::fromHsvF(qreal h, qreal s, qreal v, qreal a)
01573 {
01574     if (((h < 0.0 || h > 1.0) && h != -1.0)
01575         || (s < 0.0 || s > 1.0)
01576         || (v < 0.0 || v > 1.0)
01577         || (a < 0.0 || a > 1.0)) {
01578         qWarning("QColor::fromHsvF: HSV parameters out of range");
01579         return QColor();
01580     }
01581 
01582     QColor color;
01583     color.cspec = Hsv;
01584     color.ct.ahsv.alpha      = qRound(a * USHRT_MAX);
01585     color.ct.ahsv.hue        = h == -1.0 ? USHRT_MAX : qRound(h * 36000);
01586     color.ct.ahsv.saturation = qRound(s * USHRT_MAX);
01587     color.ct.ahsv.value      = qRound(v * USHRT_MAX);
01588     color.ct.ahsv.pad        = 0;
01589     return color;
01590 }
01591 
01602 void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a)
01603 {
01604     if (!c || !m || !y || !k)
01605         return;
01606 
01607     if (cspec != Invalid && cspec != Cmyk) {
01608         toCmyk().getCmyk(c, m, y, k, a);
01609         return;
01610     }
01611 
01612     *c = ct.acmyk.cyan >> 8;
01613     *m = ct.acmyk.magenta >> 8;
01614     *y = ct.acmyk.yellow >> 8;
01615     *k = ct.acmyk.black >> 8;
01616 
01617     if (a)
01618         *a = ct.acmyk.alpha >> 8;
01619 }
01620 
01631 void QColor::getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a)
01632 {
01633     if (!c || !m || !y || !k)
01634         return;
01635 
01636     if (cspec != Invalid && cspec != Cmyk) {
01637         toCmyk().getCmykF(c, m, y, k, a);
01638         return;
01639     }
01640 
01641     *c = ct.acmyk.cyan    / qreal(USHRT_MAX);
01642     *m = ct.acmyk.magenta / qreal(USHRT_MAX);
01643     *y = ct.acmyk.yellow  / qreal(USHRT_MAX);
01644     *k = ct.acmyk.black   / qreal(USHRT_MAX);
01645 
01646     if (a)
01647         *a = ct.acmyk.alpha / qreal(USHRT_MAX);
01648 }
01649 
01659 void QColor::setCmyk(int c, int m, int y, int k, int a)
01660 {
01661     if (c < 0 || c > 255
01662         || m < 0 || m > 255
01663         || y < 0 || y > 255
01664         || k < 0 || k > 255
01665         || a < 0 || a > 255) {
01666         qWarning("QColor::setCmyk: CMYK parameters out of range");
01667         return;
01668     }
01669 
01670     cspec = Cmyk;
01671     ct.acmyk.alpha   = a * 0x101;
01672     ct.acmyk.cyan    = c * 0x101;
01673     ct.acmyk.magenta = m * 0x101;
01674     ct.acmyk.yellow  = y * 0x101;
01675     ct.acmyk.black   = k * 0x101;
01676 }
01677 
01689 void QColor::setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a)
01690 {
01691     if (c < 0.0 || c > 1.0
01692         || m < 0.0 || m > 1.0
01693         || y < 0.0 || y > 1.0
01694         || k < 0.0 || k > 1.0
01695         || a < 0.0 || a > 1.0) {
01696         qWarning("QColor::setCmykF: CMYK parameters out of range");
01697         return;
01698     }
01699 
01700     cspec = Cmyk;
01701     ct.acmyk.alpha   = qRound(a * USHRT_MAX);
01702     ct.acmyk.cyan    = qRound(c * USHRT_MAX);
01703     ct.acmyk.magenta = qRound(m * USHRT_MAX);
01704     ct.acmyk.yellow  = qRound(y * USHRT_MAX);
01705     ct.acmyk.black   = qRound(k * USHRT_MAX);
01706 }
01707 
01719 QColor QColor::fromCmyk(int c, int m, int y, int k, int a)
01720 {
01721     if (c < 0 || c > 255
01722         || m < 0 || m > 255
01723         || y < 0 || y > 255
01724         || k < 0 || k > 255
01725         || a < 0 || a > 255) {
01726         qWarning("QColor::fromCmyk: CMYK parameters out of range");
01727         return QColor();
01728     }
01729 
01730     QColor color;
01731     color.cspec = Cmyk;
01732     color.ct.acmyk.alpha   = a * 0x101;
01733     color.ct.acmyk.cyan    = c * 0x101;
01734     color.ct.acmyk.magenta = m * 0x101;
01735     color.ct.acmyk.yellow  = y * 0x101;
01736     color.ct.acmyk.black   = k * 0x101;
01737     return color;
01738 }
01739 
01753 QColor QColor::fromCmykF(qreal c, qreal m, qreal y, qreal k, qreal a)
01754 {
01755     if (c < 0.0 || c > 1.0
01756         || m < 0.0 || m > 1.0
01757         || y < 0.0 || y > 1.0
01758         || k < 0.0 || k > 1.0
01759         || a < 0.0 || a > 1.0) {
01760         qWarning("QColor::fromCmykF: CMYK parameters out of range");
01761         return QColor();
01762     }
01763 
01764     QColor color;
01765     color.cspec = Cmyk;
01766     color.ct.acmyk.alpha   = qRound(a * USHRT_MAX);
01767     color.ct.acmyk.cyan    = qRound(c * USHRT_MAX);
01768     color.ct.acmyk.magenta = qRound(m * USHRT_MAX);
01769     color.ct.acmyk.yellow  = qRound(y * USHRT_MAX);
01770     color.ct.acmyk.black   = qRound(k * USHRT_MAX);
01771     return color;
01772 }
01773 
01791 QColor QColor::light(int factor) const
01792 {
01793     if (factor <= 0)                                // invalid lightness factor
01794         return *this;
01795     else if (factor < 100)                        // makes color darker
01796         return dark(10000/factor);
01797 
01798     QColor hsv = toHsv();
01799     int s = hsv.ct.ahsv.saturation;
01800     int v = hsv.ct.ahsv.value;
01801 
01802     v = (factor*v)/100;
01803     if (v > USHRT_MAX) {
01804         // overflow... adjust saturation
01805         s -= v - USHRT_MAX;
01806         if (s < 0)
01807             s = 0;
01808         v = USHRT_MAX;
01809     }
01810 
01811     hsv.ct.ahsv.saturation = s;
01812     hsv.ct.ahsv.value = v;
01813 
01814     // convert back to same color spec as original color
01815     return hsv.convertTo(cspec);
01816 }
01817 
01835 QColor QColor::dark(int factor) const
01836 {
01837     if (factor <= 0)                                // invalid darkness factor
01838         return *this;
01839     else if (factor < 100)                        // makes color lighter
01840         return light(10000/factor);
01841 
01842     QColor hsv = toHsv();
01843     hsv.ct.ahsv.value = (hsv.ct.ahsv.value * 100) / factor;
01844 
01845     // convert back to same color spec as original color
01846     return hsv.convertTo(cspec);
01847 }
01848 
01853 QColor &QColor::operator=(const QColor &color)
01854 {
01855     cspec = color.cspec;
01856     ct.argb = color.ct.argb;
01857     return *this;
01858 }
01859 
01863 QColor &QColor::operator=(Qt::GlobalColor color)
01864 {
01865     return operator=(QColor(color));
01866 }
01867 
01872 bool QColor::operator==(const QColor &color) const
01873 {
01874     return (cspec == color.cspec
01875             && ct.argb.alpha == color.ct.argb.alpha
01876             && ct.argb.red   == color.ct.argb.red
01877             && ct.argb.green == color.ct.argb.green
01878             && ct.argb.blue  == color.ct.argb.blue
01879             && ct.argb.pad   == color.ct.argb.pad);
01880 }
01881 
01886 bool QColor::operator!=(const QColor &color) const
01887 { return !operator==(color); }
01888 
01889 
01893 QColor::operator QVariant() const
01894 {
01895     return QVariant(QVariant::Color, this);
01896 }
01897 
01903 void QColor::invalidate()
01904 {
01905     cspec = Invalid;
01906     ct.argb.alpha = USHRT_MAX;
01907     ct.argb.red = 0;
01908     ct.argb.green = 0;
01909     ct.argb.blue = 0;
01910     ct.argb.pad = 0;
01911 }
01912 
01913 #ifdef QT3_SUPPORT
01914 
01929 uint QColor::pixel(int screen) const
01930 {
01931     QColormap cmap = QColormap::instance(screen);
01932     return cmap.pixel(*this);
01933 }
01934 
01935 #endif // QT3_SUPPORT
01936 
01937 /*****************************************************************************
01938   QColor stream functions
01939  *****************************************************************************/
01940 
01941 #ifndef QT_NO_DEBUG_STREAM
01942 QDebug operator<<(QDebug dbg, const QColor &c)
01943 {
01944 #ifndef Q_BROKEN_DEBUG_STREAM
01945     if (!c.isValid())
01946         dbg.nospace() << "QColor(Invalid)";
01947     else if (c.spec() == QColor::Rgb)
01948         dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ")";
01949     else if (c.spec() == QColor::Hsv)
01950         dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ")";
01951     else if (c.spec() == QColor::Cmyk)
01952         dbg.nospace() << "QColor(ACMYK " << c.alphaF() << ", " << c.cyanF() << ", " << c.magentaF() << ", " << c.yellowF() << ", "
01953                       << c.blackF()<< ")";
01954 
01955     return dbg.space();
01956 #else
01957     qWarning("This compiler doesn't support streaming QColor to QDebug");
01958     return dbg;
01959     Q_UNUSED(c);
01960 #endif
01961 }
01962 #endif
01963 
01964 #ifndef QT_NO_DATASTREAM
01965 
01973 QDataStream &operator<<(QDataStream &stream, const QColor &color)
01974 {
01975     if (stream.version() < 7) {
01976         quint32 p = (quint32)color.rgb();
01977         if (stream.version() == 1) // Swap red and blue
01978             p = ((p << 16) & 0xff0000) | ((p >> 16) & 0xff) | (p & 0xff00ff00);
01979         return stream << p;
01980     }
01981 
01982     qint8   s = color.cspec;
01983     quint16 a = color.ct.argb.alpha;
01984     quint16 r = color.ct.argb.red;
01985     quint16 g = color.ct.argb.green;
01986     quint16 b = color.ct.argb.blue;
01987     quint16 p = color.ct.argb.pad;
01988 
01989     stream << s;
01990     stream << a;
01991     stream << r;
01992     stream << g;
01993     stream << b;
01994     stream << p;
01995 
01996     return stream;
01997 }
01998 
02007 QDataStream &operator>>(QDataStream &stream, QColor &color)
02008 {
02009     if (stream.version() < 7) {
02010         quint32 p;
02011         stream >> p;
02012         if (stream.version() == 1) // Swap red and blue
02013             p = ((p << 16) & 0xff0000) | ((p >> 16) & 0xff) | (p & 0xff00ff00);
02014         color.setRgb(p);
02015         return stream;
02016     }
02017 
02018     qint8 s;
02019     quint16 a, r, g, b, p;
02020     stream >> s;
02021     stream >> a;
02022     stream >> r;
02023     stream >> g;
02024     stream >> b;
02025     stream >> p;
02026 
02027     color.cspec = QColor::Spec(s);
02028     color.ct.argb.alpha = a;
02029     color.ct.argb.red   = r;
02030     color.ct.argb.green = g;
02031     color.ct.argb.blue  = b;
02032     color.ct.argb.pad   = p;
02033 
02034     return stream;
02035 }
02036 #endif
02037 
02038 
02039 
02040 
02041 /*****************************************************************************
02042   QColor global functions (documentation only)
02043  *****************************************************************************/
02044 

Generated on Thu Mar 15 11:55:20 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1