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.

153 lines
5.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. extern Image JUCE_API getIconFromApplication (const String&, int);
  22. static Image getIconFromIcnsFile (const File& icnsFile, const int size)
  23. {
  24. FileInputStream stream (icnsFile);
  25. if (! stream.openedOk())
  26. return {};
  27. const int numHeaderSectionBytes = 4;
  28. char headerSection [numHeaderSectionBytes];
  29. if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes
  30. || headerSection[0] != 'i'
  31. || headerSection[1] != 'c'
  32. || headerSection[2] != 'n'
  33. || headerSection[3] != 's')
  34. return {};
  35. if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes)
  36. return {};
  37. const auto dataSize = juce::ByteOrder::bigEndianInt (headerSection);
  38. if (dataSize <= 0)
  39. return {};
  40. OwnedArray<juce::ImageFileFormat> internalFormats;
  41. internalFormats.add (new PNGImageFormat());
  42. internalFormats.add (new JPEGImageFormat());
  43. Array<Image> images;
  44. auto maxWidth = 0;
  45. auto maxWidthIndex = -1;
  46. while (stream.getPosition() < dataSize)
  47. {
  48. const auto sectionStart = stream.getPosition();
  49. if (! stream.setPosition (sectionStart + 4))
  50. break;
  51. if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes)
  52. break;
  53. const auto sectionSize = ByteOrder::bigEndianInt (headerSection);
  54. if (sectionSize <= 0)
  55. break;
  56. const auto sectionDataStart = stream.getPosition();
  57. for (auto* fmt : internalFormats)
  58. {
  59. if (fmt->canUnderstand (stream))
  60. {
  61. stream.setPosition (sectionDataStart);
  62. images.add (fmt->decodeImage (stream));
  63. const auto lastImageIndex = images.size() - 1;
  64. const auto lastWidth = images.getReference (lastImageIndex).getWidth();
  65. if (lastWidth > maxWidth)
  66. {
  67. maxWidthIndex = lastImageIndex;
  68. maxWidth = lastWidth;
  69. }
  70. }
  71. stream.setPosition (sectionDataStart);
  72. }
  73. stream.setPosition (sectionStart + sectionSize);
  74. }
  75. return maxWidthIndex == -1 ? juce::Image()
  76. : images.getReference (maxWidthIndex).rescaled (size, size, Graphics::ResamplingQuality::highResamplingQuality);
  77. }
  78. Image JUCE_API getIconFromApplication (const String& applicationPath, const int size)
  79. {
  80. Image hostIcon;
  81. if (CFStringRef pathCFString = CFStringCreateWithCString (kCFAllocatorDefault, applicationPath.toRawUTF8(), kCFStringEncodingUTF8))
  82. {
  83. if (CFURLRef url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, pathCFString, kCFURLPOSIXPathStyle, 1))
  84. {
  85. if (CFBundleRef appBundle = CFBundleCreate (kCFAllocatorDefault, url))
  86. {
  87. if (CFTypeRef infoValue = CFBundleGetValueForInfoDictionaryKey (appBundle, CFSTR("CFBundleIconFile")))
  88. {
  89. if (CFGetTypeID (infoValue) == CFStringGetTypeID())
  90. {
  91. CFStringRef iconFilename = reinterpret_cast<CFStringRef> (infoValue);
  92. CFStringRef resourceURLSuffix = CFStringHasSuffix (iconFilename, CFSTR(".icns")) ? nullptr : CFSTR("icns");
  93. if (CFURLRef iconURL = CFBundleCopyResourceURL (appBundle, iconFilename, resourceURLSuffix, nullptr))
  94. {
  95. if (CFStringRef iconPath = CFURLCopyFileSystemPath (iconURL, kCFURLPOSIXPathStyle))
  96. {
  97. File icnsFile (CFStringGetCStringPtr (iconPath, CFStringGetSystemEncoding()));
  98. hostIcon = getIconFromIcnsFile (icnsFile, size);
  99. CFRelease (iconPath);
  100. }
  101. CFRelease (iconURL);
  102. }
  103. }
  104. }
  105. CFRelease (appBundle);
  106. }
  107. CFRelease (url);
  108. }
  109. CFRelease (pathCFString);
  110. }
  111. return hostIcon;
  112. }
  113. } // namespace juce