The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

238 lines
7.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. ColourGradient::ColourGradient() noexcept
  18. {
  19. #if JUCE_DEBUG
  20. point1.setX (987654.0f);
  21. #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED jassert (point1.x != 987654.0f);
  22. #else
  23. #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED
  24. #endif
  25. }
  26. ColourGradient::ColourGradient (Colour colour1, const float x1, const float y1,
  27. Colour colour2, const float x2, const float y2,
  28. const bool radial)
  29. : point1 (x1, y1),
  30. point2 (x2, y2),
  31. isRadial (radial)
  32. {
  33. colours.add (ColourPoint (0.0, colour1));
  34. colours.add (ColourPoint (1.0, colour2));
  35. }
  36. ColourGradient::ColourGradient (Colour colour1, Point<float> p1,
  37. Colour colour2, Point<float> p2,
  38. const bool radial)
  39. : point1 (p1),
  40. point2 (p2),
  41. isRadial (radial)
  42. {
  43. colours.add (ColourPoint (0.0, colour1));
  44. colours.add (ColourPoint (1.0, colour2));
  45. }
  46. ColourGradient::~ColourGradient()
  47. {
  48. }
  49. bool ColourGradient::operator== (const ColourGradient& other) const noexcept
  50. {
  51. return point1 == other.point1 && point2 == other.point2
  52. && isRadial == other.isRadial
  53. && colours == other.colours;
  54. }
  55. bool ColourGradient::operator!= (const ColourGradient& other) const noexcept
  56. {
  57. return ! operator== (other);
  58. }
  59. //==============================================================================
  60. void ColourGradient::clearColours()
  61. {
  62. colours.clear();
  63. }
  64. int ColourGradient::addColour (const double proportionAlongGradient, Colour colour)
  65. {
  66. // must be within the two end-points
  67. jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0);
  68. if (proportionAlongGradient <= 0)
  69. {
  70. colours.set (0, ColourPoint (0.0, colour));
  71. return 0;
  72. }
  73. const double pos = jmin (1.0, proportionAlongGradient);
  74. int i;
  75. for (i = 0; i < colours.size(); ++i)
  76. if (colours.getReference(i).position > pos)
  77. break;
  78. colours.insert (i, ColourPoint (pos, colour));
  79. return i;
  80. }
  81. void ColourGradient::removeColour (int index)
  82. {
  83. jassert (index > 0 && index < colours.size() - 1);
  84. colours.remove (index);
  85. }
  86. void ColourGradient::multiplyOpacity (const float multiplier) noexcept
  87. {
  88. for (int i = 0; i < colours.size(); ++i)
  89. {
  90. Colour& c = colours.getReference(i).colour;
  91. c = c.withMultipliedAlpha (multiplier);
  92. }
  93. }
  94. //==============================================================================
  95. int ColourGradient::getNumColours() const noexcept
  96. {
  97. return colours.size();
  98. }
  99. double ColourGradient::getColourPosition (const int index) const noexcept
  100. {
  101. if (isPositiveAndBelow (index, colours.size()))
  102. return colours.getReference (index).position;
  103. return 0;
  104. }
  105. Colour ColourGradient::getColour (const int index) const noexcept
  106. {
  107. if (isPositiveAndBelow (index, colours.size()))
  108. return colours.getReference (index).colour;
  109. return Colour();
  110. }
  111. void ColourGradient::setColour (int index, Colour newColour) noexcept
  112. {
  113. if (isPositiveAndBelow (index, colours.size()))
  114. colours.getReference (index).colour = newColour;
  115. }
  116. Colour ColourGradient::getColourAtPosition (const double position) const noexcept
  117. {
  118. jassert (colours.getReference(0).position == 0.0); // the first colour specified has to go at position 0
  119. if (position <= 0 || colours.size() <= 1)
  120. return colours.getReference(0).colour;
  121. int i = colours.size() - 1;
  122. while (position < colours.getReference(i).position)
  123. --i;
  124. auto& p1 = colours.getReference (i);
  125. if (i >= colours.size() - 1)
  126. return p1.colour;
  127. auto& p2 = colours.getReference (i + 1);
  128. return p1.colour.interpolatedWith (p2.colour, (float) ((position - p1.position) / (p2.position - p1.position)));
  129. }
  130. //==============================================================================
  131. void ColourGradient::createLookupTable (PixelARGB* const lookupTable, const int numEntries) const noexcept
  132. {
  133. JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates?
  134. jassert (colours.size() >= 2);
  135. jassert (numEntries > 0);
  136. jassert (colours.getReference(0).position == 0.0); // The first colour specified has to go at position 0
  137. PixelARGB pix1 (colours.getReference (0).colour.getPixelARGB());
  138. int index = 0;
  139. for (int j = 1; j < colours.size(); ++j)
  140. {
  141. const ColourPoint& p = colours.getReference (j);
  142. const int numToDo = roundToInt (p.position * (numEntries - 1)) - index;
  143. const PixelARGB pix2 (p.colour.getPixelARGB());
  144. for (int i = 0; i < numToDo; ++i)
  145. {
  146. jassert (index >= 0 && index < numEntries);
  147. lookupTable[index] = pix1;
  148. lookupTable[index].tween (pix2, (uint32) ((i << 8) / numToDo));
  149. ++index;
  150. }
  151. pix1 = pix2;
  152. }
  153. while (index < numEntries)
  154. lookupTable [index++] = pix1;
  155. }
  156. int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlock<PixelARGB>& lookupTable) const
  157. {
  158. JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates?
  159. jassert (colours.size() >= 2);
  160. const int numEntries = jlimit (1, jmax (1, (colours.size() - 1) << 8),
  161. 3 * (int) point1.transformedBy (transform)
  162. .getDistanceFrom (point2.transformedBy (transform)));
  163. lookupTable.malloc ((size_t) numEntries);
  164. createLookupTable (lookupTable, numEntries);
  165. return numEntries;
  166. }
  167. bool ColourGradient::isOpaque() const noexcept
  168. {
  169. for (int i = 0; i < colours.size(); ++i)
  170. if (! colours.getReference(i).colour.isOpaque())
  171. return false;
  172. return true;
  173. }
  174. bool ColourGradient::isInvisible() const noexcept
  175. {
  176. for (int i = 0; i < colours.size(); ++i)
  177. if (! colours.getReference(i).colour.isTransparent())
  178. return false;
  179. return true;
  180. }
  181. bool ColourGradient::ColourPoint::operator== (const ColourPoint& other) const noexcept
  182. {
  183. return position == other.position && colour == other.colour;
  184. }
  185. bool ColourGradient::ColourPoint::operator!= (const ColourPoint& other) const noexcept
  186. {
  187. return position != other.position || colour != other.colour;
  188. }