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.

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