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.

138 lines
5.0KB

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