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.

172 lines
5.4KB

  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. #if JUCE_MSVC && JUCE_DEBUG
  19. #pragma optimize ("t", on)
  20. #endif
  21. static void blurSingleChannelImage (uint8* const data, const int width, const int height,
  22. const int lineStride, const int repetitions) noexcept
  23. {
  24. uint8* line = data;
  25. for (int y = height; --y >= 0;)
  26. {
  27. for (int i = repetitions; --i >= 0;)
  28. {
  29. uint8* p = line;
  30. *p++ = (((int) p[0]) + p[1]) / 2;
  31. for (int x = width - 2; --x >= 0;)
  32. *p++ = (((int) p[-1]) + p[0] + p[1] + 1) / 3;
  33. *p = (((int) p[0]) + p[-1]) / 2;
  34. }
  35. line += lineStride;
  36. }
  37. for (int i = repetitions; --i >= 0;)
  38. {
  39. line = data;
  40. {
  41. uint8* p1 = line;
  42. uint8* p2 = line + lineStride;
  43. for (int x = width; --x >= 0;)
  44. *p1++ = (((int) *p1) + *p2++) / 2;
  45. }
  46. line += lineStride;
  47. for (int y = height - 2; --y >= 0;)
  48. {
  49. uint8* p1 = line;
  50. uint8* p2 = line - lineStride;
  51. uint8* p3 = line + lineStride;
  52. for (int x = width; --x >= 0;)
  53. *p1++ = (((int) *p1) + *p2++ + *p3++ + 1) / 3;
  54. line += lineStride;
  55. }
  56. uint8* p1 = line;
  57. uint8* p2 = line - lineStride;
  58. for (int x = width; --x >= 0;)
  59. *p1++ = (((int) *p1) + *p2++) / 2;
  60. }
  61. }
  62. static void blurSingleChannelImage (Image& image, int radius)
  63. {
  64. const Image::BitmapData bm (image, Image::BitmapData::readWrite);
  65. blurSingleChannelImage (bm.data, bm.width, bm.height, bm.lineStride, 2 * radius);
  66. }
  67. #if JUCE_MSVC && JUCE_DEBUG
  68. #pragma optimize ("", on) // resets optimisations to the project defaults
  69. #endif
  70. //==============================================================================
  71. DropShadow::DropShadow() noexcept
  72. : colour (0x90000000), radius (4)
  73. {
  74. }
  75. DropShadow::DropShadow (const Colour& shadowColour, const int r, const Point<int>& o) noexcept
  76. : colour (shadowColour), radius (r), offset (o)
  77. {
  78. jassert (radius > 0);
  79. }
  80. void DropShadow::drawForImage (Graphics& g, const Image& srcImage) const
  81. {
  82. jassert (radius > 0);
  83. if (srcImage.isValid())
  84. {
  85. Image shadowImage (srcImage.convertedToFormat (Image::SingleChannel));
  86. shadowImage.duplicateIfShared();
  87. blurSingleChannelImage (shadowImage, radius);
  88. g.setColour (colour);
  89. g.drawImageAt (shadowImage, offset.x, offset.y, true);
  90. }
  91. }
  92. void DropShadow::drawForPath (Graphics& g, const Path& path) const
  93. {
  94. jassert (radius > 0);
  95. const Rectangle<int> area (path.getBounds().translated ((float) offset.x, (float) offset.y)
  96. .getSmallestIntegerContainer()
  97. .getIntersection (g.getClipBounds())
  98. .expanded (radius + 1, radius + 1));
  99. if (area.getWidth() > 2 && area.getHeight() > 2)
  100. {
  101. Image renderedPath (Image::SingleChannel, area.getWidth(), area.getHeight(), true);
  102. {
  103. Graphics g2 (renderedPath);
  104. g2.setColour (Colours::white);
  105. g2.fillPath (path, AffineTransform::translation ((float) (offset.x - area.getX()),
  106. (float) (offset.y - area.getY())));
  107. }
  108. blurSingleChannelImage (renderedPath, radius);
  109. g.setColour (colour);
  110. g.drawImageAt (renderedPath, area.getX(), area.getY(), true);
  111. }
  112. }
  113. //==============================================================================
  114. DropShadowEffect::DropShadowEffect() {}
  115. DropShadowEffect::~DropShadowEffect() {}
  116. void DropShadowEffect::setShadowProperties (const DropShadow& newShadow)
  117. {
  118. shadow = newShadow;
  119. }
  120. void DropShadowEffect::applyEffect (Image& image, Graphics& g, float scaleFactor, float alpha)
  121. {
  122. DropShadow s (shadow);
  123. s.radius = roundToInt (s.radius * scaleFactor);
  124. s.colour = s.colour.withMultipliedAlpha (alpha);
  125. s.offset.x = roundToInt (s.offset.x * scaleFactor);
  126. s.offset.y = roundToInt (s.offset.y * scaleFactor);
  127. s.drawForImage (g, image);
  128. g.setOpacity (alpha);
  129. g.drawImageAt (image, 0, 0);
  130. }