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.

718 lines
26KB

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