juce_DrawableShape.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. DrawableShape::DrawableShape()
  22. : strokeType (0.0f),
  23. mainFill (Colours::black),
  24. strokeFill (Colours::black)
  25. {
  26. }
  27. DrawableShape::DrawableShape (const DrawableShape& other)
  28. : Drawable (other),
  29. strokeType (other.strokeType),
  30. dashLengths (other.dashLengths),
  31. mainFill (other.mainFill),
  32. strokeFill (other.strokeFill)
  33. {
  34. }
  35. DrawableShape::~DrawableShape()
  36. {
  37. }
  38. //==============================================================================
  39. void DrawableShape::setFill (const FillType& newFill)
  40. {
  41. if (mainFill != newFill)
  42. {
  43. mainFill = newFill;
  44. repaint();
  45. }
  46. }
  47. void DrawableShape::setStrokeFill (const FillType& newFill)
  48. {
  49. if (strokeFill != newFill)
  50. {
  51. strokeFill = newFill;
  52. repaint();
  53. }
  54. }
  55. void DrawableShape::setStrokeType (const PathStrokeType& newStrokeType)
  56. {
  57. if (strokeType != newStrokeType)
  58. {
  59. strokeType = newStrokeType;
  60. strokeChanged();
  61. }
  62. }
  63. void DrawableShape::setDashLengths (const Array<float>& newDashLengths)
  64. {
  65. if (dashLengths != newDashLengths)
  66. {
  67. dashLengths = newDashLengths;
  68. strokeChanged();
  69. }
  70. }
  71. void DrawableShape::setStrokeThickness (const float newThickness)
  72. {
  73. setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle()));
  74. }
  75. bool DrawableShape::isStrokeVisible() const noexcept
  76. {
  77. return strokeType.getStrokeThickness() > 0.0f && ! strokeFill.isInvisible();
  78. }
  79. //==============================================================================
  80. void DrawableShape::paint (Graphics& g)
  81. {
  82. transformContextToCorrectOrigin (g);
  83. applyDrawableClipPath (g);
  84. g.setFillType (mainFill);
  85. g.fillPath (path);
  86. if (isStrokeVisible())
  87. {
  88. g.setFillType (strokeFill);
  89. g.fillPath (strokePath);
  90. }
  91. }
  92. void DrawableShape::pathChanged()
  93. {
  94. strokeChanged();
  95. }
  96. void DrawableShape::strokeChanged()
  97. {
  98. strokePath.clear();
  99. const float extraAccuracy = 4.0f;
  100. if (dashLengths.isEmpty())
  101. strokeType.createStrokedPath (strokePath, path, AffineTransform(), extraAccuracy);
  102. else
  103. strokeType.createDashedStroke (strokePath, path, dashLengths.getRawDataPointer(),
  104. dashLengths.size(), AffineTransform(), extraAccuracy);
  105. setBoundsToEnclose (getDrawableBounds());
  106. repaint();
  107. }
  108. Rectangle<float> DrawableShape::getDrawableBounds() const
  109. {
  110. if (isStrokeVisible())
  111. return strokePath.getBounds();
  112. return path.getBounds();
  113. }
  114. bool DrawableShape::hitTest (int x, int y)
  115. {
  116. bool allowsClicksOnThisComponent, allowsClicksOnChildComponents;
  117. getInterceptsMouseClicks (allowsClicksOnThisComponent, allowsClicksOnChildComponents);
  118. if (! allowsClicksOnThisComponent)
  119. return false;
  120. auto globalX = (float) (x - originRelativeToComponent.x);
  121. auto globalY = (float) (y - originRelativeToComponent.y);
  122. return path.contains (globalX, globalY)
  123. || (isStrokeVisible() && strokePath.contains (globalX, globalY));
  124. }
  125. //==============================================================================
  126. static bool replaceColourInFill (FillType& fill, Colour original, Colour replacement)
  127. {
  128. if (fill.colour == original && fill.isColour())
  129. {
  130. fill = FillType (replacement);
  131. return true;
  132. }
  133. return false;
  134. }
  135. bool DrawableShape::replaceColour (Colour original, Colour replacement)
  136. {
  137. bool changed1 = replaceColourInFill (mainFill, original, replacement);
  138. bool changed2 = replaceColourInFill (strokeFill, original, replacement);
  139. return changed1 || changed2;
  140. }
  141. Path DrawableShape::getOutlineAsPath() const
  142. {
  143. auto outline = isStrokeVisible() ? strokePath : path;
  144. outline.applyTransform (getTransform());
  145. return outline;
  146. }
  147. } // namespace juce