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.

136 lines
5.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. Image getIconFromIcnsFile (const File& icnsFile, const int size)
  18. {
  19. FileInputStream stream (icnsFile);
  20. if (! stream.openedOk())
  21. return {};
  22. const int numHeaderSectionBytes = 4;
  23. char headerSection [numHeaderSectionBytes];
  24. if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes
  25. || headerSection[0] != 'i'
  26. || headerSection[1] != 'c'
  27. || headerSection[2] != 'n'
  28. || headerSection[3] != 's')
  29. return {};
  30. if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes)
  31. return {};
  32. const auto dataSize = juce::ByteOrder::bigEndianInt (headerSection);
  33. if (dataSize <= 0)
  34. return {};
  35. OwnedArray<juce::ImageFileFormat> internalFormats;
  36. internalFormats.add (new PNGImageFormat());
  37. internalFormats.add (new JPEGImageFormat());
  38. Array<Image> images;
  39. auto maxWidth = 0;
  40. auto maxWidthIndex = -1;
  41. while (stream.getPosition() < dataSize)
  42. {
  43. const auto sectionStart = stream.getPosition();
  44. if (! stream.setPosition (sectionStart + 4))
  45. break;
  46. if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes)
  47. break;
  48. const auto sectionSize = ByteOrder::bigEndianInt (headerSection);
  49. if (sectionSize <= 0)
  50. break;
  51. const auto sectionDataStart = stream.getPosition();
  52. for (auto* fmt : internalFormats)
  53. {
  54. if (fmt->canUnderstand (stream))
  55. {
  56. stream.setPosition (sectionDataStart);
  57. images.add (fmt->decodeImage (stream));
  58. const auto lastImageIndex = images.size() - 1;
  59. const auto lastWidth = images.getReference (lastImageIndex).getWidth();
  60. if (lastWidth > maxWidth)
  61. {
  62. maxWidthIndex = lastImageIndex;
  63. maxWidth = lastWidth;
  64. }
  65. }
  66. stream.setPosition (sectionDataStart);
  67. }
  68. stream.setPosition (sectionStart + sectionSize);
  69. }
  70. return maxWidthIndex == -1 ? juce::Image()
  71. : images.getReference (maxWidthIndex).rescaled (size, size, Graphics::ResamplingQuality::highResamplingQuality);
  72. }
  73. Image JUCE_API getIconFromApplication (const String& applicationPath, const int size)
  74. {
  75. Image hostIcon;
  76. if (CFStringRef pathCFString = CFStringCreateWithCString (kCFAllocatorDefault, applicationPath.toRawUTF8(), kCFStringEncodingUTF8))
  77. {
  78. if (CFURLRef url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, pathCFString, kCFURLPOSIXPathStyle, 1))
  79. {
  80. if (CFBundleRef appBundle = CFBundleCreate (kCFAllocatorDefault, url))
  81. {
  82. if (CFTypeRef infoValue = CFBundleGetValueForInfoDictionaryKey (appBundle, CFSTR("CFBundleIconFile")))
  83. {
  84. if (CFGetTypeID (infoValue) == CFStringGetTypeID())
  85. {
  86. CFStringRef iconFilename = reinterpret_cast<CFStringRef> (infoValue);
  87. CFStringRef resourceURLSuffix = CFStringHasSuffix (iconFilename, CFSTR(".icns")) ? nullptr : CFSTR("icns");
  88. if (CFURLRef iconURL = CFBundleCopyResourceURL (appBundle, iconFilename, resourceURLSuffix, nullptr))
  89. {
  90. if (CFStringRef iconPath = CFURLCopyFileSystemPath (iconURL, kCFURLPOSIXPathStyle))
  91. {
  92. File icnsFile (CFStringGetCStringPtr (iconPath, CFStringGetSystemEncoding()));
  93. hostIcon = getIconFromIcnsFile (icnsFile, size);
  94. CFRelease (iconPath);
  95. }
  96. CFRelease (iconURL);
  97. }
  98. }
  99. }
  100. CFRelease (appBundle);
  101. }
  102. CFRelease (url);
  103. }
  104. CFRelease (pathCFString);
  105. }
  106. return hostIcon;
  107. }