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.

245 lines
7.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  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 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. ColourGradient::ColourGradient() noexcept
  22. {
  23. #if JUCE_DEBUG
  24. point1.setX (987654.0f);
  25. #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED jassert (point1.x != 987654.0f);
  26. #else
  27. #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED
  28. #endif
  29. }
  30. ColourGradient::ColourGradient (Colour colour1, const float x1, const float y1,
  31. Colour colour2, const float x2, const float y2,
  32. const bool radial)
  33. : point1 (x1, y1),
  34. point2 (x2, y2),
  35. isRadial (radial)
  36. {
  37. colours.add (ColourPoint (0.0, colour1));
  38. colours.add (ColourPoint (1.0, colour2));
  39. }
  40. ColourGradient::ColourGradient (Colour colour1, Point<float> p1,
  41. Colour colour2, Point<float> p2,
  42. const bool radial)
  43. : point1 (p1),
  44. point2 (p2),
  45. isRadial (radial)
  46. {
  47. colours.add (ColourPoint (0.0, colour1));
  48. colours.add (ColourPoint (1.0, colour2));
  49. }
  50. ColourGradient::~ColourGradient()
  51. {
  52. }
  53. bool ColourGradient::operator== (const ColourGradient& other) const noexcept
  54. {
  55. return point1 == other.point1 && point2 == other.point2
  56. && isRadial == other.isRadial
  57. && colours == other.colours;
  58. }
  59. bool ColourGradient::operator!= (const ColourGradient& other) const noexcept
  60. {
  61. return ! operator== (other);
  62. }
  63. //==============================================================================
  64. void ColourGradient::clearColours()
  65. {
  66. colours.clear();
  67. }
  68. int ColourGradient::addColour (const double proportionAlongGradient, Colour colour)
  69. {
  70. // must be within the two end-points
  71. jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0);
  72. if (proportionAlongGradient <= 0)
  73. {
  74. colours.set (0, ColourPoint (0.0, colour));
  75. return 0;
  76. }
  77. const double pos = jmin (1.0, proportionAlongGradient);
  78. int i;
  79. for (i = 0; i < colours.size(); ++i)
  80. if (colours.getReference(i).position > pos)
  81. break;
  82. colours.insert (i, ColourPoint (pos, colour));
  83. return i;
  84. }
  85. void ColourGradient::removeColour (int index)
  86. {
  87. jassert (index > 0 && index < colours.size() - 1);
  88. colours.remove (index);
  89. }
  90. void ColourGradient::multiplyOpacity (const float multiplier) noexcept
  91. {
  92. for (int i = 0; i < colours.size(); ++i)
  93. {
  94. Colour& c = colours.getReference(i).colour;
  95. c = c.withMultipliedAlpha (multiplier);
  96. }
  97. }
  98. //==============================================================================
  99. int ColourGradient::getNumColours() const noexcept
  100. {
  101. return colours.size();
  102. }
  103. double ColourGradient::getColourPosition (const int index) const noexcept
  104. {
  105. if (isPositiveAndBelow (index, colours.size()))
  106. return colours.getReference (index).position;
  107. return 0;
  108. }
  109. Colour ColourGradient::getColour (const int index) const noexcept
  110. {
  111. if (isPositiveAndBelow (index, colours.size()))
  112. return colours.getReference (index).colour;
  113. return Colour();
  114. }
  115. void ColourGradient::setColour (int index, Colour newColour) noexcept
  116. {
  117. if (isPositiveAndBelow (index, colours.size()))
  118. colours.getReference (index).colour = newColour;
  119. }
  120. Colour ColourGradient::getColourAtPosition (const double position) const noexcept
  121. {
  122. jassert (colours.getReference(0).position == 0.0); // the first colour specified has to go at position 0
  123. if (position <= 0 || colours.size() <= 1)
  124. return colours.getReference(0).colour;
  125. int i = colours.size() - 1;
  126. while (position < colours.getReference(i).position)
  127. --i;
  128. auto& p1 = colours.getReference (i);
  129. if (i >= colours.size() - 1)
  130. return p1.colour;
  131. auto& p2 = colours.getReference (i + 1);
  132. return p1.colour.interpolatedWith (p2.colour, (float) ((position - p1.position) / (p2.position - p1.position)));
  133. }
  134. //==============================================================================
  135. void ColourGradient::createLookupTable (PixelARGB* const lookupTable, const int numEntries) const noexcept
  136. {
  137. JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates?
  138. jassert (colours.size() >= 2);
  139. jassert (numEntries > 0);
  140. jassert (colours.getReference(0).position == 0.0); // The first colour specified has to go at position 0
  141. PixelARGB pix1 (colours.getReference (0).colour.getPixelARGB());
  142. int index = 0;
  143. for (int j = 1; j < colours.size(); ++j)
  144. {
  145. const ColourPoint& p = colours.getReference (j);
  146. const int numToDo = roundToInt (p.position * (numEntries - 1)) - index;
  147. const PixelARGB pix2 (p.colour.getPixelARGB());
  148. for (int i = 0; i < numToDo; ++i)
  149. {
  150. jassert (index >= 0 && index < numEntries);
  151. lookupTable[index] = pix1;
  152. lookupTable[index].tween (pix2, (uint32) ((i << 8) / numToDo));
  153. ++index;
  154. }
  155. pix1 = pix2;
  156. }
  157. while (index < numEntries)
  158. lookupTable [index++] = pix1;
  159. }
  160. int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlock<PixelARGB>& lookupTable) const
  161. {
  162. JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates?
  163. jassert (colours.size() >= 2);
  164. const int numEntries = jlimit (1, jmax (1, (colours.size() - 1) << 8),
  165. 3 * (int) point1.transformedBy (transform)
  166. .getDistanceFrom (point2.transformedBy (transform)));
  167. lookupTable.malloc ((size_t) numEntries);
  168. createLookupTable (lookupTable, numEntries);
  169. return numEntries;
  170. }
  171. bool ColourGradient::isOpaque() const noexcept
  172. {
  173. for (int i = 0; i < colours.size(); ++i)
  174. if (! colours.getReference(i).colour.isOpaque())
  175. return false;
  176. return true;
  177. }
  178. bool ColourGradient::isInvisible() const noexcept
  179. {
  180. for (int i = 0; i < colours.size(); ++i)
  181. if (! colours.getReference(i).colour.isTransparent())
  182. return false;
  183. return true;
  184. }
  185. bool ColourGradient::ColourPoint::operator== (const ColourPoint& other) const noexcept
  186. {
  187. return position == other.position && colour == other.colour;
  188. }
  189. bool ColourGradient::ColourPoint::operator!= (const ColourPoint& other) const noexcept
  190. {
  191. return position != other.position || colour != other.colour;
  192. }
  193. } // namespace juce