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.

263 lines
10.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - 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 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-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. #ifndef DOXYGEN
  21. namespace detail
  22. {
  23. class BoundsChangeListener final : private ComponentListener
  24. {
  25. public:
  26. BoundsChangeListener (Component& c, std::function<void()> cb)
  27. : callback (std::move (cb)),
  28. componentListenerGuard { [comp = &c, this] { comp->removeComponentListener (this); } }
  29. {
  30. jassert (callback != nullptr);
  31. c.addComponentListener (this);
  32. }
  33. private:
  34. void componentMovedOrResized (Component&, bool, bool) override
  35. {
  36. callback();
  37. }
  38. std::function<void()> callback;
  39. ErasedScopeGuard componentListenerGuard;
  40. };
  41. } // namespace detail
  42. #endif
  43. //==============================================================================
  44. /**
  45. The base class for objects which can draw themselves, e.g. polygons, images, etc.
  46. @see DrawableComposite, DrawableImage, DrawablePath, DrawableText
  47. @tags{GUI}
  48. */
  49. class JUCE_API Drawable : public Component
  50. {
  51. protected:
  52. //==============================================================================
  53. /** The base class can't be instantiated directly.
  54. @see DrawableComposite, DrawableImage, DrawablePath, DrawableText
  55. */
  56. Drawable();
  57. public:
  58. /** Destructor. */
  59. ~Drawable() override;
  60. //==============================================================================
  61. /** Creates a deep copy of this Drawable object.
  62. Use this to create a new copy of this and any sub-objects in the tree.
  63. */
  64. virtual std::unique_ptr<Drawable> createCopy() const = 0;
  65. /** Creates a path that describes the outline of this drawable. */
  66. virtual Path getOutlineAsPath() const = 0;
  67. //==============================================================================
  68. /** Renders this Drawable object.
  69. Note that the preferred way to render a drawable in future is by using it
  70. as a component and adding it to a parent, so you might want to consider that
  71. before using this method.
  72. @see drawWithin
  73. */
  74. void draw (Graphics& g, float opacity,
  75. const AffineTransform& transform = AffineTransform()) const;
  76. /** Renders the Drawable at a given offset within the Graphics context.
  77. The coordinates passed-in are used to translate the object relative to its own
  78. origin before drawing it - this is basically a quick way of saying:
  79. @code
  80. draw (g, AffineTransform::translation (x, y)).
  81. @endcode
  82. Note that the preferred way to render a drawable in future is by using it
  83. as a component and adding it to a parent, so you might want to consider that
  84. before using this method.
  85. */
  86. void drawAt (Graphics& g, float x, float y, float opacity) const;
  87. /** Renders the Drawable within a rectangle, scaling it to fit neatly inside without
  88. changing its aspect-ratio.
  89. The object can placed arbitrarily within the rectangle based on a Justification type,
  90. and can either be made as big as possible, or just reduced to fit.
  91. Note that the preferred way to render a drawable in future is by using it
  92. as a component and adding it to a parent, so you might want to consider that
  93. before using this method.
  94. @param g the graphics context to render onto
  95. @param destArea the target rectangle to fit the drawable into
  96. @param placement defines the alignment and rescaling to use to fit
  97. this object within the target rectangle.
  98. @param opacity the opacity to use, in the range 0 to 1.0
  99. */
  100. void drawWithin (Graphics& g,
  101. Rectangle<float> destArea,
  102. RectanglePlacement placement,
  103. float opacity) const;
  104. //==============================================================================
  105. /** Resets any transformations on this drawable, and positions its origin within
  106. its parent component.
  107. */
  108. void setOriginWithOriginalSize (Point<float> originWithinParent);
  109. /** Sets a transform for this drawable that will position it within the specified
  110. area of its parent component.
  111. */
  112. void setTransformToFit (const Rectangle<float>& areaInParent, RectanglePlacement placement);
  113. /** Returns the DrawableComposite that contains this object, if there is one. */
  114. DrawableComposite* getParent() const;
  115. /** Sets a the clipping region of this drawable using another drawable.
  116. The drawable passed in will be deleted when no longer needed.
  117. */
  118. void setClipPath (std::unique_ptr<Drawable> drawableClipPath);
  119. //==============================================================================
  120. /** Tries to turn some kind of image file into a drawable.
  121. The data could be an image that the ImageFileFormat class understands, or it
  122. could be SVG.
  123. */
  124. static std::unique_ptr<Drawable> createFromImageData (const void* data, size_t numBytes);
  125. /** Tries to turn a stream containing some kind of image data into a drawable.
  126. The data could be an image that the ImageFileFormat class understands, or it
  127. could be SVG.
  128. */
  129. static std::unique_ptr<Drawable> createFromImageDataStream (InputStream& dataSource);
  130. /** Tries to turn a file containing some kind of image data into a drawable.
  131. The data could be an image that the ImageFileFormat class understands, or it
  132. could be SVG.
  133. */
  134. static std::unique_ptr<Drawable> createFromImageFile (const File& file);
  135. /** Attempts to parse an SVG (Scalable Vector Graphics) document, and to turn this
  136. into a Drawable tree.
  137. If something goes wrong while parsing, it may return nullptr.
  138. SVG is a pretty large and complex spec, and this doesn't aim to be a full
  139. implementation, but it can return the basic vector objects.
  140. */
  141. static std::unique_ptr<Drawable> createFromSVG (const XmlElement& svgDocument);
  142. /** Attempts to parse an SVG (Scalable Vector Graphics) document from a file,
  143. and to turn this into a Drawable tree.
  144. If something goes wrong while parsing, it may return nullptr.
  145. SVG is a pretty large and complex spec, and this doesn't aim to be a full
  146. implementation, but it can return the basic vector objects.
  147. Any references to references to external image files will be relative to
  148. the parent directory of the file passed.
  149. */
  150. static std::unique_ptr<Drawable> createFromSVGFile (const File& svgFile);
  151. /** Parses an SVG path string and returns it. */
  152. static Path parseSVGPath (const String& svgPath);
  153. //==============================================================================
  154. /** Returns the area that this drawable covers.
  155. The result is expressed in this drawable's own coordinate space, and does not take
  156. into account any transforms that may be applied to the component.
  157. */
  158. virtual Rectangle<float> getDrawableBounds() const = 0;
  159. /** Recursively replaces a colour that might be used for filling or stroking.
  160. return true if any instances of this colour were found.
  161. */
  162. virtual bool replaceColour (Colour originalColour, Colour replacementColour);
  163. /** Sets a transformation that applies to the same coordinate system in which the rest of the
  164. draw calls are made. You almost certainly want to call this function when working with
  165. Drawables as opposed to Component::setTransform().
  166. The reason for this is that the origin of a Drawable is not the same as the point returned
  167. by Component::getPosition() but has an additional offset internal to the Drawable class.
  168. Using setDrawableTransform() will take this internal offset into account when applying the
  169. transform to the Component base.
  170. You can only use Drawable::setDrawableTransform() or Component::setTransform() for a given
  171. object. Using both will lead to unpredictable behaviour.
  172. */
  173. void setDrawableTransform (const AffineTransform& transform);
  174. protected:
  175. //==============================================================================
  176. friend class DrawableComposite;
  177. friend class DrawableShape;
  178. /** @internal */
  179. void transformContextToCorrectOrigin (Graphics&);
  180. /** @internal */
  181. void parentHierarchyChanged() override;
  182. /** @internal */
  183. void setBoundsToEnclose (Rectangle<float>);
  184. /** @internal */
  185. void applyDrawableClipPath (Graphics&);
  186. Point<int> originRelativeToComponent;
  187. std::unique_ptr<Drawable> drawableClipPath;
  188. AffineTransform drawableTransform;
  189. void nonConstDraw (Graphics&, float opacity, const AffineTransform&);
  190. Drawable (const Drawable&);
  191. Drawable& operator= (const Drawable&);
  192. JUCE_LEAK_DETECTOR (Drawable)
  193. private:
  194. void updateTransform();
  195. detail::BoundsChangeListener boundsChangeListener { *this, [this] { updateTransform(); } };
  196. };
  197. } // namespace juce