Add remaining files
[juce-lv2.git] / juce / source / src / gui / graphics / colour / juce_Colour.cpp
blob9d09d8951f19330646c55aa3f753b84433fbb33d
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../../core/juce_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_Colours.h"
33 //==============================================================================
34 namespace ColourHelpers
36 uint8 floatAlphaToInt (const float alpha) noexcept
38 return (uint8) jlimit (0, 0xff, roundToInt (alpha * 255.0f));
41 void convertHSBtoRGB (float h, float s, float v,
42 uint8& r, uint8& g, uint8& b) noexcept
44 v = jlimit (0.0f, 1.0f, v);
45 v *= 255.0f;
46 const uint8 intV = (uint8) roundToInt (v);
48 if (s <= 0)
50 r = intV;
51 g = intV;
52 b = intV;
54 else
56 s = jmin (1.0f, s);
57 h = (h - std::floor (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors
58 const float f = h - std::floor (h);
59 const uint8 x = (uint8) roundToInt (v * (1.0f - s));
61 if (h < 1.0f)
63 r = intV;
64 g = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f))));
65 b = x;
67 else if (h < 2.0f)
69 r = (uint8) roundToInt (v * (1.0f - s * f));
70 g = intV;
71 b = x;
73 else if (h < 3.0f)
75 r = x;
76 g = intV;
77 b = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f))));
79 else if (h < 4.0f)
81 r = x;
82 g = (uint8) roundToInt (v * (1.0f - s * f));
83 b = intV;
85 else if (h < 5.0f)
87 r = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f))));
88 g = x;
89 b = intV;
91 else
93 r = intV;
94 g = x;
95 b = (uint8) roundToInt (v * (1.0f - s * f));
101 //==============================================================================
102 Colour::Colour() noexcept
103 : argb (0)
107 Colour::Colour (const Colour& other) noexcept
108 : argb (other.argb)
112 Colour& Colour::operator= (const Colour& other) noexcept
114 argb = other.argb;
115 return *this;
118 bool Colour::operator== (const Colour& other) const noexcept
120 return argb.getARGB() == other.argb.getARGB();
123 bool Colour::operator!= (const Colour& other) const noexcept
125 return argb.getARGB() != other.argb.getARGB();
128 //==============================================================================
129 Colour::Colour (const uint32 argb_) noexcept
130 : argb (argb_)
134 Colour::Colour (const uint8 red,
135 const uint8 green,
136 const uint8 blue) noexcept
138 argb.setARGB (0xff, red, green, blue);
141 Colour Colour::fromRGB (const uint8 red,
142 const uint8 green,
143 const uint8 blue) noexcept
145 return Colour (red, green, blue);
148 Colour::Colour (const uint8 red,
149 const uint8 green,
150 const uint8 blue,
151 const uint8 alpha) noexcept
153 argb.setARGB (alpha, red, green, blue);
156 Colour Colour::fromRGBA (const uint8 red,
157 const uint8 green,
158 const uint8 blue,
159 const uint8 alpha) noexcept
161 return Colour (red, green, blue, alpha);
164 Colour::Colour (const uint8 red,
165 const uint8 green,
166 const uint8 blue,
167 const float alpha) noexcept
169 argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), red, green, blue);
172 Colour Colour::fromRGBAFloat (const uint8 red,
173 const uint8 green,
174 const uint8 blue,
175 const float alpha) noexcept
177 return Colour (red, green, blue, alpha);
180 Colour::Colour (const float hue,
181 const float saturation,
182 const float brightness,
183 const float alpha) noexcept
185 uint8 r, g, b;
186 ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b);
188 argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b);
191 Colour Colour::fromHSV (const float hue,
192 const float saturation,
193 const float brightness,
194 const float alpha) noexcept
196 return Colour (hue, saturation, brightness, alpha);
199 Colour::Colour (const float hue,
200 const float saturation,
201 const float brightness,
202 const uint8 alpha) noexcept
204 uint8 r, g, b;
205 ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b);
207 argb.setARGB (alpha, r, g, b);
210 Colour::~Colour() noexcept
214 //==============================================================================
215 const PixelARGB Colour::getPixelARGB() const noexcept
217 PixelARGB p (argb);
218 p.premultiply();
219 return p;
222 uint32 Colour::getARGB() const noexcept
224 return argb.getARGB();
227 //==============================================================================
228 bool Colour::isTransparent() const noexcept
230 return getAlpha() == 0;
233 bool Colour::isOpaque() const noexcept
235 return getAlpha() == 0xff;
238 Colour Colour::withAlpha (const uint8 newAlpha) const noexcept
240 PixelARGB newCol (argb);
241 newCol.setAlpha (newAlpha);
242 return Colour (newCol.getARGB());
245 Colour Colour::withAlpha (const float newAlpha) const noexcept
247 jassert (newAlpha >= 0 && newAlpha <= 1.0f);
249 PixelARGB newCol (argb);
250 newCol.setAlpha (ColourHelpers::floatAlphaToInt (newAlpha));
251 return Colour (newCol.getARGB());
254 Colour Colour::withMultipliedAlpha (const float alphaMultiplier) const noexcept
256 jassert (alphaMultiplier >= 0);
258 PixelARGB newCol (argb);
259 newCol.setAlpha ((uint8) jmin (0xff, roundToInt (alphaMultiplier * newCol.getAlpha())));
260 return Colour (newCol.getARGB());
263 //==============================================================================
264 Colour Colour::overlaidWith (const Colour& src) const noexcept
266 const int destAlpha = getAlpha();
268 if (destAlpha > 0)
270 const int invA = 0xff - (int) src.getAlpha();
271 const int resA = 0xff - (((0xff - destAlpha) * invA) >> 8);
273 if (resA > 0)
275 const int da = (invA * destAlpha) / resA;
277 return Colour ((uint8) (src.getRed() + ((((int) getRed() - src.getRed()) * da) >> 8)),
278 (uint8) (src.getGreen() + ((((int) getGreen() - src.getGreen()) * da) >> 8)),
279 (uint8) (src.getBlue() + ((((int) getBlue() - src.getBlue()) * da) >> 8)),
280 (uint8) resA);
283 return *this;
285 else
287 return src;
291 Colour Colour::interpolatedWith (const Colour& other, float proportionOfOther) const noexcept
293 if (proportionOfOther <= 0)
294 return *this;
296 if (proportionOfOther >= 1.0f)
297 return other;
299 PixelARGB c1 (getPixelARGB());
300 const PixelARGB c2 (other.getPixelARGB());
301 c1.tween (c2, roundToInt (proportionOfOther * 255.0f));
302 c1.unpremultiply();
304 return Colour (c1.getARGB());
307 //==============================================================================
308 float Colour::getFloatRed() const noexcept
310 return getRed() / 255.0f;
313 float Colour::getFloatGreen() const noexcept
315 return getGreen() / 255.0f;
318 float Colour::getFloatBlue() const noexcept
320 return getBlue() / 255.0f;
323 float Colour::getFloatAlpha() const noexcept
325 return getAlpha() / 255.0f;
328 //==============================================================================
329 void Colour::getHSB (float& h, float& s, float& v) const noexcept
331 const int r = getRed();
332 const int g = getGreen();
333 const int b = getBlue();
335 const int hi = jmax (r, g, b);
336 const int lo = jmin (r, g, b);
338 if (hi != 0)
340 s = (hi - lo) / (float) hi;
342 if (s > 0)
344 const float invDiff = 1.0f / (hi - lo);
346 const float red = (hi - r) * invDiff;
347 const float green = (hi - g) * invDiff;
348 const float blue = (hi - b) * invDiff;
350 if (r == hi)
351 h = blue - green;
352 else if (g == hi)
353 h = 2.0f + red - blue;
354 else
355 h = 4.0f + green - red;
357 h *= 1.0f / 6.0f;
359 if (h < 0)
360 ++h;
362 else
364 h = 0;
367 else
369 s = 0;
370 h = 0;
373 v = hi / 255.0f;
376 //==============================================================================
377 float Colour::getHue() const noexcept
379 float h, s, b;
380 getHSB (h, s, b);
381 return h;
384 Colour Colour::withHue (const float hue) const noexcept
386 float h, s, b;
387 getHSB (h, s, b);
389 return Colour (hue, s, b, getAlpha());
392 Colour Colour::withRotatedHue (const float amountToRotate) const noexcept
394 float h, s, b;
395 getHSB (h, s, b);
397 return Colour (h + amountToRotate, s, b, getAlpha());
400 //==============================================================================
401 float Colour::getSaturation() const noexcept
403 float h, s, b;
404 getHSB (h, s, b);
405 return s;
408 Colour Colour::withSaturation (const float saturation) const noexcept
410 float h, s, b;
411 getHSB (h, s, b);
413 return Colour (h, saturation, b, getAlpha());
416 Colour Colour::withMultipliedSaturation (const float amount) const noexcept
418 float h, s, b;
419 getHSB (h, s, b);
421 return Colour (h, jmin (1.0f, s * amount), b, getAlpha());
424 //==============================================================================
425 float Colour::getBrightness() const noexcept
427 float h, s, b;
428 getHSB (h, s, b);
429 return b;
432 Colour Colour::withBrightness (const float brightness) const noexcept
434 float h, s, b;
435 getHSB (h, s, b);
437 return Colour (h, s, brightness, getAlpha());
440 Colour Colour::withMultipliedBrightness (const float amount) const noexcept
442 float h, s, b;
443 getHSB (h, s, b);
445 b *= amount;
447 if (b > 1.0f)
448 b = 1.0f;
450 return Colour (h, s, b, getAlpha());
453 //==============================================================================
454 Colour Colour::brighter (float amount) const noexcept
456 amount = 1.0f / (1.0f + amount);
458 return Colour ((uint8) (255 - (amount * (255 - getRed()))),
459 (uint8) (255 - (amount * (255 - getGreen()))),
460 (uint8) (255 - (amount * (255 - getBlue()))),
461 getAlpha());
464 Colour Colour::darker (float amount) const noexcept
466 amount = 1.0f / (1.0f + amount);
468 return Colour ((uint8) (amount * getRed()),
469 (uint8) (amount * getGreen()),
470 (uint8) (amount * getBlue()),
471 getAlpha());
474 //==============================================================================
475 Colour Colour::greyLevel (const float brightness) noexcept
477 const uint8 level
478 = (uint8) jlimit (0x00, 0xff, roundToInt (brightness * 255.0f));
480 return Colour (level, level, level);
483 //==============================================================================
484 Colour Colour::contrasting (const float amount) const noexcept
486 return overlaidWith ((((int) getRed() + (int) getGreen() + (int) getBlue() >= 3 * 128)
487 ? Colours::black
488 : Colours::white).withAlpha (amount));
491 Colour Colour::contrasting (const Colour& colour1,
492 const Colour& colour2) noexcept
494 const float b1 = colour1.getBrightness();
495 const float b2 = colour2.getBrightness();
496 float best = 0.0f;
497 float bestDist = 0.0f;
499 for (float i = 0.0f; i < 1.0f; i += 0.02f)
501 const float d1 = std::abs (i - b1);
502 const float d2 = std::abs (i - b2);
503 const float dist = jmin (d1, d2, 1.0f - d1, 1.0f - d2);
505 if (dist > bestDist)
507 best = i;
508 bestDist = dist;
512 return colour1.overlaidWith (colour2.withMultipliedAlpha (0.5f))
513 .withBrightness (best);
516 //==============================================================================
517 String Colour::toString() const
519 return String::toHexString ((int) argb.getARGB());
522 Colour Colour::fromString (const String& encodedColourString)
524 return Colour ((uint32) encodedColourString.getHexValue32());
527 String Colour::toDisplayString (const bool includeAlphaValue) const
529 return String::toHexString ((int) (argb.getARGB() & (includeAlphaValue ? 0xffffffff : 0xffffff)))
530 .paddedLeft ('0', includeAlphaValue ? 8 : 6)
531 .toUpperCase();
535 END_JUCE_NAMESPACE