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_ColourGradient.cpp 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. ColourGradient::ColourGradient() noexcept : isRadial (false)
  21. {
  22. #if JUCE_DEBUG
  23. point1.setX (987654.0f);
  24. #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED jassert (point1.x != 987654.0f);
  25. #else
  26. #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED
  27. #endif
  28. }
  29. ColourGradient::ColourGradient (const ColourGradient& other)
  30. : point1 (other.point1), point2 (other.point2), isRadial (other.isRadial), colours (other.colours)
  31. {}
  32. ColourGradient::ColourGradient (ColourGradient&& other) noexcept
  33. : point1 (other.point1), point2 (other.point2), isRadial (other.isRadial),
  34. colours (std::move (other.colours))
  35. {}
  36. ColourGradient& ColourGradient::operator= (const ColourGradient& other)
  37. {
  38. point1 = other.point1;
  39. point2 = other.point2;
  40. isRadial = other.isRadial;
  41. colours = other.colours;
  42. return *this;
  43. }
  44. ColourGradient& ColourGradient::operator= (ColourGradient&& other) noexcept
  45. {
  46. point1 = other.point1;
  47. point2 = other.point2;
  48. isRadial = other.isRadial;
  49. colours = std::move (other.colours);
  50. return *this;
  51. }
  52. ColourGradient::ColourGradient (Colour colour1, float x1, float y1,
  53. Colour colour2, float x2, float y2, bool radial)
  54. : ColourGradient (colour1, Point<float> (x1, y1),
  55. colour2, Point<float> (x2, y2), radial)
  56. {
  57. }
  58. ColourGradient::ColourGradient (Colour colour1, Point<float> p1,
  59. Colour colour2, Point<float> p2, bool radial)
  60. : point1 (p1),
  61. point2 (p2),
  62. isRadial (radial)
  63. {
  64. colours.add (ColourPoint { 0.0, colour1 },
  65. ColourPoint { 1.0, colour2 });
  66. }
  67. ColourGradient::~ColourGradient() {}
  68. ColourGradient ColourGradient::vertical (Colour c1, float y1, Colour c2, float y2)
  69. {
  70. return { c1, 0, y1, c2, 0, y2, false };
  71. }
  72. ColourGradient ColourGradient::horizontal (Colour c1, float x1, Colour c2, float x2)
  73. {
  74. return { c1, x1, 0, c2, x2, 0, false };
  75. }
  76. bool ColourGradient::operator== (const ColourGradient& other) const noexcept
  77. {
  78. return point1 == other.point1 && point2 == other.point2
  79. && isRadial == other.isRadial
  80. && colours == other.colours;
  81. }
  82. bool ColourGradient::operator!= (const ColourGradient& other) const noexcept
  83. {
  84. return ! operator== (other);
  85. }
  86. //==============================================================================
  87. void ColourGradient::clearColours()
  88. {
  89. colours.clear();
  90. }
  91. int ColourGradient::addColour (const double proportionAlongGradient, Colour colour)
  92. {
  93. // must be within the two end-points
  94. jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0);
  95. if (proportionAlongGradient <= 0)
  96. {
  97. colours.set (0, { 0.0, colour });
  98. return 0;
  99. }
  100. auto pos = jmin (1.0, proportionAlongGradient);
  101. int i;
  102. for (i = 0; i < colours.size(); ++i)
  103. if (colours.getReference(i).position > pos)
  104. break;
  105. colours.insert (i, { pos, colour });
  106. return i;
  107. }
  108. void ColourGradient::removeColour (int index)
  109. {
  110. jassert (index > 0 && index < colours.size() - 1);
  111. colours.remove (index);
  112. }
  113. void ColourGradient::multiplyOpacity (const float multiplier) noexcept
  114. {
  115. for (auto& c : colours)
  116. c.colour = c.colour.withMultipliedAlpha (multiplier);
  117. }
  118. //==============================================================================
  119. int ColourGradient::getNumColours() const noexcept
  120. {
  121. return colours.size();
  122. }
  123. double ColourGradient::getColourPosition (int index) const noexcept
  124. {
  125. if (isPositiveAndBelow (index, colours.size()))
  126. return colours.getReference (index).position;
  127. return 0;
  128. }
  129. Colour ColourGradient::getColour (int index) const noexcept
  130. {
  131. if (isPositiveAndBelow (index, colours.size()))
  132. return colours.getReference (index).colour;
  133. return {};
  134. }
  135. void ColourGradient::setColour (int index, Colour newColour) noexcept
  136. {
  137. if (isPositiveAndBelow (index, colours.size()))
  138. colours.getReference (index).colour = newColour;
  139. }
  140. Colour ColourGradient::getColourAtPosition (double position) const noexcept
  141. {
  142. jassert (colours.getReference(0).position == 0.0); // the first colour specified has to go at position 0
  143. if (position <= 0 || colours.size() <= 1)
  144. return colours.getReference(0).colour;
  145. int i = colours.size() - 1;
  146. while (position < colours.getReference(i).position)
  147. --i;
  148. auto& p1 = colours.getReference (i);
  149. if (i >= colours.size() - 1)
  150. return p1.colour;
  151. auto& p2 = colours.getReference (i + 1);
  152. return p1.colour.interpolatedWith (p2.colour, (float) ((position - p1.position) / (p2.position - p1.position)));
  153. }
  154. //==============================================================================
  155. void ColourGradient::createLookupTable (PixelARGB* const lookupTable, const int numEntries) const noexcept
  156. {
  157. JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates?
  158. jassert (colours.size() >= 2);
  159. jassert (numEntries > 0);
  160. jassert (colours.getReference(0).position == 0.0); // The first colour specified has to go at position 0
  161. auto pix1 = colours.getReference (0).colour.getPixelARGB();
  162. int index = 0;
  163. for (int j = 1; j < colours.size(); ++j)
  164. {
  165. auto& p = colours.getReference (j);
  166. auto numToDo = roundToInt (p.position * (numEntries - 1)) - index;
  167. auto pix2 = p.colour.getPixelARGB();
  168. for (int i = 0; i < numToDo; ++i)
  169. {
  170. jassert (index >= 0 && index < numEntries);
  171. lookupTable[index] = pix1;
  172. lookupTable[index].tween (pix2, (uint32) ((i << 8) / numToDo));
  173. ++index;
  174. }
  175. pix1 = pix2;
  176. }
  177. while (index < numEntries)
  178. lookupTable [index++] = pix1;
  179. }
  180. int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlock<PixelARGB>& lookupTable) const
  181. {
  182. JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates?
  183. jassert (colours.size() >= 2);
  184. auto numEntries = jlimit (1, jmax (1, (colours.size() - 1) << 8),
  185. 3 * (int) point1.transformedBy (transform)
  186. .getDistanceFrom (point2.transformedBy (transform)));
  187. lookupTable.malloc (numEntries);
  188. createLookupTable (lookupTable, numEntries);
  189. return numEntries;
  190. }
  191. bool ColourGradient::isOpaque() const noexcept
  192. {
  193. for (auto& c : colours)
  194. if (! c.colour.isOpaque())
  195. return false;
  196. return true;
  197. }
  198. bool ColourGradient::isInvisible() const noexcept
  199. {
  200. for (auto& c : colours)
  201. if (! c.colour.isTransparent())
  202. return false;
  203. return true;
  204. }
  205. bool ColourGradient::ColourPoint::operator== (ColourPoint other) const noexcept
  206. {
  207. return position == other.position && colour == other.colour;
  208. }
  209. bool ColourGradient::ColourPoint::operator!= (ColourPoint other) const noexcept
  210. {
  211. return position != other.position || colour != other.colour;
  212. }
  213. } // namespace juce