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.

696 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 = ((h - std::floor (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 = ((h - std::floor (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 (uint8 newAlpha) const noexcept
  240. {
  241. PixelARGB newCol (argb);
  242. newCol.setAlpha (newAlpha);
  243. return Colour (newCol);
  244. }
  245. Colour Colour::withAlpha (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 (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::getSaturationHSL() const noexcept { return ColourHelpers::HSL (*this).saturation; }
  311. float Colour::getLightness() const noexcept { return ColourHelpers::HSL (*this).lightness; }
  312. Colour Colour::withHue (float h) const noexcept { ColourHelpers::HSB hsb (*this); hsb.hue = h; return hsb.toColour (*this); }
  313. Colour Colour::withSaturation (float s) const noexcept { ColourHelpers::HSB hsb (*this); hsb.saturation = s; return hsb.toColour (*this); }
  314. Colour Colour::withBrightness (float v) const noexcept { ColourHelpers::HSB hsb (*this); hsb.brightness = v; return hsb.toColour (*this); }
  315. Colour Colour::withSaturationHSL (float s) const noexcept { ColourHelpers::HSL hsl (*this); hsl.saturation = s; return hsl.toColour (*this); }
  316. Colour Colour::withLightness (float l) const noexcept { ColourHelpers::HSL hsl (*this); hsl.lightness = l; return hsl.toColour (*this); }
  317. float Colour::getPerceivedBrightness() const noexcept
  318. {
  319. return std::sqrt (0.241f * square (getFloatRed())
  320. + 0.691f * square (getFloatGreen())
  321. + 0.068f * square (getFloatBlue()));
  322. }
  323. //==============================================================================
  324. Colour Colour::withRotatedHue (float amountToRotate) const noexcept
  325. {
  326. ColourHelpers::HSB hsb (*this);
  327. hsb.hue += amountToRotate;
  328. return hsb.toColour (*this);
  329. }
  330. Colour Colour::withMultipliedSaturation (float amount) const noexcept
  331. {
  332. ColourHelpers::HSB hsb (*this);
  333. hsb.saturation = jmin (1.0f, hsb.saturation * amount);
  334. return hsb.toColour (*this);
  335. }
  336. Colour Colour::withMultipliedSaturationHSL (float amount) const noexcept
  337. {
  338. ColourHelpers::HSL hsl (*this);
  339. hsl.saturation = jmin (1.0f, hsl.saturation * amount);
  340. return hsl.toColour (*this);
  341. }
  342. Colour Colour::withMultipliedBrightness (float amount) const noexcept
  343. {
  344. ColourHelpers::HSB hsb (*this);
  345. hsb.brightness = jmin (1.0f, hsb.brightness * amount);
  346. return hsb.toColour (*this);
  347. }
  348. Colour Colour::withMultipliedLightness (float amount) const noexcept
  349. {
  350. ColourHelpers::HSL hsl (*this);
  351. hsl.lightness = jmin (1.0f, hsl.lightness * amount);
  352. return hsl.toColour (*this);
  353. }
  354. //==============================================================================
  355. Colour Colour::brighter (float amount) const noexcept
  356. {
  357. amount = 1.0f / (1.0f + amount);
  358. return Colour ((uint8) (255 - (amount * (255 - getRed()))),
  359. (uint8) (255 - (amount * (255 - getGreen()))),
  360. (uint8) (255 - (amount * (255 - getBlue()))),
  361. getAlpha());
  362. }
  363. Colour Colour::darker (float amount) const noexcept
  364. {
  365. amount = 1.0f / (1.0f + amount);
  366. return Colour ((uint8) (amount * getRed()),
  367. (uint8) (amount * getGreen()),
  368. (uint8) (amount * getBlue()),
  369. getAlpha());
  370. }
  371. //==============================================================================
  372. Colour Colour::greyLevel (float brightness) noexcept
  373. {
  374. auto level = ColourHelpers::floatToUInt8 (brightness);
  375. return Colour (level, level, level);
  376. }
  377. //==============================================================================
  378. Colour Colour::contrasting (float amount) const noexcept
  379. {
  380. return overlaidWith ((getPerceivedBrightness() >= 0.5f
  381. ? Colours::black
  382. : Colours::white).withAlpha (amount));
  383. }
  384. Colour Colour::contrasting (Colour target, float minContrast) const noexcept
  385. {
  386. ColourHelpers::YIQ bg (*this);
  387. ColourHelpers::YIQ fg (target);
  388. if (std::abs (bg.y - fg.y) >= minContrast)
  389. return target;
  390. auto y1 = jmax (0.0f, bg.y - minContrast);
  391. auto y2 = jmin (1.0f, bg.y + minContrast);
  392. fg.y = (std::abs (y1 - bg.y) > std::abs (y2 - bg.y)) ? y1 : y2;
  393. return fg.toColour();
  394. }
  395. Colour Colour::contrasting (Colour colour1,
  396. Colour colour2) noexcept
  397. {
  398. auto b1 = colour1.getPerceivedBrightness();
  399. auto b2 = colour2.getPerceivedBrightness();
  400. float best = 0.0f, bestDist = 0.0f;
  401. for (float i = 0.0f; i < 1.0f; i += 0.02f)
  402. {
  403. auto d1 = std::abs (i - b1);
  404. auto d2 = std::abs (i - b2);
  405. auto dist = jmin (d1, d2, 1.0f - d1, 1.0f - d2);
  406. if (dist > bestDist)
  407. {
  408. best = i;
  409. bestDist = dist;
  410. }
  411. }
  412. return colour1.overlaidWith (colour2.withMultipliedAlpha (0.5f))
  413. .withBrightness (best);
  414. }
  415. //==============================================================================
  416. String Colour::toString() const
  417. {
  418. return String::toHexString ((int) argb.getInARGBMaskOrder());
  419. }
  420. Colour Colour::fromString (StringRef encodedColourString)
  421. {
  422. return Colour ((uint32) CharacterFunctions::HexParser<int>::parse (encodedColourString.text));
  423. }
  424. String Colour::toDisplayString (const bool includeAlphaValue) const
  425. {
  426. return String::toHexString ((int) (argb.getInARGBMaskOrder() & (includeAlphaValue ? 0xffffffff : 0xffffff)))
  427. .paddedLeft ('0', includeAlphaValue ? 8 : 6)
  428. .toUpperCase();
  429. }
  430. //==============================================================================
  431. //==============================================================================
  432. #if JUCE_UNIT_TESTS
  433. class ColourTests : public UnitTest
  434. {
  435. public:
  436. ColourTests()
  437. : UnitTest ("Colour", UnitTestCategories::graphics)
  438. {}
  439. void runTest() override
  440. {
  441. auto testColour = [this] (Colour colour,
  442. uint8 expectedRed, uint8 expectedGreen, uint8 expectedBlue,
  443. uint8 expectedAlpha = 255, float expectedFloatAlpha = 1.0f)
  444. {
  445. expectEquals (colour.getRed(), expectedRed);
  446. expectEquals (colour.getGreen(), expectedGreen);
  447. expectEquals (colour.getBlue(), expectedBlue);
  448. expectEquals (colour.getAlpha(), expectedAlpha);
  449. expectEquals (colour.getFloatAlpha(), expectedFloatAlpha);
  450. };
  451. beginTest ("Constructors");
  452. {
  453. Colour c1;
  454. testColour (c1, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
  455. Colour c2 ((uint32) 0);
  456. testColour (c2, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
  457. Colour c3 ((uint32) 0xffffffff);
  458. testColour (c3, (uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
  459. Colour c4 (0, 0, 0);
  460. testColour (c4, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 255, 1.0f);
  461. Colour c5 (255, 255, 255);
  462. testColour (c5, (uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
  463. Colour c6 ((uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0);
  464. testColour (c6, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
  465. Colour c7 ((uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255);
  466. testColour (c7, (uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
  467. Colour c8 ((uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
  468. testColour (c8, (uint8) 0, (uint8) 0, (uint8) 0, (uint8) 0, 0.0f);
  469. Colour c9 ((uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
  470. testColour (c9, (uint8) 255, (uint8) 255, (uint8) 255, (uint8) 255, 1.0f);
  471. }
  472. beginTest ("HSV");
  473. {
  474. // black
  475. testColour (Colour::fromHSV (0.0f, 0.0f, 0.0f, 1.0f), 0, 0, 0);
  476. // white
  477. testColour (Colour::fromHSV (0.0f, 0.0f, 1.0f, 1.0f), 255, 255, 255);
  478. // red
  479. testColour (Colour::fromHSV (0.0f, 1.0f, 1.0f, 1.0f), 255, 0, 0);
  480. testColour (Colour::fromHSV (1.0f, 1.0f, 1.0f, 1.0f), 255, 0, 0);
  481. // lime
  482. testColour (Colour::fromHSV (120 / 360.0f, 1.0f, 1.0f, 1.0f), 0, 255, 0);
  483. // blue
  484. testColour (Colour::fromHSV (240 / 360.0f, 1.0f, 1.0f, 1.0f), 0, 0, 255);
  485. // yellow
  486. testColour (Colour::fromHSV (60 / 360.0f, 1.0f, 1.0f, 1.0f), 255, 255, 0);
  487. // cyan
  488. testColour (Colour::fromHSV (180 / 360.0f, 1.0f, 1.0f, 1.0f), 0, 255, 255);
  489. // magenta
  490. testColour (Colour::fromHSV (300 / 360.0f, 1.0f, 1.0f, 1.0f), 255, 0, 255);
  491. // silver
  492. testColour (Colour::fromHSV (0.0f, 0.0f, 0.75f, 1.0f), 191, 191, 191);
  493. // grey
  494. testColour (Colour::fromHSV (0.0f, 0.0f, 0.5f, 1.0f), 128, 128, 128);
  495. // maroon
  496. testColour (Colour::fromHSV (0.0f, 1.0f, 0.5f, 1.0f), 128, 0, 0);
  497. // olive
  498. testColour (Colour::fromHSV (60 / 360.0f, 1.0f, 0.5f, 1.0f), 128, 128, 0);
  499. // green
  500. testColour (Colour::fromHSV (120 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 128, 0);
  501. // purple
  502. testColour (Colour::fromHSV (300 / 360.0f, 1.0f, 0.5f, 1.0f), 128, 0, 128);
  503. // teal
  504. testColour (Colour::fromHSV (180 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 128, 128);
  505. // navy
  506. testColour (Colour::fromHSV (240 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 0, 128);
  507. }
  508. beginTest ("HSL");
  509. {
  510. // black
  511. testColour (Colour::fromHSL (0.0f, 0.0f, 0.0f, 1.0f), 0, 0, 0);
  512. // white
  513. testColour (Colour::fromHSL (0.0f, 0.0f, 1.0f, 1.0f), 255, 255, 255);
  514. // red
  515. testColour (Colour::fromHSL (0.0f, 1.0f, 0.5f, 1.0f), 255, 0, 0);
  516. testColour (Colour::fromHSL (1.0f, 1.0f, 0.5f, 1.0f), 255, 0, 0);
  517. // lime
  518. testColour (Colour::fromHSL (120 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 255, 0);
  519. // blue
  520. testColour (Colour::fromHSL (240 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 0, 255);
  521. // yellow
  522. testColour (Colour::fromHSL (60 / 360.0f, 1.0f, 0.5f, 1.0f), 255, 255, 0);
  523. // cyan
  524. testColour (Colour::fromHSL (180 / 360.0f, 1.0f, 0.5f, 1.0f), 0, 255, 255);
  525. // magenta
  526. testColour (Colour::fromHSL (300 / 360.0f, 1.0f, 0.5f, 1.0f), 255, 0, 255);
  527. // silver
  528. testColour (Colour::fromHSL (0.0f, 0.0f, 0.75f, 1.0f), 191, 191, 191);
  529. // grey
  530. testColour (Colour::fromHSL (0.0f, 0.0f, 0.5f, 1.0f), 128, 128, 128);
  531. // maroon
  532. testColour (Colour::fromHSL (0.0f, 1.0f, 0.25f, 1.0f), 128, 0, 0);
  533. // olive
  534. testColour (Colour::fromHSL (60 / 360.0f, 1.0f, 0.25f, 1.0f), 128, 128, 0);
  535. // green
  536. testColour (Colour::fromHSL (120 / 360.0f, 1.0f, 0.25f, 1.0f), 0, 128, 0);
  537. // purple
  538. testColour (Colour::fromHSL (300 / 360.0f, 1.0f, 0.25f, 1.0f), 128, 0, 128);
  539. // teal
  540. testColour (Colour::fromHSL (180 / 360.0f, 1.0f, 0.25f, 1.0f), 0, 128, 128);
  541. // navy
  542. testColour (Colour::fromHSL (240 / 360.0f, 1.0f, 0.25f, 1.0f), 0, 0, 128);
  543. }
  544. beginTest ("Modifiers");
  545. {
  546. Colour red (255, 0, 0);
  547. testColour (red, 255, 0, 0);
  548. testColour (red.withHue (120.0f / 360.0f), 0, 255, 0);
  549. testColour (red.withSaturation (0.5f), 255, 128, 128);
  550. testColour (red.withSaturationHSL (0.5f), 191, 64, 64);
  551. testColour (red.withBrightness (0.5f), 128, 0, 0);
  552. testColour (red.withLightness (1.0f), 255, 255, 255);
  553. testColour (red.withRotatedHue (120.0f / 360.0f), 0, 255, 0);
  554. testColour (red.withRotatedHue (480.0f / 360.0f), 0, 255, 0);
  555. testColour (red.withRotatedHue (-240.0f / 360.0f), 0, 255, 0);
  556. testColour (red.withRotatedHue (-600.0f / 360.0f), 0, 255, 0);
  557. testColour (red.withMultipliedSaturation (0.0f), 255, 255, 255);
  558. testColour (red.withMultipliedSaturationHSL (0.0f), 128, 128, 128);
  559. testColour (red.withMultipliedBrightness (0.5f), 128, 0, 0);
  560. testColour (red.withMultipliedLightness (2.0f), 255, 255, 255);
  561. }
  562. }
  563. };
  564. static ColourTests colourTests;
  565. #endif
  566. } // namespace juce