1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12 
13    End User License Agreement: www.juce.com/juce-6-licence
14    Privacy Policy: www.juce.com/juce-privacy-policy
15 
16    Or: You may also use this code under the terms of the GPL v3 (see
17    www.gnu.org/licenses).
18 
19    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21    DISCLAIMED.
22 
23   ==============================================================================
24 */
25 
26 namespace juce
27 {
28 
29 namespace ColourHelpers
30 {
floatToUInt8(float n)31     static uint8 floatToUInt8 (float n) noexcept
32     {
33         return n <= 0.0f ? 0 : (n >= 1.0f ? 255 : (uint8) roundToInt (n * 255.0f));
34     }
35 
getHue(Colour col)36     static float getHue (Colour col)
37     {
38         auto r = (int) col.getRed();
39         auto g = (int) col.getGreen();
40         auto b = (int) col.getBlue();
41 
42         auto hi = jmax (r, g, b);
43         auto lo = jmin (r, g, b);
44 
45         float hue = 0.0f;
46 
47         if (hi > 0)
48         {
49             auto invDiff = 1.0f / (float) (hi - lo);
50 
51             auto red   = (float) (hi - r) * invDiff;
52             auto green = (float) (hi - g) * invDiff;
53             auto blue  = (float) (hi - b) * invDiff;
54 
55             if      (r == hi)  hue = blue - green;
56             else if (g == hi)  hue = 2.0f + red - blue;
57             else               hue = 4.0f + green - red;
58 
59             hue *= 1.0f / 6.0f;
60 
61             if (hue < 0.0f)
62                 hue += 1.0f;
63         }
64 
65         return hue;
66     }
67 
68     //==============================================================================
69     struct HSL
70     {
HSLjuce::ColourHelpers::HSL71         HSL (Colour col) noexcept
72         {
73             auto r = (int) col.getRed();
74             auto g = (int) col.getGreen();
75             auto b = (int) col.getBlue();
76 
77             auto hi = jmax (r, g, b);
78             auto lo = jmin (r, g, b);
79 
80             if (hi > 0)
81             {
82                 lightness = ((float) (hi + lo) / 2.0f) / 255.0f;
83 
84                 if (lightness > 0.0f)
85                     hue = getHue (col);
86 
87                 saturation = (float) (hi - lo) / (1.0f - std::abs ((2.0f * lightness) - 1.0f));
88             }
89         }
90 
toColourjuce::ColourHelpers::HSL91         Colour toColour (Colour original) const noexcept
92         {
93             return Colour::fromHSL (hue, saturation, lightness, original.getAlpha());
94         }
95 
toRGBjuce::ColourHelpers::HSL96         static PixelARGB toRGB (float h, float s, float l, uint8 alpha) noexcept
97         {
98             auto v = l < 0.5f ? l * (1.0f + s) : l + s - (l * s);
99 
100             if (approximatelyEqual (v, 0.0f))
101                 return PixelARGB (alpha, 0, 0, 0);
102 
103             auto min = (2.0f * l) - v;
104             auto sv = (v - min) / v;
105 
106             h = ((h - std::floor (h)) * 360.0f) / 60.0f;
107             auto f = h - std::floor (h);
108             auto vsf = v * sv * f;
109             auto mid1 = min + vsf;
110             auto mid2 = v - vsf;
111 
112             if      (h < 1.0f)  return PixelARGB (alpha, floatToUInt8 (v),    floatToUInt8 (mid1), floatToUInt8 (min));
113             else if (h < 2.0f)  return PixelARGB (alpha, floatToUInt8 (mid2), floatToUInt8 (v),    floatToUInt8 (min));
114             else if (h < 3.0f)  return PixelARGB (alpha, floatToUInt8 (min),  floatToUInt8 (v),    floatToUInt8 (mid1));
115             else if (h < 4.0f)  return PixelARGB (alpha, floatToUInt8 (min),  floatToUInt8 (mid2), floatToUInt8 (v));
116             else if (h < 5.0f)  return PixelARGB (alpha, floatToUInt8 (mid1), floatToUInt8 (min),  floatToUInt8 (v));
117             else if (h < 6.0f)  return PixelARGB (alpha, floatToUInt8 (v),    floatToUInt8 (min),  floatToUInt8 (mid2));
118 
119             return PixelARGB (alpha, 0, 0, 0);
120         }
121 
122         float hue = 0.0f, saturation = 0.0f, lightness = 0.0f;
123     };
124 
125     //==============================================================================
126     struct HSB
127     {
HSBjuce::ColourHelpers::HSB128         HSB (Colour col) noexcept
129         {
130             auto r = (int) col.getRed();
131             auto g = (int) col.getGreen();
132             auto b = (int) col.getBlue();
133 
134             auto hi = jmax (r, g, b);
135             auto lo = jmin (r, g, b);
136 
137             if (hi > 0)
138             {
139                 saturation = (float) (hi - lo) / (float) hi;
140 
141                 if (saturation > 0.0f)
142                     hue = getHue (col);
143 
144                 brightness = (float) hi / 255.0f;
145             }
146         }
147 
toColourjuce::ColourHelpers::HSB148         Colour toColour (Colour original) const noexcept
149         {
150             return Colour (hue, saturation, brightness, original.getAlpha());
151         }
152 
toRGBjuce::ColourHelpers::HSB153         static PixelARGB toRGB (float h, float s, float v, uint8 alpha) noexcept
154         {
155             v = jlimit (0.0f, 255.0f, v * 255.0f);
156             auto intV = (uint8) roundToInt (v);
157 
158             if (s <= 0)
159                 return PixelARGB (alpha, intV, intV, intV);
160 
161             s = jmin (1.0f, s);
162             h = ((h - std::floor (h)) * 360.0f) / 60.0f;
163             auto f = h - std::floor (h);
164             auto x = (uint8) roundToInt (v * (1.0f - s));
165 
166             if (h < 1.0f)   return PixelARGB (alpha, intV,    (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))), x);
167             if (h < 2.0f)   return PixelARGB (alpha,          (uint8) roundToInt (v * (1.0f - s * f)), intV, x);
168             if (h < 3.0f)   return PixelARGB (alpha, x, intV, (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))));
169             if (h < 4.0f)   return PixelARGB (alpha, x,       (uint8) roundToInt (v * (1.0f - s * f)), intV);
170             if (h < 5.0f)   return PixelARGB (alpha,          (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))), x, intV);
171             return                 PixelARGB (alpha, intV, x, (uint8) roundToInt (v * (1.0f - s * f)));
172         }
173 
174         float hue = 0.0f, saturation = 0.0f, brightness = 0.0f;
175     };
176 
177     //==============================================================================
178     struct YIQ
179     {
YIQjuce::ColourHelpers::YIQ180         YIQ (Colour c) noexcept
181         {
182             auto r = c.getFloatRed();
183             auto g = c.getFloatGreen();
184             auto b = c.getFloatBlue();
185 
186             y = 0.2999f * r + 0.5870f * g + 0.1140f * b;
187             i = 0.5957f * r - 0.2744f * g - 0.3212f * b;
188             q = 0.2114f * r - 0.5225f * g - 0.3113f * b;
189             alpha = c.getFloatAlpha();
190         }
191 
toColourjuce::ColourHelpers::YIQ192         Colour toColour() const noexcept
193         {
194             return Colour::fromFloatRGBA (y + 0.9563f * i + 0.6210f * q,
195                                           y - 0.2721f * i - 0.6474f * q,
196                                           y - 1.1070f * i + 1.7046f * q,
197                                           alpha);
198         }
199 
200         float y = 0.0f, i = 0.0f, q = 0.0f, alpha = 0.0f;
201     };
202 }
203 
204 //==============================================================================
operator ==(const Colour & other) const205 bool Colour::operator== (const Colour& other) const noexcept    { return argb.getNativeARGB() == other.argb.getNativeARGB(); }
operator !=(const Colour & other) const206 bool Colour::operator!= (const Colour& other) const noexcept    { return argb.getNativeARGB() != other.argb.getNativeARGB(); }
207 
208 //==============================================================================
Colour(uint32 col)209 Colour::Colour (uint32 col) noexcept
210     : argb (static_cast<uint8> ((col >> 24) & 0xff),
211             static_cast<uint8> ((col >> 16) & 0xff),
212             static_cast<uint8> ((col >> 8) & 0xff),
213             static_cast<uint8> (col & 0xff))
214 {
215 }
216 
Colour(uint8 red,uint8 green,uint8 blue)217 Colour::Colour (uint8 red, uint8 green, uint8 blue) noexcept
218 {
219     argb.setARGB (0xff, red, green, blue);
220 }
221 
fromRGB(uint8 red,uint8 green,uint8 blue)222 Colour Colour::fromRGB (uint8 red, uint8 green, uint8 blue) noexcept
223 {
224     return Colour (red, green, blue);
225 }
226 
Colour(uint8 red,uint8 green,uint8 blue,uint8 alpha)227 Colour::Colour (uint8 red, uint8 green, uint8 blue, uint8 alpha) noexcept
228 {
229     argb.setARGB (alpha, red, green, blue);
230 }
231 
fromRGBA(uint8 red,uint8 green,uint8 blue,uint8 alpha)232 Colour Colour::fromRGBA (uint8 red, uint8 green, uint8 blue, uint8 alpha) noexcept
233 {
234     return Colour (red, green, blue, alpha);
235 }
236 
Colour(uint8 red,uint8 green,uint8 blue,float alpha)237 Colour::Colour (uint8 red, uint8 green, uint8 blue, float alpha) noexcept
238 {
239     argb.setARGB (ColourHelpers::floatToUInt8 (alpha), red, green, blue);
240 }
241 
fromFloatRGBA(float red,float green,float blue,float alpha)242 Colour Colour::fromFloatRGBA (float red, float green, float blue, float alpha) noexcept
243 {
244     return Colour (ColourHelpers::floatToUInt8 (red),
245                    ColourHelpers::floatToUInt8 (green),
246                    ColourHelpers::floatToUInt8 (blue), alpha);
247 }
248 
Colour(float hue,float saturation,float brightness,float alpha)249 Colour::Colour (float hue, float saturation, float brightness, float alpha) noexcept
250     : argb (ColourHelpers::HSB::toRGB (hue, saturation, brightness, ColourHelpers::floatToUInt8 (alpha)))
251 {
252 }
253 
fromHSV(float hue,float saturation,float brightness,float alpha)254 Colour Colour::fromHSV (float hue, float saturation, float brightness, float alpha) noexcept
255 {
256     return Colour (hue, saturation, brightness, alpha);
257 }
258 
fromHSL(float hue,float saturation,float lightness,float alpha)259 Colour Colour::fromHSL (float hue, float saturation, float lightness, float alpha) noexcept
260 {
261     Colour hslColour;
262     hslColour.argb = ColourHelpers::HSL::toRGB (hue, saturation, lightness, ColourHelpers::floatToUInt8 (alpha));
263 
264     return hslColour;
265 }
266 
Colour(float hue,float saturation,float brightness,uint8 alpha)267 Colour::Colour (float hue, float saturation, float brightness, uint8 alpha) noexcept
268     : argb (ColourHelpers::HSB::toRGB (hue, saturation, brightness, alpha))
269 {
270 }
271 
Colour(PixelARGB argb_)272 Colour::Colour (PixelARGB argb_) noexcept
273     : argb (argb_)
274 {
275 }
276 
Colour(PixelRGB rgb)277 Colour::Colour (PixelRGB rgb) noexcept
278     : argb (Colour (rgb.getInARGBMaskOrder()).argb)
279 {
280 }
281 
Colour(PixelAlpha alpha)282 Colour::Colour (PixelAlpha alpha) noexcept
283     : argb (Colour (alpha.getInARGBMaskOrder()).argb)
284 {
285 }
286 
287 //==============================================================================
getPixelARGB() const288 const PixelARGB Colour::getPixelARGB() const noexcept
289 {
290     PixelARGB p (argb);
291     p.premultiply();
292     return p;
293 }
294 
getARGB() const295 uint32 Colour::getARGB() const noexcept
296 {
297     return argb.getInARGBMaskOrder();
298 }
299 
300 //==============================================================================
isTransparent() const301 bool Colour::isTransparent() const noexcept
302 {
303     return getAlpha() == 0;
304 }
305 
isOpaque() const306 bool Colour::isOpaque() const noexcept
307 {
308     return getAlpha() == 0xff;
309 }
310 
withAlpha(uint8 newAlpha) const311 Colour Colour::withAlpha (uint8 newAlpha) const noexcept
312 {
313     PixelARGB newCol (argb);
314     newCol.setAlpha (newAlpha);
315     return Colour (newCol);
316 }
317 
withAlpha(float newAlpha) const318 Colour Colour::withAlpha (float newAlpha) const noexcept
319 {
320     jassert (newAlpha >= 0 && newAlpha <= 1.0f);
321 
322     PixelARGB newCol (argb);
323     newCol.setAlpha (ColourHelpers::floatToUInt8 (newAlpha));
324     return Colour (newCol);
325 }
326 
withMultipliedAlpha(float alphaMultiplier) const327 Colour Colour::withMultipliedAlpha (float alphaMultiplier) const noexcept
328 {
329     jassert (alphaMultiplier >= 0);
330 
331     PixelARGB newCol (argb);
332     newCol.setAlpha ((uint8) jmin (0xff, roundToInt (alphaMultiplier * newCol.getAlpha())));
333     return Colour (newCol);
334 }
335 
336 //==============================================================================
overlaidWith(Colour src) const337 Colour Colour::overlaidWith (Colour src) const noexcept
338 {
339     auto destAlpha = getAlpha();
340 
341     if (destAlpha <= 0)
342         return src;
343 
344     auto invA = 0xff - (int) src.getAlpha();
345     auto resA = 0xff - (((0xff - destAlpha) * invA) >> 8);
346 
347     if (resA <= 0)
348         return *this;
349 
350     auto da = (invA * destAlpha) / resA;
351 
352     return Colour ((uint8) (src.getRed()   + ((((int) getRed()   - src.getRed())   * da) >> 8)),
353                    (uint8) (src.getGreen() + ((((int) getGreen() - src.getGreen()) * da) >> 8)),
354                    (uint8) (src.getBlue()  + ((((int) getBlue()  - src.getBlue())  * da) >> 8)),
355                    (uint8) resA);
356 }
357 
interpolatedWith(Colour other,float proportionOfOther) const358 Colour Colour::interpolatedWith (Colour other, float proportionOfOther) const noexcept
359 {
360     if (proportionOfOther <= 0)
361         return *this;
362 
363     if (proportionOfOther >= 1.0f)
364         return other;
365 
366     PixelARGB c1 (getPixelARGB());
367     PixelARGB c2 (other.getPixelARGB());
368     c1.tween (c2, (uint32) roundToInt (proportionOfOther * 255.0f));
369     c1.unpremultiply();
370 
371     return Colour (c1);
372 }
373 
374 //==============================================================================
getFloatRed() const375 float Colour::getFloatRed() const noexcept      { return getRed()   / 255.0f; }
getFloatGreen() const376 float Colour::getFloatGreen() const noexcept    { return getGreen() / 255.0f; }
getFloatBlue() const377 float Colour::getFloatBlue() const noexcept     { return getBlue()  / 255.0f; }
getFloatAlpha() const378 float Colour::getFloatAlpha() const noexcept    { return getAlpha() / 255.0f; }
379 
380 //==============================================================================
getHSB(float & h,float & s,float & v) const381 void Colour::getHSB (float& h, float& s, float& v) const noexcept
382 {
383     ColourHelpers::HSB hsb (*this);
384     h = hsb.hue;
385     s = hsb.saturation;
386     v = hsb.brightness;
387 }
388 
getHSL(float & h,float & s,float & l) const389 void Colour::getHSL (float& h, float& s, float& l) const noexcept
390 {
391     ColourHelpers::HSL hsl (*this);
392     h = hsl.hue;
393     s = hsl.saturation;
394     l = hsl.lightness;
395 }
396 
getHue() const397 float Colour::getHue() const noexcept           { return ColourHelpers::HSB (*this).hue; }
getSaturation() const398 float Colour::getSaturation() const noexcept    { return ColourHelpers::HSB (*this).saturation; }
getBrightness() const399 float Colour::getBrightness() const noexcept    { return ColourHelpers::HSB (*this).brightness; }
400 
getSaturationHSL() const401 float Colour::getSaturationHSL() const noexcept { return ColourHelpers::HSL (*this).saturation; }
getLightness() const402 float Colour::getLightness() const noexcept     { return ColourHelpers::HSL (*this).lightness; }
403 
withHue(float h) const404 Colour Colour::withHue (float h) const noexcept          { ColourHelpers::HSB hsb (*this); hsb.hue = h;        return hsb.toColour (*this); }
withSaturation(float s) const405 Colour Colour::withSaturation (float s) const noexcept   { ColourHelpers::HSB hsb (*this); hsb.saturation = s; return hsb.toColour (*this); }
withBrightness(float v) const406 Colour Colour::withBrightness (float v) const noexcept   { ColourHelpers::HSB hsb (*this); hsb.brightness = v; return hsb.toColour (*this); }
407 
withSaturationHSL(float s) const408 Colour Colour::withSaturationHSL (float s) const noexcept { ColourHelpers::HSL hsl (*this); hsl.saturation = s; return hsl.toColour (*this); }
withLightness(float l) const409 Colour Colour::withLightness (float l) const noexcept     { ColourHelpers::HSL hsl (*this); hsl.lightness = l;  return hsl.toColour (*this); }
410 
getPerceivedBrightness() const411 float Colour::getPerceivedBrightness() const noexcept
412 {
413     return std::sqrt (0.241f * square (getFloatRed())
414                     + 0.691f * square (getFloatGreen())
415                     + 0.068f * square (getFloatBlue()));
416 }
417 
418 //==============================================================================
withRotatedHue(float amountToRotate) const419 Colour Colour::withRotatedHue (float amountToRotate) const noexcept
420 {
421     ColourHelpers::HSB hsb (*this);
422     hsb.hue += amountToRotate;
423     return hsb.toColour (*this);
424 }
425 
withMultipliedSaturation(float amount) const426 Colour Colour::withMultipliedSaturation (float amount) const noexcept
427 {
428     ColourHelpers::HSB hsb (*this);
429     hsb.saturation = jmin (1.0f, hsb.saturation * amount);
430     return hsb.toColour (*this);
431 }
432 
withMultipliedSaturationHSL(float amount) const433 Colour Colour::withMultipliedSaturationHSL (float amount) const noexcept
434 {
435     ColourHelpers::HSL hsl (*this);
436     hsl.saturation = jmin (1.0f, hsl.saturation * amount);
437     return hsl.toColour (*this);
438 }
439 
withMultipliedBrightness(float amount) const440 Colour Colour::withMultipliedBrightness (float amount) const noexcept
441 {
442     ColourHelpers::HSB hsb (*this);
443     hsb.brightness = jmin (1.0f, hsb.brightness * amount);
444     return hsb.toColour (*this);
445 }
446 
withMultipliedLightness(float amount) const447 Colour Colour::withMultipliedLightness (float amount) const noexcept
448 {
449     ColourHelpers::HSL hsl (*this);
450     hsl.lightness = jmin (1.0f, hsl.lightness * amount);
451     return hsl.toColour (*this);
452 }
453 
454 //==============================================================================
brighter(float amount) const455 Colour Colour::brighter (float amount) const noexcept
456 {
457     amount = 1.0f / (1.0f + amount);
458 
459     return Colour ((uint8) (255 - (amount * (255 - getRed()))),
460                    (uint8) (255 - (amount * (255 - getGreen()))),
461                    (uint8) (255 - (amount * (255 - getBlue()))),
462                    getAlpha());
463 }
464 
darker(float amount) const465 Colour Colour::darker (float amount) const noexcept
466 {
467     amount = 1.0f / (1.0f + amount);
468 
469     return Colour ((uint8) (amount * getRed()),
470                    (uint8) (amount * getGreen()),
471                    (uint8) (amount * getBlue()),
472                    getAlpha());
473 }
474 
475 //==============================================================================
greyLevel(float brightness)476 Colour Colour::greyLevel (float brightness) noexcept
477 {
478     auto level = ColourHelpers::floatToUInt8 (brightness);
479     return Colour (level, level, level);
480 }
481 
482 //==============================================================================
contrasting(float amount) const483 Colour Colour::contrasting (float amount) const noexcept
484 {
485    return overlaidWith ((getPerceivedBrightness() >= 0.5f
486                            ? Colours::black
487                            : Colours::white).withAlpha (amount));
488 }
489 
contrasting(Colour target,float minContrast) const490 Colour Colour::contrasting (Colour target, float minContrast) const noexcept
491 {
492     ColourHelpers::YIQ bg (*this);
493     ColourHelpers::YIQ fg (target);
494 
495     if (std::abs (bg.y - fg.y) >= minContrast)
496         return target;
497 
498     auto y1 = jmax (0.0f, bg.y - minContrast);
499     auto y2 = jmin (1.0f, bg.y + minContrast);
500     fg.y = (std::abs (y1 - bg.y) > std::abs (y2 - bg.y)) ? y1 : y2;
501 
502     return fg.toColour();
503 }
504 
contrasting(Colour colour1,Colour colour2)505 Colour Colour::contrasting (Colour colour1,
506                             Colour colour2) noexcept
507 {
508     auto b1 = colour1.getPerceivedBrightness();
509     auto b2 = colour2.getPerceivedBrightness();
510     float best = 0.0f, bestDist = 0.0f;
511 
512     for (float i = 0.0f; i < 1.0f; i += 0.02f)
513     {
514         auto d1 = std::abs (i - b1);
515         auto d2 = std::abs (i - b2);
516         auto dist = jmin (d1, d2, 1.0f - d1, 1.0f - d2);
517 
518         if (dist > bestDist)
519         {
520             best = i;
521             bestDist = dist;
522         }
523     }
524 
525     return colour1.overlaidWith (colour2.withMultipliedAlpha (0.5f))
526                   .withBrightness (best);
527 }
528 
529 //==============================================================================
toString() const530 String Colour::toString() const
531 {
532     return String::toHexString ((int) argb.getInARGBMaskOrder());
533 }
534 
fromString(StringRef encodedColourString)535 Colour Colour::fromString (StringRef encodedColourString)
536 {
537     return Colour ((uint32) CharacterFunctions::HexParser<int>::parse (encodedColourString.text));
538 }
539 
toDisplayString(const bool includeAlphaValue) const540 String Colour::toDisplayString (const bool includeAlphaValue) const
541 {
542     return String::toHexString ((int) (argb.getInARGBMaskOrder() & (includeAlphaValue ? 0xffffffff : 0xffffff)))
543                   .paddedLeft ('0', includeAlphaValue ? 8 : 6)
544                   .toUpperCase();
545 }
546 
547 
548 //==============================================================================
549 //==============================================================================
550 #if JUCE_UNIT_TESTS
551 
552 class ColourTests  : public UnitTest
553 {
554 public:
ColourTests()555     ColourTests()
556         : UnitTest ("Colour", UnitTestCategories::graphics)
557     {}
558 
runTest()559     void runTest() override
560     {
561         auto testColour = [this] (Colour colour,
562                                   uint8 expectedRed, uint8 expectedGreen, uint8 expectedBlue,
563                                   uint8 expectedAlpha = 255, float expectedFloatAlpha = 1.0f)
564         {
565             expectEquals (colour.getRed(),        expectedRed);
566             expectEquals (colour.getGreen(),      expectedGreen);
567             expectEquals (colour.getBlue(),       expectedBlue);
568             expectEquals (colour.getAlpha(),      expectedAlpha);
569             expectEquals (colour.getFloatAlpha(), expectedFloatAlpha);
570         };
571 
572         beginTest ("Constructors");
573         {
574             Colour c1;
575             testColour (c1, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
576 
577             Colour c2 ((uint32) 0);
578             testColour (c2, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
579 
580             Colour c3 ((uint32) 0xffffffff);
581             testColour (c3, (uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
582 
583             Colour c4 (0, 0, 0);
584             testColour (c4, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 255, 1.0f);
585 
586             Colour c5 (255, 255, 255);
587             testColour (c5, (uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
588 
589             Colour c6 ((uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0);
590             testColour (c6, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
591 
592             Colour c7 ((uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255);
593             testColour (c7, (uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
594 
595             Colour c8 ((uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
596             testColour (c8, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
597 
598             Colour c9 ((uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
599             testColour (c9, (uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
600         }
601 
602         beginTest ("HSV");
603         {
604             // black
605             testColour (Colour::fromHSV (0.0f, 0.0f, 0.0f, 1.0f), 0, 0, 0);
606             // white
607             testColour (Colour::fromHSV (0.0f, 0.0f, 1.0f, 1.0f), 255, 255, 255);
608             // red
609             testColour (Colour::fromHSV (0.0f, 1.0f, 1.0f, 1.0f), 255, 0, 0);
610             testColour (Colour::fromHSV (1.0f, 1.0f, 1.0f, 1.0f), 255, 0, 0);
611             // lime
612             testColour (Colour::fromHSV (120 / 360.0f, 1.0f, 1.0f, 1.0f), 0, 255, 0);
613             // blue
614             testColour (Colour::fromHSV (240 / 360.0f, 1.0f, 1.0f, 1.0f), 0, 0, 255);
615             // yellow
616             testColour (Colour::fromHSV (60 / 360.0f, 1.0f, 1.0f, 1.0f), 255, 255, 0);
617             // cyan
618             testColour (Colour::fromHSV (180 / 360.0f, 1.0f, 1.0f, 1.0f), 0, 255, 255);
619             // magenta
620             testColour (Colour::fromHSV (300 / 360.0f, 1.0f, 1.0f, 1.0f), 255, 0, 255);
621             // silver
622             testColour (Colour::fromHSV (0.0f, 0.0f, 0.75f, 1.0f), 191, 191, 191);
623             // grey
624             testColour (Colour::fromHSV (0.0f, 0.0f, 0.5f, 1.0f), 128, 128, 128);
625             // maroon
626             testColour (Colour::fromHSV (0.0f, 1.0f, 0.5f, 1.0f), 128, 0, 0);
627             // olive
628             testColour (Colour::fromHSV (60 / 360.0f, 1.0f, 0.5f, 1.0f), 128, 128, 0);
629             // green
630             testColour (Colour::fromHSV (120 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 128, 0);
631             // purple
632             testColour (Colour::fromHSV (300 / 360.0f, 1.0f, 0.5f, 1.0f), 128, 0, 128);
633             // teal
634             testColour (Colour::fromHSV (180 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 128, 128);
635             // navy
636             testColour (Colour::fromHSV (240 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 0, 128);
637         }
638 
639         beginTest ("HSL");
640         {
641             // black
642             testColour (Colour::fromHSL (0.0f, 0.0f, 0.0f, 1.0f), 0, 0, 0);
643             // white
644             testColour (Colour::fromHSL (0.0f, 0.0f, 1.0f, 1.0f), 255, 255, 255);
645             // red
646             testColour (Colour::fromHSL (0.0f, 1.0f, 0.5f, 1.0f), 255, 0, 0);
647             testColour (Colour::fromHSL (1.0f, 1.0f, 0.5f, 1.0f), 255, 0, 0);
648             // lime
649             testColour (Colour::fromHSL (120 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 255, 0);
650             // blue
651             testColour (Colour::fromHSL (240 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 0, 255);
652             // yellow
653             testColour (Colour::fromHSL (60 / 360.0f, 1.0f, 0.5f, 1.0f), 255, 255, 0);
654             // cyan
655             testColour (Colour::fromHSL (180 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 255, 255);
656             // magenta
657             testColour (Colour::fromHSL (300 / 360.0f, 1.0f, 0.5f, 1.0f), 255, 0, 255);
658             // silver
659             testColour (Colour::fromHSL (0.0f, 0.0f, 0.75f, 1.0f), 191, 191, 191);
660             // grey
661             testColour (Colour::fromHSL (0.0f, 0.0f, 0.5f, 1.0f), 128, 128, 128);
662             // maroon
663             testColour (Colour::fromHSL (0.0f, 1.0f, 0.25f, 1.0f), 128, 0, 0);
664             // olive
665             testColour (Colour::fromHSL (60 / 360.0f, 1.0f, 0.25f, 1.0f), 128, 128, 0);
666             // green
667             testColour (Colour::fromHSL (120 / 360.0f, 1.0f, 0.25f, 1.0f), 0, 128, 0);
668             // purple
669             testColour (Colour::fromHSL (300 / 360.0f, 1.0f, 0.25f, 1.0f), 128, 0, 128);
670             // teal
671             testColour (Colour::fromHSL (180 / 360.0f, 1.0f, 0.25f, 1.0f), 0, 128, 128);
672             // navy
673             testColour (Colour::fromHSL (240 / 360.0f, 1.0f, 0.25f, 1.0f), 0, 0, 128);
674         }
675 
676         beginTest ("Modifiers");
677         {
678             Colour red (255, 0, 0);
679             testColour (red, 255, 0, 0);
680 
681             testColour (red.withHue (120.0f / 360.0f), 0, 255, 0);
682             testColour (red.withSaturation (0.5f), 255, 128, 128);
683             testColour (red.withSaturationHSL (0.5f), 191, 64, 64);
684             testColour (red.withBrightness (0.5f), 128, 0, 0);
685             testColour (red.withLightness (1.0f), 255, 255, 255);
686             testColour (red.withRotatedHue (120.0f / 360.0f), 0, 255, 0);
687             testColour (red.withRotatedHue (480.0f / 360.0f), 0, 255, 0);
688             testColour (red.withRotatedHue (-240.0f / 360.0f), 0, 255, 0);
689             testColour (red.withRotatedHue (-600.0f / 360.0f), 0, 255, 0);
690             testColour (red.withMultipliedSaturation (0.0f), 255, 255, 255);
691             testColour (red.withMultipliedSaturationHSL (0.0f), 128, 128, 128);
692             testColour (red.withMultipliedBrightness (0.5f), 128, 0, 0);
693             testColour (red.withMultipliedLightness (2.0f), 255, 255, 255);
694         }
695     }
696 };
697 
698 static ColourTests colourTests;
699 
700 #endif
701 
702 } // namespace juce
703