diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_128x128.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_128x128.png index f85ced2c..c9298e1a 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_128x128.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_128x128.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png index 6516c53c..7dfe0762 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_16x16.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_16x16.png index fa6a8cf0..e20339bf 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_16x16.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_16x16.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png index 84b3ea2c..cf0a709f 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_256x256.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_256x256.png index 6516c53c..7dfe0762 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_256x256.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_256x256.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png index 5c73d4e6..930a4bb2 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_32x32.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_32x32.png index 84b3ea2c..cf0a709f 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_32x32.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_32x32.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png index 58e93947..500352c4 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_512x512.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_512x512.png index 5c73d4e6..930a4bb2 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_512x512.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_512x512.png differ diff --git a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png index 9bf9b82a..46801070 100644 Binary files a/bitchat/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png and b/bitchat/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/Contents.json b/bitchat/Assets.xcassets/AppIconDebug.appiconset/Contents.json index b74e0441..72bc51f7 100644 --- a/bitchat/Assets.xcassets/AppIconDebug.appiconset/Contents.json +++ b/bitchat/Assets.xcassets/AppIconDebug.appiconset/Contents.json @@ -27,6 +27,66 @@ "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" + }, + { + "filename" : "mac_16x16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "mac_16x16@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "mac_32x32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "mac_32x32@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "mac_128x128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "mac_128x128@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "mac_256x256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "mac_256x256@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "mac_512x512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "mac_512x512@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" } ], "info" : { diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_128x128.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_128x128.png new file mode 100644 index 00000000..9915a654 Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_128x128.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_128x128@2x.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_128x128@2x.png new file mode 100644 index 00000000..b5458dca Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_128x128@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_16x16.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_16x16.png new file mode 100644 index 00000000..c5a0c8e1 Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_16x16.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_16x16@2x.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_16x16@2x.png new file mode 100644 index 00000000..5a292f43 Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_16x16@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_256x256.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_256x256.png new file mode 100644 index 00000000..b5458dca Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_256x256.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_256x256@2x.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_256x256@2x.png new file mode 100644 index 00000000..95912d2f Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_256x256@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_32x32.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_32x32.png new file mode 100644 index 00000000..5a292f43 Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_32x32.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_32x32@2x.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_32x32@2x.png new file mode 100644 index 00000000..1cea92dd Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_32x32@2x.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_512x512.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_512x512.png new file mode 100644 index 00000000..95912d2f Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_512x512.png differ diff --git a/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_512x512@2x.png b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_512x512@2x.png new file mode 100644 index 00000000..691785a8 Binary files /dev/null and b/bitchat/Assets.xcassets/AppIconDebug.appiconset/mac_512x512@2x.png differ diff --git a/scripts/generate-mac-appicon.swift b/scripts/generate-mac-appicon.swift new file mode 100644 index 00000000..fa98934a --- /dev/null +++ b/scripts/generate-mac-appicon.swift @@ -0,0 +1,81 @@ +#!/usr/bin/env swift +// Generates macOS app-icon PNGs from a square 1024x1024 source image. +// +// macOS does not mask icons at render time the way iOS does, so the rounded +// rectangle must be baked into the artwork. This applies Apple's Big Sur icon +// grid: an 824x824 rounded-rect body (corner radius 185.4 @1024) centered on a +// transparent 1024 canvas, with the standard subtle drop shadow. +// +// Usage: swift scripts/generate-mac-appicon.swift +// e.g. swift scripts/generate-mac-appicon.swift icon_1024x1024.png bitchat/Assets.xcassets/AppIcon.appiconset icon + +import AppKit +import UniformTypeIdentifiers + +guard CommandLine.arguments.count == 4 else { + FileHandle.standardError.write(Data("usage: generate-mac-appicon.swift \n".utf8)) + exit(1) +} + +let sourcePath = CommandLine.arguments[1] +let outDir = URL(fileURLWithPath: CommandLine.arguments[2], isDirectory: true) +let prefix = CommandLine.arguments[3] + +guard let dataProvider = CGDataProvider(url: URL(fileURLWithPath: sourcePath) as CFURL), + let source = CGImage(pngDataProviderSource: dataProvider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else { + FileHandle.standardError.write(Data("error: could not read PNG at \(sourcePath)\n".utf8)) + exit(1) +} + +let sRGB = CGColorSpace(name: CGColorSpace.sRGB)! + +func render(pixels: Int) -> CGImage { + let ctx = CGContext( + data: nil, width: pixels, height: pixels, + bitsPerComponent: 8, bytesPerRow: 0, space: sRGB, + bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue + )! + let side = CGFloat(pixels) + let inset = side * 100.0 / 1024.0 + let body = CGRect(x: inset, y: inset, width: side - 2 * inset, height: side - 2 * inset) + let radius = side * 185.4 / 1024.0 + let path = CGPath(roundedRect: body, cornerWidth: radius, cornerHeight: radius, transform: nil) + + ctx.saveGState() + ctx.setShadow( + offset: CGSize(width: 0, height: -side * 10.0 / 1024.0), + blur: side * 20.0 / 1024.0, + color: CGColor(colorSpace: sRGB, components: [0, 0, 0, 0.3]) + ) + ctx.addPath(path) + ctx.setFillColor(CGColor(colorSpace: sRGB, components: [0, 0, 0, 1])!) + ctx.fillPath() + ctx.restoreGState() + + ctx.saveGState() + ctx.addPath(path) + ctx.clip() + ctx.interpolationQuality = .high + ctx.draw(source, in: body) + ctx.restoreGState() + + return ctx.makeImage()! +} + +func writePNG(_ image: CGImage, to url: URL) { + let dest = CGImageDestinationCreateWithURL(url as CFURL, UTType.png.identifier as CFString, 1, nil)! + CGImageDestinationAddImage(dest, image, nil) + guard CGImageDestinationFinalize(dest) else { + FileHandle.standardError.write(Data("error: failed to write \(url.path)\n".utf8)) + exit(1) + } +} + +// (point size, scale) for every mac slot in an appiconset +let slots: [(Int, Int)] = [(16, 1), (16, 2), (32, 1), (32, 2), (128, 1), (128, 2), (256, 1), (256, 2), (512, 1), (512, 2)] +for (points, scale) in slots { + let suffix = scale == 1 ? "" : "@\(scale)x" + let url = outDir.appendingPathComponent("\(prefix)_\(points)x\(points)\(suffix).png") + writePNG(render(pixels: points * scale), to: url) + print("wrote \(url.lastPathComponent)") +}