Audio plugin host https://kx.studio/carla
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.

706 lines
25KB

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