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.

264 lines
8.0KB

  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. RelativePointPath::RelativePointPath()
  22. : usesNonZeroWinding (true),
  23. containsDynamicPoints (false)
  24. {
  25. }
  26. RelativePointPath::RelativePointPath (const RelativePointPath& other)
  27. : usesNonZeroWinding (true),
  28. containsDynamicPoints (false)
  29. {
  30. for (int i = 0; i < other.elements.size(); ++i)
  31. elements.add (other.elements.getUnchecked(i)->clone());
  32. }
  33. RelativePointPath::RelativePointPath (const Path& path)
  34. : usesNonZeroWinding (path.isUsingNonZeroWinding()),
  35. containsDynamicPoints (false)
  36. {
  37. for (Path::Iterator i (path); i.next();)
  38. {
  39. switch (i.elementType)
  40. {
  41. case Path::Iterator::startNewSubPath: elements.add (new StartSubPath (RelativePoint (i.x1, i.y1))); break;
  42. case Path::Iterator::lineTo: elements.add (new LineTo (RelativePoint (i.x1, i.y1))); break;
  43. case Path::Iterator::quadraticTo: elements.add (new QuadraticTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2))); break;
  44. case Path::Iterator::cubicTo: elements.add (new CubicTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2), RelativePoint (i.x3, i.y3))); break;
  45. case Path::Iterator::closePath: elements.add (new CloseSubPath()); break;
  46. default: jassertfalse; break;
  47. }
  48. }
  49. }
  50. RelativePointPath::~RelativePointPath()
  51. {
  52. }
  53. bool RelativePointPath::operator== (const RelativePointPath& other) const noexcept
  54. {
  55. if (elements.size() != other.elements.size()
  56. || usesNonZeroWinding != other.usesNonZeroWinding
  57. || containsDynamicPoints != other.containsDynamicPoints)
  58. return false;
  59. for (int i = 0; i < elements.size(); ++i)
  60. {
  61. ElementBase* const e1 = elements.getUnchecked(i);
  62. ElementBase* const e2 = other.elements.getUnchecked(i);
  63. if (e1->type != e2->type)
  64. return false;
  65. int numPoints1, numPoints2;
  66. const RelativePoint* const points1 = e1->getControlPoints (numPoints1);
  67. const RelativePoint* const points2 = e2->getControlPoints (numPoints2);
  68. jassert (numPoints1 == numPoints2);
  69. for (int j = numPoints1; --j >= 0;)
  70. if (points1[j] != points2[j])
  71. return false;
  72. }
  73. return true;
  74. }
  75. bool RelativePointPath::operator!= (const RelativePointPath& other) const noexcept
  76. {
  77. return ! operator== (other);
  78. }
  79. void RelativePointPath::swapWith (RelativePointPath& other) noexcept
  80. {
  81. elements.swapWith (other.elements);
  82. std::swap (usesNonZeroWinding, other.usesNonZeroWinding);
  83. std::swap (containsDynamicPoints, other.containsDynamicPoints);
  84. }
  85. void RelativePointPath::createPath (Path& path, Expression::Scope* scope) const
  86. {
  87. for (int i = 0; i < elements.size(); ++i)
  88. elements.getUnchecked(i)->addToPath (path, scope);
  89. }
  90. bool RelativePointPath::containsAnyDynamicPoints() const
  91. {
  92. return containsDynamicPoints;
  93. }
  94. void RelativePointPath::addElement (ElementBase* newElement)
  95. {
  96. if (newElement != nullptr)
  97. {
  98. elements.add (newElement);
  99. containsDynamicPoints = containsDynamicPoints || newElement->isDynamic();
  100. }
  101. }
  102. //==============================================================================
  103. RelativePointPath::ElementBase::ElementBase (const ElementType type_) : type (type_)
  104. {
  105. }
  106. bool RelativePointPath::ElementBase::isDynamic()
  107. {
  108. int numPoints;
  109. const RelativePoint* const points = getControlPoints (numPoints);
  110. for (int i = numPoints; --i >= 0;)
  111. if (points[i].isDynamic())
  112. return true;
  113. return false;
  114. }
  115. //==============================================================================
  116. RelativePointPath::StartSubPath::StartSubPath (const RelativePoint& pos)
  117. : ElementBase (startSubPathElement), startPos (pos)
  118. {
  119. }
  120. void RelativePointPath::StartSubPath::addToPath (Path& path, Expression::Scope* scope) const
  121. {
  122. path.startNewSubPath (startPos.resolve (scope));
  123. }
  124. RelativePoint* RelativePointPath::StartSubPath::getControlPoints (int& numPoints)
  125. {
  126. numPoints = 1;
  127. return &startPos;
  128. }
  129. RelativePointPath::ElementBase* RelativePointPath::StartSubPath::clone() const
  130. {
  131. return new StartSubPath (startPos);
  132. }
  133. //==============================================================================
  134. RelativePointPath::CloseSubPath::CloseSubPath()
  135. : ElementBase (closeSubPathElement)
  136. {
  137. }
  138. void RelativePointPath::CloseSubPath::addToPath (Path& path, Expression::Scope*) const
  139. {
  140. path.closeSubPath();
  141. }
  142. RelativePoint* RelativePointPath::CloseSubPath::getControlPoints (int& numPoints)
  143. {
  144. numPoints = 0;
  145. return nullptr;
  146. }
  147. RelativePointPath::ElementBase* RelativePointPath::CloseSubPath::clone() const
  148. {
  149. return new CloseSubPath();
  150. }
  151. //==============================================================================
  152. RelativePointPath::LineTo::LineTo (const RelativePoint& endPoint_)
  153. : ElementBase (lineToElement), endPoint (endPoint_)
  154. {
  155. }
  156. void RelativePointPath::LineTo::addToPath (Path& path, Expression::Scope* scope) const
  157. {
  158. path.lineTo (endPoint.resolve (scope));
  159. }
  160. RelativePoint* RelativePointPath::LineTo::getControlPoints (int& numPoints)
  161. {
  162. numPoints = 1;
  163. return &endPoint;
  164. }
  165. RelativePointPath::ElementBase* RelativePointPath::LineTo::clone() const
  166. {
  167. return new LineTo (endPoint);
  168. }
  169. //==============================================================================
  170. RelativePointPath::QuadraticTo::QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint)
  171. : ElementBase (quadraticToElement)
  172. {
  173. controlPoints[0] = controlPoint;
  174. controlPoints[1] = endPoint;
  175. }
  176. void RelativePointPath::QuadraticTo::addToPath (Path& path, Expression::Scope* scope) const
  177. {
  178. path.quadraticTo (controlPoints[0].resolve (scope),
  179. controlPoints[1].resolve (scope));
  180. }
  181. RelativePoint* RelativePointPath::QuadraticTo::getControlPoints (int& numPoints)
  182. {
  183. numPoints = 2;
  184. return controlPoints;
  185. }
  186. RelativePointPath::ElementBase* RelativePointPath::QuadraticTo::clone() const
  187. {
  188. return new QuadraticTo (controlPoints[0], controlPoints[1]);
  189. }
  190. //==============================================================================
  191. RelativePointPath::CubicTo::CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint)
  192. : ElementBase (cubicToElement)
  193. {
  194. controlPoints[0] = controlPoint1;
  195. controlPoints[1] = controlPoint2;
  196. controlPoints[2] = endPoint;
  197. }
  198. void RelativePointPath::CubicTo::addToPath (Path& path, Expression::Scope* scope) const
  199. {
  200. path.cubicTo (controlPoints[0].resolve (scope),
  201. controlPoints[1].resolve (scope),
  202. controlPoints[2].resolve (scope));
  203. }
  204. RelativePoint* RelativePointPath::CubicTo::getControlPoints (int& numPoints)
  205. {
  206. numPoints = 3;
  207. return controlPoints;
  208. }
  209. RelativePointPath::ElementBase* RelativePointPath::CubicTo::clone() const
  210. {
  211. return new CubicTo (controlPoints[0], controlPoints[1], controlPoints[2]);
  212. }
  213. } // namespace juce