summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hartmann <Thomas.Hartmann@nokia.com>2009-08-24 11:02:27 +0200
committerThomas Hartmann <Thomas.Hartmann@nokia.com>2009-08-24 11:52:30 +0200
commitd1111859c26526227c07793aa6747efa65496055 (patch)
treed3189b11b67ccd679a076cd5f9aaea8d2bd8bddd
parent8260b28cbbc1103a20e9f920fad099922021e9c7 (diff)
downloadqt4-tools-d1111859c26526227c07793aa6747efa65496055.tar.gz
HSL support for QColor
This patch adds support for the HSL color space to QColor See discussions on dev mailing list Reviewed-by: Marco Bubke
-rw-r--r--src/gui/painting/qcolor.cpp453
-rw-r--r--src/gui/painting/qcolor.h32
-rw-r--r--tests/auto/qcolor/tst_qcolor.cpp230
3 files changed, 689 insertions, 26 deletions
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 4e93f04d51..ef884bdb2b 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -237,6 +237,15 @@ QT_BEGIN_NAMESPACE
alpha-channel to feature \l {QColor#Alpha-Blended
Drawing}{alpha-blended drawing}.
+ \section1 The HSL Color Model
+
+ HSL is similar to HSV. Instead of value parameter from HSV,
+ HSL has the lightness parameter.
+ The lightness parameter goes from black to color and from color to white.
+ If you go outside at the night its black or dark gray. At day its colorful but
+ if you look in a really strong light a things they are going to white and
+ wash out.
+
\section1 The CMYK Color Model
While the RGB and HSV color models are used for display on
@@ -437,6 +446,9 @@ QColor::QColor(Spec spec)
case Cmyk:
setCmyk(0, 0, 0, 0);
break;
+ case Hsl:
+ setHsl(0, 0, 0, 0);
+ break;
}
}
@@ -678,6 +690,113 @@ void QColor::setHsv(int h, int s, int v, int a)
}
/*!
+ Sets the contents pointed to by \a h, \a s, \a l, and \a a, to the hue,
+ saturation, lightness, and alpha-channel (transparency) components of the
+ color's HSL value.
+
+ These components can be retrieved individually using the hueHslF(),
+ saturationHslF(), lightnessF() and alphaF() functions.
+
+ \sa setHsl()
+*/
+void QColor::getHslF(qreal *h, qreal *s, qreal *l, qreal *a) const
+{
+ if (!h || !s || !l)
+ return;
+
+ if (cspec != Invalid && cspec != Hsl) {
+ toHsl().getHslF(h, s, l, a);
+ return;
+ }
+
+ *h = ct.ahsl.hue == USHRT_MAX ? -1.0 : ct.ahsl.hue / 36000.0;
+ *s = ct.ahsl.saturation / qreal(USHRT_MAX);
+ *l = ct.ahsl.lightness / qreal(USHRT_MAX);
+
+ if (a)
+ *a = ct.ahsl.alpha / qreal(USHRT_MAX);
+}
+
+/*!
+ Sets the contents pointed to by \a h, \a s, \a l, and \a a, to the hue,
+ saturation, lightness, and alpha-channel (transparency) components of the
+ color's HSL value.
+
+ These components can be retrieved individually using the hueHsl(),
+ saturationHsl(), lightness() and alpha() functions.
+
+ \sa setHsl()
+*/
+void QColor::getHsl(int *h, int *s, int *l, int *a) const
+{
+ if (!h || !s || !l)
+ return;
+
+ if (cspec != Invalid && cspec != Hsl) {
+ toHsl().getHsl(h, s, l, a);
+ return;
+ }
+
+ *h = ct.ahsl.hue == USHRT_MAX ? -1 : ct.ahsl.hue / 100;
+ *s = ct.ahsl.saturation >> 8;
+ *l = ct.ahsl.lightness >> 8;
+
+ if (a)
+ *a = ct.ahsl.alpha >> 8;
+}
+
+/*!
+ Sets a HSL color lightness; \a h is the hue, \a s is the saturation, \a l is
+ the lightness and \a a is the alpha component of the HSL color.
+
+ All the values must be in the range 0.0-1.0.
+
+ \sa getHslF(), setHsl()
+*/
+void QColor::setHslF(qreal h, qreal s, qreal l, qreal a)
+{
+ if (((h < 0.0 || h > 1.0) && h != -1.0)
+ || (s < 0.0 || s > 1.0)
+ || (l < 0.0 || l > 1.0)
+ || (a < 0.0 || a > 1.0)) {
+ qWarning("QColor::setHsvF: HSV parameters out of range");
+ return;
+ }
+
+ cspec = Hsl;
+ ct.ahsl.alpha = qRound(a * USHRT_MAX);
+ ct.ahsl.hue = h == -1.0 ? USHRT_MAX : qRound(h * 36000);
+ ct.ahsl.saturation = qRound(s * USHRT_MAX);
+ ct.ahsl.lightness = qRound(l * USHRT_MAX);
+ ct.ahsl.pad = 0;
+}
+
+/*!
+ Sets a HSL color value; \a h is the hue, \a s is the saturation, \a l is
+ the lightness and \a a is the alpha component of the HSL color.
+
+ The saturation, value and alpha-channel values must be in the range 0-255,
+ and the hue value must be greater than -1.
+
+ \sa getHsl(), setHslF()
+*/
+void QColor::setHsl(int h, int s, int l, int a)
+{
+ if (h < -1 || (uint)s > 255 || (uint)l > 255 || (uint)a > 255) {
+ qWarning("QColor::setHsv: HSV parameters out of range");
+ invalidate();
+ return;
+ }
+
+ cspec = Hsl;
+ ct.ahsl.alpha = a * 0x101;
+ ct.ahsl.hue = h == -1 ? USHRT_MAX : (h % 360) * 100;
+ ct.ahsl.saturation = s * 0x101;
+ ct.ahsl.lightness = l * 0x101;
+ ct.ahsl.pad = 0;
+}
+
+/*!
Sets the contents pointed to by \a r, \a g, \a b, and \a a, to the red,
green, blue, and alpha-channel (transparency) components of the color's
RGB value.
@@ -1082,11 +1201,25 @@ void QColor::setBlueF(qreal blue)
/*!
Returns the hue color component of this color.
- \sa hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ The color is implicitly converted to HSV.
+
+ \sa hsvHue(), hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
+
int QColor::hue() const
{
+ return hsvHue();
+}
+
+/*!
+ Returns the hue color component of this color.
+
+ \sa hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+int QColor::hsvHue() const
+{
if (cspec != Invalid && cspec != Hsv)
return toHsv().hue();
return ct.ahsv.hue == USHRT_MAX ? -1 : ct.ahsv.hue / 100;
@@ -1095,11 +1228,25 @@ int QColor::hue() const
/*!
Returns the saturation color component of this color.
- \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ The color is implicitly converted to HSV.
+
+ \sa hsvSaturation(), saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
+
int QColor::saturation() const
{
+ return hsvSaturation();
+}
+
+/*!
+ Returns the saturation color component of this color.
+
+ \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+int QColor::hsvSaturation() const
+{
if (cspec != Invalid && cspec != Hsv)
return toHsv().saturation();
return ct.ahsv.saturation >> 8;
@@ -1121,11 +1268,24 @@ int QColor::value() const
/*!
Returns the hue color component of this color.
- \sa hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color
+ The color is implicitly converted to HSV.
+
+ \sa hsvHueF(), hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
qreal QColor::hueF() const
{
+ return hsvHueF();
+}
+
+/*!
+ Returns the hue color component of this color.
+
+ \sa hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+qreal QColor::hsvHueF() const
+{
if (cspec != Invalid && cspec != Hsv)
return toHsv().hueF();
return ct.ahsv.hue == USHRT_MAX ? -1.0 : ct.ahsv.hue / 36000.0;
@@ -1134,11 +1294,24 @@ qreal QColor::hueF() const
/*!
Returns the saturation color component of this color.
- \sa saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color
+ The color is implicitly converted to HSV.
+
+ \sa hsvSaturationF(), saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
qreal QColor::saturationF() const
{
+ return hsvSaturationF();
+}
+
+/*!
+ Returns the saturation color component of this color.
+
+ \sa saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+qreal QColor::hsvSaturationF() const
+{
if (cspec != Invalid && cspec != Hsv)
return toHsv().saturationF();
return ct.ahsv.saturation / qreal(USHRT_MAX);
@@ -1158,6 +1331,79 @@ qreal QColor::valueF() const
}
/*!
+ Returns the hue color component of this color.
+
+ \sa hueHslF(), getHsl()
+*/
+int QColor::hslHue() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().hslHue();
+ return ct.ahsl.hue == USHRT_MAX ? -1 : ct.ahsl.hue / 100;
+}
+
+/*!
+ Returns the saturation color component of this color.
+
+ \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+int QColor::hslSaturation() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().hslSaturation();
+ return ct.ahsl.saturation >> 8;
+}
+
+/*!
+ Returns the lightness color component of this color.
+
+ \sa lightnessF(), getHsl()
+*/
+int QColor::lightness() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().lightness();
+ return ct.ahsl.lightness >> 8;
+}
+
+/*!
+ Returns the hue color component of this color.
+
+ \sa hue(), getHslF()
+*/
+qreal QColor::hslHueF() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().hslHueF();
+ return ct.ahsl.hue == USHRT_MAX ? -1.0 : ct.ahsl.hue / 36000.0;
+}
+
+/*!
+ Returns the saturation color component of this color.
+
+ \sa saturationHsl() getHslF()
+*/
+qreal QColor::hslSaturationF() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().hslSaturationF();
+ return ct.ahsl.saturation / qreal(USHRT_MAX);
+}
+
+/*!
+ Returns the lightness color component of this color.
+
+ \sa value() getHslF()
+*/
+qreal QColor::lightnessF() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().lightnessF();
+ return ct.ahsl.lightness / qreal(USHRT_MAX);
+}
+
+/*!
Returns the cyan color component of this color.
\sa cyanF(), getCmyk(), {QColor#The CMYK Color Model}{The CMYK
@@ -1337,6 +1583,53 @@ QColor QColor::toRgb() const
}
break;
}
+ case Hsl:
+ {
+ if (ct.ahsl.saturation == 0 || ct.ahsl.hue == USHRT_MAX) {
+ // achromatic case
+ color.ct.argb.red = color.ct.argb.green = color.ct.argb.blue = ct.ahsl.lightness;
+ } else if (ct.ahsl.lightness == 0) {
+ // lightness 0
+ color.ct.argb.red = color.ct.argb.green = color.ct.argb.blue = 0;
+ } else {
+ // chromatic case
+ const qreal h = ct.ahsl.hue == 36000 ? 0 : ct.ahsl.hue / 36000.;
+ const qreal s = ct.ahsl.saturation / qreal(USHRT_MAX);
+ const qreal l = ct.ahsl.lightness / qreal(USHRT_MAX);
+
+ qreal temp2;
+ if (l < qreal(0.5))
+ temp2 = l * (qreal(1.0) + s);
+ else
+ temp2 = l + s - (l * s);
+
+ const qreal temp1 = (qreal(2.0) * l) - temp2;
+ qreal temp3[3] = { h + (qreal(1.0) / qreal(3.0)),
+ h,
+ h - (qreal(1.0) / qreal(3.0)) };
+
+ for (int i = 0; i != 3; ++i) {
+ if (temp3[i] < qreal(0.0))
+ temp3[i] += qreal(1.0);
+ else if (temp3[i] > qreal(1.0))
+ temp3[i] -= qreal(1.0);
+
+ const qreal sixtemp3 = temp3[i] * qreal(6.0);
+ if (sixtemp3 < qreal(1.0))
+ color.ct.array[i+1] = qRound((temp1 + (temp2 - temp1) * sixtemp3) * USHRT_MAX);
+ else if ((temp3[i] * qreal(2.0)) < qreal(1.0))
+ color.ct.array[i+1] = qRound(temp2 * USHRT_MAX);
+ else if ((temp3[i] * qreal(3.0)) < qreal(2.0))
+ color.ct.array[i+1] = qRound((temp1 + (temp2 -temp1) * (qreal(2.0) /qreal(3.0) - temp3[i]) * qreal(6.0)) * USHRT_MAX);
+ else
+ color.ct.array[i+1] = qRound(temp1 * USHRT_MAX);
+ }
+ color.ct.argb.red = color.ct.argb.red == 1 ? 0 : color.ct.argb.red;
+ color.ct.argb.green = color.ct.argb.green == 1 ? 0 : color.ct.argb.green;
+ color.ct.argb.blue = color.ct.argb.blue == 1 ? 0 : color.ct.argb.blue;
+ }
+ break;
+ }
case Cmyk:
{
const qreal c = ct.acmyk.cyan / qreal(USHRT_MAX);
@@ -1414,6 +1707,62 @@ QColor QColor::toHsv() const
}
/*!
+ Creates and returns an HSL QColor based on this color.
+
+ \sa fromHsl(), convertTo(), isValid()
+*/
+QColor QColor::toHsl() const
+{
+ if (!isValid() || cspec == Hsl)
+ return *this;
+
+ if (cspec != Rgb)
+ return toRgb().toHsl();
+
+ QColor color;
+ color.cspec = Hsl;
+ color.ct.ahsl.alpha = ct.argb.alpha;
+ color.ct.ahsl.pad = 0;
+
+ const qreal r = ct.argb.red / qreal(USHRT_MAX);
+ const qreal g = ct.argb.green / qreal(USHRT_MAX);
+ const qreal b = ct.argb.blue / qreal(USHRT_MAX);
+ const qreal max = Q_MAX_3(r, g, b);
+ const qreal min = Q_MIN_3(r, g, b);
+ const qreal delta = max - min;
+ const qreal delta2 = max + min;
+ const qreal lightness = qreal(0.5) * delta2;
+ color.ct.ahsl.lightness = qRound(lightness * USHRT_MAX);
+ if (qFuzzyIsNull(delta)) {
+ // achromatic case, hue is undefined
+ color.ct.ahsl.hue = 0;
+ color.ct.ahsl.saturation = 0;
+ } else {
+ // chromatic case
+ qreal hue = 0;
+ if (lightness < qreal(0.5))
+ color.ct.ahsl.saturation = qRound((delta / delta2) * USHRT_MAX);
+ else
+ color.ct.ahsl.saturation = qRound((delta / (qreal(2.0) - delta2)) * USHRT_MAX);
+ if (qFuzzyCompare(r, max)) {
+ hue = ((g - b) /delta);
+ } else if (qFuzzyCompare(g, max)) {
+ hue = (2.0 + (b - r) / delta);
+ } else if (qFuzzyCompare(b, max)) {
+ hue = (4.0 + (r - g) / delta);
+ } else {
+ Q_ASSERT_X(false, "QColor::toHsv", "internal error");
+ }
+ hue *= 60.0;
+ if (hue < 0.0)
+ hue += 360.0;
+ color.ct.ahsl.hue = qRound(hue * 100);
+ }
+
+ return color;
+}
+
+/*!
Creates and returns a CMYK QColor based on this color.
\sa fromCmyk(), convertTo(), isValid(), {QColor#The CMYK Color
@@ -1466,6 +1815,8 @@ QColor QColor::convertTo(QColor::Spec colorSpec) const
return toHsv();
case Cmyk:
return toCmyk();
+ case Hsl:
+ return toHsl();
case Invalid:
break;
}
@@ -1627,6 +1978,70 @@ QColor QColor::fromHsvF(qreal h, qreal s, qreal v, qreal a)
}
/*!
+ Static convenience function that returns a QColor constructed from the HSV
+ color values, \a h (hue), \a s (saturation), \a l (lightness), and \a a
+ (alpha-channel, i.e. transparency).
+
+ The value of \a s, \a l, and \a a must all be in the range 0-255; the value
+ of \a h must be in the range 0-359.
+
+ \sa toHsl(), fromHslF(), isValid()
+*/
+QColor QColor::fromHsl(int h, int s, int l, int a)
+{
+ if (((h < 0 || h >= 360) && h != -1)
+ || s < 0 || s > 255
+ || l < 0 || l > 255
+ || a < 0 || a > 255) {
+ qWarning("QColor::fromHsv: HSV parameters out of range");
+ return QColor();
+ }
+
+ QColor color;
+ color.cspec = Hsl;
+ color.ct.ahsl.alpha = a * 0x101;
+ color.ct.ahsl.hue = h == -1 ? USHRT_MAX : (h % 360) * 100;
+ color.ct.ahsl.saturation = s * 0x101;
+ color.ct.ahsl.lightness = l * 0x101;
+ color.ct.ahsl.pad = 0;
+ return color;
+}
+
+/*!
+ \overload
+
+ Static convenience function that returns a QColor constructed from the HSV
+ color values, \a h (hue), \a s (saturation), \a l (lightness), and \a a
+ (alpha-channel, i.e. transparency).
+
+ All the values must be in the range 0.0-1.0.
+
+ \sa toHsl(), fromHsl(), isValid()
+*/
+QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a)
+{
+ if (((h < 0.0 || h > 1.0) && h != -1.0)
+ || (s < 0.0 || s > 1.0)
+ || (l < 0.0 || l > 1.0)
+ || (a < 0.0 || a > 1.0)) {
+ qWarning("QColor::fromHsvF: HSV parameters out of range");
+ return QColor();
+ }
+
+ QColor color;
+ color.cspec = Hsl;
+ color.ct.ahsl.alpha = qRound(a * USHRT_MAX);
+ color.ct.ahsl.hue = (h == -1.0) ? USHRT_MAX : qRound(h * 36000);
+ if (color.ct.ahsl.hue == 36000)
+ color.ct.ahsl.hue = 0;
+ color.ct.ahsl.saturation = qRound(s * USHRT_MAX);
+ color.ct.ahsl.lightness = qRound(l * USHRT_MAX);
+ color.ct.ahsl.pad = 0;
+ return color;
+}
+
+
+/*!
Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the
cyan, magenta, yellow, black, and alpha-channel (transparency) components
of the color's CMYK value.
@@ -1917,14 +2332,26 @@ QColor &QColor::operator=(Qt::GlobalColor color)
*/
bool QColor::operator==(const QColor &color) const
{
- return (cspec == color.cspec
- && ct.argb.alpha == color.ct.argb.alpha
- && ((cspec == QColor::Hsv
- && ((ct.argb.red % 36000) == (color.ct.argb.red % 36000)))
- || (ct.argb.red == color.ct.argb.red))
- && ct.argb.green == color.ct.argb.green
- && ct.argb.blue == color.ct.argb.blue
- && ct.argb.pad == color.ct.argb.pad);
+ if (cspec == Hsl && cspec == color.cspec) {
+ return (ct.argb.alpha == color.ct.argb.alpha
+ && ((((ct.ahsl.hue % 36000) == (color.ct.ahsl.hue % 36000)))
+ || (ct.ahsl.hue == color.ct.ahsl.hue))
+ && (qAbs(ct.ahsl.saturation - color.ct.ahsl.saturation) < 50
+ || ct.ahsl.lightness == 0
+ || color.ct.ahsl.lightness == 0
+ || ct.ahsl.lightness == USHRT_MAX
+ || color.ct.ahsl.lightness == USHRT_MAX)
+ && (qAbs(ct.ahsl.lightness - color.ct.ahsl.lightness)) < 50);
+ } else {
+ return (cspec == color.cspec
+ && ct.argb.alpha == color.ct.argb.alpha
+ && (((cspec == QColor::Hsv)
+ && ((ct.ahsv.hue % 36000) == (color.ct.ahsv.hue % 36000)))
+ || (ct.ahsv.hue == color.ct.ahsv.hue))
+ && ct.argb.green == color.ct.argb.green
+ && ct.argb.blue == color.ct.argb.blue
+ && ct.argb.pad == color.ct.argb.pad);
+ }
}
/*!
@@ -2028,6 +2455,8 @@ QDebug operator<<(QDebug dbg, const QColor &c)
else if (c.spec() == QColor::Cmyk)
dbg.nospace() << "QColor(ACMYK " << c.alphaF() << ", " << c.cyanF() << ", " << c.magentaF() << ", " << c.yellowF() << ", "
<< c.blackF()<< ')';
+ else if (c.spec() == QColor::Hsl)
+ dbg.nospace() << "QColor(AHSL " << c.alphaF() << ", " << c.hslHueF() << ", " << c.hslSaturationF() << ", " << c.lightnessF() << ')';
return dbg.space();
#else
diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h
index 1a59029cf4..a5e521075f 100644
--- a/src/gui/painting/qcolor.h
+++ b/src/gui/painting/qcolor.h
@@ -67,7 +67,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QColor &);
class Q_GUI_EXPORT QColor
{
public:
- enum Spec { Invalid, Rgb, Hsv, Cmyk };
+ enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl };
QColor();
QColor(Qt::GlobalColor color);
@@ -122,10 +122,14 @@ public:
int hue() const; // 0 <= hue < 360
int saturation() const;
+ int hsvHue() const; // 0 <= hue < 360
+ int hsvSaturation() const;
int value() const;
qreal hueF() const; // 0.0 <= hueF < 360.0
qreal saturationF() const;
+ qreal hsvHueF() const; // 0.0 <= hueF < 360.0
+ qreal hsvSaturationF() const;
qreal valueF() const;
void getHsv(int *h, int *s, int *v, int *a = 0) const;
@@ -150,9 +154,24 @@ public:
void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = 0);
void setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0);
+ int hslHue() const; // 0 <= hue < 360
+ int hslSaturation() const;
+ int lightness() const;
+
+ qreal hslHueF() const; // 0.0 <= hueF < 360.0
+ qreal hslSaturationF() const;
+ qreal lightnessF() const;
+
+ void getHsl(int *h, int *s, int *l, int *a = 0) const;
+ void setHsl(int h, int s, int l, int a = 255);
+
+ void getHslF(qreal *h, qreal *s, qreal *l, qreal *a = 0) const;
+ void setHslF(qreal h, qreal s, qreal l, qreal a = 1.0);
+
QColor toRgb() const;
QColor toHsv() const;
QColor toCmyk() const;
+ QColor toHsl() const;
QColor convertTo(Spec colorSpec) const;
@@ -168,6 +187,9 @@ public:
static QColor fromCmyk(int c, int m, int y, int k, int a = 255);
static QColor fromCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0);
+ static QColor fromHsl(int h, int s, int l, int a = 255);
+ static QColor fromHslF(qreal h, qreal s, qreal l, qreal a = 1.0);
+
QColor light(int f = 150) const;
QColor lighter(int f = 150) const;
QColor dark(int f = 200) const;
@@ -234,6 +256,14 @@ private:
ushort yellow;
ushort black;
} acmyk;
+ struct {
+ ushort alpha;
+ ushort hue;
+ ushort saturation;
+ ushort lightness;
+ ushort pad;
+ } ahsl;
+ ushort array[5];
} ct;
friend class QColormap;
diff --git a/tests/auto/qcolor/tst_qcolor.cpp b/tests/auto/qcolor/tst_qcolor.cpp
index bc0901a7b4..b61c98d84a 100644
--- a/tests/auto/qcolor/tst_qcolor.cpp
+++ b/tests/auto/qcolor/tst_qcolor.cpp
@@ -109,6 +109,13 @@ private slots:
void getCmyk();
void setCmyk();
+ void hueHsl();
+ void saturationHsl();
+ void lightness();
+
+ void getHsl();
+ void setHsl();
+
void toRgb_data();
void toRgb();
void toRgbNonDestructive();
@@ -121,11 +128,16 @@ private slots:
void toCmyk();
void toCmykNonDestructive();
+ void toHsl_data();
+ void toHsl();;
+ void toHslNonDestructive();
+
void convertTo();
void fromRgb();
void fromHsv();
void fromCmyk();
+ void fromHsl();
void light();
void dark();
@@ -556,6 +568,10 @@ void tst_QColor::spec()
QColor cmyk = QColor::fromCmyk(0, 0, 0, 0);
QCOMPARE(cmyk.spec(), QColor::Cmyk);
+
+ QColor hsl = QColor::fromHsl(0, 0, 0, 0);
+ QCOMPARE(hsl.spec(), QColor::Hsl);
+
}
void tst_QColor::alpha()
@@ -1044,56 +1060,179 @@ void tst_QColor::setCmyk()
}
}
+void tst_QColor::hueHsl()
+{ DEPENDS_ON(setHsl()); }
+
+void tst_QColor::saturationHsl()
+{ DEPENDS_ON(setHsl()); }
+
+void tst_QColor::lightness()
+{ DEPENDS_ON(setHsl()); }
+
+void tst_QColor::getHsl()
+{ DEPENDS_ON(setHsl()); }
+
+void tst_QColor::setHsl()
+{
+ QColor color;
+
+ for (int A = 0; A <= USHRT_MAX; ++A) {
+ {
+ // 0-255
+ int a = A >> 8;
+ color.setHsl(0, 0, 0, a);
+ QCOMPARE(color.alpha(), a);
+
+ int h, s, l, a2;
+ color.getHsv(&h, &s, &l, &a2);
+ QCOMPARE(a2, a);
+ }
+
+ {
+ // 0.0-1.0
+ qreal a = A / qreal(USHRT_MAX);
+ color.setHslF(0.0, 0.0, 0.0, a); QCOMPARE(color.alphaF(), a);
+
+ qreal h, s, l, a2;
+ color.getHslF(&h, &s, &l, &a2);
+ QCOMPARE(a2, a);
+ }
+ }
+
+ for (int H = 0; H < 36000; ++H) {
+ {
+ // 0-255
+ int h = H / 100;
+
+ color.setHsl(h, 0, 0, 0);
+ QCOMPARE(color.hslHue(), h);
+
+ int h2, s, l, a;
+ color.getHsl(&h2, &s, &l, &a);
+ QCOMPARE(h2, h);
+ }
+
+ {
+ // 0.0-1.0
+ qreal h = H / 36000.0;
+ color.setHslF(h, 0.0, 0.0, 0.0);
+ QCOMPARE(color.hslHueF(), h);
+
+ qreal h2, s, l, a;
+ color.getHslF(&h2, &s, &l, &a);
+ QCOMPARE(h2, h);
+ }
+ }
+
+ for (int S = 0; S <= USHRT_MAX; ++S) {
+ {
+ // 0-255
+ int s = S >> 8;
+ color.setHsl(0, s, 0, 0);
+ QCOMPARE(color.hslSaturation(), s);
+
+ int h, s2, l, a;
+ color.getHsl(&h, &s2, &l, &a);
+ QCOMPARE(s2, s);
+ }
+
+ {
+ // 0.0-1.0
+ qreal s = S / qreal(USHRT_MAX);
+ color.setHslF(0.0, s, 0.0, 0.0);
+ QCOMPARE(color.hslSaturationF(), s);
+
+ qreal h, s2, l, a;
+ color.getHslF(&h, &s2, &l, &a);
+ QCOMPARE(s2, s);
+ }
+ }
+
+ for (int L = 0; L <= USHRT_MAX; ++L) {
+ {
+ // 0-255
+ int l = L >> 8;
+ color.setHsl(0, 0, l, 0);
+ QCOMPARE(color.lightness(), l);
+
+ int h, s, l2, a;
+ color.getHsl(&h, &s, &l2, &a);
+ QCOMPARE(l2, l);
+ }
+
+ {
+ // 0.0-1.0
+ qreal l = L / qreal(USHRT_MAX);
+ color.setHslF(0.0, 0.0, l, 0.0);
+ QCOMPARE(color.lightnessF(), l);
+
+ qreal h, s, l2, a;
+ color.getHslF(&h, &s, &l2, &a);
+ QCOMPARE(l2, l);
+ }
+ }
+}
+
void tst_QColor::toRgb_data()
{
QTest::addColumn<QColor>("expectedColor");
QTest::addColumn<QColor>("hsvColor");
QTest::addColumn<QColor>("cmykColor");
+ QTest::addColumn<QColor>("hslColor");
QTest::newRow("black")
<< QColor::fromRgbF(0.0, 0.0, 0.0)
<< QColor::fromHsvF(-1.0, 0.0, 0.0)
- << QColor::fromCmykF(0.0, 0.0, 0.0, 1.0);
+ << QColor::fromCmykF(0.0, 0.0, 0.0, 1.0)
+ << QColor::fromHslF(-1.0, 0.0, 0.0);
QTest::newRow("white")
<< QColor::fromRgbF(1.0, 1.0, 1.0)
<< QColor::fromHsvF(-1.0, 0.0, 1.0)
- << QColor::fromCmykF(0.0, 0.0, 0.0, 0.0);
+ << QColor::fromCmykF(0.0, 0.0, 0.0, 0.0)
+ << QColor::fromHslF(-1.0, 0.0, 1.0);
QTest::newRow("red")
<< QColor::fromRgbF(1.0, 0.0, 0.0)
<< QColor::fromHsvF(0.0, 1.0, 1.0)
- << QColor::fromCmykF(0.0, 1.0, 1.0, 0.0);
+ << QColor::fromCmykF(0.0, 1.0, 1.0, 0.0)
+ << QColor::fromHslF(0.0, 1.0, 0.5, 1.0);
QTest::newRow("green")
<< QColor::fromRgbF(0.0, 1.0, 0.0)
<< QColor::fromHsvF(0.33333, 1.0, 1.0)
- << QColor::fromCmykF(1.0, 0.0, 1.0, 0.0);
+ << QColor::fromCmykF(1.0, 0.0, 1.0, 0.0)
+ << QColor::fromHslF(0.33333, 1.0, 0.5);
QTest::newRow("blue")
<< QColor::fromRgbF(0.0, 0.0, 1.0)
<< QColor::fromHsvF(0.66667, 1.0, 1.0)
- << QColor::fromCmykF(1.0, 1.0, 0.0, 0.0);
+ << QColor::fromCmykF(1.0, 1.0, 0.0, 0.0)
+ << QColor::fromHslF(0.66667, 1.0, 0.5);
QTest::newRow("cyan")
<< QColor::fromRgbF(0.0, 1.0, 1.0)
<< QColor::fromHsvF(0.5, 1.0, 1.0)
- << QColor::fromCmykF(1.0, 0.0, 0.0, 0.0);
+ << QColor::fromCmykF(1.0, 0.0, 0.0, 0.0)
+ << QColor::fromHslF(0.5, 1.0, 0.5);
QTest::newRow("magenta")
<< QColor::fromRgbF(1.0, 0.0, 1.0)
<< QColor::fromHsvF(0.83333, 1.0, 1.0)
- << QColor::fromCmykF(0.0, 1.0, 0.0, 0.0);
+ << QColor::fromCmykF(0.0, 1.0, 0.0, 0.0)
+ << QColor::fromHslF(0.83333, 1.0, 0.5);
QTest::newRow("yellow")
<< QColor::fromRgbF(1.0, 1.0, 0.0)
<< QColor::fromHsvF(0.16667, 1.0, 1.0)
- << QColor::fromCmykF(0.0, 0.0, 1.0, 0.0);
+ << QColor::fromCmykF(0.0, 0.0, 1.0, 0.0)
+ << QColor::fromHslF(0.16667, 1.0, 0.5);
QTest::newRow("gray")
<< QColor::fromRgbF(0.6431375, 0.6431375, 0.6431375)
<< QColor::fromHsvF(-1.0, 0.0, 0.6431375)
- << QColor::fromCmykF(0.0, 0.0, 0.0, 0.356863);
+ << QColor::fromCmykF(0.0, 0.0, 0.0, 0.356863)
+ << QColor::fromHslF(-1.0, 0.0, 0.6431375);
// ### add colors using the 0-255 functions
}
@@ -1106,8 +1245,11 @@ void tst_QColor::toRgb()
QFETCH(QColor, expectedColor);
QFETCH(QColor, hsvColor);
QFETCH(QColor, cmykColor);
+ QFETCH(QColor, hslColor);
QCOMPARE(hsvColor.toRgb(), expectedColor);
QCOMPARE(cmykColor.toRgb(), expectedColor);
+ QCOMPARE(hslColor.toRgb(), expectedColor);
+
}
void tst_QColor::toHsv_data()
@@ -1115,16 +1257,19 @@ void tst_QColor::toHsv_data()
QTest::addColumn<QColor>("expectedColor");
QTest::addColumn<QColor>("rgbColor");
QTest::addColumn<QColor>("cmykColor");
+ QTest::addColumn<QColor>("hslColor");
QTest::newRow("data0")
<< QColor::fromHsv(300, 255, 255)
<< QColor(255, 0, 255)
- << QColor::fromCmyk(0, 255, 0, 0);
+ << QColor::fromCmyk(0, 255, 0, 0)
+ << QColor::fromHslF(300./360., 1., 0.5, 1.0);
QTest::newRow("data1")
<< QColor::fromHsvF(1., 1., 1., 1.)
<< QColor(255, 0, 0, 255)
- << QColor::fromCmykF(0., 1., 1., 0.);
+ << QColor::fromCmykF(0., 1., 1., 0.)
+ << QColor::fromHsvF(1., 1., 1., 1.);
}
void tst_QColor::toRgbNonDestructive()
@@ -1141,8 +1286,10 @@ void tst_QColor::toHsv()
QFETCH(QColor, expectedColor);
QFETCH(QColor, rgbColor);
QFETCH(QColor, cmykColor);
+ QFETCH(QColor, hslColor);
QCOMPARE(rgbColor.toHsv(), expectedColor);
QCOMPARE(cmykColor.toHsv(), expectedColor);
+ QCOMPARE(hslColor.toHsv(), expectedColor);
}
void tst_QColor::toHsvNonDestructive()
@@ -1156,16 +1303,19 @@ void tst_QColor::toCmyk_data()
QTest::addColumn<QColor>("expectedColor");
QTest::addColumn<QColor>("rgbColor");
QTest::addColumn<QColor>("hsvColor");
+ QTest::addColumn<QColor>("hslColor");
QTest::newRow("data0")
<< QColor::fromCmykF(1.0, 0.0, 0.0, 0.0)
<< QColor(0, 255, 255)
- << QColor::fromHsv(180, 255, 255);
+ << QColor::fromHsv(180, 255, 255)
+ << QColor::fromHslF(180./360., 1., 0.5, 1.0);
QTest::newRow("data1")
<< QColor::fromCmyk(255, 255, 255, 255)
<< QColor::fromRgb(0, 0, 0)
- << QColor::fromRgb(0, 0, 0).toHsv();
+ << QColor::fromRgb(0, 0, 0).toHsv()
+ << QColor::fromRgb(0, 0, 0).toHsl();
}
void tst_QColor::toCmyk()
@@ -1176,8 +1326,10 @@ void tst_QColor::toCmyk()
QFETCH(QColor, expectedColor);
QFETCH(QColor, rgbColor);
QFETCH(QColor, hsvColor);
+ QFETCH(QColor, hslColor);
QCOMPARE(rgbColor.toHsv().toCmyk(), expectedColor);
QCOMPARE(hsvColor.toCmyk(), expectedColor);
+ QCOMPARE(hslColor.toCmyk(), expectedColor);
}
void tst_QColor::toCmykNonDestructive()
@@ -1186,6 +1338,51 @@ void tst_QColor::toCmykNonDestructive()
QCOMPARE(aColor, aColor.toCmyk());
}
+void tst_QColor::toHsl_data()
+{
+ QTest::addColumn<QColor>("expectedColor");
+ QTest::addColumn<QColor>("hsvColor");
+ QTest::addColumn<QColor>("rgbColor");
+ QTest::addColumn<QColor>("cmykColor");
+
+
+ QTest::newRow("data0")
+ << QColor::fromHslF(300./360., 1., 0.5, 1.0)
+ << QColor::fromHsv(300, 255, 255)
+ << QColor(255, 0, 255)
+ << QColor::fromCmyk(0, 255, 0, 0);
+
+ QTest::newRow("data1")
+ << QColor::fromHslF(1., 1., 0.5, 1.0)
+ << QColor::fromHsvF(1., 1., 1., 1.)
+ << QColor(255, 0, 0, 255)
+ << QColor::fromCmykF(0., 1., 1., 0.);
+}
+
+void tst_QColor::toHsl()
+{
+ // invalid should remain invalid
+ QVERIFY(!QColor().toHsl().isValid());
+
+ QFETCH(QColor, expectedColor);
+ QFETCH(QColor, rgbColor);
+ QFETCH(QColor, cmykColor);
+ QFETCH(QColor, hsvColor);
+
+ QCOMPARE(rgbColor.toHsl(), expectedColor);
+ QCOMPARE(cmykColor.toHsl(), expectedColor);
+ QCOMPARE(hsvColor.toHsl(), expectedColor);
+
+}
+
+
+void tst_QColor::toHslNonDestructive()
+{
+ QColor aColor = QColor::fromHslF(0.11, 0.22, 0.33, 0.44);
+ QCOMPARE(aColor, aColor.toHsl());
+}
+
+
void tst_QColor::convertTo()
{
QColor color(Qt::black);
@@ -1199,12 +1396,16 @@ void tst_QColor::convertTo()
QColor cmyk = color.convertTo(QColor::Cmyk);
QVERIFY(cmyk.spec() == QColor::Cmyk);
+ QColor hsl = color.convertTo(QColor::Hsl);
+ QVERIFY(hsl.spec() == QColor::Hsl);
+
QColor invalid = color.convertTo(QColor::Invalid);
QVERIFY(invalid.spec() == QColor::Invalid);
DEPENDS_ON(toRgb());
DEPENDS_ON(toHsv());
DEPENDS_ON(toCmyk());
+ DEPENDS_ON(toHsl());
}
void tst_QColor::fromRgb()
@@ -1216,6 +1417,9 @@ void tst_QColor::fromHsv()
void tst_QColor::fromCmyk()
{ DEPENDS_ON(convertTo()); }
+void tst_QColor::fromHsl()
+{ DEPENDS_ON(convertTo()); }
+
void tst_QColor::light()
{
QColor gray(Qt::gray);