Hi! Does anybody know which dimensions should an i...
# compose-desktop
y
Hi! Does anybody know which dimensions should an icon have for MacOS tray? I've tried to supply 16, 24, 32, 64, 256 icons, but they all look a bit blurry. I've found this piece of code and wondering if I really need 22x22 icon to prevent inappropriate scaling? Looks like Compose (using AWT) scales the passed icon to 22x22 before it even arrives to OS which cause a slight blurriness.
m
y
@Michael Paus the link is about app icons, and there's no problems with them. What is unclear is menu bar / tray icon.
22x22
used by Compose not even mentioned anywhere. In Compose guide, they use drawing (256x256) instead of an icon, and it looks bigger than the default icons located near.
m
But there is no separate icon for the tray. If Swing/Compose does some maybe incorrect fiddling with these icons, that’s another story and I doubt that this could be cured by providing any non-standard icon sizes.
y
I use these instructions: How to generate icon for the app itself: • create folder (called xxx.iconset) • generate the following files: icon_16x16.png icon_16x16@2x.png icon_32x32.png icon_32x32@2x.png icon_128x128.png icon_128x128@2x.png icon_256x256.png icon_256x256@2x.png icon_512x512.png icon_512x512@2x.png • run iconutil -c icns xxx.iconset • copy/paste the xxx.icns file in the app icon section (Get Info) Sources: 1) https://eshop.macsales.com/blog/28492-create-your-own-custom-icons-in-10-7-5-or-later/ 2) https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/app-icon/
I actually also translated these instructions into a gradle task so that my icon is automatically generated from an svg file
Here is the code (it uses Google Chrome to render svg -> png)
Copy code
// render a single icon with the size
fun renderIcon(size: Int, filename: String) {
  val html = """
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body style="margin:0;overflow:hidden">
      <img style="padding; margin:0" src="${rootDir}/composeApp/src/commonMain/resources/images/logo.svg" width="$size" height="$size"></img>
      </body>
      </html>
    """.trimIndent()
  val inputFile = file("${layout.buildDirectory.get().asFile}/icon.html")
  inputFile.writeText(html)
  println(inputFile)
  exec {
    commandLine(
      "/Applications/Google <http://Chrome.app/Contents/MacOS/Google|Chrome.app/Contents/MacOS/Google> Chrome",
      "--headless",
      "--screenshot=$filename",
      "--window-size=$size,$size",
      "--default-background-color=0x000000",
      inputFile.toString()
    )
  }
}

val iconsetDir = "${layout.buildDirectory.get().asFile}/workout-timer.iconset"

// render all icons required for iconset
tasks.register("iconset") {
  doLast {
    // make sure the folder exists
    mkdir(iconsetDir)

    // generate each icon
    arrayOf(512, 256, 128, 32, 16).forEach { size ->
      renderIcon(size * 2, "$iconsetDir/icon_${size}x${size}@2x.png")
      renderIcon(size, "$iconsetDir/icon_${size}x${size}.png")
    }
  }
}

// render the .icns file needed for macOS
val icnsTask = tasks.register("icns") {
  doLast {
    exec {
      commandLine("iconutil", "-c", "icns", iconsetDir)
      workingDir = layout.buildDirectory.get().asFile
    }
  }
  dependsOn("iconset")
}
m
Instead of chrome you could just use the built-in command
Copy code
sips -z 128 128 -s format png $MASTER_ICON --out appIcon.iconset/icon_128x128.png
where MASTER_ICON is some SVG icon file.
y
@Michael Paus I did not know about this command. It's obviously far more convenient (if it handles the conversion properly including transparency)
I just tested it and unfortunately the result is not the same. My logo has a shadow which does not get rendered with sips which makes me think that it doesn't handle transparency properly (at least not with the options you suggested)
a
Try ImageMagick maybe
1