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.

juce_Colour.cpp 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - 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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-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)
  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. {
  61. lightness = ((float) (hi + lo) / 2.0f) / 255.0f;
  62. if (lightness > 0.0f)
  63. hue = getHue (col);
  64. saturation = (float) (hi - lo) / (1.0f - std::abs ((2.0f * lightness) - 1.0f));
  65. }
  66. }
  67. Colour toColour (Colour original) const noexcept
  68. {
  69. return Colour::fromHSL (hue, saturation, lightness, original.getAlpha());
  70. }
  71. static PixelARGB toRGB (float h, float s, float l, uint8 alpha) noexcept
  72. {
  73. auto v = l < 0.5f ? l * (1.0f + s) : l + s - (l * s);
  74. if (approximatelyEqual (v, 0.0f))
  75. return PixelARGB (alpha, 0, 0, 0);
  76. auto min = (2.0f * l) - v;
  77. auto sv = (v - min) / v;
  78. h = ((h - std::floor (h)) * 360.0f) / 60.0f;
  79. auto f = h - std::floor (h);
  80. auto vsf = v * sv * f;
  81. auto mid1 = min + vsf;
  82. auto mid2 = v - vsf;
  83. if (h < 1.0f) return PixelARGB (alpha, floatToUInt8 (v), floatToUInt8 (mid1), floatToUInt8 (min));
  84. else if (h < 2.0f) return PixelARGB (alpha, floatToUInt8 (mid2), floatToUInt8 (v), floatToUInt8 (min));
  85. else if (h < 3.0f) return PixelARGB (alpha, floatToUInt8 (min), floatToUInt8 (v), floatToUInt8 (mid1));
  86. else if (h < 4.0f) return PixelARGB (alpha, floatToUInt8 (min), floatToUInt8 (mid2), floatToUInt8 (v));
  87. else if (h < 5.0f) return PixelARGB (alpha, floatToUInt8 (mid1), floatToUInt8 (min), floatToUInt8 (v));
  88. else if (h < 6.0f) return PixelARGB (alpha, floatToUInt8 (v), floatToUInt8 (min), floatToUInt8 (mid2));
  89. return PixelARGB (alpha, 0, 0, 0);
  90. }
  91. float hue = 0.0f, saturation = 0.0f, lightness = 0.0f;
  92. };
  93. //==============================================================================
  94. struct HSB
  95. {
  96. HSB (Colour col) noexcept
  97. {
  98. auto r = (int) col.getRed();
  99. auto g = (int) col.getGreen();
  100. auto b = (int) col.getBlue();
  101. auto hi = jmax (r, g, b);
  102. auto lo = jmin (r, g, b);
  103. if (hi > 0)
  104. {
  105. saturation = (float) (hi - lo) / (float) hi;
  106. if (saturation > 0.0f)
  107. hue = getHue (col);
  108. brightness = (float) hi / 255.0f;
  109. }
  110. }
  111. Colour toColour (Colour original) const noexcept
  112. {
  113. return Colour (hue, saturation, brightness, original.getAlpha());
  114. }
  115. static PixelARGB toRGB (float h, float s, float v, uint8 alpha) noexcept
  116. {
  117. v = jlimit (0.0f, 255.0f, v * 255.0f);
  118. auto intV = (uint8) roundToInt (v);
  119. if (s <= 0)
  120. return PixelARGB (alpha, intV, intV, intV);
  121. s = jmin (1.0f, s);
  122. h = ((h - std::floor (h)) * 360.0f) / 60.0f;
  123. auto f = h - std::floor (h);
  124. auto x = (uint8) roundToInt (v * (1.0f - s));
  125. if (h < 1.0f) return PixelARGB (alpha, intV, (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))), x);
  126. if (h < 2.0f) return PixelARGB (alpha, (uint8) roundToInt (v * (1.0f - s * f)), intV, x);
  127. if (h < 3.0f) return PixelARGB (alpha, x, intV, (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))));
  128. if (h < 4.0f) return PixelARGB (alpha, x, (uint8) roundToInt (v * (1.0f - s * f)), intV);
  129. if (h < 5.0f) return PixelARGB (alpha, (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))), x, intV);
  130. return PixelARGB (alpha, intV, x, (uint8) roundToInt (v * (1.0f - s * f)));
  131. }
  132. float hue = 0.0f, saturation = 0.0f, brightness = 0.0f;
  133. };
  134. //==============================================================================
  135. struct YIQ
  136. {
  137. YIQ (Colour c) noexcept
  138. {
  139. auto r = c.getFloatRed();
  140. auto g = c.getFloatGreen();
  141. auto b = c.getFloatBlue();
  142. y = 0.2999f * r + 0.5870f * g + 0.1140f * b;
  143. i = 0.5957f * r - 0.2744f * g - 0.3212f * b;
  144. q = 0.2114f * r - 0.5225f * g - 0.3113f * b;
  145. alpha = c.getFloatAlpha();
  146. }
  147. Colour toColour() const noexcept
  148. {
  149. return Colour::fromFloatRGBA (y + 0.9563f * i + 0.6210f * q,
  150. y - 0.2721f * i - 0.6474f * q,
  151. y - 1.1070f * i + 1.7046f * q,
  152. alpha);
  153. }
  154. float y = 0.0f, i = 0.0f, q = 0.0f, alpha = 0.0f;
  155. };
  156. }
  157. //==============================================================================
  158. bool Colour::operator== (const Colour& other) const noexcept { return argb.getNativeARGB() == other.argb.getNativeARGB(); }
  159. bool Colour::operator!= (const Colour& other) const noexcept { return argb.getNativeARGB() != other.argb.getNativeARGB(); }
  160. //==============================================================================
  161. Colour::Colour (uint32 col) noexcept
  162. : argb (static_cast<uint8> ((col >> 24) & 0xff),
  163. static_cast<uint8> ((col >> 16) & 0xff),
  164. static_cast<uint8> ((col >> 8) & 0xff),
  165. static_cast<uint8> (col & 0xff))
  166. {
  167. }
  168. Colour::Colour (uint8 red, uint8 green, uint8 blue) noexcept
  169. {
  170. argb.setARGB (0xff, red, green, blue);
  171. }
  172. Colour Colour::fromRGB (uint8 red, uint8 green, uint8 blue) noexcept
  173. {
  174. return Colour (red, green, blue);
  175. }
  176. Colour::Colour (uint8 red, uint8 green, uint8 blue, uint8 alpha) noexcept
  177. {
  178. argb.setARGB (alpha, red, green, blue);
  179. }
  180. Colour Colour::fromRGBA (uint8 red, uint8 green, uint8 blue, uint8 alpha) noexcept
  181. {
  182. return Colour (red, green, blue, alpha);
  183. }
  184. Colour::Colour (uint8 red, uint8 green, uint8 blue, float alpha) noexcept
  185. {
  186. argb.setARGB (ColourHelpers::floatToUInt8 (alpha), red, green, blue);
  187. }
  188. Colour Colour::fromFloatRGBA (float red, float green, float blue, float alpha) noexcept
  189. {
  190. return Colour (ColourHelpers::floatToUInt8 (red),
  191. ColourHelpers::floatToUInt8 (green),
  192. ColourHelpers::floatToUInt8 (blue), alpha);
  193. }
  194. Colour::Colour (float hue, float saturation, float brightness, float alpha) noexcept
  195. : argb (ColourHelpers::HSB::toRGB (hue, saturation, brightness, ColourHelpers::floatToUInt8 (alpha)))
  196. {
  197. }
  198. Colour Colour::fromHSV (float hue, float saturation, float brightness, float alpha) noexcept
  199. {
  200. return Colour (hue, saturation, brightness, alpha);
  201. }
  202. Colour Colour::fromHSL (float hue, float saturation, float lightness, float alpha) noexcept
  203. {
  204. Colour hslColour;
  205. hslColour.argb = ColourHelpers::HSL::toRGB (hue, saturation, lightness, ColourHelpers::floatToUInt8 (alpha));
  206. return hslColour;
  207. }
  208. Colour::Colour (float hue, float saturation, float brightness, uint8 alpha) noexcept
  209. : argb (ColourHelpers::HSB::toRGB (hue, saturation, brightness, alpha))
  210. {
  211. }
  212. Colour::Colour (PixelARGB argb_) noexcept
  213. : argb (argb_)
  214. {
  215. }
  216. Colour::Colour (PixelRGB rgb) noexcept
  217. : argb (Colour (rgb.getInARGBMaskOrder()).argb)
  218. {
  219. }
  220. Colour::Colour (PixelAlpha alpha) noexcept
  221. : argb (Colour (alpha.getInARGBMaskOrder()).argb)
  222. {
  223. }
  224. //==============================================================================
  225. const PixelARGB Colour::getPixelARGB() const noexcept
  226. {
  227. PixelARGB p (argb);
  228. p.premultiply();
  229. return p;
  230. }
  231. uint32 Colour::getARGB() const noexcept
  232. {
  233. return argb.getInARGBMaskOrder();
  234. }
  235. //==============================================================================
  236. bool Colour::isTransparent() const noexcept
  237. {
  238. return getAlpha() == 0;
  239. }
  240. bool Colour::isOpaque() const noexcept
  241. {
  242. return getAlpha() == 0xff;
  243. }
  244. Colour Colour::withAlpha (uint8 newAlpha) const noexcept
  245. {
  246. PixelARGB newCol (argb);
  247. newCol.setAlpha (newAlpha);
  248. return Colour (newCol);
  249. }
  250. Colour Colour::withAlpha (float newAlpha) const noexcept
  251. {
  252. jassert (newAlpha >= 0 && newAlpha <= 1.0f);
  253. PixelARGB newCol (argb);
  254. newCol.setAlpha (ColourHelpers::floatToUInt8 (newAlpha));
  255. return Colour (newCol);
  256. }
  257. Colour Colour::withMultipliedAlpha (float alphaMultiplier) const noexcept
  258. {
  259. jassert (alphaMultiplier >= 0);
  260. PixelARGB newCol (argb);
  261. newCol.setAlpha ((uint8) jmin (0xff, roundToInt (alphaMultiplier * newCol.getAlpha())));
  262. return Colour (newCol);
  263. }
  264. //==============================================================================
  265. Colour Colour::overlaidWith (Colour src) const noexcept
  266. {
  267. auto destAlpha = getAlpha();
  268. if (destAlpha <= 0)
  269. return src;
  270. auto invA = 0xff - (int) src.getAlpha();
  271. auto resA = 0xff - (((0xff - destAlpha) * invA) >> 8);
  272. if (resA <= 0)
  273. return *this;
  274. auto da = (invA * destAlpha) / resA;
  275. return Colour ((uint8) (src.getRed() + ((((int) getRed() - src.getRed()) * da) >> 8)),
  276. (uint8) (src.getGreen() + ((((int) getGreen() - src.getGreen()) * da) >> 8)),
  277. (uint8) (src.getBlue() + ((((int) getBlue() - src.getBlue()) * da) >> 8)),
  278. (uint8) resA);
  279. }
  280. Colour Colour::interpolatedWith (Colour other, float proportionOfOther) const noexcept
  281. {
  282. if (proportionOfOther <= 0)
  283. return *this;
  284. if (proportionOfOther >= 1.0f)
  285. return other;
  286. PixelARGB c1 (getPixelARGB());
  287. PixelARGB c2 (other.getPixelARGB());
  288. c1.tween (c2, (uint32) roundToInt (proportionOfOther * 255.0f));
  289. c1.unpremultiply();
  290. return Colour (c1);
  291. }
  292. //==============================================================================
  293. float Colour::getFloatRed() const noexcept { return getRed() / 255.0f; }
  294. float Colour::getFloatGreen() const noexcept { return getGreen() / 255.0f; }
  295. float Colour::getFloatBlue() const noexcept { return getBlue() / 255.0f; }
  296. float Colour::getFloatAlpha() const noexcept { return getAlpha() / 255.0f; }
  297. //==============================================================================
  298. void Colour::getHSB (float& h, float& s, float& v) const noexcept
  299. {
  300. ColourHelpers::HSB hsb (*this);
  301. h = hsb.hue;
  302. s = hsb.saturation;
  303. v = hsb.brightness;
  304. }
  305. void Colour::getHSL (float& h, float& s, float& l) const noexcept
  306. {
  307. ColourHelpers::HSL hsl (*this);
  308. h = hsl.hue;
  309. s = hsl.saturation;
  310. l = hsl.lightness;
  311. }
  312. float Colour::getHue() const noexcept { return ColourHelpers::HSB (*this).hue; }
  313. float Colour::getSaturation() const noexcept { return ColourHelpers::HSB (*this).saturation; }
  314. float Colour::getBrightness() const noexcept { return ColourHelpers::HSB (*this).brightness; }
  315. float Colour::getSaturationHSL() const noexcept { return ColourHelpers::HSL (*this).saturation; }
  316. float Colour::getLightness() const noexcept { return ColourHelpers::HSL (*this).lightness; }
  317. Colour Colour::withHue (float h) const noexcept { ColourHelpers::HSB hsb (*this); hsb.hue = h; return hsb.toColour (*this); }
  318. Colour Colour::withSaturation (float s) const noexcept { ColourHelpers::HSB hsb (*this); hsb.saturation = s; return hsb.toColour (*this); }
  319. Colour Colour::withBrightness (float v) const noexcept { ColourHelpers::HSB hsb (*this); hsb.brightness = v; return hsb.toColour (*this); }
  320. Colour Colour::withSaturationHSL (float s) const noexcept { ColourHelpers::HSL hsl (*this); hsl.saturation = s; return hsl.toColour (*this); }
  321. Colour Colour::withLightness (float l) const noexcept { ColourHelpers::HSL hsl (*this); hsl.lightness = l; return hsl.toColour (*this); }
  322. float Colour::getPerceivedBrightness() const noexcept
  323. {
  324. return std::sqrt (0.241f * square (getFloatRed())
  325. + 0.691f * square (getFloatGreen())
  326. + 0.068f * square (getFloatBlue()));
  327. }
  328. //==============================================================================
  329. Colour Colour::withRotatedHue (float amountToRotate) const noexcept
  330. {
  331. ColourHelpers::HSB hsb (*this);
  332. hsb.hue += amountToRotate;
  333. return hsb.toColour (*this);
  334. }
  335. Colour Colour::withMultipliedSaturation (float amount) const noexcept
  336. {
  337. ColourHelpers::HSB hsb (*this);
  338. hsb.saturation = jmin (1.0f, hsb.saturation * amount);
  339. return hsb.toColour (*this);
  340. }
  341. Colour Colour::withMultipliedSaturationHSL (float amount) const noexcept
  342. {
  343. ColourHelpers::HSL hsl (*this);
  344. hsl.saturation = jmin (1.0f, hsl.saturation * amount);
  345. return hsl.toColour (*this);
  346. }
  347. Colour Colour::withMultipliedBrightness (float amount) const noexcept
  348. {
  349. ColourHelpers::HSB hsb (*this);
  350. hsb.brightness = jmin (1.0f, hsb.brightness * amount);
  351. return hsb.toColour (*this);
  352. }
  353. Colour Colour::withMultipliedLightness (float amount) const noexcept
  354. {
  355. ColourHelpers::HSL hsl (*this);
  356. hsl.lightness = jmin (1.0f, hsl.lightness * amount);
  357. return hsl.toColour (*this);
  358. }
  359. //==============================================================================
  360. Colour Colour::brighter (float amount) const noexcept
  361. {
  362. amount = 1.0f / (1.0f + amount);
  363. return Colour ((uint8) (255 - (amount * (255 - getRed()))),
  364. (uint8) (255 - (amount * (255 - getGreen()))),
  365. (uint8) (255 - (amount * (255 - getBlue()))),
  366. getAlpha());
  367. }
  368. Colour Colour::darker (float amount) const noexcept
  369. {
  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 ((uint32) CharacterFunctions::HexParser<int>::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. }
  567. }
  568. };
  569. static ColourTests colourTests;
  570. #endif
  571. } // namespace juce