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.

222 lines
7.2KB

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