diff options
-rw-r--r-- | src/gui/painting/qcolor.cpp | 453 | ||||
-rw-r--r-- | src/gui/painting/qcolor.h | 32 | ||||
-rw-r--r-- | tests/auto/qcolor/tst_qcolor.cpp | 230 |
3 files changed, 689 insertions, 26 deletions
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 4e93f04..ef884bd 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 1a59029..a5e5210 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 bc0901a..b61c98d 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); |