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.

300 lines
9.8KB

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