The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

716 lines
25KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For this technical preview, this file is not subject to commercial licensing.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. namespace juce
  14. {
  15. namespace ColourHelpers
  16. {
  17. static uint8 floatToUInt8 (float n) noexcept
  18. {
  19. return n <= 0.0f ? 0 : (n >= 1.0f ? 255 : (uint8) roundToInt (n * 255.0f));
  20. }
  21. static float getHue (Colour col)
  22. {
  23. auto r = (int) col.getRed();
  24. auto g = (int) col.getGreen();
  25. auto b = (int) col.getBlue();
  26. auto hi = jmax (r, g, b);
  27. auto lo = jmin (r, g, b);
  28. float hue = 0.0f;
  29. if (hi > 0)
  30. {
  31. auto invDiff = 1.0f / (hi - lo);
  32. auto red = (hi - r) * invDiff;
  33. auto green = (hi - g) * invDiff;
  34. auto blue = (hi - b) * invDiff;
  35. if (r == hi) hue = blue - green;
  36. else if (g == hi) hue = 2.0f + red - blue;
  37. else hue = 4.0f + green - red;
  38. hue *= 1.0f / 6.0f;
  39. if (hue < 0.0f)
  40. hue += 1.0f;
  41. }
  42. return hue;
  43. }
  44. //==============================================================================
  45. struct HSL
  46. {
  47. HSL (Colour col) noexcept
  48. {
  49. auto r = (int) col.getRed();
  50. auto g = (int) col.getGreen();
  51. auto b = (int) col.getBlue();
  52. auto hi = jmax (r, g, b);
  53. auto lo = jmin (r, g, b);
  54. if (hi > 0)
  55. {
  56. lightness = ((hi + lo) / 2.0f) / 255.0f;
  57. if (lightness > 0.0f)
  58. hue = getHue (col);
  59. saturation = (hi - lo) / (1.0f - std::abs ((2.0f * lightness) - 1.0f));
  60. }
  61. }
  62. Colour toColour (Colour original) const noexcept
  63. {
  64. return Colour::fromHSL (hue, saturation, lightness, original.getAlpha());
  65. }
  66. static PixelARGB toRGB (float h, float s, float l, uint8 alpha) noexcept
  67. {
  68. auto v = l < 0.5f ? l * (1.0f + s) : l + s - (l * s);
  69. if (approximatelyEqual (v, 0.0f))
  70. return PixelARGB (alpha, 0, 0, 0);
  71. auto min = (2.0f * l) - v;
  72. auto sv = (v - min) / v;
  73. h = jlimit (0.0f, 360.0f, h * 360.0f) / 60.0f;
  74. auto f = h - std::floor (h);
  75. auto vsf = v * sv * f;
  76. auto mid1 = min + vsf;
  77. auto mid2 = v - vsf;
  78. if (h < 1.0f) return PixelARGB (alpha, floatToUInt8 (v), floatToUInt8 (mid1), floatToUInt8 (min));
  79. else if (h < 2.0f) return PixelARGB (alpha, floatToUInt8 (mid2), floatToUInt8 (v), floatToUInt8 (min));
  80. else if (h < 3.0f) return PixelARGB (alpha, floatToUInt8 (min), floatToUInt8 (v), floatToUInt8 (mid1));
  81. else if (h < 4.0f) return PixelARGB (alpha, floatToUInt8 (min), floatToUInt8 (mid2), floatToUInt8 (v));
  82. else if (h < 5.0f) return PixelARGB (alpha, floatToUInt8 (mid1), floatToUInt8 (min), floatToUInt8 (v));
  83. else if (h < 6.0f) return PixelARGB (alpha, floatToUInt8 (v), floatToUInt8 (min), floatToUInt8 (mid2));
  84. return PixelARGB (alpha, 0, 0, 0);
  85. }
  86. float hue = 0.0f, saturation = 0.0f, lightness = 0.0f;
  87. };
  88. //==============================================================================
  89. struct HSB
  90. {
  91. HSB (Colour col) noexcept
  92. {
  93. auto r = (int) col.getRed();
  94. auto g = (int) col.getGreen();
  95. auto b = (int) col.getBlue();
  96. auto hi = jmax (r, g, b);
  97. auto lo = jmin (r, g, b);
  98. if (hi > 0)
  99. {
  100. saturation = (hi - lo) / (float) hi;
  101. if (saturation > 0.0f)
  102. hue = getHue (col);
  103. brightness = hi / 255.0f;
  104. }
  105. }
  106. Colour toColour (Colour original) const noexcept
  107. {
  108. return Colour (hue, saturation, brightness, original.getAlpha());
  109. }
  110. static PixelARGB toRGB (float h, float s, float v, uint8 alpha) noexcept
  111. {
  112. v = jlimit (0.0f, 255.0f, v * 255.0f);
  113. auto intV = (uint8) roundToInt (v);
  114. if (s <= 0)
  115. return PixelARGB (alpha, intV, intV, intV);
  116. s = jmin (1.0f, s);
  117. h = jlimit (0.0f, 360.0f, h * 360.0f) / 60.0f;
  118. auto f = h - std::floor (h);
  119. auto x = (uint8) roundToInt (v * (1.0f - s));
  120. if (h < 1.0f) return PixelARGB (alpha, intV, (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))), x);
  121. if (h < 2.0f) return PixelARGB (alpha, (uint8) roundToInt (v * (1.0f - s * f)), intV, x);
  122. if (h < 3.0f) return PixelARGB (alpha, x, intV, (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))));
  123. if (h < 4.0f) return PixelARGB (alpha, x, (uint8) roundToInt (v * (1.0f - s * f)), intV);
  124. if (h < 5.0f) return PixelARGB (alpha, (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))), x, intV);
  125. return PixelARGB (alpha, intV, x, (uint8) roundToInt (v * (1.0f - s * f)));
  126. }
  127. float hue = 0.0f, saturation = 0.0f, brightness = 0.0f;
  128. };
  129. //==============================================================================
  130. struct YIQ
  131. {
  132. YIQ (Colour c) noexcept
  133. {
  134. auto r = c.getFloatRed();
  135. auto g = c.getFloatGreen();
  136. auto b = c.getFloatBlue();
  137. y = 0.2999f * r + 0.5870f * g + 0.1140f * b;
  138. i = 0.5957f * r - 0.2744f * g - 0.3212f * b;
  139. q = 0.2114f * r - 0.5225f * g - 0.3113f * b;
  140. alpha = c.getFloatAlpha();
  141. }
  142. Colour toColour() const noexcept
  143. {
  144. return Colour::fromFloatRGBA (y + 0.9563f * i + 0.6210f * q,
  145. y - 0.2721f * i - 0.6474f * q,
  146. y - 1.1070f * i + 1.7046f * q,
  147. alpha);
  148. }
  149. float y = 0.0f, i = 0.0f, q = 0.0f, alpha = 0.0f;
  150. };
  151. }
  152. //==============================================================================
  153. bool Colour::operator== (const Colour& other) const noexcept { return argb.getNativeARGB() == other.argb.getNativeARGB(); }
  154. bool Colour::operator!= (const Colour& other) const noexcept { return argb.getNativeARGB() != other.argb.getNativeARGB(); }
  155. //==============================================================================
  156. Colour::Colour (uint32 col) noexcept
  157. : argb (static_cast<uint8> ((col >> 24) & 0xff),
  158. static_cast<uint8> ((col >> 16) & 0xff),
  159. static_cast<uint8> ((col >> 8) & 0xff),
  160. static_cast<uint8> (col & 0xff))
  161. {
  162. }
  163. Colour::Colour (uint8 red, uint8 green, uint8 blue) noexcept
  164. {
  165. argb.setARGB (0xff, red, green, blue);
  166. }
  167. Colour Colour::fromRGB (uint8 red, uint8 green, uint8 blue) noexcept
  168. {
  169. return Colour (red, green, blue);
  170. }
  171. Colour::Colour (uint8 red, uint8 green, uint8 blue, uint8 alpha) noexcept
  172. {
  173. argb.setARGB (alpha, red, green, blue);
  174. }
  175. Colour Colour::fromRGBA (uint8 red, uint8 green, uint8 blue, uint8 alpha) noexcept
  176. {
  177. return Colour (red, green, blue, alpha);
  178. }
  179. Colour::Colour (uint8 red, uint8 green, uint8 blue, float alpha) noexcept
  180. {
  181. argb.setARGB (ColourHelpers::floatToUInt8 (alpha), red, green, blue);
  182. }
  183. Colour Colour::fromFloatRGBA (float red, float green, float blue, float alpha) noexcept
  184. {
  185. return Colour (ColourHelpers::floatToUInt8 (red),
  186. ColourHelpers::floatToUInt8 (green),
  187. ColourHelpers::floatToUInt8 (blue), alpha);
  188. }
  189. Colour::Colour (float hue, float saturation, float brightness, float alpha) noexcept
  190. : argb (ColourHelpers::HSB::toRGB (hue, saturation, brightness, ColourHelpers::floatToUInt8 (alpha)))
  191. {
  192. }
  193. Colour Colour::fromHSV (float hue, float saturation, float brightness, float alpha) noexcept
  194. {
  195. return Colour (hue, saturation, brightness, alpha);
  196. }
  197. Colour Colour::fromHSL (float hue, float saturation, float lightness, float alpha) noexcept
  198. {
  199. Colour hslColour;
  200. hslColour.argb = ColourHelpers::HSL::toRGB (hue, saturation, lightness, ColourHelpers::floatToUInt8 (alpha));
  201. return hslColour;
  202. }
  203. Colour::Colour (float hue, float saturation, float brightness, uint8 alpha) noexcept
  204. : argb (ColourHelpers::HSB::toRGB (hue, saturation, brightness, alpha))
  205. {
  206. }
  207. Colour::Colour (PixelARGB argb_) noexcept
  208. : argb (argb_)
  209. {
  210. }
  211. Colour::Colour (PixelRGB rgb) noexcept
  212. : argb (Colour (rgb.getInARGBMaskOrder()).argb)
  213. {
  214. }
  215. Colour::Colour (PixelAlpha alpha) noexcept
  216. : argb (Colour (alpha.getInARGBMaskOrder()).argb)
  217. {
  218. }
  219. //==============================================================================
  220. const PixelARGB Colour::getPixelARGB() const noexcept
  221. {
  222. PixelARGB p (argb);
  223. p.premultiply();
  224. return p;
  225. }
  226. uint32 Colour::getARGB() const noexcept
  227. {
  228. return argb.getInARGBMaskOrder();
  229. }
  230. //==============================================================================
  231. bool Colour::isTransparent() const noexcept
  232. {
  233. return getAlpha() == 0;
  234. }
  235. bool Colour::isOpaque() const noexcept
  236. {
  237. return getAlpha() == 0xff;
  238. }
  239. Colour Colour::withAlpha (const uint8 newAlpha) const noexcept
  240. {
  241. PixelARGB newCol (argb);
  242. newCol.setAlpha (newAlpha);
  243. return Colour (newCol);
  244. }
  245. Colour Colour::withAlpha (const float newAlpha) const noexcept
  246. {
  247. jassert (newAlpha >= 0 && newAlpha <= 1.0f);
  248. PixelARGB newCol (argb);
  249. newCol.setAlpha (ColourHelpers::floatToUInt8 (newAlpha));
  250. return Colour (newCol);
  251. }
  252. Colour Colour::withMultipliedAlpha (const float alphaMultiplier) const noexcept
  253. {
  254. jassert (alphaMultiplier >= 0);
  255. PixelARGB newCol (argb);
  256. newCol.setAlpha ((uint8) jmin (0xff, roundToInt (alphaMultiplier * newCol.getAlpha())));
  257. return Colour (newCol);
  258. }
  259. //==============================================================================
  260. Colour Colour::overlaidWith (Colour src) const noexcept
  261. {
  262. auto destAlpha = getAlpha();
  263. if (destAlpha <= 0)
  264. return src;
  265. auto invA = 0xff - (int) src.getAlpha();
  266. auto resA = 0xff - (((0xff - destAlpha) * invA) >> 8);
  267. if (resA <= 0)
  268. return *this;
  269. auto da = (invA * destAlpha) / resA;
  270. return Colour ((uint8) (src.getRed() + ((((int) getRed() - src.getRed()) * da) >> 8)),
  271. (uint8) (src.getGreen() + ((((int) getGreen() - src.getGreen()) * da) >> 8)),
  272. (uint8) (src.getBlue() + ((((int) getBlue() - src.getBlue()) * da) >> 8)),
  273. (uint8) resA);
  274. }
  275. Colour Colour::interpolatedWith (Colour other, float proportionOfOther) const noexcept
  276. {
  277. if (proportionOfOther <= 0)
  278. return *this;
  279. if (proportionOfOther >= 1.0f)
  280. return other;
  281. PixelARGB c1 (getPixelARGB());
  282. PixelARGB c2 (other.getPixelARGB());
  283. c1.tween (c2, (uint32) roundToInt (proportionOfOther * 255.0f));
  284. c1.unpremultiply();
  285. return Colour (c1);
  286. }
  287. //==============================================================================
  288. float Colour::getFloatRed() const noexcept { return getRed() / 255.0f; }
  289. float Colour::getFloatGreen() const noexcept { return getGreen() / 255.0f; }
  290. float Colour::getFloatBlue() const noexcept { return getBlue() / 255.0f; }
  291. float Colour::getFloatAlpha() const noexcept { return getAlpha() / 255.0f; }
  292. //==============================================================================
  293. void Colour::getHSB (float& h, float& s, float& v) const noexcept
  294. {
  295. ColourHelpers::HSB hsb (*this);
  296. h = hsb.hue;
  297. s = hsb.saturation;
  298. v = hsb.brightness;
  299. }
  300. void Colour::getHSL (float& h, float& s, float& l) const noexcept
  301. {
  302. ColourHelpers::HSL hsl (*this);
  303. h = hsl.hue;
  304. s = hsl.saturation;
  305. l = hsl.lightness;
  306. }
  307. float Colour::getHue() const noexcept { return ColourHelpers::HSB (*this).hue; }
  308. float Colour::getSaturation() const noexcept { return ColourHelpers::HSB (*this).saturation; }
  309. float Colour::getBrightness() const noexcept { return ColourHelpers::HSB (*this).brightness; }
  310. float Colour::getLightness() const noexcept { return ColourHelpers::HSL (*this).lightness; }
  311. Colour Colour::withHue (float h) const noexcept { ColourHelpers::HSB hsb (*this); hsb.hue = h; return hsb.toColour (*this); }
  312. Colour Colour::withSaturation (float s) const noexcept { ColourHelpers::HSB hsb (*this); hsb.saturation = s; return hsb.toColour (*this); }
  313. Colour Colour::withBrightness (float v) const noexcept { ColourHelpers::HSB hsb (*this); hsb.brightness = v; return hsb.toColour (*this); }
  314. Colour Colour::withLightness (float l) const noexcept { ColourHelpers::HSL hsl (*this); hsl.lightness = l; return hsl.toColour (*this); }
  315. float Colour::getPerceivedBrightness() const noexcept
  316. {
  317. return std::sqrt (0.241f * square (getFloatRed())
  318. + 0.691f * square (getFloatGreen())
  319. + 0.068f * square (getFloatBlue()));
  320. }
  321. //==============================================================================
  322. Colour Colour::withRotatedHue (const float amountToRotate) const noexcept
  323. {
  324. ColourHelpers::HSB hsb (*this);
  325. hsb.hue += amountToRotate;
  326. return hsb.toColour (*this);
  327. }
  328. Colour Colour::withMultipliedSaturation (const float amount) const noexcept
  329. {
  330. ColourHelpers::HSB hsb (*this);
  331. hsb.saturation = jmin (1.0f, hsb.saturation * amount);
  332. return hsb.toColour (*this);
  333. }
  334. Colour Colour::withMultipliedBrightness (const float amount) const noexcept
  335. {
  336. ColourHelpers::HSB hsb (*this);
  337. hsb.brightness = jmin (1.0f, hsb.brightness * amount);
  338. return hsb.toColour (*this);
  339. }
  340. Colour Colour::withMultipliedLightness (const float amount) const noexcept
  341. {
  342. ColourHelpers::HSL hsl (*this);
  343. hsl.lightness = jmin (1.0f, hsl.lightness * amount);
  344. return hsl.toColour (*this);
  345. }
  346. //==============================================================================
  347. Colour Colour::brighter (float amount) const noexcept
  348. {
  349. amount = 1.0f / (1.0f + amount);
  350. return Colour ((uint8) (255 - (amount * (255 - getRed()))),
  351. (uint8) (255 - (amount * (255 - getGreen()))),
  352. (uint8) (255 - (amount * (255 - getBlue()))),
  353. getAlpha());
  354. }
  355. Colour Colour::darker (float amount) const noexcept
  356. {
  357. amount = 1.0f / (1.0f + amount);
  358. return Colour ((uint8) (amount * getRed()),
  359. (uint8) (amount * getGreen()),
  360. (uint8) (amount * getBlue()),
  361. getAlpha());
  362. }
  363. //==============================================================================
  364. Colour Colour::greyLevel (const float brightness) noexcept
  365. {
  366. auto level = ColourHelpers::floatToUInt8 (brightness);
  367. return Colour (level, level, level);
  368. }
  369. //==============================================================================
  370. Colour Colour::contrasting (const float amount) const noexcept
  371. {
  372. return overlaidWith ((getPerceivedBrightness() >= 0.5f
  373. ? Colours::black
  374. : Colours::white).withAlpha (amount));
  375. }
  376. Colour Colour::contrasting (Colour target, float minContrast) const noexcept
  377. {
  378. ColourHelpers::YIQ bg (*this);
  379. ColourHelpers::YIQ fg (target);
  380. if (std::abs (bg.y - fg.y) >= minContrast)
  381. return target;
  382. auto y1 = jmax (0.0f, bg.y - minContrast);
  383. auto y2 = jmin (1.0f, bg.y + minContrast);
  384. fg.y = (std::abs (y1 - bg.y) > std::abs (y2 - bg.y)) ? y1 : y2;
  385. return fg.toColour();
  386. }
  387. Colour Colour::contrasting (Colour colour1,
  388. Colour colour2) noexcept
  389. {
  390. auto b1 = colour1.getPerceivedBrightness();
  391. auto b2 = colour2.getPerceivedBrightness();
  392. float best = 0.0f, bestDist = 0.0f;
  393. for (float i = 0.0f; i < 1.0f; i += 0.02f)
  394. {
  395. auto d1 = std::abs (i - b1);
  396. auto d2 = std::abs (i - b2);
  397. auto dist = jmin (d1, d2, 1.0f - d1, 1.0f - d2);
  398. if (dist > bestDist)
  399. {
  400. best = i;
  401. bestDist = dist;
  402. }
  403. }
  404. return colour1.overlaidWith (colour2.withMultipliedAlpha (0.5f))
  405. .withBrightness (best);
  406. }
  407. //==============================================================================
  408. String Colour::toString() const
  409. {
  410. return String::toHexString ((int) argb.getInARGBMaskOrder());
  411. }
  412. Colour Colour::fromString (StringRef encodedColourString)
  413. {
  414. return Colour ((uint32) CharacterFunctions::HexParser<int>::parse (encodedColourString.text));
  415. }
  416. String Colour::toDisplayString (const bool includeAlphaValue) const
  417. {
  418. return String::toHexString ((int) (argb.getInARGBMaskOrder() & (includeAlphaValue ? 0xffffffff : 0xffffff)))
  419. .paddedLeft ('0', includeAlphaValue ? 8 : 6)
  420. .toUpperCase();
  421. }
  422. //==============================================================================
  423. //==============================================================================
  424. #if JUCE_UNIT_TESTS
  425. class ColourTests : public UnitTest
  426. {
  427. public:
  428. ColourTests()
  429. : UnitTest ("Colour", UnitTestCategories::graphics)
  430. {}
  431. void runTest() override
  432. {
  433. beginTest ("Constructors");
  434. {
  435. Colour c1;
  436. expectEquals (c1.getRed(), (uint8) 0);
  437. expectEquals (c1.getGreen(), (uint8) 0);
  438. expectEquals (c1.getBlue(), (uint8) 0);
  439. expectEquals (c1.getAlpha(), (uint8) 0);
  440. expectEquals (c1.getFloatAlpha(), 0.0f);
  441. Colour c2 ((uint32) 0);
  442. expectEquals (c2.getRed(), (uint8) 0);
  443. expectEquals (c2.getGreen(), (uint8) 0);
  444. expectEquals (c2.getBlue(), (uint8) 0);
  445. expectEquals (c2.getAlpha(), (uint8) 0);
  446. expectEquals (c2.getFloatAlpha(), 0.0f);
  447. Colour c3 ((uint32) 0xffffffff);
  448. expectEquals (c3.getRed(), (uint8) 255);
  449. expectEquals (c3.getGreen(), (uint8) 255);
  450. expectEquals (c3.getBlue(), (uint8) 255);
  451. expectEquals (c3.getAlpha(), (uint8) 255);
  452. expectEquals (c3.getFloatAlpha(), 1.0f);
  453. Colour c4 (0, 0, 0);
  454. expectEquals (c4.getRed(), (uint8) 0);
  455. expectEquals (c4.getGreen(), (uint8) 0);
  456. expectEquals (c4.getBlue(), (uint8) 0);
  457. expectEquals (c4.getAlpha(), (uint8) 255);
  458. expectEquals (c4.getFloatAlpha(), 1.0f);
  459. Colour c5 (255, 255, 255);
  460. expectEquals (c5.getRed(), (uint8) 255);
  461. expectEquals (c5.getGreen(), (uint8) 255);
  462. expectEquals (c5.getBlue(), (uint8) 255);
  463. expectEquals (c5.getAlpha(), (uint8) 255);
  464. expectEquals (c5.getFloatAlpha(), 1.0f);
  465. Colour c6 ((uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0);
  466. expectEquals (c6.getRed(), (uint8) 0);
  467. expectEquals (c6.getGreen(), (uint8) 0);
  468. expectEquals (c6.getBlue(), (uint8) 0);
  469. expectEquals (c6.getAlpha(), (uint8) 0);
  470. expectEquals (c6.getFloatAlpha(), 0.0f);
  471. Colour c7 ((uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255);
  472. expectEquals (c7.getRed(), (uint8) 255);
  473. expectEquals (c7.getGreen(), (uint8) 255);
  474. expectEquals (c7.getBlue(), (uint8) 255);
  475. expectEquals (c7.getAlpha(), (uint8) 255);
  476. expectEquals (c7.getFloatAlpha(), 1.0f);
  477. Colour c8 ((uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
  478. expectEquals (c8.getRed(), (uint8) 0);
  479. expectEquals (c8.getGreen(), (uint8) 0);
  480. expectEquals (c8.getBlue(), (uint8) 0);
  481. expectEquals (c8.getAlpha(), (uint8) 0);
  482. expectEquals (c8.getFloatAlpha(), 0.0f);
  483. Colour c9 ((uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
  484. expectEquals (c9.getRed(), (uint8) 255);
  485. expectEquals (c9.getGreen(), (uint8) 255);
  486. expectEquals (c9.getBlue(), (uint8) 255);
  487. expectEquals (c9.getAlpha(), (uint8) 255);
  488. expectEquals (c9.getFloatAlpha(), 1.0f);
  489. }
  490. beginTest ("HSV");
  491. {
  492. auto testHSV = [this] (int hueDegrees, int saturationPercentage, int brightnessPercentage,
  493. uint8 expectedRed, uint8 expectedGreen, uint8 expectedBlue)
  494. {
  495. auto testColour = Colour::fromHSV (hueDegrees / 360.0f,
  496. saturationPercentage / 100.0f,
  497. brightnessPercentage / 100.0f,
  498. 1.0f);
  499. expectEquals (testColour.getRed(), expectedRed);
  500. expectEquals (testColour.getGreen(), expectedGreen);
  501. expectEquals (testColour.getBlue(), expectedBlue);
  502. };
  503. // black
  504. testHSV (0, 0, 0, 0, 0, 0);
  505. // white
  506. testHSV (0, 0, 100, 255, 255, 255);
  507. // red
  508. testHSV (0, 100, 100, 255, 0, 0);
  509. // lime
  510. testHSV (120, 100, 100, 0, 255, 0);
  511. // blue
  512. testHSV (240, 100, 100, 0, 0, 255);
  513. // yellow
  514. testHSV (60, 100, 100, 255, 255, 0);
  515. // cyan
  516. testHSV (180, 100, 100, 0, 255, 255);
  517. // magenta
  518. testHSV (300, 100, 100, 255, 0, 255);
  519. // silver
  520. testHSV (0, 0, 75, 191, 191, 191);
  521. // grey
  522. testHSV (0, 0, 50, 128, 128, 128);
  523. // maroon
  524. testHSV (0, 100, 50, 128, 0, 0);
  525. // olive
  526. testHSV (60, 100, 50, 128, 128, 0);
  527. // green
  528. testHSV (120, 100, 50, 0, 128, 0);
  529. // purple
  530. testHSV (300, 100, 50, 128, 0, 128);
  531. // teal
  532. testHSV (180, 100, 50, 0, 128, 128);
  533. // navy
  534. testHSV (240, 100, 50, 0, 0, 128);
  535. }
  536. beginTest ("HSL");
  537. {
  538. auto testHSL = [this] (int hueDegrees, int saturationPercentage, int lightnessPercentage,
  539. uint8 expectedRed, uint8 expectedGreen, uint8 expectedBlue)
  540. {
  541. auto testColour = Colour::fromHSL (hueDegrees / 360.0f,
  542. saturationPercentage / 100.0f,
  543. lightnessPercentage / 100.0f,
  544. 1.0f);
  545. expectEquals (testColour.getRed(), expectedRed);
  546. expectEquals (testColour.getGreen(), expectedGreen);
  547. expectEquals (testColour.getBlue(), expectedBlue);
  548. };
  549. // black
  550. testHSL (0, 0, 0, 0, 0, 0);
  551. // white
  552. testHSL (0, 0, 100, 255, 255, 255);
  553. // red
  554. testHSL (0, 100, 50, 255, 0, 0);
  555. // lime
  556. testHSL (120, 100, 50, 0, 255, 0);
  557. // blue
  558. testHSL (240, 100, 50, 0, 0, 255);
  559. // yellow
  560. testHSL (60, 100, 50, 255, 255, 0);
  561. // cyan
  562. testHSL (180, 100, 50, 0, 255, 255);
  563. // magenta
  564. testHSL (300, 100, 50, 255, 0, 255);
  565. // silver
  566. testHSL (0, 0, 75, 191, 191, 191);
  567. // grey
  568. testHSL (0, 0, 50, 128, 128, 128);
  569. // maroon
  570. testHSL (0, 100, 25, 128, 0, 0);
  571. // olive
  572. testHSL (60, 100, 25, 128, 128, 0);
  573. // green
  574. testHSL (120, 100, 25, 0, 128, 0);
  575. // purple
  576. testHSL (300, 100, 25, 128, 0, 128);
  577. // teal
  578. testHSL (180, 100, 25, 0, 128, 128);
  579. // navy
  580. testHSL (240, 100, 25, 0, 0, 128);
  581. }
  582. }
  583. };
  584. static ColourTests colourTests;
  585. #endif
  586. } // namespace juce