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.

216 lines
6.1KB

  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. Drawable::Drawable()
  22. {
  23. setInterceptsMouseClicks (false, false);
  24. setPaintingIsUnclipped (true);
  25. }
  26. Drawable::Drawable (const Drawable& other)
  27. : Component (other.getName())
  28. {
  29. setInterceptsMouseClicks (false, false);
  30. setPaintingIsUnclipped (true);
  31. setComponentID (other.getComponentID());
  32. setTransform (other.getTransform());
  33. if (auto* clipPath = other.drawableClipPath.get())
  34. setClipPath (clipPath->createCopy());
  35. }
  36. Drawable::~Drawable()
  37. {
  38. }
  39. void Drawable::applyDrawableClipPath (Graphics& g)
  40. {
  41. if (drawableClipPath != nullptr)
  42. {
  43. auto clipPath = drawableClipPath->getOutlineAsPath();
  44. if (! clipPath.isEmpty())
  45. g.getInternalContext().clipToPath (clipPath, {});
  46. }
  47. }
  48. //==============================================================================
  49. void Drawable::draw (Graphics& g, float opacity, const AffineTransform& transform) const
  50. {
  51. const_cast<Drawable*> (this)->nonConstDraw (g, opacity, transform);
  52. }
  53. void Drawable::nonConstDraw (Graphics& g, float opacity, const AffineTransform& transform)
  54. {
  55. Graphics::ScopedSaveState ss (g);
  56. g.addTransform (AffineTransform::translation ((float) -(originRelativeToComponent.x),
  57. (float) -(originRelativeToComponent.y))
  58. .followedBy (getTransform())
  59. .followedBy (transform));
  60. applyDrawableClipPath (g);
  61. if (! g.isClipEmpty())
  62. {
  63. if (opacity < 1.0f)
  64. {
  65. g.beginTransparencyLayer (opacity);
  66. paintEntireComponent (g, true);
  67. g.endTransparencyLayer();
  68. }
  69. else
  70. {
  71. paintEntireComponent (g, true);
  72. }
  73. }
  74. }
  75. void Drawable::drawAt (Graphics& g, float x, float y, float opacity) const
  76. {
  77. draw (g, opacity, AffineTransform::translation (x, y));
  78. }
  79. void Drawable::drawWithin (Graphics& g, Rectangle<float> destArea,
  80. RectanglePlacement placement, float opacity) const
  81. {
  82. draw (g, opacity, placement.getTransformToFit (getDrawableBounds(), destArea));
  83. }
  84. //==============================================================================
  85. DrawableComposite* Drawable::getParent() const
  86. {
  87. return dynamic_cast<DrawableComposite*> (getParentComponent());
  88. }
  89. void Drawable::setClipPath (Drawable* clipPath)
  90. {
  91. if (drawableClipPath.get() != clipPath)
  92. {
  93. drawableClipPath.reset (clipPath);
  94. repaint();
  95. }
  96. }
  97. void Drawable::transformContextToCorrectOrigin (Graphics& g)
  98. {
  99. g.setOrigin (originRelativeToComponent);
  100. }
  101. void Drawable::parentHierarchyChanged()
  102. {
  103. setBoundsToEnclose (getDrawableBounds());
  104. }
  105. void Drawable::setBoundsToEnclose (Rectangle<float> area)
  106. {
  107. Point<int> parentOrigin;
  108. if (auto* parent = getParent())
  109. parentOrigin = parent->originRelativeToComponent;
  110. auto newBounds = area.getSmallestIntegerContainer() + parentOrigin;
  111. originRelativeToComponent = parentOrigin - newBounds.getPosition();
  112. setBounds (newBounds);
  113. }
  114. //==============================================================================
  115. bool Drawable::replaceColour (Colour original, Colour replacement)
  116. {
  117. bool changed = false;
  118. for (auto* c : getChildren())
  119. if (auto* d = dynamic_cast<Drawable*> (c))
  120. changed = d->replaceColour (original, replacement) || changed;
  121. return changed;
  122. }
  123. //==============================================================================
  124. void Drawable::setOriginWithOriginalSize (Point<float> originWithinParent)
  125. {
  126. setTransform (AffineTransform::translation (originWithinParent.x, originWithinParent.y));
  127. }
  128. void Drawable::setTransformToFit (const Rectangle<float>& area, RectanglePlacement placement)
  129. {
  130. if (! area.isEmpty())
  131. setTransform (placement.getTransformToFit (getDrawableBounds(), area));
  132. }
  133. //==============================================================================
  134. Drawable* Drawable::createFromImageData (const void* data, const size_t numBytes)
  135. {
  136. Drawable* result = nullptr;
  137. auto image = ImageFileFormat::loadFrom (data, numBytes);
  138. if (image.isValid())
  139. {
  140. auto* di = new DrawableImage();
  141. di->setImage (image);
  142. result = di;
  143. }
  144. else
  145. {
  146. auto asString = String::createStringFromData (data, (int) numBytes);
  147. XmlDocument doc (asString);
  148. std::unique_ptr<XmlElement> outer (doc.getDocumentElement (true));
  149. if (outer != nullptr && outer->hasTagName ("svg"))
  150. {
  151. std::unique_ptr<XmlElement> svg (doc.getDocumentElement());
  152. if (svg != nullptr)
  153. result = Drawable::createFromSVG (*svg);
  154. }
  155. }
  156. return result;
  157. }
  158. Drawable* Drawable::createFromImageDataStream (InputStream& dataSource)
  159. {
  160. MemoryOutputStream mo;
  161. mo << dataSource;
  162. return createFromImageData (mo.getData(), mo.getDataSize());
  163. }
  164. Drawable* Drawable::createFromImageFile (const File& file)
  165. {
  166. FileInputStream fin (file);
  167. return fin.openedOk() ? createFromImageDataStream (fin) : nullptr;
  168. }
  169. } // namespace juce