Merge pull request #165113 from toonn/darwin-bundle-fix-icon

This commit is contained in:
Ben Siraphob 2022-03-24 22:12:56 -05:00 committed by GitHub
commit 3f1e23cf68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 16 deletions

View File

@ -5,6 +5,7 @@ let
CFBundleDevelopmentRegion = "English"; CFBundleDevelopmentRegion = "English";
CFBundleExecutable = "$name"; CFBundleExecutable = "$name";
CFBundleIconFile = "$icon"; CFBundleIconFile = "$icon";
CFBundleIconFiles = [ "$icon" ];
CFBundleIdentifier = "org.nixos.$name"; CFBundleIdentifier = "org.nixos.$name";
CFBundleInfoDictionaryVersion = "6.0"; CFBundleInfoDictionaryVersion = "6.0";
CFBundleName = "$name"; CFBundleName = "$name";
@ -25,11 +26,8 @@ in writeScriptBin "write-darwin-bundle" ''
${pListText} ${pListText}
EOF EOF
if [[ $squircle != 0 && $squircle != "false" ]]; then if [[ $squircle == 0 || $squircle == "false" ]]; then
sed " sed '/CFBundleIconFiles/,\|</array>|d' -i "$plist"
s|CFBundleIconFile|CFBundleIconFiles|;
s|<string>$icon</string>|<array><string>$icon</string></array>|
" -i "$plist"
fi fi
cat > "$prefix/Applications/$name.app/Contents/MacOS/$name" <<EOF cat > "$prefix/Applications/$name.app/Contents/MacOS/$name" <<EOF

View File

@ -18,7 +18,9 @@ convertIconTheme() {
local -r iconName=$3 local -r iconName=$3
local -r theme=${4:-hicolor} local -r theme=${4:-hicolor}
local -ra iconSizes=(16 32 48 128 256 512) # Sizes based on archived Apple documentation:
# https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/app-icon#app-icon-sizes
local -ra iconSizes=(16 32 128 256 512)
local -ra scales=([1]="" [2]="@2") local -ra scales=([1]="" [2]="@2")
# Based loosely on the algorithm at: # Based loosely on the algorithm at:
@ -31,13 +33,6 @@ convertIconTheme() {
local scaleSuffix=${scales[$scale]} local scaleSuffix=${scales[$scale]}
local exactSize=${iconSize}x${iconSize}${scaleSuffix} local exactSize=${iconSize}x${iconSize}${scaleSuffix}
if [[ $exactSize = '48x48@2' ]]; then
# macOS does not support a 2x scale variant of 48x48 icons
# See: https://en.wikipedia.org/wiki/Apple_Icon_Image_format#Icon_types
echo "unsupported"
return 0
fi
local -a validSizes=( local -a validSizes=(
${exactSize} ${exactSize}
$((iconSize + 1))x$((iconSize + 1))${scaleSuffix} $((iconSize + 1))x$((iconSize + 1))${scaleSuffix}
@ -55,8 +50,10 @@ convertIconTheme() {
else else
echo "threshold $icon" echo "threshold $icon"
fi fi
return 0 elif [[ -a $icon ]]; then
echo "fallback $icon"
fi fi
return 0
done done
done done
echo "scalable" echo "scalable"
@ -106,6 +103,17 @@ convertIconTheme() {
scalableIcon=('-') scalableIcon=('-')
fi fi
# Tri-state variable, NONE means no icons have been found, an empty
# icns file will be generated, not sure that's necessary because macOS
# will default to a generic icon if no icon can be found.
#
# OTHER means an appropriate icon was found.
#
# Any other value is a path to an icon file that isn't scalable or
# within the threshold. This is used as a fallback in case no better
# icon can be found and will be scaled as much as
# necessary to result in appropriate icon sizes.
local foundIcon=NONE
for iconSize in "${iconSizes[@]}"; do for iconSize in "${iconSizes[@]}"; do
for scale in "${!scales[@]}"; do for scale in "${!scales[@]}"; do
local iconResult=$(findIcon $iconSize $scale) local iconResult=$(findIcon $iconSize $scale)
@ -117,6 +125,7 @@ convertIconTheme() {
fixed) fixed)
local density=$((72 * scale))x$((72 * scale)) local density=$((72 * scale))x$((72 * scale))
magick convert -density "$density" -units PixelsPerInch "$icon" "$result" magick convert -density "$density" -units PixelsPerInch "$icon" "$result"
foundIcon=OTHER
;; ;;
threshold) threshold)
# Synthesize an icon of the exact size if a scalable icon is available # Synthesize an icon of the exact size if a scalable icon is available
@ -124,21 +133,38 @@ convertIconTheme() {
if ! synthesizeIcon "${scalableIcon[0]}" "$result" "$iconSize" "$scale"; then if ! synthesizeIcon "${scalableIcon[0]}" "$result" "$iconSize" "$scale"; then
resizeIcon "$icon" "$result" "$iconSize" "$scale" resizeIcon "$icon" "$result" "$iconSize" "$scale"
fi fi
foundIcon=OTHER
;; ;;
scalable) scalable)
synthesizeIcon "${scalableIcon[0]}" "$result" "$iconSize" "$scale" || true synthesizeIcon "${scalableIcon[0]}" "$result" "$iconSize" "$scale" || true
foundIcon=OTHER
;;
fallback)
# Use the largest size available to scale to
# appropriate sizes.
if [[ $foundIcon != OTHER ]]; then
foundIcon=$icon
fi
;; ;;
*) *)
;; ;;
esac esac
done done
done done
if [[ $foundIcon != NONE && $foundIcon != OTHER ]]; then
# Ideally we'd only resize to whatever the closest sizes are,
# starting from whatever icon sizes are available.
for iconSize in 16 32 128 256 512; do
local result=${resultdir}/${iconSize}x${iconSize}.png
resizeIcon "$foundIcon" "$result" "$iconSize" 1
done
fi
echo "$resultdir" echo "$resultdir"
} }
iconsdir=$(getIcons "$sharePath" "apps/${iconName}" "$theme") iconsdir=$(getIcons "$sharePath" "apps/${iconName}" "$theme")
if [[ ! -z "$(ls -1 "$iconsdir/"*)" ]]; then if [[ -n "$(ls -1 "$iconsdir/"*)" ]]; then
icnsutil compose "$out/${iconName}.icns" "$iconsdir/"* icnsutil compose --toc "$out/${iconName}.icns" "$iconsdir/"*
else else
echo "Warning: no icons were found. Creating an empty icon for ${iconName}.icns." echo "Warning: no icons were found. Creating an empty icon for ${iconName}.icns."
touch "$out/${iconName}.icns" touch "$out/${iconName}.icns"