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.

228 lines
7.3KB

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