Audio plugin host https://kx.studio/carla
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.

301 lines
13KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. //==============================================================================
  21. /**
  22. Represents a 2D affine-transformation matrix.
  23. An affine transformation is a transformation such as a rotation, scale, shear,
  24. resize or translation.
  25. These are used for various 2D transformation tasks, e.g. with Path objects.
  26. @see Path, Point, Line
  27. @tags{Graphics}
  28. */
  29. class JUCE_API AffineTransform final
  30. {
  31. public:
  32. //==============================================================================
  33. /** Creates an identity transform. */
  34. AffineTransform() = default;
  35. /** Creates a copy of another transform. */
  36. AffineTransform (const AffineTransform&) = default;
  37. /** Creates a transform from a set of raw matrix values.
  38. The resulting matrix is:
  39. (mat00 mat01 mat02)
  40. (mat10 mat11 mat12)
  41. ( 0 0 1 )
  42. */
  43. AffineTransform (float mat00, float mat01, float mat02,
  44. float mat10, float mat11, float mat12) noexcept;
  45. /** Copies from another AffineTransform object */
  46. AffineTransform& operator= (const AffineTransform&) = default;
  47. /** Compares two transforms. */
  48. bool operator== (const AffineTransform& other) const noexcept;
  49. /** Compares two transforms. */
  50. bool operator!= (const AffineTransform& other) const noexcept;
  51. //==============================================================================
  52. /** Transforms a 2D coordinate using this matrix. */
  53. template <typename ValueType>
  54. void transformPoint (ValueType& x, ValueType& y) const noexcept
  55. {
  56. auto oldX = x;
  57. x = static_cast<ValueType> (mat00 * oldX + mat01 * y + mat02);
  58. y = static_cast<ValueType> (mat10 * oldX + mat11 * y + mat12);
  59. }
  60. /** Transforms two 2D coordinates using this matrix.
  61. This is just a shortcut for calling transformPoint() on each of these pairs of
  62. coordinates in turn. (And putting all the calculations into one function hopefully
  63. also gives the compiler a bit more scope for pipelining it).
  64. */
  65. template <typename ValueType>
  66. void transformPoints (ValueType& x1, ValueType& y1,
  67. ValueType& x2, ValueType& y2) const noexcept
  68. {
  69. auto oldX1 = x1, oldX2 = x2;
  70. x1 = static_cast<ValueType> (mat00 * oldX1 + mat01 * y1 + mat02);
  71. y1 = static_cast<ValueType> (mat10 * oldX1 + mat11 * y1 + mat12);
  72. x2 = static_cast<ValueType> (mat00 * oldX2 + mat01 * y2 + mat02);
  73. y2 = static_cast<ValueType> (mat10 * oldX2 + mat11 * y2 + mat12);
  74. }
  75. /** Transforms three 2D coordinates using this matrix.
  76. This is just a shortcut for calling transformPoint() on each of these pairs of
  77. coordinates in turn. (And putting all the calculations into one function hopefully
  78. also gives the compiler a bit more scope for pipelining it).
  79. */
  80. template <typename ValueType>
  81. void transformPoints (ValueType& x1, ValueType& y1,
  82. ValueType& x2, ValueType& y2,
  83. ValueType& x3, ValueType& y3) const noexcept
  84. {
  85. auto oldX1 = x1, oldX2 = x2, oldX3 = x3;
  86. x1 = static_cast<ValueType> (mat00 * oldX1 + mat01 * y1 + mat02);
  87. y1 = static_cast<ValueType> (mat10 * oldX1 + mat11 * y1 + mat12);
  88. x2 = static_cast<ValueType> (mat00 * oldX2 + mat01 * y2 + mat02);
  89. y2 = static_cast<ValueType> (mat10 * oldX2 + mat11 * y2 + mat12);
  90. x3 = static_cast<ValueType> (mat00 * oldX3 + mat01 * y3 + mat02);
  91. y3 = static_cast<ValueType> (mat10 * oldX3 + mat11 * y3 + mat12);
  92. }
  93. //==============================================================================
  94. /** Returns a new transform which is the same as this one followed by a translation. */
  95. AffineTransform translated (float deltaX,
  96. float deltaY) const noexcept;
  97. /** Returns a new transform which is the same as this one followed by a translation. */
  98. template <typename PointType>
  99. AffineTransform translated (PointType delta) const noexcept
  100. {
  101. return translated ((float) delta.x, (float) delta.y);
  102. }
  103. /** Returns a new transform which is a translation. */
  104. static AffineTransform translation (float deltaX,
  105. float deltaY) noexcept;
  106. /** Returns a new transform which is a translation. */
  107. template <typename PointType>
  108. static AffineTransform translation (PointType delta) noexcept
  109. {
  110. return translation ((float) delta.x, (float) delta.y);
  111. }
  112. /** Returns a copy of this transform with the specified translation matrix values. */
  113. AffineTransform withAbsoluteTranslation (float translationX,
  114. float translationY) const noexcept;
  115. /** Returns a transform which is the same as this one followed by a rotation.
  116. The rotation is specified by a number of radians to rotate clockwise, centred around
  117. the origin (0, 0).
  118. */
  119. AffineTransform rotated (float angleInRadians) const noexcept;
  120. /** Returns a transform which is the same as this one followed by a rotation about a given point.
  121. The rotation is specified by a number of radians to rotate clockwise, centred around
  122. the coordinates passed in.
  123. */
  124. AffineTransform rotated (float angleInRadians,
  125. float pivotX,
  126. float pivotY) const noexcept;
  127. /** Returns a new transform which is a rotation about (0, 0). */
  128. static AffineTransform rotation (float angleInRadians) noexcept;
  129. /** Returns a new transform which is a rotation about a given point. */
  130. static AffineTransform rotation (float angleInRadians,
  131. float pivotX,
  132. float pivotY) noexcept;
  133. /** Returns a transform which is the same as this one followed by a re-scaling.
  134. The scaling is centred around the origin (0, 0).
  135. */
  136. AffineTransform scaled (float factorX,
  137. float factorY) const noexcept;
  138. /** Returns a transform which is the same as this one followed by a re-scaling.
  139. The scaling is centred around the origin (0, 0).
  140. */
  141. AffineTransform scaled (float factor) const noexcept;
  142. /** Returns a transform which is the same as this one followed by a re-scaling.
  143. The scaling is centred around the origin provided.
  144. */
  145. AffineTransform scaled (float factorX, float factorY,
  146. float pivotX, float pivotY) const noexcept;
  147. /** Returns a new transform which is a re-scale about the origin. */
  148. static AffineTransform scale (float factorX,
  149. float factorY) noexcept;
  150. /** Returns a new transform which is a re-scale about the origin. */
  151. static AffineTransform scale (float factor) noexcept;
  152. /** Returns a new transform which is a re-scale centred around the point provided. */
  153. static AffineTransform scale (float factorX, float factorY,
  154. float pivotX, float pivotY) noexcept;
  155. /** Returns a transform which is the same as this one followed by a shear.
  156. The shear is centred around the origin (0, 0).
  157. */
  158. AffineTransform sheared (float shearX, float shearY) const noexcept;
  159. /** Returns a shear transform, centred around the origin (0, 0). */
  160. static AffineTransform shear (float shearX, float shearY) noexcept;
  161. /** Returns a transform that will flip coordinates vertically within a window of the given height.
  162. This is handy for converting between upside-down coordinate systems such as OpenGL or CoreGraphics.
  163. */
  164. static AffineTransform verticalFlip (float height) noexcept;
  165. /** Returns a matrix which is the inverse operation of this one.
  166. Some matrices don't have an inverse - in this case, the method will just return
  167. an identity transform.
  168. */
  169. AffineTransform inverted() const noexcept;
  170. /** Returns the transform that will map three known points onto three coordinates
  171. that are supplied.
  172. This returns the transform that will transform (0, 0) into (x00, y00),
  173. (1, 0) to (x10, y10), and (0, 1) to (x01, y01).
  174. */
  175. static AffineTransform fromTargetPoints (float x00, float y00,
  176. float x10, float y10,
  177. float x01, float y01) noexcept;
  178. /** Returns the transform that will map three specified points onto three target points. */
  179. static AffineTransform fromTargetPoints (float sourceX1, float sourceY1, float targetX1, float targetY1,
  180. float sourceX2, float sourceY2, float targetX2, float targetY2,
  181. float sourceX3, float sourceY3, float targetX3, float targetY3) noexcept;
  182. /** Returns the transform that will map three specified points onto three target points. */
  183. template <typename PointType>
  184. static AffineTransform fromTargetPoints (PointType source1, PointType target1,
  185. PointType source2, PointType target2,
  186. PointType source3, PointType target3) noexcept
  187. {
  188. return fromTargetPoints (source1.x, source1.y, target1.x, target1.y,
  189. source2.x, source2.y, target2.x, target2.y,
  190. source3.x, source3.y, target3.x, target3.y);
  191. }
  192. //==============================================================================
  193. /** Returns the result of concatenating another transformation after this one. */
  194. AffineTransform followedBy (const AffineTransform& other) const noexcept;
  195. /** Returns true if this transform has no effect on points. */
  196. bool isIdentity() const noexcept;
  197. /** Returns true if this transform maps to a singularity - i.e. if it has no inverse. */
  198. bool isSingularity() const noexcept;
  199. /** Returns true if the transform only translates, and doesn't scale or rotate the
  200. points. */
  201. bool isOnlyTranslation() const noexcept;
  202. /** If this transform is only a translation, this returns the X offset.
  203. @see isOnlyTranslation
  204. */
  205. float getTranslationX() const noexcept { return mat02; }
  206. /** If this transform is only a translation, this returns the X offset.
  207. @see isOnlyTranslation
  208. */
  209. float getTranslationY() const noexcept { return mat12; }
  210. /** Returns the determinant of the transform. */
  211. float getDeterminant() const noexcept;
  212. /** This method has been deprecated.
  213. You can calculate the scale factor using:
  214. @code
  215. std::sqrt (std::abs (AffineTransform::getDeterminant()))
  216. @endcode
  217. This method produces incorrect values for transforms containing rotations.
  218. Returns the approximate scale factor by which lengths will be transformed.
  219. Obviously a length may be scaled by entirely different amounts depending on its
  220. direction, so this is only appropriate as a rough guide.
  221. */
  222. JUCE_DEPRECATED (float getScaleFactor() const noexcept);
  223. /* A ready-to-use identity transform - now deprecated.
  224. @deprecated If you need an identity transform, just use AffineTransform() or {}.
  225. */
  226. JUCE_DEPRECATED_STATIC (static const AffineTransform identity;)
  227. //==============================================================================
  228. /* The transform matrix is:
  229. (mat00 mat01 mat02)
  230. (mat10 mat11 mat12)
  231. ( 0 0 1 )
  232. */
  233. float mat00 { 1.0f }, mat01 { 0.0f }, mat02 { 0.0f };
  234. float mat10 { 0.0f }, mat11 { 1.0f }, mat12 { 0.0f };
  235. };
  236. } // namespace juce